/*
 * Interurban — launch site.
 *
 * Written by hand, no framework. The rules that are not obvious carry a
 * comment saying why they are there.
 *
 * The page is a technical document that happens to be selling something, so
 * the type system is the same one the game uses: Barlow Condensed for signage
 * and display, Inter for interface text, IBM Plex Mono for every figure, and
 * every figure tabular. If a number is on this page you should be able to
 * line it up with the number under it.
 */

/* ════════════════════════════════════════════════════════════════════════
   Tokens
   ════════════════════════════════════════════════════════════════════════ */

:root {
  --ground: #0E1116;
  --panel: #12171F;
  /* One step up from --panel, for a card sitting on a panel. */
  --panel-2: #171D27;
  --rule: #242C38;
  --ink: #E8ECF1;
  --ink-2: #A3AEBC;

  /*
   * The brand's ink-3 is #6B7686. Measured with the WCAG 2.x relative
   * luminance formula it scores 4.11:1 on --ground, 3.90:1 on --panel and
   * 3.67:1 on --panel-2 — all three under the 4.5:1 AA threshold for normal
   * text, and every use of it on this site is small text.
   *
   * #7E8898 scores 5.28 / 5.02 / 4.72 and sits in the same visual register.
   * The first attempt at this fix was #7A8494, which clears --ground and
   * --panel but lands at 4.48 on --panel-2 — the quotation attributions in
   * section 06 sit on exactly that ground, so it failed by two hundredths
   * where it mattered. Measure against the darkest card, not the page.
   *
   * --ink-4 is the original value and is now ONLY for hairlines, dividers
   * and disabled marks, where the text contrast minimum does not apply.
   * Nothing readable may use it.
   */
  --ink-3: #7E8898;
  --ink-4: #6B7686;

  --accent: #5FA8E8;
  --accent-dim: #3D7CB4;
  --good: #4FBF87;
  --warn: #E0A63C;
  --crit: #E2685E;

  /* The map's own ground, so the hero panel never flashes a different dark. */
  --map-ground: #0A0D12;

  --display: 'Barlow Condensed', 'Oswald', 'Arial Narrow', 'Helvetica Neue', sans-serif;
  --ui: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;

  --measure: 66ch;
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --max: 1320px;
  --radius: 4px;
}

/* ════════════════════════════════════════════════════════════════════════
   Reset and base
   ════════════════════════════════════════════════════════════════════════ */

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

html {
  /* Anchored sections must not land under the sticky nav. */
  scroll-padding-top: 5.5rem;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--ui);
  font-size: 1rem;
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { max-width: 100%; }
img { height: auto; }

/* The UA stylesheet gives <figure> a 40px side margin, which quietly stole
   80px from the hero map on a 375px phone. */
figure, blockquote { margin: 0; }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: 0.005em;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0 0 1em; max-width: var(--measure); }

a { color: var(--accent); text-underline-offset: 0.18em; }
a:hover { color: #8AC2F0; }

/*
 * One focus treatment, everywhere, and it has to survive a dark ground and a
 * bright accent sitting next to it. An outline plus an offset ring reads on
 * both the page and the buttons without needing a per-component override.
 */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
:focus:not(:focus-visible) { outline: none; }

/* Every figure on this page is tabular, so columns of numbers line up. */
.num, td.num, .mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

.skip {
  position: absolute;
  left: 0.5rem;
  top: -4rem;
  z-index: 100;
  background: var(--accent);
  color: #06131F;
  font-weight: 600;
  padding: 0.6rem 1rem;
  border-radius: var(--radius);
  transition: top 120ms ease;
}
.skip:focus { top: 0.5rem; }

.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ════════════════════════════════════════════════════════════════════════
   Nav
   ════════════════════════════════════════════════════════════════════════ */

.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(14, 17, 22, 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
}

.nav__inner {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: 3.5rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.56rem;   /* ~0.42x the cap height of the 21px wordmark */
  text-decoration: none;
  color: var(--ink);
  flex: none;
}
.brand svg, .brand img { width: 26px; height: 26px; display: block; }
.brand__word {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.32rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  line-height: 1;
}

.nav__links {
  display: flex;
  gap: 1.1rem;
  margin-left: auto;
  list-style: none;
  padding: 0;
  margin-block: 0;
}
.nav__links a {
  color: var(--ink-2);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
}
.nav__links a:hover { color: var(--ink); }

/* Below the tablet breakpoint the link list is dropped rather than folded
   into a menu: the page is one column of anchored sections and scrolling to
   them is not worse than opening a drawer to tap a link that scrolls. */
@media (max-width: 860px) {
  .nav__links { display: none; }
  .nav .btn { margin-left: auto; }
}

/* ════════════════════════════════════════════════════════════════════════
   Buttons
   ════════════════════════════════════════════════════════════════════════ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-family: var(--ui);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.75rem 1.15rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease;
}
.btn--primary {
  /* #06131F on #5FA8E8 measures 8.2:1 — the CTA is the highest-contrast
     thing on the page, which is where the contrast budget should go. */
  background: var(--accent);
  color: #06131F;
}
.btn--primary:hover { background: #7CBBF0; color: #06131F; }
.btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule);
}
.btn--ghost:hover { border-color: var(--ink-3); color: var(--ink); }
.btn--sm { padding: 0.5rem 0.85rem; font-size: 0.8125rem; }
.btn--lg { padding: 0.95rem 1.5rem; font-size: 1.0625rem; }

/* ════════════════════════════════════════════════════════════════════════
   Hero
   ════════════════════════════════════════════════════════════════════════ */

.hero {
  border-bottom: 1px solid var(--rule);
  padding-block: clamp(2rem, 5vw, 3.5rem) 0;
}

.hero__grid {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
}
@media (min-width: 1000px) {
  .hero__grid { grid-template-columns: minmax(0, 27rem) minmax(0, 1fr); }
}

.hero__kicker {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 0.9rem;
}

/*
 * The headline is the LCP element and it is never animated in. An opacity or
 * transform reveal on the largest text delays LCP by the whole duration of
 * the animation, because LCP is recorded at final position and opacity. It
 * paints immediately; the map is what moves.
 */
.hero h1 {
  font-size: clamp(2.6rem, 7.2vw, 4.5rem);
  letter-spacing: -0.005em;
  margin-bottom: 1rem;
}
.hero h1 em {
  font-style: normal;
  color: var(--accent);
}

.hero__lede {
  font-size: clamp(1.0625rem, 1.5vw, 1.1875rem);
  color: var(--ink-2);
  max-width: 34ch;
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.hero__meta {
  margin: 1rem 0 0;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink-3);
  letter-spacing: 0.02em;
}

