/* Stem wears the box's Ink & Seal tokens, copied verbatim from
   ../box/console/src/ds/tokens.css so the plane looks like family. The brand
   overlay section is left out on purpose: Stem is never white-labelled
   (CHARTER rule 7), so there is nothing for an overlay to do. Fonts fall
   back to the system stacks the tokens already name; Stem self-hosts none. */

/* ---------------------------------------------------------------------------
   THE FACES, SHIPPED RATHER THAN NAMED.
   Until 10 September 2026 this file named Sora, Figtree and IBM Plex Mono in
   its tokens and served none of them, so every face fell through to
   `system-ui` and Stem read as a different product from the box while
   carrying the same 193 tokens. Measured: zero font files in this repository
   against six in the box's build.
   Latin subsets only, copied from the box's own build so the two planes wear
   the same cut of the same face. SELF-HOSTED, never a font network: a
   `<link>` to Google would tell them which of a customer's people opened the
   plane and when, which is not a thing a vendor's plane should leak.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: "Sora";
  src: url(fonts/sora-latin-variable.woff2) format("woff2-variations");
  font-weight: 100 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Figtree";
  src: url(fonts/figtree-latin-variable.woff2) format("woff2-variations");
  font-weight: 300 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url(fonts/plex-mono-latin-400.woff2) format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url(fonts/plex-mono-latin-500.woff2) format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}

/* ============================================================================
   THE CORTEX DESIGN CONSTITUTION — TOKENS · "Ink & Seal"
   ============================================================================
   Ported verbatim from the previous build, where the owner locked it on
   20 July 2026 ("Lets go B"). Decision record 0035: the design system is
   HARVESTED, not designed — this constitution is carried whole; components
   enter the system only after they have shipped on a real surface and passed
   the surface verification protocol. If it is not on /design-system, it is
   not in the system.

   THE CONTRACT
   - Components consume ONLY semantic tokens. Raw ramps (--washi-*, --ink-*,
     --seal-*, --gold-* ...) are theme-private; touching one is a defect.
   - Brand overlays may override COLOUR semantics only - never type, spacing,
     radius, motion, elevation. If a brand needs a structural override, the
     brand is wrong.
   - Light and dark are both first-class; no stored choice means the
     operating system decides.
   - If a token is not in this file, the answer is "no".

   THE IDENTITY - INK & SEAL (Gugen: "to give form; materialise")
   The Gugen mark is a hanko - a vermillion seal, the instrument of trust.
   The interface is calligraphy - warm sumi ink on washi paper (ink-stone and
   lacquer in dark mode) - and the seal vermillion appears in EXACTLY ONE
   ROLE: the stamp on trust surfaces (the audit chain, route verdicts, the
   what-leaves-the-building ledger). Nothing else on screen ever wears it;
   the one sanctioned decorative use is the octagon seal-dot in the wordmark.
   Danger is a deliberate oxblood so a failure never reads as the stamp; gold
   serves warning; moss means "stayed on the box".

   Faces: Sora (display) · Figtree (body) · IBM Plex Mono (data) -
   self-hosted always; a client's browser never calls a font network.
   ========================================================================= */

/* ------- raw ramps (theme-private — components may not touch) ---------- */
:root {
  --washi-0: #faf7f2;    /* paper */
  --washi-50: #f4efe7;
  --washi-100: #ece5d9;
  --washi-200: #e0d8cb;
  --washi-300: #c4b9a8;
  --washi-cream: #ece6da;

  --ink-300: #a3988a;
  --ink-500: #786d5f;  /* 4.7:1 on washi — contrast-audited */
  --ink-700: #3a2f26;
  --ink-800: #2e241c;
  --ink-850: #241f1c;
  --ink-880: #1b1715;
  --ink-900: #1a1614;
  --ink-950: #131010;
  --ink-sumi: #221a14;

  --seal-400: #e5573f;   /* the mark, lifted for dark grounds */
  --seal-500: #d13e2d;   /* measured from the Gugen hanko */
  --seal-600: #c43a28;

  --gold-300: #e0b45c;
  --gold-600: #a3761c;

  --moss-300: #9cc48f;
  --moss-600: #43773f;
  --oxblood-300: #ef8f86;
  --oxblood-600: #93312c;
  --slate-300: #8fa9d6;
  --slate-600: #46628e;
  --plum-300: #b78aaf;
  --plum-600: #7d5875;
}

/* ------- semantic tokens — LIGHT (washi) ------------------------------- */
:root {
  color-scheme: light;

  /* The ground moved from washi cream to a pale blue-grey on the owner's
     direction (13 August 2026) — the ink, the seal and every accent stay;
     only the paper cooled. */
  --bg: #f2f4f7;
  --bg-sunken: #ebeef3;
  --panel: #fcfdfe;
  --panel-2: #f1f3f7;
  --border: #dfe4eb;
  --border-strong: #c3cbd6;
  --text: var(--ink-sumi);
  /* Darkened from #6e7582 (measured 4.21:1 carrying 11–12px captions) to
     clear small-text contrast — decision 0079. */
  --muted: #5f6774;

  /* the ink — calm, monochrome interaction */
  --primary: var(--ink-800);
  --primary-hover: #17100b;
  --primary-fg: #fcfdfe;
  --primary-tint: #e8ecf2;

  /* the seal — trust surfaces ONLY */
  --trust: var(--seal-600);
  --trust-tint: #f9e5e0;

  --route-local: var(--moss-600);        /* "stayed on the box" */
  --route-local-tint: #e6efe0;
  --route-external: var(--seal-600);     /* "left — audited": stamped */
  --route-external-tint: var(--trust-tint);

  --success: var(--moss-600);
  --success-tint: #e6efe0;
  --warning: var(--gold-600);
  --warning-tint: #f5edd8;
  --danger: var(--oxblood-600);          /* oxblood — never the seal */
  --danger-tint: #f6e2e0;
  --info: var(--slate-600);
  --info-tint: #e6ebf4;

  /* Each accent in two cuts (decision 0079): the plain role paints bars,
     dots and grounds; the -text cut carries WORDS, dark enough for small
     mono type on its tint. Measured before the split: gold on its tint
     3.48:1 at 10px, moss chips at exactly 4.50:1, seal on trust-tint
     4.35:1 — the provenance colours were the least legible text on
     screen, on the product whose argument they carry. */
  --trust-text: #b03222;
  --route-local-text: #3a6836;
  --success-text: #3a6836;
  --warning-text: #7c590f;
  --danger-text: var(--oxblood-600);
  --info-text: #415c86;

  --ring: color-mix(in srgb, var(--ink-700) 45%, transparent);
  --shadow-1: 0 1px 2px rgb(30 36 46 / 0.06);
  --shadow-2: 0 2px 8px rgb(30 36 46 / 0.08), 0 1px 2px rgb(30 36 46 / 0.05);
  --shadow-3: 0 12px 32px rgb(30 36 46 / 0.14), 0 2px 8px rgb(30 36 46 / 0.08);
  --scrim: rgb(20 24 32 / 0.42);

  --chart-1: var(--seal-500);
  --chart-2: #b98a2e;
  --chart-3: #6d7f4b;
  --chart-4: var(--slate-600);
  --chart-5: var(--plum-600);
  --chart-6: #8a8071;

  /* agent identity hues (avatars) — warm family, never the seal; monogram
     always washi-light on these grounds */
  --agent-1: #5c6e48;  --agent-2: #8a6d2f;  --agent-3: #4f6a8f;
  --agent-4: #7d5875;  --agent-5: #9c5c40;  --agent-6: #4f7a6a;
  --agent-7: #6b5d8e;  --agent-8: #756a5c;
  --agent-fg: #faf7f2;
}

