/* ════════════════════════════════════════════════════════════════════════════
   supernova-09 · Stage 9 DESIGN · css/motion.css
   Motion layer for the Terminal Observatory register — motion_profile absent
   from the stage-3 build-plan and no WebGL/lenis/GSAP engines were locked at
   Stage 6, so the entire layer is CSS-native (degradation documented in
   DESIGN.md §9). Everything the register promises is here:

     · lead glitch bursts      — RGB-split chromatic layers, ~7s cycle
                                 (dir: lead_glitch — user favourite)
     · blinking cursor block   — prompt grammar
     · live telemetry marker   — blinking ▋
     · CTA pill halo           — slow rose pulse under .js
     · telemetry bar draw-in   — rose→green sweep under .js
     · scroll reveals          — IntersectionObserver adds .is-revealed
                                 (js/motion.js ships at BUILD; the CSS
                                 contract lives here, .js-gated so no-JS
                                 and reduced-motion always show content)
     · chrome hide             — transition lives in layout.css
   Reduced motion: everything snaps to its final state — content is never
   hidden. Duration/easing values are tokens from css/tokens.css.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── scroll reveal (IntersectionObserver adds .is-revealed) ──────────────────
   Progressive: content is visible by default; only when the build adds the
   `js` class to <html> (inline script at BUILD) does .reveal start hidden. */
.reveal{ opacity:1; transform:none; }
html.js .reveal{
  opacity:0;
  transform:translateY(var(--sp-18));
  transition:opacity var(--dur-reveal) var(--ease-default),
             transform var(--dur-reveal) var(--ease-default);
  transition-delay:var(--reveal-delay,0s);
  will-change:opacity,transform;
}
html.js .reveal.is-revealed{
  opacity:1;
  transform:none;
}
/* stagger helper — BUILD sets data-i; delay increments come from the
   --stagger-step token so motion.css carries no raw timing values */
.reveal[data-i="1"]{ --reveal-delay:var(--stagger-step); }
.reveal[data-i="2"]{ --reveal-delay:calc(var(--stagger-step) * 2); }
.reveal[data-i="3"]{ --reveal-delay:calc(var(--stagger-step) * 3); }
.reveal[data-i="4"]{ --reveal-delay:calc(var(--stagger-step) * 4); }
.reveal[data-i="5"]{ --reveal-delay:calc(var(--stagger-step) * 5); }

/* ── lead glitch bursts — chromatic ghosts over the headline ─────────────────
   The ::before/::after layers from components.css carry the rose/green text;
   these keyframes slice and displace them in short bursts on a slow cycle.
   Reduced-motion keeps them at opacity 0 — the real headline stays. */
.glitch::before{ animation:glitchBurstA var(--dur-glitch) step-end infinite; }
.glitch::after{ animation:glitchBurstB var(--dur-glitch) step-end infinite; }
@keyframes glitchBurstA{
  0%, 79.9%{ opacity:0; }
  80%{ opacity:.85; transform:translate(-4px,1px); clip-path:inset(6% 0 58% 0); }
  82.5%{ opacity:.9; transform:translate(3px,-1px); clip-path:inset(52% 0 8% 0); }
  85%{ opacity:0; }
  92%{ opacity:.65; transform:translate(-5px,0); clip-path:inset(0 0 80% 0); }
  94%{ opacity:0; }
}
@keyframes glitchBurstB{
  0%, 79.9%{ opacity:0; }
  80.5%{ opacity:.8; transform:translate(4px,-1px); clip-path:inset(28% 0 42% 0); }
  83%{ opacity:.9; transform:translate(-3px,1px); clip-path:inset(72% 0 6% 0); }
  86%{ opacity:0; }
  92.5%{ opacity:.6; transform:translate(5px,0); clip-path:inset(10% 0 64% 0); }
  94.5%{ opacity:0; }
}

/* ── blinking cursor block (prompt grammar) ────────────────────────────────── */
.cursor{ animation:blockBlink var(--dur-cursor) var(--ease-snap) infinite; }
@keyframes blockBlink{ 50%{ opacity:0; } }

/* ── live telemetry marker ▋ ───────────────────────────────────────────────── */
.live::after{ animation:blockBlink var(--dur-blink) var(--ease-snap) infinite; }

/* ── CTA pill halo — slow rose pulse (progressive: .js-gated) ──────────────── */
.js .pill--pulse{ animation:pillHalo var(--dur-pulse) var(--ease-smooth) infinite; }
@keyframes pillHalo{
  0%, 100%{ box-shadow:0 0 0 0 var(--pill-glow-spread); }
  50%{ box-shadow:0 0 0 var(--sp-5) var(--pill-glow-edge); }
}

/* ── telemetry bar draw-in (rose→green sweep; .js-gated, base in components) */
@keyframes telemetryGrow{
  from{ transform:scaleX(0); }
  to{ transform:scaleX(1); }
}

/* ── micro-interactions — explicit property lists only (Ban #8) ────────────── */
.chrome .crumb a,
.foot a,
.pill,
.faq summary,
.win.is-clickable{
  transition-property:color,background-color,box-shadow,border-color,transform;
  transition-duration:var(--dur-micro);
  transition-timing-function:var(--ease-default);
}

/* ── reduced motion: snap to final state, never hide content ───────────────── */
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  html.js .reveal,
  .reveal,
  .reveal.is-revealed{
    opacity:1 !important;
    transform:none !important;
    transition:none !important;
  }
  .glitch::before,
  .glitch::after{ animation:none; opacity:0; }
  .cursor,
  .live::after{ animation:none; opacity:1; }
  .js .pill--pulse{ animation:none; }
  .js .bar i,
  .bar i{ animation:none; transform:scaleX(1); }
  .chrome,
  .pill,
  .faq summary,
  .win.is-clickable,
  .chrome .crumb a,
  .foot a{ transition:none; }
  .win.off,
  .win.offr{ transform:none; }
  .deck::after{ animation:none; }
}
/* manual-toggle light must behave like the media query for motion too —
   [data-theme] never changes animation needs, only the media does, so no
   extra rules required here (content is visible in both). */
