/* ==================================================================
   MADHAV FLOWER DECOR — ANIMATIONS
   1. Keyframes
   2. Floating Petals (pure CSS, no canvas)
   3. Scroll Reveal
   4. Reduced Motion
   ==================================================================
   Every animated property is transform or opacity — both composited
   on the GPU, so nothing here triggers layout or paint.
   ================================================================== */

/* ------------------------------------------------------------------
   1. KEYFRAMES
   ------------------------------------------------------------------ */

/* Hero background: an imperceptible, endless push-in. */
@keyframes hero-zoom {
    from { transform: scale(1);    }
    to   { transform: scale(1.14); }
}

/* WhatsApp button halo. */
@keyframes pulse-ring {
    0%        { transform: scale(1);    opacity: 0.7; }
    70%, 100% { transform: scale(1.55); opacity: 0;   }
}

/* Hero scroll cue line. */
@keyframes scroll-cue {
    0%        { transform: scaleY(0); transform-origin: top;    }
    45%       { transform: scaleY(1); transform-origin: top;    }
    55%       { transform: scaleY(1); transform-origin: bottom; }
    100%      { transform: scaleY(0); transform-origin: bottom; }
}

/* Button ripple — radius is set inline by main.js. */
@keyframes ripple {
    to { transform: scale(2.6); opacity: 0; }
}

/* Instagram marquee. Two sibling tracks each shift left by their own
   width plus the parent gap — the moment track A clears the viewport,
   track B occupies its exact former position and the loop restarts
   invisibly. */
@keyframes marquee {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(calc(-100% - var(--marquee-gap)), 0, 0); }
}

/* Petal descent. Drift and spin are per-petal custom properties. */
@keyframes petal-fall {
    0% {
        transform: translate3d(0, -12vh, 0) rotate(0deg) scale(var(--p-scale, 1));
        opacity: 0;
    }
    12%  { opacity: var(--p-opacity, 0.6); }
    88%  { opacity: var(--p-opacity, 0.6); }
    100% {
        transform: translate3d(var(--p-drift, 60px), 112vh, 0)
                   rotate(var(--p-spin, 540deg))
                   scale(var(--p-scale, 1));
        opacity: 0;
    }
}

/* Gentle side-to-side sway, layered on top of the fall. */
@keyframes petal-sway {
    from { margin-left: -14px; }
    to   { margin-left:  14px; }
}

/* ------------------------------------------------------------------
   2. FLOATING PETALS
   Twelve absolutely-positioned petals inside the hero. The wrapper is
   pointer-events:none so it never intercepts clicks on the CTAs.
   ------------------------------------------------------------------ */
.petals {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
}

.petal {
    position: absolute;
    top: 0;
    width: var(--p-size, 16px);
    height: calc(var(--p-size, 16px) * 1.25);
    /* Asymmetric radii give the teardrop-petal silhouette. */
    border-radius: 62% 38% 58% 42% / 58% 44% 56% 42%;
    background: linear-gradient(135deg,
        rgba(255, 255, 255, 0.95) 0%,
        rgba(248, 242, 233, 0.85) 45%,
        rgba(192, 160, 98, 0.65) 100%);
    box-shadow: inset -1px -2px 3px rgba(166, 135, 63, 0.18);
    opacity: 0;
    will-change: transform, opacity;
    animation:
        petal-fall var(--p-duration, 15s) var(--p-delay, 0s) linear infinite,
        petal-sway calc(var(--p-duration, 15s) / 5) var(--p-delay, 0s) ease-in-out infinite alternate;
}

/* Per-petal choreography. Prime-ish durations keep the loop from
   visibly re-syncing. */
.petal:nth-child(1)  { left:  4%; --p-size: 15px; --p-duration: 17s; --p-delay:  0s;   --p-drift:   70px; --p-spin: 480deg;  --p-opacity: 0.55; }
.petal:nth-child(2)  { left: 12%; --p-size: 11px; --p-duration: 23s; --p-delay: -4s;   --p-drift:  -50px; --p-spin: -620deg; --p-opacity: 0.4;  --p-scale: 0.9; }
.petal:nth-child(3)  { left: 21%; --p-size: 19px; --p-duration: 14s; --p-delay: -9s;   --p-drift:   95px; --p-spin: 720deg;  --p-opacity: 0.6;  }
.petal:nth-child(4)  { left: 29%; --p-size: 13px; --p-duration: 20s; --p-delay: -2s;   --p-drift:  -80px; --p-spin: 400deg;  --p-opacity: 0.45; }
.petal:nth-child(5)  { left: 38%; --p-size: 17px; --p-duration: 26s; --p-delay: -13s;  --p-drift:   40px; --p-spin: -540deg; --p-opacity: 0.5;  --p-scale: 1.1; }
.petal:nth-child(6)  { left: 47%; --p-size: 10px; --p-duration: 16s; --p-delay: -6s;   --p-drift:  110px; --p-spin: 660deg;  --p-opacity: 0.35; --p-scale: 0.85; }
.petal:nth-child(7)  { left: 56%; --p-size: 18px; --p-duration: 21s; --p-delay: -17s;  --p-drift:  -65px; --p-spin: 580deg;  --p-opacity: 0.58; }
.petal:nth-child(8)  { left: 64%; --p-size: 12px; --p-duration: 15s; --p-delay: -3s;   --p-drift:   85px; --p-spin: -700deg; --p-opacity: 0.42; }
.petal:nth-child(9)  { left: 73%; --p-size: 16px; --p-duration: 24s; --p-delay: -11s;  --p-drift:  -95px; --p-spin: 520deg;  --p-opacity: 0.5;  --p-scale: 1.05; }
.petal:nth-child(10) { left: 81%; --p-size: 14px; --p-duration: 18s; --p-delay: -7s;   --p-drift:   55px; --p-spin: 640deg;  --p-opacity: 0.46; }
.petal:nth-child(11) { left: 89%; --p-size: 20px; --p-duration: 27s; --p-delay: -20s;  --p-drift:  -45px; --p-spin: -460deg; --p-opacity: 0.52; }
.petal:nth-child(12) { left: 96%; --p-size: 11px; --p-duration: 19s; --p-delay: -15s;  --p-drift:  -120px;--p-spin: 760deg;  --p-opacity: 0.38; --p-scale: 0.95; }

