/* ── 00-scale.css ── */
/* Layer 1: scale — #2745 step 3 (ported from directions/ab-iteration/theme.css).
   Token layers: 00 scale -> 01/02 presets -> 03 roles. Colour values live only
   in these 0x files (contract.test.ts). Inter is self-hosted (OFL, latin subset plus arrows,
   static/fonts/), so the console makes no third-party call and screenshots are stable. */

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* The arrows ← ↑ → ↓ (activity copy: "OK → Warning"), from the same Inter v20: the latin
   file above has only ↑ and ↓. The browser fetches it only when a page shows an arrow. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/fonts/inter-arrows.woff2") format("woff2");
  unicode-range: U+2190-2193;
}

/* ---------- Layer 1: scale ---------- */
:root {
  --font: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --fs-11: 0.6875rem;
  --fs-12: 0.75rem;
  --fs-13: 0.8125rem;
  --fs-14: 0.875rem;
  --fs-15: 0.9375rem;
  --fs-16: 1rem;
  --fs-18: 1.125rem;
  --fs-24: 1.5rem;
  --fs-hero: 4rem;
  --lh-tight: 1.15;
  --lh-ui: 1.45;
  --w-text: 400;
  --w-ui: 500;
  --w-strong: 600;

  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;
  --s-8: 64px;

  --r-cell: 2px;
  --r-chip: 6px;
  --r-control: 8px;
  --r-card: 12px;
  --r-pill: 999px;

  --container: 1280px;
  --page-margin: 80px;
  --header-h: 60px;
}
@media (max-width: 760px) {
  :root { --page-margin: 16px; --fs-hero: 3rem; --fs-24: 1.375rem; }
}
@media (min-width: 761px) and (max-width: 1200px) {
  :root { --page-margin: 32px; }
}

/* ── 01-presets-light.css ── */
/* Layer 2: the light presets — #2745 step 3 (ported from directions/ab-iteration/theme.css).
   Token layers: 00 scale -> 01/02 presets -> 03 roles. Colour values live only
   in these 0x files (contract.test.ts). Light is also :root, the default for
   new users and the fallback for an unknown value; it must come first so a later
   preset on <html> wins at equal specificity. */

/* Light: true neutral greys, white cards on a grey ground, cobalt accent (from A). */
:root, [data-appearance="light"] {
  color-scheme: light;
  --ground: #f4f4f5;
  --surface: #ffffff;
  --surface-2: #f8f8f9;
  --surface-3: #ededf0;
  --surface-head: #f4f4f6; /* a widget's title row: one neutral step toward the ink (#3101) */
  --line: #e4e4e7;
  --line-strong: #d1d1d6;
  --ink: #18181b;
  --ink-2: #5f5f67;
  --ink-3: #8e8e96;
  --accent: #1f52d6;
  --accent-hover: #173fa8;
  --accent-tint: #edf2fd;
  --primary: #18181b;
  --primary-hover: #34343a;
  --on-primary: #ffffff;
  --on-accent: #ffffff;
  --control-bg: var(--surface);
  --header-focus: var(--accent);
  --header-control-on-ink: var(--ink);
  --header-control-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
  --header-bg: var(--surface);
  --header-ink: var(--ink);
  --header-ink-2: var(--ink-2);
  --header-line: var(--line);
  --header-mark: var(--accent);
  --header-control: var(--surface-3);
  --header-control-on: var(--surface);
  --shadow-card: 0 1px 2px rgba(24, 24, 27, 0.05);
  --shadow-menu: 0 1px 2px rgba(24, 24, 27, 0.06), 0 10px 28px rgba(24, 24, 27, 0.12);
  --shot-filter: none;

  --ok: #1f9d63;      --ok-ink: #13693f;   --ok-tint: #e6f5ec;   --on-ok: #ffffff;
  --warn: #e5a00d;    --warn-ink: #8a5300; --warn-tint: #fdf2d6; --on-warn: #4d2f00;
  --fail: #d92d20;    --fail-ink: #b42318; --fail-tint: #fdeceb; --on-fail: #ffffff;
  --grey: #8e8e96;    --grey-ink: #55555c; --grey-tint: #efeff1; --grey-hatch-bg: #e4e4e7;
  --none: #b8b8bf;
}

/* Light soft: warm stone. No pure white anywhere, warm-grey ink, a muted denim accent,
   and a header that sits on the ground instead of a white bar. For long sessions in daylight. */
[data-appearance="light-soft"] {
  color-scheme: light;
  --ground: #e9e5dd;
  --surface: #f6f3ec;
  --surface-2: #f0ece4;
  --surface-3: #e5e0d6;
  --surface-head: #ece8e0;
  --line: #dcd5c9;
  --line-strong: #c8bfb0;
  --ink: #29241e;
  --ink-2: #5e564a;
  --ink-3: #8c8375;
  --accent: #33589a;
  --accent-hover: #284778;
  --accent-tint: #e1e6ef;
  --on-accent: #f6f3ec;
  --primary: #29241e;
  --primary-hover: #423b32;
  --on-primary: #f6f3ec;
  --control-bg: var(--surface);
  --header-bg: var(--ground);
  --header-ink: var(--ink);
  --header-ink-2: var(--ink-2);
  --header-line: var(--line);
  --header-mark: var(--accent);
  --header-control: rgba(41, 36, 30, 0.07);
  --header-control-on: var(--surface);
  --header-control-on-ink: var(--ink);
  --header-control-shadow: 0 1px 2px rgba(60, 45, 25, 0.14);
  --header-focus: var(--accent);
  --shadow-card: 0 1px 2px rgba(60, 45, 25, 0.06);
  --shadow-menu: 0 1px 2px rgba(60, 45, 25, 0.06), 0 10px 28px rgba(60, 45, 25, 0.16);
  --shot-filter: brightness(0.96);

  --ok: #1d8856;      --ok-ink: #1c6340;   --ok-tint: #dfe9dc;   --on-ok: #ffffff;
  --warn: #c8901c;    --warn-ink: #74500c; --warn-tint: #f2e4c5; --on-warn: #3f2700;
  --fail: #c13b2d;    --fail-ink: #9b2a1f; --fail-tint: #f3ddd5; --on-fail: #ffffff;
  --grey: #8c8376;    --grey-ink: #554e44; --grey-tint: #e7e2d9; --grey-hatch-bg: #dcd6cb;
  --none: #b1a899;
}

/* Branded (provisional): our deep indigo-violet in the header, buttons and selection.
   The ground takes a faint tint of it; verdicts keep the Light tuning. */
[data-appearance="branded"] {
  color-scheme: light;
  --ground: #f3f2f7;
  --surface: #ffffff;
  --surface-2: #f8f7fb;
  --surface-3: #ecebf3;
  --surface-head: #f4f3f8;
  --line: #e4e2ec;
  --line-strong: #d0cddd;
  --ink: #17152a;
  --ink-2: #5d5a72;
  --ink-3: #8d8aa3;
  --accent: #4b32c3;
  --accent-hover: #3a249f;
  --accent-tint: #eeebfb;
  --primary: #4b32c3;
  --primary-hover: #3a249f;
  --on-primary: #ffffff;
  --on-accent: #ffffff;
  --control-bg: var(--surface);
  --header-focus: #b3a6ff;
  --header-control-on-ink: #ffffff;
  --header-control-shadow: none;
  --header-bg: #221a59;
  --header-ink: #ffffff;
  --header-ink-2: #c8c1f0;
  --header-line: #221a59;
  --header-mark: #b3a6ff;
  --header-control: rgba(255, 255, 255, 0.1);
  --header-control-on: rgba(179, 166, 255, 0.24);
  --shadow-card: 0 1px 2px rgba(23, 21, 42, 0.05);
  --shadow-menu: 0 1px 2px rgba(23, 21, 42, 0.06), 0 10px 28px rgba(23, 21, 42, 0.14);
  --shot-filter: none;

  --ok: #1f9d63;      --ok-ink: #13693f;   --ok-tint: #e6f5ec;   --on-ok: #ffffff;
  --warn: #e5a00d;    --warn-ink: #8a5300; --warn-tint: #fdf2d6; --on-warn: #4d2f00;
  --fail: #d92d20;    --fail-ink: #b42318; --fail-tint: #fdeceb; --on-fail: #ffffff;
  --grey: #8d8aa3;    --grey-ink: #55536a; --grey-tint: #efeef4; --grey-hatch-bg: #e4e2ec;
  --none: #b9b6c9;
}

/* ── 02-presets-dark.css ── */
/* Layer 2: the dark presets — #2745 step 3 (ported from directions/ab-iteration/theme.css).
   Token layers: 00 scale -> 01/02 presets -> 03 roles. Colour values live only
   in these 0x files (contract.test.ts). Loaded after the light file so a dark
   preset on <html> wins over :root at equal specificity. */

/* Dark: B's slate ground, near-white primary, a light cobalt accent. */
[data-appearance="dark"] {
  color-scheme: dark;
  --ground: #0c1220;
  --surface: #121a2a;
  --surface-2: #172034;
  --surface-3: #1e2840;
  --surface-head: #192233;
  --line: #253048;
  --line-strong: #36425e;
  --ink: #e8ecf4;
  --ink-2: #a3aec2;
  --ink-3: #75819a;
  --accent: #7ea6ff;
  --accent-hover: #a6c1ff;
  --accent-tint: rgba(126, 166, 255, 0.14);
  --primary: #e8ecf4;
  --primary-hover: #ffffff;
  --on-primary: #0c1220;
  --on-accent: #0c1220;
  --control-bg: var(--surface-3);
  --header-focus: var(--accent);
  --header-control-on-ink: var(--ink);
  --header-control-shadow: none;
  --header-bg: var(--surface);
  --header-ink: var(--ink);
  --header-ink-2: var(--ink-2);
  --header-line: var(--line);
  --header-mark: var(--accent);
  --header-control: var(--ground);
  --header-control-on: var(--surface-3);
  --shadow-card: none;
  --shadow-menu: 0 12px 32px rgba(3, 6, 14, 0.6), 0 0 0 1px var(--line-strong);
  --shot-filter: brightness(0.78);

  --ok: #2fb872;      --ok-ink: #5cd69b;   --ok-tint: #10301f;   --on-ok: #04210f;
  --warn: #e8a93a;    --warn-ink: #f2c25a; --warn-tint: #33280f; --on-warn: #2a1b00;
  --fail: #ef5a5f;    --fail-ink: #ff8a8e; --fail-tint: #3c1519; --on-fail: #ffffff;
  --grey: #74809a;    --grey-ink: #b6c0d2; --grey-tint: #1c2436; --grey-hatch-bg: #2a344b;
  --none: #4a5672;
}

/* Dark dimmed: a lighter slate with softer ink, for dark rooms that find Dark too stark. */
[data-appearance="dark-dimmed"] {
  color-scheme: dark;
  --ground: #1d222b;
  --surface: #252b35;
  --surface-2: #2b323d;
  --surface-3: #333b47;
  --surface-head: #2c333e;
  --line: #3a424f;
  --line-strong: #4b5464;
  --ink: #d3d9e2;
  --ink-2: #a0a9b8;
  --ink-3: #7d8697;
  --accent: #86acf0;
  --accent-hover: #a9c4f5;
  --accent-tint: rgba(134, 172, 240, 0.15);
  --primary: #d3d9e2;
  --primary-hover: #e9edf3;
  --on-primary: #1d222b;
  --on-accent: #1d222b;
  --control-bg: var(--surface-3);
  --header-focus: var(--accent);
  --header-control-on-ink: var(--ink);
  --header-control-shadow: none;
  --header-bg: var(--surface);
  --header-ink: var(--ink);
  --header-ink-2: var(--ink-2);
  --header-line: var(--line);
  --header-mark: var(--accent);
  --header-control: var(--ground);
  --header-control-on: var(--surface-3);
  --shadow-card: none;
  --shadow-menu: 0 12px 32px rgba(8, 10, 14, 0.5), 0 0 0 1px var(--line-strong);
  --shot-filter: brightness(0.75);

  --ok: #3caa73;      --ok-ink: #72cc9c;   --ok-tint: #263b31;   --on-ok: #0b2416;
  --warn: #d7a243;    --warn-ink: #e6bd68; --warn-tint: #3d3525; --on-warn: #2a1b00;
  --fail: #e2686a;    --fail-ink: #f59a98; --fail-tint: #452d30; --on-fail: #ffffff;
  --grey: #7e889b;    --grey-ink: #bcc4d0; --grey-tint: #323944; --grey-hatch-bg: #3a424f;
  --none: #5b6474;
}

/* ── 03-roles.css ── */
/* Layer 3: roles — #2745 step 3 (ported from directions/ab-iteration/theme.css).
   Token layers: 00 scale -> 01/02 presets -> 03 roles. Colour values live only
   in these 0x files (contract.test.ts). Re-declared on every [data-appearance]
   element so a preview can show any preset inside any page. */

:root, [data-appearance] {
  --link: var(--accent);
  --focus: var(--accent);
  --selected-ink: var(--accent);
  --selected-tint: var(--accent-tint);
  --grey-hatch: repeating-linear-gradient(135deg, var(--grey) 0 1.5px, var(--grey-hatch-bg) 1.5px 4.5px);
  --status-active: var(--ink);
  --status-inactive: var(--ink-2);
  /* An amber notice (#2745 S5-03): a button's outcome that did not happen. The warn hue's
     tint and ink, never its glyph or word: a notice is not a verdict. */
  --caution-tint: var(--warn-tint);
  --caution-ink: var(--warn-ink);
}

/* ── 10-base.css ── */
/* Base — #2745 step 3 (ported from ab-iteration/components.css § Base).
   Element defaults and the small utilities every part uses. Colours come from
   the role tokens only. */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--ground); }
body {
  margin: 0; background: var(--ground); color: var(--ink);
  font-family: var(--font); font-size: var(--fs-14); line-height: var(--lh-ui);
  font-optical-sizing: auto; font-feature-settings: "cv11", "ss01";
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
}
h1, h2, h3, h4, p, ul, ol, dl, dd, figure, fieldset { margin: 0; }
ul, ol { padding: 0; list-style: none; }
fieldset { border: 0; padding: 0; min-width: 0; }
button, input, select { font: inherit; color: inherit; }
svg { flex: none; }
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 4px; }

/* The inline icon sprite: present for <use href>, never painted. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.tnum, .num { font-variant-numeric: tabular-nums; }
/* A host stays whole on its line and moves to the next as a unit; only a host
   longer than a whole line wraps inside itself, so nothing pokes out of its card. */
.nobr { display: inline-block; max-width: 100%; white-space: normal; overflow-wrap: anywhere; vertical-align: top; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.muted { color: var(--ink-2); }
.icon { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.icon--20 { width: 20px; height: 20px; }

@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }

/* ── 11-layout.css ── */
/* Layout — #2745 step 3 (ported from ab-iteration/components.css § Layout).
   One 1280 container, the 12-column grid, vertical rhythm, the page frame and
   the phone show/hide utilities. */

.container { width: 100%; max-width: calc(var(--container) + 2 * var(--page-margin)); margin-inline: auto; padding-inline: var(--page-margin); }
.grid12 { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--s-5); }
.stack > * + * { margin-top: var(--s-5); }
.section-title { font-size: var(--fs-16); font-weight: var(--w-strong); letter-spacing: -0.01em; }
.page { padding-top: var(--s-6); padding-bottom: var(--s-8); }
.show-phone { display: none; }

@media (max-width: 760px) {
  .page { padding-top: var(--s-5); }
  .hide-phone { display: none !important; }
  .show-phone { display: block; }
}

/* ── 12-primitives.css ── */
/* Primitives — #2745 step 3 (ported from ab-iteration/components.css):
   buttons, Status, code chips, labelled facts, cards, disclosure, popovers.
   Colours come from the role tokens only. */

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  height: 36px; padding: 0 14px; border-radius: var(--r-control); border: 1px solid transparent;
  font-size: var(--fs-14); font-weight: var(--w-ui); line-height: 1; white-space: nowrap; cursor: pointer;
  background: none; color: var(--ink);
}
.btn:hover { text-decoration: none; }
.btn--primary { background: var(--primary); color: var(--on-primary); }
.btn--primary:hover { background: var(--primary-hover); }
.btn--secondary { background: var(--surface); border-color: var(--line-strong); box-shadow: var(--shadow-card); }
.btn--secondary:hover { background: var(--surface-2); }
.btn--quiet { color: var(--ink-2); padding-inline: 10px; }
.btn--quiet:hover { background: var(--surface-3); color: var(--ink); }
.btn--link { color: var(--link); padding-inline: 6px; }
.btn--sm { height: 30px; padding: 0 10px; font-size: var(--fs-13); border-radius: 7px; }
.btn--icon { width: 30px; padding: 0; }

/* ---------- Status: Active / Inactive. Neutral ink, never a hue, never a pill. ---------- */
.status { display: inline-flex; align-items: center; gap: 7px; font-size: var(--fs-13); color: var(--ink); white-space: nowrap; }
.status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--status-active); flex: none; }
.status--inactive { color: var(--ink-2); }
.status--inactive::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--status-inactive); }

/* Neutral code chip (country codes) */
.code { display: inline-flex; align-items: center; justify-content: center; min-width: 28px; height: 20px; padding: 0 5px; border-radius: 5px; border: 1px solid var(--line-strong); font-size: var(--fs-11); font-weight: var(--w-strong); letter-spacing: 0.02em; color: var(--ink); }

/* Labelled facts: label over value, divided by hairlines (no prose, no middle-dot strings) */
.facts { display: flex; flex-wrap: wrap; margin-top: var(--s-4); }
.facts > div { padding-right: var(--s-5); margin-right: var(--s-5); border-right: 1px solid var(--line); }
.facts > div:last-child { border-right: 0; margin-right: 0; padding-right: 0; }
.facts dt { color: var(--ink-2); font-size: var(--fs-12); }
.facts dd { margin-top: 2px; font-weight: var(--w-ui); font-variant-numeric: tabular-nums; white-space: nowrap; }

.facts--card { margin: 0; padding: var(--s-3) var(--s-5); border-bottom: 1px solid var(--line); }

/* ---------- Cards ----------
   The head is the title row on its own neutral band (#3101 1B, partner 2026-11-05), one step
   toward the ink, rounded to the card's inner corners; a table under it keeps the body's colour. */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--shadow-card); }
.card__head { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--line); background: var(--surface-head); border-radius: calc(var(--r-card) - 1px) calc(var(--r-card) - 1px) 0 0; }
.card__head h2, .card__head h3 { font-size: var(--fs-15); font-weight: var(--w-strong); letter-spacing: -0.01em; }
.card__head .count { color: var(--ink-2); font-size: var(--fs-13); font-variant-numeric: tabular-nums; }
.card__tools { margin-left: auto; display: flex; align-items: center; gap: var(--s-3); color: var(--ink-2); font-size: var(--fs-13); }
.card__body { padding: var(--s-5); }
.card__foot { padding: var(--s-3) var(--s-5); border-top: 1px solid var(--line); color: var(--ink-2); font-size: var(--fs-13); display: flex; gap: var(--s-4); flex-wrap: wrap; align-items: center; }

/* ---------- Disclosure ---------- */
.disclosure > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: var(--s-2); font-weight: var(--w-strong); }
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary .icon { color: var(--ink-2); transition: transform 0.15s ease; }
.disclosure[open] > summary .icon { transform: rotate(90deg); }
.disclosure__body { margin-top: var(--s-3); }

/* Popovers: one <details> primitive behind every menu (workspace, account, sort, row actions). */
.pop { position: relative; }
.pop > summary { list-style: none; cursor: pointer; }
.pop > summary::-webkit-details-marker { display: none; }
.pop__panel {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; min-width: 240px;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: var(--r-card);
  box-shadow: var(--shadow-menu); padding: var(--s-2); text-align: left;
}
.pop__panel a, .pop__panel button.pop__item, .pop__panel .pop__item { display: flex; width: 100%; align-items: center; gap: var(--s-2); padding: 8px 10px; border: 0; background: none; border-radius: 6px; color: var(--ink); font-weight: var(--w-ui); font-size: var(--fs-14); text-align: left; cursor: pointer; }
.pop__panel a:hover, .pop__panel button.pop__item:hover { background: var(--surface-2); text-decoration: none; }
.pop__form { margin: 0; } /* a POST item: the form only wraps its button */
.pop__label { padding: 6px 10px 2px; color: var(--ink-2); font-size: var(--fs-12); }
.pop__sep { height: 1px; background: var(--line); margin: 6px 0; }

/* Row actions: visible compact buttons in one fixed order, never a menu
   (partner ruling 2026-10-17). Each POST form only wraps its button. */
.row-actions { display: flex; flex-wrap: nowrap; gap: 2px var(--s-1); white-space: nowrap; }
.row-actions__form { display: contents; }
.row-actions__btn { gap: 6px; padding-inline: 8px; }
/* Each button carries its label as its hover tip, drawn only where the label rests:
   Link Admin's narrow screen (40-tables, Card 4). Where the label shows, no tip. */
.row-actions .row-actions__btn:is(:hover, :focus-visible)::before { content: none; }
/* A button with its own sentence (data-label beside it, LA-03: the old Link Admin's hover,
   what the button does) draws that sentence at every width, from the button's right edge
   leftwards: the buttons sit in a table's last column, so a centred tip would leave the page. */
.row-actions .row-actions__btn[data-label]:is(:hover, :focus-visible)::before { content: attr(data-tip); content: attr(data-tip) / ""; left: auto; right: 0; transform: none; }
/* Activate / Deactivate share one slot of one width, so every row lines up. */
.row-actions__btn--toggle { min-width: 146px; justify-content: flex-start; }
/* Two lines (Link Admin's last column, R-05): the run group, then the admin group. Each
   button has its own hairline border and one minimum width, so the two lines read as a
   grid of equal buttons (S-01, 2026-10-21); a line has no frame. A link that runs nothing
   says why on the run line (H-0501). */
.row-actions--lines { display: grid; justify-items: start; gap: 6px; white-space: normal; }
.row-actions__line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s-2); }
.row-actions__set { display: inline-flex; flex-wrap: nowrap; gap: 6px; }
.row-actions--lines .row-actions__btn { min-width: 92px; justify-content: center; border: 1px solid var(--line); background: var(--surface); }
.row-actions--lines .row-actions__btn:hover { border-color: var(--line-strong); background: var(--surface-3); }
.row-actions__note { color: var(--ink-2); font-size: var(--fs-12); line-height: 1.4; }

/* ---------- Notice: one line confirming what the user just did (#2745 Gate 3 QA) ----------
   The selected tint with a check glyph: a notice is never a verdict, so it never takes a
   result mark. Amber (S5-03): an outcome that did not happen, on the caution tint with the
   info glyph, never red. A link in it (the remedy) is ink, underlined; a long address
   wraps inside itself rather than widening the page. */
.notice { display: flex; align-items: flex-start; gap: var(--s-2); padding: var(--s-3) var(--s-4); border-radius: var(--r-card); background: var(--selected-tint); color: var(--ink); font-size: var(--fs-14); }
.notice .icon { flex: none; margin-top: 2px; color: var(--selected-ink); }
.notice > span { min-width: 0; overflow-wrap: anywhere; }
.notice a { color: inherit; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.notice--amber { background: var(--caution-tint); }
.notice--amber .icon { color: var(--caution-ink); }
/* A notice's one action (Card 2): its form under the words, the button left-aligned with them;
   on a narrow screen its label wraps inside the button rather than widening the page. */
.notice-body { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-2); min-width: 0; }
.notice-body > span { overflow-wrap: anywhere; }
.notice-action { max-width: 100%; }
.notice-action .btn { height: auto; min-height: 30px; padding-block: 6px; white-space: normal; line-height: 1.3; text-align: start; }

/* ---------- Hover tip (Gate 3 review 2026-10-19) ----------
   Zero client JS: an element carries its tip in data-tip, and CSS draws it above
   the element only while it is hovered or focused, so at rest it takes no room
   and adds no width. Ink on surface, inverted in every preset; a line break in
   data-tip starts a new line. A part holding a control (Bulk edit's three-state
   box, m 2026-10-24) shows it while that control has the keyboard focus. The
   drawn text is hidden from screen readers (its alt text is ""): the element's
   accessible name, a chart's label or an sr-only line says it. */
:where([data-tip]) { position: relative; }
[data-tip]:is(:hover, :focus-visible)::before, [data-tip]:has(:focus-visible)::before {
  content: attr(data-tip);
  content: attr(data-tip) / "";
  position: absolute; z-index: 40; left: 50%; bottom: calc(100% + 8px); transform: translateX(-50%);
  width: max-content; max-width: 280px; padding: 6px 10px; border-radius: 6px;
  background: var(--ink); color: var(--surface); box-shadow: var(--shadow-menu);
  font-size: var(--fs-12); font-weight: var(--w-ui); line-height: 1.45; letter-spacing: 0; text-align: left; text-transform: none; white-space: pre-line;
  pointer-events: none;
  animation: tip-in 120ms ease-out 150ms both;
}
@keyframes tip-in { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  [data-tip]:is(:hover, :focus-visible)::before, [data-tip]:has(:focus-visible)::before { animation: none; }
}

@media (max-width: 760px) {
  .facts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3) var(--s-4); }
  .facts > div { border: 0; margin: 0; padding: 0; }
  .facts dd { white-space: normal; }
  .facts--card { padding: var(--s-3) var(--s-4); }
  .card__head { padding: var(--s-3) var(--s-4); }
  .card__foot { padding: var(--s-3) var(--s-4); }
  .card__body { padding: var(--s-4); }
  .row-actions { flex-wrap: wrap; }
}

