/* The consultant app's one stylesheet (design/UI-GUIDELINE.md, sections 3,
   6.1 and 6.2; the first look was design/2026-09-08-first-look/01-foundation.md).
   Order: fonts, tokens, reset and base elements, the shell (header, rail,
   page head, history drawer, login page), then the components in
   alphabetical order: back link, buttons, callouts, cards, charts, checks, empty
   state, filters, forms, key-value list, pager, pills, table. A screen
   opts in to a component by using its class; a bare element already
   looks right. No framework. The one script, static/app.js, echoes the
   chosen file's name next to the styled file input and does nothing
   else.

   Type: six styles and no others (guideline 3.2). Display 28/32 strong,
   Heading 20/26 strong, Strong 16/24, Body 16/24, Label 14/20 at 500,
   Small 14/20. A rule takes a size, a weight and a text colour only from
   the tokens below, and a rule that sets a size and a weight sets one of
   the six pairs. Nothing is under 14 px, drawings included. --mute, a
   line and a ground are never text, a separator dot included. A state
   ink colours a pill, an error line, the danger button and the
   timecard's green OK, never a sentence or a number. Rust has four
   jobs: the primary button, the current rail
   item's bar, the focus ring and a link on hover. A chosen tab, segment
   or option is a surface tile on a sunken track, never rust or black.
   consultant/tests/test_type_rules.py holds all of this. */

/* ---------- fonts: self-hosted, the appliance has no internet ---------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("fonts/inter-latin.woff2") format("woff2");
}

/* ---------- tokens ---------- */
:root {
  /* ground */
  --paper: #f5f1e8;
  --sunken: #ede7da;
  --surface: #fffdf7;
  --inverted: #16150f;
  /* lines: --rule between rows; --hairline round a card or a table; --edge for the header, the rail, a secondary button and the "?" */
  --rule: #e2daca;
  --hairline: #d2c9b4;
  --edge: #b9af97;
  /* text: --ink for titles, values and body; --ink-2 for labels, buttons and rail items; --ink-3 for secondary text.
     --mute is the edge of a field, checkbox or radio, and a disabled control. It is never text. */
  --ink: #171613;
  --ink-2: #39362f;
  --ink-3: #5a554b;
  --mute: #847e70;
  --ink-inv: #f5f1e8;
  /* accent: rust for the primary button, the current rail item's bar, the focus ring and a link on hover, nothing else;
     --accent-soft for a selected row and MicroForensics's own timecard column */
  --accent: #a6410f;
  --accent-hover: #8a350c;
  --accent-soft: #f3e2d6;
  /* the five semantic pairs: text colour and its tint, for the five meanings of guideline 5.4 and nothing else. No screen invents a sixth. */
  --pass: #2e6b4e; --pass-bg: #e3efe7;
  --fail: #a32723; --fail-bg: #f6e1df;
  --warn: #87590a; --warn-bg: #f5e9cf;
  --info: #245579; --info-bg: #dfe8f0;
  --hold: #5a554b; --hold-bg: #ede7da;
  /* type: one family, four sizes with their line heights, three weights (guideline 3.2).
     Every size, weight and line height in this file is one of these. */
  --font-ui: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --text-display: 1.75rem;        /* Display: the page title, a big figure; 28 px */
  --line-display: calc(32 / 28);
  --text-heading: 1.25rem;        /* Heading: a section or card title, a step; 20 px */
  --line-heading: calc(26 / 20);
  --text-body: 1rem;              /* Body and Strong: prose, values, cells, fields, rail items; 16 px */
  --line-body: calc(24 / 16);
  --text-small: 0.875rem;         /* Label and Small: labels, controls, pills, help, captions; 14 px */
  --line-small: calc(20 / 14);
  --weight-read: 400;             /* Body and Small */
  --weight-label: 500;            /* Label: field labels, table heads, buttons, tabs, pills, tags */
  --weight-strong: 600;           /* Display, Heading and Strong */
  /* spacing, base 4px (guideline 6.2) */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 0.75rem;
  --s4: 1rem;
  --s5: 1.5rem;
  --s6: 2rem;
  --s7: 3rem;
  --s8: 4rem;
  /* shape: one radius for controls, pills' tags and cards; one height for every control (guideline 6.4) */
  --r-control: 6px;
  --r-card: 6px;
  --control-h: 36px;
  /* the shell */
  --header-h: 56px;
  --rail-w: 224px;
  /* the four state icons (5.4) and the fold's chevron (6.7) as masks, for a callout, an error line and a fold's summary;
     a pill draws its icon inline (consultant/states.py). The same four shapes, in a 24-unit box. */
  --icon-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-10'/%3E%3C/svg%3E");
  --icon-clock: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E");
  --icon-flag: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 21V4'/%3E%3Cpath d='M5 4h12l-3 4 3 4H5'/%3E%3C/svg%3E");
  --icon-slash: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='m6 6 12 12'/%3E%3C/svg%3E");
  --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 6 6 6-6 6'/%3E%3C/svg%3E");
}

/* ---------- reset and base elements ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font-ui);
  font-size: var(--text-body);
  font-weight: var(--weight-read);
  line-height: var(--line-body);
  color: var(--ink);
  background: var(--paper);
}
a { color: var(--ink); text-decoration: underline; text-decoration-color: var(--edge); text-underline-offset: 2px; }
a:hover { color: var(--accent); text-decoration-color: var(--accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-control); }
/* the six styles on the base elements: h1 Display, h2 Heading, h3 Strong, body Body, label Label, small Small */
h1 {
  font-weight: var(--weight-strong);
  font-size: var(--text-display);
  line-height: var(--line-display);
  letter-spacing: -0.01em;
  margin: 0;
}
h2 { font-size: var(--text-heading); font-weight: var(--weight-strong); line-height: var(--line-heading); margin: var(--s6) 0 var(--s3); }
h3 { font-size: var(--text-body); font-weight: var(--weight-strong); line-height: var(--line-body); margin: var(--s5) 0 var(--s2); }
h4, h5, h6 { font-size: var(--text-body); font-weight: var(--weight-strong); line-height: var(--line-body); margin: var(--s4) 0 var(--s2); }
h2:first-child, h3:first-child { margin-top: 0; }
p { margin: 0 0 var(--s3); }
ul, ol { margin: 0 0 var(--s3); padding-left: 1.25rem; }
li { margin: 0 0 var(--s1); }
b, strong { font-weight: var(--weight-strong); }
em, i, cite, address { font-style: normal; }
small { font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); color: var(--ink-3); }
/* a clock time, a file name or a fingerprint stays in Inter, at the size of the text around it */
code, kbd, .mono { font-family: inherit; font-size: inherit; }
pre { font-family: inherit; font-size: var(--text-small); line-height: var(--line-small); margin: 0 0 var(--s3); white-space: pre-wrap; word-break: break-word; }
hr { border: 0; border-top: 1px solid var(--rule); margin: var(--s5) 0; }
/* the group's name above a title: Small */
.eyebrow {
  font-size: var(--text-small);
  font-weight: var(--weight-read);
  line-height: var(--line-small);
  color: var(--ink-3);
  margin: 0 0 var(--s2);
}
.small { font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); color: var(--ink-3); }

/* tables: a bare table sits on the surface, Body with tabular figures; its head row is Label */
table {
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--hairline);
  font-size: var(--text-body);
  line-height: var(--line-body);
  font-variant-numeric: tabular-nums;
  margin: 0 0 var(--s4);
  max-width: 100%;
}
th, td { text-align: left; vertical-align: top; padding: var(--s2) var(--s3); }
thead th {
  background: var(--sunken);
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: var(--line-small);
  color: var(--ink-2);
  white-space: nowrap;
  border-bottom: 1px solid var(--hairline);
}
td { border-top: 1px solid var(--rule); }
tbody tr:first-child td { border-top: 0; }
tbody tr:hover td { background: var(--paper); }
td code, th code { white-space: normal; overflow-wrap: anywhere; }

/* forms: a bare label still wraps its input inline, so an input keeps
   its own width. Labels above inputs come with the .field component. */
form { margin: 0 0 var(--s4); }
label { font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); }
/* an inline label keeps a little air between its words and its input */
label > input, label > select, label > textarea { margin-left: var(--s1); }
label > input[type="checkbox"], label > input[type="radio"] { margin-left: 0; }
form > label, p > label { margin-right: var(--s2); }
/* a control: one height, Body text, a 1 px --mute edge, the one radius, a 2 px rust ring on focus (guideline 6.4) */
input, select, textarea {
  font: inherit;
  font-size: var(--text-body);
  font-weight: var(--weight-read);
  line-height: var(--line-body);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--mute);
  border-radius: var(--r-control);
  padding: 5px 12px;
  min-height: var(--control-h);
  max-width: 100%;
}
input::placeholder, textarea::placeholder { color: var(--ink-3); }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
input:disabled, select:disabled, textarea:disabled { background: var(--sunken); color: var(--mute); }
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 36px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%235a554b' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}
select[multiple], select[size] { background-image: none; padding-right: 12px; }
textarea { min-height: 96px; padding: 8px 12px; vertical-align: top; }
/* a checkbox or a radio is 18 px, and its line is a control tall (guideline 6.4); its check is ink, not rust */
input[type="checkbox"], input[type="radio"] {
  width: 18px;
  height: 18px;
  min-height: 0;
  padding: 0;
  margin: 0 var(--s2) 0 0;
  vertical-align: -4px;
  accent-color: var(--ink-2);
}
input[type="file"] { border: 0; background: none; padding: 0; min-height: 0; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
input[type="number"] { width: 6rem; }

/* ---------- the shell ---------- */
/* The demo strip (guideline 5.1 item 1): the band and the persona switcher's control share one
   32 px line. The band must be the first thing in the body, on its own, with the core's words,
   so the body is a two-column grid: the band takes the first column, the control the second, and
   everything else spans both. On production there is no band and no control, and every row spans. */
body.shell { display: grid; grid-template-columns: minmax(0, 1fr) auto; }
body.shell > * { grid-column: 1 / -1; }
body.shell > .kind-band { grid-column: 1; }
body.shell > .walk-bar { grid-column: 2; }
/* the counsel banner (Burns, 11 Oct 2026; consultant/counsel.py): a warn callout drawn as one band under the
   header, edge to edge, for the manager, HR and the custodian while counsel's approval is not logged; never rust */
body.shell > .counsel-banner { margin: 0; max-width: none; border-radius: 0; border-bottom: 1px solid var(--edge); }
/* the demo mark (spec 12a section 5): the band above everything on every page unless the kind is production or not_installed; the gate inlines these two rules too */
.kind-band { background: var(--warn); color: #fff; padding: var(--s2) var(--s6); font-family: var(--font-ui); font-size: 0.875rem; font-weight: 600; line-height: 1.4; text-align: center; letter-spacing: 0.01em; }
.kind-band-unknown { background: var(--fail); }
/* the band in this app's scale: the core's line above stays verbatim for the gate, so the size and the spacing are set again here.
   Label, 20 px of line and 6 px above and below: the strip's 32 px. The text sits at the left, the control at the right. */
.kind-band { font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); letter-spacing: normal; padding: 6px var(--s4); text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* the persona switcher's control (FLO-487): the strip's right end, on the band's own ground, consultant only; the gate has its own persona page */
.walk-bar { display: flex; align-items: center; gap: var(--s3); height: 32px; padding: 0 var(--s4); background: var(--warn); color: var(--ink-inv); font-size: var(--text-small); line-height: var(--line-small); white-space: nowrap; }
.kind-band-unknown + .walk-bar { background: var(--fail); }
.walk-bar .walking { font-weight: var(--weight-label); }
.walk-bar a, .walk-bar .walk-back { color: var(--ink-inv); text-decoration: underline; }
.walk-bar .walk-back { padding: 0; border: 0; background: none; font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); cursor: pointer; }
.walk-bar form { margin: 0; }
/* the switcher page's persona buttons: one form per persona the core listed */
.personas { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--s2); }
.personas form { margin: 0; }
.personas .btn { height: auto; min-height: var(--control-h); padding: var(--s2) var(--s4); display: inline-flex; align-items: center; gap: var(--s2); flex-wrap: wrap; text-align: left; }
.walk-enter .personas { flex-direction: column; margin: var(--s4) 0 0; }
.walk-enter .walk-tour { margin: var(--s4) 0 0; }
/* the guided tour's bar at the foot of the page while a tour runs (FLO-488), on a sunken ground */
.tour-bar { position: sticky; bottom: 0; z-index: 10; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2) var(--s4); padding: var(--s2) var(--s4); background: var(--sunken); color: var(--ink); font-size: var(--text-small); line-height: var(--line-small); border-top: 1px solid var(--edge); }
.tour-bar-text { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s3); flex: 1 1 24rem; min-width: 0; }
.tour-bar .tour-step { font-weight: var(--weight-label); color: var(--ink); white-space: nowrap; }
.tour-bar .tour-todo { flex: 1 1 20rem; min-width: 0; }
.tour-bar .tour-as { font-weight: var(--weight-label); color: var(--ink-2); flex-basis: 100%; }
/* what went wrong is an error line, so it is the one state colour a sentence may take (guideline 6.4) */
.tour-bar .tour-problem { font-weight: var(--weight-label); color: var(--fail); flex-basis: 100%; }
.tour-bar-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.tour-bar form { margin: 0; }
.tour-bar button[disabled] { opacity: 0.55; cursor: not-allowed; }
.tour-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); }
.tour-actions form { margin: 0; }
.tour-steps { list-style: none; margin: 0; padding: 0; }
.tour-steps li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2) var(--s3); padding: var(--s2) 0; border-top: 1px solid var(--hairline); }
.tour-steps li:first-child { border-top: 0; }
/* the stop the tour is on: a surface tile, in ink */
.tour-steps li.here { background: var(--surface); box-shadow: inset 0 0 0 1px var(--hairline); margin: 0 calc(-1 * var(--s3)); padding: var(--s2) var(--s3); border-radius: var(--r-control); }
.tour-steps li.behind { color: var(--ink-3); }
.tour-steps .tour-key { font-weight: var(--weight-strong); min-width: 2rem; }
.tour-steps .tour-words { flex: 1 1 24rem; min-width: 0; }
/* the changes tour's bar and pages (FLO-502 batch 1): beside the guided tour's, never in its place */
.changes-bar { position: sticky; bottom: 0; z-index: 10; display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--s2) var(--s4); padding: var(--s2) var(--s4); background: var(--sunken); color: var(--ink); font-size: var(--text-small); line-height: var(--line-small); border-top: 1px solid var(--edge); max-height: 50vh; overflow-y: auto; }
.changes-bar p { margin: 0 0 var(--s1); }
.changes-bar-text { flex: 2 1 24rem; min-width: 0; }
.changes-bar .tour-step { font-weight: var(--weight-label); color: var(--ink); margin-right: var(--s2); }
.changes-bar .tour-as { font-weight: var(--weight-label); color: var(--ink-2); }
.changes-bar .tour-problem { font-weight: var(--weight-label); color: var(--fail); }
.changes-label { font-weight: var(--weight-label); }
.changes-note { flex: 1 1 18rem; min-width: 0; display: flex; flex-direction: column; gap: var(--s1); margin: 0; }
.changes-note textarea { width: 100%; font: inherit; }
.changes-choices { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.changes-saved { color: var(--ink-2); }
.changes-bar .tour-bar-actions { flex-basis: 100%; }
.changes-bar form { margin: 0; }
.changes-bar button[disabled] { opacity: 0.55; cursor: not-allowed; }
.changes-stops form { margin: 0; }
.changes-note-text { white-space: pre-wrap; }
/* presenter mode (FLO-585): the lean bar, one line, the title left and the two buttons right */
.changes-bar.presenter { align-items: center; justify-content: space-between; background: var(--surface); font-size: var(--text-body); line-height: var(--line-body); max-height: none; overflow: visible; }
.changes-bar.presenter .changes-head { margin: 0; }
.changes-bar.presenter .tour-bar-actions { flex-basis: auto; }
.changes-place { color: var(--ink-2); font-size: var(--text-small); line-height: var(--line-small); white-space: nowrap; }
.header {
  position: sticky;
  top: 0;
  z-index: 10;
  height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  padding: 0 var(--s5);
  background: var(--paper);
  border-bottom: 1px solid var(--edge);
}
.brand { display: flex; align-items: baseline; gap: var(--s3); min-width: 0; }
.brand .wordmark {
  font-family: inherit;
  font-size: var(--text-heading);
  font-weight: var(--weight-strong);
  line-height: var(--line-heading);
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.brand .instance { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.brand .instance::before { content: "\00b7"; margin-right: var(--s3); color: var(--ink-3); }
.who { display: flex; align-items: center; gap: var(--s3); font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); white-space: nowrap; }
.who .name { font-weight: var(--weight-label); color: var(--ink); }
/* the role in words, after the name (guideline 5.1 item 2) */
.who .role::before { content: "\00b7"; margin-right: var(--s3); color: var(--ink-3); }
/* The person's menu: the name opens a <details> with My preferences and Sign out under it.
   No script; it closes on the next page like any <details>. */
.who .person { position: relative; }
.who .person > summary { list-style: none; display: flex; align-items: center; gap: var(--s1); padding: var(--s1) var(--s2); border-radius: var(--r-control); cursor: pointer; }
.who .person > summary::-webkit-details-marker { display: none; }
.who .person > summary::after { content: "\25BE"; color: var(--ink-3); }
.who .person > summary:hover, .who .person[open] > summary { background: var(--sunken); }
.who .person .menu { position: absolute; right: 0; top: calc(100% + var(--s1)); z-index: 20; min-width: 12rem; display: flex; flex-direction: column; padding: var(--s1); background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--r-card); box-shadow: 0 2px 6px rgba(23, 22, 19, 0.12); }
.who .person .menu a, .who .person .menu button { display: block; width: 100%; padding: var(--s2) var(--s3); border: 0; border-radius: var(--r-control); background: none; color: var(--ink); text-align: left; text-decoration: none; font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); cursor: pointer; }
.who .person .menu a:hover, .who .person .menu button:hover, .who .person .menu a[aria-current="page"] { background: var(--sunken); color: var(--ink); }
.who form { margin: 0; }
/* a link that leaves this app: the export gate */
.out::after { content: "\2197"; margin-left: var(--s1); color: var(--ink-3); }

.frame {
  display: flex;
  min-height: calc(100vh - var(--header-h));
  background: linear-gradient(to right, var(--sunken) 0, var(--sunken) var(--rail-w), var(--edge) var(--rail-w), var(--edge) calc(var(--rail-w) + 1px), transparent calc(var(--rail-w) + 1px));
}
.rail {
  flex: 0 0 var(--rail-w);
  position: sticky;
  top: var(--header-h);
  height: calc(100vh - var(--header-h));
  overflow-y: auto;
  background: var(--sunken);
  border-right: 1px solid var(--edge);
  padding: var(--s4) var(--s3);
}
/* Home alone at the top, then one <details> per group (guideline 4.1). A group's name is Label
   with its icon; a page is Body in ink-2, indented 24 px under the name; the current page is
   Strong in ink, with the one rust bar. A closed group's count sits at the right of its name. */
.rail .group { margin-top: var(--s2); }
.rail .group > summary { list-style: none; display: flex; align-items: center; gap: var(--s2); padding: 6px 10px; border-radius: var(--r-control); font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); cursor: pointer; }
.rail .group > summary::-webkit-details-marker { display: none; }
.rail .group > summary::before { content: "\25B8"; width: 10px; color: var(--ink-3); }
.rail .group[open] > summary::before { content: "\25BE"; }
.rail .group > summary:hover { background: var(--paper); color: var(--ink); }
.rail .group > summary .icon { flex: 0 0 16px; width: 16px; height: 16px; }
.rail .group > summary .label { flex: 1 1 auto; min-width: 0; }
.rail .group > summary .count { flex: 0 0 auto; min-width: 20px; padding: 0 6px; border-radius: 10px; background: var(--paper); border: 1px solid var(--hairline); text-align: center; font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); }
.rail a {
  display: block;
  position: relative;
  padding: 4px 10px;
  border-radius: var(--r-control);
  font-size: var(--text-body);
  line-height: var(--line-body);
  color: var(--ink-2);
  text-decoration: none;
}
/* 4.1: a page starts 24 px right of its group's name. The name starts after the summary's
   10 px padding, the 10 px marker, the 16 px icon and the two 8 px gaps: 52 px; so 76 px. */
