/* ============================================================
   MONTEREY STUDIO — hero.css
   The world (backdrop · canvas · fixed furniture) + hero layout
   Owner: hero specialist
   Direction: design/direction.md §5 — full bleed, horizon at 62%.
   ============================================================ */

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  background: var(--sky-top);
}

body {
  margin: 0;
  overflow-x: hidden;
}

/* ------------------------------------------------------------
   The world: CSS sky + sea. First paint IS this gradient — no
   loader, no black frame. The WebGL canvas fades in over it.
   ------------------------------------------------------------ */
#backdrop {
  position: fixed;
  inset: 0;
  z-index: -3;
  background: linear-gradient(
    to bottom,
    var(--sky-top) 0%,
    var(--sky-mid) 40%,
    var(--sky-hor) 61.4%,
    color-mix(in srgb, var(--sky-hor) 55%, var(--sea-far)) 62%,
    var(--sea-far) 66%,
    var(--sea-near) 100%
  );
}

/* Thin marine-layer haze band riding the horizon */
#backdrop::before {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: calc(var(--horizon) - 3vh);
  height: 6vh;
  background: linear-gradient(
    to bottom,
    transparent,
    color-mix(in srgb, var(--sky-hor) 65%, transparent) 46%,
    color-mix(in srgb, var(--sky-hor) 55%, transparent) 54%,
    transparent
  );
  filter: blur(6px);
}

/* Static painted glitter path — the no-WebGL / reduced-motion sea.
   Hidden once GL is confirmed alive (html.gl). */
#backdrop::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: var(--horizon);
  bottom: 0;
  background:
    radial-gradient(90% 4% at calc(50% + var(--sun-x) * 20%) 0%,
      color-mix(in srgb, var(--glint) 85%, transparent), transparent 70%),
    linear-gradient(to bottom,
      color-mix(in srgb, var(--glint) 34%, transparent),
      color-mix(in srgb, var(--glint) 10%, transparent) 30%,
      transparent 72%);
  -webkit-mask-image: linear-gradient(to bottom, #000, #000);
  mask-image: linear-gradient(to bottom, #000, #000);
  clip-path: polygon(
    calc(50% + var(--sun-x) * 20% - 4%) 0%,
    calc(50% + var(--sun-x) * 20% + 4%) 0%,
    calc(50% + var(--sun-x) * 32% + 24%) 100%,
    calc(50% + var(--sun-x) * 32% - 24%) 100%
  );
  opacity: 0.85;
  transition: opacity var(--dur-3) var(--ease);
}
html.gl #backdrop::after { opacity: 0; }

/* The living sea */
#sea {
  position: fixed;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease);
  pointer-events: none;
}
html.gl #sea { opacity: 1; }

/* ------------------------------------------------------------
   Afterglow furniture: stars, lighthouse, green flash, otter wake
   ------------------------------------------------------------ */
#stars {
  position: fixed;
  inset: 0 0 var(--horizon-b) 0;
  z-index: -1;
  pointer-events: none;
  opacity: calc(var(--dusk) * var(--dusk));
}
/* 30 static 1px stars. No twinkle loops (§6). */
#stars::before {
  content: '';
  position: absolute;
  top: 6vh; left: 4vw;
  width: 1px; height: 1px;
  background: var(--noon-haze);
  box-shadow:
    8vw 3vh 0 var(--noon-haze),   17vw 11vh 0 var(--offshore),
    23vw 5vh 0 var(--noon-haze),  29vw 16vh 0 var(--offshore),
    34vw 2vh 0 var(--noon-haze),  38vw 9vh 0 var(--noon-haze),
    45vw 14vh 0 var(--offshore),  51vw 4vh 0 var(--noon-haze),
    56vw 19vh 0 var(--offshore),  61vw 8vh 0 var(--noon-haze),
    66vw 1vh 0 var(--noon-haze),  70vw 13vh 0 var(--offshore),
    75vw 6vh 0 var(--noon-haze),  81vw 17vh 0 var(--offshore),
    85vw 3vh 0 var(--noon-haze),  90vw 10vh 0 var(--noon-haze),
    94vw 21vh 0 var(--offshore),  12vw 22vh 0 var(--offshore),
    41vw 24vh 0 var(--offshore),  63vw 27vh 0 var(--offshore),
    3vw 15vh 0 var(--offshore),   20vw 30vh 0 var(--offshore),
    48vw 33vh 0 var(--offshore),  73vw 29vh 0 var(--offshore),
    88vw 35vh 0 var(--offshore),  31vw 38vh 0 var(--offshore),
    58vw 40vh 0 var(--offshore),  9vw 36vh 0 var(--offshore),
    96vw 42vh 0 var(--offshore);
}