/* --- the map panel ----------------------------------------------------- */

.hero__map {
  position: relative;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  /* The panel is painted the map's own ground colour, so there is never a
     white flash and never a layout shift: the box is correct before a single
     byte of geometry has arrived, and if the pack fails to load it simply
     stays a clean dark panel. */
  background: var(--map-ground);
}

.hero__canvas {
  display: block;
  width: 100%;
  /* Reserving the box with aspect-ratio is what keeps CLS at zero. */
  aspect-ratio: 16 / 9;
  background: var(--map-ground);
}
@media (max-width: 700px) { .hero__canvas { aspect-ratio: 4 / 5; } }

.hero__poster { display: block; width: 100%; height: auto; }

.hero__caption {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1rem;
  align-items: baseline;
  border-top: 1px solid var(--rule);
  padding: 0.6rem 0.85rem;
  background: var(--panel);
  font-family: var(--mono);
  font-size: 0.6875rem;
  line-height: 1.5;
  color: var(--ink-3);
}
.hero__caption strong { color: var(--ink-2); font-weight: 500; }

.hero-toggle {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: rgba(10, 13, 18, 0.82);
  border: 1px solid var(--rule);
  color: var(--ink-2);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.35rem 0.6rem;
  border-radius: var(--radius);
  cursor: pointer;
}
.hero-toggle:hover { color: var(--ink); border-color: var(--ink-3); }

/* --- the legend -------------------------------------------------------- */

.legend {
  list-style: none;
  margin: 0;
  padding: 0.5rem 0.85rem 0.15rem;
  background: var(--panel);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  gap: 0 1.25rem;
  border-top: 1px solid var(--rule);
}
.legend__row {
  display: grid;
  grid-template-columns: 0.7rem 1fr auto auto auto;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--ink-3);
  padding-block: 0.18rem;
}
.legend__swatch {
  width: 0.7rem; height: 0.7rem;
  border-radius: 2px;
  background: var(--line);
}
.legend__name { color: var(--ink-2); }
.legend__year { color: var(--ink-3); }
.legend__headway { color: var(--ink-2); }
.legend__count { color: var(--accent); min-width: 1.4rem; text-align: right; }

.legend__head {
  display: grid;
  grid-template-columns: 0.7rem 1fr auto auto auto;
  gap: 0.5rem;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 0.5rem 0.85rem 0;
  background: var(--panel);
}
.legend__head span:nth-child(4),
.legend__head span:nth-child(5) { text-align: right; }
.legend__head span:nth-child(4) { text-align: left; }

/* ════════════════════════════════════════════════════════════════════════
   Promise strip — the four honest badges
   ════════════════════════════════════════════════════════════════════════ */

.promises {
  border-bottom: 1px solid var(--rule);
  background: var(--panel);
}
.promises ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.promises li {
  padding: 0.85rem 1rem 0.85rem 0;
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  font-size: 0.875rem;
  color: var(--ink-2);
  line-height: 1.45;
}
.promises b {
  display: block;
  color: var(--ink);
  font-weight: 600;
  font-size: 0.9375rem;
}
.promises svg { flex: none; margin-top: 0.15rem; color: var(--good); }

/* ════════════════════════════════════════════════════════════════════════
   Sections
   ════════════════════════════════════════════════════════════════════════ */

.section { padding-block: clamp(3rem, 7vw, 5.5rem); border-bottom: 1px solid var(--rule); }
.section--panel { background: var(--panel); }

.section__head { margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem); }
.section__num {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: block;
  margin-bottom: 0.6rem;
}
.section h2 {
  font-size: clamp(1.9rem, 4vw, 2.9rem);
  margin-bottom: 0.7rem;
}
.section__lede {
  font-size: 1.0625rem;
  color: var(--ink-2);
  max-width: 62ch;
}

.rule { border: 0; border-top: 1px solid var(--rule); margin: 2.5rem 0; }

/* ════════════════════════════════════════════════════════════════════════
   Cards
   ════════════════════════════════════════════════════════════════════════ */

.cards {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
@media (min-width: 720px) { .cards--2 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 720px) { .cards--3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .cards--3 { grid-template-columns: repeat(3, 1fr); } }

.card {
  background: var(--ground);
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
}
.section--panel .card { background: var(--panel-2); }

.card h3 {
  font-size: 1.45rem;
  margin-bottom: 0.6rem;
}
.card p { color: var(--ink-2); font-size: 0.9375rem; margin-bottom: 0.75rem; }
.card p:last-child { margin-bottom: 0; }

/* The line under a feature card that states the mechanism, in mono, so the
   claim above it is visibly backed by something specific. */
.card__cite {
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--ink-3);
  border-top: 1px dashed var(--rule);
  padding-top: 0.7rem;
  margin-top: 0.9rem;
  line-height: 1.5;
}
.card__cite b { color: var(--ink-2); font-weight: 500; }

/* A question card leads with the decision, not the system. */
.card__q {
  font-family: var(--display);
  font-size: clamp(1.35rem, 2.4vw, 1.6rem);
  font-weight: 600;
  line-height: 1.12;
  color: var(--ink);
  margin: 0 0 0.6rem;
}

/* ════════════════════════════════════════════════════════════════════════
   Tables
   ════════════════════════════════════════════════════════════════════════ */

.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  /* Wide tables scroll inside their own box; the page body never does. */
  -webkit-overflow-scrolling: touch;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
  min-width: 34rem;
}
caption {
  text-align: left;
  padding: 0.85rem 1rem;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 0.6875rem;
  line-height: 1.6;
  border-bottom: 1px solid var(--rule);
  background: var(--panel);
}
th, td {
  text-align: left;
  padding: 0.6rem 1rem;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
thead th {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 500;
  background: var(--panel);
  position: sticky;
  top: 0;
}
tbody tr:last-child td { border-bottom: 0; }
tbody th { font-weight: 600; color: var(--ink); }
td { color: var(--ink-2); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }

.tag {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.12rem 0.4rem;
  border-radius: 2px;
  border: 1px solid currentColor;
  white-space: nowrap;
}
.tag--observed { color: var(--good); }
.tag--derived { color: var(--warn); }
.tag--model { color: var(--accent); }
.tag--done { color: var(--good); }
.tag--wip { color: var(--warn); }
.tag--planned { color: var(--ink-3); }

/* ════════════════════════════════════════════════════════════════════════
   Quotes — reviews of OTHER games in this genre, never of this one
   ════════════════════════════════════════════════════════════════════════ */

.quote {
  border-left: 2px solid var(--crit);
  padding: 0.1rem 0 0.1rem 1rem;
  margin: 0 0 1rem;
}
.quote p {
  margin: 0 0 0.4rem;
  color: var(--ink);
  font-size: 0.9375rem;
  line-height: 1.5;
}
.quote footer {
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--ink-3);
}

