/* ==========================================================================
   Intro sequence — branded load, full-bleed video, scroll-driven title
   ==========================================================================
   Three beats:
     1. Solid brand field + logo (the Hinge-style load)
     2. Field lifts to reveal the full-bleed autoplaying video
     3. Scrolling reveals "Swipe. Meet. Feet.", then both fade into the page

   Scroll is driven by a tall stage with a sticky pin, NOT by hijacking wheel
   events. Same pinned feel, but the scrollbar stays honest, trackpad momentum
   is untouched, and keyboard/screen-reader users can still move at their own
   pace.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Load overlay
   -------------------------------------------------------------------------- */
.intro {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  background: var(--tunas-aqua);
  transition: opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1),
    visibility 0s linear 0.9s;
}
.intro__logo {
  width: min(58vw, 340px);
  opacity: 0;
  transform: translateY(10px) scale(0.98);
  animation: intro-logo-in 1s cubic-bezier(0.22, 1, 0.36, 1) 0.15s forwards;
}
.intro__logo img {
  width: 100%;
  height: auto;
}
@keyframes intro-logo-in {
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
body.intro-done .intro {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* Hold the page still until the reveal finishes. */
body.is-intro {
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   2. Scroll stage — tall driver, sticky pin
   -------------------------------------------------------------------------- */
.stage {
  position: relative;
  /* Height comes from the slides inside — one viewport per beat. */
  height: auto;
  /* The pin fades onto the fork, so the stage base matches the fork's field —
     otherwise a sliver of mismatched colour flashes above it during the
     hand-off. */
  background: var(--tunas-surface);
  scroll-snap-align: start;
}

/* Each beat is a snap point, so a scroll gesture advances exactly one beat and
   then locks. `scroll-snap-stop: always` is what stops a fast flick skipping
   the whole sequence — without it the entire hero goes by in one swipe.
   Only the beats and the fork are snap points; the rest of the page is free. */
html {
  scroll-snap-type: y mandatory;
}
/* Released once the last snap section has landed. Mandatory snapping has to
   come to rest ON a snap point, so with the footer not being one the browser
   pulled the page back up every time you tried to scroll into it — the footer
   was unreachable. Snapping exists for the story sections; past them it is
   only in the way. */
html.snap-free {
  scroll-snap-type: none;
}
.stage__slide {
  height: 100vh;
  height: 100dvh;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  pointer-events: none;
}
.stage__pin {
  /* Fixed, not sticky. A sticky pin has to scroll through its own height
     before the next section can arrive, which is dead scroll you cannot
     shorten. Fixed lets the fork sit immediately after the stage. */
  position: fixed;
  inset: 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: grid;
  place-items: center;
  z-index: 1;
}
/* Out of the way once its beats are done, so it cannot eat clicks. */
body.stage-passed .stage__pin {
  visibility: hidden;
  pointer-events: none;
}

.stage__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Scale slightly so the reveal has somewhere to settle from. */
  transform: scale(1.06);
  opacity: 0;
  transition: opacity 1.1s cubic-bezier(0.22, 1, 0.36, 1),
    transform 1.6s cubic-bezier(0.22, 1, 0.36, 1);
}
body.intro-done .stage__video {
  opacity: 1;
  transform: scale(1);
}

/* Keeps white type legible over an unknown frame. */
.stage__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(17, 24, 31, 0.42) 0%,
    rgba(17, 24, 31, 0.18) 38%,
    rgba(17, 24, 31, 0.46) 100%
  );
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   3. Title — one line, full width
   -------------------------------------------------------------------------- */
.stage__title {
  position: relative;
  z-index: 2;
  /* Title and explainer share one grid cell. Without this the pin's grid
     creates a row per in-flow child, so the title centres in the top half
     instead of the frame. */
  grid-area: 1 / 1;
  align-self: center;
  margin: 0;
  padding: 0 2vw;
  width: 100%;
  text-align: center;
  white-space: nowrap;
  font-family: var(--font-family-display);
  font-weight: 700;
  /* Measured, not guessed. The scare quotes added two characters and pushed
     the line to 102% of the viewport, so this is retuned from 11.85vw by the
     same ratio to land just inside the edges. */
  font-size: 10.85vw;
  line-height: 1;
  letter-spacing: -0.035em;
  color: var(--tunas-paper);
  text-shadow: 0 2px 40px rgba(17, 24, 31, 0.35);
}

/* Faithful port of the SoftBlurIn motion spec:
   opacity 0 -> 1, y 16px -> 0, blur 12px -> 0,
   duration 0.9s, ease cubic-bezier(.22,1,.36,1), 25ms per-character stagger. */
.blur-char {
  display: inline-block;
  white-space: pre;
  opacity: 0;
  transform: translateY(16px);
  filter: blur(12px);
  will-change: opacity, transform, filter;
}
.stage__title.is-revealed .blur-char {
  animation: soft-blur-in 0.9s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  animation-delay: calc(var(--i) * 25ms);
}
@keyframes soft-blur-in {
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0px);
  }
}