.rail .group a { padding-left: 76px; }
.rail a:hover { background: var(--paper); color: var(--ink); }
.rail a.here { background: var(--surface); color: var(--ink); font-weight: var(--weight-strong); }
.rail a.here::before {
  content: "";
  position: absolute;
  left: 0;
  top: 4px;
  bottom: 4px;
  width: 3px;
  border-radius: 2px;
  background: var(--accent);
}

/* A bare table wider than the column scrolls inside main, never the page.
   The table wrapper of the next ticket takes this job over per screen. */
main { flex: 1 1 auto; min-width: 0; max-width: 1320px; padding: var(--s5) var(--s6); overflow-x: auto; }
.page-head { display: flex; justify-content: space-between; align-items: flex-end; gap: var(--s4); margin-bottom: var(--s5); }
.page-head .lede { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-3); margin: var(--s2) 0 0; max-width: 72ch; }
.page-head .actions { margin: 0; flex: 0 0 auto; }
/* Batch 7 (Burns's walk of batch 6: the title and lede "stacked on the page like it is in a narrow
   column"): the title block keeps at least 24rem, and a row of actions too wide to sit beside it
   drops under it instead of squeezing it. */
.page-head { flex-wrap: wrap; }
.page-head > :first-child { flex: 1 1 24rem; min-width: 0; }
.page-head > .head-side { flex: 0 1 auto; display: flex; flex-direction: column; align-items: flex-start; gap: var(--s1); }
.page-head > .head-side .actions { flex-wrap: wrap; }
/* "Check again" is a one-button form among the links (Burns's walk, 9 Oct). */
.actions form.check-again { display: inline-flex; margin: 0; }
/* a state pill sits level with the title, not on the lede's baseline (FLO-320) */
.page-head .actions.state { align-self: flex-start; margin-top: 1.5rem; }
/* ---- page help (FLO-502 batch 3's walk; Burns, 8 Oct 2026: less to read on a page): a "?" beside
   the lede that shows the page's explanation on hover or keyboard focus. No script: the button only
   takes focus. The text hangs under the lede line, from its left edge, never wider than its measure,
   so it stays on the page however far along the line the "?" sits. ---- */
.page-head .lede { position: relative; }
/* 6.8: a 24 px circle, 8 px after the lede's last word */
.page-help { display: inline-block; margin-left: var(--s2); vertical-align: middle; }
.page-help-btn { display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; padding: 0; border: 1px solid var(--edge); border-radius: 50%; background: var(--surface); color: var(--ink-2); font: inherit; font-size: var(--text-small); font-weight: var(--weight-label); line-height: 1; cursor: help; }
.page-help-btn:hover, .page-help-btn:focus { border-color: var(--accent); color: var(--accent); outline: none; }
.page-help-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.page-help-text { display: none; position: absolute; left: 0; right: 0; top: calc(100% + var(--s1)); z-index: 20; max-width: 36rem; padding: var(--s3) var(--s4); background: var(--surface); color: var(--ink-2); border: 1px solid var(--edge); border-radius: var(--r-card); box-shadow: 0 2px 6px rgba(23, 22, 19, 0.12); font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); }
.page-help:hover .page-help-text, .page-help:focus-within .page-help-text { display: block; }
/* FLO-590: a short lede is narrow, so the pop-up takes its own width, up to the same 36rem (6.8), and never past the viewport */
.page-help-text { right: auto; width: max-content; max-width: min(36rem, calc(100vw - 2 * var(--s4))); }
/* UI-9: the "?" beside a field's label hangs its text under that label (Setup's business days) */
.field .page-help { position: relative; vertical-align: baseline; }
/* the Contractor files tile (piece 10): its "?" pops over the tile */
.tile .page-help { position: relative; }
/* a "?" near an edge (review, 12 Oct): a text that hung from its "?" ran off the right edge (Exposure's
   Contractor files tile at 1280, Setup's fields at 390). Where the browser can anchor, each text opens
   under its own "?" toward the side with room, inside the frame (the rail and main; main itself scrolls
   sideways under a wide table, so it cannot be the box), or across the frame when neither side has
   room; above the "?" when there is no room below. A browser that cannot anchor skips this block
   and keeps the pop-up the rules before it draw. A text inside a box already positioned for it, the lede (FLO-590) or a
   callout, still hangs from that box's left edge: that box, not the frame, would hold it, and it fits. */
@supports (position-area: bottom) and (anchor-scope: --a) {
  .frame { position: relative; }
  .page-help { anchor-scope: --help; }
  .page-help-btn { anchor-name: --help; }
  .page-help-text { position-anchor: --help; inset: auto; margin-top: var(--s1); position-area: bottom span-right; position-try-fallbacks: flip-inline, --help-across, flip-block, flip-block flip-inline, --help-across-up; }
  .field .page-help, .tile .page-help { position: static; }
  :is(.page-head .lede, .callout, p.problem, p.hint) .page-help-text { position-area: none; position-try-fallbacks: none; left: 0; top: calc(100% + var(--s1)); margin-top: 0; }
}
/* across the frame, centred, so a phone keeps the page's gutters on both sides */
@position-try --help-across { position-area: bottom span-all; justify-self: center; margin: var(--s1) 0 0; }
@position-try --help-across-up { position-area: top span-all; justify-self: center; margin: 0 0 var(--s1); }
.nowrap { white-space: nowrap; }
/* the foot of a page: Small, with --s8 under it (guideline 6.2) */
.footer { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); padding: var(--s5) 0 var(--s8); margin: 0; }
.footer span + span::before { content: "\00b7"; margin: 0 var(--s2); }

/* below 960px the rail becomes a wrapped list above the content: a
   fallback for a half-screen laptop, not a design target */
@media (max-width: 959px) {
  /* The header holds too much for one line at phone width: the name, the
     role, My preferences, Sign out, and for the custodian the Export gate
     button too. On one line it ran off the side and the wordmark printed
     over the name (FLO-423). Here it wraps instead, and it stops being
     sticky, because three wrapped lines pinned to the top would eat a
     third of a phone screen. Nothing under this width reads --header-h:
     the rail is already static and the page scrolls whole. */
  .header {
    position: static;
    height: auto;
    min-height: var(--header-h);
    flex-wrap: wrap;
    gap: var(--s2) var(--s4);
    padding: var(--s3) var(--s4);
  }
  .who { flex-wrap: wrap; row-gap: var(--s2); }
  /* A wrapping header is not enough on its own: .who never breaks its
     text, so a name too long for one line still pushed the page off the
     side. A 61 character name measured 433 wide in a 420 window. The name
     is the one thing here that may break, inside itself if it has to. The
     role pill and the two buttons stay whole (FLO-423). */
  .who .name { white-space: normal; overflow-wrap: anywhere; }
  .frame { display: block; background: none; }
  .rail {
    position: static;
    height: auto;
    display: flex;
    flex-wrap: wrap;
    gap: var(--s2) var(--s5);
    border-right: 0;
    border-bottom: 1px solid var(--edge);
    padding: var(--s3) var(--s4);
  }
  .rail .group { margin-top: 0; }
  .rail .group a { display: inline-block; padding-left: 10px; }
  main { padding: var(--s4); }
  /* The demo strip's one line does not fit here: the "View as" bar took
     its whole one-line width (384 at 390 for Rowan Pike) and crushed the
     core's demo sentence to nothing. Each takes a row of its own and
     wraps, and the bar keeps the page's 16 px gutters (reviewers, 11 Oct). */
  body.shell > .kind-band, body.shell > .walk-bar { grid-column: 1 / -1; }
  .kind-band { white-space: normal; }
  .walk-bar { flex-wrap: wrap; row-gap: 0; height: auto; min-height: 32px; padding: 6px var(--s4); white-space: normal; }
}

/* ---------- the history drawer ---------- */
.history { margin-top: var(--s7); background: var(--sunken); border: 1px solid var(--rule); border-radius: var(--r-card); }
.history summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s3);
  padding: 8px 14px;
  font-size: var(--text-small);
  line-height: var(--line-small);
  color: var(--ink-2);
}
.history summary::-webkit-details-marker { display: none; }
.history summary::before {
  content: "";
  display: inline-block;
  width: 0;
  height: 0;
  border: 5px solid transparent;
  border-left: 6px solid var(--ink-3);
  border-right: 0;
  transition: transform 0.15s ease;
}
.history[open] summary::before { transform: rotate(90deg); }
/* a Small line's emphasis is Label weight, so the drawer never shows a bold Small */
.history summary strong { font-weight: var(--weight-label); color: var(--ink); }
.history summary .sep { color: var(--ink-3); }
.history summary .latest { color: var(--ink-3); }
/* The rows (UI-7, guideline 2.9): a day heading in Label, then one Small
   line a row, the time in ink-3 before the sentence. A long sentence
   wraps under itself at phone width; nothing scrolls sideways. */
.history .day {
  margin: 0;
  padding: 6px 14px;
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: var(--line-small);
  color: var(--ink-2);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.history .rows { list-style: none; margin: 0; padding: 0; }
.history .row { display: flex; align-items: baseline; gap: var(--s2); padding: 4px 14px; border-top: 1px solid var(--rule); font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); }
.history .rows .row:first-child { border-top: 0; }
.history .row time { flex: 0 0 auto; color: var(--ink-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
.history .row .what { flex: 1 1 auto; min-width: 0; }
.history .empty-line { margin: 0; padding: 8px 14px; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); border-top: 1px solid var(--rule); }
.history .foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  margin: 0;
  padding: 6px 14px 8px;
  font-size: var(--text-small);
  line-height: var(--line-small);
  color: var(--ink-3);
  border-top: 1px solid var(--rule);
}
/* "Show 20 · 50 · 100": quiet buttons that read as links in the foot's line, so they keep the line's height */
.history .foot .show button {
  height: auto;
  min-height: 0;
  padding: 0 4px;
  border: 0;
  background: none;
  font-size: var(--text-small);
  font-weight: var(--weight-read);
  line-height: var(--line-small);
  color: var(--ink-3);
  text-decoration: underline;
  text-decoration-color: var(--edge);
  text-underline-offset: 2px;
}
.history .foot .show button.on { font-weight: var(--weight-label); color: var(--ink); text-decoration: none; }
.history .foot .show button + button::before { content: "\00b7"; margin-right: 6px; color: var(--ink-3); }

/* ---------- the login page ---------- */
/* The band, when there is one, sits at the top edge; the card and its
   notes centre in whatever is left (.login-body). */
.login-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.login-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--s6) var(--s4);
}
.login-card { width: 100%; max-width: 24rem; }
.login-card .wordmark {
  font-family: inherit;
  font-size: var(--text-heading);
  font-weight: var(--weight-strong);
  line-height: var(--line-heading);
  margin: 0 0 var(--s5);
}
.login-card h1 { margin: 0 0 var(--s4); }
.login-card form { margin: 0; }
.login-card .after { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: var(--s4) 0 0; }
.login-note { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); max-width: 24rem; text-align: center; margin: var(--s5) 0 0; }
.login-foot { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: var(--s7) 0 0; }

/* ---------- components, alphabetically ---------- */

/* ---- back link: one per detail page, above the page head ---- */
.back {
  display: inline-block;
  font-size: var(--text-small);
  line-height: var(--line-small);
  color: var(--ink-3);
  text-decoration: none;
  margin-bottom: var(--s3);
}
.back::before { content: "\2039"; margin-right: var(--s1); }
.back:hover { color: var(--accent); }

/* ---- buttons (guideline 6.3): one height, Label text, 16 px sides, the one radius.
   A bare button is the secondary one, so nothing regresses. The primary is the
   one rust fill on a page; the secondary is surface with an --edge border. ---- */
.btn, button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  height: var(--control-h);
  padding: 0 var(--s4);
  font: inherit;
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: var(--line-small);
  border-radius: var(--r-control);
  border: 1px solid var(--edge);
  background: var(--surface);
  color: var(--ink-2);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  vertical-align: middle;
}
.btn:hover, button:hover { border-color: var(--ink-3); color: var(--ink); }
.btn-secondary { background: var(--surface); border-color: var(--edge); color: var(--ink-2); }
.btn-secondary:hover { border-color: var(--ink-3); color: var(--ink); }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--ink-inv); }
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--ink-inv); }
.btn-danger { background: var(--surface); border-color: var(--fail); color: var(--fail); }
.btn-danger:hover { background: var(--fail); border-color: var(--fail); color: var(--ink-inv); }
/* every button is one height: the templates still say btn-sm, and it changes nothing */
.btn-sm { height: var(--control-h); padding: 0 var(--s4); }
.btn-block { width: 100%; }
/* a row of buttons (6.3): each at least 96 px; a row of buttons alone (.equal) all as wide as the widest;
   at most three in view, the fourth and on under "More", a <details> whose menu drops under its button */
.actions > .btn, .actions > button, .actions > form > .btn, .actions > form > button, .actions > details.more-actions > summary { min-width: 6rem; }
.actions.equal { display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr; }
.actions.equal > form { display: contents; }
.actions.equal .btn, .actions.equal button, .actions.equal > details.more-actions > summary { width: 100%; }
details.more-actions { position: relative; display: inline-block; }
details.more-actions > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: var(--s2); height: var(--control-h); padding: 0 var(--s4); font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); background: var(--surface); border: 1px solid var(--edge); border-radius: var(--r-control); white-space: nowrap; }
details.more-actions > summary::-webkit-details-marker { display: none; }
details.more-actions > summary::after { content: "\25BE"; color: var(--ink-3); }
details.more-actions > summary:hover, details.more-actions[open] > summary { border-color: var(--ink-3); color: var(--ink); }
details.more-actions .menu { position: absolute; right: 0; top: calc(100% + var(--s1)); z-index: 20; min-width: 14rem; display: flex; flex-direction: column; padding: var(--s1); background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--r-card); box-shadow: 0 2px 6px rgba(23, 22, 19, 0.12); }
details.more-actions .menu form { margin: 0; }
details.more-actions .menu .btn, details.more-actions .menu button { display: flex; width: 100%; height: auto; min-height: var(--control-h); justify-content: flex-start; padding: var(--s2) var(--s3); border: 0; border-radius: var(--r-control); background: none; color: var(--ink); text-align: left; white-space: normal; }
details.more-actions .menu .btn:hover, details.more-actions .menu button:hover { background: var(--sunken); color: var(--ink); }
details.more-actions .menu .help { margin: 0; padding: var(--s1) var(--s3) var(--s2); }
button:disabled, .btn:disabled, .btn[aria-disabled="true"] {
  color: var(--mute);
  border-color: var(--mute);
  background: var(--sunken);
  cursor: default;
  pointer-events: none;
}

/* ---- callouts (6.5): a tinted panel with its state icon at the left, at most two sentences and 66ch,
   its link last. A bare p.problem or p.hint gets the same look. A hint is not a state: no icon. ---- */
.callout, p.problem, p.hint {
  position: relative;
  padding: var(--s3) var(--s4) var(--s3) calc(var(--s4) + 16px + var(--s2));
  border-radius: var(--r-card);
  border: 0;
  font-size: var(--text-body);
  line-height: var(--line-body);
  margin: var(--s4) 0;
  max-width: 66ch;
}
.callout::before, p.problem::before, p.hint::before { content: ""; position: absolute; left: var(--s4); top: calc(var(--s3) + 4px); width: 16px; height: 16px; background: var(--ink-3); -webkit-mask: var(--icon) center / contain no-repeat; mask: var(--icon) center / contain no-repeat; }
.callout p { margin: 0; }
.callout p + p, .callout ul { margin-top: var(--s1); }
.callout ul { margin-bottom: 0; }
.callout.problem, p.problem { --icon: var(--icon-slash); background: var(--fail-bg); color: var(--ink); }
.callout.problem::before, p.problem::before { background: var(--fail); }
.callout.problem > :first-child, p.problem { font-weight: var(--weight-strong); }
.callout.hint, p.hint { padding-left: var(--s4); background: var(--sunken); color: var(--ink-2); }
.callout.hint::before, p.hint::before { display: none; }
.callout.success { --icon: var(--icon-check); background: var(--pass-bg); color: var(--ink); }
.callout.success::before { background: var(--pass); }
.callout.warn { --icon: var(--icon-flag); background: var(--warn-bg); color: var(--ink); }
.callout.warn::before { background: var(--warn); }
.callout.info { --icon: var(--icon-clock); background: var(--info-bg); color: var(--ink); }
.callout.info::before { background: var(--info); }
/* a callout with no state class is a note: the sunken ground, no icon */
.callout:not(.problem):not(.hint):not(.success):not(.warn):not(.info) { padding-left: var(--s4); background: var(--sunken); }
.callout:not(.problem):not(.hint):not(.success):not(.warn):not(.info)::before { display: none; }
/* the word alone, inside a sentence or a cell */
span.problem, td.problem { color: var(--fail); font-weight: var(--weight-strong); }
span.hint, small.hint { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }

/* ---- cards: a form, a detail list or a summary block. Never a table, never nested. ---- */
.card {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  padding: var(--s4) var(--s5);
  margin: 0 0 var(--s5);
}
.card > h2:first-child, .card > h3:first-child { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }
/* a callout inside a card is a tinted row with no frame, edge to edge (6.5) */
.card > .callout { border-radius: 0; margin-left: calc(-1 * var(--s5)); margin-right: calc(-1 * var(--s5)); max-width: none; }
.card-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s4);
  margin-bottom: var(--s3);
}
.card-head h2, .card-head h3 { margin: 0; }
.card-head .actions { margin: 0; }

/* ---- charts (S3): every drawing is inline SVG from templates/_charts.html,
   with its geometry from consultant/charts.py. This is the one block
   that styles them. A state class sets three colours from the semantic
   pairs: --mark for a solid mark, --mark-bg and --mark-edge for a box.
   Text stays ink. Grey and not-started also differ in line, not only in
   colour. The drawing is never wider than its column. ---- */
