/* ===========================================================================
   The single source of colour for every page on the platform.
   ---------------------------------------------------------------------------
   Before this file, the token block was copy-pasted into all 19 pages: 68 names
   for about 20 concepts, and the copies had drifted. `--navy-deep` was #152536
   on eleven pages and #141F2C on seven. `--warn` was the DANGER red on
   adminauth.html and amber everywhere else, so one page rendered warnings in the
   colour every other page reserves for refusal. Nothing detected either, because
   nothing compared the copies. This file is the fix, and
   `test_theme_tokens.py` is what keeps it the only copy.

   THREE LAYERS, and the order matters:

     1. PRIMITIVES   the palette. Raw colour, no opinion about where it is used.
     2. SEMANTICS    what a thing IS: page, surface, body text, danger fill.
                     Pages reference these. Dark mode retunes ONLY this layer.
     3. ALIASES      the historical names (--gold, --ac2, --faint, --bg0 ...)
                     pointing at semantics. They exist so 19 files did not need
                     every var() rewritten to land this, and they cost nothing:
                     an alias resolves at the same time as the thing it names.

   THE ROLE SPLIT — the part that makes dark mode correct rather than merely
   dark. Twelve tokens were used as BOTH a text colour and a background:
   `--accent` was text 20 times and a fill 31 times; `--gold` 53 and 5. On a dark
   page those two roles want opposite treatments. Accent text on #151920 must get
   LIGHTER to stay readable; an accent-filled button with a white label must stay
   saturated or the label goes. One token cannot do both, so each is split into
   `-ink` (drawn ON the page) and `-fill` (drawn UNDER something else), and the
   old name keeps working as the ink alias. That is why dark mode here does not
   produce the usual pale-blue-on-pale-blue button.

   CONTRAST is not asserted in a comment. `test_theme_contrast.py` parses these
   values, computes WCAG 2.1 ratios for every pair the pages actually paint, and
   fails below 4.5:1 for body text and 3:1 for large text and UI edges — in BOTH
   themes. A hand-written claim about contrast is worth nothing the first time
   somebody retunes a swatch.
   =========================================================================== */

/* --- 1. PRIMITIVES: light ------------------------------------------------ */
:root {
  --p-paper: #efede7;
  --p-white: #fcfbf8;
  --p-bone: #f5f3ee;
  --p-shell: #eeebe3;
  --p-sand: #ede6d6;

  --p-ink: #15171c;
  --p-ink-2: #454b56;
  /* Darkened from #7c828d and #a7abb2. Both failed WCAG AA as body text on
     every surface the pages use them on (3.24:1 and 1.97:1), and had done since
     the palette was written — the light theme shipped that way. Found by
     computing the ratios rather than by looking at them. */
  --p-ink-3: #5b6068;
  --p-ink-4: #5c6169;

  --p-navy: #21384f;
  --p-navy-deep: #152536;
  --p-navy-lift: #25405b;

  /* `-fill` values are what a white label sits on; `-ink` values are what sits
     on paper. They are separate primitives because AA pulls them in opposite
     directions: a fill must stay dark enough for its label, an ink must be dark
     enough for the page, and #3a78c2 satisfied only the first (4.57:1 with
     white on it, 3.86:1 as text on paper). */
  --p-accent-fill: #3a78c2;
  --p-accent-ink: #2a5b96;
  --p-accent-2: #2f68ad;
  /* Brass was the worst of them: 2.99:1 as text on the shell surface, well
     under AA, and it is the brand's second colour — 76 uses. Deepened until it
     passes on every surface it is painted on. */
  --p-brass-fill: #7a5f34;
  --p-brass-ink: #6f5730;
  --p-brass-2: #c8ab73;
  /* Deepened from #7a5f34. It cleared AA against `--sand` itself, but
     security.html paints it on sand with a neutral wash over the top, and the
     composite is darker than either token — 4.47:1. No palette test can see
     that: it is a property of the stacking in the page, not of the pair. Found
     by auditing the rendered DOM, which is why that sweep exists alongside the
     token maths rather than instead of it. */
  --p-brass-deep: #6b5430;

  --p-ok: #3b6349;
  --p-warn-fill: #8a5518;
  --p-warn-ink: #8a5518;
  --p-no: #8b3a30;

  --p-mint: #7ce7c5;
  --p-mint-deep: #04231a;

  /* Neutral scrims, expressed against the light ink so a wash over paper and a
     wash over a card agree. */
  --p-scrim: 21, 23, 28;
  --p-lift: 255, 255, 255;
}