/* Point Pinos — occulting light, 4s period: 3s lit, 1s dark (§6) */
#lighthouse {
  position: fixed;
  left: 26vw;
  top: calc(var(--horizon) - 10px);
  z-index: -1;
  width: 3px;
  height: 10px;
  background: color-mix(in srgb, var(--deep-pacific) 80%, var(--offshore));
  opacity: var(--dusk);
  pointer-events: none;
}
#lighthouse .lamp {
  position: absolute;
  top: -3px;
  left: -1px;
  width: 5px;
  height: 5px;
  border-radius: var(--r-full);
  background: var(--noon-haze);
  box-shadow:
    0 0 6px 2px color-mix(in srgb, var(--green-flash) 70%, transparent),
    0 0 22px 6px color-mix(in srgb, var(--green-flash) 25%, transparent);
  animation: occult 4s step-end infinite;
}
@keyframes occult {
  0%   { opacity: 1; }
  75%  { opacity: 0; }
  100% { opacity: 1; }
}

/* The green flash — 300ms, once per visit, at sunset (§6) */
#flash {
  position: fixed;
  inset: 0;
  z-index: 30;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(
    60% 22% at 50% var(--horizon),
    color-mix(in srgb, var(--green-flash) 90%, transparent),
    color-mix(in srgb, var(--green-flash) 30%, transparent) 45%,
    transparent 75%
  );
}
#flash.go { animation: greenflash 300ms var(--ease); }
@keyframes greenflash {
  0% { opacity: 0; }
  30% { opacity: 1; }
  100% { opacity: 0; }
}

/* Sea-otter V-wake — once per visit, after 10s idle (§5) */
#wake {
  position: fixed;
  top: calc(var(--horizon) + 6vh);
  left: -12vw;
  z-index: -1;
  width: 9vw;
  height: 3px;
  opacity: 0;
  pointer-events: none;
}
#wake i {
  position: absolute;
  right: 0;
  height: 1px;
  background: color-mix(in srgb, var(--noon-haze) 32%, transparent);
  border-radius: var(--r-full);
  filter: blur(0.6px);
}
#wake i:nth-child(1) { top: 0; width: 78%; transform: rotate(1.6deg); transform-origin: right; }
#wake i:nth-child(2) { top: 0; width: 78%; transform: rotate(-1.6deg); transform-origin: right; }
#wake i:nth-child(3) { top: 0; width: 40%; opacity: 0.5; }
#wake.swim { animation: otter 24s linear forwards; }
@keyframes otter {
  0% { transform: translateX(0); opacity: 0; }
  8% { opacity: 0.35; }
  92% { opacity: 0.35; }
  100% { transform: translateX(124vw); opacity: 0; }
}

/* ------------------------------------------------------------
   Chrome — fixed page furniture (§5)
   ------------------------------------------------------------ */
#chrome {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding: var(--s-4) var(--gutter);
  pointer-events: none;
}
#chrome a { pointer-events: auto; }

/* Chrome scrim (integration rule): fixed chrome may never overprint
   scene type illegibly. A masked backdrop blur softens whatever
   scrolls beneath the top band — marine haze at the top of frame,
   not a bar — so the wordmark and telemetry always sit on calm air.
   Reads as atmosphere at every hour because it carries no color. */
@media (min-width: 901px) {
  #chrome::before {
    content: '';
    position: absolute;
    inset: -1px 0 auto 0;
    height: 17vh;
    pointer-events: none;
    z-index: -1;
    backdrop-filter: blur(9px) saturate(1.05);
    -webkit-backdrop-filter: blur(9px) saturate(1.05);
    -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 38%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 0, #000 38%, transparent 100%);
  }
}

.chrome-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--s-2);
  text-align: right;
}

.skyline {
  color: color-mix(in srgb, var(--chrome-ink, var(--ink)) 82%, var(--offshore));
  white-space: nowrap;
}

/* TALK TO US — a real CTA (§3: Ember is where a hand should go).
   Solid Ember ground so it never loses contrast on peach skies or
   dusk water; Green Flash is reserved for after sunset (§3), so
   hover warms to Low Sun instead. */