/* ------- semantic tokens — DARK (ink-stone & lacquer) ------------------- */
[data-theme="dark"] {
  color-scheme: dark;

  --bg: var(--ink-950);
  --bg-sunken: var(--ink-900);
  /* Lifted (decision 0079): panels measured 1.06:1 against the ground and
     borders 1.33:1 against panels — cards dissolved into one field. The
     ladder now clears 1.15:1 and 1.6:1 — values set by measurement
     against the protocol's own floors, not by eye. */
  --panel: #262019;
  --panel-2: #2e2720;
  --border: #4a4238;
  --border-strong: #5d5347;
  --text: var(--washi-cream);
  --muted: var(--ink-300);

  /* light parchment ink on lacquer */
  --primary: #e6ddcd;
  --primary-hover: #f7f1e4;
  --primary-fg: var(--ink-sumi);
  --primary-tint: rgb(230 221 205 / 0.11);

  --trust: var(--seal-400);
  --trust-tint: rgb(229 87 63 / 0.14);

  --route-local: var(--moss-300);
  --route-local-tint: rgb(156 196 143 / 0.12);
  --route-external: var(--seal-400);
  --route-external-tint: var(--trust-tint);

  --success: var(--moss-300);
  --success-tint: rgb(156 196 143 / 0.12);
  --warning: var(--gold-300);
  --warning-tint: rgb(224 180 92 / 0.13);
  --danger: var(--oxblood-300);
  --danger-tint: rgb(239 143 134 / 0.13);
  --info: var(--slate-300);
  --info-tint: rgb(143 169 214 / 0.13);

  /* In dark the 300-series already clears 7:1 on its tints, so the -text
     cuts simply follow the plain roles (decision 0079). */
  --trust-text: var(--seal-400);
  --route-local-text: var(--moss-300);
  --success-text: var(--moss-300);
  --warning-text: var(--gold-300);
  --danger-text: var(--oxblood-300);
  --info-text: var(--slate-300);

  --ring: color-mix(in srgb, var(--washi-cream) 40%, transparent);
  /* Drop shadows cannot separate lacquer from lacquer; a hairline top
     highlight does (decision 0079). */
  --shadow-1: inset 0 1px 0 rgb(255 250 240 / 0.04), 0 1px 2px rgb(0 0 0 / 0.45);
  --shadow-2: inset 0 1px 0 rgb(255 250 240 / 0.04), 0 2px 10px rgb(0 0 0 / 0.5);
  --shadow-3: 0 16px 40px rgb(0 0 0 / 0.6);
  --scrim: rgb(0 0 0 / 0.42); /* lighter on lacquer: the answer landing behind a fresh ask stayed visible (decision 0079) */

  --chart-1: var(--seal-400);
  --chart-2: var(--gold-300);
  --chart-3: #a9bf7f;
  --chart-4: var(--slate-300);
  --chart-5: var(--plum-300);
  --chart-6: #8d8578;

  --agent-1: #7e9465;  --agent-2: #bd9c50;  --agent-3: #7593bd;
  --agent-4: #a97fa0;  --agent-5: #c07f5e;  --agent-6: #6fa18d;
  --agent-7: #9587bd;  --agent-8: #99897a;
  --agent-fg: #131010;
}

/* No explicit choice stored → the OS preference decides. Mirrors the dark
   block; an explicit [data-theme] on <html> always wins. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: var(--ink-950);
    --bg-sunken: var(--ink-900);
    --panel: #262019;
    --panel-2: #2e2720;
    --border: #4a4238;
    --border-strong: #5d5347;
    --text: var(--washi-cream);
    --muted: var(--ink-300);
    --primary: #e6ddcd;
    --primary-hover: #f7f1e4;
    --primary-fg: var(--ink-sumi);
    --primary-tint: rgb(230 221 205 / 0.11);
    --trust: var(--seal-400);
    --trust-tint: rgb(229 87 63 / 0.14);
    --route-local: var(--moss-300);
    --route-local-tint: rgb(156 196 143 / 0.12);
    --route-external: var(--seal-400);
    --route-external-tint: var(--trust-tint);
    --success: var(--moss-300);
    --success-tint: rgb(156 196 143 / 0.12);
    --warning: var(--gold-300);
    --warning-tint: rgb(224 180 92 / 0.13);
    --danger: var(--oxblood-300);
    --danger-tint: rgb(239 143 134 / 0.13);
    --info: var(--slate-300);
    --info-tint: rgb(143 169 214 / 0.13);
    --trust-text: var(--seal-400);
    --route-local-text: var(--moss-300);
    --success-text: var(--moss-300);
    --warning-text: var(--gold-300);
    --danger-text: var(--oxblood-300);
    --info-text: var(--slate-300);
    --ring: color-mix(in srgb, var(--washi-cream) 40%, transparent);
    --shadow-1: inset 0 1px 0 rgb(255 250 240 / 0.04), 0 1px 2px rgb(0 0 0 / 0.45);
    --shadow-2: inset 0 1px 0 rgb(255 250 240 / 0.04), 0 2px 10px rgb(0 0 0 / 0.5);
    --shadow-3: 0 16px 40px rgb(0 0 0 / 0.6);
    --scrim: rgb(0 0 0 / 0.42); /* lighter on lacquer: the answer landing behind a fresh ask stayed visible (decision 0079) */
    --chart-1: var(--seal-400);
    --chart-2: var(--gold-300);
    --chart-3: #a9bf7f;
    --chart-4: var(--slate-300);
    --chart-5: var(--plum-300);
    --chart-6: #8d8578;
    --agent-1: #7e9465;  --agent-2: #bd9c50;  --agent-3: #7593bd;
    --agent-4: #a97fa0;  --agent-5: #c07f5e;  --agent-6: #6fa18d;
    --agent-7: #9587bd;  --agent-8: #99897a;
    --agent-fg: #131010;
  }
}

/* ------- type · spacing · radius · motion (IMMUTABLE across brands) ---- */
:root {
  --font-display: "Sora Variable", "Sora", system-ui, sans-serif;
  --font-body: "Figtree Variable", "Figtree", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* THE SEVEN ROLES — nothing else exists, and a raw font-size in a
     component file fails the build (decision 0079). The floor is 11px:
     8–10px uppercase tracked text is where "appliance" quietly becomes
     "dashboard". */
  --text-hero: clamp(30px, 4vw, 44px);     /* Sora 600 — the greeting, a masthead */
  --text-title: clamp(21px, 2.2vw, 27px);  /* Sora 600 — page heads, the big numbers */
  --text-heading: 16px;                    /* card and panel titles, input text */
  --text-reading: 16.5px;                  /* long-form prose — briefs, evidence */
  --text-body: 14px;                       /* the default */
  --text-caption: 12.5px;                  /* provenance, metadata, footers */
  --text-micro: 11px;                      /* mono labels — the floor */
}

