/* Camino hero prototype — brand tokens from the Camino Brand Toolkit. */
:root {
  --a900: #121C33;
  --a800: #212C47;
  --a700: #33405C;
  --a600: #4A5670;
  --a500: #747F99;
  --a400: #B8C1D6;
  --a300: #D5DCEB;
  --a200: #F5F8FF;
  --white: #FFFFFF;
  --yellow: #FFB511;
  --purple: #B26EFF;
  --blue: #00AACC;
  --green: #26D19E;
  --coral: #F46677;

  --font: "Segoe UI", "Segoe UI Variable", system-ui, -apple-system,
          "Helvetica Neue", Arial, sans-serif;
  --gutter: clamp(20px, 6.6vw, 96px);
  /* the heading's type scale, shared so the scroll cue can sit a fixed
     distance under it at every viewport instead of guessing an offset */
  --h1: clamp(30px, 3.6vw, 54px);
  --h1-line: 1.16;
  /* where the copy band sits on a phone, shared with the scroll cue */
  --copy-bottom: 13vh;
  /* how strongly the sky veil deepens the top of the frame */
  --sky-veil-max: 1.58;
  --nav-h: 82px;
}

*, *::before, *::after { box-sizing: border-box; }

html { background: var(--a900); }

body {
  margin: 0;
  background: var(--a900);
  color: var(--a400);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a { color: var(--yellow); text-decoration: none; }
a:hover { color: #FFC94D; }

/* ── nav ─────────────────────────────────────────────────────────────────── */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--gutter);
  z-index: 60;
  opacity: 0;
  pointer-events: none;
  transition: background-color .3s ease, border-color .3s ease;
  border-bottom: 1px solid transparent;
}
.nav.is-visible { opacity: 1; pointer-events: auto; }
.nav.is-stuck {
  background: color-mix(in srgb, var(--a900) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom-color: var(--a800);
}
.nav__logo svg { display: block; width: 148px; height: auto; }
.nav__links { display: flex; align-items: center; gap: clamp(14px, 2vw, 30px); }
.nav__links a { color: var(--a400); font-size: 14px; }
.nav__links a:hover { color: var(--white); }

/* ── buttons ─────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 27px;
  border-radius: 3px;
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
}
.btn--sm { min-height: 40px; padding: 0 19px; font-size: 13.5px; }
.btn--solid { background: var(--yellow); color: var(--a900); }
.btn--solid:hover { background: #FFC94D; color: var(--a900); }
.btn--ghost { border: 1px solid var(--a600); color: var(--white); font-weight: 500; }
.btn--ghost:hover { border-color: var(--a400); color: var(--white); }

/* ── hero ────────────────────────────────────────────────────────────────── */
.hero { position: relative; }
.hero__stage {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  background: var(--a900);
}

.layer { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.layer--particles { z-index: 1; }
.layer--globe { z-index: 2; cursor: grab; touch-action: pan-y; }
.layer--globe.is-dragging { cursor: grabbing; }
/* Deepens the top of the frame so the sky has some weight and the lockup sits
   on a darker ground. Faded in with the sky itself via --sky-veil, so scenes
   1-3 are untouched.

   z-index 0 matters: this has to sit BEHIND the WebGL canvas, not over it. As
   an overlay it dimmed the stars by exactly as much as it darkened the sky, so
   the two changes cancelled and no amount of star gain could win. The canvas
   is transparent (it has to be, or it paints out the particle field), so a
   gradient underneath darkens the empty sky while the additive stars stay on
   top of it at full strength. */
.layer--sky {
  z-index: 0;
  pointer-events: none;
  opacity: calc(var(--sky-veil, 0) * var(--sky-veil-max, 1));
  background: linear-gradient(180deg,
    #070C18 0%,
    color-mix(in srgb, #070C18 62%, transparent) 22%,
    color-mix(in srgb, #070C18 24%, transparent) 42%,
    transparent 62%);
}

.layer--scrim {
  z-index: 3;
  pointer-events: none;
  background: linear-gradient(100deg,
    var(--a900) 0%,
    color-mix(in srgb, var(--a900) 95%, transparent) 24%,
    color-mix(in srgb, var(--a900) 62%, transparent) 41%,
    color-mix(in srgb, var(--a900) 10%, transparent) 58%,
    transparent 70%);
}

/* ── the narrative overlay ───────────────────────────────────────────────── */
/* One system for every beat rather than per-scene positioning. Blocks stack in
   the same place and are cross-faded; only one is legible at a time. */
.story { position: absolute; inset: 0; z-index: 12; pointer-events: none; }

.story__block {
  position: absolute;
  margin: 0;
  color: var(--white);
  font-size: var(--h1);
  line-height: var(--h1-line);
  font-weight: 700;
  letter-spacing: -.022em;
  text-wrap: pretty;
  opacity: 0;
  will-change: opacity, transform;
}
.story__block em { color: var(--yellow); font-style: normal; }

.story__block--left {
  left: var(--gutter);
  top: 50%;
  /* the scroll offset arrives as a custom property so JS never needs to know
     which base transform the breakpoint is using */
  transform: translateY(calc(-50% + var(--sy, 0px)));
  width: min(620px, 46%);
}

.scrollcue {
  position: absolute;
  left: var(--gutter);
  /* The heading is two lines centred on 50%, so its lower edge sits one
     line-height below the midline. Anchoring to that keeps the cue grouped
     with the copy rather than drifting away from it as the type scales. */
  top: calc(50% + (var(--h1) * var(--h1-line)) + 26px);
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 15px;
  color: var(--a300);
  font-size: clamp(14px, 1.15vw, 17px);
  letter-spacing: .01em;
  text-transform: none;
}
.scrollcue span { line-height: 1.32; }
.scrollcue svg { flex: 0 0 auto; }
/* The wheel travels inside the housing — the housing itself stays put. The
   translate is in the SVG's own user units, so 6.4 carries the dot from cy 7.4
   to 13.8 and it stays clear of the capsule's inner edge at 23. */
.scrollcue__dot { animation: cueDot 2.1s ease-in-out infinite; }
@keyframes cueDot {
  0%, 100% { transform: translateY(0); opacity: .5; }
  50% { transform: translateY(6.4px); opacity: 1; }
}

.hint {
  position: absolute;
  right: var(--gutter);
  bottom: 44px;
  margin: 0;
  z-index: 10;
  color: var(--a600);
  font-size: 11px;
  letter-spacing: .06em;
  transition: opacity .5s ease;
}

/* ── second copy beat, over the map ──────────────────────────────────────── */
/* ── the reveal ──────────────────────────────────────────────────────────── */
/* The lockup lives in the sky, not the middle of the frame — scene 5's horizon
   sits on the half-line and the convergence is below it. */
/* The lockup hovers just above the convergence point, so JS parks it from the
   point's own projected position rather than from an arbitrary offset. */
.reveal {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--reveal-bottom, 42%);
  z-index: 20;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 2.4vh, 26px);
  pointer-events: none;
}
/* Each part of the reveal is faded in on its own beat, so nothing appears
   while the convergence dot still fills the frame. */
.reveal__logo svg, .reveal__tag { opacity: 0; }
.reveal__dot { opacity: 0; }
/* The primary stacked lockup (360x315 in the brand library). */
.reveal__logo { position: relative; width: min(340px, 54vw); }
.reveal__logo svg { display: block; width: 100%; height: auto; }
/* The logomark's own dot. Its position comes from the lockup's viewBox via
   brand/inline.mjs, set as custom properties at boot — the fallbacks here are
   the stacked lockup's values. */
.reveal__dot {
  position: absolute;
  left: var(--dot-left, 57.2222%);
  top: var(--dot-top, 3.1746%);
  width: var(--dot-w, 5.5556%);
  aspect-ratio: 1;
  margin: 0;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--yellow);
  will-change: transform;
}
/* The strapline, as outlined paths from the brand library. */
.reveal__tag {
  display: block;
  width: min(430px, 66vw);
  height: auto;
  margin: 0;
}

/* ── content after the hero ──────────────────────────────────────────────── */
.after { position: relative; z-index: 5; background: var(--a900); }
.band { padding: clamp(64px, 9vw, 130px) var(--gutter); }
.band--alt { border-top: 1px solid var(--a800); }

.skel { display: flex; flex-direction: column; gap: 11px; max-width: 640px; }
.skel span { display: block; height: 13px; border-radius: 2px; background: var(--a700); }
.skel--head span { height: 17px; }

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 26px;
  margin-top: 62px;
}
.card {
  border: 1px solid var(--a800);
  border-radius: 5px;
  padding: 26px;
  display: flex;
  flex-direction: column;
  gap: 15px;
}
.card__rule { display: block; width: 30px; height: 3px; border-radius: 2px; }