/* The two things the chrome asks of you, on one line: turn the
   sea on, or talk to us. */
.chrome-actions {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

/* Sound toggle — hairline instrument, same ink as the telemetry
   and the dial, so it belongs to the chrome rather than sitting
   on it. Silent by default; the icon says which state you're in,
   never which state you'd get. */
.soundbtn {
  pointer-events: auto;
  display: grid;
  place-items: center;
  width: 2.35rem;
  height: 2.35rem;
  padding: 0;
  border-radius: var(--r-full);
  border: 1px solid color-mix(in srgb, var(--chrome-ink, var(--ink)) 26%, transparent);
  background: transparent;
  color: color-mix(in srgb, var(--chrome-ink, var(--ink)) 78%, var(--offshore));
  cursor: pointer;
  transition:
    color var(--dur-1) var(--ease),
    border-color var(--dur-1) var(--ease),
    background var(--dur-1) var(--ease);
}
.soundbtn svg { display: block; overflow: visible; }
.soundbtn .cone { fill: currentColor; }
.soundbtn .wave,
.soundbtn .slash {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
}
/* off: the slash stands in for the waves */
.soundbtn .wave { opacity: 0; }
.soundbtn .slash { opacity: 0.9; }
/* on: waves breathe, slowly, like the thing they represent. The
   live color is ember CUT WITH THE HOUR'S INK — pure ember goes
   invisible against a dusk sky and fights the pill beside it. */
.soundbtn[aria-pressed="true"] {
  color: color-mix(in srgb, var(--ember) 30%, var(--chrome-ink, var(--ink)));
  border-color: color-mix(in srgb,
    color-mix(in srgb, var(--ember) 55%, var(--chrome-ink, var(--ink))) 65%,
    transparent);
  background: color-mix(in srgb, var(--ember) 11%, transparent);
}
.soundbtn[aria-pressed="true"] .slash { opacity: 0; }
.soundbtn[aria-pressed="true"] .wave { opacity: 1; }
.soundbtn[aria-pressed="true"] .w1 { animation: sndwave 3.4s var(--ease) infinite; }
.soundbtn[aria-pressed="true"] .w2 { animation: sndwave 3.4s var(--ease) 0.45s infinite; }
@keyframes sndwave {
  0%, 100% { opacity: 0.45; }
  45%      { opacity: 1; }
}
/* hover warms toward ember but keeps riding the hour's ink —
   pure ember on a dusk sky is mud */
.soundbtn:hover {
  color: color-mix(in srgb, var(--ember) 48%, var(--chrome-ink, var(--ink)));
  border-color: color-mix(in srgb,
    color-mix(in srgb, var(--ember) 60%, var(--chrome-ink, var(--ink))) 70%,
    transparent);
}
.soundbtn:focus-visible {
  outline: 2px solid var(--ember);
  outline-offset: 3px;
}
/* fetching the recording: the ring breathes until the sea arrives */
.soundbtn.loading { cursor: progress; }
.soundbtn.loading .cone,
.soundbtn.loading .slash,
.soundbtn.loading .wave { animation: sndload 1.1s ease-in-out infinite; }
@keyframes sndload {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .soundbtn .wave { animation: none !important; }
}

.talk {
  font-family: 'Spline Sans Mono', ui-monospace, monospace;
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--noon-haze);
  background: var(--ember);
  padding: 0.62em 1.1em 0.56em;
  border: none;
  border-radius: var(--r-soft);
  box-shadow:
    calc(var(--shadow-dx) * 0.25) calc(var(--shadow-dy) * 0.25)
      calc(var(--shadow-len) * 0.3)
      color-mix(in srgb, var(--afterglow-ink) 25%, transparent);
  transition: background var(--dur-1) var(--ease);
}
.talk:hover {
  background: color-mix(in srgb, var(--ember) 55%, var(--low-sun));
  color: var(--afterglow-ink);
}

/* Sun-arc dial — the site's entire scroll-progress ornament (§5) */
#dial { display: block; overflow: visible; }
#dial .arc {
  fill: none;
  stroke: var(--hairline);
  stroke-width: 1;
}
#dial .dot {
  fill: var(--low-sun);
  stroke: none;
}
#dial .sealine {
  stroke: var(--hairline);
  stroke-width: 1;
}

#ghbadge {
  color: var(--ember);
}
#ghbadge[hidden] { display: none; }

/* ------------------------------------------------------------
   Hero — first viewport, exactly (§5)
   ------------------------------------------------------------ */
