/* Threads in Artha Frost — the sheet
   ==================================
   MPF, 28 September 2026: "From here on out artha frost is our main UI". The
   same evening, "change the login page to frost" (the sign-in slice, first),
   then "next lets do the menu and the homepage". This file is the whole of
   docs/threads-frost-look-spec.md, built stage by stage: 1 the tokens and the
   floor on every page, 2 the chrome, 6 the dashboards and Home; of stage 5,
   the toasts, tooltips, status tags, switches and (§21, 29 Sep 2026) the panel
   browsers; and (§25–§32, 29 Sep 2026) the rest of stage 5 — the dialog, the
   fields, the list and the calendar, status messages and the loader, the
   arrange rows, staging tables, the Maps boards and Cuts wizard, and the
   Dispatch Notes cards. Tables and filter boards (stages 3–4) are the page
   sheet's, threads-frost-pages.css, page by page.

   WHY A COPY AND NOT frost.css ITSELF (spec §How). Frost's look rules are all
   written on Stark's `.stark-*` classes, which Threads never draws. So this
   sheet copies Frost's tokens verbatim and re-states each look on the matching
   Threads class, naming the kit section it came from — Threads' markup, ids,
   names and scripts are untouched (spec §1).

   THE SCOPES. The colour blocks keep Frost's own `:root` and
   `:root[data-frost-theme=…]` selectors: they only set `--frost-*` and
   `--stark-*` names on <html>, which the server writes the two theme words
   onto (getFrostThemeAttributes(), init.php). Every look rule sits under
   `body.threads-koel`, Koel's scope, so it ties Koel and wins by load order —
   this sheet loads straight after koel-ui/koel.css in all four places that
   load it — and never needs `!important`.

   NO GLASS ON A PANEL'S ANCESTORS (spec §1). Nothing here sets
   `backdrop-filter`, `filter` or `transform` on a box that could hold a
   `position: fixed` panel; glass goes on a `::before` underlay, as the kit's
   menu-bar mockup draws its strips. No `display`, `position`, `overflow`,
   animation or transition timing on anything a controller owns.
   tests/frost-look-contract-test.php holds all of this (Threads rule 155).

   Source kit: UI library/Artha Frost/frost.css (over Artha Stark/stark.css)
   and Artha Frost/menu-bar.css. */


/* ============================================================ 1. the themes */
/* FROST §1, SEVEN THEMES × TWO MODES, copied value for value. MPF picked "All
   ten" (spec Open 1, 28 September 2026) — the first five, dark and daylight;
   Camel and Chocolate joined on 1 Oct 2026 (docs/camel-chocolate-themes-spec.md).
   Each reader picks (stage 7); every theme is here so a pick is a word on
   <html> and nothing else. */
:root {
  /* --- Original, dark: warm graphite, amber gold (Sender v4a, unchanged) */
  --frost-floor: #211f1c;
  --frost-floor-tint: #48453d;
  --frost-card-high: #32302b;
  --frost-card-low: #282622;
  --frost-card-edge: #0e0d0b;
  --frost-card-lip: #ffffff14;
  --frost-sink: #1a1815;
  --frost-well: #1d1b17;
  --frost-deep: #141210;
  --frost-ink: #ece7dd;
  /* #c2bbad in Sender; one step lighter here, because in Stark muted is the
     colour of every explaining paragraph and Frost holds reading text to 7:1
     (6.91 → 7.13 on the card's lighter end). */
  --frost-muted: #c5beb0;
  --frost-legend: #bab2a4;
  --frost-stone: #a29a8d;
  --frost-engrave: #100f0c;
  --frost-line: #5b5750;
  --frost-line-lit: #8b8376;
  /* THE FIELD'S LINE (run 2, 27 September 2026). Sender's `line` is a hairline
     for its own chrome; a field's line has to say "type here" on its own, so
     Frost gives it two measured tones of its own: rest at 3:1 and hover at
     4.5:1 against the lightest and darkest surface a field stands on (the
     card's two ends, the field set's well, the sink). Mixed from the ink into
     the card; the numbers are in SPEC §4. */
  --frost-field-line: #7c7973;
  --frost-field-line-lit: #9b9790;
  --frost-key: #48453d;
  --frost-accent: #f0b429;
  --frost-accent-rgb: 240 180 41;
  --frost-danger: #ff8f7a;
  /* the glass's own light, as r g b so each use carries its own alpha */
  --frost-glass-rgb: 255 248 235;
  --frost-sheen-rgb: 255 250 240;
  --frost-rim-rgb: 255 255 255;
}

:root[data-frost-theme="charcoal"] {
  /* cool neutral carbon; the gold brushed a step paler */
  --frost-floor: #1d1f21;
  --frost-floor-tint: #42464b;
  --frost-card-high: #2f3134;
  --frost-card-low: #25272a;
  --frost-card-edge: #0c0d0e;
  --frost-card-lip: #f2f6ff14;
  --frost-sink: #18191c;
  --frost-well: #1a1b1e;
  --frost-deep: #121315;
  --frost-ink: #e9ebee;
  --frost-muted: #bec2c8;
  --frost-legend: #b5bac0;
  --frost-stone: #a0a6ad;
  --frost-engrave: #0b0c0e;
  --frost-line: #555a60;
  --frost-line-lit: #858b93;
  --frost-field-line: #787a7d;
  --frost-field-line-lit: #96989b;
  --frost-key: #42464b;
  --frost-accent: #f5c552;
  --frost-accent-rgb: 245 197 82;
  --frost-danger: #ff8f7a;
  --frost-glass-rgb: 238 244 255;
  --frost-sheen-rgb: 242 247 255;
  --frost-rim-rgb: 245 249 255;
}

:root[data-frost-theme="purple"] {
  /* smoked violet; champagne gold */
  --frost-floor: #1b1726;
  --frost-floor-tint: #403653;
  --frost-card-high: #2e2640;
  --frost-card-low: #231d33;
  --frost-card-edge: #0c0a12;
  --frost-card-lip: #f4ecff14;
  --frost-sink: #19151f;
  --frost-well: #1a1524;
  --frost-deep: #120f19;
  --frost-ink: #ece8f3;
  --frost-muted: #c3bcd0;
  --frost-legend: #bbb3c9;
  --frost-stone: #a69fb5;
  --frost-engrave: #0d0b14;
  --frost-line: #58516a;
  --frost-line-lit: #8a839b;
  --frost-field-line: #767083;
  --frost-field-line-lit: #938e9f;
  --frost-key: #403653;
  --frost-accent: #e9c678;
  --frost-accent-rgb: 233 198 120;
  --frost-danger: #ff8f7a;
  --frost-glass-rgb: 244 238 255;
  --frost-sheen-rgb: 246 242 255;
  --frost-rim-rgb: 250 246 255;
}

:root[data-frost-theme="burgundy"] {
  /* wine-dark; rose gold, and a truer red so delete never reads as the accent */
  --frost-floor: #21161b;
  --frost-floor-tint: #4d303c;
  --frost-card-high: #35222b;
  --frost-card-low: #291a21;
  --frost-card-edge: #0f090c;
  --frost-card-lip: #ffecf214;
  --frost-sink: #1d1317;
  --frost-well: #1f141a;
  --frost-deep: #150d11;
  --frost-ink: #f1e7ea;
  --frost-muted: #cbb9bf;
  --frost-legend: #c3b0b7;
  --frost-stone: #ad9aa1;
  --frost-engrave: #12090d;
  --frost-line: #62515a;
  --frost-line-lit: #95818a;
  --frost-field-line: #7c6d73;
  --frost-field-line-lit: #988b90;
  --frost-key: #4d303c;
  --frost-accent: #f2b39f;
  --frost-accent-rgb: 242 179 159;
  --frost-danger: #ff6f6a;
  --frost-glass-rgb: 255 238 243;
  --frost-sheen-rgb: 255 243 246;
  --frost-rim-rgb: 255 247 250;
}

:root[data-frost-theme="navy"] {
  /* ink-navy; brass, the buttons on a navy blazer */
  --frost-floor: #10151f;
  --frost-floor-tint: #303a4b;
  --frost-card-high: #1f2939;
  --frost-card-low: #161e2b;
  --frost-card-edge: #06090e;
  --frost-card-lip: #eaf2ff14;
  --frost-sink: #121925;
  --frost-well: #131a27;
  --frost-deep: #0d131c;
  --frost-ink: #e8ecf2;
  --frost-muted: #bcc4d0;
  --frost-legend: #b3bcc9;
  --frost-stone: #9ca6b5;
  --frost-engrave: #070b12;
  --frost-line: #4a566a;
  --frost-line-lit: #7a879b;
  --frost-field-line: #6b727d;
  --frost-field-line-lit: #8a909a;
  --frost-key: #2f3d55;
  --frost-accent: #dcb866;
  --frost-accent-rgb: 220 184 102;
  --frost-danger: #ff8f7a;
  --frost-glass-rgb: 236 243 255;
  --frost-sheen-rgb: 240 246 255;
  --frost-rim-rgb: 244 248 255;
}

:root[data-frost-theme="camel"] {
  /* CAMEL (MPF, 30 September 2026: "a camel / khakhi colour which is lighter
     than the default brown"). Its colour is a cloth's: he sent a photograph of
     camel chinos the same evening, sampled at #c4875e (hue 24, a warm tan
     with orange in it, not the yellow of khaki). Dark is that hue taken as
     deep as a dark card needs — and no deeper: #5c4433 is the lightest card
     on which muted still holds 7:1 (7.53; ink 8.55), so every tier of type is
     lifted with it. The first version (#463b2a, hue 37) read as brown with a
     camel tint — his word — and is kept in the backups as camel-v1-brown.
     Peach gold for the accent. Not from Sender: Frost's own. */
  --frost-floor: #3e2d21;
  --frost-floor-tint: #7f5a40;
  --frost-card-high: #5c4433;
  --frost-card-low: #4f3a2b;
  --frost-card-edge: #1d140c;
  --frost-card-lip: #fff0e014;
  --frost-sink: #33251a;
  --frost-well: #37281d;
  --frost-deep: #291d14;
  --frost-ink: #fef8f1;
  --frost-muted: #f4e9dc;
  --frost-legend: #e1d3c1;
  --frost-stone: #d2c2ad;
  --frost-engrave: #1f150d;
  --frost-line: #82664f;
  --frost-line-lit: #bba389;
  --frost-field-line: #ad9d8b;
  --frost-field-line-lit: #cdbfae;
  --frost-key: #7f5a40;
  --frost-accent: #fcd59d;
  --frost-accent-rgb: 252 213 157;
  --frost-danger: #ffc0b0;
  --frost-glass-rgb: 255 240 224;
  --frost-sheen-rgb: 255 244 232;
  --frost-rim-rgb: 255 250 244;
}

:root[data-frost-theme="chocolate"] {
  /* CHOCOLATE (MPF, 30 September 2026, on artha-tryouts/sort-panel-mockup.html:
     "add this colour to frost, this looks like a lovely colour, like chocolate
     or caramel"). The mockup wears Stark's Espresso body ("Roasted brown. Warm
     champagne light.", stark.css) with the Amber accent, and these are those
     values verbatim, mapped onto Frost's names: Espresso's sink/well → sink,
     its group → well, its deep → deep; Amber is Original's gold. Frost's own
     additions, measured: the card's lip and the glass's champagne light, and
     the field's two lines mixed from the ink into the card as every theme's
     are (rest 3.04, lit 4.53 on the card's lighter end). Muted holds 7.29 on
     the card's lighter end as it comes, so nothing is lifted. Not from Sender:
     Frost's own; Threads took it too on 1 Oct 2026 (MPF: "Chocolate only"). */
  --frost-floor: #231c18;
  --frost-floor-tint: #4b3d31;
  --frost-card-high: #342a23;
  --frost-card-low: #29211c;
  --frost-card-edge: #110d0c;
  --frost-card-lip: #fff4ea14;
  --frost-sink: #1f1916;
  --frost-well: #241c19;
  --frost-deep: #191411;
  --frost-ink: #eee6df;
  --frost-muted: #c6b9ae;
  --frost-legend: #bfb2a7;
  --frost-stone: #a8998e;
  --frost-engrave: #150f0d;
  --frost-line: #5d544c;
  --frost-line-lit: #908479;
  --frost-field-line: #7c746e;
  --frost-field-line-lit: #99918b;
  --frost-key: #4b3d31;
  --frost-accent: #f0b429;
  --frost-accent-rgb: 240 180 41;
  --frost-danger: #ff8f7a;
  --frost-glass-rgb: 255 245 235;
  --frost-sheen-rgb: 255 249 242;
  --frost-rim-rgb: 255 252 248;
}

/* --- daylight: the same seven themes, letterpress on paper ----------------- */
/* Each theme's own stock, its own ink-dark type in three tiers, and its
   accent deepened until it reads on paper (Sender v4a, note 22). */
:root[data-frost-mode="light"]:not([data-frost-theme]),
:root[data-frost-theme="original"][data-frost-mode="light"] {
  --frost-floor: #cdc4b4;
  --frost-floor-tint: #b29f80;
  --frost-card-high: #f5f0e6;
  --frost-card-low: #ebe4d6;
  --frost-card-edge: #a39888;
  --frost-card-lip: #ffffffc0;
  --frost-sink: #e2dacb;
  --frost-well: #e6dfd1;
  --frost-deep: #ddd4c3;
  --frost-ink: #26221c;
  --frost-muted: #4c463c;
  --frost-legend: #544d42;
  --frost-stone: #645d50;
  --frost-engrave: #d3cab9;
  --frost-line: #bdb3a2;
  --frost-line-lit: #968c7b;
  --frost-field-line: #807b72;
  --frost-field-line-lit: #645f57;
  --frost-key: #c9bfad;
  --frost-accent: #7a560f;
  --frost-accent-rgb: 122 86 15;
  --frost-danger: #b3261e;
  --frost-glass-rgb: 255 253 248;
  --frost-sheen-rgb: 255 255 252;
  --frost-rim-rgb: 255 255 255;
}

:root[data-frost-theme="charcoal"][data-frost-mode="light"] {
  --frost-floor: #c4c8cd;
  --frost-floor-tint: #8e98a5;
  --frost-card-high: #f2f3f5;
  --frost-card-low: #e6e8eb;
  --frost-card-edge: #979ca4;
  --frost-card-lip: #ffffffc0;
  --frost-sink: #dcdfe3;
  --frost-well: #e0e3e7;
  --frost-deep: #d6dade;
  --frost-ink: #1d2024;
  --frost-muted: #43484f;
  --frost-legend: #4a4f56;
  --frost-stone: #5b6169;
  --frost-engrave: #d0d4d9;
  --frost-line: #b9bec5;
  --frost-line-lit: #8c929a;
  --frost-field-line: #7c7f82;
  --frost-field-line-lit: #606366;
  --frost-key: #bfc4ca;
  --frost-accent: #7d5e10;
  --frost-accent-rgb: 125 94 16;
  --frost-danger: #b3261e;
  --frost-glass-rgb: 252 253 255;
  --frost-sheen-rgb: 253 254 255;
  --frost-rim-rgb: 255 255 255;
}

:root[data-frost-theme="purple"][data-frost-mode="light"] {
  --frost-floor: #c8bfd2;
  --frost-floor-tint: #8f8499;
  --frost-card-high: #f3eff6;
  --frost-card-low: #e8e2ee;
  --frost-card-edge: #9f95ab;
  --frost-card-lip: #ffffffc0;
  --frost-sink: #ded6e6;
  --frost-well: #e2dbe9;
  --frost-deep: #d9d0e2;
  --frost-ink: #241a2f;
  --frost-muted: #4a3f58;
  --frost-legend: #52465f;
  --frost-stone: #625670;
  --frost-engrave: #d6cde0;
  --frost-line: #beb3ca;
  --frost-line-lit: #8f839d;
  --frost-field-line: #7f7787;
  --frost-field-line-lit: #645b6c;
  --frost-key: #c2b8ce;
  --frost-accent: #7b5d1c;
  --frost-accent-rgb: 123 93 28;
  --frost-danger: #b3261e;
  --frost-glass-rgb: 253 250 255;
  --frost-sheen-rgb: 254 252 255;
  --frost-rim-rgb: 255 255 255;
}

:root[data-frost-theme="burgundy"][data-frost-mode="light"] {
  --frost-floor: #d0bfc3;
  --frost-floor-tint: #9d8a8e;
  --frost-card-high: #f6eff0;
  --frost-card-low: #ede2e4;
  --frost-card-edge: #a8969b;
  --frost-card-lip: #ffffffc0;
  --frost-sink: #e4d7da;
  --frost-well: #e8dcdf;
  --frost-deep: #e0d2d5;
  --frost-ink: #2d1a20;
  --frost-muted: #56404a;
  --frost-legend: #5e4751;
  --frost-stone: #6e5760;
  --frost-engrave: #ddcfd2;
  --frost-line: #cbb9be;
  --frost-line-lit: #9c878e;
  --frost-field-line: #87787c;
  --frost-field-line-lit: #6b5b60;
  --frost-key: #cbb8bd;
  --frost-accent: #8f4b3b;
  --frost-accent-rgb: 143 75 59;
  --frost-danger: #b4121f;
  --frost-glass-rgb: 255 250 251;
  --frost-sheen-rgb: 255 252 253;
  --frost-rim-rgb: 255 255 255;
}

:root[data-frost-theme="navy"][data-frost-mode="light"] {
  --frost-floor: #bcc5d2;
  --frost-floor-tint: #8591a2;
  --frost-card-high: #f0f3f7;
  --frost-card-low: #e3e8ef;
  --frost-card-edge: #929cab;
  --frost-card-lip: #ffffffc0;
  --frost-sink: #d8dfe8;
  --frost-well: #dde3eb;
  --frost-deep: #d3dae4;
  --frost-ink: #172030;
  --frost-muted: #3c475a;
  --frost-legend: #445063;
  --frost-stone: #535f72;
  --frost-engrave: #cdd5e0;
  --frost-line: #b4bfcd;
  --frost-line-lit: #8390a3;
  --frost-field-line: #787f8a;
  --frost-field-line-lit: #5c636f;
  --frost-key: #b8c2cf;
  --frost-accent: #7a5f1c;
  --frost-accent-rgb: 122 95 28;
  --frost-danger: #b3261e;
  --frost-glass-rgb: 250 252 255;
  --frost-sheen-rgb: 252 253 255;
  --frost-rim-rgb: 255 255 255;
}

:root[data-frost-theme="camel"][data-frost-mode="light"] {
  /* the cloth itself: the hide is tinted with the sampled #c4875e and stands
     one step lighter (#d29e78) so the floor's own words keep 7:1; the stock is
     the same hue washed pale; a burnt saddle brown for the accent */
  --frost-floor: #d29e78;
  --frost-floor-tint: #c4875e;
  --frost-card-high: #f4dfca;
  --frost-card-low: #ead0b6;
  --frost-card-edge: #a67955;
  --frost-card-lip: #ffffffc0;
  --frost-sink: #dfc0a2;
  --frost-well: #e5c8ab;
  --frost-deep: #d8b694;
  --frost-ink: #2b1a0e;
  --frost-muted: #452e1b;
  --frost-legend: #4e3621;
  --frost-stone: #5c432c;
  --frost-engrave: #d2b092;
  --frost-line: #c3a283;
  --frost-line-lit: #93704f;
  --frost-field-line: #80664e;
  --frost-field-line-lit: #624a35;
  --frost-key: #c9a585;
  --frost-accent: #773a0a;
  --frost-accent-rgb: 119 58 10;
  --frost-danger: #a0160e;
  --frost-glass-rgb: 255 247 238;
  --frost-sheen-rgb: 255 251 245;
  --frost-rim-rgb: 255 255 255;
}

:root[data-frost-theme="chocolate"][data-frost-mode="light"] {
  /* the same brown washed pale, as Camel's daylight is: Original's daylight
     stock and inks turned to Espresso's hue (OKLCH 60°) with half as much
     colour again, so the paper reads as milky caramel, not cream; the hide a
     latte a step lighter than Camel's; the accent is Amber deepened for
     paper, Original's own daylight gold */
  --frost-floor: #d7b79e;
  --frost-floor-tint: #bd9576;
  --frost-card-high: #fceee3;
  --frost-card-low: #f5e1d1;
  --frost-card-edge: #ad9482;
  --frost-card-lip: #ffffffc0;
  --frost-sink: #ecd6c6;
  --frost-well: #f0dccc;
  --frost-deep: #e8d0bd;
  --frost-ink: #2a211a;
  --frost-muted: #524438;
  --frost-legend: #5b4a3e;
  --frost-stone: #6c5a4b;
  --frost-engrave: #dec6b3;
  --frost-line: #c8af9c;
  --frost-line-lit: #a18875;
  --frost-field-line: #86796f;
  --frost-field-line-lit: #695d54;
  --frost-key: #d5bba7;
  --frost-accent: #7a560f;
  --frost-accent-rgb: 122 86 15;
  --frost-danger: #b3261e;
  --frost-glass-rgb: 255 252 247;
  --frost-sheen-rgb: 255 254 251;
  --frost-rim-rgb: 255 255 255;
}


/* ================================================ 2. the mapping into Stark */
/* Frost §2: Frost's values written into Stark's names, because the look rules
   below are Stark's recipes re-stated on Threads classes and read Stark's
   names. On :root beside the themes, so a theme word on <html> reaches them. */
:root {
  --stark-floor: var(--frost-floor);
  --stark-floor-tint: var(--frost-floor-tint);
  --stark-card-high: var(--frost-card-high);
  --stark-card-low: var(--frost-card-low);
  --stark-card-edge: var(--frost-card-edge);
  --stark-sink: var(--frost-sink);
  --stark-group: var(--frost-well);
  --stark-well: var(--frost-sink);
  --stark-deep: var(--frost-deep);
  --stark-ink: var(--frost-ink);
  --stark-muted: var(--frost-muted);
  --stark-legend: var(--frost-legend);
  --stark-stone: var(--frost-stone);
  --stark-engrave: var(--frost-engrave);
  --stark-line: var(--frost-line);
  --stark-line-lit: var(--frost-line-lit);
  --stark-key: var(--frost-key);
  --stark-key-low: color-mix(in srgb, var(--frost-key) 55%, var(--frost-card-low));
  --stark-accent: var(--frost-accent);
  --stark-accent-rgb: var(--frost-accent-rgb);
  --stark-danger: var(--frost-danger);
  /* Frost rule 7: focus is a thin accent ring, never a glow. */
  --stark-focus-ring: 0 0 0 1px var(--stark-accent);

  /* --- What Frost leans on from Stark §1, with Stark's own values. Sizes
         stay Threads' own (spec Open 5); these are the sign-in card's. */
  --stark-floor-veil: 85%;
  --stark-radius: 5px;
  --stark-t-tap: 160ms;
  --stark-t-quick: 250ms;
  --stark-t-move: 300ms;
  --stark-t-settle: 450ms;
  --stark-ease: cubic-bezier(.22, 1, .36, 1);
  --stark-text-body: 17px;
  --stark-text-h1: 30px;
  --stark-text-sub: 16px;
  --stark-text-control: 18px;
  --stark-text-button: 15px;
  --stark-text-note: 14.5px;
  --stark-text-micro: 13px;
  --stark-card: 460px;
}

/* Daylight tells the browser's own controls, as Frost §2 does. Production's
   :root says dark; this ties it and follows it. */
:root[data-frost-mode="light"] { color-scheme: light; }


/* ============================================================== 3. the glass */
/* Frost §3's recipe as tokens, both modes; §13's list; §16's shell glass (the
   strips of the menu, stage 2); §19's figure red. Copied value for value. The
   kit registers the glass colours (`@property`) so a theme change fades; here
   no page changes theme while it is open until stage 7, so they are plain. */