/* --- 2. SEMANTICS: light ------------------------------------------------- */
:root {
  /* page and surfaces */
  --paper: var(--p-paper);
  --surface: var(--p-white);
  --surface-2: var(--p-bone);
  --surface-3: var(--p-shell);
  --sand: var(--p-sand);

  /* body copy */
  --ink: var(--p-ink);
  --ink-2: var(--p-ink-2);
  --ink-3: var(--p-ink-3);
  --ink-4: var(--p-ink-4);

  /* the dark brand panel — a deliberately inverted band that stays dark in
     BOTH themes, which is why its own text tokens are separate */
  --panel-navy: var(--p-navy);
  --panel-navy-deep: var(--p-navy-deep);
  --panel-lift: var(--p-navy-lift);
  --panel-edge: rgba(var(--p-lift), 0.09);
  /* Navy used as TEXT, which is a different job from navy used as a panel.
     Splitting them is what stops headings disappearing into the band in dark. */
  --navy-ink: var(--p-navy);
  /* The label on ANY filled or inverted surface — accent button, navy band,
     brass chip, danger pill. Those fills stay dark in both themes, so this
     stays light in both; that is the whole reason it is one token and not a
     per-theme decision. */
  --on-fill: #ffffff;
  /* The mark drawn on the dark band. Identical in both themes on purpose: that
     band is dark in both, so the logo on it never needs to change. */
  --logo-on-dark: #ede6d6;
  --on-navy: #f2f6fa;
  --on-navy-2: #dce4ec;
  --on-navy-3: #c4d0dc;
  --on-navy-4: #8296ad;
  --on-navy-5: #7386a0;

  /* the mint band (marketing footer, 404) — also inverted in both themes */
  --mint-ink: var(--p-mint);
  --mint-bg: var(--p-mint-deep);
  --on-mint: var(--p-mint-deep);
  --mint-wash: rgba(15, 35, 29, 0.55);
  --mint-wash-2: rgba(15, 35, 29, 0.1);

  /* ACCENT — split by role. See the header. */
  --accent-ink: var(--p-accent-ink);
  --accent-fill: var(--p-accent-fill);
  --accent-fill-2: var(--p-accent-2);
  --on-accent: #ffffff;
  --accent-w1: rgba(58, 120, 194, 0.06);
  --accent-w2: rgba(58, 120, 194, 0.12);
  --accent-w3: rgba(58, 120, 194, 0.18);
  --accent-line: rgba(58, 120, 194, 0.3);
  --accent-line-2: rgba(58, 120, 194, 0.25);
  --accent-underline: rgba(58, 120, 194, 0.4);
  --accent-glow: rgba(58, 120, 194, 0.18);
  /* Opaque, not a 60% wash. A focus indicator is the one boundary WCAG is
     unambiguous about (1.4.11, 2.4.11): it must reach 3:1 against what is
     behind it, and the translucent version managed 2.27:1. Every other hairline
     in this file is decorative; this one is a control. */
  --accent-ring: var(--p-accent-fill);

  /* BRASS — split by role */
  --brass-ink: var(--p-brass-ink);
  --brass-ink-2: var(--p-brass-2);
  --brass-ink-deep: var(--p-brass-deep);
  --brass-fill: var(--p-brass-fill);
  --on-brass: #ffffff;
  --brass-w1: rgba(165, 130, 76, 0.12);
  --brass-w2: rgba(165, 130, 76, 0.14);
  --brass-line: rgba(165, 130, 76, 0.34);
  --brass-line-2: rgba(165, 130, 76, 0.4);

  /* STATUS — each split by role, because a status pill is a fill and a status
     sentence is text, and dark mode wants opposite things from them */
  --ok-ink: var(--p-ok);
  --ok-fill: var(--p-ok);
  --on-ok: #ffffff;
  --ok-w: rgba(59, 99, 73, 0.13);
  --ok-line: rgba(59, 99, 73, 0.3);

  --warn-ink: var(--p-warn-ink);
  --warn-fill: var(--p-warn-fill);
  --on-warn: #ffffff;
  --warn-w: rgba(175, 110, 34, 0.12);
  --warn-line: rgba(175, 110, 34, 0.32);

  --no-ink: var(--p-no);
  --no-fill: var(--p-no);
  --on-no: #ffffff;
  --no-w: rgba(139, 58, 48, 0.11);
  --no-line: rgba(139, 58, 48, 0.34);

  /* rules, edges, shadows */
  --edge: rgba(var(--p-scrim), 0.13);
  --edge-2: rgba(var(--p-scrim), 0.06);
  --rule: rgba(var(--p-scrim), 0.14);
  --rule-strong: rgba(var(--p-scrim), 0.3);
  --neutral-line: rgba(var(--p-scrim), 0.16);
  --neutral-bg: rgba(var(--p-scrim), 0.05);
  --shadow-1: rgba(var(--p-scrim), 0.22);
  --shadow-2: rgba(var(--p-scrim), 0.35);
  --shadow-3: rgba(var(--p-scrim), 0.5);
  --sheen: rgba(var(--p-lift), 0.02);

  /* sticky headers sit over content, so they carry the page colour at opacity */
  --scrim: rgba(239, 237, 231, 0.85);
  --scrim-2: rgba(245, 243, 238, 0.92);

  --grad: linear-gradient(105deg, var(--p-brass-2), var(--p-accent));

  /* not colour, but they were in the same duplicated block */
  --serif: "Amiri", "Scheherazade New", "Traditional Arabic", "Al Bayan", "Times New Roman", serif;
  --sans: "IBM Plex Sans Arabic", "Noto Kufi Arabic", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  --t: 220ms;
  --r: 14px;
  --rs: 11px;
  --gut: clamp(20px, 5vw, 84px);
}

