/* doc-ray design system — "Refined SaaS".
   Source of truth for page color, type, spacing, controls, tables, document
   readers, and operator surfaces. A calm, credible enterprise-dashboard
   aesthetic: slate neutrals lead, brand red is a focused accent, subtle depth
   (radii + soft shadows), a tokenized spacing scale, and semantic status
   colors. The class and CSS-variable API is stable — templates and inline
   styles depend on these names; only values and component rules change here. */

:root {
  /* Type roles — Inter for UI, JetBrains Mono for data/IDs/labels. */
  --display: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --serif: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Long-form reading faces, offered as a reader setting. Both resolve locally
     — no extra webfont on the critical path for a page that is mostly text. */
  --reading-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --reading-serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia,
    "Times New Roman", serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Spacing scale (4px base). Additive — safe for any component to adopt. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Minimum touch target. A tap target is the area that activates a control,
     which is NOT the control's drawn representation — where a control must stay
     visually small, the active area is grown around it instead (see the
     coarse-pointer layer at the end of this file). 48px is the larger of the two
     vendor minimums (Android 48 dp, iOS 44 pt) so one value satisfies both.
     Enforced by scripts/check_touch_targets.py; vendor-sourced, so re-check it
     there against current guidance rather than editing this value in place. */
  --tap-min: 48px;

  /* Height of the thumb-region navigation bar, reserved by `main` so a
     fixed bar never covers page content. */
  --bottom-nav-h: 56px;

  /* Core surfaces + brand. */
  --color-bg: #f5f7fa;
  --color-surface: #ffffff;
  --color-text: #171a1f;
  --color-accent: #e5484d;
  --color-accent-2: #f2555a;
  --color-divider: #e3e8ef;

  /* Neutral ramp — cool slate, 100 lightest → 900 darkest. */
  --color-neutral-100: #f8fafc;
  --color-neutral-200: #eef1f6;
  --color-neutral-300: #e0e5ec;
  --color-neutral-400: #cbd2dc;
  --color-neutral-500: #97a1b0;
  --color-neutral-600: #6a7483;
  --color-neutral-700: #48515d;
  --color-neutral-800: #2d333b;
  --color-neutral-900: #171a1f;

  /* Accent ramp — brand red. 600 is the base accent. */
  --color-accent-100: #fff1f1;
  --color-accent-200: #ffe1e2;
  --color-accent-300: #fdc3c5;
  --color-accent-400: #f79a9e;
  --color-accent-500: #ee666c;
  --color-accent-600: #e5484d;
  --color-accent-700: #cb3a40;
  --color-accent-800: #a92e33;
  --color-accent-900: #7c2427;

  /* Semantic status. */
  --ok: #1f9d55;
  --ok-bg: color-mix(in srgb, #1f9d55 12%, var(--panel));
  --warn: #b7791f;
  --warn-bg: color-mix(in srgb, #d69e2e 16%, var(--panel));
  --info: #2b6cb0;
  --info-bg: color-mix(in srgb, #3182ce 12%, var(--panel));
  --danger: var(--color-accent-700);
  --danger-bg: color-mix(in srgb, var(--color-accent-600) 11%, var(--panel));

  /* Semantic aliases (the names components actually reference). */
  --bg: var(--color-bg);
  --bg2: var(--color-neutral-100);
  --panel: var(--color-surface);
  --line: var(--color-divider);
  --line-soft: var(--color-neutral-200);
  --ink: var(--color-text);
  --ink-soft: var(--color-neutral-700);
  --ink-faint: var(--color-neutral-600);
  --accent: var(--color-accent);
  --accent-ink: #ffffff;
  --accent-soft: var(--color-accent-700);
  --accent-wash: color-mix(in srgb, var(--accent) 8%, transparent);
  --sel: color-mix(in srgb, var(--accent) 20%, transparent);
  --ring: color-mix(in srgb, var(--accent) 38%, transparent);
  --link: var(--color-accent-700);

  /* Primary button = near-black slate that inverts in dark mode. */
  --btn-bg: var(--color-neutral-900);
  --btn-bg-hover: var(--color-neutral-800);
  --btn-ink: #ffffff;

  /* Part-of-speech palette (slate + red family). */
  --pos-noun: #171a1f;
  --pos-propn: #a92e33;
  --pos-verb: #e5484d;
  --pos-adj: #48515d;
  --pos-adv: #cb3a40;
  --pos-pron: #2d333b;
  --pos-num: #6a7483;
  --pos-func: #97a1b0;

  --r-sm: 6px;
  --r: 10px;
  --r-lg: 14px;
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .04);
  --shadow-md: 0 2px 6px rgba(16, 24, 40, .06), 0 8px 20px rgba(16, 24, 40, .07);
  --shadow-lg: 0 16px 40px rgba(16, 24, 40, .14);

  /* Motion — shared durations + easings so interaction feedback is consistent
     and tunable in one place. The reduced-motion block near the end neutralizes
     the resulting transitions and entrance animations. */
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.36, .5, 1);
  --dur-1: 90ms;
  --dur-2: 150ms;
  --dur-3: 260ms;
}

html[data-theme="dark"] {
  --color-bg: #0f1216;
  --color-surface: #171b21;
  --color-text: #e6e9ee;
  --color-divider: #262c35;

  --color-neutral-100: #171b21;
  --color-neutral-200: #1d222a;
  --color-neutral-300: #272e38;
  --color-neutral-400: #353d49;
  --color-neutral-500: #6a7483;
  --color-neutral-600: #939eae;
  --color-neutral-700: #b6bfcc;
  --color-neutral-800: #d4dae2;
  --color-neutral-900: #e6e9ee;

  --color-accent: #f2555a;
  --accent-soft: #f79a9e;
  --link: #f79a9e;
  --line-soft: #222833;
  --ink-soft: #b6bfcc;
  --ink-faint: #8b95a4;

  --btn-bg: var(--color-neutral-900);
  --btn-bg-hover: var(--color-neutral-800);
  --btn-ink: #0f1216;

  --sel: color-mix(in srgb, var(--accent) 30%, transparent);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-md: 0 2px 6px rgba(0, 0, 0, .4), 0 10px 24px rgba(0, 0, 0, .38);
  --shadow-lg: 0 18px 44px rgba(0, 0, 0, .5);

  --ok: #37c26b;
  --warn: #e0a63a;
  --info: #4a9eea;

  --pos-noun: #e6e9ee;
  --pos-propn: #fdc3c5;
  --pos-verb: #f2555a;
  --pos-adj: #b6bfcc;
  --pos-adv: #f79a9e;
  --pos-pron: #d4dae2;
  --pos-num: #939eae;
  --pos-func: #6a7483;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  /* Sticky footer: the page is a full-height column so a short page (e.g. the
     sign-in card) still pushes the footer to the bottom instead of leaving it
     stranded mid-viewport with page background below it. */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  letter-spacing: -0.006em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
::selection { background: var(--sel); }
a { color: var(--link); text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--accent); text-decoration-color: currentColor; }
img { display: block; max-width: 100%; }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
code {
  padding: .1rem .34rem;
  background: var(--bg2);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-sm);
  color: var(--ink);
  font-family: var(--mono);
  font-size: .86em;
  font-weight: 500;
}
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; box-shadow: 0 0 0 4px var(--ring); }

