/* shared/tokens.css
   ------------------------------------------------------------------
   The house design system. Six colour tokens, three themes, three
   faces, one scale. See `Visual Design Standards.org` at the repo
   root — it is normative; this file implements it.

   NO SITE STYLESHEET MAY DECLARE A COLOUR. Consume these tokens.

   Palette blocks are labelled by an @theme <name> marker comment;
   tests/contrast-check.py parses each one. Do not remove or reword
   these markers. (Do not requote the marker's own delimiters inside
   prose either — a comment body containing the two characters that
   close a comment ends the comment early; see the well-formedness
   check in that test for why this matters.)
   ------------------------------------------------------------------ */

/* ---------- faces: self-hosted, no third-party requests ---------- */

@font-face { font-family: "Plex Sans"; font-style: normal; font-weight: 300;
  font-display: swap; src: url("/static/fonts/IBMPlexSans-Light.woff2") format("woff2"); }
@font-face { font-family: "Plex Sans"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/static/fonts/IBMPlexSans-Regular.woff2") format("woff2"); }
@font-face { font-family: "Plex Sans"; font-style: normal; font-weight: 600;
  font-display: swap; src: url("/static/fonts/IBMPlexSans-SemiBold.woff2") format("woff2"); }
@font-face { font-family: "Plex Sans"; font-style: normal; font-weight: 700;
  font-display: swap; src: url("/static/fonts/IBMPlexSans-Bold.woff2") format("woff2"); }

@font-face { font-family: "Plex Serif"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/static/fonts/IBMPlexSerif-Regular.woff2") format("woff2"); }
@font-face { font-family: "Plex Serif"; font-style: italic; font-weight: 400;
  font-display: swap; src: url("/static/fonts/IBMPlexSerif-Italic.woff2") format("woff2"); }
@font-face { font-family: "Plex Serif"; font-style: normal; font-weight: 600;
  font-display: swap; src: url("/static/fonts/IBMPlexSerif-SemiBold.woff2") format("woff2"); }

@font-face { font-family: "Plex Mono"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("/static/fonts/IBMPlexMono-Regular.woff2") format("woff2"); }
@font-face { font-family: "Plex Mono"; font-style: normal; font-weight: 500;
  font-display: swap; src: url("/static/fonts/IBMPlexMono-Medium.woff2") format("woff2"); }

/* ---------- invariants: faces, scale, measure ---------- */

:root {
  --font-inst: "Plex Sans", system-ui, sans-serif;   /* the institution */
  --font-read: "Plex Serif", Georgia, serif;         /* the person      */
  --font-data: "Plex Mono", ui-monospace, monospace; /* the machine     */

  /* major third (1.25) on a 17px base */
  --step--1: 0.78rem;
  --step-0: 1rem;
  --step-1: 1.25rem;
  --step-2: 1.563rem;
  --step-3: 1.953rem;
  --step-4: 2.441rem;

  --measure: 66ch;   /* running serif prose. never wider */
  --gutter: clamp(1.5rem, 7vw, 9rem);
  --rail: 1px;
}

/* ---------- light: achromatic ground and ink; signal is the only hue ---------- */
/* @theme light */
:root {
  --ground: #e8e8e8;
  --ground-raise: #dbdbdb;
  --rule: #b4b4b4;
  --ink-mute: #4a4a4a;
  --ink: #1a1a1a;
  --signal: #0f5132;
}

/* ---------- dark: same structure, opposite polarity ----------
   Order matters and so does the guard. The bare :root above is the
   complete light palette and the default for the un-stamped state.
   This block applies only when the OS asks for dark AND the reader
   has not explicitly chosen otherwise. The two [data-theme] blocks
   below let an explicit choice win in either direction, and now carry
   their own markers too — see the note below them.

   The @theme marker sits INSIDE the media query. contrast-check.py
   parses from the marker to the next closing brace, which is the
   :root block's own brace, so nesting is fine — verified. */
@media (prefers-color-scheme: dark) {
  /* @theme dark */
  :root:not([data-theme="light"]):not([data-theme="after-hours"]) {
    --ground: #171717;
    --ground-raise: #232323;
    --rule: #383838;
    --ink-mute: #a8a8a8;
    --ink: #e4e4e4;
    --signal: #8fc4b6;
  }
}

/* Explicit choices. Each theme is stated more than once by design: a
   bare/media-query default above, and an explicit [data-theme] override
   here so a reader can opt out of prefers-color-scheme. Every block that
   carries live colour values gets its own @theme marker so the gate
   validates every reachable copy independently — a duplicate the gate
   never reads is a duplicate that can drift silently out of contrast. */
/* @theme light */
:root[data-theme="light"] {
  --ground: #e8e8e8;
  --ground-raise: #dbdbdb;
  --rule: #b4b4b4;
  --ink-mute: #4a4a4a;
  --ink: #1a1a1a;
  --signal: #0f5132;
}

/* @theme dark */
:root[data-theme="dark"] {
  --ground: #171717;
  --ground-raise: #232323;
  --rule: #383838;
  --ink-mute: #a8a8a8;
  --ink: #e4e4e4;
  --signal: #8fc4b6;
}

/* ---------- after-hours: the only theme whose ground carries hue ---------- */
/* @theme after-hours */
:root[data-theme="after-hours"] {
  --ground: #1f2621;
  --ground-raise: #28302a;
  --rule: #39463d;
  --ink-mute: #c0b49c;
  --ink: #ece0cd;
  --signal: #8fc4b6;
}

/* ---------- floor ---------- */

html { font-size: 17px; -webkit-text-size-adjust: 100%; }

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

body {
  margin: 0;
  /* The host paints its own ground behind the page; a transparent body
     borrows it. Always explicit. */
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-inst);
  font-size: var(--step-0);
  line-height: 1.65;
}

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

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