:root {
  --frost-glass-fill: rgb(var(--frost-glass-rgb) / 10%);
  --frost-sheen-top: rgb(var(--frost-sheen-rgb) / 5%);
  --frost-sheen-mid: rgb(var(--frost-sheen-rgb) / 1.5%);
  --frost-sheen-foot: rgb(0 0 0 / 6%);
  --frost-glass-sheen: linear-gradient(180deg, var(--frost-sheen-top), var(--frost-sheen-mid) 40%, var(--frost-sheen-foot));
  --frost-glass-rim: rgb(var(--frost-rim-rgb) / 16%);
  --frost-glass-edge: rgb(var(--frost-rim-rgb) / 7%);
  --frost-bloom-tone: rgb(var(--frost-sheen-rgb) / 14%);
  --frost-glass-bloom: inset 0 10px 14px -12px var(--frost-bloom-tone);
  --frost-glass-lift: 0 2px 6px #0004;
  --frost-glass-settled: inset 0 1px 0 var(--frost-glass-rim), inset 0 0 0 1px var(--frost-glass-edge), var(--frost-glass-bloom);
  --frost-glass-shadow: var(--frost-glass-settled), var(--frost-glass-lift);
  /* The glass row pane (docs/threads-glass-row-hover-spec.md §3, MPF 1 Oct 2026:
     "go with 1b medium blur", then 1b-iii for a picked row). Copied from the
     mockup (design-source/mockups/glass-row-hover/index.html ~698–723): the
     pane's drop, small enough to end inside the next row's padding; the picked
     row's thin bright outline, its inner twin (nothing in the dark), and the
     soft light falling from the top centre inside it. */
  --frost-pane-drop: 0 7px 14px -9px #000c, 0 1px 2px #0007;
  --frost-pick-outline: rgb(var(--frost-rim-rgb) / 30%);
  --frost-pick-outline-inner: rgb(var(--frost-rim-rgb) / 0%);
  --frost-pick-light: rgb(var(--frost-sheen-rgb) / 8%);

  /* --- the ladder: one pane, four strengths (Frost §3) */
  --frost-glass-hover: .32;
  --frost-glass-press: .66;
  --frost-press-drop: 1px;

  --frost-key-r: 999px;
  --frost-floor-ink: var(--stark-muted);
  --frost-row-r: var(--stark-radius);
  --frost-press-glass: 0 1px 1.5px rgb(0 0 0 / 55%);

  --frost-bar-filter: blur(18px) saturate(115%) brightness(1.3);
  --frost-bar-tint: color-mix(in srgb, var(--frost-card-low) 66%, transparent);
  --frost-bar-drop-far: #0006;
  --frost-bar-drop-near: #0005;
  --frost-bar-drop: 0 10px 28px var(--frost-bar-drop-far), 0 1px 3px var(--frost-bar-drop-near);

  --frost-press-body: inset 0 2px 6px #000b;
  --frost-press-lip: inset 0 -1px 0 #ffffff17;
  --frost-press-well: var(--frost-press-body), var(--frost-press-lip);
  --frost-press-shallow: inset 0 1px 3px #0008;
  --frost-slot-word-shadow: 0 1px 0 #ffffff12, 0 -1px 1px #000c;

  --frost-list-tint: color-mix(in srgb, var(--frost-card-low) 86%, transparent);
  --frost-list-sheen: none;
  --frost-list-filter: blur(16px) saturate(120%);
  --frost-list-drop: 0 22px 44px #000b, 0 2px 6px #0009;

  --frost-accent-pressed: var(--frost-accent);

  /* --- §16, the shell's glass: the menu's strips */
  --frost-glass-r: 10px;
  --frost-shell-tint: color-mix(in srgb, var(--frost-card-low) 56%, transparent);
  --frost-shell-filter: blur(10px) saturate(135%) brightness(1);
  --frost-shell-stone: color-mix(in srgb, var(--frost-stone) 55%, var(--frost-muted));
  /* Threads' second strip (stage 2): the families row and the crumbs, a
     deeper pane laid on the header's glass — the card's own colour at a
     third, so strip one's glass reads above it as the mockup's two strips
     stand apart. Not in the kit: Threads' header is one full-bleed box. */
  --frost-strip-two: color-mix(in srgb, var(--frost-card-low) 34%, transparent);
  /* Threads' drop-down sheet (stage 2): the kit's list tint is 86% because
     the kit blurs what is under it; Threads' sheet cannot be blurred (its
     held opening animation makes it its own backdrop, §14), and unblurred
     the crumbs and headings under it read through sharp — at 86%, and on the
     phone's lifted sheet even at 97% (seen at the look, 28 Sep 2026). So the
     list's own card colour, whole; the sheen, rim and drop still say glass. */
  --frost-sheet-tint: var(--frost-card-low);

  /* --- §19, the figure red a cell's negative reads in (7:1) */
  --frost-neg: #ffc4b8;
  --frost-neg-picked: #fed3cb;
  /* §19: a sentence in a well (a status message) reads in muted. */
  --frost-read-in-well: var(--stark-muted);

  /* --- Stark's card shadow and engraving, named once so no rule below holds
         a literal (Stark §4 card, §6 mark). */
  --frost-card-lip-shadow: inset 0 1px var(--frost-card-lip);
  --frost-card-shadow: var(--frost-card-lip-shadow), 0 24px 60px #0009, 0 2px 6px #0008;
  --frost-engrave-shadow: 0 1px 0 color-mix(in srgb, var(--stark-accent) 38%, #ffffff26), 0 -1px 1px #000c;
  /* A dashboard tile (stage 6): Stark's card at a key's size — its lip, a
     drop scaled to a 210px card rather than the sign-in's 460px one — and
     the nearer drop of a tile the pointer has pressed towards the floor. */
  --frost-tile-shadow: var(--frost-card-lip-shadow), 0 12px 28px #0008, 0 2px 6px #0008;
  --frost-tile-shadow-near: var(--frost-card-lip-shadow), 0 4px 12px #0007, 0 1px 3px #0008;
  /* §19: a label standing on the bare leather. */
  --frost-floor-label: var(--stark-stone);

  /* --- §18's feedback, copied from the kit (frost.css ~2044–2051): the
         tooltip's close drop — it ends inside the gap above the key it
         names, as Stark's does (24 Sep 2026) — and the danger word on
         glass, a fifth towards white in the dark so a refusal's title holds
         4.5:1 on the toast (stage 5, 29 Sep 2026). */
  /* MPF, 2 October 2026: "add a bit more glass, depth and shadow to the tooltip, not too much just slight" — a soft wider drop under the close one, a sheen down the frame, a shaded foot line. */
  --frost-tip-drop: 0 10px 24px #0005, 0 2px 6px #0008, 0 1px 2px #0009;
  --frost-tip-shine: linear-gradient(180deg, rgb(var(--frost-sheen-rgb) / 8%), transparent 55%);
  --frost-tip-foot: rgb(0 0 0 / 28%);
  --frost-danger-glass: color-mix(in srgb, var(--frost-danger) 80%, #fff);
}

:root[data-frost-mode="light"] {
  --frost-glass-fill: rgb(var(--frost-glass-rgb) / 52%);
  --frost-sheen-top: rgb(var(--frost-sheen-rgb) / 40%);
  --frost-sheen-mid: rgb(var(--frost-sheen-rgb) / 12%);
  --frost-sheen-foot: color-mix(in srgb, var(--frost-ink) 3%, transparent);
  --frost-glass-rim: rgb(var(--frost-rim-rgb) / 95%);
  --frost-glass-edge: color-mix(in srgb, var(--frost-ink) 10%, transparent);
  --frost-bloom-tone: rgb(var(--frost-sheen-rgb) / 70%);
  --frost-glass-lift: 0 1px 2px color-mix(in srgb, var(--frost-ink) 16%, transparent), 0 3px 8px color-mix(in srgb, var(--frost-ink) 7%, transparent);
  /* The glass row pane in daylight (the mockup's): the drop in the ink, the
     outline a hairline of ink with white just inside, the light white. */
  --frost-pane-drop: 0 6px 12px -8px color-mix(in srgb, var(--frost-ink) 30%, transparent), 0 1px 2px color-mix(in srgb, var(--frost-ink) 14%, transparent);
  --frost-pick-outline: color-mix(in srgb, var(--frost-ink) 20%, transparent);
  --frost-pick-outline-inner: rgb(255 255 255 / 80%);
  --frost-pick-light: rgb(255 255 255 / 55%);
  --frost-press-glass: 0 1px 0 rgb(255 255 255 / 55%);
  --frost-floor-ink: var(--stark-ink);
  --frost-bar-filter: blur(18px) saturate(90%) brightness(1.04);
  --frost-bar-tint: color-mix(in srgb, var(--frost-card-high) 62%, transparent);
  --frost-bar-drop-far: color-mix(in srgb, var(--frost-ink) 12%, transparent);
  --frost-bar-drop-near: color-mix(in srgb, var(--frost-ink) 14%, transparent);
  --frost-press-body: inset 0 1px 2px color-mix(in srgb, var(--frost-ink) 22%, transparent), inset 0 3px 8px color-mix(in srgb, var(--frost-ink) 8%, transparent);
  --frost-press-lip: inset 0 -1px 0 var(--frost-card-lip);
  --frost-press-shallow: inset 0 1px 2px color-mix(in srgb, var(--frost-ink) 14%, transparent);
  --frost-slot-word-shadow: 0 1px 0 rgb(255 255 255 / 60%);
  --frost-list-tint: color-mix(in srgb, var(--frost-card-high) 70%, transparent);
  --frost-list-sheen: var(--frost-glass-sheen);
  --frost-list-filter: blur(16px) saturate(105%) brightness(1.03);
  --frost-list-drop: 0 18px 40px color-mix(in srgb, var(--frost-ink) 18%, transparent), 0 2px 6px color-mix(in srgb, var(--frost-ink) 14%, transparent);
  --frost-accent-pressed: color-mix(in srgb, var(--frost-accent) 80%, var(--frost-ink));
  --frost-shell-tint: color-mix(in srgb, var(--frost-card-high) 54%, transparent);
  --frost-shell-filter: blur(10px) saturate(112%) brightness(1.06);
  --frost-sheet-tint: var(--frost-card-high);
  /* §18's feedback in daylight (kit ~2059–2060): the drop in the ink, the
     danger word a fifth of the ink deeper. */
  --frost-tip-drop: 0 10px 24px color-mix(in srgb, var(--frost-ink) 10%, transparent), 0 2px 6px color-mix(in srgb, var(--frost-ink) 18%, transparent), 0 1px 2px color-mix(in srgb, var(--frost-ink) 16%, transparent);
  --frost-tip-shine: linear-gradient(180deg, rgb(255 255 255 / 40%), transparent 55%);
  --frost-tip-foot: color-mix(in srgb, var(--frost-ink) 10%, transparent);
  --frost-danger-glass: color-mix(in srgb, var(--frost-danger) 80%, var(--frost-ink));
  --frost-tile-shadow: var(--frost-card-lip-shadow), 0 8px 20px color-mix(in srgb, var(--frost-ink) 14%, transparent), 0 1px 3px color-mix(in srgb, var(--frost-ink) 18%, transparent);
  --frost-tile-shadow-near: var(--frost-card-lip-shadow), 0 3px 8px color-mix(in srgb, var(--frost-ink) 12%, transparent), 0 1px 2px color-mix(in srgb, var(--frost-ink) 16%, transparent);
  /* §19: daylight labels on the leather deepen — muted with 30% of the ink. */
  --frost-floor-label: color-mix(in srgb, var(--stark-muted) 70%, var(--stark-ink));
}

/* §16: the shell's quiet words, one mix per dark theme (measured in the kit,
   SPEC §8); daylight keeps the one mix above. */
:root:not([data-frost-mode="light"]):not([data-frost-theme]),
:root[data-frost-theme="original"]:not([data-frost-mode="light"]),
:root[data-frost-theme="camel"]:not([data-frost-mode="light"]),
:root[data-frost-theme="chocolate"]:not([data-frost-mode="light"]) {
  --frost-shell-stone: color-mix(in srgb, var(--frost-stone) 20%, var(--frost-muted));
}
:root[data-frost-theme="charcoal"]:not([data-frost-mode="light"]) {
  --frost-shell-stone: color-mix(in srgb, var(--frost-stone) 32%, var(--frost-muted));
}
:root[data-frost-theme="purple"]:not([data-frost-mode="light"]),
:root[data-frost-theme="burgundy"]:not([data-frost-mode="light"]) {
  --frost-shell-stone: color-mix(in srgb, var(--frost-stone) 50%, var(--frost-muted));
}

/* §19: each theme's figure red. */
:root[data-frost-theme="charcoal"] { --frost-neg: #fec5ba; --frost-neg-picked: #fed3cb; }
:root[data-frost-theme="purple"]   { --frost-neg: #ffb8aa; --frost-neg-picked: #fec7bc; }
:root[data-frost-theme="burgundy"] { --frost-neg: #ffb1aa; --frost-neg-picked: #fec0ba; }
:root[data-frost-theme="navy"]     { --frost-neg: #ffb4a5; --frost-neg-picked: #fec3b7; }
:root[data-frost-theme="camel"]    { --frost-neg: #ffe3da; --frost-neg-picked: #ffece6; }
:root[data-frost-theme="chocolate"] { --frost-neg: #ffbcae; --frost-neg-picked: #ffcbbf; }
:root[data-frost-mode="light"]:not([data-frost-theme]),
:root[data-frost-theme="original"][data-frost-mode="light"] { --frost-neg: #920003; --frost-neg-picked: #920003; }
:root[data-frost-theme="charcoal"][data-frost-mode="light"] { --frost-neg: #940305; --frost-neg-picked: #940305; }
:root[data-frost-theme="purple"][data-frost-mode="light"]   { --frost-neg: #8e0304; --frost-neg-picked: #8e0304; }
:root[data-frost-theme="burgundy"][data-frost-mode="light"] { --frost-neg: #910012; --frost-neg-picked: #910012; }
:root[data-frost-theme="navy"][data-frost-mode="light"]     { --frost-neg: #940305; --frost-neg-picked: #940305; }
:root[data-frost-theme="camel"][data-frost-mode="light"]    { --frost-neg: #7a0002; --frost-neg-picked: #7a0002; }
:root[data-frost-theme="chocolate"][data-frost-mode="light"] { --frost-neg: #8b0000; --frost-neg-picked: #8b0000; }


/* ================================================ 4. Threads' names, pointed */
/* SPEC STAGE 1, "THE MAPPING". Threads' own sheets and Koel read these names
   in thousands of rules; writing Frost's values into them here is how a
   screen that has not reached its stage yet still stands in Frost's colours.
   On `body` because descendants inherit the nearest declaration, so this
   beats production's `:root[data-accent]` without a specificity fight.
   WHAT THIS CHANGES BY ITSELF, said plainly (the brief, 28 Sep 2026): every
   accent-coloured thing turns Frost's gold whatever accent a reader saved
   (the saved accent still drives the favicon, the brand emblem and the PDF
   emblem, spec "What still follows the old accent"); the ink, muted words,
   hairlines and Koel's two card tokens take Frost's warm tones; Koel's
   16px and 10px corners become 5px; the accent glows go (Frost rule 7). The
   many surfaces Koel paints with its own literal blue-greys — table rows,
   wells, keys, dialogs — keep them until stages 3–5. */
body.threads-koel {
  --canvas: var(--frost-floor);
  --ink: var(--frost-ink);
  --muted: var(--frost-muted);
  --line: var(--frost-line);
  --line-strong: var(--frost-line-lit);
  --surface-hover: var(--frost-key);
  --accent: var(--frost-accent);
  --accent-hover: color-mix(in srgb, var(--frost-accent) 86%, var(--frost-ink));
  --accent-readable: var(--frost-accent);
  --accent-soft: color-mix(in srgb, var(--frost-accent) 16%, var(--frost-card-low));
  --accent-focus: rgb(var(--frost-accent-rgb) / 32%);
  /* A word on an accent fill: Frost's engrave is the dark cut in the dark
     themes and the pale one in daylight, so it reads on either accent. */
  --accent-ink: var(--frost-engrave);
  /* Frost rule 7 (MPF, 24 Sep 2026): no glow — the accent halo is gone. */
  --accent-glow: transparent;
  --accent-shadow: rgb(0 0 0 / 40%);
  --accent-rgb: var(--frost-accent-rgb);
  --accent-readable-rgb: var(--frost-accent-rgb);
  /* Frost has one status hue, its danger; Threads' green, amber and blue
     have no Frost counterpart and stay Threads' own until stage 5 (feedback). */
  --error: var(--frost-danger);
  --shadow-navigation: var(--frost-bar-drop);
  --shadow-management: var(--frost-card-shadow);
  --shadow-menu: var(--frost-list-drop);

  --koel-rail: var(--frost-card-low);
  --koel-rail-deep: var(--frost-sink);
  --koel-rail-line: var(--frost-card-edge);
  --koel-rail-muted: var(--frost-muted);
  --koel-card: var(--frost-card-low);
  --koel-card-quiet: var(--frost-card-high);
  --koel-line: var(--frost-line);
  --koel-line-strong: var(--frost-line-lit);
  --koel-ink-strong: var(--frost-ink);
  --koel-muted: var(--frost-muted);
  --koel-muted-soft: var(--frost-stone);
  --koel-radius: var(--stark-radius);
  --koel-radius-sm: var(--stark-radius);
  --koel-shadow-card: var(--frost-card-shadow);
  --koel-shadow-raised: var(--frost-list-drop);
}


/* ============================================================= 5. the floor */
/* Stark §2's leather: one transparent tile, the floor colour under it, the
   tint laid over it in `color` blend so the grain keeps the hue, and the
   floor's own colour veiled back at 85% (Stark's dark veil, which Frost
   keeps). Koel's solid canvas (koel.css ~52) goes. On the body, whose
   background paints the whole window (<html> carries none). Background
   only — the page's entry fade on the production body rule keeps playing.
   The sign-in and error pages are named too: Koel paints them from
   `.threads-koel.auth-page` (koel.css ~4127), one class heavier. */
/* THREE WALLPAPERS (stage 7, MPF 28 Sep 2026: the Preferences page "similar
   to what we did with Artha billing"): leather, plain and graph paper, each
   reader's own, written on <html> as Stark's `data-stark-floor` with leather
   as absence (getFrostThemeAttributes(), init.php). Copied from stark.css §2
   ("THREE WALLPAPERS"): all three are always in the stack and a wallpaper is
   three percentages — the grid's two 1px lines in the key colour at
   `--stark-floor-lines` (0% unless graph paper), the tint at
   `--stark-floor-grain` (100% only on leather) and the veil at 100% on plain
   and grid, which is the leather hidden under a floor of its own colour. At
   the defaults the two grid layers are transparent and the tint is whole, so
   the leather is the stage 1 floor to the pixel. Stark fades a change through
   `@property`; not copied, because the fade would need a transition on
   `body`, which production's entry animation owns (spec §1: no timing on an
   element a controller owns) — a pick on Preferences changes the floor at
   once. */
:root { --stark-floor-lines: 0%; --stark-floor-grain: 100%; }
:root[data-stark-floor="plain"] { --stark-floor-lines: 0%;  --stark-floor-grain: 0%; --stark-floor-veil: 100%; }
:root[data-stark-floor="grid"]  { --stark-floor-lines: 24%; --stark-floor-grain: 0%; --stark-floor-veil: 100%; }

/* The leather is a lossless WebP of leather-floor.png (30 Sep 2026,
   first-visit smoothness fixes): the same 1024px grey-and-alpha texture pixel
   for pixel, 654 KB against 1,076 KB. The PNG stays beside it as the source. */
body.threads-koel,
body.threads-koel.auth-page {
  color-scheme: dark;
  background-color: var(--stark-floor);
  background-image:
    linear-gradient(color-mix(in srgb, var(--stark-key) var(--stark-floor-lines), transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--stark-key) var(--stark-floor-lines), transparent) 1px, transparent 1px),
    linear-gradient(
      color-mix(in srgb, var(--stark-floor-tint) var(--stark-floor-grain), transparent),
      color-mix(in srgb, var(--stark-floor-tint) var(--stark-floor-grain), transparent)
    ),
    linear-gradient(
      color-mix(in srgb, var(--stark-floor) var(--stark-floor-veil), transparent),
      color-mix(in srgb, var(--stark-floor) var(--stark-floor-veil), transparent)
    ),
    url(assets/leather-floor.webp);
  background-blend-mode: normal, normal, color, normal, normal;
  background-size: 20px 20px, 20px 20px, auto, auto, 640px 640px;
  background-position: 0 0, 0 0, 0 0, 0 0, center top;
  color: var(--stark-ink);
}
:root[data-frost-mode="light"] body.threads-koel { color-scheme: light; }


/* ======================================================= THE SIGN-IN (MPF) */
/* Built ahead of the stages on MPF's word, 28 September 2026: "change the
   login page to frost". Everything from here to §13 is under
   `body.auth-page.threads-koel`, which the sign-in and the two error pages
   wear, so it reaches no other screen. Kept exactly as it was shipped; only
   its tokens moved up to §1–§3 when the rest of Threads joined it. */

/* Stark's single-card screen: the card is 460px and stands on the optical
   middle of the window. */
body.auth-page.threads-koel .auth-shell { width: min(100%, var(--stark-card)); }


/* ============================================================== 6. the sign-in card */
/* Stark §4, which Frost keeps in the dark (Frost: "cards, fields, forms stay
   Stark's matte paper"). One material, carrying the whole shadow: a hairline
   of light along the top, a wide drop off the leather, a tight one for the
   edge. Koel's 16px corner and the classic card's glass blur both go — the
   blur set to none because a filter on a card is the thing the spec guards
   against. */
body.auth-page.threads-koel .login-card {
  padding: 30px 34px;
  border: 1px solid var(--stark-card-edge);
  border-radius: var(--stark-radius);
  background: linear-gradient(145deg, var(--stark-card-high), var(--stark-card-low));
  box-shadow: var(--frost-card-shadow);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  font-size: var(--stark-text-body);
  line-height: 1.5;
  color: var(--stark-ink);
}


/* ============================================================== 7. the sign-in mark */
/* Artha's sign-in puts the mark inside the card, first, above a left-aligned
   heading (Artha login.php, MPF 20 Sep 2026), engraved: dark ink cut into the
   card with the accent on its lower lip (Stark §6). Threads keeps its own
   emblem and letters — the emblem still follows the person's saved accent
   until Open 2 settles the accents — and takes the engraving. The descriptor
   is too small to read as a cut, so it is set as Stark's eyebrow. */
body.auth-page.threads-koel .login-brand { margin: 0 0 22px; }
body.auth-page.threads-koel .login-logo {
  width: max-content;
  max-width: 100%;
  margin: 0;
  gap: 20px;
  background: transparent;
  box-shadow: none;
}
body.auth-page.threads-koel .login-logo .threads-wordmark__emblem {
  flex: 0 0 76px;
  width: 76px;
  max-width: 76px;
}
body.auth-page.threads-koel .login-logo .threads-wordmark__name {
  color: var(--stark-engrave);
  text-shadow: var(--frost-engrave-shadow);
}
body.auth-page.threads-koel .login-logo .threads-wordmark__descriptor {
  margin-top: 8px;
  color: var(--stark-legend);
  font-size: var(--stark-text-micro);
  letter-spacing: .18em;
}


/* ============================================================ 8. the sign-in heading */
/* Stark §5: h1 at 30px, 500, the sub-line in muted at 16px, left-aligned as
   Artha's is. The 16px under it is Stark's `.stack` gap. */
body.auth-page.threads-koel .login-heading {
  margin: 0 0 16px;
  text-align: start;
}
body.auth-page.threads-koel .login-heading h1 {
  margin: 0 0 4px;
  font-size: var(--stark-text-h1);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -.4px;
  color: var(--stark-ink);
}
/* The sentence under the heading, not the eyebrow above it: the two error
   pages share this header and open it with a `management-eyebrow`, which
   keeps today's own look (its capitals, its size, its 8px gap) until stage
   7 dresses those pages (review, 28 Sep 2026). */
body.auth-page.threads-koel .login-heading p:not(.management-eyebrow) {
  margin: 0;
  font-size: var(--stark-text-sub);
  color: var(--stark-muted);
}


/* ==================================================== 9. the refusal message */
/* Stark §33 as Frost §18 dresses it: a well pressed into the paper, a 5px
   square lamp in the danger colour with no glow (Frost rule 7), and the
   first words — Threads' `<strong>` — in the danger ink, the one hue the kit
   allows. Threads' markup has the verdict and the sentence as two elements,
   so they stand as two lines beside the lamp rather than one run of text. */
body.auth-page.threads-koel .status-message {
  display: grid;
  grid-template-columns: 5px minmax(0, 1fr);
  column-gap: 14px;
  row-gap: 2px;
  align-items: start;
  margin: 0 0 16px;
  padding: 12px 14px;
  border: 0;
  border-radius: var(--stark-radius);
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
  font-size: var(--stark-text-note);
  line-height: 1.45;
  color: var(--frost-read-in-well);
}
body.auth-page.threads-koel .status-message::before {
  grid-column: 1;
  grid-row: 1;
  width: 5px;
  height: 5px;
  margin-top: 8px;
  border-radius: calc(var(--stark-radius) - 3px);
  background: var(--stark-key);
  box-shadow: none;
}
body.auth-page.threads-koel .status-message > * { grid-column: 2; }
body.auth-page.threads-koel .status-message strong { color: var(--stark-ink); font-weight: 600; }
body.auth-page.threads-koel .status-message--danger::before { background: var(--stark-danger); }
body.auth-page.threads-koel .status-message--danger strong { color: var(--stark-danger); }


/* ============================================================ 10. the sign-in fields */
/* Stark §8 with Frost §9's line tones: no box, one line under the control,
   brighter under the pointer, the accent and one pixel under it on focus.
   Koel's well, its 10px corner and its halo all go. */
body.auth-page.threads-koel .login-form { gap: 16px; }
body.auth-page.threads-koel .form-field { gap: 4px; min-width: 0; }
body.auth-page.threads-koel .form-field label {
  font-size: var(--stark-text-sub);
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: var(--stark-muted);
}
body.auth-page.threads-koel .form-field input:is([type="text"], [type="password"]) {
  --stark-line: var(--frost-field-line);
  --stark-line-lit: var(--frost-field-line-lit);
  width: 100%;
  min-width: 0;
  min-height: 42px;
  padding: 7px 0;
  border: 0;
  border-bottom: 1px solid var(--stark-line);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--stark-ink);
  font: inherit;
  font-size: var(--stark-text-control);
  text-overflow: ellipsis;
  transition: border-color var(--stark-t-move) var(--stark-ease), box-shadow var(--stark-t-move) var(--stark-ease);
}
body.auth-page.threads-koel .form-field input:is([type="text"], [type="password"]):hover {
  border-bottom-color: var(--stark-line-lit);
}
body.auth-page.threads-koel .form-field input:is([type="text"], [type="password"]):is(:focus, :focus-visible) {
  outline: none;
  border-bottom-color: var(--stark-accent);
  background: transparent;
  box-shadow: 0 1px 0 var(--stark-accent);
}


/* ======================================================== 11. the tick box */
/* Stark §9's row with Frost §11's box: the empty box is a frame in the
   field's line; ticking it drops a pane of glass into the frame holding the
   accent ✓. The pane climbs Frost's ladder — a third under the pointer, two
   thirds pressed, whole when ticked. Production draws its tick as two
   rotated borders on `::after`; that drawing is undone here and Stark's ✓
   put in its place. */
body.auth-page.threads-koel .remember-option {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 30px;
  font-size: var(--stark-text-sub);
  color: var(--stark-muted);
  transition: color var(--stark-t-move) var(--stark-ease);
}
body.auth-page.threads-koel .remember-option:has(input:checked) { color: var(--stark-ink); }

body.auth-page.threads-koel .remember-option input[type="checkbox"] {
  --stark-line: var(--frost-field-line);
  --stark-line-lit: var(--frost-field-line-lit);
  position: relative;
  isolation: isolate;
  appearance: none;
  flex: 0 0 auto;
  display: grid;
  place-content: center;
  width: 22px;
  height: 22px;
  margin: 0;
  border: 1px solid var(--stark-line);
  border-radius: var(--stark-radius);
  background: transparent;
  box-shadow: none;
  outline: none;
  accent-color: auto;
  cursor: pointer;
  transition: border-color var(--stark-t-move) var(--stark-ease);
}
body.auth-page.threads-koel .remember-option input[type="checkbox"]::before {
  content: '';
  position: absolute;
  inset: -1px;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.82);
  transition:
    opacity var(--stark-t-settle) var(--stark-ease),
    transform var(--stark-t-settle) var(--stark-ease),
    box-shadow var(--stark-t-quick) var(--stark-ease);
}
body.auth-page.threads-koel .remember-option input[type="checkbox"]::after {
  content: '✓';
  position: relative;
  z-index: 1;
  display: block;
  width: auto;
  height: auto;
  margin: 0;
  border: 0;
  color: var(--stark-accent);
  font-size: 15px;
  line-height: 1;
  opacity: 0;
  transform: scale(.5) rotate(-15deg);
  transition: opacity var(--stark-t-tap) var(--stark-ease), transform var(--stark-t-move) var(--stark-ease);
}

/* hover — the box itself, or anywhere on its row's words */
body.auth-page.threads-koel .remember-option:hover > input[type="checkbox"] { border-color: var(--stark-line-lit); }
body.auth-page.threads-koel .remember-option:hover > input[type="checkbox"]::before,
body.auth-page.threads-koel .remember-option > input[type="checkbox"]:focus-visible::before {
  opacity: var(--frost-glass-hover);
  transform: none;
}

/* ticked — the whole pane, its own edge the frame now */
body.auth-page.threads-koel .remember-option > input[type="checkbox"]:checked {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
}
body.auth-page.threads-koel .remember-option > input[type="checkbox"]:checked::before {
  opacity: 1;
  transform: none;
  box-shadow: var(--frost-glass-shadow);
}
body.auth-page.threads-koel .remember-option > input[type="checkbox"]:checked::after {
  opacity: 1;
  transform: scale(1) rotate(0);
}

/* press — two thirds, settled onto the card, the drop gone */
body.auth-page.threads-koel .remember-option:active > input[type="checkbox"]::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
  transition-duration: var(--stark-t-tap);
}

/* focus — a 1px accent ring round the box (Frost §4, rule 7) */
body.auth-page.threads-koel .remember-option > input[type="checkbox"]:focus-visible {
  outline: 1px solid var(--stark-accent);
  outline-offset: 2px;
  box-shadow: none;
}


/* ========================================================= 12. the sign-in key */
/* Stark §7 as Frost §4 redraws it: the key lies flush — no fill, no border,
   no drop — an uppercase word in the round-ended capsule (Frost rule 2), the
   primary's word at full ink turning the accent under the pointer. What a
   reader gets back is a pane of glass in `::before`: a third on hover, two
   thirds and settled 1px on press. Focus is the 1px accent ring round the
   key, never a glow (Frost rule 7). Koel's accent keycap goes. Full width,
   as Artha's `primary--wide` is. */
body.auth-page.threads-koel .button--primary.login-button {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 46px;
  padding: 12px 24px;
  border: 1px solid transparent;
  border-radius: var(--frost-key-r);
  background: none;
  box-shadow: none;
  text-shadow: none;
  color: var(--stark-ink);
  font: inherit;
  font-size: var(--stark-text-button);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--stark-t-quick) var(--stark-ease);
}
body.auth-page.threads-koel .button--primary.login-button::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.94);
  transition:
    opacity var(--stark-t-settle) var(--stark-ease),
    transform var(--stark-t-settle) var(--stark-ease),
    box-shadow var(--stark-t-quick) var(--stark-ease);
}
body.auth-page.threads-koel .button--primary.login-button:is(:hover, :focus-visible) {
  background: none;
  box-shadow: none;
  color: var(--stark-accent);
}
body.auth-page.threads-koel .button--primary.login-button:is(:hover, :focus-visible)::before {
  opacity: var(--frost-glass-hover);
  transform: none;
}
body.auth-page.threads-koel .button--primary.login-button:active::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
  transition-duration: var(--stark-t-tap);
}
body.auth-page.threads-koel .button--primary.login-button:focus-visible {
  outline: 1px solid var(--stark-accent);
  outline-offset: 0;
}


/* ========================================================= 13. the sign-in, small screen */
/* Stark §25 at 480px: the card gives up side padding rather than content,
   and the heading steps down to 24px. The floor keeps its tile. */
@media (max-width: 480px) {
  body.auth-page.threads-koel { padding: 20px 12px; }
  body.auth-page.threads-koel .login-card { padding: 22px 18px 20px; }
  body.auth-page.threads-koel .login-heading h1 { font-size: 24px; }
}

/* A thumb's target (Stark §25, pointer: coarse). */
@media (pointer: coarse) {
  body.auth-page.threads-koel .button--primary.login-button,
  body.auth-page.threads-koel .remember-option { min-height: 44px; }
  body.auth-page.threads-koel .form-field input:is([type="text"], [type="password"]) { min-height: 44px; }
}

/* Reduce Motion: every change is simply there. */
@media (prefers-reduced-motion: reduce) {
  body.auth-page.threads-koel .button--primary.login-button,
  body.auth-page.threads-koel .button--primary.login-button::before,
  body.auth-page.threads-koel .remember-option,
  body.auth-page.threads-koel .remember-option input[type="checkbox"],
  body.auth-page.threads-koel .remember-option input[type="checkbox"]::before,
  body.auth-page.threads-koel .remember-option input[type="checkbox"]::after,
  body.auth-page.threads-koel .form-field input { transition: none; }
}


/* ======================================================== 14. THE CHROME */
/* Spec stage 2. MPF, 28 September 2026: "next lets do the menu and the
   homepage". The kit's menu-bar mockup (Artha Frost/menu-bar.css) was drawn on
   Threads' own Koel classes, so this is that sheet put back on the classes it
   was copied from: the markup, the tab binder and the drop-down script are
   Threads' and are not touched. Two frosted strips, the sections and the
   families as keys that climb the hover ladder, glass drop-down sheets with
   spaced rows, the crumbs and the find key as drawn there, and the command
   bar a glass dialog.

   WHERE THE MOCKUP AND THREADS DIFFER, AND WHY.
   · The mockup's chrome floats 8px down with rounded strips; Threads' masthead
     is `.site-header`, sticky and full-bleed by its production geometry,
     which a look change may not move (spec §1). So strip one is the whole
     header's glass, drawn on the header's own `::before` (the header is
     already a stacking context, sticky at z-index 40, so the underlay needs
     no position of its own), and the families row with the crumbs is strip
     two, a second, deeper layer on top of it.
   · The mockup blurs its drop-down sheet on a `::before`. Threads' sheet opens
     on its own animation, which holds its last frame (`both`), and a held
     opacity makes the sheet the edge of its own backdrop — the blur then sees
     nothing (the mockup found it, 28 Sep 2026, and changed the fill). The
     motion is Threads' and stays (spec §1), so the sheet is the kit's list
     without the blur, its tint made whole (`--frost-sheet-tint`) so what is
     under it never reads through.
   · Sizes stay Threads' (spec Open 5): Koel's paddings and type sizes, its
     phone rules included, are left to Koel; this section says colour, case,
     spacing of letters, corners and the panes. */

/* --- the two strips ------------------------------------------------------ */
/* Frost §16's shell glass: sheen over the shell tint, a real frost of what
   scrolls beneath, the lit rim along its foot, the bar's drop. On the
   header's `::before` — never on the header, which holds the phone's lifted
   menu sheet (`position: fixed`), and a filter on it would trap that sheet. */
body.threads-koel .site-header::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--frost-glass-sheen), var(--frost-shell-tint);
  -webkit-backdrop-filter: var(--frost-shell-filter);
  backdrop-filter: var(--frost-shell-filter);
  box-shadow: inset 0 -1px 0 var(--frost-glass-edge), var(--frost-bar-drop);
  pointer-events: none;
}

/* Strip one's two lines — the masthead and the sections — stand on that glass
   with no ground of their own, as the mockup's brand, sections and person
   share one bar. Koel's solid rails, production's own blur on the masthead
   (a second frost inside the first) and the rounded foot all go. */
body.threads-koel .main-navigation {
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
body.threads-koel .koel-menubar {
  border: 0;
  background: transparent;
}

/* Strip two: the families row and the crumbs under it, one deeper pane of
   the same glass, parted from strip one by a cut — the card's own edge above
   the glass's lit rim, the way the mockup's two strips stand apart. */
body.threads-koel .koel-menubar--families,
body.threads-koel .koel-subbar {
  background: var(--frost-strip-two);
}
body.threads-koel .koel-menubar--families {
  border-top: 1px solid var(--frost-card-edge);
  box-shadow: inset 0 1px 0 var(--frost-glass-edge);
}
/* The crumbs are parted from the row by the glass's own inner edge
   (menu-bar.css §7). */
body.threads-koel .koel-subbar {
  border-top: 1px solid var(--frost-glass-edge);
  border-bottom: 0;
}

/* --- the masthead: brand and person -------------------------------------- */
body.threads-koel .koel-brand-wordmark {
  color: var(--stark-ink);
  text-shadow: var(--frost-press-glass);
}
/* Stark's eyebrow: the descriptor is a label, not a picked thing, so it
   leaves the accent (Frost: "the accent is still a breath"). */
body.threads-koel .koel-brand-tagline {
  color: var(--stark-legend);
  letter-spacing: .18em;
}
/* The person, as the mockup's `menu-bar-who`: muted words on glass, the role
   in the accent deepened for a pressed place. */
body.threads-koel .navigation-username {
  color: var(--stark-muted);
  text-shadow: var(--frost-press-glass);
}
body.threads-koel .navigation-role { color: var(--frost-accent-pressed); }
/* The signed-in lamp: Stark's 5px square lamp, lit, with no glow (Frost
   rule 7). Threads' own green: Frost has no status green (spec stage 1). */
body.threads-koel .navigation-status-light {
  flex-basis: 5px;
  width: 5px;
  height: 5px;
  border-radius: calc(var(--stark-radius) - 3px);
  background: var(--success);
  box-shadow: none;
}

/* The person is a key (it opens Preferences), so it climbs the ladder; the
   accent halo production draws round it goes. */
body.threads-koel .navigation-account-preferences {
  position: relative;
  isolation: isolate;
  border-radius: var(--stark-radius);
}
body.threads-koel .navigation-account-preferences:is(:hover, :focus-visible, [aria-current="page"]) {
  background: transparent;
  box-shadow: none;
}

/* Log out: Frost §4's key — lies flush, an uppercase word in the capsule,
   the ladder's pane behind it; Koel's keycap goes. */
body.threads-koel .navigation-logout {
  position: relative;
  isolation: isolate;
  border: 1px solid transparent;
  border-radius: var(--frost-key-r);
  background: none;
  box-shadow: none;
  text-shadow: var(--frost-press-glass);
  color: var(--stark-muted);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  transition: color var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel .navigation-logout:is(:hover, :focus-visible) {
  background: none;
  box-shadow: none;
  color: var(--stark-accent);
}
body.threads-koel .navigation-logout:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }

/* --- an entry, and its pane (menu-bar.css §4) ----------------------------- */
/* A SECTION IS A KEY, SO IT WEARS A KEY'S WORD: uppercase, spaced (Frost
   rule 1). The families row and the sheets are rows, so they keep sentence
   case. The pane is inset 5px top and foot, so the glass floats inside the
   strip's glass rather than touching its edges. Koel's seam, its washes and
   its inset focus glow all go. */
body.threads-koel .koel-menubar .navigation-link {
  position: relative;
  isolation: isolate;
  border-radius: var(--stark-radius);
  background: transparent;
  box-shadow: none;
  color: var(--stark-muted);
  letter-spacing: .08em;
  text-transform: uppercase;
  text-shadow: var(--frost-press-glass);
  transition: color var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel .koel-menubar--families .navigation-link {
  letter-spacing: .01em;
  text-transform: none;
}

/* The pane: Frost §4's recipe, one box, four strengths. Production draws a
   glowing seam on `::before` of a section holding the page (and a second on
   `::after` of the one that is it); the pane takes the first box over, whole
   — its place, its size, its breathing animation — and the second goes, as
   Frost has no glow. The same pane lies behind every row of a sheet. */
body.threads-koel .koel-menubar .navigation-link::before,
body.threads-koel .navigation-submenu__link::before,
body.threads-koel .navigation-account-preferences::before,
body.threads-koel .navigation-logout::before {
  content: '';
  position: absolute;
  inset: 5px 0;
  z-index: -1;
  width: auto;
  height: auto;
  border-radius: var(--stark-radius);
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.94);
  animation: none;
  pointer-events: none;
  transition:
    opacity var(--stark-t-settle) var(--stark-ease),
    transform var(--stark-t-settle) var(--stark-ease),
    box-shadow var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel .navigation-submenu__link::before,
body.threads-koel .navigation-account-preferences::before { inset: 0; transform: scale(.985, .9); }
body.threads-koel .navigation-logout::before { inset: 0; border-radius: inherit; }
body.threads-koel .koel-menubar .navigation-link.is-current::after,
body.threads-koel .navigation-submenu__link .navigation-submenu__label::after { content: none; }
/* A family Threads has not built has no door, so it has no pane. */
body.threads-koel .koel-menubar .navigation-link--inert { color: var(--stark-stone); }
body.threads-koel .koel-menubar .navigation-link--inert::before { content: none; }

/* hover — a third of the pane, and the word brightens to ink */
body.threads-koel .koel-menubar .navigation-link:hover,
body.threads-koel .navigation-submenu__link:hover,
body.threads-koel .navigation-account-preferences:hover {
  background: transparent;
  color: var(--stark-ink);
}
body.threads-koel .koel-menubar .navigation-link:hover::before,
body.threads-koel .navigation-submenu__link:hover::before,
body.threads-koel .navigation-account-preferences:hover::before,
body.threads-koel .navigation-logout:hover::before {
  opacity: var(--frost-glass-hover);
  transform: none;
}

/* The open section that is not the one you are in (Koel: "legible as this
   row belongs to that tab without claiming you are here") — the hover rung,
   held. */
body.threads-koel .koel-family-tab[aria-pressed="true"]:not(.is-current) {
  background: transparent;
  color: var(--stark-ink);
}
body.threads-koel .koel-family-tab[aria-pressed="true"]:not(.is-current)::before {
  opacity: var(--frost-glass-hover);
  transform: none;
}

/* An open drop-down's label: two thirds, settled — pressed and holding. */
body.threads-koel .navigation-submenu[open]:not(.is-closing) > summary {
  background: transparent;
  color: var(--stark-ink);
}
body.threads-koel .navigation-submenu[open]:not(.is-closing) > summary::before {
  opacity: var(--frost-glass-press);
  transform: none;
  box-shadow: var(--frost-glass-settled);
}

/* press — two thirds, settled 1px, the drop gone, on the `tap` rung */
body.threads-koel .koel-menubar .navigation-link:active::before,
body.threads-koel .navigation-submenu__link:active::before,
body.threads-koel .navigation-account-preferences:active::before,
body.threads-koel .navigation-logout:active::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
  transition-duration: var(--stark-t-tap);
}

/* focus — the 1px accent ring (Frost rule 7), in place of Koel's inset glow */
body.threads-koel .koel-menubar .navigation-link:focus-visible,
body.threads-koel .navigation-submenu__link:focus-visible,
body.threads-koel .navigation-account-preferences:focus-visible {
  outline: 1px solid var(--stark-accent);
  outline-offset: -1px;
  background: transparent;
  box-shadow: none;
}
body.threads-koel .koel-menubar .navigation-link:focus-visible::before,
body.threads-koel .navigation-submenu__link:focus-visible::before,
body.threads-koel .navigation-account-preferences:focus-visible::before,
body.threads-koel .navigation-logout:focus-visible::before {
  opacity: var(--frost-glass-hover);
  transform: none;
}

/* --- where you are: the lit glass tile ------------------------------------ */
/* MPF's pick, 28 September 2026 (spec Open 3, "Lit glass tile"): the page's
   name on a clear glass tile with a thin accent hairline along its foot — the
   ladder's picked rung, the whole pane, lifted; a stone mark, nothing blooms.
   The same mark on the section you are in and on the families row's entry
   you are in; in a sheet the page you are on is the list's picked row, the
   whole pane and the accent word. */
body.threads-koel .koel-menubar .navigation-link:is(.is-current, .has-current-child) {
  background: transparent;
  box-shadow: none;
  color: var(--stark-accent);
}
body.threads-koel .koel-menubar .navigation-link:is(.is-current, .has-current-child)::before {
  opacity: 1;
  transform: none;
  box-shadow: var(--frost-glass-shadow), inset 0 -1px 0 var(--stark-accent);
}
body.threads-koel .navigation-submenu__link:is(.is-current, .has-current-child) {
  background: transparent;
  color: var(--stark-accent);
}
body.threads-koel .navigation-submenu__link.is-current::before,
body.threads-koel .navigation-account-preferences[aria-current="page"]::before {
  opacity: 1;
  transform: none;
}

/* The find key (menu-bar.css §3): the glyph's narrower key outranks the
   entries' padding, as Koel has it — said again here because the entry rule
   above is one class heavier than Koel's. */
body.threads-koel .koel-menubar .navigation-link.koel-menubar__search { padding-inline: 13px; }

/* --- the drop-downs: glass sheets (menu-bar.css §5, frost.css §13) -------- */
/* Threads' geometry, open and close motion and phone lift are kept whole;
   this is the sheet's material and its rows. */
body.threads-koel .navigation-submenu__panel {
  min-width: 210px;
  padding: 8px;
  border: 0;
  border-radius: var(--stark-radius);
  background: var(--frost-list-sheen), var(--frost-sheet-tint);
  box-shadow: var(--frost-glass-settled), var(--frost-list-drop);
  color: var(--stark-ink);
}
/* Rows 3px apart, so each lit row reads as its own tile instead of touching
   the next (MPF, 28 Sep 2026, on the mockup: "space out the rows bud"). The
   sheet's own flow is left alone; the rows take the gap themselves. */
body.threads-koel .navigation-submenu__panel > li + li:not(.navigation-submenu__separator) { margin-top: 3px; }
/* A nested sheet opens beside its parent's row with their top rows level:
   the sheet's 8px padding, taken back. Not once the phone has lifted it into
   the window — that sheet is placed by the script, and production releases
   these offsets for it. */
body.threads-koel .navigation-submenu__panel .navigation-submenu:not(.is-viewport-positioned) > .navigation-submenu__panel {
  top: -8px;
  left: calc(100% + 12px);
}

/* A row in the sheet: sentence case, a 5px pane (a row is not a key). */
body.threads-koel .navigation-submenu__link {
  position: relative;
  isolation: isolate;
  padding: 9px 12px;
  border-radius: var(--stark-radius);
  color: var(--stark-muted);
  transition: color var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel .navigation-submenu__separator { background: var(--frost-glass-edge); }

/* --- the crumbs (menu-bar.css §7) ----------------------------------------- */
body.threads-koel .koel-crumbs {
  color: var(--stark-legend);
  text-shadow: var(--frost-press-glass);
}
body.threads-koel .koel-crumbs a { color: var(--stark-muted); text-decoration: none; }
body.threads-koel .koel-crumbs a:hover { color: var(--stark-ink); }
body.threads-koel .koel-crumbs a:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 2px; }
body.threads-koel .koel-crumbs__level,
body.threads-koel .koel-crumbs__separator { color: var(--stark-legend); }
body.threads-koel .koel-crumbs [aria-current="page"] { color: var(--stark-ink); }

/* --- the gap under the chrome ---------------------------------------------
   MPF, 28 Sep 2026, looking at Frost's menu over Shirt Cards: "increase the
   distance between the menu and the card on the page by about 15px". The
   header ended 42px above the first card (28px of layout + the main's 14px
   padding); the main now opens 15px further down, on every app page. The
   sign-in page has no chrome and no .application-main, so it is untouched. */
body.threads-koel .application-main { margin-top: 15px; }

/* --- room above a dialog's footer -----------------------------------------
   MPF, 29 Sep 2026, on the Arrange Category One dialog: "increase the gap
   between the last control of the dialog and the bar that goes across the
   bottom". threads-production-ui.css gave the body 18px above its first
   control and only 6px below its last ("keep the last field attached to the
   footer"), so the last row sat on the footer's line. The bottom now matches
   the top, in every dialog. The kit's dialogs got the same balance the same day:
   19px of paper under the last field, as above the first. */
body.threads-koel .user-dialog-surface > .user-dialog-form { padding-bottom: 18px; }

/* --- a dialog's outer edge, softened ahead of stage 5 ----------------------
   MPF, 28 Sep 2026, on the Arrange Category One dialog: "does the border
   around the dialog seem a bit much" — Koel's 1px line had taken Frost's
   light card edge and read as a pencil outline. Until dialogs get their Frost
   turn, the line is Frost's faint glass edge and the top takes the glass rim,
   so the sheet lifts off the page instead of being drawn round. Only the
   outer edge; Koel's drop shadow token is kept as it is (rule 155: tokens only). */
body.threads-koel .user-dialog .user-dialog-surface {
  border-color: var(--frost-glass-edge);
  box-shadow: inset 0 1px 0 var(--frost-glass-rim), var(--koel-shadow-raised);
}

/* --- one fixed colour per Master (kit §24): the map's tokens -------------- */
/* getFrostMasterHues() (includes/management-table.php) names each Master's
   hue; these are the hues. They stood in threads-frost-pages.css, on a
   switched-on page's root alone, until 29 September 2026, when the command
   bar's scope pills took the Loom's chosen chip (MPF: "make those pill in
   the command bar the same look as our standard pills") — the bar opens on
   every page, so the one map moved here, whole and value for value, rather
   than being copied for it. tests/frost-look-contract-test.php check 8
   reads them here: each hue twice, its dark tint first, then its daylight
   twin. */
:root {
  /* §24: one hue per Master, dark tints — the kit's eleven, exactly */
  --frost-hue-blue: #84b8ff;
  --frost-hue-green: #99bb8a;
  --frost-hue-cyan: #74cfe8;
  --frost-hue-violet: #bda4e6;
  --frost-hue-rose: #f2788e;
  --frost-hue-orange: #f3a15e;
  --frost-hue-yellow: #ebdc88;
  --frost-hue-magenta: #e996d8;
  --frost-hue-indigo: #a4a9ff;
  --frost-hue-teal: #7fd6bf;
  --frost-hue-lime: #c4dc7c;

  /* Threads' own Masters (getFrostMasterHues(), 28 Sep 2026): one hue each,
     none shared, every one 4.5:1 or more as words on the cards and wells. */
  --frost-hue-lifecycle: #fad1e0;
  --frost-hue-date: #f7a8ef;
  --frost-hue-period: #9aa932;
  --frost-hue-as-at: #d07cc5;
  --frost-hue-age-band: #fbbfc3;
  --frost-hue-category: #bb83dd;
  --frost-hue-item: #d8a5a7;
  --frost-hue-fit: #cbe7ca;
  --frost-hue-fabric-type: #b2d4ff;
  --frost-hue-cut-group: #dd8cc3;
  --frost-hue-packing: #98ce9b;
  --frost-hue-parent: #43bae4;
  --frost-hue-kf-prefix: #719cf5;
  --frost-hue-item-type: #de8639;
  --frost-hue-pattern: #e67d58;
  --frost-hue-mapping-state: #a3e0ca;
  --frost-hue-group: #cbd8a5;
  --frost-hue-supplier: #eca6c2;
  --frost-hue-size-group: #e79363;
  --frost-hue-dispatch: #8e93f3;
  --frost-hue-product: #a2b4db;
  --frost-hue-family: #bcb4f4;
  --frost-hue-unfiled: #ca92dc;
  --frost-hue-maps-group: #68c188;
  --frost-hue-group-order: #d4c8fa;
  --frost-hue-access: #ed8c83;
  --frost-hue-declared: #3da7ed;
  --frost-hue-menu: #e2d8fc;
  --frost-hue-balance: #f6c6a5;
  --frost-hue-make: #d9b98a;
  --frost-hue-price-source: #9cc4f0;
  --frost-hue-price-field: #e8b24a;
  --frost-hue-soft: 14%;
}
:root[data-frost-mode="light"] {
  /* §24: the deep daylight twin of each hue */
  --frost-hue-blue: #2b5c98;
  --frost-hue-green: #2f5c1f;
  --frost-hue-cyan: #0c627a;
  --frost-hue-violet: #62449d;
  --frost-hue-rose: #9f2c46;
  --frost-hue-orange: #914710;
  --frost-hue-yellow: #6d5a0a;
  --frost-hue-magenta: #8a2d7c;
  --frost-hue-indigo: #4549a8;
  --frost-hue-teal: #156859;
  --frost-hue-lime: #4f6410;

  /* Threads' own Masters, their daylight twins. */
  --frost-hue-lifecycle: #5d3c49;
  --frost-hue-date: #71516e;
  --frost-hue-period: #464b2b;
  --frost-hue-as-at: #65245e;
  --frost-hue-age-band: #7c4f53;
  --frost-hue-category: #551d71;
  --frost-hue-item: #750523;
  --frost-hue-fit: #04510e;
  --frost-hue-fabric-type: #014280;
  --frost-hue-cut-group: #7f2f69;
  --frost-hue-packing: #09641f;
  --frost-hue-parent: #274d5c;
  --frost-hue-kf-prefix: #415785;
  --frost-hue-item-type: #794c27;
  --frost-hue-pattern: #742400;
  --frost-hue-mapping-state: #2a5143;
  --frost-hue-group: #465400;
  --frost-hue-supplier: #6f0942;
  --frost-hue-size-group: #773a10;
  --frost-hue-dispatch: #383780;
  --frost-hue-product: #334a83;
  --frost-hue-family: #4d427f;
  --frost-hue-unfiled: #633970;
  --frost-hue-maps-group: #0d5c33;
  --frost-hue-group-order: #4a4260;
  --frost-hue-access: #8c2d2a;
  --frost-hue-declared: #00527e;
  --frost-hue-menu: #5e4e7f;
  --frost-hue-balance: #5d412d;
  --frost-hue-make: #6a4b1c;
  --frost-hue-price-source: #24507c;
  --frost-hue-price-field: #6b4a00;
  --frost-hue-soft: 12%;
}

/* --- the chosen pill: the Loom's, and the command bar's scope pills -------- */
/* Stark's raised key (§79) and §24's glass chip once chosen, with the filter
   well's chip and its ×, moved here whole from threads-frost-pages.css §1 on
   29 September 2026 (MPF: "make those pill in the command bar the same look
   as our standard pills"). One set of rules for both places, each selector
   an :is() of the Loom's own scope and the bar's pill row, at the Loom's own
   weight — so a Loom page reads exactly as it did, and a future change to
   the pill reaches the bar as well. The Master's colour arrives as
   `--frost-lane` / `--frost-lane-soft`: on the Loom from its root (PHP), in
   the bar from the pill itself (the same getFrostWellHue() map). */
:is(body[data-frost-page~="loom-separate"] .loom-separate-page, body .user-dialog--command-bar .threads-command-bar__scope) .stark-filter-pill,
body.threads-koel .user-dialog .shirt-fabric-links .token-input__pill {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  min-height: 34px;
  padding: 6px 12px;
  border: 1px solid transparent;
  border-radius: var(--stark-radius);
  background: linear-gradient(145deg, var(--stark-card-high), var(--stark-card-low));
  box-shadow: var(--frost-nub-lip), var(--frost-nub-drop);
  color: var(--stark-ink);
  font: inherit;
  font-size: var(--stark-text-note);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: normal;
  text-transform: none;
  cursor: pointer;
  transition: color var(--stark-t-quick) var(--stark-ease), background var(--stark-t-quick) var(--stark-ease), box-shadow var(--stark-t-quick) var(--stark-ease);
}
/* Under the pointer, a third of the pane (§4), on its own underlay. */
:is(body[data-frost-page~="loom-separate"] .loom-separate-page, body .user-dialog--command-bar .threads-command-bar__scope) .stark-filter-pill::before,
body.threads-koel .user-dialog .shirt-fabric-links .token-input__pill::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.94);
  transition: opacity var(--stark-t-settle) var(--stark-ease), transform var(--stark-t-settle) var(--stark-ease);
}
:is(body[data-frost-page~="loom-separate"] .loom-separate-page, body .user-dialog--command-bar .threads-command-bar__scope) .stark-filter-pill:hover::before { opacity: var(--frost-glass-hover); transform: none; }
:is(body[data-frost-page~="loom-separate"] .loom-separate-page, body .user-dialog--command-bar .threads-command-bar__scope) .stark-filter-pill:focus-visible { outline: none; box-shadow: var(--frost-nub-lip), var(--stark-focus-ring), var(--frost-nub-drop); }
/* §24 (queue B): chosen — a glass chip with a whisper of the Master's hue,
   and its small square in that colour standing first. */
:is(body[data-frost-page~="loom-separate"] .loom-separate-page, body .user-dialog--command-bar .threads-command-bar__scope) .stark-filter-pill.is-on,
body.threads-koel .user-dialog .shirt-fabric-links .token-input__pill {
  gap: 7px;
  background: var(--frost-glass-sheen), linear-gradient(var(--frost-lane-soft), var(--frost-lane-soft)), color-mix(in srgb, var(--frost-glass-fill) 55%, transparent);
  box-shadow: var(--frost-glass-shadow);
  color: var(--stark-ink);
}
:is(body[data-frost-page~="loom-separate"] .loom-separate-page, body .user-dialog--command-bar .threads-command-bar__scope) .stark-filter-pill.is-on::after,
body.threads-koel .user-dialog .shirt-fabric-links .token-input__pill::after {
  content: '';
  order: -1;
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--frost-lane);
}
:is(body[data-frost-page~="loom-separate"] .loom-separate-page, body .user-dialog--command-bar .threads-command-bar__scope) .stark-filter-pill.is-on::before,
body.threads-koel .user-dialog .shirt-fabric-links .token-input__pill::before { opacity: 0; }
:is(body[data-frost-page~="loom-separate"] .loom-separate-page, body .user-dialog--command-bar .threads-command-bar__scope) .stark-filter-pill.is-on:hover::before { opacity: var(--frost-glass-hover); }
:is(body[data-frost-page~="loom-separate"] .loom-separate-page, body .user-dialog--command-bar .threads-command-bar__scope) .stark-filter-pill.is-on:focus-visible { box-shadow: var(--frost-glass-shadow), var(--stark-focus-ring); }
:is(body[data-frost-page~="loom-separate"], body .user-dialog--command-bar) .loom-chip { position: relative; display: inline-flex; align-items: center; max-width: 100%; min-width: 0; }
:is(body[data-frost-page~="loom-separate"] .loom-separate-page, body .user-dialog--command-bar .threads-command-bar__scope) .loom-chip__face { gap: 7px; min-width: 0; max-width: 100%; }
:is(body[data-frost-page~="loom-separate"], body .user-dialog--command-bar) .loom-chip__x {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  margin-left: 1px;
  border-radius: 50%;
  color: var(--stark-muted);
  font-size: 14px;
  line-height: 1;
  transition: color var(--fade, var(--stark-t-quick)) ease-out, background-color var(--fade, var(--stark-t-quick)) ease-out;
}
:is(body[data-frost-page~="loom-separate"], body .user-dialog--command-bar) .loom-chip__face:is(:hover, :focus-visible) .loom-chip__x { color: var(--stark-ink); background: color-mix(in srgb, var(--stark-ink) 12%, transparent); }
/* The bar's own two words for it. Its pill row stands where the Loom's root
   would, so it names the Loom root's resting lane (a screen's chip, which is
   no Master, keeps that quiet square); each scope pill then carries its
   Master's hue as `--frost-lane` (threads-production-command-bar.js, from
   the getFrostWellHue() map on the dialog) and takes its whisper here, in
   the Loom's own mix. `--fade` is the Loom root's beat; outside a Loom page
   the × falls back to Stark's quick beat. */
/* The Fabrics Edit box's Linked Items wear the lit Loom pill (MPF, 16 Oct 2026, "do the small fixes", point 9): the same
   rules above, listed beside the Loom's and the bar's, not a copy. A linked Item is an Item, so its square and whisper are
   the Item Master's hue, as the Loom's Item well draws them; the field's own × stays its own key. */
body.threads-koel .user-dialog .shirt-fabric-links {
  --frost-lane: var(--frost-hue-item);
  --frost-lane-soft: color-mix(in srgb, var(--frost-lane) var(--frost-hue-soft), transparent);
}
body.threads-koel .user-dialog .shirt-fabric-links .token-input__pill { line-height: 1.25; white-space: nowrap; }
body.threads-koel .user-dialog--command-bar .threads-command-bar__scope {
  --frost-lane: var(--stark-line-lit);
  --frost-lane-soft: transparent;
}
body.threads-koel .user-dialog--command-bar .threads-command-bar__scope .loom-chip[data-threads-command-bar-pill] {
  --frost-lane-soft: color-mix(in srgb, var(--frost-lane) var(--frost-hue-soft), transparent);
}

/* --- the command bar: a glass dialog (frost.css §18) ---------------------- */
/* The dialog skeleton is Threads', and its rows are the house dropdown's
   (stage 5 re-dresses those everywhere at once). Here its frame becomes the
   kit's glass sheet: the drop-down's whole tint (a dialog is no more
   blurrable than a sheet here, and at the kit's 86% the filter board under
   it read through — seen at the look, 28 Sep 2026), the lit rim and edge,
   the sheet's drop, 5px corners; its header drops Koel's quieter band onto
   the same glass. */
body.threads-koel .user-dialog--command-bar .user-dialog-surface {
  border: 0;
  border-radius: var(--stark-radius);
  background: var(--frost-list-sheen), var(--frost-sheet-tint);
  box-shadow: var(--frost-glass-settled), var(--frost-list-drop);
}
body.threads-koel .user-dialog--command-bar .user-dialog-header {
  border-bottom-color: var(--frost-glass-edge);
  border-radius: var(--stark-radius) var(--stark-radius) 0 0;
  background: transparent;
}
/* THE ROWS (kit §13 and Stark's `.stark-select-list--command`). MPF, 29 Sep
   2026, looking at it: "the highlighted row isn't very clear". The house
   dropdown lights the row its keys hold by `.is-keyboard-active` and leaves
   `aria-selected` for the CHOSEN row, marked and not filled; the bar has no
   chosen row — a row is only ever walked (Stark: "nothing is chosen in a
   command bar") — so here `aria-selected` IS the walked row and takes the
   whole pane, its name in the accent and its path up to the legend's tone
   with it ("one row lighting in two colours would read as two rows"). The
   walked row stays whole under the pointer too (kit §13: "the active row is
   always the whole pane"); any other row under the pointer takes a third,
   which is the house rule already. Each name sat in a dark well of its own
   until today; that box is gone — a name is a word on the glass, and only
   the letters that answer the typed text take the accent. */
body.threads-koel .user-dialog--command-bar .threads-select__options > .threads-select__option[aria-selected="true"],
body.threads-koel .user-dialog--command-bar .threads-select__options > .threads-select__option[aria-selected="true"]:hover {
  background: var(--frost-pane-whole);
  box-shadow: var(--frost-glass-shadow);
  color: var(--stark-accent);
}
body.threads-koel .user-dialog--command-bar .threads-select__options > .threads-select__option:active {
  background: var(--frost-pane-press);
  box-shadow: var(--frost-glass-settled);
}
body.threads-koel .user-dialog--command-bar .threads-command-bar__label { color: inherit; }
/* Only the colour: the house <mark> (the table search's) also pads and
   bolds, which spread "Dispatch by Item" apart letter-group by group. */
body.threads-koel .user-dialog--command-bar .threads-command-bar__label mark {
  padding: 0;
  border-radius: 0;
  background: none;
  color: var(--stark-accent);
  font-weight: inherit;
}
body.threads-koel .user-dialog--command-bar .threads-select__option[aria-selected="true"] :is(.threads-command-bar__path, .threads-command-bar__hint) { color: var(--stark-legend); }

/* The box is the house dropdown's own search (§27): a line, lit in the
   accent while it is being typed in. Left out of §27's panel rule because
   the bar is a dialog and not a panel, it stood as Koel's dark well — in
   daylight a black slab across a light sheet. */
body.threads-koel .user-dialog--command-bar .threads-select__search {
  padding-inline: 4px;
  border-color: transparent;
  border-bottom-color: var(--frost-field-line);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel .user-dialog--command-bar .threads-select__search:hover { border-bottom-color: var(--frost-field-line-lit); }
body.threads-koel .user-dialog--command-bar .threads-select__search:is(:focus, :focus-visible) {
  outline: none;
  border-color: transparent;
  border-bottom-color: var(--stark-accent);
  box-shadow: 0 1px 0 var(--stark-accent);
}

/* The keys' legend on the foot (Stark's `.stark-command-legend`): what
   Return does now, in plain words, muted like the path words. */
body.threads-koel .user-dialog--command-bar .threads-command-bar__legend { color: var(--stark-muted); }

/* The keys' legend, at the start of the bar's foot (Stark's command bar reads
   its legends left to right from the list's foot, the keys keeping the end).
   It takes the free space so Cancel and Open stay where every dialog keeps
   them, and on a phone it goes — there is no Return to press there, as the kit
   says of its own legends at 480px. Moved here from koel.css on the
   makeover's review (29 Sep 2026): a look change lives in the Frost sheet,
   on the kit's type scale. */
body.threads-koel .user-dialog--command-bar .threads-command-bar__legend {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0 auto 0 0;
  font-size: var(--stark-text-micro);
  line-height: 1.35;
}
@media (max-width: 480px) {
  body.threads-koel .user-dialog--command-bar .threads-command-bar__legend { display: none; }
}

/* --- a phone --------------------------------------------------------------- */
/* Koel's 760px rules keep their paddings and sizes. Two things are Frost's.
   The section keys drop their capitals: set uppercase, an administrator's
   five sections measured 415px in a 363px bar at the look (28 Sep 2026) and
   "Cut Piece" slid under the find key, where Koel's sentence case keeps them
   one row as Koel designed it. And the find key, which stays put at the
   right while the sections swipe under it, stands on the strip's own card so
   they never show through (Koel painted it its rail colour for the same
   reason). */
@media (max-width: 760px) {
  body.threads-koel .koel-menubar:not(.koel-menubar--families) .navigation-link {
    letter-spacing: 0;
    text-transform: none;
  }
  body.threads-koel .koel-menubar .navigation-menu > li:has(> .koel-menubar__search) { background: var(--frost-card-low); }
}

/* Reduce Motion: every change is simply there. */
@media (prefers-reduced-motion: reduce) {
  body.threads-koel .koel-menubar .navigation-link::before,
  body.threads-koel .navigation-submenu__link::before,
  body.threads-koel .navigation-account-preferences::before,
  body.threads-koel .navigation-logout::before { transition: none; }
}


/* =============================================== 15. DASHBOARDS AND HOME */
/* Spec stage 6. MPF, 28 September 2026: "next lets do the menu and the
   homepage". Home's family tiles, the six family dashboards' figure strips
   (renderStat(), renderReportLink(), includes/koel-dashboard.php), the
   pipeline, the Requirement splits and the page glyph. The kit has no
   dashboard (spec §0 inventory: "no counterpart yet"), so each is Frost's
   own grammar put on the Threads piece: a tile is Stark's matte paper card
   (frost.css: "cards, fields, forms stay Stark's matte paper"); a tile that
   is a door is ONE KEY, so it climbs Frost's ladder — a pane of glass laid on
   the paper, a third under the pointer, two thirds pressed, the 1px accent
   ring for focus; a well is pressed into the paper; a lamp is Stark's small
   square with no glow.

   THE PRESSURE TILT IS KEPT (spec stage 6). koel-card-pressure.js writes the
   pointer's place and the tilt onto the card; application.css turns the card
   in perspective under the pointer and sinks it on press. None of that is
   said again here — only the two boxes it draws on change material: the
   card's `::before`, its face, becomes paper; its `::after`, the pointer
   halo, becomes the ladder's pane (a halo is a glow, Frost rule 7). */

/* --- the face: Stark's paper card ---------------------------------------- */
body.threads-koel .koel-page [data-card-look="pressure"]:is(.koel-stat, .koel-product, .koel-split)::before {
  border: 1px solid var(--stark-card-edge);
  border-radius: var(--stark-radius);
  background: linear-gradient(145deg, var(--stark-card-high), var(--stark-card-low));
  box-shadow: var(--frost-tile-shadow);
}
/* Under the pointer the card sinks 2px towards the floor (the tilt), so its
   drop shortens with it, as production's own hover says. */
@media (hover: hover) and (pointer: fine) {
  body.threads-koel .koel-page a[data-card-look="pressure"]:hover::before { box-shadow: var(--frost-tile-shadow-near); }
}

/* --- the key: the ladder's pane on the paper ------------------------------ */
body.threads-koel .koel-page [data-card-look="pressure"]:is(.koel-stat, .koel-product, .koel-split)::after {
  border: 0;
  border-radius: var(--stark-radius);
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
}
@media (hover: hover) and (pointer: fine) {
  body.threads-koel .koel-page a[data-card-look="pressure"]:hover::after { opacity: var(--frost-glass-hover); }
}
body.threads-koel .koel-page a[data-card-look="pressure"]:active::after {
  opacity: var(--frost-glass-press);
  box-shadow: var(--frost-glass-settled);
}
/* Focus: the 1px accent ring, never production's 2px halo (Frost rule 7). */
body.threads-koel .koel-page a[data-card-look="pressure"]:focus-visible {
  outline: 1px solid var(--stark-accent);
  outline-offset: 3px;
}
body.threads-koel .koel-page a[data-card-look="pressure"]:focus-visible::after { opacity: var(--frost-glass-hover); }

/* --- a figure tile --------------------------------------------------------- */
/* The label is a label (Frost §19: labels hold 4.5:1 in the legend tone),
   spaced as Stark's eyebrow; the figure stays ink, a negative one the §19
   figure red that holds 7:1 on the paper. */
body.threads-koel .koel-stat__label {
  color: var(--stark-legend);
  letter-spacing: .12em;
}
body.threads-koel .koel-stat__value { color: var(--stark-ink); }
body.threads-koel .koel-stat__value--negative { color: var(--frost-neg); }
body.threads-koel .koel-stat__hint { color: var(--stark-muted); }
/* The lamp: Stark's 5px square, lit in its state's colour, no glow. */
body.threads-koel .koel-stat__lamp {
  border-radius: calc(var(--stark-radius) - 3px);
  box-shadow: none;
}
body.threads-koel .koel-stat__lamp--success { background: var(--success); }
body.threads-koel .koel-stat__lamp--error { background: var(--stark-danger); }

/* --- the pipeline: a well pressed into the floor, the accent run in it ---- */
body.threads-koel .koel-pipeline__track {
  border: 0;
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
}
body.threads-koel .koel-pipeline__fill {
  background: var(--stark-accent);
  box-shadow: inset 0 1px 0 var(--frost-glass-rim);
}
body.threads-koel .koel-pipeline__legend { color: var(--stark-muted); }
body.threads-koel .koel-pipeline__legend strong { color: var(--stark-ink); }
body.threads-koel .koel-pipeline__percent {
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
  color: var(--stark-accent);
}

/* --- the Requirement splits ------------------------------------------------ */
body.threads-koel .koel-split__title { color: var(--stark-legend); letter-spacing: .12em; }
body.threads-koel .koel-split__track { stroke: var(--stark-well); }
body.threads-koel .koel-split__name { color: var(--stark-muted); }
body.threads-koel .koel-split__share { color: var(--stark-ink); }
body.threads-koel .koel-split__empty { color: var(--stark-stone); }

/* --- the page's glyph: a well holding the family's drawing ---------------- */
body.threads-koel .koel-page-glyph {
  border: 0;
  border-radius: var(--stark-radius);
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
  --ka-ink: var(--stark-muted);
  --ka-accent: var(--stark-accent);
}

/* --- a dashboard's section headings --------------------------------------- */
/* Labels on the leather (Frost §19's floor label). Home's two group headings
   keep the accent — MPF's idea, 29 August 2026 — from their own, heavier
   rule in koel.css. */
body.threads-koel .koel-section__title { color: var(--frost-floor-label); }

/* --- Home's family tiles ----------------------------------------------------- */
body.threads-koel .koel-product__glyph {
  --ka-ink: var(--stark-muted);
  --ka-accent: var(--stark-accent);
}
body.threads-koel a.koel-product:hover .koel-product__glyph { --ka-ink: var(--stark-ink); }
body.threads-koel .koel-product__name { color: var(--stark-ink); }
body.threads-koel .koel-product__hint { color: var(--stark-muted); }
/* A family Threads does not carry yet has no door: Koel sat it in the floor
   rather than on it ("a key you cannot press should not pretend
   otherwise"), and so does Frost — the face is a well pressed into the
   leather, its words the quiet tones. */
body.threads-koel .koel-page .koel-product--inert[data-card-look="pressure"]::before {
  border-color: transparent;
  background: var(--stark-sink);
  box-shadow: var(--frost-press-well);
}
body.threads-koel .koel-product--inert .koel-product__glyph { --ka-ink: var(--stark-stone); }
body.threads-koel .koel-product--inert .koel-product__name { color: var(--stark-muted); }
body.threads-koel .koel-product--inert .koel-product__hint { color: var(--stark-stone); }

@media (prefers-reduced-motion: reduce) {
  body.threads-koel .koel-page [data-card-look="pressure"]:is(.koel-stat, .koel-product, .koel-split)::after { transition: none; }
}


/* ============================================================ 16. THE MARK */
/* MPF, 28 September 2026: "put the new logo in" — option B, the bolt of cloth
   (spec, "The new mark"). The server tells browsers to keep a PNG for a year
   (public/.htaccess), so a reader who has seen the old emblem would go on
   seeing it at the old address. The new drawing lives under its own folder,
   `cloth-bolt/` — an address no browser has kept, with no query string (rule
   62) — and the PDF footer asks for the same folder (footerEmblemURL(),
   threads-production-reports.js), so screen and file agree. The bare files
   hold B too, for anything still asking by the old address. Same selectors
   as production's accent blocks, so each ties and wins by order. */
:root { --threads-emblem-image: url("assets/glyphs/cloth-bolt/threads-emblem-burgundy.png"); }
:root[data-accent="purple"] { --threads-emblem-image: url("assets/glyphs/cloth-bolt/threads-emblem-purple.png"); }
:root[data-accent="green"] { --threads-emblem-image: url("assets/glyphs/cloth-bolt/threads-emblem-green.png"); }
:root[data-accent="orange"] { --threads-emblem-image: url("assets/glyphs/cloth-bolt/threads-emblem-orange.png"); }
:root[data-accent="blue"] { --threads-emblem-image: url("assets/glyphs/cloth-bolt/threads-emblem-blue.png"); }
:root[data-accent="yellow"] { --threads-emblem-image: url("assets/glyphs/cloth-bolt/threads-emblem-yellow.png"); }


/* ============================================ 17. MY PREFERENCES (stage 7) */
/* MPF, 28 September 2026: "redesign the user's preferences page similar to
   what we did with Artha billing and give the theme options there". The one
   planned break in the spec's §1 markup guard: Preferences draws Frost's own
   theme and mode switch (Artha's /preferences, itself the kit's
   `Artha Frost/index.html`) and a word switch for the wallpaper. Copied from
   the kit's frost.css §4 (the ladder), §7 (the switch, the chip, the name
   slot) and §23 (the switch in a card, a finger tall on a phone), re-stated
   on Threads' scope rather than Stark's `.stark-kit`, which Threads never
   draws. Sizes are the kit's switch's own: it has no Threads counterpart. */

/* The swatch chips: each theme's own card, dark half then light half, with
   its accent — the same in every theme and mode (frost.css §2, verbatim). */
:root {
  --frost-sw-original: #32302b;  --frost-sw-original-l: #f5f0e6;  --frost-sw-original-a: #f0b429;
  --frost-sw-charcoal: #2f3134;  --frost-sw-charcoal-l: #f2f3f5;  --frost-sw-charcoal-a: #f5c552;
  --frost-sw-purple: #2e2640;    --frost-sw-purple-l: #f3eff6;    --frost-sw-purple-a: #e9c678;
  --frost-sw-burgundy: #35222b;  --frost-sw-burgundy-l: #f6eff0;  --frost-sw-burgundy-a: #f2b39f;
  --frost-sw-navy: #1f2939;      --frost-sw-navy-l: #f0f3f7;      --frost-sw-navy-a: #dcb866;
  --frost-sw-camel: #5c4433;     --frost-sw-camel-l: #f4dfca;     --frost-sw-camel-a: #fcd59d;
  --frost-sw-chocolate: #342a23; --frost-sw-chocolate-l: #fceee3; --frost-sw-chocolate-a: #f0b429;
}

/* --- the page: a heading card, then Artha's pair ------------------------- */
/* `.stark-app-pair` (stark.css §3), 1.6fr beside 1fr, stacking full width
   under 900px. ONE GAP BETWEEN EVERY CARD ON THE PAGE, said once as a token
   (MPF, 28 Sep 2026, of the Export theme card: "too close bud" — it touched
   the Theme card while the heading card stood 18px above the pair): the
   page is a grid of its rows and the pair a grid of its two cards, both on
   `--preferences-card-gap`, so heading → pair, pair → Export theme and
   Theme ↔ Display Pic (side by side, or stacked on a phone) are one number. */
body.threads-koel .preferences-look {
  --preferences-card-gap: 18px;
  display: grid;
  gap: var(--preferences-card-gap);
}
body.threads-koel .preferences-pair {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: var(--preferences-card-gap);
  /* Both cards the row's height, so the Display Pic card's foot stands on
     the same line as the Theme card's and the gap under the pair is one gap
     under both columns. */
  align-items: stretch;
}
@media (max-width: 900px) {
  body.threads-koel .preferences-pair { grid-template-columns: minmax(0, 1fr); }
}
body.threads-koel .preferences-card-title {
  margin: 0 0 6px;
  color: var(--stark-ink);
  font-size: 17px;
  font-weight: 700;
}
body.threads-koel .preferences-look-keys {
  display: grid;
  gap: 14px;
  margin: 18px 0 14px;
}
/* The wallpaper's label: Stark's strip label, a legend word before the keys. */
body.threads-koel .preferences-wallpaper { display: grid; gap: 6px; }
body.threads-koel .preferences-wallpaper__label {
  color: var(--stark-legend);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
}
body.threads-koel .preferences-look .preferences-form { margin-top: 14px; }

/* --- the switch (frost.css §7) ------------------------------------------- */
body.threads-koel .frost-switch { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; }

/* A switch key is Stark's word key (stark.css, `.stark-kit button`) at the
   switch's toolbar size, climbing Frost's ladder (§4) on its `::before`. */
body.threads-koel .frost-switch > button {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 40px;
  padding: 8px 16px;
  font: inherit;
  font-size: var(--stark-text-button);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: var(--frost-key-r);
  color: var(--stark-muted);
  background: none;
  box-shadow: none;
  text-shadow: var(--frost-press-glass);
  transition: color var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel .frost-switch--themes > button { padding-inline: 13px; }
body.threads-koel .frost-switch > button::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.94);
  pointer-events: none;
  transition:
    opacity var(--stark-t-settle) var(--stark-ease),
    transform var(--stark-t-settle) var(--stark-ease),
    box-shadow var(--stark-t-quick) var(--stark-ease);
}
/* hover and keyboard focus — a third of the pane, the word to ink */
body.threads-koel .frost-switch > button:is(:hover, :focus-visible) { color: var(--stark-ink); }
body.threads-koel .frost-switch > button:is(:hover, :focus-visible)::before {
  opacity: var(--frost-glass-hover);
  transform: none;
}
/* press — two thirds, settled 1px, the drop gone, on the `tap` rung */
body.threads-koel .frost-switch > button:active::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
  transition-duration: var(--stark-t-tap);
}
/* picked — the whole pane, lifted, the word in the accent */
body.threads-koel .frost-switch > button[aria-pressed="true"] { color: var(--stark-accent); }
body.threads-koel .frost-switch > button[aria-pressed="true"]::before,
body.threads-koel .frost-switch > button[aria-pressed="true"]:active::before {
  opacity: 1;
  transform: none;
  box-shadow: var(--frost-glass-shadow);
}
/* focus — a 1px accent ring round the key, never a glow (Frost rule 7) */
body.threads-koel .frost-switch > button:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }

/* A theme's chip: its dark card, its light card, and its accent between. */
body.threads-koel .frost-chip {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background:
    radial-gradient(circle, var(--chip-a) 0 2.5px, transparent 3px),
    linear-gradient(135deg, var(--chip-d) 50%, var(--chip-l) 50%);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--stark-ink) 22%, transparent);
}
body.threads-koel .frost-chip[data-chip="original"] { --chip-d: var(--frost-sw-original); --chip-l: var(--frost-sw-original-l); --chip-a: var(--frost-sw-original-a); }
body.threads-koel .frost-chip[data-chip="charcoal"] { --chip-d: var(--frost-sw-charcoal); --chip-l: var(--frost-sw-charcoal-l); --chip-a: var(--frost-sw-charcoal-a); }
body.threads-koel .frost-chip[data-chip="purple"]   { --chip-d: var(--frost-sw-purple);   --chip-l: var(--frost-sw-purple-l);   --chip-a: var(--frost-sw-purple-a); }
body.threads-koel .frost-chip[data-chip="burgundy"] { --chip-d: var(--frost-sw-burgundy); --chip-l: var(--frost-sw-burgundy-l); --chip-a: var(--frost-sw-burgundy-a); }
body.threads-koel .frost-chip[data-chip="navy"]     { --chip-d: var(--frost-sw-navy);     --chip-l: var(--frost-sw-navy-l);     --chip-a: var(--frost-sw-navy-a); }
body.threads-koel .frost-chip[data-chip="camel"]    { --chip-d: var(--frost-sw-camel);    --chip-l: var(--frost-sw-camel-l);    --chip-a: var(--frost-sw-camel-a); }
body.threads-koel .frost-chip[data-chip="chocolate"] { --chip-d: var(--frost-sw-chocolate); --chip-l: var(--frost-sw-chocolate-l); --chip-a: var(--frost-sw-chocolate-a); }

