/* Shared motion system — scroll-reveal, hero entrance, page transitions.
   Loaded by every page (hand-authored + scripts/generate-seo.mjs's page() shell).
   New tokens only — never redefines --dur-micro/--dur-transition/--dur-showcase/--ease-standard,
   which already exist on every page and remain in use elsewhere. */
:root {
    --dur-button: 220ms;
    --dur-dropdown: 260ms;
    --dur-faq: 300ms;
    --dur-modal-open: 300ms;
    --dur-modal-close: 220ms;
    --dur-page-transition: 300ms;
    --dur-reveal: 600ms;
    --ease-reveal: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ============ Scroll reveal ============
   Visible by default — crawler-safe and no-JS-safe by construction.
   Only becomes hidden-pending-animation once <html> has .js-ready, which is
   added by a synchronous inline script at the very top of <head> on each page.
   motion.js then adds .is-visible via IntersectionObserver on first intersect. */
.reveal {
    opacity: 1;
    transform: none;
}

html.js-ready .reveal {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity var(--dur-reveal) var(--ease-reveal),
                transform var(--dur-reveal) var(--ease-reveal);
}

html.js-ready .reveal.is-visible {
    opacity: 1;
    transform: none;
}

/* Stagger for direct children of a .reveal-stagger container — 90ms steps,
   capped at 8 so a long sequence never exceeds ~900ms end-to-end. */
.reveal-stagger > .reveal:nth-child(1) { transition-delay: 0ms; }
.reveal-stagger > .reveal:nth-child(2) { transition-delay: 90ms; }
.reveal-stagger > .reveal:nth-child(3) { transition-delay: 180ms; }
.reveal-stagger > .reveal:nth-child(4) { transition-delay: 270ms; }
.reveal-stagger > .reveal:nth-child(5) { transition-delay: 360ms; }
.reveal-stagger > .reveal:nth-child(6) { transition-delay: 450ms; }
.reveal-stagger > .reveal:nth-child(7) { transition-delay: 540ms; }
.reveal-stagger > .reveal:nth-child(n+8) { transition-delay: 630ms; }

/* ============ Hero entrance (load-triggered, not scroll-triggered) ============
   Runs automatically once .js-ready is present (added before first paint), so no
   JS trigger is needed beyond the bootstrap script. Per-element stagger via an
   inline `style="--enter-delay:180ms"` on the target element. */
@keyframes heroEnterUp {
    from { opacity: 0; transform: translateY(16px); }
    to { opacity: 1; transform: none; }
}

.hero-enter {
    opacity: 1;
    transform: none;
}

html.js-ready .hero-enter {
    opacity: 0;
    transform: translateY(16px);
    animation: heroEnterUp var(--dur-reveal) var(--ease-reveal) forwards;
    animation-delay: var(--enter-delay, 0ms);
}

/* ============ Homepage company-profile tab fade (fixes a latent bug: the
   .company-panel-panel rule references this keyframe but it was never defined,
   so tab switches previously animated with zero visible motion) ============ */
@keyframes ecosystemPanelIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: none; }
}

/* ============ Native page-to-page transitions ============
   Browser-owned, non-blocking by spec — cannot intercept clicks, delay unload,
   or break middle-click/back-forward. Unsupported browsers ignore this at-rule
   and navigate exactly as before: pure progressive enhancement. */
@view-transition {
    navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
    animation-duration: var(--dur-page-transition);
    animation-timing-function: var(--ease-reveal);
}

/* Defensive fallback: even on a page whose own <style> block hasn't yet been
   updated with a prefers-reduced-motion rule, this shared file's own reveal/
   entrance classes still respect the user's preference. */
@media (prefers-reduced-motion: reduce) {
    .reveal,
    html.js-ready .reveal,
    .hero-enter,
    html.js-ready .hero-enter {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
        animation: none !important;
    }

    @view-transition {
        navigation: none;
    }
}