a, button, .btn, .pill, .tag, .chip, .seg a, .pager a, .pager span,
input, select, textarea, header nav a, .nav-link-button, .toggle,
.doc-preview, .st, .card {
  transition: background-color var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out),
    color var(--dur-2) var(--ease-out),
    box-shadow var(--dur-2) var(--ease-out),
    text-decoration-color var(--dur-2) var(--ease-out),
    transform var(--dur-1) var(--ease-out);
}

/* Masthead */
header {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: stretch;
  gap: 0;
  min-height: 60px;
  padding: 0 clamp(1rem, 4vw, 2.25rem);
  background: color-mix(in srgb, var(--panel) 88%, transparent);
  backdrop-filter: saturate(1.1) blur(8px);
  border-bottom: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
}
.brand {
  display: inline-flex;
  align-items: center;
  min-width: 8rem;
  margin-right: 1.1rem;
  padding-right: 1.2rem;
  border-right: 1px solid var(--line);
  color: var(--ink);
  font-family: var(--display);
  font-size: 1.18rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-decoration: none;
  text-transform: lowercase;
}
.brand:hover { color: var(--ink); }
.brand b { color: var(--accent); font-weight: 700; }
header nav {
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  align-items: center;
  gap: .1rem;
}
.nav-group { display: flex; flex-wrap: wrap; align-items: center; gap: .1rem; }
.nav-admin { margin-left: auto; padding-left: .5rem; }
.nav-account { padding-left: .35rem; }
header nav a {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 .7rem;
  border-radius: var(--r-sm);
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: .82rem;
  font-weight: 500;
  letter-spacing: 0;
  text-decoration: none;
}
header nav a:hover { color: var(--ink); background: var(--bg2); text-decoration: none; }
header nav a.on { color: var(--accent); background: var(--accent-wash); }
.nav-inline-form { display: inline-flex; margin: 0; }
.nav-link-button {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 .7rem;
  background: transparent;
  border: 0;
  border-radius: var(--r-sm);
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: .82rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  cursor: pointer;
}
.nav-link-button:hover { color: var(--ink); background: var(--bg2); }
header nav a.nav-action {
  margin-left: .5rem;
  padding: 0 .85rem;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}
header nav a.nav-action:hover { background: var(--accent-soft); color: var(--accent-ink); }
header nav a.nav-action.on { color: var(--accent-ink); background: var(--accent); }
.toggle {
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 0;
  margin-left: .75rem;
  padding: 0;
  overflow: hidden;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
}
.toggle span {
  display: grid;
  width: 1.85rem;
  height: 1.85rem;
  place-items: center;
  font-size: .8rem;
}
html[data-theme="light"] .toggle .sun,
html[data-theme="dark"] .toggle .moon { background: var(--accent); color: var(--accent-ink); }

/* Mobile hamburger — CSP-safe checkbox toggle (no JS). Hidden on desktop. */
.nav-cb { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.nav-burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.3rem;
  height: 2.3rem;
  margin-left: .5rem;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  cursor: pointer;
}
.nav-burger span { position: relative; display: block; width: 1.05rem; height: 2px; background: var(--ink); border-radius: 2px; }
.nav-burger span::before, .nav-burger span::after { content: ""; position: absolute; left: 0; width: 1.05rem; height: 2px; background: var(--ink); border-radius: 2px; }
.nav-burger span::before { top: -6px; }
.nav-burger span::after { top: 6px; }
.nav-cb:focus-visible + .nav-burger { outline: 2px solid var(--accent); outline-offset: 2px; }