body.threads-koel .frost-glyph { flex: 0 0 auto; width: 16px; height: 16px; display: block; }

/* Only the picked theme says its name, in a slot of its own before the seven
   chips: all seven stacked in one grid cell, only the one <html> names shown,
   so the slot is the widest name's width and a pick moves nothing. */
body.threads-koel .frost-theme-name {
  display: inline-grid;
  justify-items: end;
  margin-right: 8px;
  font-size: var(--stark-text-button);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--stark-accent);
  text-shadow: var(--frost-press-glass);
}
body.threads-koel .frost-theme-name > span { grid-area: 1 / 1; visibility: hidden; }
:root:not([data-frost-theme]) body.threads-koel .frost-theme-name > [data-frost-name="original"],
:root[data-frost-theme="original"] body.threads-koel .frost-theme-name > [data-frost-name="original"],
:root[data-frost-theme="charcoal"] body.threads-koel .frost-theme-name > [data-frost-name="charcoal"],
:root[data-frost-theme="purple"] body.threads-koel .frost-theme-name > [data-frost-name="purple"],
:root[data-frost-theme="burgundy"] body.threads-koel .frost-theme-name > [data-frost-name="burgundy"],
:root[data-frost-theme="navy"] body.threads-koel .frost-theme-name > [data-frost-name="navy"],
:root[data-frost-theme="camel"] body.threads-koel .frost-theme-name > [data-frost-name="camel"],
:root[data-frost-theme="chocolate"] body.threads-koel .frost-theme-name > [data-frost-name="chocolate"] { visibility: visible; }

