/* The design tokens, and nothing else.
 *
 * ⚠️ THIS FILE EXISTS SO THE PAGES CANNOT DISAGREE. It was inline in
 * index.html until dash.html needed the same palette, and a second copy of
 * ninety lines of colour is a drift waiting to happen - the map gets a new
 * accent, the dashboard keeps the old one, and nothing at runtime says so.
 * One definition, one <link> per page.
 */
/* 🔑 NEUTRAL GROUND, TWO FAMILIES, ONE ACCENT.
 *
 * 2026-11-05, replacing the warm-paper-and-monospace theme of 2026-10-22.
 * Three things changed and each has a reason that is not taste:
 *
 * 1. THE TYPE IS SPLIT. Mono everywhere was right when this page was a
 *    table of readings. It is now mostly PROSE - a sentence under every
 *    tile saying what the number means and what not to read into it - and
 *    monospace prose is 15 % wider, loses its word shapes and reads slower.
 *    So: --ui for words, --mono for figures. The split is what makes the
 *    page feel calmer; nothing else here comes close.
 * 2. THE GROUND IS NEUTRAL. The warm cream was distinctive and it was also
 *    doing the opposite of its job: a tinted ground pushes every tinted
 *    datum towards it, and this page is now mostly data.
 * 3. ONE ACCENT. Terracotta identity plus indigo interaction plus blue and
 *    orange series was four hues competing for "look here". ⚠️ --brand and
 *    --acc are now the SAME value on purpose - they stay separate tokens so
 *    re-splitting them is one line, and because status keeps its own four.
 *
 * ⚠️ TAILWIND ITSELF IS NOT AN OPTION, and the reason is the CSP rather
 * than taste: nginx sends `script-src 'self'`, and the Tailwind CDN is a
 * SCRIPT - a runtime compiler. The built route needs Node, a CSS artifact
 * in the deploy and a staleness check: a toolchain and a new silent-failure
 * mode, for styling.
 *
 * ⚠️ AND NO WEBFONT. `default-src 'self'` allows a self-hosted woff2 but
 * not Google Fonts, and a vendored face is ~100 KB of binary for something
 * the machine already has. --ui resolves to SF Pro on the Mac and the
 * iPhone, Segoe on Windows, Roboto on Android: the face the rest of the
 * device is already using, with nothing to load and no FOUT.
 *
 * 🔑 EVERY COLOUR BELOW WAS MEASURED, NOT CHOSEN. WCAG contrast against
 * its own surface, and the series pair's separation under all three
 * dichromacies. The numbers are in the comments.
 */