.answer {
  border-left: 2px solid var(--good);
  padding: 0.1rem 0 0.1rem 1rem;
}
.answer p { margin: 0; color: var(--ink-2); font-size: 0.9375rem; }
.answer b { color: var(--ink); font-weight: 600; }

/* ════════════════════════════════════════════════════════════════════════
   Steps — the first ten minutes
   ════════════════════════════════════════════════════════════════════════ */

.steps {
  list-style: none;
  counter-reset: step;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
@media (min-width: 680px) { .steps { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1040px) { .steps { grid-template-columns: repeat(3, 1fr); } }

.steps li {
  counter-increment: step;
  background: var(--panel-2);
  padding: 1.25rem;
}
.steps li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--accent);
  display: block;
  margin-bottom: 0.5rem;
}
.steps h3 { font-size: 1.15rem; margin-bottom: 0.4rem; }
.steps p { color: var(--ink-2); font-size: 0.875rem; margin: 0; }

/* ════════════════════════════════════════════════════════════════════════
   Era / rank rails
   ════════════════════════════════════════════════════════════════════════ */

.eras {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
/* Eight eras. auto-fit rather than a fixed count so the last row is never a
   single orphan card on an awkward viewport. */
@media (min-width: 620px) { .eras { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); } }
@media (min-width: 1100px) { .eras { grid-template-columns: repeat(4, 1fr); } }

.era { background: var(--ground); padding: 1.15rem; }
.era__year {
  font-family: var(--mono);
  font-size: 1.5rem;
  color: var(--accent);
  letter-spacing: -0.02em;
  display: block;
}
.era h3 { font-size: 1.2rem; margin: 0.25rem 0 0.5rem; }
.era p { font-size: 0.8125rem; color: var(--ink-2); margin: 0 0 0.85rem; }
.era dl {
  margin: 0;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.15rem 0.5rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
}
.era dt { color: var(--ink-3); }
.era dd { margin: 0; color: var(--ink); text-align: right; font-variant-numeric: tabular-nums; }

.ladder {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
@media (min-width: 560px) { .ladder { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .ladder { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1200px) { .ladder { grid-template-columns: repeat(4, 1fr); } }

.ladder li {
  background: var(--panel-2);
  padding: 0.9rem 1rem;
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
}
.ladder__rank {
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--ink-3);
  padding-top: 0.2rem;
  min-width: 1.2rem;
}
.ladder__name {
  font-family: var(--display);
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1.15;
  display: block;
  color: var(--ink);
}
.ladder__title { font-size: 0.8125rem; color: var(--ink-2); display: block; }
.ladder__place {
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--ink-3);
  display: block;
  margin-top: 0.2rem;
}

/* ════════════════════════════════════════════════════════════════════════
   Cities
   ════════════════════════════════════════════════════════════════════════ */

.metro-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  list-style: none;
  margin: 0;
  padding: 0;
}
.metro {
  background: var(--panel-2);
  padding: 0.85rem 1rem;
}
.metro a {
  font-family: var(--display);
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  line-height: 1.15;
  display: block;
}
.metro a:hover { color: var(--accent); }
.metro__stats {
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--ink-3);
  margin-top: 0.25rem;
  display: block;
}
.metro__transit { color: var(--accent); }

/* ════════════════════════════════════════════════════════════════════════
   FAQ
   ════════════════════════════════════════════════════════════════════════ */

.faq { border: 1px solid var(--rule); border-radius: var(--radius); overflow: hidden; }
.faq details { border-bottom: 1px solid var(--rule); background: var(--panel-2); }
.faq details:last-child { border-bottom: 0; }
.faq summary {
  cursor: pointer;
  padding: 1rem 1.25rem;
  font-family: var(--display);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--ink);
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  align-items: center;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+';
  font-family: var(--mono);
  font-size: 1.1rem;
  color: var(--accent);
  flex: none;
}
.faq details[open] summary::after { content: '\2212'; }
.faq__body { padding: 0 1.25rem 1.25rem; }
.faq__body p { color: var(--ink-2); font-size: 0.9375rem; }
.faq__body p:last-child { margin-bottom: 0; }

/* ════════════════════════════════════════════════════════════════════════
   Roadmap
   ════════════════════════════════════════════════════════════════════════ */

.roadmap { list-style: none; margin: 0; padding: 0; }
.roadmap li {
  display: grid;
  gap: 0.25rem 1rem;
  grid-template-columns: 1fr;
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 700px) {
  .roadmap li { grid-template-columns: 9rem 1fr 8rem; align-items: baseline; }
}
.roadmap__when { font-family: var(--mono); font-size: 0.75rem; color: var(--ink-3); }
.roadmap__what { color: var(--ink); font-size: 0.9375rem; }
.roadmap__what small { display: block; color: var(--ink-2); font-size: 0.8125rem; }

/* ════════════════════════════════════════════════════════════════════════
   CTA band and footer
   ════════════════════════════════════════════════════════════════════════ */

.cta {
  background: var(--panel);
  border-bottom: 1px solid var(--rule);
  padding-block: clamp(3rem, 6vw, 4.5rem);
  text-align: center;
}
.cta h2 { font-size: clamp(2rem, 5vw, 3.2rem); margin-bottom: 0.75rem; }
.cta p { margin-inline: auto; color: var(--ink-2); max-width: 52ch; }
.cta .hero__cta { justify-content: center; }
.cta .hero__meta { text-align: center; }

.footer { padding-block: 2.5rem 3rem; color: var(--ink-3); font-size: 0.8125rem; }
.footer__cols {
  display: grid;
  gap: 1.75rem;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  margin-bottom: 2rem;
}
.footer h3 {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 500;
  margin-bottom: 0.65rem;
}
.footer ul { list-style: none; margin: 0; padding: 0; }
.footer li { margin-bottom: 0.35rem; }
.footer a { color: var(--ink-2); text-decoration: none; }
.footer a:hover { color: var(--ink); text-decoration: underline; }
.footer__fine { border-top: 1px solid var(--rule); padding-top: 1.5rem; }
.footer__fine p { max-width: 70ch; font-size: 0.75rem; line-height: 1.7; }

/* ════════════════════════════════════════════════════════════════════════
   Sub-page helpers
   ════════════════════════════════════════════════════════════════════════ */

.page-head { padding-block: clamp(2.5rem, 6vw, 4rem) clamp(1.5rem, 3vw, 2.5rem); }
.page-head h1 { font-size: clamp(2.2rem, 5.5vw, 3.6rem); margin-bottom: 0.75rem; }
.page-head p { color: var(--ink-2); font-size: 1.0625rem; }