.chart {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 0 0 var(--s4);
  font-family: var(--font-ui);
  --chart-surface: var(--surface);
  --mark: var(--ink-3);
  --mark-bg: var(--surface);
  --mark-edge: var(--hairline);
}
/* text on a drawing is Small. It is set in user units, so it scales with the viewBox; a drawing at its natural size shows 14 px. */
.chart text { fill: var(--ink-2); font-size: var(--text-small); font-weight: var(--weight-read); }
.chart .axis .base { stroke: var(--hairline); stroke-width: 1; }
.chart .grid line { stroke: var(--rule); stroke-width: 1; }
.chart .axis text { fill: var(--ink-3); font-size: var(--text-small); font-variant-numeric: tabular-nums; }
.chart .value { fill: var(--ink-2); font-size: var(--text-small); font-variant-numeric: tabular-nums; }
.chart .caption { fill: var(--ink-2); font-size: var(--text-small); font-weight: var(--weight-label); }
.chart .mark { fill: var(--mark); }
.chart .marker { stroke: var(--chart-surface); stroke-width: 2; }
.chart .marker-tick { stroke: var(--mark); stroke-width: 3; stroke-linecap: round; }
.chart .sparkline .line { fill: none; stroke: var(--mark); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .sparkline .end { stroke: var(--chart-surface); stroke-width: 2; }
.chart .box rect { fill: var(--mark-bg); stroke: var(--mark-edge); stroke-width: 1; }
.chart .box text { fill: var(--ink); font-size: var(--text-small); font-weight: var(--weight-label); }
.chart .box-still:not([class*="state-"]) rect { fill: none; }
.chart .box-still:not([class*="state-"]) text { fill: var(--ink-2); font-weight: var(--weight-read); }
.chart .box-small text { fill: var(--ink-2); font-size: var(--text-small); font-weight: var(--weight-read); }
.chart .arrow { --mark-edge: var(--edge); }
.chart .arrow path { fill: none; stroke: var(--mark-edge); stroke-width: 1.5; }
.chart .arrow polygon { fill: var(--mark-edge); }
.chart .tie { stroke: var(--edge); stroke-width: 1; stroke-dasharray: 2 3; }
.chart a { text-decoration: none; cursor: pointer; }
.chart a:hover .box rect, .chart a:focus-visible .box rect { stroke: var(--accent); stroke-width: 2; }
.chart a:hover .box text { fill: var(--accent); }
/* the five states */
.state-done { --mark: var(--pass); --mark-bg: var(--pass-bg); --mark-edge: var(--pass); }
.state-waiting { --mark: var(--warn); --mark-bg: var(--warn-bg); --mark-edge: var(--warn); }
.state-blocked { --mark: var(--fail); --mark-bg: var(--fail-bg); --mark-edge: var(--fail); }
.state-not-started { --mark: var(--edge); --mark-bg: var(--surface); --mark-edge: var(--edge); }
.state-greyed { --mark: var(--hairline); --mark-bg: var(--hold-bg); --mark-edge: var(--edge); }
.chart .mark.state-not-started { fill: var(--chart-surface); stroke: var(--edge); stroke-width: 1; }
.chart .box.state-blocked rect { stroke-width: 2; }
.chart .box.state-greyed rect { stroke-dasharray: 4 3; }
.chart .box.state-greyed text { fill: var(--hold); }
/* what the colours mean, in words, beside the drawing */
/* The series of a stacked chart (FLO-374): a category, never a state. A
   series takes no state class, so a hover never says "blocked" of a tier.
   The marks come from ink, --ink-3 and the hold tint (guideline 6.1):
   the first is ink, the second ink-3, the third the hold tint with an
   ink-3 edge, and the fourth is drawn as a dashed outline, so each
   differs in lightness and the last two in line too. No series is rust
   or a state colour. The legend says in words what each one is. */
.series-1 { --mark: var(--ink); --mark-bg: var(--ink); --mark-edge: var(--ink); }
.series-2 { --mark: var(--ink-3); --mark-bg: var(--ink-3); --mark-edge: var(--ink-3); }
.series-3 { --mark: var(--hold-bg); --mark-bg: var(--hold-bg); --mark-edge: var(--ink-3); }
.chart .mark.series-3 { stroke: var(--ink-3); stroke-width: 1; }
.series-4 { --mark: var(--surface); --mark-bg: var(--surface); --mark-edge: var(--ink-3); }
.chart .mark.series-4 { stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 3 2; }
.chart-legend .swatch.series-4 { border-style: dashed; }
.chart a:hover .segment, .chart a:focus-visible .segment { opacity: 0.8; }
.chart a:hover .bar:not(.segment), .chart a:focus-visible .bar:not(.segment) { fill: var(--accent); }
.chart .label { fill: var(--ink-2); font-size: var(--text-small); font-variant-numeric: tabular-nums; }
.chart a:hover .label, .chart a:focus-visible .label { fill: var(--accent); text-decoration: underline; }

.chart-legend { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s1) var(--s4); padding: 0; margin: 0 0 var(--s3); font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.chart-legend li { display: inline-flex; align-items: center; gap: var(--s2); margin: 0; }
.chart-legend .swatch { width: 12px; height: 12px; border-radius: 2px; background: var(--mark-bg); border: 1px solid var(--mark-edge); }
.chart-legend .swatch.state-greyed { border-style: dashed; }
details.chart-table table { margin-bottom: 0; }

/* ---- checks (Setup, Readiness): a pill, the check, its note ---- */
.checks { list-style: none; padding-left: 0; margin: var(--s2) 0 var(--s4); }
.checks li {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  margin: 0;
  padding: var(--s1) 0;
  border-top: 1px solid var(--rule);
  font-size: var(--text-body);
  line-height: var(--line-body);
}
.checks li:first-child { border-top: 0; }
/* one column of states (S7): wide enough for "Blocks the seal" with its icon, the icons in one line at the left */
.checks .pill { flex: 0 0 8.5rem; justify-content: flex-start; }
.checks .note { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }

/* ---- empty state (5.1 item 14; 2.6): one line, not a card. The title in ink, then what to do or
   when items appear, with one link, in the secondary ink. ---- */
.empty {
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  max-width: 66ch;
  margin: var(--s3) 0 var(--s4);
  font-size: var(--text-body);
  line-height: var(--line-body);
  color: var(--ink-3);
}
.empty p { display: inline; margin: 0; }
.empty p + p { margin-left: var(--s1); }
.empty-title { font-size: var(--text-body); font-weight: var(--weight-read); color: var(--ink); }

/* ---- filters: a GET form above a list, its fields compact ---- */
.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--s2) var(--s3);
  background: var(--sunken);
  border-radius: var(--r-card);
  padding: var(--s3) var(--s4);
  margin: 0 0 var(--s4);
}
.filters .field { margin: 0; gap: var(--s2); }
.filters label { font-size: var(--text-small); }
/* sized to their content, whatever .field says further down; one control height, Body text (guideline 6.4) */
.filters .field input, .filters .field select, .filters input, .filters select { min-height: var(--control-h); width: auto; }
.filters select { padding-right: 36px; }
.filters .actions { margin: 0; gap: var(--s2); }
.filters .btn, .filters button { height: var(--control-h); }
/* a checkbox in the well sits level with the controls beside it */
.filters .field.check { min-height: var(--control-h); align-content: center; }
/* a select shows its longest option; cap it so a long rule name does not push the next field to a new row (FLO-320) */
.filters select { max-width: 30ch; }
/* the period filter in a page head stays on one line (FLO-320) */
.page-head .filters { flex-wrap: nowrap; }
/* what is narrowing the list, as small pills above the table; the × is a link that drops one */
.active-filters { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin: 0 0 var(--s3); }
.active-filters .pill a { text-decoration: none; margin-left: var(--s1); color: var(--ink-3); }
.active-filters .pill a:hover { color: var(--accent); }

/* ---- the fold (6.7): one pattern for every closed block. The whole summary row is the target, at
   least 40 px tall; a 16 px chevron at the left turns 90° when open; the title is Body, or Strong for
   a section (.section); a note at the right (.small) is Small; the body sits 24 px in and 12 px under
   the summary. The rail's groups (UI-3), the Activity strip (UI-7), the header's menu, the "More"
   menu and a disclosure that stands as a button (.disclose) keep their own shapes. ---- */
.fold > summary { list-style: none; cursor: pointer; display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2); min-height: 40px; padding: var(--s2) 0; font-size: var(--text-body); font-weight: var(--weight-read); line-height: var(--line-body); color: var(--ink); }
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::before { content: ""; flex: none; width: 16px; height: 16px; background: var(--ink-3); -webkit-mask: var(--icon-chevron) center / contain no-repeat; mask: var(--icon-chevron) center / contain no-repeat; transition: transform 0.15s ease; }
.fold[open] > summary::before { transform: rotate(90deg); }
.fold > summary:hover { color: var(--accent); }
.fold > summary:hover::before { background: var(--accent); }
.fold.section > summary { font-weight: var(--weight-strong); }
.fold > summary .small { margin-left: auto; }
.fold > :not(summary) { margin: var(--s3) 0 0 var(--s5); }
/* a heading inside a summary keeps its id for links into the page and sits on the summary's own row */
.fold > summary > h2, .fold > summary > h3 { margin: 0; }
/* UI-9 (5.3): a "#" link to a section opens it with no script. The browser opens a fold around a target
   inside it; a fold that is the target itself shows its body and turns its chevron here. A fold that holds
   part of the record (.record) prints open; a show-all fold is one of those. A Setup step is not one of
   these: a link into a step carries ?step=<step>, and the server opens that step alone. */
.fold:not(.step):target:not([open])::details-content { content-visibility: visible; display: block; }
.fold:not(.step):target > summary::before { transform: rotate(90deg); }
@media print { .fold.record:not([open])::details-content { content-visibility: visible; display: block; } }
/* The header is sticky, so what a "#" link lands on stops under the header, never behind it (UI-9's review). */
:target { scroll-margin-top: calc(var(--header-h) + var(--s4)); }

/* ---- forms: labels above inputs, help under them, one primary action ---- */
.form { max-width: 640px; }
.form form { margin: 0; }
/* a field (6.4): the label above the control, 8 px between them; help 4 px under; 24 px to the next field */
.field { display: grid; gap: var(--s1); margin-bottom: var(--s5); }
.field label { margin: 0; }
.field > label { margin: 0 0 var(--s1); }
.field label > input, .field label > select, .field label > textarea { margin-left: 0; }
.field input, .field select, .field textarea { width: 100%; }
.field input[type="checkbox"], .field input[type="radio"] { width: 18px; }
/* a checkbox or radio line: the control, 12 px, its words in Body, the line a control tall (guideline 6.4) */
.field.check label { display: inline-flex; align-items: center; gap: var(--s3); min-height: var(--control-h); font-size: var(--text-body); font-weight: var(--weight-read); line-height: var(--line-body); color: var(--ink); }
label .opt { font-weight: var(--weight-read); color: var(--ink-3); }
.help { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: 0; }
/* an error is one Small line in --fail with its icon (guideline 6.4) */
.error { display: flex; align-items: center; gap: var(--s1); font-size: var(--text-small); line-height: var(--line-small); color: var(--fail); margin: 0; }
.error::before { content: ""; flex: none; width: 16px; height: 16px; background: var(--fail); -webkit-mask: var(--icon-slash) center / contain no-repeat; mask: var(--icon-slash) center / contain no-repeat; }
.is-invalid input, .is-invalid select, .is-invalid textarea { border-color: var(--fail); }
.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--s3); }
.field-row .field { margin-bottom: 0; }
.field-row + .field-row, .field-row + .field { margin-top: var(--s5); }
.actions { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s5); }
.actions .link { font-size: var(--text-small); margin-left: var(--s2); }
/* the file input: the native control is off screen, its label is the button,
   and app.js writes the chosen name into .filename */
.file { display: flex; align-items: center; gap: var(--s3); }
.file input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; pointer-events: none; }
.file:focus-within label.btn { outline: 2px solid var(--accent); outline-offset: 2px; }
.file label.btn { margin: 0; }
.file .filename { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); overflow-wrap: anywhere; }

/* ---- label-and-value panel (5.7): one fact per row, the labels in one 11rem column so every panel on a
   page lines up, 12 px between rows, a long value wrapping under itself ---- */
.kv {
  display: grid;
  grid-template-columns: 11rem minmax(0, 1fr);
  gap: var(--s3) var(--s5);
  align-items: baseline;
  margin: 0 0 var(--s3);
}
/* the label of a pair is Small, its value Body */
.kv dt { font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); color: var(--ink-3); }
.kv dd { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink); margin: 0; min-width: 0; overflow-wrap: anywhere; }
.kv dd.mono { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); }
/* a hash or a key fingerprint: one click selects the whole value, no script needed (FLO-327; the export gate has no JavaScript by decision) */
.kv dd.hash, span.hash { user-select: all; }
/* an empty value reads as intentionally empty */
.kv dd:empty::before { content: "\2014"; color: var(--ink-3); }
/* two pairs a row on a wide screen; the pairs fill left to right */
.kv.cols-2 { grid-template-columns: 11rem minmax(0, 1fr) 11rem minmax(0, 1fr); }
@media (max-width: 1199px) {
  .kv.cols-2 { grid-template-columns: 11rem minmax(0, 1fr); }
}

/* ---- pager: under the table, the position left and the two buttons right ---- */
.pager {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s3);
  font-size: var(--text-small);
  line-height: var(--line-small);
  color: var(--ink-3);
  margin: var(--s3) 0 var(--s4);
}
.pager .btns { display: flex; gap: var(--s2); }
.pager form { margin: 0; display: inline; }

/* ---- pills (guideline 6.6): a state is a pill, 24 px tall, round, Label text, an icon and a word
   from the state table (consultant/states.py); five classes, one per meaning, and the pill filter
   picks the class. A category drawn as pill-neutral reads as a tag: the one radius, a hairline. ---- */
.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s1);
  height: 24px;
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: 1;
  padding: 0 var(--s2);
  border-radius: 999px;
  border: 1px solid transparent;
  white-space: nowrap;
  vertical-align: middle;
}
/* the state's icon beside its word (5.4, 6.9): 14 px, the pill's own colour; set aside has none */
.pill .icon { width: 14px; height: 14px; flex: none; }
.pill-info { color: var(--info); background: var(--info-bg); border-color: var(--info-bg); }
.pill-pass { color: var(--pass); background: var(--pass-bg); border-color: var(--pass-bg); }
.pill-fail { color: var(--fail); background: var(--fail-bg); border-color: var(--fail-bg); }
.pill-warn { color: var(--warn); background: var(--warn-bg); border-color: var(--warn-bg); }
.pill-hold { color: var(--hold); background: var(--hold-bg); border: 1px dashed var(--edge); }
.pill-neutral { color: var(--ink-2); background: transparent; border-color: var(--hairline); border-radius: var(--r-control); }
.pill-solid { color: var(--ink-inv); background: var(--inverted); border-color: var(--inverted); }
/* the history drawer's ×N count, not a state */
.pill-count { color: var(--ink-3); background: var(--paper); border-color: var(--hairline); }
/* a category is a tag (guideline 6.6): 24 px tall, the one radius, a solid hairline, Label text, no icon.
   Dashed means set aside, so a tag is never dashed, except the one that says "not for managers". */
.tag {
  display: inline-flex;
  align-items: center;
  height: 24px;
  margin-left: var(--s2);
  padding: 0 var(--s2);
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: 1;
  color: var(--ink-2);
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
  vertical-align: middle;
  white-space: nowrap;
}

