/**
 * Tend.ai Alerts — admin console.
 *
 * The statutory instrument, rendered as software. Square corners without exception,
 * hairline rules and tonal layering instead of shadows, a signage grotesque for prose
 * and a mono reserved strictly for values that are measured, cited or legally
 * identified. See DESIGN.md; the rules there are load-bearing, not preferences.
 *
 * Fonts are self-hosted because the console's CSP is `default-src 'self'` — a
 * fonts.googleapis.com link is blocked outright, and silently falling back to Helvetica
 * would collapse the world this console is supposed to inhabit.
 */

/* --------------------------------------------------------------------------
   Faces
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url('fonts/archivo-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;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url('fonts/archivo-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Martian Mono';
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url('fonts/martian-mono-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;
}
@font-face {
  font-family: 'Martian Mono';
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url('fonts/martian-mono-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
    U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Ledger stock and printing ink. */
  --paper: #e7eae1;
  --paper-lit: #f3f5ef;
  --paper-sunk: #daded1;
  --ink: #0b0d0a;
  --ink-secondary: #4a5148;
  --rule: #c3c9bc;
  --pula: #0a5c9e;
  --pula-deep: #073f6d;
  --pula-tint: #bbd9f0;
  --mark: #ff3b00;      /* 24px and above, or on ink. Never below. */
  --mark-ink: #b82a00;  /* the only orange permitted on small text */
  --scan: #8b9384;

  /* Names the old stylesheet used. Kept so nothing has to be renamed to be restyled. */
  --bg: var(--paper);
  --panel: var(--paper-lit);
  --line: var(--rule);
  --edge: var(--ink);
  --muted: var(--ink-secondary);
  --accent: var(--mark-ink);
  --on-accent: var(--paper-lit);
  --danger: var(--mark-ink);
  --on-danger: var(--paper-lit);
  --warn: var(--mark-ink);
  --on-warn: var(--paper-lit);
  --ok: var(--ink);
  --selected-bg: var(--paper-lit);
  --selected-marker: var(--ink);

  --display: 'Archivo', Helvetica, Arial, sans-serif;
  --mono: 'Martian Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --hair: 1px;
  --xs: 4px;
  --sm: 8px;
  --md: 16px;
  --lg: 32px;
  --xl: 64px;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

/* An author `display` beats the UA stylesheet's rule for [hidden], and this system sets
   display on the header, the banner and the views. Restore the attribute's meaning once,
   here, rather than remembering it at every call site — the failure mode is the signed-out
   page leaking the whole console chrome. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--display);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* Nothing in this system is round. Stated once, at the top, as a rule rather than as a
   value repeated on every component — a radius anywhere is a defect. */
button, input, select, textarea, table, th, td, img, .card, .detail, .tag, kbd {
  border-radius: 0;
}

a { color: var(--ink); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--mark-ink); }

:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

h1, h2, h3, h4, h5 {
  margin: 0 0 var(--sm);
  font-weight: 650;
  letter-spacing: -0.025em;
  line-height: 1.05;
  font-variation-settings: 'wdth' 112;
  text-wrap: balance;
}
h1 { font-size: clamp(1.75rem, 3.4vw, 2.5rem); font-weight: 700; font-variation-settings: 'wdth' 118; }
h2 { font-size: 1.5rem; margin-bottom: var(--md); }
h3 { font-size: 1.0625rem; margin-top: var(--lg); font-variation-settings: 'wdth' 106; }
h4 { font-size: 0.9375rem; font-variation-settings: 'wdth' 100; letter-spacing: -0.01em; }
h5 { font-size: 0.875rem; font-variation-settings: 'wdth' 100; }
h2 + p.muted, h3 + p.muted { margin-top: calc(var(--sm) * -1); }

p { margin: 0 0 var(--md); max-width: 78ch; }

/* --------------------------------------------------------------------------
   Chrome
   -------------------------------------------------------------------------- */

header {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--md);
  padding: 0 var(--lg);
  height: 56px;
  background: var(--paper-lit);
  border-bottom: 1px solid var(--rule);
}

header strong {
  font-weight: 650;
  font-variation-settings: 'wdth' 112;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

header nav {
  display: flex;
  gap: 0;
  flex: 1;
  overflow-x: auto;
  scrollbar-width: none;
}
header nav::-webkit-scrollbar { display: none; }

header nav button {
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--ink-secondary);
  font-family: var(--display);
  font-size: 0.875rem;
  font-weight: 500;
  padding: 18px 14px 16px;
  white-space: nowrap;
  cursor: pointer;
  transition: color 120ms linear, border-color 120ms linear;
}
header nav button:hover { color: var(--ink); background: transparent; }
header nav button.active { color: var(--ink); border-bottom-color: var(--ink); font-weight: 600; }

#who {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  color: var(--ink-secondary);
  white-space: nowrap;
}

/*
 * `--main-pad` is `main`'s own padding, published so a full-bleed view can cancel exactly
 * as much as there is. The narrow breakpoint below halves it, and the company workspace
 * pulled a flat -32px through a 16px gutter — 16px of sideways scroll on the viewport
 * that could least afford it.
 */
main { --main-pad: var(--lg); padding: var(--main-pad); }

/* --------------------------------------------------------------------------
   Sign in and invitation redemption
   -------------------------------------------------------------------------- */

#signin, #redeem {
  max-width: 420px;
  margin: 12vh auto;
  padding: 0 var(--md);
}
#signin h1, #redeem h1 { margin-bottom: var(--xs); }
#signin .muted, #redeem .muted { margin-bottom: var(--lg); }

.signin-card {
  display: flex;
  flex-direction: column;
  gap: var(--md);
  background: var(--paper-lit);
  border: 1px solid var(--rule);
  padding: var(--lg) var(--md);
}

.or {
  position: relative;
  text-align: center;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  margin: var(--md) 0;
}
.or::before, .or::after {
  content: '';
  position: absolute;
  top: 50%;
  width: calc(50% - 24px);
  border-top: 1px solid var(--rule);
}
.or::before { left: 0; }
.or::after { right: 0; }

/* --------------------------------------------------------------------------
   Controls
   -------------------------------------------------------------------------- */