/* --- 2b. DARK: the semantic layer only ----------------------------------- *
   Nothing below re-declares a primitive or a page rule. Dark mode is a
   different set of answers to the same questions, which is what keeps it one
   implementation instead of two.

   Surfaces LIFT as they come forward (paper darkest, cards lighter) — the
   inverse of the light theme, matching how depth reads on a dark ground.
   Pure black is avoided: #0e1116 keeps the warm-neutral identity and stops the
   halation that pure black + light text produces on OLED.                    */
:root[data-theme="dark"] {
  --paper: #0e1116;
  --surface: #151920;
  --surface-2: #1b2029;
  --surface-3: #222833;
  --sand: #2a2418;

  --ink: #e9ecf1;
  --ink-2: #b4bcc8;
  --ink-3: #9ba4b2;
  --ink-4: #959eac;

  /* The navy band was already the dark part of a light page. On a dark page it
     must separate from the background rather than merge with it, so it lifts
     rather than deepens — and its own text tokens barely move, because that
     band's foreground was always light. */
  --panel-navy: #1b2e42;
  --panel-navy-deep: #14212f;
  --panel-lift: #24384f;
  --panel-edge: rgba(var(--p-lift), 0.12);
  --navy-ink: #a8c4e0;
  --on-fill: #ffffff;
  --logo-on-dark: #ede6d6;
  --on-navy: #f2f6fa;
  --on-navy-2: #dce4ec;
  --on-navy-3: #c4d0dc;
  --on-navy-4: #9aabc0;
  --on-navy-5: #8b9cb2;

  --mint-ink: #7ce7c5;
  --mint-bg: #04231a;
  --mint-wash: rgba(15, 35, 29, 0.75);
  --mint-wash-2: rgba(124, 231, 197, 0.08);

  /* Ink lightens so it reads on the page; fill holds its saturation so a white
     label on a filled button survives. This is the whole point of the split. */
  --accent-ink: #8cbcf2;
  --accent-fill: #3a78c2;
  /* Hover DEEPENS rather than lightens. Lightening reads better on a dark page
     right up until you notice the white label on it drops to 3.66:1 — the hover
     state is where a filled control is most likely to be read, not least. */
  --accent-fill-2: #2f68ad;
  --on-accent: #ffffff;
  --accent-w1: rgba(140, 188, 242, 0.08);
  --accent-w2: rgba(140, 188, 242, 0.14);
  --accent-w3: rgba(140, 188, 242, 0.2);
  --accent-line: rgba(140, 188, 242, 0.35);
  --accent-line-2: rgba(140, 188, 242, 0.28);
  --accent-underline: rgba(140, 188, 242, 0.45);
  --accent-glow: rgba(58, 120, 194, 0.35);
  --accent-ring: #8cbcf2;

  --brass-ink: #d9b87f;
  --brass-ink-2: #e6cd9d;
  --brass-ink-deep: #c8ab73;
  --brass-fill: #8a6b3d;
  --on-brass: #ffffff;
  --brass-w1: rgba(217, 184, 127, 0.1);
  --brass-w2: rgba(217, 184, 127, 0.14);
  --brass-line: rgba(217, 184, 127, 0.32);
  --brass-line-2: rgba(217, 184, 127, 0.4);

  --ok-ink: #7fcb9e;
  --ok-fill: #2f5a42;
  --on-ok: #ffffff;
  --ok-w: rgba(127, 203, 158, 0.12);
  --ok-line: rgba(127, 203, 158, 0.32);

  --warn-ink: #e3a455;
  --warn-fill: #8a5518;
  --on-warn: #ffffff;
  --warn-w: rgba(227, 164, 85, 0.12);
  --warn-line: rgba(227, 164, 85, 0.32);

  --no-ink: #f0928a;
  --no-fill: #7a2e26;
  --on-no: #ffffff;
  --no-w: rgba(240, 146, 138, 0.12);
  --no-line: rgba(240, 146, 138, 0.34);

  /* Edges invert: on a dark ground a lighter line reads as a raised edge,
     while a darker one disappears. */
  --edge: rgba(var(--p-lift), 0.14);
  --edge-2: rgba(var(--p-lift), 0.07);
  --rule: rgba(var(--p-lift), 0.15);
  --rule-strong: rgba(var(--p-lift), 0.3);
  --neutral-line: rgba(var(--p-lift), 0.18);
  --neutral-bg: rgba(var(--p-lift), 0.05);
  /* Shadows stay black and get deeper — a "lighter" shadow is a glow, and a
     glow where a shadow belongs is what makes a dark UI look plastic. */
  --shadow-1: rgba(0, 0, 0, 0.5);
  --shadow-2: rgba(0, 0, 0, 0.62);
  --shadow-3: rgba(0, 0, 0, 0.75);
  --sheen: rgba(var(--p-lift), 0.03);

  --scrim: rgba(14, 17, 22, 0.88);
  --scrim-2: rgba(21, 25, 32, 0.94);

  --grad: linear-gradient(105deg, #d9b87f, #8cbcf2);
}

/* System preference, for the reader who has chosen nothing here.
   `:not([data-theme])` only — an explicit choice must beat the OS, or the
   toggle silently does nothing for anyone whose OS is set to dark. The
   bootstrap script normally stamps data-theme before first paint; this rule is
   what makes System work with JavaScript disabled, and it must therefore repeat
   the dark values rather than reference them. `test_theme_tokens.py` asserts
   the two dark blocks agree, so this cannot rot into a second palette. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --paper: #0e1116;
    --surface: #151920;
    --surface-2: #1b2029;
    --surface-3: #222833;
    --sand: #2a2418;

    --ink: #e9ecf1;
    --ink-2: #b4bcc8;
    --ink-3: #9ba4b2;
    --ink-4: #959eac;

    /* The navy band was already the dark part of a light page. On a dark page it
       must separate from the background rather than merge with it, so it lifts
       rather than deepens — and its own text tokens barely move, because that
       band's foreground was always light. */
    --panel-navy: #1b2e42;
    --panel-navy-deep: #14212f;
    --panel-lift: #24384f;
    --panel-edge: rgba(var(--p-lift), 0.12);
    --navy-ink: #a8c4e0;
    --on-fill: #ffffff;
    --logo-on-dark: #ede6d6;
    --on-navy: #f2f6fa;
    --on-navy-2: #dce4ec;
    --on-navy-3: #c4d0dc;
    --on-navy-4: #9aabc0;
    --on-navy-5: #8b9cb2;

    --mint-ink: #7ce7c5;
    --mint-bg: #04231a;
    --mint-wash: rgba(15, 35, 29, 0.75);
    --mint-wash-2: rgba(124, 231, 197, 0.08);

    /* Ink lightens so it reads on the page; fill holds its saturation so a white
       label on a filled button survives. This is the whole point of the split. */
    --accent-ink: #8cbcf2;
    --accent-fill: #3a78c2;
    /* Hover DEEPENS rather than lightens. Lightening reads better on a dark page
       right up until you notice the white label on it drops to 3.66:1 — the hover
       state is where a filled control is most likely to be read, not least. */
    --accent-fill-2: #2f68ad;
    --on-accent: #ffffff;
    --accent-w1: rgba(140, 188, 242, 0.08);
    --accent-w2: rgba(140, 188, 242, 0.14);
    --accent-w3: rgba(140, 188, 242, 0.2);
    --accent-line: rgba(140, 188, 242, 0.35);
    --accent-line-2: rgba(140, 188, 242, 0.28);
    --accent-underline: rgba(140, 188, 242, 0.45);
    --accent-glow: rgba(58, 120, 194, 0.35);
    --accent-ring: #8cbcf2;

    --brass-ink: #d9b87f;
    --brass-ink-2: #e6cd9d;
    --brass-ink-deep: #c8ab73;
    --brass-fill: #8a6b3d;
    --on-brass: #ffffff;
    --brass-w1: rgba(217, 184, 127, 0.1);
    --brass-w2: rgba(217, 184, 127, 0.14);
    --brass-line: rgba(217, 184, 127, 0.32);
    --brass-line-2: rgba(217, 184, 127, 0.4);

    --ok-ink: #7fcb9e;
    --ok-fill: #2f5a42;
    --on-ok: #ffffff;
    --ok-w: rgba(127, 203, 158, 0.12);
    --ok-line: rgba(127, 203, 158, 0.32);

    --warn-ink: #e3a455;
    --warn-fill: #8a5518;
    --on-warn: #ffffff;
    --warn-w: rgba(227, 164, 85, 0.12);
    --warn-line: rgba(227, 164, 85, 0.32);

    --no-ink: #f0928a;
    --no-fill: #7a2e26;
    --on-no: #ffffff;
    --no-w: rgba(240, 146, 138, 0.12);
    --no-line: rgba(240, 146, 138, 0.34);

    /* Edges invert: on a dark ground a lighter line reads as a raised edge,
       while a darker one disappears. */
    --edge: rgba(var(--p-lift), 0.14);
    --edge-2: rgba(var(--p-lift), 0.07);
    --rule: rgba(var(--p-lift), 0.15);
    --rule-strong: rgba(var(--p-lift), 0.3);
    --neutral-line: rgba(var(--p-lift), 0.18);
    --neutral-bg: rgba(var(--p-lift), 0.05);
    /* Shadows stay black and get deeper — a "lighter" shadow is a glow, and a
       glow where a shadow belongs is what makes a dark UI look plastic. */
    --shadow-1: rgba(0, 0, 0, 0.5);
    --shadow-2: rgba(0, 0, 0, 0.62);
    --shadow-3: rgba(0, 0, 0, 0.75);
    --sheen: rgba(var(--p-lift), 0.03);

    --scrim: rgba(14, 17, 22, 0.88);
    --scrim-2: rgba(21, 25, 32, 0.94);

    --grad: linear-gradient(105deg, #d9b87f, #8cbcf2);
  }
}

