/* BriefCycle — application styles.

   The register is the university's own paperwork: committee papers, minute
   books, registry documents. Parchment rather than white, an editorial serif
   that carries the headings and the small-caps labels, crisp corners, and one
   signature device — the double rule (a heavy line with a gilt hairline under
   it) that closes the masthead, the page title and the footer, and appears
   nowhere else. Colour beyond that is reserved for workflow state, so the eye
   goes to the grid.

   THEMING: every colour below is a token with a light and a dark value. Never
   hard-code a hex in a rule — it will be invisible or blinding in the other
   theme. The dark values are declared once as --d-*, then remapped by the two
   dark selectors, so a token can never gain a light value and lose its dark
   one. core/tests.py reads these blocks back and checks every pair for AA
   contrast, in both themes.

   --brand/-ink/-soft and --on-brand come from base.html, derived per tenant in
   core/branding.py (see relight(): a dark accent on a dark background is
   unreadable, so the dark set is the same hue re-lit, not the same hex). */

:root {
  /* Typography — the serif is the signature, and it sets the labels too. */
  --serif: "Charter", "Bitstream Charter", "Sitka Text", "Iowan Old Style", "Palatino Linotype", Cambria, Georgia, serif;
  --sans: ui-sans-serif, "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", sans-serif;
  --mono: ui-monospace, "Cascadia Code", "SF Mono", Consolas, Menlo, monospace;

  /* Crisp, not bubbly: 6px panels, 3px controls, 2px stamps. */
  --radius: 6px;
  --radius-sm: 3px;
  --radius-stamp: 2px;
  --shadow: 0 18px 40px -24px rgba(24, 32, 54, 0.30);
  --shadow-lift: 0 22px 44px -20px rgba(24, 32, 54, 0.38);

  font-size: 16.5px;

  /* Fallback accent — replaced per tenant by base.html. */
  --brand: #24385b;
  --brand-ink: #1e2e4b;
  --brand-soft: #e3e5ea;
  --on-brand: #f5f8fc;

  /* ---------- dark values, declared once ---------- */
  /* Read as "the same room at night": the paper goes to ink-navy and the ink
     goes to warm parchment, so the page never turns into grey-on-grey. */
  --d-ink: #e6e2d4;
  --d-muted: #a3a595;
  --d-faint: #8a91a3;
  --d-bg: #131722;
  --d-card: #1a2030;
  --d-card-2: #202839;
  --d-line: #2c3447;
  --d-line-soft: #232b3d;
  --d-row-hover: #202839;
  --d-rule: #647096;
  --d-gilt: #c2a24b;

  --d-done-bg: #1d2f24;   --d-done-fg: #a3c9ad;
  --d-curr-bg: #1f2a45;   --d-curr-fg: #a9c1ea;
  --d-ret-bg: #33260f;    --d-ret-fg: #d9a86a;
  --d-pend-bg: #232a38;   --d-pend-fg: #b0a995;
  --d-na-fg: #454e63;
  --d-pending: #232a38;

  --d-info-bg: #1d2843;   --d-info-fg: #a8c4fb;
  --d-warn-bg: #332913;   --d-warn-fg: #e5c078;   --d-warn-line: #a5822e;
  --d-error-bg: #391a1e;  --d-error-fg: #f0a2a2;  --d-error-line: #c25858;
  --d-success-bg: #1b2e21; --d-success-fg: #97c9a4; --d-success-line: #47775b;
  --d-danger: #b0453f;    --d-danger-hover: #a83f3a;
  --d-danger-line: #5c2c28; --d-on-danger: #f7ece9;

  --d-conf-bg: #322817;   --d-conf-fg: #e0b878;   --d-conf-line: #84682f;
  --d-conf-pill: #46381d;

  --d-viewer-bg: #232a3a;
  --d-scrim: rgba(0, 0, 0, 0.55);
}

/* ---------- light theme (default) ---------- */
:root, :root[data-theme="light"] {
  color-scheme: light;
  --ink: #1d2433;
  --muted: #4f596e;
  --faint: #5f6982;
  --bg: #f5f1e8;
  --card: #fdfbf4;
  --card-2: #f0ebdd;
  --line: #d8d2c2;
  --line-soft: #e8e3d4;
  --row-hover: #efeadd;
  /* The double rule: a heavy line and, a hair below it, gilt. */
  --rule: #2b3348;
  --gilt: #8a6c1f;

  /* Workflow state — a registry's own inks, never a highlighter. */
  --done-bg: #dfe8dc;   --done-fg: #2f5d3a;
  --curr-bg: #dde6f5;   --curr-fg: #2a4a8f;
  --ret-bg: #f3e2cf;    --ret-fg: #7a4a12;
  --pend-bg: #ece9e0;   --pend-fg: #6b6353;
  --na-fg: #a9a795;
  --pending: #ece9e0;

  /* Feedback */
  --info-bg: #e7ecf6;   --info-fg: #1e3a6e;
  --warn-bg: #f7edd8;   --warn-fg: #6d4a0c;   --warn-line: #b98a22;
  --error-bg: #f6e4e0;  --error-fg: #7a1f1f;  --error-line: #a83232;
  --success-bg: #e4ecdf; --success-fg: #29512f; --success-line: #4c7d55;
  --danger: #9d2b2b;    --danger-hover: #872424;
  --danger-line: #e5c1b8; --on-danger: #fdfbf4;

  /* Confidential — the manila folder. Deliberately its own colour, never
     confusable with a workflow state. */
  --conf-bg: #f8efdd;   --conf-fg: #7a5218;   --conf-line: #c9a25c;
  --conf-pill: #f0dfb8;

  --viewer-bg: #3f4658;
  --scrim: rgba(21, 28, 48, 0.4);
}