button {
  font-family: var(--display);
  font-size: 0.875rem;
  font-weight: 600;
  padding: 9px 15px;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--ink);
  cursor: pointer;
  transition: background-color 120ms linear, color 120ms linear;
}
button:hover { background: var(--ink); color: var(--paper-lit); }

/* Primary is Marking Orange with ink text — the accessible pairing at 5.3:1, and the
   authentic one: marking paint is always read dark-on-orange. */
button.primary {
  background: var(--mark);
  color: var(--ink);
  border-color: var(--mark);
  padding: 12px 22px;
  font-size: 0.9375rem;
}
button.primary:hover { background: var(--ink); color: var(--paper-lit); border-color: var(--ink); }

button.danger { color: var(--mark-ink); border-color: var(--mark-ink); }
button.danger:hover { background: var(--mark-ink); color: var(--paper-lit); }

button.block { display: block; width: 100%; }

button.link {
  border: 0;
  padding: 4px 0;
  font-weight: 500;
  color: var(--ink-secondary);
  text-decoration: underline;
  text-underline-offset: 3px;
}
button.link:hover { background: transparent; color: var(--ink); }

button[disabled] {
  color: var(--ink-secondary);
  background: transparent;
  border-color: var(--rule);
  cursor: not-allowed;
}
button[disabled]:hover { background: transparent; color: var(--ink-secondary); }

button kbd { margin-left: var(--sm); }
button.danger kbd { border-color: currentColor; color: currentColor; }

input, select, textarea {
  font-family: var(--display);
  font-size: 0.9375rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: 9px 10px;
  width: 100%;
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  border-color: var(--ink);
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
textarea { min-height: 64px; resize: vertical; }
select { appearance: none; background-image: none; padding-right: 10px; }

/* Values are measured things, so they set in mono even while being typed. */
input[inputmode='numeric'], input[type='number'], input[type='date'] { font-family: var(--mono); font-size: 0.8125rem; }

label {
  display: block;
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  margin-bottom: var(--md);
}
label input, label select, label textarea { margin-top: var(--xs); }
label.inline {
  display: inline-flex;
  align-items: center;
  gap: var(--sm);
  text-transform: none;
  letter-spacing: 0.02em;
  font-family: var(--display);
  font-size: 0.875rem;
  margin-bottom: 0;
}
label.inline input { width: auto; margin-top: 0; }
label .req, label span.req {
  color: var(--mark-ink);
  margin-left: var(--sm);
}

input[type='checkbox'] {
  width: 15px;
  height: 15px;
  accent-color: var(--ink);
  border: 1px solid var(--ink);
}
input[type='file'] {
  font-family: var(--mono);
  font-size: 0.75rem;
  background: var(--paper-sunk);
  border: 1px dashed var(--rule);
  padding: var(--md);
}

/* --------------------------------------------------------------------------
   Toolbars, keys, rows
   -------------------------------------------------------------------------- */

.toolbar {
  display: flex;
  align-items: center;
  gap: var(--sm);
  flex-wrap: wrap;
  padding: var(--sm) 0 var(--md);
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--md);
}
/*
 * A toolbar's text and select controls get a usable minimum width.
 *
 * `:not([type='checkbox'])` is load-bearing. `min-width` beats the 15px `width` set on
 * `input[type='checkbox']` above, so without the exclusion every checkbox in a toolbar
 * was laid out 190px wide — the box floated at one end of that span and its label text at
 * the other, reading as two unrelated controls. It affected the "show used, withdrawn and
 * expired" toggle on Invites and the closed-requests toggle on Compilation, both of which
 * shipped that way.
 */
.toolbar input:not([type='checkbox']), .toolbar select { width: auto; min-width: 190px; }
.toolbar-title { margin: 0; flex: 1; }

.row { display: flex; gap: var(--sm); flex-wrap: wrap; align-items: center; margin-bottom: var(--md); }
.row input, .row select { width: auto; flex: 1 1 180px; }

.hint { margin-left: auto; font-size: 0.8125rem; color: var(--ink-secondary); }

kbd {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 600;
  line-height: 1;
  padding: 4px 5px;
  border: 1px solid var(--rule);
  background: var(--paper-lit);
  color: var(--ink);
  margin: 0 2px;
}

/* --------------------------------------------------------------------------
   Split: the review queue
   -------------------------------------------------------------------------- */

.split {
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr);
  gap: 0;
  border-top: 1px solid var(--rule);
  min-height: 70vh;
}

.list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-right: 1px solid var(--rule);
  overflow-y: auto;
  max-height: 78vh;
}
.list li {
  display: grid;
  /* Third column is Jev's advisory verdict, right-aligned and spanning both rows. It is
     `auto`, so a queue with no verdicts collapses it to nothing and the layout is
     byte-identical to what it was before the column existed. */
  grid-template-columns: 56px minmax(0, 1fr) auto;
  grid-template-areas: 'gain title jev' 'gain kind jev';
  gap: 0 var(--sm);
  padding: 12px var(--md) 12px 10px;
  border-bottom: 1px solid var(--rule);
  border-left: 2px solid transparent;
  cursor: pointer;
}
.list li:last-child { border-bottom: 1px solid var(--rule); }
.list li:hover { background: var(--paper-lit); }
.list li.selected { background: var(--paper-lit); border-left-color: var(--ink); }
.list li.selected .gain, .list li.selected .title { color: var(--ink); font-weight: 600; }
.list li.claimed { text-decoration: line-through; color: var(--ink-secondary); }
.list li:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

.list .gain {
  grid-area: gain;
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--ink-secondary);
  font-variant-numeric: tabular-nums;
}
.list .title { grid-area: title; font-size: 0.9375rem; line-height: 1.35; }
.list .kind {
  grid-area: kind;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-secondary);
}

/*
  Jev's verdict on a queue row.

  Deliberately quiet: a monospace tag in secondary ink, not a coloured pill. A reviewer
  who reads a machine suggestion as an answer to confirm has stopped reviewing, and the
  cost of that is a wrong code broadcast to the wrong trade. It is legible when looked
  at and ignorable when not — the same weight the .kind tag carries.

  `reject` is the one that gets a border, because it is the verdict that would otherwise
  be invisible on a queue a reviewer is publishing through quickly.
*/
.list .jev {
  grid-area: jev;
  align-self: center;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.04em;
  color: var(--ink-secondary);
  font-variant-numeric: tabular-nums;
  padding: 2px 6px;
  border: 1px solid var(--rule);
  border-radius: 2px;
  white-space: nowrap;
}
.list .jev-reject { border-color: var(--ink-secondary); }

