/* SG BUMPER CARS — the site that accompanies the game.
   ============================================================================
   ONE stylesheet for every static page in public/. Before this file each page
   carried its own copy of the same ~25 line inline <style> block, which is how
   a design drifts: change a link colour and you change it eight times, and one
   page quietly does not get the memo.

   The look is the game's, not a generic dark theme. Every value below is taken
   from src/style.css so the site and the cabinet cannot diverge:

     button  background var(--sg-red), 4px solid white, box-shadow 6px 6px 0 #000,
             hover translate(2px,2px) + shadow 4px 4px           (style.css button.btn)
     card    background var(--panel), 4px solid #46506b, shadow 6px 6px 0 #000,
             hover border gold + the same translate               (style.css .card)
     focus   3px solid var(--neon), offset 2px                    (style.css :focus-visible)
     CRT     1px scanline every 3px + a corner vignette           (style.css #crt)

   Rules that apply here as much as in the game:
     - No platform emoji and no image files for UI furniture. The only images
       are real gameplay screenshots (public/shots/) and the pixel mark, which
       is the same bitmap as the favicon.
     - Press Start 2P is for headlines, eyebrows and buttons ONLY. It is
       genuinely unreadable at paragraph length, so body copy stays on the
       system stack.
   ========================================================================== */

@font-face {
  font-family: 'Press Start 2P';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/press-start-2p.woff2') format('woff2');
}

:root {
  color-scheme: dark;

  /* Palette, verbatim from src/style.css :root */
  --sg-red: #ee2536;
  --sg-white: #f4f4f4;
  --neon: #38e8ff;
  --gold: #ffd34d;
  --danger: #ff3b3b;
  --ok: #3ddc6a;
  --panel: #0d0f1e;

  /* Site-only extensions: a darker page bed than the panels sit on, plus the
     two greys the old inline styles already used for body text and captions. */
  --ink: #05060f;
  --panel-2: #12162a;
  --line: #262c44;
  --edge: #46506b;          /* card border, from .card in style.css */
  --text: #e8e8ef;
  --dim: #9aa3bd;

  --font-pix: 'Press Start 2P', 'Courier New', monospace;
  --font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;

  --measure: 68ch;
  --wide: 1120px;
}

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

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

body {
  background: var(--ink);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.7;
  /* The pages scroll (unlike the game at /, which must never scroll). */
  overflow-x: hidden;
}

/* ---------- CRT overlay ------------------------------------------------
   Same recipe as the game's #crt, dialled well back: at the game's 0.22 the
   scanlines eat body copy. Fixed so it does not scroll with the content. */
body::after {
  content: '';
  position: fixed; inset: 0; z-index: 900; pointer-events: none;
  background:
    radial-gradient(ellipse at center, transparent 62%, rgba(0, 0, 0, 0.45) 100%),
    repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.13) 0 1px, transparent 1px 3px);
}
/* Readers who ask for maximum contrast do not want a texture over their text. */
@media (prefers-contrast: more) {
  body::after { display: none; }
}

/* ---------- links + focus ---------------------------------------------- */
a { color: var(--neon); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--gold); }
:focus-visible { outline: 3px solid var(--neon); outline-offset: 2px; }
:focus:not(:focus-visible) { outline: none; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 1000;
  background: var(--gold); color: #000; padding: 12px 18px;
  font-family: var(--font-pix); font-size: 11px; text-decoration: none;
}
.skip:focus { left: 8px; top: 8px; }

/* ---------- header -----------------------------------------------------
   Sticky, so "Play free" is always one click away. That button is the whole
   point of the site: no install is the strongest thing this game has. */
.site-head {
  position: sticky; top: 0; z-index: 800;
  display: flex; align-items: center; gap: 18px;
  padding: 10px 20px;
  background: rgba(5, 6, 15, 0.94);
  border-bottom: 2px solid var(--line);
  backdrop-filter: blur(6px);
}

.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; flex: 0 0 auto; }
.brand-mark { width: 30px; height: 30px; image-rendering: pixelated; }
.brand-name {
  font-family: var(--font-pix); font-size: 11px; letter-spacing: 1px;
  color: var(--sg-white); line-height: 1.4;
}
.brand:hover .brand-name { color: var(--gold); }