/* ---------- dark theme ---------- */
/* Follows the OS by default; [data-theme] beats it when the user has chosen.
   Both blocks are the same list of remaps — no values live here, so the two
   can never drift apart the way two copies of a palette do. */
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --ink: var(--d-ink); --muted: var(--d-muted); --faint: var(--d-faint);
    --bg: var(--d-bg); --card: var(--d-card); --card-2: var(--d-card-2);
    --line: var(--d-line); --line-soft: var(--d-line-soft);
    --row-hover: var(--d-row-hover);
    --rule: var(--d-rule); --gilt: var(--d-gilt);

    --done-bg: var(--d-done-bg);   --done-fg: var(--d-done-fg);
    --curr-bg: var(--d-curr-bg);   --curr-fg: var(--d-curr-fg);
    --ret-bg: var(--d-ret-bg);     --ret-fg: var(--d-ret-fg);
    --pend-bg: var(--d-pend-bg);   --pend-fg: var(--d-pend-fg);
    --na-fg: var(--d-na-fg);       --pending: var(--d-pending);

    --info-bg: var(--d-info-bg);   --info-fg: var(--d-info-fg);
    --warn-bg: var(--d-warn-bg);   --warn-fg: var(--d-warn-fg);
    --warn-line: var(--d-warn-line);
    --error-bg: var(--d-error-bg); --error-fg: var(--d-error-fg);
    --error-line: var(--d-error-line);
    --success-bg: var(--d-success-bg); --success-fg: var(--d-success-fg);
    --success-line: var(--d-success-line);
    --danger: var(--d-danger);     --danger-hover: var(--d-danger-hover);
    --danger-line: var(--d-danger-line); --on-danger: var(--d-on-danger);

    --conf-bg: var(--d-conf-bg);   --conf-fg: var(--d-conf-fg);
    --conf-line: var(--d-conf-line); --conf-pill: var(--d-conf-pill);

    --viewer-bg: var(--d-viewer-bg); --scrim: var(--d-scrim);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --ink: var(--d-ink); --muted: var(--d-muted); --faint: var(--d-faint);
  --bg: var(--d-bg); --card: var(--d-card); --card-2: var(--d-card-2);
  --line: var(--d-line); --line-soft: var(--d-line-soft);
  --row-hover: var(--d-row-hover);
  --rule: var(--d-rule); --gilt: var(--d-gilt);

  --done-bg: var(--d-done-bg);   --done-fg: var(--d-done-fg);
  --curr-bg: var(--d-curr-bg);   --curr-fg: var(--d-curr-fg);
  --ret-bg: var(--d-ret-bg);     --ret-fg: var(--d-ret-fg);
  --pend-bg: var(--d-pend-bg);   --pend-fg: var(--d-pend-fg);
  --na-fg: var(--d-na-fg);       --pending: var(--d-pending);

  --info-bg: var(--d-info-bg);   --info-fg: var(--d-info-fg);
  --warn-bg: var(--d-warn-bg);   --warn-fg: var(--d-warn-fg);
  --warn-line: var(--d-warn-line);
  --error-bg: var(--d-error-bg); --error-fg: var(--d-error-fg);
  --error-line: var(--d-error-line);
  --success-bg: var(--d-success-bg); --success-fg: var(--d-success-fg);
  --success-line: var(--d-success-line);
  --danger: var(--d-danger);     --danger-hover: var(--d-danger-hover);
  --danger-line: var(--d-danger-line); --on-danger: var(--d-on-danger);

  --conf-bg: var(--d-conf-bg);   --conf-fg: var(--d-conf-fg);
  --conf-line: var(--d-conf-line); --conf-pill: var(--d-conf-pill);

  --viewer-bg: var(--d-viewer-bg); --scrim: var(--d-scrim);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--sans);
  color: var(--ink);
  background: var(--bg);
  display: flex;
  min-height: 100vh;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 600;
  line-height: 1.15;
  text-wrap: balance;
}

a { color: var(--brand); }

/* ---------- header ---------- */
/* The double rule, used here, under the page title and above the footer, and
   nowhere else: a heavy rule, a hair of paper, then gilt — how a printed
   committee paper closes a section. The two box-shadows are copies of the box
   offset 1px and 2px: the first paints the gap in the page colour, the second
   leaves exactly 1px of gilt showing beneath it. */