/* Studio widths read at armslength-plus: the reading roles step up half a
   size together (decision 0079's still-owed list; the relook measured 14px
   body as undersized on a 34-inch monitor while headings hit their clamp).
   1600, NOT 1920 (10 September 2026). Grant approved four breakpoints — 560,
   900, 1280, 1600 — and the console keeps them. This file had exactly one
   width of its own and it was not among them, so the two halves of the same
   product changed shape at different places. `scripts/verify_breakpoints.py`
   now stops a fifth appearing in either half. */
@media (min-width: 1600px) {
  :root {
    --text-heading: 17px;
    --text-reading: 17.5px;
    --text-body: 15px;
    --text-caption: 13.5px;
    --text-micro: 12px;
  }
}

/* ---- THE ROUNDING, THE SEAL AND THE EASING, RE-HOMED 10 September 2026 ----
   Every declaration below sat INSIDE `@media (min-width: 1920px)` (as it then
   was) but OUTSIDE
   the `:root` block within it — a custom property declared straight into a
   media block, which is invalid CSS, so the browser discarded all of them.
   The box had the identical fault in its own tokens file and found it the same
   day; this file was never checked, because Stem had no token gate.
   WHAT IT MEANT ON THE DEPLOYED PLANE: `--radius-ctl`, `--radius-card`,
   `--radius-modal`, `--radius-full`, `--octagon`, `--ease`, `--t-micro` and
   `--t-panel` all resolved to the empty string. EVERY ROUNDED THING IN THE
   PLANE WAS SQUARE, the hanko's octagon never clipped the seal in the header,
   and every transition naming the easing curve was dropped. It reads as a
   deliberate flat style until you measure it — and it was measured only
   because five badge tokens added here today came out 5.4px short of the
   box's, which is the whole argument for measuring the rendered result rather
   than reading the rule. */
:root {
  /* ---- THE BADGE, ONE GEOMETRY — the same values the console declares in
     its own `ds/tokens.css`, because a customer who sees the plane and their
     box should not be able to tell they were built by different hands
     (proposal move 3, and Grant on 10 September: "on all surfaces spend some
     time polishing and getting the look perfect, and consistent"). The
     console's badge row wore five vertical paddings; this file's `.chip` was
     a sixth. One geometry, declared in both. */
  --badge-pad-y: 3px;
  --badge-pad-x: 10px;
  --badge-gap: 7px;
  --badge-weight: 600;
  --badge-line: 1.45;
  --badge-font: var(--font-body); /* a chip is a word about a state, never code (the box's 0154) */

  --radius-ctl: 8px;    /* buttons, inputs, chips */
  --radius-card: 14px;  /* panels, cards */
  --radius-modal: 18px;
  --radius-full: 999px;

  /* the octagon seal (the hanko's silhouette) — clip-path for the brand
     mark and seal-stamped moments; the ONE sanctioned decorative seal use */
  --octagon: polygon(30% 0, 70% 0, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0 70%, 0 30%);

  --ease: cubic-bezier(0.2, 0, 0, 1);
  --t-micro: 120ms;  /* hover, focus, chip */
  --t-panel: 220ms;  /* panel/modal entrance */
}

@media (prefers-reduced-motion: reduce) {
  :root { --t-micro: 0ms; --t-panel: 0ms; }
}

/* ------- Stem's own components, in the seven type roles ------------------ */
* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); color: var(--text); font-family: var(--font-body); font-size: var(--text-body); line-height: 1.5; }
main { max-width: 1100px; margin: 0 auto; padding: 24px 16px 48px; }

/* ---------------------------------------------------------------------------
   THE PAPER (decision 0017, 25 September 2026): the box's shell, worn by the
   plane, so a vendor who moves between a customer's box and the estate is in
   one product. A rail of places from 900 pixels; beneath that a top line and
   tabs along the foot, with what does not fit behind More. The door keeps its
   one-line header (header.top, below); only signed-in pages wear the shell.
   --------------------------------------------------------------------------- */
.st-app { min-height: 100vh; }
.st-rail { display: none; }
.st-main { min-width: 0; }
/* THE ONE GRID (decision 0032, Grant's approved redesign of 3 October 2026): a page's
   content starts a fixed gutter from the rail and never floats to the middle of a wide
   window; one content width; labels in one column. The gutter and the widths are tokens
   below, stepped at the four breakpoints. */
.st-main main {
  max-width: calc(var(--content) + 2 * var(--gutter)); margin: 0;
  padding: 22px var(--gutter) calc(104px + env(safe-area-inset-bottom, 0px));
}
.word { font-family: var(--font-display); font-weight: 600; font-size: var(--text-heading); white-space: nowrap; }
.seal { display: inline-block; width: 10px; height: 10px; background: var(--trust); clip-path: var(--octagon); margin-right: 8px; vertical-align: baseline; }
.who { font-family: var(--font-mono); font-size: var(--text-micro); color: var(--muted); }
.st-ptop {
  position: sticky; top: 0; z-index: 10; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: calc(10px + env(safe-area-inset-top, 0px)) 16px 10px; background: var(--bg); border-bottom: 1px solid var(--border);
}
.st-ptop .trustchip { max-width: 62vw; }
.st-ic { flex: none; }
.st-ri {
  display: flex; align-items: center; gap: 10px; min-height: 36px; padding: 0 10px; border-radius: var(--radius-ctl);
  color: var(--muted); text-decoration: none; font-size: var(--text-body); font-weight: 500;
}
.st-ri:hover { background: var(--panel-2); color: var(--text); }
.st-ri[aria-current="page"] { background: var(--panel); color: var(--text); font-weight: 600; box-shadow: var(--shadow-1); }
.st-ri.sub { min-height: 30px; padding-left: 40px; font-size: var(--text-caption); }
.st-gl { display: block; padding: 10px 10px 4px; font-size: var(--text-caption); font-weight: 600; color: var(--muted); }
.st-rule { height: 1px; background: var(--border); margin: 8px 6px; }
.st-tabs {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  padding: 4px 4px calc(8px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 94%, transparent); backdrop-filter: blur(12px);
}
.st-tab {
  display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 2px; min-height: 52px;
  color: var(--muted); text-decoration: none; font-size: var(--text-micro); font-weight: 500; cursor: pointer; list-style: none;
}
.st-tab::-webkit-details-marker { display: none; }
.st-tab[aria-current="page"] { color: var(--text); font-weight: 650; }
.st-more { position: relative; }
.st-more > summary { height: 100%; }
.st-sheet {
  position: fixed; left: 8px; right: 8px; bottom: calc(72px + env(safe-area-inset-bottom, 0px)); z-index: 30;
  display: flex; flex-direction: column; gap: 2px; padding: 10px; background: var(--panel);
  border: 1px solid var(--border-strong); border-radius: var(--radius-modal); box-shadow: var(--shadow-2);
}
.st-sheet .plane { margin: 4px 10px; }
/* The plane chip: the host in the chip and the commit beside it as its own word, so
   neither is ever cut short by the other. */