/* ── 13-result.css ── */
/* Result marks — #2745 step 3 (ported from ab-iteration/components.css § Result
   and widgets.css § result cell, day strip). One mark in three sizes, the
   result line and the day strip of same-size boxes. Colour + shape + word,
   always. */

:root {
  /* The ! and x cut into Warning and Fail marks. Masks, so the fill colour is
     irrelevant; health (Health over time) reuses them. */
  --mask-warn: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Crect x='3' y='0' width='2' height='5' rx='1'/%3E%3Ccircle cx='4' cy='7' r='1'/%3E%3C/svg%3E");
  --mask-fail: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath d='M1 1l6 6M7 1L1 7' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* ---------- Result: one mark, three sizes. Colour + shape + word, always. ---------- */
.glyph { width: 14px; height: 14px; display: inline-block; vertical-align: -2px; }
.g-ok { color: var(--ok); } .g-warn { color: var(--warn); } .g-fail { color: var(--fail); } .g-grey { color: var(--grey); } .g-none { color: var(--none); }
.badge {
  display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 8px 0 5px;
  border-radius: var(--r-pill); font-size: var(--fs-12); font-weight: var(--w-strong); line-height: 1; white-space: nowrap;
}
.badge--ok { background: var(--ok-tint); color: var(--ok-ink); }
.badge--warn { background: var(--warn-tint); color: var(--warn-ink); }
.badge--fail { background: var(--fail-tint); color: var(--fail-ink); }
.badge--grey { background: var(--grey-tint); color: var(--grey-ink); }
.badge--none { background: transparent; color: var(--ink-2); box-shadow: inset 0 0 0 1px var(--line-strong); }
/* A badge that opens something (All links: Reports on the link's runs) is the same pill. */
a.badge:hover { text-decoration: none; box-shadow: inset 0 0 0 1px currentColor; }
.word { display: inline-flex; align-items: center; gap: 6px; font-weight: var(--w-ui); white-space: nowrap; }
.tile { width: 40px; height: 40px; border-radius: 10px; display: grid; place-items: center; flex: none; }
.tile .glyph { width: 20px; height: 20px; }
.tile--fail { background: var(--fail-tint); } .tile--warn { background: var(--warn-tint); } .tile--grey { background: var(--grey-tint); } .tile--ok { background: var(--ok-tint); }
/* Not yet checked: an outline, like its badge (the mockup never drew this tile). */
.tile--none { background: transparent; box-shadow: inset 0 0 0 1px var(--line-strong); }
.tile--lg { width: 48px; height: 48px; border-radius: 12px; }
.tile--lg .glyph { width: 24px; height: 24px; }

/* Result line: badge + score base, then one line per reason. For Needs attention
   and the link pages; a table's result cell is the badge alone. */
.res { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.res__score { color: var(--ink-2); font-size: var(--fs-13); font-variant-numeric: tabular-nums; white-space: nowrap; }
.res__why { display: block; margin-top: 3px; color: var(--ink-2); font-size: var(--fs-13); line-height: 1.35; }
.res__note { color: var(--ink-2); } /* the Advanced note: as quiet as a reason, named for its hook */

/* ---------- Day strip: one box per day, every state the same size ----------
   Partner ruling 2026-10-17 (overrides the mockup's tall/low bars): state is
   carried only by colour, glyph or hatch. OK in the OK colour (the same token as
   every chart, ADR-0076 (c)), Warning and Fail solid with their glyph, Couldn't be measured hatched, no check a faint
   outline. Size the whole strip with --sc (box) and --sc-gap; state rules
   never set a size (result.test.ts holds this). */
.strip { --sc: 14px; --sc-gap: 3px; display: flex; align-items: center; gap: var(--sc-gap); }
.sc { position: relative; flex: none; width: var(--sc); height: var(--sc); border-radius: var(--r-cell); }
.sc--ok { background: var(--ok); }
.sc--none { box-shadow: inset 0 0 0 1px var(--none); }
.sc--warn { background: var(--warn); }
.sc--fail { background: var(--fail); }
.sc--grey { background: var(--grey-hatch); box-shadow: inset 0 0 0 1px var(--grey); }
.sc--warn::after, .sc--fail::after { content: ""; position: absolute; inset: 0; -webkit-mask: var(--m) center / 8px 8px no-repeat; mask: var(--m) center / 8px 8px no-repeat; }
.sc--warn::after { background: var(--on-warn); --m: var(--mask-warn); }
.sc--fail::after { background: var(--on-fail); --m: var(--mask-fail); }
/* A day that opens something (All links: Reports on the link's runs that day). */
a.sc:is(:hover, :focus-visible) { outline: 2px solid var(--ink); outline-offset: 1px; z-index: 2; }
.strip--mini { --sc: 10px; --sc-gap: 2px; }
.strip--mini .sc::after { -webkit-mask-size: 6px 6px; mask-size: 6px 6px; }
/* A phone (S-03: 30 days do not fit at 14 px): the strip keeps to its box. Every box
   shrinks alike and stays square, so it is still one size for every state. */
@media (max-width: 760px) {
  .sc { flex: 0 1 var(--sc); min-width: 0; height: auto; aspect-ratio: 1; }
  .strip .sc::after { -webkit-mask-size: 70% 70%; mask-size: 70% 70%; }
}
.legend { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); }
.legend > span { display: inline-flex; align-items: center; gap: 6px; }

/* ── 14-table.css ── */
/* Table — #2745 step 3 (ported from ab-iteration/components.css § Cards and
   tables). The base table; the tables family adds link tables, row actions and
   phone stacking. The wrapper scrolls rather than pushing the page sideways. */

.table-wrap { overflow-x: auto; }
/* A hover tip inside a table is drawn above its cell; the wrapper's clip lifts
   while one shows, so a tip in the first row is never cut off. */
.table-wrap:has([data-tip]:hover) { overflow: visible; }
.card > .table-wrap { border-radius: calc(var(--r-card) - 1px); }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-14); }
.table th { text-align: left; font-size: var(--fs-12); font-weight: var(--w-ui); color: var(--ink-2); padding: 9px 16px; background: var(--surface-2); border-bottom: 1px solid var(--line); white-space: nowrap; }
/* Under a card's banded head the column labels take the body's colour: one band per widget (#3101). */
.card:has(> .card__head) .table th { background: var(--surface); }
.table td { padding: 12px 16px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover td { background: var(--surface-2); }
.table .num { text-align: right; }
.table td.num { white-space: nowrap; }
.card > .table-wrap:first-child thead th:first-child { border-top-left-radius: calc(var(--r-card) - 1px); }
.card > .table-wrap:first-child thead th:last-child { border-top-right-radius: calc(var(--r-card) - 1px); }
.table__empty { padding-block: var(--s-6); text-align: center; color: var(--ink-2); }

/* ── 20-navigation.css ── */
/* 20-navigation — #2745 step 3.2 Navigation and shell (ported from
   ab-iteration/components.css § App header, § Page head, § Breadcrumb,
   § Footer, and widgets.css § Page flow). Header, tabs, Simple | Advanced,
   the Appearance popover, the switcher, the account and phone menus, the
   breadcrumb, the page head with the On-demand checks meter, the footer and
   the console page flow. Colours come from the role tokens only.

   The header lays itself out by its own width: it is a size container, and
   its narrow rules are container queries. In the console it is full width,
   so they track the viewport; in a narrow preview (the gallery's phone
   stage, the five-preset matrix) the header shows its phone layout too. */

/* ---------- App header ---------- */
.app-header {
  container: app-header / inline-size;
  /* Above the page, so its open menus are never painted under page content. */
  position: relative; z-index: 30;
  background: var(--header-bg); border-bottom: 1px solid var(--header-line); color: var(--header-ink);
  --focus: var(--header-focus);
}
.app-header .pop__panel { --focus: var(--accent); }
.app-header__bar { height: var(--header-h); display: flex; align-items: center; gap: var(--s-6); }
.brand { display: inline-flex; flex: none; align-items: center; gap: 10px; color: var(--header-ink); font-weight: var(--w-strong); font-size: var(--fs-15); letter-spacing: -0.01em; white-space: nowrap; }
.brand:hover { text-decoration: none; }
.brand__mark { display: block; flex: none; width: 20px; height: 20px; color: var(--header-ink); }
.brand__mark svg { display: block; width: 100%; height: 100%; }

.tabs { display: flex; align-self: stretch; gap: var(--s-1); }
.tabs a { display: flex; align-items: center; padding-inline: var(--s-3); color: var(--header-ink-2); font-weight: var(--w-ui); white-space: nowrap; box-shadow: inset 0 -2px 0 transparent; }
.tabs a:hover { color: var(--header-ink); text-decoration: none; }
.tabs a[aria-current="page"] { color: var(--header-ink); box-shadow: inset 0 -2px 0 var(--header-mark); }
.tabs a:focus-visible { outline-offset: -2px; }
/* #2974: a tab's tip (the old sidebar's sentence) is drawn under it: above would leave the window. */
.tabs a:is(:hover, :focus-visible)::before { bottom: auto; top: calc(100% + 4px); }
.app-header__end { margin-left: auto; min-width: 0; display: flex; align-items: center; gap: var(--s-3); }
/* If the header is ever too tight, only the workspace name gives way (an
   ellipsis); the product name, tabs and controls keep their size. */
.app-header__end > * { flex: none; }
.app-header__end > .switcher { flex: 0 1 auto; min-width: 0; }

/* Simple | Advanced: a POST form of two buttons, the pressed one raised */
.mode-form { display: flex; margin: 0; }
.mode { display: inline-flex; padding: 3px; gap: 2px; border-radius: var(--r-control); background: var(--header-control); }
.mode button {
  display: inline-flex; align-items: center; height: 26px; padding: 0 10px; border: 0; border-radius: 6px;
  background: none; color: var(--header-ink-2); font-size: var(--fs-13); font-weight: var(--w-ui); line-height: 1; white-space: nowrap; cursor: pointer;
}
.mode button:hover { color: var(--header-ink); }
.mode button[aria-pressed="true"] { background: var(--header-control-on); color: var(--header-control-on-ink); box-shadow: var(--header-control-shadow); }

/* Icon-only header control (the Appearance summary) */
.icon-btn { display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r-control); color: var(--header-ink-2); }
.icon-btn:hover, .appear[open] > .icon-btn { background: var(--header-control); color: var(--header-ink); }

/* Appearance popover: five presets, Light first, then Apply */
.appear .pop__panel { min-width: 232px; }
.appear__form { margin: 0; }
.appear__form fieldset { display: grid; gap: 2px; }
.appear__form legend { float: left; width: 100%; }
.appear__opt { clear: both; display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: 6px; font-weight: var(--w-ui); cursor: pointer; }
.appear__opt:hover { background: var(--surface-2); }
.appear__opt:has(input:checked) { background: var(--selected-tint); }
/* Radios drawn from tokens, scoped to this popover, so the header never
   depends on another family's control rules. */
.appear__opt input {
  appearance: none; width: 16px; height: 16px; margin: 0; flex: none; display: inline-grid; place-content: center; cursor: pointer;
  background: var(--control-bg); border: 1px solid var(--line-strong); border-radius: 50%;
}
.appear__opt input:hover { border-color: var(--ink-3); }
.appear__opt input:checked { background: var(--accent); border-color: var(--accent); }
.appear__opt input:checked::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--on-accent); }
.appear__opt input:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.appear__foot { display: flex; justify-content: flex-end; padding: 8px 4px 2px; margin-top: 6px; border-top: 1px solid var(--line); }
/* A preset swatch paints from that preset's own tokens (data-appearance). */
.sw { display: inline-block; width: 26px; height: 18px; flex: none; border-radius: 5px; overflow: hidden; background: var(--surface); box-shadow: inset 0 0 0 1px var(--line-strong); }
.sw i { display: block; height: 6px; background: var(--header-bg); box-shadow: inset 0 -1px 0 var(--header-line); }

/* Workspace switcher: text and chevron; the client heads its menu */
.switcher > summary { display: inline-flex; max-width: 100%; align-items: center; gap: 6px; height: 34px; padding: 0 6px 0 8px; border-radius: var(--r-control); font-size: var(--fs-13); white-space: nowrap; color: var(--header-ink); }
.switcher > summary:hover, .switcher[open] > summary { background: var(--header-control); }
.switcher > summary .icon { color: var(--header-ink-2); }
.switcher__workspace { min-width: 0; max-width: 220px; overflow: hidden; text-overflow: ellipsis; font-weight: var(--w-ui); }
/* Header menus size to their longest line (up to a cap) instead of wrapping in the trigger's width. */
.switcher .pop__panel, .account .pop__panel { width: max-content; max-width: min(360px, calc(100cqw - 32px)); }
/* An operator's client switcher under the workspaces (#2745 OP-02): the old top bar's select and Switch on one line */
.switcher__client { display: flex; align-items: center; gap: var(--s-2); padding: 4px 10px 6px; margin: 0; }
.switcher__client .select { flex: 1 1 auto; min-width: 0; height: 30px; font-size: var(--fs-13); }
.switcher__client .btn { flex: none; }

/* Account menu: initials */
.account > summary { border-radius: 50%; }
.avatar { width: 32px; height: 32px; border-radius: 50%; background: var(--header-control); color: var(--header-ink); display: grid; place-items: center; font-size: var(--fs-12); font-weight: var(--w-strong); }

/* Phone menu: replaces the tabs, Appearance, the switcher and the account menu */
.phone-menu { display: none; }
.phone-menu > summary { display: inline-grid; place-items: center; width: 36px; height: 36px; border-radius: var(--r-control); color: var(--header-ink); background: var(--header-control); }
.phone-menu .pop__panel { width: min(320px, calc(100cqw - 32px)); }
.phone-menu nav a[aria-current="page"] { background: var(--selected-tint); color: var(--selected-ink); }

/* The header needs about 1080 px with the name (plus the page margins): from
   1240 px it closes up, then shows the mark alone; the name stays the
   link's accessible name. */
@container app-header (max-width: 1239px) {
  .app-header__bar { gap: var(--s-5); }
}
@container app-header (max-width: 1219px) {
  .brand__name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@container app-header (max-width: 1120px) {
  .app-header__bar { gap: var(--s-4); }
}
@container app-header (max-width: 960px) {
  .tabs, .app-header__end > .appear, .app-header__end > .switcher, .app-header__end > .account { display: none; }
  .phone-menu { display: block; }
  .app-header__end { gap: var(--s-2); }
}

/* ---------- Breadcrumb ---------- */
.breadcrumb ol { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: var(--fs-13); color: var(--ink-2); }
.breadcrumb li + li::before { content: "›"; margin-right: 6px; color: var(--ink-3); }
.breadcrumb a { color: var(--ink-2); }
.breadcrumb a:hover { color: var(--ink); }
.breadcrumb [aria-current="page"] { color: var(--ink); font-weight: var(--w-ui); }

/* ---------- Page head: title over labelled facts, actions at the end ---------- */
.page-head .breadcrumb + .page-head__row { margin-top: var(--s-3); }
.page-head__row { display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap; min-height: 36px; } /* Advanced's filter summary never moves the page */
/* A title is at most two lines, cut with an ellipsis, the whole title in its tip (partner,
   2026-10-28): a page titled by a link with no name is titled by its URL, 3+ lines of it. */
.page-head h1 { min-width: 0; font-size: var(--fs-24); font-weight: var(--w-strong); letter-spacing: -0.02em; line-height: var(--lh-tight); overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
/* The cut clips at the box, and Inter's accented capitals (É) reach above the tight line: room above
   the first line, taken back by the margin, so the title does not move. */
.page-head h1 { padding-top: 0.1em; margin-top: -0.1em; }
.page-head__aside { margin-left: auto; min-width: 0; }
.page-head__lede { margin-top: var(--s-2); color: var(--ink-2); overflow-wrap: anywhere; } /* Edit link's lede is the link's name, an unnamed link's URL */
.page-head__actions { margin-left: auto; display: flex; gap: var(--s-2); flex-wrap: wrap; justify-content: flex-end; align-items: center; }
.page-head__aside + .page-head__actions { margin-left: 0; }

/* On-demand checks: the line over a thin neutral meter (never a result colour) */
.quota { display: grid; gap: 6px; min-width: 180px; }
.meter { display: block; height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.meter > span { display: block; width: var(--meter, 0%); height: 100%; border-radius: 3px; background: var(--ink-2); }

/* ---------- Footer ---------- */
.app-footer { border-top: 1px solid var(--line); padding: var(--s-5) 0 var(--s-6); color: var(--ink-2); font-size: var(--fs-13); }
.app-footer .container { display: flex; gap: var(--s-4); flex-wrap: wrap; justify-content: space-between; }

/* ---------- Console page flow ---------- */
.flow > * + * { margin-top: var(--s-5); }
.flow > .page-head + * { margin-top: var(--s-6); }

@media (max-width: 760px) {
  .flow > .page-head + * { margin-top: var(--s-5); }
  .page-head__actions { justify-content: flex-start; }
  .page-head__actions .btn--primary { order: -1; } /* the primary action first (design call 15) */
  .facts > div:has(.quota) { grid-column: 1 / -1; }
}

/* ── 30-forms.css ── */
/* 30-forms — #2745 step 3.3 Forms and controls. Ported from ab-iteration
   components.css § Inputs and widgets.css § Filter summary, § Links page
   (the toolbar) and § Settings. Colours come from the role tokens only.
   Field errors are drawn in ink with a mark, never red: red is only for a
   certain Fail result. Holds its own narrow-screen rules. */

/* ---------- Inputs and selects ---------- */
.input, .select {
  height: 36px; border: 1px solid var(--line-strong); border-radius: var(--r-control); background: var(--surface);
  padding: 0 12px; font-size: var(--fs-14); color: var(--ink); min-width: 0;
}
.input::placeholder { color: var(--ink-2); }
.textarea { height: auto; padding: 8px 12px; line-height: 1.5; resize: vertical; font-family: inherit; }
.input:focus-visible, .select:focus-visible { outline: 2px solid var(--focus); outline-offset: 0; border-color: var(--focus); border-radius: var(--r-control); }
.input:disabled, .select:disabled { background-color: var(--surface-2); border-color: var(--line); color: var(--ink-3); cursor: not-allowed; }
.select {
  appearance: none; padding-right: 32px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%), linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-size: 5px 5px; background-position: right 16px center, right 11px center; background-repeat: no-repeat;
}
.search { position: relative; display: flex; align-items: center; }
.search .icon { position: absolute; left: 11px; color: var(--ink-2); pointer-events: none; }
.search .input { padding-left: 34px; width: 100%; }
.search .input::-webkit-search-cancel-button { display: none; }

/* ---------- Fields: label, control, hint, error ---------- */
.field { display: grid; gap: 6px; max-width: 400px; }
.field .input, .field .select { width: 100%; }
.field__label { font-size: var(--fs-13); font-weight: var(--w-ui); color: var(--ink); }
legend.field__label { padding: 0; margin-bottom: var(--s-2); }
.field__hint { color: var(--ink-2); font-size: var(--fs-13); }
.field__error { display: flex; align-items: flex-start; gap: 6px; color: var(--ink); font-size: var(--fs-13); font-weight: var(--w-ui); }
.field__error::before {
  content: "!"; flex: none; display: inline-grid; place-items: center; width: 16px; height: 16px; margin-top: 1px;
  border-radius: 50%; background: var(--ink); color: var(--surface); font-size: var(--fs-11); font-weight: var(--w-strong); line-height: 1;
}
.field--error .input, .field--error .select { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.choice-group__options { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); }
.choice-group .field__error { margin-top: var(--s-2); }
.choice-group--error input[type="checkbox"]:not(:checked), .choice-group--error input[type="radio"]:not(:checked) { border-color: var(--ink); }

/* ---------- Checkboxes and radios, drawn from tokens ---------- */
.check { display: inline-flex; align-items: center; gap: var(--s-2); font-size: var(--fs-13); color: var(--ink); cursor: pointer; white-space: nowrap; }
.check:has(input:disabled) { color: var(--ink-2); cursor: not-allowed; }
/* A label with a lead or a note (#2745 step 5): its words wrap beside the box, top-aligned. */
.check--long { display: flex; align-items: flex-start; white-space: normal; line-height: 1.45; }
.check--long > input { margin-top: 2px; }
.check__note { color: var(--ink-2); }
input[type="checkbox"], input[type="radio"] {
  appearance: none; width: 16px; height: 16px; margin: 0; flex: none; display: inline-grid; place-content: center; cursor: pointer;
  background: var(--control-bg); border: 1px solid var(--line-strong); border-radius: 4px;
}
input[type="radio"] { border-radius: 50%; }
input[type="checkbox"]:hover, input[type="radio"]:hover { border-color: var(--ink-3); }
input[type="checkbox"]:checked, input[type="radio"]:checked { background: var(--accent); border-color: var(--accent); }
input[type="checkbox"]:checked::before, .tri:has(.tri__in[value="on"]:checked) .tri__box::before {
  content: ""; width: 10px; height: 10px; background: var(--on-accent);
  --tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M1.8 5.2 4 7.3 8.3 2.8' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  -webkit-mask: var(--tick) center / contain no-repeat; mask: var(--tick) center / contain no-repeat;
}
input[type="radio"]:checked::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--on-accent); }
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
input[type="checkbox"]:disabled, input[type="radio"]:disabled { cursor: not-allowed; background: var(--surface-3); border-color: var(--line-strong); }
input[type="checkbox"]:disabled:checked, input[type="radio"]:disabled:checked { background: var(--ink-3); border-color: var(--ink-3); }

/* A box some of Bulk edit's ticked links have (#2745 review, m 2026-10-23): three radios, each in
   its own label laid over one drawn box; only the next state's label takes the click, so a click
   cycles mixed → ticked → empty → mixed. Mixed is the modern "partly ticked" box (m 2026-10-24,
   design 2): a small filled accent square inside an accent-bordered box, never a tick; ticked and
   empty are drawn as a checkbox is. */
.tri { position: relative; }
.tri > .tri__face { display: flex; }
.tri__box {
  width: 16px; height: 16px; flex: none; display: inline-grid; place-content: center;
  background: var(--control-bg); border: 1px solid var(--line-strong); border-radius: 4px;
}
.check--long > .tri__box { margin-top: 2px; }
.tri__go { position: absolute; inset: 0; pointer-events: none; }
.tri:has(.tri__in[value="mixed"]:checked) .tri__go--on, .tri:has(.tri__in[value="on"]:checked) .tri__go--off, .tri:has(.tri__in[value="off"]:checked) .tri__go--mixed { pointer-events: auto; cursor: pointer; }
.tri__in { position: absolute; top: 0; left: 0; opacity: 0; }
.tri:hover .tri__box { border-color: var(--ink-3); }
.tri:has(.tri__in[value="on"]:checked) .tri__box { background: var(--accent); border-color: var(--accent); }
.tri:has(.tri__in[value="mixed"]:checked) .tri__box { background: var(--control-bg); border-color: var(--accent); }
.tri:has(.tri__in[value="mixed"]:checked) .tri__box::before { content: ""; width: 8px; height: 8px; border-radius: 2px; background: var(--accent); }
.tri:has(.tri__in:focus-visible) .tri__box { outline: 2px solid var(--focus); outline-offset: 2px; }
/* Which of the links have it (m 2026-10-24): the console's hover tip (12-primitives.css, data-tip),
   shown on hover and while a radio has the keyboard focus, hangs over the box rather than the
   middle of its row; a long name (a tracking URL) breaks inside itself. */
.tri:is(:hover, :has(.tri__in:focus-visible))::before { left: -6px; transform: none; overflow-wrap: anywhere; }

/* ---------- Filter bar (Links): the sort control keeps the first row; filters wrap before it does ---------- */
.toolbar-row { display: flex; align-items: flex-start; gap: var(--s-2) var(--s-4); }
.toolbar-row > .toolbar { flex: 1 1 auto; min-width: 0; }
.toolbar-row .sort { flex: none; margin: 3px 0 0 auto; }
/* A view switch (Link Admin's "Show archived links", #2788): a plain link before the sort. */
.toolbar-row .toolbar-switch { flex: none; margin-top: 3px; }
.toolbar, .filterbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
.filter { display: block; min-width: 0; }
.filter .select { width: 136px; }
.toolbar .search { width: 260px; }
.filterbar .filter .select { width: 132px; }
/* Advanced adds four filters: the Simple ones tighten so the row still fits. */
.toolbar:has(.filter--adv) .search { width: 200px; }
.toolbar:has(.filter--adv) .filter .select { width: 108px; }
/* A chosen value is never clipped: the select grows to its text (Chromium), keeping the widths above as minimums. */
@supports (field-sizing: content) {
  .filter .select { field-sizing: content; width: auto; min-width: 136px; max-width: 240px; }
  .filterbar .filter .select { width: auto; min-width: 132px; }
  .toolbar:has(.filter--adv) .filter .select { width: auto; min-width: 108px; }
}

/* ---------- Filter summary (Advanced): labelled values + Edit filters over the GET form ---------- */
.fsum { position: relative; margin-left: auto; width: max-content; max-width: 100%; }
.fsum > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: var(--s-4); height: 36px; padding: 0 6px 0 12px;
  border: 1px solid var(--line-strong); border-radius: var(--r-control); background: var(--surface); font-size: var(--fs-13); white-space: nowrap; box-shadow: var(--shadow-card);
}
.fsum > summary::-webkit-details-marker { display: none; }
.fsum > summary .icon { color: var(--ink-2); }
.fsum__k { color: var(--ink-2); }
.fsum__edit { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 8px; border-radius: 6px; background: var(--surface-3); color: var(--ink); font-weight: var(--w-ui); }
.fsum[open] > summary { border-color: var(--focus); }
.fsum .filterbar {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 15; width: max-content; max-width: min(760px, calc(100vw - 32px));
  padding: var(--s-3); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--shadow-menu);
}

