/* Launch-sequence hero.
 *
 * One number drives the whole scene: --p, scroll progress through the hero, 0 to 1.
 *  - Where CSS scroll-driven animation exists, the browser animates --p from the hero's scroll
 *    position (no JavaScript needed).
 *  - Elsewhere, js/hero.js writes --p on scroll. Same styles, same look.
 *  - Reduced motion, or no JavaScript: hero-static.css freezes a calm composition instead.
 * Before either kicks in --p is 0, which is the opening frame (night, rocket on the pad).
 *
 * Nothing here uses inline styles (the site's CSP forbids them); JS sets --p through the CSSOM.
 * One art pixel is --px, so every sprite and hill line shares the same pixel grid.
 */
@property --p { syntax: "<number>"; inherits: true; initial-value: 0; }

.has-hero .site-header { position: absolute; inset: 0 0 auto; z-index: 30; }

.hero { position: relative; height: calc(100svh * 2.6); }

.hero__stage {
  position: sticky; top: 0;
  height: 100svh;
  overflow: clip;
  container-type: size;            /* lets children size themselves in cqh / cqw */
  background: var(--night-900);
  isolation: isolate;

  /* Choreography: each beat is a 0..1 value derived from --p. Tweak the numbers to re-time it. */
  --sky: clamp(0, (var(--p) - 0.08) / 0.7, 1);        /* night sky gives way to dawn */
  --sun: clamp(0, (var(--p) - 0.05) / 0.85, 1);       /* sun climbs from behind the hills */
  --stars: clamp(0, (var(--p) - 0.2) / 0.6, 1);       /* stars fade as it gets light */
  --ignite: clamp(0, (var(--p) - 0.08) / 0.08, 1);    /* engines light */
  --lift: clamp(0, (var(--p) - 0.16) / 0.6, 1);       /* rocket climbs away */
  --cam: clamp(0, (var(--p) - 0.16) / 0.7, 1);        /* camera tilts up: land drifts down */
  --welcome: clamp(0, 1 - (var(--p) - 0.12) / 0.2, 1);/* opening words fade before the rocket rises through */
  --arrive: clamp(0, (var(--p) - 0.78) / 0.15, 1);    /* closing line arrives */

  /* The beats above are progress (0..1). These turn three of them into levels between the current
     time of day's start and end values (--sun-from etc., set in "Time of day" below). */
  --sun-at: calc(var(--sun-from) + (var(--sun-to) - var(--sun-from)) * var(--sun));
  --stars-at: calc(var(--stars-from) + (var(--stars-to) - var(--stars-from)) * var(--stars));
  --rim-at: calc(var(--rim-from) + (var(--rim-to) - var(--rim-from)) * var(--sky));
}

.hero__scene {
  position: absolute; inset: 0;
  --px: min(0.75cqh, 1.4cqw);      /* one art pixel */
  pointer-events: none;
}
.hero__layer, .hero__hills, .hero__near { position: absolute; inset-inline: 0; }
.hero__layer { top: 0; bottom: 0; }
.hero__svg { width: 100%; height: 100%; }

/* Art colours: every palette name used in site/data/hero.yml maps to a design token. */
.px-outline { fill: var(--px-outline); }
.px-red { fill: var(--px-red); }
.px-red-dark { fill: var(--px-red-dark); }
.px-hull { fill: var(--px-hull); }
.px-hull-shade { fill: var(--px-hull-shade); }
.px-hull-dark { fill: var(--px-hull-dark); }
.px-window { fill: var(--px-window); }
.px-window-glow { fill: var(--px-window-glow); }
.px-steel { fill: var(--px-steel); }
.px-steel-light { fill: var(--px-steel-light); }
.px-steel-dark { fill: var(--px-steel-dark); }
.px-lamp { fill: var(--px-lamp); }
.px-flame-core { fill: var(--px-flame-core); }
.px-flame { fill: var(--px-flame); }
.px-flame-edge { fill: var(--px-flame-edge); }
.px-smoke { fill: var(--px-smoke); }
.px-sun-rim { fill: var(--px-sun-rim); }
.px-sun-outer { fill: var(--px-sun-outer); }
.px-sun-mid { fill: var(--px-sun-mid); }
.px-sun-core { fill: var(--px-sun-core); }
.px-star { fill: var(--cream); }

/* Sky: the opening sky underneath, the closing sky fading in on top. Which two, and how the sun,
   stars and rim light start and end, depends on the visitor's clock (see "Time of day" below). */
.hero__sky--open { background: var(--sky-open); }
.hero__sky--close { background: var(--sky-close); opacity: var(--sky); will-change: opacity; }

