/* ============================================
   FastClean Service — Shared Animation Layer
   Pairs with js/animations.js
   Respects prefers-reduced-motion
   ============================================ */

/* ===== Reveal (single element) — soft floaty drift by default ===== */
.fx-reveal, .fx-stagger-item {
    opacity: 0;
    transform: translateY(90px);
    transition: opacity 1.3s cubic-bezier(.16,.84,.44,1), transform 1.5s cubic-bezier(.16,.84,.44,1);
    will-change: opacity, transform;
}
.fx-reveal.fx-left  { transform: translateX(-80px); }
.fx-reveal.fx-right { transform: translateX( 80px); }
.fx-reveal.fx-zoom  { transform: scale(.7); }
.fx-reveal.fx-drop  { transform: translateY(-90px); }
.fx-reveal.fx-bouncy { transition: opacity .75s cubic-bezier(.34,1.56,.64,1), transform .85s cubic-bezier(.34,1.56,.64,1); transform: translateY(48px); }
.fx-reveal.fx-in,
.fx-stagger-item.fx-in { opacity: 1; transform: none; }

/* ===== Pop — scale-in with overshoot ===== */
.fx-pop { opacity: 0; transform: scale(.3); transition: opacity .5s ease, transform .65s cubic-bezier(.34,1.8,.64,1); will-change: opacity, transform; }
.fx-pop.fx-in { opacity: 1; transform: scale(1); }

/* ===== Icon spin-in ===== */
.fx-icon-spin { display: inline-block; opacity: 0; transform: rotate(-180deg) scale(.5); transition: opacity .55s, transform .75s cubic-bezier(.34,1.56,.64,1); }
.fx-icon-spin.fx-in { opacity: 1; transform: rotate(0) scale(1); }

/* ===== Float (continuous) — for badges/icons ===== */
.fx-float { animation: fx-float-y 3.5s ease-in-out infinite; will-change: transform; }
@keyframes fx-float-y {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-8px); }
}

/* ===== Wobble icon on hover ===== */
.fx-wobble:hover i,
.fx-wobble:hover .ico { animation: fx-wobble .6s ease; display: inline-block; }
@keyframes fx-wobble {
    0%,100% { transform: rotate(0); }
    20%     { transform: rotate(-12deg); }
    40%     { transform: rotate(10deg); }
    60%     { transform: rotate(-6deg); }
    80%     { transform: rotate(4deg); }
}

/* ===== Bouncy step circle on first paint ===== */
.fx-bounce-in { animation: fx-bounce-in-kf .7s cubic-bezier(.34,1.8,.64,1) both; }
@keyframes fx-bounce-in-kf {
    0%   { transform: scale(0);    opacity: 0; }
    60%  { transform: scale(1.25); opacity: 1; }
    100% { transform: scale(1); }
}

/* ===== Lift on hover ===== */
.fx-lift { transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease; }
.fx-lift:hover { transform: translateY(-6px); box-shadow: 0 18px 38px rgba(15,23,42,.10); }

/* ===== Glow ring on hover ===== */
.fx-glow { position: relative; }
.fx-glow::after {
    content:''; position:absolute; inset:-4px; border-radius:inherit;
    background: radial-gradient(60% 80% at 50% 50%, rgba(0,112,224,.45), transparent 70%);
    filter: blur(10px); opacity:0; transition: opacity .4s; z-index:-1;
}
.fx-glow:hover::after { opacity:.9; }

/* ===== Pulse ring (continuous) ===== */
.fx-pulse { position: relative; }
.fx-pulse::before {
    content:''; position:absolute; inset:0; border-radius:inherit;
    box-shadow: 0 0 0 0 rgba(0,112,224,.55);
    animation: fx-pulse-ring 2.2s infinite;
    z-index:0; pointer-events:none;
}
@keyframes fx-pulse-ring {
    0%   { box-shadow: 0 0 0 0   rgba(0,112,224,.55); }
    70%  { box-shadow: 0 0 0 22px rgba(0,112,224, 0); }
    100% { box-shadow: 0 0 0 0   rgba(0,112,224, 0); }
}

/* ===== Sparkle dots (JS-spawned) ===== */
.fx-sparkle-dot {
    position:absolute; width:8px; height:8px; border-radius:50%;
    background:#fde047; box-shadow: 0 0 12px #fcd34d;
    pointer-events:none; transform: translate(-50%,-50%);
    animation: fx-sparkle-pop .9s forwards ease-out; z-index:5;
}
@keyframes fx-sparkle-pop {
    0%   { opacity: 1; transform: translate(-50%,-50%) scale(.4); }
    60%  { opacity: 1; }
    100% { opacity: 0; transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--dy, -30px))) scale(1.4); }
}

