/* ============================================================================
   FAHO — THEMES
   ----------------------------------------------------------------------------
   THE single source of colour. Every colour the UI uses is a token defined
   here; every stylesheet references only `var(--token)` (deriving tints/glows from
   these via `color-mix()`), so it never hardcodes a colour.

   Two orthogonal axes drive the look:

     • MODE   — `data-mode="dark" | "light"` (the light/dark accent). Sets the
                base surfaces, ink, semantic signals and atmosphere. No/unknown
                mode = light, so a page is never colourless — though in practice
                both attributes are always rendered by the server (see themes.py).
     • THEME  — `data-theme="<palette>"`. The palette set is defined once by
                `PALETTES` in apps/accounts/themes.py;
                each id has a colour block below. A palette overrides only the
                SURFACES tint and the primary ACCENT on top of the mode base — so
                one theme renders differently depending on the mode. `olive` is the
                mode base itself, so it needs no override block; `khaki` is what an
                account with no stored preference gets (themes.py:DEFAULT_PALETTE).

   Both attributes live on <html> (`:root`). A palette therefore needs a block
   per mode: `:root[data-theme="<name>"][data-mode="<mode>"]`.

   Every selector is duplicated onto `.swatch[...]` so a preview tile in the
   theme picker resolves the very same tokens, scoped to itself — no separate
   preview palette to keep in sync.

   Adding a palette = copy the two override blocks below, retune the surfaces +
   accent, then add an (id, label) tuple to `PALETTES` in apps/accounts/themes.py.
   The picker on /settings/ renders its tile from that tuple and the JS is
   data-driven off the markup, so no template/JS change is needed.
   ========================================================================== */

/* ── THE TWO SPECK VARIANTS ────────────────────────────────────────────────
   The paper texture (see base/tokens.css `--paper`) comes in exactly two
   flavours, because a speck is only visible against the surface it sits on: one
   that lightens a dark surface and one that darkens a light one. Which of the two
   a surface takes is a per-mode — and, for the khaki drab chrome, a per-surface —
   decision made further down by assigning to `--grain`; the encoded noise itself
   is stated here, once each.

   It has to be spelled out twice at all only because the two differ inside a
   `url("data:…")` string (a colour matrix that keeps white vs one that keeps
   black, and the strength on the `<rect>`), and no `var()` can reach inside one.
   But the DARK flavour was being picked by two separate blocks, each carrying its
   own copy of the same 400 characters — so a retune of the noise would have had to
   find both or let the drab sidebar drift away from dark mode. Hence a name.

   Declared on bare `:root` rather than in a mode block: neither the mode blocks nor
   the drab-chrome selector is an ancestor of the other, so a shared value has to
   sit above both. `.swatch` previews inherit it from `:root` like everything else.

   Alpha-only noise: feTurbulence, then a colour matrix that throws its colour away
   and keeps the channel as opacity — so the strength is the one number on the rect.
   ──────────────────────────────────────────────────────────────────────────── */
:root {
  --grain-on-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .6 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23g)' opacity='.055'/%3E%3C/svg%3E");
  --grain-on-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .6 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23g)' opacity='.07'/%3E%3C/svg%3E");
}