/* ---------- Sort control: "Sort by: <current>" over a menu of links ---------- */
.sort > summary b { color: var(--ink); font-weight: var(--w-strong); }
.sort[open] > summary { background: var(--surface-3); color: var(--ink); }
.sort .pop__panel { min-width: 200px; }

/* ---------- Settings: Appearance and Detail level as radio cards ---------- */
.settings { margin-top: var(--s-5); }
.set-section { padding-block: var(--s-5) var(--s-6); border-top: 1px solid var(--line); }
.set-section:first-of-type { border-top: 0; padding-top: 0; }
.set-section legend { float: left; width: 100%; padding: 0; font-size: var(--fs-15); font-weight: var(--w-strong); }
.set-section__desc { clear: both; padding-top: 4px; color: var(--ink-2); }
.set-section__now { padding-top: var(--s-3); font-weight: var(--w-ui); }
.set-section > .field { margin-top: var(--s-4); }
.choice-grid { display: grid; gap: var(--s-4); }
.set-section .choice-grid, .choice-grid + .choice-grid { margin-top: var(--s-4); }
/* Five presets as 3 + 2: the light family on the first row, the dark family on the second. */
.choice-grid--presets { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.choice-grid--presets > .choice { grid-column: span 2; }
.choice-grid--presets > .choice:nth-child(n + 4) { grid-column: span 3; }
.choice-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.choice {
  position: relative; display: grid; align-content: start; gap: var(--s-3); padding: var(--s-3);
  border: 1px solid var(--line-strong); border-radius: var(--r-card); background: var(--surface); cursor: pointer; box-shadow: var(--shadow-card);
}
.choice:hover { border-color: var(--ink-3); }
.choice:has(input:checked) { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.choice:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 2px; }
.choice input:focus-visible { outline: none; } /* the card carries the ring */
.choice:has(input:disabled) { cursor: not-allowed; background: var(--surface-2); border-color: var(--line); box-shadow: none; }
.choice:has(input:disabled) .choice__name { color: var(--ink-2); }
.choice__row { display: flex; align-items: flex-start; gap: 10px; }
.choice__row input { margin-top: 2px; }
.choice__name { font-weight: var(--w-strong); }
.choice__desc { display: block; margin-top: 2px; color: var(--ink-2); font-size: var(--fs-13); line-height: 1.4; }
.choice--detail { padding: var(--s-4); }
/* Save stays in reach: a bar along the bottom of the window while the form is on screen.
   It is the form's full width and sits flush with the window's edge on the page ground,
   so text scrolls under its top line like under any page edge, never beside or below it
   (pre-review QA 28b: a floating group at the right covered the end of the Detail level
   text while the rest of the line showed). */
.set-actions {
  position: sticky; bottom: 0; z-index: 5; display: flex; justify-content: flex-end; gap: var(--s-2); margin-top: var(--s-4);
  padding: var(--s-3) 0; background: var(--ground); border-top: 1px solid var(--line-strong);
}

/* Preset preview: a small console drawn with that preset's own tokens. */
.pv { display: grid; grid-template-rows: 26px 1fr; height: 196px; overflow: hidden; border-radius: 8px; background: var(--ground); border: 1px solid var(--line); }
.pv__bar { display: flex; align-items: center; gap: 8px; padding: 0 12px; background: var(--header-bg); border-bottom: 1px solid var(--header-line); }
.pv__bar i { width: 16px; height: 9px; border-radius: 2px; background: var(--header-ink); }
.pv__bar b { width: 34px; height: 4px; border-radius: 2px; background: var(--header-ink-2); opacity: 0.8; }
.pv__bar b:first-of-type { background: var(--header-mark); opacity: 1; }
.pv__bar u { margin-left: auto; width: 44px; height: 12px; border-radius: 4px; background: var(--header-control); }
.pv__body { padding: 12px; display: grid; gap: 10px; align-content: start; }
.pv__card, .pv__rows { background: var(--surface); border: 1px solid var(--line); border-radius: 7px; box-shadow: var(--shadow-card); }
.pv__card { padding: 12px; display: grid; gap: 9px; }
.pv__score { display: flex; align-items: center; gap: 10px; }
.pv__score b { width: 40px; height: 16px; border-radius: 3px; background: var(--ink); }
.pv__score s { width: 80px; height: 5px; border-radius: 3px; background: var(--ink-2); opacity: 0.6; }
.pv__score em { margin-left: auto; width: 48px; height: 16px; border-radius: 5px; background: var(--primary); }
.pv__ruler { display: grid; grid-template-columns: 20fr 3fr 2fr 4px 3fr; gap: 2px; height: 8px; }
.pv__ruler span:nth-child(1) { background: var(--ok); border-radius: 3px 0 0 3px; }
.pv__ruler span:nth-child(2) { background: var(--warn); }
.pv__ruler span:nth-child(3) { background: var(--fail); border-radius: 0 3px 3px 0; }
.pv__ruler span:nth-child(5) { background: var(--grey-hatch); border-radius: 3px; }
.pv__rows > span { display: flex; align-items: center; gap: 8px; height: 22px; padding: 0 12px; border-bottom: 1px solid var(--line); }
.pv__rows > span:last-child { border-bottom: 0; }
.pv__dot { width: 9px; height: 9px; border-radius: 50%; }
.pv__dot--fail { background: var(--fail); }
.pv__dot--warn { background: var(--warn); }
.pv__dot--ok { background: var(--ok); }
.pv__rows s { width: 110px; height: 5px; border-radius: 3px; background: var(--ink-2); opacity: 0.6; }
.pv__rows u { margin-left: auto; width: 34px; height: 5px; border-radius: 3px; background: var(--link); }

/* ---------- Narrow screens ---------- */
@media (max-width: 960px) {
  .pv { height: 168px; }
}
@media (max-width: 760px) {
  .toolbar-row { flex-wrap: wrap; }
  .toolbar-row > .toolbar { flex-basis: 100%; }
  .toolbar-row .sort { margin: 0; }
  /* Here the sort control starts the row, so its menu opens from its left edge, on the screen. */
  .toolbar-row .sort .pop__panel { right: auto; left: 0; }
  .toolbar { display: grid; grid-template-columns: 1fr 1fr; width: 100%; }
  .toolbar .search, .toolbar:has(.filter--adv) .search { grid-column: 1 / -1; width: 100%; }
  .toolbar .filter .select, .toolbar:has(.filter--adv) .filter .select { width: 100%; min-width: 0; max-width: none; field-sizing: fixed; }
  .toolbar .btn--link { justify-self: start; }
  .fsum { margin-left: 0; width: 100%; }
  .fsum > summary { white-space: normal; height: auto; padding: 8px 6px 8px 12px; flex-wrap: wrap; gap: 4px 12px; }
  .fsum .filterbar { left: 0; right: 0; width: auto; max-width: none; }
  .choice-grid--presets, .choice-grid--2 { grid-template-columns: 1fr; }
  .choice-grid--presets > .choice, .choice-grid--presets > .choice:nth-child(n + 4) { grid-column: auto; }
  .pv { height: 180px; }
  .field { max-width: none; }
}

/* ── 40-tables.css ── */
/* 40-tables — #2745 step 3.4 Tables and lists (ported from ab-iteration
   widgets.css § Link tables, § Links page, § Narrow screens). Link and result
   cells, Status, Schedule, Last checked, the select column, countries and
   devices, the Last 30 days column, row actions under the name, phone stacking
   and the empty list. Colours come from the role tokens only.

   Partner rulings 2026-10-17: a result cell is the badge alone; row actions are
   the foundation's inline buttons, never a menu; every strip and legend box is
   one size (the strip is resized only through --sc and --sc-gap).

   Columns are sized by content (design call 4, after the badge-only ruling):
   the fact columns read as one cluster on the right; the slack goes to Link in
   both modes (#2745 step 3.7 critique). All links takes each fact column's width
   from its content (Gate 3 review 2026-10-19, G-01: fixed widths left Last
   checked short, so the table scrolled sideways); Link Admin keeps fixed widths,
   its row actions in a last column on two lines (R-05, 2026-10-21).

   Card 4 (partner, 2026-10-22): Link Admin shows Country, Devices and the device
   key at every width, and gains the room from its row actions: at 1100 px and
   below each is its icon alone. Should a row still not fit, the table scrolls
   sideways inside its card (.table-wrap), never the page. */

/* ---------- Cells ---------- */
/* A name is at most two lines inside its cell, cut with an ellipsis, the whole name in its
   tip (partner, 2026-10-28): a link with no name is named by its URL, one unbroken word that
   ran over the next columns of Link Admin's fixed table. */
.lname { color: var(--ink); font-weight: var(--w-ui); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
a.lname:hover { color: var(--link); }
.lhost { display: block; margin-top: 2px; color: var(--ink-2); font-size: var(--fs-12); font-weight: var(--w-ui); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* An archived link (#2788, "Show archived links" on): a quiet neutral label under its name,
   never a Status and never a result colour. */
.larchived { display: block; width: fit-content; margin-top: 4px; padding: 0 6px; border: 1px dashed var(--line-strong); border-radius: 5px; color: var(--ink-2); font-size: var(--fs-11); font-weight: var(--w-strong); line-height: 18px; white-space: nowrap; }
/* A competitor link (#3021, ADR-0069 §a): "Subject: a competitor benchmark", a quiet line under
   its name in both modes, as the retired link page said it. */
.lsubject { display: block; margin-top: 2px; color: var(--ink-2); font-size: var(--fs-12); font-weight: var(--w-ui); }
/* Link Admin, Advanced (#2975): the placement under the host, as quiet as the host, cut to two
   lines as a name is, the whole placement in its tip (a page's URL is often one long word). */
.lplace { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; margin-top: 2px; color: var(--ink-2); font-size: var(--fs-12); font-weight: var(--w-ui); }
.when { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--ink); font-size: var(--fs-13); }
/* A schedule word wraps between its words: a link kept on an older cadence says its own
   (Every 12 hours, LA-04), and the column stays its width. */
.sched { color: var(--ink); font-size: var(--fs-13); }
.sched--none { color: var(--ink-3); }
.when--note { white-space: normal; color: var(--ink-2); }
/* Link Admin: a check running now opens its live progress page (RP-13), ink at rest like a name. */
a.when:hover { color: var(--link); }
/* A link the scheduler holds (#1625): a neutral chip under its schedule, its reason in the
   hover tip. Never a result colour and never a Status. */
.held { display: block; width: fit-content; margin-top: 4px; padding: 0 6px; border: 1px dashed var(--line-strong); border-radius: 5px; color: var(--ink-2); font-size: var(--fs-11); font-weight: var(--w-strong); line-height: 18px; white-space: nowrap; }
.cellbox { display: inline-block; width: 62px; text-align: left; }
.select-box { display: block; width: 16px; height: 16px; margin: 2px 0 0; accent-color: var(--accent); cursor: pointer; }

/* Country (code chips, two to a line) and Devices (four fixed slots): two columns. */
.codes { display: inline-flex; flex-wrap: wrap; gap: 3px; }
.codes .code { min-width: 26px; }
.codes--none { color: var(--ink-3); }
.slots { display: inline-flex; gap: 2px; }
.slot { display: inline-grid; color: var(--line-strong); }
.slot--on { color: var(--ink); }
.slot .icon, .device-key .icon { width: 14px; height: 14px; }

/* Last 30 days: the head names the window only (S-02); each box's tip carries its date. */
.strip-head { font-size: var(--fs-12); font-weight: var(--w-ui); color: var(--ink-2); }
.table-keys { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--s-2) var(--s-5); width: 100%; }

/* ---------- Link tables ---------- */
.linktable { table-layout: fixed; }
/* #2905: Link Admin's Link and Last checked headers sort the list: the header's ink, a chevron on the sorted one. */
.th-sort { display: inline-flex; align-items: center; gap: 6px; color: inherit; text-decoration: none; }
.th-sort:hover { color: var(--ink); text-decoration: underline; }
.th-sort:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 2px; }
th[aria-sort] .th-sort { color: var(--ink); font-weight: var(--w-strong); }
th[aria-sort] .th-sort::after { content: ''; width: 5px; height: 5px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); }
th[aria-sort="ascending"] .th-sort::after { transform: translateY(1px) rotate(-135deg); }
.linktable .c-link { width: auto; } /* Link takes the slack in both tables */
.linktable td { padding-block: 11px; }
.linktable .td-status { text-align: right; }
.linktable .strip { --sc: var(--day); --sc-gap: var(--day-gap); }
/* All links' Latest result: the badge alone, on one line. */
.linktable .c-result { width: auto; }
.linktable .td-result { white-space: nowrap; }

/* All links (Link Health): every fact column shrinks to its widest value on one
   line, and Link takes the rest, so the table always fits its card and never
   scrolls sideways; a long name wraps inside Link. */
.linktable--health { --day: 14px; --day-gap: 3px; table-layout: auto; }
.linktable--health .td-link { overflow-wrap: anywhere; }
@media (min-width: 761px) {
  .linktable--health :is(th, td):not(.td-link) { width: 1px; white-space: nowrap; }
}

/* Link Admin: denser cells, every value on the name's first line; the row
   actions in the last column, on two lines. */
.linktable--manage { --day: 10px; --day-gap: 2px; }
.linktable--manage th, .linktable--manage td { padding-inline: 8px; }
.linktable--manage td { padding-block: 8px; vertical-align: top; }
.linktable--manage th:first-child, .linktable--manage td:first-child { padding-left: 16px; }
.linktable--manage th:last-child, .linktable--manage td:last-child { padding-right: 16px; }
@media (min-width: 961px) {
  .linktable--manage .td-country, .linktable--manage .td-devices { padding-top: 9px; }
  .linktable--manage .td-status, .linktable--manage .td-schedule, .linktable--manage .td-when { padding-top: 9px; }
  .linktable--manage .td-select { padding-right: 4px; }
}
.linktable--manage .c-select { width: 36px; }
.linktable--manage .c-country { width: 80px; }
.linktable--manage .c-devices { width: 80px; }
.linktable--manage .c-status { width: 78px; }
.linktable--manage .c-schedule { width: 69px; }
.linktable--manage .c-when { width: 108px; }
/* Three 92 px buttons a line, 6 px apart, plus the cell's padding (S-01). */
.linktable--manage .c-actions { width: 312px; }

/* ---------- Empty list ---------- */
.empty-list { display: grid; justify-items: center; gap: var(--s-2); padding: var(--s-6) var(--s-4); text-align: center; }
.empty-list__title { font-size: var(--fs-15); font-weight: var(--w-strong); }
.empty-list__text { max-width: 46ch; color: var(--ink-2); }
.empty-list .btn { margin-top: var(--s-2); }

/* ---------- Narrow screens ---------- */
@media (max-width: 1100px) {
  .linktable--health { --day: 10px; } /* All links shrinks its strip */
  /* Link Admin's row actions show their icon alone (Card 4): each an equal 30 px square in
     its own border (S-01), three to a line, its label resting only visually (its accessible
     name, "Run now: <link>", still starts with it) and drawn as the hover tip. */
  .linktable--manage .c-actions { width: 126px; } /* three squares 6 px apart, plus the cell's padding */
  .linktable--manage .row-actions--lines .row-actions__btn { width: 30px; min-width: 0; padding-inline: 0; }
  .linktable--manage .row-actions__label { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .linktable--manage .row-actions .row-actions__btn:is(:hover, :focus-visible)::before { content: attr(data-tip); content: attr(data-tip) / ""; }
  /* A button with its own sentence (LA-03) draws its label first, then the sentence. */
  .linktable--manage .row-actions .row-actions__btn[data-label]:is(:hover, :focus-visible)::before { content: attr(data-label) "\A" attr(data-tip); content: attr(data-label) "\A" attr(data-tip) / ""; }
  /* Set countries and devices (LA-13) has no icon: its label stays, wrapping inside the
     column, and its tip is the sentence alone. */
  .linktable--manage .row-actions--lines .row-actions__btn--remedy { width: auto; height: auto; min-height: 30px; padding: 4px 8px; white-space: normal; text-align: start; line-height: 1.3; }
  .linktable--manage .row-actions__btn--remedy .row-actions__label { position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; white-space: normal; }
  .linktable--manage .row-actions .row-actions__btn--remedy[data-label]:is(:hover, :focus-visible)::before { content: attr(data-tip); content: attr(data-tip) / ""; }
}
@media (min-width: 761px) and (max-width: 960px) {
  .linktable--health .c-strip, .linktable--health .td-strip { display: none; }
}

/* Rows stack into cards: Link Admin at <= 960 px, All links at <= 760 px. Name
   first, then the facts inline, each named (Link Admin: Country, Devices, Status,
   Schedule and Last checked; All links: the result, Status and Last checked), so a
   phone reads one link at a time with nothing off to the side. On Link Admin the row
   is a wrapping flex line and the link cell lets its parts join it, so the two lines
   of icon buttons close the card. */
@media (max-width: 960px) {
  .linktable--manage thead { display: none; }
  .linktable--manage, .linktable--manage tbody, .linktable--manage td { display: block; width: auto; }
  .linktable--manage tr { position: relative; display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px var(--s-4); padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
  .linktable--manage tbody tr:last-child { border-bottom: 0; }
  .linktable--manage td, .linktable--manage td:first-child, .linktable--manage td:last-child { padding: 0; border: 0; text-align: left; }
  .linktable--manage .td-link { display: contents; }
  .linktable--manage .lname, .linktable--manage .lsubject, .linktable--manage .lhost, .linktable--manage .lplace { flex: 1 0 100%; min-width: 0; }
  .linktable--manage .lsubject, .linktable--manage .lhost, .linktable--manage .lplace { margin-top: -4px; }
  .linktable--manage .td-select + .td-link > :is(.lname, .lsubject, .lhost, .lplace) { padding-left: 28px; }
  .linktable--manage .larchived { flex: none; margin-top: -2px; }
  .linktable--manage .td-select + .td-link > .larchived { margin-left: 28px; }
  .linktable--manage .td-actions { order: 1; flex: 1 0 100%; margin-top: 4px; }
  .linktable--manage td[data-k]::before { content: attr(data-k); margin-right: 6px; color: var(--ink-2); font-size: var(--fs-12); }
  .linktable--manage .cellbox { width: auto; }
  .linktable--manage tbody tr:hover td { background: none; }
  .linktable--manage .td-select { position: absolute; left: var(--s-4); top: var(--s-3); }
}
@media (max-width: 760px) {
  .linktable--health thead { display: none; }
  .linktable--health, .linktable--health tbody, .linktable--health tr, .linktable--health td { display: block; width: auto; }
  .linktable--health tr { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
  .linktable--health tbody tr:last-child { border-bottom: 0; }
  .linktable--health td { padding: 0; border: 0; text-align: left; }
  .linktable--health td + td { margin-top: 6px; }
  .linktable--health .td-inline { display: inline-block; margin-right: var(--s-4); }
  .linktable--health td[data-k]::before { content: attr(data-k); margin-right: 6px; color: var(--ink-2); font-size: var(--fs-12); }
  .linktable--health .cellbox { width: auto; }
  .linktable--health tbody tr:hover td { background: none; }
  .table-keys { justify-content: flex-start; }
  .empty-list { padding-block: var(--s-5); }
}

/* ── 45-link-forms.css ── */
/* 45-link-forms — #2745 step 5: Link Admin's forms (ui/widgets/link-forms): Edit link,
   Countries and devices, Archive this link?. Each section is a card in one column; the
   country + device grid lays its boxes in columns, and a box with a note keeps a whole
   row. Colours come from the role tokens only: a refusal is the amber notice, never red.
   Holds its own narrow-screen rules. */

.lform { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }
.lform__body > * { margin-top: 0; }
.lform__body > * + * { margin-top: var(--s-4); }
.lform__desc { color: var(--ink-2); max-width: 72ch; }
.lform__desc strong { color: var(--ink); }
/* A link inside a sentence is told apart by more than its colour (axe link-in-text-block). */
.lform__body p a:not(.btn), .lform__body li a:not(.btn) { text-decoration: underline; text-underline-offset: 2px; }
/* A link inside a sentence is underlined, so it reads as a link without its colour. */
.lform__prose a { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.lform__fields { display: grid; gap: var(--s-4); }
.lform__fields .field { max-width: 520px; }
.lform__choices { display: grid; gap: var(--s-2); }

/* The tracking URL as stored: whole, wrapping anywhere rather than overflowing. */
.lform__url code { display: block; padding: var(--s-2) var(--s-3); border: 1px solid var(--line); border-radius: var(--r-control); background: var(--surface-2); overflow-wrap: anywhere; font-size: var(--fs-13); }
.lform__subject { font-size: var(--fs-15); overflow-wrap: anywhere; }
.lform__effects { display: grid; gap: var(--s-2); padding-left: var(--s-5); list-style: disc; }

.lform .btn[disabled] { opacity: 0.45; cursor: not-allowed; } /* as Customise's (60-health.css) */
.lform__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s-2); }

/* The country + device grid */
.cov { display: grid; gap: var(--s-5); }
.cov__group { min-width: 0; }
.cov__boxes { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s-3) var(--s-5); }
.cov__wide { grid-column: 1 / -1; }

/* Add a link (#2745 step 5): the step indicator, the link type, the review's summary and count */
.steps { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); margin: var(--s-2) 0 var(--s-5); padding: 0; list-style: none; color: var(--ink-2); font-size: var(--fs-13); }
.steps__item { display: inline-flex; align-items: center; gap: var(--s-2); }
.steps__n { display: inline-grid; place-items: center; width: 22px; height: 22px; border: 1px solid var(--line-strong); border-radius: 50%; font-size: var(--fs-12); font-variant-numeric: tabular-nums; }
.steps__item--done .steps__n { border-color: var(--ink-2); }
.steps__item--now { color: var(--ink); font-weight: var(--w-ui); }
.steps__item--now .steps__n { background: var(--ink); border-color: var(--ink); color: var(--surface); }
.lform__type { min-width: 0; }
.lform__type .choice-grid { margin-top: var(--s-2); }
.lform__slug { padding: 1px 6px; border-radius: 4px; background: var(--surface-3); color: var(--ink-2); font-size: var(--fs-12); font-weight: var(--w-text); }
.lform__summary { display: grid; grid-template-columns: max-content minmax(0, 1fr); border-top: 1px solid var(--line); }
.lform__summary > div { display: contents; }
.lform__summary dt, .lform__summary dd { padding: var(--s-2) 0; border-bottom: 1px solid var(--line); }
.lform__summary dt { padding-right: var(--s-5); color: var(--ink-2); }
.lform__summary dd { overflow-wrap: anywhere; }
.lform__note { color: var(--ink-2); }
.lform__fanout { display: flex; align-items: flex-start; gap: var(--s-4); padding: var(--s-3) var(--s-4); border: 1px solid var(--line); border-radius: var(--r-card); background: var(--surface-2); }
.lform__fanout-n { font-size: var(--fs-24); font-weight: var(--w-strong); line-height: 1; font-variant-numeric: tabular-nums; }

/* Import links and Preview import (#2745 step 5) */
.lform__file { height: auto; padding: 6px; }
.lform__list { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); padding: 0; list-style: none; }
.lform__body h3 { font-size: var(--fs-14); font-weight: var(--w-strong); }
.lform__groupnote { padding-bottom: var(--s-3); }
.lform__table .lform__col-check { width: 44px; }
.lform__table .input { width: 100%; min-width: 160px; }
.lform__code { font-size: var(--fs-13); overflow-wrap: anywhere; }
.lform__row--quiet td { color: var(--ink-2); }
.lform__foot { display: grid; gap: var(--s-3); }
/* #2977: Import preview counts the ticked rows as they are ticked, with no script, as Bulk edit's bar does (#2744).
   The number sits in text beside Save, never in the button: Chromium drops a counter from a button's name. */
.limport { counter-reset: ticked; }
.limport .lform__table input[type="checkbox"]:checked { counter-increment: ticked; }
.limport__count { margin-right: auto; align-self: center; color: var(--ink-2); }
.limport__ticked::after { content: " (" counter(ticked) ")"; }
.lform__foot .lform__desc { max-width: none; }
/* Bulk edit (#2745 step 5): the filter, the count and Select all, the list, the actions;
   the preview's links, its new value and Archive's confirm (neutral ink, never red). */
/* One toolbar row (#2744): the filter, then the count and Select all at its right end, as
   Link Admin's sort control sits (30-forms.css .toolbar-row); on a phone they wrap under it. */
.lbulk__toolbar { margin-bottom: var(--s-4); }
.lbulk__match { flex: none; align-self: center; margin-left: auto; }
.lbulk { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); counter-reset: ticked; }
/* How many links are ticked (#2744), with no script: each ticked box counts, and the action
   bar under the list says the sum. Without the stylesheet it reads "With ticked links:". */
.lbulk .select-box:checked { counter-increment: ticked; }
.lbulk__ticked::after { content: " (" counter(ticked) ")"; }
/* Archive, the destructive action, at the bar's far end, apart from the others (#2744). */
.lbulk__apart { display: flex; margin-left: auto; }
.lbulk__match, .lbulk__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-3); }
.lbulk__count { font-weight: var(--w-ui); }
.lbulk__actions { position: sticky; bottom: 0; z-index: 5; padding: var(--s-3) 0; background: var(--ground); border-top: 1px solid var(--line-strong); }
/* From 600 px up the bar is sticky at the bottom of the window: a tick box the keyboard moves
   to is scrolled clear of it (WCAG 2.4.11, #2964), by the bar's height at each width (one line
   from 1280 px, two from 600). On the boxes, not the page, so nothing else scrolls differently.
   A pointer reaches every row anyway: at the end the bar sits under the last. Below 600 px
   (partner, 2026-10-29, #2982) its actions wrap to four lines, so it is not pinned: it sits
   after the list, with full labels, and covers nothing while the list scrolls. */