/* ---- table: the wrapper scrolls, never the page ---- */
.table-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s3);
  font-size: var(--text-small);
  line-height: var(--line-small);
  color: var(--ink-3);
  margin: 0 0 var(--s2);
}
.table-meta .count { margin-left: auto; }
.table-wrap {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  overflow-x: auto;
  margin: 0 0 var(--s4);
}
.table-wrap .table, .table-wrap table { border: 0; margin: 0; max-width: none; }
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-body);
  line-height: var(--line-body);
  font-variant-numeric: tabular-nums;
}
.table thead th {
  background: var(--sunken);
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: var(--line-small);
  color: var(--ink-2);
  text-align: left;
  padding: var(--s3) var(--s4);
  white-space: nowrap;
  border-bottom: 1px solid var(--hairline);
}
.table thead th a { color: inherit; text-decoration: none; }
.table thead th a:hover { color: var(--accent); }
/* the column the server ordered by; .desc flips the caret */
.table thead th.sorted::after {
  content: "";
  display: inline-block;
  margin-left: 6px;
  border: 4px solid transparent;
  border-top: 5px solid var(--ink-3);
  border-bottom: 0;
  vertical-align: 2px;
}
.table thead th.sorted.desc::after { border-top: 0; border-bottom: 5px solid var(--ink-3); }
.table td { padding: var(--s3) var(--s4); border-top: 1px solid var(--rule); vertical-align: top; white-space: normal; overflow-wrap: break-word; }
.table tbody tr:first-child td { border-top: 0; }
.table tbody tr:hover td { background: var(--paper); }
.table tbody tr.selected td { background: var(--accent-soft); }
.table th.num, .table td.num { text-align: right; }
/* a cell wraps (5.5); only a number, a time, a date and a pill stay on one line */
.table td.num, .table td time, .table td.date, .table td .pill { white-space: nowrap; }
/* the prose column asks for a share of the width first; every column wraps */
.table td.wrap { white-space: normal; min-width: 26ch; }
/* the rule name may wrap too, so Findings fits 1280 wide with its eight columns (FLO-320) */
.table td.rule { white-space: normal; min-width: 16ch; }
.table td.mono { font-family: inherit; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.table td.id a { font-weight: var(--weight-strong); color: var(--ink); text-decoration-color: var(--hairline); }
.table td.id a:hover { color: var(--accent); text-decoration-color: var(--accent); }
/* a second fact under a cell's first: the rule version under the rule */
.table td .sub { display: block; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin-top: 2px; white-space: normal; font-weight: var(--weight-read); }
/* the machine-readable twin under a prose cell: the verdict under the message */
.table td .verdict {
  display: block;
  margin-top: 4px;
  font-family: inherit;
  font-size: var(--text-small);
  color: var(--ink-3);
  line-height: var(--line-small);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.table td form { margin: 0; display: inline; }
.table td .btn + .btn, .table td form + form { margin-left: var(--s1); }

/* ---- the row fold (5.5, 5.8; UI-5): a chevron starts the row (a checkbox and its label, so no script) and
   the fold opens under the row as a label-and-value block 24 px in, while the box is ticked or the row is
   the page's target (#finding-23). A child row indents 24 px under its parent. A total row is bold with a
   rule above. The summary line's order words, the pager's place and "More filters" are the pattern's too;
   consultant/tables.py and templates/_table.html make them. ---- */
.table td.lead { white-space: normal; }
.table .row-toggle { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; overflow: hidden; pointer-events: none; }
.table .chevron { display: inline-block; vertical-align: -3px; width: 16px; height: 16px; margin: 0 var(--s2) 0 0; cursor: pointer; background: var(--ink-3); -webkit-mask: var(--icon-chevron) center / contain no-repeat; mask: var(--icon-chevron) center / contain no-repeat; transition: transform 0.15s ease; }
.table .chevron:hover { background: var(--ink); }
.table tr:has(> td > .row-toggle:checked) .chevron, .table tr:target .chevron { transform: rotate(90deg); }
.table tr:has(> td > .row-toggle:focus-visible) .chevron { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
.table tr.row-fold { display: none; }
.table tr:has(> td > .row-toggle:checked) + tr.row-fold, .table tr:target + tr.row-fold { display: table-row; }
.table tr.row-fold > td { padding: var(--s3) var(--s4) var(--s4) calc(var(--s4) + var(--s5)); background: var(--paper); border-top: 0; }
.table tbody tr.row-fold:hover > td { background: var(--paper); }
.table tr.row-fold > td .kv { margin: 0; }
.table tr.row-fold > td .actions { margin-top: var(--s3); }
.table tr.child > td:first-child { padding-left: calc(var(--s4) + var(--s5)); }
.table tr.total td { font-weight: var(--weight-strong); border-top: 1px solid var(--edge); }
/* the summary line's sort order, in Small after the counts */
.summary .order { font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); color: var(--ink-3); }
.pager .where { font-variant-numeric: tabular-nums; }
/* "Show all 59" (5.1 row 13; UI-9): the rows past the tenth inside a section wait behind one line at the
   table's foot, a checkbox and its label like the row fold, so no script. On paper every row prints. */
.table .show-all-toggle { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; overflow: hidden; pointer-events: none; }
.table tr.past-fold { display: none; }
.table:has(.show-all-toggle:checked) tr.past-fold { display: table-row; }
.table:has(.show-all-toggle:checked) tr.show-all { display: none; }
/* a "#" link to a row past the tenth shows every row, so the link lands on it (UI-9's review) */
.table:has(tr.past-fold:target) tr.past-fold { display: table-row; }
.table:has(tr.past-fold:target) tr.show-all { display: none; }
.table tr.show-all > td { padding: 0 var(--s4); }
.table tbody tr.show-all:hover > td { background: var(--surface); }
.table tr.show-all label { display: flex; align-items: center; gap: var(--s2); min-height: 40px; cursor: pointer; font-size: var(--text-body); font-weight: var(--weight-read); line-height: var(--line-body); color: var(--ink); }
.table tr.show-all label::before { content: ""; flex: none; width: 16px; height: 16px; background: var(--ink-3); -webkit-mask: var(--icon-chevron) center / contain no-repeat; mask: var(--icon-chevron) center / contain no-repeat; }
.table tr.show-all label:hover::before { background: var(--ink); }
.table tr:has(> td > .show-all-toggle:focus-visible) label { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
@media print { .table tr.past-fold { display: table-row; } .table tr.show-all { display: none; } }
/* "More filters": the fields past the first two, folded on their own line of the filter well */
.filters .more-filters { flex: 1 1 100%; margin: 0; }
.filters .more-filters > summary { min-height: var(--control-h); padding: 0; font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); }
.filters .more-filters > .more-fields { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s2) var(--s3); margin: var(--s2) 0 0; }

/* ---------- per-screen additions (FLO-315) ---------- */

/* ---- details reveal: a small fold (the one pattern above). Setup's channel blocks, Settings'
   advanced form, User admin's set-password and deactivate confirm, API tokens' sessions, AI models'
   edit-costs and add-model. ---- */
details.reveal { margin: var(--s2) 0 var(--s3); }
/* inside a table cell the reveal's body sits under the row's buttons */
.table td details.reveal { display: inline-block; margin: 0; vertical-align: middle; }
.table td details.reveal > summary { font-size: var(--text-small); line-height: var(--line-small); min-height: var(--control-h); padding: 0; }
.table td details.reveal[open] { display: block; }
.table td details.reveal > .panel {
  display: block;
  margin-top: var(--s2);
  padding: var(--s3);
  background: var(--sunken);
  border-radius: var(--r-card);
  white-space: normal;
  min-width: 14rem;
}
/* the fields stack: two side by side widen the actions column past the wrapper at 1280 (FLO-327) */
.table td details.reveal .field-row { gap: var(--s2); grid-template-columns: 1fr; }

.table td details.reveal .actions { margin-top: var(--s2); }
.table td details.reveal form { display: block; }

/* ---- Home: the widget grid (FLO-374), then the needs-you list. The workflow
   map has its own block below. A full widget is the page itself, with no
   frame, so "Needs you" and the map read as they did. A wide or a small
   widget is a card. Four columns wide, two under 1100, one on a phone. ---- */
.widgets { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s4) var(--s5); align-items: start; margin: var(--s4) 0; }
.widget { min-width: 0; }
/* With the row gap this is the space an h2 had above it before the grid. */
.widget-full > h2:first-child { margin-top: var(--s4); }
.widget-full { grid-column: 1 / -1; }
.widget-wide { grid-column: span 2; }
.widget-wide, .widget-small {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  padding: var(--s4) var(--s5);
  align-self: stretch;
}
.widget-wide > h2, .widget-small > h2 { font-size: var(--text-heading); margin-bottom: var(--s3); }
.widget > :last-child { margin-bottom: 0; }
.widget .could-not-load { color: var(--ink-3); font-size: var(--text-body); line-height: var(--line-body); }
.widget-failed { border-style: dashed; }
.widget-full.widget-failed { border: 1px dashed var(--hairline); border-radius: var(--r-card); padding: var(--s4) var(--s5); }
.home-arrange { margin: 0 0 var(--s4); }
.widget .widget-chart { margin-bottom: var(--s2); }
/* A ring over a completion column with something still open: a nearly full column looks full. */
.widget .completion-ring { fill: var(--surface, #fff); stroke: var(--ink, currentColor); stroke-width: 1.5; }
.widget .series-legend { margin-bottom: var(--s2); }
/* a card's one number is Display with tabular figures; its words, its empty sentence, and the short lists of counts are Body */
.widget .big { font-family: inherit; font-size: var(--text-display); font-weight: var(--weight-strong); line-height: var(--line-display); letter-spacing: -0.01em; margin: 0 0 var(--s2); font-variant-numeric: tabular-nums; }
.widget .big a { color: var(--ink); text-decoration: none; }
.widget .big a:hover { color: var(--accent); text-decoration: underline; }
.widget .what { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-3); margin: 0 0 var(--s2); }
.widget .widget-empty { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-2); margin: 0 0 var(--s2); }
.widget .ai-health.not-ok, .widget .ai-health.not-ok a { color: var(--fail); }
.pipeline-steps, .state-counts { list-style: none; padding: 0; margin: 0 0 var(--s3); }
.pipeline-steps { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--s3) 0; }
.pipeline-steps li { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s1); margin: 0; min-width: 0; }
.pipeline-steps li + li { padding-left: var(--s2); border-left: 1px solid var(--rule); }
.pipeline-steps .pill { padding-left: var(--s1); padding-right: var(--s1); }
@media (max-width: 479px) { .pipeline-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* a count in a list of counts is a Heading, so five of them in one card never outweigh the page title */
.pipeline-steps .count, .state-counts .count { font-family: inherit; font-size: var(--text-heading); font-weight: var(--weight-strong); line-height: var(--line-heading); font-variant-numeric: tabular-nums; color: var(--ink); }
.pipeline-steps .count a, .state-counts .count a { color: inherit; }
.pipeline-steps li.none .count, .state-counts li.none .count { color: var(--ink-3); }
.state-counts li { display: flex; align-items: baseline; gap: var(--s2); margin: 0; padding: var(--s1) 0; font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-2); }
.state-counts .count { flex: 0 0 2rem; text-align: right; }
@media (max-width: 1099px) {
  .widgets { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 719px) {
  .widgets { grid-template-columns: minmax(0, 1fr); }
  .widget-wide { grid-column: auto; }
}
/* Arrange Home (/home/arrange): one row per card, its words left and its
   buttons right. The pinned row has words where the buttons would be. */
.arrange h2 { font-size: var(--text-heading); margin: var(--s5) 0 var(--s1); }
.arrange-standing { color: var(--ink-3); margin: 0 0 var(--s2); }
.arrange-list { list-style: none; padding: 0; margin: 0 0 var(--s3); max-width: 720px; }
.arrange-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  margin: 0;
  padding: var(--s2) 0;
  border-top: 1px solid var(--rule);
  background: var(--paper);
}
.arrange-list li:first-child { border-top: 0; }
.arrange-what { min-width: 0; font-size: var(--text-body); line-height: var(--line-body); }
.arrange-what .blurb { display: block; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.arrange-what .arrange-refused { color: var(--ink-2); }
.arrange-acts { flex: 0 0 auto; display: flex; gap: var(--s1); }
.arrange-pinned { color: var(--ink-3); }
.arrange .actions { margin-top: var(--s5); }
/* Drag is the script's extra (static/app.js). The script marks the list,
   so a page with no script shows no grip and no grab cursor. */
.arrange-list.can-drag li[draggable="true"] { cursor: grab; }
.arrange-list.can-drag li[draggable="true"] .arrange-what::before { content: "\2261"; float: left; margin-right: var(--s2); color: var(--ink-3); line-height: var(--line-body); }
.arrange-list.can-drag li.dragging { opacity: 0.5; outline: 2px solid var(--ink-2); outline-offset: -2px; }
.arrange-drag-hint { margin: 0 0 var(--s3); }
@media (max-width: 479px) {
  .arrange-list li { flex-direction: column; align-items: flex-start; gap: var(--s2); }
}
.setup-banner p:last-child { font-size: var(--text-small); line-height: var(--line-small); }
.needs { list-style: none; padding: 0; margin: 0 0 var(--s4); max-width: 720px; }
.needs li {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  padding: var(--s2) 0;
  border-top: 1px solid var(--rule);
  font-size: var(--text-body);
  line-height: var(--line-body);
}
.needs li:first-child { border-top: 0; }
/* the count is a Heading: a key figure in its row that never outweighs the title. Every count is ink; the custody row is no longer rust. */
.needs .count {
  flex: 0 0 2.5rem;
  text-align: right;
  font-family: inherit;
  font-size: var(--text-heading);
  font-weight: var(--weight-strong);
  line-height: var(--line-heading);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.needs .what a { font-weight: var(--weight-strong); }
.needs .reason { color: var(--ink-3); font-size: var(--text-body); }
.needs .reason::before { content: "\00b7"; margin: 0 var(--s2); color: var(--ink-3); }
/* Home per role (UI-8, guideline 5.2): the Setup line is one line; the rows past five fold under
   "Show N more" with no gap above them; a Waiting-on line names its group and links each row's
   reason; the All-clear line stands where the empty cards were. */
.setup-line { margin: 0 0 var(--s4); }
.setup-line .page-help { vertical-align: middle; }
.needs-you .show-more { margin-top: 0; }
.needs-you .show-more > summary { font-size: var(--text-body); }
.needs-you .show-more > ul.needs { margin: 0; }
.needs.waiting .what a { font-weight: var(--weight-read); }
.needs.waiting .what b { font-weight: var(--weight-strong); }
.needs.waiting .what .n { font-weight: var(--weight-strong); font-variant-numeric: tabular-nums; }
.map-fold > section.widget-full > h2:first-child { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.everything-else .all-clear { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-2); margin: 0 0 var(--s3); }
.everything-else .widgets { margin-top: 0; }
.needs .out { font-size: var(--text-small); margin-left: var(--s2); }

/* ---- the workflow map (FLO-375), on Home and on /map. Its boxes and arrows
   are the charts block's. Wide, it is the drawing; on a narrow screen it
   is the same steps as a numbered list, and only one of the two shows. ---- */
.workflow-map { margin: 0 0 var(--s4); }
.workflow-map .map-controls { margin: 0 0 var(--s3); }
.workflow-map .map-drawing { margin-bottom: var(--s2); }
.workflow-map .map-list { display: none; max-width: 720px; font-size: var(--text-body); line-height: var(--line-body); }
.workflow-map .map-list li { padding: 2px 0; }
.workflow-map .map-list .greyed { color: var(--ink-3); }
.workflow-map .map-list .reason { color: var(--ink-3); font-size: var(--text-small); }
.workflow-map .map-list .reason::before { content: "\00b7"; margin: 0 var(--s2); color: var(--ink-3); }
/* The overlay (375-e): one mark a box for the pay period shown. The shape
   says the state and the colour repeats it. A mark takes no clicks, so the
   box under it stays the link. */
.workflow-map .map-controls .filters { margin: 0 0 var(--s2); }
.workflow-map .map-controls .callout { margin: 0 0 var(--s2); }
.workflow-map .map-period-line { margin: 0; }
.workflow-map .map-showing { color: var(--ink); font-weight: var(--weight-label); }
.workflow-map .map-mark { pointer-events: none; }
.workflow-map .map-mark .shape { fill: var(--mark); stroke: var(--chart-surface); stroke-width: 2; }
.workflow-map .map-mark .glyph { fill: none; stroke: var(--surface); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.workflow-map .map-mark text { fill: var(--surface); font-size: var(--text-small); font-weight: var(--weight-label); font-variant-numeric: tabular-nums; }
.workflow-map .map-mark.mark-not-started .shape { fill: var(--surface); stroke: var(--ink-3); stroke-width: 1.5; stroke-dasharray: 3 2.5; }
.workflow-map .map-legend { margin-bottom: var(--s1); }
.workflow-map .map-legend-note { margin: 0 0 var(--s2); }
.workflow-map .map-legend-mark { flex: 0 0 auto; margin: 0; overflow: visible; }
.workflow-map .map-list .map-state { display: inline-flex; align-items: center; height: 24px; margin-left: var(--s2); padding: 0 var(--s2); border: 1px solid var(--edge); border-radius: 999px; font-size: var(--text-small); font-weight: var(--weight-label); line-height: 1; white-space: nowrap; color: var(--ink-2); }
.workflow-map .map-list .map-state-done { border-color: var(--pass); color: var(--pass); background: var(--pass-bg); }
.workflow-map .map-list .map-state-waiting { border-color: var(--warn); color: var(--warn); background: var(--warn-bg); }
.workflow-map .map-list .map-state-blocked { border-color: var(--fail); color: var(--fail); background: var(--fail-bg); border-width: 2px; }
.workflow-map .map-list .map-state-not-started { border-style: dashed; }
@media (max-width: 719px) {
  .workflow-map .map-drawing { display: none; }
  .workflow-map .map-list { display: block; }
  /* The list says each state in words, so it needs no legend of shapes. */
  .workflow-map .map-legend, .workflow-map .map-legend-note { display: none; }
}

/* ---- Setup: the spine, the steps, the box-only callout ---- */
.summary { font-size: var(--text-body); font-weight: var(--weight-strong); line-height: var(--line-body); margin: 0 0 var(--s3); }
.spine td.id a { text-decoration: none; }
/* On a phone the spine stacks (FLO-640, defect 20): each step is a block, its number and name on one line,
   the phase and the state beside each other, the detail under them. The table no longer scrolls in its wrap. */
@media (max-width: 719px) {
  .table-wrap:has(> .spine) { overflow: visible; border: 0; }
  .spine, .spine tbody, .spine tr, .spine td { display: block; }
  .spine thead { display: none; }
  .spine tr { padding: var(--s3) 0; border-top: 1px solid var(--rule); }
  .spine tbody tr:first-child { border-top: 0; }
  .spine td { padding: 0; border-top: 0; }
  .spine td.num, .spine td.id, .spine td.phase, .spine td.phase + td { display: inline-block; margin-right: var(--s2); }
  .spine td.id { font-weight: var(--weight-strong); }
  .spine td.wrap { margin-top: var(--s1); }
}
details.step { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--r-card); margin: 0 0 var(--s3); padding: 0 var(--s5); }
/* a step is a section fold (6.7): Strong, its number in ink-3, its state pill at the right */
details.step > summary { padding: var(--s3) 0; }
details.step > summary .n { color: var(--ink-3); }
details.step > summary .pill { margin-left: auto; }
details.step[open] > summary { border-bottom: 1px solid var(--rule); }
/* UI-9 (5.3, 6.7): one step open at a time. The steps share a name, so opening one closes the rest. A link
   into a step carries ?step=<step> and the server opens that step alone, so no :target rule draws a step. */
details.step > :last-child { margin-bottom: var(--s4); }
details.step .checks .name { min-width: 14rem; }
details.step .checks .name code { color: var(--ink-3); margin-left: var(--s1); }
details.step .form { max-width: 880px; }
details.step .field-row .field { align-content: start; }
details.step .locked { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-2); }
details.step .locked .pill { margin-right: var(--s1); }
.field.check-list { display: block; }
.field.check-list .label { display: block; font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); margin-bottom: var(--s1); }
.field.check-list label { font-size: var(--text-body); font-weight: var(--weight-read); line-height: var(--line-body); color: var(--ink); margin-right: var(--s3); }
/* Client choices, part 1: a role's pages as a grid of check lines, each box with its words, never split across lines */
.screen-choices .field.check-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); column-gap: var(--s5); margin-bottom: var(--s4); }
.screen-choices .field.check-list .label { grid-column: 1 / -1; }
/* the clock on Setup's Account step: a short field (guideline 6.4) */
.field.short.clock select { max-width: 14rem; }
.screen-choices .field.check-list label { display: inline-flex; align-items: center; gap: var(--s2); min-height: var(--control-h); margin-right: 0; }
.callout.box .eyebrow { margin-bottom: var(--s1); }
.callout.box pre { background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-control); padding: var(--s2) var(--s3); margin: var(--s1) 0 var(--s2); }
.callout.box p:last-child { margin: 0; }

/* ---- Settings: the list's tags and the detail's locked card ---- */
/* quiet words keep the class name and take the secondary ink: --mute is never text */
.mute { color: var(--ink-3); }
.table td .tag, .kv dd .tag { margin-left: var(--s2); }
.settings td.set-by .sub { display: inline; margin-left: var(--s1); }
.card .locked { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-2); margin: 0; }
.card .locked .pill { margin-right: var(--s1); }
/* every settings table shares one column grid, so the eye can walk down the page (FLO-320) */
.table.settings { table-layout: fixed; }
.table.settings td { white-space: normal; overflow-wrap: anywhere; }
.settings th:first-child { width: 40%; }
.settings th:last-child { width: 22%; }
.mapping td input { width: 14rem; }
/* The earning code map (FLO-337): a code can be long, so the input fills its cell. */
.earning-codes td input { width: 100%; }

/* ---- User admin and API tokens: the person cell, the token reveal ---- */
/* the custodian-on-record note wraps instead of widening the Status column (FLO-320) */
.table.users td .sub { white-space: normal; max-width: 40ch; }
.table td.person { font-weight: var(--weight-strong); }
.table tr.inactive td { color: var(--ink-3); }
.table tr.inactive td.person { font-weight: var(--weight-read); }
.table td .sub.note { white-space: normal; max-width: 28ch; }
.token-once pre.token { margin: var(--s2) 0; padding: var(--s3) var(--s4); background: var(--surface); border: 1px solid var(--edge); border-radius: var(--r-control); font-size: var(--text-body); line-height: var(--line-body); user-select: all; white-space: pre-wrap; overflow-wrap: anywhere; }
.token-once code.token { font-size: inherit; }
.card .form { max-width: none; }
.help.narrow { max-width: 72ch; }

/* ---- AI models: a provider block is a head row and the shared table ---- */
.provider { margin: 0 0 var(--s5); }
.provider-head { display: flex; align-items: center; gap: var(--s3); margin: 0 0 var(--s2); }
.provider-head h2 { margin: 0; }
.provider-head h2 code { color: var(--ink-3); margin-left: var(--s1); }
.provider-head form { margin: 0 0 0 auto; }
.provider.is-stub .provider-head h2 { color: var(--ink-3); }
.provider.is-stub .table td { color: var(--ink-3); }
/* the first capability tag sits flush; elsewhere a tag follows text and keeps its gap (FLO-320) */
.table td.caps .tag:first-child { margin-left: 0; }
.table.models td.id .sub code { white-space: nowrap; }
/* the three actions may wrap, so the model id never has to (FLO-320) */
.table.models td:last-child { white-space: normal; min-width: 9rem; }
.table.models td details.reveal > .panel { min-width: 10rem; }
details.reveal.card { padding-top: var(--s3); padding-bottom: var(--s3); }

/* ---- AI features: one card per feature ---- */
.card.feature h2 code { color: var(--ink-3); margin-left: var(--s1); }
.card.feature .assign .field-row { grid-template-columns: 1fr 1fr auto; align-items: end; }
.card.feature .assign-action .label { display: block; font-size: var(--text-small); line-height: var(--line-small); }
.card.feature .foot { margin-top: var(--s3); }
.card.feature.is-test { background: var(--paper); color: var(--ink-3); }
.field-row .field { align-content: start; }
.table td details.reveal + details.reveal { margin-left: var(--s2); }


/* ---------- Bundle scope (FLO-318): the scope panel, the summary strip,
   the action bar, the grouped contents and the readiness component ---------- */
.scope-panel { padding-bottom: var(--s4); }
/* the /readiness deep link lands under the sticky header without this (FLO-320) */
#readiness { scroll-margin-top: calc(var(--header-h) + var(--s4)); }
.scope-grid { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--s5); }
@media (max-width: 1099px) { .scope-grid { grid-template-columns: 1fr; } }
/* the radio tabs: the input is off screen, its label is the tab, and the
   chosen tab's pane is the only one shown; no script */