/* --- the phone (frost.css §7's 600px rule and §23) ------------------------ */
/* The switch asks its own width, so a card is judged by the card: when the
   name and seven chips no longer fit on one line, the name takes a line of its
   own above them, at the left, and the chips stay together under it. It
   Asked of the window here, not of the switch as the kit's container query
   does: a container is a containing block for fixed descendants, which the
   spec's §1 guard keeps off every Threads box. The card is under 344px
   exactly when the window is a phone's (the pair stacks under 900px). */
@media (max-width: 480px) {
  body.threads-koel .frost-switch--themes > .frost-theme-name { flex: 0 0 100%; justify-items: start; margin: 0 0 2px; }
  body.threads-koel .frost-switch--themes > button:last-child { margin-right: auto; }
}
/* A finger tall on a phone or under any coarse pointer (stark.css §56). */
@media (max-width: 480px), (pointer: coarse) {
  body.threads-koel .frost-switch > button { min-height: 44px; }
}

/* --- the Export theme card (administrators; MPF, 28 Sep 2026) ------------- */
/* A picture per set, copied from the mockup MPF chose from
   (logo-preview-tmp/export-colours.html): a sheet of paper with the set's
   heading row, a plain and a shaded row, the closing rule and the footer's
   mark. The set's colours arrive inline as `--export-*` from
   ApplicationSettingsService::EXPORT_THEMES; the paper is white and the
   negative red one colour in every set, as the files print them. Each
   picture is a switch key: its ladder pane is §4's, its picked state the
   whole pane and the name in the accent. */
:root { --export-paper: #ffffff; --export-negative: #b3261e; }
body.threads-koel .export-theme-choices {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* 12px read as crowded (MPF, 28 Sep 2026: "the cards are sitting too close
     to each other"); 20px lets each picture stand as its own card. */
  gap: 20px;
  margin: 16px 0 12px;
}
@media (max-width: 900px) {
  body.threads-koel .export-theme-choices { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* One across on a phone (review, 28 Sep 2026): two across left each picture
   155px and its item column 26px, so every name was an ellipsis. */
@media (max-width: 480px) {
  body.threads-koel .export-theme-choices { grid-template-columns: minmax(0, 1fr); }
}
body.threads-koel .export-theme-choice {
  position: relative;
  isolation: isolate;
  display: grid;
  gap: 8px;
  min-width: 0;
  padding: 10px;
  font: inherit;
  text-align: left;
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: var(--stark-radius);
  background: none;
  box-shadow: none;
  color: var(--stark-muted);
  transition: color var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel .export-theme-choice::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.97);
  pointer-events: none;
  transition:
    opacity var(--stark-t-settle) var(--stark-ease),
    transform var(--stark-t-settle) var(--stark-ease);
}
body.threads-koel .export-theme-choice:is(:hover, :focus-visible) { color: var(--stark-ink); }
body.threads-koel .export-theme-choice:is(:hover, :focus-visible)::before { opacity: var(--frost-glass-hover); transform: none; }
body.threads-koel .export-theme-choice:active::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
  transition-duration: var(--stark-t-tap);
}
body.threads-koel .export-theme-choice[aria-pressed="true"] { color: var(--stark-accent); }
body.threads-koel .export-theme-choice[aria-pressed="true"]::before { opacity: 1; transform: none; box-shadow: var(--frost-glass-shadow), 0 0 0 1px var(--stark-accent); }
body.threads-koel .export-theme-choice:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }

body.threads-koel .export-theme-choice__paper {
  display: grid;
  padding: 10px 10px 6px;
  border-radius: 3px;
  background: var(--export-paper);
  color: var(--export-text);
  font-size: 10px;
  line-height: 1.2;
  box-shadow: var(--frost-glass-lift);
}
body.threads-koel .export-theme-choice__line {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 6px;
  padding: 4px 5px;
  border: .5px solid var(--export-border);
  border-top-width: 0;
}
body.threads-koel .export-theme-choice__line > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
body.threads-koel .export-theme-choice__line > span + span { text-align: right; min-width: 3.2em; }
body.threads-koel .export-theme-choice__line--heading {
  border-top-width: .5px;
  background: var(--export-heading);
  color: var(--export-heading-text);
  font-weight: 700;
}
body.threads-koel .export-theme-choice__line--shaded { background: var(--export-shade); }
body.threads-koel .export-theme-choice__line--total {
  border-top: 1.5px solid var(--export-rule);
  color: var(--export-rule);
  font-weight: 700;
}
body.threads-koel .export-theme-choice__negative { color: var(--export-negative); }
body.threads-koel .export-theme-choice__foot {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 6px;
  color: var(--export-text);
  font-size: 9px;
  font-weight: 700;
}
body.threads-koel .export-theme-choice__foot svg { width: 12px; height: 12px; color: var(--export-emblem); }
body.threads-koel .export-theme-choice__name {
  font-size: var(--stark-text-micro);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-shadow: var(--frost-press-glass);
}

/* --- the Display Pic well and Stark's emoji picker (MPF, 28 Sep 2026) ------ */
/* "the well doesn't look right to me and clicking it doesn't open the emoji
   picker like it does in artha". The well is Artha's `.artha-emoji-well`
   (artha-app.css), renamed to Threads': the kit's well material —
   `--stark-well` pressed with Frost's `--frost-press-well` — sized for one
   big glyph, never wider than its card. Koel's black field inset goes; every
   colour is a theme token, so it reads in all ten themes. The same class
   draws an administrator's trigger and everybody else's read-only glyph. */
body.threads-koel .threads-emoji-well {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: 100%;
  min-height: 112px;
  box-sizing: border-box;
  padding: 0;
  font-size: 96px;
  line-height: 1;
  color: var(--stark-ink);
  background: var(--stark-well);
  border: 0;
  border-radius: var(--stark-radius);
  box-shadow: var(--frost-press-well);
  overflow: hidden;
}
/* The trigger inside the well (artha-app.css, "THE TRIGGER, INSIDE THE
   WELL"): no line, no fill, no chevron — the well is its own material and the
   glyph is the value. A breath of the glass pane under the pointer, and
   Frost's 1px accent ring for the keyboard. */
body.threads-koel .threads-emoji-well .stark-emoji-well-face {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 112px;
  border: 0;
  outline: none;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: inherit;
  line-height: inherit;
  padding: 8px 16px;
  cursor: pointer;
  border-radius: inherit;
  box-shadow: none;
  transition: background-color var(--stark-t-move) var(--stark-ease);
}
body.threads-koel .threads-emoji-well .stark-emoji-well-face:hover { background: var(--frost-glass-fill); }
body.threads-koel .threads-emoji-well .stark-emoji-well-face:focus-visible {
  background: var(--frost-glass-fill);
  box-shadow: inset 0 0 0 1px var(--stark-accent);
}

/* The box's tokens (frost.css §18, "glass that floats"), copied value for
   value: the floor under a box, the glass frame and the paper sheet inside
   it, and Stark's arrival rung. */
:root {
  --stark-t-arrive: 650ms;
  --frost-scrim: color-mix(in srgb, var(--frost-floor) 62%, transparent);
  --frost-scrim-filter: blur(4px) saturate(90%);
  --frost-frame: 8px;
  --frost-frame-tint: color-mix(in srgb, var(--frost-card-low) 56%, transparent);
  --frost-frame-fill: var(--frost-glass-fill);
  --frost-sheet: color-mix(in srgb, var(--frost-card-high) 55%, var(--frost-card-low));
  --frost-sheet-line: var(--frost-card-edge);
}
:root[data-frost-mode="light"] {
  --frost-scrim: color-mix(in srgb, var(--frost-ink) 24%, transparent);
  --frost-scrim-filter: blur(4px) saturate(80%);
  --frost-frame-tint: color-mix(in srgb, var(--frost-card-high) 54%, transparent);
  --frost-frame-fill: transparent;
  --frost-sheet-line: color-mix(in srgb, var(--frost-ink) 14%, transparent);
}
@media (max-width: 480px) { :root { --frost-frame: 6px; } }

/* THE DIALOG (stark.css §13, frost.css §18): a glass frame round one paper
   sheet, on a soft floor. It hangs from <body>, so nothing here sits on an
   ancestor of any fixed panel. */
body.threads-koel .stark-dialog {
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--stark-ink);
  font: inherit;
  max-height: calc(100dvh - 32px);
  overflow: visible;
}
body.threads-koel .stark-dialog::backdrop {
  background: var(--frost-scrim);
  -webkit-backdrop-filter: var(--frost-scrim-filter);
  backdrop-filter: var(--frost-scrim-filter);
}
@keyframes stark-dialog-in { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes stark-dialog-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(8px) scale(.99); } }
@keyframes stark-backdrop-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes stark-backdrop-out { from { opacity: 1; } to { opacity: 0; } }
body.threads-koel .stark-dialog[open] > .stark-dialog-surface { animation: stark-dialog-in var(--stark-t-arrive) var(--stark-ease) both; }
body.threads-koel .stark-dialog[open]::backdrop { animation: stark-backdrop-in var(--stark-t-settle) var(--stark-ease) both; }
body.threads-koel .stark-dialog[data-closing] > .stark-dialog-surface { animation: stark-dialog-out var(--stark-t-move) var(--stark-ease) both; }
body.threads-koel .stark-dialog[data-closing]::backdrop { animation: stark-backdrop-out var(--stark-t-move) var(--stark-ease) both; }
@media (prefers-reduced-motion: reduce) {
  body.threads-koel .stark-dialog[open] > .stark-dialog-surface,
  body.threads-koel .stark-dialog[open]::backdrop,
  body.threads-koel .stark-dialog[data-closing] > .stark-dialog-surface,
  body.threads-koel .stark-dialog[data-closing]::backdrop { animation: none; }
}
body.threads-koel .stark-dialog-surface {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  max-height: calc(100dvh - 32px);
  overflow: hidden;
  border: 1px solid var(--stark-card-edge);
  border-radius: var(--stark-radius);
  background: none;
  box-shadow: var(--frost-glass-settled), var(--frost-list-drop);
}
/* The frame's glass on an underlay, as every Threads glass is (spec §1: never
   a filter on a box that could hold a fixed panel). */
body.threads-koel .stark-dialog-surface::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-list-sheen), linear-gradient(var(--frost-frame-fill), var(--frost-frame-fill)), var(--frost-frame-tint);
  -webkit-backdrop-filter: var(--frost-list-filter);
  backdrop-filter: var(--frost-list-filter);
  pointer-events: none;
}
body.threads-koel .stark-dialog-header {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin: var(--frost-frame) var(--frost-frame) -1px;
  padding: calc(18px - var(--frost-frame)) calc(20px - var(--frost-frame)) 14px;
  border-radius: var(--stark-radius) var(--stark-radius) 0 0;
  background: var(--frost-sheet);
  box-shadow: inset 0 1px 0 var(--frost-card-lip), 0 -1px 0 var(--frost-sheet-line), inset 1px 0 0 var(--frost-sheet-line), inset -1px 0 0 var(--frost-sheet-line);
}
body.threads-koel .stark-dialog-heading { min-width: 0; }
body.threads-koel .stark-dialog-heading h2 { margin: 0 0 4px; font-size: 20px; color: var(--stark-accent); }
/* The ×: a key on the ladder, a glyph one character wide with no tracking. */
body.threads-koel .stark-dialog-close {
  position: relative;
  isolation: isolate;
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  min-height: 36px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--frost-key-r);
  background: none;
  box-shadow: none;
  color: var(--stark-muted);
  font: inherit;
  font-size: 18px;
  line-height: 1;
  letter-spacing: normal;
  cursor: pointer;
  transition: color var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel .stark-dialog-close::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.94);
  pointer-events: none;
  transition: opacity var(--stark-t-settle) var(--stark-ease), transform var(--stark-t-settle) var(--stark-ease);
}
body.threads-koel .stark-dialog-close:is(:hover, :focus-visible) { color: var(--stark-ink); }
body.threads-koel .stark-dialog-close:is(:hover, :focus-visible)::before { opacity: var(--frost-glass-hover); transform: none; }
body.threads-koel .stark-dialog-close:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }
body.threads-koel .stark-dialog-body {
  position: relative;
  min-height: 0;
  margin-inline: var(--frost-frame);
  margin-bottom: var(--frost-frame);
  padding: 19px calc(10px - var(--frost-frame)) 13px;
  border-radius: 0 0 var(--stark-radius) var(--stark-radius);
  background: var(--frost-sheet);
  box-shadow: 0 1px 0 var(--frost-sheet-line), inset 1px 0 0 var(--frost-sheet-line), inset -1px 0 0 var(--frost-sheet-line);
  scrollbar-gutter: stable both-edges;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--stark-line) transparent;
}

/* THE PICKER (stark.css §93). The frame is the one child the surface's
   second row expects; the search line, the category row and the scrolling
   grid stand in it. Sheet-coloured so the frame's glass shows only round
   the edge, as Frost's dialog does. */
body.threads-koel .stark-emoji-picker { width: min(700px, calc(100vw - 32px)); }
body.threads-koel .stark-emoji-frame {
  display: flex;
  flex-direction: column;
  min-height: 0;
  margin-inline: var(--frost-frame);
  margin-bottom: var(--frost-frame);
  border-radius: 0 0 var(--stark-radius) var(--stark-radius);
  background: var(--frost-sheet);
  box-shadow: 0 1px 0 var(--frost-sheet-line), inset 1px 0 0 var(--frost-sheet-line), inset -1px 0 0 var(--frost-sheet-line);
}
body.threads-koel .stark-emoji-frame > .stark-emoji-body {
  flex: 1 1 auto;
  min-height: 0;
  height: min(52vh, 480px);
  margin: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  box-shadow: none;
  overscroll-behavior: contain;
}
body.threads-koel .stark-search-line {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 18px 20px 14px;
  border-bottom: 1px solid var(--frost-field-line);
  transition: border-color var(--stark-t-move) var(--stark-ease), box-shadow var(--stark-t-move) var(--stark-ease);
}
body.threads-koel .stark-search-line:hover { border-bottom-color: var(--frost-field-line-lit); }
body.threads-koel .stark-search-line:focus-within { border-bottom-color: var(--stark-accent); box-shadow: 0 1px 0 var(--stark-accent); }
body.threads-koel .stark-search-line .stark-glyph {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  color: var(--stark-stone);
}
body.threads-koel .stark-search-line:focus-within .stark-glyph { color: var(--stark-accent); }
body.threads-koel .stark-search-line input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 8px 0;
  border: 0;
  outline: none;
  background: transparent;
  box-shadow: none;
  color: var(--stark-ink);
  font: inherit;
  font-size: var(--stark-text-control);
}
body.threads-koel .stark-search-line input::placeholder { color: var(--stark-stone); }
body.threads-koel .stark-emoji-jump {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 20px 14px;
  border-bottom: 1px solid var(--frost-sheet-line);
}
body.threads-koel .stark-emoji-jump[hidden] { display: none; }
body.threads-koel .stark-emoji-jump button {
  border: 0;
  background: transparent;
  color: var(--stark-muted);
  font: inherit;
  font-size: var(--stark-text-note);
  padding: 5px 9px;
  border-radius: var(--frost-key-r);
  cursor: pointer;
  transition: background-color var(--stark-t-move) var(--stark-ease), color var(--stark-t-move) var(--stark-ease);
}
/* Frost's ladder on the category keys: a third of the pane under the
   pointer, the whole pane and the accent word where you are. */
body.threads-koel .stark-emoji-jump button:hover { background: color-mix(in srgb, var(--frost-glass-fill) 60%, transparent); color: var(--stark-ink); }
body.threads-koel .stark-emoji-jump button[aria-current="true"] { background: var(--frost-glass-sheen), var(--frost-glass-fill); box-shadow: var(--frost-glass-shadow); color: var(--stark-accent); }
body.threads-koel .stark-emoji-jump button:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }
body.threads-koel .stark-emoji-group { padding: 0 20px; }
body.threads-koel .stark-emoji-group[hidden] { display: none; }
body.threads-koel .stark-emoji-heading {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0;
  padding: 10px 14px 8px;
  background: var(--frost-sheet);
  font-size: var(--stark-text-note);
  font-weight: 600;
  color: var(--stark-muted);
  text-transform: uppercase;
  letter-spacing: .04em;
}
body.threads-koel .stark-emoji-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(58px, 1fr));
  gap: 2px;
  padding-bottom: 10px;
}
body.threads-koel .stark-emoji-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  border-radius: var(--stark-radius);
  background: transparent;
  font: inherit;
  font-size: 38px;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--stark-t-move) var(--stark-ease);
}
body.threads-koel .stark-emoji-cell[hidden] { display: none; }
body.threads-koel .stark-emoji-cell:hover { background: var(--stark-well); }
body.threads-koel .stark-emoji-cell:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--stark-accent); }
/* At a phone's width the kit's full-width sheet hanging from the top. */
@media (max-width: 480px) {
  body.threads-koel .stark-emoji-picker { width: 100%; max-width: none; margin: 0 0 auto; max-height: 100dvh; }
  body.threads-koel .stark-emoji-picker > .stark-dialog-surface { max-height: 100dvh; border-radius: 0 0 var(--stark-radius) var(--stark-radius); border-top: 0; border-inline: 0; }
  body.threads-koel .stark-emoji-frame > .stark-emoji-body { height: calc(100dvh - 190px); }
  body.threads-koel .stark-emoji-grid { grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); }
  body.threads-koel .stark-emoji-cell { font-size: 24px; }
  body.threads-koel .stark-dialog-close { width: 44px; height: 44px; min-height: 44px; }
}


/* ============================ 18. TOASTS AND TOOLTIPS (stage 5, feedback) */
/* MPF, 29 Sep 2026: "next do the toasters and tooltips". They float over
   every page, so they live here rather than in the pages sheet. The kit's
   recipes are frost.css §"toasts: frosted strips" (~2277) and §"the tooltip:
   a small frosted card" (~2289), with run 5's lamps and no glow (Frost
   rule 7: a status lamp is a stone mark, no bloom).

   ONE CHANGE FROM THE KIT, and why: the kit lays `backdrop-filter` on the
   toast and the tooltip themselves. Here that is rule 155's forbidden glass
   on a box (§1: blur makes a box the frame a fixed panel inside it is
   placed against — the notes popover holds buttons), and an underlay has
   nowhere to stand: the toast has no position of its own (it is a
   controller's box, so none may be given), and the tooltip's two pseudo-
   boxes are already its danger lamp and its speech-point. So both take
   what the menu's sheets took in stage 2: the list's card colour made whole
   (`--frost-sheet-tint`), with the list's sheen, the glass rim and the kit's
   drop still saying glass. At the kit's 86% dark tint the blur showed a
   fifth-of-a-tone difference; the drop and the rim carry the float.

   Only colour, fill, border colour, shadow and corner change. Sizes, the
   4px stripe's width, padding, position, the entrance and exit motion
   (is-entering / is-leaving), the tooltip's placement and the
   speech-point's geometry are production's and stay so — the tooltip
   suites hold them to the 25 Sep 2026 baseline. */

/* --- the toast: a frosted strip ------------------------------------------ */
/* The state is still said three times (MPF, 1 Sep 2026: a save and a
   refusal told apart before they are read): the stripe, the mark and a
   wash. In Frost's words: success is the accent, a warning the legend, a
   refusal the danger, a plain notice the stone — Stark's four lamps. */
body.threads-koel .toast {
  --toast-state: var(--stark-stone);
  border-color: var(--stark-card-edge);
  border-left-color: var(--toast-state);
  border-radius: var(--frost-glass-r);
  background:
    var(--frost-list-sheen),
    linear-gradient(color-mix(in srgb, var(--toast-state) 8%, transparent), color-mix(in srgb, var(--toast-state) 8%, transparent)),
    var(--frost-sheet-tint);
  box-shadow: var(--frost-glass-settled), var(--frost-list-drop);
}
body.threads-koel .toast--success { --toast-state: var(--stark-accent); }

/* A dialog's help line that answers an action (rule 68 modifiers of the house
   `user-dialog-help`): `--refused` in the danger, nothing done; `--done` in
   Frost's green, done. First for the TR price dialogs' paste note (MPF, 5 Oct
   2026: red for a refused paste, green after a good one); at rest the line
   keeps the help's own colour. */
body.threads-koel .user-dialog-help--refused { color: var(--stark-danger); }
body.threads-koel .user-dialog-help--done { color: var(--frost-hue-green); }
body.threads-koel .toast--warning { --toast-state: var(--stark-legend); }
body.threads-koel .toast--danger { --toast-state: var(--stark-danger); }
/* The kit's daylight warning lamp measured under 3:1 in the legend tone on
   the daylight glass, so it takes the stone (a lamp is a mark, need 3). */
:root[data-frost-mode="light"] body.threads-koel .toast--warning { --toast-state: var(--stark-stone); }

/* The mark: Koel's round disc becomes a stone mark — square with Frost's
   corner, filled with the state and no bloom — lettered in the glass's own
   ground so the ✓, ! and × read on every state. */
body.threads-koel .toast__icon {
  border-radius: var(--stark-radius);
  background: var(--toast-state);
  color: var(--frost-card-low);
  box-shadow: none;
}
body.threads-koel .toast__content strong { color: var(--stark-ink); }
body.threads-koel .toast__content span { color: var(--stark-muted); }
/* A refusal's title on the strip takes the glass's danger (the kit's §18
   token, measured to 4.5 on the toast). */
body.threads-koel .toast--danger .toast__content strong { color: var(--frost-danger-glass); }
/* The close key: a third of the pane under the pointer, as a key on glass
   lights; focus is the thin accent ring (Frost rule 7), never a glow. */
body.threads-koel .toast button { color: var(--stark-muted); }
body.threads-koel .toast button:hover,
body.threads-koel .toast button:focus-visible {
  background: var(--frost-glass-fill);
  color: var(--stark-ink);
}
body.threads-koel .toast button:focus-visible { box-shadow: var(--stark-focus-ring); }

/* --- the tooltip: a small frosted card ------------------------------------ */
/* Stark's edge and corner, the kit's close drop. The words keep Koel's
   12.5px (a size is not the look's to change). */
body.threads-koel .table-action-tooltip {
  /* A TINY DIALOG (MPF, 30 September 2026: "add glass border to the tooltip
     too and make it slightly lighter, have it be the same look as the
     dialog" — not the menus, which keep their sheet). The dialog's paper
     (--frost-sheet) fills the card; the frame is a thin glass rim painted in
     the dialog frame's own glass fill over that paper, a hairline of the
     sheet's line inside it, and the glass edge outside — the dialog's frame
     at a tooltip's width (its 8px, MPF: "match"). */
  --frost-tip-frame: var(--frost-frame, 8px);
  --frost-tip-paper-radius: var(--stark-radius);
  border-color: var(--frost-glass-edge);
  border-radius: var(--stark-radius);
  /* Painted exactly as the dialog is: the frame's own glass (sheen, glass
     fill, frame tint) from the outer edge in, then the sheet's dark line and
     the paper laid on it, inset by the frame — one box, so the glass edge
     sits on the frame's glass and reads lighter, as the dialog's does. */
  /* The paper and its line are rounded rects (two crossing bands and four
     corner discs each), so the paper's corners round as the dialog's do; the
     paper's top carries the dialog sheet's 1px light lip, which is what makes
     the dark line beside it read as thin as the dialog's (measured on MPF's
     screenshot: dark 1px, then the lip, then the paper). */
  background:
    linear-gradient(var(--frost-card-lip), var(--frost-card-lip)) center var(--frost-tip-frame) / calc(100% - 2 * var(--frost-tip-frame) - 2 * var(--frost-tip-paper-radius)) 1px no-repeat border-box,
    linear-gradient(var(--frost-sheet), var(--frost-sheet)) center / calc(100% - 2 * var(--frost-tip-frame)) calc(100% - 2 * var(--frost-tip-frame) - 2 * var(--frost-tip-paper-radius)) no-repeat border-box,
    linear-gradient(var(--frost-sheet), var(--frost-sheet)) center / calc(100% - 2 * var(--frost-tip-frame) - 2 * var(--frost-tip-paper-radius)) calc(100% - 2 * var(--frost-tip-frame)) no-repeat border-box,
    radial-gradient(circle at center, var(--frost-sheet) calc(var(--frost-tip-paper-radius) - .5px), transparent var(--frost-tip-paper-radius)) var(--frost-tip-frame) var(--frost-tip-frame) / calc(2 * var(--frost-tip-paper-radius)) calc(2 * var(--frost-tip-paper-radius)) no-repeat border-box,
    radial-gradient(circle at center, var(--frost-sheet) calc(var(--frost-tip-paper-radius) - .5px), transparent var(--frost-tip-paper-radius)) calc(100% - var(--frost-tip-frame)) var(--frost-tip-frame) / calc(2 * var(--frost-tip-paper-radius)) calc(2 * var(--frost-tip-paper-radius)) no-repeat border-box,
    radial-gradient(circle at center, var(--frost-sheet) calc(var(--frost-tip-paper-radius) - .5px), transparent var(--frost-tip-paper-radius)) var(--frost-tip-frame) calc(100% - var(--frost-tip-frame)) / calc(2 * var(--frost-tip-paper-radius)) calc(2 * var(--frost-tip-paper-radius)) no-repeat border-box,
    radial-gradient(circle at center, var(--frost-sheet) calc(var(--frost-tip-paper-radius) - .5px), transparent var(--frost-tip-paper-radius)) calc(100% - var(--frost-tip-frame)) calc(100% - var(--frost-tip-frame)) / calc(2 * var(--frost-tip-paper-radius)) calc(2 * var(--frost-tip-paper-radius)) no-repeat border-box,
    linear-gradient(var(--frost-sheet-line), var(--frost-sheet-line)) center / calc(100% - 2 * calc(var(--frost-tip-frame) - 1px)) calc(100% - 2 * calc(var(--frost-tip-frame) - 1px) - 2 * calc(var(--frost-tip-paper-radius) + 1px)) no-repeat border-box,
    linear-gradient(var(--frost-sheet-line), var(--frost-sheet-line)) center / calc(100% - 2 * calc(var(--frost-tip-frame) - 1px) - 2 * calc(var(--frost-tip-paper-radius) + 1px)) calc(100% - 2 * calc(var(--frost-tip-frame) - 1px)) no-repeat border-box,
    radial-gradient(circle at center, var(--frost-sheet-line) calc(calc(var(--frost-tip-paper-radius) + 1px) - .5px), transparent calc(var(--frost-tip-paper-radius) + 1px)) calc(var(--frost-tip-frame) - 1px) calc(var(--frost-tip-frame) - 1px) / calc(2 * calc(var(--frost-tip-paper-radius) + 1px)) calc(2 * calc(var(--frost-tip-paper-radius) + 1px)) no-repeat border-box,
    radial-gradient(circle at center, var(--frost-sheet-line) calc(calc(var(--frost-tip-paper-radius) + 1px) - .5px), transparent calc(var(--frost-tip-paper-radius) + 1px)) calc(100% - calc(var(--frost-tip-frame) - 1px)) calc(var(--frost-tip-frame) - 1px) / calc(2 * calc(var(--frost-tip-paper-radius) + 1px)) calc(2 * calc(var(--frost-tip-paper-radius) + 1px)) no-repeat border-box,
    radial-gradient(circle at center, var(--frost-sheet-line) calc(calc(var(--frost-tip-paper-radius) + 1px) - .5px), transparent calc(var(--frost-tip-paper-radius) + 1px)) calc(var(--frost-tip-frame) - 1px) calc(100% - calc(var(--frost-tip-frame) - 1px)) / calc(2 * calc(var(--frost-tip-paper-radius) + 1px)) calc(2 * calc(var(--frost-tip-paper-radius) + 1px)) no-repeat border-box,
    radial-gradient(circle at center, var(--frost-sheet-line) calc(calc(var(--frost-tip-paper-radius) + 1px) - .5px), transparent calc(var(--frost-tip-paper-radius) + 1px)) calc(100% - calc(var(--frost-tip-frame) - 1px)) calc(100% - calc(var(--frost-tip-frame) - 1px)) / calc(2 * calc(var(--frost-tip-paper-radius) + 1px)) calc(2 * calc(var(--frost-tip-paper-radius) + 1px)) no-repeat border-box,
    var(--frost-tip-shine) border-box,
    var(--frost-list-sheen) border-box,
    linear-gradient(var(--frost-frame-fill), var(--frost-frame-fill)) border-box,
    linear-gradient(var(--frost-frame-tint), var(--frost-frame-tint)) border-box,
    /* The frame's glass laid over the card's low shade, not over whatever
       the tooltip happens to float on, so it always measures as the dialog's
       frame does (~54–57 against the paper's 44, measured side by side at 4×) and the paper reads sunk
       into it, not lifted (MPF, 30 Sep 2026). */
    linear-gradient(var(--frost-card-low), var(--frost-card-low)) border-box;
  /* The dialog frame's settled glass — its lit top line; the glass edge is
     the border alone, drawn once (MPF, 30 Sep: a second inner edge line split
     the frame into "bright edge + strip") — and WITHOUT its bloom: on the dialog the bloom lies on the frame and
     the paper (a child) covers it, but here the paper is painted in the
     same box, so the bloom fell across the paper's top as a gradient and
     made it read raised (MPF, 30 Sep 2026). */
  box-shadow: inset 0 1px 0 var(--frost-glass-rim), inset 0 -1px 0 var(--frost-tip-foot), var(--frost-tip-drop);
  color: var(--stark-ink);
}
/* The words keep their breathing room inside the rim (the grid and popover
   tooltips carry their own padding and keep it). */
body.threads-koel .table-action-tooltip:not([data-grid], [data-popover]) {
  padding: calc(7px + var(--frost-tip-frame)) calc(10px + var(--frost-tip-frame));
}
body.threads-koel .table-action-tooltip[data-placement="above"]::after,
body.threads-koel .table-action-tooltip[data-placement="below"]::after {
  /* No speech-point on the tiny dialog (MPF, 30 Sep 2026, after trying a
     glass one: "let's remove the arrow from the tooltip") — the kit's
     tooltip has none either; the card stands 8px off its key. */
  border-color: transparent;
  background: transparent;
}
/* A refusal's lamp: Stark's §46 danger square — the kit's no-glow override
   (frost.css ~2260, `.stark-tooltip[data-tone="danger"]::before`). Koel drew
   it white with a red bloom; here it is the danger itself, and nothing
   round it. */
body.threads-koel .table-action-tooltip[data-tone="danger"]::before {
  border-radius: calc(var(--stark-radius) - 3px);
  background: var(--stark-danger);
  box-shadow: none;
}
/* A negative figure in the grid tooltip reads in §19's figure red, as every
   negative on a Frost screen does (stage 6). */
body.threads-koel .table-action-tooltip-negative { color: var(--frost-neg); }
/* The notes popover's body, reached by keyboard: the thin accent ring. */
body.threads-koel .table-action-tooltip-popover-body:focus-visible { box-shadow: inset 0 0 0 1px var(--stark-accent); }
/* The popover's rules between lines and figures: the card's edge. */
body.threads-koel .table-action-tooltip .dispatch-report-note-sizes { border-top-color: var(--stark-card-edge); }

/* ==================================================== 19. THE STATUS TAG */
/* MPF, 29 Sep 2026, pointing at a table's "Active" capsule with its glowing
   green dot: "bud you need to swap out these too". Threads' `.status-tag`
   (and `--warning`) becomes the kit's status pill — Stark's `.stark-pill`:
   5px corners, small spaced capitals, and a 6px SQUARE lamp with no glow
   (Frost rule 7). Active is the accent, a warning the danger red; a tag with
   no lamp keeps the key stone. Koel's own selectors are matched weight for
   weight (`[data-search-text]`) and this sheet loads after koel.css, so it
   wins by order. On every page, like the toasts: a status is a mark, not a
   table look. Markup and the search text untouched. */