/* The same tag inside a table cell, where there is no grid area to sit in. */
td .jev {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.04em;
  color: var(--ink-secondary);
  font-variant-numeric: tabular-nums;
  padding: 2px 6px;
  border: 1px solid var(--rule);
  border-radius: 2px;
  white-space: nowrap;
}
/* The two answers that say "this is not a source". Marked, because they are the ones an
   operator scanning a list of plausible-looking hostnames would otherwise promote. */
td .jev-republisher, td .jev-newspaper { border-color: var(--ink-secondary); border-style: dashed; }
.list .jev-needs_human { border-style: dashed; }

.detail { padding: 0 0 0 var(--lg); overflow-y: auto; max-height: 78vh; }

/* --------------------------------------------------------------------------
   Sheets. There are no cards in this system — .card is a ruled sheet.
   -------------------------------------------------------------------------- */

.card {
  background: var(--paper-lit);
  border: 1px solid var(--rule);
  padding: var(--md) var(--md) var(--sm);
  margin-bottom: var(--lg);
}
.card h3 { margin-top: 0; }

.split-forms {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: var(--lg);
  align-items: start;
}

.actions {
  display: flex;
  gap: var(--sm);
  align-items: center;
  padding: var(--md) 0;
  border-top: 2px solid var(--ink);
  margin-top: var(--md);
  position: sticky;
  bottom: 0;
  background: var(--paper);
}

/* --------------------------------------------------------------------------
   Definition lists and field grids
   -------------------------------------------------------------------------- */

dl { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--xs) var(--md); margin: 0 0 var(--md); }
dt {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  padding-top: 3px;
}
dd { margin: 0; font-family: var(--mono); font-size: 0.8125rem; font-variant-numeric: tabular-nums; }

.field-grid { grid-template-columns: 168px minmax(0, 1fr); border-top: 1px solid var(--rule); padding-top: var(--sm); }
.field-grid dt { padding-top: 4px; }
.field-grid dd { padding-bottom: var(--xs); }
/* Prose is prose even inside a field grid. Mono is for measured values only. */
.field-grid dd.prose { font-family: var(--display); font-size: 0.9375rem; }
.field-grid dd.absent, .absent { color: var(--ink-secondary); font-style: italic; }

.reasons { list-style: none; margin: 0 0 var(--md); padding: 0; }
.reasons li {
  padding: var(--sm) 0 var(--sm) var(--md);
  border-bottom: 1px solid var(--rule);
  border-left: 2px solid var(--rule);
  font-size: 0.9375rem;
}

/* --------------------------------------------------------------------------
   Tables
   -------------------------------------------------------------------------- */

.scroller { overflow-x: auto; margin-bottom: var(--lg); border-top: 1px solid var(--rule); }
.scroller table { min-width: 100%; }

table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
th, td { text-align: left; padding: 9px var(--md) 9px 0; border-bottom: 1px solid var(--rule); vertical-align: top; }
th {
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  border-bottom: 1px solid var(--ink);
  white-space: nowrap;
}
td { font-family: var(--mono); font-size: 0.75rem; font-variant-numeric: tabular-nums; }
td.num { text-align: right; padding-right: var(--lg); }
/* A reason is a sentence, not a value. */
td.reason, td.prose { font-family: var(--display); font-size: 0.875rem; }
td button { padding: 5px 9px; font-size: 0.75rem; }
tr.warn td { border-left: 2px solid var(--mark-ink); }
tr.warn td:not(:first-child) { border-left: 0; }
.alarm-row > td { border-left: 2px solid var(--mark-ink); }
.alarm-row > td:not(:first-child) { border-left: 0; }

details pre {
  font-family: var(--mono);
  font-size: 0.6875rem;
  line-height: 1.5;
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
  padding: var(--sm);
  overflow-x: auto;
  max-width: 60ch;
}
details summary {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  color: var(--ink-secondary);
}
details[open] summary { color: var(--ink); }

/* --------------------------------------------------------------------------
   State. Every state prints a word — colour is never the only carrier.
   -------------------------------------------------------------------------- */

.muted { color: var(--ink-secondary); }
.small { font-size: 0.8125rem; }
.lede { font-size: 1rem; }
.ok { color: var(--ink); }
.error { color: var(--mark-ink); }
.warn { color: var(--mark-ink); }
.alarm { color: var(--mark-ink); font-weight: 600; }

.warn-inline, p.warn {
  background: var(--paper-sunk);
  border-left: 2px solid var(--ink);
  padding: var(--md);
  color: var(--ink);
  max-width: none;
}

.result { margin: 0 0 var(--md); font-size: 0.875rem; padding: var(--sm) 0 var(--sm) var(--md); border-left: 2px solid var(--rule); }
.result:empty { display: none; }
.result.ok { border-left-color: var(--ink); }
.result.error, .result.warn { border-left-color: var(--mark-ink); color: var(--mark-ink); }

/* A tag is square, ruled, and carries its word. Never a coloured pill. */
.flag, .tag, .pill {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.5625rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 2px 5px;
  margin-left: var(--sm);
  border: 1px solid var(--rule);
  color: var(--ink-secondary);
  white-space: nowrap;
}
.flag-warn, .flag-alarm { border-color: var(--mark-ink); color: var(--mark-ink); }
.flag-ok { border-color: var(--ink); color: var(--ink); }
.pill.open { border-color: var(--ink); color: var(--ink); }
.pill.closed { border-color: var(--rule); color: var(--ink-secondary); }

.conf {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.625rem;
  padding: 1px 4px;
  border: 1px solid var(--rule);
  color: var(--ink-secondary);
  margin-left: var(--xs);
}
.conf-low { border-color: var(--mark-ink); color: var(--mark-ink); }
.conf-low::after { content: ' low'; }

.role-pill {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  padding: 2px 6px;
  border: 1px solid var(--rule);
}
.role-pill.admin { border-color: var(--ink); color: var(--ink); font-weight: 600; }
.self-note { font-family: var(--display); font-size: 0.8125rem; color: var(--ink-secondary); }