main {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  flex: 1 0 auto;  /* grow to fill the column so the footer sits at the bottom */
  padding: var(--space-7) clamp(1rem, 4vw, 2.25rem) var(--space-8);
}
h1 {
  margin: .1rem 0 var(--space-3);
  font-family: var(--display);
  font-size: clamp(1.55rem, 2.6vw, 2rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-transform: none;
}
h1 .accent { color: var(--accent); }
h2 {
  margin: var(--space-6) 0 var(--space-3);
  padding-bottom: .5rem;
  border-bottom: 1px solid var(--line);
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: .74rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}
h3, h4 { font-family: var(--display); font-weight: 650; letter-spacing: -0.01em; }
.lede {
  max-width: 52rem;
  color: var(--ink-soft);
  font-size: 1.02rem;
  line-height: 1.55;
}
.kicker {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.kicker a { color: var(--accent); text-decoration: none; }
.kicker a:hover { text-decoration: underline; }

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--space-5);
  margin-bottom: var(--space-5);
  box-shadow: var(--shadow-sm);
}
.table-card {
  overflow: hidden;
  padding: 0;
}
.table-card > table,
.table-card > form,
.table-card > .toolbar,
.table-card > .pager { overflow-x: auto; }
.table-card table { min-width: 760px; }
.table-card .toolbar {
  margin: 0;
  padding: var(--space-4);
  border-bottom: 1px solid var(--line);
}
.table-card .pager {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--line);
}
.table-card th:first-child,
.table-card td:first-child { padding-left: var(--space-4); }
.table-card th:last-child,
.table-card td:last-child { padding-right: var(--space-4); }
.grid { display: grid; gap: var(--space-4); }
.grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 800px) { .grid.two { grid-template-columns: 1fr; } }

table { width: 100%; border-collapse: collapse; font-size: .92rem; }
th, td {
  text-align: left;
  padding: .7rem .8rem;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: baseline;
}
th {
  background: var(--bg2);
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--line);
}
tbody tr { transition: background-color .1s ease; }
tbody tr:hover td { background: var(--bg2); }
tbody tr:has(input[type="checkbox"]:checked) td { background: var(--accent-wash); }
.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.table-title {
  color: var(--ink);
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
}
.table-title a { color: inherit; text-decoration: none; }
.table-title a:hover { color: var(--accent); text-decoration: underline; }
.meta-cell {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .02em;
  text-transform: uppercase;
}

.pill, .tag {
  display: inline-flex;
  align-items: center;
  min-height: 1.5rem;
  margin: .14rem .2rem 0 0;
  padding: .16rem .55rem;
  background: var(--bg2);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  color: var(--ink-soft);
  font-family: var(--mono);
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .02em;
  line-height: 1.2;
  text-transform: uppercase;
}
.pill:hover { text-decoration: none; border-color: var(--accent); color: var(--accent); }
.lang { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); background: var(--accent-wash); }
.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;
}
.tip { position: relative; cursor: help; }
.tip[data-tip]:hover::after,
.tip[data-tip]:focus-visible::after {
  content: attr(data-tip);
  position: absolute;
  left: 0;
  bottom: calc(100% + 8px);
  z-index: 100;
  width: max-content;
  max-width: min(22rem, 72vw);
  padding: .5rem .65rem;
  background: var(--color-neutral-900);
  color: var(--color-neutral-100);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-md);
  font-family: var(--sans);
  font-size: .76rem;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0;
  text-align: left;
  text-transform: none;
  white-space: normal;
  pointer-events: none;
}
.bar { height: 7px; min-width: 2px; background: var(--accent); border-radius: 999px; opacity: 1; }

.p-NOUN{--c:var(--pos-noun)} .p-PROPN{--c:var(--pos-propn)} .p-VERB{--c:var(--pos-verb)}
.p-ADJ{--c:var(--pos-adj)} .p-ADV{--c:var(--pos-adv)} .p-PRON{--c:var(--pos-pron)}
.p-NUM{--c:var(--pos-num)}
.p-DET,.p-ADP,.p-CCONJ,.p-SCONJ,.p-PART,.p-AUX,.p-PUNCT,.p-SYM,.p-X,.p-INTJ{--c:var(--pos-func)}
.swatch {
  display: inline-block;
  width: .68rem;
  height: .68rem;
  margin-right: .4rem;
  background: var(--c);
  border-radius: 2px;
  vertical-align: baseline;
}

.pager {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
  align-items: center;
  margin-top: var(--space-5);
  font-family: var(--mono);
  font-size: .74rem;
  font-weight: 500;
  text-transform: uppercase;
}
.pager a, .pager span {
  min-height: 2rem;
  padding: .4rem .8rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--ink-soft);
  text-decoration: none;
}
.pager a:hover { background: var(--bg2); border-color: var(--color-neutral-400); color: var(--ink); }
.pager span { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); background: var(--accent-wash); }

form.filters, .toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: .65rem;
  align-items: flex-end;
  margin-bottom: var(--space-5);
}
label {
  color: var(--ink-soft);
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: none;
}
/* `input:not([type])` is deliberate: an input with no type attribute defaults to
   text but is NOT matched by `input[type=text]`, so a type-less field (e.g.
   register's display_name) would otherwise fall through to the UA-default white
   background — invisible-breaking in dark mode. Keep it first in the list. */
