/* motion.css
   Consumes the --motion-* tokens generated from design/tokens.json.

   THE RULE THAT GOVERNS THIS FILE:
   Nothing is hidden in base CSS. Every pre-animation state is scoped behind
   .js, which motion.js stamps on <html> before first paint. If JavaScript is
   disabled, blocked, or fails, no rule below applies and every section renders
   at its final state. The AEO architecture depends on this, and so does anyone
   reading the page with assistive technology or a text browser.

   Everything also collapses to final state under prefers-reduced-motion.
*/

/* ---------------------------------------------------------------------- */
/* Scroll reveals                                                         */
/* ---------------------------------------------------------------------- */

.js .reveal {
  opacity: 0;
  transform: translateY(var(--motion-reveal-distance));
  transition: opacity var(--motion-duration-base) var(--motion-ease-out),
              transform var(--motion-duration-base) var(--motion-ease-out);
}
.js .reveal.is-visible { opacity: 1; transform: none; }

/* Staggered children within a revealed group. */
.js .reveal-group > * {
  opacity: 0;
  transform: translateY(var(--motion-reveal-distance));
  transition: opacity var(--motion-duration-base) var(--motion-ease-out),
              transform var(--motion-duration-base) var(--motion-ease-out);
}
.js .reveal-group.is-visible > * { opacity: 1; transform: none; }
.js .reveal-group.is-visible > *:nth-child(1) { transition-delay: 0ms; }
.js .reveal-group.is-visible > *:nth-child(2) { transition-delay: calc(var(--motion-stagger) * 1); }
.js .reveal-group.is-visible > *:nth-child(3) { transition-delay: calc(var(--motion-stagger) * 2); }
.js .reveal-group.is-visible > *:nth-child(4) { transition-delay: calc(var(--motion-stagger) * 3); }
.js .reveal-group.is-visible > *:nth-child(5) { transition-delay: calc(var(--motion-stagger) * 4); }
.js .reveal-group.is-visible > *:nth-child(6) { transition-delay: calc(var(--motion-stagger) * 5); }

/* ---------------------------------------------------------------------- */
/* Hero entrance. One orchestrated sequence, under 900ms total.           */
/* ---------------------------------------------------------------------- */

.js .hero-seq > * {
  opacity: 0;
  transform: translateY(var(--motion-hero-reveal-distance));
  transition: opacity 600ms var(--motion-ease-out),
              transform 600ms var(--motion-ease-out);
}
.js .hero.is-ready .hero-seq > * { opacity: 1; transform: none; }

/* Beat timings from the approved plan, section 3. */
.js .hero.is-ready .hero-seq > .hero-eyebrow  { transition-delay: 40ms; }
.js .hero.is-ready .hero-seq > .hero-title    { transition-delay: 80ms; }
.js .hero.is-ready .hero-seq > .hero-lead     { transition-delay: 300ms; }
.js .hero.is-ready .hero-seq > .hero-actions  { transition-delay: 380ms; }

.js .hero .audience-card {
  opacity: 0;
  transform: translateY(var(--motion-hero-reveal-distance));
  transition: opacity 600ms var(--motion-ease-out),
              transform 600ms var(--motion-ease-out),
              background-color var(--motion-duration-fast) var(--motion-ease-out),
              border-color var(--motion-duration-fast) var(--motion-ease-out);
}
.js .hero.is-ready .audience-card { opacity: 1; transform: none; }
.js .hero.is-ready .audience-card:nth-child(1) { transition-delay: 460ms; }
.js .hero.is-ready .audience-card:nth-child(2) { transition-delay: 520ms; }

/* The hero backdrop is already painted and never animates, so the composed
   sequence never fights a loading image. */

/* ---------------------------------------------------------------------- */
/* Converging-lines diagram                                               */
/* ---------------------------------------------------------------------- */

.js .converge-path {
  stroke-dasharray: var(--path-length, 600);
  stroke-dashoffset: var(--path-length, 600);
  transition: stroke-dashoffset var(--motion-duration-draw) var(--motion-ease-in-out);
}
.js .converge.is-visible .converge-path { stroke-dashoffset: 0; }

.js .converge-node { opacity: 0; transition: opacity 400ms var(--motion-ease-out); }
.js .converge.is-visible .converge-node { opacity: 1; }
.js .converge.is-visible .converge-node:nth-of-type(1) { transition-delay: 120ms; }
.js .converge.is-visible .converge-node:nth-of-type(2) { transition-delay: 220ms; }
.js .converge.is-visible .converge-node:nth-of-type(3) { transition-delay: 320ms; }
.js .converge.is-visible .converge-node:nth-of-type(4) { transition-delay: 420ms; }

.js .converge-target {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(0.4);
  transition: opacity 300ms var(--motion-ease-out),
              transform 500ms var(--motion-ease-out);
}
.js .converge.is-visible .converge-target {
  opacity: 1; transform: scale(1);
  transition-delay: var(--motion-duration-draw);
}

/* A single soft pulse on arrival. Runs once, does not loop. */
.js .converge.is-visible .converge-halo {
  animation: converge-pulse 900ms var(--motion-ease-out) 1 forwards;
  animation-delay: calc(var(--motion-duration-draw) + 200ms);
}
@keyframes converge-pulse {
  0%   { opacity: 0.5; transform: scale(0.85); }
  60%  { opacity: 0.18; transform: scale(1.25); }
  100% { opacity: 0.25; transform: scale(1); }
}
.js .converge-halo { transform-box: fill-box; transform-origin: center; opacity: 0; }

/* ---------------------------------------------------------------------- */
/* Full-bleed image bands, slow scale across the scroll range             */
/* ---------------------------------------------------------------------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .band-image .band-image-media img,
    .hero-media img {
      animation: band-drift linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
    }
    @keyframes band-drift {
      from { transform: scale(1); }
      to   { transform: scale(1.06); }
    }
  }
}

/* ---------------------------------------------------------------------- */
/* View transitions between pages, progressive enhancement               */
/* ---------------------------------------------------------------------- */

@view-transition { navigation: auto; }

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: vt-fade-out 120ms ease both; }
  ::view-transition-new(root) { animation: vt-fade-in 200ms ease both; }
  @keyframes vt-fade-out { to { opacity: 0; } }
  @keyframes vt-fade-in { from { opacity: 0; } }
}

/* ---------------------------------------------------------------------- */
/* Reduced motion. Everything lands at final state.                       */
/* ---------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .js .reveal,
  .js .reveal-group > *,
  .js .hero-seq > *,
  .js .hero .audience-card,
  .js .converge-node,
  .js .converge-target {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    transition-delay: 0ms !important;
  }
  .js .converge-path {
    stroke-dashoffset: 0 !important;
    transition: none !important;
  }
  .js .converge-halo { animation: none !important; opacity: 0.25 !important; }
  .team-photo { filter: grayscale(1); transition: none; }
  .btn .arrow, .audience-card .arrow, .service-card h3::after { transition: none !important; }
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; }
}