/* --- 3. ALIASES ---------------------------------------------------------- *
   The historical names, kept so this change did not have to rewrite every
   var() in 19 files. Each points at a semantic token, so dark mode reaches them
   without knowing they exist. Six families had accumulated three spellings of
   the same idea (--gold / --amber / --brass; --ac / --ac2 / --accent /
   --accent-deep), which is how the drift got in unnoticed.

   Dual-role names resolve to the INK role: a bare `--gold` in a rule the sweep
   could not attribute is far more likely to be text than a fill, and text that
   is slightly too bright is a smaller failure than a label that vanishes.     */
:root {
  --bg: var(--paper);
  --bg0: var(--paper);
  --bg1: var(--surface-2);
  --card: var(--surface);
  --panel: var(--surface);
  --panel2: var(--surface-2);
  --soft: var(--surface-2);
  --reg: var(--rule);

  --text: var(--ink);
  --dim: var(--ink-2);
  --faint: var(--ink-3);

  --navy: var(--navy-ink);
  --navy-deep: var(--panel-navy-deep);
  --toast: var(--panel-navy);

  --accent: var(--accent-ink);
  --ac: var(--accent-ink);
  --ac2: var(--accent-ink);
  --accent-deep: var(--accent-ink);
  --accent-2: var(--accent-fill-2);
  --wash: var(--accent-w1);
  --ac-dim: var(--accent-w1);
  --accent-dim: var(--accent-w1);
  --accent-wash: var(--accent-w2);
  --ac-line: var(--accent-line);

  --brass: var(--brass-ink);
  --brass-2: var(--brass-ink-2);
  --gold: var(--brass-ink);
  --amber: var(--brass-ink);
  --gold-dim: var(--brass-w1);
  --brass-dim: var(--brass-w1);
  --amber-wash: var(--brass-w1);
  --brass-wash: var(--brass-w2);
  --gold-line: var(--brass-line);

  --ok: var(--ok-ink);
  --warn: var(--warn-ink);
  --warn-wash: var(--warn-w);
  --warn-l: var(--warn-line);
  --no: var(--no-ink);
  --bad: var(--no-ink);
  --risk: var(--no-ink);
  --risk-dim: var(--no-w);
  --no-wash: var(--no-w);
  --risk-line: var(--no-line);
  --no-l: var(--no-line);

  --line: var(--edge-2);
  --line2: var(--edge);
}