.scope-what input[type="radio"], .scope-who input[type="radio"] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; pointer-events: none; }
/* a tab is a tile on the sunken track its siblings make; the chosen one is raised to the surface, in ink (guideline 6.1) */
.scope-panel .tab {
  display: inline-flex;
  align-items: center;
  height: var(--control-h);
  padding: 0 var(--s3);
  margin: 0 var(--s1) var(--s3) 0;
  border: 1px solid transparent;
  border-radius: var(--r-control);
  background: var(--sunken);
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: var(--line-small);
  color: var(--ink-2);
  cursor: pointer;
}
.scope-panel .tab:hover { color: var(--ink); }
.scope-panel input:checked + .tab { background: var(--surface); border-color: var(--hairline); color: var(--ink); }
.scope-panel input:focus-visible + .tab { outline: 2px solid var(--accent); outline-offset: 2px; }
.scope-panel .pane { display: none; }
#kind-period:checked ~ .pane-period, #kind-dates:checked ~ .pane-dates, #kind-notice:checked ~ .pane-notice, #who-some:checked ~ .pane-some { display: block; }
.scope-panel .field { margin-bottom: var(--s2); }
.scope-panel .field-row .field { margin-bottom: 0; }
.scope-panel .field-row + .help { margin-top: var(--s2); }
.scope-panel .field-row + .first-record, .scope-panel .field-row + .first-record-set { margin-top: var(--s2); }
.scope-panel .first-record { margin: 0 0 var(--s2); font-size: var(--text-small); }
.worker-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px var(--s3);
  max-height: 180px;
  overflow-y: auto;
  padding: var(--s2) var(--s3);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
}
.worker-list .worker { display: flex; align-items: center; gap: var(--s3); min-height: var(--control-h); font-weight: var(--weight-read); font-size: var(--text-body); line-height: var(--line-body); color: var(--ink); margin: 0; }
.worker-list .worker .type { color: var(--ink-3); }
.scope-foot { display: flex; justify-content: space-between; align-items: center; gap: var(--s4); margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--rule); }
/* a chip names a saved scope or a filter: a tag-shaped link on a sunken ground. Defined once, here; the finding page's chips are these. */
.chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); min-width: 0; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
  height: 24px;
  padding: 0 var(--s2);
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
  background: var(--sunken);
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: 1;
  color: var(--ink-2);
  text-decoration: none;
}
a.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip .pill { height: 20px; padding: 0 6px; }
.manage-scopes { margin: calc(-1 * var(--s3)) 0 var(--s5); font-size: var(--text-small); line-height: var(--line-small); }
/* the four tiles: items, workers, the verdict, the holds */
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3); margin: 0 0 var(--s4); }
@media (max-width: 1099px) { .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.stat { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--r-card); padding: var(--s3) var(--s4); }
/* the tile's figure is a Heading in ink (it is sometimes words, "Ready to seal"); its state tints the tile, as a callout is tinted, and never colours the figure */
.stat .n { display: block; font-family: inherit; font-size: var(--text-heading); font-weight: var(--weight-strong); line-height: var(--line-heading); color: var(--ink); font-variant-numeric: tabular-nums; }
.stat .sub { display: block; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin-top: 2px; }
.stat.is-pass { background: var(--pass-bg); }
.stat.is-fail { background: var(--fail-bg); }
.stat.is-warn { background: var(--warn-bg); }
.stat.is-mute .n { color: var(--ink-3); }
/* the action bar: Prepare and check first, Save as… beside it */
.action-bar { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--s3) var(--s4); margin: 0 0 var(--s2); }
.action-bar form { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.action-bar form > label { margin: 0; }
.action-bar select { width: auto; min-height: var(--control-h); }
.action-bar .save-as summary { list-style: none; }
.action-bar .save-as summary::-webkit-details-marker { display: none; }
.action-bar .save-as form { margin-top: var(--s2); padding: var(--s3) var(--s4); background: var(--sunken); border-radius: var(--r-card); }
.action-bar .save-as input[name="name"] { width: 18ch; }
.action-bar .save-as .help { flex: 1 0 100%; }
.bar-note { margin: 0 0 var(--s5); }
/* the two columns under the bar; the bundle detail uses the same pair */
.two-col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); align-items: start; margin: 0 0 var(--s5); }
@media (max-width: 1099px) { .two-col { grid-template-columns: 1fr; } }
.two-col .card { margin: 0; }
/* a section's name in the contents list is a Label */
.contents-card h3 { margin: var(--s4) 0 var(--s1); font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); }
.contents { list-style: none; padding: 0; margin: 0; }
.contents li { display: flex; justify-content: space-between; gap: var(--s3); padding: 3px 0; margin: 0; border-top: 1px solid var(--rule); font-size: var(--text-body); line-height: var(--line-body); }
.contents li:first-child { border-top: 0; }
.contents li .n { font-variant-numeric: tabular-nums; font-weight: var(--weight-strong); }
.contents li.zero { color: var(--ink-3); }
.contents li.zero .n { font-weight: var(--weight-read); }
.contents-card details.list { margin-top: var(--s3); font-size: var(--text-body); line-height: var(--line-body); }
.contents-card details.list .table-wrap { margin-bottom: var(--s2); }
/* the source files as one wrapping line each, so the list fits the card at any width (FLO-320) */
.artifacts { list-style: none; padding: 0; margin: 0 0 var(--s2); font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); }
.artifacts li { padding: 3px 0; border-top: 1px solid var(--rule); overflow-wrap: anywhere; }
.artifacts li:first-child { border-top: 0; }
.artifacts li .n { font-weight: var(--weight-label); color: var(--ink); }
.hold-list { padding-left: 1.25rem; margin: 0 0 var(--s2); font-size: var(--text-body); line-height: var(--line-body); }
/* the readiness component: the verdict, then each check as a pill, its
   words with the detail under them, and the raw name at the right */
.readiness .verdict { display: flex; align-items: baseline; gap: var(--s3); font-size: var(--text-body); line-height: var(--line-body); margin: 0 0 var(--s1); }
.readiness .verdict .pill { flex: 0 0 auto; }
.readiness .checked { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: 0 0 var(--s3); }
.readiness .checks { margin: 0; }
.readiness .checks li { align-items: flex-start; padding: var(--s2) 0; }
.readiness .checks .pill { margin-top: 2px; }
.readiness .checks .body { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.readiness .checks .body strong { font-weight: var(--weight-strong); }
.readiness .checks .detail { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); overflow-wrap: anywhere; }
.readiness .checks .note { display: block; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); padding-left: var(--s3); border-left: 2px solid var(--edge); quotes: none; }
.readiness .checks .by { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); padding-left: var(--s3); }
.readiness .checks .raw { font-family: inherit; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.readiness details.passed { margin-top: var(--s3); font-size: var(--text-body); line-height: var(--line-body); }

/* ---- bundle preview (FLO-379): the summary on top, the folder below, one file a page ---- */
.preview-summary .two-col { margin-bottom: var(--s4); }
.preview-notes p + p { margin-top: var(--s2); }
.preview-folder .table-wrap { margin-bottom: var(--s4); }
.table.folder-tree tr.folder th { text-align: left; font-family: inherit; font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); background: var(--sunken); }
.table.folder-tree td.mono { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink); }
.table.folder-tree tr.raw-file td.mono { color: var(--ink-3); }
.table.folder-tree .pill + .pill { margin-left: var(--s1); }
.file-facts { margin-bottom: var(--s4); }
.table.file-rows td.mono { color: var(--ink-2); vertical-align: top; white-space: normal; overflow-wrap: anywhere; min-width: 14ch; max-width: 44ch; }
pre.file-text { background: var(--sunken); border: 1px solid var(--rule); border-radius: var(--r-control); padding: var(--s3) var(--s4); overflow-x: auto; }
/* the callout after a prepare carries its failed checks and two buttons */
.callout.prepared .checks { margin: var(--s2) 0 0; }
.callout.prepared .actions { margin-top: var(--s3); }
.callout .actions .help { margin-left: var(--s1); }

/* ---------- Bundle browser (FLO-318): the segmented state filter, the
   register, the timeline strip and the seal record ---------- */
/* the segmented filter: a sunken track, Label text, the chosen segment a surface tile in ink (guideline 6.1) */
.segmented { display: inline-flex; gap: var(--s1); padding: var(--s1); background: var(--sunken); border-radius: var(--r-control); }
.segmented a { display: inline-flex; align-items: center; min-height: 28px; padding: 0 var(--s3); font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); text-decoration: none; border: 1px solid transparent; border-radius: var(--r-control); white-space: nowrap; }
.segmented a:hover { color: var(--ink); }
.segmented a.on { background: var(--surface); border-color: var(--hairline); color: var(--ink); }
.table.register tr.void td.id a { text-decoration: line-through; color: var(--ink-3); }
ol.timeline { list-style: none; display: flex; gap: var(--s4); padding: 0; margin: 0 0 var(--s5); }
ol.timeline li { flex: 1 1 0; position: relative; margin: 0; padding-top: var(--s3); border-top: 2px solid var(--rule); font-size: var(--text-body); line-height: var(--line-body); }
ol.timeline li.done { border-top-color: var(--pass); }
ol.timeline li.void { border-top-color: var(--fail); }
ol.timeline .dot { position: absolute; top: -6px; left: 0; width: 10px; height: 10px; border-radius: 50%; background: var(--surface); border: 2px solid var(--edge); }
ol.timeline li.done .dot { background: var(--pass); border-color: var(--pass); }
ol.timeline li.void .dot { background: var(--fail); border-color: var(--fail); }
ol.timeline .step { display: block; font-weight: var(--weight-strong); color: var(--ink); }
ol.timeline li:not(.done) .step { color: var(--ink-3); font-weight: var(--weight-strong); }
ol.timeline .sub { display: block; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.seal-record .help { margin: 0 0 var(--s3); }
.retained-note .actions { margin-top: var(--s3); }


/* ---------- screen additions (FLO-316, the Ingest and Report screens) ---------- */

/* Findings: the pay-period group row, and the finding's evidence sheet */
.table tr.group td { background: var(--sunken); font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); border-top: 1px solid var(--hairline); }
.table td .sub.mono { font-family: inherit; }
.statement { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink); }
.cols { display: grid; grid-template-columns: 3fr 2fr; gap: var(--s5); align-items: start; }
.cols > .card { margin-bottom: var(--s5); }
/* the measure is one Strong sentence, with no tint: rust is not for a finding's facts */
.against { font-weight: var(--weight-strong); margin: 0 0 var(--s3); }
/* the threshold row: its label a Label, its value Strong, both in ink */
.kv dt.threshold { font-weight: var(--weight-label); color: var(--ink-2); }
.kv dd.threshold { font-weight: var(--weight-strong); color: var(--ink); }
.kv dd .sub { display: block; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
details.more { margin-top: var(--s3); }
details.more pre { background: var(--sunken); padding: var(--s3); border-radius: var(--r-control); }
/* the finding's chips are the Bundle scope block's .chips and .chip, defined once there; in a card they keep their air below */
.card > .chips { margin: 0 0 var(--s3); }
.lookups { margin: 0; font-size: var(--text-body); line-height: var(--line-body); }
ul.timeline { list-style: none; padding: 0; margin: 0; }
ul.timeline li { position: relative; padding: 0 0 var(--s3) var(--s5); margin: 0; border-left: 2px solid var(--rule); font-size: var(--text-body); line-height: var(--line-body); }
ul.timeline li:last-child { padding-bottom: 0; }
ul.timeline li::before { content: ""; position: absolute; left: -6px; top: 6px; width: 10px; height: 10px; border-radius: 50%; background: var(--surface); border: 2px solid var(--edge); }
/* the latest event's dot is filled ink; rust marks an action, not a date */
ul.timeline li:first-child::before { border-color: var(--ink); background: var(--ink); }
/* The finding page's day row (FLO-372): the head and the sentences around
   it. The row itself is the Timeline's, and so is every rule about it. */
.finding-day { margin: 0 0 var(--s5); }
.finding-day-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s1) var(--s4); margin: 0 0 var(--s2); }
.finding-day-head h2, .finding-day-nav { margin: 0; }
.finding-day-nav { font-size: var(--text-body); line-height: var(--line-body); }
.finding-day-own, .finding-day-none { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-2); margin: 0 0 var(--s3); max-width: 80ch; }
/* This finding's own mark links to the statement above, and only that link does. Its name under the row, in Small text, is a Label: a step heavier, never bold. */
.finding-day a[href="#this-finding"] { font-weight: var(--weight-label); }
@media (max-width: 1199px) { .cols { grid-template-columns: 1fr; } }

/* Exposure: the tier tiles */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--s4); margin: 0 0 var(--s4); }
.tile { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--r-card); padding: var(--s4) var(--s5); }
/* the tier that matters most has a darker edge, not a rust stripe */
.tile.accent { border-color: var(--ink-3); }
.tile.muted { border-style: dashed; }
.tile .big { font-family: inherit; font-size: var(--text-display); font-weight: var(--weight-strong); line-height: var(--line-display); letter-spacing: -0.01em; margin: var(--s2) 0; font-variant-numeric: tabular-nums; }
.tile .meaning { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: 0; }
.tile .note { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: var(--s2) 0 0; }
.tile .premium { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); margin: var(--s2) 0 0; font-variant-numeric: tabular-nums; }
.scope { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: 0 0 var(--s4); }
.table td.live { font-weight: var(--weight-strong); }
.table td.quiet { color: var(--ink-3); }

/* Pulls: its state tabs are the view tabs (defined once, below); the decision panel on one pull */
.decision { display: grid; grid-template-columns: 3fr 2fr; gap: var(--s5); }
.decision h3 { margin-top: 0; }
.decision .facts p { margin: 0 0 var(--s2); font-size: var(--text-body); line-height: var(--line-body); }
.decision .facts p:last-child { margin-bottom: 0; }
.decision .facts strong { font-weight: var(--weight-strong); }
.decision .actions { margin-top: 0; }
.decision .reason { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: var(--s2) 0 0; }
.decision form { margin: 0; }
.decision .callout { margin: 0; }
.decision details { margin-top: var(--s3); }
.decision details .field { margin: var(--s2) 0; }
.callout .actions { margin-top: var(--s3); }
.callout dl.kv { margin: var(--s2) 0 0; }
/* one column on a narrower screen; it never grows past the card, and a period's long "Findings for ..." button wraps inside it, as the long buttons elsewhere do */
@media (max-width: 1199px) { .decision { grid-template-columns: minmax(0, 1fr); } .decision .btn { height: auto; min-height: var(--control-h); padding: var(--s1) var(--s4); white-space: normal; text-align: left; } }

/* Parked names: the pull banner, the match line and the decision group */
.filters select[name="pull"] { min-width: 30ch; }
.filters select[name="period"] { min-width: 26ch; }
.card .status { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-3); margin: 0 0 var(--s3); }
.banner { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); flex-wrap: wrap; font-size: var(--text-body); line-height: var(--line-body); }
.banner .facts { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; margin: 0; }
.banner .sep { color: var(--ink-3); }
.table td.name { white-space: normal; min-width: 14ch; }
.table td.name strong { font-weight: var(--weight-strong); }
/* Workers (UI-5): the occupation box and the two pick-lists take their column's width, not their own, so the
   five columns fit 1280 px; the name keeps 14ch */
.table.workers td.occupation, .table.workers td.language, .table.workers td.agency { width: 21%; }
.table.workers td.occupation input { width: 100%; min-width: 10ch; box-sizing: border-box; }
.table.workers td.language select, .table.workers td.agency select { width: 100%; min-width: 0; max-width: 100%; box-sizing: border-box; }
/* Setup's recipients (UI-5): the name and address boxes and the two pick-lists take their column's width, not
   their own, so the table fits its wrap at 1280 px. The two picks keep a width of their own (FLO-640, defect
   16): "Email" read "Ema" when the name and address columns took the room. */
.table.recipients td input:not([type="checkbox"]), .table.recipients td select { width: 100%; min-width: 0; max-width: 100%; box-sizing: border-box; }
.table.recipients td:first-child, .table.recipients td:nth-child(4) { width: 28%; }
.table.recipients td:nth-child(2) { width: 11rem; }
.table.recipients td:nth-child(3) { width: 8rem; }
.table td.status { white-space: normal; min-width: 20ch; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.table td.decide { white-space: normal; min-width: 30ch; }
.decide form { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.decide form input, .decide form select { width: auto; min-height: var(--control-h); }
/* the name input gives way first, so the button stays on the line at 1280 (FLO-320) */
.decide form input[type=text] { flex: 1 1 12ch; min-width: 12ch; }
.decide form select { padding-right: 36px; }
.decide form .btn, .decide form button { height: var(--control-h); }
.decide details { margin-top: var(--s2); }
.decide .decided { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.triage { margin: 0 0 var(--s2); font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.triage p { margin: 0 0 var(--s1); }
.triage form { display: inline; margin: 0; }
.triage button { height: var(--control-h); padding: 0 var(--s4); }
.table td.hash { font-family: inherit; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }

/* ---- Policies (FLO-507): one card per version; a version no longer in effect is greyed, its rows stay ---- */
.card.policy .policy-text { white-space: pre-wrap; }
.card.policy .stats { margin-top: var(--s3); }
.card.policy.closed { background: var(--paper); color: var(--ink-3); }
.card.policy.closed h2, .card.policy.closed .stat .n { color: var(--ink-3); }

/* ---- view tabs (Pulls, Obligations, Corrections, Conversations; FLO-316, FLO-317): one link per view,
   its count beside it. A sunken track, Label text; the chosen view is a surface tile in ink, never rust
   or black (guideline 6.1). The track with its tiles is one control tall. ---- */
.tabs {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--s1);
  padding: var(--s1);
  background: var(--sunken);
  border-radius: var(--r-control);
  margin: 0 0 var(--s4);
}
.tabs a {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 28px;
  padding: 0 var(--s3);
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: var(--line-small);
  color: var(--ink-2);
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--r-control);
}
.tabs a:hover { color: var(--ink); }
.tabs a.here { color: var(--ink); background: var(--surface); border-color: var(--hairline); }
/* a count on a tab is a plain number in Small after the tab's word, not a badge (guideline 6.6) */
.tabs .count {
  font-size: var(--text-small);
  font-weight: var(--weight-read);
  line-height: var(--line-small);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

/* ---- row disclosure (Obligations, Corrections, AI confirmations; FLO-317): the rare action and its reason field, open on demand ---- */
.disclose { display: inline-block; vertical-align: middle; }
.disclose summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  height: var(--control-h);
  padding: 0 var(--s4);
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: var(--line-small);
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: var(--r-control);
  white-space: nowrap;
}
.disclose summary::-webkit-details-marker { display: none; }
.disclose summary:hover { border-color: var(--ink-3); color: var(--ink); }
.disclose.danger summary { color: var(--fail); border-color: var(--fail); }
.disclose[open] summary { background: var(--sunken); }
.disclose > :not(summary) { margin-top: var(--s2); }
.disclose .form { max-width: 200px; }
.disclose .field { margin-bottom: var(--s2); }
.disclose .actions { margin-top: var(--s2); }
.disclose p { font-size: var(--text-small); line-height: var(--line-small); white-space: normal; }
.table td .disclose form { display: block; }
.table td .disclose .field input { width: 100%; min-width: 0; }
/* an open disclosure drops under the row's buttons instead of widening the column (FLO-320) */
.table td .disclose[open] { display: block; }
/* the second fact under a cell when the first is a pill */
.table td .pill + .sub { margin-top: 4px; }
/* a tag after a pill goes under it, so a State column stays one pill wide (FLO-320) */
.table td .pill + .tag { display: block; width: max-content; margin: 4px 0 0; }
/* an action cell holds a button and a disclosure side by side and may wrap */
.table td.acts { white-space: normal; min-width: 7rem; }
/* Corrections has two prose columns; each takes a little less room */
.corrections .table td.wrap { min-width: 20ch; }
/* Obligations' What column and the failed view's Why column give way first, so both tables fit 1280 (FLO-320) */
.table.obligations td.wrap, .table td.why { min-width: 20ch; }
.corrections .table td .pill + .sub { white-space: normal; }
.table td.acts form, .table td.acts .disclose { display: inline-block; vertical-align: top; margin: 0 var(--s1) var(--s1) 0; }
.table td.wrap .sub { white-space: normal; }
.field.short input { max-width: 12rem; }

/* ---- work list (Gusto checklist; FLO-317): one line per correction, the instruction is the hero ---- */
.worklist { list-style: none; padding: 0; margin: 0 0 var(--s5); }
.worklist li {
  display: grid;
  grid-template-columns: 9rem 1fr auto;
  gap: var(--s3) var(--s5);
  align-items: start;
  padding: var(--s3) var(--s4);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  margin: 0 0 var(--s2);
}
/* the day is the row's Label; the instruction is the hero, in Strong; the rest is Small */
.worklist .day { font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); padding-top: 2px; }
.worklist .todo { font-size: var(--text-body); font-weight: var(--weight-strong); line-height: var(--line-body); margin: 0; }
.worklist .about { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: var(--s1) 0 0; }
.worklist .side { text-align: right; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.worklist .side form { margin: 0 0 var(--s1); }
.worklist-worker { margin: var(--s5) 0 var(--s2); }

/* ---- conversation cards and threads (Conversations; FLO-317) ---- */
.convo { margin: 0 0 var(--s4); }
.convo .card-head { flex-wrap: wrap; align-items: center; }
.convo .meta { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.convo .ask { font-size: var(--text-body); line-height: var(--line-body); margin: 0 0 var(--s2); }
.convo .answer { font-size: var(--text-body); line-height: var(--line-body); margin: 0 0 var(--s2); }
.thread { margin-top: var(--s3); }
.thread .msg { padding: var(--s2) 0; border-top: 1px solid var(--rule); }
.thread .msg .from { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: 0 0 2px; }
.thread .msg .from b { font-weight: var(--weight-label); color: var(--ink-2); }
.thread .msg .text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }

/* ---- the message template editor (Template editor; FLO-317): kinds left, editor right ---- */
.editor-layout { display: grid; grid-template-columns: minmax(280px, 1fr) minmax(320px, 1.6fr); gap: var(--s5); align-items: start; }
@media (max-width: 1099px) { .editor-layout { grid-template-columns: 1fr; } }
.kinds { list-style: none; padding: 0; margin: 0; }
.kinds > li { padding: var(--s3) 0; border-top: 1px solid var(--rule); }
.kinds > li:first-child { border-top: 0; padding-top: 0; }
.kinds .kind-name { font-weight: var(--weight-strong); margin: 0; }
.kinds .kind-desc { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: 0 0 var(--s2); }
.kinds .versions { list-style: none; padding: 0; margin: 0; font-size: var(--text-small); line-height: var(--line-small); }
.kinds .versions li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin: 0 0 var(--s1); }
.kinds .versions .text { flex-basis: 100%; color: var(--ink-2); white-space: pre-wrap; overflow-wrap: anywhere; margin: 0 0 var(--s1); }
.kinds .builtin { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); background: var(--sunken); border-radius: var(--r-control); padding: var(--s2) var(--s3); margin: 0 0 var(--s1); white-space: pre-wrap; }
.kinds .builtin-label { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: 0 0 2px; }
/* FLO-377: who still receives this built-in. Plain case, because it is a
   sentence and not a caption, and it wraps rather than pushing the column. */
