/* ============================================================
   RIVETDATA CONSOLE — component layer
   ------------------------------------------------------------
   Load order: css/styles.css → css/console-base.css → this file.
   Tokens (type scale, radii, surfaces, status colours, layout
   dimensions) all come from console-base.css; nothing here sets
   a raw px font-size or a literal status rgba().
   ============================================================ */

/* ---- shared primitives ----
   THE BUTTON SYSTEM. Three tiers, nothing else:
     .btn--glow / .btn--primary   primary   — filled brand green, white label.
                                             The OUTPUT of the screen (download /
                                             export / run / new) or the commit
                                             action. Approve and friends are state
                                             changes, not output: keep them secondary.
     .btn (bare) / .btn--ghost    secondary — white surface + hairline. Everything else.
     .cfm__danger / .bulkbar__del destructive — red fill. Delete only.
   Anything that needs to look different is a bug, not a fourth tier.

   styles.css gives .btn only geometry and no fill, so a bare `class="btn"` used to
   render as the browser's native button (#EFEFEF + a black label). The base below
   closes that: a missing modifier degrades to secondary instead of leaking UA chrome.
   ORDER MATTERS: base first, then size modifiers, then tier modifiers. Every rule
   here is one class (0,1,0), so source order is the only tie-breaker.

   NEVER use the `font` shorthand on a button. It resets font-size to the inherited
   value, so a base rule carrying `font: inherit` silently outranks `.btn--sm`
   further up the file and the button swells to whatever the surrounding block is
   set to — which is how Export Report ended up oversized next to the Review/Redline
   segment, and why `.cres-rename-edit .btn` below had to patch Cancel by hand.
   Use `font-family: inherit` plus an explicit `font-size`. */
.btn {
  background: var(--surface); border: 1px solid var(--hairline-hard); color: var(--t1);
  border-radius: var(--rx-sm); font-family: inherit; font-size: var(--fs-md);
  font-weight: 600; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.btn:hover { border-color: var(--acc-line); background: var(--hover); }

.btn--sm   { padding: 7px 14px; font-size: var(--fs-sm); }
.btn--full { width: 100%; justify-content: center; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }

/* Primary CTA — every "+ New …", every run, every deliverable download/export,
   every commit action. Overrides the marketing system's .btn--glow/.btn--primary
   (--acc fill + a near-black #04140C label): that's a dark-hero treatment, and on
   this light canvas it read muddy. Same green a step darker so the label can be
   white at 4.84:1. Rules sit AFTER .btn[disabled] on purpose — equal specificity,
   so source order decides the disabled fill. */
.btn--glow, .btn--primary {
  background: var(--pri-bg); color: var(--pri-fg); border: 1px solid var(--pri-bg);
  border-radius: var(--rx-sm); font-weight: 600; cursor: pointer;
  transition: background .15s, border-color .15s, color .15s, transform .08s;
}
.btn--glow:hover, .btn--primary:hover {
  background: var(--pri-bg-hover); border-color: var(--pri-bg-hover); color: var(--pri-fg);
}
.btn--glow:active, .btn--primary:active { transform: translateY(1px); }
.btn--glow:focus-visible, .btn--primary:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.btn--glow[disabled], .btn--primary[disabled] {
  opacity: 1; transform: none;
  background: var(--pri-off-bg); color: var(--pri-off-fg); border-color: var(--pri-off-line);
}

/* The primary action when it will go ahead with something missing — same shape, amber, so the
   label ("Generate WITHOUT utility bill") is read rather than clicked past. */
.btn--glow.btn--caution, .btn--primary.btn--caution {
  background: var(--warn-bg); color: var(--warn-fg); border-color: var(--warn-line);
}
.btn--glow.btn--caution:hover, .btn--primary.btn--caution:hover {
  background: var(--warn-line); color: var(--warn-fg); border-color: var(--warn-line);
}

/* Same look as the bare base — the explicit name for "secondary".
   font-family, NOT the `font` shorthand: see the note above. */
.btn--ghost {
  background: var(--surface); border: 1px solid var(--hairline-hard); color: var(--t1);
  border-radius: var(--rx-sm); cursor: pointer; font-family: inherit; font-weight: 600;
  display: inline-flex; align-items: center; transition: border-color .15s, background .15s;
}
.btn--ghost:hover { border-color: var(--acc-line); background: var(--hover); }
.err-msg { color: var(--bad-fg); font-size: var(--fs-sm); margin-top: 10px; min-height: 16px; }
.err-msg:empty { display: none; }

/* ============================================================
   SIGN-IN GATE — two-panel product login
   ============================================================ */
.gate { min-height: 100vh; display: grid; grid-template-columns: 1.05fr 0.95fr; background: var(--canvas); }
.gate--single { grid-template-columns: 1fr; }
.gate__aside {
  position: relative; overflow: hidden; border-right: 1px solid var(--hairline);
  background: var(--surface); padding: clamp(34px, 5vw, 72px);
  display: flex; flex-direction: column; justify-content: space-between; gap: var(--sp-10);
}
.gate__aside::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(115% 80% at 12% -5%, var(--acc-dim), transparent 55%);
}
.gate__aside > * { position: relative; z-index: 1; }
.gate__logo, .gate__brand { display: inline-flex; align-items: center; gap: 10px; }
.gate__logo b, .gate__brand b { font-size: var(--fs-lg); font-weight: 650; letter-spacing: -0.02em; }
.gate__pitch h2 {
  font-size: clamp(1.55rem, 2.5vw, 2.15rem); font-weight: 650;
  letter-spacing: -0.03em; line-height: 1.14;
}
.gate__pitch p { color: var(--t2); margin-top: 14px; font-size: var(--fs-md); max-width: 40ch; }
.gate__feats { list-style: none; margin-top: var(--sp-6); padding: 0; display: flex; flex-direction: column; gap: 13px; }
.gate__feats li { display: flex; align-items: flex-start; gap: 11px; font-size: var(--fs-md); color: var(--t2); }
.gate__feats svg { flex: none; color: var(--acc); margin-top: 2px; }
.gate__note {
  font-family: var(--mono); font-size: var(--fs-2xs); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--t4);
}
.gate__main { display: grid; place-items: center; padding: var(--gutter); }
.gate__card { width: 100%; max-width: 380px; }
.gate__brand { margin-bottom: var(--sp-6); }
.gate__card h1 { font-size: clamp(1.35rem, 3vw, 1.65rem); font-weight: 650; letter-spacing: -0.03em; }
.gate__sub { color: var(--t2); margin-top: var(--sp-2); font-size: var(--fs-md); }
.g-btn {
  width: 100%; justify-content: center; display: inline-flex; align-items: center; gap: 10px;
  margin-top: 22px; padding: 12px 18px; border: 1px solid var(--hairline-hard);
  border-radius: var(--rx-sm); background: var(--surface); color: var(--t1);
  font-weight: 600; font-size: var(--fs-md); cursor: pointer;
  transition: border-color .2s, background .2s;
}
.g-btn:hover { border-color: var(--acc-line); background: var(--hover); }
.g-btn svg { width: 18px; height: 18px; }
.gate__legal { font-size: var(--fs-xs); color: var(--t4); margin-top: 18px; }
.gate__or { display: flex; align-items: center; gap: var(--sp-3); margin: 18px 0 14px; color: var(--t4); font-size: var(--fs-xs); }
.gate__or::before, .gate__or::after { content: ""; flex: 1; height: 1px; background: var(--hairline); }
.gate__email {
  width: 100%; padding: 11px 14px; border: 1px solid var(--hairline-hard);
  border-radius: var(--rx-sm); background: var(--surface); color: var(--t1);
  font: inherit; font-size: var(--fs-md); margin-bottom: 10px;
  transition: border-color .15s, box-shadow .15s;
}
.gate__email::placeholder { color: var(--t4); }
.gate__email:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }
.gate__links { display: flex; justify-content: space-between; gap: var(--sp-3); margin-top: var(--sp-1); }
.gate__link {
  display: inline-block; background: none; border: 0; padding: 6px 2px;
  color: var(--t3); font: inherit; font-size: var(--fs-xs); cursor: pointer; text-decoration: underline;
}
.gate__link:hover { color: var(--acc); }
@media (max-width: 860px) { .gate { grid-template-columns: 1fr; } .gate__aside { display: none; } }

/* ---- no workspace yet ---- */
.nows { display: grid; place-items: center; min-height: 60vh; }
.nows__card {
  max-width: 460px; text-align: center; padding: var(--sp-10) var(--sp-8);
  border: 1px solid var(--hairline); border-radius: var(--rx-lg);
  background: var(--surface); box-shadow: var(--elev-1);
}
.nows__card svg { color: var(--acc); margin-bottom: 14px; }
.nows__card h2 { font-size: var(--fs-xl); letter-spacing: -0.02em; }
.nows__card p { color: var(--t2); font-size: var(--fs-md); line-height: var(--lh-body); margin-top: 10px; }
.nows__contact { color: var(--t4) !important; font-size: var(--fs-sm) !important; margin-top: var(--sp-4) !important; }

/* ============================================================
   TOPBAR CHROME — breadcrumb, agent switcher, account menu
   ============================================================ */
.tb-brand { display: inline-flex; align-items: center; }
.tb-brand .brand__logo { height: 20px; width: 118px; }

.tb-crumb {
  color: var(--t2); font-size: var(--fs-sm); font-weight: 550; letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 30vw;
}
.tb-caret { flex: none; color: var(--t4); transition: transform .18s var(--ease-out); }
[aria-expanded="true"] > .tb-caret { transform: rotate(180deg); }

/* account pill */
.tb-acct { position: relative; }
.tb-acct__btn {
  display: inline-flex; align-items: center; gap: var(--sp-2); padding: 5px 10px 5px 5px;
  border: 1px solid var(--hairline); border-radius: var(--rx-pill);
  background: var(--surface); color: var(--t1); font: inherit; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.tb-acct__btn:hover { border-color: var(--acc-line); background: var(--hover); }
.tb-acct__name {
  font-size: var(--fs-sm); font-weight: 600; max-width: 150px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.side__ava {
  flex: none; width: 28px; height: 28px; border-radius: 50%; background: var(--acc-dim);
  border: 1px solid var(--acc-line); color: var(--acc); display: grid; place-items: center;
  font-weight: 700; font-size: var(--fs-sm);
}
.side__email {
  display: block; font-size: var(--fs-xs); color: var(--t4); line-height: var(--lh-snug);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* shared dropdown menus */
.tb-menu {
  position: absolute; top: calc(100% + 8px); min-width: 236px; padding: 6px;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--rx); box-shadow: var(--elev-3); z-index: 60;
  animation: tbMenuIn .13s var(--ease-out);
}
.tb-menu[hidden] { display: none; }
.tb-acct__menu { right: 0; min-width: 248px; }
@keyframes tbMenuIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.tb-menu__item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 9px 10px; border: 0; border-radius: var(--rx-sm); background: none;
  color: var(--t1); font: inherit; font-size: var(--fs-sm); font-weight: 550;
  cursor: pointer; transition: background .12s;
}
.tb-menu__item:hover { background: var(--hover); }

.tb-acct__ws {
  display: flex; align-items: center; gap: 10px; padding: var(--sp-2) var(--sp-2) 10px;
  margin-bottom: 6px; border-bottom: 1px solid var(--hairline-soft);
}
.tb-acct__ws .badge-sq {
  flex: none; width: 30px; height: 30px; border-radius: var(--rx-xs);
  background: var(--acc); color: #fff; display: grid; place-items: center;
  font-weight: 700; font-size: var(--fs-sm); overflow: hidden;
}
.tb-acct__ws .badge-sq.has-logo { background: #fff; padding: 2px; border: 1px solid var(--hairline); }
.tb-acct__ws .badge-sq img { width: 100%; height: 100%; object-fit: contain; border-radius: inherit; display: block; }
.tb-acct__ws b { font-size: var(--fs-sm); color: var(--t1); letter-spacing: -0.01em; }
.tb-acct__ws span { font-size: var(--fs-2xs); color: var(--t4); }
/* Workspace switcher — only present for someone in more than one workspace. */
.tb-acct__wslist { padding: 0 0 6px; margin-bottom: 6px; border-bottom: 1px solid var(--hairline-soft); }
.tb-acct__wslabel {
  padding: 2px 10px 4px; font-size: var(--fs-2xs); color: var(--t4);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.tb-ws__item { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; width: 100%; }
.tb-ws__nm { font-size: var(--fs-sm); color: var(--t1); }
/* The role is the reason the switcher exists — read-only in one workspace and not in another —
   so it is always visible, not a hover affordance. */
.tb-ws__role { font-size: var(--fs-2xs); color: var(--t4); text-transform: lowercase; }
.tb-ws__item.is-active { cursor: default; }
.tb-ws__item.is-active .tb-ws__nm { font-weight: 600; }
.tb-ws__item.is-active:hover { background: none; }

.tb-acct__email { padding: 0 10px var(--sp-2); }
.tb-signout { color: var(--t2); }
.tb-signout:hover { color: var(--acc); }
.tb-signout svg { flex: none; }

@media (max-width: 560px) {
  .tb-acct__name { display: none; }
}

/* ---- workspace search (docs/SEARCH.md, workstream B) ----------------
   One field for every agent. Deliberately the SAME geometry as the
   per-agent .tbl-search below, so the global field and the scoped ones
   read as one control at two scopes rather than two designs. The panel
   borrows .tb-menu's surface, radius, elevation and entry animation —
   it is a dropdown off the top bar like the account menu, not a modal. */
.tb-search { position: relative; display: flex; align-items: center; flex: none; }
.tb-search > svg { position: absolute; left: 11px; color: var(--t4); pointer-events: none; }
.tb-search__in {
  /* Wide enough for a NAME at rest, wide enough for a QUESTION in use. A search box you can
     type a sentence into but only read six words of is worse than a short one. */
  width: min(320px, 32vw); padding: 8px 34px 8px 32px;
  transition: width .18s var(--ease-out), border-color .15s, box-shadow .15s, background .15s;
  border: 1px solid var(--hairline-hard); border-radius: var(--rx-sm);
  background: var(--surface-sub); color: var(--t1); font-family: inherit; font-size: var(--fs-sm);
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.tb-search__in::placeholder { color: var(--t4); }
.tb-search__in:focus {
  outline: none; width: min(560px, 52vw);
  background: var(--surface); border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim);
}
.tb-search__in::-webkit-search-cancel-button { -webkit-appearance: none; }
/* The "/" affordance, treated like the rail's "soon" tag. It steps aside
   the moment the field is in use — it is a hint, not a decoration. */
.tb-search__kbd {
  position: absolute; right: 8px; pointer-events: none;
  font-family: var(--mono); font-size: 9px; line-height: 1; letter-spacing: 0.06em;
  color: var(--t4); background: var(--surface);
  border: 1px solid var(--hairline); border-radius: var(--rx-xs); padding: 3px 5px;
}
.tb-search:focus-within .tb-search__kbd { display: none; }
/* The crumb only exists inside a run, so this divider appears with it. */
.tb-search + .tb-crumb { border-left: 1px solid var(--hairline); padding-left: var(--sp-3); margin-left: var(--sp-1); }

.tb-search__panel {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 60;
  width: min(560px, 78vw); max-height: min(58vh, 440px); overflow-y: auto;
  padding: 6px; background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--rx); box-shadow: var(--elev-3);
  animation: tbMenuIn .13s var(--ease-out);
}
.tb-search__panel[hidden] { display: none; }

/* One block per agent, separated by a hairline — never above the first. */
.tb-search__g + .tb-search__g { border-top: 1px solid var(--hairline-soft); margin-top: 4px; padding-top: 2px; }
.tb-search__grp { display: flex; align-items: center; gap: 8px; padding: 9px 10px 5px; }
.tb-search__gico {
  flex: none; display: grid; place-items: center; width: 20px; height: 20px;
  border-radius: var(--rx-xs); color: rgb(var(--dacc));
  background: rgba(var(--dacc), 0.11); border: 1px solid rgba(var(--dacc), 0.22);
}
.tb-search__gico svg { width: 12px; height: 12px; }
.tb-search__glabel {
  min-width: 0; font-family: var(--mono); font-size: var(--fs-2xs); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--t4);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-search__gn { margin-left: auto; font-size: var(--fs-2xs); color: var(--t4); font-variant-numeric: tabular-nums; }

.tb-search__row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center;
  gap: 10px; width: 100%; text-align: left; padding: 8px 10px;
  border: 0; border-radius: var(--rx-sm); background: none; color: var(--t1);
  font-family: inherit; font-size: var(--fs-sm); cursor: pointer;
  transition: background .12s, box-shadow .12s;
}
.tb-search__row:hover { background: var(--hover); }
/* Keyboard highlight. The agent's hue is a 2px edge, not a fill — a tinted
   row in four different hues would turn the panel into a paint chart. */
.tb-search__row.is-active { background: var(--hover); box-shadow: inset 2px 0 0 rgb(var(--dacc)); }
.tb-search__row:focus-visible { outline: 2px solid rgb(var(--dacc)); outline-offset: -2px; }
.tb-search__tx { min-width: 0; }
.tb-search__t {
  display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--t1);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-search__sub {
  display: block; margin-top: 1px; font-size: var(--fs-xs); color: var(--t4);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-search__when { font-size: var(--fs-xs); color: var(--t4); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tb-search__msg { padding: 16px 12px; font-size: var(--fs-sm); color: var(--t4); text-align: center; }

/* ---- waiting --------------------------------------------------------
   A search that keeps the previous results on screen is right about flicker
   and wrong about feedback: with nothing else moving it reads as frozen. So
   the panel gets a bar of its own and the stale rows step back, which says
   "this list is the last answer, a new one is coming" without throwing away
   the thing the user is still reading. */
.tb-search__panel::before {
  content: ""; position: sticky; top: -6px; z-index: 2; display: block;
  height: 2px; margin: -6px -6px 0; border-radius: var(--rx) var(--rx) 0 0;
  background: linear-gradient(90deg, transparent, rgb(var(--dacc, 90 120 255)), transparent);
  background-size: 40% 100%; background-repeat: no-repeat;
  opacity: 0; transition: opacity .12s;
}
.tb-search__panel.is-busy::before { opacity: 1; animation: tbSearchBar 1.1s var(--ease-out) infinite; }
.tb-search__panel.is-busy .tb-search__g,
.tb-search__panel.is-busy .tb-ask { opacity: .42; transition: opacity .15s; }
@keyframes tbSearchBar {
  0%   { background-position: -45% 0; }
  100% { background-position: 145% 0; }
}
@keyframes tbSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .tb-search__panel.is-busy::before { animation: none; background: rgb(var(--dacc, 90 120 255)); background-size: 100% 100%; }
}

/* T2 is seconds of model work, so it gets a stated wait rather than a bar. */
.tb-search__work { display: flex; align-items: center; gap: 10px; padding: 18px 14px; }
.tb-search__workspin {
  flex: none; width: 13px; height: 13px; border: 2px solid var(--hairline-hard);
  border-top-color: var(--acc); border-radius: 50%; animation: tbSpin .6s linear infinite;
}
.tb-search__worktx { min-width: 0; font-size: var(--fs-sm); color: var(--t3); }
.tb-search__worktx em {
  display: block; margin-top: 2px; font-style: normal; color: var(--t1);
  overflow-wrap: anywhere;      /* wrap the question rather than clip it — it is the subject */
}
@media (prefers-reduced-motion: reduce) { .tb-search__workspin { animation: none; } }

/* The "answer this across every job" row. It sits above the runs and is the
   Enter target, so it reads as the primary action without being a second
   button style — it is still a result row. */
.tb-search__row--ask { grid-template-columns: minmax(0, 1fr) auto; }
.tb-search__row--ask .tb-search__t { color: var(--acc); }
.tb-search__ent {
  flex: none; font-family: var(--mono); font-size: 10px; line-height: 1; color: var(--t4);
  background: var(--surface-sub); border: 1px solid var(--hairline); border-radius: var(--rx-xs);
  padding: 4px 6px;
}
.tb-search__row--ask.is-active .tb-search__ent { color: var(--acc); border-color: var(--acc-dim); }
.tb-search__foot {
  margin-top: 4px; padding: 8px 10px 4px; border-top: 1px solid var(--hairline-soft);
  font-size: var(--fs-xs); color: var(--t4);
}

/* T2 — the answer to a question, above the runs it was computed from. Given the weight of
   being the first thing read, but kept inside the same panel: it is a search result, not a chat. */
.tb-ask {
  padding: 12px 12px 10px; border-bottom: 1px solid var(--hairline);
  background: var(--surface-sub);
}
.tb-ask__a { font-size: var(--fs-sm); line-height: var(--lh-body); color: var(--t1); }
/* Provenance is deliberately legible rather than fine print: "12 runs matched, 10 recorded this
   figure" is the difference between a total and a total over part of the data. */
.tb-ask__prov { margin-top: 6px; font-size: var(--fs-xs); color: var(--t3); }
.tb-ask__caveat {
  margin-top: 6px; padding-left: 8px; border-left: 2px solid var(--warn-line);
  font-size: var(--fs-xs); color: var(--warn-fg); line-height: var(--lh-snug);
}

/* T3 — document hits. Run on demand, so the offer is a button rather than a silent extra call. */
.tb-search__docsbtn {
  display: block; width: 100%; margin-top: 4px; padding: 9px 10px;
  border: 0; border-top: 1px solid var(--hairline-soft); background: none;
  font: inherit; font-size: var(--fs-xs); font-weight: 600; color: var(--acc);
  text-align: left; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tb-search__docsbtn:hover:not(:disabled) { background: var(--acc-dim); }
.tb-search__docsbtn:disabled { color: var(--t4); cursor: default; }
.tb-search__row--doc { align-items: flex-start; }
.tb-search__pg {
  font-family: var(--mono); font-size: var(--fs-2xs); font-weight: 600; color: var(--t4);
}
/* The matched passage. Two lines is enough to judge relevance without turning the panel into a
   reader — the run itself is one click away. */
.tb-search__snip {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  margin-top: 2px; font-size: var(--fs-xs); line-height: var(--lh-snug); color: var(--t3);
  white-space: normal;
}

@media (max-width: 900px) {
  .tb-search__in { width: min(240px, 40vw); }
}
@media (max-width: 640px) {
  .tb-search__in { width: min(200px, 46vw); padding-right: 12px; }
  .tb-search__kbd { display: none; }
  .tb-search__panel { width: min(440px, 90vw); }
}

/* ============================================================
   PAGE HEADER + KPI STRIP
   ============================================================ */
.top {
  display: flex; align-items: flex-start; justify-content: space-between;
  margin-bottom: var(--sp-6); gap: var(--sp-4); flex-wrap: wrap;
}
.top__eyebrow {
  font-family: var(--mono); font-size: var(--fs-2xs); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--t4); margin-bottom: 7px;
}
.top h1 { font-size: var(--fs-2xl); font-weight: 650; letter-spacing: -0.03em; line-height: var(--lh-tight); }
.top .sub { font-size: var(--fs-md); color: var(--t3); margin-top: 6px; max-width: 68ch; line-height: var(--lh-snug); }
.top .btn--glow { flex: none; align-self: flex-start; }

/* KPI cards — separate floating tiles (the references' pattern) rather
   than one hairline-divided strip, so the numbers read as headline facts. */
.kpis {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(215px, 100%), 1fr));
  gap: var(--sp-3); margin-bottom: var(--sp-6);
}
/* Label first (with a glyph), figure second and large. Reading order matches
   how the tile is scanned: what am I looking at, then what is it. */
