/* =============================================================================
   Agentics — hero.css  (shared living-hero presentation layer)
   Pairs with hero-engine.js.  Load order:  tokens.css -> site.css -> hero.css.
   Uses ONLY existing tokens (proof axis, --ease-spring, --dur-*, --grad-brand).
   No new design tokens (per GLOBAL PRINCIPLES #9).

   Responsibilities:
     • Position the ambient flow-field canvas BEHIND hero content, aria-hidden,
       pointer-events:none, never the LCP element, contributes ~0 CLS.
     • Provide entrance start-states + will-change discipline (removed post-reveal).
     • Provide a static END-STATE poster path for reduced motion (WCAG 2.3.3):
       the engine never starts the rAF loop; CSS shows the resolved scene.
   ============================================================================= */

/* ---------------------------------------------------------------------------
   1. HERO STAGE  (the positioned container the canvas + content share)
   --------------------------------------------------------------------------- */
.hero-stage {
  position: relative;
  isolation: isolate;            /* own stacking context: canvas can't escape */
  overflow: clip;                /* trails never bleed past the hero */
}

/* The shared ambient flow-field canvas. AMBIENT ONLY — decorative, never a
   telemetry feed (honesty discipline), so it is aria-hidden + inert. */
.hero-flow {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: var(--z-atmos, -2);   /* behind content; never the LCP element */
  display: block;
  pointer-events: none;
  /* Edge fade so the field dissolves into the page rather than hard-clipping. */
  -webkit-mask-image: radial-gradient(120% 120% at 50% 40%, #000 55%, transparent 100%);
          mask-image: radial-gradient(120% 120% at 50% 40%, #000 55%, transparent 100%);
  /* Animate the bitmap only — no layout/paint of siblings, ~0 CLS. */
  will-change: contents;
  contain: strict;
  opacity: 0.9;
}

/* Content sits above the field. */
.hero-stage > :not(.hero-flow) { position: relative; z-index: var(--z-base, 0); }

/* ---------------------------------------------------------------------------
   2. WAAPI ENTRANCE START-STATES
   The engine drives the actual motion with the Web Animations API (fill:both),
   but we set the *visual* start-state in CSS so there is no flash of the
   final frame before hero-engine.js runs (it loads deferred).
   `.reveal-ready` is added to <html> by site.js once JS is alive — mirrors the
   existing reveal contract so a no-JS / failed-load page shows full content.
   --------------------------------------------------------------------------- */
.reveal-ready .hero-anim {
  opacity: 0;
  will-change: transform, opacity;
}
.reveal-ready .hero-anim[data-preset="fade-up"],
.reveal-ready .hero-anim[data-preset="rise"] { transform: translateY(16px); }
.reveal-ready .hero-anim[data-preset="fade-left"] { transform: translateX(-18px); }
.reveal-ready .hero-anim[data-preset="fade-right"] { transform: translateX(18px); }
.reveal-ready .hero-anim[data-preset="scale"] { transform: scale(0.92); }
.reveal-ready .hero-anim[data-preset="anchor"] { transform: scale(0.6); }

/* Drop will-change once the entrance has played (engine adds .is-anchored
   to the stage on timeline finish). Keeps the compositor layer count low. */
.hero-stage.is-anchored .hero-anim { will-change: auto; }

/* The signature "anchor lands" pop, available as a pure-CSS utility too
   (used by the reduced-data / progressive-enhancement path). */
.hero-anchor-pop {
  animation: hero-anchor-pop var(--dur-4, 560ms) var(--ease-spring, cubic-bezier(.34,1.56,.64,1)) both;
}
@keyframes hero-anchor-pop {
  from { opacity: 0; transform: scale(0.6); }
  60%  { opacity: 1; }
  to   { opacity: 1; transform: scale(1); }
}

/* SVG draw-on (proof mesh / spine drop-lines). The engine can drive these via
   the `draw` preset; this is the CSS fallback. */
.hero-draw {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: hero-draw var(--dur-4, 560ms) var(--ease-inout, cubic-bezier(.65,.05,.36,1)) forwards;
}
@keyframes hero-draw { to { stroke-dashoffset: 0; } }

/* ---------------------------------------------------------------------------
   3. PROOF-AXIS GLYPH STATES (shared classes the heroes can color a node by)
   Color is STATUS, not decoration — uses the signal spectrum tokens directly.
   --------------------------------------------------------------------------- */
.proof-ember  { color: var(--danger); }
.proof-warm   { color: var(--warn); }
.proof-cyan   { color: var(--info); }
.proof-anchor { color: var(--accent); }

/* ---------------------------------------------------------------------------
   4. REDUCED MOTION  (WCAG 2.3.3) — render the static END-STATE poster.
   The engine already refuses to start the rAF loop; here we make the DOM show
   the resolved/anchored scene with zero animation. Belt-and-suspenders so the
   poster is correct even if the engine never executes.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .hero-anim,
  .reveal-ready .hero-anim {
    opacity: 1 !important;
    transform: none !important;
    will-change: auto !important;
    animation: none !important;
    transition: none !important;
  }
  .hero-anchor-pop,
  .hero-draw {
    animation: none !important;
  }
  .hero-draw { stroke-dashoffset: 0 !important; }

  /* The canvas keeps its single static poster frame the engine painted; if the
     engine never ran, dim it so it reads as a still backdrop, not a dead feed. */
  .hero-flow { opacity: 0.7; }
}

/* Honor coarse-pointer / low-power the same way the engine hard-offs the loop:
   the canvas stays a static poster, no perpetual motion on touch devices. */
@media (pointer: coarse) {
  .hero-flow { opacity: 0.8; }
}