/* ------------------------------------------------------------------
   3. SCROLL REVEAL

   Reveals run as ANIMATIONS, not transitions, for two reasons:

   a) A `transition` shorthand on `[data-stagger] > *` would override
      the one each card declares for itself (equal specificity, and
      this sheet loads last), silently killing the hover lift and the
      shadow fade on every card that happens to sit inside a stagger
      group. Animations leave `transition` untouched.

   b) The displacement animates `translate`, the independent transform
      property — so `transform: translateY(-8px)` on :hover composes
      with it instead of fighting it.

   The IntersectionObserver in animations.js adds .is-visible once.
   ------------------------------------------------------------------ */
@keyframes reveal-up    { from { opacity: 0; translate: 0 44px;  } to { opacity: 1; translate: 0 0; } }
@keyframes reveal-down  { from { opacity: 0; translate: 0 -44px; } to { opacity: 1; translate: 0 0; } }
@keyframes reveal-left  { from { opacity: 0; translate: -56px 0; } to { opacity: 1; translate: 0 0; } }
@keyframes reveal-right { from { opacity: 0; translate: 56px 0;  } to { opacity: 1; translate: 0 0; } }
@keyframes reveal-zoom  { from { opacity: 0; scale: 0.92;        } to { opacity: 1; scale: 1;      } }
@keyframes reveal-fade  { from { opacity: 0;                     } to { opacity: 1;                } }
@keyframes reveal-line  { from { translate: 0 100%;              } to { translate: 0 0;            } }

/* Hidden until observed. `will-change` is scoped to this state, so the
   compositor hint is dropped the moment the element settles. */
[data-reveal]:not(.is-visible),
[data-stagger]:not(.is-visible) > * {
    opacity: 0;
    will-change: translate, opacity;
}

[data-reveal].is-visible {
    animation-duration: 0.9s;
    animation-timing-function: var(--ease-out);
    animation-fill-mode: both;
    animation-delay: var(--reveal-delay, 0s);
}

[data-reveal="up"].is-visible    { animation-name: reveal-up;    }
[data-reveal="down"].is-visible  { animation-name: reveal-down;  }
[data-reveal="left"].is-visible  { animation-name: reveal-left;  }
[data-reveal="right"].is-visible { animation-name: reveal-right; }
[data-reveal="zoom"].is-visible  { animation-name: reveal-zoom;  }
[data-reveal="fade"].is-visible  { animation-name: reveal-fade;  }

/* Staggered children. animations.js writes each child's
   animation-delay inline from its index. */
[data-stagger].is-visible > * {
    animation-name: reveal-up;
    animation-duration: 0.75s;
    animation-timing-function: var(--ease-out);
    animation-fill-mode: both;
}

/* Text lines that wipe upward from a clipping mask. */
.reveal-text {
    display: block;
    overflow: hidden;
}
.reveal-text > span {
    display: block;
    translate: 0 100%;
}
.is-visible .reveal-text > span,
.reveal-text.is-visible > span {
    animation: reveal-line 1s var(--ease-out) var(--reveal-delay, 0s) both;
}

/* ------------------------------------------------------------------
   4. REDUCED MOTION
   Honour the OS setting: keep every reveal in its final state and
   silence the decorative loops entirely.
   ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    .petals { display: none; }

    /* Show every revealable element in its settled state, and cancel
       the keyframes outright rather than merely shortening them. */
    [data-reveal],
    [data-stagger] > * {
        opacity: 1 !important;
        animation: none !important;
        translate: none !important;
        scale: none !important;
        will-change: auto !important;
    }
    .reveal-text > span { animation: none !important; translate: none !important; }

    .hero__media img { animation: none; }
    .marquee__track  { animation: none; }
    .process__progress { transform: scaleX(1); }
}