.kpi {
  --ktone: var(--mute-fg);
  display: block; width: 100%; text-align: left; font: inherit; cursor: default;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--rx); padding: 17px 19px 18px;
  transition: border-color .15s, box-shadow .15s;
}
.kpi__h { display: flex; align-items: center; gap: 9px; margin-bottom: var(--sp-3); }
.kpi__ico {
  flex: none; display: grid; place-items: center; width: 27px; height: 27px;
  border-radius: var(--rx-xs); color: var(--ktone);
  background: color-mix(in srgb, var(--ktone) 11%, transparent);
}
.kpi .k {
  font-size: var(--fs-sm); font-weight: 550; letter-spacing: -0.005em;
  text-transform: none; color: var(--t3); margin: 0;
  display: flex; align-items: center; gap: 6px; min-width: 0;
}
.kpi .k .kdot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.kpi .v {
  font-size: var(--fs-3xl); font-weight: 680; letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums; color: var(--t1); line-height: 1.05;
}
.kpi--link { cursor: pointer; }
.kpi--link:hover { border-color: var(--hairline-hard); box-shadow: var(--elev-2); }
.kpi--rev { --ktone: var(--warn-fg); }
.kpi--ok  { --ktone: var(--ok-fg); }
/* the contract dashboard's "Hard blocks" tile asks for this tone; without the rule it
   silently fell back to the muted default, so a blocking run looked like any other count */
.kpi--bad { --ktone: var(--bad-fg); }

/* ============================================================
   AGENT GALLERY — the console landing
   ============================================================ */
#galleryView:not([hidden]) { animation: viewin .35s var(--ease-out); }
.gal-hero { margin-bottom: var(--sp-5); }
.gal-hero h1 { font-size: var(--fs-2xl); font-weight: 650; letter-spacing: -0.03em; line-height: var(--lh-tight); }
.gal-hero .sub { font-size: var(--fs-md); color: var(--t3); margin-top: 6px; max-width: 68ch; line-height: var(--lh-snug); }

/* ---- field audits (agent #5) ------------------------------------------
   The list reuses .atbl and .st; only what a captured audit needs is new. */
.atbl__sub { display: block; margin-top: 3px; font-size: var(--fs-sm); color: var(--t3); }
.t4 { color: var(--t4); }

/* the header facts — a short, scannable strip, not a form */
/* Even columns, not content-width flex. The scope pane's two of these hold three and
   four short figures, and flex sized each one by its own value — so "Units 12" sat
   tight against "Absent 1" while "Date known 9" floated off on its own. A grid gives
   them one rhythm and costs nothing.
   --rx, not --rx-lg: 18px is for the big floating surfaces, and this is a strip inside
   a panel. Same correction as .aroom. */
.kvs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--sp-3) var(--sp-5);
  padding: 14px 16px; margin-bottom: var(--sp-4);
  border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface-sub);
}
.kvl { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.kvl span { font-size: var(--fs-2xs); letter-spacing: 0.06em; text-transform: uppercase; color: var(--t4); }
.kvl b { font-size: var(--fs-sm); font-weight: 600; color: var(--t1); }

/* ---- the trade band: "Lighting", "HVAC", "Water", "Other", "Photos" -------------
   These are not labels in a column of text. They are the BOUNDARIES between trades —
   separate equipment, separate reviewers, separate tables, separate CSV. The panel is
   one long scroll and they are the only thing telling you which trade you are in.

   Two earlier versions were wrong in opposite directions. First the class carried NO
   rule at all, so it fell back to inherited 14px/1.6 body copy with no bottom margin —
   the gap beneath "Lighting" was half of its own line box's leading, not a chosen
   space. Then it was set as the 11px faint uppercase micro-label, which is EXACTLY
   what .cpanel__h two lines above already is: three ranks of heading (panel, trade,
   room) all rendering alike, the trade name the quietest text in its own section. A
   heading that is smaller and lighter than the content under it is not a heading.

   So: a band, not a word. Full-bleed across the panel, ruled top and bottom, on the
   inset surface, title in ink at body size — it reads as a rule across the page, which
   is what a section break is. It ends in a count, so the band states what is in the
   section rather than only naming it. The rank now reads panel (faint caps) → trade
   (ink band) → room (quiet caps), each distinguishable without reading the words.

   Not sticky. It was, on the argument that fourteen rows in you lose track of the
   trade; the owner's call was that a header following you down the page is more
   intrusion than that is worth, and he is reading these panes and I am not. */
.psec__h {
  position: relative;
  display: flex; align-items: baseline; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4); background: var(--surface-sub);
  border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline);
  font-size: var(--fs-md); font-weight: 650; letter-spacing: -0.01em; text-transform: none;
  color: var(--t1); line-height: var(--lh-snug);
}
/* A marker on the panel's own edge. One accent used once, for one meaning — "a section
   starts here" — which is the brand colour earning its place rather than decorating.
   Because the band is full-bleed the bar lands on the panel edge, so scrolling the pane
   reads as a run of tabs rather than a wall of grey. */
.psec__h::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--acc);
}
/* The count that closes the band — the section's one-line summary. Faint and
   tabular so a column of them does not compete with the trade name. */
.psec__n {
  margin-left: auto; font-size: var(--fs-2xs); font-weight: 600; letter-spacing: .02em;
  color: var(--t4); font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* ---- ONE LEFT EDGE ---------------------------------------------------------------
   The spacing read as broken because the section had FOUR of them, none aligned: the
   accent bar on the panel edge (0), the band's title at the panel's 16px padding, the
   room card's border also at 16px, and the room name and every row at 16 + the card's
   own 14 = 30px. So the trade name and the content it introduced hung off different
   verticals, and the eye reads that as wrong before it reads any of the words.

   The cause was the room CARD. A bordered, rounded, inset box inside a panel that is
   already a bordered, rounded box buys nothing — it is a second frame around content
   that was never ambiguous about where it belonged — and it costs an indent that
   nothing else in the section shares. So the card is gone. The section is now a flat
   document: band, room, rows, all bled to the panel edge, all text on the same 16px
   vertical, separated by rules rather than by boxes and gaps.

   That also removes the two-greys problem — the tinted band is now the only filled
   surface in the pane, so it is unambiguously the section marker. */
.awork .psec__h, .awork .aroom, .awork .psec > .aline {
  margin-left: calc(var(--sp-4) * -1); margin-right: calc(var(--sp-4) * -1);
}
/* Rows butt straight onto the band's rule — that join is what makes the trade read as
   one block. Anything else (the scope pane's .kvs, a note, a table) is a separate
   object and still wants its gap. */
.awork .psec__h { margin-bottom: var(--sp-3); }
.awork .psec__h:has(+ .aroom), .awork .psec__h:has(+ .aline) { margin-bottom: 0; }
/* The first band sits flush under the panel header rather than floating below it with
   a second rule — one line between "FROM THE PHONE" and "Lighting", not two. */
.awork .psec:first-child > .psec__h { margin-top: calc(var(--sp-3) * -1); border-top: 0; }
/* Between trades: white space, then the next band's own rule. The band is drawn now,
   so it does not need 30px of air standing in for it as well. */
.awork .psec + .psec { margin-top: var(--sp-5); }

/* one room, then its lines. Grouped by space because that is how it was walked,
   and how anyone checking it against the building will read it. */
.aroom { margin-bottom: 0; }
/* The room is a divider inside the trade, not a competing heading — the rank it needs
   is "quieter than its rows, louder than nothing". Caps at the hint size do that
   without a second tinted bar, and it is the only label at this rank so there is
   nothing for it to blend into. Sentence case on a grey fill was reading as a card
   header, which is what it was, and that is what put the indent there. */
.aroom__h {
  padding: var(--sp-4) var(--sp-4) var(--sp-2);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--t4); line-height: var(--lh-snug);
}
/* The first room opens straight under the band, so it does not need the 16px that
   separates the later ones from the rows above them. */
.psec__h + .aroom > .aroom__h { padding-top: var(--sp-3); }
/* Rows hang off the same 16px as everything else (they were at 14 inside the card).
   line-height pinned: without it they inherited the body's 1.6, meant for prose, and
   a two-line row's internal leading came out wider than the gap meant to separate the
   note from the line it annotates. */
.aline {
  padding: 9px var(--sp-4); border-top: 1px solid var(--hairline-soft);
  font-size: var(--fs-sm); line-height: var(--lh-snug);
}
.aroom__h + .aline, .psec__h + .aline { border-top: 0; }
/* --fs-xs, the token whose job is "meta, captions, hints". It was --fs-sm: the note sat
   at exactly the size of the line it hangs off, so only colour ranked them. */
.aline__n { margin-top: var(--sp-1); font-size: var(--fs-xs); color: var(--t3); }

/* photos. Fixed-ratio tiles so a wide shot and a data plate line up, and a slot
   that is still uploading keeps its place rather than reflowing the grid later. */
.agrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--sp-3); }
/* A field photo is EVIDENCE — a reviewer clicks it to check a model number against what we
   transcribed, which a 90px square crop cannot settle. So the thumbnail advertises that it
   opens. */
.ashot { margin: 0; }
.ashot[data-open] { cursor: zoom-in; }
.ashot[data-open] .ashot__im { transition: box-shadow .12s ease, transform .12s ease; }
.ashot[data-open]:hover .ashot__im,
.ashot[data-open]:focus-visible .ashot__im {
  box-shadow: 0 0 0 2px var(--acc); transform: translateY(-1px);
}
.ashot[data-open]:focus-visible { outline: none; }

/* The lightbox. Fixed, above everything, and dismissible three ways (Esc, the backdrop,
   the button) because a viewer you cannot get out of is worse than no viewer. */
.lbx {
  position: fixed; inset: 0; z-index: 1000; display: flex;
  align-items: center; justify-content: center;
  background: rgba(8, 10, 14, .88); backdrop-filter: blur(3px);
}
.lbx__im {
  max-width: 92vw; max-height: 82vh; object-fit: contain;
  border-radius: var(--rx-md); box-shadow: 0 24px 64px rgba(0, 0, 0, .55);
}
.lbx__bar {
  position: absolute; top: 0; left: 0; right: 0; display: flex; align-items: center;
  gap: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  background: linear-gradient(rgba(8, 10, 14, .75), transparent);
}
.lbx__t { color: #fff; font-size: var(--fs-sm); font-weight: 600; margin-right: auto;
  text-transform: capitalize; }
.lbx__bar .t4 { color: rgba(255, 255, 255, .6); font-weight: 400; }
.lbx__bar .btn { background: rgba(255, 255, 255, .12); color: #fff;
  border-color: rgba(255, 255, 255, .25); text-decoration: none; }
.lbx__bar .btn:hover { background: rgba(255, 255, 255, .2); }
.lbx__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 44px; height: 64px; border: 0; cursor: pointer; color: #fff; font-size: 30px;
  line-height: 1; background: rgba(255, 255, 255, .1); border-radius: var(--rx-md);
}
.lbx__nav:hover { background: rgba(255, 255, 255, .2); }
.lbx__nav--l { left: max(12px, 2vw); }
.lbx__nav--r { right: max(12px, 2vw); }
@media (prefers-reduced-motion: reduce) {
  .ashot[data-open]:hover .ashot__im { transform: none; }
}
.ashot__im {
  aspect-ratio: 4 / 3; display: grid; place-items: center; overflow: hidden;
  border: 1px solid var(--hairline); border-radius: var(--rx-sm); background: var(--surface-sub);
}
.ashot__im img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ashot__im--wait { font-size: var(--fs-2xs); color: var(--t4); }
.ashot figcaption { margin-top: 6px; font-size: var(--fs-2xs); color: var(--t4); text-transform: capitalize; }

/* ---- field audit: two-pane workbench --------------------------------
   Same shape and chrome as the contract workbench (.cpanel), for the same reason: the job
   is comparing one side against the other. What came off the phone sits beside what we are
   handing back, so a reviewer can see whether we read a fixture right without scrolling
   between the two. Stacked, they are not comparable.

   Sized by flex against the viewport rather than growing with content — two panels that
   each scroll internally keep the header and the action button on screen while you work
   down either side. */
.awork {
  display: grid; gap: var(--sp-3); align-items: stretch;
  grid-template-columns: minmax(min(320px, 100%), 1fr) minmax(min(420px, 100%), 1.25fr);
  height: calc(100vh - 290px); min-height: 520px;
}
/* Below this the two panels are too narrow to compare anything, so stop pretending and
   let them stack and scroll with the page. */
@media (max-width: 1040px) {
  .awork { grid-template-columns: 1fr; height: auto; min-height: 0; }
  .awork .cpanel { height: auto; max-height: 70vh; }
}
.awork .cpanel__b { padding: var(--sp-3) var(--sp-4); }
/* The trade sections are the panel's content, so the first one should not add a second
   top margin under the panel header. */
.awork .psec:first-child, .psec--flush:first-child { margin-top: 0; }

/* The header block is read-once context; keep it compact so the panels get the height. */
.ares-top { margin-bottom: var(--sp-3); }
.ares-act { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }
/* The audit header strip — auditor, captured, last update, photos.
   It was the plain .kvs: `display:flex` with content-sized items, so on a full-width
   pane four short facts bunched into the left third and the gaps between them were set
   by how long the VALUES happened to be — a wide "RivetData (sample)" pushed CAPTURED
   far right, a one-character "—" pulled LAST UPDATE hard against it. Nothing lined up
   with anything, which is the ragged look.
   An even grid instead: each fact gets the same width, so the labels sit on a rhythm and
   the row still reads left to right. And no card — this is read-once context sitting
   directly above two panels whose own headers are tinted bands, and three stacked tinted
   surfaces was two too many. Hairlines above and below are enough to group it. */
/* A CARD, the same card as the two panels under it. Read the tokens before changing
   this: in light mode `--surface-sub` is #F7F8FA and `--canvas` is #F7F8FA — the SAME
   COLOUR. So anything tinted "inset" that sits directly on the page background is not a
   subtle surface, it is the page, and the border round it reads as an outline drawn on
   nothing. That is why this strip never looked like its own section, and no amount of
   spacing was going to fix it. (Inside a white panel the same tint works fine, which is
   why the panel headers and the trade bands are unaffected — the collision only bites on
   the canvas.)
   So: `--surface` white, the panel's own hairline, the panel's own radius and elevation.
   It now reads as a sibling of the Field audit and Scope sheet cards rather than as a
   hole in the page. */
.kvs--tight {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--sp-3) var(--sp-5);
  margin-bottom: var(--sp-3); padding: 14px var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--hairline); border-radius: var(--rx);
  box-shadow: var(--elev-1);
}

/* ---- scope sheet ------------------------------------------------------
   A dense read-only grid. Scrolls sideways rather than wrapping: these are
   short codes and descriptions, and a wrapped table of them is unreadable. */
.stbl { overflow-x: auto; border: 1px solid var(--hairline); border-radius: var(--rx-lg); }
.stbl table { border-collapse: collapse; width: 100%; font-size: var(--fs-sm); }
.stbl th, .stbl td { padding: 8px 12px; text-align: left; white-space: nowrap;
  border-top: 1px solid var(--hairline-soft); }
.stbl thead th {
  position: sticky; top: 0; background: var(--surface-sub); border-top: 0;
  font-size: var(--fs-2xs); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--t4); font-weight: 600;
}
/* The whole row is tinted, not just the flag cell — a reviewer scanning for what needs
   them should not have to read across to the last column to find out. */
.stbl--soft td { background: var(--acc-dim); }

/* An assumption, or outstanding research: stated once above the table rather than repeated
   down it. Ten identical per-row notes read as one and get skimmed together. */
.snote {
  margin: 0 0 var(--sp-3); padding: 11px 14px; font-size: var(--fs-sm);
  border: 1px solid var(--hairline); border-left: 3px solid var(--acc);
  border-radius: var(--rx-sm); background: var(--surface-sub); color: var(--t2);
}
.snote b { display: block; margin-bottom: 4px; font-size: var(--fs-2xs);
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--t4); }

/* Auditor-app card — phone widths only, see the note in console.html.
   Hidden by default at every width, so the [hidden] attribute still wins on a
   desktop; the media query only promotes it once JS has unhidden it. */
.fieldcard { display: none; }
@media (max-width: 640px) {
  .fieldcard:not([hidden]) {
    display: flex; align-items: center; gap: var(--sp-3);
    margin-bottom: var(--sp-4); padding: 14px;
    border: 1px solid var(--acc-line); border-radius: var(--rx-lg);
    background: var(--acc-dim); color: var(--t1); text-decoration: none;
  }
  .fieldcard__ico {
    flex: none; display: grid; place-items: center; width: 40px; height: 40px;
    border-radius: var(--rx-sm); color: #fff; background: var(--pri-bg);
  }
  .fieldcard__tx { min-width: 0; display: block; }
  .fieldcard__tx b { display: block; font-size: var(--fs-md); font-weight: 650; }
  .fieldcard__tx span { display: block; margin-top: 2px; font-size: var(--fs-sm); color: var(--t3); line-height: var(--lh-snug); }
  .fieldcard__go { flex: none; color: var(--t4); }
}

.gal-filter { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin: 22px 0 var(--sp-5); }
.gal-chip {
  font: inherit; font-size: var(--fs-sm); font-weight: 550; color: var(--t3);
  background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rx-pill);
  padding: 7px 15px; cursor: pointer; transition: color .15s, border-color .15s, background .15s;
  display: inline-flex; align-items: center; gap: 7px;
}
.gal-chip:hover { color: var(--t1); border-color: var(--acc-line); background: var(--hover); }
.gal-chip.is-on { color: var(--acc); border-color: var(--acc-line); background: var(--acc-dim); }
.gal-chip__n { font-family: var(--mono); font-size: var(--fs-2xs); color: var(--t4); }
.gal-chip.is-on .gal-chip__n { color: var(--acc); }

.gal-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(292px, 100%), 1fr)); gap: var(--sp-4); }
.gcard {
  position: relative; display: flex; flex-direction: column;
  border: 1px solid var(--hairline); border-radius: var(--rx-lg);
  background: var(--surface); padding: 24px 24px 20px; box-shadow: var(--elev-1);
  overflow: hidden; transition: transform .18s var(--ease-out), border-color .18s, box-shadow .18s, opacity .18s;
}
.gcard--live { cursor: pointer; }
.gcard--live:hover {
  transform: translateY(-2px); border-color: rgba(var(--dacc), 0.40); box-shadow: var(--elev-2);
}
.gcard--live:focus-visible { outline: 2px solid rgb(var(--dacc)); outline-offset: 2px; }
.gcard--soon { opacity: .78; background: var(--surface-sub); box-shadow: none; }
.gcard--soon:hover { opacity: .95; }
.gcard__ico {
  width: 40px; height: 40px; border-radius: var(--rx-sm); display: grid; place-items: center;
  color: rgb(var(--dacc)); background: rgba(var(--dacc), 0.11);
  border: 1px solid rgba(var(--dacc), 0.22); margin-bottom: 15px;
}
.gcard__title { font-size: var(--fs-lg); font-weight: 680; letter-spacing: -0.025em; color: var(--t1); }
.gcard__tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 9px 0 var(--sp-3); }
.gtag {
  font-size: var(--fs-2xs); font-weight: 600; letter-spacing: .01em; padding: 3px 9px;
  border-radius: var(--rx-pill); color: rgb(var(--dacc));
  background: rgba(var(--dacc), 0.11); border: 1px solid rgba(var(--dacc), 0.22);
}
.gtag--muted { color: var(--t4); background: transparent; border-color: var(--hairline); }
.gtag--live { color: var(--ok-fg); background: var(--ok-bg); border-color: var(--ok-line); }
.gtag--live::before {
  content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--ok-fg); margin-right: 5px; vertical-align: middle; box-shadow: 0 0 0 3px var(--ok-bg);
}
.gcard__desc { font-size: var(--fs-sm); color: var(--t3); line-height: var(--lh-body); flex: 1; }
.gcard__foot {
  margin-top: var(--sp-4); padding-top: 13px; border-top: 1px solid var(--hairline-soft);
  display: flex; align-items: center;
}
.gcard__launch {
  font-size: var(--fs-sm); font-weight: 600; color: rgb(var(--dacc));
  display: inline-flex; align-items: center; gap: 6px;
}
.gcard__launch svg { transition: transform .18s var(--ease-out); }
.gcard--live:hover .gcard__launch svg { transform: translateX(3px); }
.gcard__soon {
  font-size: var(--fs-2xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  font-family: var(--mono); color: var(--t4);
}
.gal-empty { color: var(--t4); font-size: var(--fs-sm); padding: 30px 4px; }

/* ============================================================
   VIEW TRANSITIONS + SHARED SURFACES
   ============================================================ */
#homeView:not([hidden]), #intakeView:not([hidden]), #resultView:not([hidden]),
#pHomeView:not([hidden]), #pIntakeView:not([hidden]), #pResultView:not([hidden]) {
  animation: viewin .35s var(--ease-out);
}
@keyframes viewin { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

.step {
  border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface);
  padding: clamp(20px, 2.4vw, 28px); margin-bottom: var(--sp-4);
}
.step--bare, .step--bare:hover { border: 0; background: none; padding: 0; box-shadow: none; }

/* ---- pagination ---- */
.pager {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  padding: 12px 18px; background: var(--surface);
  border: 1px solid var(--hairline); border-top: 1px solid var(--hairline-soft);
  border-radius: 0 0 var(--rx) var(--rx);
}
.pager__info { font-family: var(--mono); font-size: var(--fs-xs); color: var(--t4); }
.pager__btns { display: flex; gap: var(--sp-2); }
.pager__btns .btn[disabled] { opacity: .35; }