.plane { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.st-sheet .who { padding: 4px 10px; }

@media (min-width: 900px) {
  .st-app { display: grid; grid-template-columns: 232px minmax(0, 1fr); }
  /* The rail's ground runs the whole page; what is in it stays in view. */
  .st-rail { display: block; border-right: 1px solid var(--border); background: color-mix(in srgb, var(--bg-sunken) 55%, var(--bg)); }
  .st-rail-in {
    position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column; gap: 2px; overflow-y: auto;
    padding: 16px 12px 12px;
  }
  .st-rail .word { padding: 4px 10px 6px; }
  .st-rail .plane { margin: 0 10px 14px; }
  .st-places { display: flex; flex-direction: column; gap: 2px; }
  .st-rail .grow { flex: 1; }
  .st-acct { display: flex; flex-direction: column; gap: 6px; padding: 10px; border-top: 1px solid var(--border); }
  .st-acct .trustchip { max-width: 100%; align-self: flex-start; }
  .st-ptop, .st-tabs { display: none; }
  .st-main main { padding-top: 28px; padding-bottom: 64px; }
}

/* The paper's headings: the page's name large, and each section under the
   heavy rule the box's pages wear. */
main > h1 { font-size: var(--text-hero); letter-spacing: -0.01em; line-height: 1.1; margin-bottom: 8px; }
main > h2, main section > h2 { border-top: 2px solid var(--text); padding-top: 10px; margin-top: 30px; }
main > p.lede { font-size: var(--text-reading); max-width: 70ch; }
/* THE DOOR'S HEADER (sign-in, recovery): one word, no navigation — the
   signed-in pages wear the paper's shell above instead. It wraps rather than
   pushing a phone sideways (measured 10 September 2026). */
header.top {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px;
  border-bottom: 1px solid var(--border); padding: 14px 20px;
}
h1 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-title); margin: 0 0 6px; }
h2 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-heading); margin: 22px 0 8px; }
p.lede { color: var(--muted); margin: 0 0 18px; }
table.estate { width: 100%; border-collapse: collapse; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-card); overflow: hidden; }
table.estate th { text-align: left; font-family: var(--font-mono); font-size: var(--text-micro); text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); padding: 10px 12px; border-bottom: 1px solid var(--border); background: var(--panel-2); }
table.estate td { padding: 10px 12px; border-bottom: 1px solid var(--border); vertical-align: top; }
table.estate tr:last-child td { border-bottom: 0; }
table.estate a { color: var(--text); font-weight: 600; text-decoration: none; }
table.estate a:not(.button):hover { text-decoration: underline; }
table.estate a.button { font-size: var(--text-caption); padding: 4px 10px; color: var(--primary-fg); }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--text-caption); }
/* A BADGE IS A STATE, AND IT IS QUIET (10 September 2026, on Grant's word that
   the badges looked ugly). Two faults were under that: sentences inside a
   pill-radius box, wrapping to three lines in a narrow column; and two
   grammars across two planes — the box's `.pill` uppercase with tracking and
   no border, this one lowercase with a border on the plain variant only.

   The distinction kept rather than flattened: a card's KIND is a label and may
   shout, which is the box's `.pill`. A thing's STATE is quiet and lowercase,
   which is this. One shape for every variant, and `nowrap` so a badge can
   never become a paragraph by accident — anything longer than a state is a
   note in muted text beside the thing, not a badge. */
/* ---- THE ONE LINE: the same two chips the console wears ----
   Move 5 of the surfaces proposal (10 September 2026). Copied in shape, not in
   spirit: the geometry comes from the same `--badge-*` tokens both files
   declare, so these sit at exactly the height every other badge does. The
   colours are the plane's own, from the same palette.

   THE SEAL IS IN ONE ROLE HERE, as it is in the console (decision 0035): the
   stamp on the trust chip and nowhere else on this page. */
.envchip {
  display: inline-flex; align-items: center;
  font-family: var(--font-mono); font-size: var(--text-micro); color: var(--muted);
  font-weight: var(--badge-weight); line-height: var(--badge-line);
  font-variant-numeric: tabular-nums;
  border: 1px solid var(--border); border-radius: var(--radius-full);
  padding: var(--badge-pad-y) var(--badge-pad-x); white-space: nowrap;
}
/* The cloud plane says so in the trust colour: a vendor with three tabs open
   must be able to tell which one is real without reading. */
.envchip.onplane {
  color: var(--trust-text);
  border-color: color-mix(in srgb, var(--trust) 40%, var(--border));
  background: var(--trust-tint);
}
.envchip .rdg { margin: 0 0.45ch; }
/* THE TRUST CHIP WRAPS OR FITS; IT NEVER CLIPS (3 October 2026). It carries the estate's
   own sentence, which is as long as the estate's worst news, and it was held to one line
   with an ellipsis: at the foot of the rail it read "Three boxes, one has gone…". So it
   takes the width of whatever holds it and breaks onto as many lines as the sentence
   needs. The radius is the card's, not the pill's: one line still reads as a pill (the
   radius is more than half its height) and several lines read as a rounded block rather
   than a lozenge with its corners eaten. `tests/test_the_trust_chip_never_clips.py` reads
   these rules, and the surface check measures the longest sentence on every page. */
.trustchip {
  display: inline-flex; align-items: flex-start; gap: var(--badge-gap);
  font-family: var(--font-mono); font-size: var(--text-micro);
  font-weight: var(--badge-weight); line-height: var(--badge-line);
  font-variant-numeric: tabular-nums;
  color: var(--muted); background: var(--panel-2);
  border: 1px solid transparent; border-radius: var(--radius-card);
  max-width: 100%; min-width: 0; white-space: normal; overflow-wrap: anywhere;
  padding: var(--badge-pad-y) var(--badge-pad-x);
}
.trustchip .stamp { color: var(--trust-text); flex: none; }
.trustchip.well { color: var(--success-text); background: var(--success-tint); }
.trustchip.watch { color: var(--warning-text); background: var(--warning-tint); }
.trustchip.trouble { color: var(--danger-text); background: var(--danger-tint); }
/* Nothing to judge is not judged well — it wears the quiet grey and says so. */
.trustchip.quiet { color: var(--muted); background: var(--panel-2); }

.chip {
  display: inline-flex; align-items: center;
  font-family: var(--font-mono); font-size: var(--text-micro);
  font-weight: var(--badge-weight); line-height: var(--badge-line);
  padding: var(--badge-pad-y) var(--badge-pad-x);
  border-radius: var(--radius-full); border: 1px solid transparent;
  white-space: nowrap; background: var(--panel-2); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.chip.ok { color: var(--success-text); background: var(--success-tint); }
.chip.warn { color: var(--warning-text); background: var(--warning-tint); }
.chip.bad { color: var(--danger-text); background: var(--danger-tint); }
.chip.quiet { color: var(--muted); background: var(--panel-2); }

/* The long form of a state, which is not a badge. */
.saidof { color: var(--muted); font-size: var(--text-caption); }
.panel { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-card); padding: 16px 18px; margin: 12px 0; box-shadow: var(--shadow-1); }
.panel dl { display: grid; grid-template-columns: max-content 1fr; gap: 6px 18px; margin: 0; }
.panel dt { color: var(--muted); font-family: var(--font-mono); font-size: var(--text-micro); text-transform: uppercase; letter-spacing: 0.08em; padding-top: 3px; }
.panel dd { margin: 0; }
.empty { color: var(--muted); padding: 24px; text-align: center; border: 1px dashed var(--border); border-radius: var(--radius-card); }
button, .button { font-family: inherit; font-size: var(--text-body); border-radius: var(--radius-ctl); border: 1px solid var(--border-strong); background: var(--primary); color: var(--primary-fg); padding: 7px 14px; cursor: pointer; }
button[disabled] { opacity: 0.55; cursor: not-allowed; }
input { font-family: inherit; font-size: var(--text-heading); border-radius: var(--radius-ctl); border: 1px solid var(--border-strong); background: var(--panel); color: var(--text); padding: 6px 10px; }
.why { font-size: var(--text-caption); color: var(--muted); }
/* The line an owner copies from /signed-in (decision 0042): one row, as wide as the page allows. */
input.line { width: 100%; max-width: 76ch; font-family: var(--font-mono); font-size: var(--text-caption); }