.panel {
  position: relative;
  min-height: 100vh;
}

#hero { z-index: 1; }

/* ---- Live sky glare — the sun made visible in the CSS layer.
   Driven by the §2 bridge: azimuth from --sun-x, height from
   --sun-elev, temperature from --sun-warmth. Screen-blended so
   it can only add light; strongest where the sky is coolest,
   right above the horizon, and across the upper sea. ---- */
.hero-glare {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  --gx: calc(50% + var(--sun-x) * 34%);
  --gy: calc(6% + (1 - var(--sun-elev)) * 48%);
  background:
    /* glare core — the light source itself, high in the frame */
    radial-gradient(34vw 27vw at var(--gx) var(--gy),
      color-mix(in srgb, var(--noon-haze) 76%, var(--low-sun)) 0%,
      color-mix(in srgb, var(--golden-hour)
        calc(64% * (0.2 + 0.8 * var(--sun-warmth))), transparent) 34%,
      transparent 72%),
    /* broad atmospheric wash pouring down toward the horizon.
       Gold strength rides --sun-warmth: at noon (warmth≈0) the air
       is near-neutral — the 0.68 opacity floor alone was leaking a
       saturated sunset band into noon skies (cloud critic catch) */
    radial-gradient(96vw 78vh at var(--gx) calc(var(--gy) + 14%),
      color-mix(in srgb, var(--golden-hour)
        calc(34% * (0.2 + 0.8 * var(--sun-warmth))), transparent) 0%,
      color-mix(in srgb, var(--golden-hour)
        calc(12% * (0.2 + 0.8 * var(--sun-warmth))), transparent) 45%,
      transparent 74%),
    /* haze bloom hugging the waterline under the sun (noon-haze is
       neutral — safe at every hour) */
    radial-gradient(60vw 16vh at var(--gx) var(--horizon),
      color-mix(in srgb, var(--noon-haze) 46%, transparent) 0%,
      transparent 70%);
  mix-blend-mode: screen;
  opacity: calc(0.68 + var(--sun-warmth) * 0.32);
}

/* Swell licking the letter baselines (§5): a thin sheet of bright
   water riding the waterline OVER the headline's feet, breathing
   sideways with the swell period. The letters stand in the Pacific,
   not on it. One easing, no bounce. */
@media (min-width: 901px) {
#hero::before {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: calc(var(--horizon) - 0.5vh);
  height: 2.1vh;
  z-index: 3;
  pointer-events: none;
  background:
    radial-gradient(58vw 130% at var(--sun-sx) 42%,
      color-mix(in srgb, var(--glint) 88%, transparent),
      color-mix(in srgb, var(--glint) 38%, transparent) 55%,
      transparent 78%),
    linear-gradient(to bottom,
      transparent,
      color-mix(in srgb, var(--sky-hor) 42%, transparent) 40%,
      color-mix(in srgb, var(--sky-hor) 30%, transparent) 70%,
      transparent);
  filter: blur(1.5px);
  animation: lick 9s var(--ease) infinite alternate;
}
}
@keyframes lick {
  from { transform: translateY(-0.25vh) scaleY(0.72); opacity: 0.75; }
  to   { transform: translateY(0.3vh)  scaleY(1.15); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  #hero::before { animation: none; }
}

/* Seat the waterline furniture: the sea gathers depth toward the
   fold so the meta lines rest on still, dark water. */
#hero::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 24vh;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    transparent,
    color-mix(in srgb, var(--deep-pacific) 16%, transparent) 45%,
    color-mix(in srgb, var(--deep-pacific) 42%, transparent)
  );
  -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 55%, transparent 100%);
}
/* Desktop: viewport-anchored, so the gather lives at the FOOT OF
   THE FRAME and can never become a stray grey band over the next
   section's sky once the hero scrolls away. (Mobile browsers treat
   fixed attachment as scroll, so they keep the masked fallback.) */
@media (min-width: 901px) {
  #hero::after {
    background: linear-gradient(
      to bottom,
      transparent 76vh,
      color-mix(in srgb, var(--deep-pacific) 16%, transparent) 89vh,
      color-mix(in srgb, var(--deep-pacific) 42%, transparent) 100vh
    );
    background-attachment: fixed;
    -webkit-mask-image: none;
    mask-image: none;
  }
}