/* --------------------------------------------------------------------------
   Boards, drift, guards, previews
   -------------------------------------------------------------------------- */

.stage-board {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border: 1px solid var(--rule);
  margin-bottom: var(--lg);
  overflow-x: auto;
}
.stage { padding: var(--md); border-right: 1px solid var(--rule); }
.stage:last-child { border-right: 0; }
.stage .n {
  display: block;
  font-family: var(--mono);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.stage .label {
  display: block;
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  margin-top: var(--xs);
}
/* The last stage is the one that pays. It takes the blue field. */
.stage-board .stage:last-child { background: var(--pula); }
.stage-board .stage:last-child .n { color: var(--paper-lit); }
.stage-board .stage:last-child .label { color: var(--pula-tint); }

.drift { list-style: none; margin: 0 0 var(--md); padding: 0; }
.drift li {
  padding: var(--sm) var(--md);
  border-bottom: 1px solid var(--rule);
  border-left: 2px solid var(--ink);
  font-size: 0.875rem;
}
.drift li::before {
  content: 'info';
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  margin-right: var(--sm);
  min-width: 44px;
}
.drift li.warn::before { content: 'warn'; color: var(--mark-ink); }
.drift li.alarm::before { content: 'alarm'; color: var(--mark-ink); }
.drift li.warn, .drift li.alarm { border-left-color: var(--mark-ink); }
.drift li strong { font-family: var(--mono); font-size: 0.8125rem; }

ul.guard { list-style: none; margin: 0; padding: 0; }
#crm-guard:not(:empty) {
  background: var(--paper-lit);
  border: 1px solid var(--rule);
  border-left: 2px solid var(--ink);
  padding: var(--md);
  margin-bottom: var(--lg);
}
#crm-guard p { margin: 0; }

/* The contractor's top-up menu, as a printed notice rather than cloned chat chrome.
   The notch is a registration mark; a rounded tail would make this a chat bubble. */
.wa-preview {
  background: var(--paper-lit);
  border: 1px solid var(--rule);
  padding: var(--md);
  max-width: 380px;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 10px 100%, 0 calc(100% - 10px));
}
.wa-preview h4 {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  margin: var(--md) 0 var(--xs);
}
.wa-preview h4:first-child { margin-top: 0; }

/* --------------------------------------------------------------------------
   Evidence
   -------------------------------------------------------------------------- */

.evidence { margin-bottom: var(--lg); }
.evidence h4 {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  margin: var(--lg) 0 var(--sm);
  padding-bottom: var(--xs);
  border-bottom: 1px solid var(--rule);
}
.evidence h4:first-child { margin-top: 0; }

.scope {
  background: var(--paper-sunk);
  border: 1px solid var(--rule);
  padding: var(--md);
  font-size: 0.9375rem;
  line-height: 1.6;
  max-width: 72ch;
  margin-bottom: var(--md);
}

.doc-actions { display: flex; gap: var(--md); align-items: center; margin-bottom: var(--md); }
/* Registration offset: the one permitted depth device. Hard, zero blur, a sheet on a plate. */
.doc-image {
  display: block;
  max-width: 100%;
  border: 1px solid var(--ink);
  box-shadow: 3px 3px 0 0 var(--ink);
  background: var(--paper-lit);
}

.candidate { border: 1px solid var(--rule); padding: var(--md); margin-bottom: var(--md); }
.candidate.subject { border-left: 2px solid var(--ink); }
.candidate h5 { margin-bottom: var(--sm); }

.resolution-note { margin: var(--lg) 0 var(--md); }
.resolution-note textarea { margin-top: var(--xs); }
.resolution-note .hint-line {
  display: block;
  margin-top: var(--xs);
  font-size: 0.8125rem;
  color: var(--ink-secondary);
}
.resolution-note label {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.audit-detail { font-family: var(--display); font-size: 0.875rem; }
td.actor { font-family: var(--display); font-size: 0.875rem; }

/* --------------------------------------------------------------------------
   The standing ruleset warning
   -------------------------------------------------------------------------- */

#ruleset-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  display: flex;
  align-items: baseline;
  gap: var(--md);
  flex-wrap: wrap;
  padding: 12px var(--lg);
  background: var(--mark-ink);
  color: var(--paper-lit);
  border-top: 1px solid var(--ink);
  font-size: 0.875rem;
}
#ruleset-banner strong { font-weight: 700; }
#ruleset-banner span { flex: 1; min-width: 280px; }
#ruleset-banner button {
  border-color: var(--paper-lit);
  color: var(--paper-lit);
  padding: 6px 12px;
  font-size: 0.8125rem;
}
#ruleset-banner button:hover { background: var(--paper-lit); color: var(--mark-ink); }
#ruleset-banner em { font-style: normal; text-decoration: underline; }

/* --------------------------------------------------------------------------
   Loading and failure. A control never refuses silently.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   The labelled set. Chips for what is selected, a ruled picker for what could be.

   No rounded pills and no coloured badges: a chip here is a legal identifier with its
   provenance printed beside it, so it sets in mono inside a hairline box like every other
   cited value in this console. The three origins are distinguished by the weight of the
   left rule rather than by hue — the difference between a code the model proposed and one
   a reviewer chose is a matter of record, not a status to be colour-coded, and the
   stylesheet has exactly one accent which is spent on marking.
   -------------------------------------------------------------------------- */

.ovl {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  margin: 0 0 var(--sm);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sm);
  margin-bottom: var(--md);
  padding-bottom: var(--md);
  border-bottom: 1px solid var(--rule);
}
.chips p { margin: 0; }

.chip {
  display: inline-flex;
  /* Centred rather than baseline-aligned: the chip carries two lines now — the trade and
     the parent code under it — and a baseline hung the number off the first of them. */
  align-items: center;
  gap: var(--sm);
  padding: 4px var(--xs) 4px var(--sm);
  border: 1px solid var(--rule);
  border-left-width: 2px;
  border-left-color: var(--ink-secondary);
  background: var(--paper);
}
/* The model marking its own work. Set apart because a holdout made of these measures
   agreement rather than correctness — see the comment on `label_source`. */
.chip-extraction { border-left-style: dashed; }
.chip-assist { border-left-style: dotted; }
.chip-manual { border-left-color: var(--ink); }