.note { color: var(--a600); font-size: 11.5px; letter-spacing: .06em; margin: 40px 0 0; }

/* ── debug readout ───────────────────────────────────────────────────────── */
.debug {
  position: fixed;
  right: 12px;
  top: 12px;
  z-index: 100;
  padding: 10px 12px;
  border: 1px solid var(--a700);
  border-radius: 4px;
  background: color-mix(in srgb, var(--a900) 90%, transparent);
  color: var(--a400);
  font: 11px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre;
  pointer-events: none;
}

/* ── responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 860px) {
  .nav__links a:not(.btn) { display: none; }
  .layer--scrim {
    background: linear-gradient(180deg,
      transparent 0%,
      color-mix(in srgb, var(--a900) 18%, transparent) 24%,
      color-mix(in srgb, var(--a900) 78%, transparent) 44%,
      var(--a900) 62%);
  }
  .eyebrow { flex-wrap: wrap; row-gap: 8px; }
  /* no room beside the visual on a phone, so copy takes a lower band */
  .story__block--left {
    top: auto;
    bottom: var(--copy-bottom);
    width: auto;
    right: var(--gutter);
    transform: translateY(var(--sy, 0px));
  }
  /* The copy moves to a lower band here, so the cue has to follow it. Left on
     the desktop rule it stayed pinned near the viewport middle and ended up
     stranded halfway up the page, nowhere near the heading it belongs to.
     66px is the cue's own height plus the same 26px gap used on desktop. */
  .scrollcue {
    top: auto;
    bottom: calc(var(--copy-bottom) - 66px);
  }
  .story__block { font-size: clamp(26px, 7.2vw, 34px); }
  .hint { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .scrollcue__dot { animation: none; }
}

/* ── reduced motion ──────────────────────────────────────────────────────── */
/* No pin, so nobody is dragged through five viewport-heights of artificial
   scroll. The hero holds one composition and every narrative block is laid out
   as ordinary stacked text, ending with the lockup. */
body.is-reduced .story {
  position: static;
  inset: auto;
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 5vw, 56px);
  padding: clamp(48px, 8vw, 110px) var(--gutter);
  pointer-events: auto;
}
body.is-reduced .story__block {
  position: static;
  opacity: 1 !important;
  transform: none !important;
  width: min(760px, 100%);
}
body.is-reduced .hero__stage { height: auto; min-height: 100svh; overflow: visible; }
body.is-reduced .layer { position: sticky; top: 0; height: 100svh; }
body.is-reduced .reveal {
  position: static;
  opacity: 1 !important;
  padding: clamp(40px, 7vw, 90px) var(--gutter) clamp(60px, 9vw, 120px);
}
body.is-reduced .reveal__logo svg,
body.is-reduced .reveal__tag { opacity: 1 !important; transform: none !important; }
body.is-reduced .scrollcue, body.is-reduced .hint { display: none; }