.kinds .builtin-reach { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); margin: 0 0 2px; overflow-wrap: anywhere; }
/* FLO-377: under a built-in, the link that starts a version from it, or
   the core's reason there is none. */
.kinds .builtin-from { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); margin: 0 0 var(--s2); overflow-wrap: anywhere; }
.kinds .versions form { margin: 0; display: inline; }
.count-line { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: 2px 0 0; }
.preview { font-size: var(--text-body); line-height: var(--line-body); background: var(--sunken); border-radius: var(--r-control); padding: var(--s2) var(--s3); white-space: pre-wrap; overflow-wrap: anywhere; margin: var(--s2) 0 0; }

/* ---- held AI output (AI confirmations; FLO-317) ---- */
.held { font: inherit; font-size: var(--text-body); line-height: var(--line-body); background: var(--sunken); border-radius: var(--r-control); padding: var(--s3) var(--s4); margin: 0 0 var(--s3); white-space: pre-wrap; }

/* ---- print (UI-13; guideline section 8): Letter pages with a head and a foot, nothing to press, colour as ink ----
   Paper is US Letter, portrait, 0.6 in margins. The page number sits in the bottom margin
   (a browser without page margin boxes prints the page without it). A wrap marked
   .print-landscape (the timecard inside a record) gets its own landscape pages; a
   screen that is one wide table links print-landscape.css instead, and is landscape whole. */
@page { size: letter; margin: 0.6in; @bottom-right { content: "Page " counter(page) " of " counter(pages); font-family: var(--font-ui); font-size: var(--text-small); color: #000; } }
@page landscape { size: letter landscape; }
/* The print frame: on screen a stack of plain blocks, the head and the foot out of sight.
   The generic table rules (a border, a ground, a hover) are undone here. */
.print-frame, .print-frame > thead, .print-frame > tbody, .print-frame > tfoot, .print-frame > * > tr, .print-frame > * > tr > td { display: block; width: auto; max-width: none; padding: 0; border: 0; margin: 0; background: none; font-size: inherit; line-height: inherit; }
.print-frame > tbody > tr:hover > td { background: none; }
.print-head, .print-foot, .print-only { display: none; }
@media print {
  /* never printed: the rail, the header bar, Activity, the demo and tour bars, back links, eyebrows, ledes, tabs,
     filters, buttons, forms, the "?" and anything marked print-hide */
  .header, .rail, .history, .footer, .tabs, .kind-band, .walk-bar, .tour-bar, .changes-bar, .demo-view-band, .counsel-banner,
  .back, .eyebrow, .lede, .page-head .actions, .filters, .btn, button, form, .actions, .page-help, .fv-ask, .finding-day-nav, .print-hide, form.workers .help, form.workers .add-agency { display: none !important; }
  /* the state pill beside the title is the record's (a finding's open, an invoice's paid): it prints; the buttons beside it do not */
  .page-head .actions.state { display: flex !important; }
  /* Workers and Issue attestations wrap their tables in a form: the table prints, a text input or a select prints as its value with no box, a checkbox prints as nothing */
  form.workers, form.issue { display: block !important; }
  form.workers input, form.workers select, form.issue input, form.issue select { appearance: none; border: 0; padding: 0; background: none; font: inherit; color: #000; }
  form.workers input[type=checkbox], form.issue input[type=checkbox], form.workers datalist { display: none; }
  .frame { display: block; background: none; }
  main { max-width: none; padding: 0; overflow: visible; }
  body { background: #fff; color: #000; }
  /* the frame is a table again: the head and the foot repeat on every page, above and below that page's text */
  .print-frame { display: table; width: 100%; border-collapse: collapse; table-layout: fixed; }
  .print-frame > thead { display: table-header-group; }
  .print-frame > tfoot { display: table-footer-group; }
  .print-frame > tbody { display: table-row-group; }
  .print-frame > * > tr { display: table-row; }
  .print-frame > * > tr > td { display: table-cell; vertical-align: top; }
  .print-head { display: block; margin: 0 0 4mm; padding: 0 0 2mm; border-bottom: 1px solid #000; font-size: var(--text-small); line-height: var(--line-small); color: #000; }
  .print-head p { margin: 0; }
  .print-foot { display: block; margin: 4mm 0 0; padding: 2mm 0 0; border-top: 1px solid #999; font-size: var(--text-small); line-height: var(--line-small); color: #000; }
  .print-only { display: block; }
  .print-landscape { page: landscape; }
  /* folds that hold the record print open; folds that hold actions, explanations or settings do not print at all */
  .print-frame details:not([open])::details-content { content-visibility: visible; display: block; }
  .print-frame summary { list-style: none; }
  .print-frame summary::-webkit-details-marker { display: none; }
  details.how, details.disclose, details.new-panel, details.reveal:not(.chart-table), details.save-as, details.manage-scopes { display: none !important; }
  /* a long table runs on across pages, its heads repeat, a row never splits, and every cell wraps */
  .table-wrap { overflow: visible; border-color: #999; break-inside: auto; }
  .table-wrap thead, .table thead { display: table-header-group; }
  .table-wrap tr, .table tr { break-inside: avoid; }
  .table td, .table th, .table td .sub { white-space: normal; overflow-wrap: break-word; }
  /* a row's fold holds part of the record: it prints open, on the same page as its row, and never splits; its chevron does not print */
  .table tr.row-fold { display: table-row; break-before: avoid; break-inside: avoid; }
  .table tr:has(+ tr.row-fold) { break-after: avoid; }
  .table .chevron, .table .row-toggle { display: none; }
  .worklist li, .card { border-color: #999; break-inside: avoid; }
  a { color: inherit; text-decoration: none; }
  /* colour turns to ink: grounds are the paper, pills and tags are outlined words, tints are light grey, and no word is paler than the page */
  .card, .table-wrap, table, .table, .empty, .held, .frame, .cols > .card { background: #fff; }
  .pill, .tag, .chip { color: #000; background: #fff; border: 1px solid #000; }
  .callout, .callout.problem, .callout.hint, .callout.success, .callout.warn, .callout.info, p.problem, p.hint { background: #eee; border-left-color: #000; color: #000; }
  thead th, .table thead th { background: #eee; color: #000; border-bottom-color: #999; }
  details.more pre, pre.file-text { background: #eee; }
  td, .table td { border-top-color: #999; }
  .small, .help, .sub, .eyebrow, .kv dt, .table td .sub, .table td.mono, .table td.hash, .empty { color: #000; }
  /* a fingerprint prints short in a table; the print appendix has it whole */
  .table td.hash, .table td.file-hash { max-width: 14ch; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}

/* ---- period picks and the how-it-works disclosure (Issue attestations; FLO-317). The periods sit on
   a sunken track; the chosen one (.on) is a surface tile in ink, so the page's one rust button stays
   the action (guideline 6.1). ---- */
.period-picks { display: inline-flex; flex-wrap: wrap; gap: var(--s1); padding: var(--s1); background: var(--sunken); border-radius: var(--r-control); margin: 0 0 var(--s2); }
.period-picks .btn { height: auto; min-height: 28px; padding: var(--s1) var(--s3); background: transparent; border-color: transparent; color: var(--ink-2); white-space: normal; }
.period-picks .btn:hover { color: var(--ink); }
.period-picks .btn.on { background: var(--surface); border-color: var(--hairline); color: var(--ink); }
.how { margin: var(--s6) 0 0; font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-2); }
.how ul { margin-top: var(--s2); }

/* ---- the New panel (Conversations; FLO-317): a card that opens on demand, preset from a finding ---- */
.new-panel .tabs { margin-bottom: var(--s3); }
/* a radio's words are Body; what they mean sits under them in Small */
.field label.radio { display: block; font-size: var(--text-body); font-weight: var(--weight-read); line-height: var(--line-body); color: var(--ink); margin: 0 0 var(--s1); }
.field label.radio .opt { display: block; margin-left: 1.4em; font-size: var(--text-small); line-height: var(--line-small); }

/* ---- Upload (FLO-323): the step strip, the file-role radios, the drop area, the aside ---- */
/* the three steps a file goes through; the first is this page */
ol.steps { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); list-style: none; padding: 0; margin: 0 0 var(--s5); font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-3); }
ol.steps li { display: inline-flex; align-items: center; gap: var(--s2); }
ol.steps .n { display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; border-radius: 50%; border: 1px solid var(--edge); font-size: var(--text-small); font-weight: var(--weight-label); line-height: 1; color: var(--ink-2); background: var(--surface); }
/* the step this page is: a heavier ink ring and Strong words; rust is for the action, not the place */
ol.steps li.current { color: var(--ink); font-weight: var(--weight-strong); }
ol.steps li.current .n { border: 2px solid var(--ink); color: var(--ink); }
ol.steps li + li::before { content: "\2192"; color: var(--ink-3); margin-right: var(--s2); }
/* the form on the left, the two aside cards on the right; one column when narrow */
.upload-cols { display: grid; grid-template-columns: 2fr minmax(260px, 1fr); gap: var(--s5); align-items: start; margin: 0 0 var(--s5); }
.upload-cols .card { margin: 0; }
.upload-cols .card.form { max-width: none; }
.upload-aside { display: grid; gap: var(--s4); }
@media (max-width: 1099px) { .upload-cols { grid-template-columns: 1fr; } }
/* the file-role radios: a fieldset with no chrome, one choice per line, its meaning under the name */
fieldset.choices { border: 0; padding: 0; margin: 0 0 var(--s4); min-width: 0; }
/* the legend is a Label; each choice is a radio line, a control tall, its words Body (guideline 6.4) */
fieldset.choices legend { font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); padding: 0; margin: 0 0 var(--s1); }
.choice { display: flex; align-items: flex-start; gap: var(--s3); min-height: var(--control-h); font-size: var(--text-body); font-weight: var(--weight-read); line-height: var(--line-body); color: var(--ink); margin: 0 0 var(--s2); cursor: pointer; }
.choice input[type="radio"] { margin: 3px 0 0; flex: none; }
.choice .what { display: grid; gap: 2px; }
.choice .name { font-weight: var(--weight-strong); }
fieldset.choices.is-invalid legend { color: var(--fail); }
/* the drop area: a dashed box the native input covers, so a dropped file or a click anywhere lands on it with no script */
.file.drop { position: relative; flex-wrap: wrap; justify-content: center; text-align: center; border: 1px dashed var(--edge); border-radius: var(--r-card); background: var(--sunken); padding: var(--s5) var(--s4); }
.file.drop input[type="file"] { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; pointer-events: auto; cursor: pointer; }
.file.drop .drop-words { width: 100%; margin: 0; font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-2); }
/* a darker edge on hover, like a secondary button; the rust ring is for focus */
.file.drop:hover { border-color: var(--ink-3); }
.file.drop:focus-within { border-color: var(--accent); }
.is-invalid .file.drop { border-color: var(--fail); }
/* the aside: three pulls as file, pill and one line under; the export notes as a short list */
.recent-list { list-style: none; padding: 0; margin: 0; }
.recent-list li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); padding: var(--s2) 0; border-top: 1px solid var(--rule); }
.recent-list li:first-child { border-top: 0; padding-top: 0; }
.recent-list li a { font-weight: var(--weight-strong); overflow-wrap: anywhere; }
.recent-list .sub { width: 100%; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.recent .empty-line { margin: 0; color: var(--ink-3); }
.recent .foot { margin: var(--s3) 0 0; font-size: var(--text-small); line-height: var(--line-small); }
.card.export ul { margin: 0; padding-left: 1.2em; font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-2); }
.card.export li + li { margin-top: var(--s2); }
.card.export .version { white-space: nowrap; }

/* ---------- the Analysis filter (FLO-372): one GET form above the Timeline
   and the Calendar, templates/_analysis_filter.html. Every class here
   starts with af- or is .analysis-filter. Start of the block. ---------- */
.analysis-filter {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: var(--s3) var(--s6);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  padding: var(--s4) var(--s5) var(--s3);
  margin: 0 0 var(--s4);
}
@media (max-width: 899px) { .analysis-filter { grid-template-columns: minmax(0, 1fr); padding: var(--s4); } }
.af-group { min-width: 0; }
/* the radio tabs: the input is off screen, its label is the tab, and the
   chosen tab's pane is the only one shown; no script */
.af-group > input[type="radio"] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; pointer-events: none; }
.af-tab {
  display: inline-flex;
  align-items: center;
  height: var(--control-h);
  padding: 0 var(--s3);
  margin: 0 var(--s1) var(--s3) 0;
  border: 1px solid transparent;
  border-radius: var(--r-control);
  background: var(--sunken);
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: var(--line-small);
  color: var(--ink-2);
  cursor: pointer;
}
.af-tab:hover { color: var(--ink); }
.af-group > input:checked + .af-tab { background: var(--surface); border-color: var(--hairline); color: var(--ink); }
.af-group > input:focus-visible + .af-tab { outline: 2px solid var(--accent); outline-offset: 2px; }
.af-pane { display: none; }
.af-pane-only,
#af-range-period:checked ~ .af-pane-period,
#af-range-dates:checked ~ .af-pane-dates,
#af-who-some:checked ~ .af-pane-some { display: block; }
.analysis-filter .field { margin-bottom: var(--s1); }
.analysis-filter .field label { font-size: var(--text-small); }
.analysis-filter select, .analysis-filter input[type="date"] { width: 100%; max-width: 100%; min-width: 0; }
.af-dates { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
/* the worker list scrolls inside its own box, never the page */
.af-workers {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 0 var(--s4);
  max-height: 180px;
  overflow-y: auto;
  padding: var(--s2) var(--s3);
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
}
.af-worker { display: flex; align-items: center; gap: var(--s3); min-height: var(--control-h); font-weight: var(--weight-read); font-size: var(--text-body); line-height: var(--line-body); color: var(--ink); margin: 0; padding: 0; min-width: 0; cursor: pointer; }
.af-worker input[type="checkbox"] { flex: none; margin: 0; }
.af-worker span { overflow-wrap: anywhere; }
.af-worker .type { color: var(--ink-3); }
.af-foot {
  grid-column: 1 / -1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule);
}
.af-now { margin: 0; min-width: 0; font-size: var(--text-body); font-weight: var(--weight-strong); line-height: var(--line-body); color: var(--ink); overflow-wrap: anywhere; }
/* "Showing" is the label of a pair, the words after it the value: Small */
.af-now-label { font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); color: var(--ink-3); margin-right: var(--s2); }
.af-problems p, .af-nothing p { overflow-wrap: anywhere; }
.af-problems .small { font-weight: var(--weight-read); color: var(--ink-2); }
.af-stub { max-width: 640px; }
/* ---------- end of the Analysis filter block ---------- */

/* Two lanes add CSS at the same time. Each writes only between its own
   two marker lines, so the branches merge with no conflict. Do not move
   or reword a marker line. */
/* ---------- the Timeline (FLO-372): start of the block ---------- */
/* One worker's day, drawn (templates/_worker_day.html, from
   consultant/worker_day.py). The Timeline's two views and the finding
   page's day row share it. Shape first: a punch is a bar, a meal is a
   box (hollow when it does not count), a rule line is a line (solid,
   dotted or dashed by its kind), a finding is a small shape by its
   outcome, filled while it is live. Colour second, and only from ink,
   --ink-3 and the hold tint (guideline 6.1): worked time is an ink-3
   bar, a meal a hold-tinted box with an ink-3 edge, a rule line an ink
   line, a finding an ink shape. The pay period by day (the pt- block
   below) draws the same kinds the same way. Nothing in a day is rust,
   blue or amber. Text is always ink, in Small, scaled with the drawing.
   No mark takes one of the charts block's five state classes. The
   drawing always fits its column, so the page never scrolls sideways;
   .wd-scroll is only a guard. */
.wd-scroll { overflow-x: auto; max-width: 100%; }
.wd-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wd-svg { display: block; width: 100%; height: auto; font-family: var(--font-ui); overflow: visible; }
.wd-svg text { fill: var(--ink-2); font-size: var(--text-small); font-weight: var(--weight-read); }
.wd-svg line, .wd-svg .wd-mark, .wd-svg .wd-meal, .wd-svg .wd-problem rect { vector-effect: non-scaling-stroke; }
.wd-grid line { stroke: var(--rule); stroke-width: 1; }
.wd-track { fill: var(--paper); }
.wd-span { fill: var(--ink-3); }
.wd-chevron { fill: var(--ink-3); }
.wd-meal { fill: var(--hold-bg); stroke: var(--ink-3); stroke-width: 1.5; }
.wd-meal.wd-meal-hollow { fill: var(--surface); stroke: var(--ink-3); stroke-dasharray: 3 2; }
.wd-tick .wd-tick-halo { stroke: var(--surface); stroke-width: 5; }
.wd-tick .wd-tick-line { stroke: var(--ink); stroke-width: 2; }
.wd-tick-rest .wd-tick-line { stroke-width: 3; stroke-dasharray: 0.1 5; stroke-linecap: round; }
.wd-tick-overtime .wd-tick-line { stroke-dasharray: 8 3; }
.wd-tick-label-ground { fill: var(--surface); }
.wd-tick-other .wd-tick-line { stroke-width: 1; }
.wd-svg .wd-tick-label { fill: var(--ink-2); font-size: var(--text-small); paint-order: stroke; stroke: var(--surface); stroke-width: 3; stroke-linejoin: round; }
.wd-mark { fill: var(--surface); stroke: var(--ink-2); stroke-width: 1.75; stroke-linejoin: round; stroke-linecap: round; }
.wd-mark.wd-live { fill: var(--ink); stroke: var(--surface); stroke-width: 2; paint-order: stroke; }
.wd-mark.wd-outcome-other { stroke: var(--ink); stroke-width: 2.5; }
.wd-mark .wd-hit { fill: transparent; stroke: none; }
.wd-svg a { cursor: pointer; }
.wd-svg a:hover .wd-mark, .wd-svg a:focus-visible .wd-mark { stroke: var(--accent); }
.wd-svg a:hover .wd-mark.wd-live, .wd-svg a:focus-visible .wd-mark.wd-live { fill: var(--accent); stroke: var(--surface); }
.wd-svg a:focus-visible { outline: none; }
.wd-svg a:focus-visible .wd-hit { stroke: var(--accent); stroke-width: 1.5; }
/* On the finding page, the finding's own mark links to the statement on the same page. That mark wears an ink ring. */
.wd-svg a[href="#this-finding"] .wd-hit { stroke: var(--ink); stroke-width: 2; vector-effect: non-scaling-stroke; }
.wd-problem rect { fill: var(--hold-bg); stroke: var(--edge); stroke-width: 1; stroke-dasharray: 4 3; }
.wd-svg .wd-problem text { fill: var(--ink); font-size: var(--text-small); font-weight: var(--weight-label); }
.wd-axis-base, .wd-axis-tick { stroke: var(--hairline); stroke-width: 1; }
/* every clock label is centred on its tick; the drawing's margins give the first and the last their room */
.wd-svg .wd-axis text { fill: var(--ink-3); font-size: var(--text-small); font-variant-numeric: tabular-nums; text-anchor: middle; }

.wd-key { display: inline-block; vertical-align: -2px; margin-right: var(--s2); overflow: visible; }
.wd-legend { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s1) var(--s4); padding: 0; margin: 0 0 var(--s4); font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.wd-legend li { display: inline-flex; align-items: center; margin: 0; white-space: nowrap; }
.wd-legend .wd-key { margin-right: 6px; }

.wd-row.wd-large { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--r-card); padding: var(--s4) var(--s5) var(--s3); margin: 0 0 var(--s4); }
.wd-large .wd-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s4); margin: 0 0 var(--s2); }
.wd-large .wd-name { margin: 0; font-size: var(--text-heading); font-weight: var(--weight-strong); line-height: var(--line-heading); overflow-wrap: anywhere; }
.wd-facts { margin: 0; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s3); }
.wd-worked { font-variant-numeric: tabular-nums; }
.wd-zone { white-space: nowrap; color: var(--ink-3); font-size: var(--text-small); border: 1px solid var(--hairline); border-radius: var(--r-control); padding: 0 var(--s1); }
.wd-under { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); }
.wd-large .wd-under { margin-top: var(--s2); }
.wd-under p { margin: 0 0 var(--s1); max-width: 72ch; }
.wd-found { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s1) var(--s5); padding: 0; margin: 0 0 var(--s2); }
.wd-found li { margin: 0; }
.wd-found a { font-weight: var(--weight-read); }
.wd-when { color: var(--ink-3); font-variant-numeric: tabular-nums; }
/* the word before a line's items is the label of a pair: Small */
.wd-line-label { color: var(--ink-3); font-weight: var(--weight-read); font-size: var(--text-small); margin-right: var(--s2); }
.wd-reason { color: var(--ink-2); }
.wd-item { white-space: nowrap; }
.wd-unfit-list { margin: 0 0 var(--s2); padding-left: var(--s5); max-width: 72ch; }
.wd-unfit-list li { margin: 0; }
.wd-words-table { max-width: 640px; margin-bottom: var(--s3); }
.wd-words-table caption { text-align: left; font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); color: var(--ink-3); padding: 0 0 var(--s1); }
.wd-zone-line { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: 0 0 var(--s2); max-width: 80ch; }
.wd-zone-line.wd-zone-mixed { color: var(--ink-2); }