.crumbs {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 0.9rem;
}
.crumbs a { color: var(--ink-3); text-decoration: none; }
.crumbs a:hover { color: var(--ink); }

.prose { max-width: 70ch; }
.prose h2 { font-size: clamp(1.7rem, 3.4vw, 2.3rem); margin: 2.5rem 0 0.75rem; }
.prose h3 { font-size: 1.35rem; margin: 1.75rem 0 0.5rem; }
.prose p, .prose li { color: var(--ink-2); }
.prose ul, .prose ol { padding-left: 1.2rem; }
.prose li { margin-bottom: 0.4rem; }
.prose code {
  font-family: var(--mono);
  font-size: 0.85em;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.05em 0.35em;
  color: var(--ink);
}

.callout {
  border: 1px solid var(--rule);
  border-left: 3px solid var(--warn);
  background: var(--panel);
  padding: 1rem 1.25rem;
  border-radius: var(--radius);
  margin: 1.5rem 0;
}
.callout p:last-child { margin-bottom: 0; }
.callout strong { color: var(--ink); }

.city-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  margin: 1.75rem 0;
}
.city-stats div { background: var(--panel-2); padding: 1rem; }
.city-stats dt {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 0.3rem;
}
.city-stats dd {
  margin: 0;
  font-family: var(--mono);
  font-size: 1.4rem;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.city-stats dd small { font-size: 0.75rem; color: var(--ink-3); display: block; margin-top: 0.2rem; }

/* ════════════════════════════════════════════════════════════════════════
   Motion
   ════════════════════════════════════════════════════════════════════════ */

/*
 * Nothing on this page animates on scroll and nothing animates on load. The
 * only motion is the hero canvas, which has its own visible pause control and
 * its own reduced-motion path in js/hero.js (the identical frame, stopped, with
 * every vehicle still drawn). This block covers the small transitions on links
 * and buttons and is here so the preference is honoured page-wide.
 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/*
 * Printing. Somebody will print the model page or the data table — it is that
 * kind of document — and a dark ground wastes a cartridge saying nothing.
 */
@media print {
  body { background: #fff; color: #000; }
  .nav, .hero__map, .cta, .btn, .skip { display: none !important; }
  a { color: #000; }
  .section { border: 0; padding-block: 1rem; }
}

/* ════════════════════════════════════════════════════════════════════════
   The diagram
   ════════════════════════════════════════════════════════════════════════

   The site is about transit maps, so it is built like one.

   Every convention below is borrowed from real diagrams rather than invented:
   the circular route bullet is New York's, in use since 1967 and the reason
   anyone can say "take the 6"; the coloured line with ticks for stops and
   rings for interchanges is Beck's, 1933, and has since been copied by
   basically every system on earth; and the palette is not a decorator's
   choice but the game's own ROUTE_COLORS, so a line that is red here is red
   when you build it.

   The structural claim: each section of this page is a line, and the steps
   inside a section are stations on it. That is only worth doing because it
   is TRUE of the content — the first ten minutes really is a sequence, and
   the price tiers really are three stops on one route. Where the content is
   not a sequence, it does not get a diagram.
*/

:root {
  /* From src/engine/constants.ts — ROUTE_COLORS. Same hues the game draws. */
  --line-red: #E4002B;
  --line-blue: #0039A6;
  --line-green: #00933C;
  --line-orange: #FF6319;
  --line-purple: #B933AD;
  --line-cyan: #00ADD0;
  --line-yellow: #FCCC0A;

  /*
   * The dark ground eats a saturated navy — #0039A6 on #0E1116 measures under
   * 3:1 and a line you cannot see is not a line. These are the same hues
   * lifted in luminance for a dark diagram, which is what every transit
   * authority that ships a dark-mode map has had to do too.
   */
  --line-blue-lit: #4C8FE8;
  --line-green-lit: #37C06C;
  --line-red-lit: #F2564F;
  --line-purple-lit: #D06BC8;
}

/*
 * A route bullet. New York's, and it has to be a perfect circle with the
 * glyph optically centred or it stops reading as one.
 */
.bullet {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2.1em;
  block-size: 2.1em;
  border-radius: 50%;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1;
  letter-spacing: 0;
  color: #0B0E13;
  background: var(--bullet, var(--accent));
  flex: none;
}
.bullet--lg { font-size: 1.35rem; }

/* Section eyebrows become a bullet plus the line's name. */
.section__num--line {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 0.85rem;
}
.section__num--line .bullet { font-size: 0.8rem; }
.section__num--line b {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
  font-weight: 500;
}

/* ── A route diagram: stations strung along a coloured line ──────────────
 *
 * Horizontal on a wide screen, vertical on a narrow one, which is exactly
 * what real diagrams do when they meet a platform poster instead of a wall.
 */
.route {
  --route-color: var(--accent);
  display: grid;
  gap: 0;
  position: relative;
  margin-block: 2rem;
}
.route__stop {
  position: relative;
  padding-inline-start: 2.6rem;
  padding-block: 0 2rem;
}
.route__stop:last-child { padding-block-end: 0; }

/* The line itself, drawn behind the ticks. */
.route__stop::before {
  content: "";
  position: absolute;
  inset-block: 0.35em 0;
  inset-inline-start: 0.5rem;
  inline-size: 6px;
  border-radius: 3px;
  background: var(--route-color);
}
.route__stop:last-child::before { block-size: 0.4em; inset-block-end: auto; }

/* The station: a ring, the way an interchange is drawn. */
.route__stop::after {
  content: "";
  position: absolute;
  inset-block-start: 0.1em;
  inset-inline-start: 0;
  inline-size: 1.25rem;
  block-size: 1.25rem;
  border-radius: 50%;
  background: var(--ground);
  border: 4px solid var(--route-color);
  box-sizing: border-box;
}
.section--panel .route__stop::after { background: var(--panel); }

.route__name {
  font-family: var(--display);
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink);
  margin-bottom: 0.3rem;
  line-height: 1.15;
}
.route__body { color: var(--ink-2); font-size: 0.9375rem; max-width: 58ch; }
.route__body b { color: var(--ink); font-weight: 600; }
.route__meta {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 0.45rem;
}

@media (min-width: 900px) {
  .route--wide { grid-auto-flow: column; grid-auto-columns: 1fr; }
  .route--wide .route__stop {
    padding-inline: 0 1.5rem;
    padding-block-start: 2.5rem;
  }
  .route--wide .route__stop::before {
    inset-block: auto;
    inset-block-start: 0.5rem;
    inset-inline: 0 -1.5rem;
    inline-size: auto;
    block-size: 6px;
  }
  .route--wide .route__stop:last-child::before { inset-inline-end: auto; inline-size: 0.6rem; block-size: 6px; }
  .route--wide .route__stop::after { inset-block-start: 0.1rem; inset-inline-start: 0; }
}

/* ── Decision cards, each one its own line ────────────────────────────── */

.decisions {
  display: grid;
  gap: 1rem;
  margin-top: 2rem;
}
@media (min-width: 760px) { .decisions { grid-template-columns: 1fr 1fr; } }

.decision {
  --dc: var(--accent);
  position: relative;
  background: var(--panel-2);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 1.15rem 1.25rem 1.15rem 1.6rem;
  overflow: hidden;
}
.section--panel .decision { background: var(--ground); }
/* The line's own colour, run down the edge like a platform stripe. */
.decision::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 6px;
  background: var(--dc);
}
.decision h3 {
  font-family: var(--display);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.45rem;
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
}
.decision h3 small {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--dc);
  font-weight: 500;
}
.decision p { color: var(--ink-2); font-size: 0.9375rem; margin-bottom: 0.6rem; }
.decision p:last-child { margin-bottom: 0; }