.chip-code {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}
.chip-origin {
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-secondary);
}
.chip-what { font-size: 0.8125rem; line-height: 1.3; }

/*
 * The parent code and the category it names, set under the specific trade.
 *
 * `100/01` was always printed in full, so the parent number was never missing — but it
 * was never named, and the parent is the half that carries the meaning: a contractor
 * quotes it ("we are 100"), and `match/engine.ts` selects candidates on the code alone
 * and never on the sub-code. Its own line, in the mono face the numbers use, so it reads
 * as the statutory entry it is rather than as a subtitle.
 */
.code-parent {
  display: block;
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink-secondary);
}
.picker-text .code-parent { font-size: 0.75rem; }
.chip-x {
  border: 0;
  background: transparent;
  color: var(--ink-secondary);
  font-size: 1rem;
  line-height: 1;
  padding: 0 var(--xs);
  cursor: pointer;
}
.chip-x:hover { background: transparent; color: var(--mark-ink); }
.chip-x:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }

/* The pre-filtered list. Rows are buttons because choosing one is an action, and they
   are full-width and ruled because it is a list of statutory entries, not a menu. */
.picker { border-top: 1px solid var(--rule); margin-bottom: var(--md); }
.picker-row {
  display: grid;
  grid-template-columns: 78px minmax(0, 1fr);
  gap: var(--sm) var(--md);
  width: 100%;
  text-align: left;
  padding: var(--sm) var(--xs);
  border: 0;
  border-bottom: 1px solid var(--rule);
  background: transparent;
  font-weight: 400;
  cursor: pointer;
}
.picker-row:hover { background: var(--paper-sunk); color: var(--ink); }
.picker-row:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.picker-code {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}
.picker-text { font-size: 0.875rem; line-height: 1.35; }
.picker-text .muted { display: block; font-size: 0.75rem; }
.picker-aside { grid-column: 2; }

/* A quoted span is evidence, so it is set as a quotation and never paraphrased away. */
.span {
  display: block;
  margin-top: var(--xs);
  padding-left: var(--sm);
  border-left: 2px solid var(--rule);
  font-family: var(--mono);
  font-size: 0.6875rem;
  line-height: 1.5;
  color: var(--ink-secondary);
}

.assist-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sm); margin-bottom: var(--md); }
.assist-line .hint-line { font-size: 0.8125rem; color: var(--ink-secondary); flex: 1 1 220px; }

button.quiet {
  border-color: var(--rule);
  font-weight: 500;
  font-size: 0.8125rem;
  padding: 6px 11px;
}

.assist-verdict, .assist-diff {
  padding: var(--sm) var(--md);
  margin-bottom: var(--md);
  background: var(--paper-sunk);
  border-left: 2px solid var(--ink);
  font-size: 0.875rem;
  line-height: 1.45;
}
/* Two independent readings landing on different trades is the case a human is actually
   needed for, so it is the one thing in this card allowed to raise its voice. */
.assist-diff { border-left-color: var(--mark-ink); }

.shortlist { margin-bottom: var(--md); }
.shortlist summary {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  cursor: pointer;
  padding: var(--sm) 0;
}
.shortlist summary:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

label.no-codes { margin-bottom: var(--xs); }

@media (max-width: 720px) {
  .picker-row { grid-template-columns: 1fr; gap: var(--xs); }
  .picker-aside { grid-column: 1; }
}

.view-error {
  background: var(--paper-sunk);
  border-left: 2px solid var(--ink);
  padding: var(--md);
  margin-bottom: var(--lg);
}
.view-error p { margin: 0 0 var(--sm); }

.loading {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  color: var(--ink-secondary);
}
.loading::after {
  content: '';
  animation: dots 1.2s steps(4, end) infinite;
}
@keyframes dots { 0% { content: ''; } 25% { content: '.'; } 50% { content: '..'; } 75% { content: '...'; } }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  .loading::after { content: '…'; }
}

.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 statutory dialog

   The console's single modal. It replaces every native confirm() and prompt() on a
   consequential action: those are rounded chrome from another world, they state none of
   the consequence, they cannot hold a labelled reason field, and in some embedding
   contexts they are suppressed outright — returning null so the action silently does
   nothing, which is the one refusal this console may never make.

   A document plate, so it takes the one permitted depth device: the registration
   offset, hard and zero-blur. Square, hairline-ruled, no radius, no glass.
   -------------------------------------------------------------------------- */

#statutory-dialog {
  position: fixed;
  margin: auto;
  width: min(560px, calc(100vw - 2 * var(--md)));
  max-height: calc(100vh - 2 * var(--md));
  overflow-y: auto;
  padding: var(--lg);
  border: 2px solid var(--ink);
  background: var(--paper-lit);
  color: var(--ink);
  font-family: var(--display);
  font-size: 1.0625rem;
  line-height: 1.55;
  /* The one permitted depth device: print registration, hard, zero blur. */
  box-shadow: 3px 3px 0 0 var(--ink);
}
#statutory-dialog::backdrop { background: rgba(11, 13, 10, 0.45); }
#statutory-dialog[open] { display: block; }

/* Printer's furniture. Hairlines, not glyphs — the CSP forbids an icon font. */
#statutory-dialog .reg-cross {
  position: absolute;
  width: 9px;
  height: 9px;
  pointer-events: none;
}
#statutory-dialog .reg-cross::before,
#statutory-dialog .reg-cross::after {
  content: '';
  position: absolute;
  background: var(--ink);
}
#statutory-dialog .reg-cross::before { left: 0; right: 0; top: 4px; height: 1px; }
#statutory-dialog .reg-cross::after { top: 0; bottom: 0; left: 4px; width: 1px; }
#statutory-dialog .reg-tl { top: 6px; left: 6px; }
#statutory-dialog .reg-tr { top: 6px; right: 6px; }
#statutory-dialog .reg-bl { bottom: 6px; left: 6px; }
#statutory-dialog .reg-br { bottom: 6px; right: 6px; }

#statutory-dialog-title {
  margin: 0 0 var(--sm);
  font-size: 1.375rem;
  font-weight: 650;
  font-variation-settings: 'wdth' 106;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