.site-nav {
  display: flex; gap: 6px; flex: 1 1 auto; min-width: 0;
  overflow-x: auto; scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.site-nav::-webkit-scrollbar { display: none; }
.site-nav a {
  flex: 0 0 auto;
  font-family: var(--font-pix); font-size: 9px; letter-spacing: 0.5px;
  color: var(--dim); text-decoration: none;
  padding: 9px 10px; border: 2px solid transparent;
}
.site-nav a:hover { color: var(--sg-white); border-color: var(--edge); }
.site-nav a[aria-current='page'] { color: var(--gold); border-color: var(--gold); }

/* ---------- buttons -----------------------------------------------------
   button.btn from src/style.css, including the press-down on hover. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-pix); font-size: 12px; letter-spacing: 1px;
  text-transform: uppercase; text-decoration: none;
  color: var(--sg-white); background: var(--sg-red);
  border: 4px solid var(--sg-white); padding: 14px 22px;
  box-shadow: 6px 6px 0 #000; cursor: pointer;
  line-height: 1.4; min-height: 52px;
}
.btn:hover, .btn:focus {
  color: var(--sg-white); transform: translate(2px, 2px); box-shadow: 4px 4px 0 #000;
}
.btn.ghost { background: transparent; border-color: var(--neon); color: var(--neon); }
.btn.ghost:hover { color: var(--gold); border-color: var(--gold); }
.btn.gold { background: var(--gold); color: #1a1405; border-color: var(--sg-white); }
.btn.small { font-size: 10px; padding: 10px 14px; min-height: 40px; box-shadow: 4px 4px 0 #000; }

/* The header's play button keeps its shadow tight so it does not crowd the bar. */
.site-head .btn { flex: 0 0 auto; font-size: 10px; padding: 10px 14px; min-height: 40px; box-shadow: 4px 4px 0 #000; }

@media (max-width: 860px) {
  .site-head { gap: 10px; padding: 8px 12px; flex-wrap: wrap; }
  .brand-name { display: none; }
  /* nav drops to its own row underneath, so the play button needs pushing to
     the right edge itself rather than relying on the nav to fill the gap */
  .site-head .btn { margin-left: auto; }
  .site-nav { order: 3; width: 100%; flex-basis: 100%; padding-bottom: 2px; }
}

/* ---------- layout ------------------------------------------------------ */
main { display: block; }
.wrap { max-width: var(--wide); margin: 0 auto; padding: 0 20px; }
section { padding: 46px 0; }

/* The reading column. `.col` deliberately does NOT set its own max-width: it is
   applied to the same element as `.wrap`, so a width here would shrink the
   centred container and push the prose to a different left edge than the hero
   headline above it. Instead the measure is capped per child, which keeps one
   left edge down the whole page while still letting full-width things (screenshot
   rows, card grids) run out to the container edge. */
.col > * { max-width: var(--measure); }
.col > .grid,
.col > .stats,
.col > .shot,
.col > .shot-row,
.col > .video,
.col > .table-scroll,
.col > table,
.col > .rule,
.col > .tags,
.col > .cab { max-width: none; }

/* ---------- hero --------------------------------------------------------
   --hero-img is set per page to a real gameplay screenshot (public/shots/).
   Pages without one fall back to the gradient alone, so the hero never shows
   a broken image while the shots are being generated. */
.hero {
  position: relative; overflow: hidden;
  border-bottom: 2px solid var(--line);
  padding: 62px 0 54px;
  background:
    linear-gradient(180deg, rgba(5, 6, 15, 0.80) 0%, rgba(5, 6, 15, 0.93) 58%, var(--ink) 100%),
    var(--hero-img, linear-gradient(160deg, #14183a 0%, #0a0c1c 55%, #05060f 100%));
  background-size: cover, cover;
  /* Frame low in the screenshot. The top of a gameplay frame is HUD and toast
     boxes, and a health bar sliding out from under the site header reads as a
     rendering fault, not as art. The bottom two thirds are road and scenery,
     which is what should sit behind the headline. */
  background-position: center, center 78%;
  image-rendering: pixelated;
}
/* Heavier scanlines over the art than over body copy: this is the one band on
   the page that is supposed to look like a screen. */
.hero::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.26) 0 1px, transparent 1px 3px);
}
.hero > .wrap { position: relative; }

.eyebrow {
  font-family: var(--font-pix); font-size: 10px; letter-spacing: 2px;
  color: var(--neon); text-transform: uppercase;
}

h1 {
  font-family: var(--font-pix);
  font-size: clamp(19px, 4.4vw, 34px);
  line-height: 1.45; letter-spacing: 1px;
  color: var(--gold);
  /* the store-screenshot headline treatment: red offset, then black */
  text-shadow: 4px 4px 0 #b3123c, 7px 7px 0 rgba(0, 0, 0, 0.55);
  margin: 16px 0 0;
}

.lede { font-size: 19px; color: var(--text); max-width: 60ch; margin-top: 20px; }
.hero .meta { margin-top: 12px; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 28px; }

/* ---------- section headings ------------------------------------------- */
h2 {
  font-family: var(--font-pix);
  font-size: clamp(13px, 2.1vw, 17px); line-height: 1.6; letter-spacing: 1px;
  color: var(--neon);
  border-left: 6px solid var(--sg-red); padding-left: 14px;
  margin: 44px 0 16px;
}
h3 {
  font-family: var(--font-pix);
  font-size: 12px; line-height: 1.7; letter-spacing: 0.5px;
  color: var(--gold);
  margin: 30px 0 10px;
}
h4 { font-size: 17px; color: var(--sg-white); margin: 22px 0 6px; }

p, ul, ol, table, figure, blockquote { max-width: var(--measure); }
p + p, p + ul, ul + p, p + ol, ol + p { margin-top: 14px; }
ul, ol { padding-left: 22px; }
li { margin: 7px 0; }
li::marker { color: var(--sg-red); }
strong { color: var(--sg-white); }
small { font-size: 14px; color: var(--dim); }

.meta { color: var(--dim); font-size: 15px; }
.dim { color: var(--dim); }

/* ---------- road-sign rule ---------------------------------------------
   Lane markings as a section divider. Same dash geometry as the caption band
   stamped on the store screenshots, so site, store listing and share cards
   read as one campaign. */
.rule {
  height: 10px; border: 0; margin: 40px 0;
  background: repeating-linear-gradient(90deg, var(--gold) 0 44px, transparent 44px 86px);
  opacity: 0.75;
}

/* ---------- cabinet card ------------------------------------------------ */
.cab {
  background: var(--panel); border: 4px solid var(--edge);
  padding: 20px; box-shadow: 6px 6px 0 #000;
  max-width: none;
}
.cab > * { max-width: none; }
.cab h3 { margin-top: 0; }
a.cab { display: block; text-decoration: none; color: var(--text); }
a.cab:hover { border-color: var(--gold); transform: translate(2px, 2px); box-shadow: 4px 4px 0 #000; }

.grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); }
.grid.two { grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }

