/* ==========================================================================
   tokens.css — the ONLY file a fork repaints.

   Palette, type, rhythm and the two per-site image slots live here. Nothing
   below this file knows a colour name or a font family: main.css and the
   markup speak in tokens only, so forking a site means writing new values
   here, never editing layout.

   HOW A TOKEN IS DECLARED — the trailing CSS comment on the token's own line
   is machine-read by palette.py:

       --ma-<name>: <opaque hex>;   [[ <role> · on: <surface>=<ratio> … ]]

   where [[ … ]] stands for an ordinary CSS comment. It is written that way
   here, and not literally, for a reason that cost this file its entire effect:
   CSS COMMENTS DO NOT NEST. A literal comment inside this header terminates
   the header at that point; everything below — the prose AND the whole :root
   block — is then parsed as one malformed rule and dropped. The stylesheet
   loaded with 200 OK and produced ZERO rules, so every var() below resolved to
   nothing, the pages fell back to Times New Roman on a white ground, and no
   automated check noticed because nothing parsed the CSS. There is now one
   that does (validate.py, output check `css_parses`).

   role      `surface` | `DECOR ONLY` | anything else, which means TEXT.
             Fail closed: a token added in a hurry with no role is checked as
             text against every declared surface. Exemption only by writing
             DECOR ONLY, and that exemption simultaneously FORBIDS the token
             from carrying text — an exemption that restricts nothing is a
             switch, not a rule.
   on:       every surface this text token is allowed to sit on, each with its
             CONTRAST RATIO COMPUTED BY THE WCAG FORMULA. The numbers are
             verified against the formula by the test suite; a comment that
             claims a pass where the computation fails is an error, not a note.
             This is Л27, and Moscow paid for it: tokens whose comment said
             "AA" measured 4.07 against a threshold of 4.5. The comment was
             written by someone looking at a screen and believing it.

   TRAP — alpha is refused, not ignored. A colour with an alpha channel has no
   contrast until you know what is behind it, so every token here is opaque.
   Translucency belongs to a scrim built from two opaque stops, never to a
   token that text is painted with.

   TRAP — a text token can pass AA on a light ground or on a dark one, never on
   both. Tokens for the dark inset therefore pin themselves with `on: deep=…`
   and are checked against THAT ground only. Leaving them unpinned would make
   the check impossible to satisfy, and an unusable check gets deleted.
   ========================================================================== */

:root {
  /* ---- surfaces: every ground the site paints, declared ---------------- */
  /* A silently excluded background is a surface on which nobody computed
     the contrast. If you add a background colour anywhere, add it here. */
  --ma-paper: #F4F1EA;      /* surface · page ground */
  --ma-card:  #FBF9F4;      /* surface · raised card, form panel */
  --ma-sand:  #EAE4D7;      /* surface · alternating band, table stripe */
  --ma-deep:  #14211F;      /* surface · dark inset (footer, quote band) */

  /* ---- text on the light grounds -------------------------------------- */
  --ma-ink:      #16191C;   /* text · on: paper=15.65 card=16.77 sand=13.93 */
  --ma-ink-soft: #55595C;   /* text · on: paper=6.27 card=6.72 sand=5.58 */
  --ma-accent:   #1F5F57;   /* text · on: paper=6.57 card=7.05 sand=5.85 */
  --ma-warm:     #7A5A2E;   /* text · on: paper=5.59 card=5.99 sand=4.98 */

  /* ---- text on the dark inset ----------------------------------------- */
  --ma-on-deep:      #F4F1EA;  /* text · on: deep=14.69 */
  --ma-on-deep-soft: #CFC9BB;  /* text · on: deep=10.04 */
  --ma-on-deep-lit:  #8FCBBB;  /* text · on: deep=9.02 */

  /* ---- decoration: hairlines, rules, motifs ---------------------------- */
  /* DECOR ONLY is not a note. palette.py reads main.css and fails the build
     if any of these ever ends up in a `color:` declaration. */
  --ma-brass: #B08A55;      /* DECOR ONLY · hairline, motif stroke (2.82 on paper) */
  --ma-rule:  #DAD3C4;      /* DECOR ONLY · rules and borders (1.32 on paper) */
  --ma-mist:  #E7E1D4;      /* DECOR ONLY · panel fill behind decoration (1.15 on paper) */

  /* ---- type ------------------------------------------------------------
     A strict grotesque reads expensive; a rounded one reads cheap (Л28).
     The base stack deliberately ships NO webfont:
       · a family shipped here would be inherited by every fork by default,
         and one family across N domains is a signature;
       · the family has to be chosen by DRAWING SAMPLES, and for an Arabic
         site by drawing them in both scripts — a font that falls back to a
         substitute in one of the two is chosen by name, not by eye;
       · Google Fonts silently drops a family when the request names an axis
         it does not have (opsz), and the page then looks whole on a fallback.
     A fork sets these three lines and adds its own <link> in parts/_layout.html. */
  --ma-font-text: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --ma-font-display: var(--ma-font-text);
  --ma-font-mono: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  /* Tight tracking is a property of a grotesque. On a serif the same value
     collides the serifs, so a serif fork raises this to 0 or above — the
     Moscow mistake was carrying a rule measured on a Didone into a grotesque. */
  --ma-track-display: -0.02em;
  --ma-track-label: 0.08em;

  --ma-step-0: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --ma-step-1: clamp(1.25rem, 1.16rem + 0.45vw, 1.5rem);
  --ma-step-2: clamp(1.6rem, 1.4rem + 1vw, 2.25rem);
  --ma-step-3: clamp(2.1rem, 1.6rem + 2.4vw, 3.5rem);
  --ma-step-4: clamp(2.6rem, 1.7rem + 4.2vw, 5rem);
  --ma-step-small: 0.9375rem;   /* the page's footnote size — the legal block
                                   is never allowed below this (see main.css) */

  /* ---- rhythm ---------------------------------------------------------- */
  --ma-gap: clamp(1rem, 0.8rem + 1vw, 1.75rem);
  --ma-section: clamp(3.5rem, 2.5rem + 4vw, 7rem);
  --ma-measure: 62ch;
  --ma-page: 76rem;
  --ma-radius: 2px;

  /* ---- per-site imagery ------------------------------------------------
     Both are `none` in the base stack ON PURPOSE: an <img> pointing at a file
     that does not exist yet renders a broken-image icon and the page still
     looks "complete" from every automated check. As a background that is
     absent, the block falls back to its motif and the typographic content
     underneath, which is a page that works. A fork sets the url. */
  --ma-hero-image: none;
  --ma-locmap-image: none;
  --ma-motif: url("/img/motif.svg?v=3ca96fb3");
}