#statutory-dialog-body { margin-bottom: var(--md); }
#statutory-dialog-body p {
  margin: 0 0 var(--sm);
  font-size: 0.9375rem;
  color: var(--ink-secondary);
  max-width: 62ch;
}
#statutory-dialog-body p:last-child { margin-bottom: 0; }

/* The measured values the question is about — codes, ids, amounts. Mono, per the
   Measured Value Rule; `.field-grid` already sets the pair. */
#statutory-dialog-cited { margin-bottom: var(--md); border-bottom: 1px solid var(--rule); }

#statutory-dialog-field { margin-bottom: var(--md); }
#statutory-dialog-label {
  display: block;
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
}
#statutory-dialog-input {
  width: 100%;
  margin-top: var(--xs);
  font-family: var(--display);
  font-size: 0.9375rem;
}
.dialog-hint {
  display: block;
  margin-top: var(--xs);
  font-size: 0.8125rem;
  color: var(--ink-secondary);
}
#statutory-dialog-error { margin: 0 0 var(--md); }

.dialog-actions {
  display: flex;
  gap: var(--sm);
  justify-content: flex-end;
  flex-wrap: wrap;
  border-top: 1px solid var(--rule);
  padding-top: var(--md);
}
.dialog-actions button { flex: 0 1 auto; }

@media (max-width: 420px) {
  #statutory-dialog { padding: var(--md); }
  .dialog-actions { flex-direction: column-reverse; }
  .dialog-actions button { width: 100%; }
}

/* --------------------------------------------------------------------------
   Shared primitives app.js emits

   These classes were written by `loadInvites`, `loadAccess` and the row templates and
   had no definition anywhere — the state printed as unstyled text.
   -------------------------------------------------------------------------- */

/* An invitation's status, as the record states it. `.flag` / `.pill` carry a border and
   the word; `.status` is the same vocabulary keyed to the four values `statusOf` can
   return: open, redeemed, revoked, expired. Colour is never the only carrier — the word
   is always printed, and a closed record is also distinguished by a dashed rule. */
.status {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  padding: 2px 6px;
  border: 1px solid var(--rule);
  color: var(--ink-secondary);
  white-space: nowrap;
}
.status-open { border-color: var(--ink); color: var(--ink); font-weight: 600; }
.status-redeemed { border-color: var(--ink); color: var(--ink); }
.status-revoked,
.status-expired { border-style: dashed; border-color: var(--mark-ink); color: var(--mark-ink); }

/* A timestamp, printed as the measured value it is: the date, then the time of day.
   Both mono; the time is secondary because the day is what is usually being read. */
.stamp { display: inline-flex; flex-wrap: wrap; gap: 0 var(--sm); align-items: baseline; }
.stamp-date { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.stamp-time {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.02em;
  color: var(--ink-secondary);
  font-variant-numeric: tabular-nums;
}

/* A fact about an account that is not its name or its role — today, only that the
   account itself is disabled. Prose, so it sets in Archivo, and deliberately not
   `.muted.small`: views/access.js reads that class as the account's email address. */
.account-state {
  display: block;
  margin-top: var(--xs);
  font-family: var(--display);
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--ink-secondary);
  max-width: 44ch;
}

/* --------------------------------------------------------------------------
   The customer-success editors.

   Every form on the company inspector and the compilation queue is behind a
   disclosure, closed by default. That screen's stated purpose is answering "why
   was this contractor not told about this tender", and a support agent opens it
   to look far more often than to change something — a page of open forms reads
   as a form to fill in rather than a record to check.
   -------------------------------------------------------------------------- */

.editor {
  margin-top: var(--md);
  border-top: 1px solid var(--rule);
  padding-top: var(--sm);
}

.editor > summary {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  cursor: pointer;
  padding: var(--xs) 0;
}

.editor > summary:hover,
.editor > summary:focus-visible { color: var(--ink); }

.editor[open] > summary { color: var(--ink); margin-bottom: var(--sm); }

/* Inside a table cell the rule has nothing to separate — it reads as a stray line
   floating above the word, and there is already a row border doing that job. */
td > .editor { border-top: 0; margin-top: 0; padding-top: 0; }

/* A form inside a cell is narrow by definition, so it never gets two columns. */
td .grid-form { grid-template-columns: 1fr; }

/* Two columns on a desk, one on a phone. `.wide` spans both, which is what the
   reason field and the warnings want — a reason box half the width of the form
   invites half a sentence. */
.grid-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sm) var(--md);
  align-items: end;
}

.grid-form > .wide,
.grid-form > p,
.grid-form > label.wide { grid-column: 1 / -1; }

.grid-form label {
  display: block;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  min-width: 0;
}

.grid-form label.inline {
  display: flex;
  align-items: center;
  gap: var(--xs);
  text-transform: none;
  letter-spacing: 0;
  font-family: var(--display);
  font-size: 0.8125rem;
}

.grid-form input,
.grid-form select {
  display: block;
  width: 100%;
  margin-top: var(--xs);
  font-family: var(--display);
  font-size: 0.875rem;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: 6px 8px;
}

.grid-form label.inline input { width: auto; margin: 0; }
.grid-form input:focus-visible,
.grid-form select:focus-visible { outline: 2px solid var(--pula); outline-offset: 1px; }

/* The ownership warning. Hidden until the tier is actually being changed — a
   warning that is always on the page is a warning nobody reads. */
.ownership-evidence {
  border-left: 2px solid var(--mark);
  background: var(--paper-sunk);
  padding: var(--sm) var(--md);
}

.ownership-evidence p { margin: 0 0 var(--sm); max-width: 72ch; }

/* A company name in the compilation queue. It navigates, so it is a button —
   but it reads as the name it is, not as a control. */
.linklike {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  text-align: left;
}

.linklike:hover { color: var(--pula); }

button.small { font-size: 0.75rem; padding: 3px 7px; }

/* --------------------------------------------------------------------------
   Narrow. Reviewers work from phones in the field, so 320px is a normal case.
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  main { --main-pad: var(--md); }
  header { padding: 0 var(--md); gap: var(--sm); }
  .split { grid-template-columns: 1fr; }
  .list { border-right: 0; border-bottom: 1px solid var(--rule); max-height: 40vh; }
  .detail { padding-left: 0; padding-top: var(--md); max-height: none; }
  .stage-board { grid-auto-flow: row; grid-auto-columns: auto; }
  .stage { border-right: 0; border-bottom: 1px solid var(--rule); }
  .field-grid { grid-template-columns: 1fr; }
  .field-grid dt { padding-top: var(--sm); }
  .grid-form { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   Partner API
   -------------------------------------------------------------------------- */