input:not([type]),
input[type=text], input[type=file], input[type=email], input[type=password],
input[type=search], input[type=number], input[type=tel], input[type=url],
select, textarea {
  min-height: 2.4rem;
  padding: .55rem .7rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--ink);
  font: inherit;
  font-size: .95rem;
  box-shadow: var(--shadow-sm);
}
input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  margin: 0;
  accent-color: var(--accent);
}
input::placeholder, textarea::placeholder { color: var(--ink-faint); }
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--ring);
}
/* Chrome/WebKit paint autofilled inputs with their own opaque background that
   ignores `background` — in dark mode it flashes light grey (most visible on the
   autocomplete="name" field, which the browser fills from the saved profile).
   Repaint the fill with the panel colour via the inset box-shadow trick, keep
   text + caret on-token, and stall the transition so there is no flash. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
select:-webkit-autofill,
textarea:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 1000px var(--panel) inset, var(--shadow-sm);
  caret-color: var(--ink);
  transition: background-color 9999s ease-out 0s;
}
input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--panel) inset, 0 0 0 3px var(--ring);
}

button, .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  min-height: 2.4rem;
  padding: .58rem 1rem;
  background: var(--btn-bg);
  border: 1px solid var(--btn-bg);
  border-radius: var(--r-sm);
  color: var(--btn-ink);
  cursor: pointer;
  font-family: var(--sans);
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  text-transform: none;
  box-shadow: var(--shadow-sm);
}
button:hover, .btn:hover { background: var(--btn-bg-hover); border-color: var(--btn-bg-hover); text-decoration: none; color: var(--btn-ink); transform: translateY(-1px); box-shadow: var(--shadow-sm); }
button:active, .btn:active { transform: translateY(0); box-shadow: none; }
button:disabled { opacity: .45; cursor: not-allowed; }
button.danger, .btn.danger { background: var(--danger); border-color: var(--danger); color: #fff; }
button.danger:hover, .btn.danger:hover { background: var(--color-accent-800); border-color: var(--color-accent-800); color: #fff; }
mark { background: var(--sel); color: inherit; padding: 0 .12em; border-radius: 3px; }

/* Auth screens — login / register / verify-email / profile.
   A centered, narrow card with stacked, full-width fields. Styles the panel's
   forms generically so both `.stack` forms and plain forms lay out correctly. */
.page-head {
  max-width: 27rem;
  margin: var(--space-6) auto var(--space-3);
}
.page-head h1 { margin: .1rem 0 0; }
.eyebrow {
  margin: 0 0 .1rem;
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.auth-panel {
  max-width: 27rem;
  margin: 0 auto var(--space-6);
  padding: var(--space-5);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-sm);
}
.auth-panel form, .stack { display: grid; gap: var(--space-4); }
.auth-panel label { display: grid; gap: .35rem; }
.auth-panel input, .auth-panel select, .auth-panel textarea { width: 100%; }
.auth-panel button, .auth-panel .btn { width: 100%; justify-content: center; margin-top: .1rem; }
.auth-panel code { display: inline-block; max-width: 100%; overflow-wrap: anywhere; }
.auth-panel .muted { margin-top: var(--space-4); text-align: center; }
.auth-panel .muted a { font-weight: 600; }

/* Work head — the header band of a working screen (distinct from `.page-head`,
   which centres the narrow auth cards). Title and counters share a single row
   so the surface below — a table, a result list — starts inside the first
   viewport instead of behind a hero. */
.work-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--line);
}
.work-head h1 { margin: 0; }
/* A working screen opens at the top of the viewport: the hero-scale breathing
   room above the fold buys nothing once the header is a single row. */
main:has(.work-head) { padding-top: var(--space-5); }
/* Corpus counters as a dense rail: readable at a glance, cheap in vertical
   space. Replaces the full-width card of display-size numbers. */
.stat-rail {
  display: flex;
  flex-wrap: wrap;
  gap: .2rem var(--space-4);
  margin: 0;
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: .7rem;
  font-weight: 500;
  letter-spacing: .05em;
  text-transform: uppercase;
  white-space: nowrap;
}
.stat-rail b {
  margin-right: .3rem;
  color: var(--ink);
  font-family: var(--display);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

/* Read-path guarantee. Four totals sit on one rail and they do not all promise
   the same thing; the debounced one says when it was last computed instead of
   borrowing the credibility of the exact counts beside it. Past its declared
   window the note goes warm — the number is still shown, because a lagging
   figure is not an error, but it stops reading as current. */
.stat-rail__as-of {
  margin-left: .35rem;
  color: var(--ink-faint);
  font-size: .92em;
  font-weight: 400;
  letter-spacing: .02em;
  text-transform: none;
  opacity: .85;
}
.stat-rail [data-stale="true"] .stat-rail__as-of { color: var(--warn); opacity: 1; }

.hint, .muted { margin-top: .2rem; color: var(--ink-faint); font-size: .82rem; }
.notice, .errbox, .error {
  margin: var(--space-3) 0;
  padding: .7rem .9rem;
  background: var(--info-bg);
  border: 1px solid color-mix(in srgb, var(--info) 30%, transparent);
  border-left: 3px solid var(--info);
  border-radius: var(--r-sm);
  color: var(--ink);
  font-family: var(--sans);
  font-size: .88rem;
  font-weight: 500;
}
details.card summary {
  margin: calc(-1 * var(--space-5)) calc(-1 * var(--space-5)) var(--space-4);
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--line);
  font-weight: 600;
  cursor: pointer;
}
.errbox, .error, .notice.error {
  color: var(--ink);
  background: var(--danger-bg);
  border-color: color-mix(in srgb, var(--danger) 32%, transparent);
  border-left-color: var(--danger);
}
.kv {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: .6rem 1.1rem;
  margin: 0;
}
.kv dt {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
}
.kv dd {
  min-width: 0;
  margin: 0;
  overflow-wrap: anywhere;
}
.st {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .16rem .55rem;
  background: var(--bg2);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  color: var(--ink-soft);
  font-family: var(--mono);
  font-size: .66rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
}
.st-succeeded, .st-approved { color: var(--ok); background: var(--ok-bg); border-color: color-mix(in srgb, var(--ok) 34%, transparent); }
.st-failed, .st-rejected { color: var(--danger); background: var(--danger-bg); border-color: color-mix(in srgb, var(--danger) 34%, transparent); }
.st-running { color: var(--info); background: var(--info-bg); border-color: color-mix(in srgb, var(--info) 34%, transparent); }
.st-seeded { color: var(--warn); background: var(--warn-bg); border-color: color-mix(in srgb, var(--warn) 36%, transparent); }