.lbulk .select-box { scroll-margin-bottom: 5rem; }
@media (max-width: 1279px) { .lbulk .select-box { scroll-margin-bottom: 8rem; } }
@media (max-width: 599px) {
  .lbulk__actions { position: static; }
  .lbulk .select-box { scroll-margin-bottom: 0; }
}
/* The list is Link Admin's table (40-tables.css .linktable--manage, #2744) plus Tags, whose
   chips wrap inside the column; the slack goes to Link. */
.lbulk .linktable--manage .c-tags { width: 150px; }
.lbulk__url { display: block; max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-2); font-size: var(--fs-13); }
/* The whole URL on hover, "so truncation hides nothing" (#1640, LF-31): the tip hangs from a
   wrapper, since the cut-short URL clips anything drawn from it, and wraps anywhere. */
.lbulk__tip { display: block; width: fit-content; max-width: 100%; }
.lbulk__tip:is(:hover, :focus-visible)::before { overflow-wrap: anywhere; max-width: min(420px, 80vw); }
.lbulk__table td { vertical-align: top; }
.lbulk__affected { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-3); margin-bottom: var(--s-5); }
.lbulk__confirm { display: grid; gap: var(--s-3); padding: var(--s-4); border: 1px solid var(--line-strong); border-radius: var(--r-card); background: var(--surface); }

/* Tags' chips sit on the name's first line, as Country's do (40-tables.css). */
@media (min-width: 961px) {
  .lbulk .linktable--manage .td-tags { padding-top: 9px; }
}
/* Rows stack into cards at Link Admin's width: the cut-short URL takes its own line under the
   name, clear of the box. */
@media (max-width: 960px) {
  .lbulk .linktable--manage .td-link > .lbulk__tip { flex: 1 0 100%; margin-top: -4px; padding-left: 28px; }
}
@media (max-width: 760px) {
  .lbulk__match { margin-left: 0; }
  .lbulk__url { max-width: 200px; }
  .lform { gap: var(--s-4); }
  .cov__boxes { grid-template-columns: 1fr; }
  .lform__actions { justify-content: stretch; }
  .lform__actions > .btn { flex: 1 1 auto; justify-content: center; }
}

/* ── 50-evidence.css ── */
/* 50-evidence — #2745 step 3.5 Audit evidence: the head, the result facts,
   the screenshots, the steps, Other checks in this run, and the Advanced-only
   Earlier checks, Cookies, Configuration and Technical details (the Redirect
   chain is 56-evidence-chain.css, #2793). Ported from ab-iteration/widgets.css § Audit evidence. Every class
   is ev-*, so no other family's rule can reach it. Colours come from the role
   tokens only. Holds its own narrow-screen rules (at the end).
   #2947 (the partner: "it reads very badly overall"): one column at every width, no
   side-by-side panes; one type scale (section titles and the result 15 bold, body
   text 14, labels 12 in --ink-2 at regular weight); and every quoted URL a full-width
   line of its own under its label, 12 (a step under the body text, partner 2026-10-28),
   breaking anywhere, never cut and never squeezed into a label/value column. */

/* ---------- A quoted URL (#2947): whole, on a line of its own, breaking anywhere ---------- */
.ev-url-line, .ev-carried code.ev-url-line, .ev-carried code.break-all, .ev-carried td.break-all > code {
  display: block; max-width: 100%; font-family: inherit; font-size: var(--fs-12); font-weight: var(--w-text); line-height: var(--lh-ui);
  color: var(--ink); white-space: normal; word-break: normal; overflow-wrap: anywhere;
}
/* Quoted URLs under their labels: label, then the URL's own line. */
.ev-urls { display: grid; gap: var(--s-2); min-width: 0; }
.ev-urls dt { color: var(--ink-2); font-size: var(--fs-12); }
.ev-urls dd { min-width: 0; }

/* ---------- Head: tile, link name and its country · device, Re-check; then the facts ---------- */
.ev-head { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--s-4); align-items: start; }
.ev-head__text { min-width: 0; }
.page-head .breadcrumb + .ev-head { margin-top: var(--s-4); }
.ev-head__title { font-size: var(--fs-24); font-weight: var(--w-strong); letter-spacing: -0.02em; line-height: 1.2; }
.ev-head__place { margin-top: 4px; color: var(--ink-2); }
.ev-head__act { display: grid; gap: var(--s-2); justify-items: end; }
.ev-place__browser { white-space: nowrap; }
/* The head's facts: values at the body weight (the result's badge keeps its own); a
   quoted URL takes the full width under its label, so it never pushes a fact beside it. */
.ev-head + .facts { row-gap: var(--s-3); }
.ev-head + .facts dd { font-weight: var(--w-text); }
.ev-head + .facts dd:has(> .ev-url-line) { white-space: normal; }
.ev-head + .facts > div:has(.ev-url-line) { flex: 1 0 100%; min-width: 0; }
.ev-head + .facts > div:has(.ev-url-line), .ev-head + .facts > div:has(+ div .ev-url-line) { margin-right: 0; padding-right: 0; border-right: 0; }

/* The evidence page's result grammar: the badge, then the reason on the same line. */
.ev-res { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s-2); }
.ev-res__reason { color: var(--ink); }
.ev-res__then { display: block; margin-top: 4px; color: var(--ink-2); font-size: var(--fs-12); }
.ev-when { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--ink); }
.ev-empty { color: var(--ink-2); }
/* Several evidence cards in one place, with the page's vertical rhythm. */
.ev-stack > * + * { margin-top: var(--s-5); }

/* ---------- Result facts, then the screenshots under them (#2947: one column) ---------- */
.ev-facts { padding: var(--s-2) var(--s-5); }
.ev-facts__list { display: grid; grid-template-columns: 168px minmax(0, 1fr); }
.ev-facts__list > div { display: contents; }
.ev-facts__list dt, .ev-facts__list dd { padding: 14px 0; border-bottom: 1px solid var(--line); }
.ev-facts__list > div:last-child dt, .ev-facts__list > div:last-child dd { border-bottom: 0; }
.ev-facts__list dt { padding-top: 16px; color: var(--ink-2); font-size: var(--fs-12); }
.ev-facts__host { color: var(--ink); }
/* A URL never sits in the label column's neighbour: its row is the full width, label over it. */
.ev-facts__list > div:has(.ev-url-line) > *, .ev-kv > .ev-kv__url > * { grid-column: 1 / -1; }
.ev-facts__list > div:has(.ev-url-line) > dt, .ev-kv > .ev-kv__url > dt { padding-bottom: 0; border-bottom: 0; }
.ev-facts__list > div:has(.ev-url-line) > dd, .ev-kv > .ev-kv__url > dd { padding-top: 4px; }

/* Screenshots: labelled captures in a crisp frame, never a browser bar. Only
   the capture is dimmed in the dark presets (--shot-filter); the frame stays crisp. */
.ev-shots { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); gap: var(--s-4); align-content: start; }
/* The label, then the address it was taken from on its own line, whole. */
.ev-shot { min-width: 0; }
.ev-shot figcaption { display: grid; gap: 2px; margin-bottom: 6px; }
.ev-shot__label { color: var(--ink-2); font-size: var(--fs-12); }
.ev-shot__frame { height: 200px; border: 1px solid var(--line-strong); border-radius: var(--r-control); overflow: hidden; background: var(--surface); }
.ev-shot__img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top left; filter: var(--shot-filter); }

/* ---------- Steps: bar, result, then name, so every result lines up ---------- */
.ev-steps { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 2px; }
.ev-step { min-width: 0; padding-right: var(--s-3); }
.ev-step__bar { display: block; height: 8px; border-radius: var(--r-cell); }
.ev-step:first-child .ev-step__bar { border-radius: 4px var(--r-cell) var(--r-cell) 4px; }
.ev-step:last-child .ev-step__bar { border-radius: var(--r-cell) 4px 4px var(--r-cell); }
.ev-step--ok .ev-step__bar { background: var(--ok); }
.ev-step--warn .ev-step__bar { background: var(--warn); }
.ev-step--fail .ev-step__bar { background: var(--fail); }
.ev-step--grey .ev-step__bar { background: var(--grey-hatch); box-shadow: inset 0 0 0 1px var(--grey); }
.ev-step--none .ev-step__bar {
  background: repeating-linear-gradient(90deg, var(--none) 0 4px, transparent 4px 8px) center / 100% 1px no-repeat;
  box-shadow: inset 0 0 0 1px var(--none);
}
.ev-step__res { display: flex; align-items: center; gap: 6px; margin-top: var(--s-3); color: var(--ink-2); font-size: var(--fs-12); white-space: nowrap; }
.ev-step--warn .ev-step__res { color: var(--warn-ink); }
.ev-step--fail .ev-step__res { color: var(--fail-ink); }
.ev-step__name { display: flex; gap: 6px; margin-top: 4px; line-height: 1.35; }
.ev-step__n { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.ev-step__detail { margin-top: var(--s-2); color: var(--ink-2); font-size: var(--fs-12); line-height: 1.45; }

/* ---------- Other checks in this run · Earlier checks of this country · device ---------- */
.ev-others, .ev-earlier { table-layout: fixed; }
.ev-others__where { width: 300px; }
.ev-others__when { width: 140px; }
.ev-others__act { width: 150px; }
.ev-table__act { text-align: right; }
.ev-earlier__when { width: 160px; }
.ev-earlier__check { width: 180px; }
.ev-earlier__change td { padding-block: 6px; background: var(--surface-2); color: var(--ink-2); font-size: var(--fs-12); }

/* A URL as its host (ink) and its path and query (quiet), parts.ts evidenceUrl. */
.ev-url { color: var(--ink-2); }
.ev-url__host { color: var(--ink); }

/* ---------- Configuration and Technical details (Advanced) ---------- */
.ev-kv { display: grid; grid-template-columns: 180px minmax(0, 1fr); }
.ev-kv > div { display: contents; }
.ev-kv dt, .ev-kv dd { padding: 9px 0; border-bottom: 1px solid var(--line); }
.ev-kv > div:last-child dt, .ev-kv > div:last-child dd { border-bottom: 0; }
.ev-kv dt { padding-top: 11px; color: var(--ink-2); font-size: var(--fs-12); }
.ev-kv--2 { grid-template-columns: 180px minmax(0, 1fr) 180px minmax(0, 1fr); column-gap: var(--s-5); margin-block: calc(-1 * var(--s-4)); }
.ev-kv--2 > div:nth-last-child(2) dt, .ev-kv--2 > div:nth-last-child(2) dd { border-bottom: 0; }
/* Mono only here, inside Technical details (notes.md). */
.ev-kv code { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: var(--fs-12); overflow-wrap: anywhere; }
.ev-tech > .disclosure > summary { padding: var(--s-4) var(--s-5); background: var(--surface-head); border-radius: calc(var(--r-card) - 1px); }
.ev-tech > .disclosure[open] > summary { border-bottom: 1px solid var(--line); border-radius: calc(var(--r-card) - 1px) calc(var(--r-card) - 1px) 0 0; }
.ev-tech > .disclosure > .disclosure__body { margin-top: 0; padding: var(--s-2) var(--s-5) var(--s-3); }

/* ---------- The live page (#2745 look port): the head's legend, then each part under the last ---------- */
.ev-chip { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: var(--r-chip); background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--line-strong); color: var(--ink); font-size: var(--fs-12); }
/* #2945: a Test run's reason, whole under its label like a quoted URL (on a phone Marked too);
   then, for an admin or operator, the closed form that marks the run or clears the mark. */
.ev-head + .facts dd:has(> .ev-why) { white-space: normal; overflow-wrap: anywhere; }
.ev-head + .facts > div:has(.ev-why) { flex: 1 0 100%; min-width: 0; }
.ev-head + .facts > div:has(.ev-why), .ev-head + .facts > div:has(+ div .ev-why) { margin-right: 0; padding-right: 0; border-right: 0; }
.ev-test-run { margin-top: var(--s-4); }
.ev-test-run > .disclosure > summary { width: fit-content; font-size: var(--fs-13); font-weight: var(--w-ui); }
.ev-test-run__form { display: grid; gap: var(--s-3); justify-items: start; }
.ev-test-run__form .field { width: 100%; }
.ev-stages { display: grid; gap: 2px; }
.ev-stage > details > summary { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s-3); padding: var(--s-2) 0; list-style: none; cursor: pointer; }
.ev-stage > details > summary::-webkit-details-marker { display: none; }
.ev-stage + .ev-stage { border-top: 1px solid var(--line); }
.ev-stage__res { display: inline-flex; align-items: center; gap: 5px; min-width: 7.5em; color: var(--ink-2); }
/* A stage's result word in ink, red only for a stage that failed (a certain Fail); none stays quiet. */
.ev-stage--ok .ev-stage__res { color: var(--ink); }
.ev-stage--fail .ev-stage__res { color: var(--fail-ink); }
.ev-stage--grey .ev-stage__res, .ev-stage--none .ev-stage__res { color: var(--ink-2); }
.ev-stage__name { color: var(--ink); }
.ev-stage__key, .ev-stage__note { color: var(--ink-2); font-size: var(--fs-12); }
.ev-stage__codes { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.ev-stage__detail { padding: 0 0 var(--s-3); }

/* One box (#2826, partner 2026-11-02: "harmonize the design"): every part of the check report
   folds the same way, a card whose summary is its head with the chevron at its end. A library
   box (.ev-box, box.ts: Stages, Technical details) and today's carried disclosures share these rules.
   The summary is the title row on the card's band (#3101 1B), so a closed box shows as its band;
   the column labels inside take the body's colour, one band per box. */
/* Today's markup, in the console look: each part a card, today's disclosures with their summary as the head. */
.ev-carried { display: grid; gap: var(--s-4); min-width: 0; font-size: var(--fs-14); overflow-wrap: anywhere; }
.ev-carried code { font: inherit; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.ev-carried p + p, .ev-carried p + div, .ev-carried div + p { margin-top: var(--s-2); }
/* Bold only on section titles and the result (#2947): today's inline labels ("What we saw:")
   are labels, in the quiet ink at regular weight. */
.ev-carried strong { font-weight: var(--w-text); }
.ev-carried .diagnosis-detail > strong:first-child, .ev-carried .customer-observation > strong, .ev-carried .customer-action > strong { color: var(--ink-2); }
.ev-carried pre { overflow: auto; max-height: 24rem; padding: var(--s-3); border-radius: var(--r-control); background: var(--surface-2); font-size: var(--fs-12); white-space: pre-wrap; overflow-wrap: anywhere; }
.ev-box, .ev-carried > details, .ev-carried > .diagnosis-block, .ev-carried > .callout, .ev-carried > .status-axes, .ev-carried > .insight-panel, .ev-carried > .facts {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--shadow-card); padding: var(--s-4) var(--s-5);
}
/* #2906: Video: Not recorded for this check, where the video would be. */
.ev-carried > .facts { margin-top: 0; }
.ev-box, .ev-carried > details { padding: 0; min-width: 0; overflow-x: auto; }
.ev-box > summary, .ev-carried > details > summary { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-3) var(--s-5); list-style: none; cursor: pointer; font-size: var(--fs-15); font-weight: var(--w-strong); background: var(--surface-head); border-radius: calc(var(--r-card) - 1px); }
.ev-box > summary::-webkit-details-marker, .ev-carried > details > summary::-webkit-details-marker { display: none; }
.ev-carried > details > summary h3 { font: inherit; }
.ev-box > summary::after, .ev-carried > details > summary::after { content: ''; width: 7px; height: 7px; margin-left: auto; border-right: 1.5px solid var(--ink-2); border-bottom: 1.5px solid var(--ink-2); transform: rotate(-45deg); }
.ev-box[open] > summary::after, .ev-carried > details[open] > summary::after { transform: rotate(45deg); }
.ev-box[open] > summary, .ev-carried > details[open] > summary { border-bottom: 1px solid var(--line); border-radius: calc(var(--r-card) - 1px) calc(var(--r-card) - 1px) 0 0; }
.ev-box > .ev-box__body, .ev-carried > details > :not(summary) { margin: var(--s-3) var(--s-5); }
.ev-carried > details > .table-scroll, .ev-carried > details > table, .ev-carried > details > .table-wrap { margin: 0; }
.ev-carried .table-scroll { overflow-x: auto; }
.ev-carried table { width: 100%; border-collapse: collapse; }
.ev-carried th { padding: 8px var(--s-4); background: var(--surface-2); border-bottom: 1px solid var(--line); color: var(--ink-2); font-size: var(--fs-12); font-weight: var(--w-text); text-align: left; white-space: nowrap; }
.ev-box th, .ev-carried > details th { background: var(--surface); }
.ev-carried td { padding: 10px var(--s-4); border-bottom: 1px solid var(--line); vertical-align: top; }
.ev-carried tbody tr:last-child td { border-bottom: 0; }
.ev-carried .hop-note { margin-top: 2px; color: var(--ink-2); font-size: var(--fs-12); }
.ev-carried code.badge, .ev-carried .badge-not_applicable { height: 20px; padding: 0 7px; background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--line); color: var(--ink); font-weight: var(--w-text); }
.ev-carried .badge-headline-OK, .ev-carried code.badge-pass { background: var(--ok-tint); box-shadow: none; color: var(--ok-ink); }
.ev-carried .badge-headline-WARN, .ev-carried code.badge-warn { background: var(--warn-tint); box-shadow: none; color: var(--warn-ink); }
.ev-carried .badge-headline-FAIL, .ev-carried code.badge-fail { background: var(--fail-tint); box-shadow: none; color: var(--fail-ink); }
/* The decisive finding: its tone on the left edge, as today (red only for a finding that fails the run). */
.ev-carried > .diagnosis-block { border-left: 4px solid var(--grey); }
.ev-carried > .diagnosis-audit_ending, .ev-carried > .diagnosis-stage_blocking { border-left-color: var(--fail); }
.ev-carried > .diagnosis-non_blocking { border-left-color: var(--warn); }
.ev-carried > .diagnosis-note { border-left-color: var(--ink-2); }
.ev-carried .diagnosis-headline { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: var(--fs-15); font-weight: var(--w-strong); }
.ev-carried .diagnosis-code { color: var(--ink-2); font-size: var(--fs-12); font-weight: var(--w-text); }
.ev-carried .status-axes { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); align-items: center; color: var(--ink-2); }
.ev-carried .axis code { margin-left: 4px; color: var(--ink); }
.ev-carried .config-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: var(--s-2) var(--s-5); }
.ev-carried .config-row { display: grid; gap: 2px; }
.ev-carried .config-key { font-size: var(--fs-12); }
.ev-carried .geo-mismatch, .ev-carried .diagnosis-detail, .ev-carried .platform-skip-caption { line-height: var(--lh-ui); }
.ev-carried .stages-list { display: grid; gap: var(--s-2); }
.ev-carried .stage-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s-3); }
.ev-carried .skipped-stages h3 { margin: var(--s-4) 0 var(--s-2); font-size: var(--fs-14); font-weight: var(--w-strong); }
.ev-carried .reason-codes { display: inline-flex; gap: 4px; }
.ev-carried .reason-code-row > summary { cursor: pointer; }
.ev-carried .reason-code-content, .ev-carried .checkpoint-finding { margin-top: var(--s-2); }
/* Playback video and screenshots: today's no-JS enlarge (popover), framed as the console's captures. */
.ev-carried .audit-video-player:not(:popover-open) { display: block; position: static; inset: auto; width: min(100%, 300px); height: auto; margin: var(--s-3) var(--s-5); padding: 0; border: 0; overflow: visible; background: transparent; color: inherit; }
.ev-carried .audit-video { display: block; width: 100%; max-height: 300px; border-radius: var(--r-control); background: var(--surface-3); }
.ev-carried .audit-video-bar { display: none; }
.ev-carried .audit-video-player:popover-open, .ev-carried .shot-zoom:popover-open { max-width: calc(100vw - 32px); max-height: calc(100dvh - 32px); padding: 0; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--surface); color: var(--ink); overflow: hidden; }
.ev-carried .audit-video-player:popover-open { width: min(1200px, calc(100vw - 32px)); }
.ev-carried .audit-video-player:popover-open .audit-video { max-height: calc(100dvh - 88px); border-radius: 0; }
.ev-carried .audit-video-player:popover-open .audit-video-bar, .ev-carried .shot-zoom-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--s-2) var(--s-3); margin: 0; padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--line); font-size: var(--fs-13); }
.ev-carried .shot-zoom:popover-open { display: flex; flex-direction: column; width: fit-content; min-width: min(22rem, calc(100vw - 32px)); }
.ev-carried .shot-zoom::backdrop, .ev-carried .audit-video-player::backdrop { background: color-mix(in srgb, var(--ink) 72%, transparent); }
.ev-carried .popover-dismiss { display: none; }
.ev-carried :popover-open > .popover-dismiss { display: block; position: fixed; inset: 0; z-index: -1; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; background: transparent; }
.ev-carried .shot-zoom-caption { flex: 1 1 12rem; min-width: 0; overflow-wrap: anywhere; }
.ev-carried .shot-zoom-body { flex: 1 1 auto; min-height: 0; overflow: auto; background: var(--surface-2); }
.ev-carried .shot-zoom-body img { display: block; max-width: 100%; height: auto; margin: 0 auto; filter: var(--shot-filter); }
.ev-carried .audit-video-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-3); margin-top: var(--s-3); font-size: var(--fs-13); }
.ev-carried .audit-video-enlarge, .ev-carried .audit-video-close, .ev-carried .shot-zoom-close {
  height: 30px; padding: 0 10px; border: 1px solid var(--line-strong); border-radius: 7px; background: var(--control-bg); color: var(--ink); font: inherit; font-size: var(--fs-13); font-weight: var(--w-ui); cursor: pointer;
}
.ev-carried .screenshots-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--s-4); }
.ev-carried .screenshots-grid figure { min-width: 0; }
.ev-carried .shot-thumb { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }
.ev-carried .shot-thumb img { display: block; width: 100%; height: auto; max-height: 360px; object-fit: cover; object-position: top; border: 1px solid var(--line-strong); border-radius: var(--r-control); background: var(--surface-2); filter: var(--shot-filter); }
.ev-carried .shot-thumb:hover img { border-color: var(--accent); }
.ev-carried .screenshots-grid figcaption { margin-top: 6px; color: var(--ink-2); font-size: var(--fs-12); overflow-wrap: anywhere; }
.ev-carried .near-blank-tag { display: block; color: var(--ink); }
@supports not selector(:popover-open) {
  .ev-carried .shot-thumb { cursor: default; }
  .ev-carried .shot-zoom-caption, .ev-carried .shot-zoom-close, .ev-carried .shot-zoom-body, .ev-carried .audit-video-enlarge { display: none; }
}

/* ---------- Narrow screens ---------- */
@media (max-width: 1100px) {
  .ev-steps { grid-auto-flow: row; grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: var(--s-5); }
}
@media (max-width: 960px) {
  .ev-kv--2 { grid-template-columns: 150px minmax(0, 1fr) 150px minmax(0, 1fr); }
}
@media (max-width: 760px) {
  /* Today's tables keep their columns and scroll inside their card, URLs wrapping at a readable width. */
  .ev-carried .table-scroll > table, .ev-carried > details > table { min-width: 34rem; }
  .page-head:has(> .ev-head) .breadcrumb [aria-current="page"] { display: none; }
  .ev-head { grid-template-columns: auto minmax(0, 1fr); }
  .ev-head__act { grid-column: 1 / -1; justify-items: start; }
  .ev-head + .facts > div:has(.ev-url-line), .ev-head + .facts > div:has(.ev-why), .ev-head + .facts > div:has(.ev-marked) { grid-column: 1 / -1; }
  .ev-head + .facts dd:has(> .ev-marked) { overflow-wrap: anywhere; }
  .ev-place__browser--wide { display: none; }
  .ev-facts { padding: var(--s-1) var(--s-4); }
  .ev-facts__list { grid-template-columns: minmax(0, 1fr); }
  .ev-facts__list dt { border-bottom: 0; padding-bottom: 0; }
  .ev-facts__list dd { padding-top: 4px; }
  .ev-steps { grid-template-columns: minmax(0, 1fr); gap: var(--s-3); }
  .ev-step { padding-right: 0; }
  .ev-kv, .ev-kv--2 { grid-template-columns: minmax(0, 1fr); margin-block: 0; }
  .ev-kv dt { border-bottom: 0; padding-bottom: 0; }
  .ev-kv dd { padding-top: 2px; }
  .ev-kv--2 > div:nth-last-child(2) dd { border-bottom: 1px solid var(--line); }
  .ev-tech > .disclosure > summary { padding: var(--s-3) var(--s-4); }
  .ev-tech > .disclosure > .disclosure__body { padding: var(--s-1) var(--s-4) var(--s-3); }
}

/* Tables stack into one block per row, labels inline (critique round 3), whenever
   their card is narrower than the columns need: phones, and the 768 px tablet. */