/* ---- loading skeleton ---- */
.sk-row {
  height: 46px; border-radius: var(--rx-sm); margin: 5px 0;
  background: linear-gradient(100deg, var(--surface-sub) 40%, var(--mute-bg) 50%, var(--surface-sub) 60%);
  background-size: 200% 100%; animation: skshine 1.2s linear infinite;
}
@keyframes skshine { to { background-position: -200% 0; } }

/* ============================================================
   INTAKE — work surface left, sticky run rail right
   ============================================================ */
.intake { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--sp-5); align-items: start; }
.pane {
  border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface);
  padding: clamp(22px, 2.6vw, 32px); box-shadow: var(--elev-1);
}
.psec + .psec { margin-top: 30px; }
.psec > .elig__section { margin-top: 0; }
.fgrid { display: grid; gap: var(--sp-4); margin-bottom: 18px; }
@media (min-width: 900px) { .fgrid { grid-template-columns: 1fr 1fr; } }
/* 3-up variant: Financials | donut | Scope — the chart sits in the centre column between the tables. */
@media (min-width: 900px) { .fgrid--3 { grid-template-columns: 1fr auto 1fr; } }
.fgrid .fld { margin-bottom: 0; }

/* ---- fields ---- */
.fld { display: block; margin-bottom: 18px; }
.fld:last-child { margin-bottom: 0; }
.fld > span {
  display: flex; align-items: center; gap: 6px; font-size: var(--fs-sm);
  font-weight: 550; color: var(--t2); margin-bottom: 7px;
}
/* Matched by EXCLUSION, not by listing the types we happen to use today. The old rule
   enumerated text and number, so the first `type=date` added to a form rendered as a raw
   browser control in the middle of a styled one. A list like that is only ever correct
   until the next field type. Checkboxes, radios and file inputs keep their own chrome. */
.fld input:not([type=checkbox]):not([type=radio]):not([type=file]), .fld select {
  width: 100%; padding: 11px 14px; border: 1px solid var(--hairline-hard);
  border-radius: var(--rx-sm); background: var(--surface); color: var(--t1);
  font: inherit; font-size: var(--fs-md); transition: border-color .15s, box-shadow .15s;
}
.fld input:not([type=checkbox]):not([type=radio]):not([type=file])::placeholder { color: var(--t4); }
.fld input:not([type=checkbox]):not([type=radio]):not([type=file]):focus, .fld select:focus {
  outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim);
}
/* A date input still ships its own typeface and a black calendar glyph. Both have to be
   overridden explicitly — inheriting `font` does not reach the mm/dd/yyyy segments. */
.fld input[type=date] { font-family: var(--sans); min-height: 45px; }
.fld input[type=date]::-webkit-datetime-edit { color: var(--t1); }
.fld input[type=date]:invalid::-webkit-datetime-edit { color: var(--t4); }
.fld input[type=date]::-webkit-calendar-picker-indicator {
  opacity: .45; cursor: pointer; transition: opacity .15s;
}
.fld input[type=date]::-webkit-calendar-picker-indicator:hover { opacity: .9; }
.fld select {
  cursor: pointer; -webkit-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2300000080' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
  background-repeat: no-repeat; background-position: right 12px center; padding-right: 36px;
}
.fld select:required:invalid { color: var(--t4); }

/* Same iOS focus-zoom trap as the auditor app: Safari zooms the page in on any focused
   control under 16px and does not reliably zoom back out. Scoped to touch input so the
   desktop type scale is untouched — this is a phone behaviour, not a design change. */
@media (pointer: coarse) {
  .fld input:not([type=checkbox]):not([type=radio]):not([type=file]),
  .fld select, .fld textarea, .tbl-search input, .gate__email { font-size: 16px; }
}
/* The checklist report is stored before the open-ended read finishes, and that read
   decides what is published — so for those minutes every number on the page is
   provisional. Saying so is cheaper than someone acting on a count that is about to
   drop by most of its value. */
.c-prov {
  margin-bottom: var(--sp-4); padding: 10px 14px; border-radius: var(--rx-sm);
  background: var(--warn-bg); border: 1px solid var(--warn-line);
  color: var(--t2); font-size: var(--fs-sm); line-height: var(--lh-snug);
}

/* The finding count beside the issue count: present, subordinate. Issues are the work;
   findings are the evidence under them, and approvals are still per finding. */
.cnt-chip--sub {
  background: transparent; border-color: transparent; color: var(--t4);
  font-weight: 400; cursor: default;
}

/* A REVIEW ISSUE — one decision, with the clauses it rests on and its evidence folded
   away underneath. This is the row a reviewer reads; the findings below it are the
   working-out, open only when somebody wants the quotes. */
.c-iss {
  border: 1px solid var(--hairline); border-radius: var(--rx-sm);
  padding: var(--sp-4); margin-bottom: var(--sp-3); background: var(--surface);
}
.c-iss--block { border-left: 3px solid var(--bad-fg); }
.c-iss__h { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; }
.c-iss__n {
  font-size: var(--fs-2xs); font-weight: 700; color: var(--t4);
  min-width: 18px; font-variant-numeric: tabular-nums;
}
.c-iss__t { font-weight: 650; color: var(--t1); font-size: var(--fs-sm); flex: 1 1 320px; }
.c-iss__x {
  margin-top: 7px; font-size: var(--fs-sm); color: var(--t2); line-height: var(--lh-normal);
}
.c-iss__a { margin-top: 7px; font-size: var(--fs-sm); color: var(--t2); }
.c-iss__cls { margin-top: 9px; display: flex; flex-wrap: wrap; gap: 6px; }
.c-iss__cl {
  font-size: var(--fs-2xs); font-family: var(--mono, ui-monospace, monospace);
  color: var(--t3); background: var(--surface-sub); border: 1px solid var(--hairline);
  border-radius: 4px; padding: 2px 7px;
}
.c-iss__cl i { font-style: normal; color: var(--t4); }
.c-iss__ev { margin-top: 10px; }
.c-iss__ev > summary {
  cursor: pointer; list-style: none; font-size: var(--fs-xs); color: var(--t4);
  padding: 4px 0; user-select: none;
}
.c-iss__ev > summary::-webkit-details-marker { display: none; }
.c-iss__ev > summary::before { content: "+ "; font-weight: 700; }
.c-iss__ev[open] > summary::before { content: "\2212 "; }
.c-iss__ev > summary:hover { color: var(--t3); }
.c-iss__evb { border-top: 1px solid var(--hairline); padding-top: var(--sp-3); margin-top: 4px; }

/* Coverage behind the report: the checklist items that were looked at and did not need
   a person. Deliberately quiet — this is evidence of thoroughness, not a second list of
   problems competing with the first. */
.c-obs { margin: var(--sp-3) 0 0; }
.c-obs > summary {
  cursor: pointer; list-style: none; font-size: var(--fs-xs); color: var(--t4);
  padding: 7px 0; user-select: none;
}
.c-obs > summary::-webkit-details-marker { display: none; }
.c-obs > summary::before { content: "+ "; font-weight: 700; }
.c-obs[open] > summary::before { content: "\2212 "; }
.c-obs > summary:hover { color: var(--t3); }
.c-obs__b { border-top: 1px solid var(--hairline); padding-top: var(--sp-2); }
.c-obs__i {
  font-size: var(--fs-xs); color: var(--t3); line-height: var(--lh-snug);
  padding: 6px 0; border-bottom: 1px solid var(--hairline);
}
.c-obs__i:last-child { border-bottom: 0; }
.c-obs__s { font-weight: 600; color: var(--t2); margin-right: 8px; }

/* A field the form is refusing. Used by the DN guard and by the programme check, both
   of which focus the field as well — the outline is for finding it again after you have
   scrolled, not for the first moment. */
.fld input.is-bad, .fld select.is-bad, input.is-bad, select.is-bad {
  border-color: var(--bad-fg);
  box-shadow: 0 0 0 3px var(--bad-bg);
}

/* A line under a field saying where its value came from. Quiet by default; the field
   itself turns red when the answer is a refusal, so this does not need to shout. */
.fld-note { display: block; margin-top: 6px; font-size: var(--fs-xs); color: var(--t3);
  line-height: var(--lh-snug); }
.fld-opt { font-style: normal; font-weight: 400; color: var(--t4); font-size: var(--fs-xs); }
/* "required" has to read differently from "optional" at a glance, or the label change is
   invisible and people keep skipping the field. Same size, more weight, body colour
   rather than the muted grey — a statement, not an aside. */
.fld-req { font-style: normal; font-weight: 600; color: var(--t2); font-size: var(--fs-xs); }
.elig__section .fld-opt { font-size: inherit; }
.fld-hint { display: block; font-size: var(--fs-xs); color: var(--t4); line-height: var(--lh-snug); margin-top: 6px; }
/* keep the datalist type-ahead but drop Chrome's chevron */
input[list]::-webkit-calendar-picker-indicator { display: none !important; }

/* info tooltip */
.fld-tip {
  position: relative; flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; border: 1px solid var(--hairline-hard); border-radius: 50%;
  color: var(--t4); font-size: 10px; font-style: normal; font-weight: 700; line-height: 1;
  cursor: help; user-select: none; transition: color .15s, border-color .15s;
}
.fld-tip:hover, .fld-tip:focus-visible { color: var(--t1); border-color: var(--t3); outline: none; }
.fld-tip::after {
  content: attr(data-tip); position: absolute; left: 50%; bottom: calc(100% + 9px);
  transform: translateX(-50%); width: max-content; max-width: 230px; padding: 8px 11px;
  border-radius: var(--rx-sm); background: var(--t1); color: var(--surface);
  font-size: var(--fs-xs); font-weight: 500; font-style: normal; line-height: var(--lh-snug);
  text-align: left; white-space: normal; box-shadow: var(--elev-3);
  opacity: 0; visibility: hidden; transition: opacity .14s ease, visibility .14s; z-index: 60; pointer-events: none;
}
.fld-tip::before {
  content: ""; position: absolute; left: 50%; bottom: calc(100% + 4px); transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: var(--t1);
  opacity: 0; visibility: hidden; transition: opacity .14s ease, visibility .14s; z-index: 60; pointer-events: none;
}
.fld-tip:hover::after, .fld-tip:hover::before,
.fld-tip:focus-visible::after, .fld-tip:focus-visible::before { opacity: 1; visibility: visible; }

/* ---- run rail ----
   NB: `.rail` here is the intake flow's sticky run summary (an <aside> inside
   .intake), NOT the left navigation — that is `.sidebar`, in console-base.css. */
.rail { position: sticky; top: var(--sp-1); }
/* The run rail is a card like any other: a header band, then its contents.
   The header bleeds to the card edges via a negative inline margin that cancels
   the card's side padding, so it lines up with .cpanel__h and .atbl__head. */
.rail__card {
  border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface);
  overflow: hidden; padding: 0 var(--sp-5) var(--sp-5);
}
.rail__h {
  display: flex; align-items: center; gap: var(--sp-3);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--t4);
  margin: 0 calc(var(--sp-5) * -1) var(--sp-5);
  padding: 13px var(--sp-5); background: var(--surface-sub); border-bottom: 1px solid var(--hairline);
}
.rail__list { list-style: none; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.rail__list li { display: flex; align-items: flex-start; gap: 9px; font-size: var(--fs-sm); color: var(--t4); line-height: var(--lh-snug); }
.rail__list li i {
  flex: none; width: 16px; height: 16px; margin-top: 1px; border-radius: 50%;
  border: 1.5px solid var(--hairline-hard); display: grid; place-items: center;
  font-style: normal; transition: border-color .2s, background .2s;
}
.rail__list li.ok { color: var(--t2); }
.rail__list li.ok i { border-color: var(--ok-line); background: var(--ok-bg); }
.rail__list li.ok i::after { content: "✓"; font-size: 9px; font-weight: 700; color: var(--ok-fg); }
/* A checklist line that is not an error but must not read as "fine either". Used when a
   Multifamily package is about to be generated with no utility bill: the form comes out looking
   complete with its customer and utility rows blank, which a grey note did not convey. */
.rail__list li.warn { color: var(--warn-fg); }
.rail__list li.warn i { border-color: var(--warn-line); background: var(--warn-bg); }
.rail__list li.warn i::after { content: "!"; font-size: 10px; font-weight: 700; color: var(--warn-fg); }
.rail .run-stages { max-width: none; }
.rail__note {
  font-size: var(--fs-xs); color: var(--t4); line-height: var(--lh-body);
  margin-top: 14px; padding-top: 13px; border-top: 1px solid var(--hairline-soft);
}
/* Standalone callout (e.g. a partial-draft package): amber card, no top rule. */
.rail__note--warn {
  color: var(--warn-fg); background: var(--warn-bg); border: 1px solid var(--warn-line);
  border-radius: var(--rx-lg); padding: 12px 14px; margin-top: 16px;
}
@media (max-width: 1000px) { .intake { grid-template-columns: 1fr; } .rail { position: static; } }

/* ---- upload ---- */
.drop {
  border: 1.5px dashed var(--hairline-hard); border-radius: var(--rx-lg);
  padding: clamp(30px, 4vw, 44px) var(--sp-6); text-align: center; cursor: pointer;
  transition: border-color .2s, background .2s; background: var(--surface-sub);
}
.drop:hover { border-color: var(--acc); background: var(--acc-dim); }
.drop.drag { border-color: var(--acc); background: var(--acc-dim); }
.drop__ico {
  width: 48px; height: 48px; margin: 0 auto 14px; border-radius: var(--rx);
  display: grid; place-items: center; color: var(--acc); background: var(--acc-dim);
  border: 1px solid var(--acc-line); transition: transform .25s var(--ease-out);
}
.drop:hover .drop__ico, .drop.drag .drop__ico { transform: translateY(-2px); }
.drop h2 { font-size: var(--fs-lg); font-weight: 650; letter-spacing: -0.02em; }
.drop p { color: var(--t3); font-size: var(--fs-md); margin-top: 6px; max-width: none; }

.rows { display: flex; flex-direction: column; gap: var(--sp-2); }
#uploadList { margin-top: var(--sp-4); }
.up-row {
  display: grid; grid-template-columns: 1fr 120px 90px 22px; align-items: center; gap: var(--sp-3);
  border: 1px solid var(--hairline); border-radius: var(--rx-sm);
  background: var(--surface); padding: 13px var(--sp-4); font-size: var(--fs-sm);
}
.up-x {
  border: 0; background: none; color: var(--t4); font-size: var(--fs-md); line-height: 1;
  padding: 2px; border-radius: var(--rx-xs); cursor: pointer; visibility: hidden;
}
.up-row.is-done .up-x { visibility: visible; }
.up-x:hover { color: var(--bad-fg); background: var(--hover); }
.up-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.up-prog { height: 5px; border-radius: var(--rx-pill); background: var(--mute-bg); overflow: hidden; }
.up-prog i { display: block; height: 100%; width: 0; background: var(--acc); border-radius: var(--rx-pill); transition: width .25s; }
.up-prog i.is-indet { transition: none; animation: upindet 1.1s ease-in-out infinite; }
@keyframes upindet { 0% { margin-left: -45%; } 100% { margin-left: 100%; } }
.up-state { text-align: right; color: var(--t3); font-family: var(--mono); font-size: var(--fs-2xs); }
.up-state--err { color: var(--bad-fg); }
.up-state--ok { color: var(--ok-fg); }
/* Contract intake takes many files (base + exhibits), ordered + combined server-side. */
#cUploadList:not(:empty) { margin-top: 14px; }
/* E.2 labeled upload: a document-type select sits after the name. */
#cUploadList .up-row { grid-template-columns: auto minmax(0, 1fr) 150px 110px 80px auto 22px; }
.up-ord { color: var(--t4); font-family: var(--mono); font-size: var(--fs-2xs); min-width: 15px; }
.up-move { display: inline-flex; gap: 3px; }
.up-up, .up-dn {
  border: 1px solid var(--hairline); background: var(--surface); color: var(--t3);
  width: 21px; height: 21px; line-height: 1; border-radius: var(--rx-xs);
  cursor: pointer; font-size: var(--fs-2xs); padding: 0;
}
.up-up:hover:not(:disabled), .up-dn:hover:not(:disabled) { color: var(--t1); border-color: var(--acc-line); background: var(--hover); }
.up-up:disabled, .up-dn:disabled { opacity: .35; cursor: default; }

/* ---- entity flags as segmented pills ---- */
.chks { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chk {
  position: relative; display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: 8px 15px; border: 1px solid var(--hairline-hard); border-radius: var(--rx-pill);
  background: var(--surface); cursor: pointer; font-size: var(--fs-sm); color: var(--t2);
  transition: border-color .15s, background .15s, color .15s;
}
.chk::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--hairline-hard); transition: background .15s; }
.chk input { position: absolute; opacity: 0; pointer-events: none; }
.chk:hover { border-color: var(--acc-line); color: var(--t1); }
.chk:has(input:checked) { border-color: var(--acc-line); background: var(--acc-dim); color: var(--t1); }
.chk:has(input:checked)::before { background: var(--acc); }
.chk:has(input:focus-visible) { outline: 2px solid var(--acc); outline-offset: 2px; }

/* descriptive opt-in rows */
.psec__hint { font-size: var(--fs-sm); color: var(--t3); margin: -4px 0 var(--sp-3); line-height: var(--lh-snug); }
.chkrow {
  display: flex; gap: 11px; align-items: flex-start; padding: var(--sp-3) 14px;
  border: 1px solid var(--hairline-hard); border-radius: var(--rx); background: var(--surface);
  cursor: pointer; transition: border-color .15s, background .15s;
}
.chkrow + .chkrow { margin-top: 10px; }
.chkrow:hover { border-color: var(--acc-line); }
.chkrow:has(input:checked) { border-color: var(--acc-line); background: var(--acc-dim); }
.chkrow:has(input:focus-visible) { outline: 2px solid var(--acc); outline-offset: 2px; }
.chkrow input { margin: 1px 0 0; width: 16px; height: 16px; accent-color: var(--acc); flex: 0 0 auto; cursor: pointer; }
.chkrow__t { font-size: var(--fs-md); color: var(--t1); font-weight: 600; }
.chkrow__d { font-size: var(--fs-sm); color: var(--t3); margin-top: 3px; line-height: var(--lh-snug); }

/* ---- run controls ---- */
.run-hint { display: block; margin-top: var(--sp-3); font-size: var(--fs-sm); color: var(--t4); }
.run-hint--live { color: var(--acc); font-family: var(--mono); font-size: var(--fs-xs); }
#runBtn { display: inline-flex; align-items: center; justify-content: center; }
.run-bar { height: 4px; max-width: 340px; margin-top: 14px; border-radius: var(--rx-pill); background: var(--mute-bg); overflow: hidden; }
.run-bar i { display: block; height: 100%; width: 38%; border-radius: var(--rx-pill); background: var(--acc); animation: runbar 1.15s ease-in-out infinite; }
@keyframes runbar { 0% { transform: translateX(-110%); } 100% { transform: translateX(280%); } }
.spinner {
  width: 15px; height: 15px; border: 2px solid var(--acc-line); border-top-color: var(--acc);
  border-radius: 50%; animation: spin .7s linear infinite; display: inline-block;
  vertical-align: -2px; margin-right: var(--sp-2);
}
@keyframes spin { to { transform: rotate(360deg); } }

.run-stages { list-style: none; margin: var(--sp-4) 0 0; padding: 0; display: flex; flex-direction: column; gap: 7px; max-width: 420px; }
/* Two columns: bullet, then text — so a long stage label wraps its TEXT inside its
   own column instead of jumping below the bullet, and the sub-label lands under the
   text. (This was briefly `display:flex` + `flex-wrap:wrap`, which wrapped the label
   as a whole item and left a lone dot on the line above.) */
.run-stages li {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  column-gap: 10px; row-gap: 3px; align-items: center;
  font-size: var(--fs-sm); color: var(--t4); transition: color .3s;
}
.run-stages li .rs-i {
  flex: none; width: 18px; height: 18px; border-radius: 50%;
  border: 1.5px solid var(--hairline-hard); display: grid; place-items: center; transition: border-color .3s;
}
.run-stages li.is-active { color: var(--t1); }
.run-stages li.is-active .rs-i { border-color: var(--acc); }
.run-stages li.is-active .rs-i::after {
  content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--acc);
  animation: rspulse 1.1s ease-in-out infinite;
}
@keyframes rspulse { 0%, 100% { transform: scale(0.7); opacity: .6; } 50% { transform: scale(1); opacity: 1; } }
.run-stages li.is-done { color: var(--t3); }
.run-stages li.is-done .rs-i { border-color: var(--ok-line); background: var(--ok-bg); }
/* Sub-label under the active stage: page counter and time estimate. */
.rs-sub {
  grid-column: 2;      /* under the label, not under the bullet */
  font-size: var(--fs-xs); color: var(--t4); font-variant-numeric: tabular-nums;
}
.run-stages li.is-done .rs-i::after { content: "✓"; font-size: 10px; font-weight: 700; color: var(--ok-fg); }

/* ============================================================
   ASSESSMENT RESULT — the "dossier" card
   ============================================================ */
/* Frozen header — toolbar + approval bar + summary stay pinned. */
/* Same correction as .pj-sticky below: 20 ties with .topbar and wins on DOM order, so
   the account menu — stuck inside the topbar's stacking context — can never paint above
   it however high its own z-index goes. This panel only needs to clear its own content. */
.pnl-sticky { position: sticky; top: 0; z-index: 5; background: var(--canvas); padding-bottom: 18px; }
.pnl-sticky::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 100%;
  height: var(--shell-pad); background: var(--canvas);
}
.sum {
  border: 1px solid var(--hairline); border-radius: var(--rx-lg);
  background: var(--surface); overflow: hidden; box-shadow: var(--elev-1);
}
.sum__head {
  position: relative; display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--sp-4); flex-wrap: wrap; padding: var(--sp-6) var(--sp-6) 22px;
}
.sum__head .who { font-size: var(--fs-2xl); font-weight: 650; letter-spacing: -0.03em; line-height: var(--lh-tight); }
.sum__head .addr { font-size: var(--fs-md); color: var(--t3); margin-top: 6px; }
.tier { display: inline-flex; flex-direction: column; align-items: flex-end; }
.tier .badge {
  font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.02em; padding: 8px 19px;
  border-radius: var(--rx-sm); color: var(--ok-fg); background: var(--ok-bg); border: 1px solid var(--ok-line);
}
.tier .badge.na { color: var(--t3); background: var(--mute-bg); border-color: var(--hairline); }
.tier .cap {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--t4); margin-bottom: 6px;
}
.sum__metrics {
  display: grid; grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--hairline); background: var(--surface-sub);
}
/* Same reading order as the dashboard KPI tiles: label, then the figure. */
.sm { padding: 16px var(--sp-6) 18px; border-left: 1px solid var(--hairline); min-width: 0; }
.sm:first-child { border-left: 0; }
.sm .k {
  font-size: var(--fs-2xs); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--t4); margin: 0 0 7px;
}
.sm .v { font-size: var(--fs-2xl); font-weight: 680; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; line-height: 1.1; }
@media (max-width: 640px) {
  .sum__metrics { grid-template-columns: 1fr; }
  .sm { border-left: 0; border-top: 1px solid var(--hairline-soft); }
  .sm:first-child { border-top: 0; }
}

