/* ============================================================================
   BusTrakr — core system: tokens, typography, chrome, motion primitives.

   This page commits to one visual world (a near-black cinematic environment)
   rather than shipping light and dark variants, so every colour is painted
   explicitly and nothing is inherited from the host.
   ========================================================================= */

:root {
  color-scheme: dark;

  /* Ground & structure. Neutrals are biased a few degrees toward the signal
     hue so nothing on the page reads as a default grey. */
  --ink:        #05070c;
  --ink-2:      #080c14;
  --ink-3:      #0c121c;
  --panel:      rgba(11, 16, 26, 0.58);
  --panel-thin: rgba(9, 14, 23, 0.44);
  --panel-solid:#0b1019;
  --tick:       rgba(190, 226, 255, 0.30);
  --line:       rgba(255, 255, 255, 0.085);
  --line-2:     rgba(255, 255, 255, 0.16);

  /* Text */
  --text:       #e9ecf5;
  --text-dim:   #8b95ab;
  --text-mute:  #5a6478;

  /* Accents. Four of these are the running application's own tokens; the
     signal cyan is the site-facing brightening of its periwinkle blue. */
  --signal:      #38ddf5;
  --signal-soft: #7c93e0;
  --violet:      #9b8ce0;
  --live:        #7fb88a;
  --warn:        #ffb454;

  /* Read by the WebGL layer so the 3D and the CSS can never disagree. */
  --signal-rgbsrc: #38ddf5;
  --violet-rgbsrc: #9b8ce0;

  --font-display: "Archivo", "Arial Black", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-body:    "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-serif:   "Instrument Serif", Georgia, "Times New Roman", serif;
  --font-mono:    "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --ease:      cubic-bezier(0.16, 1, 0.30, 1);
  --ease-soft: cubic-bezier(0.22, 0.61, 0.36, 1);

  --gutter: clamp(20px, 5vw, 84px);
  --rail-w: 190px;
  --nav-h: 74px;
}

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

html {
  scroll-behavior: smooth;
  /* Anchors land below the fixed header rather than under it. */
  scroll-padding-top: calc(var(--nav-h) + 12px);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* `clip`, not `hidden`: overflow-x:hidden silently turns <body> into a
     scroll container, which breaks every `position: sticky` section on the
     page. `clip` contains overflow without creating one. */
  overflow-x: clip;
}

img, svg, canvas { max-width: 100%; }
svg { display: block; }

::selection { background: rgba(56, 221, 245, 0.26); color: #fff; }

:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 200;
  padding: 10px 16px;
  background: var(--signal);
  color: #04070c;
  font: 600 13px/1 var(--font-mono);
  border-radius: 8px;
  transform: translateY(-160%);
  transition: transform 0.25s var(--ease);
}
.skip-link:focus-visible { transform: none; }

/* ---------------------------------------------------------------- 3D stage */

#stage {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  /* Above the veil, below the content. The veil is a sibling that comes
     later in the DOM, so without an explicit order it would paint over the
     canvas and hide the entire 3D layer. */
  z-index: 1;
  /* The canvas is decoration behind live text — never let it eat a tap. */
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.4s var(--ease-soft);
}
#stage.is-live { opacity: 1; }

/* Painted while the WebGL layer boots, and left in place permanently when
   WebGL is unavailable — so the page always sits on a composed ground rather
   than flat black. */
.stage-veil {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(90ch 60ch at 62% 18%, rgba(56, 221, 245, 0.10), transparent 62%),
    radial-gradient(70ch 50ch at 18% 78%, rgba(155, 140, 224, 0.09), transparent 64%),
    linear-gradient(180deg, #070b13 0%, #05070c 52%, #04060a 100%);
}

/* --------------------------------------------------------------------- nav */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 60;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 0 var(--gutter);
  background: linear-gradient(180deg, rgba(5, 7, 12, 0.86), rgba(5, 7, 12, 0));
  transition: background 0.4s var(--ease-soft), border-color 0.4s var(--ease-soft);
  border-bottom: 1px solid transparent;
}
.nav.is-stuck {
  background: rgba(6, 9, 15, 0.82);
  backdrop-filter: blur(18px) saturate(130%);
  -webkit-backdrop-filter: blur(18px) saturate(130%);
  border-bottom-color: var(--line);
}

.nav__brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  text-decoration: none;
  margin-right: auto;
}
.nav__word {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 118%;
  font-size: 15px;
  letter-spacing: 0.10em;
}
/* Three ascending bars — a signal meter, not a bus icon. */
.nav__mark { display: flex; align-items: flex-end; gap: 2px; height: 14px; }
.nav__mark span {
  width: 3px;
  background: var(--signal);
  border-radius: 1px;
  animation: meter 2.4s var(--ease-soft) infinite;
}
.nav__mark span:nth-child(1) { height: 45%; animation-delay: 0s; }
.nav__mark span:nth-child(2) { height: 75%; animation-delay: 0.18s; }
.nav__mark span:nth-child(3) { height: 100%; animation-delay: 0.36s; opacity: 0.55; }
@keyframes meter {
  0%, 100% { transform: scaleY(0.72); opacity: 0.55; }
  45%      { transform: scaleY(1);    opacity: 1; }
}