.ev-table-wrap { container-type: inline-size; }
@container (max-width: 759px) {
  .ev-table thead, .ev-table colgroup { display: none; }
  .ev-table, .ev-table tbody, .ev-table tr, .ev-table td { display: block; width: auto; }
  .ev-table tr { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
  .ev-table tbody tr:last-child { border-bottom: 0; }
  .ev-table td, .ev-table .num { padding: 0; border: 0; text-align: left; }
  .ev-table td + td { margin-top: 6px; }
  .ev-table td[data-k]::before { content: attr(data-k); margin-right: 6px; color: var(--ink-2); font-size: var(--fs-12); }
  .ev-table .ev-table__inline { display: inline-block; margin-right: var(--s-4); }
  .ev-table tbody tr:hover td { background: none; }
  .ev-table .ev-table__act { margin-top: var(--s-2); text-align: right; }
  .ev-earlier__change { background: var(--surface-2); }
  .ev-earlier__change td { padding: 0; background: none; }
}

/* ── 51-evidence-downloads.css ── */
/* The check report's downloads (#2826, partner 2026-11-02): "Download log", "Download
   report" and (Q8) the ZIP side by side, top right of the head; on a phone they start a row of their own,
   left-aligned, as Re-check does (50-evidence.css). */
.ev-head__downloads { display: flex; flex-wrap: wrap; gap: var(--s-2); justify-content: flex-end; }
@media (max-width: 760px) {
  .ev-head__downloads { justify-content: flex-start; }
}

/* ── 52-evidence-actions.css ── */
/* The check report's "What to do" (#2826, partner decision Q4, 2026-11-03): its own box
   right after the summary box, one row per finding: #, the action under its finding and its
   code, Losing money now?, the owner and why it matters. The box and the table are the evidence family's (.ev-box,
   .ev-table in 50-evidence.css, which also stacks the rows on a narrow screen); this file
   holds only the columns and the owner's chip. Colours from the role tokens only. */
.ev-actions__lead { color: var(--ink-2); }
.ev-actions__lead + .ev-table-wrap { margin-top: var(--s-3); }
.ev-actions .ev-actions__col-n { width: 3rem; }
.ev-actions .ev-actions__col-action { width: auto; }
.ev-actions .ev-actions__col-money { width: 9rem; }
.ev-actions .ev-actions__col-owner { width: 11rem; }
.ev-actions .ev-actions__col-why { width: 30%; }
/* One type scale (#2947): the column labels and the finding are quiet labels at the regular
   weight; the action is the body text under its finding. */
.ev-actions th { font-weight: var(--w-text); }
.ev-actions td { vertical-align: top; }
.ev-actions .ev-actions__n { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.ev-actions__finding { display: block; color: var(--ink-2); font-size: var(--fs-12); }
.ev-actions__do { display: block; margin-top: 2px; color: var(--ink); }
.ev-actions__why { color: var(--ink-2); }
/* "Losing money now?" (#2826 QA: the run report's rating, kept when it left the console): plain
   words at the regular weight (one type scale, #2947), Yes in the Fail colour and Not yet in
   the Warning colour, as the result words are; No and Can't tell quiet. */
.ev-actions__money { font-size: var(--fs-12); line-height: var(--lh-ui); color: var(--ink-2); }
.ev-actions__money--yes { color: var(--fail-ink); }
.ev-actions__money--atrisk { color: var(--warn-ink); }
.ev-actions__money--no, .ev-actions__money--untold { color: var(--ink-2); }
/* The owner: a quiet chip for the party the reader forwards it to; plain words for us, or no one. */
.ev-actions__owner { display: inline-block; max-width: 100%; font-size: var(--fs-12); line-height: var(--lh-ui); overflow-wrap: anywhere; }
.ev-actions__owner--forward { padding: 1px 8px; border: 1px solid var(--line-strong); border-radius: var(--r-control); color: var(--ink); }
.ev-actions__owner--quiet { color: var(--ink-2); }

/* Stacked (50-evidence.css .ev-table): the number in a gutter beside its finding and action, not on a line of its own. */
@container (max-width: 759px) {
  .ev-actions .ev-actions__n { float: left; width: 1.75em; }
  .ev-actions .ev-actions__n + td { margin-top: 0; margin-left: 1.75em; }
  .ev-actions td[data-k="Owner"]::before { vertical-align: middle; }
}

/* ── 52-evidence-copies.css ── */
/* 52-evidence-copies — every copy of the link on the placement page (#2794, P-03 agreed by m
   2026-10-18), at the end of the placement step's detail: the count, the copies that point
   somewhere else, then the copies that point to the link folded away (a disclosure; on paper
   it stays folded under its count, 95-print.css). Each copy its mark and word (red only for one
   that points somewhere else: the placement check's certain finding), its place on the page, where it points
   (a whole line under its label, #2947) and its picture, or the line that says our capture
   has none. Colours come from the role tokens only. */
.ev-copies { display: grid; gap: var(--s-2); min-width: 0; margin-top: var(--s-3); }
.ev-copies__head, .ev-copies__none { margin: 0; font-size: var(--fs-14); }
.ev-copies__list { display: grid; gap: var(--s-2); margin: 0; padding: 0; list-style: none; }
.ev-copy { display: grid; gap: var(--s-1); min-width: 0; padding: var(--s-2) var(--s-3); border: 1px solid var(--line); border-radius: var(--r-control); background: var(--surface); }
.ev-copy__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-1) var(--s-3); margin: 0; }
.ev-copy__mark { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-13); }
.ev-copy--ok .ev-copy__mark { color: var(--ink); }
.ev-copy--wrong .ev-copy__mark { color: var(--fail-ink); }
.ev-copy__n { color: var(--ink-2); font-size: var(--fs-12); }
.ev-copy__shot { justify-self: start; }
.ev-copy__shot img { display: block; max-width: min(100%, 360px); max-height: 160px; object-fit: contain; border: 1px solid var(--line-strong); border-radius: var(--r-control); background: var(--surface-2); filter: var(--shot-filter); }
.ev-copy__shot:hover img { border-color: var(--accent); }
.ev-copy__noshot { margin: 0; color: var(--ink-2); font-size: var(--fs-12); }
.ev-copies .disclosure > summary { font-size: var(--fs-13); }
.ev-copies .disclosure__body { margin-top: var(--s-2); }

/* ── 52-evidence-stages.css ── */
/* 52-evidence-stages — the six stages, each a line opening to its steps (#2826, partner Q2
   2026-11-03): the stage explorer (widgets/evidence/stage-explorer.ts) of the Stages box and of
   Diagnostics by step. A line is its mark and word, its name, View steps, and what it checks and
   why beside it (with why it matters where it failed); its steps show under it on Reports'
   breakdown band (70-reports.css) while it is open. Expand all and Collapse all sit top right.
   In-page state, zero client JS (#2826, partner 2026-11-04): each button is a label over a
   checkbox the box's empty form owns (Collapse all is its reset), and `:has()` reads them, so
   nothing reloads or scrolls. A button's box sits inside it, so focusing it never scrolls; the
   button takes the console's focus ring and, while on, the breakdown's pressed fill. Narrower,
   what it checks folds under the name; on a phone, under the line. Each step keeps today's row
   (.ev-stage, 50-evidence.css). On paper every stage is open (95-print.css). Colours come from
   the role tokens only. */
.ev-sg-all { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s-2); margin: 0 0 var(--s-1); }
.ev-sgx__tg { position: relative; cursor: pointer; user-select: none; }
.ev-sgx__in { position: absolute; top: 0; left: 0; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.ev-sgx__tg:has(.ev-sgx__in:focus-visible) { outline: 2px solid var(--focus); outline-offset: 2px; }
.ev-sgx__tg:has(.ev-sgx__in:checked) { background: var(--surface-3); }
/* --sg-res: the result column, wide enough for "Couldn't be measured" and "Not part of this check" on one line. */
.ev-sgs { --sg-res: 13.25em; list-style: none; margin: 0; padding: 0; display: grid; }
.ev-sg + .ev-sg { border-top: 1px solid var(--line); }
.ev-sg__line {
  display: grid; grid-template-columns: var(--sg-res) minmax(10em, 17em) minmax(0, 1fr) auto; align-items: baseline;
  gap: var(--s-1) var(--s-4); padding: var(--s-3) 0;
}
.ev-sg__res { grid-column: 1; grid-row: 1; display: block; color: var(--ink-2); white-space: nowrap; }
/* The mark inline before the word, so the word sits on the line's baseline with the name beside it (#2826 alignment). */
.ev-sg__res > :is(.glyph, .icon) { margin-right: 5px; }
/* The Whole check line's Note mark, the Diagnostics box's info icon at its size (#3157 point 8). */
.ev-sg__res > .icon { width: 14px; height: 14px; vertical-align: -2px; }
/* A stage's word as a step's: ink, red only for a stage that failed, quiet when not checked. */
.ev-sg--ok .ev-sg__res { color: var(--ink); }
.ev-sg--warn .ev-sg__res { color: var(--warn-ink); }
.ev-sg--fail .ev-sg__res { color: var(--fail-ink); }
/* A note (#3157 point 8: the Whole check line) reads grey, as the Diagnostics box says one. */
.ev-sg--grey .ev-sg__res, .ev-sg--none .ev-sg__res, .ev-sg--note .ev-sg__res { color: var(--ink-2); }
/* Regular weight (#2947: bold only on section titles and the result): ink over the quiet column. */
.ev-sg__name { grid-column: 2; grid-row: 1; min-width: 0; color: var(--ink); }
.ev-sg__about { grid-column: 3; grid-row: 1; min-width: 0; color: var(--ink-2); font-size: var(--fs-13); }
.ev-sg__why { margin-top: var(--s-1); color: var(--ink); }
.ev-sg__label { color: var(--ink-2); }
.ev-sg__bd { grid-column: 4; grid-row: 1; align-self: start; display: flex; }
.ev-sg__bd > .ev-sgx__tg { width: 7.5rem; }
/* Expand all on: every stage's second button, checked to start, in place of its first. */
.ev-sg__tg--all { display: none; }
.ev-sgx:has(> .ev-sg-all .ev-sgx__all > :checked) .ev-sg__tg--each { display: none; }
.ev-sgx:has(> .ev-sg-all .ev-sgx__all > :checked) .ev-sg__tg--all { display: inline-flex; }
/* The steps: the breakdown's band under its line, shown while its button is on; each step's
   name under its stage's (the band's padding is the line's column gap). */
.ev-sg__steps { display: none; margin: 0 0 var(--s-3); padding: 0 var(--s-4); border-radius: var(--r-control); background: var(--surface-2); }
.ev-sg__steps .ev-stage__res { min-width: calc(var(--sg-res) - var(--s-3)); white-space: nowrap; }
.ev-sgx:not(:has(> .ev-sg-all .ev-sgx__all > :checked)) .ev-sg:has(> .ev-sg__line .ev-sg__tg--each > :checked) > .ev-sg__steps,
.ev-sgx:has(> .ev-sg-all .ev-sgx__all > :checked) .ev-sg:has(> .ev-sg__line .ev-sg__tg--all > :checked) > .ev-sg__steps { display: grid; }
.ev-sg-other { margin-top: var(--s-2); }
/* Diagnostics by step's Whole check line (#3157, partner ruling 2026-11-10, point 8): the tests that read the
   whole visit, said once before the stages. It has no View steps: its tests always show under it. */
.ev-sg--whole > .ev-sg__steps { display: grid; }

@media (max-width: 960px) {
  .ev-sg__line { grid-template-columns: var(--sg-res) minmax(0, 1fr) auto; }
  .ev-sg__bd { grid-column: 3; }
  .ev-sg__about { grid-column: 2 / -1; grid-row: 2; }
}

@media (max-width: 760px) {
  .ev-sg__line { grid-template-columns: minmax(0, 1fr) auto; gap: var(--s-1) var(--s-3); }
  .ev-sg__res { grid-column: 1; grid-row: 1; min-width: 0; white-space: normal; }
  .ev-sg__bd { grid-column: 2; grid-row: 1; }
  .ev-sg__bd > .ev-sgx__tg { width: auto; }
  .ev-sg__name { grid-column: 1 / -1; grid-row: 2; }
  .ev-sg__steps .ev-stage__res { min-width: 7.5em; }
  .ev-sg__about { grid-column: 1 / -1; grid-row: 3; }
  .ev-sg__steps { padding: 0 var(--s-3); }
}

/* ── 53-evidence-diagnostics.css ── */
/* The check report's Diagnostics box (#2826 Q5, widgets/evidence/diagnostics.ts): one line per
   test, its mark and word, its name and what it verifies side by side; a flagged line's reading
   under the name; the tests that didn't run on one quiet line. The count rides the box's head. */
.ev-box__count { color: var(--ink-2); font-size: var(--fs-13); font-weight: var(--w-text); }
.ev-diag__lines { display: grid; }
.ev-diag__line { display: grid; grid-template-columns: 7.5em minmax(10rem, 16rem) minmax(0, 1fr); gap: 2px var(--s-4); align-items: start; padding: var(--s-2) 0; font-size: var(--fs-14); line-height: var(--lh-ui); }
.ev-diag__line + .ev-diag__line { border-top: 1px solid var(--line); }
.ev-diag > .ev-box__body { margin-top: var(--s-2); }
.ev-diag__res { display: inline-flex; align-items: center; gap: 5px; color: var(--ink); }
.ev-diag--ok .ev-diag__res { color: var(--ink); }
.ev-diag__res .icon { width: 14px; height: 14px; color: var(--ink-2); }
/* The word in ink, red only for a test that failed (a certain Fail), amber ink for a warning. */
.ev-diag--fail .ev-diag__res { color: var(--fail-ink); }
.ev-diag--warn .ev-diag__res { color: var(--warn-ink); }
.ev-diag--note .ev-diag__res { color: var(--ink-2); }
.ev-diag__name { color: var(--ink); font-weight: var(--w-ui); }
.ev-diag__id { margin-left: 6px; vertical-align: 1px; color: var(--ink-2); }
.ev-diag__verifies { color: var(--ink-2); }
.ev-diag__more { grid-column: 2 / -1; display: grid; gap: var(--s-2); min-width: 0; overflow-wrap: anywhere; }
.ev-diag__saw { overflow-wrap: anywhere; }
.ev-diag__label, .ev-diag__where { color: var(--ink-2); }
.ev-diag__where { margin-right: var(--s-2); }
.ev-diag__codes { display: inline-flex; flex-wrap: wrap; gap: 4px; vertical-align: 1px; }
.ev-diag__facts { display: grid; gap: 2px; }
.ev-diag__facts dt { display: inline; color: var(--ink-2); }
.ev-diag__facts dd { display: inline; }
.ev-diag__source, .ev-diag__note { color: var(--ink-2); }
.ev-diag__note { font-size: var(--fs-13); }
.ev-diag__notrun { margin-top: var(--s-2); color: var(--ink-2); font-size: var(--fs-13); line-height: var(--lh-ui); }
.ev-diag__lines + .ev-diag__notrun { padding-top: var(--s-3); border-top: 1px solid var(--line); }
@media (max-width: 760px) {
  /* The mark and the name on one row, what it verifies and the reading under them, full width. */
  .ev-diag__line { grid-template-columns: auto minmax(0, 1fr); column-gap: var(--s-3); }
  .ev-diag__verifies, .ev-diag__more { grid-column: 1 / -1; }
}

/* ── 54-evidence-map.css ── */
/* 54-evidence-map — the check report's Stage map (#2826, partner Q3 2026-11-03): the six
   stages in a row, each a shape with its mark, its word and its name, arrows between; the
   selected one ringed in the accent, its details under the row on the quiet band the Stages box
   opens its steps on. In-page state, zero client JS (#2826, partner 2026-11-04): each shape is a
   label over a radio of the map's group, every stage's details are on the page, and `:has()`
   shows the checked stage's; the radio sits inside its shape, so focusing it never scrolls, and
   the shape takes the console's focus ring. Narrower, three to a row; on a phone, two, and no
   arrows (a wrapped row has no "next" beside it). The steps keep today's row (.ev-stage,
   50-evidence.css). On paper the row prints, every stage's details under it unless the page
   also shows the Stages box (95-print.css). Colours come from the role tokens only. */
.ev-map { display: grid; gap: var(--s-3); }
.ev-map__strip { --map-gap: var(--s-6); list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--s-2) var(--map-gap); }
/* The arrow in the gap before a shape: decorative, so its alternative text is empty. */
.ev-map__stage + .ev-map__stage::before {
  content: "\2192" / ""; position: absolute; top: 50%; left: calc(-1 * var(--map-gap)); width: var(--map-gap);
  transform: translateY(-50%); text-align: center; color: var(--ink-3); line-height: 1;
}
.ev-map__stage {
  position: relative; display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; padding: var(--s-3); cursor: pointer;
  border: 1px solid var(--line-strong); border-radius: var(--r-control); background: var(--surface); color: var(--ink);
}
.ev-map__stage:hover { border-color: var(--ink-3); }
.ev-map__in { position: absolute; top: 0; left: 0; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }
.ev-map__stage:has(.ev-map__in:focus-visible) { outline: 2px solid var(--focus); outline-offset: 2px; }
.ev-map__res { display: inline-flex; align-items: center; gap: 5px; color: var(--ink-2); font-size: var(--fs-13); }
.ev-map__name { min-width: 0; font-size: var(--fs-13); line-height: var(--lh-ui); overflow-wrap: anywhere; }
/* A shape's mark as a stage's word in the Stages box: ink, amber for a warning, red only for a
   stage that failed (its shape tinted, as the run report draws it), quiet when not checked. */
.ev-map__stage--ok .ev-map__res { color: var(--ink); }
.ev-map__stage--grey .ev-map__res, .ev-map__stage--none .ev-map__res { color: var(--ink-2); }
.ev-map__stage--warn { border-color: var(--warn); background: var(--warn-tint); }
.ev-map__stage--warn .ev-map__res { color: var(--warn-ink); }
.ev-map__stage--fail { border-color: var(--fail); background: var(--fail-tint); }
.ev-map__stage--fail .ev-map__res { color: var(--fail-ink); }
/* The selected stage: ringed in the accent (#2947: bold only on section titles and the result). */
.ev-map__stage:has(.ev-map__in:checked) { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
/* Its details, under the row: only the checked stage's; the hint while none is. */
.ev-map__panel { display: none; min-width: 0; padding: var(--s-3) var(--s-4); border-radius: var(--r-control); background: var(--surface-2); }
.ev-map:has(.ev-map__in[value="click"]:checked) > .ev-map__panel[data-stage="click"],
.ev-map:has(.ev-map__in[value="redirect"]:checked) > .ev-map__panel[data-stage="redirect"],
.ev-map:has(.ev-map__in[value="click-recorded"]:checked) > .ev-map__panel[data-stage="click-recorded"],
.ev-map:has(.ev-map__in[value="browser"]:checked) > .ev-map__panel[data-stage="browser"],
.ev-map:has(.ev-map__in[value="landing-responds"]:checked) > .ev-map__panel[data-stage="landing-responds"],
.ev-map:has(.ev-map__in[value="landing-renders"]:checked) > .ev-map__panel[data-stage="landing-renders"] { display: block; }
.ev-map:has(.ev-map__in:checked) > .ev-map__hint { display: none; }
.ev-map__title { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-1) var(--s-4); margin: 0 0 var(--s-2); font-size: var(--fs-14); font-weight: var(--w-text); }
.ev-map__title .ev-map__name { font-size: var(--fs-14); font-weight: var(--w-strong); color: var(--ink); }
/* The stage's word on the title's baseline: the mark inline before it (#2826 alignment). */
.ev-map__title .ev-map__res { display: inline-block; }
.ev-map__title .ev-map__res > .glyph { margin-right: 5px; }
.ev-map__panel--ok .ev-map__title .ev-map__res { color: var(--ink); }
.ev-map__panel--warn .ev-map__title .ev-map__res { color: var(--warn-ink); }
.ev-map__panel--fail .ev-map__title .ev-map__res { color: var(--fail-ink); }
.ev-map__panel--grey .ev-map__title .ev-map__res, .ev-map__panel--none .ev-map__title .ev-map__res { color: var(--ink-2); }
.ev-map__about { color: var(--ink-2); font-size: var(--fs-13); }
.ev-map__about > p { margin: 0; }
.ev-map__about .ev-sg__why { margin-top: var(--s-1); color: var(--ink); }
.ev-map__steps { margin: var(--s-2) 0 0; padding: 0; }
.ev-map__steps .ev-stage__res { min-width: 12.5em; white-space: nowrap; }
.ev-map__hint, .ev-map__none { margin: 0; color: var(--ink-2); font-size: var(--fs-13); }

@media (max-width: 960px) {
  .ev-map__strip { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ev-map__stage:nth-child(3n + 1)::before { content: none; }
}

@media (max-width: 760px) {
  .ev-map__strip { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); }
  .ev-map__stage + .ev-map__stage::before { content: none; }
  .ev-map__panel { padding: var(--s-3); }
  .ev-map__steps .ev-stage__res { min-width: 7.5em; white-space: normal; }
}

/* ── 55-evidence-log.css ── */
/* 55-evidence-log — the check report's Technical log (#2826, partner 2026-11-03,
   widgets/evidence/technical-log.ts), Diagnostics by step (step-diagnostics.ts) and Methodology
   (methodology.ts), boxes of their own since the partner's 2026-11-04 list. How this check ran is
   one small labelled list per group, the groups side by side where they fit, filling the row (one
   column on a phone); Assertions by step lists each stage, its steps under it and each step's
   assertions, one line each: the word as a step's, the name, Expected and Observed as quiet
   labels before their values (a long value breaks anywhere rather than widen the page; on a phone
   the word on a line of its own, so every assertion reads alike). Diagnostics by step is the
   stage explorer (52-evidence-stages.css), each step's tests under its name, a test's word as the
   Diagnostics box sets it. Methodology's text and glossary run the box's full width (#2826, partner
   2026-11-04: no empty column to the right). One type scale (#2947): bold only on the part
   titles; a group's title is a label (quiet ink, regular). Colours come from the role tokens only. */
.ev-log > .ev-box__body { margin-bottom: var(--s-5); }
.ev-log__part + .ev-log__part { margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid var(--line); }
.ev-log__heading { margin: 0 0 var(--s-3); font-size: var(--fs-14); font-weight: var(--w-strong); }
/* The groups flow down columns of at least 22rem, as many as fit, so a short group never leaves
   an empty cell beside a tall one (#2826: no empty column to the right); one column on a phone. */
.ev-log__groups { columns: 3 22rem; column-gap: var(--s-6); }
.ev-log__group { min-width: 0; break-inside: avoid; margin-bottom: var(--s-4); }
.ev-log__group:last-child { margin-bottom: 0; }
.ev-log__title { margin: 0 0 var(--s-1); color: var(--ink-2); font-size: var(--fs-12); font-weight: var(--w-text); }
/* One column of label and value (the two-column Configuration grid is too wide for a group). */
.ev-log__facts { grid-template-columns: 9.5rem minmax(0, 1fr); font-size: var(--fs-13); }
.ev-log__facts dt, .ev-log__facts dd { padding: 5px 0; }
.ev-log__facts dt { padding-top: 6px; }
.ev-log__facts dd { overflow-wrap: anywhere; }
.ev-log__note { margin-top: var(--s-2); color: var(--ink-2); font-size: var(--fs-13); line-height: var(--lh-ui); }
.ev-log__empty { color: var(--ink-2); font-size: var(--fs-13); }