table.jobs th, table.seed th, .compact th {
  padding: .5rem .6rem;
  background: var(--bg2);
  border-bottom: 1px solid var(--line);
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: .64rem;
  font-weight: 600;
  letter-spacing: .05em;
  text-align: left;
  text-transform: uppercase;
}
table.jobs td, table.seed td, .compact td {
  padding: .55rem .6rem;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}

.preview-cell { width: 5.8rem; vertical-align: top; }
.doc-title-strip { display: flex; align-items: flex-start; gap: var(--space-4); flex-wrap: wrap; }
.doc-title-main { min-width: min(100%, 24rem); flex: 1 1 28rem; }
.doc-title-main h1 { margin-top: 0; }
.doc-preview {
  display: grid;
  width: 4.8rem;
  aspect-ratio: 3 / 4;
  place-items: center;
  overflow: hidden;
  background: var(--bg2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-sm);
}
.doc-preview:hover { border-color: var(--accent); text-decoration: none; box-shadow: var(--shadow-md); }
/* Reader cover: enough to recognise the document at a glance. It sets the
   header strip's minimum height, so it stays close to the list thumbnail
   rather than reaching title-page scale. */
.doc-preview-large { width: 4.6rem; flex: 0 0 auto; }
.doc-preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.doc-preview-icon span {
  max-width: calc(100% - .6rem);
  overflow: hidden;
  padding: .18rem .3rem;
  border-radius: 3px;
  border: 1px solid var(--line);
  color: var(--ink-soft);
  font-family: var(--mono);
  font-size: .66rem;
  font-weight: 600;
  text-overflow: ellipsis;
  text-transform: uppercase;
}
.doc-preview-pending {
  background: repeating-linear-gradient(135deg, var(--bg2), var(--bg2) .42rem, var(--line-soft) .42rem, var(--line-soft) .84rem);
}
.doc-preview-failed { border-color: var(--danger); }
.preview-status {
  margin-top: .3rem;
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: .62rem;
  font-weight: 500;
  line-height: 1.25;
  text-transform: uppercase;
}
.preview-status-ready, .preview-status-pending { color: var(--ink-soft); }
.preview-status-failed { color: var(--danger); }

