/* Design tokens – single source of truth for the Sauna xS palette.
 *
 * Mirrors design/tokens.json. If you change a value here, change it there.
 * Pages must not declare their own hexes; add a token instead.
 *
 * Naming: primitives (--blue, --green, --red) name the colour; semantic
 * aliases (--over, --under) name the meaning. Prefer the semantic name when
 * one exists. The old --accent is retired: it meant blue on the dashboard and
 * pink on the London page, so it was never safe to share.
 *
 * Leak: Leaflet and MapLibre paint properties take colour strings in JS, where
 * var() does not resolve, so the map layers in index.html, pcon/ and london/
 * still hold literal hexes (--bss pink for sauna dots, --blue for the user
 * pin). Change a colour here and you must grep the JS too.
 */

/* Inter, self-hosted so every OS gets the same face. Variable (wght 100-900 +
 * optical size), subset to the characters these pages actually use: 87 KB.
 * SIL Open Font License – see fonts/LICENSE.txt.
 *
 * Two glyphs are NOT in Inter and fall back per-glyph to the system font:
 * ✕ (U+2715, the league-modal close button) and ◐ (U+25D0, London's theme
 * toggle). They render fine, but in the OS face – swap them for SVG icons if
 * you want the last of the platform variance gone.
 *
 * font-display: swap – text paints immediately in the system font and swaps
 * when Inter lands, so a slow font never blocks reading. */