/**
 * A minted key, the one secret this console ever displays.
 *
 * Set in mono at a size that survives being read off a screen and typed into a terminal,
 * and allowed to wrap rather than scroll: a value that runs off the edge of its box is
 * one somebody copies half of. `user-select: all` makes a single click take the whole
 * key, because a partial selection of a credential fails in a way that looks like the
 * credential is wrong.
 */
.minted-key {
  display: inline-block;
  font-family: var(--mono);
  font-size: 1rem;
  line-height: 1.6;
  padding: var(--sm) var(--md);
  margin: var(--sm) 0;
  background: var(--paper-sunk);
  border: 1px solid var(--edge);
  overflow-wrap: anywhere;
  user-select: all;
}

/**
 * The company picker's results.
 *
 * Buttons rather than a datalist or a select: the rows carry two lines each — the name
 * and the CIPA number — and a native control renders neither. Capped in height because
 * the search returns up to twenty-five and an unbounded list pushes the consent field,
 * which is the required one, off the screen.
 */
#partner-client-results {
  max-height: 16rem;
  margin-bottom: var(--sm);
}
#partner-client-results:not(:empty) {
  border: 1px solid var(--rule);
}
.company-pick {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-lit);
  padding: var(--sm) var(--md);
  font: inherit;
  cursor: pointer;
}
.company-pick:last-child { border-bottom: 0; }
.company-pick:hover,
.company-pick:focus-visible { background: var(--paper-sunk); }
.company-pick .small { display: block; }

/* The chosen contractor, stated before the consent field rather than left implicit in a
   cleared search box. */
#partner-client-chosen:not(:empty) {
  font-weight: 600;
  color: var(--ink);
}

/* A revoked key or a withdrawn authorisation stays on the register — "which one did we
   switch off, when and why" is the first question asked — so it is dimmed rather than
   hidden, and its flag carries the word. */
#partner-keys-table tr.muted td,
#partner-clients-table tr.muted td { opacity: 0.65; }

#partner-detail h4 {
  margin-top: var(--lg);
  padding-top: var(--md);
  border-top: 1px solid var(--rule);
}

/* A measured value that must not break across lines. A date split after the year reads
   as two numbers. */
.nowrap { white-space: nowrap; }

/*
 * The two authorisation grants, stacked.
 *
 * `label.inline` flows inline, which put "may file documents" and "may download the
 * files" side by side looking like a matched pair of equal weight. They are not: one
 * lets a firm add to a contractor's record, the other hands over scans of directors'
 * identity documents. Each gets its own line so neither is read past.
 */
#partner-client-form label.inline {
  display: flex;
  margin-bottom: var(--sm);
}

/* --------------------------------------------------------------------------
   The company workspace.

   One screen that does not scroll. Everything above the panel — the filters, the
   register, the identity line, the tab strip — holds its position, and the panel showing
   one topic is the only thing with a scrollbar. That is the whole design: a support agent
   answering "is their tax clearance current" should not have to travel past the gate
   traces to find out, and should not lose their place in the register to do it.

   The negative margin is how the section escapes `main`'s padding without `main` having
   to know which view is open. 56px is the header, which is sticky and therefore always
   occupying that band.
   -------------------------------------------------------------------------- */

.view.workspace {
  display: flex;
  flex-direction: column;
  /*
   * Out through `main`'s padding, without doing arithmetic about it. A negative inline
   * margin on a block box already widens it by exactly that much; adding an explicit
   * `width: calc(100% + …)` on top double-counts, because the percentage resolves against
   * the containing block rather than against the widened box — which is how this first
   * shipped 32px wider than the viewport and scrolling sideways.
   */
  margin: calc(var(--main-pad, var(--lg)) * -1);
  /*
   * `--chrome-h` is the header measured at runtime, not 56px.
   *
   * The header is 56px tall on a desktop and 101px at 820px wide, where the nav wraps
   * under the wordmark. A hardcoded 56 makes this section taller than the space left for
   * it on exactly the viewports where the layout is already tightest, and the page then
   * scrolls — which is the one thing this screen exists not to do. app.js keeps the
   * property in step; the fallback is the desktop height for the frame before it runs.
   */
  height: calc(100dvh - var(--chrome-h, 56px));
  min-height: 0;
}

.workspace-filters {
  display: flex;
  gap: var(--sm);
  align-items: center;
  flex-wrap: wrap;
  padding: var(--sm) var(--lg);
  border-bottom: 1px solid var(--rule);
  background: var(--paper-lit);
  flex: 0 0 auto;
}
.workspace-filters input, .workspace-filters select { width: auto; min-width: 150px; }
.workspace-filters input.narrow { min-width: 110px; }
.workspace-filters #company-search { min-width: 260px; flex: 1 1 260px; }

.view.workspace > .result { margin: 0; padding: var(--sm) var(--lg); flex: 0 0 auto; }

.workspace-grid {
  display: grid;
  grid-template-columns: 348px minmax(0, 1fr);
  flex: 1 1 auto;
  /* Without this the grid takes its height from its content and the page scrolls after
     all — the one failure this whole layout exists to prevent. */
  min-height: 0;
}

/* --- the register ------------------------------------------------------- */

.company-rail {
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--rule);
  min-height: 0;
  background: var(--paper-sunk);
}

.rail-list { flex: 1 1 auto; overflow-y: auto; min-height: 0; }

.rail-row {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  border-bottom: 1px solid var(--rule);
  border-left: 2px solid transparent;
  background: transparent;
  padding: var(--sm) var(--md);
  font-family: var(--display);
  font-size: 0.875rem;
  color: var(--ink);
  cursor: pointer;
}
.rail-row:hover { background: var(--paper-lit); }
.rail-row.selected { background: var(--paper-lit); border-left-color: var(--ink); }
.rail-row.selected .rail-name { font-weight: 650; }
.rail-row:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