/* Assertions by step: stage, then its steps, then each step's assertions, each a step in. */
.ev-log-sgs, .ev-log-sts, .ev-log-ts { list-style: none; margin: 0; padding: 0; }
.ev-log-sg + .ev-log-sg { margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--line); }
.ev-log-sg__head, .ev-log-st__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px var(--s-3); font-size: var(--fs-14); line-height: var(--lh-ui); }
.ev-log-sg__head .ev-sg__res { display: inline-block; min-width: 13.25em; color: var(--ink-2); }
/* A word after its mark sits on its line's baseline beside the name (#2826 alignment): the mark inline, not a flex item. */
:is(.ev-log-sg__head .ev-sg__res, .ev-log-st__head .ev-stage__res, .ev-log-a__res, .ev-log-t .ev-diag__res) { display: inline-block; }
:is(.ev-log-sg__head .ev-sg__res, .ev-log-st__head .ev-stage__res, .ev-log-a__res, .ev-log-t .ev-diag__res) > :is(.glyph, .icon) { margin-right: 5px; }
.ev-log-t .ev-diag__res > .icon { vertical-align: -2px; }
.ev-log-sg.ev-sg--ok .ev-sg__res { color: var(--ink); }
.ev-log-sg.ev-sg--warn .ev-sg__res { color: var(--warn-ink); }
.ev-log-sg.ev-sg--fail .ev-sg__res { color: var(--fail-ink); }
.ev-log-sg__name { color: var(--ink); }
.ev-log-sts { margin: var(--s-2) 0 0; padding: var(--s-1) var(--s-4); border-radius: var(--r-control); background: var(--surface-2); }
.ev-log-other { margin-top: var(--s-3); }
.ev-log-st { padding: var(--s-2) 0; }
.ev-log-st + .ev-log-st { border-top: 1px solid var(--line); }
.ev-log-st__name { color: var(--ink); }
.ev-log-st__head .ev-stage__res { min-width: calc(13.25em - var(--s-4)); }
.ev-log-ts { display: grid; margin-top: var(--s-1); padding-left: calc(13.25em - var(--s-4) + var(--s-3)); }
.ev-log-t { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px var(--s-3); padding: 2px 0; font-size: var(--fs-13); line-height: var(--lh-ui); }
.ev-log-t .ev-diag__res { min-width: 6.5em; }
.ev-log-t__name { color: var(--ink); }
.ev-log__codes { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.ev-log-st__quiet { margin-top: 2px; padding-left: calc(13.25em - var(--s-4) + var(--s-3)); color: var(--ink-2); font-size: var(--fs-12); line-height: var(--lh-ui); }
.ev-log-as { margin-top: var(--s-1); padding-left: calc(13.25em - var(--s-4) + var(--s-3)); }
.ev-log-as__title { color: var(--ink-2); font-size: var(--fs-12); line-height: var(--lh-ui); }
.ev-log-as__list { display: grid; list-style: none; margin: 0; padding: 0; }
.ev-log-a { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px var(--s-3); padding: 2px 0; font-size: var(--fs-13); line-height: var(--lh-ui); }
.ev-log-a__res { min-width: 11.5em; }
.ev-log-a--ok .ev-log-a__res { color: var(--ink); }
.ev-log-a--fail .ev-log-a__res { color: var(--fail-ink); }
.ev-log-a--none .ev-log-a__res { color: var(--ink-2); }
.ev-log-a__name { color: var(--ink); }
.ev-log-a__v { min-width: 0; color: var(--ink); overflow-wrap: anywhere; }
.ev-log-a__k { color: var(--ink-2); }

/* Diagnostics by step: each step in the stage explorer's band, its word in the steps' column,
   its tests and its quiet line at its name's indent. */
.ev-sg__steps > .ev-log-st .ev-stage__res { min-width: calc(var(--sg-res) - var(--s-3)); }
.ev-sg__steps > .ev-log-st .ev-log-st__head { gap: 2px var(--s-3); }
/* The step's tests and its quiet line under its name: one indent at the line's own size, so the
   quiet line's smaller type starts where the tests do (#2826 alignment). */
.ev-log-st__under { padding-left: var(--sg-res); }
.ev-log-st__under > :is(.ev-log-ts, .ev-log-st__quiet) { padding-left: 0; }
.ev-log__requests { margin-top: var(--s-5); }

/* Methodology: reading text across the box, then the glossary, each term beside its meaning. */
.ev-method__text p { font-size: var(--fs-14); line-height: var(--lh-ui); }
.ev-method__text p + p { margin-top: var(--s-2); }
.ev-method__part { margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid var(--line); }
.ev-method__heading { margin: 0 0 var(--s-3); font-size: var(--fs-14); font-weight: var(--w-strong); }
.ev-method__glossary { display: grid; grid-template-columns: 12rem minmax(0, 1fr); gap: var(--s-2) var(--s-4); font-size: var(--fs-13); line-height: var(--lh-ui); }
.ev-method__glossary > div { display: contents; }
.ev-method__glossary dt { color: var(--ink); }
.ev-method__glossary dd { color: var(--ink-2); }
.ev-method > .ev-box__body { margin-bottom: var(--s-5); }

@media (max-width: 760px) {
  .ev-log__facts { grid-template-columns: minmax(0, 1fr); }
  .ev-log__facts dt { padding-bottom: 0; border-bottom: 0; }
  .ev-log__facts dd { padding-top: 2px; }
  .ev-log-sg__head .ev-sg__res, .ev-log-st__name { color: var(--ink); }
  .ev-log-st__head .ev-stage__res { min-width: 0; }
  .ev-log-sg__head, .ev-log-st__head { flex-direction: column; align-items: flex-start; }
  .ev-log-ts, .ev-log-st__quiet, .ev-log-as, .ev-log-st__under { padding-left: var(--s-3); }
  .ev-sg__steps > .ev-log-st .ev-stage__res { min-width: 0; }
  .ev-log-a__res { min-width: 0; flex-basis: 100%; }
  .ev-log-sts { padding: var(--s-1) var(--s-3); }
  .ev-method__glossary { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .ev-method__glossary dd { margin-bottom: var(--s-2); }
}

/* ── 56-evidence-chain.css ── */
/* 56-evidence-chain — the check report's Redirect chain (#2793, P-04 agreed by m 2026-10-18):
   the click ids named (#3157: or one line saying why none is, quiet where it wasn't recorded), then one row of host boxes, an arrow between, each the host and its
   answer with the click id introduced, carried or missing; the failing hop in the check's
   result (amber for a Warning, grey for couldn't be measured, red only for a Fail); the full
   URLs one click away, each hop named by what happened there. The row wraps where it runs out
   of room, each arrow staying before its box; on a phone the boxes stack, the arrows pointing
   down. The box itself is today's frame (.ev-carried, 50-evidence.css). On paper the full
   URLs print open (95-print.css). Colours come from the role tokens only. */
.ev-chain__body { display: grid; gap: var(--s-3); min-width: 0; }
.ev-chain__id { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-2); margin: 0; }
.ev-chain__id > div { display: contents; }
.ev-chain__id dt { color: var(--ink-2); font-size: var(--fs-12); line-height: var(--lh-ui); }
.ev-chain__id dd { min-width: 0; margin: 0; font-size: var(--fs-12); line-height: var(--lh-ui); overflow-wrap: anywhere; }
.ev-chain__none { margin: 0; font-size: var(--fs-13); line-height: var(--lh-ui); }
.ev-chain__row { display: flex; flex-wrap: wrap; align-items: stretch; gap: var(--s-2) 0; margin: 0; padding: 0; list-style: none; }
.ev-chain__hop { display: flex; align-items: stretch; min-width: 0; max-width: 100%; }
/* The arrow before a box: decorative, so its alternative text is empty. */
.ev-chain__hop + .ev-chain__hop::before { content: "\2192"; content: "\2192" / ""; align-self: center; padding: 0 var(--s-2); color: var(--ink-3); line-height: 1; }
.ev-chain__box {
  display: grid; align-content: start; gap: 2px; min-width: 0; max-width: 20rem; padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line-strong); border-radius: var(--r-control); background: var(--surface);
}
.ev-chain__host { color: var(--ink); font-size: var(--fs-13); line-height: var(--lh-ui); overflow-wrap: anywhere; }
.ev-chain__ans { color: var(--ink-2); font-size: var(--fs-12); line-height: var(--lh-ui); font-variant-numeric: tabular-nums; }
/* The failing hop's result: its mark and word, over its host. */
.ev-chain__res { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-12); line-height: var(--lh-ui); }
/* The failing hop, in the check's result. */
.ev-chain__box--fail { border-color: var(--fail); background: var(--fail-tint); }
.ev-chain__box--fail .ev-chain__res { color: var(--fail-ink); }
.ev-chain__box--warn { border-color: var(--warn); background: var(--warn-tint); }
.ev-chain__box--warn .ev-chain__res { color: var(--warn-ink); }
.ev-chain__box--grey { border-color: var(--grey); background: var(--surface-2); }
.ev-chain__box--grey .ev-chain__res { color: var(--ink-2); }
/* The full URLs, one click away: each hop named by what happened there, its addresses under it. */
.ev-chain .disclosure > summary { font-size: var(--fs-13); }
.ev-chain__list { display: grid; gap: var(--s-4); margin: 0; padding-left: var(--s-5); list-style: decimal outside; }
.ev-chain__list > li::marker { color: var(--ink-2); font-size: var(--fs-13); }
.ev-chain__said { margin: 0 0 var(--s-2); font-size: var(--fs-14); }

@media (max-width: 760px) {
  .ev-chain__row { flex-direction: column; gap: 0; }
  .ev-chain__hop { flex-direction: column; align-items: stretch; }
  .ev-chain__hop + .ev-chain__hop::before { content: "\2193"; content: "\2193" / ""; align-self: flex-start; padding: var(--s-1) 0 var(--s-1) var(--s-4); }
  .ev-chain__box { max-width: none; }
}

/* ── 56-evidence-progress.css ── */
/* The check report's live line (#2826, seen after #3080, 2026-11-04; widgets/evidence/progress.ts).
   While a check runs, the page never reloads itself: the summary box's line is a frame that alone
   refreshes. On the page the frame is the box, the card the static line was, one line tall; inside
   it, its own document (body.frame) is that line on the card's surface, with the card's padding. */
.ev-progress {
  display: block; width: 100%; height: calc(var(--fs-14) * var(--lh-ui) + 2 * var(--s-4) + 2px);
  border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--shadow-card); background: var(--surface);
}
html:has(> body.frame), body.frame { background: var(--surface); }
/* Never a line out of reach: should the text outgrow the frame (a larger text setting), it scrolls. */
body.frame { overflow-x: hidden; overflow-y: auto; }
.ev-live { padding: var(--s-4) var(--s-5); color: var(--ink-2); font-size: var(--fs-14); line-height: var(--lh-ui); }
.ev-live .status-axes { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); align-items: center; }
/* The way to the result sits inside a sentence: underlined, not told apart by colour alone (WCAG 1.4.1). */
.ev-live__done a { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
/* A narrow screen, down to 320 px (WCAG 1.4.10): room for the finished line on two lines. */
@media (max-width: 400px) {
  .ev-progress { height: calc(2 * var(--fs-14) * var(--lh-ui) + 2 * var(--s-4) + 2px); }
}
/* On paper the page prints the line itself, never the frame (pages/audit-evidence/page.ts). */
@media print {
  .ev-progress { display: none; }
}

/* ── 57-carried.css ── */
/* 57-carried — #3021: carried markup (ui/primitives/carried.ts). A page whose content is kept
   as it was while its words wait to be rewritten (the Registration Insights pages until #2505)
   renders inside the console with the old page vocabulary restyled from the console's tokens:
   the page header, the content card, labelled fields, buttons, notes and tables. Nothing new
   is written in this vocabulary; it goes when the last carried page is rewritten. */

.carried { display: grid; gap: var(--s-5); min-width: 0; overflow-wrap: anywhere; }
.carried .page-header { display: grid; gap: var(--s-2); }
.carried .page-title, .carried .page-header h1 { font-size: var(--fs-24); font-weight: var(--w-strong); letter-spacing: -0.02em; line-height: var(--lh-tight); }
.carried .content-card {
  display: grid; gap: var(--s-3); padding: var(--s-5); min-width: 0;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--shadow-card);
}
.carried h2 { margin-top: var(--s-3); font-size: var(--fs-15); font-weight: var(--w-strong); letter-spacing: -0.01em; }
.carried .muted { color: var(--ink-2); }
.carried .page-header .muted, .carried .journey-field-note { font-size: var(--fs-13); }
.carried code { font-size: 0.92em; padding: 1px 5px; border-radius: 5px; background: var(--surface-3); overflow-wrap: anywhere; }
.carried .history-url code { font-size: var(--fs-13); }
.carried pre { overflow: auto; max-height: 24rem; padding: var(--s-3); border-radius: var(--r-control); background: var(--surface-2); font-size: var(--fs-12); white-space: pre-wrap; overflow-wrap: anywhere; }
.carried strong { font-weight: var(--w-strong); }

/* A refusal or a form error: amber, never red (red means a certain Fail result only). */
.carried .error { padding: var(--s-2) var(--s-3); border-radius: var(--r-control); background: var(--caution-tint); color: var(--caution-ink); font-weight: var(--w-ui); }

/* Forms: one labelled field per row, the console's control look. */
.carried form { display: grid; gap: var(--s-4); }
.carried form.inline-form { display: inline-flex; gap: var(--s-2); }
.carried .config-section { display: grid; gap: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--line); }
.carried .config-section > h2 { margin-top: 0; }
.carried .journey-field { display: grid; gap: 6px; max-width: 400px; }
.carried label { font-size: var(--fs-13); font-weight: var(--w-ui); color: var(--ink); }
.carried select, .carried input[type="text"], .carried input[type="email"], .carried input[type="tel"], .carried input[type="number"], .carried textarea {
  width: 100%; min-width: 0; height: 36px; padding: 0 12px; border: 1px solid var(--line-strong); border-radius: var(--r-control);
  background: var(--surface); color: var(--ink); font: inherit; font-size: var(--fs-14);
}
.carried textarea { height: auto; min-height: 8rem; padding: 8px 12px; line-height: 1.5; resize: vertical; }
.carried select {
  appearance: none; padding-right: 32px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%), linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-size: 5px 5px; background-position: right 16px center, right 11px center; background-repeat: no-repeat;
}
.carried select:focus-visible, .carried input:focus-visible, .carried textarea:focus-visible { outline: 2px solid var(--focus); outline-offset: 0; border-color: var(--focus); }

/* Buttons: the old classes on the console's button. */
.carried .btn { justify-self: start; border-color: var(--line-strong); background: var(--surface); }
.carried .btn-primary { border-color: transparent; background: var(--primary); color: var(--on-primary); }
.carried .btn-primary:hover { background: var(--primary-hover); }
.carried .btn-small { height: 30px; padding: 0 10px; font-size: var(--fs-13); }
.carried .btn:disabled { color: var(--ink-3); cursor: not-allowed; }

/* Tables and lists. */
.carried .data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-13); }
.carried .data-table th { padding: 8px var(--s-3); background: var(--surface-2); border-bottom: 1px solid var(--line); color: var(--ink-2); font-weight: var(--w-text); text-align: left; }
.carried .data-table td { padding: 8px var(--s-3); border-bottom: 1px solid var(--line); vertical-align: top; }
.carried ul { display: grid; gap: var(--s-2); }

@media (max-width: 760px) {
  .carried .content-card { padding: var(--s-4); }
  .carried .data-table { display: block; overflow-x: auto; }
}

/* ── 58-customise.css ── */
/* 58-customise — Customise mode (#2745 L-11, ADR-0076 amendment 2026-10-20): the bar and each
   widget's frame, for every page a user arranges (Link Health; the check report, #2826 Q3).
   Moved here from 60-health.css unchanged. */
/* ---------- Ported from gate3-rework-v2 rework.css § Customise.
   Zero JS: each frame's buttons are one form, and a step reloads the page at the widget's
   frame (scroll-margin keeps its controls clear of the top). The bar is not sticky: it would
   cover the frame a step returns to. A frame's preview is inert (no focus, no clicks) and
   fades out (the mask reads only alpha, so any opaque token serves). ---------- */
.wc-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-4); padding: var(--s-3) var(--s-4); border: 1px solid var(--accent); border-radius: var(--r-card); background: var(--accent-tint); color: var(--ink); }
.wc-bar__end { margin-left: auto; display: flex; flex-wrap: wrap; gap: var(--s-2); }
.wc-bar__form, .wc__form { display: contents; }
.wc { border-radius: calc(var(--r-card) + 4px); outline: 1.5px dashed var(--line-strong); outline-offset: 4px; scroll-margin-top: 96px; }
.wc__bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); margin-bottom: var(--s-2); }
.wc__name { margin: 0 auto 0 0; font-size: var(--fs-13); font-weight: var(--w-strong); color: var(--ink); }
.wc__note { margin-left: 6px; color: var(--ink-2); font-weight: var(--w-text); }
.wc .btn[disabled] { opacity: 0.45; cursor: not-allowed; }
.wc__body { max-height: 260px; overflow: hidden; -webkit-mask-image: linear-gradient(to bottom, var(--ink) 70%, transparent); mask-image: linear-gradient(to bottom, var(--ink) 70%, transparent); }
.wc--hidden { padding: var(--s-3) var(--s-4); background: var(--surface-2); border: 1px dashed var(--line-strong); border-radius: var(--r-card); outline: 0; }
.wc--hidden .wc__bar { margin: 0; }
.wc-empty { color: var(--ink-2); text-align: center; }
/* Its Customise link sits in a sentence: underlined, so it never relies on colour alone (axe link-in-text-block). */
.wc-empty a { text-decoration: underline; }
/* A phone: the widget's name on its own line, then Move up, Move down and Hide on one row. */
@media (max-width: 760px) {
  .wc__note { display: block; margin-left: 0; }
  .wc__name { flex-basis: 100%; }
}

/* ── 60-health.css ── */
/* 60-health — #2745 Gate 3 rework v2 (rulings L-01 to L-03, L-07 to L-09; ported from
   directions/gate3-rework-v2/rework2.css): Overall health's ring and its legend, the
   breakdowns by country, device and reason, Health over time as stacked daily counts,
   and the Country / Device filters. One palette for every chart: the result tokens, the
   same in the ring, the bars and the timeline; Couldn't be measured is the hatch. Each
   widget adapts to its own width through a named container. Zero client JS: a hover is
   data-tip or :has(); a click is a plain link into Reports. */

/* ---------- One swatch: a result's colour (legends, bars, timeline parts) ---------- */
.k { display: block; border-radius: 2px; }
.k--ok { background: var(--ok); }
.k--warn { background: var(--warn); }
.k--fail { background: var(--fail); }
.k--grey { background: var(--grey-hatch); box-shadow: inset 0 0 0 1px var(--grey); }

/* ---------- Overall health: the ring, the links by result, the door ---------- */
.oh { container: oh / inline-size; }
.oh__title { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s-3); }
.oh__body { display: grid; grid-template-columns: auto minmax(0, 440px) minmax(0, 360px); justify-content: space-between; gap: var(--s-5) var(--s-7); align-items: center; padding: var(--s-5) var(--s-6); }
.oh__key { display: grid; gap: 2px; }
/* The Health score on its own line (L-07, R-02), never beside a count of links. */
.oh__score { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3); padding: 0 8px var(--s-3); color: var(--ink-2); font-size: var(--fs-13); }
.oh__score b { color: var(--ink); font-size: var(--fs-18); font-weight: var(--w-strong); font-variant-numeric: tabular-nums; }
.oh__k { display: flex; justify-content: space-between; font-size: var(--fs-12); color: var(--ink-2); padding: 0 8px 4px; border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.oh__note { margin-top: var(--s-2); padding: 0 8px; font-size: var(--fs-12); color: var(--ink-2); }
.oh__foot { justify-content: space-between; }
.oh__door { align-self: stretch; display: flex; flex-direction: column; justify-content: center; gap: var(--s-2); padding: var(--s-4) var(--s-5); border-radius: var(--r-control); background: var(--surface-2); border: 1px solid var(--line); }
.oh__door b { font-size: var(--fs-18); font-weight: var(--w-strong); }
.oh__door p { color: var(--ink-2); font-size: var(--fs-13); }
.oh__door .btn { align-self: flex-start; }
@container oh (max-width: 900px) {
  .oh__body { grid-template-columns: auto minmax(0, 1fr); justify-content: stretch; }
  .oh__door { grid-column: 1 / -1; }
}
@container oh (max-width: 520px) {
  .oh__body { grid-template-columns: minmax(0, 1fr); justify-items: center; padding: var(--s-4); }
  .oh__key, .oh__door { width: 100%; }
}

.lg { display: grid; grid-template-columns: 12px 28px minmax(0, 1fr); align-items: center; gap: 8px; padding: 6px 8px; border-radius: 6px; color: var(--ink); font-size: var(--fs-14); }
.lg:not(.lg--zero):is(:hover, :focus-visible) { background: var(--surface-2); text-decoration: none; }
.lg .k { width: 12px; height: 12px; border-radius: 3px; }
.lg__n { font-weight: var(--w-strong); font-variant-numeric: tabular-nums; text-align: right; }
.lg__w { min-width: 0; }
.lg--zero { color: var(--ink-2); }
.lg--zero .k { opacity: 0.35; }

/* The ring is the score: green is the %, the rest split by the links that miss it. */
.ring { position: relative; width: 168px; height: 168px; flex: none; }
.ring svg { display: block; width: 100%; height: 100%; overflow: visible; }
.ring circle { fill: none; stroke-width: 16; transition: stroke-width 120ms ease-out; }
.ring__track { stroke: var(--surface-3); }
.ring__arc--ok circle { stroke: var(--ok); }
.ring__arc--warn circle { stroke: var(--warn); }
.ring__arc--fail circle { stroke: var(--fail); }
.ring__arc--grey circle { stroke: var(--hatch); }
.ring__hatch-bg { fill: var(--grey-hatch-bg); }
.ring__hatch-line { stroke: var(--grey); stroke-width: 2.2; }
a.ring__arc { cursor: pointer; outline: none; }
a.ring__arc:hover circle { stroke-width: 21; }
.ring__ctr { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; pointer-events: none; }
.ring__r { grid-area: 1 / 1; display: grid; gap: 2px; justify-items: center; width: 58%; }
.ring__r b { font-size: 34px; font-weight: 650; letter-spacing: -0.04em; line-height: 1; font-variant-numeric: tabular-nums; }
.ring__r small { font-size: var(--fs-11); color: var(--ink-2); line-height: 1.25; text-wrap: balance; }
.ring__r:not(.ring__r--base) { visibility: hidden; }
.oh:has(:is(.ring__arc, .lg:not(.lg--zero)):is(:hover, :focus-visible)) .ring__r--base { visibility: hidden; }
.oh:has(:is(.ring__arc--ok, .lg--ok:not(.lg--zero)):is(:hover, :focus-visible)) .ring__r--ok,
.oh:has(:is(.ring__arc--warn, .lg--warn:not(.lg--zero)):is(:hover, :focus-visible)) .ring__r--warn,
.oh:has(:is(.ring__arc--fail, .lg--fail:not(.lg--zero)):is(:hover, :focus-visible)) .ring__r--fail,
.oh:has(:is(.ring__arc--grey, .lg--grey:not(.lg--zero)):is(:hover, :focus-visible)) .ring__r--grey { visibility: visible; }
.oh:has(.lg--ok:not(.lg--zero):is(:hover, :focus-visible)) .ring__arc--ok circle,
.oh:has(.lg--warn:not(.lg--zero):is(:hover, :focus-visible)) .ring__arc--warn circle,
.oh:has(.lg--fail:not(.lg--zero):is(:hover, :focus-visible)) .ring__arc--fail circle,
.oh:has(.lg--grey:not(.lg--zero):is(:hover, :focus-visible)) .ring__arc--grey circle { stroke-width: 21; }

/* ---------- Breakdowns: country beside device; reason below (Advanced) ---------- */
.bd-pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s-5); align-items: stretch; }
.bd-pair > .card { display: flex; flex-direction: column; }
@media (max-width: 1100px) { .bd-pair { grid-template-columns: minmax(0, 1fr); } }
.bd { container: bd / inline-size; }
.bd .table { table-layout: fixed; }
.bd td { padding-block: 10px; vertical-align: middle; }
.bd--country th:nth-child(1), .bd--device th:nth-child(1) { width: 36%; }
.bd--country th:nth-child(2), .bd--device th:nth-child(2) { width: 30%; }
.bd--reason th:nth-child(2) { width: 72px; }
.bd--reason th:nth-child(3) { width: 72px; }
.bd--reason th:nth-child(4) { width: 30%; }
.bd__label { display: inline-flex; align-items: center; gap: 8px; }
.bd__res { display: inline-grid; color: var(--ink); }
.bd__res:hover { text-decoration: none; }
.bd__res:hover .word { text-decoration: underline; }
.bd__sub { margin-top: 2px; color: var(--ink-2); font-size: var(--fs-12); font-variant-numeric: tabular-nums; white-space: nowrap; }
.bd__reason { display: inline-flex; align-items: flex-start; gap: 6px; font-weight: var(--w-ui); color: var(--ink); }
a.bd__reason:hover { text-decoration: none; }
a.bd__reason:hover > span { text-decoration: underline; text-underline-offset: 3px; }
.bd__reason .glyph { margin-top: 3px; flex: none; }
.bd__owners { display: flex; flex-wrap: wrap; gap: 4px var(--s-4); }
.bd__owners a { font-weight: var(--w-ui); }
.bdbar { display: grid; grid-template-columns: minmax(0, 1fr) 28px; align-items: center; gap: 8px; }
.minibar { display: flex; gap: 2px; height: 10px; width: calc(var(--t) / var(--max) * 100%); }
.minibar__seg { display: block; flex: var(--n) 1 0; min-width: 4px; height: 100%; border-radius: 2px; }
.minibar__seg:is(:hover, :focus-visible) { outline: 2px solid var(--ink); outline-offset: 1px; }
.minibar__seg--ok { background: var(--ok); }
.minibar__seg--warn { background: var(--warn); }
.minibar__seg--fail { background: var(--fail); }
.minibar__seg--grey { background: var(--grey-hatch); box-shadow: inset 0 0 0 1px var(--grey); }
.bd__n { color: var(--ink-2); font-size: var(--fs-13); font-variant-numeric: tabular-nums; text-align: right; }
@container bd (max-width: 460px) {
  .bd .table { table-layout: auto; }
  .bd td, .bd th { padding-inline: 12px; }
  .bd--country th:nth-child(3), .bd--device th:nth-child(3) { width: 96px; }
  .bdbar { grid-template-columns: minmax(0, 1fr) 20px; }
}
/* A flush table that ends its card keeps the card's rounded corners on hover. */
.card > .bd:last-child > .table-wrap { border-radius: 0 0 calc(var(--r-card) - 1px) calc(var(--r-card) - 1px); }

/* ---------- Breakdown by link (#2986, Advanced): Overall health's ring, small, per link.
   Twelve tiles fill whole rows at 1440 (6), 1024 (4), 768 (3) and on a phone (2). ---------- */
.lb { container: lb / inline-size; }
.lb__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(184px, 1fr)); gap: var(--s-3); }
/* The word and base sit at each tile's foot, so a row's badges line up under names of one or two lines. */
.lt { min-width: 0; display: grid; grid-template-rows: auto 1fr auto; justify-items: center; gap: var(--s-2); padding: var(--s-4) var(--s-3) var(--s-3); border: 1px solid var(--line); border-radius: var(--r-control); text-align: center; }
.ring--sm { width: 80px; height: 80px; }
.ring--sm .ring__r { width: 64%; }
.ring--sm .ring__r b { font-size: var(--fs-14); letter-spacing: -0.02em; }
.lt__name { align-self: start; max-width: 100%; font-size: var(--fs-13); line-height: 1.3; }
.lt__res { display: grid; justify-items: center; gap: 4px; color: var(--ink); }
.lt__res:hover { text-decoration: none; }
.lt__res:hover .lt__base { text-decoration: underline; }
/* A long word (Couldn't be measured) wraps inside its pill on a phone's narrow tile. */
.lt .badge { height: auto; min-height: 22px; padding-block: 3px; white-space: normal; line-height: 1.2; text-align: left; }
.lt__base { color: var(--ink-2); font-size: var(--fs-12); font-variant-numeric: tabular-nums; }
.lb > .disclosure { margin-top: var(--s-4); }
.lb__empty { color: var(--ink-2); font-size: var(--fs-13); }
@container lb (max-width: 520px) {
  .lb__grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: var(--s-2); }
  .lt { padding: var(--s-3) var(--s-2) var(--s-2); }
  .ring--sm { width: 64px; height: 64px; }
  .ring--sm .ring__r b { font-size: var(--fs-13); }
}