.topbar {
  /* Sticky and opaque. A masthead is printed, not frosted. */
  position: sticky; top: 0; z-index: 20;
  background: var(--bg);
  border-bottom: 2px solid var(--rule);
  box-shadow: 0 1px 0 var(--bg), 0 2px 0 var(--gilt);
}
.topbar-inner {
  max-width: 1120px; margin: 0 auto; padding: 0.65rem 1.25rem;
  display: flex; align-items: center; gap: 2rem; flex-wrap: wrap;
}
.brand {
  color: var(--ink); text-decoration: none; font-family: var(--serif);
  font-size: 1.3rem; font-weight: 600;
  display: flex; align-items: center; gap: 0.6rem;
}
.brand-logo { height: 32px; width: auto; display: block; }
/* The mark's cycle inherits currentColor, so it follows the tenant's accent. */
.brand-mark { display: block; flex: none; color: var(--brand); }
.brand-name { color: var(--brand-ink); letter-spacing: 0.01em; }
.footer .powered { color: var(--muted); }
.mainnav { display: flex; gap: 0.65rem; flex: 1; flex-wrap: wrap; }
.mainnav a {
  color: var(--muted); text-decoration: none; padding: 0.35rem 0.35rem;
  font-weight: 500; font-size: 0.9rem;
}
/* An underline set clear of the baseline, the way a reference is marked up on
   paper — not a filled pill. */
.mainnav a:hover, .mainnav a:focus {
  color: var(--brand-ink);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--gilt);
  text-underline-offset: 6px;
}
.userbox { display: flex; align-items: center; gap: 0.75rem; font-size: 0.88rem; color: var(--muted); }
.username { color: var(--ink); }
.linklike {
  background: none; border: none; color: var(--brand); cursor: pointer;
  text-decoration: underline; font-size: 0.88rem; padding: 0; font-family: inherit;
}
.linklike:hover { color: var(--brand-ink); }

/* ---------- layout ---------- */
.page { max-width: 1120px; margin: 0 auto; padding: 1.5rem 1.25rem; width: 100%; flex: 1; }
/* The overview is a data grid, not prose: its metadata columns need ~1400px, so
   it keeps its own measure rather than scrolling sideways inside the site's. */
.page.wide { max-width: 1500px; }
.footer {
  color: var(--muted);
  padding: 1.25rem; font-size: 0.85rem; text-align: center; margin-top: 2rem;
  background: var(--card);
  border-top: 2px solid var(--rule);
  box-shadow: 0 -1px 0 var(--bg), 0 -2px 0 var(--gilt);
}
.page-title {
  font-family: var(--serif); font-size: 1.6rem; font-weight: 600;
  margin: 0.25rem 0 1.35rem; padding-bottom: 0.4rem; letter-spacing: -0.005em;
  border-bottom: 2px solid var(--rule);
  box-shadow: 0 1px 0 var(--bg), 0 2px 0 var(--gilt);
}
.breadcrumb {
  font-family: var(--serif); font-size: 1.25rem;
  margin: 0.25rem 0 1.35rem; padding-bottom: 0.4rem;
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; font-weight: 600;
  border-bottom: 2px solid var(--rule);
  box-shadow: 0 1px 0 var(--bg), 0 2px 0 var(--gilt);
}
/* One rule to a page. Where a breadcrumb introduces a title, the title carries
   it; browsers without :has() simply show both, which is only a redundancy. */
.breadcrumb:has(+ .page-title) {
  border-bottom: none; box-shadow: none; padding-bottom: 0; margin-bottom: 0.5rem;
  font-size: 1rem; font-weight: 500;
}
.breadcrumb span { color: var(--faint); font-weight: 400; }
.breadcrumb a { color: var(--brand); text-decoration: none; }
.breadcrumb a:hover { text-decoration: underline; }
.assigned-note { font-size: 0.85rem; color: var(--muted); font-weight: 400; }

/* ---------- small caps ---------- */
/* Every label, panel header and column head is set in letterspaced serif caps
   — a registry's own labelling. Real small-caps are synthesised inconsistently
   across the fallback stack, so this is uppercase and tracking, which renders
   identically everywhere. */
.panel-header,
.workflow-table thead .group-row th,
.workflow-table th.grid-col,
.doc-table th,
.data-table th,
.console-nav h2 {
  font-family: var(--serif);
  text-transform: uppercase;
  letter-spacing: 0.11em;
  font-weight: 600;
  /* These serif faces default to old-style figures, which set a "1" at
     x-height — "SEM 1" would read as "SEM ₁" beside capitals. */
  font-variant-numeric: lining-nums;
}

/* ---------- cards & banners ---------- */
.panel {
  border: 1px solid var(--line); border-radius: var(--radius);
  margin-bottom: 1.1rem; overflow: hidden; background: var(--card);
  box-shadow: var(--shadow);
}
.panel-header {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.7rem 1rem; border-bottom: 1px solid var(--line);
  background: var(--card-2);
  font-size: 0.76rem; color: var(--muted);
}
.panel-body { padding: 1rem; }

.banner { padding: 0.65rem 1rem; font-size: 0.93rem; border-left: 4px solid transparent; }
.banner.info { background: var(--info-bg); border-left-color: var(--curr-fg); color: var(--info-fg); }
.banner.warn, .banner.warning { background: var(--warn-bg); border-left-color: var(--warn-line); color: var(--warn-fg); }
.banner.error { background: var(--error-bg); border-left-color: var(--error-line); color: var(--error-fg); }
.banner.success { background: var(--success-bg); border-left-color: var(--success-line); color: var(--success-fg); }
/* Flash messages arrive wrapped in .messages, so they need naming here too —
   without this they are the only banners on the site with square corners. */