body.threads-koel .status-tag,
body.threads-koel .status-tag[data-search-text],
body.threads-koel .status-tag--warning[data-search-text] {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 26px;
  padding: 3px 10px;
  border: 1px solid color-mix(in srgb, var(--stark-ink) 7%, transparent);
  border-radius: var(--stark-radius);
  background: color-mix(in srgb, var(--stark-ink) 4%, transparent);
  box-shadow: none;
  color: var(--stark-muted);
  font-size: var(--stark-text-micro);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
}
body.threads-koel .status-tag[data-search-text] { color: var(--stark-ink); }
body.threads-koel .status-tag[data-search-text]::before,
body.threads-koel .status-tag--warning[data-search-text]::before {
  content: "";
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  margin: 0;
  border-radius: calc(var(--stark-radius) - 3px);
  background: var(--stark-accent);
  box-shadow: none;
}
body.threads-koel .status-tag--warning[data-search-text]::before { background: var(--stark-danger); }
/* Daylight: the kit's pill draws its hairline with the ink (frost.css §17). */
:root[data-frost-mode="light"] body.threads-koel :is(.status-tag, .status-tag[data-search-text], .status-tag--warning[data-search-text]) {
  border-color: color-mix(in srgb, var(--stark-ink) 16%, transparent);
}


/* ======================================== 20. THE SWITCH (every page, every family) */
/* Moved here from threads-frost-pages.css and widened, MPF 29 Sep 2026, on Shirt
   Sizes' old toggles: "shouldn't a change have change everywhere!" It had been
   scoped to the pages switched on one by one, and it named only the
   fabric-status-toggle family; Sizes (and the other Card-count masters) use
   card-status-toggle, the same markup under another name. Both families, on
   every page. Since 29 September 2026 there is one family: the 27 pages on
   card-status-toggle wear the house class (Frost sweep, stray #1), so this
   section names it alone. The original note follows. */
/* MPF, 29 Sep 2026, on the Frost Category One page: "bud you forgot to change
   the toggles!" The house switch — `fabric-status-toggle`, its __track and
   __thumb, in a table row and, as `form-field__toggle`, in a dialog — dressed
   as the kit's Frost switch (frost.css §12 over Stark's slot, stark.css §9),
   copied onto Threads' own classes; the markup, `is-active`, the click and
   the in-place save are the house's, untouched.
     the track   Stark's slot, pressed into the paper (the press tokens)
     the thumb   a pane of glass with its 2px bar, muted OFF, accent ON
     the word    OFF / ON in the room the pane leaves — CSS content on the
                 track's own ::after, so no markup is added; the house's
                 visually-hidden label still speaks the state
     hover       the pane lifts to its full drop, its bar to the ink
     press       the pane settles 1px, its drop gone
     focus       the 1px accent ring round the slot (Frost rule 7)
   The pane is drawn on the thumb's ::after and moved there: spec §1 keeps a
   transform off every box, so the thumb itself becomes a still frame the
   size of the slot. Koel's LED (the thumb's ::after, with its glow) is
   replaced by the pane — no glow (Frost rule 7). Sizes are Stark's: a row
   switch `s` (54 × 24), a dialog's `m` (66 × 28). */
body.threads-koel .fabric-status-toggle {
  --tg-w: 54px;
  --tg-h: 24px;
  --tg-word: 8.5px;
  --frost-thumb-in: 3px;
  --frost-thumb-w: calc(var(--tg-h) - 2 * var(--frost-thumb-in) + 2px);
  --frost-thumb-bar: var(--stark-muted);
  color: var(--stark-muted);
  /* The button is as wide as its track (MPF, 29 Sep 2026: "the spacing is wrong"):
     Koel held card-status-toggle at 46px, so the 54px Frost track spilled 8px past
     it and swallowed the row's 7px gap to the pencil. */
  flex: 0 0 auto;
  width: var(--tg-w);
  min-width: var(--tg-w);
  /* and nothing inside pushes the track off its left edge: the master switch
     carried 2px of side padding and an 8px gap to its hidden label. */
  padding-inline: 0;
  gap: 0;
}
body.threads-koel .fabric-status-toggle.form-field__toggle { --tg-w: 66px; --tg-h: 28px; --tg-word: 9.5px; }
/* By the export keys (`form-field--export-switch`, the Price List's "Block
   headings"): the row switch's `s`, the size of the keys beside it. */
body.threads-koel .form-field--export-switch .fabric-status-toggle.form-field__toggle { --tg-w: 54px; --tg-h: 24px; --tg-word: 8.5px; }
/* …and its word in the export label's own voice ("Export", "Folds"), not a
   dialog field's capitals. */
body.threads-koel .user-table-export-switch .form-field--export-switch > span:first-child { text-transform: none; letter-spacing: normal; font-size: 11px; }
body.threads-koel .fabric-status-toggle.is-active { color: var(--stark-ink); }

/* The slot — GLASS EVERYWHERE (MPF, 30 Sep 2026: "the dialog uses the inset
   toggle style while data tables use glass toggle can we make it glass toggle
   everywhere?"). A switch outside a row's rail (a dialog's `form-field__toggle`,
   a product column, a permission switch) is the table capsule on its own: the
   quiet glass fill and one even light line round it, no pressed well, no amber
   lip, no pressed shadow under the word — the values the pure table's row
   capsule had (30 Sep 2026; the capsule itself went on 1 Oct), kept here
   because a dialog also opens on pages that do not wear that look. In a row
   the engraved bar is the ground and the slot stays clear (§23). */
body.threads-koel {
  --tg-glass-fill: rgb(255 248 235 / 4%);
  --tg-glass-rim: rgb(255 250 240 / 22%);
}
:root[data-frost-mode="light"] body.threads-koel {
  --tg-glass-fill: rgb(255 253 248 / 30%);
  --tg-glass-rim: color-mix(in srgb, var(--stark-ink) 20%, transparent);
}
body.threads-koel .fabric-status-toggle .fabric-status-toggle__track,
body.threads-koel .fabric-status-toggle.is-active .fabric-status-toggle__track {
  width: var(--tg-w);
  height: var(--tg-h);
  flex: 0 0 var(--tg-w);
  border: 0;
  border-radius: var(--stark-radius);
  background: var(--tg-glass-fill);
  box-shadow: inset 0 0 0 1px var(--tg-glass-rim);
}

/* The thumb: a still frame the slot's size; the pane is its ::after. */
body.threads-koel .fabric-status-toggle .fabric-status-toggle__thumb,
body.threads-koel .fabric-status-toggle.is-active .fabric-status-toggle__thumb {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  background: none;
  box-shadow: none;
  transform: none;
}
body.threads-koel .fabric-status-toggle .fabric-status-toggle__thumb::after {
  content: "";
  position: absolute;
  top: var(--frost-thumb-in);
  left: var(--frost-thumb-in);
  width: var(--frost-thumb-w);
  height: calc(var(--tg-h) - 2 * var(--frost-thumb-in));
  border-radius: calc(var(--stark-radius) - 2px);
  /* the bar, 2px wide and half the pane tall, painted on the pane itself */
  background:
    linear-gradient(var(--frost-thumb-bar), var(--frost-thumb-bar)) center / 2px 52% no-repeat,
    var(--frost-glass-sheen),
    var(--frost-glass-fill);
  box-shadow: var(--frost-glass-settled);
  transform: none;
  transition: transform var(--stark-t-settle) var(--stark-ease), box-shadow var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel .fabric-status-toggle:not(:disabled):is(:hover, :focus-visible) .fabric-status-toggle__thumb::after {
  --frost-thumb-bar: var(--stark-ink);
  box-shadow: var(--frost-glass-shadow);
}
/* ON: straight across, the bar in the accent — a breath, no glow. */
body.threads-koel .fabric-status-toggle.is-active .fabric-status-toggle__thumb::after,
body.threads-koel .fabric-status-toggle.is-active:not(:disabled):is(:hover, :focus-visible) .fabric-status-toggle__thumb::after {
  --frost-thumb-bar: var(--stark-accent);
  transform: translateX(calc(var(--tg-w) - var(--frost-thumb-w) - 2 * var(--frost-thumb-in)));
  box-shadow: var(--frost-glass-shadow);
}
/* Press: the pane settles, its drop gone; OFF, it drops 1px. */
body.threads-koel .fabric-status-toggle:not(:disabled):active .fabric-status-toggle__thumb::after { box-shadow: var(--frost-glass-settled); }
body.threads-koel .fabric-status-toggle:not(:disabled, .is-active):active .fabric-status-toggle__thumb::after { transform: translateY(var(--frost-press-drop)); }

/* The word, centred in the room the pane is not using. */
body.threads-koel .fabric-status-toggle .fabric-status-toggle__track::after {
  content: "OFF";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--frost-thumb-in) + var(--frost-thumb-w));
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* glass: the pure table's OFF ink (halfway between muted and stone), and no
     pressed shadow — there is no well under the word any more */
  color: color-mix(in srgb, var(--stark-muted) 50%, var(--stark-stone));
  font-size: var(--tg-word);
  font-weight: 700;
  letter-spacing: .16em;
  line-height: 1;
  text-shadow: none;
  pointer-events: none;
}
body.threads-koel .fabric-status-toggle.is-active .fabric-status-toggle__track::after {
  content: "ON";
  left: 0;
  right: calc(var(--frost-thumb-in) + var(--frost-thumb-w));
  color: var(--frost-accent-pressed);
}

/* Focus: the 1px ring round the slot, not round the whole button. */
body.threads-koel .fabric-status-toggle:focus-visible { outline: none; }
body.threads-koel .fabric-status-toggle:focus-visible .fabric-status-toggle__track { outline: 1px solid var(--stark-accent); outline-offset: 2px; }

/* A finger's 44px on a phone or a touch screen (the row button already is). */
@media (max-width: 480px), (pointer: coarse) {
  body.threads-koel .fabric-status-toggle.form-field__toggle { min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  body.threads-koel .fabric-status-toggle .fabric-status-toggle__thumb::after { transition-duration: .01ms; }
}


/* ====================================== 21. THE PANEL BROWSERS (every page, every family) */
/* MPF, 29 Sep 2026, on Shirts › Sizes › Size Mappings: "bud do these panels
   look ok to you?" They did not: the columns waiting their turn went near
   black with their words barely there (Koel's list at 30% opacity), the Sizes
   column was a black void, the first column a lighter paper beside three
   black ones, and the letter badges and gold count pills cluttered. Then: "go
   ahead bud, dress all the panel pages" — and, the same day, "shouldn't a
   change have change everywhere!", so this is written once on the shared
   `ppc-panel*` family and reaches every page that draws it: Shirts, Jeans and
   TR Size Mappings, Shirts and TR PPC Default and Custom, Production Type
   Mappings, Jeans Item Mapping, Permissions and the Shirting, Suiting and
   Jodi Cut workspaces.

   Copied from the kit's panel chain (Artha Frost/frost.css, "the panel
   chain") over Stark's panel base (stark.css §60–§61, §65) for geometry:
     the browser   Stark's row of separate panels, 10px apart — no shared
                   frame, no 1px black seams
     a panel       A PANEL IS A WELL: one paper tone for every column, pressed
                   in with the tokens; ASLEEP (locked, dormant, or Permissions'
                   aria-disabled), flat — but its words stay readable, muted
                   rather than faded (MPF's complaint; kit changed with it)
     the head      the kit's head: the title in the legend's spaced capitals,
                   the state line muted, a hairline under it
     an option     THE OPTION IS A ROW, NOT A KEY'S CAPSULE: a pane in the
                   row's own `::before`, a third under the pointer, the whole
                   pane once chosen (the page's own `is-selected`, or the
                   option's aria-selected), the chosen word the accent
     the glyph     a pit cut in the paper, not a dark box; on the chosen pane
                   it steps back to the glass
     the count     the kit's quiet figure (tally), not a gold pill
     dividers      the kit's hairline (`--stark-key-low`)
     the search    a panel's search is a line (Stark rule 5), no glow on focus
     an empty one  "No combination selected" is a quiet sentence on the well
   Colour, fill, border colour, shadow, corner and the gap between panels
   only. Markup, ids, data-* and every script untouched; heights, the list's
   scroll and the fade timings are application.css's. No transform or filter
   on a box — the pane's scale lives on the row's `::before` (§1). */

/* The kit's pit and cut (frost.css ~1498 and ~1780), copied value for value. */
:root {
  --frost-pit: inset 0 1px 3px #000c;
  --frost-pit-lip: inset 0 -1px 0 #ffffff1c;
  --frost-cut: inset 0 2px 5px #000c;
  --frost-cut-lip: inset 0 -1px 0 #ffffff1f;
}
:root[data-frost-mode="light"] {
  --frost-pit: inset 0 1px 2px color-mix(in srgb, var(--frost-ink) 24%, transparent);
  --frost-pit-lip: inset 0 -1px 0 var(--frost-card-lip);
  --frost-cut: inset 0 1px 2px color-mix(in srgb, var(--frost-ink) 22%, transparent), inset 0 3px 8px color-mix(in srgb, var(--frost-ink) 8%, transparent);
  --frost-cut-lip: inset 0 -1px 0 var(--frost-card-lip);
}
/* The row pane's fill: the kit's dark row is the fill without the sheen's lit
   top, as a table row's is (frost.css §17); daylight keeps the sheen. And the
   kit's quiet chip (Stark's hairline, drawn with the ink in daylight). */
body.threads-koel {
  --frost-row-pane: var(--frost-glass-fill);
  --frost-quiet-edge: color-mix(in srgb, var(--stark-ink) 7%, transparent);
  --frost-quiet-fill: color-mix(in srgb, var(--stark-ink) 4%, transparent);
}
:root[data-frost-mode="light"] body.threads-koel {
  --frost-row-pane: var(--frost-glass-sheen), var(--frost-glass-fill);
  --frost-quiet-edge: color-mix(in srgb, var(--stark-ink) 16%, transparent);
}

/* --- the browser: panels side by side, no frame ---------------------------- */
body.threads-koel .ppc-panel-browser {
  gap: 10px;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}
/* Permissions' pill lanes stood on a literal blue-black ground. */
body.threads-koel .ppc-panel-browser--permissions { --filter-lane-ground: var(--stark-sink); }

/* --- a panel: a well ----------------------------------------------------------- */
body.threads-koel .ppc-panel,
body.threads-koel .ppc-panel-browser .ppc-panel + .ppc-panel {
  border: 0;
  border-radius: var(--stark-radius);
  background: var(--stark-group);
  box-shadow: var(--frost-press-well);
}
/* Asleep: flat, the same paper. Koel faded the list to 30% (the dormant PPC
   editors to 35%, Permissions' waiting panels to 40%) and the words went
   under 3:1; here the list stays whole and its words step down to muted, so
   a waiting column reads as waiting and can still be read (≥4.5, measured). */
body.threads-koel :is(.ppc-panel.is-locked, .ppc-panel[aria-disabled="true"], .ppc-panel-browser.is-dormant .ppc-panel) {
  background: var(--stark-group);
  box-shadow: none;
}
body.threads-koel .ppc-panel-browser .ppc-panel.is-locked .ppc-panel-list,
body.threads-koel .ppc-panel-browser.is-dormant :is(.ppc-panel-list, .ppc-panel-search, .ppc-pieces-form),
body.threads-koel .ppc-panel-browser--permissions .ppc-panel[aria-disabled="true"] { opacity: 1; }
/* Its rows, glyphs, hint and cursor: "a WAITING panel", at the end of §21. */

/* --- the head ------------------------------------------------------------------ */
body.threads-koel .ppc-panel-header {
  border-bottom: 1px solid var(--stark-key-low);
  border-radius: var(--stark-radius) var(--stark-radius) 0 0;
  background: none;
}
body.threads-koel .ppc-panel-header :is(h2, h3) {
  color: var(--stark-legend);
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
}
body.threads-koel .ppc-panel-header p { color: var(--stark-muted); }
/* The running "12 Fabrics" beside Production Type Mappings' heading. */
body.threads-koel .production-type-mapper__count { color: var(--stark-muted); font-variant-numeric: tabular-nums; }

/* The head's small keys — the sort, the pager's arrows: Stark's panel key,
   the capsule on the ladder (rest nothing, a third of the pane under the
   pointer, two thirds pressed, the 1px ring for focus). */
body.threads-koel :is(.ppc-panel-sort, .ppc-panel-pagination button) {
  border: 1px solid transparent;
  border-radius: var(--frost-key-r);
  background: none;
  box-shadow: none;
  color: var(--stark-muted);
}
body.threads-koel :is(.ppc-panel-sort, .ppc-panel-pagination button):not(:disabled):is(:hover, :focus-visible) {
  border-color: transparent;
  background: color-mix(in srgb, var(--frost-glass-fill) calc(var(--frost-glass-hover) * 100%), transparent);
  box-shadow: var(--frost-glass-shadow);
  color: var(--stark-ink);
  outline: none;
}
body.threads-koel :is(.ppc-panel-sort, .ppc-panel-pagination button):not(:disabled):active {
  background: color-mix(in srgb, var(--frost-glass-fill) calc(var(--frost-glass-press) * 100%), transparent);
  box-shadow: var(--frost-glass-settled);
}
body.threads-koel :is(.ppc-panel-sort, .ppc-panel-pagination button):focus-visible { border-color: var(--stark-accent); }
body.threads-koel .ppc-panel-pagination {
  border-top: 1px solid var(--stark-key-low);
  background: none;
  color: var(--stark-muted);
}

/* --- the search: a line ------------------------------------------------------ */
body.threads-koel .ppc-panel-search {
  border-bottom: 1px solid var(--stark-key-low);
  background: none;
}
body.threads-koel .ppc-panel-search__icon { color: var(--stark-stone); }
body.threads-koel .ppc-panel-search input,
body.threads-koel .size-mapping-filter {
  border: 0;
  border-bottom: 1px solid var(--frost-field-line);
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel :is(.ppc-panel-search input, .size-mapping-filter)::placeholder { color: var(--stark-muted); }
body.threads-koel :is(.ppc-panel-search input, .size-mapping-filter):hover { border-bottom-color: var(--frost-field-line-lit); }
body.threads-koel :is(.ppc-panel-search input, .size-mapping-filter):focus {
  border-bottom-color: var(--stark-accent);
  box-shadow: none;
  outline: none;
}

/* --- a row: the hairline, and the pane in its ::before ------------------------- */
/* The row is already the positioned box (application.css); `isolation` makes
   it its own stacking context so the pane can sit UNDER the words — it is not
   a containing block for anything fixed. The pane was Koel's 3px accent bar;
   it is inset from the hairlines so a column of chosen rows never touches. */
body.threads-koel .ppc-panel-row {
  isolation: isolate;
  border-bottom: 1px solid var(--stark-key-low);
  background: none;
  box-shadow: none;
}
/* Koel pressed the chosen row into a near-black slab (#0d0d0d, its own
   `.ppc-panel-row.is-selected`, a class heavier than the row alone). */
body.threads-koel .ppc-panel-row:hover,
body.threads-koel .ppc-panel-row.is-selected {
  background: none;
  box-shadow: none;
}
body.threads-koel .ppc-panel-row::before,
body.threads-koel .ppc-panel-row.is-selected::before {
  inset: 3px 4px;
  z-index: -1;
  width: auto;
  border-radius: var(--stark-radius);
  background: var(--frost-row-pane);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.985, .9);
  transition:
    opacity var(--stark-t-settle) var(--stark-ease),
    transform var(--stark-t-settle) var(--stark-ease),
    box-shadow var(--stark-t-quick) var(--stark-ease);
  pointer-events: none;
}
body.threads-koel .ppc-panel-row:is(:hover, :focus-within)::before {
  opacity: var(--frost-glass-hover);
  transform: none;
}
body.threads-koel .ppc-panel-row:has(> .ppc-panel-option:active)::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
  transition-duration: var(--stark-t-tap);
}
/* Chosen: the whole pane, and it stays whole under the pointer and a press,
   because it is already down. */
body.threads-koel :is(.ppc-panel-row.is-selected, .ppc-panel-row:has(> .ppc-panel-option[aria-selected="true"]))::before,
body.threads-koel :is(.ppc-panel-row.is-selected, .ppc-panel-row:has(> .ppc-panel-option[aria-selected="true"])):is(:hover, :focus-within, :has(> .ppc-panel-option:active))::before {
  opacity: 1;
  transform: none;
  box-shadow: var(--frost-glass-shadow);
}

/* --- the option: words, glyph, count, status ----------------------------------- */
body.threads-koel .ppc-panel-option {
  border-radius: var(--stark-radius);
  background: none;
  color: var(--stark-ink);
}
body.threads-koel .ppc-panel-option:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 1px var(--stark-accent);
}
body.threads-koel .ppc-panel-row.is-selected .ppc-panel-option,
body.threads-koel .ppc-panel-row.is-selected .ppc-panel-option__label,
body.threads-koel .ppc-panel-option[aria-selected="true"] .ppc-panel-option__label { color: var(--stark-accent); }

/* The glyph: a pit cut in the paper, the letter in stone. */
body.threads-koel .ppc-panel-option__glyph {
  border: 0;
  border-radius: calc(var(--stark-radius) - 1px);
  background: var(--stark-sink);
  box-shadow: var(--frost-pit), var(--frost-pit-lip);
  color: var(--stark-stone);
}
/* On the whole pane the pit is the pane's own: it steps back to the glass. */
body.threads-koel .ppc-panel-row.is-selected .ppc-panel-option__glyph,
body.threads-koel .ppc-panel-option[aria-selected="true"] .ppc-panel-option__glyph {
  border: 0;
  background: none;
  box-shadow: inset 0 0 0 1px var(--frost-glass-edge);
  color: var(--stark-accent);
}

/* The count: a quiet figure, tabular, answering a question not yet asked. */
body.threads-koel .size-mapping-option__count {
  min-width: 0;
  padding: 0;
  border-radius: 0;
  background: none;
  color: var(--stark-muted);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
body.threads-koel .ppc-panel-row.is-selected .size-mapping-option__count { color: var(--stark-ink); }

body.threads-koel .ppc-panel-option__note { color: var(--stark-muted); }
body.threads-koel .ppc-panel-option__status {
  color: var(--stark-danger);
  font-weight: 600;
  letter-spacing: .06em;
}

/* --- an empty panel: a quiet sentence on the well ----------------------------- */
body.threads-koel .ppc-panel-empty { color: var(--stark-muted); }
body.threads-koel .ppc-panel-empty strong { color: var(--stark-ink); font-weight: 600; }

/* --- the Pieces panel (PPC, Item Mapping) --------------------------------------- */
body.threads-koel .ppc-pieces-form .form-field > span { color: var(--stark-ink); }
body.threads-koel .ppc-combination-summary { color: var(--stark-muted); }

/* --- the Sizes column (stark.css §65): the order is placed rows in the sink ------ */
body.threads-koel .size-mapping-subhead { color: var(--stark-legend); }
body.threads-koel .size-mapping-hint { color: var(--stark-muted); }
body.threads-koel :is(.size-mapping-order__item, .ppc-panel-browser .order-editor-item) {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--stark-sink);
  box-shadow: var(--frost-cut), var(--frost-cut-lip);
}
body.threads-koel .size-mapping-order__item.is-inactive { border-color: var(--stark-key-low); }
body.threads-koel .size-mapping-order__label { color: var(--stark-ink); }
body.threads-koel .size-mapping-order__item.is-inactive .size-mapping-order__label { color: var(--stark-muted); }
/* The position: the kit's figure in stone, no badge. */
body.threads-koel .size-mapping-order__position {
  border-radius: calc(var(--stark-radius) - 1px);
  background: none;
  color: var(--stark-stone);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
body.threads-koel .size-mapping-order__handle { color: var(--stark-stone); }
body.threads-koel .size-mapping-order__status {
  border: 1px solid var(--frost-quiet-edge);
  border-radius: var(--stark-radius);
  background: var(--frost-quiet-fill);
  color: var(--stark-muted);
}
body.threads-koel .size-mapping-order__remove {
  border-radius: var(--frost-key-r);
  color: var(--stark-muted);
}
body.threads-koel .size-mapping-order__remove:is(:hover, :focus-visible) {
  background: var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  color: var(--stark-ink);
}
/* A token waiting to be placed: the kit's quiet chip; under the pointer a
   third of the pane, the word to the ink — no accent wash, no glow. */
body.threads-koel .size-mapping-token {
  border-color: var(--frost-quiet-edge);
  border-radius: var(--stark-radius);
  background: var(--frost-quiet-fill);
  color: var(--stark-ink);
}
body.threads-koel .size-mapping-token:hover:not(:disabled),
body.threads-koel .size-mapping-token:focus-visible {
  border-color: var(--frost-quiet-edge);
  background: color-mix(in srgb, var(--frost-glass-fill) calc(var(--frost-glass-hover) * 100%), var(--frost-quiet-fill));
  box-shadow: var(--frost-glass-shadow);
  color: var(--stark-ink);
}
body.threads-koel .size-mapping-token:focus-visible { border-color: var(--stark-accent); outline: none; }

/* ============================================================ 22. THE FOOTER */
/* MPF, 29 Sep 2026, going to bed: "can you also change the footer on threads
   make it glass please". The page foot takes the header's shell glass (§14's
   first strip): sheen over the shell tint, the real frost of what scrolls
   beneath, a lit rim along its TOP (the header's is along its foot), no drop
   — it sits on the page's end, it doesn't float over rows. Drawn on
   `::before` so nothing inside the footer is ever held by a filter (the rule
   the header follows). The product tag loses Koel's dark capsule for the
   kit's quiet chip (5px corners, no glow); the words keep their tones. */
body.threads-koel .site-footer { position: relative; isolation: isolate; }
body.threads-koel .application-footer {
  position: relative;
  /* Full-bleed like the header's strips (§14: "the rounded foot all go"): production's
     own blur, 14px top corners and side lines go, so the only frost is the one on
     ::before and nothing in the footer is held by a filter (re-check, 29 Sep night). */
  border: 0;
  border-radius: 0;
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
body.threads-koel .application-footer::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--frost-glass-sheen), var(--frost-shell-tint);
  -webkit-backdrop-filter: var(--frost-shell-filter);
  backdrop-filter: var(--frost-shell-filter);
  box-shadow: inset 0 1px 0 var(--frost-glass-edge), inset 0 2px 0 var(--frost-glass-rim);
  pointer-events: none;
}
body.threads-koel .application-footer__product {
  border: 1px solid var(--frost-glass-edge);
  border-radius: var(--stark-radius);
  background: var(--frost-glass-sheen), color-mix(in srgb, var(--frost-glass-fill) 55%, transparent);
  box-shadow: var(--frost-glass-settled);
}

/* --- a WAITING panel: plainly not yet its turn ------------------------------------ */
/* MPF, 29 Sep 2026, before bed: "the inactive panels in the panel control need a
   slightly better look to indicate they are inactive, it's not very obvious right
   now." Word colour alone was the whole difference (ink → muted). So a waiting
   column now differs from a live one in five ways at a glance, and every word in
   it still reads (stone on the well: 6.18 Original dark, lowest 4.86 Charcoal
   daylight):
     the well       flat — no press (above)
     the rows       stone, a clear step under the live ink (13.95 → 6.18), their
                    hairlines gone, no pane under the pointer or a press, and
                    `not-allowed` for the cursor
     the glyphs     an empty outlined square where a live row has a cut pit
     the head       its hint IS the reason, in the ink behind the kit's arrow —
                    "← Choose a Customer Group", the page's own words
   Waiting means `is-locked` (every cascade), a dormant PPC editor, or
   Permissions' `aria-disabled` panel. The scripts drop the mark the moment the
   column before is picked, and every rule below goes with it. Permissions'
   waiting panels are `inert` in the markup, so no pointer reaches them and the
   cursor cannot be drawn there by style; the rest of the look is theirs too. */
body.threads-koel :is(.ppc-panel.is-locked, .ppc-panel[aria-disabled="true"], .ppc-panel-browser.is-dormant .ppc-panel) { cursor: not-allowed; }
body.threads-koel :is(.ppc-panel.is-locked, .ppc-panel[aria-disabled="true"], .ppc-panel-browser.is-dormant .ppc-panel) .ppc-panel-header { cursor: default; }
body.threads-koel :is(.ppc-panel.is-locked, .ppc-panel[aria-disabled="true"], .ppc-panel-browser.is-dormant .ppc-panel) .ppc-panel-row {
  border-bottom-color: transparent;
  cursor: not-allowed;
}
body.threads-koel :is(.ppc-panel.is-locked, .ppc-panel[aria-disabled="true"], .ppc-panel-browser.is-dormant .ppc-panel) .ppc-panel-row:not(.is-selected)::before { opacity: 0; }
body.threads-koel :is(.ppc-panel.is-locked, .ppc-panel[aria-disabled="true"], .ppc-panel-browser.is-dormant .ppc-panel) :is(.ppc-panel-option, .ppc-panel-option__note, .size-mapping-option__count) {
  color: var(--stark-stone);
  cursor: not-allowed;
}
body.threads-koel :is(.ppc-panel.is-locked, .ppc-panel[aria-disabled="true"], .ppc-panel-browser.is-dormant .ppc-panel) .ppc-panel-option__glyph {
  background: none;
  box-shadow: inset 0 0 0 1px var(--stark-key-low);
  color: var(--stark-stone);
}
body.threads-koel :is(.ppc-panel.is-locked, .ppc-panel[aria-disabled="true"], .ppc-panel-browser.is-dormant .ppc-panel) .ppc-panel-header p { color: var(--stark-ink); }
body.threads-koel :is(.ppc-panel.is-locked, .ppc-panel[aria-disabled="true"], .ppc-panel-browser.is-dormant .ppc-panel) .ppc-panel-header p:not(:empty)::before {
  content: "\2190\00a0";
  color: var(--stark-accent);
}

/* --- a panel a drag is over: the kit's drop target ------------------------------ */
/* Production Type Mappings' Fabrics panel takes a Fabric dragged back out of a
   well, and application.css rang it (`.ppc-panel.is-drop-target`, MPF 4 Sep
   2026) — a ring the well's press above out-weighed. The kit's own drop target
   (stark.css `.stark-well-track[data-drop-target]`, Frost's press): the well's
   body with the 1px accent ring round it, no glow. Written after the waiting
   look and as heavy, so it rings whatever state the panel is in. */
body.threads-koel :is(.ppc-panel, .ppc-panel.is-locked, .ppc-panel[aria-disabled="true"]).is-drop-target {
  /* INSIDE the panel (re-check, 29 Sep night): the panel sits flush with its row,
     which clips anything outside it, so an outer ring showed only its left edge. */
  box-shadow: var(--frost-press-body), inset 0 0 0 1px var(--stark-accent);
}


/* ============================ 23. THE ROW KEYS: the engraved bar (every page, every family) */
/* MPF, 30 Sep 2026, on artha-tryouts/sort-panel-mockup.html: "can we also copy
   over these ON, edit and delete action button to our threads data table?";
   then, 1 Oct 2026, "once chocolate is done will you go ahead with the glass
   sheen and the buttons bud". This is the buttons
   (docs/threads-row-keys-engraved-bar-spec.md). The row keys are Stark's
   ENGRAVED BAR (stark.css §15, MPF's mockup F of 24 Sep 2026) as the Artha
   Frost kit keeps it (frost.css §17 tokens, §33): ONE shallow cut in the card
   — the switch, the pencil, the bin and every other key as segments of the
   same bar, parted by an engraved seam, each glyph engraved into it. It
   replaces option E's pressed rail (29 Sep) and the pure tables' capsule
   (30 Sep, threads-frost-pages.css), so this one section draws row keys
   everywhere: every table, the Card Dispatches dialogs, staged lines,
   multi-edit rows, Dispatch Notes and their report cards. A ROW is a table
   cell or a Dispatch Note's line; keys outside a row (a card head's Copy /
   Excel / PDF, a note card's order keys and its +) keep their own look.
     the bar      34px tall (44 on a phone), `--stark-well` at 35%, the hair
                  cut and its lip (Stark's `inset 0 1px 1px` and 1px lip)
     a key        40px wide (44 on a phone), no box of its own, the glyph
                  19px and engraved (`--frost-glyph-cut`), the engrave mixed
                  40% into the muted ink at rest
     a seam       the key's `::after`, 1px of `--frost-seam` with its lip,
                  8px short of the bar's top and bottom; none before the
                  bar's first segment
     hover        the glyph lights in the accent, nothing else
     pressed      the segment a shade deeper (the well at 70%), no drop
     focus        the kit's 1px accent ring inside the segment, on a key and
                  on the switch alike (Frost rule 7)
     the switch   the bar's first segment, 52px wide and the bar's height;
                  its slot clear, so the bar is its ground. Its own look and
                  hover stay the house glass switch (§20): Stark's slot hover
                  (the well at 55%) is not taken, frost-look-contract check 10
     the bin      `--danger` at rest and in every state; on a ticked row,
                  Frost's danger-on-glass (the picked row's pane lightens it)
     disabled     production's half-strength glyph and not-allowed cursor
   NO GLOW (kit rule, 24 Sep 2026): Stark's glyph halo on hover and press and
   the ON knob's halo are the kit's to leave off, and are off here. NO TIMING:
   nothing inside a row the table controller owns carries a transition
   (frost-look-contract), so every state arrives at once.
   The markup is the house's, untouched (rule 119): `.user-table-row-actions`
   holding the lifecycle `<form>` and its `.fabric-status-toggle`, then the
   `.user-table-row-action` keys. App-wide, it stands down Koel's boxed key
   (koel.css "Row actions") and production's bordered one with its halo.
   THE PHONE (≤480px, or a touch screen): the bar 44px tall and every key 44px
   wide, so a key IS the 44px target (§23's old hit margin is retired and the
   key's `::after` draws the seam, as in the kit); the switch takes the bar's
   height. The bar stays ONE line — Koel's two-to-a-line grid and
   production's 5.5rem cap are put down. The phone table's `+`
   (`.user-table-mobile-disclosure`, injected INTO the group by
   threads-production-mobile-table.js) is not a segment: the bar is the
   group's ::before, drawn short of the `+` by `--rail-tail`, and the group
   never clips, so the `+` keeps production's own bordered look beside it.
   ROWS KEEP THEIR HEIGHT: the bar is taller than the capsule it replaces (34
   vs 28px; 44 vs 37 on a phone) and the Actions cell sets a row's height, so
   in a table cell the bar hands the difference back in `--bar-trim`, a
   negative margin above and below, measured in the pane (1 Oct 2026: -3.5px
   at 1440 → 50px rows, -4.5px at 375 → 56px rows, Shirt Cards, as before).
   A PRICE CARD'S LINE (Trousers › Price List, `loom-sep-card__line`, 4 Oct
   2026 — MPF: "the action buttons look different than in the other data
   tables") carries the same group, so it is drawn here as the same bar, as
   a note line's is; no trim, it is not a table cell. So does a price's pair
   of keys on its Fit card's head (`loom-sep-card__fit-price`, same day). */

/* The kit's bar tokens (frost.css §17, ~2007 and ~2020), value for value:
   the cut and its lip, the seam and its lip, the glyph's engraving. */