/*
 * The trade-off, stated as two opposed arms. This is the whole point of the
 * section: a decision with only an upside is not a decision, so the layout
 * refuses to render one — both arms are required.
 */
.tradeoff {
  display: grid;
  gap: 0.4rem;
  margin-top: 0.7rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--rule);
}
.tradeoff div {
  display: grid;
  grid-template-columns: 1.4rem 1fr;
  gap: 0.5rem;
  align-items: baseline;
  font-size: 0.875rem;
  color: var(--ink-2);
}
.tradeoff span {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 600;
}
.tradeoff .up span { color: var(--good); }
.tradeoff .down span { color: var(--crit); }

/* ── Price tiers, drawn as three stops on one line ───────────────────── */

.fares { margin-top: 2.25rem; }
.fares__line {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 3px;
  overflow: hidden;
}
@media (min-width: 880px) { .fares__line { grid-template-columns: repeat(3, 1fr); } }

.fare {
  background: var(--panel-2);
  padding: 1.5rem 1.35rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.section--panel .fare { background: var(--ground); }
.fare--pick { background: var(--panel); box-shadow: inset 0 3px 0 0 var(--fare-c, var(--accent)); }
.section--panel .fare--pick { background: var(--panel-2); }

.fare__top { display: flex; align-items: center; gap: 0.7rem; }
.fare__name {
  font-family: var(--display);
  font-size: 1.45rem;
  font-weight: 600;
  color: var(--ink);
  line-height: 1;
}
.fare__price {
  font-family: var(--mono);
  font-size: 2.1rem;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.fare__price small {
  font-size: 0.75rem;
  color: var(--ink-3);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  display: block;
  margin-top: 0.35rem;
  font-weight: 400;
}
.fare ul { list-style: none; display: grid; gap: 0.45rem; margin: 0; padding: 0; }
.fare li {
  display: grid;
  grid-template-columns: 1.1rem 1fr;
  gap: 0.55rem;
  align-items: baseline;
  font-size: 0.9375rem;
  color: var(--ink-2);
}
.fare li b { color: var(--ink); font-weight: 600; }
.fare li i {
  font-style: normal;
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--fare-c, var(--accent));
}
.fare li.no { color: var(--ink-3); }
.fare li.no i { color: var(--ink-4); }
.fare__note {
  font-size: 0.8125rem;
  color: var(--ink-3);
  margin-top: auto;
  padding-top: 0.5rem;
  line-height: 1.5;
}

/* ── The donation line ───────────────────────────────────────────────── */

.tithe {
  display: grid;
  gap: 0.9rem;
  align-items: start;
  margin-top: 1.75rem;
  padding: 1.25rem 1.4rem;
  background: color-mix(in srgb, var(--good) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--good) 28%, transparent);
  border-radius: 3px;
}
@media (min-width: 720px) { .tithe { grid-template-columns: auto 1fr; gap: 1.2rem; } }
.tithe__figure {
  font-family: var(--display);
  font-size: 2.6rem;
  font-weight: 600;
  color: var(--good);
  line-height: 0.9;
}
.tithe p { font-size: 0.9375rem; color: var(--ink-2); max-width: 60ch; }
.tithe p b { color: var(--ink); font-weight: 600; }

/* ── About page ─────────────────────────────────────────────────────── */

.prose { max-width: 64ch; }
.prose p { color: var(--ink-2); font-size: 1.0625rem; margin-bottom: 1.1rem; line-height: 1.65; }
.prose p b { color: var(--ink); font-weight: 600; }
.prose h3 {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--ink);
  margin: 2.25rem 0 0.75rem;
}
.prose a { color: var(--accent); }

.pullquote {
  border-inline-start: 6px solid var(--line-orange);
  padding: 0.3rem 0 0.3rem 1.25rem;
  margin: 1.75rem 0;
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 500;
  color: var(--ink);
  line-height: 1.25;
  max-width: 34ch;
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ════════════════════════════════════════════════════════════════════════
   The platform — decisions arriving by train
   ════════════════════════════════════════════════════════════════════════

   Each decision pulls in, opens its doors, is read, closes and leaves. The
   conceit earns its keep because the content really does behave this way:
   a decision in this game arrives whether you were ready or not, is open for
   a limited time, and then departs having been taken or not taken.

   Three rules this had to obey and the reason for each:

   1. Everything readable is present at rest. The first carriage is already
      berthed with its doors open on load, so a reader who never waits — and a
      thumbnail, and a crawler — gets the content, not an empty platform.
   2. Every carriage is in the DOM, always. The animation moves them; it does
      not create them. Without JS you get a readable stack.
   3. Reduced motion stops the train. Not "speeds it up" — a person who has
      asked for no motion should get a static list, and the controls still work.
*/

.platform {
  margin-top: 2rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--panel-2);
  overflow: hidden;
}
.section--panel .platform { background: var(--ground); }

.platform__head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--rule);
  background: var(--panel);
  flex-wrap: wrap;
}
.section--panel .platform__head { background: var(--panel-2); }

.platform__where {
  font-family: var(--display);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink);
}
/* A dot-matrix next-train indicator, because that is what is on every platform. */
.platform__dmi {
  margin-inline-start: auto;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--warn);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.platform__dmi::before {
  content: "";
  inline-size: 7px;
  block-size: 7px;
  border-radius: 50%;
  background: var(--warn);
  animation: dmi-blink 1.6s steps(1, end) infinite;
}
@keyframes dmi-blink { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0.15; } }