/* rule-style section labels — the result reads like a filed document */
/* Section label between cards. Same uppercase micro-label as every table header
   in the console, so the result page and the dashboards share one vocabulary. */
.elig__section {
  display: flex; align-items: center; gap: var(--sp-3);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--t4); margin: var(--sp-8) 0 var(--sp-3);
}

/* ...but when the section introduces a TABLE, it becomes that table's card
   header instead of a floating label above a boxed grid — title inside the
   card, sentence case, with a glyph tile. Joined to the table below by sharing
   the surface and dropping the adjoining edge. */
.elig__section:has(+ .srctbl),
.elig__section:has(+ .fee-tbl) {
  margin: var(--sp-8) 0 0; padding: 16px var(--sp-5) 15px;
  font-size: var(--fs-lg); font-weight: 650; letter-spacing: -0.02em; text-transform: none;
  color: var(--t1);
  background: var(--surface); border: 1px solid var(--hairline); border-bottom: 0;
  border-radius: var(--rx) var(--rx) 0 0;
}
/* Inside a .psec the wrapper already supplies the outer spacing, so the joined
   header must not add its own on top (the plain .psec > .elig__section rule
   ties with the :has() rules on specificity, so state it explicitly). */
.psec > .elig__section:has(+ .srctbl),
.psec > .elig__section:has(+ .fee-tbl) { margin-top: 0; }

.elig__section:has(+ .srctbl)::before,
.elig__section:has(+ .fee-tbl)::before {
  content: ""; flex: none; width: 28px; height: 28px; border-radius: var(--rx-xs);
  background: var(--surface-sub); border: 1px solid var(--hairline);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%235C6675' stroke-width='1.9' stroke-linecap='round'><path d='M3 6h18M3 12h18M3 18h18'/></svg>");
  background-repeat: no-repeat; background-position: center;
}

.flags { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)); gap: var(--sp-2); }
/* Label left, verdict pill right, ALWAYS on one line. This used to wrap, so a
   long label ("Overburdened Community") pushed its pill onto a second row and
   made that card taller than the ones beside it. The label wraps internally
   instead; the pill never shrinks and never moves. */
.flag {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  border: 1px solid var(--hairline); border-radius: var(--rx-sm);
  background: var(--surface); padding: 14px 16px;
}
.flag .fl-k { font-size: var(--fs-sm); color: var(--t2); min-width: 0; line-height: var(--lh-snug); }
.flag .fl-v {
  flex: none; white-space: nowrap;
  font-size: var(--fs-2xs); font-weight: 700; padding: 3px 10px; border-radius: var(--rx-pill);
  color: var(--t4); background: var(--mute-bg); border: 1px solid var(--hairline);
}
.flag.on { border-color: var(--ok-line); background: var(--ok-bg); }
.flag.on .fl-k { color: var(--t1); font-weight: 600; }
.flag.on .fl-v { color: var(--ok-fg); background: var(--surface); border-color: var(--ok-line); }

/* min() keeps the track from ever being wider than the container: a bare
   minmax(300px,1fr) floors each track at the item's min-content width, which
   let a long account number push the whole grid past the page. */
.util2 {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: var(--sp-3);
}
/* Utility breakdown card — header band, then rows, matching the table cards. */
.util {
  border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface);
  overflow: hidden; min-width: 0;
}
.util .u-h {
  display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); font-weight: 650;
  margin: 0; padding: 12px var(--sp-4); background: var(--surface-sub);
  border-bottom: 1px solid var(--hairline);
}
.util .u-h .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--acc); flex: none; }
.util .u-h .dot.gas { background: var(--warn-fg); }
.util .u-h .dot.mix { background: linear-gradient(135deg, #0E9E67, #2a78d6); }
/* the centre chart column: header at top, donut+legend vertically centred in the remaining space */
.util--chart { display: flex; flex-direction: column; }
.util--chart .cost-donut--col { flex: 1; }
/* One padding declaration per element — no shorthand after a longhand. */
.util .u-row {
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-4);
  min-width: 0; padding: 11px var(--sp-4);
  border-top: 1px solid var(--hairline-soft); font-size: var(--fs-sm);
}
.util .u-row:first-of-type { border-top: 0; }
.util .u-row .u-k { color: var(--t3); min-width: 0; }
.util .u-row .u-v {
  color: var(--t1); font-weight: 600; text-align: right; font-family: var(--mono);
  font-size: var(--fs-xs); min-width: 0; overflow-wrap: anywhere;
}
.util .u-add {
  font-size: var(--fs-xs); color: var(--t4); padding: 0 var(--sp-4) var(--sp-3);
  overflow-wrap: anywhere;
}
.util .u-add b { color: var(--t2); font-weight: 600; }

.notice {
  display: flex; align-items: flex-start; gap: 10px; border: 1px solid var(--warn-line);
  background: var(--warn-bg); border-radius: var(--rx-sm); padding: 11px 14px;
  font-size: var(--fs-sm); color: var(--t1); margin-bottom: var(--sp-2);
}
.notice svg { flex: none; margin-top: 1px; color: var(--warn-fg); }

.cov { font-size: var(--fs-2xs); font-weight: 600; padding: 3px 10px; border-radius: var(--rx-pill); white-space: nowrap; }
.cov--full { color: var(--ok-fg); background: var(--ok-bg); border: 1px solid var(--ok-line); }
.cov--part { color: var(--warn-fg); background: var(--warn-bg); border: 1px solid var(--warn-line); }
.covstrip { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: var(--sp-3); }

/* ---- source table ---- */
/* The card's body. Horizontal padding lives here, so the header band and the
   row rules are inset from the card edge rather than running into it — that
   inset is most of what separates a designed table from a bordered box. */
.srctbl {
  border: 1px solid var(--hairline); border-top: 0; border-radius: 0 0 var(--rx) var(--rx);
  overflow-x: auto; background: var(--surface); padding: 0 var(--sp-4) var(--sp-2);
}
/* `separate` so the head band's rounded corners actually render. */
.srctbl table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--fs-sm); }
.srctbl th {
  text-align: left; font-size: var(--fs-2xs); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--t4); font-weight: 600; padding: 11px var(--sp-3); white-space: nowrap;
  background: var(--surface-sub); border: 0;
}
.srctbl th:first-child { border-radius: var(--rx-xs) 0 0 var(--rx-xs); }
.srctbl th:last-child  { border-radius: 0 var(--rx-xs) var(--rx-xs) 0; }
.srctbl td {
  padding: 17px var(--sp-3); border-bottom: 1px solid var(--hairline-soft);
  color: var(--t1); vertical-align: middle;
}
.srctbl tbody tr { transition: background .15s; }
.srctbl tbody tr:hover { background: var(--hover); }
.srctbl tbody tr:last-child td { border-bottom: 0; }
.srctbl td.num { font-family: var(--mono); font-size: var(--fs-xs); text-align: right; }
.srctbl .tag { font-size: var(--fs-2xs); font-weight: 700; padding: 1px 7px; border-radius: var(--rx-pill); }
.srctbl .tag.e { color: var(--ok-fg); background: var(--ok-bg); }
.srctbl .tag.g { color: var(--warn-fg); background: var(--warn-bg); }
.row-view { border: 0; background: none; color: var(--acc); font-size: var(--fs-2xs); font-weight: 600; cursor: pointer; padding: 0; white-space: nowrap; }
.row-view:hover { text-decoration: underline; }
.srctbl-sum { margin-top: var(--sp-3); font-size: var(--fs-sm); color: var(--t3); line-height: var(--lh-body); }
.srctbl-sum b { color: var(--t1); font-weight: 600; }

/* ---- proposal generator result ---- */
#pResult { margin-top: 26px; }
.p-dl { margin-top: 18px; }
/* The sign-off strip under a run's review flags. Sits apart from them — the flags are
   what the agent could not settle, this is the person settling it — so it gets a hairline
   above rather than another warning-coloured card. */
.signoff {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--hairline);
}
.signoff__m { font-size: var(--fs-sm); color: var(--t3); flex: 1 1 auto; min-width: 180px; }
.signoff--ok .signoff__m { color: var(--t4); }

.p-flags { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.p-flags li {
  position: relative; padding: 11px 14px 11px 34px; font-size: var(--fs-sm); line-height: var(--lh-snug);
  color: var(--t2); background: var(--warn-bg); border: 1px solid var(--warn-line); border-radius: var(--rx-sm);
}
.p-flags li::before {
  content: "!"; position: absolute; left: 13px; top: 11px; width: 16px; height: 16px;
  border-radius: 50%; background: var(--warn-fg); color: var(--surface);
  font-size: 10px; font-weight: 800; text-align: center; line-height: 16px;
}

/* ============================================================
   CONTRACT REVIEW (agent #4)
   ============================================================ */
#cResult { margin-top: var(--sp-2); }
.cres-top { margin-bottom: var(--sp-5); display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); }
.cres-title { display: flex; align-items: center; gap: var(--sp-2); }
.cres-rename {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; border: 1px solid var(--hairline-hard);
  border-radius: var(--rx-xs); background: none; color: var(--t3); font-size: var(--fs-md);
  cursor: pointer; transition: background .15s, border-color .15s, color .15s;
}
.cres-rename:hover, .cres-rename:focus-visible { background: var(--hover); border-color: var(--acc-line); color: var(--t1); }
.cres-rename-edit { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
/* Slightly tighter than .btn--sm so Save/Cancel sit inside the title row. The
   font-size is no longer defensive — the `font: inherit` that used to blow these
   up to the header size is gone from the base and from .btn--ghost. */
.cres-rename-edit .btn { font-size: var(--fs-sm); padding: 6px 12px; }
.cres-rename__input {
  font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -0.02em; color: var(--t1);
  padding: var(--sp-1) 10px; border: 1px solid var(--acc); border-radius: var(--rx-xs);
  background: var(--surface); min-width: 240px; max-width: 60vw; outline: none;
}
.cres-rename__input:focus { box-shadow: 0 0 0 3px var(--acc-dim); }
.cnt-strip { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); }
.cres-actions { flex: none; }

/* export menu */
.expwrap { position: relative; }
.expmenu {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; min-width: 170px;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rx);
  box-shadow: var(--elev-3); padding: 6px;
}
.expmenu[hidden] { display: none; }
.expmenu__item {
  display: block; width: 100%; text-align: left; padding: 9px 11px; border: 0;
  background: transparent; border-radius: var(--rx-sm); font: inherit; font-size: var(--fs-sm);
  color: var(--t1); cursor: pointer;
}
.expmenu__item:hover, .expmenu__item:focus { background: var(--hover); outline: none; }

/* severity chips + counts */
.cnt-chip {
  font-size: var(--fs-xs); font-weight: 700; padding: 4px 11px; border-radius: var(--rx-pill);
  color: var(--t2); background: var(--mute-bg); border: 1px solid var(--hairline);
}
.cnt-chip.sev--high  { color: var(--bad-fg);  background: var(--bad-bg);  border-color: var(--bad-line); }
.cnt-chip.sev--med   { color: var(--warn-fg); background: var(--warn-bg); border-color: var(--warn-line); }
.cnt-chip.sev--low   { color: var(--t3);      background: var(--mute-bg); border-color: var(--hairline); }
.cnt-chip--block     { color: var(--bad-fg);  background: var(--bad-bg);  border-color: var(--bad-line); font-weight: 800; }
/* chips-as-filters: clickable, with a clear active state so the current filter is obvious */
.cnt-chip--btn { cursor: pointer; font-family: inherit; line-height: 1.2; transition: box-shadow .12s, transform .05s; }
.cnt-chip--btn:hover { box-shadow: 0 0 0 2px var(--hairline); }
.cnt-chip--btn:active { transform: translateY(1px); }
.cnt-chip--btn:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.cnt-chip--btn.is-active { box-shadow: 0 0 0 2px var(--acc); }
.hidden { display: none !important; }

/* project cost breakdown — Chart.js donut with KPI tiles above it (proposal result; on-screen only) */
.cost-donut {
  display: flex; flex-direction: column; align-items: center; gap: clamp(20px, 3vw, 30px);
  border: 1px solid var(--hairline); border-radius: var(--rx);
  background: var(--surface); padding: clamp(22px, 3vw, 32px);
  --cd-inc: #199e70;              /* dark default — kept in sync with CD_COLORS in console.js */
  --cd-cust: #3987e5;
}
[data-theme="light"] .cost-donut { --cd-inc: #0E9E67; --cd-cust: #2a78d6; }
/* in-column variant: no card chrome (it lives inside the .util column beside the tables). A WIDE centre
   column, with the donut and legend side by side so the block stays short — it no longer out-grows the
   Financials/Scope tables, so the row stops stretching. The pair is centred in the column's height. */
.cost-donut--col {
  border: 0; background: none; padding: 16px var(--sp-4); margin-top: 0;
  flex-direction: row; align-items: center; justify-content: center;
  gap: clamp(18px, 2vw, 32px);
}
.cost-donut--col .cd-chart { width: 176px; height: 176px; }
.cost-donut--col .cd-center { padding: 0 14px; gap: 3px; }
.cost-donut--col .cd-total-v { font-size: var(--fs-xl); }
/* keep the centre caption inside the ring */
.cost-donut--col .cd-total-k { font-size: 9px; letter-spacing: .02em; }
.cost-donut--col .cd-kpi__v { font-size: var(--fs-lg); }
/* legend stacked to the RIGHT of the donut, left-aligned */
.cost-donut--col .cd-kpis { flex-direction: column; flex-wrap: nowrap; align-items: flex-start; gap: 16px; }
/* KPI tiles: a thin colour tick, the label, then the figure — the console's stat-tile idiom */
/* Keep the two tiles as one compact, centred group — a wide gap made them read as opposite sides. */
.cd-kpis { display: flex; flex-wrap: wrap; justify-content: center; gap: 20px 36px; }
.cd-kpi { display: flex; gap: 12px; cursor: pointer; transition: opacity .16s ease; }
.cd-kpi.is-dim { opacity: .34; }
.cd-kpi__bar { width: 3px; border-radius: 2px; flex: none; transition: transform .16s ease; transform-origin: center; }
.cd-kpi.slice-inc  .cd-kpi__bar { background: var(--cd-inc); }
.cd-kpi.slice-cust .cd-kpi__bar { background: var(--cd-cust); }
.cd-kpi.is-active .cd-kpi__bar { transform: scaleX(2); }
.cd-kpi__body { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.cd-kpi__k { color: var(--t3); font-size: var(--fs-sm); font-weight: 600; }
.cd-kpi__v { color: var(--t1); font-size: var(--fs-xl); font-weight: 800; letter-spacing: -.01em; font-variant-numeric: tabular-nums; line-height: 1; }
.cd-kpi__pct { color: var(--t3); font-size: var(--fs-sm); font-weight: 600; margin-left: 8px; }
/* chart */
.cd-chart { position: relative; width: 220px; height: 220px; flex: none; }
.cd-chart canvas { display: block; width: 100% !important; height: 100% !important; }
/* the exact total, centred in the ring — padded so the caption keeps clear of the ring edge */
.cd-center {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 5px; pointer-events: none;
  padding: 0 24px; text-align: center;
}
.cd-total-v { color: var(--t1); font-size: var(--fs-2xl); font-weight: 800; letter-spacing: -.02em; line-height: 1; }
.cd-total-k {
  color: var(--t4); font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; line-height: 1.3; white-space: nowrap;
}
.sev { font-size: var(--fs-2xs); font-weight: 800; padding: 2px 8px; border-radius: var(--rx-pill); letter-spacing: .02em; white-space: nowrap; }
.sev--high { color: var(--bad-fg);  background: var(--bad-bg);  border: 1px solid var(--bad-line); }
.sev--med  { color: var(--warn-fg); background: var(--warn-bg); border: 1px solid var(--warn-line); }
.sev--low  { color: var(--t3);      background: var(--mute-bg); border: 1px solid var(--hairline); }

/* contract & fee summary */
.fee-tbl {
  border: 1px solid var(--hairline); border-top: 0; border-radius: 0 0 var(--rx) var(--rx);
  background: var(--surface); padding: 0 var(--sp-4) var(--sp-2);
}
.fee-row {
  display: grid; grid-template-columns: 1.3fr 1.6fr 1.1fr; gap: 14px; padding: 16px var(--sp-3);
  border-top: 1px solid var(--hairline-soft); font-size: var(--fs-sm); align-items: baseline;
}
.fee-row:first-child { border-top: 0; }
.fee-row--head {
  background: var(--surface-sub); border-radius: var(--rx-xs); padding-block: 11px; margin-top: 0;
}
.fee-row--head + .fee-row { border-top: 0; }
.fee-row--head span { font-size: var(--fs-2xs); letter-spacing: 0.06em; color: var(--t4); font-weight: 600; text-transform: uppercase; }
.fee-k { color: var(--t2); font-weight: 600; }
.fee-v { color: var(--t1); }
.fee-c { color: var(--t4); font-size: var(--fs-xs); }

/* per-area accordion */
.acc { border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface); margin-bottom: var(--sp-2); overflow: hidden; }
.acc[open] { background: var(--surface); }
.acc > summary {
  display: flex; align-items: center; gap: var(--sp-3); padding: 14px var(--sp-4);
  cursor: pointer; list-style: none; font-size: var(--fs-md); font-weight: 620; color: var(--t1);
  transition: background .12s;
}
.acc[open] > summary { background: var(--surface-sub); border-bottom: 1px solid var(--hairline); }
.acc > summary::-webkit-details-marker { display: none; }
.acc > summary::before { content: "▸"; color: var(--t4); font-size: var(--fs-2xs); transition: transform .15s; }
.acc[open] > summary::before { transform: rotate(90deg); }
.acc > summary:hover { background: var(--hover); }
.acc-t { flex: 1; }
.acc-cnts { display: flex; align-items: center; gap: 6px; }
.acc-n { font-size: var(--fs-2xs); font-weight: 700; color: var(--t4); font-family: var(--mono); min-width: 20px; text-align: right; }
.acc--empty > summary { color: var(--t4); font-weight: 600; }
.acc-body { padding: 2px var(--sp-4) var(--sp-3); }
/* Review scope (contract full read): verdict paragraph + missing-document list. */
.cscope__v { margin: 0 0 var(--sp-2); font-size: var(--fs-sm); line-height: 1.55; color: var(--t2); }
.cscope__list { margin: 0; padding-left: 18px; font-size: var(--fs-sm); line-height: 1.55; color: var(--t2); }
.cscope__list li { margin-bottom: 6px; }
.cscope__list b { color: var(--t1); font-weight: 600; }
.acc-none { font-size: var(--fs-sm); color: var(--t4); padding: 10px 0; }
.acc-tools { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); text-transform: none; letter-spacing: 0; }
.acc-tools__sep { color: var(--hairline-hard); font-weight: 400; }
.acc-tool {
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit; font-size: var(--fs-2xs);
  font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--t4); transition: color .15s;
}
.acc-tool:hover { color: var(--acc); }

/* a single finding */
.finding { padding: var(--sp-4) var(--sp-3); border-top: 1px solid var(--hairline-soft); }
.finding:first-child { border-top: 0; }
.finding-h { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: 6px; }
.finding-item { font-size: var(--fs-md); font-weight: 650; color: var(--t1); letter-spacing: -0.01em; }
.finding-fig {
  font-family: var(--mono); font-size: var(--fs-2xs); color: var(--acc);
  background: var(--acc-dim); border: 1px solid var(--acc-line); padding: 1px 8px; border-radius: var(--rx-pill);
}
.finding-sum { font-size: var(--fs-sm); color: var(--t2); line-height: var(--lh-body); }
.finding-why, .finding-act { font-size: var(--fs-xs); color: var(--t3); line-height: var(--lh-snug); margin-top: 5px; }
.finding-why b, .finding-act b { color: var(--t2); font-weight: 600; }
/* The cited clause — set as a quotation block, the evidence behind the finding. */
.finding-quote {
  font-size: var(--fs-sm); color: var(--t2); line-height: var(--lh-body); margin-top: 10px;
  padding: 11px var(--sp-3); border-left: 2px solid var(--hairline-hard);
  background: var(--surface-sub); border-radius: 0 var(--rx-xs) var(--rx-xs) 0; font-style: italic;
}
.finding-f { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 9px; }
.finding-cite { font-size: var(--fs-2xs); color: var(--t4); font-family: var(--mono); }
/* the source FILE inside a citation — the first thing a reviewer looks for, so it out-weighs
   the section/page that follow it */
.cite-doc { color: var(--t2); font-weight: 700; }
.finding-badges { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.badge { font-size: var(--fs-2xs); font-weight: 700; padding: 2px 8px; border-radius: var(--rx-pill); color: var(--t3); background: var(--mute-bg); border: 1px solid var(--hairline); }
.badge--block { color: var(--bad-fg); background: var(--bad-bg); border-color: var(--bad-line); }
.badge--pb { color: var(--acc); background: var(--acc-dim); border-color: var(--acc-line); }

/* "Why it matters" — the plain-English consequence */
.finding-matters {
  font-size: var(--fs-sm); color: var(--t2); line-height: var(--lh-snug); margin-top: var(--sp-2);
  padding: 10px var(--sp-3); border-left: 2px solid var(--warn-line);
  background: var(--warn-bg); border-radius: 0 var(--rx-xs) var(--rx-xs) 0;
}
.finding-matters b { color: var(--t1); font-weight: 650; }

/* per-finding triage */
.finding-triage {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 10px;
  padding-top: 10px; border-top: 1px dashed var(--hairline);
}
.finding-triage.is-saving { opacity: .55; pointer-events: none; }
.tri-lbl { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--t4); margin-right: 2px; }
.tri-btn {
  font: inherit; font-size: var(--fs-xs); font-weight: 650; cursor: pointer; padding: 4px 12px;
  border-radius: var(--rx-pill); color: var(--t2); background: var(--surface); border: 1px solid var(--hairline-hard);
}
.tri-btn:hover { border-color: var(--acc-line); background: var(--hover); }
.tri-btn.is-on { color: var(--acc); background: var(--acc-dim); border-color: var(--acc); }
.tri-note {
  flex: 1 1 200px; min-width: 160px; font: inherit; font-size: var(--fs-xs); color: var(--t1);
  background: var(--surface); border: 1px solid var(--hairline-hard); border-radius: var(--rx-xs); padding: 5px 10px;
}
.tri-note:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }

