/* RailMind launch site — tokens lifted from the app's Core/Theme.swift and the Figma launch file
   (A7NUxNKc34DYRV55aeAqTw). The site follows the app: Auto / Light / Dark. Auto tracks the OS via
   `color-scheme: light dark` + light-dark(); the nav toggle pins a mode by setting data-theme on
   <html>, which narrows color-scheme and re-resolves every token below.

   Light values are the WCAG-retuned set from the app (PR #66): accent #0075A6, success #17783D,
   cta #0054A3. Each pair is declared twice on purpose — the bare dark hex first, the light-dark()
   pair second. A browser too old for light-dark() drops the second declaration and keeps the dark
   site it has always had, which is the correct degradation. Do not "simplify" by deleting the
   first declaration. */

:root {
  color-scheme: light dark;

  --ink: #14141A;
  --ink: light-dark(#F4F4F7, #14141A);          /* page — darkBackground / light surface */
  --surface: #1B1B23;
  --surface: light-dark(#FFFFFF, #1B1B23);      /* cards — one step off ink */
  --control: #292933;
  --control: light-dark(#E9E9EF, #292933);
  --accent: #00BFF2;
  --accent: light-dark(#0075A6, #00BFF2);       /* 4.67:1 on light ink, 13px mono passes AA */
  --cta: #0054A3;                               /* ctaFill — AA with white text, both modes */
  --cta-hover: #00457F;
  --success: #33CC66;
  --success: light-dark(#17783D, #33CC66);      /* 5.05:1 on light ink — the [OK] flags */
  --text: #FFFFFF;
  --text: light-dark(#14141A, #FFFFFF);
  --text-2: #9E9E9E;
  --text-2: light-dark(#52525E, #9E9E9E);       /* 7.02:1 on light ink */
  --hairline: rgba(255, 255, 255, 0.10);
  --hairline: light-dark(rgba(0, 0, 0, 0.12), rgba(255, 255, 255, 0.10));

  /* Scheme-dependent washes. These were hardcoded rgba(0,191,242,…) / rgba(20,20,26,…) literals
     scattered through the sheet; they are tokens now so a mode switch cannot miss one. */
  --nav-bg: rgba(20, 20, 26, .82);
  --nav-bg: light-dark(rgba(244, 244, 247, .82), rgba(20, 20, 26, .82));
  --hero-glow: rgba(0, 191, 242, .14);
  --hero-glow: light-dark(rgba(0, 117, 166, .10), rgba(0, 191, 242, .14));
  --accent-wash: rgba(0, 191, 242, .04);
  --accent-wash: light-dark(rgba(0, 117, 166, .05), rgba(0, 191, 242, .04));
  --accent-edge: color-mix(in srgb, var(--accent) 45%, transparent);
  --ghost-hover: rgba(255, 255, 255, .05);
  --ghost-hover: light-dark(rgba(0, 0, 0, .05), rgba(255, 255, 255, .05));

  --radius: 14px;          /* RailThrottleTheme.cornerRadius */
  --radius-sm: 8px;

  /* Space — the app's 4pt rhythm */
  --xs: 4px; --sm: 8px; --md: 12px; --lg: 16px; --xl: 24px;
  --2xl: 40px; --3xl: 64px; --4xl: 88px;

  /* The app locks Helvetica Neue + SF Mono (Apple-platform faces). Non-Apple visitors fall back
     through the grotesque cousins — Helvetica, then Arial — NOT Inter: Inter-as-fallback meant
     most Windows/Android visitors rendered the one typeface the brand deliberately never chose. */
  --sans: "Helvetica Neue", Helvetica, Arial, system-ui, "Segoe UI", sans-serif;
  --mono: ui-monospace, "SF Mono", "IBM Plex Mono", Menlo, monospace;
}

/* The toggle pins a mode. Narrowing color-scheme is all that is needed — every light-dark() pair
   above re-resolves against it, and native form controls / scrollbars follow too. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark; }

* { box-sizing: border-box; margin: 0; padding: 0; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 50;
  background: var(--cta); color: #fff; padding: 12px 20px; border-radius: 0 0 var(--radius-sm) 0;
  text-decoration: none; font-size: 14px; font-weight: 600;
}
.skip:focus { left: 0; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  background: var(--ink);
  color: var(--text);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 1200px; margin: 0 auto; padding: 0 var(--xl); }
.narrow { max-width: 760px; margin: 0 auto; }

/* ---------- nav ---------- */
.nav {
  position: sticky; top: 0; z-index: 20;
  background: var(--nav-bg);
  backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid var(--hairline);
}
.nav-in { display: flex; align-items: center; gap: var(--xl); height: 64px; }
.brand { display: flex; align-items: center; gap: 10px; font-weight: 700; letter-spacing: -.01em; text-decoration: none; color: var(--text); }
.brand img { width: 28px; height: 28px; border-radius: 7px; }
.nav-links { margin-left: auto; display: flex; align-items: center; gap: var(--xl); }
.nav-links a { color: var(--text-2); text-decoration: none; font-size: 15px; font-weight: 500; }
.nav-links a:hover { color: var(--text); }
/* The nav CTA is an <a>, so `.nav-links a` (0,1,1) would otherwise repaint .btn's white label in
   the muted nav-link grey — invisible on the blue fill. Restate it at equal-or-higher specificity. */
.nav-links a.btn, .nav-links a.btn:hover { color: #fff; }
@media (max-width: 860px) { .nav-links a:not(.nav-cta) { display: none; } }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: var(--sm);
  background: var(--cta); color: #fff; text-decoration: none;
  padding: 14px 24px; border-radius: 999px; font-weight: 600; font-size: 15px;
  border: 0; transition: background .15s ease;
}
.btn:hover { background: var(--cta-hover); }
.btn-ghost { background: transparent; color: var(--text-2); border: 1px solid var(--hairline); }
.btn-ghost:hover { background: var(--ghost-hover); color: var(--text); }
.btn.is-soon { background: color-mix(in srgb, var(--cta) 55%, transparent); cursor: default; }
.btn.is-soon:hover { background: color-mix(in srgb, var(--cta) 55%, transparent); }
.nav-cta { font-size: 14px; padding: 9px 16px; }
/* Figma's hero CTA row is 71px tall (Badge/App Store) — match that mass while the badge
   itself waits on an actual App Store listing. */
.btn-lg { padding: 17px 30px; font-size: 16px; }

/* ---------- eyebrow / section ---------- */
.eyebrow {
  font-family: var(--mono); font-size: 13px; font-weight: 500;
  letter-spacing: 2px; color: var(--accent); text-transform: uppercase;
}
section { padding: var(--4xl) 0; border-bottom: 1px solid var(--hairline); }
h1, h2, h3 { letter-spacing: -.02em; line-height: 1.12; }
h2 { font-size: 32px; font-weight: 700; margin: var(--lg) 0 var(--md); }
.lede { color: var(--text-2); font-size: 17px; max-width: 640px; }

/* ---------- hero ---------- */
/* Figma Landing/Desktop 1440 → hero (13:22) is centre-stacked and anchored by the editor canvas. */
.hero { position: relative; overflow: hidden; padding: var(--4xl) 0 var(--3xl); border-bottom: 1px solid var(--hairline); }
.hero::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(60rem 40rem at 50% -10%, var(--hero-glow), transparent 60%);
}
.hero .wrap { position: relative; }
.hero-in { text-align: center; }
.hero h1 { font-size: clamp(38px, 5.4vw, 64px); font-weight: 700; margin: var(--lg) 0; }
.hero .lede { font-size: 20px; max-width: 720px; margin-inline: auto; }
.hero-cta { display: flex; flex-wrap: wrap; gap: var(--lg); margin: var(--2xl) 0 var(--xl); align-items: center; justify-content: center; }

/* spec plates — the bordered chips from the Figma hero (13:39), not dot-pills */
.plates { display: flex; flex-wrap: wrap; gap: var(--md); list-style: none; justify-content: center; }
.plates li {
  font-family: var(--mono); font-size: 12px; letter-spacing: 1.5px; text-transform: uppercase;
  /* Optical, not mathematical, centring. These labels are ALL CAPS, so no glyph ever reaches the
     descender; symmetric padding centres the line box but leaves the ink sitting visibly high in
     the chip. Weighting the padding 9/5 drops the caps ~2px onto the optical centre. */
  color: var(--accent); padding: 9px 14px 5px; border-radius: var(--radius-sm);
  border: 1px solid var(--accent-edge);
  background: var(--accent-wash);
}

.hero-art { margin-top: var(--4xl); }
.hero-art img {
  width: 100%; height: auto; display: block;
  border-radius: var(--radius); border: 1px solid var(--hairline);
}

/* ---------- spec box (the instrument readout) ---------- */
.spec {
  border: 1px solid var(--accent-edge);
  border-radius: var(--radius-sm);
  padding: 32px 36px; display: inline-flex; flex-direction: column; gap: 18px;
  background: var(--accent-wash);
  margin-top: var(--2xl);
}
.spec-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--2xl);
  font-family: var(--mono); font-size: 16px; letter-spacing: 2px; text-transform: uppercase;
}
.flag { color: var(--success); font-size: 14px; letter-spacing: 1px; white-space: nowrap; }
@media (max-width: 520px) {
  .spec { padding: 24px; width: 100%; }
  .spec-row { font-size: 13px; letter-spacing: 1px; gap: var(--lg); }
}
.center { text-align: center; }
.center .lede, .center .spec { margin-left: auto; margin-right: auto; }
.center .spec { text-align: left; }

/* ---------- feature sections ---------- */
/* Figma sections 14:86 / 14:92 / 14:101 / 14:107: a 440px text column beside a 580x400 art
   frame, alternating sides down the page. */
figure { margin: 0; }

.feature-in {
  display: grid; grid-template-columns: minmax(0, 440fr) minmax(0, 580fr);
  gap: var(--4xl); align-items: center;
}
.feature-in.reverse { grid-template-columns: minmax(0, 580fr) minmax(0, 440fr); }
.feature-text .lede { max-width: 46ch; }
.feature-art img { width: 100%; height: auto; display: block; }

@media (max-width: 900px) {
  .feature-in, .feature-in.reverse { grid-template-columns: 1fr; gap: var(--2xl); }
  /* art below prose on every section, whatever the desktop order */
  .feature-in.reverse .feature-art { order: 2; }
  .feature-in.reverse .feature-text { order: 1; }
}

/* ---------- example layouts ---------- */
/* Figma examples-grid (14:117) is 3 across, 2 rows — not a free-wrapping auto-fit. */
.examples {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--xl); margin-top: var(--2xl); text-align: left;
}
@media (max-width: 980px) { .examples { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .examples { grid-template-columns: 1fr; } }
.ex {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius); padding: 20px;
}
.ex img { width: 100%; height: auto; display: block; }
.ex figcaption { display: flex; flex-direction: column; gap: 8px; margin-top: 20px; }
.ex-name { font-size: 15px; font-weight: 700; color: var(--text); }
.ex-meta { font-family: var(--mono); font-size: 11px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--text-2); }
.ex-more { color: var(--text-2); font-size: 14px; margin-top: var(--xl); }

/* ---------- final cta ---------- */
/* Two lines, broken at the comma: "If it connects on screen, / it connects on the table."
   18ch forced three lines. 26ch gave two but pulled "it" onto line one, breaking mid-clause;
   24ch is narrow enough that the second clause stays whole, so the two halves stay parallel. */
.final-line { font-size: clamp(28px, 4vw, 40px); max-width: 24ch; margin-inline: auto; text-wrap: balance; }
.final-cta { margin-top: var(--xl); }

/* ---------- faq ---------- */
.faq { border: 1px solid var(--hairline); border-radius: var(--radius); overflow: hidden; margin-top: var(--2xl); background: var(--surface); }
.faq details { border-bottom: 1px solid var(--hairline); }
.faq details:last-child { border-bottom: 0; }
.faq summary { cursor: pointer; list-style: none; padding: var(--xl); font-weight: 600; display: flex; justify-content: space-between; gap: var(--lg); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--text-2); font-size: 20px; line-height: 1; transition: transform .15s ease; }
.faq details[open] summary::after { transform: rotate(45deg); }
.faq p { padding: 0 var(--xl) var(--xl); color: var(--text-2); font-size: 15px; }

/* ---------- footer ---------- */
footer { padding: var(--3xl) 0; color: var(--text-2); font-size: 14px; }
footer .cols { display: flex; flex-wrap: wrap; gap: var(--xl); justify-content: space-between; }
.foot-brand { color: var(--text); font-weight: 700; }
footer a { color: var(--text-2); }
footer a:hover { color: var(--text); }
.legal { font-size: 12px; margin-top: var(--xl); opacity: .75; line-height: 1.7; }
.offline { font-family: var(--mono); font-size: 12px; letter-spacing: 2px; color: var(--accent); }

/* ---------- content pages ---------- */
.doc { padding: var(--3xl) 0; }
.doc h1 { font-size: 44px; font-weight: 700; margin: var(--lg) 0; }
.doc h2 { font-size: 21px; margin-top: var(--2xl); }
.doc p { color: var(--text-2); margin-top: var(--md); }
.doc a { color: var(--accent); }
/* ...but not buttons. `.doc a` (0,1,1) outranks `.btn` (0,1,0), so a filled button inside a .doc
   page had its label repainted in the accent colour — on 404 that was cyan on the blue fill at
   roughly 1.5:1, effectively illegible in light mode. Same collision family as `.nav-links a.btn`.
   Higher specificity and declared after, so these win. */
.doc a.btn { color: #fff; }
.doc a.btn-ghost { color: var(--text-2); }
.doc a.btn-ghost:hover { color: var(--text); }
.back { color: var(--text-2); text-decoration: none; font-size: 14px; display: inline-block; margin-bottom: var(--xl); }

/* The 404 headline is a single sentence and should read as a single line. It sat inside .narrow
   (760px), which broke it after "connect to". It now uses the full wrap and scales with the
   viewport, so it stays on one line from desktop down to about a large phone, and only wraps
   where wrapping is genuinely unavoidable. */
.doc h1.err-title { max-width: none; font-size: clamp(24px, 4.4vw, 44px); }
.back:hover { color: var(--text); }

/* ---------- launch switch ---------- */
/* One attribute on <html> flips the whole page between pre-launch and live:
   data-launch="soon" (today) → the "Coming to the App Store" elements
   data-launch="live"          → the App Store badge + download links
   Both markups ship in the HTML so launch day is an attribute edit, not a rewrite. No JS: the
   correct CTA is right in the first paint, and a JS-blocked visitor still sees the truth. */
:root[data-launch="soon"] .cta-live { display: none !important; }
:root[data-launch="live"] .cta-soon { display: none !important; }

/* ---------- App Store badge ---------- */
/* Apple's rules, enforced in CSS (see assets/badge/README.md):
   min height 40px · clear space ≥ ¼ height · never modify, recolour, angle, crop or shadow it.
   Black artwork on light backgrounds, white on dark — hence two files, swapped by scheme rather
   than by filter, because a CSS filter would be a prohibited modification. */
.appstore-badge { display: inline-block; line-height: 0; border-radius: var(--radius-sm); }
.appstore-badge img { height: 54px; width: auto; display: block; }   /* 54px > 40px minimum */
.appstore-badge:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
/* Every swap rule below must out-specify `.appstore-badge img` (0,1,1) or both badges paint at
   once — a bare `.badge-dark { display: none }` (0,1,0) loses and stacks them. Keep the
   `.appstore-badge` prefix on all four. */
.appstore-badge .badge-dark { display: none; }
:root[data-theme="dark"] .appstore-badge .badge-dark { display: block; }
:root[data-theme="dark"] .appstore-badge .badge-light { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .appstore-badge .badge-dark { display: block; }
  :root:not([data-theme="light"]) .appstore-badge .badge-light { display: none; }
}

/* ---------- theme toggle ---------- */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; flex: none;
  background: transparent; color: var(--text-2);
  border: 1px solid var(--hairline); border-radius: 999px;
  cursor: pointer; transition: background .15s ease, color .15s ease;
}
.theme-toggle:hover { background: var(--ghost-hover); color: var(--text); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-toggle svg { width: 17px; height: 17px; display: block; }
/* Show the icon of the mode you would switch TO, so the control reads as an action. */
.theme-toggle .i-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .i-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .i-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .i-sun { display: block; }
  :root:not([data-theme="light"]) .theme-toggle .i-moon { display: none; }
}

/* ---------- theme-swapped imagery ---------- */
/* Two <img> per illustration, one shown per mode. Same mechanism as the App Store badge, and for
   the same reason: <picture media="(prefers-color-scheme:…)"> only answers the OS, so it would
   ignore the nav toggle and strand a pinned theme with the wrong artwork. loading="lazy" on both
   twins keeps the hidden one from being fetched at all — a display:none lazy image is never
   requested, so this costs no extra bytes despite shipping two sources.
   Specificity note: .themed .t-dark is (0,2,0), which must out-rank `.hero-art img` /
   `.feature-art img` / `.ex img` at (0,1,1) — otherwise both twins paint, as the badge did. */
.themed .t-dark { display: none; }
:root[data-theme="dark"] .themed .t-dark { display: block; }
:root[data-theme="dark"] .themed .t-light { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .themed .t-dark { display: block; }
  :root:not([data-theme="light"]) .themed .t-light { display: none; }
}