main > .banner, .messages .banner { border-radius: var(--radius); box-shadow: var(--shadow); }
.messages { display: flex; flex-direction: column; gap: 0.6rem; margin-bottom: 0.9rem; }

a.banner-link { display: block; text-decoration: none; transition: filter 0.15s ease, transform 0.15s ease; }
a.banner-link:hover { filter: brightness(0.97); transform: translateY(-1px); }

.task-list {
  list-style: none; margin: -0.25rem 0 1rem; padding: 0.25rem 0;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card); box-shadow: var(--shadow);
}
.task-list li {
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  padding: 0.55rem 1rem; align-items: baseline;
}
.task-list li + li { border-top: 1px solid var(--line-soft); }
.task-list a { color: var(--brand-ink); font-weight: 600; text-decoration: none; }
.task-list a:hover { text-decoration: underline; }
.task-list .muted-text { font-size: 0.85rem; }

/* ---------- home ---------- */
.home-links { display: flex; flex-direction: column; gap: 1rem; margin-top: 1.25rem; max-width: 860px; }
.home-link {
  display: block; padding: 1.15rem 1.35rem; border: 1px solid var(--line);
  border-radius: var(--radius); text-decoration: none; color: var(--ink);
  background: var(--card); box-shadow: var(--shadow);
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.home-link:hover {
  border-color: var(--brand); transform: translateY(-1px);
  box-shadow: var(--shadow-lift);
}
.home-link.muted { opacity: 0.65; }
.home-link-title { display: block; font-family: var(--serif); font-size: 1.15rem; font-weight: 600; color: var(--brand-ink); }
.home-link-desc { display: block; color: var(--muted); margin-top: 0.3rem; font-size: 0.93rem; }

/* ---------- filters ---------- */
.filters { padding: 0.85rem 1rem; }
.filter-row { display: flex; gap: 1rem; align-items: end; flex-wrap: wrap; }
.filters label { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.8rem; color: var(--muted); font-weight: 500; }
.filters label.checkbox { flex-direction: row; align-items: center; gap: 0.4rem; padding-bottom: 0.5rem; font-size: 0.88rem; }
.filters input[type="text"], .filters select {
  padding: 0.4rem 0.6rem; border: 1px solid var(--line); border-radius: var(--radius-sm);
  font-size: 0.9rem; min-width: 10rem; background: var(--card); color: var(--ink);
}
.filters input[type="text"]:focus, .filters select:focus { border-color: var(--brand); }

/* ---------- overview table ---------- */
.table-scroll {
  overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card); box-shadow: var(--shadow);
}
.workflow-table { border-collapse: collapse; width: 100%; font-size: 0.86rem; }
.workflow-table th, .workflow-table td {
  padding: 0.45rem 0.6rem; text-align: left; white-space: nowrap;
  border-bottom: 1px solid var(--line-soft);
}
.workflow-table thead .group-row th {
  background: var(--card); text-align: center; font-size: 0.72rem;
  color: var(--muted); border-bottom: none; padding-bottom: 0.1rem;
}
.workflow-table thead tr:nth-child(2) th {
  background: var(--card); font-size: 0.8rem; color: var(--ink);
  border-bottom: 2px solid var(--rule);
}
.workflow-table th.grid-col {
  width: 88px; text-align: center; font-size: 0.7rem;
  /* Tracking pushes centred text right by one space; pull it back. */
  padding-left: 0.71rem;
}
.workflow-table td.num { text-align: right; }
.workflow-table tbody tr:hover td { background: var(--row-hover); }
.workflow-table a { color: var(--brand-ink); font-weight: 600; text-decoration: none; }
.workflow-table a:hover { text-decoration: underline; }
.completed-note { color: var(--muted); font-style: italic; text-align: center; }

/* deadline cell in the overview */
.deadline { display: inline-block; padding: 0.1rem 0.4rem; border-radius: var(--radius-sm); white-space: nowrap; }
.deadline.overdue { background: var(--error-bg); color: var(--error-fg); font-weight: 600; }
.deadline.due_soon { background: var(--ret-bg); color: var(--ret-fg); font-weight: 600; }
.deadline.ok, .deadline { color: var(--ink); }

/* ---------- stamps ---------- */
/* A committee paper stamps a document; it does not badge it. Square-ish
   corners, serif caps, tracked out. */
.badge, .pill, .deadline-badge {
  border-radius: var(--radius-stamp);
  font-family: var(--serif);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-variant-numeric: lining-nums;
}
.deadline-badge {
  display: inline-block; padding: 0.1rem 0.45rem;
  font-size: 0.72rem; font-weight: 700; vertical-align: middle;
}
.deadline-badge.overdue { background: var(--error-bg); color: var(--error-fg); }
.deadline-badge.due_soon { background: var(--ret-bg); color: var(--ret-fg); }

.badge {
  display: inline-block; padding: 0.16rem 0.55rem;
  font-size: 0.74rem; font-weight: 600; vertical-align: middle;
}
.badge.current-step { background: var(--curr-bg); color: var(--curr-fg); }
.badge.done-step { background: var(--done-bg); color: var(--done-fg); }
.badge-returned { background: var(--ret-bg); color: var(--ret-fg); }
.badge-accepted { background: var(--done-bg); color: var(--done-fg); }