/* ---- Redline Builder (§12 / CAP-19–21) ---- */
/* Gate 1: the per-finding "Include in redline" toggle, under the triage row. */
.finding-rl { margin-top: 8px; }
.rl-chip {
  display: inline-flex; align-items: center; gap: 7px; font: inherit; font-size: var(--fs-xs);
  font-weight: 650; cursor: pointer; padding: 4px 12px; border-radius: var(--rx-pill);
  color: var(--t2); background: var(--surface); border: 1px solid var(--hairline-hard);
  transition: color .15s, background .15s, border-color .15s;
}
.rl-chip:hover { border-color: var(--acc-line); background: var(--hover); }
.rl-chip.is-busy { opacity: .55; pointer-events: none; }
.rl-chip__box {
  width: 13px; height: 13px; flex: none; border-radius: var(--rx-xs);
  border: 1.5px solid var(--t4); position: relative; transition: border-color .15s, background .15s;
}
.rl-chip.is-on { color: var(--acc); background: var(--acc-dim); border-color: var(--acc); }
.rl-chip.is-on .rl-chip__box { background: var(--acc); border-color: var(--acc); }
.rl-chip.is-on .rl-chip__box::after {
  content: "✓"; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 900; color: var(--surface); line-height: 1;
}
.rl-chip.is-ready { color: var(--ok-fg); background: var(--ok-bg); border-color: var(--ok-line); }
.rl-chip.is-ready .rl-chip__box { background: var(--ok-fg); border-color: var(--ok-fg); }

/* header Review ↔ Redline segmented toggle */
.cres-actions { display: flex; align-items: center; gap: var(--sp-2); }
.cview-seg { display: inline-flex; background: var(--mute-bg); border: 1px solid var(--hairline); border-radius: var(--rx-pill); padding: 3px; }
.cview-tab {
  font: inherit; font-size: var(--fs-xs); font-weight: 650; cursor: pointer; padding: 5px 14px;
  border: 0; background: transparent; color: var(--t3); border-radius: var(--rx-pill);
  display: inline-flex; align-items: center; gap: 6px; transition: color .15s, background .15s;
}
.cview-tab:hover { color: var(--t1); }
.cview-tab.is-on { color: var(--t1); background: var(--surface); box-shadow: var(--elev-1, 0 1px 2px rgba(0,0,0,.08)); }
.cview-n {
  font-size: var(--fs-2xs); font-weight: 800; min-width: 17px; height: 17px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center; border-radius: var(--rx-pill);
  background: var(--acc); color: #fff;
}
.cview-tab[hidden] { display: none; }

/* the builder body */
.rbuild { animation: cfmfade .16s var(--ease-out); }
.rbuild__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; }
.rbuild__title h2 { margin: 0; font-size: var(--fs-xl); font-weight: 750; letter-spacing: -.01em; color: var(--t1); }
.rbuild__sub { margin-top: 4px; font-size: var(--fs-sm); color: var(--t3); font-weight: 600; }
.rbuild__intro { margin: var(--sp-3) 0 var(--sp-4); font-size: var(--fs-sm); color: var(--t3); max-width: 720px; line-height: 1.55; }
.rbuild__intro b { color: var(--t2); font-weight: 700; }

.rl-nudge {
  display: flex; flex-direction: column; gap: 8px; margin-bottom: var(--sp-4);
  padding: var(--sp-3) var(--sp-4); border: 1px solid var(--warn-line); background: var(--warn-bg);
  border-radius: var(--rx); font-size: var(--fs-sm); color: var(--warn-fg);
}
.rl-nudge__txt b { font-weight: 800; }
.rl-nudge__list { display: flex; flex-wrap: wrap; gap: 7px; }
.rl-nudge__add {
  font: inherit; font-size: var(--fs-xs); font-weight: 650; cursor: pointer; padding: 4px 11px;
  border-radius: var(--rx-pill); color: var(--warn-fg); background: var(--surface); border: 1px solid var(--warn-line);
}
.rl-nudge__add:hover { background: var(--hover); }
.rl-nudge__add:disabled { opacity: .5; pointer-events: none; }

.rl-cards { display: grid; gap: var(--sp-3); grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); }
.rl-card {
  display: flex; flex-direction: column; gap: 8px; padding: var(--sp-4);
  border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface);
}
.rl-card.is-ready { border-color: var(--ok-line); box-shadow: inset 3px 0 0 var(--ok-fg); }
.rl-card__h { display: flex; align-items: center; gap: var(--sp-2); }
.rl-card__cat { font-size: var(--fs-sm); font-weight: 700; color: var(--t1); flex: 1 1 auto; min-width: 0; }
.rl-card__clause { font-weight: 600; color: var(--t3); }
.rl-card__state {
  font-size: var(--fs-2xs); font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  padding: 2px 8px; border-radius: var(--rx-pill); color: var(--t3); background: var(--mute-bg); border: 1px solid var(--hairline);
}
.rl-card.is-ready .rl-card__state { color: var(--ok-fg); background: var(--ok-bg); border-color: var(--ok-line); }
.rl-card__rm { font: inherit; font-size: var(--fs-xs); font-weight: 600; cursor: pointer; border: 0; background: none; color: var(--t4); padding: 2px 4px; }
.rl-card__rm:hover { color: var(--bad-fg); text-decoration: underline; }
.rl-card__cite { font-size: var(--fs-xs); color: var(--t3); }
.rl-card__concern { font-size: var(--fs-sm); color: var(--t2); line-height: 1.5; }
.rl-card__concern b { color: var(--t1); font-weight: 650; }
.rl-card__notelbl { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); margin-top: 2px; }
.rl-card__notelbl .rl-card__lbl { margin-top: 0; }
.rl-card__tri-tag {
  font-size: var(--fs-2xs); font-weight: 700; color: var(--warn-fg); background: var(--warn-bg);
  border: 1px solid var(--warn-line); padding: 1px 8px; border-radius: var(--rx-pill);
}
.rl-card__note {
  font: inherit; font-size: var(--fs-sm); color: var(--t1); line-height: 1.5; resize: vertical;
  background: var(--surface); border: 1px solid var(--hairline-hard); border-radius: var(--rx-xs); padding: 8px 11px;
}
.rl-card__note:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }
.rl-card__note[readonly] { background: var(--mute-bg); color: var(--t2); cursor: default; }
.rl-card__lbl { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--t4); margin-top: 2px; }
.rl-card__draftlbl { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); margin-top: 2px; }
.rl-card__draftlbl .rl-card__lbl { margin-top: 0; }
.rl-card__redraft {
  font: inherit; font-size: var(--fs-2xs); font-weight: 700; color: var(--acc); background: none; border: 0;
  cursor: pointer; padding: 0; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
}
.rl-card__redraft:hover { text-decoration: underline; }
.rl-card__redraft:disabled { opacity: .55; cursor: default; text-decoration: none; }
.rl-card__draft {
  font: inherit; font-size: var(--fs-sm); color: var(--t1); line-height: 1.5; resize: vertical;
  background: var(--surface); border: 1px solid var(--hairline-hard); border-radius: var(--rx-xs); padding: 8px 11px;
}
.rl-card__draft:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }
.rl-card__draft[readonly] { background: var(--mute-bg); color: var(--t2); cursor: default; }
.rl-card__row { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin-top: 2px; }
.rl-card__row--end { justify-content: flex-end; }
.rl-card__ready { margin-left: auto; }
.rl-card__cited {
  font: inherit; font-size: var(--fs-xs); font-weight: 650; color: var(--acc);
  background: none; border: 0; cursor: pointer; padding: 0; margin-left: 6px; white-space: nowrap;
}
.rl-card__cited:hover { text-decoration: underline; }
.rl-card.is-viewing { border-color: var(--acc); box-shadow: 0 0 0 2px var(--acc-dim); }

/* the on-screen source-document drawer, beside the builder (no tab-flip to check a clause) */
.rbwrap:not([hidden]).has-doc { display: flex; gap: var(--sp-4); align-items: flex-start; }
.rbwrap.has-doc .rbuild { flex: 1 1 auto; min-width: 0; }
.rldoc {
  flex: 0 0 clamp(340px, 42%, 560px); position: sticky; top: 12px; align-self: flex-start;
  display: flex; flex-direction: column; max-height: calc(100vh - 100px); overflow: hidden;
  border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface); box-shadow: var(--elev-1);
}
.rldoc[hidden] { display: none; }
.rldoc__h {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  padding: 10px 14px; border-bottom: 1px solid var(--hairline); flex: none;
}
.rldoc__t { font-size: var(--fs-sm); font-weight: 700; color: var(--t1); }
.rldoc__x {
  border: 0; background: none; color: var(--t3); font-size: var(--fs-md); line-height: 1;
  cursor: pointer; padding: 4px 6px; border-radius: var(--rx-xs);
}
.rldoc__x:hover { background: var(--hover); color: var(--t1); }
.rldoc__b { flex: 1 1 auto; min-height: 0; overflow: auto; }
@media (max-width: 900px) {
  .rbwrap:not([hidden]).has-doc { flex-direction: column; }
  .rldoc { flex-basis: auto; width: 100%; position: static; max-height: 72vh; }
}

/* ---- approval summary bar ----
   This selector was previously declared TWICE with conflicting rules (a neutral
   progress bar for the contract workbench, and a green "approved" banner for the
   assessment result); the later one silently won for both. Merged into one neutral
   surface — the pills and the fill bar carry the state, not the container. */
.appr-bar {
  display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap; padding: var(--sp-3) var(--sp-4);
  margin: var(--sp-1) 0 var(--sp-4); border: 1px solid var(--hairline);
  border-radius: var(--rx); background: var(--surface);
  font-size: var(--fs-sm); color: var(--t1);
}
.appr-bar svg { color: var(--acc); flex: none; }
.appr-bar__stat { display: flex; align-items: baseline; gap: 7px; }
.appr-bar__num { font-size: var(--fs-2xl); font-weight: 680; color: var(--t1); letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.appr-bar__lbl { font-size: var(--fs-sm); color: var(--t3); font-weight: 600; }
.appr-bar__track { flex: 1 1 160px; min-width: 120px; height: 6px; border-radius: var(--rx-pill); background: var(--canvas); overflow: hidden; }
.appr-bar__fill { height: 100%; width: 0; background: var(--acc); border-radius: var(--rx-pill); transition: width .3s var(--ease-out); }
.appr-bar__pills { display: flex; gap: 7px; flex-wrap: wrap; }
.appr-bar .appr-meta { color: var(--t3); font-size: var(--fs-xs); }
.appr-bar .appr-reopen { margin-left: auto; }
.appr-pill {
  font-size: var(--fs-2xs); font-weight: 700; padding: 3px 10px; border-radius: var(--rx-pill);
  border: 1px solid var(--hairline); color: var(--t3); background: var(--mute-bg); white-space: nowrap;
}
.appr-pill--ok  { color: var(--ok-fg);   background: var(--ok-bg);   border-color: var(--ok-line); }
.appr-pill--neg { color: var(--bad-fg);  background: var(--bad-bg);  border-color: var(--bad-line); }
.appr-pill--rev { color: var(--warn-fg); background: var(--warn-bg); border-color: var(--warn-line); }
.appr-pill--out { color: var(--t3); }
.stale-note { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--warn-fg); margin-left: var(--sp-2); }

/* ============================================================
   FOCUS MODE — the workbench takes the screen
   Everything above the panels is read-once context: the topbar, the title block, the
   sub-line, the triage bar, the closing disclaimer. Focus mode folds that to one compact
   row and drops the sidebar, so the three panels get the full viewport height. What stays
   is what a reviewer still ACTS on: the filter chips, the Review/Redline tabs, Export, and
   the way out.
   ============================================================ */
.cfocus-btn { display: inline-flex; align-items: center; gap: 6px; }
.app.contract-focus .sidebar,
.app.contract-focus .topbar,
.app.contract-focus .cres-top .top__eyebrow,
.app.contract-focus .cres-top .sub,
.app.contract-focus .cres-rename,
.app.contract-focus #cResult > .rail__note { display: none; }
/* Triage progress SURVIVES focus mode — it's the only thing above the panels that changes as you
   work, so dropping it meant leaving focus to answer "how far in am I?". It just stops being a
   card: no fill, no border, no 26px figure, a 4px track. ~26px of height instead of ~90px. */
.app.contract-focus .appr-bar {
  margin: 0 0 var(--sp-2); padding: 0 2px; gap: var(--sp-3);
  border: 0; background: none; box-shadow: none; flex-wrap: nowrap;
}
.app.contract-focus .appr-bar__num { font-size: var(--fs-md); }
.app.contract-focus .appr-bar__lbl { font-size: var(--fs-xs); }
.app.contract-focus .appr-bar__track { height: 4px; }
.app.contract-focus .appr-bar__pills { flex: none; }
.app.contract-focus .appr-pill { padding: 2px 8px; }
/* Hiding the sidebar and topbar ELEMENTS doesn't reclaim their space — the shell grid still
   reserves a --sidebar-w column and a --topbar-h row for them, which is 60px of empty canvas
   sitting above the header. Collapse the tracks too. Scoped above the phone breakpoint, where
   the shell switches to a stacked three-row layout whose tracks are already auto (so they
   collapse on their own). */
@media (min-width: 641px) {
  .app.contract-focus { grid-template-columns: 0 minmax(0, 1fr); grid-template-rows: 0 minmax(0, 1fr); }
}
.app.contract-focus .main { padding: var(--sp-3); }
.app.contract-focus #cResult { margin-top: 0; }
/* One row: title · filters · actions. The chips move up beside the title instead of
   claiming a line of their own. */
.app.contract-focus .cres-top {
  margin-bottom: var(--sp-2); align-items: center; flex-wrap: wrap; gap: var(--sp-3);
}
.app.contract-focus .cres-top > div:first-child {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; min-width: 0;
}
.app.contract-focus .cres-title h1 { font-size: var(--fs-lg); letter-spacing: -.01em; }
.app.contract-focus .cnt-strip { margin-top: 0; }
/* The panels ARE the page now. Sized by flex rather than `100vh − a guessed header height`:
   the header row's height moves with the title and how many filter chips wrap, and guessing it
   left the page a few pixels scrollable — enough that selecting a finding scrolled the header
   off the top. Nothing outside the panels scrolls in focus mode, so nothing can be scrolled away.
   Only where the panels sit side by side: below the stacking breakpoint they scroll normally,
   and pinning them to the viewport would clip them. */
@media (min-width: 1341px) {
  .app.contract-focus .main { overflow: hidden; display: flex; }
  .app.contract-focus .main .inner,
  .app.contract-focus #workspace,
  .app.contract-focus #contractView:not([hidden]),
  .app.contract-focus #cResultView:not([hidden]),
  .app.contract-focus #cResult { display: flex; flex-direction: column; flex: 1; min-height: 0; }
  .app.contract-focus .cwork { flex: 1; height: auto; min-height: 320px; }
  /* The redline tab is a long scrolling list, not a fixed workbench — give it the same
     leftover height and let it scroll inside, since the page itself no longer can. */
  .app.contract-focus .rbwrap:not([hidden]) { flex: 1; min-height: 0; overflow-y: auto; }
}
.app.contract-focus .cfocus-btn { color: var(--acc); border-color: var(--acc-line); }

/* ---- 3-panel workbench: findings · document · chat ---- */
/* Three panels need ~1100px before the sidebar and page padding are taken out,
   so the stacking breakpoint accounts for that chrome rather than the raw
   viewport. min() also stops any single panel's content from widening the grid. */
.cwork {
  display: grid;
  grid-template-columns: minmax(min(300px, 100%), 1fr) minmax(min(380px, 100%), 1.45fr) minmax(min(300px, 100%), 1fr);
  gap: var(--sp-3); align-items: stretch; height: calc(100vh - 250px); min-height: 560px;
  transition: grid-template-columns .22s var(--ease-out);
}
/* Chat shelved: its column collapses to a rail and the two working panels take the space. */
.cwork.chat-shelved {
  grid-template-columns: minmax(min(300px, 100%), 1fr) minmax(min(380px, 100%), 1.7fr) 40px;
}
.cwork.chat-shelved .cwork__right { display: none; }

/* The rail — a closed drawer's spine. Reads bottom-to-top so the label fits 40px. */
.cwork__rail {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) 0; border: 1px solid var(--hairline); border-radius: var(--rx);
  background: var(--surface); color: var(--t3); cursor: pointer; box-shadow: var(--elev-1);
  transition: color .15s, background .15s, border-color .15s;
}
.cwork__rail:hover { color: var(--acc); border-color: var(--acc-line); background: var(--acc-dim); }
.cwork__rail:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.cwork__rail-ico { display: grid; place-items: center; flex: none; }
.cwork__rail-ico svg { width: 15px; height: 15px; }
.cwork__rail-t {
  writing-mode: vertical-rl; transform: rotate(180deg);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* the header's shelve control — same weight as the panel's other header affordances */
.cpanel__shelf {
  margin-left: auto; flex: none; display: grid; place-items: center; width: 24px; height: 24px;
  padding: 0; border: 0; border-radius: var(--rx-xs); background: transparent; color: var(--t4);
  cursor: pointer; transition: color .12s, background .12s;
}
.cpanel__shelf svg { width: 14px; height: 14px; }
.cpanel__shelf:hover { color: var(--acc); background: var(--acc-dim); }
.cpanel__shelf:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }
.cpanel {
  display: flex; flex-direction: column; border: 1px solid var(--hairline);
  border-radius: var(--rx); background: var(--surface); overflow: hidden;
  min-height: 0; box-shadow: var(--elev-1);
}
.cpanel__h {
  display: flex; align-items: center; gap: var(--sp-2); padding: 13px var(--sp-4);
  border-bottom: 1px solid var(--hairline); font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--t4); flex: none;
  background: var(--surface-sub);
}
.cpanel__n { font-family: var(--mono); font-size: var(--fs-2xs); font-weight: 700; color: var(--t4); }
.cpanel__hint { margin-left: auto; font-size: var(--fs-2xs); font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--t4); text-align: right; }
.cpanel__b { flex: 1; overflow-y: auto; padding: var(--sp-4); min-height: 0; }
/* Zoomed in, the page is wider than the panel — let it scroll sideways instead of clipping. */
.cwork__mid .cpanel__b { padding: var(--sp-3); background: var(--canvas); overflow-x: auto; }
.cwork__right .cpanel__b { display: flex; flex-direction: column; padding: var(--sp-3) 14px; }
.cwork__left .psec { margin-top: var(--sp-4); }
.cpdf__ph { padding: var(--sp-6) var(--sp-4); text-align: center; color: var(--t4); font-size: var(--fs-sm); }

/* §9.9 direct document navigation — the strip under the viewer header: a prev/page/next pager
   and a jump-to-document picker. Always present, so the reviewer can browse without a finding.
   This is the one control a reviewer touches on every page of the contract, so it is deliberately
   the most present thing in the panel chrome: a floating pill on a tinted rail, not another row
   of hairline-on-surface form controls that reads as part of the header. */
/* Sized against the panel header above it, not as a hero: one line, never two. Everything
   except the file picker is fixed-width, so the picker is what absorbs a narrow panel. */
.cpdfnav {
  display: flex; align-items: center; gap: var(--sp-2); flex: none; flex-wrap: nowrap;
  padding: 5px var(--sp-3); border-bottom: 1px solid var(--hairline-hard);
  background: linear-gradient(180deg, var(--surface) 0%, var(--surface-sub) 100%);
}
.cpdfnav__lab { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--t4); }
.cpdfnav__lab--doc { margin-left: auto; flex: none; }

/* the pager pill: [‹] 7 of 83 [›] */
.cpdfnav__pager {
  display: inline-flex; align-items: center; gap: 1px; padding: 2px; flex: none;
  border: 1px solid var(--hairline-hard); border-radius: var(--rx-pill);
  background: var(--surface); box-shadow: var(--elev-2);
}
.cpdfnav__arrow {
  display: inline-grid; place-items: center; width: 24px; height: 24px; padding: 0; flex: none;
  border: 0; border-radius: 50%; background: transparent; color: var(--t2); cursor: pointer;
  transition: background .12s var(--ease-out), color .12s var(--ease-out), transform .08s var(--ease-out);
}
.cpdfnav__arrow svg { width: 14px; height: 14px; }
.cpdfnav__arrow:hover:not(:disabled) { background: var(--acc-dim); color: var(--acc); }
.cpdfnav__arrow:active:not(:disabled) { transform: scale(.9); }
.cpdfnav__arrow:disabled { color: var(--t4); opacity: .35; cursor: default; }
.cpdfnav__arrow:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }
.cpdfnav__field { display: inline-flex; align-items: center; gap: 4px; padding: 0 5px; }
.cpdfnav__num {
  width: 32px; padding: 2px; border: 1px solid transparent; border-radius: var(--rx-xs);
  background: transparent; color: var(--t1); font-family: var(--mono); font-size: var(--fs-xs);
  font-weight: 700; text-align: center; font-variant-numeric: tabular-nums;
  -moz-appearance: textfield; appearance: textfield;
}
/* the spinner arrows were the only way to page — they're replaced by real controls */
.cpdfnav__num::-webkit-outer-spin-button,
.cpdfnav__num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.cpdfnav__num:hover:not(:disabled) { border-color: var(--hairline-hard); }
.cpdfnav__num:focus {
  outline: none; background: var(--surface);
  border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim);
}
.cpdfnav__of {
  font-family: var(--mono); font-size: var(--fs-2xs); color: var(--t4);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* zoom: the same pill as the pager, with the percentage doubling as a reset button */
.cpdfnav__zoom { flex: none; }
.cpdfnav__pct {
  min-width: 40px; padding: 2px; border: 1px solid transparent; border-radius: var(--rx-pill);
  background: transparent; color: var(--t1); font-family: var(--mono); font-size: var(--fs-2xs);
  font-weight: 700; font-variant-numeric: tabular-nums; text-align: center; cursor: pointer;
  transition: background .12s var(--ease-out), color .12s var(--ease-out);
}
.cpdfnav__pct:hover { background: var(--acc-dim); color: var(--acc); }
.cpdfnav__pct:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }
/* The picker is also the "which file am I in" readout. It takes whatever width is left and
   truncates — the alternative is a contract filename wrapping the strip onto a second line. */
