/* hero.css: hero section builder's motion rules (spec §4.1, §7). Loaded after site.css; the static
   hero layout stays in site.css (=== section: hero ===). Everything here is scoped under .motion,
   except the load settle (a CSS animation, so it starts on first paint, before any JS runs). */

/* Load settle (§4.1): the wrapper, not the img, breathes 1.06 -> 1 (origin 50% 40%, the face), so it
   is a slow zoom-out of the cover. The individual `scale` property composes with nothing else on this
   element (the scrub only tweens its clip-path). Off under reduced motion; visible throughout. */
@media (prefers-reduced-motion: no-preference){
  .hero__photo{ animation: hero-settle 1.8s var(--ease-out) backwards; }
  .hero__photo img{ transition: opacity .45s var(--ease-out); }
}
/* JS, image still loading at boot (site.js): hold the settle and fade the cover in once it is decoded */
.hero__photo.is-loading{ animation: none; }
.hero__photo.is-loading img{ opacity: 0; transition: none; }   /* hide at once; the fade is on the way in */
@keyframes hero-settle{ from{ scale: 1.06; } to{ scale: 1; } }

/* Scroll track: 220svh with a sticky 100svh stage. CSS sticky, never a ScrollTrigger pin. */
.motion .hero{ height: 220svh; }
.motion .hero__stage{ position: sticky; top: 0; }
.motion .hero:not(.hero--past) .hero__photo img{ will-change: transform; }   /* dropped once the track has passed */
/* while hero.js has the H1 split, each line clips its chars: they leave through their own line box and
   never rise into the header (top edge only; the text shadow keeps its sides and bottom) */
.hero__copy h1.is-split > .t-sans{ clip-path: inset(-2px -40px -40px -40px); }
/* hero.js tweens the 12-value inset() string as --hero-clip (Chrome would re-serialize a clip-path
   tween's ends compactly and break the interpolation); without it the photo stays full-bleed. */
.motion .hero--live .hero__photo{ clip-path: var(--hero-clip, none); }

/* Nav theme zones (§4.0; the .hero itself is dark: Vanilla ink over the scrimmed cover).
   Light: from the scroll where the shrinking photo's top edge reaches the header's controls (hero.js sets
   --hero-light-top from the scrub's ease; ≈ 0.17 H at 844 tall; the bar gets its backing there too) until
   the dark zone takes over.
   Dark: its top crosses the header line at scroll = 0.5 H. Later in document order wins. */
.motion .hero__light-zone, .motion .hero__dark-zone{ display: block; position: absolute; left: 0; width: 1px; bottom: 0; pointer-events: none; }
.motion .hero__light-zone{ top: var(--hero-light-top, calc(17svh + 32px + env(safe-area-inset-top, 0px))); }
.motion .hero__dark-zone{ top: calc(50svh + 32px + env(safe-area-inset-top, 0px)); }

/* Scroll-only layers: above the photo (1) and the copy (2). */
.motion .sig--hero, .motion .hero__handle{ display: block; position: absolute; z-index: 3; pointer-events: none; }
/* Invisible until hero.js has put them in their from-state (signature armed: mask on, nothing inked; chars
   lowered), so a fully drawn signature never flashes over the cover while the page boots. */
.motion .hero:not(.hero--live) .sig--hero,
.motion .hero:not(.hero--live) .hero__handle{ visibility: hidden; }

/* Signature (Lorena's LM, Vanilla ink): 92% of the stage (max 560 px), and at most 50svh so on short screens it
   keeps its proportion to the card (.33 H wide); it overflows the card's sides, as in the reference. hero.js
   sets its top (--sig-top: just under her chin, its baseline inside the card's lower edge) and, where the card
   is too short for that, a narrower width (--sig-w, down to 44svh); 54% is only a fallback. */
.sig--hero{ left: 50%; top: var(--sig-top, 54%); width: var(--sig-w, min(92%, 560px, 50svh)); color: var(--vanilla); translate: -50% 0; }

/* Rising handle: Sand eyebrow, centred 24 px above the card; the line box clips the rising chars. */
.hero__handle{ left: var(--pad-x-l); right: var(--pad-x-r); top: calc(20% - 24px); translate: 0 -100%;
  margin: 0; text-align: center; color: var(--sand); overflow: clip; padding-block: .15em; }