:root {
  --frost-hair-cut: inset 0 1px 1px #000c;
  --frost-hair-lip: 0 1px 0 #ffffff14;
  --frost-seam: #000;
  --frost-seam-lip: #ffffff12;
  --frost-glyph-cut: drop-shadow(0 -1px 0 #000d) drop-shadow(0 1px 0 #ffffff1a);
}
:root[data-frost-mode="light"] {
  --frost-hair-cut: inset 0 1px 2px color-mix(in srgb, var(--frost-ink) 20%, transparent);
  --frost-hair-lip: 0 1px 0 var(--frost-card-lip);
  --frost-seam: color-mix(in srgb, var(--frost-ink) 22%, transparent);
  --frost-seam-lip: rgb(255 255 255 / 70%);
  --frost-glyph-cut: drop-shadow(0 1px 0 rgb(255 255 255 / 70%));
}

body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions {
  --bar-h: 34px;                   /* Stark's --stark-rowkey-h */
  --bar-key-w: 40px;               /* Stark's --stark-rowkey-w */
  --bar-glyph: 19px;
  --bar-switch-w: 52px;            /* Stark's row switch, --tg-w */
  --bar-thumb-w: 24px;             /* the switch's glass pane */
  --rail-disc-w: 2.1rem;           /* the phone's +, as production draws it (33.6px) */
  --rail-disc-gap: .15rem;         /* bar to the + (production's 2.4px) */
  --rail-tail: 0px;                /* what the bar leaves to the + */
  position: relative;
  isolation: isolate;
  display: inline-flex;
  flex-wrap: nowrap;
  align-items: center;
  align-self: center;
  vertical-align: middle;
  gap: 0;
  height: var(--bar-h);
  min-width: 0;
  max-width: none;
  /* the height handed back in a table cell (--bar-trim, below); none on a
     note line, which is not a table row */
  margin-block: var(--bar-trim, 0px);
  /* Koel's phone grid (koel.css, two keys a line) goes: one line, always */
  grid-template-columns: none;
}
body.threads-koel td .user-table-row-actions { --bar-trim: -3.5px; }
/* THE BAR: the one shallow cut, drawn behind the segments. It is the group's
   own underlay so the `+` can stand outside it, and so nothing clips. */
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions::before {
  content: '';
  position: absolute;
  inset: 0 var(--rail-tail) 0 0;
  z-index: -1;
  border-radius: var(--stark-radius);
  background: color-mix(in srgb, var(--stark-well) 35%, transparent);
  box-shadow: var(--frost-hair-cut), var(--frost-hair-lip);
  pointer-events: none;
}
/* The `+` is in the markup at every width but drawn only under 760px
   (production), so the bar stops short of it there and nowhere else. While
   its band arrives or leaves production collapses the `+`, and the bar runs
   the whole group; it steps back once the `+` stands again (no timing). */
@media (max-width: 760px) {
  body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions:has(> [data-mobile-disclosure]) { --rail-tail: calc(var(--rail-disc-w) + var(--rail-disc-gap)); }
}
body.threads-koel .user-table tr.user-table__data-row--band-arriving :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions,
body.threads-koel .user-table tr.user-table__data-row--band-leaving :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions { --rail-tail: 0px; }

/* THE SWITCH, the bar's first segment: its slot clear (the bar is its
   ground), its outer end the bar's corner and its inner end square where the
   seam parts it from the pencil; a switch with no key after it keeps both
   corners. No lit edge under ON (the kit has none): ON reads by the accent
   word and the pane standing right. The form around it stands as tall as the
   bar. */
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions > form:has(> .fabric-status-toggle) { display: flex; height: var(--bar-h); }
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .fabric-status-toggle {
  --tg-w: var(--bar-switch-w);
  --tg-h: var(--bar-h);
  /* the pane keeps the width it had in the capsule (24px), not §20's
     height-led one: at the bar's 34px (44 on a phone) that pane grew to 30
     (40) and squeezed the OFF word out of a 52px slot */
  --frost-thumb-w: var(--bar-thumb-w);
  height: var(--bar-h);
  min-height: 0;
  margin-block: 0;
}
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .fabric-status-toggle .fabric-status-toggle__track,
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .fabric-status-toggle.is-active .fabric-status-toggle__track {
  border-radius: var(--stark-radius) 0 0 var(--stark-radius);
  background: transparent;
  box-shadow: none;
  /* production's 220ms fade on the slot stands down: the focus ring arrives
     at once, as on a key */
  transition-property: none;
}
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions > :is(form:has(> .fabric-status-toggle), .fabric-status-toggle):not(:has(~ .user-table-row-action)) .fabric-status-toggle__track { border-radius: var(--stark-radius); }
/* focus: the kit's 1px accent ring inside the segment, whole, as on a key */
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .fabric-status-toggle:focus-visible .fabric-status-toggle__track {
  outline: none;
  box-shadow: inset 0 0 0 1px var(--stark-accent);
}

/* THE KEY: no box, no radius of its own, the engraved glyph. The bar's end
   keys take its corners, so a pressed segment's well stays inside the bar
   (the phone's + follows the last key, so the last key is found by no key
   after it, not by :last-child). */
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action {
  position: relative;
  isolation: isolate;
  display: inline-grid;
  place-items: center;
  width: var(--bar-key-w);
  height: var(--bar-h);
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  outline: none;
  background: none;
  box-shadow: none;
  color: color-mix(in srgb, var(--stark-engrave) 40%, var(--stark-muted));
  /* production's 130ms key fade stands down: every state arrives at once */
  transition-property: none;
}
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action:first-child { border-radius: var(--stark-radius) 0 0 var(--stark-radius); }
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action:not(:has(~ .user-table-row-action)) { border-radius: 0 var(--stark-radius) var(--stark-radius) 0; }
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action:first-child:not(:has(~ .user-table-row-action)) { border-radius: var(--stark-radius); }
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action svg {
  width: var(--bar-glyph);
  height: var(--bar-glyph);
  filter: var(--frost-glyph-cut);
}
/* the segment's well: clear at rest and under the pointer */
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: none;
  box-shadow: none;
  pointer-events: none;
}
/* the seam, parting a key from whatever stands before it */
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action::after {
  content: '';
  position: absolute;
  top: 8px;
  bottom: 8px;
  left: 0;
  width: 1px;
  background: var(--frost-seam);
  box-shadow: 1px 0 0 var(--frost-seam-lip);
  pointer-events: none;
}
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action:first-child::after { content: none; }
/* hover: the glyph lights in the accent, the switch's own light */
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action:not(:disabled, [aria-disabled="true"]):hover { color: var(--stark-accent); }
/* pressed: the glyph lit, the segment a shade deeper — Stark's well, no drop */
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action:not(:disabled, [aria-disabled="true"]):active { color: var(--stark-accent); }
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action:not(:disabled, [aria-disabled="true"]):active::before { background: color-mix(in srgb, var(--stark-well) 70%, transparent); }
/* keyboard focus: the glyph to the ink, the kit's 1px accent ring inside the
   segment (the bar never crosses a seam or leaves the cut) */
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action:focus-visible { color: var(--stark-ink); }
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action:focus-visible::before { box-shadow: inset 0 0 0 1px var(--stark-accent); }

/* THE PREVIEW KEY (`--preview`): a key holding a picture instead of a glyph —
   the Jodi Price List's photo PDF, its first page drawn inside the Download
   key (docs/jodi-photo-preview-spec.md §1.4, MPF 1 Oct 2026). The house key
   with a modifier (rules 67, 68), so its click, seams, corners and focus are
   the key's own. The picture stands 40px tall, so a bar holding one is 40px
   (a phone's 44 already clears it) and hands the extra 3px back above and
   below, so the row keeps its height. The key is as wide as the page's
   picture is, up to 4:3; the picture takes the key's corners. Under the pointer the
   picture takes the kit's thin accent ring, the glyph's lit state having no
   glyph to light. */
body.threads-koel td .user-table-row-actions:has(> .user-table-row-action--preview) {
  --bar-preview-h: 40px;
  --bar-h: var(--bar-preview-h);
  --bar-trim: -6.5px;
}
body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions .user-table-row-action--preview {
  width: auto;
  min-width: 0;
}
body.threads-koel .user-table-row-action--preview .user-table-row-action__preview {
  display: block;
  width: auto;
  height: var(--bar-h);
  /* a wide page is cut to 4:3 at its centre, so one landscape PDF cannot
     widen the Photos column for every row (an 80px key added 40px to it) */
  max-width: calc(var(--bar-h) * 4 / 3);
  object-fit: cover;
  border-radius: inherit;
  background: var(--stark-well);
}
body.threads-koel .user-table-row-action--preview:not(:disabled, [aria-disabled="true"]):hover .user-table-row-action__preview,
body.threads-koel .user-table-row-action--preview:focus-visible .user-table-row-action__preview {
  outline: 1px solid var(--stark-accent);
  outline-offset: -1px;
}
@media (max-width: 480px), (pointer: coarse) {
  body.threads-koel td .user-table-row-actions:has(> .user-table-row-action--preview) {
    --bar-h: 44px;
    --bar-trim: -4.5px;
  }
}

/* THE BIN IS AN ORDINARY KEY in Threads (MPF, 1 Oct 2026: "make the data
   table delete action not red, just normal … just threads, leave the kit
   red"): `--danger` adds no colour here, so the bin rests, lights in the
   accent, presses and takes focus exactly as the pencil does. The kit's §33
   keeps its red bin; this is the one place Threads' bar differs from it. */

/* THE `+`: the phone table's row disclosure keeps production's own bordered
   look, its width (2.1rem) and its gap (.15rem), and its band animation; only
   its height is matched to the bar (reached by its `data-mobile-disclosure`
   hook, not its class: this is the bar's geometry, so the disclosure's look
   stays Koel's and F5i stays open). Said at two classes' weight so the band's
   collapse (three classes) still wins while a row opens or shuts. */
:where(body.threads-koel) .user-table-row-actions > [data-mobile-disclosure] {
  min-height: var(--bar-h);
  align-self: center;
}

/* A PHONE: the bar 44px tall, every key 44px wide (the kit's §33, on Stark's
   no-keyboard trigger), the switch the bar's height; in a table cell the
   bar hands back 4.5px above and below, so a row still measures 56px. */
@media (max-width: 480px), (pointer: coarse) {
  body.threads-koel :is(td, .dispatch-note-line, .loom-sep-card__line, .loom-sep-card__fit-price) .user-table-row-actions {
    --bar-h: 44px;
    --bar-key-w: 44px;
  }
  body.threads-koel td .user-table-row-actions { --bar-trim: -4.5px; }
}

/* ======================================== 24. THE TABLE GROUND IN DAYLIGHT
   Production draws every table's wrapper as a literal dark well
   (threads-production-ui.css `.user-table-wrapper`, 48% near-black), right
   for Koel's dark and for Frost's dark, but in Frost's daylight it laid a
   grey band under every table on a light card: §23's bin measured 1.6–1.7
   and the muted pencil 2.3 on it (29 Sep 2026 review of the row keys).
   Frost's tables stay paper (spec, stage 3), so in daylight the wrapper
   stops painting and the rows sit on the card itself; the border, the
   corners and the scroll stay production's. DARK KEEPS THE BAND, as it
   was: MPF saw both the morning of 29 Sep 2026 ("I think the darker
   version is better") and chose "Exactly as before" over a warm dark. */
:root[data-frost-mode="light"] body.threads-koel .user-table-wrapper { background: transparent; }


/* ======================== 25. THE DIALOG: a frosted frame round one paper sheet
   Spec stage 5 (MPF's night run, 29→29 Sep 2026: "dialogs and fields").
   Written once on the house skeleton — `.user-dialog` › `.user-dialog-surface`
   › header, `.user-dialog-form`, `.user-dialog-actions` (docs/ui-catalogue.md,
   "The dialog skeleton") — so it reaches every dialog of every family at once
   (MPF, 29 Sep 2026: "shouldn't a change have change everywhere!"). Copied
   from the kit's frost.css §18 ("the dialog", "the paper sheet", "the words on
   the glass foot") and §4 (the key ladder), values as the kit has them:
     the floor      the theme's own floor at 62% (daylight the ink at 24%),
                    blurred 4px — the page further away, not a black slab
     the frame      the frame's glass: the card at 56%, the pane's fill in the
                    dark, daylight's sheen; the pane's rim, edge and bloom and
                    the list's drop
     the sheet      the header and the form body, ONE flat paper tone inset by
                    the frame, the sheet's edge drawn on three sides of each
                    half so the two boxes read as one sheet
     the foot       the footer stands on the frame's glass: its keys climb the
                    ladder (rest nothing, a third under the pointer, two thirds
                    pressed and settled 1px, the 1px accent ring for focus)
     the confirm    the same box; its danger key keeps the danger word, lifted
                    for the glass (the kit's `--frost-foot-danger`)
   TWO DIFFERENCES FROM THE KIT, and why.
     1. No blur on the frame. The kit's frame is a real `backdrop-filter`
        sheet; here the surface is a box a controller animates (rule 155's
        owned list) and may hold the house dropdown, so it takes neither a
        filter (§1) nor the `position` an underlay would need. What shows
        through the frame is already the floor's 4px-blurred page, so the
        glass reads as frost without one.
     2. The paper gives back what the frame takes. The sheet's margin is the
        frame; its side padding is Threads' 20px (18px under 820px) less the
        frame, so every field stands exactly where it stood and the shared
        tracks (rule 70, `--dialog-pad`) are untouched. The header's 1px
        rule stays as a border painted in the paper (one sheet has no
        seam), so nothing below it moves.
   The command bar keeps its own glass sheet (§14), so the frame and the
   sheet below say `:not(.user-dialog--command-bar)`; its keys and its ×
   do not (MPF, 29 Sep 2026: Cancel, Open and × get the key look every
   other dialog has), so the key and × rules name every dialog. Colour,
   fill, border colour, shadow, corner and padding only. */
:root {
  /* The words on the glass foot (kit §18, measured there over the worst
     backdrop): the primary's accent a step lighter, the danger 40% towards
     white in the dark; daylight's own mixes. */
  --frost-foot-accent: color-mix(in srgb, var(--frost-accent) 80%, #fff);
  --frost-foot-danger: color-mix(in srgb, var(--frost-danger) 60%, #fff);
  /* A third of the pane without its lit top, as a row's is (kit §17/§24's
     `--frost-fb-hover`), and two thirds for a press. */
  --frost-pane-third: color-mix(in srgb, var(--frost-glass-fill) calc(var(--frost-glass-hover) * 100%), transparent);
  --frost-pane-press: color-mix(in srgb, var(--frost-glass-fill) calc(var(--frost-glass-press) * 100%), transparent);
  --frost-pane-whole: var(--frost-glass-fill);
}
@supports (color: oklch(from red l c h)) {
  :root { --frost-foot-accent: oklch(from var(--frost-accent) calc(l + .06) c h); }
}
:root[data-frost-mode="light"] {
  --frost-foot-accent: color-mix(in srgb, var(--frost-accent) 70%, var(--frost-ink));
  --frost-foot-danger: var(--frost-danger-glass);
  --frost-pane-whole: var(--frost-glass-sheen), var(--frost-glass-fill);
}

/* --- the floor ---------------------------------------------------------------- */
body.threads-koel .user-dialog::backdrop {
  background: var(--frost-scrim);
  -webkit-backdrop-filter: var(--frost-scrim-filter);
  backdrop-filter: var(--frost-scrim-filter);
}

/* --- the frame ------------------------------------------------------------------ */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-surface {
  border-color: var(--frost-glass-edge);
  border-radius: var(--stark-radius);
  background: var(--frost-list-sheen), linear-gradient(var(--frost-frame-fill), var(--frost-frame-fill)), var(--frost-frame-tint);
  box-shadow: var(--frost-glass-settled), var(--frost-list-drop);
}

/* --- the sheet: the header ------------------------------------------------------ */
/* On its own (a confirm, whose keys stand on the glass straight under it,
   or the rare box whose body is not the house form) the header is a whole
   sheet. Its 1px rule stays as a border in the paper's own colour (the
   border box takes the sheet's fill), so a header that sets its own bottom
   padding (the card batch dialogs' 18px) keeps it and nothing below moves. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-surface > .user-dialog-header {
  margin: var(--frost-frame) var(--frost-frame) 0;
  padding-top: calc(18px - var(--frost-frame));
  padding-inline: calc(20px - var(--frost-frame));
  border-bottom-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--frost-sheet);
  box-shadow: inset 0 1px 0 var(--frost-card-lip), 0 -1px 0 var(--frost-sheet-line), 0 1px 0 var(--frost-sheet-line), inset 1px 0 0 var(--frost-sheet-line), inset -1px 0 0 var(--frost-sheet-line);
}
/* Over the form body it is the sheet's top half: square at the foot, its
   own paper carried a pixel down over the join (the kit's 27 Sep review: a
   box landing on a half pixel showed a hairline of glass between the two
   halves); the body paints over that pixel, so the join cannot open. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-surface > .user-dialog-header:has(+ .user-dialog-form) {
  border-radius: var(--stark-radius) var(--stark-radius) 0 0;
  box-shadow: inset 0 1px 0 var(--frost-card-lip), 0 -1px 0 var(--frost-sheet-line), 0 1px 0 var(--frost-sheet), inset 1px 0 0 var(--frost-sheet-line), inset -1px 0 0 var(--frost-sheet-line);
}
/* The title takes the accent (Stark §13, MPF 21 Sep 2026: "a word in the
   accent is a breath, not a fill"); its size stays Threads'. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-heading h2 { color: var(--stark-accent); }
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-heading p { color: var(--stark-muted); }

/* The confirm's danger mark (kit §18, Stark's `.stark-danger-mark`): a well
   cut into the paper sheet, Stark's 5px square corner, the ! in the danger
   ink — Koel's round red wash goes. Its size stays Threads'. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-danger-icon {
  border-radius: var(--stark-radius);
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
  color: var(--stark-danger);
}

/* --- the sheet: the form body ---------------------------------------------------- */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-surface > .user-dialog-form {
  margin-inline: var(--frost-frame);
  padding-inline: calc(20px - var(--frost-frame));
  border-radius: 0 0 var(--stark-radius) var(--stark-radius);
  background: var(--frost-sheet);
  box-shadow: 0 1px 0 var(--frost-sheet-line), inset 1px 0 0 var(--frost-sheet-line), inset -1px 0 0 var(--frost-sheet-line);
  scrollbar-color: var(--stark-line) transparent;
}
/* A body with no header above it is a whole sheet. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-surface > .user-dialog-form:first-child {
  margin-top: var(--frost-frame);
  border-radius: var(--stark-radius);
}
@media (max-width: 820px) {
  body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-surface > .user-dialog-header { padding-inline: calc(18px - var(--frost-frame)); }
  body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-surface > .user-dialog-form { padding-inline: calc(18px - var(--frost-frame)); }
}

/* --- the foot: the frame's own glass --------------------------------------------- */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-surface > .user-dialog-actions {
  border-top-color: transparent;
  border-radius: 0 0 var(--stark-radius) var(--stark-radius);
  background: transparent;
}

/* --- the ×: a key on the ladder (the Preferences box's, §17) ---------------------- */
body.threads-koel .user-dialog .user-dialog-close {
  position: relative;
  isolation: isolate;
  border-color: transparent;
  border-radius: var(--frost-key-r);
  background: none;
  box-shadow: none;
  color: var(--stark-muted);
}
body.threads-koel .user-dialog .user-dialog-close::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.94);
  pointer-events: none;
  transition: opacity var(--stark-t-settle) var(--stark-ease), transform var(--stark-t-settle) var(--stark-ease);
}
body.threads-koel .user-dialog .user-dialog-close:is(:hover, :focus-visible) {
  border-color: transparent;
  background: none;
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel .user-dialog .user-dialog-close:is(:hover, :focus-visible)::before { opacity: var(--frost-glass-hover); transform: none; }
body.threads-koel .user-dialog .user-dialog-close:active::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
  transition-duration: var(--stark-t-tap);
}
body.threads-koel .user-dialog .user-dialog-close:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }

/* --- the keys: Stark §7 as Frost §4 redraws them -----------------------------------
   Every `.button` a dialog holds, on the foot or in the body (the line
   builders' +, the stepper, Select all), and the Maps boards' own keys
   (Reset, Apply, Undo, Save — §31): the key lies flush — no fill, no
   border, no drop — an uppercase word in the round-ended capsule (Frost rule
   2), and the reader gets back a pane of glass in `::before`. The inks are
   Stark's: a secondary in the muted brightening to the ink, a primary in the
   ink turning the accent, the danger in its own word. Heights and paddings
   stay the dialog's (threads-production-ui.css: 40px, 8px 13px). */
body.threads-koel :is(.user-dialog, .cut-maps) .button {
  position: relative;
  isolation: isolate;
  border-color: transparent;
  border-radius: var(--frost-key-r);
  background: none;
  box-shadow: none;
  text-shadow: none;
  color: var(--stark-muted);
  font-size: var(--stark-text-button);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  /* A key's word is one line (stage 5 review, 29 Sep 2026: at 375 the
     capitals wrapped "SAVE 0 CARDS" and "DELETE REQUIREMENTS" onto two
     lines and the foot grew 36 → 50px); on a phone the spacing closes up
     so the longest pair still fits the foot. */
  white-space: nowrap;
}
@media (max-width: 600px) {
  body.threads-koel :is(.user-dialog, .cut-maps) .button { letter-spacing: .02em; padding-inline: 10px; }
}
/* The Fabric mapping manager's Create key stands IN the field row, not on a
   foot, so its capitals were taking width from the three fields (review:
   362/268/268 → 342/254/253px at 1440); there it closes up as on a phone. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .fabric-mapping-create-action { letter-spacing: .02em; padding-inline: 10px; }
body.threads-koel :is(.user-dialog, .cut-maps) .button::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.94);
  pointer-events: none;
  transition:
    opacity var(--stark-t-settle) var(--stark-ease),
    transform var(--stark-t-settle) var(--stark-ease),
    box-shadow var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel :is(.user-dialog, .cut-maps) .button--primary { color: var(--stark-ink); }
body.threads-koel :is(.user-dialog, .cut-maps) .button--danger { color: var(--frost-foot-danger); }
body.threads-koel :is(.user-dialog, .cut-maps) .button:is(:hover, :focus-visible) {
  border-color: transparent;
  background: none;
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel :is(.user-dialog, .cut-maps) .button--primary:is(:hover, :focus-visible) { color: var(--frost-foot-accent); }
body.threads-koel :is(.user-dialog, .cut-maps) .button--danger:is(:hover, :focus-visible) { color: var(--frost-foot-danger); }
body.threads-koel :is(.user-dialog, .cut-maps) .button:not(:disabled, [aria-disabled="true"]):is(:hover, :focus-visible)::before { opacity: var(--frost-glass-hover); transform: none; }
body.threads-koel :is(.user-dialog, .cut-maps) .button:not(:disabled, [aria-disabled="true"]):active {
  border-color: transparent;
  background: none;
  box-shadow: none;
}
body.threads-koel :is(.user-dialog, .cut-maps) .button:not(:disabled, [aria-disabled="true"]):active::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
  transition-duration: var(--stark-t-tap);
}
body.threads-koel :is(.user-dialog, .cut-maps) .button:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }
body.threads-koel :is(.user-dialog, .cut-maps) .button--danger:focus-visible { outline-color: var(--frost-foot-danger); }
/* Unavailable: no pane, even under the pointer (Stark §7). */
body.threads-koel :is(.user-dialog, .cut-maps) .button:is(:disabled, [aria-disabled="true"]) { color: var(--stark-stone); }

@media (prefers-reduced-motion: reduce) {
  body.threads-koel :is(.user-dialog, .cut-maps) .button::before,
  body.threads-koel .user-dialog .user-dialog-close::before { transition-duration: .01ms; }
}


/* --- the batch dialogs' furniture ------------------------------------------------
   The card dialogs (Add Cards, Add split cards, and every family's batch and
   dispatch dialogs that copied them) group their fields in sections with a
   numbered step and count their lines in a chip; Frost's words for each:
   a section is a group, so a well pressed into the sheet (kit §10) — Koel's
   accent-washed gradient box goes; its step number a pit cut in the paper
   (kit §18's panel step); the count a chip that names a thing (kit §18: a
   pane at 55% of a key's fill); the line's + and × keys on the ladder in
   Frost's capsule, the + a primary (its word the accent under the pointer),
   no accent slab and no halo. Sizes stay production's. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.card-batch-context, .card-batch-lines) {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--stark-group);
  box-shadow: var(--frost-press-well);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .card-batch-step {
  border-color: transparent;
  border-radius: calc(var(--stark-radius) - 1px);
  background: var(--stark-sink);
  box-shadow: var(--frost-pit), var(--frost-pit-lip);
  color: var(--stark-legend);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .card-batch-count {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--frost-glass-sheen), color-mix(in srgb, var(--frost-glass-fill) 55%, transparent);
  box-shadow: var(--frost-glass-shadow);
  color: var(--stark-ink);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .card-entry-add,
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .card-entry-remove {
  position: relative;
  isolation: isolate;
  border-color: transparent;
  border-radius: var(--frost-key-r);
  background: none;
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.card-entry-add, .card-entry-remove)::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.94);
  pointer-events: none;
  transition: opacity var(--stark-t-settle) var(--stark-ease), transform var(--stark-t-settle) var(--stark-ease);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.card-entry-add, .card-entry-remove):is(:hover, :focus-visible) {
  border-color: transparent;
  background: none;
  box-shadow: none;
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .card-entry-add:is(:hover, :focus-visible) { color: var(--stark-accent); }
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.card-entry-add, .card-entry-remove):is(:hover, :focus-visible)::before { opacity: var(--frost-glass-hover); transform: none; }
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.card-entry-add, .card-entry-remove):active::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.card-entry-add, .card-entry-remove):focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }


/* The Fabric mapping manager (every family's Fabrics › Map dialog) is the one
   house box whose body is two forms rather than the house form body, so its
   header stands as a whole sheet and its two groups stand on the frame's
   glass: each group a well (kit §10), its heading the accent lifted for the
   glass as the foot's words are (kit §18, `--frost-foot-accent`). A token
   input's pill well (the Fabric dialog's Parent Items) is a well too. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .fabric-mapping-create-form,
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .token-input__well {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--stark-group);
  box-shadow: var(--frost-press-well);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.fabric-mapping-create-heading, .user-dialog-group > legend) { color: var(--frost-foot-accent); }


/* ============================================= 26. THE FIELDS KEEP THEIR LINE
   Frost rule 6 (kit §9): a thing that holds input is a line — no box, one
   line under the control in the field's own measured tones, brighter under
   the pointer, the accent and one pixel under it on focus. Koel's near-black
   well, its corner and its accent halo go. Written on the house field,
   `.form-field`, wherever it stands — a dialog, Preferences, a report's
   scope form, the PPC Pieces panel — and on the two enhanced faces that
   stand in a field for a select and a date (`threads-select__trigger`,
   `threads-date__trigger`) — and every such control inside a dialog, field
   or not (a split card's lines, a staged row's own faces). A table's column filter and a filter board's
   date well are not `.form-field`s and keep their own stage's look.
   The border keeps its 1px on every side, only coloured away from the
   bottom, so no field grows or shrinks by a pixel; the words start on the
   line's left end, as the kit's do, and the right keeps production's room,
   where a chevron or a scroller's bar stands. The note (a textarea) is
   the rule's exception, as in the kit (§10): Stark's well at a field's size.
   A REFUSED FIELD IS RED, WHATEVER ELSE IT IS (MPF, 27 Sep 2026; Koel's
   words, kept): its line in the danger, rest, focus and open alike. */
body.threads-koel :is(.form-field, .user-dialog:not(.user-dialog--command-bar)) :is(input:not([type="checkbox"], [type="radio"], [type="hidden"], [type="file"], [type="range"], [type="color"], .threads-select__search), select, .threads-select__trigger, .threads-date__trigger) {
  --stark-line: var(--frost-field-line);
  --stark-line-lit: var(--frost-field-line-lit);
  padding-left: 0;
  border-color: transparent;
  border-bottom-color: var(--stark-line);
  border-radius: 0;
  background-color: transparent;
  box-shadow: none;
  color: var(--stark-ink);
}
/* The inputs and the enhanced faces carry no chevron image of their own; a
   plain select keeps Koel's drawn chevron (`background-image`). */