ul.plain { margin: 0 0 0.4rem; padding-left: 1rem; }

/* ---------------------------------------------------------------------------
   THE ESTATE AS CARDS (10 September 2026, on Grant's word). The twelve-column
   table forced the PAGE to scroll sideways — scrollWidth 1002 against a 586
   viewport, five columns off the right edge with nothing saying they existed,
   and every cell wrapping mid-value. A card grid reflows; a twelve-column
   table never will. Six facts per card and the rest on the box's own page.
   --------------------------------------------------------------------------- */
.verdict {
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-heading);
  line-height: 1.35; margin: 0 0 18px; padding: 12px 16px;
  border-radius: var(--radius-card); border: 1px solid var(--border);
  background: var(--panel); color: var(--text);
}
.verdict.well { border-color: var(--success); background: var(--success-tint); color: var(--success-text); }
.verdict.watch { border-color: var(--warning); background: var(--warning-tint); color: var(--warning-text); }
.verdict.trouble { border-color: var(--danger); background: var(--danger-tint); color: var(--danger-text); }
.verdict.quiet { color: var(--muted); }

.boxcards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 12px; }
.boxcard {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 15px 16px; box-shadow: var(--shadow-1);
}
.boxcard .bname {
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-heading);
  color: var(--text); text-decoration: none;
}
.boxcard .bname:hover { text-decoration: underline; }
.boxcard .bwho { font-family: var(--font-mono); font-size: var(--text-micro); color: var(--muted); margin: 2px 0 12px; }
.bfacts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 7px 14px; margin: 0; }
.bfacts dt {
  font-family: var(--font-mono); font-size: var(--text-micro); color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.08em; padding-top: 3px;
}
.bfacts dd { margin: 0; font-size: var(--text-body); min-width: 0; }
.bopen { margin: 12px 0 0; }
.bcounts {
  display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 13px 0 0; padding-top: 11px;
  border-top: 1px solid var(--border);
  font-family: var(--font-mono); font-size: var(--text-micro); color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* A WIDE TABLE SCROLLS ITSELF; THE PAGE NEVER DOES (10 September 2026).
   Measured on the live plane: /customers was 258px wider than a 390px window,
   /users 241, /releases 222, /catalogue 109 — and at 560px still 88, 71, 52.
   The whole page carried the overflow, which takes the headings and the
   navigation sideways with it. A table is allowed to be wider than the window;
   a page is not. The columns are the point, so the wrapper is the fix rather
   than shrinking the table. */
.tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* A FORM WRAPS; IT DOES NOT PUSH THE PAGE SIDEWAYS (10 September 2026).
   With every table wrapped, /users still ran 241px past a 390px window and the
   culprit was the "Add a person" form: two labels inline in one paragraph, and
   a <select> whose widest option is a sentence ("governance — the customer's
   own person: sees their boxes, follows a channel…"). A select is as wide as
   its longest option unless it is told otherwise, and an option is not a place
   to keep an explanation — but the explanation is genuinely useful, so the
   control is constrained instead of the words being cut. */
form.panel p { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
form.panel label { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
form.panel input, form.panel select { max-width: 100%; }
form.panel select { max-width: min(100%, 34ch); }

/* ---- brands (decision 0016): a naming form that reads as a sentence, and a
   pack shown in both modes because a pack that was only ever seen in daylight
   is a pack whose other half nobody checked. ---- */
.naming { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: flex-end; }
.naming label, .brandform label { display: flex; flex-direction: column; gap: 3px;
  font-size: var(--text-caption); color: var(--muted); }
.naming select, .naming input, .brandform select, .brandform input, .brandform textarea {
  font: inherit; font-size: var(--text-body); color: var(--text);
  background: var(--panel); border: 1px solid var(--border-strong);
  border-radius: var(--radius-ctl); padding: 5px 8px; }
.naming .grant { flex-direction: row; align-items: center; gap: 6px; }
.brandform { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: flex-end;
  max-width: 900px; }
.brandform .wide { flex: 1 1 380px; }
.brandform textarea { width: 100%; font-family: var(--font-mono);
  font-size: var(--text-micro); }
.brand { margin: 18px 0 22px; }
.swatches { display: flex; flex-wrap: wrap; gap: 12px; margin: 8px 0 10px; }
.swatch { display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  border: 1px solid; border-radius: var(--radius-card); min-width: 260px; }
.swatch .fill { border-radius: var(--radius-ctl); padding: 5px 12px;
  font-size: var(--text-caption); font-weight: 600; }

/* ---- the two design-system pages (decision 0017) ---- */
.dsg { margin-top: 8px; }
.dsg-rules { padding-left: 1.2rem; max-width: 76ch; }
.dsg-rules li { margin: 6px 0; }
.dsg-row { display: flex; flex-wrap: wrap; gap: 8px 10px; align-items: center; margin: 10px 0; }
.dsg-swatches { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; margin: 12px 0; }
.dsg-swatch { border: 1px solid var(--border); border-radius: var(--radius-ctl); overflow: hidden; }
.dsg-swatch div { height: 40px; }
.dsg-swatch span { display: block; padding: 4px 8px; font-family: var(--font-mono); font-size: var(--text-micro); color: var(--muted); }
.dsg-type { display: grid; gap: 6px; margin: 14px 0; }
.dsg-spec { max-width: 720px; margin-top: 12px; }
/* Specimen frames: the shell's fixed parts lifted into the page flow, each
   frame scrolling inside itself so the page never goes sideways. */
.dsg-frames { display: flex; flex-wrap: wrap; gap: 20px; align-items: flex-start; margin-top: 12px; }
.dsg-desk {
  display: grid; width: 100%; max-width: 900px; min-width: 0; height: 520px;
  border: 1px solid var(--border-strong); border-radius: var(--radius-card); overflow: hidden; background: var(--bg);
}
.dsg-desk .pa-rail {
  display: flex; flex-direction: column; gap: 2px; padding: 14px 10px 10px; border-right: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg-sunken) 55%, var(--bg)); overflow: hidden;
}
.dsg-phone {
  display: flex; flex-direction: column; width: 360px; max-width: 100%; height: 640px;
  border: 1px solid var(--border-strong); border-radius: 28px; overflow: hidden; background: var(--bg);
}
.dsg-phone .pa-ptop { display: flex; padding-top: 10px; }
.dsg-phone .pa-tabbar { display: grid; position: static; margin-top: auto; }
.dsg-paperframe { overflow-y: auto; min-height: 0; flex: 1; padding: 12px 16px 16px; }
.dsg-mark { display: inline-block; width: 12px; height: 12px; margin-right: 8px; background: var(--trust); clip-path: var(--octagon); }
.dsg-brands { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; margin-top: 12px; }
.dsg-brand { margin: 0; }
.dsg-brand figcaption { margin-top: 6px; font-size: var(--text-caption); color: var(--muted); }
.dsg-brandpage {
  padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--bg); color: var(--text); max-height: 420px; overflow: hidden;
}
.dsg-brandmark { display: block; margin-bottom: 8px; }
/* Below 560 the desk frame shows its paper alone; the rail joins from 560. */
.dsg-desk { grid-template-columns: minmax(0, 1fr); }
.dsg-desk .pa-rail { display: none; }
@media (min-width: 560px) {
  .dsg-desk { grid-template-columns: 210px minmax(0, 1fr); }
  .dsg-desk .pa-rail { display: flex; }
}

/* Seat requests (Stem decision 0020): a card per ask on the customers page. Approve is one
   press; Decline takes its reason on the same line, and the line wraps on a phone rather
   than pushing the page sideways. */
.seatask form { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 12px 0 0; }
.seatask form input { flex: 1 1 180px; min-width: 0; max-width: 100%; }
.seatask button.quiet { background: var(--panel); color: var(--text); }

/* ===========================================================================
   THE CUSTOMERS AREA (decisions 0032 to 0037; Grant's approved redesign of
   3 October 2026, `stem-customers-redesign.html`). Built to look like what was
   shown: a page head with crumbs, sections under the heavy rule, rows and
   tables drawn with rules rather than boxes, one card per page for what is
   waiting, forms that open as <details> so the plane still needs no script.

   The mockup stepped its rows at 700 pixels; the plane keeps the four widths
   Grant approved on 10 September 2026, so that step is 560 here.
   =========================================================================== */
:root { --gutter: 16px; --content: 1040px; --label: 120px; --gap-sec: 36px; }
@media (min-width: 900px) {
  :root { --gutter: 40px; }
}
@media (min-width: 1280px) {
  :root { --gutter: 56px; }
}
@media (min-width: 1600px) {
  :root { --content: 1120px; --label: 132px; }
}

.st-main .strong, .st-main strong { font-weight: 600; }
.st-main .sub { display: block; font-size: var(--text-caption); color: var(--muted); font-weight: 400; }
.why.under { margin-top: 10px; }
.sec > .why, .pagehead .why, .formpanel .why, .st-once .why { margin: 0; max-width: 76ch; }
.alert { color: var(--danger-text); font-weight: 600; }
.st-main code { font-family: var(--font-mono); font-size: var(--text-caption); user-select: all; }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; padding: 0; margin: -1px; }
.chip.dotted::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; margin-right: 6px; flex: none; }