.cpdfnav__sel {
  flex: 0 1 auto; min-width: 60px; width: auto;
  padding: 3px var(--sp-2); border: 1px solid var(--hairline-hard); border-radius: var(--rx-pill);
  background: var(--surface); color: var(--t2); font-size: var(--fs-2xs); font-weight: 600; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cpdfnav__sel:hover { border-color: var(--acc-line); color: var(--t1); }
.cpdfnav__num:disabled, .cpdfnav__sel:disabled { opacity: .45; cursor: not-allowed; }
.cpdfnav__num:focus-visible, .cpdfnav__sel:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }
.cpanel-empty { color: var(--t4); font-size: var(--fs-sm); line-height: var(--lh-body); padding: var(--sp-2) 2px; }

/* findings become clickable rows that drive the document panel */
.finding--src { cursor: pointer; border-radius: var(--rx-xs); transition: background .12s; }
.finding--src:hover { background: var(--hover); }
/* Active = which finding the document panel is showing. Keep it NEUTRAL — the actual
   highlight lives on the PDF (the yellow clause box), not on the left list. */
.finding.is-active { background: var(--surface-sub); box-shadow: inset 3px 0 0 var(--t4); }
.finding--src .finding-h::after { content: "→"; margin-left: auto; color: var(--t4); font-weight: 700; font-size: var(--fs-xs); opacity: 0; transition: opacity .12s; }
.finding--src:hover .finding-h::after, .finding.is-active .finding-h::after { opacity: 1; }
.finding--src:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }

@media (max-width: 1340px) {
  .cwork, .cwork.chat-shelved { grid-template-columns: 1fr; height: auto; min-height: 0; }
  .cwork__mid .cpanel__b, .cwork__right .cpanel__b { min-height: 420px; }
  .cpanel { max-height: 640px; }
  /* Stacked, there is no side to shelve to — the rail becomes a full-width "open the chat" bar. */
  .cwork__rail { flex-direction: row; justify-content: center; padding: 11px var(--sp-3); }
  .cwork__rail-t { writing-mode: horizontal-tb; transform: none; }
  .cwork__rail-ico svg { transform: rotate(90deg); }
}

/* ============================================================
   CHAT WITH YOUR CONTRACT — grounded Q&A
   ============================================================ */
/* Saved-chat bar: resume a thread, start a new one, delete the open one. Hidden until there is
   actually something to switch between, so the common single-thread case is unchanged. */
.cchat__bar {
  display: flex; align-items: center; gap: var(--sp-2);
  padding-bottom: var(--sp-2); margin-bottom: var(--sp-2);
  border-bottom: 1px solid var(--hairline-soft);
}
.cchat__pick {
  flex: 1 1 auto; min-width: 0;            /* a long chat title must not widen the panel */
  font: inherit; font-size: var(--fs-xs); color: var(--t2);
  padding: 4px 6px; border: 1px solid var(--hairline); border-radius: var(--rx-xs);
  background: var(--surface); cursor: pointer;
}
.cchat__barbtn {
  flex: none; font: inherit; font-size: var(--fs-xs); color: var(--t2);
  padding: 4px 8px; border: 1px solid var(--hairline); border-radius: var(--rx-xs);
  background: var(--surface); cursor: pointer;
}
.cchat__barbtn:hover { background: var(--hover); color: var(--t1); }
.cchat__barbtn:disabled { opacity: 0.4; cursor: default; }
.cchat__barbtn:disabled:hover { background: var(--surface); color: var(--t2); }

.cchat__log { display: flex; flex-direction: column; gap: var(--sp-3); max-height: 420px; overflow-y: auto; padding: var(--sp-1) 2px var(--sp-3); }
.cwork__right .cchat__log { flex: 1; max-height: none; }
.cwork__right .cchat__form { margin-top: var(--sp-2); }
.cchat__hint { font-size: var(--fs-sm); color: var(--t3); line-height: var(--lh-body); }
.cchat__msg { max-width: 88%; }
.cchat__msg--user { align-self: flex-end; text-align: right; }
.cchat__who { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--t4); margin-bottom: 3px; }
.cchat__body {
  font-size: var(--fs-sm); line-height: var(--lh-body); color: var(--t1); white-space: pre-wrap;
  word-wrap: break-word; padding: 11px 14px; border-radius: var(--rx-sm);
  background: var(--surface-sub); border: 1px solid var(--hairline); display: inline-block; text-align: left;
}
.cchat__msg--user .cchat__body { color: var(--acc); background: var(--acc-dim); border-color: var(--acc-line); }
.cchat__form { display: flex; gap: var(--sp-2); margin-top: var(--sp-1); }
.cchat__form input {
  flex: 1; font: inherit; font-size: var(--fs-sm); color: var(--t1); background: var(--surface);
  border: 1px solid var(--hairline-hard); border-radius: var(--rx-sm); padding: 10px 13px;
}
.cchat__form input[type="text"]:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }

/* reference-form attachment chip */
.cchat__attach {
  display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2); padding: 7px 10px;
  background: var(--acc-dim); border: 1px solid var(--acc-line); border-radius: var(--rx-sm); font-size: var(--fs-xs);
}
.cchat__attach-ic { font-size: var(--fs-sm); }
.cchat__attach-name { color: var(--t1); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 55%; }
.cchat__attach-sz { color: var(--t4); }
.cchat__attach-tag {
  margin-left: auto; font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--acc); background: var(--surface);
  border: 1px solid var(--acc-line); border-radius: var(--rx-pill); padding: 2px 8px;
}
.cchat__attach-x { flex: 0 0 auto; border: none; background: none; color: var(--t3); cursor: pointer; font-size: var(--fs-sm); line-height: 1; padding: 2px 4px; border-radius: var(--rx-xs); }
.cchat__attach-x:hover { color: var(--t1); background: var(--surface-sub); }
.cchat__clip {
  flex: 0 0 auto; font-size: var(--fs-lg); line-height: 1; background: var(--surface);
  border: 1px solid var(--hairline-hard); border-radius: var(--rx-sm); color: var(--t2); cursor: pointer; padding: 0 11px;
}
.cchat__clip:hover { border-color: var(--acc); color: var(--acc); }
.cchat__clip.is-on { border-color: var(--acc); color: var(--acc); background: var(--acc-dim); }
.cchat__pin { margin-top: 6px; }
.cchat__pin .is-on { color: var(--acc); border-color: var(--acc-line); background: var(--acc-dim); cursor: default; }

/* clickable page citations inside an answer */
.cite-page {
  font: inherit; font-family: var(--mono); font-size: var(--fs-2xs); font-weight: 700; line-height: var(--lh-snug);
  color: var(--acc); background: var(--acc-dim); border: 1px solid var(--acc-line); border-radius: var(--rx-xs);
  padding: 0 6px; margin: 0 1px; cursor: pointer; vertical-align: baseline; white-space: nowrap;
}
.cite-page:hover { background: var(--acc); color: var(--surface); border-color: var(--acc); }

/* answers rendered from the model's markdown */
.cchat__body--rich { white-space: normal; }
.cchat__body--rich > :first-child { margin-top: 0; }
.cchat__body--rich > :last-child { margin-bottom: 0; }
.cchat__body--rich p { margin: 0 0 var(--sp-2); }
.cchat__body--rich ul, .cchat__body--rich ol { margin: 0 0 var(--sp-2); padding-left: 18px; }
.cchat__body--rich li { margin: 3px 0; }
.cchat__body--rich li::marker { color: var(--t4); }
.cchat__body--rich .ans-h { font-weight: 700; color: var(--t1); line-height: 1.35; margin: var(--sp-3) 0 5px; }
.cchat__body--rich .ans-h1 { font-size: var(--fs-md); }
.cchat__body--rich .ans-h2 { font-size: var(--fs-md); }
.cchat__body--rich .ans-h3 { font-size: var(--fs-sm); }
.cchat__body--rich .ans-h4 { font-size: var(--fs-sm); color: var(--t2); }
/* Answer tables. The chat column is narrow, so the table scrolls sideways rather than forcing
   the panel wider — the same treatment the workspace-search result table gets. */
.cchat__body--rich .ans-tbl {
  display: block; width: 100%; overflow-x: auto;
  border-collapse: collapse; margin: var(--sp-2) 0; font-size: var(--fs-xs);
}
.cchat__body--rich .ans-tbl th,
.cchat__body--rich .ans-tbl td {
  border: 1px solid var(--hairline); padding: 5px 8px; text-align: left; vertical-align: top;
  white-space: normal;
}
.cchat__body--rich .ans-tbl th { background: var(--surface-2, var(--hover)); font-weight: 600; color: var(--t1); }
.cchat__body--rich .ans-tbl td { color: var(--t2); }

/* animated "thinking" indicator */
.cchat__typing { display: inline-flex; align-items: center; gap: 5px; padding: 11px 14px; }
.cchat__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--t3); animation: cchat-blink 1.4s infinite ease-in-out both; }
.cchat__dot:nth-child(2) { animation-delay: .2s; }
.cchat__dot:nth-child(3) { animation-delay: .4s; }
@keyframes cchat-blink { 0%, 80%, 100% { opacity: .3; transform: translateY(0); } 40% { opacity: 1; transform: translateY(-3px); } }
@media (prefers-reduced-motion: reduce) { .cchat__dot { animation: none; opacity: .55; } }

/* ============================================================
   CORRECTIONS / OVERRIDE UI
   ============================================================ */
.elig__actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--sp-2); margin-bottom: 14px; }
.corr-badge {
  display: inline-block; margin-left: 6px; font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase; padding: 1px 7px; border-radius: var(--rx-pill);
  color: var(--warn-fg); background: var(--warn-bg); border: 1px solid var(--warn-line); vertical-align: middle;
}
.metric-edit {
  width: 100%; font-size: var(--fs-xl); font-weight: 650; letter-spacing: -0.03em;
  padding: 6px var(--sp-2); border: 1px solid var(--acc-line); border-radius: var(--rx-xs);
  background: var(--surface); color: var(--t1); font-family: inherit;
}
.metric-edit:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }
.fl-toggle { display: inline-flex; flex: none; border: 1px solid var(--hairline-hard); border-radius: var(--rx-pill); overflow: hidden; }
.fl-toggle .ft { border: 0; background: none; color: var(--t3); font: inherit; font-size: var(--fs-2xs); font-weight: 700; padding: 3px 11px; cursor: pointer; }
.fl-toggle .ft.ft-on { background: var(--acc-dim); color: var(--acc); }
.ov-audit { border: 1px solid var(--hairline); border-radius: var(--rx-sm); background: var(--surface-sub); padding: var(--sp-3) 14px; margin-top: var(--sp-3); }
.ov-audit-h { font-size: var(--fs-2xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--t4); margin-bottom: var(--sp-2); }
.ov-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; padding: 6px 0; border-top: 1px solid var(--hairline-soft); font-size: var(--fs-sm); }
.ov-row:first-of-type { border-top: 0; }
.ov-row .ov-f { font-weight: 600; color: var(--t1); min-width: 150px; }
.ov-row .ov-chg { font-family: var(--mono); font-size: var(--fs-xs); color: var(--t2); }
.ov-row .ov-chg s { color: var(--t4); }
.ov-row .ov-chg b { color: var(--acc); }
.ov-row .ov-meta { margin-left: auto; font-size: var(--fs-2xs); color: var(--t4); }

/* ============================================================
   SOURCE DOCUMENT — inline preview + slide-in drawer
   ============================================================ */
.srcdoc { border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface); overflow: hidden; }
.srcdoc__load { padding: var(--sp-6); text-align: center; color: var(--t4); font-size: var(--fs-sm); }
.srcdoc__ph { padding: 22px var(--sp-5); }
.srcdoc__ph-t { font-size: var(--fs-md); font-weight: 650; margin-bottom: 6px; }
.srcdoc__ph p { font-size: var(--fs-sm); color: var(--t3); max-width: 60ch; margin-bottom: 14px; }
.srcdoc__ph code { font-family: var(--mono); font-size: var(--fs-xs); color: var(--t2); }
.srcdoc__foot { padding: 10px 14px; font-size: var(--fs-xs); color: var(--t4); border-top: 1px solid var(--hairline); }
.srcdoc__foot a { color: var(--acc); }
.srcdoc__item { border-top: 1px solid var(--hairline); }
.srcdoc__item:first-child { border-top: 0; }
.srcdoc__label {
  padding: 9px 14px; font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--t3); background: var(--surface-sub); border-bottom: 1px solid var(--hairline);
}
.srcdoc-open {
  display: flex; align-items: center; gap: 13px; width: 100%; text-align: left; padding: 14px var(--sp-4);
  border: 1px solid var(--hairline); border-radius: var(--rx-sm); background: var(--surface);
  color: var(--t1); cursor: pointer; transition: border-color .2s, background .2s;
}
.srcdoc-open:hover { border-color: var(--acc-line); background: var(--hover); }
.srcdoc-open svg { color: var(--acc); flex: none; }
.srcdoc-open__txt b { font-size: var(--fs-md); font-weight: 600; }
.srcdoc-open__sub { display: block; font-size: var(--fs-xs); color: var(--t4); margin-top: 2px; }
.srcdoc-open__arrow { margin-left: auto; color: var(--t4); font-size: var(--fs-lg); }
.see-src { border: 0; background: none; color: var(--acc); font-size: var(--fs-2xs); font-weight: 600; cursor: pointer; padding: 0; margin-left: 5px; }
.see-src:hover { text-decoration: underline; }

/* drawer — slides in on the right; the result stays visible for cross-check */
.modal { position: fixed; top: 0; right: 0; height: 100vh; width: min(560px, 96vw); z-index: 60; }
.modal__backdrop { display: none; }   /* no dim — the result must stay readable beside it */
.modal__card {
  width: 100%; height: 100%; display: flex; flex-direction: column; background: var(--surface);
  border-left: 1px solid var(--hairline-hard); box-shadow: var(--elev-3); overflow: hidden;
}
.app.srcopen .main { padding-right: calc(min(560px, 92vw) + var(--sp-8)); transition: padding-right .2s var(--ease-out); }
.modal__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--hairline); background: var(--surface-sub); }
.modal__title { font-size: var(--fs-lg); font-weight: 680; letter-spacing: -0.025em; }
.modal__sub { font-size: var(--fs-xs); color: var(--t4); margin-top: 3px; }
.modal__x { background: none; border: 0; color: var(--t3); font-size: var(--fs-lg); cursor: pointer; padding: 4px 6px; line-height: 1; border-radius: var(--rx-xs); }
.modal__x:hover { color: var(--t1); background: var(--hover); }
.modal__body { flex: 1; overflow: auto; padding: 18px var(--sp-5); background: var(--canvas); display: grid; place-items: center; }
.modal__body canvas, .modal__body img { max-width: 100%; height: auto; box-shadow: var(--elev-2); border-radius: var(--rx-xs); }
.modal__foot { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-5); border-top: 1px solid var(--hairline); }
.modal__count { font-size: var(--fs-xs); color: var(--t3); font-family: var(--mono); }
.modal__link { margin-left: auto; color: var(--acc); font-size: var(--fs-xs); text-decoration: none; }
.modal__link:hover { text-decoration: underline; }

/* ============================================================
   DASHBOARD LIST — toolbar, table, empty states
   ============================================================ */
.backlink {
  background: none; border: 0; color: var(--t3); font: inherit; font-size: var(--fs-sm);
  font-weight: 600; cursor: pointer; padding: 0; margin-bottom: var(--sp-4);
  display: inline-flex; align-items: center; gap: 6px;
}
.backlink:hover { color: var(--acc); }

/* The toolbar is the table card's header: same white surface, hairline and top
   radius as the table below it, with the bottom edge left open so the two read
   as one card rather than two stacked boxes. */
.listbar {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  margin-bottom: 0; padding: 15px 18px;
  background: var(--surface); border: 1px solid var(--hairline); border-bottom: 0;
  border-radius: var(--rx) var(--rx) 0 0;
}
.listbar__l { font-size: var(--fs-lg); font-weight: 650; letter-spacing: -0.02em; text-transform: none; color: var(--t1); }
.listbar__n { color: var(--t4); font-weight: 600; margin-left: 6px; font-variant-numeric: tabular-nums; }
.listbar__r { display: flex; align-items: center; gap: 10px; }
.listbar .side-filters { padding: 0; }
.listbar .chip { flex: 0 0 auto; padding: 7px 13px; font-size: var(--fs-xs); }

.tbl-search { position: relative; display: flex; align-items: center; }
.tbl-search svg { position: absolute; left: 11px; color: var(--t4); pointer-events: none; }
.tbl-search input {
  width: min(280px, 60vw); padding: 9px 12px 9px 32px; border: 1px solid var(--hairline-hard);
  border-radius: var(--rx-sm); background: var(--surface); color: var(--t1); font: inherit;
  font-size: var(--fs-sm); transition: border-color .15s, box-shadow .15s;
}
.tbl-search input::placeholder { color: var(--t4); }
.tbl-search input:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }
.tbl-search input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* filter chips (shared by the list toolbar) */
.side-filters { display: flex; gap: 6px; padding: 0 2px var(--sp-1); }
.chip {
  flex: 1; padding: 6px 10px; border: 1px solid var(--hairline); border-radius: var(--rx-pill);
  background: var(--surface); color: var(--t3); font: inherit; font-size: var(--fs-xs);
  font-weight: 600; cursor: pointer; transition: color .15s, border-color .15s, background .15s;
}
.chip:hover { border-color: var(--acc-line); color: var(--t1); }
.chip.is-on { background: var(--acc-dim); border-color: var(--acc-line); color: var(--acc); }