/* ── MODE BASE: dark (olive palette) ──────────────────────────────────────── */
:root[data-mode="dark"],
.swatch[data-mode="dark"] {
  color-scheme: dark;

  /* Surfaces */
  --bg: #0c100d;
  --bg-2: #0f1411;
  --panel: #141a16;
  --panel-2: #1b2219;
  --panel-3: #222b21;
  --border: #2b342b;
  --border-bright: #3a463a;

  /* Ink */
  --text: #e9efe7;
  --text-strong: #ffffff;   /* max-contrast ink (hover states) */
  --on-accent: #ffffff;     /* ink over filled accent/danger surfaces */
  --muted: #8f9d8c;
  --muted-2: #6b766a;
  /* Down-chevron for form fields — one shared arrow for native <select>s and the
     picker comboboxes, so every dropdown-like control carries the identical mark.
     Colour is baked in (data URIs can't read vars), so it's keyed per mode here. */
  --field-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238f9d8c' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");

  /* Signal palette */
  --accent: #5e7d4f;        /* olive (primary action) */
  --accent-2: #84b06a;      /* bright olive (links) */
  --signal: #d7a13b;        /* amber — command/alert accent */
  --signal-2: #e9b94f;
  --danger: #d35c52;
  --warn: #c7993f;
  --ok: #6fae6b;
  --ok-glow: #8fd486;
  --info: #5b8aa6;
  --violet: #9a86c4;

  /* No `--st-<code>` for a person's «Стан»: it is a catalogue row now and carries its
     own hex, handed to the markup inline (see registry/models/person_status.py). The
     muster page's furniture reads the semantic tokens above — the readiness bar is
     `--ok`, the alert rule falls back to `--danger` behind the row's own `--st`. What
     is left below is the two location-kind chart series, a fixed enum the stylesheet
     may legitimately know. Semantic, so shared across palettes. */
  /* Location-kind chart series (registry/services/analytics/timeline.py) */
  --st-hospital: #d9634f;
  --st-training: #8f7ad0;

  /* Atmosphere & depth */
  /* Relief — the two neutral stops every gradient and every letterpress in the app
     derives from: `--lift` is light arriving from above, `--shade` the surface
     falling away below. Neutral (white/black alpha) rather than tinted, so one pair
     serves all ten palettes and a new one inherits the relief without declaring it.
     Composed once into `--surface` in base/tokens.css. */
  --lift: rgba(255, 255, 255, .02);
  --shade: rgba(0, 0, 0, .055);
  /* Letterpress under display type (base/relief.css) — type pressed INTO the sheet,
     not standing off it. Which is the order of the two stops: light arrives from
     above, so a glyph sunk into the surface is shadowed along its upper lip (`-1px`)
     and catches the light along its lower one (`+1px`). Reversing them — the shadow
     below — is a drop shadow, i.e. type floating above the sheet.
     Neither stop carries a blur radius, in any of the three blocks: a pressed edge is
     the surface meeting the glyph, so it is exactly as sharp as the glyph. Give it
     even 1px of blur and it stops being an edge and reads as a soft shadow behind the
     type — which was the first thing anybody noticed on the nav, where 13px uppercase
     ink sits on a mid-tone plate.
     All three blocks are tuned to read as TEXTURE, not as a second colour: the press
     should be visible on a heading when looked for and invisible while the heading is
     being read. At roughly twice these alphas it was an outline instead.
     Per surface, not per palette — see the khaki drab chrome further down. And
     retuning it for a scope is the ONLY way to give a screen a different letterpress:
     `text-shadow` is asserted to appear in exactly one file (see relief.css). */
  --letterpress: 0 -1px 0 rgba(0, 0, 0, .22), 0 1px 0 rgba(255, 255, 255, .02);
  /* Paper speckle — the flavour that lightens, since these surfaces are dark. */
  --grain: var(--grain-on-dark);
  --topbar-veil: rgba(0, 0, 0, .25);          /* darkening above the topbar */
  --backdrop: rgba(6, 9, 7, .66);             /* modal backdrop */
  --shadow: none;
  --logo-invert: 0;                           /* white logo reads as-is on dark */
}