body.threads-koel :is(.form-field, .user-dialog:not(.user-dialog--command-bar)) :is(input:not([type="checkbox"], [type="radio"], [type="hidden"], [type="file"], [type="range"], [type="color"], .threads-select__search), .threads-select__trigger, .threads-date__trigger) { background-image: none; }
body.threads-koel :is(.form-field, .user-dialog:not(.user-dialog--command-bar)) :is(input:not([type="checkbox"], [type="radio"], [type="hidden"], [type="file"], [type="range"], [type="color"], .threads-select__search), select, .threads-select__trigger, .threads-date__trigger):hover {
  border-bottom-color: var(--stark-line-lit);
}
body.threads-koel :is(.form-field, .user-dialog:not(.user-dialog--command-bar)) :is(input:not([type="checkbox"], [type="radio"], [type="hidden"], [type="file"], [type="range"], [type="color"], .threads-select__search), select, .threads-select__trigger, .threads-date__trigger):is(:focus, :focus-visible, .is-open),
body.threads-koel :is(.form-field, .user-dialog:not(.user-dialog--command-bar)) .threads-date.is-open > .threads-date__trigger {
  outline: none;
  border-color: transparent;
  border-bottom-color: var(--stark-accent);
  box-shadow: 0 1px 0 var(--stark-accent);
}
/* The line builders' field, where the + puts focus back by script (MPF,
   2 Sep 2026: make it obvious): the same accent line with a whisper of the
   accent under it — a place, not a glow. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .requirement-line-builder :is(.threads-select__trigger, input):focus {
  border-color: transparent;
  border-bottom-color: var(--stark-accent);
  background-color: color-mix(in srgb, var(--stark-accent) 12%, transparent);
  box-shadow: 0 1px 0 var(--stark-accent);
}
body.threads-koel :is(.form-field, .user-dialog:not(.user-dialog--command-bar)) :is(.threads-select__trigger, .threads-date__trigger).is-placeholder { color: var(--stark-muted); }
body.threads-koel .form-field :is(input, textarea)::placeholder { color: var(--stark-stone); }
body.threads-koel :is(.form-field, .user-dialog:not(.user-dialog--command-bar)) :is(.threads-select__chevron, .threads-date__chevron, .threads-date__icon) { color: var(--stark-stone); border-color: var(--stark-stone); }
body.threads-koel .form-field :is(input, select, textarea):disabled { color: var(--stark-muted); }

/* Refused. */
body.threads-koel :is(.form-field, .user-dialog:not(.user-dialog--command-bar)) :is(input, select, .threads-select__trigger, .threads-date__trigger)[aria-invalid="true"],
body.threads-koel :is(.form-field, .user-dialog:not(.user-dialog--command-bar)) :is(input, select, .threads-select__trigger, .threads-date__trigger)[aria-invalid="true"]:is(:focus, :focus-visible, .is-open) {
  border-color: transparent;
  border-bottom-color: var(--stark-danger);
  box-shadow: 0 1px 0 var(--stark-danger);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .requirement-line-builder :is(.threads-select__trigger, input)[aria-invalid="true"]:is(:focus, :focus-visible) {
  border-color: transparent;
  border-bottom-color: var(--stark-danger);
  background-color: color-mix(in srgb, var(--stark-danger) 12%, transparent);
  box-shadow: 0 1px 0 var(--stark-danger);
}

/* The note: Stark's well at a field's size (kit §10). */
body.threads-koel .form-field textarea {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
  color: var(--stark-ink);
}
body.threads-koel .form-field textarea:hover:not(:disabled, [readonly]) { box-shadow: var(--frost-press-body), inset 0 -1px 0 var(--stark-line-lit); }
body.threads-koel .form-field textarea:is(:focus, :focus-visible) {
  outline: none;
  border-color: transparent;
  box-shadow: var(--frost-press-body), var(--stark-focus-ring);
}
body.threads-koel .form-field textarea[readonly] { box-shadow: var(--frost-press-shallow); }
body.threads-koel .form-field textarea[aria-invalid="true"] { box-shadow: var(--frost-press-body), inset 0 -1px 0 var(--stark-danger), 0 1px 0 var(--stark-danger); }

/* A line builder (the fieldset a staging dialog builds each line in): a
   thing that groups is a well (kit §10, Stark's `.stark-fieldset`) — the
   group's paper pressed in with the tokens; its line and 12px corner go.
   A field group on a `--rows` dialog (`.user-dialog-group`, the TR
   Price Group dialogs' "Price fields", 4 Oct 2026) is the same well, its
   legend the group heading in the lifted accent the mapping manager's
   headings wear. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.requirement-line-builder, .user-dialog-group) {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--stark-group);
  box-shadow: var(--frost-press-well);
}

/* A staged line's own inputs, inside a dialog's staging table: lines too. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.card-staging-table, .requirement-staging-table) input:not([type="checkbox"], [type="radio"], [type="hidden"]) {
  border-color: transparent;
  border-bottom-color: var(--frost-field-line);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.card-staging-table, .requirement-staging-table) input:not([type="checkbox"], [type="radio"], [type="hidden"]):hover { border-bottom-color: var(--frost-field-line-lit); }
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.card-staging-table, .requirement-staging-table) input:not([type="checkbox"], [type="radio"], [type="hidden"]):is(:focus, :focus-visible) {
  outline: none;
  border-color: transparent;
  border-bottom-color: var(--stark-accent);
  box-shadow: 0 1px 0 var(--stark-accent);
}


/* ====================================== 27. THE LIST AND THE CALENDAR: glass cards
   Kit §13 ("the dropdown's list: glass") and §18 ("the calendar: a frosted
   card"). The house dropdown's panel — in a dialog, on a page, a table's
   column filter (the same panel, MPF 28 Aug 2026: "the dialog dropdown, full
   stop") — and the date picker's calendar are the things that float over a
   form, so they are glass. As with the menu's sheets (§14) and the toasts
   (§18), no blur: both panels are controllers' boxes lifted to the top
   layer, and their held opening animation makes them their own backdrop, so
   the list's card colour goes on whole with the list's sheen and the list's
   drop (the pane's rim and edge went 16 Oct 2026, below).
   ITS ROWS CLIMB THE LADDER (kit §13): a third of the pane under the pointer,
   two thirds pressed and settled, the whole pane on the row the arrow keys
   hold (the one Enter will take), its word the accent. The chosen row is
   MARKED, not filled — its ✓ in the accent, as Stark marks it with a square.
   THE CALENDAR (kit §18): days keep Stark's square; a third under the
   pointer, the picked day the whole pane in the accent, today a quiet
   square in the legend's tone (the accent belongs to the pick), a day of the
   next or last month the shell's stone. No LED, no glow. Colours, fills,
   borders, corners and shadows only — the panels' place, size, scroll and
   motion are the controllers'. */
body.threads-koel :is(.threads-select__panel, .threads-date__panel) {
  border-color: var(--stark-card-edge);
  border-radius: var(--stark-radius);
  background: var(--frost-list-sheen), var(--frost-sheet-tint);
  /* The drop alone: no glass rim, edge or bloom (MPF, 16 Oct 2026: "do you see
     the whitish borders", then "add it for all dropdowns"). The bloom also
     peeked out at the top corners beside the search's sheet-coloured shadow,
     a paler strip above the box. */
  box-shadow: var(--frost-list-drop);
  color: var(--stark-ink);
}

/* The panel's search: a line (Stark rule 5), no glow on focus.
   ON THE PANEL'S OWN GROUND, NOT TRANSPARENT (MPF, 1 Oct 2026: "the item name
   dropdown doesn't look right"). The search is the house's STICKY field — the
   panel owns the scroll and the rows pass under it (threads-production-ui.css,
   "Stay fully opaque while option rows scroll underneath this sticky field").
   A transparent line let every scrolled row read through it: a list opened
   on its chosen Item (or scrolled at all) drew "Kit Kat" above the box and
   "Bon Bon" struck through by its underline. So the box takes the sheet's
   own colour, and a shadow of that colour taller than the panel's 8px padding
   (the panel clips the rest) closes the strip above it, where rows would
   show over the sticky top; a second, 5px down, fills the box's own 5px
   margin, so a row is gone under the line rather than peeking below it.
   Threads-only: the kit's lists have no sticky search. */
body.threads-koel :is(.threads-select__panel, .user-table-filter__panel) :is(.threads-select__search, .user-table-filter__search) {
  padding-inline: 4px;
  border-color: transparent;
  border-bottom-color: var(--frost-field-line);
  border-radius: 0;
  background: var(--frost-sheet-tint);
  box-shadow: 0 -12px 0 var(--frost-sheet-tint), 0 5px 0 var(--frost-sheet-tint);
  color: var(--stark-ink);
}
body.threads-koel :is(.threads-select__panel, .user-table-filter__panel) :is(.threads-select__search, .user-table-filter__search):hover { border-bottom-color: var(--frost-field-line-lit); }
body.threads-koel :is(.threads-select__panel, .user-table-filter__panel) :is(.threads-select__search, .user-table-filter__search):is(:focus, :focus-visible) {
  outline: none;
  border-color: transparent;
  border-bottom-color: var(--stark-accent);
  box-shadow: 0 1px 0 var(--stark-accent), 0 -12px 0 var(--frost-sheet-tint), 0 5px 0 var(--frost-sheet-tint);
}

/* --- the rows --------------------------------------------------------------------- */
body.threads-koel .threads-select__options > .threads-select__option,
body.threads-koel .user-table-filter__panel .user-table-filter__option {
  border-radius: var(--frost-row-r);
  background: none;
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel .threads-select__options > .threads-select__option:hover,
body.threads-koel .user-table-filter__panel .user-table-filter__option:hover {
  background: var(--frost-pane-third);
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel .threads-select__options > .threads-select__option[aria-selected="true"],
body.threads-koel .user-table-filter__panel .user-table-filter__option:has(input:checked) {
  background: none;
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel .threads-select__options > .threads-select__option[aria-selected="true"]:hover,
body.threads-koel .user-table-filter__panel .user-table-filter__option:has(input:checked):hover { background: var(--frost-pane-third); }
body.threads-koel .threads-select__options > .threads-select__option .threads-select__selected-marker { color: var(--stark-accent); }
/* The row the keys hold: the whole pane, whether or not it is the chosen one. */
body.threads-koel .threads-select__options > .threads-select__option.is-keyboard-active,
body.threads-koel .threads-select__options > .threads-select__option[aria-selected="true"].is-keyboard-active,
body.threads-koel .user-table-filter__panel .user-table-filter__option.is-keyboard-active,
body.threads-koel .user-table-filter__panel .user-table-filter__option.is-keyboard-active:has(input:checked) {
  background: var(--frost-pane-whole);
  box-shadow: var(--frost-glass-shadow);
  color: var(--stark-accent);
}
body.threads-koel .threads-select__options > .threads-select__option:active,
body.threads-koel .user-table-filter__panel .user-table-filter__option:active {
  background: var(--frost-pane-press);
  box-shadow: var(--frost-glass-settled);
}
body.threads-koel .threads-select__options > .threads-select__option:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }
/* "Choose …" clears rather than chooses: it reads quieter. */
body.threads-koel .threads-select__options > .threads-select__option[data-value=""] { color: var(--stark-muted); }
body.threads-koel .threads-select__options > .threads-select__option[data-value=""].is-keyboard-active { color: var(--stark-accent); }

/* --- the calendar ----------------------------------------------------------------- */
body.threads-koel .threads-date__header strong { color: var(--stark-ink); }
body.threads-koel .threads-date__weekdays span { color: var(--stark-legend); }
/* The month's arrows and Today: keys on the ladder, in Frost's capsule. */
body.threads-koel :is(.threads-date__step, .threads-date__footer button) {
  border-color: transparent;
  border-radius: var(--frost-key-r);
  background: none;
  box-shadow: none;
  color: var(--stark-muted);
}
body.threads-koel :is(.threads-date__step, .threads-date__footer button):is(:hover, :focus-visible) {
  border-color: transparent;
  background: var(--frost-pane-third);
  color: var(--stark-ink);
}
body.threads-koel :is(.threads-date__step, .threads-date__footer button):active { background: var(--frost-pane-press); box-shadow: var(--frost-glass-settled); }
body.threads-koel :is(.threads-date__step, .threads-date__footer button):focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }
body.threads-koel .threads-date__footer { border-top-color: var(--stark-key-low); }
/* A day: Stark's square, the figure in the ink. */
body.threads-koel .threads-date__grid button {
  border-radius: var(--stark-radius);
  background: none;
  box-shadow: none;
  color: var(--stark-ink);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}
body.threads-koel .threads-date__grid button:hover { background: var(--frost-pane-third); box-shadow: none; color: var(--stark-ink); }
body.threads-koel .threads-date__grid button:active { background: var(--frost-pane-press); box-shadow: var(--frost-glass-settled); }
body.threads-koel .threads-date__grid button:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--stark-accent); }
body.threads-koel .threads-date__grid button[data-outside="true"] { color: var(--frost-shell-stone); }
body.threads-koel .threads-date__grid button[data-today="true"] { background: none; box-shadow: none; color: var(--stark-ink); }
body.threads-koel .threads-date__grid button[data-today="true"]:hover { background: var(--frost-pane-third); }
body.threads-koel .threads-date__grid button[data-today="true"]::after {
  border-radius: 1px;
  background: var(--stark-legend);
  box-shadow: none;
}
body.threads-koel .threads-date__grid button[aria-selected="true"],
body.threads-koel .threads-date__grid button[aria-selected="true"]:is(:hover, :active) {
  background: var(--frost-pane-whole);
  box-shadow: var(--frost-glass-shadow);
  color: var(--stark-accent);
}
body.threads-koel .threads-date__grid button[aria-selected="true"][data-today="true"]::after { background: var(--stark-accent); }


/* ========================================= 28. STATUS MESSAGES AND THE LOADER
   Kit §18: a status is a sentence in a card, so it stays paper — Stark's
   well, pressed in with the tokens — and its lamp is a 5px square of colour
   with nothing round it (Frost rule 7). Koel's LED (a white dot with a
   coloured bloom) goes. The lamps say what the toasts say (§18): a plain
   message the accent, a note (`--info`) the stone, a warning the legend
   (the stone in daylight, where the legend measured under 3:1 on the well),
   a refusal the danger, whose first words take the danger too. Koel's flex
   row, gap and sizes stay: only colour, fill, border colour, shadow and
   corner change. The sign-in's own refusal (§9) is its own. */
body.threads-koel .status-message {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
  color: var(--frost-read-in-well);
}
body.threads-koel .status-message::before {
  border-radius: calc(var(--stark-radius) - 3px);
  background: var(--stark-accent);
  box-shadow: none;
}
body.threads-koel .status-message--info::before { background: var(--stark-stone); }
body.threads-koel .status-message--warning::before { background: var(--stark-legend); }
:root[data-frost-mode="light"] body.threads-koel .status-message--warning::before { background: var(--stark-stone); }
body.threads-koel .status-message--danger::before { background: var(--stark-danger); }
body.threads-koel .status-message strong { color: var(--stark-ink); }
body.threads-koel .status-message--danger strong { color: var(--stark-danger); }

/* THE LOADER (kit §18, "loaders: calm"): between pages koel.js lays its
   overlay over the canvas after 650ms. Its drawing — the brand thread and
   the blinking eye with its halo — becomes Stark's page loader: a 2px track
   in the key's low tone with a plain accent segment, a third of it long,
   travelling on the arrival rung; held still under Reduce Motion. The
   overlay's slab becomes the dialog's soft floor. The overlay, its timing
   and its fade are koel.js's and stay. */
body.threads-koel .koel-page-loader { background: var(--frost-scrim); }
body.threads-koel .koel-page-loader > svg { display: none; }
body.threads-koel .koel-page-loader::after {
  content: '';
  width: min(240px, 60vw);
  height: 2px;
  border-radius: 1px;
  background: linear-gradient(var(--stark-accent), var(--stark-accent)) no-repeat, var(--stark-key-low);
  background-size: 32% 100%, auto;
  background-position: 0 0, 0 0;
}
@keyframes frost-loader-travel {
  from { background-position: -47% 0, 0 0; }
  to { background-position: 147% 0, 0 0; }
}
@media (prefers-reduced-motion: no-preference) {
  body.threads-koel .koel-page-loader::after { animation: frost-loader-travel var(--stark-t-arrive) var(--stark-ease) infinite; }
}


/* ============================================ 29. THE ARRANGE ROWS: paper and glass
   Kit §34 ("the order editor's rows"), every Arrange order dialog and the
   Cuts pages' Arrange panel (the shared `order-editor-*`): a row is plain
   paper; under the pointer, or with its grip holding the keyboard, a third
   of the pane; the row being carried the whole pane, lifted with the list's
   drop (production's fade kept — the drag's own opacity is the script's
   word); the row it would land on answers with the accent line on its edge,
   2px, solid, no glow. The grip is option A's quiet glyph (kit §33): the
   dots bare in the muted ink, no box at rest, the ladder's pane under the
   pointer, two thirds pressed, the 1px accent ring for the keyboard. Only
   colour, fill, border colour, shadow and corner change; the row's grid,
   44px and the grip's 36px stay production's. */
body.threads-koel .order-editor-item {
  position: relative;
  isolation: isolate;
  border-color: transparent;
  border-radius: var(--frost-row-r);
  background: none;
  box-shadow: none;
}
body.threads-koel .order-editor-item::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.995, .9);
  pointer-events: none;
  transition:
    opacity var(--stark-t-settle) var(--stark-ease),
    transform var(--stark-t-settle) var(--stark-ease),
    box-shadow var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel .order-editor-item:is(:hover, :has(:focus-visible))::before { opacity: var(--frost-glass-hover); transform: none; }
body.threads-koel .order-editor-item.is-dragging::before,
body.threads-koel .order-editor-item:has(.order-editor-handle[aria-pressed="true"])::before {
  opacity: 1;
  transform: none;
  box-shadow: var(--frost-glass-shadow), var(--frost-list-drop);
}
/* Threads' editor says only which row is under the drop, not which edge it
   joins, so the landing is the thin accent ring round that row (the kit's
   drop-target word, §18), solid, no glow. */
body.threads-koel .order-editor-item.is-drag-over {
  border-color: transparent;
  background: none;
  box-shadow: inset 0 0 0 1px var(--stark-accent);
}
body.threads-koel .order-editor-position { color: var(--stark-muted); }
body.threads-koel .order-editor-name { color: var(--stark-ink); }
body.threads-koel .order-editor-guidance { color: var(--stark-muted); }
body.threads-koel .order-editor-handle {
  position: relative;
  isolation: isolate;
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: none;
  box-shadow: none;
  color: var(--stark-muted);
}
body.threads-koel .order-editor-handle::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.94);
  pointer-events: none;
  transition: opacity var(--stark-t-settle) var(--stark-ease), transform var(--stark-t-settle) var(--stark-ease);
}
body.threads-koel .order-editor-handle:is(:hover, :focus-visible, [aria-pressed="true"]) {
  outline: 0;
  border-color: transparent;
  background: none;
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel .order-editor-handle:is(:hover, :focus-visible)::before { opacity: var(--frost-glass-hover); transform: none; }
body.threads-koel .order-editor-handle:is(:active, [aria-pressed="true"])::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
  transition-duration: var(--stark-t-tap);
}
body.threads-koel .order-editor-handle:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }
@media (prefers-reduced-motion: reduce) {
  body.threads-koel :is(.order-editor-item, .order-editor-handle)::before { transition-duration: .01ms; }
}


/* ======================================== 30. THE STAGING TABLES IN A DIALOG
   The lines a dialog stages before one save (docs/ui-catalogue.md, "A dialog
   that stages lines"): `requirement-staging` and `card-staging-wrap` round
   their tables, in every family. Kit §17's paper table at a dialog's size:
   the wrap a well pressed into the sheet (its line and 12px corner go), the
   sticky head the card's low paper so the lines pass under it, the head's
   words the legend's spaced capitals, rows split by the card's hairline and
   a third of the pane under the pointer; the running total above the lines
   a pressed well too (its accent wash was a fill, rule 11), its figure the
   ink; a staged negative §19's red. Scroll caps, widths, the sticky head's
   place and the lines' arrive and leave motion stay production's. */
/* A split card's written lines (Add split cards) are the same answer-shaped
   table under its row, so the same well. */
/* …and a house table set inside a dialog (the Fabric mapping manager's list,
   the PPC manager's) is the same well round its rows. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.requirement-staging, .card-staging-wrap, .split-card-row__lines, .user-table-wrapper) {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.requirement-staging-table, .card-staging-table) :is(th, td) { border-bottom-color: var(--stark-key-low); }
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.requirement-staging-table, .card-staging-table) th {
  background: var(--stark-card-low);
  color: var(--stark-legend);
}
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.requirement-staging-table, .card-staging-table) td { color: var(--stark-ink); }
body.threads-koel .user-dialog:not(.user-dialog--command-bar) :is(.requirement-staging-table, .card-staging-table) tbody tr:hover > td { background: var(--frost-pane-third); }
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .card-staging-table [data-card-staged-empty] td { color: var(--stark-muted); }
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .requirement-staging-table .card-working-negative { color: var(--frost-neg); }
/* The Revise balance dialog's negative Balance reads in the negative colour,
   as it does in the table — the cell rule above would otherwise paint it ink
   (the stage-1 review, 30 September 2026). Its own form only, no id. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) [data-revise-form] .card-staging-table td.balance-row-pieces.is-negative { color: var(--frost-neg); }
body.threads-koel .staging-running-total {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
  color: var(--frost-read-in-well);
}
body.threads-koel .staging-running-total strong { color: var(--stark-ink); }
body.threads-koel .staging-running-total__divider { color: var(--stark-stone); }


/* ================================ 31. THE MAPS BOARDS AND THE CUTS WIZARD
   Left by the change-over (batch A, 29 Sep 2026) for this stage: Shirting,
   Suiting and Jodi › Maps (two house scope boards whose wells take dragged
   Cuts, `.cut-maps`) and the Cuts pages' Add Cuts wizard (`.cut-wizard`,
   whose step two is a row of the same house wells). The Loom cannot draw
   either — their wells are drop targets that post — so the HOUSE board is
   dressed in the kit's shared ground (frost.css §24), on these two scopes
   alone; one class family serves all three families (application.css,
   "One class family for all three cut-piece families"):
     the board      the card's own paper — Koel's dark tray and line go
     a well         its track a well pressed into the paper (§10, §17)
     a legend       Stark's legend: the name in the legend's spaced
                    capitals, its mark a small square in its Master's fixed
                    colour (MPF, 28 Sep 2026: "One fixed colour per Master,
                    the same on every board") — Fabric Type, Not filed, and
                    every Cut Group the Maps Group's one hue; under the
                    pointer a third of the pane
     a pill         Stark's raised pill (§79) on the paper, its LED a plain
                    square of its Master's colour; under the pointer a third
                    of the pane; chosen (`is-on`) the §24 glass chip with a
                    whisper of the hue; a Cut still unsaved keeps its dashed
                    rim, in the hue; the pill being carried (`is-picked`)
                    the whole pane with the accent word; a Fabric's default
                    Cut stays quieter, as the house draws it
     a drop         the well it would land in answers with the thin accent
                    ring; in the wizard, where it is also the keyboard's
                    only cursor (MPF, 10 Sep 2026), two pixels in the
                    Group's hue and its legend lit
     the Filter lane, the scope line, the tray: a well's rail legend, a
                    line field, a pressed tray; the keys the dialog's (§25)
   The house's colours arrive inline (`--filter-lane-colour`, Koel's
   hexes); a stylesheet cannot outrank an inline value, so the Frost hue
   travels in its own name, `--frost-maps-lane`, set on each well by its
   key (and on a Fabric Type pill wherever it has been carried, by the well
   it came from). Colour, fill, border colour, shadow and corner only: the tracks'
   locked heights, the pills' flight and every drop are the scripts'. */
:root {
  /* The three Masters these boards draw (Fabric Type, Unfiled, a Map's
     Group) are the one map's, "one fixed colour per Master" above, which
     stands app-wide so the boards wear them on pages the page sheet does not
     load. The pill's raised lip and drop (kit §17). */
  --frost-nub-lip: inset 0 1px #ffffff14;
  --frost-nub-drop: 0 2px 4px #000a;
}
:root[data-frost-mode="light"] {
  --frost-nub-lip: inset 0 1px var(--frost-card-lip);
  --frost-nub-drop: 0 1px 2px color-mix(in srgb, var(--frost-ink) 18%, transparent);
}
body.threads-koel :is(.cut-maps, .cut-wizard) {
  --frost-maps-lane: var(--frost-hue-maps-group);
}
body.threads-koel :is(.cut-maps, .cut-wizard) :is([data-production-table-filter-board-well="fabric-type"], [data-production-table-filter-board-of="fabric-type"]) { --frost-maps-lane: var(--frost-hue-fabric-type); }
body.threads-koel :is(.cut-maps, .cut-wizard) [data-production-table-filter-board-well="unfiled"] { --frost-maps-lane: var(--frost-hue-unfiled); }
/* Production Type Mappings' mapper (MPF, 15 Oct 2026: "the production type mappings page still has the older style of
   pills"): its Fabrics panel and its Assign wells are house wells and pills (shirt-production-type-mappings.js buildPill()),
   named in the selectors here beside the Maps boards' so the one Frost dress — the Loom's raised pill, its glass chip once
   lifted, the pending dash — reaches them; the page went to the Loom on 29 Sep 2026 but these, not being its board, kept the
   old sunken pill with the LED. A panel pill wears the Fabric Master's own hue (management-table.php: fabric → orange), a
   well's pills that well's Production Type, read from the well's own `--filter-lane-colour`; a flight carries both
   (`data-mapper-flight`, PILL_LANE_PROPERTIES). */
body.threads-koel [data-production-type-mapper] { --frost-maps-lane: var(--frost-hue-orange); }
body.threads-koel [data-mapper-assign] [data-mapper-well] { --frost-maps-lane: var(--filter-lane-colour); }
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) :is(.filter-well, .filter-lane, .filter-pill) {
  --frost-maps-soft: color-mix(in srgb, var(--frost-maps-lane) var(--frost-hue-soft), transparent);
}

/* --- the board ------------------------------------------------------------------ */
body.threads-koel :is(.cut-maps, .cut-wizard) .filter-board {
  border-color: transparent;
  background: none;
  box-shadow: none;
}
body.threads-koel :is(.cut-maps, .cut-wizard) .filter-lane { border-bottom-color: var(--stark-key-low); }
body.threads-koel :is(.cut-maps, .cut-wizard) .filter-lane--chosen { border-top-color: var(--stark-key-low); }

/* --- a well --------------------------------------------------------------------- */
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) :is(.filter-well__track, .filter-lane__track) {
  border-radius: var(--stark-radius);
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
}
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) :is(.filter-well__track, .filter-lane__track).is-over,
body.threads-koel :is(.cut-maps, [data-mapper-assign]) .filter-well.is-drop-target .filter-well__track {
  box-shadow: var(--frost-press-body), var(--stark-focus-ring);
}
body.threads-koel .cut-wizard .cut-wizard__well.is-drop-target .filter-well__track {
  box-shadow: var(--frost-press-body), inset 0 0 0 2px var(--frost-maps-lane);
}

/* --- a legend ------------------------------------------------------------------- */
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) :is(.filter-well__legend, .filter-lane__legend) {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: none;
  box-shadow: none;
  color: var(--stark-legend);
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
}
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) :is(.filter-well__legend, .filter-lane__legend):is(:hover, :focus-visible),
body.threads-koel .cut-wizard .cut-wizard__well.is-drop-target .filter-well__legend {
  border-color: transparent;
  background: var(--frost-pane-third);
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) :is(.filter-well__legend, .filter-lane__legend):active { background: var(--frost-pane-press); box-shadow: var(--frost-glass-settled); }
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) :is(.filter-well__legend, .filter-lane__legend):focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) :is(.filter-well__legend, .filter-lane__legend):disabled { color: var(--stark-stone); background: none; }
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) :is(.filter-well__swatch, .filter-lane__swatch) {
  border-radius: 2px;
  background: var(--frost-maps-lane);
}
body.threads-koel :is(.cut-maps, .cut-wizard) .filter-lane--chosen .filter-lane__swatch { background: var(--stark-stone); }

/* --- a pill --------------------------------------------------------------------- */
body.threads-koel .filter-pill--flight[data-mapper-flight],
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: linear-gradient(145deg, var(--stark-card-high), var(--stark-card-low));
  box-shadow: var(--frost-nub-lip), var(--frost-nub-drop);
  color: var(--stark-ink);
}
body.threads-koel .filter-pill--flight[data-mapper-flight]::before,
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill::before {
  border-radius: 1px;
  background: var(--frost-maps-lane);
  box-shadow: none;
}
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill:hover {
  background: linear-gradient(var(--frost-pane-third), var(--frost-pane-third)), linear-gradient(145deg, var(--stark-card-high), var(--stark-card-low));
  box-shadow: var(--frost-nub-lip), var(--frost-nub-drop);
  color: var(--stark-ink);
}
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 2px; }
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill__count { background: none; color: var(--stark-stone); }
body.threads-koel .filter-pill--flight[data-mapper-flight].is-on,
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill.is-on,
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill.is-on:hover {
  border-color: transparent;
  background: var(--frost-glass-sheen), linear-gradient(var(--frost-maps-soft), var(--frost-maps-soft)), color-mix(in srgb, var(--frost-glass-fill) 55%, transparent);
  box-shadow: var(--frost-glass-shadow);
  color: var(--stark-ink);
}
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill.is-on .filter-pill__count { background: none; color: var(--stark-muted); }
body.threads-koel .filter-pill--flight.filter-pill--pending[data-mapper-flight],
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill--pending { border-color: var(--frost-maps-lane); }
body.threads-koel .filter-pill--flight[data-mapper-flight].is-picked,
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill.is-picked,
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill.is-on.is-picked {
  border-color: transparent;
  background: var(--frost-pane-whole);
  box-shadow: var(--frost-glass-shadow), var(--stark-focus-ring);
  color: var(--stark-accent);
}
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill.is-kin,
body.threads-koel :is(.cut-maps, .cut-wizard, [data-production-type-mapper], [data-mapper-assign]) .filter-pill.is-on.is-kin { box-shadow: var(--frost-nub-lip), var(--frost-nub-drop), inset 0 0 0 1px var(--frost-maps-lane); }

/* --- the scope line, the status, the tray ---------------------------------------- */
body.threads-koel .cut-maps .filter-scope input:not([type="hidden"]) {
  padding-inline: 0;
  border-color: transparent;
  border-bottom-color: var(--frost-field-line);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--stark-ink);
}
body.threads-koel .cut-maps .filter-scope input:not([type="hidden"]):hover { border-bottom-color: var(--frost-field-line-lit); }
body.threads-koel .cut-maps .filter-scope input:not([type="hidden"]):is(:focus, :focus-visible) {
  outline: none;
  border-color: transparent;
  border-bottom-color: var(--stark-accent);
  box-shadow: 0 1px 0 var(--stark-accent);
}
body.threads-koel .cut-maps .filter-scope input::placeholder { color: var(--stark-stone); }
body.threads-koel .cut-maps .filter-scope__status { color: var(--stark-muted); }
body.threads-koel :is(.cut-maps__tray, .cut-wizard__group-add) {
  border-color: transparent;
  border-radius: var(--stark-radius);
  background: var(--stark-well);
  box-shadow: var(--frost-press-well);
}
body.threads-koel :is(.cut-maps__pending, .cut-wizard__help, .cut-wizard__type) { color: var(--stark-muted); }
body.threads-koel .cut-maps__pending strong { color: var(--stark-ink); }


/* ============================================ 32. THE DISPATCH NOTES CARDS
   Left by change-over batch B ("the cards keep their look") for this stage:
   Shirts and Jeans › Dispatch Notes, and the Open notes card on both
   Dispatch by Item reports — one include, one stylesheet, every family that
   has notes. No kit counterpart (spec §0 inventory: "note cards … no
   counterpart yet"), so each part takes the Frost word for what it is:
     a note card    Stark's paper, a card on the card: its two ends, its
                    edge, the card's lip and a key's small drop
     its head       the paper under a hairline; the name in the ink, its
                    combination muted
     the All card   it leads the grid and applies to everything below: its
                    head is the whole pane of glass and its name the accent
                    (Koel's accent wash was a fill, rule 11)
     a line         paper; under the pointer a third of the pane (was an
                    accent wash); hairlines between
     closed lines   history under the live ones: a pressed well, their
                    words muted
     the drag       the line under a carried note answers with the thin
                    accent ring (production's fade on the carried one kept)
   Colour, fill, border colour, shadow and corner only; the packer's
   positions, the cards' arrival and every line's leave and flight are
   shirt-dispatch-notes.js's and application.css's. The keys on a card and
   a line are §23's. */
body.threads-koel .dispatch-note-card {
  border-color: var(--stark-card-edge);
  border-radius: var(--stark-radius);
  background: linear-gradient(145deg, var(--stark-card-high), var(--stark-card-low));
  box-shadow: var(--frost-card-lip-shadow), var(--frost-nub-drop);
}
body.threads-koel .dispatch-note-card__heading {
  border-bottom-color: var(--stark-key-low);
  background: none;
}
body.threads-koel .dispatch-note-card__heading strong { color: var(--stark-ink); }
body.threads-koel .dispatch-note-card__heading span { color: var(--stark-muted); }
body.threads-koel .dispatch-note-card--all { border-color: var(--stark-card-edge); }
body.threads-koel .dispatch-note-card--all .dispatch-note-card__heading {
  background: var(--frost-pane-whole);
  box-shadow: var(--frost-glass-settled);
}
body.threads-koel .dispatch-note-card--all .dispatch-note-card__heading strong { color: var(--stark-accent); }
body.threads-koel .dispatch-note-line { border-bottom-color: var(--stark-key-low); }
body.threads-koel .dispatch-note-line:hover { background: var(--frost-pane-third); }
body.threads-koel .dispatch-note-line__shop,
body.threads-koel .dispatch-note-line__text { color: var(--stark-ink); }
body.threads-koel :is(.dispatch-note-line__date, .dispatch-note-line__detail) { color: var(--stark-muted); }
body.threads-koel .dispatch-note-lines--closed {
  border-top-color: var(--stark-key-low);
  background: var(--stark-well);
  box-shadow: var(--frost-press-shallow);
}
body.threads-koel .dispatch-note-line--closed :is(.dispatch-note-line__shop, .dispatch-note-line__text) { color: var(--stark-muted); }
body.threads-koel .dispatch-note-line__closed { color: var(--stark-legend); }
body.threads-koel .dispatch-note-line__grip { color: var(--stark-muted); }
body.threads-koel .dispatch-note-line__grip:is(:hover, [aria-pressed="true"]) { color: var(--stark-ink); }
body.threads-koel .dispatch-note-line__grip:focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }
body.threads-koel .dispatch-note-line.is-drag-over { box-shadow: inset 0 0 0 1px var(--stark-accent); }
body.threads-koel :is(.dispatch-note-card__empty, .dispatch-notes-empty) { color: var(--stark-muted); }
body.threads-koel .dispatch-notes-group__heading { color: var(--stark-legend); }


/* ====================================== 33. THE PAGE KEYS (every page, every family)
   Stage 7 (29 Sep 2026). Stage 5 moved every key a dialog holds onto the
   ladder (§25); the keys that stand on the page itself still wore Koel's
   keycap — the card head's "+ Add Territory" and Arrange order, a report's
   Clear and View Report, the PPC and permission panels' Save, Reset, Grant
   all and Revoke all, the Dispatch Notes head, the Size Mappings and
   Production Type panels, Preferences and Change password. Written once on
   the house key, `.button` (docs/ui-catalogue.md, "Buttons"), so it reaches
   every family at once. Copied from §25, which is the kit's frost.css §4:
     rest      the key lies flush — no fill, no border, no drop — an
               uppercase word in the round-ended capsule (Frost rule 2)
     hover     a third of the glass pane in `::before`
     press     two thirds, settled 1px, the drop gone
     focus     a 1px accent ring round the key, never a glow (Frost rule 7)
     inks      Stark's: a secondary in the muted brightening to the ink, a
               primary in the ink turning the accent, the danger its own word
   ONE DIFFERENCE FROM §25, and why. The word keeps the page's own size
   (Koel's 13px, not the dialog's 15): these keys stand in card heads and
   beside fields, and the Loom's Reset
   and Apply and the masthead's Log out, their neighbours, are already that
   size. Heights and paddings stay the page's too, so a card head measures
   as before but for the capitals.
   NOT HERE, each already Frost's own: the row keys (§23, not `.button`),
   every dialog's keys (§25, which outranks this), the sign-in key (§12),
   Log out (§14), the Loom's keys (threads-frost-pages.css), and the ⌘K
   bar's two keys (§14 keeps that dialog). The Balance by Shop rail's tab
   stays Koel's: it is the rail's handle, fixed to the window edge and
   turned on its side by a transform (F16, no kit counterpart), and a key
   that lies flush would leave nothing on the edge to find. It is left out
   by its `data-balance-rail-tab` hook, not its class, so the coverage
   suite does not read the rail family (F16) as dressed.
   Colour, fill, border colour, shadow, corner, weight, tracking and case
   only; `position: relative` gives the pane its box, as §25's does, on
   keys no controller places. `:where()` keeps the exclusions weightless,
   so every context rule that outranks Koel still outranks this. */
body.threads-koel .button:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab])) {
  position: relative;
  isolation: isolate;
  border-color: transparent;
  border-radius: var(--frost-key-r);
  background: none;
  box-shadow: none;
  text-shadow: none;
  color: var(--stark-muted);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  /* One line, as §25's keys (its review: capitals wrapped at 375). */
  white-space: nowrap;
}
@media (max-width: 600px) {
  body.threads-koel .button:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab])) { letter-spacing: .02em; padding-inline: 10px; }
}
body.threads-koel .button:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab]))::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--frost-glass-sheen), var(--frost-glass-fill);
  box-shadow: var(--frost-glass-shadow);
  opacity: 0;
  transform: scale(.94);
  pointer-events: none;
  transition:
    opacity var(--stark-t-settle) var(--stark-ease),
    transform var(--stark-t-settle) var(--stark-ease),
    box-shadow var(--stark-t-quick) var(--stark-ease);
}
body.threads-koel .button--primary:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab])) { color: var(--stark-ink); }
body.threads-koel .button--danger:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab])) { color: var(--stark-danger); }
/* Koel's and production's hover and focus fills sit on `:hover`, so the
   ladder states it on `:hover` too, to stand over them. */
body.threads-koel .button:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab])):is(:hover, :focus-visible, :active) {
  border-color: transparent;
  background: none;
  box-shadow: none;
}
body.threads-koel .button:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab], :disabled, [aria-disabled="true"])):is(:hover, :focus-visible) { color: var(--stark-ink); }
body.threads-koel .button--primary:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab], :disabled, [aria-disabled="true"])):is(:hover, :focus-visible) { color: var(--stark-accent); }
body.threads-koel .button--danger:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab], :disabled, [aria-disabled="true"])):is(:hover, :focus-visible) { color: var(--stark-danger); }
body.threads-koel .button:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab], :disabled, [aria-disabled="true"])):is(:hover, :focus-visible)::before { opacity: var(--frost-glass-hover); transform: none; }
body.threads-koel .button:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab], :disabled, [aria-disabled="true"])):active::before {
  opacity: var(--frost-glass-press);
  transform: translateY(var(--frost-press-drop));
  box-shadow: var(--frost-glass-settled);
  transition-duration: var(--stark-t-tap);
}
body.threads-koel .button:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab])):focus-visible { outline: 1px solid var(--stark-accent); outline-offset: 0; }
body.threads-koel .button--danger:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab])):focus-visible { outline-color: var(--stark-danger); }
/* Unavailable: the stone word and no pane, even under the pointer (Stark §7). */
body.threads-koel .button:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab])):is(:disabled, [aria-disabled="true"]) { color: var(--stark-stone); }

@media (prefers-reduced-motion: reduce) {
  body.threads-koel .button:where(:not(.user-dialog--command-bar .button, .login-button, .navigation-logout, .loom-separate-page .frost-fb-key, .loom-separate-page .filter-scope__action, [data-balance-rail-tab]))::before { transition-duration: .01ms; }
}

/* The page keys' chords (MPF, 30 September 2026): every Add key carries
   "⌥ A" and Arrange order "⌥ O", drawn by koel.js drawPageKeyCaps() — the
   same two caps as the Loom's Show Loom "⌥ 1" (threads-frost-pages.css,
   Stark §5), copied value for value so the three read as one key look. The
   pit is defined here as well as on the Frost pages' root because these keys
   stand on every page. The word keeps its line; the caps sit after it and
   take no extra height. Hidden on a phone and
   under a coarse pointer, as the Loom's are: a chord is a keyboard's. */