/* ===== Hero gradient orbs ===== */
.fx-orb-wrap { position:absolute; inset:0; pointer-events:none; overflow:hidden; z-index:0; }
.fx-orb {
    position:absolute; border-radius:50%; filter: blur(60px); opacity:.55;
    will-change: transform; animation: fx-orb-float 14s ease-in-out infinite;
}
.fx-orb.o1 { width:340px; height:340px; background: radial-gradient(circle, #7cc4ff, transparent 70%); top:-60px;   left:-80px;  animation-delay: 0s; }
.fx-orb.o2 { width:280px; height:280px; background: radial-gradient(circle, #c7e9ff, transparent 70%); top: 40%;    right:-60px; animation-delay: -5s; }
.fx-orb.o3 { width:220px; height:220px; background: radial-gradient(circle, #fde68a, transparent 70%); bottom:-40px; left: 30%;  animation-delay: -9s; opacity:.35; }
@keyframes fx-orb-float {
    0%,100% { transform: translate(0,0) scale(1); }
    50%     { transform: translate(14px,-22px) scale(1.05); }
}

/* ===== Tabular nums for counters (avoid jitter) ===== */
.fx-count { font-variant-numeric: tabular-nums; }

/* ===== Shimmer (used on tags) ===== */
.fx-shimmer { position: relative; overflow: hidden; }
.fx-shimmer::after {
    content:''; position:absolute; top:0; left:-60%; width:60%; height:100%;
    background: linear-gradient(110deg, transparent, rgba(255,255,255,.55), transparent);
    animation: fx-shimmer 2.4s infinite;
}
@keyframes fx-shimmer { 0% { left:-60%; } 100% { left:160%; } }

/* ===== Bouncy step circle ===== */
@keyframes fx-bounce-in {
    0%   { transform: translateX(-50%) scale(.3); opacity:0; }
    60%  { transform: translateX(-50%) scale(1.15); opacity:1; }
    100% { transform: translateX(-50%) scale(1); }
}
.fx-step-bounce.fx-in > div:first-child { animation: fx-bounce-in .6s cubic-bezier(.34,1.56,.64,1) both; }

/* ===== Booking-specific: ticked option pops in ===== */
@keyframes fx-tick-pop {
    0%   { transform: scale(0) rotate(-180deg); opacity: 0; }
    60%  { transform: scale(1.3) rotate(0deg); opacity: 1; }
    100% { transform: scale(1) rotate(0deg); }
}
.opt.on::after { animation: fx-tick-pop .35s cubic-bezier(.34,1.56,.64,1); }

/* ===== Counter button press feedback ===== */
.counter button {
    transition: transform .12s ease, background .15s ease, color .15s ease !important;
}
.counter button:active { transform: scale(.85); }

/* ===== Price flip when total changes ===== */
@keyframes fx-price-flip {
    0%   { transform: translateY(0);    opacity: 1; }
    40%  { transform: translateY(-8px); opacity: 0; }
    60%  { transform: translateY( 8px); opacity: 0; }
    100% { transform: translateY(0);    opacity: 1; }
}
.fx-price-changed { animation: fx-price-flip .35s ease; }

/* ===== Success burst ===== */
@keyframes fx-success-pop {
    0%   { transform: scale(.3); opacity: 0; }
    50%  { transform: scale(1.1); opacity: 1; }
    100% { transform: scale(1); }
}
.fx-success-pop { animation: fx-success-pop .55s cubic-bezier(.34,1.56,.64,1) both; }

/* ===== Hero sparkles (JS-spawned floating particles) ===== */
.fx-hero-sparkle {
    position: absolute; width: 6px; height: 6px; border-radius: 50%;
    background: radial-gradient(circle, #fff, rgba(255,255,255,.3));
    box-shadow: 0 0 8px rgba(255,255,255,.8);
    pointer-events: none; opacity: 0;
    animation: fx-sparkle-rise linear forwards;
}
.fx-hero-sparkle.gold { background: radial-gradient(circle, #fde047, rgba(253,224,71,.3)); box-shadow: 0 0 10px rgba(253,224,71,.8); }
@keyframes fx-sparkle-rise {
    0%   { opacity: 0; transform: translateY(0) scale(.4); }
    15%  { opacity: 1; }
    85%  { opacity: 1; }
    100% { opacity: 0; transform: translateY(var(--rise, -300px)) translateX(var(--drift, 0)) scale(1.3); }
}

/* ===== Cursor trail dots ===== */
.fx-cursor-dot {
    position: fixed; width: 10px; height: 10px; border-radius: 50%;
    background: radial-gradient(circle, #fde047, transparent 70%);
    pointer-events: none; z-index: 9997;
    transform: translate(-50%, -50%);
    animation: fx-cursor-fade .8s forwards ease-out;
}
@keyframes fx-cursor-fade {
    0%   { opacity: 1; transform: translate(-50%,-50%) scale(1); }
    100% { opacity: 0; transform: translate(-50%,-50%) scale(.2); }
}

/* ===== Typewriter ===== */
.fx-typewriter { display: inline-block; min-height: 1em; }
.fx-typing::after { content:'|'; margin-left: 2px; animation: fx-caret-blink 1s steps(2,end) infinite; color: currentColor; font-weight: 400; }
@keyframes fx-caret-blink { 50% { opacity: 0; } }

/* ===== Gradient shifting text ===== */
.fx-grad-text {
    background: linear-gradient(90deg, #0070e0, #8b5cf6, #ec4899, #06b6d4, #0070e0);
    background-size: 300% auto;
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    animation: fx-grad-shift 6s linear infinite;
}
@keyframes fx-grad-shift { to { background-position: -300% center; } }

/* ===== Hero image 3D tilt ===== */
.fx-tilt-img { transition: transform .35s cubic-bezier(.2,.7,.2,1); transform-style: preserve-3d; will-change: transform; }

/* ===== Live notification toast (bottom-left) ===== */
#fx-notif-host { position: fixed; left: 16px; bottom: 16px; z-index: 9996; pointer-events: none; max-width: 320px; }
.fx-notif {
    background: #fff; border-radius: 14px; padding: 12px 14px;
    box-shadow: 0 10px 28px rgba(15,23,42,.18), 0 0 0 1px rgba(15,23,42,.05);
    display: flex; align-items: center; gap: 10px;
    transform: translateX(-110%); opacity: 0;
    animation: fx-notif-in .5s cubic-bezier(.34,1.56,.64,1) forwards, fx-notif-out .5s 4.5s forwards ease-in;
    pointer-events: auto;
}
.fx-notif-avatar {
    width: 38px; height: 38px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-weight: 800; color: #fff; flex-shrink: 0;
}
.fx-notif-body { font-size: .85rem; color: #1e293b; line-height: 1.4; }
.fx-notif-body strong { color: #0070e0; }
.fx-notif-body .muted { color: #94a3b8; font-size: .72rem; display: block; margin-top: 2px; }
.fx-notif-pulse { position: absolute; right: 10px; top: 10px; width: 8px; height: 8px; border-radius: 50%; background: #22c55e; box-shadow: 0 0 0 0 rgba(34,197,94,.5); animation: fx-pulse-ring 1.6s infinite; }
@keyframes fx-notif-in  { to { transform: translateX(0); opacity: 1; } }
@keyframes fx-notif-out { to { transform: translateX(-110%); opacity: 0; } }
@media (max-width: 520px) {
    #fx-notif-host { left: 8px; right: 8px; max-width: none; bottom: 80px; }
}

/* ===== Scroll progress bar (top of page) ===== */
.fx-progress {
    position: fixed; top: 0; left: 0; height: 3px; width: 0;
    background: linear-gradient(90deg, #0070e0, #22c55e, #fde047);
    z-index: 9999; pointer-events: none; transition: width .1s linear;
    box-shadow: 0 0 8px rgba(0,112,224,.5);
}

/* ===== Magnetic / spotlight hover (cursor-tracking radial highlight) =====
   Note: NO overflow:hidden — would clip badges/tags positioned outside the card. */
.fx-spotlight { position: relative; }
.fx-spotlight::before {
    content: ''; position: absolute; inset: 0; border-radius: inherit;
    background: radial-gradient(180px circle at var(--mx, 50%) var(--my, 50%), rgba(0,112,224,.12), transparent 60%);
    opacity: 0; transition: opacity .25s; pointer-events: none;
}
.fx-spotlight:hover::before { opacity: 1; }

/* ===== Marquee — endless horizontal scroll for trust strip ===== */
.fx-marquee { overflow: hidden; }
.fx-marquee-track { display: flex; gap: 48px; animation: fx-marquee 28s linear infinite; will-change: transform; }
@keyframes fx-marquee {
    0%   { transform: translateX(0); }
    100% { transform: translateX(-50%); }
}
.fx-marquee:hover .fx-marquee-track { animation-play-state: paused; }

/* ===== Confetti burst (JS-spawned) ===== */
.fx-confetti {
    position: absolute; width: 8px; height: 14px; pointer-events: none;
    animation: fx-confetti-fall 2.2s ease-out forwards;
}
@keyframes fx-confetti-fall {
    0%   { opacity: 1; transform: translate(0,0) rotate(0); }
    100% { opacity: 0; transform: translate(var(--cx,0), var(--cy,180px)) rotate(var(--cr,720deg)); }
}

/* ===== Reduced motion ===== */
@media (prefers-reduced-motion: reduce) {
    .fx-orb, .fx-pulse::before, .fx-shimmer::after, .fx-float,
    .opt.on::after, .fx-price-changed, .fx-success-pop, .fx-bounce-in,
    .fx-marquee-track, .fx-confetti { animation: none !important; }
    .fx-reveal, .fx-stagger-item, .fx-pop, .fx-icon-spin { opacity:1 !important; transform:none !important; }
}