.legend {
  display: flex; gap: 1.25rem; margin: 0.85rem 0.25rem; align-items: center;
  font-size: 0.85rem; color: var(--muted); flex-wrap: wrap;
}
.legend span { display: inline-flex; align-items: center; gap: 0.4rem; }
/* A key, not a control: the swatch must not inherit the grid cell's full width. */
.legend .cell.sample {
  width: 26px; min-width: 26px; height: 20px; margin: 0;
  font-size: 0.72rem; font-style: normal;
}

/* ---------- detail page ---------- */
.details-grid {
  display: grid; grid-template-columns: repeat(4, minmax(180px, 1fr));
  gap: 0.65rem 1.5rem;
}
.detail { display: flex; gap: 0.5rem; font-size: 0.9rem; align-items: baseline; }
.detail .k { color: var(--muted); min-width: 7.5rem; }
.detail .v.strong { color: var(--brand-ink); font-weight: 650; }
.detail-wide { grid-column: 1 / -1; }

.doc-table { border-collapse: collapse; width: 100%; font-size: 0.9rem; }
.doc-table th, .doc-table td { border-bottom: 1px solid var(--line-soft); padding: 0.45rem 0.6rem; text-align: left; }
.doc-table th { font-size: 0.74rem; color: var(--muted); }
.doc-table a { color: var(--brand-ink); font-weight: 600; }
.doc-table .superseded td { color: var(--muted); }

details > summary { cursor: pointer; color: var(--brand-ink); font-weight: 600; padding: 0.35rem 0; }
details.revisions { margin-top: 0.75rem; }

.history { list-style: none; margin: 0.5rem 0 0; padding: 0; }
.history li { padding: 0.65rem 0; border-bottom: 1px solid var(--line-soft); }
.history li:last-child { border-bottom: none; }
.history-head { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; }
/* A reviewer's comment is quoted material — set it like marginalia. */
.history-comments {
  margin: 0.45rem 0 0 0.25rem; padding: 0.5rem 0.9rem;
  border-left: 3px solid var(--gilt); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--bg); color: var(--ink);
  font-family: var(--serif); font-size: 0.95rem; line-height: 1.5;
}
.history-uploads { font-size: 0.85rem; color: var(--muted); margin-top: 0.35rem; }
.history-uploads a { color: var(--brand-ink); }

/* ---------- document viewer & review workspace ---------- */
.viewer-panel iframe {
  display: block; width: 100%; height: 70vh; border: 0; background: var(--viewer-bg);
}
/* A text/plain document paints no background of its own, so whatever is behind
   the frame shows through — and the browser draws that text black or white
   purely from the OS preference. `color-scheme` on the iframe does not reach a
   UA-rendered document, so we cannot force it either way.
   These two hexes are therefore deliberately NOT tokens: tokens follow the
   in-app theme toggle, and a reader whose OS is dark while the app is set to
   light would get white text on light paper. Match the OS instead. Values are
   --card and --d-card. A PDF keeps --viewer-bg: it paints its own page. */
.viewer-panel iframe[data-kind="text"] { background: #fdfbf4; }
@media (prefers-color-scheme: dark) {
  .viewer-panel iframe[data-kind="text"] { background: #1a2030; }
}
.viewer-tabs {
  display: flex; gap: 0.35rem; flex-wrap: wrap; padding: 0.55rem 0.75rem;
  border-bottom: 1px solid var(--line-soft);
}
.viewer-tab {
  padding: 0.32rem 0.8rem; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); cursor: pointer; font-size: 0.85rem; font-family: inherit;
  color: var(--ink);
}
.viewer-tab:hover { border-color: var(--brand); color: var(--brand-ink); }
.viewer-tab.active { background: var(--brand); color: var(--on-brand); border-color: var(--brand); }
/* No opacity here: a tenant accent leaves little headroom over its own text
   colour, and fading the label is what pushed this below AA in dark. The
   smaller size already reads as secondary. */
.viewer-tab.active .muted-text { color: var(--on-brand); }

.workspace {
  display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: 1.1rem; align-items: start; margin-bottom: 1.1rem;
}
.workspace .panel { margin-bottom: 0; }
.workspace .action-panel { position: sticky; top: 1rem; }
.workspace .review-layout { grid-template-columns: 1fr; }

@media (max-width: 1100px) {
  .workspace { grid-template-columns: 1fr; }
  .workspace .action-panel { position: static; }
}

/* ---------- forms ---------- */
.stacked-form { max-width: 42rem; }
.field { margin-bottom: 0.95rem; display: flex; flex-direction: column; gap: 0.3rem; }
.field label { font-weight: 600; font-size: 0.88rem; }
.field input[type="text"], .field input[type="number"], .field input[type="date"],
.field input[type="password"], .field select, .field textarea {
  padding: 0.5rem 0.65rem; border: 1px solid var(--line); border-radius: var(--radius-sm);
  font-size: 0.95rem; font-family: inherit; background: var(--card);
  color: var(--ink); max-width: 40rem;
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--brand); }
.field textarea { width: 100%; max-width: 100%; }
.field input[type="file"] { font-size: 0.9rem; }
.field.has-error input, .field.has-error textarea, .field.has-error select { border-color: var(--error-line); }
.field-error { color: var(--error-fg); font-size: 0.85rem; }
.help { color: var(--muted); font-size: 0.85rem; }