/* ---------- screenshots -------------------------------------------------
   The game renders at 240p/480p and upscales with hard pixels, so a screenshot
   that does the same thing is honest as well as small. Never smooth these. */
.shot { margin: 26px 0; max-width: none; }
.shot img {
  display: block; width: 100%; height: auto;
  image-rendering: pixelated;
  border: 4px solid var(--edge); box-shadow: 6px 6px 0 #000;
  background: #000;
}
.shot figcaption {
  font-size: 15px; color: var(--dim); margin-top: 14px; max-width: var(--measure);
}
.shot-row { display: grid; gap: 22px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.shot-row .shot { margin: 0; }

/* ---------- voice-line callout -----------------------------------------
   Quoted in-game Singlish. This is the one place em dashes are allowed in the
   site copy, because the dialogue uses them deliberately and is drift-checked
   against the voice registry (see tools/voice-lines.mjs). */
.vo {
  border-left: 6px solid var(--gold);
  background: var(--panel-2);
  padding: 16px 20px; margin: 24px 0;
  max-width: var(--measure);
}
.vo p { font-size: 18px; color: var(--sg-white); max-width: none; }
.vo .who {
  display: block; margin-top: 10px;
  font-family: var(--font-pix); font-size: 9px; letter-spacing: 1px; color: var(--gold);
}
/* Play button for the real baked clip (cast.html). Audio is preload="none", so
   nothing is fetched until it is pressed. */
.vo-play {
  margin-top: 12px; font-family: var(--font-pix); font-size: 9px; letter-spacing: 1px;
  background: transparent; color: var(--neon); border: 2px solid var(--neon);
  padding: 8px 12px; cursor: pointer; text-transform: uppercase;
}
.vo-play:hover { color: var(--gold); border-color: var(--gold); }
.vo-play[aria-pressed='true'] { color: var(--gold); border-color: var(--gold); }

/* ---------- cast cards (cast.html) --------------------------------------
   No portraits: the game has no image files and the site keeps that rule, so a
   character is identified by their initial set in the pixel font over their own
   signature colour, which is passed in as --c on the card. */
.cast-card { display: flex; flex-direction: column; gap: 4px; }
.cast-head { display: flex; align-items: center; gap: 14px; margin-bottom: 6px; }
.cast-mark {
  flex: 0 0 auto; width: 54px; height: 54px;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-pix); font-size: 20px; color: var(--c, var(--gold));
  border: 3px solid var(--c, var(--gold)); background: #05060f;
  box-shadow: 4px 4px 0 #000;
}
.cast-card h3 { margin: 0; color: var(--c, var(--gold)); }
.cast-role { font-size: 14px; color: var(--dim); margin-top: 4px; }
.cast-card .vo { margin: 14px 0 0; border-left-color: var(--c, var(--gold)); }