/* ---- the page head and the sections ---- */
.pagehead { position: relative; margin-bottom: 20px; }
.pagehead h1 { font-size: var(--text-hero); letter-spacing: -0.01em; line-height: 1.1; text-wrap: balance; margin: 0; }
.pagehead .lede { color: var(--muted); margin: 8px 0 0; max-width: 76ch; font-size: var(--text-body); }
.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: var(--text-caption); color: var(--muted); margin-bottom: 10px; }
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:hover { color: var(--text); text-decoration: underline; }
.crumbs [aria-current] { color: var(--text); }
.sec { position: relative; margin-top: var(--gap-sec); }
.sec > h2 { border-top: 2px solid var(--text); padding-top: 16px; margin: 0 0 12px; min-height: 52px; line-height: 1.35; }
.sec > h2 .n { display: inline-grid; place-items: center; width: 22px; height: 22px; margin-right: 10px; border-radius: 50%; background: var(--primary); color: var(--primary-fg); font-family: var(--font-body); font-size: var(--text-caption); font-weight: 600; vertical-align: 1px; }
.sec > .why:first-of-type { margin-bottom: 12px; }
.st-main .lead { margin: 0 0 14px; max-width: 76ch; }
.narrow > * { max-width: 640px; }
.st-main h3 { font-family: var(--font-display); font-weight: 600; font-size: var(--text-heading); line-height: 1.35; margin: 0; }

/* ---- an act that opens a labelled form: a <details>, so no script ---- */
.st-main details > summary { list-style: none; cursor: pointer; }
.st-main details > summary::-webkit-details-marker { display: none; }
details.act > summary { display: inline-flex; border-radius: var(--radius-ctl); }
details.act > summary .when-open { display: none; }
details.act[open] > summary .when-closed { display: none; }
details.act[open] > summary .when-open { display: inline-flex; }
.sec > details.act > summary, .sec > .secact { position: absolute; top: 9px; right: 0; }
.pagehead > details.act > summary, .pagehead > .headact { margin-top: 12px; }
.pagehead > details.act[open] > summary { margin-bottom: 12px; }
@media (min-width: 560px) {
  .pagehead > details.act > summary, .pagehead > .headact { position: absolute; right: 0; bottom: 0; margin: 0; }
  .pagehead:has(> details.act[open]) > details.act > summary { position: static; margin: 12px 0; }
  .pagehead:has(> details.act, > .headact) > h1, .pagehead:has(> details.act, > .headact) > .lede { max-width: calc(100% - 190px); }
}

/* ---- controls: one geometry. 36px buttons, 40px fields; 32px inside a table. ---- */
.cx-btn { appearance: none; display: inline-flex; align-items: center; justify-content: center; gap: 7px; font: inherit; font-size: var(--text-body); font-weight: 600; line-height: 1.2; padding: 8px 14px; min-height: 36px; border-radius: var(--radius-ctl); border: 1px solid var(--border-strong); background: var(--panel); color: var(--text); cursor: pointer; white-space: nowrap; text-decoration: none; transition: background var(--t-micro) var(--ease), border-color var(--t-micro) var(--ease); }
.cx-btn:hover { background: var(--primary-tint); }
.cx-btn.primary { background: var(--primary); border-color: var(--primary); color: var(--primary-fg); }
.cx-btn.primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); }
.cx-btn.quiet { border-color: transparent; background: none; color: var(--muted); font-weight: 500; }
.cx-btn.quiet:hover { color: var(--text); background: var(--panel-2); }
.cx-btn.danger { color: var(--danger-text); border-color: var(--danger); background: var(--panel); }
.cx-btn.danger:hover { background: var(--danger-tint); }
.cx-btn[disabled] { opacity: 0.55; cursor: not-allowed; }
.cx-btn .st-ic { width: 16px; height: 16px; }
.cx-link { color: var(--text); text-decoration: underline; text-decoration-color: var(--border-strong); text-underline-offset: 3px; }
.cx-link:hover { text-decoration-color: var(--text); }
.cx-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.cx-field > label { font-size: var(--text-caption); font-weight: 600; color: var(--text); }
.cx-field .hint { font-size: var(--text-caption); color: var(--muted); }
.cx-input, .cx-select { font: inherit; font-size: var(--text-body); color: var(--text); width: 100%; min-width: 0; background: var(--panel); border: 1px solid var(--border-strong); border-radius: var(--radius-ctl); padding: 8px 12px; min-height: 40px; }
.cx-input::placeholder { color: var(--muted); opacity: 0.75; }
.cx-input:focus, .cx-select:focus { outline: 2px solid var(--info); outline-offset: 1px; border-color: var(--info); }
.withsuffix { display: flex; align-items: stretch; min-width: 0; }
.withsuffix .cx-input { border-top-right-radius: 0; border-bottom-right-radius: 0; flex: 1; }
.withsuffix .suffix { display: flex; align-items: center; padding: 0 10px; font-family: var(--font-mono); font-size: var(--text-caption); color: var(--muted); background: var(--panel-2); border: 1px solid var(--border-strong); border-left: 0; border-radius: 0 var(--radius-ctl) var(--radius-ctl) 0; white-space: nowrap; }