.review-layout { display: grid; grid-template-columns: 2fr 1fr; gap: 1.25rem; align-items: start; }
.decision-box {
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 0.85rem 1.1rem; background: var(--bg);
}
.decision-box legend { font-family: var(--serif); font-weight: 600; padding: 0 0.4rem; }
.decision-box ul { list-style: none; margin: 0; padding: 0; }
.decision-box li { padding: 0.3rem 0; }
.decision-box label { font-weight: 400; }

.btn {
  /* 3px, and no lift: a control on a form, not a call to action. */
  display: inline-block; padding: 0.5rem 1.1rem; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--card); color: var(--ink); cursor: pointer;
  text-decoration: none; font-size: 0.92rem; font-family: inherit; font-weight: 500;
}
.btn:hover { border-color: var(--brand); color: var(--brand-ink); }
.btn.primary { background: var(--brand); color: var(--on-brand); border-color: var(--brand); }
.btn.primary:hover { background: var(--brand-ink); color: var(--on-brand); }
.btn.ghost { color: var(--muted); }

.muted-text { color: var(--muted); }

/* ---------- documentation ---------- */
.docs { max-width: 56rem; }
.docs h2 { font-size: 1.2rem; margin: 1.75rem 0 0.6rem; }
.docs h3 { font-size: 1rem; margin: 1.25rem 0 0.5rem; }
.docs p, .docs li { line-height: 1.55; }
.docs .doc-table { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.docs .doc-table th, .docs .doc-table td { padding: 0.5rem 0.75rem; }
.docs-steps { counter-reset: step; list-style: none; margin: 0.75rem 0; padding: 0; }
.docs-steps li {
  position: relative; padding: 0.55rem 0 0.55rem 2.6rem; counter-increment: step;
}
/* The steps are a real sequence — a numbered clause, set like one. */
.docs-steps li::before {
  content: counter(step); position: absolute; left: 0; top: 0.55rem;
  width: 1.7rem; height: 1.7rem; border-radius: var(--radius-stamp);
  background: var(--brand); color: var(--on-brand);
  font-family: var(--serif); font-weight: 600; font-size: 0.9rem;
  display: flex; align-items: center; justify-content: center;
}
.docs-steps li + li { border-top: 1px solid var(--line-soft); }
.docs-list { padding-left: 1.2rem; }
.docs-list li { margin-bottom: 0.5rem; }

/* ---------- login ---------- */
.login-card {
  max-width: 24rem; margin: 4rem auto; padding: 1.75rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card); box-shadow: var(--shadow);
}
.login-card h1 { margin-top: 0; font-size: 1.35rem; }
.login-card input { width: 100%; }
.sso-btn { display: block; text-align: center; width: 100%; margin-bottom: 0.5rem; }
.sso-divider {
  display: flex; align-items: center; text-align: center; color: var(--muted);
  font-size: 0.82rem; margin: 1rem 0;
}
.sso-divider::before, .sso-divider::after {
  content: ""; flex: 1; border-bottom: 1px solid var(--line);
}
.sso-divider span { padding: 0 0.6rem; }

@media (max-width: 900px) {
  .details-grid { grid-template-columns: 1fr; }
  .review-layout { grid-template-columns: 1fr; }
}

/* ---------- administration console ---------- */
/* Sidebar + content. Reuses the app's tokens so it never feels like a
   different product (the old Django admin very much did). */
.console { display: grid; grid-template-columns: 210px 1fr; gap: 1.5rem; align-items: start; }
.console-nav { position: sticky; top: 1rem; }
.console-nav h2 {
  font-size: 0.75rem; color: var(--muted); margin: 0 0 0.6rem 0.7rem;
}
.console-nav nav { display: flex; flex-direction: column; gap: 0.1rem; }
.console-nav a {
  padding: 0.45rem 0.7rem; border-radius: var(--radius-sm); text-decoration: none;
  color: var(--ink); font-size: 0.92rem; font-weight: 500;
}
.console-nav a:hover { background: var(--line-soft); }
/* The accent fill is ambience — a tenant's brand-soft can be very close to the
   card at night — so the current page is marked by a rule as well. */
.console-nav a.on {
  background: var(--brand-soft); color: var(--brand-ink); font-weight: 650;
  box-shadow: inset 2px 0 0 var(--brand);
}
.console-hint {
  margin: 1.25rem 0.7rem 0; font-size: 0.78rem; color: var(--muted); line-height: 1.5;
}
.console-main { min-width: 0; }
/* Here the title shares its line with an action, so the rule belongs to the
   whole head — on the title alone it would stop at whatever width the words
   happened to be. */