.collection-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(17rem, 23rem);
  gap: var(--space-5);
  align-items: start;
}
.collection-list { display: grid; gap: 0; border-top: 1px solid var(--line); }
.collection-card {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
}
.collection-card h2 { margin: 0 0 .2rem; border: 0; padding: 0; font-size: 1.1rem; font-family: var(--display); font-weight: 650; letter-spacing: -0.01em; text-transform: none; color: var(--ink); }
.collection-meta { display: flex; gap: .35rem; align-items: flex-start; flex-wrap: wrap; justify-content: flex-end; }
.collection-create form, .collection-add-list { display: grid; gap: .7rem; }
.collection-create label { display: grid; gap: .3rem; }
.collection-add-list form { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.collection-add-list button { padding: .35rem .7rem; min-height: 2rem; }

.seg {
  display: inline-flex;
  overflow: hidden;
  padding: 3px;
  gap: 2px;
  background: var(--bg2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}
.seg a {
  display: inline-flex;
  align-items: center;
  min-height: 1.9rem;
  padding: .35rem .8rem;
  border-radius: calc(var(--r-sm) - 3px);
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: 0;
  text-decoration: none;
  text-transform: none;
}
.seg a:hover { background: var(--panel); color: var(--ink); text-decoration: none; }
.seg a.on { background: var(--accent); color: var(--accent-ink); box-shadow: var(--shadow-sm); }
.chip {
  display: inline-flex;
  align-items: center;
  min-height: 1.5rem;
  padding: .2rem .55rem;
  background: var(--bg2);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  color: var(--ink-soft);
  cursor: pointer;
  font-family: var(--mono);
  font-size: .64rem;
  font-weight: 600;
  letter-spacing: .03em;
  text-transform: uppercase;
  user-select: none;
}
.chip:hover { border-color: var(--c, var(--accent)); color: var(--ink); }
.chip.muted { opacity: .4; text-decoration: line-through; }

/* Confirmation dialog — on-brand replacement for native confirm() on
   destructive actions. Uses the native <dialog> (showModal) for a free
   backdrop, focus trap, and Escape-to-close. */
dialog.confirm {
  width: min(30rem, calc(100vw - 2rem));
  padding: var(--space-5);
  background: var(--panel);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
}
dialog.confirm::backdrop { background: rgba(10, 12, 16, .55); backdrop-filter: blur(2px); }
dialog.confirm h2 {
  margin: 0 0 .5rem;
  padding: 0;
  border: 0;
  font-family: var(--display);
  font-size: 1.2rem;
  font-weight: 650;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--ink);
}
dialog.confirm p { margin: 0 0 var(--space-5); color: var(--ink-soft); font-size: .92rem; line-height: 1.55; }
.confirm-actions { display: flex; justify-content: flex-end; gap: .6rem; }
.btn-ghost { background: transparent; border-color: var(--line); color: var(--ink); box-shadow: none; }
.btn-ghost:hover { background: var(--bg2); border-color: var(--color-neutral-400); color: var(--ink); }

@media (max-width: 920px) {
  header { flex-wrap: wrap; align-items: center; min-height: 56px; padding: 0 1rem; backdrop-filter: none; }
  .brand { margin-right: auto; padding-right: 0; border-right: 0; }
  .nav-burger { display: inline-flex; order: 2; }
  .toggle { order: 3; position: static; margin: 0 0 0 .5rem; }
  /* Nav collapses to a full-width dropdown, revealed by the burger checkbox.
     Selectors match `header nav` specificity (0,0,2) so the base rule doesn't
     win and keep the nav open on mobile. */
  header nav { order: 4; flex-basis: 100%; width: 100%; display: none; flex-direction: column; gap: 0; padding: .35rem 0 .7rem; }
  header .nav-cb:checked ~ nav { display: flex; }
  .nav-group { flex-direction: column; width: 100%; gap: 0; }
  .nav-admin, .nav-account { margin-left: 0; padding-left: 0; }
  header nav a, .nav-link-button { width: 100%; min-height: 46px; border-radius: var(--r-sm); padding: 0 .65rem; }
  header nav a.nav-action { margin: .35rem 0 0; }
  .nav-inline-form, .nav-inline-form .nav-link-button { width: 100%; }
  main { padding-top: var(--space-5); }
  /* Phone: the rail sits under the title rather than beside it. */
  .work-head { gap: var(--space-2); }
  .stat-rail { gap: .2rem var(--space-3); font-size: .66rem; }
  .collection-layout { grid-template-columns: 1fr; }
  th, td { padding: .6rem .55rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
  button:active, .btn:active { transform: none; }
}

/* Site footer — product chrome shared across every page. Mirrors the `main`
   container (max-width + side padding) so the signature line aligns with the
   page body. Composition + tokens only. */
.site-footer {
  flex-shrink: 0;
  margin-top: var(--space-8);
  /* High-contrast footer band: a dark slate surface anchors the page and lifts
     the footer clear of the near-matching page background (the old translucent
     panel was almost invisible). Footer text switches to a footer-scoped light
     ink ramp; the brand dot and link hover stay accent red for pop. */
  background: #13161b;
  border-top: 1px solid #05070a;
  box-shadow: inset 0 1px 0 color-mix(in srgb, #ffffff 7%, transparent);
  color: var(--footer-soft);
  --footer-ink: #f6f8fb;
  --footer-soft: #c4ccd8;
  --footer-faint: #8b95a4;
  --footer-line: color-mix(in srgb, #ffffff 13%, transparent);
}
/* Dark theme: the page is already near-black, so the footer lifts UP to a
   lighter elevated panel to stay distinct instead of dropping darker. */
html[data-theme="dark"] .site-footer {
  background: #1b212a;
  border-top: 1px solid #05070a;
}
.footer-top,
.footer-base {
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 clamp(1rem, 4vw, 2.25rem);
}
.footer-top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-6);
  padding-top: var(--space-7);
  padding-bottom: var(--space-6);
}
.footer-brand { max-width: 30rem; }
.footer-mark {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 1.25rem;
  color: var(--footer-ink);
}
.footer-mark:hover { color: var(--footer-ink); }
.footer-pitch {
  margin: .55rem 0 0;
  color: var(--footer-soft);
  font-size: .88rem;
  line-height: 1.55;
}
.footer-nav { display: flex; flex-wrap: wrap; gap: var(--space-6); }
.footer-col { display: flex; flex-direction: column; gap: .32rem; }
.footer-h {
  margin-bottom: .2rem;
  color: var(--footer-faint);
  font-family: var(--mono);
  font-size: .66rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.footer-col a { color: var(--footer-soft); font-size: .86rem; }
.footer-col a:hover { color: var(--accent); text-decoration: none; }
.footer-base {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .4rem var(--space-4);
  padding-top: var(--space-4);
  padding-bottom: var(--space-6);
  border-top: 1px solid var(--footer-line);
  color: var(--footer-faint);
  font-size: .78rem;
}
.footer-copy { font-weight: 500; color: var(--footer-soft); }
.footer-creed { font-style: italic; }
@media (max-width: 640px) {
  .footer-top { gap: var(--space-5); }
}
/* ── Navigation feedback ──────────────────────────────────────────────────
   Instant response to a click on a server-rendered page: a top progress bar
   plus a busy state on the activated control, so a slow page load never reads
   as a freeze. Driven by webapp/static/nav-progress.js. Also exposes reusable
   .spinner and .skeleton utilities for per-page async/placeholder states. */
#nav-progress {
  position: fixed; inset: 0 auto auto 0; height: 3px; width: 0;
  background: var(--accent); z-index: 9999; pointer-events: none;
  opacity: 0; box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 60%, transparent);
  transition: width .24s ease, opacity .2s ease;
}
#nav-progress.on { opacity: 1; }

/* The activated link/button while its navigation is in flight. */
.is-loading { cursor: progress; }
a.is-loading, button.is-loading, input.is-loading[type="submit"] { opacity: .72; }
.is-loading::after {
  content: ""; display: inline-block; width: .8em; height: .8em;
  margin-left: .5em; vertical-align: -.1em;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; animation: docray-spin .6s linear infinite;
}

/* Standalone spinner for JS-driven / async areas. */
.spinner {
  display: inline-block; width: 1.1em; height: 1.1em;
  border: 2px solid var(--ring); border-top-color: var(--accent);
  border-radius: 50%; animation: docray-spin .7s linear infinite;
}
@keyframes docray-spin { to { transform: rotate(360deg); } }

/* Content placeholder for slow panels/lists (add .skeleton to a sized box). */
.skeleton {
  position: relative; overflow: hidden; border-radius: 8px; min-height: 1em;
  background: var(--accent-wash);
}
.skeleton::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent,
    color-mix(in srgb, var(--accent) 14%, transparent), transparent);
  animation: docray-shimmer 1.3s infinite;
}
@keyframes docray-shimmer { 100% { transform: translateX(100%); } }

