/* ==========================================================================
   THEME — 06 motion
   --------------------------------------------------------------------------
   Scroll reveals and entrance animations. Every rule here is transform or
   opacity only, so the compositor handles them and layout is never
   recalculated mid-animation.

   `.no-js` / `[data-reveal="off"]` disable the effect entirely, and the
   prefers-reduced-motion block at the bottom removes the remaining continuous
   animations.
   ========================================================================== */

/* ---- Scroll reveal ---------------------------------------------------------
   The element starts offset and faded, then app.js adds `.is-revealed` when it
   enters the viewport via IntersectionObserver.

   Everything is scoped under `html.js` — the class is set by an inline script
   in <head> before first paint. If that script or app.js never runs, no
   element is ever hidden, so a JS failure can never blank the page. */
.js [data-reveal] {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity var(--dur-slower) var(--ease-out),
                transform var(--dur-slower) var(--ease-out);
    transition-delay: var(--reveal-delay, 0ms);
    will-change: opacity, transform;
}

.js [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
    will-change: auto;
}

.js [data-reveal="left"]  { transform: translateX(-32px); }
.js [data-reveal="right"] { transform: translateX(32px); }
.js [data-reveal="scale"] { transform: scale(.94); }

.js [data-reveal="left"].is-revealed,
.js [data-reveal="right"].is-revealed,
.js [data-reveal="scale"].is-revealed {
    transform: none;
}

/* Stagger: --reveal-delay is set inline by the view, e.g. style="--reveal-delay:120ms" */
[data-reveal][style*="--reveal-delay"] { transition-delay: var(--reveal-delay); }

/* ---- Hero entrance --------------------------------------------------------
   Plays once on load. Removed from the DOM's critical path by the class
   toggling to `.is-entered`, after which no animation remains. */
.p-hero [data-enter] {
    opacity: 0;
    transform: translateY(24px);
    animation: enter-up .7s var(--ease-out) forwards;
    animation-delay: calc(var(--enter-delay, 0) * 1ms);
}

@keyframes enter-up {
    to { opacity: 1; transform: none; }
}

/* ---- Floating accent ------------------------------------------------------ */
.p-float {
    animation: p-float-y 6s var(--ease-in-out) infinite;
}

.p-float--delay {
    animation-delay: -3s;
}

@keyframes p-float-y {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-12px); }
}

/* ---- Interactive lift ----------------------------------------------------- */
.p-lift {
    transition: transform var(--dur-base) var(--ease-out),
                box-shadow var(--dur-base) var(--ease-out);
}

.p-lift:hover {
    transform: translateY(-4px);
    box-shadow: var(--sh-lg);
}

/* ---- Number counter flash ------------------------------------------------- */
.p-counting {
    animation: count-flash .5s var(--ease-out);
}

@keyframes count-flash {
    0%   { color: var(--brand); }
    100% { color: inherit; }
}

/* ---- Drawer / modal backdrop --------------------------------------------- */
.t-scrim.is-open { transition-duration: var(--dur-base); }

/* ---- Reduced motion -------------------------------------------------------
   The one rule that matters most. Everything continuous stops; everything
   triggered resolves to its final state immediately so no content is ever
   left invisible. */
@media (prefers-reduced-motion: reduce) {
    .grad-text,
    .p-cta,
    .p-hero__blob,
    .p-hero__dot::after,
    .p-float,
    .p-counting {
        animation: none !important;
    }

    /* Entrance states must end up visible, not stuck at opacity 0. */
    .js [data-reveal] {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }

    .p-hero [data-enter] {
        opacity: 1;
        transform: none;
        animation: none;
    }

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

    html {
        scroll-behavior: auto;
    }
}

/* ---- Opt-out hook ---------------------------------------------------------
   Set data-reveal="off" on <html> (or any ancestor) to disable reveals without
   touching the user's OS preference. */
[data-reveal="off"] [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
}

[data-reveal="off"] .p-float,
[data-reveal="off"] .p-hero__blob,
[data-reveal="off"] .p-marquee__track {
    animation: none;
}