.console-head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem;
  padding-bottom: 0.5rem; margin-bottom: 1.35rem;
  border-bottom: 2px solid var(--rule);
  box-shadow: 0 1px 0 var(--bg), 0 2px 0 var(--gilt);
}
.console-head .page-title {
  margin-bottom: 0.3rem; padding-bottom: 0;
  border-bottom: none; box-shadow: none;
}
.console-head .lede { margin-bottom: 0; }
.lede { color: var(--muted); font-size: 0.92rem; margin: 0 0 1.25rem; max-width: 60ch; line-height: 1.5; }

/* Dashboard tiles */
.tile-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.85rem; margin-bottom: 1.25rem; }
.tile {
  display: flex; flex-direction: column; gap: 0.15rem; padding: 1rem;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); text-decoration: none; color: var(--ink);
}
.tile:hover { border-color: var(--brand); }
.tile-figure { font-family: var(--serif); font-size: 1.8rem; font-weight: 600; color: var(--brand-ink); line-height: 1.1; }
.tile-label { font-weight: 600; font-size: 0.92rem; }
.tile-note { font-size: 0.8rem; color: var(--muted); }
.tile-note.warn { color: var(--ret-fg); font-weight: 600; }

/* Generic admin tables */
.data-table { border-collapse: collapse; width: 100%; font-size: 0.9rem; }
.data-table th, .data-table td { border-bottom: 1px solid var(--line-soft); padding: 0.55rem 0.6rem; text-align: left; vertical-align: top; }
.data-table th { font-size: 0.72rem; color: var(--muted); }
.data-table tbody tr:hover td { background: var(--row-hover); }
.data-table a { color: var(--brand-ink); font-weight: 600; text-decoration: none; }
.data-table a:hover { text-decoration: underline; }
.data-table td.right, .data-table th.right { text-align: right; }
.data-table tr.muted td { color: var(--muted); }
.data-table .empty { color: var(--muted); text-align: center; padding: 1.5rem; }
.mono { font-family: var(--mono); font-size: 0.85rem; }

.pill {
  display: inline-block; padding: 0.08rem 0.42rem;
  background: var(--pending); color: var(--ink); font-size: 0.7rem; font-weight: 600;
  vertical-align: middle;
}
.pill.warn { background: var(--ret-bg); color: var(--ret-fg); }

.filter-bar { display: flex; gap: 0.5rem; margin-bottom: 1rem; }
.filter-bar input[type="search"] {
  flex: 1; max-width: 320px; padding: 0.4rem 0.6rem;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  font: inherit; font-size: 0.9rem; background: var(--card); color: var(--ink);
}
.filter-bar input[type="search"]:focus { border-color: var(--brand); outline: none; }

/* Checkbox fields read as "[x] label", not label-above-box. */
.field.check label { display: flex; align-items: center; gap: 0.45rem; font-weight: 500; cursor: pointer; }
.field.check input[type="checkbox"] { width: 1.5rem; height: 1.5rem; accent-color: var(--brand); }

/* Console lists read as prose — "link — what it does" — rather than the home
   page's task row, whose space-between pushes trailing text to the far edge. */
.task-list.prose li { display: block; }
.panel-body > .task-list { border: none; box-shadow: none; margin: 0; }

/* Destructive areas are visually quarantined. */
.panel.danger { border-color: var(--danger-line); }
.panel.danger .panel-header { background: var(--error-bg); color: var(--error-fg); border-bottom-color: var(--danger-line); }
.btn.danger { background: var(--danger); color: var(--on-danger); border-color: var(--danger); }
.btn.danger:hover { background: var(--danger-hover); color: var(--on-danger); border-color: var(--danger-hover); }

.logo-preview {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0.6rem 0.9rem; background: var(--line-soft); border-radius: var(--radius-sm); margin-bottom: 0.5rem;
}
.logo-preview img { max-height: 42px; max-width: 220px; }

@media (max-width: 780px) {
  .console { grid-template-columns: 1fr; }
  .console-nav { position: static; }
  .console-nav nav { flex-direction: row; flex-wrap: wrap; }
}

/* ---------- bulk import ---------- */
.import-summary {
  list-style: none; margin: 0.8rem 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.5rem;
}
.import-summary li {
  padding: 0.4rem 0.7rem; border-radius: var(--radius-sm);
  background: var(--pending); font-size: 0.9rem;
}
.import-summary li strong { font-size: 1.05rem; }
.import-summary li.ok { background: var(--done-bg); color: var(--done-fg); }
.import-summary li.bad { background: var(--error-bg); color: var(--error-fg); }

.import-rows { max-height: 22rem; overflow: auto; margin: 0.8rem 0; border: 1px solid var(--line-soft); border-radius: var(--radius-sm); }
.import-rows .data-table { font-size: 0.85rem; }
.import-rows th { position: sticky; top: 0; background: var(--card); z-index: 1; }
td.cell-note { color: var(--muted); }

.pill.created { background: var(--done-bg); color: var(--done-fg); }
.pill.updated { background: var(--brand-soft); color: var(--brand-ink); }
.pill.skipped { background: var(--pending); color: var(--muted); }
.pill.error   { background: var(--error-bg); color: var(--error-fg); }

.field-list { line-height: 2; }
.field-list code {
  background: var(--pending); padding: 0.1rem 0.4rem; border-radius: var(--radius-sm);
  font-family: var(--mono); font-size: 0.82rem;
}
.field-list code.req { font-weight: 700; color: var(--brand-ink); }
.inline-actions { display: flex; gap: 0.6rem; align-items: center; margin-top: 1rem; }
p.muted, .muted { color: var(--muted); }
p.muted { font-size: 0.85rem; }