@media (prefers-reduced-motion: reduce) {
  #nav-progress { transition: opacity .2s ease; }
  .is-loading::after, .spinner, .skeleton::after { animation: none; }
}

/* Entrance choreography — opt-in. A container with .reveal rises its direct
   children in a short staggered sequence on load. Marketing/hero surfaces only;
   never wrap data tables (motion on dense rows reads as jank). */
@keyframes docray-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.reveal > * { opacity: 0; animation: docray-rise var(--dur-3) var(--ease-out) both; }
.reveal > *:nth-child(1) { animation-delay: 40ms; }
.reveal > *:nth-child(2) { animation-delay: 110ms; }
.reveal > *:nth-child(3) { animation-delay: 180ms; }
.reveal > *:nth-child(4) { animation-delay: 250ms; }
.reveal > *:nth-child(n+5) { animation-delay: 320ms; }

@media (prefers-reduced-motion: reduce) {
  .reveal > * { opacity: 1; animation: none; }
}

/* ============================================================================
   Corpus view modes — table / compact / gallery / grouped (BL-143)
   One control strip, four layouts over the same rows and selection model.
   ========================================================================= */
.corpus-controls {
  display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1rem;
  margin: 0 0 .9rem;
}
.view-switch {
  display: inline-flex; border: 1px solid var(--line); border-radius: var(--r-sm);
  overflow: hidden; background: var(--panel);
}
.view-switch__btn {
  font-family: var(--mono); font-size: .8rem; letter-spacing: .02em;
  padding: .38rem .72rem; color: var(--ink-soft); text-decoration: none;
  border-right: 1px solid var(--line-soft); white-space: nowrap;
}
.view-switch__btn:last-child { border-right: 0; }
.view-switch__btn:hover { background: var(--accent-wash); color: var(--accent); }
.view-switch__btn[aria-current="page"] { background: var(--accent); color: var(--btn-ink, #fff); }
.corpus-lens { display: inline-flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-left: auto; }
.corpus-lens label {
  font-family: var(--mono); font-size: .72rem; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-faint); display: inline-flex; align-items: center; gap: .35rem;
}
.corpus-lens select {
  font-family: var(--mono); font-size: .8rem; color: var(--ink); background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r-sm); padding: .3rem .5rem; text-transform: none; letter-spacing: 0;
}
.corpus-lens__apply {
  font-family: var(--mono); font-size: .78rem; padding: .34rem .7rem;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--panel); color: var(--ink); cursor: pointer;
}
.corpus-lens__apply:hover { border-color: var(--accent); color: var(--accent); }

/* type badge shared by compact + grouped */
.ti {
  font-family: var(--mono); font-size: .62rem; font-weight: 600; letter-spacing: .04em;
  padding: .12rem .34rem; border-radius: 4px; background: var(--panel);
  border: 1px solid var(--line); color: var(--ink-soft); white-space: nowrap;
}
.ti-pdf { color: var(--accent-ink); border-color: color-mix(in srgb, var(--accent) 30%, var(--line)); }
.ti-epub, .ti-md, .ti-txt, .ti-docx { color: var(--info); border-color: color-mix(in srgb, var(--info) 34%, var(--line)); }