/* Stars: three depths. Farther ones are dimmer and drift less. */
.hero__stars { will-change: transform, opacity; opacity: var(--stars-at); }
.hero__stars { top: -10cqh; }
.hero__stars--far { transform: translateY(calc(var(--cam) * 2cqh)); }
.hero__stars--far .px-star { opacity: 0.5; }
.hero__stars--mid { transform: translateY(calc(var(--cam) * 4cqh)); }
.hero__stars--mid .px-star { opacity: 0.75; }
.hero__stars--near { transform: translateY(calc(var(--cam) * 7cqh)); }
.tw-a { animation: twinkle 3.1s ease-in-out infinite; }
.tw-b { animation: twinkle 4.3s ease-in-out -1.2s infinite; }
.tw-c { animation: twinkle 5.2s ease-in-out -2.6s infinite; }
@keyframes twinkle { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }

/* Sun: rises from behind the far hills, with a soft glow */
.hero__sun {
  position: absolute; left: 50%; bottom: calc(var(--px) * 12);
  width: calc(var(--px) * 30); aspect-ratio: 1;
  transform: translate(-50%, calc((1 - var(--sun-at)) * 34cqh));
  will-change: transform;
}
.hero__sun::before {
  content: ""; position: absolute; inset: -80%;
  background: radial-gradient(closest-side, rgb(255 191 92 / 0.55), rgb(255 138 107 / 0.22) 55%, transparent);
  opacity: clamp(0, var(--sun-at), 1);
}
.hero__sun-art { position: relative; width: 100%; height: 100%; }

/* Land: three depths, darker and closer to the page colour toward the front */
.hero__hills { bottom: 0; will-change: transform; }
.hero__hills .hero__svg { height: 100%; }
.hero__hills--far { height: calc(var(--px) * 40); transform: translateY(calc(var(--cam) * 6cqh)); }
.hero__hills--far .px-hill { fill: var(--indigo-700); }
.hero__hills--mid { height: calc(var(--px) * 40); transform: translateY(calc(var(--cam) * 10cqh)); }
.hero__hills--mid .px-hill { fill: var(--indigo-800); }
.hero__hills .px-rim { fill: var(--amber-500); opacity: var(--rim-at); }
.hero__hills--near { height: calc(var(--px) * 20); }
.hero__hills--near .px-hill { fill: var(--night-900); }   /* same as the page, so the hero lands softly */

/* Foreground: ground, launch pad and exhaust move together */
.hero__near { top: 0; bottom: 0; transform: translateY(calc(var(--cam) * 14cqh)); will-change: transform; }
.hero__pad {
  position: absolute; left: 50%; bottom: calc(var(--px) * 8);
  height: calc(var(--px) * 30); transform: translateX(-50%);
}
.hero__pad-art { height: 100%; width: auto; }

.hero__smoke {
  position: absolute; bottom: calc(var(--px) * 12); left: 50%;
  width: calc(var(--px) * 14);
  --puff: calc(0.5 + var(--ignite) * 0.4 + var(--lift) * 1.6);
  opacity: calc(var(--ignite) * 0.85 * (1 - clamp(0, (var(--p) - 0.42) / 0.3, 1)));
}
.hero__smoke--left { transform: translate(-115%, calc(var(--lift) * -3cqh)) scale(var(--puff)); transform-origin: 100% 100%; }
.hero__smoke--right { transform: translate(15%, calc(var(--lift) * -3cqh)) scale(calc(var(--puff) * -1), var(--puff)); transform-origin: 100% 100%; }
.hero__smoke-art { width: 100%; height: auto; }

/* Rocket: stands on the pad, then climbs out of the top of the frame */
.hero__rocket {
  position: absolute; left: 50%; bottom: calc(var(--px) * 12);
  width: calc(var(--px) * 16); height: calc(var(--px) * 35);
  transform: translate(-50%, calc(var(--lift) * var(--lift) * -125cqh));
  will-change: transform;
}
/* The one live thing in the scene: a tap or click on the rocket starts an easter-egg sky (js/eggs.js).
   It stays decorative to assistive tech; the Konami code is the keyboard way in. */