/* A card only where a thing is a separate object: what is waiting, an open form, a secret. */
.formpanel { margin: 0 0 16px; display: grid; gap: 14px; max-width: 760px; padding: 18px 20px; }
.formpanel > * { margin: 0; }
.formgrid { display: grid; grid-template-columns: 1fr; gap: 14px 16px; max-width: 720px; }
@media (min-width: 560px) {
  .formgrid { grid-template-columns: 1fr 1fr; }
  .formgrid.three { grid-template-columns: 1fr 1fr 1fr; }
}
.formacts { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.formacts.foot { margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--border); }

/* ---- label and value, one way everywhere ---- */
.facts { margin: 0; }
.facts .r { display: grid; grid-template-columns: var(--label) minmax(0, 1fr); gap: 0 12px; padding: 7px 0; min-height: 38px; border-top: 1px solid var(--border); align-items: center; }
.facts .r:first-child { border-top: 0; }
.facts dt { color: var(--muted); font-size: var(--text-caption); }
.facts dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.facts .r:has(details[open]) { align-items: start; }
.facts2 { display: grid; grid-template-columns: 1fr; gap: 0 56px; max-width: 920px; }
.facts2 .facts + .facts .r:first-child { border-top: 1px solid var(--border); }
@media (min-width: 900px) {
  .facts2 { grid-template-columns: 1fr 1fr; }
  .facts2 .facts + .facts .r:first-child { border-top: 0; }
}
details.inl { display: inline; }
details.inl > summary { display: inline; margin-left: 10px; }
details.inl[open] > summary { color: var(--muted); }
.inlform { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.inlform .cx-select, .inlform .cx-input { width: 132px; min-height: 36px; padding: 6px 10px; }

/* ---- rows: rules, not boxes. Full width for a page's main lists; `fit` takes only what it needs. ---- */
.rows .hd { display: none; }
.rows .row { position: relative; display: grid; grid-template-columns: 1fr; gap: 6px; padding: 14px 0; border-top: 1px solid var(--border); }
.rows .row:first-of-type { border-top: 1px solid var(--border-strong); }
.rows .row:last-child { border-bottom: 1px solid var(--border); }
.rows .cell { min-width: 0; }
.rows .cell[data-l] { display: grid; grid-template-columns: var(--label) minmax(0, 1fr); gap: 12px; align-items: baseline; }
.rows .cell[data-l] > * { justify-self: start; }
.rows .cell[data-l]::before { content: attr(data-l); font-size: var(--text-caption); color: var(--muted); }
.rowlink { font-weight: 600; color: var(--text); text-decoration: none; }
a.rowlink { text-decoration: underline; text-decoration-color: var(--border-strong); text-underline-offset: 3px; }
a.rowlink:hover { text-decoration-color: var(--text); }
.rowlink.stretched::after { content: ""; position: absolute; inset: 0; }
.rows .main .sub { overflow-wrap: anywhere; }
.stack { display: flex; flex-direction: column; gap: 3px; align-items: flex-start; min-width: 0; }
.flag { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.boxmark { display: inline-flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.boxmark .dot, .said .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); flex: none; transform: translateY(-1px); }
.boxmark.warn .dot, .said.warn .dot { background: var(--warning); }
.boxmark.bad .dot, .said.bad .dot { background: var(--danger); }
.boxmark.quiet .dot, .said.quiet .dot { background: var(--border-strong); }
.said { display: inline-flex; align-items: baseline; gap: 8px; }
@media (min-width: 560px) {
  .rows .hd, .rows .row { display: grid; gap: 0 24px; align-items: start; }
  .rows .hd { padding: 0 0 8px; font-size: var(--text-caption); font-weight: 600; color: var(--muted); }
  .rows .row { padding: 12px 0; }
  .rows .cell[data-l] { display: block; }
  .rows .cell[data-l]::before { content: none; }
  .rows .num { text-align: right; }
  .rows.fit { width: fit-content; max-width: 100%; }
  .custs .hd, .custs .row { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1.2fr) minmax(0, 1.4fr) 140px; }
  .boxes .hd, .boxes .row { grid-template-columns: minmax(0, 1.6fr) minmax(0, 0.9fr) minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr); }
  .boxes .row, .acts3 .row, .spend .row { align-items: center; }
  .rows .cell.wide { grid-column: span 2; }
  .spend .hd, .spend .row { grid-template-columns: minmax(0, 200px) 80px 96px minmax(0, 330px); }
  .rows .cell.wide3 { grid-column: span 3; }
  .changes .hd, .changes .row { grid-template-columns: minmax(0, 260px) minmax(0, 170px) minmax(0, 110px) minmax(0, 130px); }
  .checks .hd, .checks .row { grid-template-columns: minmax(0, 230px) minmax(0, 330px) 90px; }
  .asks .hd, .asks .row { grid-template-columns: minmax(0, 130px) minmax(0, 420px) minmax(0, 260px); }
  .news .hd, .news .row { grid-template-columns: minmax(0, 170px) minmax(0, 560px) minmax(0, 170px); }
  .acts3 .row { grid-template-columns: minmax(0, 520px) 96px; }
  .acts3 .row .cx-btn { justify-self: end; width: 96px; }
}