@font-face {
  font-family: "Inter";
  src: url("fonts/InterVariable-subset.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* type – Inter, with the old system stack retained as the fallback: if the
   * font fails to load, the site degrades to exactly how it looked before,
   * not to Times. */
  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* type scale – one consolidated set of steps for the lookup + pcon pages.
   * The four display steps are fluid: clamp(min, Nvw, max) grows the text with
   * the viewport on phones and pins to the max on anything wider (each clamp
   * reaches its max by ~490px viewport, so tablet/desktop always render the max
   * – the wider 640px column never over-scales the type). The five body steps
   * are fixed; near-duplicate sizes that used to drift (13/13.5/14, 12/12.5)
   * were snapped onto the nearest step here. Map-overlay chrome (attribution,
   * tooltips, scale bar) keeps its own literal px in app.css – it is not part
   * of this reading scale. */
  --fs-micro: 11px;
  --fs-caption: 12px;
  --fs-small: 14px;
  --fs-body: 15px;
  --fs-ui: 16px;
  --fs-md: clamp(17px, 4.4vw, 19px);
  --fs-lg: clamp(20px, 5vw, 24px);
  --fs-xl: clamp(28px, 8.4vw, 40px);
  --fs-display: clamp(42px, 13vw, 64px);

  /* radii – derived from what the pages actually shipped, not invented. Every
   * border-radius should reference one of these; a new literal px value means
   * either you want an existing step or the scale needs a new one.
   *
   * --r-pill is 999px: a radius larger than half the box clamps to a full
   * pill, so badges that used 20px and chips that used 999px were already
   * rendering the same shape under two numbers. */
  --r-xs: 4px;      /* inline code */
  --r-sm: 5px;      /* BSS badge (lookup + dashboard agree) */
  --r-md: 10px;     /* small controls: pager, search, legend, current row */
  --r-lg: 12px;     /* fields, buttons, modal search, popups, London cards */
  --r-row: 14px;    /* sauna list rows */
  --r-xl: 18px;     /* panels: tile, surprise, card, kpi */
  --r-pill: 999px;  /* fully rounded: badges, chips */
  --r-circle: 50%;  /* icon buttons, dots */

  /* surfaces */
  --bg: #000;
  --card: #1c1c1e;
  --card-raised: #26262a;
  --border: #2c2c2e;
  --border-light: rgba(255, 255, 255, .28);  /* hairline for chips ON the chart
                              (surprise-card callouts): --border reads too
                              quiet over the curve fill, --ink too loud.
                              Settled on the dotplot bench, 6 Aug 2026. */
  --grid: #232326;
  --map-ground: #111122;   /* Leaflet map ground: matches the carto dark tiles so
                              tile-load gaps read as map, not a pale flash */

  /* text */
  --ink: #fff;
  --ink-dim: #aeaeb2;
  --muted: #8e8e93;

  /* primitives */
  --blue: #2f9fff;
  --blue-soft: rgba(47, 159, 255, .14);
  --green: #2f9e57;
  --red: #ff5a4f;
  --bss: #ff4fd8;   /* BSS = British Sauna Society. Semantic despite living with
                       the primitives: the pink of the sauna markers and the
                       ★ member badge (listings via saunamap.uk, which the BSS
                       runs) – see components/badge.md and map.md. If a pink is
                       ever needed that does NOT mean membership, mint a new
                       token rather than borrowing this one. */

  /* semantic: xS gap direction */
  --over: var(--green);
  --over-soft: rgba(47, 158, 87, .16);
  --under: var(--red);
  --under-soft: rgba(255, 90, 79, .14);

  /* map: the faint highlight of the selected area (local authority / seat) on
   * the lookup + pcon map tile. Consumed by the Leaflet layer in JS, where
   * var() does not resolve – so index.html and pcon/ mirror these values
   * literally, exactly like the marker colours. See design/components/map.md.
   * The fill sits a shade under --blue-soft so it reads as a backdrop beneath
   * the sauna markers, not as a filled shape. */
  --area-fill: rgba(47, 159, 255, .1);   /* selected-area fill */
  --area-line: rgba(47, 159, 255, .5);   /* selected-area outline */
  --area-line-w: 1.2px;                  /* outline stroke width */
  --area-ring: rgba(47, 159, 255, .35);  /* dashed radius ring at the slider distance */
  --coast-line: rgba(255, 255, 255, .25); /* coastline vector while a drag hides the
                                             tiles – a JS literal in app.js coastline() */

  /* map: floating-over-map chrome – one look shared by the map buttons, the
   * fullscreen zoom control and the hover tooltips (all in app.css, where
   * var() resolves). The strong variant is the hover/pressed state. */
  --map-chrome-bg: rgba(0, 0, 0, .55);
  --map-chrome-bg-strong: rgba(0, 0, 0, .8);
  /* legibility halo behind bare-text map labels (.sauna-label) */
  --map-label-shadow: 0 1px 3px rgba(0, 0, 0, .95), 0 0 3px rgba(0, 0, 0, .9);
  /* the heavier halo the radar's own labels carry (.radar-label). They are read
   * in passing, over whatever the sweep happens to be crossing, and their real
   * competition is the basemap's OWN place names sitting in the same visual
   * register – so this reaches far enough out to push those back, where the
   * shadow above only separates text from terrain. */
  --radar-label-shadow: 0 1px 2px rgba(0, 0, 0, 1), 0 0 6px rgba(0, 0, 0, 1),
                        0 0 13px rgba(0, 0, 0, .95);

  /* map: your-location pin (.pin – a divIcon, so CSS-styled: no JS mirror).
   * The fill sits under a solid --blue ring; the live pulse halo is --blue. */
  --pin-fill: rgba(47, 159, 255, .5);

  /* map: the radar sweep off a live pin (.radar in app.css – CSS-styled, no JS
   * mirror). One blue at four alphas: the leading edge of the wedge, the trail
   * behind it, and where the trail dies. --radar-tail is a zero-alpha BLUE, not
   * `transparent` – a conic gradient interpolating to transparent black greys
   * the wedge out on the way. --radar-line is the scan line at the leading
   * edge, the only part meant to read as a line. */
  --radar-edge: rgba(47, 159, 255, .3);
  --radar-trail: rgba(47, 159, 255, .08);
  --radar-tail: rgba(47, 159, 255, 0);
  --radar-line: rgba(47, 159, 255, .55);

  /* nations */
  --n-eng: #3987e5;
  --n-sco: #199e70;
  --n-wal: #c98500;
  --n-ire: #008300;
  --n-ni: #9085e9;
  --n-iom: #d4567e;
  --n-ci: #23b5c9;

  --shadow: none;
}

/* Light theme – opt in per page with <body class="light">. Only the London
 * map page uses it today; the lookup app and dashboard commit to black. */
body.light {
  --bg: #f7f6f2;
  --card: #fff;
  --border: #dddbd4;
  --ink: #1c1c1e;
  --muted: #7c7a74;
}