.hero__rocket { pointer-events: auto; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.hero__rocket-art { width: 100%; height: 100%; }
.hero__flame {
  position: absolute; top: 100%; left: 50%; width: calc(var(--px) * 8); height: calc(var(--px) * 9);
  transform: translateX(-50%) scaleY(calc(0.4 + var(--ignite) * 0.6 + var(--lift) * 1.2));
  transform-origin: 50% 0; opacity: var(--ignite);
}
.hero__flame-frame { position: absolute; inset: 0; }
.hero__flame-art { width: 100%; height: 100%; }
.hero__flame-frame--a { animation: flame-a 0.24s steps(1) infinite; }
.hero__flame-frame--b { animation: flame-b 0.24s steps(1) infinite; }
@keyframes flame-a { 0% { opacity: 1; } 50% { opacity: 0; } }
@keyframes flame-b { 0% { opacity: 0; } 50% { opacity: 1; } }

/* Words */
.hero__copy, .hero__arrival {
  position: absolute; inset-inline: 0; margin-inline: auto;
  width: min(100% - 2 * var(--gutter), 46rem);
  text-align: center; z-index: 5;
}
.hero__copy { top: clamp(6rem, 17cqh, 12rem); opacity: var(--welcome); transform: translateY(calc((1 - var(--welcome)) * -2.5rem)); }
.hero__copy p { margin-inline: auto; }
.hero__copy .eyebrow { color: var(--amber-300); }
.hero__title { margin-bottom: var(--space-4); text-shadow: none; }
.hero__lead { margin-inline: auto; font-size: var(--text-lg); color: var(--text); text-shadow: 0 1px 12px var(--night-950); }
.hero__hint {
  margin: var(--space-6) auto 0; font: 600 var(--text-sm) / 1 var(--font-pixel);
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--amber-300);
}
.hero__hint::after {
  content: ""; display: block; width: 0.7rem; height: 0.7rem; margin: var(--space-3) auto 0;
  border: solid var(--amber-300); border-width: 0 3px 3px 0; transform: rotate(45deg);
  animation: nudge 1.6s ease-in-out infinite;
}
/* On shortish windows the cue would sit on top of the rocket, and the words already say scroll. */
@media (max-height: 44rem) { .hero__hint { display: none; } }
@keyframes nudge { 0%, 100% { translate: 0 -3px; } 50% { translate: 0 5px; } }

.hero__arrival {
  top: clamp(6rem, 17cqh, 12rem); margin-block: 0;
  font: 600 var(--text-xl) / var(--leading-tight) var(--font-display); color: var(--amber-200);
  text-shadow: 0 2px 18px var(--night-950);
  opacity: var(--arrive); transform: translateY(calc((1 - var(--arrive)) * 2.5rem));
}

/* Time of day. static/js/sky.js sets data-sky on <html> from the visitor's own clock (hours in
   data/sky.yml). Each phase names the opening and closing sky, and where the sun, stars and the
   amber rim light on the hills start and end (0 = gone, 1 = the sun has just risen; above 1 is
   higher). No data-sky (no JavaScript) is night, which is the original story: night breaks into dawn.
   The calm version (hero-static.css) freezes the scene 60% of the way along, whatever the phase. */
:root {
  --sky-open: var(--gradient-night); --sky-close: var(--gradient-dawn);
  --sun-from: 0; --sun-to: 1;
  --stars-from: 1; --stars-to: 0.08;
  --rim-from: 0; --rim-to: 1;
}
:root[data-sky="dawn"] {
  --sky-open: var(--gradient-dawn); --sky-close: var(--gradient-morning);
  --sun-from: 0.35; --sun-to: 1;
  --stars-from: 0.5; --stars-to: 0;
  --rim-from: 0.6; --rim-to: 1;
}
:root[data-sky="day"] {
  --sky-open: var(--gradient-day); --sky-close: var(--gradient-day);
  --sun-from: 1.1; --sun-to: 1.25;
  --stars-from: 0; --stars-to: 0;
  --rim-from: 0.2; --rim-to: 0.2;
}
:root[data-sky="dusk"] {
  --sky-open: var(--gradient-dusk); --sky-close: var(--gradient-night);
  --sun-from: 1.15; --sun-to: 0.15;
  --stars-from: 0.15; --stars-to: 1;
  --rim-from: 1; --rim-to: 0.2;
}

/* The closing line follows the sky: the four lines are all in the page, the current one shows.
   Without JavaScript (no data-sky) the neutral line shows. */
.hero__arrival-line { display: none; }
.hero__arrival-line--any { display: inline; }
:root:is([data-sky="dawn"], [data-sky="day"], [data-sky="dusk"], [data-sky="night"]) .hero__arrival-line--any { display: none; }
:root[data-sky="dawn"] [data-sky-line="dawn"],
:root[data-sky="day"] [data-sky-line="day"],
:root[data-sky="dusk"] [data-sky-line="dusk"],
:root[data-sky="night"] [data-sky-line="night"] { display: inline; }

/* Native scroll-driven animation: the browser turns scroll position into --p */
@supports (animation-timeline: view()) {
  .hero {
    animation: hero-progress linear both;
    animation-timeline: view();
    animation-range: contain 0% contain 100%;   /* exactly while the stage is stuck to the viewport */
  }
}
@keyframes hero-progress { from { --p: 0; } to { --p: 1; } }
