/*
 * The design tokens (task 3.1, R-PROD-1).
 *
 * Ported from `docs/mockups/lab-console.html`, not re-derived. The chart marks
 * in particular were checked with the dataviz validator against each mode's own
 * surface — lightness band, chroma floor and contrast — and a value picked again
 * by eye would pass nothing. The plan says so explicitly; this comment is the
 * second place it is said, because the first is a file nobody edits.
 *
 * Three theme states, not two. An explicit choice stamps `data-theme` on the
 * root; the default "system" setting stamps nothing, and only
 * `prefers-color-scheme` separates light from dark there. So the bare `:root`
 * block below is the complete light palette, the media query redefines only the
 * tokens (guarded so an explicit light choice beats a dark OS), and the
 * `[data-theme="dark"]` block redefines them again so the toggle wins in both
 * directions. A colour whose only definition sits inside one of those blocks
 * never applies in the un-stamped state, which is how a page renders one
 * theme's text on the other theme's ground.
 *
 * Every component styles through these names and never against a literal.
 */

/* -- Typefaces ------------------------------------------------------------
 *
 * Self-hosted; see fonts/README.md for why, and for how to refresh them. The
 * source URL, kept here so the refresh instruction has something to copy:
 *
 *   https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=Bricolage+Grotesque:opsz,wght@12..96,800&display=swap
 */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  /* One variable file covers the whole body range, so a weight change costs no
     download. */
  font-weight: 400 700;
  font-display: swap;
  src: url('./fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('./fonts/bricolage-grotesque-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* -- Light, and the complete set ---------------------------------------- */
:root {
  --navy: #1C3760;
  --navy-2: #274573;
  --navy-3: #395187;

  --accent: #F6921E;
  /* Not the accent itself: #F6921E on white is under 3:1, so accent-coloured
     text uses this instead and the orange stays on fills and rules. */
  --accent-ink: #7A4408;
  --accent-soft: #FDF0DD;

  --link: #1B4799;

  --ink: #232830;
  --ink-2: #525C69;
  --ink-3: #77828F;

  --paper: #F4F6FA;
  --card: #FFFFFF;

  /* -- The rail: one surface, one colour, all three theme states ----------
   *
   * `--rail` and its inks are declared here and appear NOWHERE ELSE in this
   * file. Not in the media query, not in the `[data-theme="dark"]` block. That
   * is not an omission; it is the property being chosen.
   *
   * Every other surface here flips because the page flips with it: a card is
   * white on a light page and #141D2B on a dark one, and `--ink` flips to stay
   * readable on it. The rail is not that kind of surface. It is a brand band --
   * the masthead, and only the masthead -- and its whole job is to be the dark
   * ground a REVERSED logo is drawn for. A brand colour that changes with the
   * reader's operating system is not a brand colour.
   *
   * It used to flip to #0A111B in dark mode, and the result was a header that
   * measured 1.03:1 against `--paper` (#0D1420): not a navy band, just the top
   * of the page with a rule under it. Holding the navy is a hue shift rather
   * than a luminance one -- 1.55:1 against the dark page, still quiet, but the
   * difference between "there is no band" and "there is a blue band".
   *
   * Because the ground never changes, its inks never have to. One set of
   * measurements now covers every theme state, which is the real dividend:
   *
   *   --rail-ink   on --rail = 11.90:1     (white)
   *   --rail-ink-2 on --rail =  7.49:1     (muted)
   *   --accent     on --rail =  5.13:1     (the focus ring inside the band)
   *
   * The two inks are 1.59:1 apart, which is enough to read as emphasis and not
   * enough to carry meaning on its own -- so the current page in a nav is
   * marked by ink AND weight AND a rule, never by ink alone.
   *
   * `--rail-line` is not text. It is the band's finish: at 2.23:1 it draws a
   * crisp boundary rather than leaving the eye to find the edge of a fill, and
   * it is what keeps the band's bottom exact against `--paper` in dark mode,
   * where 1.55:1 is visible but soft.
   */
  --rail: #1C3760;
  --rail-ink: #FFFFFF;
  --rail-ink-2: #C3CEE0;
  --rail-line: #4A6BA5;

  --line: #DDE3EE;
  --line-2: #EAEEF6;

  /* Status. Each pairs an ink with a ground so a chip can carry both, and each
     is used *alongside* a word -- never instead of one (R-PROD-1). */
  --ok: #1F7A55;
  --ok-bg: #E4F4EC;
  --warn: #8A6100;
  --warn-bg: #FBF0D9;
  --crit: #A32117;
  --crit-bg: #FBE7E5;

  /*
   * The filled/selected surface, as its own token rather than `--navy`.
   *
   * `--navy` is a *brand* colour and works as a fill on white. In dark mode it
   * is #132743 against a #141D2B card -- all but identical, so a selected
   * button was indistinguishable from an unselected one. Found by looking at
   * the screen, which is the only way that class of bug is ever found.
   *
   * A filled control needs to contrast with the surface it sits on, and that is
   * a different requirement from being on-brand. In dark mode it goes lighter
   * than the card rather than darker.
   */
  --primary-bg: #1C3760;
  --primary-ink: #FFFFFF;

  --shadow: 0 1px 2px rgba(28, 55, 96, .06), 0 8px 24px rgba(28, 55, 96, .07);
  --radius: 7px;

  /* Chart marks. Validator-checked against this mode's surface; see the module
     comment before changing either. */
  --chart-bar: #2B5FBF;
  --chart-grid: #E4E9F2;

  /* Type. A scale rather than ad-hoc sizes, so a heading two levels down is a
     decision somebody made once. */
  --font-body: Inter, -apple-system, 'Segoe UI', sans-serif;
  --font-display: 'Bricolage Grotesque', Inter, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --text-xs: 12px;
  --text-sm: 13px;
  --text-base: 15px;
  --text-lg: 18px;
  --text-xl: 22px;
  --text-2xl: 28px;

  /* Spacing, on a 4px grid. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
}

/* -- Dark, by system preference ------------------------------------------
 *
 * Guarded on `:not([data-theme="light"])` so an explicit light choice beats a
 * dark operating system. Only tokens are redefined here: no component rule
 * belongs in this block.
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --navy: #132743;
    --navy-2: #1B3559;
    --navy-3: #2C4877;

    --accent: #F6921E;
    --accent-ink: #FFCE8C;
    --accent-soft: #3A2A12;

    --link: #8FB3F5;

    --ink: #E7ECF5;
    --ink-2: #A9B4C6;
    --ink-3: #7E8B9E;

    --paper: #0D1420;
    --card: #141D2B;
    /* No --rail here. The masthead's navy is a brand band and holds across all
       three theme states; see where it is declared. */

    --line: #26324A;
    --line-2: #1D2738;

    --ok: #6FD3A5;
    --ok-bg: #12301F;
    --warn: #F0C264;
    --warn-bg: #33280D;
    --crit: #F79A90;
    --crit-bg: #3A1815;

    --primary-bg: #8FB3F5;
    --primary-ink: #0D1420;

    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px rgba(0, 0, 0, .35);

    /* Not an inversion of the light value: stepped again from the same ramp and
       validated against the dark surface. */
    --chart-bar: #5B8DE8;
    --chart-grid: #232F45;
  }
}

/* -- Dark, chosen ---------------------------------------------------------
 *
 * The same tokens again. Duplication is deliberate: CSS has no way to share one
 * block between a media query and an attribute selector, and the alternative --
 * a second custom-property indirection - would make every colour two lookups
 * away from its value for the reader.
 */
:root[data-theme="dark"] {
  --navy: #132743;
  --navy-2: #1B3559;
  --navy-3: #2C4877;

  --accent: #F6921E;
  --accent-ink: #FFCE8C;
  --accent-soft: #3A2A12;

  --link: #8FB3F5;

  --ink: #E7ECF5;
  --ink-2: #A9B4C6;
  --ink-3: #7E8B9E;

  --paper: #0D1420;
  --card: #141D2B;
  /* No --rail here, for the same reason as the media query above. */

  --line: #26324A;
  --line-2: #1D2738;

  --ok: #6FD3A5;
  --ok-bg: #12301F;
  --warn: #F0C264;
  --warn-bg: #33280D;
  --crit: #F79A90;
  --crit-bg: #3A1815;

  --primary-bg: #8FB3F5;
  --primary-ink: #0D1420;

  --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px rgba(0, 0, 0, .35);

  --chart-bar: #5B8DE8;
  --chart-grid: #232F45;
}