/* the assessment / proposal / review table */
.atbl {
  border: 1px solid var(--hairline); border-top: 0; border-radius: 0 0 var(--rx) var(--rx);
  overflow: hidden; background: var(--surface);
}
/* When a pager follows, the table is a middle segment and the pager closes the card. */
.atbl:has(+ .pager) { border-radius: 0; border-bottom: 0; }
.atbl__row {
  display: grid; grid-template-columns: 1.6fr 1.8fr 0.7fr 1fr 0.8fr; align-items: center;
  gap: 14px; padding: 17px 18px; border-top: 1px solid var(--hairline-soft);
  cursor: pointer; transition: background .12s; width: 100%; text-align: left;
  background: none; border-left: 0; border-right: 0; border-bottom: 0;
}
.atbl__row:hover { background: var(--hover); }
.atbl__head { cursor: default; background: var(--surface-sub); border-top: 0; padding-block: 12px; }
.atbl__head:hover { background: var(--surface-sub); }
.atbl__head span {
  font-size: var(--fs-2xs); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--t4); font-weight: 600;
}
.atbl__head span.sortable { cursor: pointer; user-select: none; display: inline-flex; align-items: center; gap: 4px; transition: color .12s; }
.atbl__head span.sortable:hover { color: var(--t1); }
.atbl__head span.sortable.is-sorted { color: var(--acc); }
.atbl__head .sort-caret { font-size: 9px; opacity: 0; transition: opacity .12s; }
.atbl__head span.is-sorted .sort-caret { opacity: 1; }
.atbl .c-client { font-size: var(--fs-md); font-weight: 600; color: var(--t1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.atbl .c-addr { font-size: var(--fs-sm); color: var(--t3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.atbl .c-tier { font-size: var(--fs-sm); font-weight: 700; color: var(--acc); }
.atbl .c-tier.na { color: var(--t4); }
/* An in-flight run has no findings yet — never render its column as a result. */
.atbl .c-tier.is-muted { color: var(--t4); font-weight: 550; }
/* A project the document never named — a statement, not a value. */
.atbl .c-client.is-muted { color: var(--t4); font-weight: 400; font-style: italic; }
.atbl .c-date { font-size: var(--fs-xs); color: var(--t4); font-variant-numeric: tabular-nums; }

/* status pill */
/* The base carries the pill, not just the padding. Every colour variant used to supply
   its own background and border, so a status with no variant — `pending` on a field audit —
   rendered as bare text with a dot beside three proper pills. A default that already looks
   right means the next status added cannot arrive naked. */
.st {
  font-size: var(--fs-2xs); font-weight: 700; padding: 4px 10px;
  border-radius: var(--rx-pill); white-space: nowrap; display: inline-flex;
  align-items: center; gap: 5px;
  color: var(--t3); background: var(--mute-bg); border: 1px solid var(--hairline);
}
.st::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.st--ok  { color: var(--ok-fg);   background: var(--ok-bg);   border: 1px solid var(--ok-line); }
.st--rev { color: var(--warn-fg); background: var(--warn-bg); border: 1px solid var(--warn-line); }
.st--new { color: var(--t3);      background: var(--mute-bg); border: 1px solid var(--hairline); }
.st--bad { color: var(--bad-fg);  background: var(--bad-bg);  border: 1px solid var(--bad-line); }
/* Still running. The dot pulses so an in-flight row is distinguishable from a
   finished one at a glance — these used to render as a green "Reviewed" pill. */
.st--work { color: var(--info-fg); background: var(--info-bg); border: 1px solid var(--info-line); }
.st--work::before { animation: stpulse 1.3s ease-in-out infinite; }
@keyframes stpulse { 0%, 100% { opacity: .35; transform: scale(.8); } 50% { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .st--work::before { animation: none; opacity: .8; } }
/* An in-flight run has no report to show yet, so its row isn't a link. */
.atbl__row.is-working { cursor: default; }
.atbl__row.is-working:hover { background: none; }

.side-noresults { font-size: var(--fs-sm); color: var(--t4); padding: 22px; text-align: center; }

@media (max-width: 760px) {
  .atbl__row { grid-template-columns: 1.4fr 0.7fr 0.9fr; }
  .atbl .c-addr, .atbl .c-date, .atbl__head .h-addr, .atbl__head .h-date { display: none; }
}

/* ---- past assessment rows ---- */
.past-row {
  border: 1px solid var(--hairline); border-radius: var(--rx-sm); background: var(--surface);
  padding: 14px var(--sp-4); display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); cursor: pointer; transition: border-color .15s;
}
.past-row:hover { border-color: var(--acc-line); }
.past-row .pr-a { font-size: var(--fs-md); font-weight: 600; }
.past-row .pr-m { font-size: var(--fs-xs); color: var(--t4); margin-top: 2px; }
.past-row .pr-t {
  font-size: var(--fs-2xs); font-weight: 700; padding: 3px 10px; border-radius: var(--rx-pill);
  color: var(--ok-fg); background: var(--ok-bg); border: 1px solid var(--ok-line); white-space: nowrap;
}

/* ============================================================
   EMPTY STATES
   ------------------------------------------------------------
   These are the first thing a new workspace sees, so they get a
   glyph, a headline, an explanatory line and the primary action
   rather than a bare sentence in a dashed box.
   ============================================================ */
.empty {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: var(--sp-10) var(--sp-5); border: 1px solid var(--hairline);
  border-radius: var(--rx-lg); background: var(--surface);
  color: var(--t3); font-size: var(--fs-md); line-height: var(--lh-body);
}
.empty__ico {
  display: grid; place-items: center; width: 48px; height: 48px; margin-bottom: var(--sp-4);
  border-radius: var(--rx); color: var(--acc); background: var(--acc-dim); border: 1px solid var(--acc-line);
}
.empty__t { font-size: var(--fs-lg); font-weight: 650; letter-spacing: -0.02em; color: var(--t1); margin-bottom: 6px; }
.empty__d { font-size: var(--fs-md); color: var(--t3); max-width: 46ch; line-height: var(--lh-body); }
.empty .btn { margin-top: var(--sp-5); }

/* ============================================================
   TOAST
   ============================================================ */
.toast {
  position: fixed; bottom: 22px; left: 50%; transform: translate(-50%, 20px); opacity: 0;
  background: var(--t1); color: var(--surface); border-radius: var(--rx-sm);
  padding: 11px 18px; font-size: var(--fs-sm); font-weight: 550; box-shadow: var(--elev-3);
  transition: opacity .3s, transform .35s var(--ease-out); z-index: 40;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ============================================================
   FEEDBACK WIDGET — self-hosted (no third-party script)
   ============================================================ */
.fb-fab {
  position: fixed; right: 60px; bottom: 16px; z-index: 60; display: inline-flex; align-items: center; gap: 7px;
  height: 34px; padding: 0 13px; border-radius: var(--rx-sm); border: 1px solid var(--hairline-hard);
  background: var(--surface); color: var(--t2); font: inherit; font-size: var(--fs-sm);
  font-weight: 600; line-height: 1; cursor: pointer; box-shadow: var(--elev-2); white-space: nowrap;
  transition: color .2s, border-color .2s, background .2s;
}
.fb-fab:hover { color: var(--t1); border-color: var(--acc-line); background: var(--hover); }
.fb-fab svg { width: 16px; height: 16px; display: block; flex: none; color: var(--acc); }
.fb-panel {
  position: fixed; right: 16px; bottom: 60px; z-index: 56; width: min(340px, 92vw);
  border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface);
  box-shadow: var(--elev-3); overflow: hidden;
}
.fb-head { display: flex; align-items: center; justify-content: space-between; padding: 13px var(--sp-4); border-bottom: 1px solid var(--hairline); }
.fb-title { font-size: var(--fs-md); font-weight: 650; letter-spacing: -0.01em; }
.fb-x { background: none; border: 0; color: var(--t3); font-size: var(--fs-lg); cursor: pointer; padding: 4px 6px; line-height: 1; border-radius: var(--rx-xs); }
.fb-x:hover { color: var(--t1); background: var(--hover); }
.fb-body { padding: 14px var(--sp-4) var(--sp-4); }
.fb-types { display: flex; gap: 7px; margin-bottom: 11px; }
.fb-chip {
  flex: 1; padding: 6px var(--sp-2); border: 1px solid var(--hairline-hard); border-radius: var(--rx-pill);
  background: none; color: var(--t3); font: inherit; font-size: var(--fs-xs); font-weight: 600;
  cursor: pointer; transition: color .15s, border-color .15s, background .15s;
}
.fb-chip:hover { border-color: var(--acc-line); color: var(--t1); }
.fb-chip.is-on { background: var(--acc-dim); border-color: var(--acc-line); color: var(--acc); }
.fb-text {
  width: 100%; padding: 11px 13px; border: 1px solid var(--hairline-hard); border-radius: var(--rx-sm);
  background: var(--surface); color: var(--t1); font: inherit; font-size: var(--fs-md);
  line-height: var(--lh-snug); resize: vertical; min-height: 88px;
}
.fb-text::placeholder { color: var(--t4); }
.fb-text:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }
.fb-body .btn--full { margin-top: 11px; }
.fb-shot {
  width: 100%; margin-top: 10px; display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: var(--sp-2) 10px; border: 1px dashed var(--hairline-hard); border-radius: var(--rx-sm);
  background: none; color: var(--t2); font: inherit; font-size: var(--fs-sm); cursor: pointer; transition: .15s;
}
.fb-shot:hover { border-color: var(--acc-line); color: var(--t1); background: var(--hover); }
.fb-shot:disabled { opacity: .6; cursor: default; }
.fb-shot svg { color: var(--acc); }
.fb-shot-preview { position: relative; margin-top: 10px; }
.fb-shot-preview img { width: 100%; border: 1px solid var(--hairline); border-radius: var(--rx-sm); display: block; }
.fb-shot-rm {
  position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; border: 0; border-radius: 50%;
  background: rgba(0, 0, 0, .62); color: #fff; font-size: var(--fs-xs); line-height: 1; cursor: pointer;
}
.fb-shot-rm:hover { background: rgba(0, 0, 0, .82); }
.fb-note { font-size: var(--fs-xs); color: var(--t4); line-height: var(--lh-snug); margin-top: 11px; }

/* ============================================================
   ADMIN: RUN DELETION — selection, bulk bar, confirm, trash
   ------------------------------------------------------------
   See docs/ADMIN_RUN_DELETION.md. Everything here is admin-only
   chrome: it is injected by js/console.js when the resolved role
   allows it, so operators never see any of it.
   ============================================================ */

/* ---- row selection --------------------------------------------------
   Table rows are <button>s, so the checkbox sits beside the row rather
   than inside it: [checkbox][row]. The header row is a direct child of
   .atbl and isn't wrapped, so it gets an equal indent to stay aligned. */
.atbl__line { display: grid; grid-template-columns: 40px minmax(0, 1fr); align-items: stretch; }
.atbl__line + .atbl__line .atbl__row,
.atbl__line + .atbl__line .atbl__sel { border-top: 1px solid var(--hairline-soft); }
.atbl__line .atbl__row { border-top: 0; }
.atbl__line.is-sel { background: var(--acc-dim); }
.atbl__line.is-sel .atbl__row:hover { background: transparent; }

.atbl__sel { display: grid; place-items: center; cursor: pointer; padding-left: 18px; }
.atbl__sel input {
  width: 16px; height: 16px; margin: 0; cursor: pointer; flex: none;
  accent-color: var(--acc); border-radius: var(--rx-xs);
}
/* Reveal the checkbox on hover/focus/selection only — an unselected table
   shouldn't read as a form. */
/* Always visible — the reference keeps the selection column present rather than
   revealing it on hover, which is what makes bulk actions discoverable. */
.atbl__line--head { background: var(--surface-sub); border-bottom: 1px solid var(--hairline); }
.atbl__line--head .atbl__head { background: none; border-top: 0; }

/* ---- floating bulk action bar --------------------------------------- */
.bulkbar {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 55;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 10px 12px 10px 18px; border-radius: var(--rx-pill);
  background: var(--t1); color: var(--surface);
  box-shadow: var(--elev-3); animation: bulkin .18s var(--ease-out);
}
@keyframes bulkin { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }
.bulkbar__n { font-size: var(--fs-sm); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.bulkbar .btn--ghost {
  background: transparent; border-color: rgba(255, 255, 255, .28); color: var(--surface);
}
.bulkbar .btn--ghost:hover { background: rgba(255, 255, 255, .12); border-color: rgba(255, 255, 255, .45); }
.bulkbar__del {
  border: 1px solid transparent; border-radius: var(--rx-sm); cursor: pointer;
  font: inherit; font-size: var(--fs-sm); font-weight: 650; padding: 7px 14px;
  background: var(--bad-fg); color: #fff; transition: filter .15s;
}
.bulkbar__del:hover { filter: brightness(1.1); }

/* ---- confirm dialog -------------------------------------------------- */
.cfm { position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; padding: var(--sp-5); }
.cfm__backdrop { position: absolute; inset: 0; background: rgba(10, 13, 18, .45); animation: cfmfade .15s ease; }
@keyframes cfmfade { from { opacity: 0; } to { opacity: 1; } }
.cfm__card {
  position: relative; width: min(440px, 100%); padding: var(--sp-6);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--rx-lg); box-shadow: var(--elev-3);
  animation: cfmin .18s var(--ease-out);
}
@keyframes cfmin { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }
.cfm__t { font-size: var(--fs-xl); font-weight: 650; letter-spacing: -0.02em; color: var(--t1); }
.cfm__b { font-size: var(--fs-md); color: var(--t3); line-height: var(--lh-body); margin-top: var(--sp-2); }
.cfm__card .fld { margin: var(--sp-5) 0 0; }
.cfm__f { display: flex; justify-content: flex-end; gap: var(--sp-2); margin-top: var(--sp-6); }
.cfm__danger {
  border: 1px solid transparent; border-radius: var(--rx-sm); cursor: pointer;
  font: inherit; font-size: var(--fs-sm); font-weight: 650; padding: 7px 14px;
  background: var(--bad-fg); color: #fff; transition: filter .15s;
}
.cfm__danger:hover:not(:disabled) { filter: brightness(1.1); }
.cfm__danger:disabled { opacity: .45; cursor: not-allowed; }

/* ---- undo affordance in the toast ------------------------------------ */
.toast__undo {
  border: 0; background: none; padding: 0 2px; margin-left: 4px; cursor: pointer;
  font: inherit; font-size: var(--fs-sm); font-weight: 700; color: var(--acc);
  text-decoration: underline; text-underline-offset: 2px;
}
.toast__undo:hover { filter: brightness(1.15); }

/* ---- trash view ------------------------------------------------------ */
.trash-toggle { flex: 0 0 auto; }
.trash__row { grid-template-columns: 1.4fr 1.8fr 0.7fr auto; cursor: default; padding: 15px 18px; }
.trash__row:hover { background: none; }
.trash__acts { display: flex; justify-content: flex-end; gap: var(--sp-2); flex-wrap: wrap; }

/* ============================================================
   SEARCH RESULTS PAGE — the surface behind the instant dropdown
   ------------------------------------------------------------
   The dropdown answers "is the thing I want right here"; this page answers
   "show me everything you have". Modelled on the Lightning search results
   layout the owner asked for: a rail of agents with match counts on the left,
   per-agent sections with real columns on the right, and one agent at a time
   when you narrow to it.
   ============================================================ */
.sr { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: var(--sp-5); align-items: start; }
@media (max-width: 900px) { .sr { grid-template-columns: 1fr; } }

.sr__side {
  position: sticky; top: var(--sp-4); background: var(--surface);
  border: 1px solid var(--hairline); border-radius: var(--rx); overflow: hidden;
}
.sr__sidehd {
  padding: 11px 14px 9px; font-family: var(--mono); font-size: var(--fs-2xs);
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--t4);
  border-bottom: 1px solid var(--hairline-soft);
}
.sr__nav { padding: 4px; }
.sr__navb {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px;
  border: 0; border-radius: var(--rx-sm); background: none; color: var(--t2);
  font-family: inherit; font-size: var(--fs-sm); text-align: left; cursor: pointer;
}
.sr__navb:hover { background: var(--hover); }
.sr__navb.is-on { background: var(--hover); color: var(--t1); font-weight: 600; box-shadow: inset 2px 0 0 var(--acc); }
.sr__navb__n {
  margin-left: auto; min-width: 22px; padding: 1px 6px; border-radius: 999px;
  border: 1px solid var(--hairline); background: var(--surface-sub);
  font-size: var(--fs-2xs); color: var(--t4); text-align: center; font-variant-numeric: tabular-nums;
}
.sr__navb.is-on .sr__navb__n { border-color: var(--acc-dim); color: var(--acc); }
/* A zero is information — it says we looked there and found nothing — so it stays legible
   but recedes, and the row stops inviting a click that leads to an empty table. */
.sr__navb.is-zero { color: var(--t4); cursor: default; }
.sr__navb.is-zero:hover { background: none; }

.sr__top { margin-bottom: var(--sp-4); }
.sr__h { margin: 0; font-size: var(--fs-xl); font-weight: 650; color: var(--t1); }
.sr__sub { margin-top: 3px; font-size: var(--fs-sm); color: var(--t4); }

/* One section per kind of evidence, each labelled. A section is a labelled band, not another
   white card — three anonymous cards read as one list that keeps changing its mind. */
.sr__sec { margin-bottom: var(--sp-5); }
.sr__sechd {
  display: flex; align-items: baseline; gap: 10px; padding: 0 2px 7px;
  border-bottom: 1px solid var(--hairline); margin-bottom: 10px;
}
.sr__seclabel {
  font-family: var(--mono); font-size: var(--fs-2xs); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--t3); font-weight: 600;
}
.sr__secstate { margin-left: auto; font-size: var(--fs-xs); color: var(--t4); }
.sr__sec--answer .tb-ask { padding: 0 2px 4px; border-bottom: 0; }
.sr__sec--answer .tb-ask__a { font-size: var(--fs-md); line-height: 1.5; }

/* An absence is one quiet line, not a 200px centred box. */
.sr__note { padding: 4px 2px 10px; font-size: var(--fs-sm); color: var(--t4); }
.sr__note--work { display: flex; align-items: center; gap: 9px; }
.sr__spin {
  flex: none; width: 12px; height: 12px; border: 2px solid var(--hairline-hard);
  border-top-color: var(--acc); border-radius: 50%; animation: tbSpin .6s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .sr__spin { animation: none; } }

.sr__docsbtn {
  border: 0; background: none; padding: 0; font-family: inherit; font-size: var(--fs-xs);
  color: var(--acc); cursor: pointer;
}
.sr__docsbtn:hover { text-decoration: underline; }
.sr__docsbtn:disabled { color: var(--t4); cursor: default; text-decoration: none; }

.sr__grp { margin-bottom: var(--sp-4); border: 1px solid var(--hairline); border-radius: var(--rx); overflow: hidden; background: var(--surface); }
.sr__grphd { display: flex; align-items: baseline; gap: 10px; padding: 12px 14px 10px; }
.sr__grpt { font-size: var(--fs-md); font-weight: 650; color: var(--t1); }
.sr__grpn { font-size: var(--fs-xs); color: var(--t4); }
.sr__more { margin-left: auto; font-size: var(--fs-xs); color: var(--acc); background: none; border: 0; cursor: pointer; font-family: inherit; }
.sr__more:hover { text-decoration: underline; }

.sr__tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.sr__tbl th {
  padding: 7px 14px; text-align: left; font-family: var(--mono); font-size: var(--fs-2xs);
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--t4); font-weight: 500;
  background: var(--surface-sub); border-top: 1px solid var(--hairline-soft);
  border-bottom: 1px solid var(--hairline-soft); white-space: nowrap;
}
.sr__tbl th button {
  border: 0; background: none; padding: 0; font: inherit; color: inherit; cursor: pointer;
  letter-spacing: inherit; text-transform: inherit;
}
.sr__tbl th button:hover { color: var(--t2); }
.sr__tbl th .sr__dir { color: var(--acc); }
.sr__tbl td { padding: 9px 14px; border-bottom: 1px solid var(--hairline-soft); color: var(--t2); vertical-align: top; }
.sr__tbl tr:last-child td { border-bottom: 0; }
.sr__tbl tbody tr:hover { background: var(--hover); }
.sr__name { border: 0; background: none; padding: 0; font: inherit; font-weight: 600; color: var(--acc); cursor: pointer; text-align: left; }
.sr__name:hover { text-decoration: underline; }
.sr__sub2 { display: block; margin-top: 2px; font-size: var(--fs-xs); color: var(--t4); }
.sr__when { color: var(--t4); white-space: nowrap; font-variant-numeric: tabular-nums; }
.sr__empty { padding: 14px 2px; color: var(--t4); font-size: var(--fs-sm); }

/* The two "search options" rows at the top of the dropdown: search everything, or search
   inside the agent you are already looking at. */
.tb-search__opt { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 9px; align-items: center; }
.tb-search__opt .tb-search__t { font-weight: 500; color: var(--t2); }
.tb-search__opt .tb-search__t b { font-weight: 650; color: var(--t1); }
.tb-search__oico { display: grid; place-items: center; width: 20px; height: 20px; color: var(--t4); }

/* The answer, on the results page. Same block the dropdown shows — one query, one story, told
   at two densities rather than two features that disagree. */
/* A single agent's table stands alone inside its section, so it keeps the card. */
/* The card is now the WRAPPER, not the table. It used to be the table itself with
   overflow:hidden for the rounded corners — which clipped the last column's header mid-word once
   the money block made the table wider than the panel. The wrapper scrolls horizontally instead,
   so a wide result set is reachable rather than truncated. */
.sr__sec > .sr__tblwrap {
  border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface);
  overflow-x: auto; overflow-y: hidden;
}
.sr__tblwrap { max-width: 100%; }

/* The name column carries a title AND an address subtitle. Without a floor it collapses to the
   narrowest thing the money columns leave over, and a two-word customer name wraps down six
   lines while five figures sit on one. */
.sr__tbl td:first-child, .sr__tbl th:first-child { min-width: 210px; }
.sr__tbl td:first-child { padding-right: 18px; }
.sr__sub2 { text-wrap: pretty; }

/* Question-driven columns. Figures stay tabular so digits line up down the page — that is the
   entire reason the column is there — but header and value are CENTRED together (Donnelly,
   2026-08-24). They used to disagree: left-aligned headers over right-aligned numbers, so with
   five money columns the label sat at one end of the cell and its figures at the other, and
   reading across a row meant guessing which heading a number belonged to. Matching them is what
   was actually being asked for. Name, Status and Date keep their left edge. */
.sr__num { white-space: nowrap; color: var(--t2); font-variant-numeric: tabular-nums;
           text-align: center; }
.sr__num--n { text-align: center; }
.sr__tbl th.sr__th--fact { text-align: center; }
.sr__tbl th:has(button[data-sort]:not([data-sort="title"])) { white-space: nowrap; }

/* A figure borrowed from the run for the SAME job — an assessment showing the money from its
   proposal. Footnoted, because the figure is true of the job but was not produced by the run on
   this row, and an unmarked cost on an assessment reads as something the assessment measured.
   A dagger and a caption under the table, which explains itself on sight. The first attempt was
   a bare dot with `cursor: help`; it communicated nothing until a slow native tooltip appeared,
   and the '?' pointer reads as an error rather than as a note. */
.sr__lent__m { color: var(--t4); margin-left: 2px; vertical-align: super; font-size: 0.75em; }
.sr__tblnote {
  padding: 8px 2px 0; font-size: var(--fs-xs); color: var(--t4); line-height: 1.45;
}
.sr-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
              overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.sr__none { color: var(--t4); }

/* ── Cost split (document-package result) ─────────────────────────────────────
   Donnelly asked for a financial visual here, and for it to be built the way the
   proposal's is: same Chart.js pipeline, same CD_COLORS, same KPI tiles, same
   hover-linking, same theme observer. Only the chart TYPE differs — a horizontal
   stacked bar instead of a ring.

   That is also what keeps the two screens apart. The figures are identical (OBR
   equals customer cost on all 31 packages in the workspace, so there is no fourth
   number here), so the separation has to be geometry: linear, not radial. Colour
   stays the donut's, because it encodes the same two parties and re-hueing per
   screen would be the real confusion. */
.cost-donut--bar { flex-direction: column; align-items: stretch; justify-content: center;
                   gap: 18px; width: 100%; }
/* A DEFINITE width, not a percentage. The 3-up centre column is `auto` — sized to its
   content — so `width:100%` there is circular: Chart.js (responsive) grows the canvas to the
   container, the container grows to the canvas, and the card walks off the screen. The donut
   never hits this because .cd-chart is a fixed 176px square. Same treatment here. */
@media (min-width: 900px) { .fgrid--3 .util--chart .cost-donut--bar { width: 360px; } }
/* Wide and short, where the donut's canvas is square. The canvas is taken OUT of flow so it
   can never feed its own measurement back into the container. */
.cost-donut--bar .cd-chart { position: relative; width: 100%; height: 56px; flex: none; }
.cost-donut--bar .cd-chart canvas { position: absolute; inset: 0; }
/* Tiles stack full-width beneath the bar rather than sitting beside it. */
.cost-donut--bar .cd-kpis { flex-direction: column; flex-wrap: nowrap; align-items: stretch;
                            gap: 14px; }
/* The anchor figure, which the donut carries inside its ring and a bar has no inside for. */
.cd-bartotal { display: flex; flex-direction: column; gap: 2px; }
.cd-bartotal .cd-total-v { font-size: var(--fs-2xl); font-weight: 650; color: var(--t1);
                           line-height: 1.05; }
.cd-bartotal .cd-total-k { font-family: var(--mono); font-size: var(--fs-2xs);
                           letter-spacing: .06em; text-transform: uppercase; color: var(--t4); }
/* The 3-up centre column is `auto`, i.e. sized to content. The donut fills it because its
   canvas is a fixed 176px; a bar has no intrinsic width, so without a floor the column
   collapses to the widest tile and the chart renders as a cramped sliver between two
   full-width tables. Only inside the 3-up, so the stacked mobile layout is untouched. */

/* An area that FAILED reads differently from one that was clean — both have zero findings, and
   showing both as "no findings" reported unchecked sections of a contract as safe. */