/* ---- COMPACT: one line per document (the density fix) ---- */
.doc-compact { list-style: none; margin: 0; padding: 0; }
.doc-compact__row {
  display: grid; grid-template-columns: auto auto 1fr auto; align-items: center; gap: .8rem;
  padding: .5rem .85rem; border-bottom: 1px solid var(--line-soft);
}
.doc-compact__row:last-child { border-bottom: 0; }
.doc-compact__row:hover { background: var(--accent-wash); }
.doc-compact__title {
  font-family: var(--display); color: var(--ink); text-decoration: none; font-weight: 550;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.doc-compact__title:hover { color: var(--accent); }
.doc-compact__meta { display: flex; align-items: center; gap: 1.1rem; color: var(--ink-soft); }
.doc-compact__meta .num { font-size: .82rem; }
.doc-compact__meta .u { color: var(--ink-faint); font-size: .62rem; margin-left: .15rem; }
.corpus[data-density="compact"] .doc-compact__row { padding: .3rem .85rem; }
.corpus[data-density="compact"] .doc-compact__meta { gap: .8rem; }

/* ---- GALLERY: cover-forward cards ---- */
.doc-gallery {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: 1rem; padding: 1rem;
}
.corpus[data-density="compact"] .doc-gallery { grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr)); gap: .7rem; }
.doc-card { position: relative; border: 1px solid var(--line); border-radius: var(--r-sm); overflow: hidden; background: var(--panel); }
.doc-card__pick { position: absolute; top: .4rem; left: .4rem; z-index: 2; background: color-mix(in srgb, var(--panel) 80%, transparent); border-radius: 4px; padding: .1rem; }
.doc-card__cover { display: block; aspect-ratio: 3 / 4; background: var(--line-soft); }
.doc-card__cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.doc-card__placeholder {
  width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .3rem; color: var(--ink-faint); font-family: var(--mono); font-size: .62rem; text-align: center; padding: .5rem;
}
.doc-card__placeholder b { font-size: .9rem; color: var(--ink-soft); }
.doc-card__body { padding: .5rem .6rem .6rem; display: flex; flex-direction: column; gap: .2rem; }
.doc-card__title {
  font-family: var(--display); font-size: .82rem; font-weight: 550; color: var(--ink); text-decoration: none; line-height: 1.2;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.doc-card__title:hover { color: var(--accent); }
.doc-card__meta { font-family: var(--mono); font-size: .68rem; color: var(--ink-faint); }

/* ---- GROUPED: sections with a header, count, subtotal ---- */
.doc-group { border-bottom: 1px solid var(--line); }
.doc-group:last-of-type { border-bottom: 0; }
.doc-group__head { display: flex; align-items: center; gap: .7rem; padding: .8rem .85rem .4rem; }
.doc-group__name { font-family: var(--display); font-weight: 620; color: var(--ink); }
.doc-group__count {
  font-family: var(--mono); font-size: .7rem; color: var(--ink-faint);
  background: var(--panel); border: 1px solid var(--line); border-radius: 999px; padding: .05rem .5rem;
}
.doc-group__sum { margin-left: auto; color: var(--ink-faint); font-size: .72rem; }

/* ── Thumb-region navigation ───────────────────────────────────────────────
   On a phone the binding constraint is reach, not screen area: about half of
   users drive the device one-handed and the reachable region is the bottom of
   the screen. The recurring destinations therefore sit in a bottom bar, and a
   page's back affordance sits beside them, instead of both living in a masthead
   that a thumb has to stretch to the top edge to reach.

   Hidden by default: under a fine pointer the masthead nav is already the right
   control, and a fixed bar would only spend vertical space. */
.bottom-nav { display: none; }
.bottom-nav a, .bottom-nav__more {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .1rem;
  min-width: 0;
  padding: .3rem .2rem;
  border-radius: var(--r-sm);
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: .72rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
}
.bottom-nav a.on { color: var(--accent); background: var(--accent-wash); }
.bottom-nav__t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.bottom-nav__back { color: var(--ink); }

/* ── Coarse-pointer control layer ──────────────────────────────────────────
   Sizing is scoped to the input device in use, not to the viewport. Target
   acquisition time is a function of distance and size, and a finger is
   imprecise where a mouse is precise — so the compact sizing above stays
   correct under a mouse, and everything a user can activate grows to
   --tap-min once the primary pointer is coarse.

   Deliberately NOT keyed to a width breakpoint: a narrow desktop window is
   still driven by a mouse, and a large tablet is still driven by a thumb.
   Width is a fact about the viewport, never about the hand.

   Last in the file so it wins over the width-based layout rules above at equal
   specificity. Enforced by scripts/check_touch_targets.py. */
@media (pointer: coarse) {
  button, .btn,
  input:not([type]),
  input[type=text], input[type=file], input[type=email], input[type=password],
  input[type=search], input[type=number], input[type=tel], input[type=url],
  select, textarea {
    min-height: var(--tap-min);
  }

  /* Navigation, paging and segmented controls: the drawn chip may stay small
     on a mouse, but on touch these are primary targets. */
  header nav a, .nav-link-button, .pager a, .seg a, .seg label, .footer-nav a, a.pill {
    min-height: var(--tap-min);
    display: inline-flex;
    align-items: center;
  }
  .footer-nav a, .seg a, .seg label { display: flex; }

  /* Icon buttons are square, so both axes bound the target. */
  .nav-burger, .toggle {
    min-width: var(--tap-min);
    min-height: var(--tap-min);
    width: var(--tap-min);
    height: var(--tap-min);
  }
  .toggle span { width: calc(var(--tap-min) / 2); height: var(--tap-min); }

  /* A disclosure heading is the control for the section it opens. */
  summary { min-height: var(--tap-min); display: flex; align-items: center; }

  /* Tick boxes must stay tick-box sized to read as one, so the ACTIVE area is
     grown around the ink instead: 21.6px drawn + 13.2px of overlay on every
     side = a 48px target that changes nothing visually. */
  input[type=checkbox], input[type=radio] {
    position: relative;
    width: 1.35rem;
    height: 1.35rem;
  }
  input[type=checkbox]::after, input[type=radio]::after {
    content: "";
    position: absolute;
    inset: -13.2px;
  }

  /* Adjacent targets need ample spacing or the enlarged areas above start
     overlapping, which trades a small-target miss for an ambiguous hit. Row
     padding keeps a table row taller than one tap target. */
  th, td { padding: .85rem .6rem; }
  .seg { gap: .25rem; }
  .doc-compact__row { padding: .7rem .85rem; }
}

/* Thumb-region navigation, active only where there is a thumb. */
@media (pointer: coarse) {
  .bottom-nav {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    gap: .15rem;
    align-items: stretch;
    padding: .25rem .4rem;
    /* Clear the home indicator: a gesture bar must never sit on a tap target. */
    padding-bottom: calc(.25rem + env(safe-area-inset-bottom, 0px));
    background: color-mix(in srgb, var(--panel) 96%, transparent);
    border-top: 1px solid var(--line);
    box-shadow: 0 -1px 3px rgba(16, 24, 40, .06);
  }
  .bottom-nav a, .bottom-nav__more { min-height: var(--tap-min); }

  /* Reserve the bar's own height so a fixed bar never covers the last line of
     the page, and the footer stays reachable by scrolling. */
  main { padding-bottom: calc(var(--bottom-nav-h) + var(--space-5)); }
  .site-footer { margin-bottom: var(--bottom-nav-h); }

  /* The long tail opens upward from the bar rather than downward from the
     masthead, so the whole menu lands in the region the thumb can cover. */
  header .nav-cb:checked ~ nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(var(--bottom-nav-h) + env(safe-area-inset-bottom, 0px));
    z-index: 59;
    max-height: 60vh;
    overflow-y: auto;
    padding: .4rem .6rem .6rem;
    background: var(--panel);
    border-top: 1px solid var(--line);
    box-shadow: var(--shadow-lg);
  }
}