.wd-row.wd-small { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: 0 var(--s3); align-items: start; padding: 2px 0; border-top: 1px solid var(--rule); }
.wd-row.wd-small:first-child, .wd-row.wd-axis-row { border-top: 0; }
/* a small row's name is a Label in ink; the hours under it are Small */
.wd-small .wd-name { font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink); padding-top: 2px; overflow-wrap: anywhere; }
.wd-small .wd-name .wd-worked { display: block; font-weight: var(--weight-read); font-size: var(--text-small); color: var(--ink-3); }
.wd-small .wd-under { padding: 0 0 var(--s1) 16px; font-size: var(--text-small); line-height: var(--line-small); }
.wd-small .wd-under p, .wd-small .wd-found { margin-bottom: 2px; }
/* On a small row the rule lines a day never reached are said quietly, so a
   page of many rows reads as its drawings first. A reason stays in full ink. */
.wd-small .wd-under .wd-line { color: var(--ink-3); }

/* Narrow: the whole day still fits the width, because half a day on view
   would understate it. The words on the drawing give way: only every
   third clock label shows, larger, and a rule line's word is read under
   the row. A finding's shape is drawn larger so it can be pressed. The
   drawing scales to under half its size here, so the labels take the
   Display and Heading sizes in drawing units to land near 14 px. */
@media (max-width: 719px) {
  .wd-row.wd-large { padding: var(--s3) var(--s3) var(--s2); }
  .wd-svg { margin-bottom: 16px; }
  .wd-svg .wd-axis text { font-size: var(--text-display); transform: translateY(14px); }
  /* the end labels are too wide for the margins here, so they hang inward from the edges */
  .wd-svg .wd-axis text:first-of-type { text-anchor: start; }
  .wd-svg .wd-axis text:last-of-type { text-anchor: end; }
  .wd-svg .wd-tick-label-ground { display: none; }
  .wd-svg .wd-axis text.wd-minor, .wd-svg .wd-tick-label { display: none; }
  .wd-svg .wd-problem text { font-size: var(--text-heading); }
  .wd-svg .wd-mark { transform-box: fill-box; transform-origin: center; transform: scale(1.7); }
  .wd-row.wd-small { grid-template-columns: minmax(0, 1fr); }
  .wd-small .wd-name { padding-top: var(--s1); }
  .wd-small .wd-name .wd-worked { display: inline; margin-left: var(--s2); }
  .wd-axis-row .wd-name { display: none; }
}

.tl-day-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s2) var(--s4); margin: var(--s5) 0 var(--s3); }
.tl-day-head h2 { margin: 0; }
.tl-day-nav { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); font-size: var(--text-body); line-height: var(--line-body); margin: 0; }
.tl-note { font-size: var(--text-body); line-height: var(--line-body); color: var(--ink-3); margin: 0 0 var(--s3); }

/* The period view: one card a day, the day's workers as small rows on
   one clock inside it. A day with no record is one quiet line. */
.tl-day { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--r-card); padding: var(--s3) var(--s5) var(--s2); margin: 0 0 var(--s3); }
.tl-day-name { margin: 0 0 var(--s2); font-size: var(--text-heading); font-weight: var(--weight-strong); line-height: var(--line-heading); font-variant-numeric: tabular-nums; }
.tl-day .tl-note { margin: 0 0 var(--s1); font-size: var(--text-small); line-height: var(--line-small); }
.tl-day .tl-absent { margin-top: var(--s1); }
.tl-day.tl-day-bare { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s4); background: transparent; border-style: dashed; padding: var(--s2) var(--s5); }
.tl-day.tl-day-bare .tl-day-name { margin: 0; font-weight: var(--weight-strong); }
.tl-day.tl-day-bare .tl-note { margin: 0; }
@media (max-width: 719px) {
  .tl-day { padding: var(--s3) var(--s3) var(--s1); }
  .tl-day.tl-day-bare { padding: var(--s2) var(--s3); }
}
/* ---------- the Timeline: end of the block ---------- */

/* (this line stays as it is: it keeps the two blocks apart in a merge) */

/* ---------- the Calendar (FLO-372): start of the block ---------- */
/* The grid is a table of days, drawn on the card surface. Shape first,
   colour second: a finding is a diamond, solid while live and hollow
   once closed; attestation activity is a dot; a correction pending is
   a tick; a period's findings with no day are a bar. A live mark is
   filled ink and a closed one hollow; nothing is rust, so a busy month
   is not a wall of colour. A period edge is a heavy line on the side of a cell.
   The marks scale with the cell, so the grid never scrolls sideways. */
.cal { margin: var(--s5) 0 0; }
.cal-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s4); margin: 0 0 var(--s3); }
.cal-title { margin: 0; font-family: inherit; font-size: var(--text-heading); font-weight: var(--weight-strong); line-height: var(--line-heading); }
.cal-paging { display: flex; flex-wrap: wrap; gap: var(--s2); }
.cal-to-timeline { margin-left: auto; font-size: var(--text-small); line-height: var(--line-small); }
.cal-key { margin: 0 0 var(--s3); gap: var(--s1) var(--s5); }
.cal-key-mark { display: inline-block; margin: 0; flex: 0 0 auto; }
/* The edge in the key is a little cell with one heavy side, so that with
   no colour it is not taken for the tick of a correction pending. */
.cal-key-edge { display: inline-block; box-sizing: border-box; width: 14px; height: 12px; background: var(--surface); border: 1px solid var(--edge); border-left: 3px solid var(--ink-2); margin: 0 2px; flex: 0 0 auto; }
.cal-grid {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--hairline);
  margin: 0 0 var(--s4);
}
.cal-grid th {
  padding: var(--s2) var(--s2);
  border: 0;
  border-bottom: 1px solid var(--hairline);
  background: var(--sunken);
  color: var(--ink-2);
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: var(--line-small);
  text-align: left;
}
.cal-grid th abbr { text-decoration: none; }
.cal-cell { height: 84px; padding: 0; border: 1px solid var(--rule); vertical-align: top; }
.cal-weeks .cal-cell { height: 104px; }
.cal-cell.cal-off { background: var(--paper); padding: var(--s2); }
.cal-cell.cal-off .cal-num { color: var(--ink-3); font-weight: var(--weight-read); }
.cal-cell.cal-starts { border-left: 3px solid var(--ink-2); }
.cal-cell.cal-ends { border-right: 3px solid var(--ink-2); }
.cal-day {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s2);
  height: 100%;
  min-height: inherit;
  padding: var(--s2);
  color: var(--ink-2);
  text-decoration: none;
}
.cal-cell { position: relative; }
.cal-day:hover, .cal-day:focus-visible { background: var(--paper); color: var(--ink); }
.cal-day:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.cal-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s1); }
.cal-num { font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); font-variant-numeric: tabular-nums; color: var(--ink-2); white-space: nowrap; }
.cal-busy .cal-num { color: var(--ink); }
.cal-pay {
  font-size: var(--text-small);
  font-weight: var(--weight-label);
  line-height: var(--line-small);
  color: var(--ink-2);
  border: 1px solid var(--edge);
  border-radius: var(--r-control);
  padding: 0 var(--s1);
}
/* Each mark sits in its own place with its count beside it. The count
   is text, in ink, so it reads at any width and never leans on colour.
   A cell with a mark has four places of one width, so a
   kind lines up down a column. A place grows for a long number and the
   row then wraps: a count is never clipped or drawn over the next day. */
.cal-marks { display: flex; flex-wrap: wrap; align-items: center; gap: 3px 0; }
.cal-slot { display: inline-flex; align-items: center; gap: 2px; flex: 0 0 auto; min-width: 21%; box-sizing: border-box; padding-right: 3px; }
.cal-slot-undated { min-width: 100%; gap: var(--s1); }
.chart.cal-mark-svg { display: block; margin: 0; flex: 0 0 auto; width: 16px; height: 16px; overflow: visible; }
.chart.cal-bar-svg { width: 46px; height: 9px; }
.cal-count { font-size: var(--text-small); font-weight: var(--weight-label); line-height: 1; font-variant-numeric: tabular-nums; color: var(--ink-2); }
.cal-position { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
/* No two marks touch, so none needs the ring that parts overlapping marks. */
.cal-mark .mark.marker-diamond, .cal-mark .mark.marker-dot { stroke: none; }
.cal-mark-live { --mark: var(--ink); }
.cal-mark-closed .mark.marker { fill: var(--chart-surface); stroke: var(--ink-3); stroke-width: 1.5; }
.cal-mark-attestation, .cal-mark-corrections { --mark: var(--ink-3); }
.cal-mark-corrections .mark.marker-tick { stroke: var(--ink-3); }
.cal-undated .mark.span { fill: var(--chart-surface); stroke: var(--ink-3); stroke-width: 1.5; }
.cal-undated-live .mark.span { fill: var(--ink); stroke: var(--ink); }
.cal-undated-lines { margin: 0 0 var(--s3); }
.cal-undated-why { margin: 0 0 var(--s3); }
.cal-numbers { overflow-x: auto; }
.cal-numbers table { width: 100%; }
.cal-numbers th { white-space: normal; vertical-align: bottom; }
.cal-numbers td:first-child { white-space: nowrap; }
.cal-numbers td:last-child { min-width: 16rem; color: var(--ink-3); }
.cal-numbers tbody tr:last-child td { font-weight: var(--weight-strong); border-top: 1px solid var(--edge); }
.cal-numbers td:not(:first-child):not(:last-child), .cal-numbers th:not(:first-child):not(:last-child) { text-align: right; font-variant-numeric: tabular-nums; }
.cal-empty { margin-left: 0; }
@media (max-width: 719px) {
  .cal-to-timeline { margin-left: 0; }
  .cal-cell, .cal-weeks .cal-cell { height: 68px; }
  .cal-day { padding: var(--s1); gap: var(--s1); }
  .cal-cell.cal-off { padding: var(--s1); }
  .cal-grid th { padding: var(--s1); }
  .cal-top { flex-direction: column; align-items: flex-start; gap: 1px; }
  .cal-marks { gap: 2px 0; }
  .cal-slot { min-width: 46%; gap: 1px; padding-right: 1px; }
  .chart.cal-mark-svg { width: 11px; height: 11px; }
  .chart.cal-bar-svg { width: 28px; height: 6px; }
  .cal-count { font-size: var(--text-small); }
  .cal-pay { font-size: var(--text-small); padding: 0 2px; }
}
/* ---------- the Calendar: end of the block ---------- */

/* ---------- the Timecard (FLO-512): start of the block ----------
   The timecard_table macro in _timecard.html, on the Timecard page and
   in the full view, and Setup's Timecards section. Our own column is
   tinted and says so; total rows are bold; both hold on paper. */
.tc-head { margin: 0 0 var(--s3); }
.tc-title { margin: 0; }
.tc-when { margin: 0 0 var(--s2); color: var(--ink-2); }
.tc-facts { display: grid; grid-template-columns: max-content 1fr; gap: 2px var(--s3); margin: 0 0 var(--s2); font-size: var(--text-body); line-height: var(--line-body); }
.tc-facts dt { color: var(--ink-3); }
.tc-facts dd { margin: 0; }
.tc-layout { margin: 0; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.tc-table td { white-space: normal; }
/* body-size figures, so the cells give back the room a smaller size used to make */
.tc-table th, .tc-table td { padding-left: 10px; padding-right: 10px; }
/* the head cells wrap too, so the client's columns fit the page at 1280 px; a narrower screen scrolls the table inside its frame */
.tc-table thead th { white-space: normal; }
.tc-table thead th.tc-ours { white-space: normal; min-width: 9rem; }
/* MicroForensics's own column keeps its tint and gets no rust stripe: rust is for the action and "you are here" (guideline 5.6) */
.tc-table th.tc-ours, .tc-table td.tc-ours { background: var(--accent-soft); }
/* The client's own figure columns (guideline 5.6): right-aligned in tabular figures, header too; a zero muted. */
.tc-table th.tc-figure, .tc-table td.tc-figure { text-align: right; font-variant-numeric: tabular-nums; }
.tc-table td.tc-zero { color: var(--ink-3); }
.tc-ours-tag { display: block; font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); color: var(--ink-3); }
.tc-table tr.tc-total td { font-weight: var(--weight-strong); background: var(--sunken); border-top: 2px solid var(--edge); }
.tc-table tr.tc-total:hover td { background: var(--sunken); }
.tc-flags { list-style: none; margin: 4px 0 0; padding: 0; font-size: var(--text-small); line-height: var(--line-small); }
.tc-flags li { margin: 2px 0 0; }
.tc-flag-state { color: var(--ink-3); }
.tc-flag-state::before { content: "· "; }
.tc-note { margin: 4px 0 0; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); }
.tc-table tr.tc-marked td { background: var(--warn-bg); }
.tc-table tr.tc-marked td:first-child { border-left: 3px solid var(--warn); }
.tc-picker { margin: 0 0 var(--s4); }
/* The claims lens (batch 7): the days inside a claim's dates, shaded, the claims named under the
   date, and that claim's flags outlined. Shaded in the sunken ground with an ink edge: blue is the
   "waiting" state and not a highlight (guideline 6.1). MicroForensics's own columns keep their tint. */
