/*
 * Motion primitives — keyframes + utility classes consumed by marketing
 * surfaces, AppShell chrome, and the dashboard re-imagination.
 *
 * Every animation here uses `var(--motion-duration-*)` so the
 * `prefers-reduced-motion: reduce` cascade in tokens.css collapses the
 * duration to 0ms without per-rule conditionals. Consumers compose via
 * utility classes (`.motion-fade-in-up`) or the keyframes directly.
 *
 * Crisp-tech aesthetic: motion is functional, not decorative. Entry
 * fades from below with a small offset; hovers lift on shadow + tiny
 * translate; CTAs glow on hover via the brand shadow token. Anything
 * longer than 500ms or larger than 8px of travel is out of style and
 * should not be added here.
 */

@keyframes companion-fade-in-up {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes companion-fade-in {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

@keyframes companion-glow-pulse {
    0%, 100% {
        box-shadow: var(--shadow-glow);
    }
    50% {
        box-shadow: 0 0 0 1px rgba(15, 95, 214, 0.25),
                    0 12px 32px -8px rgba(15, 95, 214, 0.5);
    }
}

@keyframes companion-theme-crossfade {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

/* ----- Utility classes ----------------------------------------------- */
/* These are opt-in: components add a class only when they want the
   effect. We deliberately don't apply animations to every component
   surface because most signed-in chrome should stay static for SRE-
   readability. */

.motion-fade-in-up {
    animation: companion-fade-in-up var(--motion-duration-slower)
        var(--motion-easing-emphasized) both;
}

.motion-fade-in {
    animation: companion-fade-in var(--motion-duration-normal)
        var(--motion-easing-standard) both;
}

/* Staggered child entrance — apply to a parent, children inherit a
   delay derived from their index. Up to 5 children covered; further
   children fall through to the cap (no point staggering past 1.2s, the
   user has moved on). The step is token-driven so reduced-motion users
   get a flat 0ms — pairing a custom animation with `.motion-stagger`
   then inherits the right behaviour for free instead of needing its
   own override. */
.motion-stagger > * {
    animation-delay: 0ms;
}

.motion-stagger > *:nth-child(2) {
    animation-delay: calc(var(--motion-stagger-step) * 1);
}

.motion-stagger > *:nth-child(3) {
    animation-delay: calc(var(--motion-stagger-step) * 2);
}

.motion-stagger > *:nth-child(4) {
    animation-delay: calc(var(--motion-stagger-step) * 3);
}

.motion-stagger > *:nth-child(5) {
    animation-delay: calc(var(--motion-stagger-step) * 4);
}

.motion-stagger > *:nth-child(n+6) {
    animation-delay: calc(var(--motion-stagger-step) * 5);
}

/* Hover-lift used on CTA buttons, feature cards, and nav items. The
   transition tokens already collapse under reduced motion. */
.motion-lift {
    transition:
        transform var(--motion-duration-fast) var(--motion-easing-standard),
        box-shadow var(--motion-duration-fast) var(--motion-easing-standard);
}

.motion-lift:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-md);
}

/* Scroll-reveal target. Markup-side opt-in via `data-reveal` (handled
   by scroll-reveal.js); the JS module sets `is-revealed` once the
   element crosses the viewport, which triggers the transition. */
[data-reveal] {
    opacity: 0;
    transform: translateY(12px);
    transition:
        opacity var(--motion-duration-slower) var(--motion-easing-emphasized),
        transform var(--motion-duration-slower) var(--motion-easing-emphasized);
    will-change: opacity, transform;
}

[data-reveal].is-revealed {
    opacity: 1;
    transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
    /* Belt-and-braces: the token cascade already collapses durations,
       but motion utilities that derive their own keyframe motion (the
       glow-pulse, for example) need to be flat-stopped too. */
    .motion-fade-in-up,
    .motion-fade-in {
        animation: none;
        opacity: 1;
        transform: none;
    }

    .motion-lift:hover {
        transform: none;
    }

    [data-reveal] {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

@media (forced-colors: active) {
    /* In Windows High Contrast, animations are visually pointless
       (the OS palette is a small set of solid colours) and the
       reveal opacity dance can hide content from screen readers if
       JS fails. Flat-stop everything. */
    .motion-fade-in-up,
    .motion-fade-in {
        animation: none;
        opacity: 1;
        transform: none;
    }

    [data-reveal] {
        opacity: 1;
        transform: none;
        transition: none;
    }
}