/* Scroll-driven exit.
   Applied to the pin, not to each child. Putting it on the children lost a
   specificity fight with `body.intro-done .stage__video { opacity: 1 }`
   (0,2,0 beats 0,1,0), so the video never faded and you got a frame with the
   video and the next section both on screen. One opacity owner avoids that
   whole class of bug. */
.stage__pin {
  --exit: 0;   /* whole-pin departure fade */
  --v: 1;      /* video + title */
  --w: 0;      /* white wash */
  --e: 0;      /* the line */
  --e2: 0;     /* the second line */
  opacity: calc(1 - var(--exit));
}
.stage__video,
.stage__scrim,
.stage__title,
.stage__wash,
.stage__note {
  transition: opacity 0.75s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.75s cubic-bezier(0.22, 1, 0.36, 1);
}
.stage__video,
.stage__scrim,
.stage__title {
  opacity: var(--v);
}
.stage__title {
  transform: translateY(calc((1 - var(--v)) * -34px));
}
@media (prefers-reduced-motion: reduce) {
  .stage__video,
  .stage__scrim,
  .stage__title,
  .stage__wash,
  .stage__note {
    transition: none;
  }
}

/* --- beat two: the two ways in ---------------------------------------------
   Sits under the title in the same grid cell rather than in a column with it,
   so the title stays optically centred in the frame and the pills hang off it
   by a fixed proportion of the viewport at every width.

   Opacity is `--v`, the same value that drives the video and the title, so
   when the white field arrives the pills leave with the picture they were
   sitting on instead of fading on their own schedule. */
.stage__cta {
  grid-area: 1 / 1;
  align-self: center;
  justify-self: center;
  z-index: 2;
  display: flex;
  gap: 12px;
  transform: translateY(calc(9vw + 16px));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}
body.stage-cta .stage__cta {
  opacity: var(--v);
  transform: translateY(9vw);
  pointer-events: auto;
}

.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 13px 26px;
  border-radius: 999px;
  font-family: var(--font-family-default);
  font-size: clamp(14px, 1.15vw, 17px);
  font-weight: var(--font-weight-bold);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1),
    background 0.25s ease, box-shadow 0.25s ease;
}
.pill--light {
  background: var(--tunas-paper);
  color: var(--tunas-ink);
}
.pill--light:hover {
  background: #fff;
}
.pill--brand {
  background: var(--tunas-teal);
  color: var(--tunas-paper);
}
.pill--brand:hover {
  background: var(--tunas-teal-pressed);
}
.pill:hover,
.pill:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 10px 26px rgba(17, 24, 31, 0.28);
}
.pill:focus-visible {
  outline: 2px solid var(--tunas-paper);
  outline-offset: 3px;
}