/* ---------- Health over time: stacked counts, a tip and a link on every part ---------- */
.tl { --tl-h: 168px; padding: var(--s-4) var(--s-5) var(--s-5); container: tl / inline-size; }
.tl__plot, .tl__axis { display: grid; grid-template-columns: repeat(var(--days, 30), minmax(0, 1fr)); column-gap: 6px; }
.tl__plot { height: calc(var(--tl-h) + 22px); align-items: end; border-bottom: 1px solid var(--line-strong); }
.tl__col { display: flex; flex-direction: column; justify-content: flex-end; height: 100%; border-radius: 6px 6px 0 0; }
.tl__col.is-today { background: var(--surface-2); box-shadow: 0 0 0 4px var(--surface-2); }
.tl__tot { text-align: center; font-size: var(--fs-12); color: var(--ink-2); font-variant-numeric: tabular-nums; line-height: 18px; }
.tl__col.is-today .tl__tot { color: var(--ink); font-weight: var(--w-strong); }
.tl__stack { display: flex; flex-direction: column-reverse; gap: 2px; height: calc(var(--t) / var(--max) * var(--tl-h)); min-height: 4px; }
.tl__seg { flex: var(--n) 1 0; min-height: 4px; display: grid; place-items: center; border-radius: 3px; text-decoration: none; }
.tl__seg:is(:hover, :focus-visible) { outline: 2px solid var(--ink); outline-offset: 1px; z-index: 2; text-decoration: none; }
.tl__n { font-size: var(--fs-11); font-weight: var(--w-strong); line-height: 1; font-variant-numeric: tabular-nums; }
.tl__seg.k--ok .tl__n { color: var(--on-ok); }
.tl__seg.k--warn .tl__n { color: var(--on-warn); }
.tl__seg.k--fail .tl__n { color: var(--on-fail); }
.tl__seg.k--grey .tl__n { color: var(--grey-ink); }
.tl__empty { display: block; height: 3px; background: var(--surface-3); border-radius: 2px; }
.tl__axis { margin-top: 6px; font-size: var(--fs-11); color: var(--ink-2); text-align: center; font-variant-numeric: tabular-nums; line-height: 1.25; }
.tl__axis > span, .tl__wd { display: block; }
.tl__wd { color: var(--ink-2); }
.tl__axis .is-today { color: var(--ink); font-weight: var(--w-strong); }
/* Every day's total in a row over the plot: shown only where a column is too thin for its
   number (a phone), each total centred on its own column, every other one a line lower so
   neighbours never touch; today's last, on the lower line, next to the plot. */
.tl__tots { display: none; }
.tl__legend { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); margin-top: var(--s-4); font-size: var(--fs-13); color: var(--ink-2); }
.tl__legend > span { display: inline-flex; align-items: center; gap: 6px; }
.tl__legend .k { width: 12px; height: 12px; border-radius: 3px; }
.tl__how { color: var(--ink-2); }
@container tl (max-width: 560px) {
  .tl { padding-inline: var(--s-3); }
  .tl__plot, .tl__axis { column-gap: 3px; }
  .tl__wd, .tl__n { display: none; }
  .tl__tot { font-size: 10px; }
}
/* 30 days on a phone (S-03): a column is too narrow for every date and for a total on it.
   Every 7th date back from today keeps its label (today, a week ago ...); every total moves
   to the row over the plot (QA 2026-10-22 #11: the legend promises a number on top). */
@container tl (max-width: 440px) {
  .tl__plot, .tl__axis, .tl__tots { column-gap: 2px; }
  .tl__col .tl__tot, .tl__axis > span { visibility: hidden; }
  .tl__axis > span:nth-last-child(7n+1) { visibility: visible; }
  .tl__tots { position: relative; z-index: 1; display: grid; grid-template-columns: repeat(var(--days, 30), minmax(0, 1fr)); height: 26px; margin-bottom: -18px; font-size: 10px; line-height: 13px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
  .tl__tots > span { justify-self: center; align-self: start; white-space: nowrap; }
  .tl__tots > span:nth-last-child(odd) { align-self: end; }
  .tl__tots > .is-today { color: var(--ink); font-weight: var(--w-strong); }
}

/* ---------- Filters (Advanced): Country and Device recompute every widget ---------- */
.lh-filters { display: grid; gap: var(--s-2); }
.lh-on { display: flex; flex-wrap: wrap; align-items: center; gap: 6px var(--s-3); padding: var(--s-2) var(--s-3); border-radius: var(--r-control); background: var(--accent-tint); border: 1px solid var(--accent); color: var(--ink); font-size: var(--fs-13); }
.lh-on a { font-weight: var(--w-ui); }

/* Customise mode (#2745 L-11): the frames are 58-customise.css; the breakdowns' pair keeps
   two frames side by side, without their notes. */
.bd-pair > .wc { min-width: 0; }
.bd-pair > .wc .wc__note { display: none; }

/* ── 70-reports.css ── */
/* 70-reports — #2745 L-04, L-05, R-04 and the partner's fixes of 2026-10-21. The two
   views, the way back to Link Health, the scope with both counts, the pages named by
   their days, and a day's runs: one dry line per run (Finished in Advanced only, Link,
   Run, the badge alone, Score, View breakdown and View report; Simple has no time,
   ruling 4), fixed columns and tabular figures. View breakdown is a <details> whose
   open state shows the sub-row under its line (`:has()`, zero client JS). The lines
   fit the table's own width (a container query): Advanced's two buttons stack when it
   narrows, and the lines stack on a phone. A run's live progress (UNSURE-5): the count, the
   refresh sentence, the result with its two buttons, and one row per check. Colours come
   from the role tokens only. */

/* ---------- The two views: All results, Needs attention ---------- */
.rep-tabs { display: flex; flex-wrap: wrap; gap: var(--s-1); border-bottom: 1px solid var(--line); }
.rep-tabs a { display: inline-flex; align-items: center; gap: 6px; padding: 10px var(--s-3); color: var(--ink-2); font-weight: var(--w-ui); box-shadow: inset 0 -2px 0 transparent; }
.rep-tabs a:hover { color: var(--ink); text-decoration: none; }
.rep-tabs a[aria-current="page"] { color: var(--ink); box-shadow: inset 0 -2px 0 var(--accent); }
.rep-tabs__n { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--r-pill); background: var(--surface-3); color: var(--ink); font-size: var(--fs-12); font-variant-numeric: tabular-nums; }

.rep-back { font-size: var(--fs-13); }
.rep-back a { font-weight: var(--w-ui); }
.rep-back a::before { content: "← "; content: "← " / ""; }
.rep-empty { color: var(--ink-2); text-align: center; }
.rep-empty + .rep-empty { margin-top: var(--s-3); } /* #2974: the way to Link Admin under the sentence */

/* ---------- The scope with both counts; the pages, named by their days ---------- */
.rep-sum { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-1) var(--s-3); }
.rep-sum b { font-weight: var(--w-ui); }
.rep-pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--s-2) var(--s-4); }
.rep-pager__at { color: var(--ink-2); font-size: var(--fs-13); font-variant-numeric: tabular-nums; }

/* ---------- A day's runs ----------
   One set of fixed column widths for every day's table (QA 2026-10-22 #13): each day is
   its own table, so a fixed layout keeps Finished (Advanced), Run, Result, Score and the
   button in the same place in every group; Link takes the rest. The breakdown's sub-lines use the
   same tracks, so where a check ran sits under Link, its result under Result, why under
   Score and each check's View report under View breakdown (#15). The two share one width
   (#14, S-01; #2826 renamed them, and retired the run's own Run report beside them). */
.run-table {
  --run-btn: 8rem;
  --rc-when: 112px; --rc-kind: 116px; --rc-result: 172px; --rc-score: 116px;
  --rc-act: calc(var(--run-btn) + 2 * var(--s-4));
  --run-cols: minmax(0, 1fr) var(--rc-kind) var(--rc-result) var(--rc-score) var(--rc-act);
  table-layout: fixed;
}
.run-table--adv { --run-cols: var(--rc-when) minmax(0, 1fr) var(--rc-kind) var(--rc-result) var(--rc-score) var(--rc-act); }
.run-line > td { vertical-align: top; }
.run-table--adv th:nth-child(1) { width: var(--rc-when); }
.run-table:not(.run-table--adv) th:nth-child(2), .run-table--adv th:nth-child(3) { width: var(--rc-kind); }
.run-table:not(.run-table--adv) th:nth-child(3), .run-table--adv th:nth-child(4) { width: var(--rc-result); }
.run-table:not(.run-table--adv) th:nth-child(4), .run-table--adv th:nth-child(5) { width: var(--rc-score); }
.run-table th:last-child { width: var(--rc-act); }
.run-td-when, .run-td-kind, .run-td-result, .run-td-score { white-space: nowrap; font-variant-numeric: tabular-nums; }
.run-td-when, .run-td-kind { color: var(--ink-2); font-size: var(--fs-13); }
.run-td-link { overflow-wrap: anywhere; }
.run-link { color: var(--ink); font-weight: var(--w-ui); }
a.run-link:hover { color: var(--link); }
.run-running { color: var(--ink-2); font-size: var(--fs-13); font-weight: var(--w-ui); }
/* A run still going: its Running opens its live progress page (#1562, #2434). */
a.run-running:hover { color: var(--link); }
.run-score { color: var(--ink-2); font-size: var(--fs-13); font-variant-numeric: tabular-nums; }
.run-score b { color: var(--ink); font-weight: var(--w-ui); }
.run-td-score .run-why { white-space: normal; }
.run-why { color: var(--ink-2); font-size: var(--fs-13); overflow-wrap: anywhere; }
.run-td-act { text-align: right; }
.run-open { display: inline-grid; grid-auto-flow: column; grid-auto-columns: var(--run-btn); gap: var(--s-1); vertical-align: top; }
.run-open .btn, .run-checks .btn { width: var(--run-btn); }
.run-bd > summary { list-style: none; }
.run-bd > summary::-webkit-details-marker { display: none; }
.run-bd[open] > summary { background: var(--surface-3); }
/* The breakdown: the sub-row under its line shows while its View breakdown is open. */
.run-table tr.run-sub { display: none; }
.run-table tr.run-line:has(.run-bd[open]) + tr.run-sub { display: table-row; }
.run-table tr.run-line:has(.run-bd[open]) > td { border-bottom-color: transparent; }
.run-sub > td { padding: 0; background: var(--surface-2); }
.run-checks { list-style: none; margin: 0; padding: var(--s-2) 0; display: grid; gap: 6px; }
/* A sub-line on the line's own tracks: each part takes a cell's padding. */
.run-checks li { display: grid; grid-template-columns: var(--run-cols); align-items: center; }
.run-checks li > :is(.run-at, .run-why, .run-running) { padding-inline: var(--s-4); min-width: 0; }
.run-checks li > :is(.badge, .btn) { margin-inline: var(--s-4); }
.run-at { grid-column: 1 / span 2; font-size: var(--fs-13); font-weight: var(--w-ui); }
.run-checks li > :is(.badge, .run-running) { grid-column: 3; justify-self: start; }
.run-checks li > .run-why { grid-column: 4 / -1; grid-row: 1; }
.run-checks li > .btn { grid-column: -2; grid-row: 1; justify-self: end; }
/* A check's View report shares the buttons' column: why stops short of it. */
.run-checks li:has(> .btn) > .run-why { padding-right: calc(var(--run-btn) + 2 * var(--s-4)); }
.run-table--adv .run-at { grid-column: 2 / span 2; }
.run-table--adv .run-checks li > :is(.badge, .run-running) { grid-column: 4; }
.run-table--adv .run-checks li > .run-why { grid-column: 5 / -1; }
/* The wrapper is the containing block, so the hidden column label stays inside its clip,
   and the container the lines fit to: the table's own width, whatever the page around it. */
.table-wrap:has(> .run-table) { position: relative; container: runs / inline-size; }
/* Narrower still (a phone, a narrow window): each line stacks. */
@container runs (max-width: 939px) {
  .run-table, .run-table tbody { display: block; }
  .run-table thead { display: none; }
  .run-table tr.run-line { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 12px; padding: 12px 16px; border-bottom: 1px solid var(--line); }
  .run-table tr.run-line:has(.run-bd[open]) + tr.run-sub { display: block; }
  .run-table tbody tr:last-child { border-bottom: 0; }
  .run-table td { display: block; padding: 0; border: 0; }
  /* A stacked line says what its time is: Finished, in Advanced (QA 2026-10-22 #12). */
  .run-table td[data-k]::before { content: attr(data-k); margin-right: 6px; color: var(--ink-2); font-size: var(--fs-12); }
  .run-table tr.run-line > td:first-child { grid-column: 1; grid-row: 1; }
  .run-table td.run-td-result { grid-column: 2; grid-row: 1; justify-self: end; }
  .run-table tr.run-line > td:not(:first-child):not(.run-td-result) { grid-column: 1 / -1; }
  .run-table td.run-td-act { text-align: left; }
  .run-table .run-open { grid-auto-flow: column; grid-template-columns: none; }
  .run-sub > td { padding: 0 16px 12px; border-bottom: 1px solid var(--line); }
  .run-checks li { grid-template-columns: minmax(0, 1fr) auto; gap: var(--s-1) var(--s-3); align-items: baseline; }
  .run-table .run-checks li > :is(.run-at, .run-why, .run-running) { padding-inline: 0; }
  .run-table .run-checks li > :is(.badge, .btn) { margin-inline: 0; }
  .run-table .run-checks li > .run-at { grid-column: 1; }
  .run-table .run-checks li > :is(.badge, .run-running) { grid-column: 2; }
  .run-table .run-checks li > .run-why { grid-column: 1 / -1; grid-row: auto; }
  .run-table .run-checks li > .btn { grid-column: 1 / -1; grid-row: auto; justify-self: start; }
  .run-table td.table__empty { grid-column: 1 / -1; padding: 12px 16px; }
  .run-table tbody tr:hover td { background: none; }
}

/* ---------- A run's live progress (UNSURE-5): the page Run now opens ----------
   Today's page in the console look: the count, the refresh sentence while in flight, the
   result (its glyph and today's word) with its check's report (a one-check run, #2826) and
   the way back, then one row per
   check, its mark beside its state word. */
.prog { display: grid; gap: var(--s-2); justify-items: start; }
.prog__count { font-weight: var(--w-ui); font-variant-numeric: tabular-nums; }
.prog__eta, .prog__note { color: var(--ink-2); font-size: var(--fs-13); }
.prog__result { display: inline-flex; align-items: center; gap: var(--s-2); font-size: var(--fs-18); font-weight: var(--w-ui); }
.prog__result .glyph { width: 20px; height: 20px; vertical-align: 0; }
.prog__actions { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.prog-table td:first-child { overflow-wrap: anywhere; }
.prog__state { display: inline-flex; align-items: center; gap: 6px; }
.prog__state--quiet { color: var(--ink-2); }

/* ── 80-account.css ── */
/* 80-account — #2745 step 5: the Account page's cards (ui/widgets/account). Two columns
   on a wide screen, one on a phone; each card's parts stacked with one rhythm. Colours
   come from the role tokens only: the refusal is ink with a mark, never red (red is a
   certain Fail). Holds its own narrow-screen rules.
   One family (#2745 review, m 2026-10-24): a row's cards share its height (the grid
   stretches them), each card's body fills it and its foot (the actions) keeps to the
   bottom edge, so the actions of a row line up. */

.acct-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-5); }
/* An odd number of cards: the right column's last card spans two rows, so the last card
   sits beside it under the left column and no row ends in a hole (an admin's User
   management beside Account access and Daily limit; Sign-in security beside Profile and
   Account access when there is no Daily limit). */
.acct-grid > .card:nth-child(even):nth-last-child(2) { grid-row: span 2; }
.acct-grid > .card { display: flex; flex-direction: column; }
.acct-grid > .card > .card__body { flex: 1; display: flex; flex-direction: column; }
.acct-body { flex: 1; display: flex; flex-direction: column; gap: var(--s-4); }
.acct-body > * { margin-top: 0; }
/* The foot: at least a button's height (12-primitives .btn), so a link alone there (Change
   the time zone in Settings) reads on the line of the buttons beside it. */
.acct-foot { margin-top: auto; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); min-height: 36px; }
.acct-foot > .acct-reset { flex: 1 1 100%; }
/* Facts in even columns, one where the card is narrow: a wrapped row never leaves a fact
   under another with a hairline beside nothing (the facts' own narrow-screen look). */
.acct-body .facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); gap: var(--s-3) var(--s-5); }
.acct-body .facts > div { border: 0; margin: 0; padding: 0; }
.acct-body .facts dd { white-space: normal; overflow-wrap: anywhere; }

/* The temporary password, shown once: kept whole on its own line when it does not fit,
   selectable in one click, never clipped (only a password longer than a line wraps). */
.acct-secret { display: inline-block; max-width: 100%; vertical-align: top; font: inherit; font-weight: var(--w-strong); font-variant-numeric: tabular-nums slashed-zero; user-select: all; overflow-wrap: anywhere; }
.notice strong { overflow-wrap: anywhere; }

.acct-users { display: grid; gap: 4px; }
.acct-users__name { font-weight: var(--w-ui); overflow-wrap: anywhere; }
/* #3129: what each person sees on its own line under them, and Role and access after it. */
.acct-users__access { display: block; color: var(--ink-2); font-size: var(--fs-13); overflow-wrap: anywhere; }
.acct-users .btn { margin: var(--s-1) 0 var(--s-2); }

.acct-reset, .acct-contact { display: grid; gap: var(--s-3); justify-items: start; }
.acct-reset > .field, .acct-contact > .field { width: 100%; }

/* The 2FA-disable refusal: ink with the forms family's mark. */
.acct-refusal { display: flex; align-items: flex-start; gap: 6px; font-weight: var(--w-ui); }
.acct-refusal::before {
  content: "!"; flex: none; display: inline-grid; place-items: center; width: 16px; height: 16px; margin-top: 2px;
  border-radius: 50%; background: var(--ink); color: var(--surface); font-size: var(--fs-11); font-weight: var(--w-strong); line-height: 1;
}

/* Workspaces (#1897): its own card under the grid, a client's admin's. Each table in a bordered
   frame whose rows stack on a narrow card (the name first, then the other cells on one wrapping
   line, each after its phone label), as User management's do (87-operator.css). Rename and
   Archive sit at the row's end; Bring back is a POST form in its cell. */
.acct-ws { container: acct-ws / inline-size; border: 1px solid var(--line); border-radius: var(--r-card); }
.acct-ws__name { font-weight: var(--w-strong); overflow-wrap: anywhere; }
.acct-ws__actions { display: flex; justify-content: flex-end; gap: var(--s-2); }
.acct-ws__form { display: flex; justify-content: flex-end; margin: 0; }
.acct-ws .table td:last-child { width: 1%; white-space: nowrap; }
.acct-body > .disclosure .acct-ws { margin-top: var(--s-3); }
@container acct-ws (max-width: 520px) {
  .acct-ws thead { display: none; }
  .acct-ws .table, .acct-ws tbody, .acct-ws tr, .acct-ws td { display: block; width: auto; }
  .acct-ws tr { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
  .acct-ws tbody tr:last-child { border-bottom: 0; }
  .acct-ws .table td { padding: 0; border: 0; text-align: left; }
  .acct-ws .table td + td { display: inline-block; margin-top: 6px; margin-right: var(--s-4); }
  .acct-ws .table td:last-child { display: block; width: auto; margin: var(--s-2) 0 0; }
  .acct-ws__actions, .acct-ws__form { flex-wrap: wrap; justify-content: flex-start; }
  .acct-ws td[data-k]::before { content: attr(data-k); margin-right: 6px; color: var(--ink-2); font-size: var(--fs-12); }
  .acct-ws tbody tr:hover td { background: none; }
}

@media (max-width: 760px) {
  .acct-grid { grid-template-columns: 1fr; gap: var(--s-4); }
  .acct-grid > .card:nth-child(even):nth-last-child(2) { grid-row: auto; }
  .acct-body .facts { grid-template-columns: 1fr; } /* a username or email keeps its line */
}

/* ── 85-sign-in.css ── */
/* 85-sign-in — #2745 step 5: the plain-card layout (the product name over one
   centred card, no header controls) and the sign-in cards inside it: Sign in, the
   two-factor challenge, Forgot password, Change password, Set up two-factor,
   the session gate's dead ends, the error pages (Page not found, Access
   denied: the plain card, or one message card in the console layout) and
   Choose a workspace (the workspace list at /). Colours
   come from the role tokens only. A form error is the forms family's ink and
   mark, never red: red is only for a certain Fail result. Holds its own
   narrow-screen rules. */

/* ---------- Plain layout ---------- */
.plain { display: flex; flex-direction: column; align-items: center; gap: var(--s-5); padding: clamp(var(--s-6), 10vh, 112px) var(--page-margin) var(--s-8); }
.plain__head { display: flex; justify-content: center; max-width: 100%; }
.plain__brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); font-size: var(--fs-15); font-weight: var(--w-strong); letter-spacing: -0.01em; text-align: center; }
.plain__mark { display: block; flex: none; width: 20px; height: 20px; color: var(--ink); }
.plain__mark svg { display: block; width: 100%; height: 100%; }
.plain__main { width: 100%; max-width: 440px; }
/* The wide card: a plain page that holds a table (the operator console, #2745 Gate 4). */
.plain__main--wide { max-width: 1040px; }
.plain__card { padding: var(--s-6); }

/* ---------- The card: title, form, foot ---------- */
.signin__title { font-size: var(--fs-24); font-weight: var(--w-strong); letter-spacing: -0.02em; line-height: var(--lh-tight); overflow-wrap: anywhere; }
.signin__sub { margin-top: var(--s-2); color: var(--ink-2); }
.signin__text { margin-top: var(--s-3); }
.signin__text code { font-family: var(--font); font-size: 0.92em; font-weight: var(--w-ui); padding: 1px 5px; border-radius: 5px; background: var(--surface-3); white-space: nowrap; }
.signin__form, .account-2fa-form { display: grid; gap: var(--s-4); margin-top: var(--s-5); }
.signin__form .field, .account-2fa-form .field { max-width: none; }
.signin__row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-2) var(--s-4); font-size: var(--fs-13); }
.signin__actions { margin-top: var(--s-5); }
.signin__form .signin__actions, .account-2fa-form .signin__actions { margin-top: var(--s-1); }
.signin__actions .btn { width: 100%; height: 40px; }
.signin__foot { margin-top: var(--s-5); font-size: var(--fs-13); }
.signin__foot + .signin__foot { margin-top: var(--s-3); }

/* ---------- Set up two-factor: Scan, then Confirm ---------- */
.signin__step { margin-top: var(--s-5); padding-top: var(--s-5); border-top: 1px solid var(--line); }
.signin__step-title { font-size: var(--fs-15); font-weight: var(--w-strong); letter-spacing: -0.01em; }
.signin__step .account-2fa-form { margin-top: var(--s-3); }
/* The QR keeps its own light ground and dark modules in every preset: scanners need them. */
.twofa-qr { width: 176px; height: 176px; margin-top: var(--s-3); overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-chip); }
.twofa-qr svg { display: block; width: 100%; height: 100%; }
.signin__hint { margin-top: var(--s-3); font-size: var(--fs-13); }
.twofa-secret {
  display: inline-block; max-width: 100%; margin-top: var(--s-1); padding: 4px 8px; border-radius: var(--r-chip); background: var(--surface-3);
  font-family: var(--font); font-size: var(--fs-14); font-weight: var(--w-strong); letter-spacing: 0.08em; overflow-wrap: anywhere;
}

/* ---------- Choose a workspace: one line per workspace, the whole line its link ---------- */
.workspace-list { margin-top: var(--s-4); border-top: 1px solid var(--line); }
.workspace-list li { border-bottom: 1px solid var(--line); }
.workspace-list a { display: block; padding: var(--s-3) 0; font-weight: var(--w-ui); overflow-wrap: anywhere; }

/* ---------- The error pages' message card (inside a workspace) ---------- */
.error__home { margin-top: var(--s-3); }
/* The hosted report's refusals (#3021): sentences, the reports the check has, the evidence keys. */
.error__text { overflow-wrap: anywhere; }
.error__text + .error__text { margin-top: var(--s-3); }
.error__text code { font-size: 0.92em; padding: 1px 5px; border-radius: 5px; background: var(--surface-3); }
.error__list { display: grid; gap: var(--s-2); margin-top: var(--s-2); overflow-wrap: anywhere; }
/* A link inside a sentence is underlined, not told apart by colour alone (axe link-in-text-block). */
.error__list a { text-decoration: underline; text-underline-offset: 2px; }
.error__detail {
  margin-top: var(--s-3); padding: var(--s-3); overflow: auto; max-height: 24rem; border-radius: var(--r-control);
  background: var(--surface-2); font-size: var(--fs-12); white-space: pre-wrap; overflow-wrap: anywhere;
}

/* ---------- Narrow screens ---------- */
@media (max-width: 760px) {
  .plain { padding-top: var(--s-6); gap: var(--s-4); }
  .plain__card { padding: var(--s-5); }
}

/* ── 87-operator.css ── */
/* 87-operator — #2745 Gate 4: the operator console's plain cards (Choose a customer
   and a customer's workspaces reuse Choose a workspace's lines, 85-sign-in) and Reason Code
   Coverage: its counts on one wrapping line, then the table, which scrolls inside the
   card on a narrow screen. A status is plain ink: colour means a result only. */