/* ── MODE BASE: light (also the default olive palette, pre-JS) ────────────── */
:root,
:root[data-mode="light"],
.swatch[data-mode="light"] {
  color-scheme: light;

  /* Surfaces — warm olive-tinted paper. The bg sits noticeably below the
     near-white panels so cards lift off the page (depth the old, too-close
     values lacked); panel-3 is the darker "well" for chart tracks/inputs. */
  --bg: #e4e8da;
  --bg-2: #dde1d1;
  --panel: #fbfcf8;
  --panel-2: #f1f4ea;
  --panel-3: #e1e5d4;
  --border: #ccd1bd;
  --border-bright: #b3ba9e;

  /* Ink */
  --text: #232a1e;
  --text-strong: #12160d;
  --on-accent: #ffffff;
  /* Both muted tones are darker than the dark mode's are light: ink on paper needs
     more contrast than ink on ink, and `--muted-2` in particular carries the smallest
     text in the app (9.5–11px mono captions, table headers, chart axis labels), which
     is exactly where a tint that merely *looks* quiet stops being readable.
     They are tuned against **`--bg-2`**, not `--bg`: the sidebar is the one surface
     that uses it, and it is a step darker than the page — so the nav's own section
     labels are the worst case in the app for the smallest ink in it. And since a
     palette may retune `--bg-2` without touching these, the value clears 4.5:1 against
     the darkest `--bg-2` any light palette below declares (desert's), not just this
     block's own. */
  --muted: #4f5744;
  --muted-2: #58614b;
  --field-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%234f5744' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");

  /* Signal palette — darkened so it reads on light surfaces */
  --accent: #5a7849;
  --accent-2: #4d6b3c;
  /* The amber pair carries text as well as chrome — a rank eyebrow, a picker title, a
     tracking number — and an amber is the hue that loses contrast fastest against warm
     paper, so both sit deeper than the eye first wants. `--signal-2` is the darker of
     the two here, i.e. the emphatic one, matching what it means in dark mode. */
  --signal: #93670f;
  --signal-2: #87600d;
  --danger: #b8342a;
  --warn: #a9781b;
  --ok: #4f9a4b;
  --ok-glow: #3c8638;
  --info: #3c7191;
  --violet: #6c58a3;

  /* See the dark block above for why no person-status code appears here. `--ok` and
     `--warn` are also the hexes `registry/statuses.py` seeds «У строю» and «Поранення»
     with, since one mid-tone has to read on both themes and print legibly. `--danger`
     used to be «СЗЧ»'s #c23b30 as well and is now a shade deeper: it carries small text
     here (a delete button's label, a segment count) where that value came out at 4.3:1,
     while the catalogue's hex has to survive being *printed* and stays where it is. The
     two were only ever equal by coincidence — the seeder writes rows into a table an
     operator then owns, so nothing keeps them in step anyway. */
  /* Location-kind chart series (registry/services/analytics/timeline.py) */
  --st-hospital: #c24a38;
  --st-training: #6c58a3;

  /* Atmosphere & depth */
  /* See the dark block for what the four below are. The light values are not that
     block's mirrored: paper is nearly white already, so `--lift` mostly does its work
     on the sidebar and the darker wells while `--shade` is what actually draws the
     curvature; and the letterpress carries BOTH its stops, because the white lower
     one — the whole of the effect on a mid-tone surface — is invisible on a #fbfcf8
     card, and the dark upper lip is then the only thing left sinking the type — which
     is why it is also the stop kept faintest, being the one actually seen. */
  --lift: rgba(255, 255, 255, .18);
  --shade: rgba(45, 55, 30, .028);
  --letterpress: 0 -1px 0 rgba(35, 40, 25, .06), 0 1px 0 rgba(255, 255, 255, .55);
  --grain: var(--grain-on-light);
  --topbar-veil: rgba(40, 50, 30, .05);
  --backdrop: rgba(35, 42, 30, .42);
  --shadow: none;
  --logo-invert: 1;                           /* invert the white logo on light */
}

/* ============================================================================
   PALETTE OVERRIDES
   Each palette retunes surfaces + primary accent on top of the mode base. The
   `olive` palette is the base itself, so it needs no override block.
   ========================================================================== */

/* ── desert — warm sand / coyote ──────────────────────────────────────────── */
:root[data-theme="desert"][data-mode="dark"],
.swatch[data-theme="desert"][data-mode="dark"] {
  --bg: #14100b;
  --bg-2: #181310;
  --panel: #1e1811;
  --panel-2: #261e15;
  --panel-3: #2e241a;
  --border: #382c1f;
  --border-bright: #4c3b28;
  --accent: #b89355;        /* clean sand-khaki */
  --accent-2: #d6b56f;      /* bright sand */
}
:root[data-theme="desert"][data-mode="light"],
.swatch[data-theme="desert"][data-mode="light"] {
  --bg: #e9e0cd;
  --bg-2: #e2d8c0;
  --panel: #fcf9f0;
  --panel-2: #f3ecda;
  --panel-3: #e6dbc3;
  --border: #d3c6a8;
  --border-bright: #bcac88;
  --accent: #8a6d2c;
  --accent-2: #6f571f;
}

/* ── navy — cold steel blue ───────────────────────────────────────────────── */
:root[data-theme="navy"][data-mode="dark"],
.swatch[data-theme="navy"][data-mode="dark"] {
  --bg: #0a0e12;
  --bg-2: #0c1116;
  --panel: #10161d;
  --panel-2: #151d26;
  --panel-3: #1b2530;
  --border: #263341;
  --border-bright: #35485a;
  --accent: #3f7098;        /* steel blue */
  --accent-2: #61a0c8;
}
:root[data-theme="navy"][data-mode="light"],
.swatch[data-theme="navy"][data-mode="light"] {
  --bg: #dbe2ea;
  --bg-2: #d1dae4;
  --panel: #f7fafd;
  --panel-2: #eaf0f6;
  --panel-3: #d9e2ec;
  --border: #c0cbd8;
  --border-bright: #a2b1c2;
  --accent: #2f6389;
  --accent-2: #274f6e;
}