/* The signature frame: headline standing ON the horizon.
   Baseline of the last line kisses the 62% line; the sea below
   carries its live reflection (drawn in WebGL). A dense slab of
   Archivo 900 running gutter to gutter — the hero's monolith. */
#headline {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: calc(var(--horizon-b) - 0.085em);
  margin: 0;
  z-index: 2;
  /* 8.8vw (was 9.25) — the comma of GOLDEN HOUR, gets air at the
     right edge of the frame instead of crowding it */
  font-size: clamp(2.1rem, 8.8vw, 10.4rem);
  white-space: nowrap;
}
#headline .line { display: block; width: fit-content; }

/* PHOTOREAL pass — the headline is a BACKLIT SILHOUETTE hanging in
   golden-hour air, not a printed layer:
   · no cast shadow: there is nothing behind the glyphs but open sky,
     and a drop shadow on air is the one thing a photograph cannot do;
   · atmosphere grades each line — the lower a glyph sits, the more
     marine haze stands between it and the lens, so its blacks lift
     toward the horizon color exactly like the sea's own aerial
     perspective (and, because the mix uses the live sky tokens, the
     veil tracks the hour with the rest of the scene);
   · halation instead of shadow — the bright air bleeds a breath of
     warm light around the letterforms, biased toward the sun. */
@media (min-width: 901px) {
  #headline {
    text-shadow: none;
    color: transparent;
    filter:
      drop-shadow(calc(var(--sun-x) * 7px) -2px 14px
        color-mix(in srgb, var(--golden-hour) 34%, transparent))
      drop-shadow(0 0 1.5px
        color-mix(in srgb, var(--sky-hor) 38%, transparent));
  }
  #headline .line {
    background-image: linear-gradient(
      to bottom,
      color-mix(in srgb, var(--afterglow-ink) 97%, var(--sky-hor)),
      color-mix(in srgb, var(--afterglow-ink) 86%, var(--sky-hor)));
    -webkit-background-clip: text;
    background-clip: text;
  }
  /* the second line stands ON the horizon: haze veils its feet */
  #headline .line:nth-child(2) {
    background-image: linear-gradient(
      to bottom,
      color-mix(in srgb, var(--afterglow-ink) 93%, var(--sky-hor)) 0%,
      color-mix(in srgb, var(--afterglow-ink) 76%, var(--sky-hor)) 62%,
      color-mix(in srgb, var(--afterglow-ink) 54%, var(--sky-hor)) 100%);
  }
}

/* Condense entrance (§8.3): light gathers into the letters once,
   on load. No translate-in from off-screen; drift ≤ 12px. */
html.js #headline .line {
  animation: condense var(--dur-3) var(--ease) both;
}
html.js #headline .line:nth-child(2) { animation-delay: 140ms; }
@keyframes condense {
  from { opacity: 0; filter: blur(10px); transform: translateY(12px); }
  to   { opacity: 1; filter: none;       transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  html.js #headline .line { animation: none; }
}

.hero-services {
  position: absolute;
  left: var(--gutter);
  bottom: var(--s-5);
  font-style: italic;
  font-size: 1.2rem;
  letter-spacing: 0.01em;
  color: var(--noon-haze);
  margin: 0;
  z-index: 2;
  text-shadow: 0 1px 14px color-mix(in srgb, var(--deep-pacific) 55%, transparent);
}

.hero-scroll {
  position: absolute;
  right: var(--gutter);
  bottom: var(--s-5);
  color: color-mix(in srgb, var(--noon-haze) 92%, transparent);
  margin: 0;
  z-index: 2;
  text-shadow: 0 1px 14px color-mix(in srgb, var(--deep-pacific) 55%, transparent);
}

/* ------------------------------------------------------------
   Chrome presence — confident, quiet, exactly placed
   ------------------------------------------------------------ */
#chrome .wordmark {
  font-size: 1.02rem;
  letter-spacing: 0.18em;
  font-variation-settings: 'wght' 620, 'wdth' 112;
}

#chrome .chrome-right { gap: var(--s-2); }

#chrome .talk { border-bottom: none; }

/* Sun-arc dial — finished: legible strokes at every hour, the dot
   glowing like the sun it tracks, a tick where the sun will set. */
#dial { margin-top: var(--s-1); opacity: 0.95; }
#dial .arc,
#dial .sealine {
  stroke: color-mix(in srgb, var(--chrome-ink, var(--ink)) 46%, var(--offshore));
}
#dial .dot {
  fill: var(--low-sun);
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--low-sun) 85%, transparent));
}