@media (max-width: 620px) {
  .stage__cta {
    /* The title is far taller relative to the frame here, so the pills need
       proportionally more clearance to sit clear of its descenders. */
    transform: translateY(calc(16vw + 16px));
  }
  body.stage-cta .stage__cta {
    transform: translateY(16vw);
  }
  .pill {
    padding: 12px 20px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .stage__cta,
  .pill {
    transition-duration: 0.001s;
  }
}

/* --- beat three: white field + centred explainer ------------------------- */
.stage__wash {
  position: absolute;
  inset: 0;
  /* Plain white rather than the paper token. Paper is #fffcfa — warm by a
     couple of points, which is right against cream sections but reads as
     cream itself when it is the whole screen with nothing to compare it to.
     This beat is the only full-frame field on the page, so it gets white. */
  background: #ffffff;
  opacity: var(--w);
  pointer-events: none;
  z-index: 3;
}

/* The ruled backdrop, on the beat where the scene arrives.
   Same depth as the wash and immediately after it in the markup, so it paints
   on the white field; the globe, the tokens and the photographs are all a
   layer above and stay in front of it.

   Qualified by the pin rather than left as a bare modifier. `.gridbg` sets
   `z-index: 0` for its use behind the cards, story.css loads after this file,
   and one class against one class is a tie that load order settles — so the
   modifier lost and the grid went under the white field it is supposed to be
   drawn on. Two classes settles it wherever the file sits. */
.stage__pin .gridbg--stage {
  z-index: 3;
  opacity: 0;
  transition: opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}
body.stage-globe .stage__pin .gridbg--stage {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .stage__pin .gridbg--stage {
    transition: none;
  }
}
.stage__note {
  position: relative;
  z-index: 5;
  grid-area: 1 / 1;
  align-self: center;
  width: 100%;
  max-width: 980px;
  padding: 0 24px;
  margin: 0 auto;
  text-align: center;
  opacity: var(--e);
  /* Two movements on one axis. The first is the entrance. The second is the
     lift: on its own beat the line is centred on the frame, but once the
     second line hangs beneath it the pair are bottom-heavy and crowd the
     globe on the beat after. Rising by a little over half the second line's
     height re-centres the pair and buys the scene below some air. */
  --note-lift: clamp(34px, 5.5vh, 76px);
  transform: translateY(
    calc((1 - var(--e)) * 18px - var(--e2) * var(--note-lift))
  );
  transition: opacity 0.75s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.85s cubic-bezier(0.22, 1, 0.36, 1);
}
.stage__note-lead {
  font-family: var(--font-family-display);
  font-weight: 700;
  font-size: clamp(28px, 4.4vw, 62px);
  line-height: 1.06;
  letter-spacing: -0.02em;
  color: var(--tunas-ink);
  text-wrap: balance;
}
/* Out of flow, so the line above it is centred on the frame whether the sub
   is showing or not. Left in flow it added its own height to the block and
   pushed the headline up off centre on the beat where it is the only thing
   on screen. */
.stage__note-sub {
  position: absolute;
  left: 50%;
  top: calc(100% + clamp(14px, 1.6vw, 24px));
  translate: -50% 0;
  width: 100%;
  opacity: var(--e2);
  transform: translateY(calc((1 - var(--e2)) * 14px));
  transition: opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  font-family: var(--font-family-default);
  font-weight: 400;
  font-size: clamp(16px, 1.5vw, 22px);
  line-height: 1.45;
  color: var(--tunas-ink-soft);
  max-width: 620px;
  margin-left: auto;
  margin-right: auto;
  text-wrap: balance;
}


/* --- beat four: the globe -------------------------------------------------
   Anchored to the bottom edge and pulled up by a little over half its own
   height, so it reads as a world the page is sitting on rather than a picture
   of one: the horizon is the fold, and the bottom of the sphere is simply not
   there. Sized off both axes because a short window would otherwise push the
   whole thing off screen. */
.stage__globe {
  position: absolute;
  left: 50%;
  top: 100%;
  z-index: 4;
  width: min(46vw, 68vh);
  aspect-ratio: 1;
  opacity: 0;
  /* Sits low and small, then rises into place when the beat lands. */
  transform: translate(-50%, -50%) scale(0.92);
  transition: opacity 0.85s cubic-bezier(0.22, 1, 0.36, 1),
    transform 1s cubic-bezier(0.22, 1, 0.36, 1);
}
body.stage-globe .stage__globe {
  opacity: 1;
  transform: translate(-50%, -57%) scale(1);
}

.stage__globe-canvas {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  cursor: grab;
  /* Not `none`: that would swallow vertical swipes and trap the scroll on a
     phone, where the globe covers most of the lower half of the frame. */
  touch-action: pan-y;
}

/* Emoji riding the arcs. cobe keeps a tracking element per arc and flips
   --cobe-visible-arc-<id> as it passes behind the sphere; the custom property
   is not a number, so when it is set the opacity declaration is dropped and
   the element shows, and when it is removed the fallback 0 hides it. */
.stage__globe-pin {
  position: absolute;
  bottom: anchor(top);
  left: anchor(center);
  translate: -50% 0;
  font-size: clamp(15px, 1.5vw, 22px);
  line-height: 1;
  pointer-events: none;
  filter: drop-shadow(0 1px 3px rgba(17, 24, 31, 0.28));
  transition: opacity 0.3s ease;
}

@media (max-width: 760px) {
  .stage__globe {
    width: min(88vw, 54vh);
  }
}

@media (prefers-reduced-motion: reduce) {
  .stage__globe {
    transition: opacity 0.3s linear;
    transform: translate(-50%, -57%);
  }
}

/* --- the TUNAS key ----------------------------------------------------------
   Nobody arrives knowing the name is an acronym, so the headline carries a
   footnote marker that opens the words it stands for. Annotation, not UI: the
   arrows are drawn on rather than faded in, the way a note is added to a page
   after the fact.

   The marker hangs in the margin. Its wrapper is zero-width and the glyph is
   positioned out of it, so adding the asterisk does not shift the centred
   headline by half its width. */
.tunas-key {
  position: relative;
  display: inline-block;
  width: 0;
  font-style: normal;
}
.tunas-key__mark {
  position: absolute;
  /* Out past the T's own left edge and up onto its shoulder. Tucked any
     closer it sat on the stem and read as part of the letter. */
  right: 0.2em;
  top: -0.99em;
  padding: 0 0.06em;
  border: 0;
  background: none;
  font: inherit;
  line-height: 1;
  color: var(--tunas-coral);
  cursor: help;
  transform-origin: 50% 60%;
}
/* A little life on the marker once the line has landed — enough to catch the
   eye and say "this is a thing you can touch", not enough to fidget. */
body.stage-note .tunas-key__mark {
  animation: key-bob 2.6s cubic-bezier(0.45, 0, 0.35, 1) infinite;
}
.tunas-key:hover .tunas-key__mark,
.tunas-key.is-open .tunas-key__mark {
  animation-play-state: paused;
}
@keyframes key-bob {
  0%,
  100% {
    transform: translateY(0) rotate(0deg) scale(1);
  }
  22% {
    transform: translateY(-0.13em) rotate(-14deg) scale(1.08);
  }
  46% {
    transform: translateY(0) rotate(6deg) scale(1);
  }
  62% {
    transform: translateY(-0.05em) rotate(-3deg) scale(1.02);
  }
  78% {
    transform: translateY(0) rotate(0deg) scale(1);
  }
}
/* The glyph itself is only a few pixels wide. This gives it a target you can
   actually land on without changing where it sits. */
.tunas-key__mark::after {
  content: "";
  position: absolute;
  inset: -8px -12px;
}
.tunas-key__mark:focus-visible {
  outline: 2px solid var(--tunas-teal);
  outline-offset: 3px;
  border-radius: 3px;
}

/* The drawing spans the whole frame rather than hanging off the marker: the
   arrows have to reach photographs sitting anywhere on the stage. app.js
   measures the geometry and writes the paths. */
.tunas-key__map {
  position: absolute;
  inset: 0;
  z-index: 7;
  pointer-events: none;
}
.tunas-key__lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.key__line,
.key__head {
  fill: none;
  stroke: var(--tunas-coral);
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* pathLength normalises every path to 1, so one dash length draws them all
     regardless of how long each curve actually is. */
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  opacity: 0;
  transition: stroke-dashoffset 0.01s linear;
}

.key__label {
  position: absolute;
  left: 0;
  top: 0;
  translate: var(--x) var(--y);
  transform: translate(-50%, -50%) scale(0.92);
  white-space: nowrap;
  font-family: var(--font-family-display);
  font-weight: 600;
  font-size: clamp(14px, 1.32vw, 19px);
  letter-spacing: -0.01em;
  color: var(--tunas-ink-soft);
  opacity: 0;
  transition: opacity 0.28s ease, transform 0.36s cubic-bezier(0.22, 1, 0.36, 1);
}
.key__label b {
  font-weight: 700;
  color: var(--tunas-coral);
}

/* Open on hover, on keyboard focus, and on tap. The marker is no longer an
   ancestor of the drawing, so the state is read off the shared frame with
   :has() instead of from a parent. */
.stage__pin:has(.tunas-key:hover) .key__line,
.stage__pin:has(.tunas-key:focus-within) .key__line,
.stage__pin:has(.tunas-key.is-open) .key__line,
.stage__pin:has(.tunas-key:hover) .key__head,
.stage__pin:has(.tunas-key:focus-within) .key__head,
.stage__pin:has(.tunas-key.is-open) .key__head {
  opacity: 1;
  stroke-dashoffset: 0;
}
.stage__pin:has(.tunas-key:hover) .key__line,
.stage__pin:has(.tunas-key:focus-within) .key__line,
.stage__pin:has(.tunas-key.is-open) .key__line {
  transition: stroke-dashoffset 0.42s cubic-bezier(0.65, 0, 0.35, 1)
    calc(var(--i) * 90ms);
}
.stage__pin:has(.tunas-key:hover) .key__head,
.stage__pin:has(.tunas-key:focus-within) .key__head,
.stage__pin:has(.tunas-key.is-open) .key__head {
  transition: stroke-dashoffset 0.14s linear calc(var(--i) * 90ms + 380ms);
}
.stage__pin:has(.tunas-key:hover) .key__label,
.stage__pin:has(.tunas-key:focus-within) .key__label,
.stage__pin:has(.tunas-key.is-open) .key__label {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
  transition-delay: calc(var(--i) * 90ms + 320ms);
}

/* The second line sits where two of the arrows travel, so it steps back while
   the note is open rather than the arrows being routed around it. */
.stage__pin:has(.tunas-key:hover) .stage__note-sub,
.stage__pin:has(.tunas-key:focus-within) .stage__note-sub,
.stage__pin:has(.tunas-key.is-open) .stage__note-sub {
  opacity: 0.16;
}
.stage__note-sub {
  transition: opacity 0.4s ease;
}

@media (max-width: 620px) {
  /* A phone cannot hold the fan, so the words are simply listed under the
     copy instead. */
  .tunas-key {
    position: static;
    width: auto;
  }
  .tunas-key__mark {
    position: static;
    margin-right: 0.1em;
  }
  .tunas-key__lines {
    display: none;
  }
  .tunas-key__map {
    inset: auto 0 12% 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 4px 16px;
  }
  .key__label {
    position: static;
    translate: none;
    transform: translateY(6px);
    font-size: 15px;
  }
  .stage__pin:has(.tunas-key:hover) .key__label,
  .stage__pin:has(.tunas-key:focus-within) .key__label,
  .stage__pin:has(.tunas-key.is-open) .key__label {
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .key__line,
  .key__head,
  .key__label {
    transition-duration: 0.001s !important;
    transition-delay: 0s !important;
  }
}

/* --- payout quotes off the globe -------------------------------------------
   Anchored to the same tracking element the arc's 💲 rides, so a quote is
   pinned to a real point on the sphere and travels with it. Sits above the
   emoji rather than on it. */
.globe-quote {
  position: absolute;
  bottom: calc(anchor(top) + 30px);
  left: anchor(center);
  translate: -50% 0;
  margin: 0;
  width: max-content;
  max-width: min(240px, 42vw);
  padding: 10px 13px;
  border-radius: 12px;
  background: var(--tunas-paper);
  box-shadow: 0 14px 34px rgba(17, 24, 31, 0.18),
    inset 0 0 0 1px rgba(17, 24, 31, 0.07);
  text-align: left;
  pointer-events: none;
  opacity: 0;
  transform: translateY(8px) scale(0.94);
  transform-origin: 50% 100%;
  transition: opacity 0.34s ease, transform 0.44s cubic-bezier(0.22, 1, 0.36, 1);
  z-index: 6;
}
.globe-quote.is-on {
  opacity: 1;
  transform: translateY(0) scale(1);
}
/* A small tail pointing back down at the arc it came from. */
.globe-quote::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  translate: -50% -3px;
  width: 11px;
  height: 11px;
  background: var(--tunas-paper);
  rotate: 45deg;
  box-shadow: 2px 2px 4px rgba(17, 24, 31, 0.08);
}
.globe-quote__text {
  margin: 0;
  font-family: var(--font-family-display);
  font-weight: 600;
  font-size: 14px;
  line-height: 1.28;
  letter-spacing: -0.01em;
  color: var(--tunas-ink);
}
.globe-quote__who {
  margin-top: 5px;
  font-family: var(--font-family-default);
  font-size: 11.5px;
  font-weight: var(--font-weight-medium);
  letter-spacing: 0.02em;
  color: var(--tunas-teal);
}

@media (max-width: 620px) {
  .globe-quote {
    max-width: 60vw;
    padding: 8px 11px;
  }
  .globe-quote__text {
    font-size: 12.5px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .globe-quote {
    transition-duration: 0.001s;
  }
}

/* --------------------------------------------------------------------------
   4. Header over the video
   -------------------------------------------------------------------------- */
body.is-intro .header-container,
body.is-intro .devbar {
  opacity: 0;
  pointer-events: none;
}
.header-container,
.devbar {
  transition: opacity 0.6s ease;
}

/* While the header sits on top of the video, invert it so it stays readable. */
body:is(.over-hero, .welcome-live, .reel-dark, .orbit-live, .fork-live) .header .logo {
  --logo-color: var(--tunas-paper);
}
body:is(.over-hero, .welcome-live, .reel-dark, .orbit-live, .fork-live) .header-menu {
  background: rgba(255, 252, 250, 0.14);
  border-color: rgba(255, 252, 250, 0.28);
}
body:is(.over-hero, .welcome-live, .reel-dark, .orbit-live, .fork-live) .header-menu__link {
  color: var(--tunas-paper);
}
body:is(.over-hero, .welcome-live, .reel-dark, .orbit-live, .fork-live) .header-menu__link:hover {
  background: rgba(255, 252, 250, 0.2);
  border-color: rgba(255, 252, 250, 0.3);
}
body:is(.over-hero, .welcome-live, .reel-dark, .orbit-live, .fork-live) .header__actions .dropdown__label {
  background: rgba(255, 252, 250, 0.14);
  border-color: rgba(255, 252, 250, 0.28);
}
body:is(.over-hero, .welcome-live, .reel-dark, .orbit-live, .fork-live) .header__actions .dropdown__label .icon {
  color: var(--tunas-paper);
}
body:is(.over-hero, .welcome-live, .reel-dark, .orbit-live, .fork-live) .header .button--color-default.button--primary {
  --button-background-color: var(--tunas-paper);
  --button-color: var(--tunas-ink);
}
body:is(.over-hero, .welcome-live, .reel-dark, .orbit-live, .fork-live) .header::before {
  opacity: 0;
}


/* --- header alignment ------------------------------------------------------
   Three equal-weight columns rather than space-between. With space-between
   the middle item is centred in whatever the outer two leave over, and those
   are nowhere near equal — the logo is under 100px while the language,
   Sign in and Sign up cluster is over 300. The nav sat 120px left of the page
   centre because of it. A 1fr / auto / 1fr grid centres the nav on the PAGE
   and lets the sides be whatever width they need. */
.header__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  /* Full bleed. The clone capped the bar at the 1440 content width, so on a
     wide monitor the whole header was centred inside that cap — the mark got
     dragged in from the left edge and the buttons in from the right, which is
     what made them read as crowding the middle. The bar is chrome, not
     content; it should run the width of the window. */
  max-width: none;
  padding-inline: clamp(16px, 1vw, 24px);
}
.header__logo {
  justify-self: start;
}
.header__menu {
  justify-self: center;
}
.header__actions {
  justify-self: end;
}

@media (max-width: 1023px) {
  /* No centre nav at this width, so the grid collapses back to a simple
     two-end row. */
  .header__inner {
    grid-template-columns: auto auto;
  }
  .header__actions {
    grid-column: 2;
  }
}

/* --- sign up --------------------------------------------------------------
   Sign in is the quiet one and Sign up is the ask, so they are a pair rather
   than two identical buttons: outline over the video, filled teal against a
   light page. */
.header__signup {
  --button-background-color: var(--tunas-teal);
  --button-color: var(--tunas-paper);
  margin-left: 8px;
}
.header__signup:hover {
  --button-background-color: var(--tunas-teal-pressed);
}
body:is(.over-hero, .welcome-live, .reel-dark, .orbit-live, .fork-live) .header .header__signup {
  --button-background-color: transparent;
  --button-color: var(--tunas-paper);
  box-shadow: inset 0 0 0 1.5px rgba(255, 252, 250, 0.55);
}
body:is(.over-hero, .welcome-live, .reel-dark, .orbit-live, .fork-live) .header .header__signup:hover {
  --button-background-color: rgba(255, 252, 250, 0.16);
}

/* Off the video the header has to read on cream, which is what the inversion
   was hiding: ink type, an ink-tinted nav pill, and the bar's own scrim back. */
body:not(.over-hero):not(.welcome-live):not(.reel-dark):not(.orbit-live):not(.fork-live) .header-menu {
  background: rgba(17, 24, 31, 0.05);
  border-color: rgba(17, 24, 31, 0.09);
}
body:not(.over-hero):not(.welcome-live):not(.reel-dark):not(.orbit-live):not(.fork-live) .header-menu__link,
body:not(.over-hero):not(.welcome-live):not(.reel-dark):not(.orbit-live):not(.fork-live) .header__actions .dropdown__label .icon {
  color: var(--tunas-ink);
}
body:not(.over-hero):not(.welcome-live):not(.reel-dark):not(.orbit-live):not(.fork-live) .header__actions .dropdown__label {
  background: rgba(17, 24, 31, 0.05);
  border-color: rgba(17, 24, 31, 0.09);
}
body:not(.over-hero):not(.welcome-live):not(.reel-dark):not(.orbit-live):not(.fork-live) .header .logo {
  --logo-color: var(--tunas-ink);
}

/* --------------------------------------------------------------------------
   5. Reduced motion — show everything, animate nothing
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .intro {
    transition: none;
  }
  .intro__logo {
    opacity: 1;
    transform: none;
    animation: none;
  }
  .stage {
    height: 100vh;
  }
  .stage__video {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .blur-char {
    opacity: 1;
    transform: none;
    filter: none;
  }
  .stage__title.is-revealed .blur-char {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   6. Small screens
   -------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .stage {
    height: auto;
  }
  .stage__title {
    padding: 0 1vw;
    font-size: 11.6vw;
    letter-spacing: -0.04em;
  }
}

/* "digitally" carries the brand accent inside the lead line. */
.stage__note-lead em {
  font-style: normal;
  color: var(--tunas-teal);
}