.nav__links { display: flex; gap: 26px; }
.nav__links a {
  font: 500 13px/1 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--text-dim);
  text-decoration: none;
  position: relative;
  padding: 6px 0;
  transition: color 0.25s var(--ease);
}
.nav__links a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--signal);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s var(--ease);
}
.nav__links a:hover { color: var(--text); }
.nav__links a:hover::after { transform: scaleX(1); }

.nav__actions { display: flex; align-items: center; gap: 12px; }

/* ----------------------------------------------------------------- buttons */

.btn {
  --btn-fg: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 20px;
  border-radius: 100px;
  border: 1px solid var(--line-2);
  color: var(--btn-fg);
  background: transparent;
  font: 600 13px/1 var(--font-mono);
  letter-spacing: 0.04em;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 0.3s var(--ease), background 0.3s var(--ease),
              color 0.3s var(--ease), transform 0.3s var(--ease);
}
.btn svg { width: 15px; height: 15px; }
/* Inside the flex-column pinned blocks a stretched button fills the whole
   column; keep it the width of its own content. */
.sec__inner > .btn, .sec__inner > .eyebrow { align-self: flex-start; }
.answer__inner > .btn, .answer__inner > .eyebrow,
.connected__inner > .btn, .connected__inner > .eyebrow,
.finale__inner > .btn, .finale__inner > .eyebrow { align-self: center; }
.btn:hover { border-color: var(--signal); color: #fff; transform: translateY(-1px); }

.btn--primary {
  background: var(--signal);
  border-color: var(--signal);
  color: #04070c;
  --btn-fg: #04070c;
}
.btn--primary:hover {
  background: #5ce7fb;
  border-color: #5ce7fb;
  color: #04070c;
}
.btn--lg { padding: 16px 30px; font-size: 14px; }
.btn--ghost { padding: 10px 17px; }

/* Sound toggle */
.sound {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 9px 15px 9px 12px;
  border-radius: 100px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-dim);
  font: 500 12px/1 var(--font-mono);
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.sound:hover { color: var(--text); border-color: var(--line-2); }
.sound__bars { display: flex; align-items: center; gap: 2px; height: 12px; }
.sound__bars i {
  width: 2px;
  height: 3px;
  background: currentColor;
  border-radius: 1px;
  transition: height 0.3s var(--ease);
}
.sound[aria-pressed="true"] { color: var(--signal); border-color: rgba(56, 221, 245, 0.4); }
.sound[aria-pressed="true"] .sound__bars i { animation: eq 1.1s ease-in-out infinite; }
.sound[aria-pressed="true"] .sound__bars i:nth-child(2) { animation-delay: 0.15s; }
.sound[aria-pressed="true"] .sound__bars i:nth-child(3) { animation-delay: 0.3s; }
.sound[aria-pressed="true"] .sound__bars i:nth-child(4) { animation-delay: 0.45s; }
@keyframes eq {
  0%, 100% { height: 3px; }
  50%      { height: 12px; }
}

/* -------------------------------------------------------------------- rail */

.rail {
  position: fixed;
  top: 50%;
  right: clamp(14px, 2.4vw, 34px);
  transform: translateY(-50%);
  z-index: 55;
  display: flex;
  gap: 14px;
  opacity: 0;
  transition: opacity 0.6s var(--ease-soft);
}
/* The rail sits over whatever the 3D is doing; without this the labels
   disappear into a particle burst exactly when they're most useful. */
.rail::before {
  content: "";
  position: absolute;
  inset: -26px -22px -26px -30px;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    120% 68% at 78% 50%,
    rgba(4, 6, 11, 0.82) 0%,
    rgba(4, 6, 11, 0.55) 46%,
    rgba(4, 6, 11, 0) 82%
  );
}
.rail.is-visible { opacity: 1; }

.rail__track {
  position: relative;
  width: 1px;
  background: var(--line);
  border-radius: 1px;
}
.rail__fill {
  position: absolute;
  inset: 0 0 auto 0;
  height: 0%;
  background: linear-gradient(180deg, var(--signal), var(--violet));
  border-radius: 1px;
}

.rail__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.rail__list a {
  display: flex;
  align-items: baseline;
  gap: 9px;
  padding: 5px 0;
  font: 500 10.5px/1 var(--font-mono);
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--text-mute);
  text-decoration: none;
  transition: color 0.3s var(--ease);
}
.rail__list a span { color: var(--line-2); font-size: 9.5px; }
.rail__list a:hover { color: var(--text-dim); }
.rail__list a.is-active { color: var(--signal); }
.rail__list a.is-active span { color: var(--signal); }