/* ── steel — neutral graphite / gunmetal ──────────────────────────────────── */
:root[data-theme="steel"][data-mode="dark"],
.swatch[data-theme="steel"][data-mode="dark"] {
  --bg: #0d0e0f;
  --bg-2: #101113;
  --panel: #16181a;
  --panel-2: #1d2023;
  --panel-3: #24282b;
  --border: #2f3438;
  --border-bright: #40474c;
  --accent: #6c7681;        /* gunmetal */
  --accent-2: #97a3ae;
}
:root[data-theme="steel"][data-mode="light"],
.swatch[data-theme="steel"][data-mode="light"] {
  --bg: #e2e4e7;
  --bg-2: #d8dbdf;
  --panel: #fafbfc;
  --panel-2: #eef0f2;
  --panel-3: #dee1e5;
  --border: #c8ccd1;
  --border-bright: #adb3ba;
  --accent: #59636d;
  --accent-2: #454d55;
}

/* ── forest — deep pine green (cooler & more saturated than olive) ─────────── */
:root[data-theme="forest"][data-mode="dark"],
.swatch[data-theme="forest"][data-mode="dark"] {
  --bg: #0a120c;
  --bg-2: #0c150e;
  --panel: #101c14;
  --panel-2: #152618;
  --panel-3: #1b2f1f;
  --border: #243a29;
  --border-bright: #345039;
  --accent: #3f8c56;        /* pine green */
  --accent-2: #63b97c;      /* bright leaf */
}
:root[data-theme="forest"][data-mode="light"],
.swatch[data-theme="forest"][data-mode="light"] {
  --bg: #dde8dd;
  --bg-2: #d4e2d4;
  --panel: #f6faf6;
  --panel-2: #e9f1e9;
  --panel-3: #d8e4d8;
  --border: #c3d4c3;
  --border-bright: #a5bca8;
  --accent: #2f7a48;
  --accent-2: #24623a;
}

/* ── blood — dark neutral + saturated crimson ─────────────────────────────── */
:root[data-theme="blood"][data-mode="dark"],
.swatch[data-theme="blood"][data-mode="dark"] {
  --bg: #100a0a;
  --bg-2: #140c0c;
  --panel: #1a1010;
  --panel-2: #241616;
  --panel-3: #2c1c1c;
  --border: #3a2626;
  --border-bright: #523535;
  --accent: #b73030;        /* crimson */
  --accent-2: #e0554a;      /* bright red */
}
:root[data-theme="blood"][data-mode="light"],
.swatch[data-theme="blood"][data-mode="light"] {
  --bg: #ece2e1;
  --bg-2: #e5d8d7;
  --panel: #fdf8f7;
  --panel-2: #f5eae9;
  --panel-3: #ecdcdb;
  --border: #d8c4c2;
  --border-bright: #c0a4a2;
  --accent: #b02a1e;
  --accent-2: #8f2016;
}

/* ── ember — near-black charcoal + warm amber ─────────────────────────────── */
:root[data-theme="ember"][data-mode="dark"],
.swatch[data-theme="ember"][data-mode="dark"] {
  --bg: #0c0c0c;
  --bg-2: #0f0f0e;
  --panel: #151513;
  --panel-2: #1d1c19;
  --panel-3: #24231f;
  --border: #302e29;
  --border-bright: #423f38;
  --accent: #d98324;        /* ember amber */
  --accent-2: #f0a63f;      /* bright amber */
}
:root[data-theme="ember"][data-mode="light"],
.swatch[data-theme="ember"][data-mode="light"] {
  --bg: #e8e6e1;
  --bg-2: #e0ddd7;
  --panel: #fbfaf7;
  --panel-2: #f0eee8;
  --panel-3: #e2dfd7;
  --border: #cecac0;
  --border-bright: #b3aea1;
  --accent: #b56a12;
  --accent-2: #965408;
}

