/* Bike or Die 2026 — design tokens
 * Art direction: remake/design/visual-identity.md
 *
 * The concept is a surveyor's section drawing on the game's own integer
 * lattice. Light theme is a whiteprint (dark line on warm paper); dark theme
 * is a cyanotype blueprint (chalk line on Prussian blue). The canvas is the
 * sheet — the in-world colours follow the theme, they are not a fixed device
 * screen.
 *
 * Structure, and it is a hard rule:
 *   :root                                            complete LIGHT palette
 *   @media (prefers-color-scheme: dark) :root:not([data-theme="light"])
 *   :root[data-theme="dark"]
 * No colour is ever defined only inside a media or [data-theme] block. The
 * two dark blocks redefine tokens that already exist on bare :root and add
 * none of their own, so an explicit light choice and a webfont-less fallback
 * both resolve to a complete palette.
 *
 * Canvas side: read these with
 *   const T = getComputedStyle(document.documentElement);
 *   const c = n => T.getPropertyValue(n).trim();
 * once per theme change, cached — never per frame.
 */

/* ========================================================================
   LIGHT — whiteprint. Complete palette; everything below is defined here.
   ======================================================================== */
:root {
  color-scheme: light dark;

  /* --- interface: surfaces ------------------------------------------- */
  --sheet:          #F3F0E8;  /* page background — warm drawing paper       */
  --sheet-sunk:     #E7E2D5;  /* wells, toolbars, letterbox — recessed      */
  --panel:          #FCFAF5;  /* cards and rows raised off the sheet        */

  /* --- interface: rules ---------------------------------------------- */
  --rule:           #D2CBB9;  /* every 1px hairline: borders, dividers, grid*/
  --rule-2:         #B3AA93;  /* input/button borders — must hold at 1px    */

  /* --- interface: ink ------------------------------------------------- */
  --ink:            #16202B;  /* headings, level names, primary text        */
  --ink-2:          #46525E;  /* body prose, secondary values               */
  --muted:          #78838B;  /* labels, captions, units, disabled          */

  /* --- interface: the one accent, and measurement --------------------- */
  --signal:         #C03A16;  /* red flags, the single primary button       */
  --signal-soft:    #F6E3DA;  /* tint behind a signal chip                  */
  --annot:          #1D5E93;  /* force fields, cues, links, annotation      */
  --annot-soft:     #DEE9F3;  /* tint behind an annot chip                  */
  --pass:           #2E6A4A;  /* verified, conformance OK, run completed    */
  --fail:           #A32A12;  /* diverged, timed out, crashed               */

  /* --- in-world: the sheet -------------------------------------------- */
  --sky:            #EFEBE1;  /* the void. Flat, no gradient, ever          */
  --terrain-fill:   #D8D2C2;  /* the solid body — sky moved 14% to --line   */
  --line:           #1D2833;  /* terrain stroke; material 0 (grip); default */

  /* --- in-world: materials, coloured on the stroke, never the fill ---- */
  --mat-slip:       #7E5410;  /* material 1 — half traction                 */
  --mat-ice:        #186E99;  /* material 2 — ICE                           */
  --mat-glue:       #7B3F9B;  /* material 3 — glue                          */
  --mat-ghost:      #1D283347;/* material 4 — non-colliding; 1px dashed     */

  /* --- in-world: objects ---------------------------------------------- */
  --flag:           #C03A16;  /* red checkpoint flags   (tracks --signal)   */
  --hazard:         #101820;  /* obstacles — max contrast on the sheet      */
  --portal:         #1E7A4F;  /* portals only. "marked with green arrows"   */
  --field:          #1D5E93;  /* force-field bands      (tracks --annot)    */
  --spark:          #AE5810;  /* contact sparks, the wheel that is touching */
  --bike:           #16202B;  /* frame tubes and rider  (tracks --ink)      */

  /* ====================================================================
     Type. Theme-independent — defined once, never redefined below.
     Rule: anything the simulation produced is set in --font-mono, tabular.
           Anything a human wrote is set in --font-ui.
     ==================================================================== */
  --font-ui:   "Space Grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono",
               Menlo, Consolas, monospace;

  --fs-masthead:      clamp(26px, 3.6vw, 40px);
  --lh-masthead:      1.08;
  --ls-masthead:      -0.022em;

  --fs-head:          13px;    /* section heading, --font-ui 500            */
  --fs-body:          16px;    /* prose, --font-ui 400                      */
  --lh-body:          1.55;
  --measure:          68ch;

  --fs-name:          15px;    /* level / collection name, --font-ui 500    */

  --fs-label:         10.5px;  /* --font-mono 500, uppercase                */
  --ls-label:         0.14em;

  --fs-read:          19px;    /* large readout, --font-mono 500, tabular   */
  --fs-read-sm:       12px;    /* chip / small readout, --font-mono 400     */
  --fs-canvas:        11px;    /* in-canvas text — screen space only        */

  /* ====================================================================
     Geometry. The sheet has hairlines and right angles.
     ==================================================================== */
  --radius:           2px;     /* nothing above 3px. No pills.              */
  --radius-panel:     3px;
  --hairline:         1px;
  --gap:              14px;
  --pad-panel:        18px 20px;

  /* World constants, mirrored here so CSS-side legends stay in step with
     the renderer. World units, not pixels. */
  --wu-tile:          2048;    /* lattice, major                            */
  --wu-wheel:         256;     /* lattice, minor; wheel collision radius    */
  --wu-cell:          128;     /* force-field cell; one band                */
  --wu-wheelbase:     768;     /* the remake's own choice (RE-7)            */
}