.acc--failed { border-color: var(--warn-bd, #e6c07a); background: var(--warn-bg, #fffaf0); }
.acc-n--failed { color: var(--warn-fg, #a4650a); font-weight: 600; }

/* A fixture's own photographs, on the fixture's own row. Small and square so a strip of
   three under a line reads as evidence attached to it rather than as a gallery; the full
   grid at the bottom of the pane is still there for downloading the lot. */
.aline__ph { display: flex; gap: 6px; margin-top: var(--sp-2); flex-wrap: wrap; }
.ashot--sm { width: 56px; }
.ashot--sm .ashot__im { aspect-ratio: 1; border-radius: var(--rx-xs); overflow: hidden; }
.ashot--sm .ashot__im img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ashot--sm .ashot__im--wait { font-size: 0; }

/* ---- what the lookup found, per unit -------------------------------------------
   This was six to eight paragraphs of full-width grey prose per unit, all expanded, so
   a twelve-unit sheet was a wall nobody reads and therefore nobody checks. The content
   was right and the shape was wrong: a reviewer wants to know at a glance what is still
   open, and only sometimes wants the reasoning.
   Two labelled rows and one disclosure. Label column fixed so the values line up down
   the sheet — scanning "Still to find" across twelve units is the actual job. */
.ures { margin-top: var(--sp-2); display: flex; flex-direction: column; gap: 3px; }
.ures__r { display: grid; grid-template-columns: 104px 1fr; gap: var(--sp-2);
  align-items: baseline; font-size: var(--fs-xs); line-height: var(--lh-snug); }
.ures__k { color: var(--t4); font-weight: 600; letter-spacing: .01em; }
.ures__v { color: var(--t2); }

/* The disclosure. Quiet when shut — it must not compete with the figures above it — and
   it carries its own caret because the UA triangle sits at a different baseline in every
   browser and looked broken next to a 12px label. */
.ures__d { margin-top: 3px; }
.ures__d > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-xs); color: var(--t4); padding: 2px 0;
}
.ures__d > summary::-webkit-details-marker { display: none; }
.ures__d > summary::before {
  content: ""; width: 0; height: 0; flex: none;
  border-left: 4px solid currentColor; border-top: 3.5px solid transparent;
  border-bottom: 3.5px solid transparent; transition: transform .12s ease;
}
.ures__d[open] > summary::before { transform: rotate(90deg); }
.ures__d > summary:hover { color: var(--t2); }

/* Open: indented under the caret and ruled off, so the reasoning reads as a footnote to
   the row rather than as more row. */
.ures__p {
  margin: var(--sp-2) 0 var(--sp-2) 9px; padding-left: var(--sp-3);
  border-left: 2px solid var(--hairline);
  font-size: var(--fs-xs); line-height: var(--lh-body); color: var(--t3);
}
.ures__p p { margin: 0 0 7px; }
.ures__p p:last-child { margin-bottom: 0; }
.ures__p b { color: var(--t2); font-weight: 650; }
/* Each exemption with its own reason, as a definition list: the field reads as the term
   and the reason as its definition, which is what they are. */
.ures__na { margin: 0 0 7px; display: grid; grid-template-columns: auto 1fr; gap: 2px var(--sp-2); }
.ures__na dt { color: var(--t2); font-weight: 600; white-space: nowrap; }
.ures__na dd { margin: 0; }

/* ============================================================
   CONTRACT REVIEW — Upgrade Requirements (2026-09-29)
   Labeled upload + checklist (E.2), workflow per finding (C.1 / CAP-11), cross-references (F10),
   per-area deliverables (F5), and the Contract Summary / Deliverables tabs (D / E.2). Only reports
   carrying `framework` render any of the result-view classes below.
   ============================================================ */
.up-lbl {
  min-width: 0; width: 100%; font: inherit; font-size: var(--fs-xs); color: var(--t1);
  background: var(--surface); border: 1px solid var(--hairline-hard); border-radius: var(--rx-xs); padding: 4px 6px;
}
.up-lbl:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }
.c-upchk { margin-top: var(--sp-3); border: 1px solid var(--hairline); border-radius: var(--rx-sm); background: var(--surface); padding: 10px var(--sp-4); }
.c-upchk[hidden] { display: none; }
.c-upchk__h { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--t4); margin-bottom: 6px; }
.c-upchk__n { font-family: var(--mono); letter-spacing: 0; text-transform: none; margin-left: 6px; }
.c-upchk__list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 3px var(--sp-4); }
.c-upchk__list li { display: flex; align-items: baseline; gap: 7px; font-size: var(--fs-xs); line-height: 1.5; min-width: 0; }
.c-upchk__i { width: 12px; flex: none; text-align: center; font-weight: 800; }
.c-upchk__list li.is-ok .c-upchk__i { color: var(--ok-fg); }
.c-upchk__list li.is-miss .c-upchk__i { color: var(--t4); }
.c-upchk__l { color: var(--t1); font-weight: 600; flex: none; }
.c-upchk__list li.is-miss .c-upchk__l { color: var(--t3); }
.c-upchk__w { color: var(--t4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.c-upchk__note { margin: 8px 0 0; font-size: var(--fs-xs); color: var(--t3); line-height: var(--lh-snug); }

/* workflow row under a finding's triage */
.c-wf { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 8px; }
.c-wf.is-saving { opacity: .55; pointer-events: none; }
.c-wf__st, .c-sel {
  font: inherit; font-size: var(--fs-xs); font-weight: 600; color: var(--t1); cursor: pointer;
  background: var(--surface); border: 1px solid var(--hairline-hard); border-radius: var(--rx-xs); padding: 3px 6px;
}
.c-wf__st[data-st="Done"] { color: var(--ok-fg); border-color: var(--ok-line); background: var(--ok-bg); }
.c-wf__st[data-st="In Progress"] { color: var(--warn-fg); border-color: var(--warn-line); background: var(--warn-bg); }
.c-wf__st[data-st="Overdue"] { color: var(--bad-fg); border-color: var(--bad-line); background: var(--bad-bg); }
.c-wf__who, .c-inp {
  font: inherit; font-size: var(--fs-xs); color: var(--t1); background: var(--surface);
  border: 1px solid var(--hairline-hard); border-radius: var(--rx-xs); padding: 4px 8px;
}
.c-wf__who { flex: 0 1 180px; min-width: 120px; }
.c-wf__st:focus, .c-sel:focus, .c-wf__who:focus, .c-inp:focus { outline: none; border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }
.c-inp:disabled, .c-sel:disabled { opacity: .5; cursor: not-allowed; }

/* a cross-reference: one line, pointing at the primary finding */
.finding.c-xref { padding: 8px var(--sp-3); }
.c-xref__link {
  display: flex; align-items: baseline; gap: 8px; width: 100%; min-width: 0; text-align: left;
  border: 0; background: none; padding: 0; font: inherit; font-size: var(--fs-xs); color: var(--t3); cursor: pointer;
}
.c-xref__own { color: var(--t2); font-weight: 600; flex: none; }
.c-xref__lbl { color: var(--acc); font-weight: 650; flex: none; }
.c-xref__sum { color: var(--t4); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.c-xref__link:hover .c-xref__lbl { text-decoration: underline; }
.c-xref__link:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
@keyframes cflash { 0% { box-shadow: inset 3px 0 0 var(--acc); background: var(--acc-dim); } 100% { box-shadow: inset 3px 0 0 transparent; background: transparent; } }
.finding.c-flash { animation: cflash 1.8s var(--ease-out); }

/* source references and finding links as quiet inline buttons */
.c-srcbtn, .c-flink {
  border: 0; background: none; padding: 0; font: inherit; color: var(--acc); cursor: pointer; text-align: left;
}
.c-srcbtn { font-family: var(--mono); font-size: var(--fs-2xs); }
.c-flink { font-weight: 650; }
.c-srcbtn:hover, .c-flink:hover { text-decoration: underline; }
.c-srcbtn:focus-visible, .c-flink:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.c-dim { color: var(--t4); }

/* F5: an area's deliverables, after its findings */
.c-adlv { margin-top: var(--sp-2); padding-top: var(--sp-2); border-top: 1px dashed var(--hairline); }
.c-adlv__h { font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--t4); margin-bottom: 4px; }
.c-adlv__row { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; padding: 5px 0; font-size: var(--fs-xs); border-top: 1px solid var(--hairline-soft); }
.c-adlv__row:first-of-type { border-top: 0; }
.c-adlv__d { color: var(--t1); flex: 1 1 200px; min-width: 0; }
.c-adlv__due { color: var(--t3); }

/* Findings / Contract Summary / Deliverables tabs (same vocabulary as the Review ↔ Redline toggle) */
.c-rtabs, .c-seg { display: inline-flex; background: var(--mute-bg); border: 1px solid var(--hairline); border-radius: var(--rx-pill); padding: 3px; }
.c-rtabs { margin: 0 0 var(--sp-3); }
.c-rtabs[hidden] { display: none; }
.c-rtab {
  font: inherit; font-size: var(--fs-xs); font-weight: 650; cursor: pointer; padding: 5px 14px;
  border: 0; background: transparent; color: var(--t3); border-radius: var(--rx-pill);
  display: inline-flex; align-items: center; gap: 6px; transition: color .15s, background .15s;
}
.c-rtab:hover { color: var(--t1); }
.c-rtab.is-on { color: var(--t1); background: var(--surface); box-shadow: var(--elev-1, 0 1px 2px rgba(0,0,0,.08)); }
.c-rtab:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }
.c-tabpane { border: 1px solid var(--hairline); border-radius: var(--rx); background: var(--surface); padding: var(--sp-4); box-shadow: var(--elev-1); }
.c-pane__h { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; margin-bottom: var(--sp-3); }
.c-pane__h h2 { font-size: var(--fs-lg); font-weight: 650; letter-spacing: -0.01em; }
.c-pane__sub { font-size: var(--fs-sm); color: var(--t3); margin-top: 3px; }
.c-pane__tools { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.c-tabpane .elig__section { margin-top: var(--sp-4); }

/* Contract Summary tables */
.c-sumtbl td, .c-regtbl td { padding: 10px var(--sp-3); vertical-align: top; font-size: var(--fs-xs); line-height: var(--lh-snug); }
.c-sum__item { color: var(--t2); font-weight: 600; min-width: 140px; }
.c-sum__req { min-width: 200px; }
.c-sum__src { white-space: nowrap; }
.c-sumtbl tr.c-vs-muted td.c-sum__req { color: var(--t4); font-style: italic; }
.c-sumtbl tr.c-vs-warn td.c-sum__req { color: var(--warn-fg); font-weight: 600; }
.c-sum__m { font-size: var(--fs-sm); color: var(--t3); padding: var(--sp-2) 0; }
.c-partl { padding: var(--sp-2) 0; }
.c-partl__h { font-size: var(--fs-xs); font-weight: 700; color: var(--t2); margin: var(--sp-3) 0 6px; }
.c-partl__h:first-child { margin-top: 0; }
.c-risks, .c-partl__list { margin: 0; padding-left: 20px; font-size: var(--fs-sm); color: var(--t2); line-height: var(--lh-snug); }
.c-risks li, .c-partl__list li { margin-bottom: 8px; }
.c-risks__r { display: inline; }

/* Deliverables Register */
.c-regtbl table { min-width: 1280px; }
.c-reg__d { color: var(--t1); font-weight: 600; min-width: 180px; }
.c-reg__st { white-space: nowrap; }
.c-reg__st .c-dl-od { margin-left: 6px; }
.c-dl-od[hidden] { display: none; }
.c-regtbl .c-dl-who { width: 130px; }
.c-regtbl .c-dl-due { width: 140px; }

@media (min-width: 1341px) {
  /* Focus mode: the tab panes take the leftover height and scroll inside, like the redline tab. */
  .app.contract-focus .c-tabpane:not([hidden]) { flex: 1; min-height: 0; overflow-y: auto; }
}

/* ---- the projects board ---------------------------------------------------------
   A grid, not a table, because the columns must line up down the page: the job people
   actually do here is scanning ONE stage across every project ("who is waiting on an
   auditor"), far more often than reading one project across its stages. Fixed stage
   columns, a flexible name, and the action pinned right. */
.pj-board { display: grid; grid-template-columns: minmax(200px, 1.4fr) repeat(5, 96px) minmax(170px, auto);
  align-items: stretch; border: 1px solid var(--hairline); border-radius: var(--rx);
  background: var(--surface);
  /* `clip`, NOT `hidden`, and that one word is why the sticky header did not stick.
     `overflow: hidden` makes this element a SCROLL CONTAINER — scrolling is merely
     disabled on it — so a sticky descendant takes the board as its scrollport and sticks
     to a box that never moves. The page scrolls in `.main` (console-base.css: the shell
     sets `body { overflow: hidden }` and gives `.main` the `overflow-y: auto`), and the
     header has to reach that one. `clip` gives the same corner clipping without
     establishing a scrollport, so the header now sticks to the pane that actually
     scrolls. It was here to round the grid's children to the card radius; it still
     does. */
  overflow: clip; }
.pj-row { display: contents; }
.pj-row > * { padding: 11px var(--sp-3); border-top: 1px solid var(--hairline-soft);
  display: flex; align-items: center; min-width: 0; }
.pj-row--head > * { border-top: 0; background: var(--surface-sub); color: var(--t4);
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.pj-job { flex-direction: column; align-items: flex-start; gap: 1px; }
.pj-job b { font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.pj-nm { font-size: var(--fs-xs); color: var(--t3); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.pj-cell { justify-content: center; font-size: 15px; line-height: 1; }
.pj-cell[role="button"] { cursor: pointer; }
.pj-cell[role="button"]:hover, .pj-cell[role="button"]:focus-visible {
  background: var(--surface-sub); outline: none; }
/* State reads from the GLYPH first and colour second, so it survives a mono screen, a
   projector, and the ~8% of men who will be looking at this. */
.pj--none  { color: var(--t4); opacity: .45; }
/* A skipped stage reads as a struck-through gap rather than a faint dot: the job went
   past it and nobody is going back, which is a different fact from "not started yet". */
.pj--skip  { color: var(--t4); opacity: .3; font-weight: 600; letter-spacing: -.04em; }
.pj--wait  { color: #B4791A; }
.pj--run   { color: var(--t3); }
.pj--ready { color: var(--acc); }
.pj--done  { color: var(--acc); opacity: .55; }
.pj--fail  { color: #C0392B; }
.pj-next { justify-content: flex-end; gap: var(--sp-2); font-size: var(--fs-xs); }
.pj-find { max-width: 260px; }
.pj-loose { margin-top: var(--sp-6); }
.pj-note { font-size: var(--fs-xs); color: var(--t3); line-height: var(--lh-body);
  margin: 0 0 var(--sp-3); max-width: 76ch; }
@media (max-width: 900px) {
  .pj-board { grid-template-columns: minmax(140px, 1fr) repeat(5, 54px) auto; }
  .pj-nm { display: none; }
}

/* The board's toolbar. It borrowed .ares-act, which is a COLUMN built for the audit
   pane's stacked status pill and buttons — so the search box and Refresh stacked, and
   the input kept the browser's default width and clipped its own placeholder. */
.pj-act { display: flex; align-items: center; gap: var(--sp-2); }
.pj-search { position: relative; display: flex; align-items: center; }
.pj-search svg { position: absolute; left: 11px; color: var(--t4); pointer-events: none; }
.pj-search input {
  width: 280px; padding: 9px 12px 9px 32px;
  font: inherit; font-size: var(--fs-sm); color: var(--t1);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--rx-sm); outline: none;
}
.pj-search input::placeholder { color: var(--t4); }
.pj-search input:focus { border-color: var(--acc); box-shadow: 0 0 0 3px var(--acc-dim); }
/* Safari draws its own clear button AND a magnifier; we have a magnifier already. */
.pj-search input::-webkit-search-decoration { -webkit-appearance: none; }
@media (max-width: 760px) { .pj-search input { width: 170px; } }

/* PROPOSAL and AGREEMENT ran into each other — "PROPOSALAGREEMENT" with no gap. Two
   causes, both mine: the stage columns were 96px, which at 11px uppercase with 0.06em
   tracking is narrower than the word AGREEMENT needs; and the header cells never got the
   `justify-content: center` the dot cells have, so the labels sat hard left against the
   next column while the dots below them were centred. Both fixed; the labels also wrap
   now, because "Utility bills" and "Field audit" read better on two lines than squeezed
   onto one. */
.pj-board { grid-template-columns: minmax(200px, 1.4fr) repeat(5, 124px) minmax(170px, auto); }
.pj-row--head > * { justify-content: center; text-align: center; line-height: 1.25; }
.pj-row--head > .pj-job { justify-content: flex-start; text-align: left; }
.pj-row--head > .pj-next { justify-content: flex-end; text-align: right; }
/* `overflow-wrap: anywhere` was mine and it was wrong here: it let the browser break
   INSIDE a word the moment it would overflow, so the headers read PROPOSA/L and
   AGREEME/NT. A column label that breaks mid-word is worse than one that is clipped —
   it looks like a different word. Wrap between words only, and give the columns the
   room AGREEMENT actually needs at 11px with 0.06em tracking. */
.pj-cell { white-space: normal; overflow-wrap: normal; word-break: keep-all; hyphens: none; }
/* 6px is for the STAGE labels only — they are narrow columns where the long words need
   the room. Applied to every header cell, as it was, it also squeezed JOB and ACTION to
   6px while their own rows sat at 12px, so the header text hung further out than the
   content beneath it and ACTION ended up against the card edge. First and last columns
   now share one generous inset, header and rows alike, so the two edges line up. */
.pj-row--head > .pj-cell { padding-left: 6px; padding-right: 6px; }
.pj-job, .pj-next { padding-left: var(--sp-4); padding-right: var(--sp-4); }
@media (max-width: 900px) {
  .pj-board { grid-template-columns: minmax(140px, 1fr) repeat(5, 62px) auto; }
}

/* The DN badge is an editable control, not a label — a number typed onto the wrong run
   has to be correctable, and a dash with no affordance just tells you something is
   missing without offering to fix it. */
.pj-dn { cursor: pointer; border-bottom: 1px dashed var(--hairline); }
.pj-dn:hover, .pj-dn:focus-visible { color: var(--acc); border-bottom-color: var(--acc);
  outline: none; }
/* "2 runs on this stage" — the board shows the latest and admits there were others. */
.pj-n { font-size: 9px; font-weight: 700; color: var(--t4); margin-left: 2px; top: -6px;
  position: relative; }

/* ---- the board, as a worklist -------------------------------------------------
   ONE header per table, and it sticks. It was two stacked bands — a section title, then
   a column row — spending ~90px to say what one line says, and the column labels
   scrolled away exactly when a list long enough to need them appeared. */
.pj-row--head > * {
  position: sticky; top: 0; z-index: 3;
  background: var(--surface-sub);
  border-bottom: 1px solid var(--hairline);
}
/* The corners are the header's own, not the card's. They were coming from
   `.pj-board { overflow: clip }`, which only rounds what sits AT the corner — so the
   moment the header detached and stuck mid-scroll, it squared off and the bar changed
   shape under the cursor. Owning the radius makes it look identical at rest and stuck. */
.pj-row--head > .pj-job  { border-top-left-radius: var(--rx); }
.pj-row--head > .pj-next { border-top-right-radius: var(--rx); }
/* The header's job cell is a ROW. `.pj-job` is a column flex because a DATA row stacks
   the DN over the site name — but the header puts a title beside a count, and inheriting
   the column direction stacked them instead, which both made the sticky band two lines
   taller than it needed to be and left the count orphaned under the heading. The count
   also carries `margin-left: auto` from .psec__n, which does nothing in a column and
   would shove it into the middle of a wide column if it did; it sits next to the words,
   where it reads as part of the heading. */
/* ONE TREATMENT FOR EVERY HEADER CELL. The job cell was set in dark sentence case at
   13px while its neighbours were 11px grey caps, because it started life as a section
   title in a band of its own and kept that styling when the two bands merged. The result
   was a header row where one cell shouted and six whispered — the eye reads it as a
   title with some labels stuck to it rather than as one row of column names. It is a
   column name now, like the rest; the base `.pj-row--head > *` rule supplies the caps,
   size, colour and tracking, so there is one place to change them. */
.pj-row--head > .pj-job { flex-direction: row; align-items: center; gap: var(--sp-2); }
.pj-row--head > .pj-job .psec__n { margin-left: 0; }
.pj-board--loose { margin-top: var(--sp-6); }

/* The filter rail. Three rows out of 395 need you today; without this the board is
   somewhere to scroll and the question it exists to answer takes longer than opening
   four agents by hand. Counts are always visible, so an empty bucket is information. */
.pj-rail { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.pj-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 11px; font: inherit; font-size: var(--fs-xs); color: var(--t2);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--rx-pill); cursor: pointer;
}
.pj-chip span { font-variant-numeric: tabular-nums; font-weight: 650; color: var(--t4); }
.pj-chip:hover:not(:disabled) { border-color: var(--t4); }
.pj-chip.on { background: var(--ink, #11182A); border-color: transparent; color: #fff; }
.pj-chip.on span { color: rgba(255,255,255,.65); }
.pj-chip:disabled { opacity: .4; cursor: default; }

/* Age on the frontier stage. A date cannot be read at a glance; "9d" can, and a board
   whose job is showing what has STOPPED has to answer "for how long" without being
   asked. Amber past a fortnight with the auditor — that is a chase, not a status. */
.pj-age { font-size: var(--fs-2xs); color: var(--t4); font-variant-numeric: tabular-nums;
  white-space: nowrap; }
.pj-age--stale { color: #B4791A; font-weight: 650; }
.pj-nm i { font-style: normal; color: var(--t4); }

/* Editing a DN in place. This replaced a window.prompt() — a grey OS dialog dropped into
   the middle of a product, which loses the row you were looking at, cannot carry a hint
   and cannot show that a save is in flight. */
.pj-dnedit {
  width: 110px; padding: 4px 7px; font: inherit; font-size: var(--fs-sm); font-weight: 600;
  color: var(--t1); background: var(--surface);
  border: 1px solid var(--acc); border-radius: var(--rx-xs); outline: none;
  box-shadow: 0 0 0 3px var(--acc-dim);
  font-variant-numeric: tabular-nums; text-transform: uppercase;
}
.pj-dnhint { font-size: var(--fs-2xs); color: var(--t4); margin-top: 2px; }
.pj-dnsaving { font-size: var(--fs-xs); color: var(--t4); }
/* The search box widens as the thing it searches grows — it now matches address, owner,
   stage state and summary, not just a DN. */
.pj-search input { width: 320px; }

/* The frozen top: title, search, filter rail. Same recipe as .pnl-sticky, including the
   ::before — `.main` is the scroll container and it has `padding: var(--shell-pad)`, so
   without something painting that strip, rows slide up THROUGH it and appear above the
   header. That gap is what "stuff above the header" was. */
.pj-sticky {
  /* 5, NOT 20. The account menu lives inside `.topbar`, which carries `z-index: 20` and
     therefore creates a stacking context — so the menu's own `z-index: 60` is scored
     against its siblings INSIDE the topbar, not against the page. At 20 this bar tied
     with the topbar and won on DOM order, which no z-index on the menu could ever
     overcome: it was trapped in a context that had already lost. This bar only has to
     beat the table under it (header cells are 3), so it sits well below the chrome. */
  position: sticky; top: 0; z-index: 5;
  background: var(--canvas); padding-bottom: var(--sp-3);
}
.pj-sticky::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 100%;
  height: var(--shell-pad); background: var(--canvas);
}
.pj-sticky .top { margin-bottom: var(--sp-3); }
.pj-rail { margin-bottom: 0; }
/* ...and the column header stops just below it. --pj-top is measured in console.js,
   because the rail wraps at narrow widths and a hard-coded offset would either float the
   header or hide a row under it. */
.pj-row--head > * { top: var(--pj-top, 0px); z-index: 3; }

/* .pj-when is gone with the Refresh button it existed to explain. The board refetches
   itself now, so a "read 2 mins ago" stamp is churn rather than information. */