/* --- The mark ------------------------------------------------------------ *
   The logo ships as inline SVG on all 19 pages with its fills written as
   presentation attributes: navy where it sits on paper, sand where it sits on
   the dark band. In dark mode the navy version would all but vanish into the
   page — a two-tone mark cannot be fixed with `currentColor`.

   Matched on the attribute VALUE rather than rewritten in the markup. A CSS
   declaration always beats a presentation attribute, so this themes every copy
   without editing nineteen files, light mode resolves to the identical colour
   it already had, and a page that adds another copy of the mark is themed the
   moment it renders. */
svg [fill="#21384F"],
svg [fill="#21384f"] {
  fill: var(--navy-ink);
}

svg [fill="#EDE6D6"],
svg [fill="#ede6d6"] {
  fill: var(--logo-on-dark);
}

svg [stroke^="rgba(21,23,28"] {
  stroke: var(--edge);
}

/* --- Theme transition ---------------------------------------------------- *
   Colour only, and never on first paint — the bootstrap script adds
   `data-theme-ready` one frame after stamping the theme, so switching animates
   but loading does not. Honours reduced-motion. */
:root[data-theme-ready] body,
:root[data-theme-ready] body * {
  transition:
    background-color var(--t) var(--ease),
    border-color var(--t) var(--ease),
    color var(--t) var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  :root[data-theme-ready] body,
  :root[data-theme-ready] body * {
    transition: none;
  }
}