:root { --frost-keycap-pit: inset 0 1px 3px #000c; }
:root[data-frost-mode="light"] { --frost-keycap-pit: inset 0 1px 2px color-mix(in srgb, var(--frost-ink) 28%, transparent); }
body.threads-koel :is(.management-add-user-button, .management-heading-actions > [data-threads-dialog-open^="arrange-"]) > .stark-keycaps {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: 6px;
  /* 21px caps in a 7px-padded key made it 37px, a pixel over its 36px
     floor; the caps give the pixel back so the card head keeps its height. */
  margin-block: -1px;
}
body.threads-koel :is(.management-add-user-button, .management-heading-actions > [data-threads-dialog-open^="arrange-"]) .stark-keycap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 21px;
  height: 21px;
  padding: 0 5px;
  border-radius: var(--stark-radius);
  background: var(--stark-deep);
  box-shadow: var(--frost-keycap-pit), var(--frost-cut-lip);
  color: var(--stark-stone);
  font: 500 var(--stark-text-micro)/1 inherit;
  font-variant-numeric: tabular-nums;
  letter-spacing: normal;
  text-transform: none;
}
body.threads-koel :is(.management-add-user-button, .management-heading-actions > [data-threads-dialog-open^="arrange-"]):is(:hover, :focus-visible) .stark-keycap { color: var(--stark-legend); box-shadow: var(--frost-keycap-pit), inset 0 -1px 0 var(--stark-line-lit); }
@media (max-width: 480px), (pointer: coarse) {
  body.threads-koel :is(.management-add-user-button, .management-heading-actions > [data-threads-dialog-open^="arrange-"]) > .stark-keycaps { display: none; }
}


/* ============================================ 34. THE LONE PAGES (stage 7)
   The sign-in card (§6–§13) was dressed ahead of the stages; what it left
   is here.
     the error pages   403 and 500 wear the sign-in card and open its
                       header with a `management-eyebrow` that §8 left in
                       Koel's colours; it becomes Stark's eyebrow (stark.css
                       `.eyebrow`: the micro size, 600, .18em, capitals, the
                       legend ink), its 8px gap kept. Their Return home is
                       §12's key drawn on a link, so the link's underline
                       goes: a key is a word in a capsule, never underlined.
     Change password   the same `login-card` inside the signed-in shell
                       (`.password-page`), which §6 does not reach (it is
                       scoped to `body.auth-page`). It takes §6's card, the
                       eyebrow above, §8's heading and sub-line, and §10's
                       fields — Stark's line under the control, the accent
                       and one pixel under it on focus; production's accent
                       halo on the focused field goes (Frost rule 7). Its
                       Save key is a page key (§33).
   Preferences (MPF's 28 Sep redesign, §17) needs nothing here. Colour, fill,
   border, shadow, corner and type only; the card's width and the form's
   grid are the page's. */
body.auth-page.threads-koel .login-heading .management-eyebrow,
body.threads-koel .password-page .eyebrow {
  color: var(--stark-legend);
  font-size: var(--stark-text-micro);
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
}

body.auth-page.threads-koel a.login-button { text-decoration: none; }

body.threads-koel .password-page .login-card {
  padding: 30px 34px;
  border: 1px solid var(--stark-card-edge);
  border-radius: var(--stark-radius);
  background: linear-gradient(145deg, var(--stark-card-high), var(--stark-card-low));
  box-shadow: var(--frost-card-shadow);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  color: var(--stark-ink);
}
body.threads-koel .password-page .login-card h1 {
  font-size: var(--stark-text-h1);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -.4px;
  color: var(--stark-ink);
}
body.threads-koel .password-page .intro__copy {
  font-size: var(--stark-text-sub);
  color: var(--stark-muted);
}
body.threads-koel .password-page .field__label {
  font-size: var(--stark-text-sub);
  font-weight: 400;
  color: var(--stark-muted);
}
body.threads-koel .password-page .field__control {
  --stark-line: var(--frost-field-line);
  --stark-line-lit: var(--frost-field-line-lit);
  padding-inline: 0;
  border: 0;
  border-bottom: 1px solid var(--stark-line);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--stark-ink);
  font-size: var(--stark-text-control);
  transition: border-color var(--stark-t-move) var(--stark-ease), box-shadow var(--stark-t-move) var(--stark-ease);
}
body.threads-koel .password-page .field__control:hover { border-bottom-color: var(--stark-line-lit); }
body.threads-koel .password-page .field__control:is(:focus, :focus-visible) {
  outline: none;
  border-bottom-color: var(--stark-accent);
  background: transparent;
  box-shadow: 0 1px 0 var(--stark-accent);
}
@media (max-width: 480px) {
  body.threads-koel .password-page .login-card { padding: 22px 18px 20px; }
  body.threads-koel .password-page .login-card h1 { font-size: 24px; }
}
@media (prefers-reduced-motion: reduce) {
  body.threads-koel .password-page .field__control { transition: none; }
}

/* ======================================== 35. THE 375 PASS (stage 8, page by page)
   Each fix below was found at 375 on the page it names, fixed, and re-checked
   there (rule 80). Colour, border, box and type only, except where a note
   says why a box's display is touched.

   The totals row on a phone table (found on Trousers › Fabrics, then its
   second shape on Trousers › Cards, 29 Sep 2026). Production
   (`threads-production-ui.css`, "Small-screen table disclosure") takes the
   totals row out of table layout as a flex line and drops its `:empty` cells.
   Two things have since broken that: Koel brought the row selector back on
   phones, and a flex row becomes ONE anonymous cell, which sits in the first
   column — the 44px selection column; and the label-only cells ("No Status
   total", a `visually-hidden` span) are not `:empty`, so they stayed in the
   line as bordered slivers. On Trousers › Fabrics the selection column grew
   to 231px and the table scrolled 99px sideways inside its card; on Shirt
   Requirements it grew to 97px and gave most of the table's own 19px scroll;
   on Trousers › Cards (a `colspan` row) to 94px.
   So on a phone the label-only cells go from every totals row, and a totals
   row with one figure (the working pages' Total and Grand total) stays a
   table row: its label and figure stand as blocks in one anonymous cell,
   right-aligned and stacked. Where the phone columns are stamped
   (`threads-production-mobile-table.js` marks `data-mobile-secondary`; a row
   whose cell count differs from the head's, like a `colspan` row, is not),
   the leading cells that stand in visible columns stay cells — all but the
   last of them, whose column the total takes — so the band runs the row's
   width and the total sits under the naming column. Every block follows the
   kept cells, so no column is ever split or added. A row of several figures
   (the Balance and Consolidated reports) keeps production's one line, where
   the figures read in order. The row is not a box a controller moves (the
   table controller only fills its figures and sets `hidden` on it). A group subtotal wears the
   same class but is the group-by animation's band (rule 78): every rule here
   leaves `.user-table-subtotal-row` exactly as production draws it. */
@media (max-width: 760px) {
  body.threads-koel .user-table-total-row:not(.user-table-subtotal-row, [hidden], :has(> [data-production-table-total] ~ [data-production-table-total])) { display: table-row; }
  /* The controller hides the row (`hidden`) when no record shows; production's
     flex line overrode that and drew an empty band under an empty table
     (Shirting Stock). A display here must not do the same. */
  body.threads-koel .user-table-total-row:not(.user-table-subtotal-row)[hidden] { display: none; }
  body.threads-koel .user-table-total-row:not(.user-table-subtotal-row, :has(> [data-production-table-total] ~ [data-production-table-total])) > :is(th, td):not(:empty) {
    display: block;
    text-align: end;
  }
  /* after the blocks, which it ties with: a label-only cell is not :empty */
  body.threads-koel .user-table-total-row:not(.user-table-subtotal-row) > td:not([data-production-table-total]):has(> .visually-hidden:only-child) { display: none; }
  body.threads-koel .user-table-total-row:not(.user-table-subtotal-row, :has(> [data-production-table-total] ~ [data-production-table-total])):has(> [data-mobile-secondary]) > :is(th, td):not([data-mobile-secondary], [data-mobile-secondary] ~ *):has(+ :is(th, td):not([data-mobile-secondary])) {
    display: table-cell;
    text-align: revert;
  }
  body.threads-koel .user-table-total-row:not(.user-table-subtotal-row, :has(> [data-production-table-total] ~ [data-production-table-total])) > th { border-bottom: 0; }
  body.threads-koel .user-table-total-row:not(.user-table-subtotal-row, :has(> [data-production-table-total] ~ [data-production-table-total])) > th ~ td { border-top: 0; }
}

/* The Maps tray's keys (found on Suiting › Maps, 29 Sep 2026). The Custom
   board's tray carries three keys — Undo changes, Reset to default, Save —
   and §33's capitals and tracking made them 393px on one unwrapping line in
   a 355px tray, so the page itself scrolled 43px sideways. The keys wrap
   instead, right-aligned; each key still keeps its word on one line. */
@media (max-width: 760px) {
  body.threads-koel .cut-maps__buttons {
    flex-wrap: wrap;
    justify-content: flex-end;
  }
}


/* ============================================== 36. THE PRICE PILL (Jodi) */
/* MPF, 1 October 2026: "please style the prices as pills", "Single pill
   please" — one pill per price ("180. MOK", "180" or "MOK"), matte and fully
   round as he approved in design-source/mockups/jodi-price-history-mockup.html
   ("perfect"). docs/jodi-price-list-views-spec.md §2.

   ONE COLOUR PER NUMBER (MPF, 4 October 2026: "a new colour for every number
   and each number gets the same colour"; the eleven code-hashed tones
   retired). PriceCode::colour() on the server gives each price a hue — the
   last two digits × the golden angle, so 185, 186, 187 land far apart — and
   a family, the hundreds (cycling every 400). The pill carries both as
   `data-price-hue` / `data-price-family`; this section only paints them: the
   fill is OKLCH, its lightness and chroma the family's tokens below, its hue
   the server's number. A code-only pill wears its number's colour too (his
   popup: "Coloured like the number"). No attr() (typed attr() draws nothing
   in Safari) and no inline style (the house CSP), so the hue reaches the
   fill through the hundred mapping rules further down — one per hue the
   formula can give.

   THE FOUR FAMILIES — his words: "100s a bit deeper, 200s mid, 300s a touch
   lighter … all readable with white text". Each lightness/chroma pair stays
   inside sRGB for nearly every hue (the drift where it clips is under 9°),
   and the lightest family still holds a white figure at 5:1 or better, so
   one set serves dark and daylight alike — the fills are opaque. */
:root {
  --price-family-0-l: 0.43; --price-family-0-c: 0.10;   /* 0–99, 400s … · 7.4:1 worst */
  --price-family-1-l: 0.40; --price-family-1-c: 0.09;   /* 100s, deeper · 8.5:1 worst */
  --price-family-2-l: 0.46; --price-family-2-c: 0.10;   /* 200s, mid · 6.5:1 worst */
  --price-family-3-l: 0.52; --price-family-3-c: 0.11;   /* 300s, a touch lighter · 5.0:1 worst */
  --price-ink: #fff;                                      /* the figure, white on every family */
  /* THE QUIET PILL's three: its rim (the hue at a mid lightness), its wash
     (a fifth of the fill) and its figure, which sits on the page through the
     wash — light in the dark, deep in daylight. */
  --price-quiet-rim-l: 0.66;
  --price-quiet-wash: 22%;
  --price-quiet-ink-l: 0.95; --price-quiet-ink-c: 0.03;
  /* Depth, not shine (MPF: "a bit more depth and shadow"): a soft neutral
     lift beneath the capsule, never the accent, no inner bottom shade. */
  --price-pill-lift: 0 1px 1px rgb(0 0 0 / 50%), 0 3px 5px -1px rgb(0 0 0 / 45%);
}
:root[data-frost-mode="light"] {
  --price-quiet-rim-l: 0.58;
  --price-quiet-ink-l: 0.34; --price-quiet-ink-c: 0.08;
  --price-pill-lift: 0 1px 1px color-mix(in srgb, var(--frost-ink) 20%, transparent), 0 3px 5px -1px color-mix(in srgb, var(--frost-ink) 14%, transparent);
}
/* A pill names its family; the family names its lightness and chroma. */
[data-price-family="0"] { --price-l: var(--price-family-0-l); --price-c: var(--price-family-0-c); }
[data-price-family="1"] { --price-l: var(--price-family-1-l); --price-c: var(--price-family-1-c); }
[data-price-family="2"] { --price-l: var(--price-family-2-l); --price-c: var(--price-family-2-c); }
[data-price-family="3"] { --price-l: var(--price-family-3-l); --price-c: var(--price-family-3-c); }
/* The hundred hues PriceCode::colour() can give, as it writes them (the
   golden-angle steps of 0–99, to the thousandth). Generated, never edited by
   hand: a hue's text here must match the payload's byte for byte. */
[data-price-hue="0"] { --price-hue: 0; } [data-price-hue="137.508"] { --price-hue: 137.508; } [data-price-hue="275.016"] { --price-hue: 275.016; } [data-price-hue="52.524"] { --price-hue: 52.524; }
[data-price-hue="190.032"] { --price-hue: 190.032; } [data-price-hue="327.54"] { --price-hue: 327.54; } [data-price-hue="105.048"] { --price-hue: 105.048; } [data-price-hue="242.556"] { --price-hue: 242.556; }
[data-price-hue="20.064"] { --price-hue: 20.064; } [data-price-hue="157.572"] { --price-hue: 157.572; } [data-price-hue="295.08"] { --price-hue: 295.08; } [data-price-hue="72.588"] { --price-hue: 72.588; }
[data-price-hue="210.096"] { --price-hue: 210.096; } [data-price-hue="347.604"] { --price-hue: 347.604; } [data-price-hue="125.112"] { --price-hue: 125.112; } [data-price-hue="262.62"] { --price-hue: 262.62; }
[data-price-hue="40.128"] { --price-hue: 40.128; } [data-price-hue="177.636"] { --price-hue: 177.636; } [data-price-hue="315.144"] { --price-hue: 315.144; } [data-price-hue="92.652"] { --price-hue: 92.652; }
[data-price-hue="230.16"] { --price-hue: 230.16; } [data-price-hue="7.668"] { --price-hue: 7.668; } [data-price-hue="145.176"] { --price-hue: 145.176; } [data-price-hue="282.684"] { --price-hue: 282.684; }
[data-price-hue="60.192"] { --price-hue: 60.192; } [data-price-hue="197.7"] { --price-hue: 197.7; } [data-price-hue="335.208"] { --price-hue: 335.208; } [data-price-hue="112.716"] { --price-hue: 112.716; }
[data-price-hue="250.224"] { --price-hue: 250.224; } [data-price-hue="27.732"] { --price-hue: 27.732; } [data-price-hue="165.24"] { --price-hue: 165.24; } [data-price-hue="302.748"] { --price-hue: 302.748; }
[data-price-hue="80.256"] { --price-hue: 80.256; } [data-price-hue="217.764"] { --price-hue: 217.764; } [data-price-hue="355.272"] { --price-hue: 355.272; } [data-price-hue="132.78"] { --price-hue: 132.78; }
[data-price-hue="270.288"] { --price-hue: 270.288; } [data-price-hue="47.796"] { --price-hue: 47.796; } [data-price-hue="185.304"] { --price-hue: 185.304; } [data-price-hue="322.812"] { --price-hue: 322.812; }
[data-price-hue="100.32"] { --price-hue: 100.32; } [data-price-hue="237.828"] { --price-hue: 237.828; } [data-price-hue="15.336"] { --price-hue: 15.336; } [data-price-hue="152.844"] { --price-hue: 152.844; }
[data-price-hue="290.352"] { --price-hue: 290.352; } [data-price-hue="67.86"] { --price-hue: 67.86; } [data-price-hue="205.368"] { --price-hue: 205.368; } [data-price-hue="342.876"] { --price-hue: 342.876; }
[data-price-hue="120.384"] { --price-hue: 120.384; } [data-price-hue="257.892"] { --price-hue: 257.892; } [data-price-hue="35.4"] { --price-hue: 35.4; } [data-price-hue="172.908"] { --price-hue: 172.908; }
[data-price-hue="310.416"] { --price-hue: 310.416; } [data-price-hue="87.924"] { --price-hue: 87.924; } [data-price-hue="225.432"] { --price-hue: 225.432; } [data-price-hue="2.94"] { --price-hue: 2.94; }
[data-price-hue="140.448"] { --price-hue: 140.448; } [data-price-hue="277.956"] { --price-hue: 277.956; } [data-price-hue="55.464"] { --price-hue: 55.464; } [data-price-hue="192.972"] { --price-hue: 192.972; }
[data-price-hue="330.48"] { --price-hue: 330.48; } [data-price-hue="107.988"] { --price-hue: 107.988; } [data-price-hue="245.496"] { --price-hue: 245.496; } [data-price-hue="23.004"] { --price-hue: 23.004; }
[data-price-hue="160.512"] { --price-hue: 160.512; } [data-price-hue="298.02"] { --price-hue: 298.02; } [data-price-hue="75.528"] { --price-hue: 75.528; } [data-price-hue="213.036"] { --price-hue: 213.036; }
[data-price-hue="350.544"] { --price-hue: 350.544; } [data-price-hue="128.052"] { --price-hue: 128.052; } [data-price-hue="265.56"] { --price-hue: 265.56; } [data-price-hue="43.068"] { --price-hue: 43.068; }
[data-price-hue="180.576"] { --price-hue: 180.576; } [data-price-hue="318.084"] { --price-hue: 318.084; } [data-price-hue="95.592"] { --price-hue: 95.592; } [data-price-hue="233.1"] { --price-hue: 233.1; }
[data-price-hue="10.608"] { --price-hue: 10.608; } [data-price-hue="148.116"] { --price-hue: 148.116; } [data-price-hue="285.624"] { --price-hue: 285.624; } [data-price-hue="63.132"] { --price-hue: 63.132; }
[data-price-hue="200.64"] { --price-hue: 200.64; } [data-price-hue="338.148"] { --price-hue: 338.148; } [data-price-hue="115.656"] { --price-hue: 115.656; } [data-price-hue="253.164"] { --price-hue: 253.164; }
[data-price-hue="30.672"] { --price-hue: 30.672; } [data-price-hue="168.18"] { --price-hue: 168.18; } [data-price-hue="305.688"] { --price-hue: 305.688; } [data-price-hue="83.196"] { --price-hue: 83.196; }
[data-price-hue="220.704"] { --price-hue: 220.704; } [data-price-hue="358.212"] { --price-hue: 358.212; } [data-price-hue="135.72"] { --price-hue: 135.72; } [data-price-hue="273.228"] { --price-hue: 273.228; }
[data-price-hue="50.736"] { --price-hue: 50.736; } [data-price-hue="188.244"] { --price-hue: 188.244; } [data-price-hue="325.752"] { --price-hue: 325.752; } [data-price-hue="103.26"] { --price-hue: 103.26; }
[data-price-hue="240.768"] { --price-hue: 240.768; } [data-price-hue="18.276"] { --price-hue: 18.276; } [data-price-hue="155.784"] { --price-hue: 155.784; } [data-price-hue="293.292"] { --price-hue: 293.292; }
/* The house count pill with its price modifier (rule 68). NOT scoped to the
   dialog, as the count pill's Frost look is — that one would give a table
   cell the glass fill and edge — and the border goes transparent, so the
   colour alone draws it: matte and fully round as the mockup's rule ~240, no
   sheen, no rim line, no glow, no bottom inner line. The size is the
   mockup's grid pill (~138): the micro text, figures on one width, one line.
   `[data-price-hue]` in the selector (docs/jodi-price-history-view-spec.md
   §2.3): it ties the dialog's own count-pill rule (~4110) and wins by order,
   so a price pill in History draws as a price, not as accent glass. A pill
   with no hue (none is drawn today) falls back to a grey of family 0. */
body.threads-koel .card-batch-count.card-batch-count--price[data-price-hue] {
  padding: 3px 8px;
  border-color: transparent;
  border-radius: 999px;
  background: oklch(var(--price-l, var(--price-family-0-l)) var(--price-c, 0) var(--price-hue, 0));
  box-shadow: var(--price-pill-lift);
  color: var(--price-ink);
  font-size: var(--stark-text-micro);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* THE QUIET PRICE PILL — a rate read FROM DEFAULT, not typed (the Trousers
   Price List, docs/tr-price-list-spec.md §6.4: a Shop line with no rate of
   its own reads the Default line's; a typed number is "own". It once marked
   a by-rule rate too — the rules were withdrawn 3 October 2026, stage 4r).
   The same pill and the same colour, a modifier of `--price` (rule 68): its
   fill thinned to a wash, the rim drawn dashed in the number's hue, no lift,
   the figure in a light (dark) or deep (daylight) shade of the hue — so a
   typed rate stands forward and a worked-out one sits back. Tokens only
   (rule 155), no glow. On screen only: the PDF prints every rate the same
   (Open 7). The selector carries every class the pill rule above does and
   one more, so it wins by weight wherever both apply. */
body.threads-koel .card-batch-count.card-batch-count--price.card-batch-count--price--quiet[data-price-hue] {
  border: 1px dashed oklch(var(--price-quiet-rim-l) var(--price-c, 0) var(--price-hue, 0));
  background: color-mix(in oklab, oklch(var(--price-l, var(--price-family-0-l)) var(--price-c, 0) var(--price-hue, 0)) var(--price-quiet-wash), transparent);
  box-shadow: none;
  color: oklch(var(--price-quiet-ink-l) var(--price-quiet-ink-c) var(--price-hue, 0));
  padding: 2px 7px;
}

/* ======================================= 37. THE PHOTO VIEWER (Jodi Price List) */
/* MPF, 1 October 2026, on Jodi › Price List: a row's photo opens a larger
   picture on hover and the whole PDF on a click. Both are the house's — the
   popover is #table-action-tooltip in its passive mode, the viewer is the
   History dialog's frame (user-dialog--card-dispatches, nine tracks) — so
   this section draws only what they hold: the first page in the popover, the
   pages in the viewer's well, and the slot the Download glyph stands in when
   a PDF has no preview. jodi-price-list.js draws every page with pdf.js at
   the screen's pixel ratio; here they are sized, never scaled up. */

/* The popover's picture: 150px wide, a little room round it (the popover
   body has no padding of its own), the page's shape from the start so the
   surface does not jump when the drawing lands. Until then, the well. */
body.threads-koel .jodi-photo-popover {
  width: 150px;
  aspect-ratio: 3 / 4;
  margin: 8px;
  border-radius: calc(var(--stark-radius) - 2px);
  background: var(--stark-well);
}
body.threads-koel .jodi-photo-popover__page {
  display: block;
  width: 100%;
  height: auto;
  border-radius: inherit;
}
body.threads-koel .jodi-photo-popover__note {
  display: block;
  padding: 10px;
  color: var(--stark-muted);
  font-size: var(--stark-text-micro);
  line-height: 1.4;
}

/* The viewer's well: every page one under the other, scrolling inside the
   dialog, the dialog itself held within the screen. Its height is set, not
   capped: the dialog is the same size from "Opening the PDF…" to the last
   page, so nothing under the pointer moves as the pages land (the close key
   included). A page is white paper on the well, the width of the well, its
   corners just softened. */
body.threads-koel .jodi-photo-viewer-pages {
  /* the one row of the house --rows form (rule 70), the whole ruler wide */
  grid-column: 1 / -1;
  min-width: 0;
  display: grid;
  gap: 12px;
  align-content: start;
  height: min(70vh, 760px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 12px;
  border-radius: var(--stark-radius);
  background: color-mix(in srgb, var(--stark-well) 60%, transparent);
  box-shadow: var(--frost-hair-cut), var(--frost-hair-lip);
  outline: none;
}
body.threads-koel .jodi-photo-viewer-pages:focus-visible { box-shadow: var(--frost-hair-cut), inset 0 0 0 1px var(--stark-accent); }
body.threads-koel .jodi-photo-viewer-page {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 4px;
  box-shadow: var(--price-pill-lift);
}
body.threads-koel .jodi-photo-viewer-status {
  margin: 0;
  padding: 48px 12px;
  color: var(--stark-muted);
  text-align: center;
}
/* A phone: the surface is already a column whose body scrolls (production,
   "held to the screen"); the well takes what the header and the two-line
   footer leave, so only the well scrolls. */
@media (max-width: 760px) {
  body.threads-koel .jodi-photo-viewer-pages { height: calc(100dvh - 300px); }
}

/* The Download glyph's slot, drawn only for a PDF with no preview: it stands
   aside, so the key is a segment of the bar like any other. */
body.threads-koel .jodi-photo-download-slot { display: contents; }
/* On a phone the photo key is a key in the row's `+` panel too (the panel
   keeps a control marked data-mobile-detail-keep). There it stands on a line
   of its own, not in a row the bar must keep the height of: no trim, so the
   key sits wholly inside its line and a tap lands on it. */
body.threads-koel [data-mobile-detail-row] td .user-table-row-actions:has(> [data-mobile-detail-keep]) { --bar-trim: 0px; }

/* ============================ 38. TABLE OPTIONS, RENDITION E5 (stage T1, 8 Oct 2026) */
/* MPF approved rendition E5 of the Table options panel on 8 October 2026
   (design-source/mockups/sort-panel-renditions/versions/v7.html, card E5 —
   the mock-up is the spec; docs/table-options-e5-plan.md stage T1). The kit
   drew it on Stark's pieces (frost.css §43); here it is drawn on the HOUSE
   pieces it was designed on (rule 67): the house dialog, the side-by-side
   panel browser `.ppc-panel-browser` › `.ppc-panel`, and the panel's rows.
   Three MODIFIERS on the browser, never a new component (rule 155):
     --table-options  two columns, the first three of the dialog's tracks wide
                      plus half a gap, so its rows run to the hairline;
     --joined         one darker pressed-in well, one hairline between the
                      columns — a Finder window's column view;
     --fits           no floor: as tall as its work, Stark's one height
                      watcher (`data-stark-eases`) easing the box.
   Every rule here hangs from one of the three, so no other page can move
   (tests/table-v2-isolation-test.php). Tokens only; nothing here transforms,
   filters or frosts anything (a row's dropdown list stands inside the box).
   The place under the key, and the chevron's turn, are threads-table-v2.css's. Under the box's own rules, the kit's §43 rules for
   the work column said again for the house scope: the kit reads a
   `.stark-kit` ABOVE its panel, and here the work column's body IS the kit's
   scope (the house shell around it keeps the house look), so each is the
   kit's own rule on the compound selector, its values unchanged. */

/* THE BOX. */
body.threads-koel .ppc-panel-browser.ppc-panel-browser--table-options {
  grid-template-columns: calc(3 * var(--track) + 2 * var(--track-gap) + var(--track-gap) / 2) minmax(0, 1fr);
  align-items: stretch;
  margin-top: 0;
  overflow: visible;
  --ppc-panel-height: auto;
}
body.threads-koel .ppc-panel-browser.ppc-panel-browser--joined {
  gap: 0;
  border-radius: var(--stark-radius);
  background: var(--stark-group);
  box-shadow: var(--frost-press-well);
}
body.threads-koel .ppc-panel-browser.ppc-panel-browser--joined .ppc-panel,
body.threads-koel .ppc-panel-browser.ppc-panel-browser--joined .ppc-panel + .ppc-panel {
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}
body.threads-koel .ppc-panel-browser.ppc-panel-browser--joined .ppc-panel + .ppc-panel { border-left: 1px solid var(--stark-key-low); }
body.threads-koel .ppc-panel-browser--joined .ppc-panel-header { border-radius: 0; }
/* No floor: each column as tall as its work, nothing clipped inside it. */
body.threads-koel .ppc-panel-browser--fits .ppc-panel { height: auto; min-height: 0; max-height: none; overflow: visible; }
body.threads-koel .ppc-panel-browser--table-options .ppc-panel-list { overflow: visible; }
/* The work column's body is the kit's sort body; the Pieces body's own words and padding stay on the PPC pages. */
body.threads-koel .ppc-panel-browser--table-options .ppc-pieces-body { display: block; padding: 0; font-size: inherit; line-height: inherit; }
/* The work column's head never wraps, so both heads share one height and their hairline runs straight across. */
body.threads-koel .ppc-panel-browser--table-options .ppc-panel-header p { min-height: 1lh; }
/* "What it is set to" under each choice: Custom PPC's note line, on one line, cut with an ellipsis. */
body.threads-koel .ppc-panel-browser--table-options .ppc-panel-option__label { display: grid; gap: 1px; min-width: 0; }
body.threads-koel .ppc-panel-browser--table-options .ppc-panel-option__note { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Finder's › on a choice: the kit's chevron (the dropdown's and the sort
   key's drawing), the accent once chosen. Its quarter turn into the next
   column is threads-table-v2.css's: this sheet turns nothing (rule 155). */
.ppc-panel-browser--table-options .ppc-panel-option__opens { margin-right: 4px; }
.ppc-panel-browser--table-options .ppc-panel-option[aria-selected="true"] .ppc-panel-option__opens { border-color: var(--stark-accent); }

/* The footer's "…" (kit §43 (6)) stands at the left of the house actions, Save at the right. */
.user-dialog:has(.ppc-panel-browser--table-options) .user-dialog-actions > .stark-kit:has(> .frost-sort-more) { width: auto; max-width: none; margin-right: auto; display: inline-flex; }

/* THE WORK COLUMN: the kit's sort body (§35) and §43 (4)'s one grid and one type. */
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel [data-frost-options-pane][hidden] { display: none; }
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel .frost-sort-body { padding: 14px 20px 18px; display: grid; gap: 10px; }
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel .frost-sort-add {
  justify-self: start;
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--stark-text-note);
}
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid :is(.dlg-order, .frost-cols-list) { display: grid; gap: 6px; margin: 0; padding: 0; }
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid .frost-order-locked + .dlg-order { margin-top: -4px; }
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid :is(.dlg-order-row, .frost-cols-row) {
  display: grid;
  grid-template-columns: var(--frost-opt-at) minmax(0, 1fr) auto;
  align-items: center;
  column-gap: var(--frost-opt-gap);
  box-sizing: border-box;
  min-height: var(--frost-opt-row);
  margin: 0;
  padding: 2px var(--frost-opt-pad-r) 2px var(--frost-opt-pad-l);
}
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid .dlg-order-at {
  display: grid;
  place-items: center;
  width: auto;
  min-width: 0;
  margin: 0;
  text-align: center;
}
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid .dlg-order-at .frost-cols-lock { margin: 0; padding: 0; width: auto; height: auto; min-width: 0; min-height: 0; }
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid .dlg-order-row.frost-sort-row {
  grid-template-columns: var(--frost-opt-at) minmax(0, 1fr) auto auto auto;
  gap: 0 var(--frost-opt-gap);
  padding: 2px var(--frost-opt-pad-r) 2px var(--frost-opt-pad-l);
}
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid .frost-cols-row > .stark-toggle {
  grid-column: 2 / -1;
  min-height: 0;
  margin: 0;
  padding: 0 0 0 var(--frost-opt-name-inset);
}
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid [data-frost-options-pane="order"] .dlg-order-row { grid-template-columns: var(--frost-opt-at) minmax(0, 1fr) auto auto; }
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid [data-frost-options-pane="order"] .dlg-order-grip { grid-column: 4; }
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid [data-frost-options-pane="order"] .frost-order-hidden-word { grid-column: 3; }
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid [data-frost-options-pane="order"] :is(.dlg-order-name, .frost-order-name) { padding-left: var(--frost-opt-name-inset); min-width: 0; }
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-type :is(.stark-select-button, .stark-select-value, .frost-cols-row > .stark-toggle, .frost-cols-name, .dlg-order-name, .frost-order-name, .dlg-order-at) {
  font-size: var(--frost-opt-type);
  font-weight: 400;
  line-height: normal;
}
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-type :is(.frost-cols-name, .dlg-order-name, .frost-order-name) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-type .frost-cols-row > .stark-toggle { gap: var(--frost-opt-gap); }
@media (max-width: 560px), (pointer: coarse) {
  .ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid .frost-cols-row > .stark-toggle { align-self: stretch; }
}
/* Order's handle at Sort's small size with a mouse, the kit's 44 for a finger (§43 (5)). */
@media (min-width: 561px) and (pointer: fine) {
  .ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid [data-frost-options-pane="order"] .dlg-order-grip { width: 22px; min-height: 26px; height: 26px; font-size: 13px; }
}

/* THE PHONE (kit §43 (7)). The two columns stack in the one box, the hairline
   running across, the › pointing down into the column below; a sort row
   takes two lines — the column and its arrow, then ✕ and the handle at the
   end; the footer's keys close up so "…" and Save fit at 375. */
@media (max-width: 700px) {
  body.threads-koel .ppc-panel-browser.ppc-panel-browser--table-options { display: grid; grid-template-columns: minmax(0, 1fr); grid-auto-flow: row; }
  body.threads-koel .ppc-panel-browser.ppc-panel-browser--joined .ppc-panel + .ppc-panel { border-left: 0; border-top: 1px solid var(--stark-key-low); }
}
@media (max-width: 560px) {
  body.threads-koel .user-dialog:has(.ppc-panel-browser--table-options) .user-dialog-actions { gap: 4px; }
  .ppc-panel-browser--table-options .stark-kit.frost-sort-panel .frost-sort-body { padding: 12px 14px 14px; }
  .ppc-panel-browser--table-options .stark-kit.frost-sort-panel--one-grid .dlg-order-row.frost-sort-row:has(.frost-sort-dir--arrow) {
    grid-template-columns: var(--frost-opt-at) minmax(0, 1fr) auto auto;
    grid-template-areas: "at col col dir" "at . rm grip";
  }
}

/* ONE SECTION-TITLE SIZE (design review, 17 Oct 2026). Every section title on a
   page — a card's own h2 beside its keys, the Saved Rules and Saved Mappings
   heads, the Preferences cards, Card Ageing's spine — is the kit's card title,
   22px (Stark's h2), the size the Loom's and the Filter's titles already are.
   Dialogs keep their own headings. */
body.threads-koel main.application-main h2:not(dialog *) { font-size: 22px; }

/* A KEY UNDER A THUMB (design review, 17 Oct 2026). On a phone every key on the
   page and on a dialog's foot is at least 44px tall — Stark's 44, the floor the
   Loom's pills, the switches and the phone rows already keep. Koel's 36px stays
   on a computer. */
@media (max-width: 760px) {
  body.threads-koel main.application-main .button,
  body.threads-koel .user-dialog .user-dialog-actions .button { min-height: 44px; }
}

/* NO KEY LEAVES ITS DIALOG (design review, 17 Oct 2026). A foot whose keys are
   wider than a narrow dialog — Shirt Production Types' Add, at its 380px:
   CANCEL and CREATE PRODUCTION TYPE — wraps onto a second line, still against
   the right edge, rather than pushing Cancel out past the dialog's left edge. */
body.threads-koel .user-dialog:not(.user-dialog--command-bar) .user-dialog-surface > .user-dialog-actions {
  flex-wrap: wrap;
  row-gap: 8px;
}

/* ONE TITLE-BLOCK HEIGHT PER KIND (design review, 17 Oct 2026). From the gold
   eyebrow to the foot of the heading row every list page measured the same,
   and every report page — except where the line under the title ran to a
   second line (it then stood 21px taller) or a report card's own grid gap
   stood between the eyebrow and the title (20px more). So the line under the
   page's title keeps room for two lines on every page, and a report card's
   eyebrow sits as close to its title as every other card's. */
body.threads-koel main.application-main .management-eyebrow + .management-heading-row .management-heading-copy > .management-description { min-height: 2lh; }
body.threads-koel .dispatch-report-card > .management-eyebrow:has(+ .management-heading-row) { margin-bottom: -12px; }