/* ── The scene ────────────────────────────────────────────────────────
 *
 * Three bands, and the proportions are the whole of the fix. The carriage
 * used to fill the frame top to bottom, which made it read as a fat slab
 * rather than as a train: real rolling stock is long and shallow, and you
 * are always looking at it across a platform with air above it.
 *
 *   SIGN     the destination board, hanging from the ceiling
 *   TRAIN    a shallow band the service runs through
 *   DECK     the platform you are standing on
 */

.platform__track {
  --band-sign: 6.4rem;
  --band-deck: 3.4rem;
  position: relative;
  block-size: 25rem;
  overflow: hidden;
  isolation: isolate;
}
@media (min-width: 900px) { .platform__track { block-size: 22rem; } }

/* ── The station ─────────────────────────────────────────────────────── */

.station { position: absolute; inset: 0; z-index: 0; }
.station__wall {
  position: absolute;
  inset: 0;
  background:
    repeating-linear-gradient(90deg, #1A222E 0 44px, #151C26 44px 46px),
    repeating-linear-gradient(0deg, #1A222E 0 32px, #141A23 32px 34px),
    #161D27;
}
/* A lit soffit, so the air above the train is a ceiling rather than a gap. */
.station__ceiling {
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: var(--band-sign);
  background:
    linear-gradient(180deg, rgba(255, 240, 205, 0.16), transparent 78%),
    linear-gradient(180deg, #0D1219 0 10px, transparent 10px);
  border-block-end: 1px solid rgba(255, 255, 255, 0.05);
}
/* The tunnel a departing service runs into. */
.station__tunnel {
  position: absolute;
  inset-block: 0 var(--band-deck);
  inset-inline-start: 0;
  inline-size: 14%;
  background: linear-gradient(90deg, #04060A 0%, #04060A 38%, transparent 100%);
  z-index: 2;
  pointer-events: none;
}

/* ── The hanging destination board ───────────────────────────────────── */

.hangsign {
  position: absolute;
  inset-block-start: 0.55rem;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  z-index: 3;
  display: grid;
  justify-items: center;
  inline-size: min(92%, 40rem);
}
.hangsign__rod {
  position: absolute;
  inset-block-start: 0;
  block-size: 0.85rem;
  inline-size: 2px;
  background: #3A4656;
}
.hangsign__rod { inset-inline-start: 18%; }
.hangsign__rod--b { inset-inline-start: auto; inset-inline-end: 18%; }

.hangsign__panel {
  margin-block-start: 0.8rem;
  inline-size: 100%;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 0.9rem;
  border-radius: 4px;
  background: #06080C;
  border: 1px solid #222B38;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.5), inset 0 0 22px rgba(255, 180, 60, 0.05);
  flex-wrap: wrap;
}
.hangsign__route {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 1.7rem;
  block-size: 1.7rem;
  border-radius: 50%;
  background: var(--sign-c, var(--accent));
  color: #06080B;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.95rem;
  flex: none;
  transition: background 260ms linear;
}
.hangsign__dest {
  font-family: var(--display);
  font-size: clamp(1.15rem, 2.4vw, 1.65rem);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #FFC14D;
  line-height: 1;
  /* The faint bloom a real dot-matrix has behind the lit pixels. */
  text-shadow: 0 0 14px rgba(255, 176, 48, 0.35);
}
.hangsign__svc {
  margin-inline-start: auto;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #C0872F;
}
/* The board blanks for a beat while the next service is called. */
.hangsign__dest, .hangsign__svc { transition: opacity 160ms linear; }
.platform[data-doors="open"] .hangsign__dest,
.platform[data-doors="open"] .hangsign__svc { opacity: 0.12; }

/* ── The service ─────────────────────────────────────────────────────── */

.service {
  position: absolute;
  inset-block: var(--band-sign) var(--band-deck);
  inset-inline: 0;
  z-index: 1;
  display: flex;
  align-items: flex-end;
  padding-inline: 0.5rem;
  transform: translateX(104%);
  opacity: 0;
  visibility: hidden;
  transition:
    transform 420ms cubic-bezier(0.16, 0.74, 0.3, 1),
    opacity 160ms linear,
    visibility 0s linear 420ms;
}
.service[data-state="berthed"] {
  transform: translateX(0);
  opacity: 1;
  visibility: visible;
  transition:
    transform 420ms cubic-bezier(0.16, 0.74, 0.3, 1),
    opacity 160ms linear,
    visibility 0s linear 0s;
}
.service[data-state="departing"] {
  transform: translateX(-122%);
  opacity: 0;
  transition:
    transform 380ms cubic-bezier(0.55, 0, 0.9, 0.45),
    opacity 240ms linear 120ms,
    visibility 0s linear 380ms;
}

/* ── The carriage ────────────────────────────────────────────────────── */

.car { inline-size: 100%; }

.car__shell {
  border-radius: 10px 10px 4px 4px;
  overflow: hidden;
  background:
    /* a highlight running the length of the body, as on any painted panel */
    linear-gradient(180deg,
      rgba(255, 255, 255, 0.16) 0 2px,
      transparent 2px 46%,
      rgba(0, 0, 0, 0.14) 60%,
      transparent 72%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--dc) 90%, #FFF) 0%,
      var(--dc) 20%,
      color-mix(in srgb, var(--dc) 70%, #05070A) 100%);
  box-shadow:
    0 16px 34px rgba(0, 0, 0, 0.5),
    inset 0 0 0 1px rgba(0, 0, 0, 0.22);
}
.car__roof {
  block-size: 7px;
  background: rgba(255, 255, 255, 0.3);
  border-block-end: 1px solid rgba(0, 0, 0, 0.22);
}

/*
 * The band above the windows: side destination blind at one end, fleet
 * number at the other. Both are on every real car and both are what stops
 * a coloured rectangle reading as a coloured rectangle.
 */
.car__band {
  display: none;
  align-items: center;
  gap: 0.6rem;
  padding: 0.22rem 0.85rem 0.1rem;
  border-block-end: 1px solid rgba(0, 0, 0, 0.18);
}
@media (min-width: 760px) { .car__band { display: flex; } }
.car__blind {
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(5, 8, 12, 0.72);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.car__no {
  margin-inline-start: auto;
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.14em;
  color: rgba(5, 8, 12, 0.48);
}

/* The step between platform and carriage, lit from inside. */
.car__threshold {
  block-size: 4px;
  background: linear-gradient(180deg, rgba(255, 228, 170, 0.32), rgba(0, 0, 0, 0.45));
}
.car__side {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
  padding: 6px;
}
@media (min-width: 900px) {
  .car__side { grid-template-columns: 5.5rem 1fr 5.5rem; }
}
.car__skirt {
  block-size: 7px;
  background: rgba(0, 0, 0, 0.42);
}

/* Window bays at each end, so the doorway is part of a vehicle. */
.car__bay { display: none; gap: 4px; align-items: stretch; }
@media (min-width: 900px) { .car__bay { display: grid; grid-auto-flow: column; } }
.car__bay i {
  display: block;
  border-radius: 3px;
  background:
    /* the diagonal a lit interior throws across window glass */
    linear-gradient(112deg,
      transparent 0 38%,
      rgba(255, 233, 186, 0.10) 38% 47%,
      transparent 47% 60%,
      rgba(255, 233, 186, 0.05) 60% 66%,
      transparent 66%),
    linear-gradient(180deg, #0C1521 0%, #121F30 52%, #0A1119 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.09),
    inset 0 -1px 0 rgba(0, 0, 0, 0.5);
}

/* ── The doorway, and the two leaves the argument is printed on ──────── */

.car__doorway {
  position: relative;
  border-radius: 4px;
  /* Warm light from inside the car, strongest at the doors. */
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(255, 226, 170, 0.09), transparent 62%),
    #090E15;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09);
  display: grid;
  grid-template-columns: 1fr;
  overflow: hidden;
  min-block-size: 8.5rem;
}
@media (min-width: 680px) { .car__doorway { grid-template-columns: 1fr 1fr; } }

.leaf {
  padding: 0.7rem 0.85rem;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.055), rgba(255, 255, 255, 0.015));
  transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1), opacity 220ms linear;
}
/* The rubber gasket each leaf closes against, and the recessed panel line. */
.leaf--l {
  box-shadow:
    inset -3px 0 0 rgba(0, 0, 0, 0.6),
    inset 1px 0 0 rgba(255, 255, 255, 0.07);
}
.leaf--r {
  box-shadow:
    inset 3px 0 0 rgba(0, 0, 0, 0.6),
    inset -1px 0 0 rgba(255, 255, 255, 0.07);
}

.platform[data-doors="open"] .service[data-state="berthed"] .leaf--l {
  transform: translateX(-102%); opacity: 0;
}
.platform[data-doors="open"] .service[data-state="berthed"] .leaf--r {
  transform: translateX(102%); opacity: 0;
}

.leaf__tag {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.12rem 0.38rem;
  border-radius: 2px;
  margin-bottom: 0.35rem;
}
.leaf__tag--pro { color: #08150E; background: var(--good); }
.leaf__tag--con { color: #180909; background: var(--crit); }
.leaf__head {
  display: block;
  font-family: var(--display);
  font-size: clamp(1rem, 1.9vw, 1.25rem);
  font-weight: 600;
  color: var(--ink);
  line-height: 1.12;
  margin-bottom: 0.25rem;
}
.leaf p {
  font-size: 0.8125rem;
  color: var(--ink-2);
  line-height: 1.5;
  margin: 0;
  max-width: 46ch;
}

/* Running gear. Shallow, because a bogie is mostly under the car. */
.car__running { display: block; inline-size: 100%; block-size: 16px; margin-block-start: -3px; }
.rs-bogie { fill: #05070A; opacity: 0.9; }
.rs-wheel { fill: #1A2330; }
.rs-hub { fill: #47566B; }

/* ── The platform you are standing on ────────────────────────────────── */

.deck {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  block-size: var(--band-deck);
  z-index: 2;
}
/* The tactile strip, and the yellow line nobody is supposed to cross. */
.deck__edge {
  block-size: 12px;
  background:
    linear-gradient(180deg, rgba(0, 0, 0, 0.5), transparent 70%),
    repeating-linear-gradient(90deg, var(--warn) 0 10px, #6A4E14 10px 20px);
  opacity: 0.85;
}
.deck__floor {
  block-size: calc(var(--band-deck) - 12px);
  background:
    repeating-linear-gradient(90deg, #232B37 0 58px, #1D2430 58px 60px),
    linear-gradient(180deg, #232B37, #171D26);
}

.platform__caption {
  padding: 0.7rem 1rem;
  border-block-start: 1px solid var(--rule);
  font-size: 0.8125rem;
  color: var(--ink-2);
  line-height: 1.5;
  margin: 0;
}
.platform__caption b {
  display: block;
  font-family: var(--mono);
  font-weight: 400;
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  color: var(--ink-3);
  margin-top: 0.3rem;
}

.platform__foot {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.65rem 1rem;
  border-top: 1px solid var(--rule);
  background: var(--panel);
  flex-wrap: wrap;
}
.section--panel .platform__foot { background: var(--panel-2); }

/* Stop markers, drawn as the calling points of a line. */
.platform__stops { display: flex; align-items: center; gap: 0; flex: 1; min-inline-size: 10rem; }
.stopdot {
  position: relative;
  flex: 1;
  block-size: 2rem;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 0;
  color: inherit;
}
.stopdot::before {
  content: "";
  position: absolute;
  inset-block-start: calc(50% - 1.5px);
  inset-inline: 0;
  block-size: 3px;
  background: var(--rule);
}
.stopdot:first-child::before { inset-inline-start: 50%; }
.stopdot:last-child::before { inset-inline-end: 50%; }
.stopdot::after {
  content: "";
  position: absolute;
  inset-block-start: calc(50% - 5px);
  inset-inline-start: calc(50% - 5px);
  inline-size: 10px;
  block-size: 10px;
  border-radius: 50%;
  background: var(--ground);
  border: 3px solid var(--ink-4);
  transition: border-color 200ms, transform 200ms;
}
.section--panel .stopdot::after { background: var(--panel-2); }
.stopdot[aria-current="true"]::after {
  border-color: var(--sd, var(--accent));
  transform: scale(1.5);
}
.stopdot:hover::after { border-color: var(--sd, var(--accent)); }
.stopdot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

.platform__btn {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 0.35rem 0.6rem;
  cursor: pointer;
}
.platform__btn:hover { color: var(--ink); border-color: var(--ink-4); }
.platform__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/*
 * No script, or motion refused: the platform becomes a readable list. Every
 * carriage is already in the DOM, so this costs nothing but the positioning.
 */
.platform.is-static .platform__track { min-block-size: 0; overflow: visible; }
.platform.is-static .service {
  position: static;
  transform: none;
  opacity: 1;
  visibility: visible;
  transition: none;
  border-block-end: 1px solid var(--rule);
}
.platform.is-static .station,
.platform.is-static .hangsign,
.platform.is-static .deck { display: none; }
.platform.is-static .platform__caption,
.platform.is-static .platform__foot,
.platform.is-static .platform__dmi { display: none; }

@media (prefers-reduced-motion: reduce) {
  .service { transition: none; }
  .leaf { transition: none; }
  .platform__dmi::before { animation: none; }
}

/* ════════════════════════════════════════════════════════════════════════
   The city — districts you can point at
   ════════════════════════════════════════════════════════════════════════

   A stylised metro seen from above: a dense core, a ring of inner
   neighbourhoods, arterials running out, and the seven characters a tract
   can take. Hovering a parcel names it and says what the model read to
   decide it was that.

   Laid out on a grid rather than drawn as a map, because a made-up map of a
   made-up city would invite the reader to look for a place they know. This is
   explicitly a diagram of the CATEGORIES, not a picture of any metro.
*/

.citymap {
  display: grid;
  gap: 1.5rem;
  margin-top: 2rem;
  align-items: start;
}
@media (min-width: 900px) { .citymap { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); } }

/*
 * The plan, in axonometric.
 *
 * Two versions of this were rejected before it looked like anywhere. The
 * first was a grid of identical flat squares — a colour-swatch chart. The
 * second was irregular flat rectangles, which is a zoning map, not a city.
 * A city has BUILDINGS, and the useful thing about drawing them is that
 * height carries the meaning the flat versions had to caption: downtown is
 * towers, residential is small houses, industry is long low sheds, and the
 * office park is mid-rise boxes sitting on their own past the water.
 *
 * 2:1 axonometric, which every isometric city has used since SimCity 2000,
 * because it tiles on integers and stays legible small. Buildings are drawn
 * back to front so the painter's algorithm holds without any z-sorting at
 * render time, and the whole thing is generated from a seeded random so the
 * city is the same city on every load — one that reshuffled per visit would
 * not be a diagram of anything.
 */
.cityplan {
  display: block;
  inline-size: 100%;
  block-size: auto;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--map-ground);
}
.cp-sky { fill: var(--map-ground); }
.cp-land { fill: #10151C; }
.cp-water { fill: #0E2A39; }
.cp-park { fill: #1C4A2A; }
.cp-plot { fill: #141A22; }
.cp-street { fill: #1A222E; }

/* Roof, then the two walls. The shading is baked per building so a cluster
 * reads as solid rather than as outlines. */
.cp-parcel polygon { transition: opacity 140ms; }
.cp-parcel { cursor: pointer; }
.cp-parcel .b-win { fill: #FFE9A8; opacity: 0.22; }
.cp-parcel:hover .b-win,
.cp-parcel:focus-visible .b-win,
.cp-parcel[aria-pressed="true"] .b-win { opacity: 0.85; }
/* Lifting a cluster dims everything else rather than outlining the one —
 * an outline on an axonometric block reads as a seam. */
.citymap:has(.cp-parcel:hover) .cp-parcel:not(:hover) polygon,
.citymap:has(.cp-parcel[aria-pressed="true"]) .cp-parcel:not([aria-pressed="true"]) polygon {
  opacity: 0.34;
}
.cp-parcel:focus-visible { outline: none; }
.cp-parcel:focus-visible .b-t { stroke: #FFF; stroke-width: 2; }

.cp-rail {
  fill: none;
  stroke: var(--line-yellow);
  stroke-width: 5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.cp-stop { fill: var(--map-ground); stroke: var(--line-yellow); stroke-width: 3; }

.citymap__key { display: grid; gap: 0.9rem; }

.citymap__readout {
  min-block-size: 9.5rem;
  padding: 1rem 1.1rem;
  background: var(--panel-2);
  border: 1px solid var(--rule);
  border-inline-start: 6px solid var(--rc, var(--accent));
  border-radius: 3px;
}
.section--panel .citymap__readout { background: var(--ground); }
.citymap__readout h3 {
  font-family: var(--display);
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.35rem;
}
.citymap__readout p { color: var(--ink-2); font-size: 0.9375rem; margin-bottom: 0.6rem; }
.citymap__basis {
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--ink-3);
  line-height: 1.5;
}
.citymap__basis b { color: var(--ink-2); }

.legend-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.legend-chips button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: none;
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.3rem 0.6rem 0.3rem 0.35rem;
  cursor: pointer;
}
.legend-chips button::before {
  content: "";
  inline-size: 10px;
  block-size: 10px;
  border-radius: 2px;
  background: var(--pc);
}
.legend-chips button:hover, .legend-chips button[aria-pressed="true"] { color: var(--ink); border-color: var(--ink-4); }
.legend-chips button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ════════════════════════════════════════════════════════════════════════
   Base against full
   ════════════════════════════════════════════════════════════════════════ */

.vs { margin-top: 1.75rem; overflow-x: auto; }
.vs table { inline-size: 100%; border-collapse: collapse; min-inline-size: 30rem; }
.vs caption {
  text-align: start;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-bottom: 0.6rem;
}
.vs th, .vs td {
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--rule);
  text-align: start;
  font-size: 0.9375rem;
  vertical-align: baseline;
}
.vs thead th {
  font-family: var(--display);
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--ink);
  border-bottom: 2px solid var(--rule);
}
.vs thead th:nth-child(2) { color: var(--line-green-lit); }
.vs thead th:nth-child(3) { color: var(--line-yellow); }
.vs tbody th { font-weight: 500; color: var(--ink-2); }
.vs td { font-family: var(--mono); font-size: 0.875rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.vs td.yes { color: var(--good); }
.vs td.no { color: var(--ink-4); }
.vs tbody tr:hover { background: color-mix(in srgb, var(--ink) 4%, transparent); }

/* ── The "and much more" bar ─────────────────────────────────────────── */

.more {
  display: grid;
  gap: 1rem;
  align-items: center;
  margin-top: 2rem;
  padding: 1.4rem 1.5rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background:
    linear-gradient(90deg,
      color-mix(in srgb, var(--line-blue-lit) 12%, transparent),
      transparent 55%),
    var(--panel-2);
}
.section--panel .more {
  background:
    linear-gradient(90deg,
      color-mix(in srgb, var(--line-blue-lit) 12%, transparent),
      transparent 55%),
    var(--ground);
}
@media (min-width: 780px) { .more { grid-template-columns: 1fr auto; gap: 1.75rem; } }
.more h3 {
  font-family: var(--display);
  font-size: clamp(1.35rem, 2.6vw, 1.75rem);
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.4rem;
  text-wrap: balance;
}
.more p { color: var(--ink-2); font-size: 0.9375rem; max-width: 62ch; margin-bottom: 0.6rem; }
.more ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  padding: 0;
  margin: 0;
}
.more li {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-3);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 0.25rem 0.55rem;
}

/*
 * Visually hidden, still announced. The stop markers on the platform are
 * circles with no text in them; without this a screen reader gets six
 * identical unlabelled buttons.
 */
.sr-only {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
