/* ruum — the palette, defined once.
   =========================================================================

   Linked by the public landing page, the privacy statement, and the internal
   browser's base template. Before this file the same colours were written out
   four times and had already drifted apart (the landing's accent was #1257d6,
   the app's #0b53c8 -- close enough to look like a mistake rather than a
   choice). Nothing else may declare these tokens; tests/test_palette.py fails
   the build if a second definition appears.

   In production Caddy's catch-all `file_server` over /srv/web serves this, so
   no Caddyfile route is needed. Locally the dev proxy serves it off disk.

   ------------------------------------------------------------------- roles

   Three families, and a colour never crosses between them:

   `--accent` is chrome: "you can act on this" and nothing else. It is black,
   which is both the Swiss idiom and the reason the verdict ramp can own the
   colour. Buttons, focus rings, and the pressed state come from here.
   `--accent-wash` is its quiet form -- the tint behind a thing that is
   currently on: an applied filter chip, a facet count, the row in the peers
   table that is the car you are looking at. It is a neutral, not a hue, so it
   can sit next to a verdict colour without being read as one.

   `--brand` is identity: the mark, the hero rules, the large graphic moments.
   Signal orange, and only ever used as a fill or a rule at size -- never as
   small text, where it manages 3.01:1 against the page and fails AA. Text on
   a brand fill is `--brand-ink` (near-black, 5.96:1); white on orange is
   3.32:1 and is the one combination this palette forbids.

   `--cheap` / `--fair` / `--dear` are the verdict, and are reserved for it, so
   a green figure on any ruum surface always means the same thing. Green reads
   as "deal" to a buyer without being taught to, which is worth more here than
   the navy it replaces, and worth spending some of the margin below on.

   That navy existed for a reason, and the reason has not gone away: red-green
   is the common confusion line, this product's audience skews male, and
   deuteranopia runs around 8% there. Green against rust is exactly the pair
   that line eats. Simulating both dichromacies (Machado 2009, full severity)
   against `--dear`, the navy separated by dE 102 under protanopia; this green
   manages 38. That is a real loss and it is being taken deliberately.

   What makes it affordable is that hue was never carrying the verdict alone.
   The pill says "znatno ispod" in words, the figure carries its own sign, and
   -- the part that actually matters -- both ends of the ramp differ in
   *lightness*: 1.69:1 between `--cheap` and `--dear`, which is what a
   dichromat reads when hue is gone. The mid-tone green this palette used
   before last measured 1.08:1 there, near-identical in weight to the rust,
   and that collapse is what the navy was really fixing.

   That lightness gap is also the ceiling on how light this green may be, and
   it binds: a first attempt sat at L* 25.9 and read as black on a dim panel.
   The room between "legible as green when the screen is poor" and "still a
   different weight from the rust" is roughly L* 26-31, and this sits near the
   top of it at 31. Lighter than this is not available without either moving
   the rust or giving up the gap, and the gap is the whole argument for being
   allowed a green at all. tests/test_palette.py pins both ends.

   Every pairing here clears WCAG AA (4.5:1 for text, 3:1 for large graphics)
   in both schemes -- but one of them only just. `--brand` on `--bg` measures
   3.01:1 against a test that asserts 3.0, so nudging either the bone
   background or the orange by a single step will fail the build, and the
   failure will not obviously point here. Change those two together or not at
   all.                                                                       */

:root {
  color-scheme: light;

  /* surfaces — warm bone, not the blue-grey this replaced. The ground is
     paper and `--panel` is the white sheet laid on it; the login's form side
     and every card depend on those two being different. */
  --bg: #f4f4f0;
  --panel: #ffffff;
  --sunk: #eaeae4;
  --deep: #d2d2c8;

  /* text */
  --ink: #0a0a0a;
  --muted: #55554e;
  --faint: #68685f;

  /* lines. `--line` is incidental (row separators, card edges); `--rule` is
     structural and hard, the black bar that does the Swiss grid work.

     `--line` was #d8d8d0, which is 1.43:1 against the panel and 1.30:1 against
     the page -- a grid you cannot see. On a direction that is entirely made of
     grid, that was most of the washed-out feeling. It is only ever a border or
     a stroke, never text, so it is free to darken; it now sits at 1.76:1.
     `--deep` moved with it, but is capped: it backs the default pill, whose
     label is `--muted`, and that pairing has to stay above 4.5:1. It is at
     4.93:1, so there is room but not much. */
  --line: #c4c4b8;
  --rule: #0a0a0a;

  /* chrome */
  --accent: #0a0a0a;
  --accent-ink: #f4f4f0;
  --accent-wash: #c3c3b4;

  /* identity */
  --brand: #ff4d17;
  --brand-ink: #0a0a0a;
  --brand-wash: #ffe9e1;

  /* verdict */
  --cheap: #00503c;
  --cheap-wash: #e2ebe7;
  --fair: #55554e;
  --dear: #c03403;
  --dear-wash: #fbe8e0;

  /* the engine-risk note, which is a caution and not a price verdict */
  --warn-bg: #fbf3e0;
  --warn-ink: #7a5200;
  --warn-line: #e8d5a8;

  /* Flat by construction: square corners and no shadows are tokens rather
     than a hundred edited rules, so `.card`, `.btn`, and the inputs go flat
     without their layout being touched. */
  --r: 0px;
  --shadow: none;

  /* Site chrome height, including its 2px bottom rule. One number because
     three things have to agree on it: the public masthead, the signed-in
     topbar, and browse.html's rail, which is stuck underneath with `top:` and
     sized with `calc(100vh - ...)`. They disagreed by eight pixels. */
  --chrome-h: 52px;

  /* Two faces, declared in web/assets/fonts.css and served from our own
     origin. Both fall back to the system stack they replaced, so a page whose
     font files fail to load is plainer but never broken -- and the fallbacks
     are ordered to be metrically close, because `swap` means the fallback is
     what most readers see first.

     Archivo is doing real work here and is not decoration: the design leans on
     800-weight uppercase headlines at 112px, and system-ui at that size is a
     UI face being asked to be a display face. */
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo,
          Consolas, monospace;
  --sans: "Archivo", system-ui, -apple-system, "Segoe UI", Roboto, Inter,
          sans-serif;
}