/* ---------- confidentiality ---------- */
/* A confidential assessment should look different at a glance — an exams
   officer must never wonder whether the paper they're looking at is
   restricted. Manila, and the word itself: never colour alone. */
.panel.confidential { border-color: var(--conf-line); }
.panel.confidential .panel-header {
  background: var(--conf-bg); color: var(--conf-fg); border-bottom-color: var(--conf-line);
  display: flex; align-items: center; gap: 0.5rem;
}
.pill.lock { background: var(--conf-pill); color: var(--conf-fg); }

/* ---------- theme toggle ---------- */
/* Shows the theme you'd switch TO, which is the convention users expect. */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; cursor: pointer;
  background: none; border: 1px solid transparent; border-radius: var(--radius-sm);
  color: var(--muted);
}
.theme-toggle:hover { color: var(--ink); border-color: var(--line); }
.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: block; }
@media (prefers-color-scheme: dark) {
  .theme-toggle .icon-sun { display: block; }
  .theme-toggle .icon-moon { display: none; }
}
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }

/* ---------- stage cells ---------- */
/* One cell per stage (5), not per possible round (16). A round count appears
   only when a stage took more than one pass, so churn shows in a scan without
   spending a column on the exception. */
td.cell-wrap { text-align: center; padding: 0.3rem 0.15rem; min-width: 2rem; }
.cell {
  position: relative;
  display: grid; place-items: center;
  height: 34px; margin: 3px auto; width: calc(100% - 6px); min-width: 44px;
  border-radius: var(--radius-sm);
  font-size: 0.85rem; font-weight: 700; text-decoration: none;
}
a.cell:hover { filter: brightness(0.94); text-decoration: none; }
.cell.done { background: var(--done-bg); color: var(--done-fg); }
.cell.returned { background: var(--ret-bg); color: var(--ret-fg); }
.cell.pending { background: var(--pend-bg); color: var(--pend-fg); }
/* The stage awaiting someone is ruled, not animated — the glyph and the
   aria-label say which it is; the ring only helps you find it in a scan. */
.cell.current {
  background: var(--curr-bg); color: var(--curr-fg);
  box-shadow: inset 0 0 0 1.5px var(--curr-fg);
}
.cell.na {
  background: repeating-linear-gradient(45deg, var(--line-soft) 0 4px, var(--card) 4px 8px);
  border: 1px solid var(--line-soft);
}
.cell .rounds {
  position: absolute; top: 1px; right: 4px;
  font-size: 0.6rem; font-weight: 700; opacity: 0.8;
}
.legend-note { color: var(--muted); font-size: 0.8rem; }

/* ---------- accessibility ---------- */
/* Visually hidden until focused: keyboard users get a jump to the content
   without tabbing the whole nav; nobody else sees it. */
.skip-link {
  position: absolute; left: 0.5rem; top: -3rem; z-index: 100;
  background: var(--brand); color: var(--on-brand);
  padding: 0.5rem 0.9rem; border-radius: var(--radius-sm);
  text-decoration: none; font-weight: 600;
  transition: top 0.15s ease;
}
.skip-link:focus { top: 0.5rem; }

/* For content that must exist for screen readers but not be shown. */
.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;
}

/* The skip target shouldn't show a focus ring when jumped to (it's not
   interactive), but every real control must. */
#main-content:focus { outline: none; }

/* A focus ring that stays visible on the accent and in both themes. */
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 2px;
}

/* WCAG 2.2 (2.5.8) target size: radios/checkboxes must be at least 24px. */
.field input[type="radio"],
.field input[type="checkbox"],
.filters input[type="checkbox"] {
  width: 1.5rem; height: 1.5rem; accent-color: var(--brand);
}

/* ---------- prose pages (accessibility statement, etc.) ---------- */
.prose-page { max-width: 70ch; }
.prose h2 { font-size: 1.15rem; margin: 1.4rem 0 0.5rem; }
.prose h2:first-child { margin-top: 0; }
.prose p { margin: 0 0 0.8rem; line-height: 1.6; }
.prose ul { margin: 0 0 0.9rem; padding-left: 1.3rem; line-height: 1.6; }
.prose li { margin-bottom: 0.35rem; }
.prose a { color: var(--brand-ink); }

/* ---------- workflow stage editor ---------- */
.stage-editor td { vertical-align: top; }
.stage-editor input[type="text"], .stage-editor select { width: 100%; min-width: 6rem; }
.stage-editor input[type="number"] { width: 4.5rem; }
.stage-editor input, .stage-editor select {
  padding: 0.35rem 0.45rem; border: 1px solid var(--line);
  border-radius: var(--radius-sm); font: inherit; font-size: 0.9rem;
  background: var(--card); color: var(--ink);
}
.stage-editor input[type="checkbox"] { width: 1.5rem; height: 1.5rem; }

/* ---------- reports ---------- */
.overview-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
.report-cell { text-align: center; white-space: nowrap; }
.report-cell.done { color: var(--done-fg); font-weight: 700; }