/* The canvas. Every page sets `body{background:var(--paper)}` itself, but the
   root element does not, and the area outside the body box — overscroll on iOS,
   the strip under a short page, the gap beside a centred layout — is painted
   from the ROOT background, falling back to the browser's canvas colour when
   there is none. With `color-scheme: dark` that fallback is dark, so a light
   theme on a dark-OS machine could show a dark band around a light page.
   Declaring it here means the theme owns the canvas rather than inheriting
   whatever the browser felt like. */
html {
  background: var(--paper);
}

/* Native controls, scrollbars and form UI follow the theme instead of staying
   light — a dark page with a white select dropdown is the giveaway that a dark
   mode was painted on rather than built in. */
:root {
  color-scheme: light;
}
:root[data-theme="dark"] {
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    color-scheme: dark;
  }
}

/* --- The theme control --------------------------------------------------- *
   Injected into every page by `_strict_page`, so it cannot be present on
   eighteen pages and missing on the nineteenth. Fixed to the bottom-inline-
   start corner: RTL-aware via logical properties, and clear of the sticky
   headers every page already has at the top. */
.themepick {
  position: fixed;
  inset-block-end: 14px;
  inset-inline-start: 14px;
  z-index: 9998;
  display: flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: 0 6px 20px var(--shadow-1);
  font-family: var(--sans);
  opacity: 0.55;
  transition: opacity var(--t) var(--ease);
}

.themepick:hover,
.themepick:focus-within {
  opacity: 1;
}

.themepick button {
  appearance: none;
  border: 0;
  cursor: pointer;
  border-radius: 999px;
  padding: 5px 11px;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--ink-2);
  background: transparent;
  transition:
    background-color var(--t) var(--ease),
    color var(--t) var(--ease);
}

.themepick button:hover {
  background: var(--accent-w2);
  color: var(--ink);
}

/* :focus-visible only — a mouse click on a theme button should not leave a ring
   behind, but a keyboard user must never lose their place. */
.themepick button:focus-visible {
  outline: 2px solid var(--accent-ring);
  outline-offset: 2px;
}

.themepick button[aria-pressed="true"] {
  background: var(--accent-fill);
  color: var(--on-accent);
}

@media print {
  .themepick {
    display: none;
  }
}