.tc-table tr.tc-lens td:not(.tc-ours) { background: var(--sunken); }
.tc-table tr.tc-lens td:first-child { border-left: 3px solid var(--ink-2); }
.tc-table tr.tc-lens-start td { border-top: 2px solid var(--ink-2); }
/* Burns's walk, 9 Oct: a day the core marks OK, and a resolved flag, read in green. A state word may. */
.tc-ok, .tc-flags li.tc-flag-resolved, .tc-flags li.tc-flag-resolved a, .tc-flags li.tc-flag-resolved .tc-flag-state { color: var(--pass); }
.tc-lens-tag { display: block; font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); white-space: normal; }
.tc-flags li.tc-flag-lens { display: inline-block; padding: 0 var(--s1); border: 1px solid var(--ink-2); border-radius: var(--r-control); background: var(--surface); font-weight: var(--weight-label); }
.lens-pick input[type="date"] { width: 10rem; max-width: 100%; }
.lens-choose { margin: var(--s4) 0 var(--s2); }
/* Setup's columns form: one row per column, the order a small number. */
.tc-columns td { white-space: normal; vertical-align: middle; }
.tc-columns input[type="number"] { width: 4.5rem; }
.tc-columns input[type="text"] { width: 14rem; max-width: 100%; }
.tc-columns td.tc-ours { background: var(--accent-soft); }
.tc-stamps { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); margin: var(--s2) 0 0; }
@media print {
  /* UI-13: the green OK and the resolved flag are ink on paper; the word carries the meaning */
  .tc-ok, .tc-flags li.tc-flag-resolved, .tc-flags li.tc-flag-resolved a, .tc-flags li.tc-flag-resolved .tc-flag-state { color: #000; }
  .tc-table th.tc-ours, .tc-table td.tc-ours { background: #eee; border-left: 2px solid #000; }
  .tc-table th, .tc-table td { border: 1px solid #999; }
  .tc-table tr.tc-total td { background: #f4f4f4; }
  .tc-table tr.tc-marked td { background: #f4f4f4; }
  .tc-table tr.tc-marked td:first-child { border-left: 3px solid #000; }
  .tc-table tr.tc-lens td:not(.tc-ours) { background: #f4f4f4; }
  .tc-table tr.tc-lens td:first-child { border-left: 3px solid #000; }
  .tc-flags li.tc-flag-lens { border-color: #000; }
}
/* ---------- the Timecard: end of the block ---------- */
/* ---- Invoices (FLO-513): the printable detail's two parties side by side ---- */
.invoice-parties { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--s4); }
.invoice-parties h2 { margin-top: 0; }
.invoice-lines tfoot th { text-align: right; }
.table tr.waiting td.person a { font-weight: var(--weight-strong); }
/* ---- the attestation org chart (FLO-502, Setup's /setup/chart) ---- */
/* A line's form sits in a table cell. A table cell does not wrap, so the help ran
   over the next field (batch 2, C): the form's cell wraps like a page. */
.table.org-chart td.chart-form { white-space: normal; padding-top: var(--s1); padding-bottom: var(--s3); }
.org-chart .chart-form summary { cursor: pointer; color: var(--ink-2); }
.org-chart .chart-form .form { max-width: 720px; margin-top: var(--s3); }
.org-chart fieldset.picks { border: 0; padding: 0; margin: 0 0 var(--s4); min-width: 0; }
.org-chart fieldset.picks legend { padding: 0; margin: 0 0 var(--s1); font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); }
.org-chart fieldset.picks .field.check { margin-bottom: var(--s1); }
.org-chart-mine > h2 { margin: 0 0 var(--s1); }
/* Narrow: a worker's line is a block, each fact under the last with its column's
   name above it, so the form and its help fit the screen with no sideways scroll. */
@media (max-width: 719px) {
  .table.org-chart, .table.org-chart tbody, .table.org-chart tr, .table.org-chart td { display: block; width: 100%; }
  .table.org-chart thead { display: none; }
  .table.org-chart td { white-space: normal; border-top: 0; padding-top: var(--s1); padding-bottom: var(--s1); }
  .table.org-chart tr { border-top: 1px solid var(--rule); padding: var(--s2) 0; }
  .table.org-chart tbody tr:first-child, .table.org-chart tr.chart-form-row { border-top: 0; padding-top: 0; }
  .table.org-chart td[data-label]::before { content: attr(data-label); display: block; font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); }
}
/* Setup's extra documents (per-client choices, part 2) stack the same way on a phone (reviewers, 11 Oct):
   the name field takes the width, and a box sits before its column's name on one line. */
@media (max-width: 719px) {
  .table.extras, .table.extras tbody, .table.extras tr, .table.extras td { display: block; width: 100%; }
  .table.extras thead { display: none; }
  .table.extras td { white-space: normal; border-top: 0; padding-top: var(--s1); padding-bottom: var(--s1); }
  .table.extras tr { border-top: 1px solid var(--rule); padding: var(--s2) 0; }
  .table.extras tbody tr:first-child { border-top: 0; }
  .table.extras td:empty { display: none; }
  .table.extras td[data-label]::before { content: attr(data-label); display: block; font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); }
  .table.extras td:has(> input[type=checkbox]) { display: flex; flex-direction: row-reverse; justify-content: flex-end; align-items: center; }
  .table.extras input:not([type=checkbox]) { width: 100%; }
}
/* ---- the full view (FLO-511): one attestation as one printable record ---- */
.fv-section { margin-top: var(--s6); }
.fv-section > h2 { margin-bottom: var(--s3); }
.fv-question h3 { font-size: var(--text-body); font-weight: var(--weight-strong); line-height: var(--line-body); margin: 0 0 var(--s3); }
/* the attestation page's question reads as the full view's does: Strong */
.card.question > h2 { font-size: var(--text-body); line-height: var(--line-body); }
.fv-question .heading { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); margin: 0 0 var(--s3); }
.fv-hidden { color: var(--ink-3); }
.tag.fv-not-for-manager { border-style: dashed; }
.fv-notes, .fv-follow-ups { list-style: none; padding: 0; margin: 0 0 var(--s4); }
.fv-notes li, .fv-follow-ups li { padding: var(--s3) 0; border-top: 1px solid var(--hairline); }
.fv-notes li:first-child, .fv-follow-ups li:first-child { border-top: 0; padding-top: 0; }
.fv-notes li p, .fv-follow-ups li p { margin: 0 0 var(--s1); }
.fv-follow-ups .fv-reply { padding-left: var(--s4); border-left: 2px solid var(--edge); }
/* ---- the thread under an answer (FLO-588, the Ricker pilot): a manager's
   question and the worker's reply, each with the name and the time on its
   own line; the reply inset. Printed with the record; the ask forms and the
   HR links carry print-hide. ---- */
.fv-asks { margin-top: var(--s3); }
.fv-round { padding-top: var(--s2); border-top: 1px solid var(--hairline); }
.fv-round p { margin: 0 0 var(--s2); }
.fv-round .fv-who { display: block; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.fv-round .fv-words { display: block; }
.fv-asks .fv-reply { padding-left: var(--s4); border-left: 2px solid var(--edge); }
@media print {
  .fv-section { break-inside: auto; }
  .fv-question, .fv-notes li, .fv-follow-ups li, .fv-round { break-inside: avoid; }
  .fv-question .heading { color: #000; }
  .fv-round { border-top-color: #999; }
  .fv-asks .fv-reply { border-left-color: #000; }
  .fv-round .fv-who { color: #000; }
}
/* ---- the pay period by day (FLO-502 batch 3; Burns, 6 Oct 2026) ----
   The attestation page and the full view: one row a day, the day's times
   as a bar on one hour scale for the whole table and as text beside it,
   the hours, and the day's flags on the right. The table scrolls inside
   its frame on a phone; the page never scrolls sideways. Only the tokens,
   so the table follows the page's colours. */
/* By day / By question: tiles on the sunken ground their siblings make; the chosen one is raised to the surface, in ink */
.pt-switch { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1); margin: var(--s4) 0; }
.pt-switch .btn { background: var(--sunken); border-color: transparent; color: var(--ink-2); }
.pt-switch .btn:hover { color: var(--ink); }
.pt-switch .btn.on, .pt-switch .btn[aria-pressed="true"] { background: var(--surface); border-color: var(--hairline); color: var(--ink); }
.pt-switch .small { margin-left: var(--s2); }
.by-question[hidden] { display: none; }
.pt > h2 { margin-bottom: var(--s1); }
.pt > p.small { margin: 0 0 var(--s3); max-width: 72ch; }
.pt-caption { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.pt-legend { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); margin: 0 0 var(--s2); }
.pt-key { display: inline-block; width: 1.5rem; height: 0.625rem; border-radius: 2px; }
.pt-key + .pt-key, .pt-legend .pt-key-meal { margin-left: var(--s3); }
/* worked time and a meal look as they do on the Timeline's day drawing: an ink-3 bar, a hold-tinted box */
.pt-key-worked { background: var(--ink-3); }
.pt-key-meal { background: var(--hold-bg); border: 1px solid var(--ink-3); }
.pt-table { min-width: 44rem; }
.pt-table th, .pt-table td { padding-left: 10px; padding-right: 10px; vertical-align: top; }
.pt-table tbody th { text-align: left; font-weight: var(--weight-read); white-space: nowrap; }
.pt-table td.pt-flags, .pt-table td.pt-times { white-space: normal; }
.pt-day .pt-wd { display: inline-block; min-width: 2.25rem; font-weight: var(--weight-strong); }
.pt-day .pt-date { font-variant-numeric: tabular-nums; }
.pt-table .pt-bar-col { width: 30%; min-width: 14rem; }
.pt-bar-head { display: block; }
.pt-scale { display: flex; margin-top: var(--s1); font-weight: var(--weight-read); }
.pt-scale span { flex: 1 1 0; min-width: 0; white-space: nowrap; overflow: hidden; border-left: 1px solid var(--hairline); padding-left: 3px; }
.pt-bar { display: block; width: 100%; height: 20px; margin-top: 1px; }
.pt-bar .pt-grid { stroke: var(--rule); stroke-width: 1; }
.pt-bar .pt-work { fill: var(--ink-3); }
.pt-bar .pt-meal { fill: var(--hold-bg); stroke: var(--ink-3); stroke-width: 1; }
.pt-status { color: var(--ink-3); }
.pt-times-list { display: grid; grid-template-columns: max-content max-content; gap: 0 var(--s2); margin: 0; }
.pt-times-list dt { color: var(--ink-3); }
.pt-times-list dd { margin: 0; white-space: nowrap; font-variant-numeric: tabular-nums; }
.pt-t { display: inline-block; min-width: 4.5rem; text-align: right; }
.pt-note { margin: var(--s1) 0 0; }
.pt-words { margin: var(--s1) 0 0; }
.pt-hours { font-variant-numeric: tabular-nums; }
.pt-table .pt-flags-col { min-width: 13rem; }
.pt-flag-list { list-style: none; margin: 0; padding: 0; }
.pt-flag + .pt-flag { margin-top: var(--s2); padding-top: var(--s2); border-top: 1px solid var(--rule); }
.pt-flag > a, .pt-flag-words { font-weight: var(--weight-strong); }
.pt-flag .pt-answer { display: block; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-2); }
.pt-table tr.pt-flagged td.pt-flags { background: var(--warn-bg); }
.pt-table tr.pt-not_worked th, .pt-table tr.pt-not_worked td, .pt-table tr.pt-none th, .pt-table tr.pt-none td { color: var(--ink-3); }
.pt-others td.pt-number { width: 2.5rem; color: var(--ink-3); }
.pt-others th.pt-name { text-align: left; font-weight: var(--weight-read); white-space: nowrap; }
.pt-others td.pt-answer { white-space: normal; }
/* FLO-502 batch 3: a decline flagged for the managers, the core's words under the answer */
.pt-decline { display: block; margin-top: var(--s1); font-size: var(--text-small); line-height: var(--line-small); color: var(--ink); }
.fv-decline-flag { margin: var(--s2) 0 0; }
/* FLO-502 batch 3: an HR item's events, in the order they happened */
ol.hr-events { margin: 0 0 var(--s4); padding-left: var(--s4); }
.hr-event + .hr-event { margin-top: var(--s3); }
.hr-event p { margin: 0; }
.hr-event .sub { display: block; font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
@media print {
  .pt-bar .pt-work { fill: #000; }
  .pt-bar .pt-meal { fill: #fff; stroke: #000; }
  .pt-table tr.pt-flagged td.pt-flags { background: #f4f4f4; }
}

/* Response Bundle: the claims lens (FLO-579) and the sealed view (FLO-576). */
.claims-lens h2 .pill { vertical-align: middle; margin-left: var(--s2); }
.table.lens th[scope="row"] { font-weight: var(--weight-strong); vertical-align: top; min-width: 10em; }
.table.lens th[scope="row"] .small { display: block; font-weight: var(--weight-read); margin-top: var(--s1); max-width: 28ch; }
.table.lens ul.plain, .sealed-view ul.plain { list-style: none; margin: 0; padding: 0; }
.table.lens ul.plain li + li { margin-top: var(--s1); }
.seal-help { margin: var(--s1) 0 0; }
@media print { .lens-form, .seal-help { display: none; } }

/* ---- HR snapshot (FLO-589, the Ricker pilot): one pay period's sets on one
   printable page. The picker, the Print button and the "?" never print; the
   print frame's head names the period and the scope, and its foot says when
   the page was printed (UI-13). A row never splits across pages. ---- */
.snap-pick { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); margin: 0 0 var(--s4); }
.snap-pick label { font-size: var(--text-small); color: var(--ink-2); }
.snap-counts { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); margin: 0 0 var(--s4); }
.snap-counts dt { font-size: var(--text-small); line-height: var(--line-small); color: var(--ink-3); }
.snap-counts dd { margin: 0 0 0 0; font-weight: var(--weight-strong); font-variant-numeric: tabular-nums; }
.snap-counts > div { display: flex; flex-direction: column; }
.table.snapshot { width: 100%; table-layout: fixed; }
.table.snapshot th:nth-child(1) { width: 15%; }
.table.snapshot th:nth-child(2) { width: 14%; }
.table.snapshot th:nth-child(3) { width: 21%; }
.table.snapshot th:nth-child(4) { width: 22%; }
.table.snapshot td { white-space: normal; min-width: 0; vertical-align: top; overflow-wrap: anywhere; }
.table.snapshot td .sub { white-space: normal; }
.table.snapshot ul.plain { list-style: none; margin: 0; padding: 0; }
.table.snapshot ul.plain li + li { margin-top: var(--s2); padding-top: var(--s2); border-top: 1px solid var(--hairline); }
.table.snapshot .snap-rounds .wrap { display: block; }
.table.snapshot .snap-reply { padding-left: var(--s3); border-left: 2px solid var(--edge); }
@media print {
  .snap-wrap { border: 0; }
  .table.snapshot th, .table.snapshot td { border: 1px solid #999; }
  .table.snapshot ul.plain li + li { border-top-color: #999; }
  .table.snapshot .snap-reply { border-left-color: #000; }
}
/* ---- Response Bundle, round 2 (FLO-578): the sealed index's hash column, the print view ---- */
.table.sealed-index td.file-hash { white-space: normal; overflow-wrap: anywhere; max-width: 24ch; }
.lens-from-url { margin-top: 0; }
/* The print view (UI-13): the print frame's head carries the mark as one line
   of text, so the band on screen is off paper; nothing that is a button prints.
   The fingerprints print short in the index and whole in the appendix under it. */
.rb-print-mark { margin-bottom: var(--s4); }
.hash-appendix dl { display: grid; grid-template-columns: max-content 1fr; gap: var(--s1) var(--s4); margin: 0; font-size: var(--text-small); line-height: var(--line-small); }
.hash-appendix dd { margin: 0; overflow-wrap: anywhere; }
@media print {
  .rb-print-mark, .rb-print .btn, .rb-print .actions, .rb-print form, .rb-print button, .print-btn { display: none !important; }
  .rb-print .card { border-color: #999; break-inside: avoid; }
  .bundle-index tr.folder { break-after: avoid; }
  .hash-appendix { break-before: page; }
  .hash-appendix dt, .hash-appendix dd { break-inside: avoid; }
}
/* ---- Contractors and a contractor's file (FLO-606, Phase 1). Layout only: the
   words keep the six text styles and the state pills keep their tokens. ---- */
.table.contractors td.list { white-space: normal; min-width: 14ch; }
.table.contractors td.list .tag { margin-left: 0; }
.table.contractors td.name details.reveal { margin-top: var(--s1); }
/* the questions block: the question sentence first, in Strong; its answers an inset list; a date a field of its own */
fieldset.question { margin-bottom: var(--s5); }
fieldset.question legend { font-size: var(--text-body); font-weight: var(--weight-strong); line-height: var(--line-body); color: var(--ink); margin-bottom: var(--s2); }
fieldset.question .choice { margin-left: var(--s5); }
fieldset.question .field.inset { margin-left: calc(var(--s5) * 2); margin-bottom: var(--s3); }
fieldset.question .tag { margin-left: 0; }
details.questions > :not(summary) { margin-top: var(--s3); }
/* the papers table: the paper's question under its name, a date a field of its own, the request form in the action cell */
.table.papers td.name { white-space: normal; min-width: 22ch; max-width: 36ch; }
.table.papers td.name .sub, .table.papers td.name .problem { white-space: normal; display: block; }
.table.papers td.have { white-space: normal; min-width: 16ch; }
.table.papers td.have .choice { margin: 0 0 var(--s1); min-height: 0; }
.table.papers td.dates .field, .table.papers td.acts .field { margin-bottom: var(--s2); }
.table.papers td.acts { min-width: 14rem; }
.table.papers td.acts form { display: block; }
/* the signs table (piece 6): the fact wraps, its tag sits under it in Small */
.table.signs td.wrap { min-width: 18ch; }
.table.signs td .sub { white-space: normal; }
/* the document request (piece 8): a letter's measure, its rows, and the lettered replies */
.letter { max-width: 64ch; }
.letter .opening { font-weight: var(--weight-strong); }
.letter .replies { list-style: none; padding: 0; margin: 0 0 var(--s4); }
.letter .replies li { display: grid; grid-template-columns: 2ch 1fr; gap: var(--s3); padding: var(--s1) 0 var(--s1) var(--s4); }
.letter .replies .mark { font-weight: var(--weight-strong); }
/* on paper (UI-13): the file's record folds print open (the frame's rule hides details.reveal, an action fold
   elsewhere); the questions form prints, its marks as marks and its text and date fields as words with no
   box; the papers table's own controls print as their values; the action forms are forms, so off paper */
@media print {
  .print-frame details.reveal.record { display: block !important; }
  form.questions { display: block !important; }
  form.questions input:not([type=radio]):not([type=checkbox]), .table.papers input:not([type=checkbox]), .table.papers select { appearance: none; border: 0; padding: 0; background: none; font: inherit; color: #000; }
  .table.papers td.acts { display: none; }
  details.record .table.papers th:last-child { display: none; }
  /* the table fits the paper (reviewers, 11 Oct): a select was as wide as its longest choice, so one long
     choice ran the table past the right edge. On paper a select is its chosen words, wrapping in the cell,
     with no arrow; a date is as wide as the date, with no calendar button; the name and the answer give way */
  .table.papers select { appearance: base-select; width: 100%; min-width: 0; max-width: 100%; height: auto; min-height: 0; white-space: normal; }
  .table.papers select::picker-icon { display: none; }
  .table.papers input[type=date] { field-sizing: content; width: auto; max-width: none; }
  .table.papers input[type=date]::-webkit-calendar-picker-indicator { display: none; }
  .table.papers td.name, .table.papers td.have, .table.papers td.wrap { min-width: 0; }
  /* the file summary prints the same table with plain-word cells (td.wrap): they give way too, each date line whole */
  .table.papers td.wrap .sub { white-space: nowrap; }
}
/* the File risk meter (piece 7; proposal 3.4). Four tokens with one job each: the meter's four steps, tinted
   pale to deep in one hue the palette does not use, a slate ramp. Never --pass (green would read as advice),
   never --fail (red is a failure's), never --accent (rust is the one primary button's). The level reads
   four ways before colour: the step's place in the row, the raised tile with its ink outline, the pointer
   under it, and the word itself. The gate inlines tokens.css and draws no meter, so these stay out of it. */
:root {
  --risk-low: #e3e9f0;
  --risk-moderate: #b7c6d6;
  --risk-high: #6f8aa6;
  --risk-extreme: #2f4a66;
}
.risk-meter { max-width: 66ch; margin: 0 0 var(--s5); }
/* the caption is Small (guideline 3.2: a caption is 14 px at 400 in ink-3) */
.risk-meter figcaption { font-size: var(--text-small); font-weight: var(--weight-read); line-height: var(--line-small); color: var(--ink-3); margin: 0 0 var(--s2); }
/* the track: four equal steps on sunken ground, each 36 px tall, the words centered in Label style (14 px at 500 in ink-2, like a tag) */
.risk-track { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s1); padding: var(--s1); background: var(--sunken); border-radius: var(--r-control); margin: 0 0 var(--s5); }
.risk-step { position: relative; display: flex; align-items: center; justify-content: center; height: 36px; font-size: var(--text-small); font-weight: var(--weight-label); line-height: var(--line-small); color: var(--ink-2); border-radius: var(--r-control); border-bottom: 6px solid transparent; }
.risk-step.risk-low { border-bottom-color: var(--risk-low); }
.risk-step.risk-moderate { border-bottom-color: var(--risk-moderate); }
.risk-step.risk-high { border-bottom-color: var(--risk-high); }
.risk-step.risk-extreme { border-bottom-color: var(--risk-extreme); }
/* the marked step is raised: a surface tile on the track with a solid ink outline, its word in ink, a pointer under it (guideline 6.1) */
.risk-step.marked { background: var(--surface); outline: 1px solid var(--ink); color: var(--ink); }
.risk-step .pointer { position: absolute; left: 50%; bottom: -22px; transform: translateX(-50%); color: var(--ink); }
.risk-meaning { margin: 0 0 var(--s2); max-width: 66ch; }
.risk-line, .risk-from { margin: 0 0 var(--s1); }
.risk-line .page-help { margin-left: var(--s1); }
/* the level on a table row: the word with a 16 px four-step glyph beside it, never the glyph alone (guideline 6.9) */
.risk-word { display: inline-flex; align-items: center; gap: var(--s1); white-space: nowrap; }
.risk-glyph { flex: none; }
@media print {
  .risk-step { border-bottom-color: #ccc !important; }
  .risk-step.marked { outline: 1px solid #000; }
}
/* the Contractor files tile (piece 10): the levels line in Heading style where the tier tiles show a count (its "?" is with the page help) */
.tile .levels { font-size: var(--text-heading); font-weight: var(--weight-strong); line-height: var(--line-heading); margin: var(--s2) 0; font-variant-numeric: tabular-nums; }

/* UI-4 meets UI-13: a record fold prints open, so its chevron has nothing to say on paper. */
@media print { .fold > summary::before { display: none; } }