/* ── copper — dark warm base + copper / bronze ────────────────────────────── */
:root[data-theme="copper"][data-mode="dark"],
.swatch[data-theme="copper"][data-mode="dark"] {
  --bg: #0f0c0a;
  --bg-2: #12100d;
  --panel: #191512;
  --panel-2: #221c18;
  --panel-3: #2a231e;
  --border: #382e27;
  --border-bright: #4b3e33;
  --accent: #b5703f;        /* copper */
  --accent-2: #d4915e;      /* bronze */
}
:root[data-theme="copper"][data-mode="light"],
.swatch[data-theme="copper"][data-mode="light"] {
  --bg: #ebe4de;
  --bg-2: #e3dbd3;
  --panel: #fcf9f5;
  --panel-2: #f2ebe4;
  --panel-3: #e5dbd0;
  --border: #d5c7ba;
  --border-bright: #bda797;
  --accent: #99552a;
  --accent-2: #7d4420;
}

/* ── cobalt — deep base + electric blue (bolder than navy) ─────────────────── */
:root[data-theme="cobalt"][data-mode="dark"],
.swatch[data-theme="cobalt"][data-mode="dark"] {
  --bg: #08090f;
  --bg-2: #0a0c13;
  --panel: #0f1118;
  --panel-2: #141824;
  --panel-3: #1a1f30;
  --border: #262d42;
  --border-bright: #35405c;
  --accent: #2f6bd6;        /* electric cobalt */
  --accent-2: #5a90f0;      /* bright cobalt */
}
:root[data-theme="cobalt"][data-mode="light"],
.swatch[data-theme="cobalt"][data-mode="light"] {
  --bg: #dde1ec;
  --bg-2: #d3d9e8;
  --panel: #f8f9fd;
  --panel-2: #eaeef7;
  --panel-3: #d8def0;
  --border: #bfc7dc;
  --border-bright: #9fabc8;
  --accent: #2357bd;
  --accent-2: #1c4699;
}

/* ── gold — gunmetal base + instrument brass ───────────────────────────────
   The warm accent on a COOL base, which is what separates it from `ember` (warm
   charcoal + orange amber) and `desert` (sand on sand): brass fittings on a grey
   receiver. Surfaces are the neutral greys, only the accent carries the hue. */
:root[data-theme="gold"][data-mode="dark"],
.swatch[data-theme="gold"][data-mode="dark"] {
  --bg: #0c0d0f;
  --bg-2: #0f1013;
  --panel: #14161a;
  --panel-2: #1b1e22;
  --panel-3: #22262b;
  --border: #2d3238;
  --border-bright: #3e444b;
  --accent: #a8862c;        /* brass */
  --accent-2: #dcbb5e;      /* polished brass */
}
:root[data-theme="gold"][data-mode="light"],
.swatch[data-theme="gold"][data-mode="light"] {
  --bg: #e4e6e4;
  --bg-2: #d9dcd9;
  --panel: #fbfcfb;
  --panel-2: #eef0ee;
  --panel-3: #e0e3e0;
  --border: #cacdc9;
  --border-bright: #adb1ac;
  --accent: #8a6a15;
  --accent-2: #6f5410;
}

/* ── teal — deep blue-green, the cool twin of olive ────────────────────────── */
:root[data-theme="teal"][data-mode="dark"],
.swatch[data-theme="teal"][data-mode="dark"] {
  --bg: #081210;
  --bg-2: #0a1614;
  --panel: #0e1c1a;
  --panel-2: #132521;
  --panel-3: #1a2f2a;
  --border: #234039;
  --border-bright: #31564d;
  --accent: #2f9184;        /* teal */
  --accent-2: #58c2b1;      /* bright aqua */
}
:root[data-theme="teal"][data-mode="light"],
.swatch[data-theme="teal"][data-mode="light"] {
  --bg: #dceae6;
  --bg-2: #cfe0dc;
  --panel: #f5fbf9;
  --panel-2: #e8f3f0;
  --panel-3: #d7e7e3;
  --border: #c1d6d1;
  --border-bright: #a1bdb6;
  --accent: #0e7a6d;
  --accent-2: #0a6055;
}

/* ── arctic — high-key cool: slate-blue rather than near-black, icy cyan ────
   The one dark palette whose surfaces are deliberately NOT nearly black. `navy`
   already owns «cold steel blue at the bottom of the range», so this one earns its
   place by sitting a full step lighter — a daylight cockpit rather than a night one —
   with a cyan accent instead of navy's steel blue. */