/* ---- apps and seats: one table, read or as the one form ---- */
table.lines { border-collapse: collapse; width: 100%; }
.lines th { text-align: left; font-size: var(--text-caption); font-weight: 600; color: var(--muted); padding: 0 12px 8px 0; border-bottom: 1px solid var(--border-strong); white-space: nowrap; }
.lines td { padding: 9px 12px 9px 0; vertical-align: middle; border-top: 1px solid var(--border); }
.lines tbody tr:first-child td { border-top: 0; }
.lines tbody tr:last-child td { border-bottom: 1px solid var(--border); }
.lines .num { text-align: right; white-space: nowrap; }
.lines td.app { font-weight: 600; }
.lines td.unit, .lines td.use { color: var(--muted); font-size: var(--text-caption); white-space: nowrap; }
.st-meter { display: inline-flex; align-items: center; margin-left: 10px; vertical-align: middle; }
.st-meter .track { width: 64px; height: 6px; border-radius: var(--radius-full); background: var(--panel-2); overflow: hidden; border: 1px solid var(--border); }
.st-meter .track span { display: block; height: 100%; background: var(--route-local); }
.st-meter.over .track span { background: var(--danger); }
.st-meter.none { visibility: hidden; }
/* the control column: a seats field or an On tick, the same box either way */
.seatin { font: inherit; font-size: var(--text-body); color: var(--text); width: 72px; height: 32px; padding: 4px 10px; text-align: right; background: var(--panel); border: 1px solid var(--border-strong); border-radius: var(--radius-ctl); }
.seatin::placeholder { color: var(--muted); opacity: 0.6; }
.seatin:focus { outline: 2px solid var(--info); outline-offset: 1px; border-color: var(--info); }
.tick { display: inline-flex; align-items: center; justify-content: flex-end; gap: 8px; width: 72px; height: 32px; cursor: pointer; font-size: var(--text-caption); color: var(--muted); }
.tick input { width: 18px; height: 18px; accent-color: var(--primary); margin: 0; padding: 0; }
@media (min-width: 560px) {
  .lines tr.first td { border-top-color: var(--border-strong); }
  .lines td.app.rep span { visibility: hidden; }
  .lines.read th:nth-child(1) { width: 21%; }
  .lines.read th:nth-child(2) { width: 25%; }
  .lines.read th:nth-child(3) { width: 104px; }
  .lines.read th:nth-child(4) { width: 150px; }
  .lines.read th:nth-child(5), .lines.read td.state { padding-left: 28px; }
  /* the form: fixed columns, so the held list and the catalogue list line up */
  table.lines.form { width: 100%; table-layout: fixed; }
  .lines.form .c-app { width: 190px; }
  .lines.form .c-level { width: 230px; }
  .lines.form .c-use { width: 170px; }
  .lines.form .c-ctl { width: 84px; }
  .lines.form td.ctl, .lines.form th.ctl { padding-right: 0; text-align: right; }
  .lines.form td.level { padding-left: 0; }
  .lines.form td { padding-top: 6px; padding-bottom: 6px; }
}
@media (max-width: 559.98px) {
  .lines thead { display: none; }
  .lines, .lines tbody { display: block; }
  .lines tr { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; padding: 10px 0; border-top: 1px solid var(--border); }
  .lines tbody tr:first-child { border-top: 1px solid var(--border-strong); }
  .lines tbody tr:last-child { border-bottom: 1px solid var(--border); }
  .lines tr::before { content: ""; flex-basis: 100%; order: 2; }
  .lines td { display: block; padding: 0 !important; border: 0 !important; width: auto; }
  .lines td.app, .lines td.level, .lines td.state, .lines td.ctl { order: 1; }
  .lines td.state, .lines td.ctl { margin-left: auto; }
  .lines td.allow, .lines td.used, .lines td.unit, .lines td.use { order: 3; font-size: var(--text-caption); color: var(--muted); }
  .lines td.allow::after { content: " " attr(data-w) ","; }
  .lines td.used { display: flex; align-items: center; gap: 5px; }
  .lines td.used::after { content: attr(data-w); order: 2; }
  .lines td.used .st-meter { order: 3; margin-left: 4px; }
  .lines td.level .sub { display: none; }
  .lines td.allow.nocount, .lines .st-meter.none, .lines td.use:empty, .lines td.used:empty { display: none; }
  .lines td.use:not(:empty)::before { content: "· "; }
}
/* the catalogue, collapsed until wanted */
details.cat { margin-top: 20px; }
details.cat > summary { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; padding: 12px 0; border-top: 1px solid var(--border-strong); border-bottom: 1px solid var(--border-strong); font-family: var(--font-display); font-weight: 600; font-size: var(--text-heading); }
details.cat > summary::before { content: "+"; font-family: var(--font-mono); font-weight: 500; width: 14px; }
details.cat[open] > summary::before { content: "\2212"; }
details.cat[open] > summary { border-bottom-color: transparent; }
details.cat > summary .saidof { font-family: var(--font-body); font-weight: 400; }

/* ---- waiting on you: the one card on a page, a compact line per thing, each with its act ---- */
.waits { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-card); box-shadow: var(--shadow-1); overflow: hidden; }
.waits > .hd { padding: 10px 18px 0; font-size: var(--text-caption); font-weight: 600; color: var(--muted); }
.wait { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; padding: 12px 18px; }
.wait + .wait { border-top: 1px solid var(--border); }
.wait > .dot { width: 10px; height: 10px; border-radius: 50%; background: var(--border-strong); flex: none; align-self: flex-start; margin-top: 6px; }
.wait.bad > .dot { background: var(--danger); }
.wait.warn > .dot { background: var(--warning); }
.wait.ok > .dot { background: var(--success); }
.wtext { flex: 1 1 280px; min-width: 0; }
.wacts { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start; }
.wacts details > summary { display: inline-flex; }
.wait:has(details[open]) .wacts { flex: 1 1 100%; padding-left: 24px; }
.wacts details[open] { flex: 1 1 100%; }
.waits.calm { box-shadow: none; }
.waits.calm .sub { display: inline; margin-left: 6px; }
@media (max-width: 559.98px) {
  .wacts { flex: 1 1 100%; padding-left: 24px; }
  .acts3 .row .cx-btn { justify-self: start; min-width: 96px; }
}
.confirmbox { margin-top: 10px; padding: 14px; background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius-ctl); display: grid; gap: 12px; justify-items: start; max-width: 640px; }
.confirmbox p { margin: 0; }
.confirmbox .cx-field { width: 100%; }
.confirmpage { display: grid; gap: 18px; }
.confirmpage > p { margin: 0; max-width: 72ch; }

/* ---- the code shown once, and the IDs ---- */
.st-once { display: grid; gap: 10px; padding: 18px 20px; border: 1px dashed var(--border-strong); border-radius: var(--radius-card); background: var(--panel); }
.st-once h3 { margin-top: 6px; }
.st-once .code { font-size: 22px; letter-spacing: 0.1em; font-weight: 500; padding: 12px 14px; background: var(--bg-sunken); border-radius: var(--radius-ctl); text-align: center; user-select: all; overflow-wrap: anywhere; }
.st-once .code.small { font-size: var(--text-caption); letter-spacing: 0; text-align: left; }
.st-once .once { display: flex; gap: 8px; align-items: flex-start; margin: 4px 0 0; }
.ids { margin-top: var(--gap-sec); padding-top: 12px; border-top: 1px solid var(--border); }
.ids > summary { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-caption); color: var(--muted); font-weight: 600; padding: 4px 0; }
.ids > summary::before { content: "+"; font-family: var(--font-mono); }
.ids[open] > summary::before { content: "\2212"; }
.ids .facts { max-width: 560px; margin: 6px 0; }

/* form pages: every rule ends where the list ends */
.formpage > *, .formpage > form > * { max-width: 794px; }
@media (min-width: 1600px) {
  .formpage > *, .formpage > form > * { max-width: 834px; }
  .lines.form .c-level { width: 250px; }
  .lines.form .c-use { width: 180px; }
}
.formpage .formgrid { max-width: none; }
@media (min-width: 560px) {
  .formpage .rows.fit { width: 100%; }
  .formpage .changes .hd, .formpage .changes .row { grid-template-columns: minmax(0, 1.7fr) minmax(0, 1.1fr) minmax(0, 0.8fr) minmax(0, 0.8fr); }
}