/* -------------------------------------------------------------- typography */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 22px;
  font: 600 11px/1 var(--font-mono);
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--signal);
}
.eyebrow--center { justify-content: center; }
.eyebrow__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--signal);
  box-shadow: 0 0 0 0 rgba(56, 221, 245, 0.55);
  animation: ping 2.6s var(--ease-soft) infinite;
}
@keyframes ping {
  0%   { box-shadow: 0 0 0 0 rgba(56, 221, 245, 0.5); }
  70%  { box-shadow: 0 0 0 11px rgba(56, 221, 245, 0); }
  100% { box-shadow: 0 0 0 0 rgba(56, 221, 245, 0); }
}

/* The three display scales. All uppercase, tightly tracked, deliberately
   oversized — the words are the art direction, not a label on it. */
.mega, .big, .intro__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-stretch: 116%;
  text-transform: uppercase;
  letter-spacing: -0.025em;
  line-height: 0.86;
  margin: 0;
  text-wrap: balance;
  color: #fff;
}
.mega        { font-size: clamp(2.9rem, 10.5vw, 9rem); }
/* Capped below .mega: past ~130px the hero headline grows into the vehicle
   on wide screens, and the opening shot has two subjects fighting. */
.intro__title{ font-size: clamp(3.1rem, 9.4vw, 8.1rem); }
.big         { font-size: clamp(2.1rem, 5.4vw, 4.3rem); line-height: 0.94; letter-spacing: -0.02em; }
.mega--center{ text-align: center; }
.mega--tight { line-height: 0.9; }

.line--accent > span,
.line--accent {
  background: linear-gradient(96deg, #ffffff 18%, var(--signal) 62%, var(--signal-soft) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* The editorial counter-voice: lowercase, italic, high-contrast serif. Used
   three times on the whole page, always against the industrial caps. */
.line--serif > span {
  font-family: var(--font-serif);
  font-weight: 400;
  font-style: italic;
  font-stretch: normal;
  text-transform: none;
  letter-spacing: -0.01em;
  color: var(--signal);
  /* The serif's cap height is shorter, so it needs a nudge up in size — but
     only a little: at 1.16em the accent line wrapped and unbalanced the
     whole block. */
  font-size: 0.94em;
  line-height: 1.0;
}

.lede {
  margin: 0;
  font-size: clamp(1rem, 1.25vw, 1.16rem);
  line-height: 1.62;
  color: var(--text-dim);
  max-width: 46ch;
}

.num {
  font: 500 11px/1 var(--font-mono);
  color: var(--signal);
  letter-spacing: 0.08em;
}

/* ------------------------------------------------------------------ motion */

/* Reveals are opt-in and only armed once JS confirms it is running, so a
   script failure can never leave the page invisible. */
.reveals-armed [data-reveal]:not(.line) {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.95s var(--ease), transform 0.95s var(--ease);
}
.reveals-armed [data-reveal]:not(.line).is-revealed {
  opacity: 1;
  transform: none;
}

/* Masked line reveal: the glyphs slide up out of their own overflow box. */
.line { display: block; overflow: hidden; padding-bottom: 0.06em; }
.line > span { display: block; will-change: transform; }
.reveals-armed .line > span { transform: translateY(112%); }
.reveals-armed .line {
  transition: none;
}
.reveals-armed .line > span {
  transition: transform 1.15s var(--ease);
}
.reveals-armed .line[data-reveal].is-revealed > span,
.reveals-armed [data-reveal].is-revealed .line > span { transform: none; }
/* Stagger stacked lines inside one revealed block. */
.reveals-armed [data-reveal].is-revealed .line:nth-child(2) > span { transition-delay: 0.10s; }
.reveals-armed [data-reveal].is-revealed .line:nth-child(3) > span { transition-delay: 0.20s; }

.scroll-cue {
  position: absolute;
  left: var(--gutter);
  bottom: 30px;
  display: flex;
  align-items: center;
  gap: 12px;
  font: 500 10.5px/1 var(--font-mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-mute);
}
.scroll-cue__line {
  width: 46px;
  height: 1px;
  background: linear-gradient(90deg, var(--signal), transparent);
  transform-origin: left;
  animation: sweep 2.8s var(--ease-soft) infinite;
}
@keyframes sweep {
  0%, 100% { transform: scaleX(0.35); opacity: 0.45; }
  50%      { transform: scaleX(1);    opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveals-armed [data-reveal]:not(.line),
  .reveals-armed .line > span {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .finale__line,
  #finale-cta {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .nav__mark span,
  .eyebrow__dot,
  .scroll-cue__line,
  .sound__bars i { animation: none !important; }
}