:root[data-theme="arctic"][data-mode="dark"],
.swatch[data-theme="arctic"][data-mode="dark"] {
  --bg: #121a1f;
  --bg-2: #151f25;
  --panel: #1b262d;
  --panel-2: #223038;
  --panel-3: #2a3a44;
  --border: #364a55;
  --border-bright: #47606e;
  --accent: #2e9dc4;        /* ice cyan */
  --accent-2: #7fd4ee;
}
:root[data-theme="arctic"][data-mode="light"],
.swatch[data-theme="arctic"][data-mode="light"] {
  --bg: #e6eef4;
  --bg-2: #d9e5ee;
  --panel: #ffffff;
  --panel-2: #eff5fa;
  --panel-3: #dfeaf2;
  --border: #c6d6e2;
  --border-bright: #a6bccd;
  --accent: #0f6f96;
  --accent-2: #0b5877;
}

/* ── plum — wine base + rose accent ───────────────────────────────────────── */
:root[data-theme="plum"][data-mode="dark"],
.swatch[data-theme="plum"][data-mode="dark"] {
  --bg: #100a0f;
  --bg-2: #140d13;
  --panel: #1b1119;
  --panel-2: #241722;
  --panel-3: #2d1d2a;
  --border: #3c2838;
  --border-bright: #52384c;
  --accent: #b8446f;        /* rose */
  --accent-2: #e07a9e;
}
:root[data-theme="plum"][data-mode="light"],
.swatch[data-theme="plum"][data-mode="light"] {
  --bg: #f0e3e8;
  --bg-2: #ead6dd;
  --panel: #fdf8fa;
  --panel-2: #f6eaef;
  --panel-3: #ecdae1;
  --border: #dbc4ce;
  --border-bright: #c2a4b1;
  --accent: #a32d5c;
  --accent-2: #8a2450;
}

/* ── violet — near-black aubergine + amethyst ──────────────────────────────── */
:root[data-theme="violet"][data-mode="dark"],
.swatch[data-theme="violet"][data-mode="dark"] {
  --bg: #0c0a12;
  --bg-2: #0f0c16;
  --panel: #14101d;
  --panel-2: #1b1626;
  --panel-3: #231d31;
  --border: #2f2743;
  --border-bright: #41365c;
  --accent: #7d5ad2;        /* amethyst */
  --accent-2: #a992f2;
}
:root[data-theme="violet"][data-mode="light"],
.swatch[data-theme="violet"][data-mode="light"] {
  --bg: #e4e0ee;
  --bg-2: #ddd7ea;
  --panel: #faf8fd;
  --panel-2: #efebf8;
  --panel-3: #ded8ef;
  --border: #cac2de;
  --border-bright: #aca1c6;
  --accent: #5a3fb0;
  --accent-2: #4a2f97;
}

/* ── contrast — maximum legibility, no atmosphere ──────────────────────────
   The one palette that is a *function* rather than a taste: a tablet in direct
   sunlight, a projector, an operator who cannot read the drab. So it is the only one
   that overrides more than surfaces + accent, and each override is the same decision
   made three ways:

     • ink goes to pure black / pure white, and both muted tints are pulled far past
       what the other palettes need — the smallest type in the app (9.5px mono
       captions, table headers, axis labels) is what this palette exists for;
     • `--field-arrow` follows the ink, since the glyph's colour is baked into the data
       URI and would otherwise stay the olive-tinted grey of the mode base — the one
       control mark in the app that cannot read a token;
     • **the paper texture and the letterpress are switched off** (`none`). Both are
       deliberately sub-threshold effects (see the mode blocks above), and a speckle
       plus a 1px shadow under type is exactly the contrast a bright screen eats
       first: they cost legibility here and buy nothing. `--paper` composes `--grain`
       into a background layer list, where `none` is a legal image, and
       `base/relief.css` reads `--letterpress` straight into `text-shadow`.

   Borders are stronger than any other palette's for the same reason: with no wash and
   no grain, the border is the only thing left separating two flat surfaces. */