.rail-name { display: block; line-height: 1.3; }
/* An archived contractor still reads as one on every screen that can reach them. A row
   that looks identical to a live client is how somebody credits a wallet belonging to a
   company we removed six weeks ago. */
.rail-row.gone .rail-name { text-decoration: line-through; color: var(--ink-secondary); }

.rail-meta {
  display: flex;
  gap: var(--sm);
  flex-wrap: wrap;
  align-items: center;
  margin-top: 2px;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.03em;
  color: var(--ink-secondary);
}

.rail-pager {
  flex: 0 0 auto;
  display: flex;
  gap: var(--sm);
  align-items: center;
  padding: var(--sm) var(--md);
  border-top: 1px solid var(--rule);
  background: var(--paper-lit);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.03em;
  color: var(--ink-secondary);
}
.rail-pager button { padding: 4px 10px; font-size: 0.75rem; }
.rail-pager .count { flex: 1; }

.rail-empty { padding: var(--md); font-size: 0.875rem; color: var(--ink-secondary); }

/* --- the record --------------------------------------------------------- */

.company-pane {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}

.pane-head {
  flex: 0 0 auto;
  display: flex;
  gap: var(--md);
  align-items: flex-start;
  padding: var(--md) var(--lg) var(--sm);
  border-bottom: 1px solid var(--rule);
}
.pane-ident { flex: 1; min-width: 0; }
.pane-ident h2 { margin: 0 0 2px; font-size: 1.25rem; }
.pane-ident .ident-line {
  display: flex;
  gap: var(--sm);
  flex-wrap: wrap;
  align-items: center;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.03em;
  color: var(--ink-secondary);
}
.pane-actions {
  display: flex;
  gap: var(--sm);
  flex: 0 1 auto;
  flex-wrap: wrap;
  justify-content: flex-end;
  max-width: 50%;
}
.pane-actions button { padding: 6px 12px; font-size: 0.8125rem; }
/*
 * Why a disabled button is disabled, on its own line.
 *
 * admin/views/company.js writes this note in beside the control it explains, which is
 * right — a `title` is not readable by keyboard or by a screen reader, and that is the
 * whole reason the note exists. Inside a flex row, though, it is a flex item: a sentence
 * became a third column and pushed Suspend, Remove and Restore off the side of the pane.
 * It takes the full row instead, under the buttons it is about.
 */
.pane-actions .self-note {
  flex-basis: 100%;
  text-align: right;
  line-height: 1.35;
}

/*
 * Why this contractor is off the platform, on every tab rather than on one.
 *
 * A state that is only visible where it was set is a state somebody edits around. This
 * band sits above the tab strip so a suspended company cannot be corrected, credited or
 * re-matched by anybody who has not read the reason first.
 */
.lifecycle-band {
  flex: 0 0 auto;
  padding: var(--sm) var(--lg);
  border-bottom: 1px solid var(--mark-ink);
  border-left: 3px solid var(--mark-ink);
  background: var(--paper-lit);
  font-size: 0.875rem;
  color: var(--mark-ink);
}
.lifecycle-band strong { font-weight: 650; }
.lifecycle-band .who { color: var(--ink-secondary); font-family: var(--mono); font-size: 0.6875rem; }

.tabs {
  flex: 0 0 auto;
  display: flex;
  gap: 0;
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--rule);
  padding: 0 var(--lg);
  background: var(--paper-lit);
}
.tabs::-webkit-scrollbar { display: none; }
.tabs:empty { display: none; }

.tabs [role='tab'] {
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--ink-secondary);
  font-family: var(--display);
  font-size: 0.8125rem;
  font-weight: 500;
  padding: 10px 14px 8px;
  white-space: nowrap;
  cursor: pointer;
}
.tabs [role='tab']:hover { color: var(--ink); background: transparent; }
.tabs [role='tab'][aria-selected='true'] {
  color: var(--ink);
  border-bottom-color: var(--ink);
  font-weight: 650;
}
.tabs [role='tab']:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

/*
 * The count a tab carries while it is shut.
 *
 * A tab nobody has opened must not read as empty. "Documents" beside a contractor holding
 * nothing and "Documents" beside one holding six are the same word, and the operator has
 * to press to find out which — so the number is on the tab. Same rule as lib/panels.js:
 * a collapsed section keeps its summary.
 */
.tabs .tab-n {
  margin-left: 6px;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.03em;
  color: var(--ink-secondary);
}
.tabs [role='tab'][aria-selected='true'] .tab-n { color: var(--ink); }
.tabs .tab-n.alarm { color: var(--mark-ink); font-weight: 700; }

.pane-body {
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 0;
  padding: var(--md) var(--lg) var(--lg);
}
/* The cards were built for a page with a bottom. Inside a panel that scrolls on its own,
   the last one's 32px tail is the panel's padding twice over. */
.pane-body .card:last-child { margin-bottom: 0; }
.pane-body .card { background: transparent; border: 0; padding: 0; margin-bottom: var(--lg); }
.pane-body .card + .card { border-top: 1px solid var(--rule); padding-top: var(--md); }
.pane-body .card h3 { margin-top: 0; }

.pane-empty { padding: var(--xl) var(--lg); max-width: 60ch; color: var(--ink-secondary); }

/*
 * Below a laptop the two panes cannot both be a column. The register becomes a strip
 * across the top and the record takes the rest; the page still does not scroll.
 */
@media (max-width: 900px) {
  .workspace-grid { grid-template-columns: minmax(0, 1fr); grid-template-rows: 180px minmax(0, 1fr); }
  .company-rail { border-right: 0; border-bottom: 1px solid var(--rule); }
  .pane-head { flex-wrap: wrap; }
}

/* --------------------------------------------------------------------------
   The PPRA register page, pasted or chosen (Sales → No codes)
   -------------------------------------------------------------------------- */

.dropzone {
  border: 2px dashed var(--ink);
  background: var(--paper-lit);
  padding: var(--md);
  margin: var(--sm) 0 var(--md);
}
.dropzone:focus-visible,
.dropzone.is-over { background: var(--paper-sunk); outline: none; }
.dropzone img { display: block; max-width: 100%; max-height: 240px; margin-top: var(--sm); }
#ipms-guide-text { white-space: pre-wrap; background: var(--paper-lit); padding: var(--sm); }