:root{
  /* ---- the ground ----------------------------------------------------
     A cool near-white page with white cards one step above it. The step
     is small on purpose (1.06:1): it separates card from page without
     drawing a line, which is how most of the hairlines came off. */
  --bg:#f7f8fa;
  --card:#ffffff;
  --line:#e4e7ec;      /* hairline, 1.24:1 on the card - visible, quiet */
  --line2:#cdd3dc;     /* a hover edge, 1.51:1                          */
  --fg:#0f1626;        /* 18.1:1 on the card                            */
  --mut:#5a6472;       /* 6.00:1 - a caption is text, not decoration    */

  /* ---- the accent ----------------------------------------------------
     🔑 ONE HUE FOR IDENTITY AND INTERACTION BOTH. The wordmark, the
     current view, a link, a focus ring and the primary button are the
     same indigo; everything else on the page is neutral or a status.
     ⚠️ It is also further from --warn than the old terracotta was, so
     "this is the view you are in" and "this reading needs acting on" can
     no longer be confused with each other. */
  --acc:#4f46e5;       /* indigo-600, 6.29:1 on the card */
  --acc-soft:#eef0fe;
  --brand:#4f46e5;     /* the same, deliberately - see the header note */
  --brand-soft:#eef0fe;
  --ring:#4f46e566;

  /* ---- status, reserved ----------------------------------------------
     ⚠️ NEVER a series colour and never a tab's identity: these three mean
     a STATE, and a palette that spends red on "the third line" has
     nothing left to say "this battery is flat". */
  --ok:#067647;        /* 5.69:1 */
  --warn:#b54708;      /* 5.43:1 */
  --bad:#d92d20;       /* 4.83:1 */

  /* ---- type -----------------------------------------------------------
     🔑 TWO FAMILIES WITH ONE JOB EACH. --ui for anything made of words;
     --mono for anything made of digits, plus identifiers like `batt_pct`
     that are code and read as code. ⚠️ The split only works if it is
     kept: a number in --ui loses tabular alignment, and a sentence in
     --mono is the thing this theme exists to stop. */
  --ui:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,
       "Helvetica Neue",Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,
         "DejaVu Sans Mono",monospace;

  /* A scale with real steps in it. The old one ran 11.5/12/13/14/25, so a
     heading outranked body text by half a point and hierarchy was left to
     colour alone.
     ⚠️ STEPPED UP ONCE on first use, 2026-11-05: 13.5px of a UI face
     reads smaller than 13.5px of a mono one, because mono carries more
     ink per character and sets wider. The split made the page calmer and
     a touch too quiet with it. Everything here is a token, so this is the
     one line to turn if it is still off. */
  --fs-xs:11.5px; --fs-sm:13px; --fs:14.5px;
  --fs-md:16px; --fs-lg:21px; --fs-xl:30px;

  /* spacing: the 0.25rem step */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px;
  /* radius. Softer than the mono theme's crisp corners, which belonged to
     the paper-and-typewriter idea rather than to this one. */
  --r-sm:4px; --r:6px; --r-md:8px; --r-lg:12px; --r-xl:16px;
  /* elevation. Neutral now: the warm shadow was for a cream ground. */
  --sh-sm:0 1px 2px 0 #0f162608;
  --sh:0 1px 3px 0 #0f162614,0 1px 2px -1px #0f162610;
  --sh-lg:0 12px 24px -6px #0f16261f,0 4px 8px -4px #0f162614;
  /* motion */
  --t:150ms cubic-bezier(.4,0,.2,1);
  /* 🔑 ONE HEIGHT FOR EVERY INLINE CONTROL. See the select rule in
     dash.css for why matching padding is not enough. */
  --ctl-h:32px;

  /* ---- chart series -------------------------------------------------
     🔑 VALIDATED, NOT CHOSEN - contrast against this theme's own card and
     separation under all three dichromacies:

       light  #2563eb + #ea580c   on #ffffff 5.17 / 3.56
       dark   #3b82f6 + #ea580c   on #151a22 4.75 / 4.91
              dE normal 36.1  protan 30.6  deutan 33.4  tritan 40.7

     ⚠️ THE PAIR SURVIVED THE REPALETTE UNCHANGED, and that is a measured
     claim rather than laziness: dE is colour against colour, so a new
     SURFACE cannot move it - only the contrasts above needed recomputing,
     and on the new dark card both improved.

     ⚠️ Two slots, in a fixed order, and a third series is NOT a third hue
     invented here - it is a second chart. */
  --c1:#2563eb; --c2:#ea580c;
  /* Sequential, one hue light->dark: how well a cell's position is known. */
  --q1:#dbeafe; --q2:#93c5fd; --q3:#60a5fa; --q4:#3b82f6; --q5:#1d4ed8;
  --chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%235a6472' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 7.5 5 5 5-5'/%3E%3C/svg%3E");
  /* ⚠️ THE BASEMAP IS BARELY TOUCHED NOW. It was sepia-warmed to sit in a
     cream page; against a neutral one the standard OSM sheet already
     belongs, and every filter costs legibility on a map people navigate
     by. A whisker of desaturation, no hue shift. */
  --tile-filter:saturate(.88) contrast(.97);
  --attrib-bg:#f7f8fac0;

  /* ⚠️ NOT COSMETIC: THE NATIVE WIDGETS READ THIS. A date input's calendar
     panel, the scrollbars and a select's open list are drawn by the
     browser, not by anything above - they take their colours from
     `color-scheme` alone, so a dark page without this line drops a
     white calendar on top of itself. It is declared in all three blocks
     for the same reason the rest of the palette is. */
  color-scheme:light;
}
/* 🔑 THREE STATES, TWO SELECTORS.
   An absent `data-theme` means FOLLOW THE SYSTEM - the default, and what
   the media query is for. ⚠️ :not([data-theme="light"]) is what lets
   somebody on a dark Mac force light: without it the media query still
   wins and the toggle looks broken in exactly one direction, which is the
   hardest kind of broken to notice while testing on a light machine.
   The second selector is the mirror - dark forced on a light system.

   ⚠️ THE DARK SET IS SELECTED, NOT FLIPPED. Inverting a light palette
   gives muddy mid-greys and an accent that glows; every step below was
   re-measured against the dark card, and the accent is a lighter indigo
   because the 600 step is unreadable on ink. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --bg:#0c0f14;
    --card:#151a22;
    --line:#252c37;    /* 1.24:1 on the card */
    --line2:#37404d;   /* 1.67:1 */
    --fg:#e8edf4;      /* 14.8:1 */
    --mut:#98a2b3;     /* 6.78:1 */
    --acc:#8b96ff;     /* indigo lifted off the ink, 6.57:1 */
    --acc-soft:#1c2033;
    --brand:#8b96ff;
    --brand-soft:#1c2033;
    --ring:#8b96ff80;
    --ok:#3ddc97;      /* 9.88:1 */
    --warn:#fdb022;    /* 9.49:1 */
    --bad:#fb7185;     /* 6.49:1 */
    --sh-sm:0 1px 2px 0 #00000066;
    --sh:0 1px 3px 0 #00000080,0 1px 2px -1px #00000080;
    --sh-lg:0 12px 24px -6px #0000008c,0 4px 8px -4px #00000080;
    --c1:#3b82f6; --c2:#ea580c;
    /* ⚠️ The ramp RUNS THE OTHER WAY on a dark surface - a near-white step
       is the loud end here, where on white it was the quiet one. */
    --q1:#1e3a8a; --q2:#1d4ed8; --q3:#2563eb; --q4:#3b82f6; --q5:#93c5fd;
    --chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%2398a2b3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 7.5 5 5 5-5'/%3E%3C/svg%3E");
    --tile-filter:invert(1) hue-rotate(180deg) brightness(.93)
      contrast(.88) saturate(.78);
    --attrib-bg:#151a22c0;
    color-scheme:dark;
  }
}
:root[data-theme="dark"]{
    --bg:#0c0f14;
    --card:#151a22;
    --line:#252c37;
    --line2:#37404d;
    --fg:#e8edf4;
    --mut:#98a2b3;
    --acc:#8b96ff;
    --acc-soft:#1c2033;
    --brand:#8b96ff;
    --brand-soft:#1c2033;
    --ring:#8b96ff80;
    --ok:#3ddc97;
    --warn:#fdb022;
    --bad:#fb7185;
    --sh-sm:0 1px 2px 0 #00000066;
    --sh:0 1px 3px 0 #00000080,0 1px 2px -1px #00000080;
    --sh-lg:0 12px 24px -6px #0000008c,0 4px 8px -4px #00000080;
    --c1:#3b82f6; --c2:#ea580c;
    --q1:#1e3a8a; --q2:#1d4ed8; --q3:#2563eb; --q4:#3b82f6; --q5:#93c5fd;
    --chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%2398a2b3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 7.5 5 5 5-5'/%3E%3C/svg%3E");
    --tile-filter:invert(1) hue-rotate(180deg) brightness(.93)
      contrast(.88) saturate(.78);
    --attrib-bg:#151a22c0;
    color-scheme:dark;
}