:root[data-theme="contrast"][data-mode="dark"],
.swatch[data-theme="contrast"][data-mode="dark"] {
  --bg: #000000;
  --bg-2: #050505;
  --panel: #0d0d0d;
  --panel-2: #151515;
  --panel-3: #1e1e1e;
  --border: #3a3a3a;
  --border-bright: #5c5c5c;
  --text: #ffffff;
  --text-strong: #ffffff;
  --muted: #c9c9c9;
  --muted-2: #b0b0b0;
  --field-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23c9c9c9' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  --accent: #1a6ae8;
  --accent-2: #7bb2ff;
  --grain: none;
  --letterpress: none;
  --lift: rgba(255, 255, 255, .04);
  --shade: rgba(0, 0, 0, .12);
}
:root[data-theme="contrast"][data-mode="light"],
.swatch[data-theme="contrast"][data-mode="light"] {
  --bg: #eeeeee;
  --bg-2: #e4e4e4;
  --panel: #ffffff;
  --panel-2: #f7f7f7;
  --panel-3: #e9e9e9;
  --border: #a8a8a8;
  --border-bright: #7c7c7c;
  --text: #000000;
  --text-strong: #000000;
  --muted: #3d3d3d;
  --muted-2: #454545;
  --field-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%233d3d3d' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  --accent: #0b4fc8;
  --accent-2: #0940a2;
  --grain: none;
  --letterpress: none;
  --lift: rgba(255, 255, 255, .5);
  --shade: rgba(0, 0, 0, .04);
}

/* ── khaki — sage paper + drab command chrome, orange CTA ──────────────────
   The signature light look (см. mockups): a sage-paper page with cream cards,
   an orange primary action, and — unlike every other palette — a dark olive-drab
   sidebar + login card *even in light mode*. That chrome inversion is done by
   re-declaring the inherited surface/ink tokens SCOPED to those two containers
   (the two blocks after the surface blocks), so no rule needs changing and no
   other palette is touched. Colours here match the base light-mode signals
   (gold `--signal`, semantic status hues) — only surfaces + accent are retuned. */
:root[data-theme="khaki"][data-mode="dark"],
.swatch[data-theme="khaki"][data-mode="dark"] {
  --bg: #12130c;
  --bg-2: #16170e;
  --panel: #1b1c11;
  --panel-2: #222314;
  --panel-3: #2a2b19;
  --border: #33341f;
  --border-bright: #454629;
  --accent: #ec8f27;        /* signal orange (primary action) */
  --accent-2: #f0a24a;
}
:root[data-theme="khaki"][data-mode="light"],
.swatch[data-theme="khaki"][data-mode="light"] {
  /* Surfaces mostly match the base light palette; only the ones that differ are
     retuned here (bg/panel-2/border inherit the base values unchanged). */
  --bg-2: #dbe0cf;
  --panel: #fbfcf7;         /* cream cards */
  --panel-3: #e6ead9;
  --border-bright: #b6bb9c;
  /* Ink is dark OLIVE, not near-black — sampled straight from the mockup
     (headings/numbers ≈ #5f5e35, body a touch darker). This is what gives the
     theme its drab-on-paper character; the base light palette's near-black ink
     would read wrong here. */
  --text: #4c4b2a;
  /* `--text-strong` is the MAX-contrast ink (hover states), so it has to be darker
     than `--text` on paper — it used to be lighter (#565530), which quietly inverted
     the token everywhere a hover reached for it. */
  --text-strong: #33321a;
  --muted: #5c5a38;
  --muted-2: #656344;      /* against this palette's own, darker `--bg-2` — see the base block */
  /* The orange is deeper than the mockup's #ec8f27 for one reason: it is a *filled*
     surface — the primary button, the active page number, the active segment count —
     and `--on-accent` is white, which on the mockup value came out at 2.5:1. It is
     shared with `--danger` and with a «Стан» row's own hex, so the ink cannot go dark
     instead; the fill has to. Same hue, same family, enough depth for white to read.
     `--accent-2` is the paper *text* accent (every link, callsign and tracking number),
     so it clears 4.5:1 against `--bg` — the darkest surface a link is printed on. */
  --accent: #b45f08;        /* signal orange (primary action) */
  --accent-2: #9c5504;      /* darker orange — hover / links on paper */
}

/* Dark "command chrome": the sidebar + login card flip to olive drab with cream
   ink. Re-declaring the inherited tokens on these containers cascades to every
   descendant that reads them (nav, user block, headings, dividers) — no per-rule
   edits, and it only fires for khaki-light so the other palettes stay intact.

   The third selector is the preview tile's own miniature sidebar (`.swatch-nav`, see
   pages/settings.css). It is scoped to the *swatch's* attributes rather than to
   `:root`'s, because a tile previews a palette the page is not painted in — and it is
   here rather than left out because the drab chrome IS what khaki looks like: a tile
   showing a sage sidebar would be a preview of a theme the app does not have. */