.opcodes__tally { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-4); margin-top: var(--s-4); font-size: var(--fs-13); color: var(--ink-2); }
.opcodes__tally strong { color: var(--ink); font-weight: var(--w-strong); }
.opcodes { margin-top: var(--s-4); border: 1px solid var(--line); border-radius: var(--r-card); }
.opcodes .table td { white-space: nowrap; }

/* ---------- Recent activity, the platform log (#2745 L-06): Link Health's old Recent
   activity lines with the customer and workspace; the link name leads the Detail cell. The
   rows stack when the card is narrow: when and workspace, the event, then the detail. ---------- */
.activity { container: activity / inline-size; margin-top: var(--s-4); border: 1px solid var(--line); border-radius: var(--r-card); }
.activity .table { table-layout: fixed; }
.activity th:nth-child(1) { width: 132px; }
.activity th:nth-child(2) { width: 220px; }
.activity th:nth-child(3) { width: 220px; }
.activity__when { font-variant-numeric: tabular-nums; white-space: nowrap; font-size: var(--fs-13); }
.activity__workspace { display: block; color: var(--ink-2); font-size: var(--fs-13); overflow-wrap: anywhere; }
.activity__ev { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; font-weight: var(--w-ui); }
.activity__link { display: block; color: var(--ink); font-weight: var(--w-strong); overflow-wrap: anywhere; }
a.activity__link:hover { color: var(--link); }
.activity__rest { display: block; margin-top: 2px; color: var(--ink-2); font-size: var(--fs-13); overflow-wrap: anywhere; }
.activity__rest:first-child { margin-top: 0; color: var(--ink); font-size: inherit; }
@container activity (max-width: 700px) {
  .activity thead { display: none; }
  .activity .table, .activity tbody, .activity tr, .activity td { display: block; width: auto; }
  .activity tr { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
  .activity tbody tr:last-child { border-bottom: 0; }
  .activity td { padding: 0; border: 0; }
  .activity td:nth-child(1), .activity td:nth-child(2) { display: inline-block; margin-right: var(--s-4); vertical-align: baseline; }
  .activity td:nth-child(2) .activity__workspace { display: inline; }
  .activity td:nth-child(3) { margin-top: 6px; }
  .activity td:nth-child(4) { margin-top: 6px; }
  .activity tbody tr:hover td { background: none; }
}

/* ---------- User management (#3078): the accounts list, an account's page and its forms.
   A section's heading with its one action at the right; each table in a bordered frame
   whose rows stack on a narrow card (the name first, then the other cells on one wrapping
   line, each after its phone label); the facts wrap, so a long contact email never pushes
   the card sideways. A Test account chip and the statuses are plain ink. ---------- */
.um-notice { margin-top: var(--s-4); }
.um-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-2) var(--s-4); margin-top: var(--s-6); }
.um-head__title { font-size: var(--fs-15); font-weight: var(--w-strong); letter-spacing: -0.01em; }
.um-table { container: um-table / inline-size; margin-top: var(--s-3); border: 1px solid var(--line); border-radius: var(--r-card); }
.um-table .table td { vertical-align: top; }
.um-name { color: var(--ink); font-weight: var(--w-strong); overflow-wrap: anywhere; }
a.um-name:hover { color: var(--link); }
.um-name + .code { margin-left: 6px; vertical-align: 1px; white-space: nowrap; }
.um-sub { display: block; margin-top: 2px; color: var(--ink-2); font-size: var(--fs-13); overflow-wrap: anywhere; }
.um-archived { margin-top: var(--s-5); }
.um-facts .facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-3) var(--s-5); }
.um-facts .facts > div { margin: 0; padding: 0; border: 0; }
.um-facts .facts dd { white-space: normal; overflow-wrap: anywhere; }
@media (max-width: 600px) { .um-facts .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.um-quiet { margin-top: var(--s-2); color: var(--ink-2); font-size: var(--fs-13); }
.um-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-4); }
.um-inline { display: inline-flex; margin: 0; }
.um-form { display: grid; gap: var(--s-4); margin-top: var(--s-5); }
.um-form .field { max-width: none; }
.um-effects { margin-top: var(--s-4); }
.um-effects + form { margin-top: var(--s-5); }
/* A user's role and the workspaces they see (#3129, widgets/operator/user-access.ts): each choice
   on its own line with what it means; the ticks only under Only these, and no access at all while
   Admin is chosen, where the one line saying why shows instead (:has(), zero client JS). */
.um-choices { display: grid; gap: var(--s-2); }
.um-access__ticks { display: none; margin: var(--s-3) 0 0 26px; padding: 0; border: 0; min-width: 0; }
.um-access:has(input[name="access"][value="chosen"]:checked) .um-access__ticks { display: grid; gap: var(--s-2); }
/* A long workspace name wraps beside its box, the box on its first line (as .check--long). */
.um-access__ticks .check { display: flex; align-items: flex-start; white-space: normal; line-height: 1.45; overflow-wrap: anywhere; }
.um-access__ticks .check > input { margin-top: 2px; }
.um-access-admin { display: none; margin-top: 0; }
.um-form:has(input[name="role"][value="admin"]:checked) .um-access { display: none; }
.um-form:has(input[name="role"][value="admin"]:checked) .um-access-admin { display: block; }
/* #3129: on Archive this workspace?, the users it would leave with no workspace, under its effects. */
.um-left { margin-top: var(--s-4); }
.um-left + .um-effects { margin-top: var(--s-2); }
@container um-table (max-width: 600px) {
  .um-table thead { display: none; }
  .um-table .table, .um-table tbody, .um-table tr, .um-table td { display: block; width: auto; }
  .um-table tr { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
  .um-table tbody tr:last-child { border-bottom: 0; }
  .um-table td { padding: 0; border: 0; text-align: left; }
  .um-table td + td { display: inline-block; margin-top: 6px; margin-right: var(--s-4); }
  .um-table td[data-k]::before { content: attr(data-k); margin-right: 6px; color: var(--ink-2); font-size: var(--fs-12); }
  .um-table td.table__empty { padding-block: var(--s-4); text-align: center; }
  .um-table tbody tr:hover td { background: none; }
}

/* ---------- Platform monitoring (#3112): the wide card's sections, each a heading and its
   facts, stacked so a later part is one more section. What needs a look is one amber notice,
   a line per flag; a flagged machine's state is bold ink with the info glyph (colour means a
   result only). The machines' table sits in a bordered frame whose rows stack on a narrow
   card: the machine first, then each fact after its phone label. ---------- */
.mon-ok { margin-top: var(--s-4); color: var(--ink-2); }
.mon-notice { margin-top: var(--s-4); }
.mon-notice__title { display: block; font-weight: var(--w-strong); }
.mon-line { display: block; margin-top: 2px; }
.mon-section { margin-top: var(--s-6); }
.mon-head { font-size: var(--fs-15); font-weight: var(--w-strong); letter-spacing: -0.01em; }
.mon-quiet { margin-top: var(--s-2); color: var(--ink-2); font-size: var(--fs-13); }
.mon-missing, .mon-note { display: flex; align-items: flex-start; gap: 6px; margin-top: var(--s-2); }
.mon-missing .icon, .mon-note .icon { flex: none; margin-top: 2px; color: var(--caution-ink); }
.mon-missing strong { font-weight: var(--w-strong); }
/* The Checks schedule (#3124): three parts under one heading, each a sub-heading; a start's
   accounts one per line; the scheduler's stop one sentence with the info glyph (a fact). */
.mon-subhead { margin-top: var(--s-5); font-size: var(--fs-14); font-weight: var(--w-strong); }
.mon-head + .mon-subhead { margin-top: var(--s-3); }
.mon-note { color: var(--ink); }
.mon-entries, .mon-entry { display: block; overflow-wrap: anywhere; }
.mon-entry + .mon-entry { margin-top: 2px; }
/* Countries and VPN (#3131): a country's providers numbered in the order a check tries them,
   one line each with its 7 days. */
.mon-providers { padding-left: 1.5em; list-style: decimal; }
.mon-providers li { overflow-wrap: anywhere; }
.mon-providers li + li { margin-top: 2px; }
.mon-provider { color: var(--ink); font-weight: var(--w-strong); }
.mon-table .table .mon-providers-cell { min-width: 20em; }
.mon-flag { display: inline-flex; align-items: flex-start; gap: 6px; color: var(--ink); font-weight: var(--w-strong); }
.mon-flag .icon { flex: none; margin-top: 2px; color: var(--caution-ink); }
.mon-table { container: mon-table / inline-size; margin-top: var(--s-3); border: 1px solid var(--line); border-radius: var(--r-card); }
.mon-table .table td { vertical-align: top; }
.mon-table .table td:first-child { min-width: 8em; }
.mon-table .table .mon-state { min-width: 12.5em; }
.mon-name { display: block; color: var(--ink); font-weight: var(--w-strong); }
.mon-value { display: block; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mon-sub { display: block; margin-top: 2px; color: var(--ink-2); font-size: var(--fs-13); overflow-wrap: anywhere; }
.mon-facts .facts dd a { text-decoration: underline; text-underline-offset: 2px; }
@container mon-table (max-width: 760px) {
  .mon-table thead { display: none; }
  .mon-table .table, .mon-table tbody, .mon-table tr, .mon-table td { display: block; width: auto; }
  .mon-table tr { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); }
  .mon-table tbody tr:last-child { border-bottom: 0; }
  .mon-table td, .mon-table .table td:first-child, .mon-table .table .mon-state { min-width: 0; padding: 0; border: 0; text-align: left; }
  .mon-table td + td { display: grid; grid-template-columns: 9.5em minmax(0, 1fr); column-gap: var(--s-2); margin-top: 6px; }
  .mon-table td + td > * { grid-column: 2; }
  .mon-table td[data-k]::before { content: attr(data-k); grid-column: 1; grid-row: 1; color: var(--ink-2); font-size: var(--fs-13); }
  .mon-table td.table__empty { padding-block: var(--s-4); text-align: center; }
  /* Countries and VPN's tunnel and providers: the label above, the value the card's width. */
  .mon-table .table .mon-stack { min-width: 0; grid-template-columns: minmax(0, 1fr); }
  .mon-table td.mon-stack > * { grid-column: 1; }
  .mon-table tbody tr:hover td { background: none; }
}
/* The users (#3078 slice 3): "(you)" beside the viewer's own line, the pointer to the
   platform admins, and the temporary password shown once in its own framed box. */
.um-you { color: var(--ink-2); font-size: var(--fs-13); }
.um-admins { margin-top: var(--s-5); }
.um-admins a, .um-facts dd a { text-decoration: underline; text-underline-offset: 2px; }
.um-secret { margin-top: var(--s-5); padding: var(--s-4); border: 1px solid var(--line-strong); border-radius: var(--r-card); background: var(--surface-2); }
.um-secret__label { color: var(--ink-2); font-size: var(--fs-12); }
.um-secret .acct-secret { margin-top: var(--s-1); font-size: var(--fs-15); }
/* The change history (#3078 slice 4): when, who and what, after the rest of the page. */
.um-history .table td:first-child { white-space: nowrap; font-variant-numeric: tabular-nums; }
.um-who, .um-what { overflow-wrap: anywhere; }
.um-who { color: var(--ink-2); }
/* An account's workspaces (#3078 item 6): Rename and Archive at the row's end, Bring back a POST
   form in its cell; on a narrow card they wrap on their own line under the row. */
.um-ws .table td { vertical-align: middle; }
.um-cell-actions { width: 1%; white-space: nowrap; }
.um-row-actions { display: flex; justify-content: flex-end; gap: var(--s-2); }
@container um-table (max-width: 600px) {
  .um-table td.um-cell-actions { display: block; width: auto; margin: var(--s-2) 0 0; }
  .um-row-actions { flex-wrap: wrap; justify-content: flex-start; }
}

/* ── 90-gallery.css ── */
/* Gallery shell — #2745 step 3 (GET /console/ui and its static export).
   Only the gallery chrome lives here; every component it shows brings its own
   family file. Each state sits in a dashed frame on the page ground. */

/* .gallery wraps the whole page; it sits on the ground like a console page. */
.gallery { min-height: 100vh; background: var(--ground); }
.gallery__bar { background: var(--surface); border-bottom: 1px solid var(--line); }
.gallery__bar-inner { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--s-4) var(--s-6); padding-block: var(--s-5); }
.gallery__title { flex: 1 1 260px; min-width: 0; }
.gallery__title h1 { font-size: var(--fs-24); font-weight: var(--w-strong); letter-spacing: -0.02em; line-height: var(--lh-tight); }
.gallery__title p { margin-top: var(--s-1); font-size: var(--fs-13); }

.gallery__form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s-2) var(--s-3); }
.gallery__field { display: grid; gap: 2px; font-size: var(--fs-12); color: var(--ink-2); }
.gallery__field select, .gallery__submit {
  height: 32px; padding: 0 10px; border: 1px solid var(--line-strong); border-radius: var(--r-control);
  background: var(--control-bg); color: var(--ink); font-size: var(--fs-13);
}
.gallery__submit { font-weight: var(--w-ui); cursor: pointer; background: var(--primary); color: var(--on-primary); border-color: var(--primary); }
.gallery__submit:hover { background: var(--primary-hover); }

.gallery__switch { flex: none; }
.gallery__grid { border-collapse: collapse; font-size: var(--fs-13); }
.gallery__grid th { padding: 2px var(--s-3) 2px 0; text-align: left; font-weight: var(--w-ui); color: var(--ink-2); white-space: nowrap; }
.gallery__grid td { padding: 2px; }
.gallery__grid a { display: inline-flex; align-items: center; height: 24px; padding: 0 var(--s-2); border-radius: var(--r-chip); }
.gallery__grid a[aria-current="true"] { background: var(--selected-tint); color: var(--selected-ink); font-weight: var(--w-strong); }

.gallery__sections { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-2); font-size: var(--fs-13); }
.gallery__sections a { padding: 4px var(--s-2); border-radius: var(--r-chip); }
.gallery__sections a[aria-current="true"] { background: var(--selected-tint); color: var(--selected-ink); font-weight: var(--w-strong); }
.gallery__sections .gallery__view { margin-left: auto; }

.gallery__main { padding-block: var(--s-6) var(--s-8); }
.gallery__section + .gallery__section { margin-top: var(--s-7); }
.gallery__h2 { font-size: var(--fs-18); font-weight: var(--w-strong); letter-spacing: -0.01em; margin-bottom: var(--s-4); }
.gallery__state + .gallery__state { margin-top: var(--s-5); }
.gallery__label { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-1) var(--s-2); margin-bottom: var(--s-2); font-size: var(--fs-13); font-weight: var(--w-strong); }
.gallery code { font-family: var(--font); font-size: 0.92em; }
.gallery__id { font-size: var(--fs-12); font-weight: var(--w-text); color: var(--ink-2); overflow-wrap: anywhere; }
.gallery__frame { padding: var(--s-5); border: 1px dashed var(--line-strong); border-radius: var(--r-card); background: var(--ground); min-width: 0; }
.gallery__pending { color: var(--ink-2); }
/* Pages: each page state spans the viewport (the gallery's page margins
   bleed away), so a page lays out at the width it has in the console. A family's
   own page states (`<family>/page/<state>`, Reports) do the same. */
.gallery__section > .gallery__state:is([data-state^="pages/"], [data-state*="/page/"]) { margin-inline: calc(-1 * var(--page-margin)); }
.gallery__section > .gallery__state:is([data-state^="pages/"], [data-state*="/page/"]) > .gallery__label { padding-inline: var(--page-margin); }
.gallery__section > .gallery__state:is([data-state^="pages/"], [data-state*="/page/"]) > .gallery__frame { padding: 0; border-inline: 0; border-radius: 0; }

.gallery__presets { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr)); gap: var(--s-4); }
.gallery__preset { min-width: 0; padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r-card); background: var(--ground); color: var(--ink); }
.gallery__preset-name { margin-bottom: var(--s-3); font-weight: var(--w-strong); }
.gallery__preset .gallery__frame { padding: var(--s-3); }

@media (max-width: 760px) {
  .gallery__bar-inner { padding-block: var(--s-4); }
  .gallery__frame { padding: var(--s-3); }
  .gallery__sections .gallery__view { margin-left: 0; }
}

/* Layout helpers for the states (gallery only). */
.gallery__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3) var(--s-4); }
.gallery__row + .gallery__row { margin-top: var(--s-3); }
.gallery__list .gallery__row { display: grid; grid-template-columns: minmax(0, 320px) auto; justify-content: start; }
.gallery__cells { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: var(--s-4) var(--s-5); }
.gallery__name { font-size: var(--fs-13); font-weight: var(--w-ui); margin-bottom: var(--s-1); }
.gallery__narrow { max-width: 300px; }
/* Open popover panels are absolute: the container reserves their room. */
.gallery__pops { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s-4); min-height: 340px; }
.gallery__pop-start .pop__panel { left: 0; right: auto; }
/* A stage reserves room for an open panel below its trigger: the state sets
   --stage-room. A phone stage is 390 px wide with phone page margins (a part
   that lays itself out by its own width shows its phone layout at any
   viewport); an end stage stacks its parts at the right, as in a page head. */
.gallery__stage { padding-bottom: var(--stage-room, 0px); }
.gallery__stage--phone { max-width: 390px; --page-margin: 16px; }
.gallery__stage--end { display: grid; justify-items: end; gap: var(--s-4); }

/* Tokens section: swatches and pairs paint from inline custom properties that
   name a token (style="--sw: var(--surface)"), never from a colour literal. */
.tok-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 230px), 1fr)); gap: var(--s-3); }
.tok-swatch { display: grid; grid-template-columns: 40px minmax(0, 1fr); column-gap: var(--s-3); align-items: center; font-size: var(--fs-13); }
.tok-swatch__chip { grid-row: span 2; width: 40px; height: 40px; border-radius: var(--r-control); background: var(--sw); box-shadow: inset 0 0 0 1px var(--line-strong); }
.tok-swatch__value, .tok-pair__names, .tok-verdict__ratio { color: var(--ink-2); font-size: var(--fs-12); font-variant-numeric: tabular-nums; }
.tok-pair { display: grid; grid-template-columns: 48px minmax(0, 1fr) auto; column-gap: var(--s-3); align-items: center; padding: var(--s-2); border-radius: var(--r-control); background: var(--surface); border: 1px solid var(--line); }
.tok-pair__sample { display: grid; place-items: center; height: 36px; border-radius: var(--r-chip); background: var(--bg); color: var(--fg); font-size: var(--fs-16); font-weight: var(--w-strong); box-shadow: inset 0 0 0 1px var(--line); }
.tok-pair__ratio { font-weight: var(--w-strong); font-variant-numeric: tabular-nums; }
.tok-header { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-4); min-height: 52px; padding: var(--s-2) var(--s-4); border-radius: var(--r-control); background: var(--header-bg); border: 1px solid var(--header-line); color: var(--header-ink); }
.tok-header__mark { width: 18px; height: 18px; border-radius: 4px; background: var(--header-mark); }
.tok-header__ink { font-weight: var(--w-strong); box-shadow: inset 0 -2px 0 var(--header-mark); padding-bottom: 2px; }
.tok-header__ink-2 { color: var(--header-ink-2); }
.tok-header__control { display: inline-flex; gap: 2px; padding: 3px; border-radius: var(--r-control); background: var(--header-control); font-size: var(--fs-13); }
.tok-header__control > span { padding: 2px 10px; border-radius: 6px; }
.tok-header__on { background: var(--header-control-on); color: var(--header-control-on-ink); box-shadow: var(--header-control-shadow); }
.tok-ratios { display: flex; flex-wrap: wrap; gap: var(--s-1) var(--s-5); margin-top: var(--s-3); font-size: var(--fs-12); color: var(--ink-2); }
.tok-ratios b { color: var(--ink); font-variant-numeric: tabular-nums; }
.tok-verdicts { display: grid; gap: var(--s-2); }
.tok-verdict { display: grid; grid-template-columns: 28px 200px 96px minmax(0, 1fr); column-gap: var(--s-3); align-items: center; }
.tok-verdict__mark { width: 28px; height: 28px; border-radius: 50%; background: var(--mk); box-shadow: inset 0 0 0 1.5px var(--ring); }
.tok-verdict__word { font-weight: var(--w-ui); }
.tok-verdict__tint { justify-self: start; padding: 2px 10px; border-radius: var(--r-pill); background: var(--tint); color: var(--tink); font-size: var(--fs-12); font-weight: var(--w-strong); box-shadow: inset 0 0 0 1px var(--line); }
.tok-note { margin-top: var(--s-3); color: var(--ink-2); font-size: var(--fs-13); }
.tok-type { display: grid; grid-template-columns: 88px minmax(0, 1fr); align-items: baseline; gap: var(--s-3); }
.tok-type + .tok-type { margin-top: var(--s-2); }
.tok-type code, .tok-space code, .tok-radius code { font-size: var(--fs-12); color: var(--ink-2); }
.tok-type__sample { font-size: var(--fs); line-height: var(--lh-tight); overflow-wrap: anywhere; }
.tok-type--hero .tok-type__sample { font-weight: 650; letter-spacing: -0.045em; }
.tok-weights { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); margin-top: var(--s-4); }
.tok-w400 { font-weight: 400; } .tok-w500 { font-weight: 500; } .tok-w600 { font-weight: 600; }
.tok-spaces, .tok-radiuss { display: grid; gap: var(--s-2); }
.tok-space, .tok-radius { display: grid; grid-template-columns: 72px 72px minmax(0, 1fr); align-items: center; gap: var(--s-3); font-size: var(--fs-13); }
.tok-space__shape { width: var(--v); height: 12px; border-radius: 2px; background: var(--ink-2); }
.tok-radius__shape { width: 56px; height: 32px; border-radius: var(--v); background: var(--surface); border: 1px solid var(--line-strong); }

@media (max-width: 760px) {
  .gallery__list .gallery__row { grid-template-columns: minmax(0, 1fr); row-gap: var(--s-1); }
  .gallery__pops { flex-direction: column; justify-content: flex-start; gap: 160px; min-height: 0; padding-bottom: 290px; }
  .gallery__pops > .pop:last-child { align-self: flex-end; }
  .tok-verdict { grid-template-columns: 28px minmax(0, 1fr); row-gap: 2px; }
  .tok-verdict__ratio, .tok-verdict__tint { grid-column: 2; }
}

/* ── 95-print.css ── */
/* On paper (#2826): the check report's "Download report" is the page printed (Light, by
   check-report-pdf.ts), and a reader's own Print gets the same. The console's chrome goes;
   every box opens, whatever it starts as on screen (partner 2026-11-04: collapsed is a
   reader's choice), since a folded box is only its heading on paper (the placement step's copies
   that point to the link stay folded, #2794); what is only there to
   download or to read raw stays on screen (the check log has it); the video is its still
   and a link. No control prints. Last in ui.css, so it overrides the families' screen rules. */
@page { size: A4; margin: 14mm 12mm; }
.audit-video-print { display: none; }

@media print {
  .app-header, .app-footer, .ev-head__act, .ev-test-run { display: none !important; }
  html, body { background: var(--surface); }
  .container.page { max-width: none; padding: 0; }
  details::details-content { content-visibility: visible; display: contents; }
  .ev-box > summary::after, .ev-carried > details > summary::after { display: none; }
  /* A code's explanation under a step prints open, so it loses its closed-looking marker (#2826 QA). */
  .reason-code-row > summary { list-style: none; }
  .reason-code-row > summary::-webkit-details-marker { display: none; }
  .stage-data, .evidence-section:has(> .request-log-list) { display: none; }
  /* The Technical log (#2826): how the check ran and each step's assertions, so the report stays
     a dated record a reader can follow; the operator's request logs stay on screen and in the
     check log. */
  .ev-log__requests { display: none; }
  .ev-log__group { break-inside: avoid; }
  /* Stages and Diagnostics by step (#2826 Q2): every stage open on paper, without its View steps,
     Expand all or Collapse all. */
  .ev-sg__steps { display: grid !important; }
  .ev-sg-all, .ev-sg__bd { display: none !important; }
  /* Stage map (#2826 Q3): its row of marks, no selection, every stage's details under it; only
     the row where the page also shows the Stages box, which prints every stage open. */
  .ev-map__hint { display: none !important; }
  .ev-map > .ev-map__panel { display: block !important; }
  .ev-map__panel + .ev-map__panel { margin-top: var(--s-2); }
  .page:has(.ev-stages-box) .ev-map > .ev-map__panel { display: none !important; }
  .ev-map__stage:has(.ev-map__in:checked) { box-shadow: none; }
  .ev-map__stage:has(.ev-map__in:checked):not(.ev-map__stage--fail, .ev-map__stage--warn) { border-color: var(--line-strong); }
  .ev-map__strip, .ev-map__title { break-inside: avoid; }
  /* The placement step's copies of the link (#2794): the ones that point somewhere else print, the
     ones that point to the link stay folded under their count (hundreds of copies would print
     dozens of pages). */
  .ev-copies > .disclosure > .disclosure__body { display: none !important; }
  .ev-copies > .disclosure > summary .icon { display: none; }
  .ev-copy { break-inside: avoid; }
  .ev-carried .audit-video-actions, .ev-carried .audit-video-player, .ev-carried .audit-video-player:not(:popover-open) { display: none; }
  .audit-video-print { display: block; margin: var(--s-3) var(--s-5); }
  .audit-video-still { display: block; width: auto; max-width: min(100%, 300px); max-height: 110mm; margin-bottom: var(--s-2); border: 1px solid var(--line); border-radius: var(--r-control); }
  figure, tr, .config-row, .diagnosis-block { break-inside: avoid; }
  summary, h1, h2, h3 { break-after: avoid; }
}