/* ========================================================================
   DARK — cyanotype. System preference, unless the user chose light.
   Redefines existing tokens only; introduces none.
   ======================================================================== */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --sheet:        #0A1420;
    --sheet-sunk:   #06101A;
    --panel:        #0F1D2C;

    --rule:         #1E3348;
    --rule-2:       #2C4A64;

    --ink:          #E3EBF3;
    --ink-2:        #A8BACA;
    --muted:        #74899B;

    --signal:       #FF6A3C;
    --signal-soft:  #2A1610;
    --annot:        #6FB3E8;
    --annot-soft:   #0E2233;
    --pass:         #55BE8A;
    --fail:         #FF7A66;

    --sky:          #08131E;
    --terrain-fill: #16283A;
    --line:         #C9DAE8;

    --mat-slip:     #E8B45C;
    --mat-ice:      #7FD9F5;
    --mat-glue:     #C58CE6;
    --mat-ghost:    #C9DAE847;

    --flag:         #FF6A3C;
    --hazard:       #F2F7FC;
    --portal:       #4FD08E;
    --field:        #6FB3E8;
    --spark:        #FFB055;
    --bike:         #E3EBF3;
  }
}

/* ========================================================================
   DARK — explicit user choice. Same values; wins in both directions.
   ======================================================================== */
:root[data-theme="dark"] {
  --sheet:          #0A1420;
  --sheet-sunk:     #06101A;
  --panel:          #0F1D2C;

  --rule:           #1E3348;
  --rule-2:         #2C4A64;

  --ink:            #E3EBF3;
  --ink-2:          #A8BACA;
  --muted:          #74899B;

  --signal:         #FF6A3C;
  --signal-soft:    #2A1610;
  --annot:          #6FB3E8;
  --annot-soft:     #0E2233;
  --pass:           #55BE8A;
  --fail:           #FF7A66;

  --sky:            #08131E;
  --terrain-fill:   #16283A;
  --line:           #C9DAE8;

  --mat-slip:       #E8B45C;
  --mat-ice:        #7FD9F5;
  --mat-glue:       #C58CE6;
  --mat-ghost:      #C9DAE847;

  --flag:           #FF6A3C;
  --hazard:         #F2F7FC;
  --portal:         #4FD08E;
  --field:          #6FB3E8;
  --spark:          #FFB055;
  --bike:           #E3EBF3;
}

/* ========================================================================
   Base application of the tokens. Nothing here introduces a colour.
   ======================================================================== */
html { background: var(--sheet); }

body {
  margin: 0;
  background: var(--sheet);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

canvas { display: block; background: var(--sky); }

.mono,
[data-num] {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.label {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
}

:focus-visible {
  outline: 2px solid var(--annot);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