:root[data-theme="khaki"][data-mode="light"] .sidebar,
:root[data-theme="khaki"][data-mode="light"] .login-card,
.swatch[data-theme="khaki"][data-mode="light"] .swatch-nav {
  /* The drab sits deeper than the mockup's #6a6a3e, and the reason is arithmetic
     rather than taste: the *lightest* of these four surfaces is what every cream ink
     on the sidebar has to clear, and at #797949 even pure white reached only 4.5:1 —
     so the whole nav (section labels, links, «система активна») was capped below
     legible no matter how the ink was retuned. Darkening the four surfaces is what
     buys the headroom back; the ink is then lifted to spend it. */
  --bg-2: #53532e;          /* drab surface (sidebar background) */
  --panel: #63633b;         /* hover / active-nav well */
  --panel-2: #5c5c37;
  --panel-3: #4f4f2f;
  --text: #f2f3e8;          /* cream ink */
  --text-strong: #ffffff;
  --muted: #dcddc9;
  --muted-2: #c9cab0;
  --border: #494928;
  --border-bright: #61613b;
  --accent-2: #e6deb4;      /* soft khaki-gold (role label, links) — not the orange CTA */
  /* The paper `--signal` is an amber tuned to read on cream; on the drab it is the
     nav's active marker and the brand ribbon, i.e. the same hue needing the opposite
     direction. This is the only token the chrome inverts for a graphic rather than
     for text — and it matters more than it used to, since that stripe is now the one
     thing marking the active row (see shell.css). */
  --signal: #e0ab3e;
  --logo-invert: 0;         /* keep the white logo white on the drab chrome */
  /* Relief follows the SURFACE, not the mode: these two containers are dark in a
     light theme, so they take the dark block's values. Without this the drab sidebar
     would carry the paper letterpress — a white shadow under cream ink, which reads
     as a blur — and its grain would be dark specks on an already dark olive, i.e.
     nothing. Every relief token has to be re-declared here for the same reason the
     surfaces and the ink above it are — and `--letterpress` is the dark block's pair
     verbatim, so retuning the press means editing the two identical lines, not three
     divergent ones. */
  --lift: rgba(255, 255, 255, .028);
  --shade: rgba(0, 0, 0, .05);
  --letterpress: 0 -1px 0 rgba(0, 0, 0, .22), 0 1px 0 rgba(255, 255, 255, .02);
  --grain: var(--grain-on-dark);
}

/* Login inputs sit on the drab card but stay light paper with dark ink. */
:root[data-theme="khaki"][data-mode="light"] .login-card input,
:root[data-theme="khaki"][data-mode="light"] .login-card textarea {
  background: #dce0cf; color: #23271a; border-color: #c8ccb4;
}

/* The mockup fills the logout button orange like the login CTA. Scoped to the
   `.btn-logout` semantic class (not a DOM-shape selector), so adding another form
   or button to the sidebar can't accidentally inherit it, and other themes stay put. */
:root[data-theme="khaki"][data-mode="light"] .btn-logout {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}

/* Every FILLED button inside the drab chrome needs its hover spelled out here, and the
   reason is a token that means two things in this one scope. The block above rebinds
   `--accent-2` to the khaki-gold *ink* the drab needs for links («Подати заявку» is the
   only thing reading it that way). But the shared `.btn.primary:hover` in buttons.css
   reads `--accent-2` as a *background* — so on the login card the orange CTA hovered to
   pale gold and kept its white ink, landing near 1.4:1: the label vanished under the
   cursor. `.btn-logout` already carried a literal for exactly this; the login CTA hit
   the same seam and was simply never hovered while it was being written.
   A literal is the fix rather than a third token: the chrome's two meanings for
   `--accent-2` are both legitimate, and the fill is the rarer one. */
:root[data-theme="khaki"][data-mode="light"] .btn-logout:hover,
:root[data-theme="khaki"][data-mode="light"] .sidebar .btn.primary:hover,
:root[data-theme="khaki"][data-mode="light"] .login-card .btn.primary:hover {
  background: #8b4b03; border-color: #8b4b03; color: var(--on-accent);
}