/* ---------- stat tiles (facts.html) ------------------------------------- */
.stats { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); margin: 26px 0; }
.stat { background: var(--panel); border: 4px solid var(--edge); padding: 18px; box-shadow: 6px 6px 0 #000; }
.stat b {
  display: block; font-family: var(--font-pix); font-size: clamp(17px, 3vw, 24px);
  color: var(--gold); line-height: 1.4;
}
.stat span { display: block; margin-top: 12px; font-size: 15px; color: var(--dim); line-height: 1.6; }
.stat.warn b { color: var(--danger); }

/* ---------- tags -------------------------------------------------------- */
.tags { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0; max-width: none; }
.tag {
  font-family: var(--font-pix); font-size: 8px; letter-spacing: 1px;
  color: var(--dim); border: 2px solid var(--line); padding: 6px 8px; text-transform: uppercase;
}
.tag.gold { color: var(--gold); border-color: var(--gold); }
.tag.neon { color: var(--neon); border-color: var(--neon); }
.tag.red { color: var(--sg-red); border-color: var(--sg-red); }

/* ---------- tables ------------------------------------------------------ */
.table-scroll { overflow-x: auto; margin: 22px 0; max-width: none; }
table { border-collapse: collapse; width: 100%; font-size: 15px; }
th, td { border: 2px solid var(--line); padding: 10px 12px; text-align: left; vertical-align: top; }
th { font-family: var(--font-pix); font-size: 9px; letter-spacing: 0.5px; color: var(--gold); background: var(--panel); }

/* ---------- page furniture carried over from the old inline styles ------
   These classes are already in the page markup; they used to be styled eight
   times over. Same jobs, cabinet treatment. */

/* jump list at the top of the long guides (guide, modes, jbrun) */
.toc {
  display: flex; flex-wrap: wrap; gap: 8px;
  background: var(--panel); border: 4px solid var(--edge); box-shadow: 6px 6px 0 #000;
  padding: 16px; margin: 8px 0 30px; max-width: none;
}
.toc a {
  font-family: var(--font-pix); font-size: 9px; letter-spacing: 0.5px;
  text-decoration: none; color: var(--neon);
  border: 2px solid var(--line); padding: 8px 10px;
}
.toc a:hover { color: var(--gold); border-color: var(--gold); }

/* campaign.html: the chapter strapline under each chapter heading */
.chapline { color: var(--dim); font-size: 15px; margin: -6px 0 16px; }

/* campaign.html level tables: the number column, and the boss rows */
td.lv { color: var(--gold); white-space: nowrap; font-family: var(--font-pix); font-size: 10px; }
.boss td { background: rgba(238, 37, 54, 0.10); }
.boss td.lv { color: var(--sg-red); }

/* updates.html changelog entries */
.entry { border-top: 2px solid var(--line); padding-top: 10px; margin-top: 38px; max-width: none; }
.entry > * { max-width: var(--measure); }
.entry h2 { margin-top: 14px; }
.entry .date {
  font-family: var(--font-pix); font-size: 9px; letter-spacing: 1px;
  color: var(--dim); margin: 0 0 14px;
}

/* ---------- video facade ------------------------------------------------
   Nothing is requested from YouTube until the visitor clicks: the poster is a
   local PNG and the iframe is only injected on activation, against
   youtube-nocookie.com. That matches the consent discipline in src/consent.js,
   where nothing third-party fires before the user says yes. */
.video { margin: 26px 0; max-width: none; }
.facade {
  position: relative; display: block; width: 100%; aspect-ratio: 16 / 9;
  border: 4px solid var(--edge); box-shadow: 6px 6px 0 #000;
  background: #000 center / cover no-repeat; cursor: pointer; padding: 0;
  overflow: hidden;
}
.facade:hover { border-color: var(--gold); }
.facade img { display: block; width: 100%; height: 100%; object-fit: cover; image-rendering: pixelated; }
.facade .play-mark {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(5, 6, 15, 0.35);
}
.facade .play-mark span {
  font-family: var(--font-pix); font-size: 12px; letter-spacing: 1px; color: var(--sg-white);
  background: var(--sg-red); border: 4px solid var(--sg-white); box-shadow: 6px 6px 0 #000;
  padding: 14px 20px; text-transform: uppercase;
}
.facade:hover .play-mark span { transform: translate(2px, 2px); box-shadow: 4px 4px 0 #000; }
.video iframe { display: block; width: 100%; aspect-ratio: 16 / 9; border: 4px solid var(--edge); }
.video figcaption { font-size: 15px; color: var(--dim); margin-top: 14px; max-width: var(--measure); }

.transcript { margin-top: 18px; }
.transcript summary {
  font-family: var(--font-pix); font-size: 10px; letter-spacing: 1px; color: var(--neon);
  cursor: pointer; padding: 12px 0;
}
.transcript summary:hover { color: var(--gold); }
.transcript[open] summary { color: var(--gold); }

/* ---------- callout ----------------------------------------------------- */
.note {
  border: 4px solid var(--gold); background: rgba(255, 211, 77, 0.07);
  padding: 18px 20px; margin: 26px 0; max-width: var(--measure);
}
.note.red { border-color: var(--sg-red); background: rgba(238, 37, 54, 0.08); }
.note > :first-child { margin-top: 0; }

/* ---------- source list -------------------------------------------------
   story.html and facts.html show their sources on the page. The whole point of
   those pages is that the numbers are real, so the citations are content, not
   an appendix. */
.sources { font-size: 14px; color: var(--dim); }
.sources li { margin: 9px 0; }

/* ---------- footer ------------------------------------------------------ */
.site-foot {
  border-top: 2px solid var(--line); background: var(--panel);
  margin-top: 60px; padding: 44px 0 60px;
}
.foot-grid { display: grid; gap: 30px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.foot-grid h2 {
  font-size: 10px; color: var(--gold); border: 0; padding: 0; margin: 0 0 12px;
}
.foot-grid ul { list-style: none; padding: 0; }
.foot-grid li { margin: 8px 0; }
.foot-grid a { font-size: 15px; text-decoration: none; }
.foot-grid a:hover { text-decoration: underline; }
.foot-legal {
  margin-top: 34px; padding-top: 22px; border-top: 2px solid var(--line);
  font-size: 14px; color: var(--dim); max-width: none;
}

/* ---------- small screens ---------------------------------------------- */
@media (max-width: 640px) {
  body { font-size: 16px; }
  section { padding: 34px 0; }
  .hero { padding: 42px 0 38px; }
  .lede { font-size: 17px; }
  .cab, .stat { padding: 16px; box-shadow: 4px 4px 0 #000; }
  .btn { font-size: 11px; padding: 12px 16px; }
}
