/* Cairn operating UI — design system (CV-2).
 * Extracted from the operator-signed-off mockups
 * (docs/jules/strategy/cairn-sentinel/ui_mockups/screen-1, screen-2).
 * Visual language per cairn_ui_design.md §5: neutral, dense, calm; authority
 * levels colour-coded consistently; confidence rendered as value + n, never bare.
 * Served as a static 'self' asset (helmet CSP); no external fonts/CDN. */

:root {
  /* MEMRY brand tokens (memry.dev): ink text, orange accent, warm paper. */
  --memry-ink: #1E2A32;
  --memry-accent: #D85A30;
  --memry-accent-dark: #E8794A;
  --memry-accent-tint: #FBE7DD;
  --memry-paper: #F5F3EE;
  --color-background-primary: #ffffff;        /* white cards (kept for contrast) */
  --color-background-secondary: #EFEBE2;       /* warm neutral surface (paper-tint) */
  --color-background-tertiary: #E7E1D5;
  --color-background-info: #e6f1fb;
  --color-text-primary: #1E2A32;               /* brand ink */
  --color-text-secondary: #5f5e5a;
  --color-text-tertiary: #888780;
  --color-border-tertiary: rgba(30, 42, 50, 0.10);
  --color-border-secondary: rgba(30, 42, 50, 0.18);
  --color-border-primary: rgba(30, 42, 50, 0.28);
  --color-accent: #D85A30;                      /* brand accent (orange) */
  --color-accent-dark: #E8794A;
  --color-danger: #A32D2D;
  --color-warn: #854F0B;
  --color-ok: #3B6D11;
  /* Dark chrome scale — the header band. Multiple shades of dark slate anchored on
     the brand ink (#1E2A32), restoring the wow-mockup's "multiple shades of dark
     grey" header. The orange accent reads as a signal against this slate. */
  --chrome-deep: #141B21;                        /* deepest — chrome edges (top bar / sidebar rail) + the inset chrome chips */
  --chrome-base: #1E2A32;                        /* brand ink — main header fill */
  --chrome-raise: #2C3A44;                       /* raised — nav hover / active fill */
  --chrome-text: #AEB9C0;                        /* muted light text on chrome */
  --chrome-text-strong: #FFFFFF;
  --chrome-border: rgba(255, 255, 255, 0.09);
  --topbar-h: 56px;                              /* top-bar height (sidebar sticks below it) */
  --sidebar-w: 248px;
  --border-radius-md: 8px;
  --border-radius-lg: 12px;
  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'SF Mono', 'Fira Code', ui-monospace, Menlo, monospace;
  /* MEMRY brand face (self-hosted Space Grotesk, OFL). Display layer — headings,
     panel titles, nav, vital numbers, the brand chrome. Dense body/tables keep the
     system sans for legibility at 11–13px (operator tunes body-vs-heading live). */
  --font-display: 'Space Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  /* Soft elevation for white cards — depth + hierarchy over the flat 0.5px borders. */
  --shadow-card: 0 1px 2px rgba(30, 42, 50, 0.04), 0 2px 6px rgba(30, 42, 50, 0.06);
  --shadow-card-hover: 0 2px 6px rgba(30, 42, 50, 0.07), 0 6px 18px rgba(30, 42, 50, 0.09);
}

/* --- MEMRY brand face: Space Grotesk (self-hosted woff2, OFL; CSP fontSrc 'self') --- */
@font-face {
  font-family: 'Space Grotesk'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('/font/space-grotesk-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Space Grotesk'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('/font/space-grotesk-latin-500-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Space Grotesk'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('/font/space-grotesk-latin-700-normal.woff2') format('woff2');
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  margin: 0;
  background: var(--memry-paper);
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--color-text-primary);
}

.root { padding: 20px 24px; display: flex; flex-direction: column; gap: 16px; flex: 1; min-width: 0; }

a { color: inherit; text-decoration: none; }

/* --- demo banner (DEMO mode disclosure; cairn_ui_design.md §8) --- */
.demo-banner {
  background: var(--memry-accent-tint); color: var(--memry-ink); font-size: 11px; font-weight: 500;
  text-align: center; padding: 5px 12px; letter-spacing: 0.02em;
  border-bottom: 0.5px solid #F3C9B5;
}
/* The demo visitor's two doors — sign up, or walk the tour the front door no longer opens onto.
   The base rule `a { color: inherit; text-decoration: none; }` at the head of this file would
   otherwise render both as plain banner text, i.e. present in the DOM and invisible to a reader,
   which is the failure mode worth naming: the conversion path would be "shipped" and unusable.
   The CTA is underlined and heavier; the tour link is quieter, because it is no longer the main
   event. Both are inline so the centred banner stays one line. */
.demo-banner-cta, .demo-banner-walk { margin-left: 10px; text-decoration: underline; }
.demo-banner-cta { font-weight: 700; text-underline-offset: 2px; }
.demo-banner-walk { font-weight: 500; opacity: 0.75; }
.demo-banner-cta:hover, .demo-banner-walk:hover { opacity: 1; text-decoration-thickness: 2px; }

/* --- app shell: dark top bar (full-bleed) + dark left sidebar (Glean/Notion/Linear) --- */
/* The top bar is a slim slate band across the top: brand white-lockup at the left
   (over the sidebar column), global search in the middle, the governance dividend at
   the right. The sidebar is a dark full-height rail holding the primary nav. Both
   wear the multi-shade `--chrome-*` slate + Space Grotesk + orange-accent active. */
.topbar { background: var(--chrome-base); border-bottom: 1px solid var(--chrome-deep);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.35), 0 4px 14px rgba(20, 27, 33, 0.18);
  position: sticky; top: 0; z-index: 40; }
.topbar-inner { padding: 0 20px; min-height: var(--topbar-h);
  display: flex; align-items: center; gap: 18px; }
.topbar-spacer { flex: 1; }
.brand { display: inline-flex; align-items: center; }
.brand-logo { display: block; height: 22px; width: auto; } /* MEMRY white lockup on dark chrome; min lockup width ~96px per brand guide */

/* Global search in the top bar (the ⌘K / Glean affordance). Plain GET form → /search
   (works JS-absent); the token rides a hidden field. ⌘K focus is progressive (app.js). */
.topbar-search { position: relative; display: flex; align-items: center; }
.topbar-search input { width: 300px; max-width: 38vw; background: var(--chrome-deep);
  border: 1px solid var(--chrome-border); color: var(--chrome-text-strong); border-radius: 8px;
  padding: 7px 36px 7px 12px; font-family: var(--font-sans); font-size: 12.5px; }
.topbar-search input::placeholder { color: var(--chrome-text); }
.topbar-search input:focus { outline: none; border-color: var(--color-accent); background: #10161B; }
.kbd-hint { position: absolute; right: 8px; pointer-events: none; font-family: var(--font-display);
  font-size: 10px; font-weight: 500; color: var(--chrome-text); border: 1px solid var(--chrome-border);
  border-radius: 4px; padding: 1px 5px; }

.app-shell { display: grid; grid-template-columns: var(--sidebar-w) minmax(0, 1fr); align-items: start; }
.app-main { min-width: 0; display: flex; flex-direction: column; }
.sidebar { background: var(--chrome-base); border-right: 1px solid var(--chrome-deep);
  position: sticky; top: var(--topbar-h); height: calc(100vh - var(--topbar-h)); overflow-y: auto;
  padding: 14px 12px; display: flex; flex-direction: column; }
.side-nav { display: flex; flex-direction: column; gap: 2px; }
.side-link { display: flex; align-items: center; gap: 11px; padding: 9px 12px;
  font-family: var(--font-display); font-size: 13px; font-weight: 500; color: var(--chrome-text);
  border-radius: 8px; transition: background 0.12s, color 0.12s; }
.side-link:hover { background: var(--chrome-raise); color: var(--chrome-text-strong); }
.side-link.active { color: var(--chrome-text-strong); background: rgba(216, 90, 48, 0.16); box-shadow: inset 2px 0 0 var(--color-accent); }
.side-link .node-icon { color: inherit; flex-shrink: 0; }
.side-label { flex: 1; }
.side-link .badge { margin-left: auto; }
/* Memry W4 Slice C -- the logout control lives at the sidebar foot (the topbar is at capacity).
   .side-foot pins it to the bottom; the button is reset to render as a .side-link. */
.side-foot { margin-top: auto; padding-top: 8px; }
.side-logout { width: 100%; background: transparent; border: 0; cursor: pointer; font: inherit; }
/* Memry W4 Slice C-2 -- "Signed in as <email>" identity at the sidebar foot, above the logout
   button. Muted small chrome text (same tokens as .side-link, so it flips correctly in both
   themes); a long email truncates with an ellipsis (the title= carries the full value) so it
   never breaks the fixed sidebar width. */
.side-identity { padding: 4px 12px 6px; font-family: var(--font-display); font-size: 11px;
  color: var(--chrome-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-identity-email { color: var(--chrome-text-strong); font-weight: 500; }

/* --- governance dividend cluster (A3; design §2/§3) — NOT THE TOP BAR ANY MORE: doc 05 §3.4
   moved it into Home's "What MEMRY caught for you" band (render/home.js — caughtDividend,
   wrapping render/components.js — dividendCluster). See the FIX B block below. --- */
/* Three honest audit-derived counts; the whole cluster drills to /audit. Calm,
   dense, monospace numerals so it reads as a measured scoreboard, not a banner. */
/* ⛔ AND ITS LIVERY IS THE PANEL'S, NOT THE CHROME'S, BECAUSE THE §3.4 MOVE CHANGED THE
   SURFACE UNDERNEATH IT. These rules were authored for the dark slate bar — --chrome-text on
   --chrome-deep, a white-alpha separator, the #10161B chrome hover — and the cluster now
   renders in exactly ONE place: inside a .panel on the light paper canvas (dividendCluster has
   a single call site, render/home.js caughtDividend). Left on the chrome palette it drew a
   dark pill on a light band.
   ⚑ THE HIERARCHY IS PRESERVED, ONLY THE PALETTE MOVED: the chrome livery was a muted label
   text with a STRONG figure (--chrome-text / --chrome-text-strong), and the panel livery is
   the same two tiers in the canvas tokens (--color-text-secondary / --color-text-primary). The
   pill takes the SECONDARY (inset) surface because the enclosing .panel is the PRIMARY one —
   the .rec-tile / .vital / .cmt-party idiom — and hover is .hcaught-row's own hover fill, so
   the strip lifts the same way the rows beneath it do. Every value is a semantic token, so
   both themes flip with no per-theme override and no raw hex.
   ⛔ THE BARE SELECTOR IS RIGHT AND MUST NOT BE NARROWED to `.hcaught-dividend .dividend`.
   There is no second surface left to protect (measured: dividendCluster's one call site above,
   and class="dividend" is emitted from that function alone), so scoping would buy nothing and
   would tell the next reader a dark instance still exists somewhere. The ONE scoped rule is the
   1080px `.topbar .dividend` guard below, scoped for the opposite reason — see its own note. */
.dividend { display: inline-flex; align-items: center; gap: 7px; font-size: 11px;
  color: var(--color-text-secondary); background: var(--color-background-secondary);
  border: 1px solid var(--color-border-tertiary); border-radius: var(--border-radius-md);
  padding: 5px 11px; white-space: nowrap; transition: border-color 0.12s, background 0.12s; }
.dividend:hover { background: var(--color-background-tertiary); border-color: var(--color-accent); }
.dividend .dv { display: inline-flex; align-items: baseline; gap: 4px; }
.dividend .dv b { font-family: var(--font-display); font-weight: 600; font-size: 12px; color: var(--color-text-primary); font-variant-numeric: tabular-nums; }
/* The interpunct is decorative (aria-hidden) and must stay quieter than the label it separates:
   --color-text-tertiary is the tone .breadcrumb-path's own separator and .hcaught-time take. */
.dividend .dv-sep { color: var(--color-text-tertiary); }
.dividend .dv-arrow { color: var(--color-accent-dark); font-size: 11px; margin-left: 1px; }

/* FIX B (OCCm9 papercut) — narrow-width topbar leak: below ~1080px the fixed topbar cluster
   (search + Add/Update/Catch-up/Ask + the ~243px governance dividend + toggle) overruns the
   viewport, forcing a PAGE-level horizontal scroll on every screen (probe @900px: dividend
   right=980, toggle right=1032 vs clientWidth 900). Drop the governance dividend — the standard
   responsive tradeoff: it is a portfolio nicety (its counts stay on /audit), not a primary control
   — and let the search flex-shrink, so the cluster fits (post-drop it ends ~771px @900px).

   ⛔ THE MEASUREMENT ABOVE IS HISTORY, AND THE RULE IS NOW TOP-BAR-SCOPED. Its whole rationale is
   a TOP-BAR overrun, and doc 05 §3.4 took the cluster out of the top bar — but the selector was
   the bare .dividend, which matches the element WHEREVER it renders. Home's band emits that same
   class (render/home.js — caughtDividend), so below 1080px this rule was deleting the proof
   surface from Home, the "N catch-ups" figure included, at every laptop width. Scoped to a
   dividend INSIDE the top bar it buys back exactly what the probe paid for and nothing else. It is
   KEPT rather than deleted though it matches nothing today (layout.js — page() emits no cluster):
   the overrun is a property of that bar's CONTENTS, so the guard outlives this one tenant. */
@media (max-width: 1080px) {
  .topbar .dividend { display: none; }
  .topbar-search { min-width: 0; }
}

/* --- in-project chrome: body + persistent governance feed rail (design §2 D1) --- */
/* Two-column grid; the main column gets min-width:0 so its inner grids (zones,
   tables) reflow instead of overflowing when the rail claims the right edge. */
.proj-chrome { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 16px; align-items: start; }

/* Responsive: collapse the sidebar to an icon rail + stack the in-project rail. The
   live walk is desktop-width (SSH tunnel), so this is a safety net, not the target. */
@media (max-width: 1100px) {
  .app-shell { grid-template-columns: 64px minmax(0, 1fr); }
  .sidebar { padding: 14px 8px; }
  .side-label { display: none; }
  /* Slice C-2 — the collapsed icon rail hides labels; the text identity has no place there, so
     hide it too (rather than show a truncated "Sig…" fragment). */
  .side-identity { display: none; }
  .side-link { justify-content: center; padding: 10px; gap: 0; }
  .side-link .badge { margin-left: 4px; }
  .topbar-search input { width: 180px; }
  .proj-chrome { grid-template-columns: minmax(0, 1fr); }
}
.proj-main { min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.gov-rail { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); position: sticky; top: 16px; overflow: hidden; }
.gov-rail-hdr { padding: 11px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); font-size: 11px; font-weight: 500; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.07em; }
.gov-rail-scroll { max-height: 560px; overflow-y: auto; }
.gov-rail-empty { padding: 16px; font-size: 11px; color: var(--color-text-tertiary); line-height: 1.6; }
.gov-card { display: flex; gap: 10px; padding: 11px 14px; border-bottom: 0.5px solid var(--color-border-tertiary); border-left: 2px solid transparent; }
.gov-card:last-child { border-bottom: none; }
.gov-ic { font-size: 13px; line-height: 1.3; flex-shrink: 0; width: 16px; text-align: center; }
.gov-card-body { min-width: 0; }
.gov-card-label { font-size: 12px; font-weight: 500; color: var(--color-text-primary); line-height: 1.35; }
/* FIX 3 (2026-06-28) — collapsed-group count badge ("Memory injected 8×"). */
.gov-card-count { display: inline-block; font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  color: var(--color-text-secondary); background: var(--color-background-secondary);
  border-radius: 4px; padding: 0 5px; margin-left: 2px; }
.gov-card-sum { font-size: 10px; color: var(--color-text-secondary); font-family: var(--font-mono); margin-top: 2px; word-break: break-word; }
.gov-card-time { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); margin-top: 3px; }
/* Authority-consistent kind accents (left border + icon hue). */
.gov-contradiction { border-left-color: #FAC775; } .gov-contradiction .gov-ic { color: var(--color-warn); }
.gov-blocked { border-left-color: #E0B4B4; } .gov-blocked .gov-ic { color: var(--color-danger); }
.gov-locked { border-left-color: var(--memry-ink); } .gov-locked .gov-ic { color: var(--color-text-primary); }
.gov-confirmed { border-left-color: #B7D89A; } .gov-confirmed .gov-ic { color: var(--color-ok); }
.gov-prediction { border-left-color: #B5D4F4; } .gov-prediction .gov-ic { color: var(--color-accent); }
.gov-memory { border-left-color: #B5D4F4; } .gov-memory .gov-ic { color: var(--color-accent); }

/* --- pills --- */
.pill { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 500; padding: 3px 9px; border-radius: var(--border-radius-md); }
.pill-normal { background: #EAF3DE; color: var(--color-ok); }
.pill-passthrough { background: #FAEEDA; color: var(--color-warn); }
.pill-off { background: #f0efeb; color: var(--color-text-tertiary); }
.dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; }

/* --- authority badges (principle 3: authority is a UI primitive) --- */
.auth { display: inline-flex; align-items: center; font-size: 10px; font-weight: 500; padding: 2px 6px; border-radius: 3px; font-family: var(--font-mono); white-space: nowrap; }
.auth-canonical { background: var(--memry-ink); color: #F1EFE8; }
.auth-working { background: #E6F1FB; color: #0C447C; border: 0.5px solid #B5D4F4; }
.auth-provisional { background: #FAEEDA; color: var(--color-warn); border: 0.5px solid #FAC775; }
.auth-inferred { background: transparent; color: var(--color-text-secondary); border: 0.5px dashed rgba(0, 0, 0, 0.28); }

/* --- commitment status pills --- */
.cs { font-size: 10px; font-weight: 500; padding: 2px 7px; border-radius: 3px; white-space: nowrap; }
.cs-open { background: #FAEEDA; color: var(--color-warn); }
.cs-met { background: #EAF3DE; color: var(--color-ok); }
.cs-failed { background: #FCEBEB; color: var(--color-danger); }
.cs-renegotiated, .cs-reneg { background: #E6F1FB; color: #185FA5; }

/* --- panels + tables --- */
.panel { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); display: flex; flex-direction: column; }
.panel-header { display: flex; align-items: center; justify-content: space-between; padding: 11px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.panel-title { font-size: 11px; font-weight: 500; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.07em; }
.panel-sub { font-size: 11px; color: var(--color-text-tertiary); }
/* OCCm10 — a right-aligned panel-header / topbar link to the all-discussion surface (/discussion):
   Home's Recent-discussion band "See all →" + the /inbox topbar "All discussion →". Muted by
   default, accent on hover (theme tokens flip in dark mode). .panel-hdr-end groups the sub-count +
   the link on the header's right so the space-between title|group layout stays clean. */
.panel-link { font-size: 11px; font-weight: 500; color: var(--color-text-tertiary); white-space: nowrap; }
.panel-link:hover { color: var(--color-accent-dark); }
.panel-hdr-end { display: inline-flex; align-items: baseline; gap: 10px; }

.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl th { padding: 8px 16px; text-align: left; font-size: 10px; font-weight: 500; color: var(--color-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; border-bottom: 0.5px solid var(--color-border-tertiary); }
.tbl td { padding: 10px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); vertical-align: top; line-height: 1.4; }
.tbl tr:last-child td { border-bottom: none; }
.tbl tbody tr:hover td { background: var(--color-background-secondary); }
.primary { font-weight: 500; }
.secondary { font-size: 11px; color: var(--color-text-secondary); margin-top: 2px; font-family: var(--font-mono); }
.mono { font-family: var(--font-mono); font-size: 11px; color: var(--color-text-secondary); }
.chain { font-size: 11px; color: var(--color-accent); margin-top: 2px; }
/* Drill-through id link (UR-06) — a decision id that opens its detail on the
   Decisions register. Accent colour signals interactivity; underline on hover. */
.id-link { color: var(--color-accent); text-decoration: none; }
.id-link:hover { text-decoration: underline; }
.warn-inline { font-size: 11px; color: var(--color-warn); margin-top: 2px; }
.superseded-row td { opacity: 0.5; }
.superseded-text { text-decoration: line-through; }
.overdue { color: var(--color-danger); font-weight: 500; }
.soon { color: var(--color-warn); }
.view-all { font-size: 12px; color: var(--color-accent); padding: 9px 16px; display: block; border-top: 0.5px solid var(--color-border-tertiary); text-align: center; }

/* --- empty states (cairn_ui_design.md §3.2: never a bare empty grid) --- */
.empty { padding: 18px 16px; font-size: 12px; color: var(--color-text-tertiary); line-height: 1.5; }

/* --- dashboard zones --- */
.breadcrumb { font-size: 11px; color: var(--color-text-secondary); font-family: var(--font-mono); display: flex; align-items: center; justify-content: space-between; }
.breadcrumb-path span { color: var(--color-text-tertiary); margin: 0 5px; }
.breadcrumb-path strong { color: var(--color-text-primary); }
.zone-a { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; }
.vital { background: var(--color-background-secondary); border-radius: var(--border-radius-md); padding: 12px 16px; }
.vital-label { font-size: 11px; color: var(--color-text-secondary); margin-bottom: 5px; }
.vital-value { font-size: 24px; font-weight: 500; line-height: 1; }
.vital-sub { font-size: 11px; color: var(--color-text-secondary); margin-top: 4px; }
.zone-bc { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.zone-d { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); }
.zone-d-header { display: flex; align-items: center; justify-content: space-between; padding: 11px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.zone-d-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0; }
.zone-d-col { padding: 14px 18px; border-right: 0.5px solid var(--color-border-tertiary); }
.zone-d-col:last-child { border-right: none; }
.col-title { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.07em; color: var(--color-text-tertiary); margin-bottom: 12px; }
.kv { margin-bottom: 12px; }
.kv-actor { font-size: 13px; font-weight: 500; margin-bottom: 3px; font-family: var(--font-mono); }
.kv-row { font-size: 11px; color: var(--color-text-secondary); line-height: 1.45; }
.kv-row b { color: var(--color-text-primary); font-weight: 500; }
.conf { font-family: var(--font-mono); font-size: 10px; color: var(--color-text-tertiary); }
.pred-row { margin-bottom: 12px; }
.pred-claim { font-size: 12px; line-height: 1.4; }
.pred-meta { font-size: 10px; color: var(--color-text-tertiary); margin-top: 3px; font-family: var(--font-mono); }
.outcome-confirmed { color: var(--color-ok); }
.outcome-contradicted { color: var(--color-danger); }
.outcome-partial { color: var(--color-warn); }
/* CAL-CONV-1 — 'unresolvable' is a neutral, couldn't-determine outcome (neither success
   nor failure): render it in the muted tertiary text colour already used by .pred-meta /
   .conf in this column, so it reads de-emphasised against the coloured matched/contradicted/
   partial tokens rather than unstyled (default body ink). */
.outcome-unresolvable { color: var(--color-text-tertiary); }
.surprise-row { margin-bottom: 12px; }
.stag { font-size: 10px; font-weight: 500; color: var(--color-warn); text-transform: uppercase; letter-spacing: 0.06em; }
.stext { font-size: 12px; color: var(--color-text-primary); line-height: 1.4; margin-top: 2px; }
.smeta { font-size: 10px; color: var(--color-text-tertiary); margin-top: 3px; font-family: var(--font-mono); }
/* Beat 2 (OCCm11) — the "Customize panels" affordance: a right-aligned no-JS <details> (the
   tl-addms summary-button idiom) whose body is an inline checkbox row + Save. Theme tokens only. */
.dash-settings { align-self: flex-end; }
.dash-settings > summary { list-style: none; cursor: pointer; white-space: nowrap; display: inline-flex; }
.dash-settings > summary::-webkit-details-marker { display: none; }
.dash-settings-form { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 8px;
  padding: 10px 14px; background: var(--color-background-primary);
  border: 0.5px solid var(--color-border-secondary); border-radius: var(--border-radius-md); }
.dash-set-row { display: inline-flex; align-items: center; gap: 5px; font-size: 12px;
  color: var(--color-text-primary); white-space: nowrap; cursor: pointer; }

/* --- projects home --- */
.content { display: grid; grid-template-columns: 340px 1fr; gap: 16px; align-items: start; }
.tree-panel { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); }
.tree-header { padding: 11px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); font-size: 11px; font-weight: 500; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.07em; }
.node-row { display: flex; align-items: center; padding: 9px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); cursor: pointer; }
.node-row:last-child { border-bottom: none; }
.node-row:hover { background: var(--color-background-secondary); }
.node-row.selected { background: var(--color-background-info); }
.indent1 { padding-left: 28px; }
.indent2 { padding-left: 48px; }
.node-icon { color: var(--color-text-tertiary); margin-right: 8px; flex-shrink: 0; display: inline-flex; }
.node-name { font-size: 13px; color: var(--color-text-primary); flex: 1; font-family: var(--font-mono); }
.node-name.selected { color: #042C53; font-weight: 500; }
.badge-red { background: #FCEBEB; color: var(--color-danger); font-size: 9px; font-weight: 500; padding: 2px 6px; border-radius: 3px; margin-left: 8px; }
.badge-amber { background: #FAEEDA; color: var(--color-warn); font-size: 9px; font-weight: 500; padding: 2px 6px; border-radius: 3px; margin-left: 8px; }
.vitals-panel { display: flex; flex-direction: column; gap: 14px; }
.proj-header { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: 16px 20px; }
.proj-title { font-size: 18px; font-weight: 500; margin-bottom: 4px; font-family: var(--font-mono); }
.proj-path { font-size: 11px; color: var(--color-text-secondary); font-family: var(--font-mono); margin-bottom: 12px; }
.proj-vitals-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; margin-bottom: 14px; }
.v { background: var(--color-background-secondary); border-radius: var(--border-radius-md); padding: 10px 14px; }
.v-label { font-size: 10px; color: var(--color-text-secondary); margin-bottom: 4px; }
.v-val { font-size: 18px; font-weight: 500; }
.v-sub { font-size: 10px; color: var(--color-text-secondary); margin-top: 3px; }
.connect-panel { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); }
.connect-header { display: flex; align-items: center; justify-content: space-between; padding: 11px 18px; border-bottom: 0.5px solid var(--color-border-tertiary); }
/* The block holds shell lines a reader is told to copy EXACTLY, so no break may land inside a
   token — not inside the gateway URL, not inside the quoted scope value. NO wrapping rule can
   promise that, which is why none is used. `export ANTHROPIC_BASE_URL="http://127.0.0.1:4100"`
   offers no break opportunity between the `=` and the closing quote, and that run is wider than
   this block is ever given inside a project card — so any rule permitted to wrap MUST break it
   somewhere, and only WHERE it breaks is up for negotiation. `pre` therefore declines to wrap at
   all and `overflow-x: auto` makes the overspill reachable; a select-and-copy then takes the whole
   logical line rather than a visually broken one. The newline joining the lines stays the only
   thing that separates them, exactly as under pre-wrap.

   ⚑ THE SCROLLBAR IS AN AFFORDANCE, NOT TRIM, because a line running past the right edge under a
   bar that is invisible at rest is indistinguishable from a line that ends there — and a reader
   who cannot tell that the address continues will copy a truncated one. It is therefore SIZED,
   which is what asks an engine for a bar that occupies its own strip rather than an overlay.
   `scrollbar-width` / `scrollbar-color` are deliberately NOT set alongside these: when the
   standard properties are present Chromium ignores the ::-webkit-scrollbar rules entirely, so
   declaring both would silently discard the sized bar and leave only the overlay. Engines that
   honour neither keep their own default bar, which is already a persistent one. */
.code-block { margin: 14px 18px; background: var(--color-background-secondary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); padding: 12px 14px; font-family: var(--font-mono); font-size: 11px; color: var(--color-text-primary); line-height: 1.65; position: relative; white-space: pre; overflow-x: auto; }
.code-block::-webkit-scrollbar { height: 8px; }
.code-block::-webkit-scrollbar-track { background: transparent; }
.code-block::-webkit-scrollbar-thumb { background: var(--color-border-primary); border-radius: 4px; }
.code-copy { position: absolute; top: 8px; right: 10px; font-size: 10px; color: var(--color-accent); cursor: pointer; background: var(--color-background-secondary); padding: 2px 6px; border-radius: 3px; border: 0.5px solid var(--color-border-tertiary); }
.code-comment { color: var(--color-text-tertiary); }
.code-key { color: #185FA5; }
.code-val { color: var(--color-ok); }
.connect-note { padding: 0 18px 14px; font-size: 11px; color: var(--color-text-tertiary); line-height: 1.5; }
.all-projects { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); }
.section-head { display: flex; align-items: center; justify-content: space-between; padding: 11px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.section-head .panel-title { margin: 0; }

/* Per-project cards (walkthrough 2026-06-28) — one peer card per project, no hero. */
.proj-cards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.proj-card { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: 16px 18px; display: flex; flex-direction: column; gap: 12px; }
.proj-card-head { display: flex; flex-direction: column; gap: 3px; }
.proj-card-title { font-size: 15px; font-weight: 500; font-family: var(--font-mono); color: var(--color-text-primary); }
.proj-card-title:hover { color: var(--color-accent-dark); }
.proj-card-path { font-size: 10px; color: var(--color-text-secondary); }
.proj-card-stats { display: flex; flex-direction: column; gap: 6px; font-size: 12.5px; color: var(--color-text-primary); }
/* WF-8 #3 — the vital COUNT is a v-val v-link anchor; keep it inline-sized (not the 18px
   hero number) so it reads as part of the stat line, underlined on hover (.v-link rule). */
.proj-card-stats .v-val { font-size: inherit; font-weight: 600; letter-spacing: 0; }
.pc-overdue { color: var(--color-danger); font-weight: 500; }
.pc-muted { color: var(--color-text-secondary); }
/* The actions strip carries the Connect disclosure and the Open link side by side, and it WRAPS
   so the disclosure can claim a whole row once it is open. That width is load-bearing, not
   cosmetic: a flex item sharing a row with a button is handed only the leftover slot, and the
   panel inside this one holds shell lines that must be read character by character. */
.proj-card-actions { display: flex; align-items: center; gap: 8px; margin-top: 2px; flex-wrap: wrap; }
.pc-connect { flex: 1; min-width: 0; }
/* Open, the disclosure spans the card and the Open link moves to the row beneath it. Closed, the
   basis stays at the flex default above, so summary and link share one row as before. */
.pc-connect[open] { flex-basis: 100%; }
.pc-connect-btn { list-style: none; cursor: pointer; }
.pc-connect-btn::-webkit-details-marker { display: none; }
/* The summary's native disclosure triangle is suppressed in both engines by the two rules above,
   and it sits beside a filled Open link of the same size and shape — so nothing would otherwise
   tell a reader that this one GROWS THE CARD IN PLACE rather than navigating away. It supplies
   its own cue: a caret pointing down while the panel is closed, turned up while it is open, so
   the two states are told apart at a glance. Drawn from borders rather than a glyph so it needs
   no font coverage, and coloured currentColor so it inherits the button's text colour in both
   themes. `content: ''` keeps it out of the text a reader or a vocabulary check reads. */
.pc-connect-btn::after { content: ''; flex: 0 0 auto; width: 0; height: 0;
  border-left: 3.5px solid transparent; border-right: 3.5px solid transparent;
  border-top: 4px solid currentColor; }
.pc-connect[open] > .pc-connect-btn::after { transform: rotate(180deg); }
.pc-connect[open] .pc-connect-btn { margin-bottom: 10px; }
.pc-connect .connect-panel { margin-top: 4px; }
/* The page-level half of the connect explanation — said once, above the cards. Sits in the same
   hairline-card idiom as .connect-panel / .proj-card so it reads as part of the page rather than
   as a banner, and zeroes the inner paddings those two classes carry for their in-panel use. */
.connect-explainer { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: 12px 16px; }
.connect-explainer .connect-lead { padding: 0; }
.connect-explainer .connect-note { padding: 7px 0 0; }
.pc-open { white-space: nowrap; }

/* --- conflict queue (screen 3) --- */
.conflicts-topbar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; }
.ct-title { display: flex; align-items: baseline; gap: 12px; }
.page-title { font-size: 16px; font-weight: 500; }
.ct-sub { font-size: 12px; color: var(--color-text-tertiary); }
.ct-filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.filter-chip { font-size: 11px; padding: 5px 12px; border: 0.5px solid var(--color-border-secondary); border-radius: var(--border-radius-md); background: var(--color-background-secondary); color: var(--color-text-secondary); font-family: var(--font-mono); }
.filter-chip.active { background: var(--color-background-primary); color: var(--color-text-primary); font-weight: 500; border-color: var(--color-border-primary); }
.chip-n { font-size: 10px; color: var(--color-text-tertiary); margin-left: 1px; }
.filter-chip.active .chip-n { color: var(--color-accent-dark); }
.conflict-layout { display: grid; grid-template-columns: 320px 1fr; gap: 16px; align-items: start; }
.conflict-list { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); }
.list-header { padding: 11px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); font-size: 11px; font-weight: 500; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.07em; }
.citem { display: block; padding: 12px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); cursor: pointer; scroll-margin-top: calc(var(--topbar-h) + 12px); }
.citem:last-of-type { border-bottom: none; }
/* WF-1 click-to-source landing anchor — a zero-height marker before each row so a
   #src-<id> fragment (Update/Catch-up source links) scrolls the opened row into view,
   clearing the sticky topbar. A non-<a> tag so .citem:last-of-type stays correct. */
.row-src { display: block; height: 0; scroll-margin-top: calc(var(--topbar-h) + 12px); }
.citem:hover { background: var(--color-background-secondary); }
.citem.selected { background: var(--color-background-info); }
/* OCCm10 — a comment row with no resolvable target (marker-only / malformed) is non-clickable
   (commentRow renders it as a <div>, not an <a>): drop the pointer + hover affordance so it never
   reads as a dead link. */
.citem-nolink { cursor: default; }
.citem-nolink:hover { background: none; }
/* FIX 2 (2026-06-28) — "See all N →" on the Home "Start here" band when >6 are pending. */
.triage-seeall { display: block; padding: 10px 16px; border-top: 0.5px solid var(--color-border-tertiary);
  font-size: 12px; font-weight: 500; color: var(--color-accent-dark); }
.triage-seeall:hover { background: var(--color-background-secondary); }
.citem-id { font-family: var(--font-mono); font-size: 10px; color: var(--color-text-tertiary); margin-bottom: 4px; }
.citem-title { font-size: 12px; font-weight: 500; line-height: 1.35; margin-bottom: 5px; color: var(--color-text-primary); }
.citem-meta { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.clist-foot { padding: 10px 16px; border-top: 0.5px solid var(--color-border-tertiary); font-size: 11px; color: var(--color-text-tertiary); }
.sev { font-size: 9px; font-weight: 500; padding: 1px 6px; border-radius: 2px; }
.sev-blocking { background: #FCEBEB; color: var(--color-danger); }
.sev-advisory { background: #FAEEDA; color: var(--color-warn); }
.cdetail { display: flex; flex-direction: column; gap: 14px; }
.detail-header { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: 16px 20px; }
.detail-id { font-family: var(--font-mono); font-size: 11px; color: var(--color-text-tertiary); margin-bottom: 6px; }
.detail-title { font-size: 15px; font-weight: 500; margin-bottom: 10px; line-height: 1.4; }
.highlight-box { background: #FAEEDA; border: 0.5px solid #FAC775; border-radius: var(--border-radius-md); padding: 10px 14px; font-size: 12px; color: #633806; line-height: 1.5; }
.highlight-label { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.07em; color: var(--color-warn); margin-bottom: 4px; }
.ver-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.ver-card { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); overflow: hidden; }
.ver-card-header { padding: 10px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); display: flex; align-items: center; justify-content: space-between; gap: 8px; background: var(--color-background-secondary); }
.ver-card-id { font-family: var(--font-mono); font-size: 11px; font-weight: 500; }
.ver-card-body { padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; }
.field-row { display: flex; flex-direction: column; gap: 3px; }
.field-label { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-tertiary); }
.field-val { font-size: 13px; color: var(--color-text-primary); line-height: 1.45; }
.field-val.mono { font-family: var(--font-mono); font-size: 11px; color: var(--color-text-secondary); }
.field-val.conflict-hl { background: #FAEEDA; padding: 4px 7px; border-radius: 3px; color: #412402; }
.auth-claim { display: inline-flex; align-items: center; font-size: 9px; font-weight: 500; padding: 2px 6px; border-radius: 3px; font-family: var(--font-mono); background: var(--color-background-tertiary); color: var(--color-text-secondary); border: 0.5px dashed var(--color-border-secondary); }
.resolution { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: 16px 20px; }
.res-title { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.07em; color: var(--color-text-secondary); margin-bottom: 12px; }
.actions-row { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.act-btn { padding: 8px 14px; border-radius: var(--border-radius-md); font-size: 12px; font-weight: 500; border: 0.5px solid; display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.act-disabled { background: var(--color-background-secondary); color: var(--color-text-tertiary); border-color: var(--color-border-tertiary); cursor: not-allowed; opacity: 0.7; }
.authority-note { font-size: 11px; color: var(--color-text-secondary); line-height: 1.55; padding: 10px 12px; background: var(--color-background-secondary); border-radius: var(--border-radius-md); border: 0.5px solid var(--color-border-tertiary); display: flex; gap: 8px; align-items: flex-start; }
.authority-note .node-icon { color: var(--color-text-tertiary); flex-shrink: 0; margin-top: 2px; }

/* --- audit & lineage (screen 6) --- */
.audit-layout { display: grid; grid-template-columns: 1fr 400px; gap: 16px; align-items: start; }
.log-panel { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); overflow: hidden; }
.filter-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 11px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.filter-label { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-tertiary); }
/* Wave 3F-b — Tasks list group-by sections. */
.mem-group { margin-bottom: 14px; }
.mem-group-hd { display: flex; align-items: center; gap: 7px; font-family: var(--font-display); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-tertiary); padding: 6px 2px 4px; border-bottom: 1px solid var(--color-border-tertiary); margin-bottom: 4px; }
.mem-group-n { font-family: var(--font-mono); font-size: 10px; color: var(--color-text-tertiary); }
.filter-sep { width: 1px; height: 16px; background: var(--color-border-tertiary); margin: 0 2px; }
.action-tag { display: inline-flex; font-size: 9px; font-weight: 500; padding: 2px 7px; border-radius: 3px; text-transform: uppercase; letter-spacing: 0.04em; background: var(--color-background-secondary); color: var(--color-text-secondary); }
.at-propose { background: #E6F1FB; color: #0C447C; }
.at-confirm { background: #EAF3DE; color: var(--color-ok); }
.at-promote { background: #2C2C2A; color: #F1EFE8; }
.at-supersede { background: #ECE3F6; color: #5B2E91; }
.at-conflict { background: #FCEBEB; color: var(--color-danger); }
.at-reject { background: #FAEEDA; color: var(--color-warn); }
.audit-detail { font-size: 12px; color: var(--color-text-secondary); line-height: 1.4; }
.lineage-panel { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); }
.lineage-header { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 11px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.lineage-title { font-size: 12px; font-weight: 500; font-family: var(--font-mono); }
.ltree-body { padding: 16px; }
.ltree-node { display: flex; }
.node-card { flex: 1; border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); padding: 10px 14px; background: var(--color-background-secondary); }
.node-card.active-node { background: var(--color-background-info); border-color: #B5D4F4; }
.node-card.superseded-node { opacity: 0.7; }
.node-id { font-family: var(--font-mono); font-size: 11px; font-weight: 500; display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.node-text { font-size: 13px; line-height: 1.4; margin-bottom: 4px; }
.node-card.superseded-node .node-text { text-decoration: line-through; color: var(--color-text-secondary); }
.node-meta { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); }
.lineage-link { font-size: 11px; color: var(--color-accent); padding: 6px 0 6px 14px; }
.diff-panel { margin: 0 16px 16px; border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); padding: 12px 14px; }
.diff-title { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-tertiary); margin-bottom: 10px; }
.diff-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 10px; }
.diff-row:last-child { margin-bottom: 0; }
.diff-label { font-size: 10px; color: var(--color-text-tertiary); margin-bottom: 3px; }
.diff-old { font-size: 12px; color: var(--color-danger); background: #FCEBEB; padding: 4px 7px; border-radius: 3px; line-height: 1.4; }
.diff-new { font-size: 12px; color: var(--color-ok); background: #EAF3DE; padding: 4px 7px; border-radius: 3px; line-height: 1.4; }

/* --- in-project tabs (cairn_ui_design.md §2) --- */
.ptabs { display: flex; gap: 4px; }
.ptab { padding: 7px 16px; font-size: 12px; color: var(--color-text-secondary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); background: var(--color-background-secondary); }
.ptab.active { background: var(--color-background-primary); color: var(--color-text-primary); font-weight: 500; border-color: var(--color-border-primary); }
/* WF-2 — the top-level project-SCOPE tab bar (Everything · one tab per project), reusing
   the .ptab visual; a little breathing room below it before the screen header. */
.ptabs-scope { flex-wrap: wrap; margin-bottom: 14px; }
.badge { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 5px; border-radius: 8px; background: #E24B4A; color: #fff; font-size: 9px; font-weight: 500; margin-left: 6px; }

/* --- chat + briefing panel (screen 4) --- */
.chat-topbar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; }
.scope-chip { font-size: 11px; font-family: var(--font-mono); color: var(--color-text-secondary); background: var(--color-background-secondary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); padding: 4px 10px; }
.chat-controls { display: flex; align-items: center; gap: 12px; }
.mem-toggle { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--color-text-secondary); }
.mem-toggle .track { width: 30px; height: 17px; border-radius: 9px; background: var(--color-border-secondary); position: relative; display: inline-block; }
.mem-toggle .track.on { background: var(--color-ok); }
.mem-toggle .thumb { position: absolute; top: 2px; left: 2px; width: 13px; height: 13px; border-radius: 50%; background: #fff; transition: left 0.1s; }
.mem-toggle .track.on .thumb { left: 15px; }
.chat-panes { display: grid; grid-template-columns: 280px 1fr 380px; gap: 14px; align-items: start; }
.chat-pane { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); display: flex; flex-direction: column; max-height: 640px; }
.pane-hdr { padding: 11px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); font-size: 11px; font-weight: 500; color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: 0.07em; }
.pane-hdr.accent { color: var(--color-text-primary); display: flex; align-items: center; }
.feed-scroll { padding: 8px 0; overflow-y: auto; }
.feed-item { padding: 9px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.feed-item:last-child { border-bottom: none; }
.ftype { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 3px; }
.ft-surprise { color: var(--color-warn); }
.ft-commitment { color: #0C447C; }
.ft-decision { color: #5B2E91; }
.ft-prediction { color: var(--color-accent); }
.ft-entity, .ft-relationship, .ft-event { color: var(--color-text-tertiary); }
.ftext { font-size: 12px; line-height: 1.4; }
.ftime { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); margin-top: 3px; }
.conv-pane { justify-content: space-between; }
.conv-explain { padding: 18px 20px; }
.conv-explain-title { font-size: 14px; font-weight: 500; margin-bottom: 8px; }
.conv-explain p { font-size: 12px; color: var(--color-text-secondary); line-height: 1.6; margin: 0 0 12px; }
.conv-note { font-size: 11px; color: var(--color-text-tertiary); }
.input-area { border-top: 0.5px solid var(--color-border-tertiary); padding: 12px 16px; }
.inp { width: 100%; border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); padding: 9px 12px; font-family: var(--font-sans); font-size: 13px; resize: none; background: var(--color-background-secondary); color: var(--color-text-tertiary); }
.input-footer { display: flex; align-items: center; justify-content: space-between; margin-top: 8px; }
.hint { font-size: 11px; color: var(--color-text-tertiary); display: inline-flex; align-items: center; gap: 5px; }
.send-btn { padding: 7px 14px; border-radius: var(--border-radius-md); font-size: 12px; font-weight: 500; display: inline-flex; align-items: center; gap: 6px; border: 0.5px solid; }
/* live assistant conversation (design §6, Option B) */
.conv-thread { flex: 1; overflow-y: auto; padding: 14px 16px; display: flex; flex-direction: column; gap: 12px; min-height: 0; }
.msg { display: flex; flex-direction: column; gap: 3px; max-width: 92%; }
.msg-user { align-self: flex-end; align-items: flex-end; }
.msg-assistant { align-self: flex-start; align-items: flex-start; }
.msg-role { font-size: 9px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-tertiary); }
.msg-text { font-size: 13px; line-height: 1.5; padding: 9px 12px; border-radius: var(--border-radius-md); white-space: pre-wrap; word-break: break-word; }
.msg-user .msg-text { background: var(--color-background-info); color: #0C2E52; border: 0.5px solid #B5D4F4; }
.msg-assistant .msg-text { background: var(--color-background-secondary); color: var(--color-text-primary); border: 0.5px solid var(--color-border-tertiary); }
.msg-resume .msg-text { background: var(--color-background-primary); border-style: dashed; color: var(--color-text-secondary); }
/* Streaming reply (assistant increment 1.5): a soft blinking caret on the live
   assistant bubble while tokens are arriving. Pure enhancement — removed on the
   `done` frame; absent entirely on the no-JS form-POST path. */
.msg-streaming .msg-text::after { content: '▍'; margin-left: 1px; color: var(--color-text-tertiary); animation: cairn-caret 1s step-end infinite; }
@keyframes cairn-caret { 50% { opacity: 0; } }
.inp-live { color: var(--color-text-primary); background: var(--color-background-primary); }
/* The Catch (§6.4): the substrate's block/file rendered inside the conversation */
.catch-card { align-self: stretch; border: 0.5px solid; border-radius: var(--border-radius-md); padding: 11px 14px; display: flex; flex-direction: column; gap: 5px; }
.catch-blocked { background: #FCEBEB; border-color: #E0B4B4; }
.catch-filed { background: var(--color-background-info); border-color: #B5D4F4; }
.catch-rejected { background: #FAEEDA; border-color: #FAC775; }
.catch-hdr { font-size: 12px; font-weight: 600; display: flex; align-items: center; gap: 7px; }
.catch-blocked .catch-hdr { color: var(--color-danger); }
.catch-filed .catch-hdr { color: #0C447C; }
.catch-rejected .catch-hdr { color: var(--color-warn); }
.catch-ic { font-size: 14px; }
.catch-line { font-size: 12px; color: var(--color-text-primary); line-height: 1.45; }
.catch-k { font-size: 9px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-tertiary); margin-right: 6px; }
.catch-reason { font-size: 11px; color: var(--color-text-secondary); line-height: 1.5; }
.catch-review { font-size: 11px; font-weight: 500; color: var(--color-accent); margin-top: 2px; }
/* Safe-to-act gate (§6.5): preflight checklist + verdict, inside the conversation */
.pf-card { align-self: stretch; border: 0.5px solid; border-radius: var(--border-radius-md); padding: 11px 14px; display: flex; flex-direction: column; gap: 6px; }
.pf-card-green { background: #F4F8EE; border-color: #B7D89A; }
.pf-card-red { background: var(--color-background-secondary); border-color: var(--color-border-secondary); }
.pf-hdr { font-size: 12px; font-weight: 600; color: var(--color-text-primary); }
.pf-check { display: grid; grid-template-columns: 16px 120px 1fr; gap: 8px; align-items: baseline; font-size: 11px; }
.pf-mark { font-weight: 700; text-align: center; }
.pf-ok .pf-mark { color: var(--color-ok); }
.pf-bad .pf-mark { color: var(--color-danger); }
.pf-bad .pf-label { color: var(--color-danger); font-weight: 600; }
/* HALT-B: a WARNING row (an open clash) — its own state; it reminds, it never blocks */
.pf-warn .pf-mark { color: var(--color-warn); }
.pf-warn .pf-label { color: var(--color-warn); font-weight: 600; }
.pf-card-warn { border-color: #FAC775; }
.pf-reminder { font-size: 11px; line-height: 1.5; padding: 7px 10px; border-radius: var(--border-radius-md); background: #FAEEDA; color: var(--color-warn); }
.pf-label { font-weight: 500; color: var(--color-text-secondary); }
.pf-detail { color: var(--color-text-tertiary); }
.pf-verdict { font-size: 12px; font-weight: 600; padding: 7px 10px; border-radius: var(--border-radius-md); margin-top: 2px; }
.pf-v-green { background: #EAF3DE; color: var(--color-ok); }
.pf-v-red { background: #FCEBEB; color: var(--color-danger); }

/* The Split (§6.6): memory off vs memory on, side by side */
.split-link { font-size: 11px; color: var(--color-accent); font-weight: 500; }
.split-composer { display: flex; gap: 10px; align-items: flex-end; background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: 14px 16px; }
.split-composer .inp-live { flex: 1; }
.split-intro { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: 16px 18px; font-size: 12px; color: var(--color-text-secondary); line-height: 1.6; }
.split-panes { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; }
.split-arm { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: 14px 16px; display: flex; flex-direction: column; gap: 8px; }
.split-on { border-color: #B5D4F4; }
.split-hdr { display: flex; align-items: baseline; gap: 8px; border-bottom: 0.5px solid var(--color-border-tertiary); padding-bottom: 8px; }
.split-title { font-size: 12px; font-weight: 600; }
.split-off .split-title { color: var(--color-text-secondary); }
.split-on .split-title { color: #0C447C; }
.split-sub { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); }
.split-q { font-size: 11px; color: var(--color-text-tertiary); font-style: italic; }
.split-a { font-size: 13px; line-height: 1.5; color: var(--color-text-primary); white-space: pre-wrap; word-break: break-word; }
.split-empty { font-size: 12px; color: var(--color-text-tertiary); }

.brief-scroll { padding: 6px 0; overflow-y: auto; }
.bsec { border-bottom: 0.5px solid var(--color-border-tertiary); }
.bsec:last-child { border-bottom: none; }
.bsec-hdr { display: flex; align-items: center; justify-content: space-between; padding: 10px 16px; font-size: 11px; font-weight: 500; color: var(--color-text-secondary); }
.bcnt { font-family: var(--font-mono); font-size: 10px; color: var(--color-text-tertiary); background: var(--color-background-secondary); padding: 1px 7px; border-radius: 8px; }
.bcnt-warn { background: #FAEEDA; color: var(--color-warn); }
.bitems { padding: 0 16px 10px; }
.bitem { padding: 8px 0; border-top: 0.5px solid var(--color-border-tertiary); }
.bitem-meta { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; }
.bitem-label { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); }
.bitem-label.warn { color: var(--color-warn); font-weight: 500; }
.bitem-text { font-size: 12px; line-height: 1.4; }
.bitem-prov { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); margin-top: 3px; }
/* Glass-box provenance popover (design D2): ▸ → source span + who/when, no JS */
.prov { font-family: var(--font-mono); }
.prov-toggle { font-size: 10px; color: var(--color-accent); cursor: pointer; list-style: none; display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prov-toggle::-webkit-details-marker { display: none; }
.prov[open] .prov-toggle { color: var(--color-text-secondary); }
.prov-pop { margin-top: 5px; padding: 8px 10px; background: var(--color-background-secondary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); display: flex; flex-direction: column; gap: 3px; }
.prov-line { font-size: 10px; color: var(--color-text-secondary); line-height: 1.4; word-break: break-word; }
.prov-k { color: var(--color-text-tertiary); text-transform: uppercase; letter-spacing: 0.04em; margin-right: 5px; }
.brief-trunc { padding: 10px 16px; font-size: 11px; color: var(--color-text-tertiary); }

/* --- documents (screen 5) --- */
.doc-list { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); overflow: hidden; }
.doc-list .primary a { display: inline-flex; align-items: center; gap: 6px; }
.doc-list .primary .node-icon { color: var(--color-text-tertiary); }
.sp { display: inline-flex; font-size: 9px; font-weight: 500; padding: 2px 7px; border-radius: 2px; }
.sp-done { background: #EAF3DE; color: var(--color-ok); }
.sp-review { background: #FAEEDA; color: var(--color-warn); }
.doc-review { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); padding: 16px 20px; }
.review-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.review-title { font-size: 14px; font-weight: 500; font-family: var(--font-mono); margin-bottom: 4px; }
.review-sub { font-size: 11px; color: var(--color-text-secondary); line-height: 1.5; }
.bbtn { padding: 8px 14px; border-radius: var(--border-radius-md); font-size: 12px; font-weight: 500; border: 0.5px solid; white-space: nowrap; }
.cand-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.cand-card { border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); overflow: hidden; }
.cand-card-header { display: flex; align-items: center; gap: 8px; padding: 9px 14px; background: var(--color-background-secondary); border-bottom: 0.5px solid var(--color-border-tertiary); }
.ctype { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-secondary); }
.confirmed-badge { margin-left: auto; font-size: 10px; color: var(--color-ok); font-weight: 500; }
.cand-body { padding: 12px 14px; }
.cf-val { font-size: 13px; line-height: 1.45; margin-bottom: 4px; }

/* UR-22 — progressive-disclosure overflow ("Show all N") for the dense list screens
   (Memory kind-groups, Documents extracted-fact grid). A no-JS <details> (strict-CSP
   safe, like the receipt/provenance disclosures); the summary is a quiet, full-width
   control under the visible rows. All colours are theme tokens — adaptive in dark, no
   hard-coded hex to override. */
.more { display: block; }
.more-toggle { cursor: pointer; list-style: none; font-size: 11px; font-weight: 500;
  color: var(--color-text-secondary); padding: 9px 16px; user-select: none;
  border-top: 0.5px solid var(--color-border-tertiary); }
.more-toggle::-webkit-details-marker { display: none; }
.more-toggle:hover { background: var(--color-background-secondary); color: var(--color-text-primary); }
.more-toggle::before { content: "\25B8 "; color: var(--color-text-tertiary); }
.more[open] > .more-toggle::before { content: "\25BE "; }
.more-n { color: var(--color-text-tertiary); font-family: var(--font-mono); margin-left: 4px; }
/* In the Documents 2-col fact grid the <details> must span both columns and re-grid
   its revealed cards so the expanded set keeps the 2-up layout (a grid child otherwise
   stacks single-column). */
.cand-grid .more { grid-column: 1 / -1; }
.cand-grid .more-toggle { border: 0.5px dashed var(--color-border-tertiary);
  border-radius: var(--border-radius-md); text-align: center; }
.cand-grid .more-body { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; }

/* --- settings (screen 7) --- */
.settings-grid { display: flex; flex-direction: column; gap: 14px; }
.setting-section { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg); }
.setting-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 14px 18px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.setting-title { font-size: 13px; font-weight: 500; margin-bottom: 3px; }
.setting-desc { font-size: 11px; color: var(--color-text-secondary); line-height: 1.5; max-width: 720px; }
.setting-body { padding: 14px 18px; }
.setting-row { display: grid; grid-template-columns: 180px 1fr; gap: 14px; padding: 8px 0; border-bottom: 0.5px solid var(--color-border-tertiary); align-items: start; }
.setting-row:last-child { border-bottom: none; }
.setting-label { font-size: 11px; font-weight: 500; color: var(--color-text-secondary); }
.setting-val { font-size: 12px; color: var(--color-text-primary); line-height: 1.5; }
.btn { padding: 7px 14px; border-radius: var(--border-radius-md); font-size: 12px; font-weight: 500; border: 0.5px solid; white-space: nowrap; }
.key-hygiene { display: flex; gap: 10px; align-items: flex-start; font-size: 12px; color: var(--color-text-secondary); line-height: 1.6; background: var(--color-background-secondary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); padding: 12px 14px; }
.key-hygiene .node-icon { color: var(--color-text-tertiary); flex-shrink: 0; margin-top: 1px; }
.key-hygiene strong { color: var(--color-text-primary); }

/* --- write affordances (CV-2 write paths; CV-1.5 identity unblocked) --- */
/* Primary (enabled) action button — accent fill, applies to .act-btn + .bbtn. */
.act-primary { background: var(--color-accent); color: #ffffff; border-color: var(--color-accent); cursor: pointer; }
.act-primary:hover { filter: brightness(0.94); }
/* Resolution form (Conflict Queue) — stacked fields above the action row. */
.res-form { display: flex; flex-direction: column; gap: 12px; }
.res-field { display: flex; flex-direction: column; gap: 5px; }
.res-label { font-size: 11px; font-weight: 500; color: var(--color-text-secondary); }
.res-form select, .res-form textarea {
  font-family: var(--font-sans); font-size: 12px; color: var(--color-text-primary);
  background: var(--color-background-primary); border: 0.5px solid var(--color-border-secondary);
  border-radius: var(--border-radius-md); padding: 8px 10px; width: 100%; box-sizing: border-box;
}
.res-form textarea { resize: vertical; min-height: 60px; line-height: 1.5; }
/* Per-entry transition action (Documents extracted-entry cards). */
.cand-action { padding: 10px 14px; border-top: 0.5px solid var(--color-border-tertiary); display: flex; }
.cand-action form { margin: 0; }
/* Post-write flash banner (PRG outcome; message escaped in layout.page). */
.flash { font-size: 12px; padding: 10px 16px; border-radius: var(--border-radius-md); margin-bottom: 14px; border: 0.5px solid; line-height: 1.5; }
.flash-ok { background: #EAF3DE; color: var(--color-ok); border-color: #B7D89A; }
.flash-err { background: #F7E4E4; color: var(--color-danger); border-color: #E0B4B4; }

/* Authority-grants management (Settings screen 7; CV-1.5 §5 write affordance). */
.act-danger { background: var(--color-background-primary); color: var(--color-danger); border-color: #E0B4B4; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; }
.act-danger:hover { background: #F7E4E4; }
.grant-action { text-align: right; white-space: nowrap; }
.grant-revoke { margin: 0; display: inline-block; }
.grant-add { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 14px; padding-top: 14px; border-top: 0.5px solid var(--color-border-tertiary); }
.grant-add .act-primary { display: inline-flex; align-items: center; gap: 5px; }
.grant-input {
  font-family: var(--font-sans); font-size: 12px; color: var(--color-text-primary);
  background: var(--color-background-primary); border: 0.5px solid var(--color-border-secondary);
  border-radius: var(--border-radius-md); padding: 8px 10px; box-sizing: border-box;
}
.grant-add input.grant-input { flex: 1 1 200px; min-width: 160px; }
.grant-level { flex: 0 0 auto; }
.grant-add-note { display: flex; gap: 10px; align-items: flex-start; font-size: 11px; color: var(--color-text-secondary); line-height: 1.6; margin-top: 14px; padding-top: 14px; border-top: 0.5px solid var(--color-border-tertiary); }
.grant-add-note .node-icon { color: var(--color-text-tertiary); flex-shrink: 0; margin-top: 1px; }

/* Create-project + document-ingest forms (CV-2 write increment). Reuse the
   grant-input control idiom; stacked labelled fields inside a padded panel. */
.np-form, .ingest-form, .ingest-accept-form { display: flex; flex-direction: column; gap: 14px; padding: 16px; }
.np-label { display: flex; flex-direction: column; gap: 6px; font-size: 11px; font-weight: 500; color: var(--color-text-secondary); }
.np-label .grant-input { width: 100%; }
.np-opt { font-weight: 400; color: var(--color-text-tertiary); }
.np-actions { display: flex; align-items: center; gap: 14px; margin-top: 2px; }
.back-link { font-size: 12px; color: var(--color-accent); display: inline-flex; align-items: center; gap: 5px; }
.ingest-textarea {
  font-family: var(--font-mono); font-size: 12px; color: var(--color-text-primary);
  background: var(--color-background-primary); border: 0.5px solid var(--color-border-secondary);
  border-radius: var(--border-radius-md); padding: 10px 12px; width: 100%; box-sizing: border-box;
  resize: vertical; min-height: 200px; line-height: 1.5;
}
/* Drag-drop / browse file-upload zone (revealed by app.js; paste is the no-JS path). */
.ingest-drop { display: flex; flex-direction: column; align-items: center; gap: 4px;
  border: 1.5px dashed var(--color-border-secondary); border-radius: var(--border-radius-md);
  padding: 20px; text-align: center; background: var(--color-background-secondary); cursor: pointer;
  transition: border-color 0.12s, background 0.12s; }
.ingest-drop.dragover { border-color: var(--color-accent); background: var(--memry-accent-tint); }
.ingest-drop-label { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--color-text-secondary); }
.ingest-browse { color: var(--color-accent); font-weight: 500; }
.ingest-drop-hint { font-size: 10px; color: var(--color-text-tertiary); }
.ingest-file { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; }
/* Ingest preview cards (proposed entries; reuse cand-card grid from Documents). */
.ingest-accept { font-size: 12px; color: var(--color-text-secondary); display: inline-flex; align-items: center; gap: 5px; margin-right: 6px; cursor: pointer; }
.ingest-quote { font-size: 11px; color: var(--color-text-secondary); margin-top: 6px; line-height: 1.5; font-style: italic; }
.ingest-noquote { font-style: normal; color: var(--color-text-tertiary); }
.qv { font-style: normal; font-size: 10px; font-weight: 500; padding: 1px 6px; border-radius: var(--border-radius-md); margin-left: 4px; }
.qv-ok { color: var(--color-ok); background: #EAF3DE; }
.qv-warn { color: var(--color-danger); background: #F7E4E4; }

/* ===========================================================================
   Visual polish pass (2026-06-21) — brand-forward type, depth, contrast fix.
   Appended last so the display-face rules win over any earlier same-specificity
   font-family. Body text + mono identifiers (scope paths, ids) keep their stacks
   deliberately; the brand face rides the heading / title / number layer.
   =========================================================================== */

/* Brand display face (Space Grotesk) on the prominent type layer. */
h1, h2, h3,
.page-title, .detail-title, .conv-explain-title,
.panel-title, .col-title, .tree-header, .list-header, .gov-rail-hdr,
.pane-hdr, .bsec-hdr, .setting-title,
.vital-value, .v-val, .vital-label, .v-label { font-family: var(--font-display); }
/* Tabular, tightened numerals for the big vital figures (scoreboard feel). */
.vital-value, .v-val { font-feature-settings: 'tnum' 1; letter-spacing: -0.01em; }

/* Soft elevation on the primary white cards — depth + hierarchy over flat borders. */
.panel, .zone-d, .tree-panel, .all-projects, .proj-header, .connect-panel,
.conflict-list, .detail-header, .resolution, .log-panel, .lineage-panel,
.setting-section, .chat-pane, .doc-list, .doc-review, .gov-rail,
.split-arm, .split-intro, .split-composer { box-shadow: var(--shadow-card); }

/* Search results (top-bar search → /search). Card list, authority + type + scope +
   glass-box "where this came from". */
.search-list { background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary);
  border-radius: var(--border-radius-lg); box-shadow: var(--shadow-card); overflow: hidden; }
.search-row { display: flex; flex-direction: column; gap: 6px; padding: 12px 16px;
  border-bottom: 0.5px solid var(--color-border-tertiary); }
.search-row:last-child { border-bottom: none; }
.search-row:hover { background: var(--color-background-secondary); }
.search-row-main { display: flex; align-items: center; gap: 9px; }
.search-row-link { text-decoration: none; color: inherit; }
.search-row-link:hover .search-row-label { color: var(--color-accent); }
.search-row-label { flex: 1; font-size: 13px; font-weight: 500; line-height: 1.4; color: var(--color-text-primary); }
.search-row-meta { display: flex; align-items: center; gap: 7px; font-size: 10px;
  color: var(--color-text-tertiary); font-family: var(--font-mono); flex-wrap: wrap; }
/* OCCm22 (Beat D) — the verbatim document-BODY excerpt on a search hit whose body matched
   (present-only; the text is C.esc'd at the data boundary). A muted secondary line inside the row,
   between the title and the meta; theme tokens only (flips in dark), no hard-coded hex. */
.search-row-snippet { font-size: 11.5px; line-height: 1.5; color: var(--color-text-secondary);
  word-break: break-word; }

/* Contrast fix (operator-flagged, root cause verified): an icon inside a filled
   primary button must inherit the button's white. .node-icon sets a tertiary grey
   that otherwise wins over .act-primary's color:#fff → a grey glyph on orange,
   unreadable. inherit restores the white on .act-primary (.act-btn + .bbtn) and the
   send button variant. */
.act-primary .node-icon,
.send-btn.act-primary .node-icon { color: inherit; }

/* Home — the approval queue (Max §1). A review card = main content on the left, the
   Approve / Reject (or Review) actions on the right; a one-line "why this surfaced"
   under the title. Cards live inside the existing .panel shell. */
.hq-card { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 12px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.hq-card:last-of-type { border-bottom: none; }
.hq-card-link { cursor: pointer; color: inherit; text-decoration: none; }
.hq-card-link:hover { background: var(--color-background-secondary); }
.hq-card-main { flex: 1 1 auto; min-width: 0; }
.hq-why { font-size: 11px; color: var(--color-text-tertiary); line-height: 1.45; margin-top: 6px; }
/* UR-07 — "new since you last looked" badge on a What-changed row (theme tokens). */
.chg-new { font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
  color: #fff; background: var(--color-accent); padding: 1px 5px; border-radius: 2px; }
/* UR-19 — sign-off consequence preview: a compact "replaces / conflicts / new" line
   so the approver sees the effect before signing. Three honest states; the icon and
   tint key off the kind. Backgrounds use hard hex (the trust-signal pastels) with
   dark-mode overrides below, mirroring .sev / .diff-old (UR-13). */
.hq-consequence { font-size: 11px; line-height: 1.45; margin-top: 6px; padding: 3px 8px;
  border-radius: 3px; display: inline-flex; align-items: center; gap: 5px; max-width: 100%; }
.hq-consequence .cq-k { font-weight: 600; }
.hq-consequence .cq-old { color: var(--color-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cq-replaces { background: #EFF1F4; color: var(--color-text-secondary); }
.cq-conflicts { background: #FAEEDA; color: var(--color-warn); }
.cq-new { background: transparent; padding-left: 0; color: var(--color-text-tertiary); }
/* Actions stack vertically: Approve on its own row; the Reject control with its
   reason on the next — so the reason field reads as belonging to Reject, not Approve
   (operator walk feedback 2026-06-21). */
.hq-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; flex: 0 0 auto; }
.hq-act { display: inline-flex; align-items: center; gap: 6px; margin: 0; }
.hq-reject { gap: 6px; }
.hq-reason { width: 150px; padding: 7px 9px; font-size: 11px; }

/* ===========================================================================
   Dark-mode toggle + full dark theme (2026-06-22, milestone 2 — the VISUAL pass §6).
   A single root attribute drives the whole flip: <html data-theme="dark">.
   public/js/theme.js applies the saved choice in <head> before paint (no flash); the
   top-bar toggle (app.js wireThemeToggle) flips it + persists to localStorage (key
   'memry-theme'). NO server state.

   The flip works through the SEMANTIC tokens (canvas, cards, text, borders, accent,
   elevation), so panels / tables / forms / most chrome invert with no per-rule edits.
   The dark CHROME stays dark in both themes (its brand identity): over the light paper
   canvas it reads as dark chrome; over the dark canvas it reads as a raised rail. The
   shared status-colour families (authority / commitment / message / flash / selected)
   carry hard-coded pastels, so they get a bounded dark retune below. FIRST CUT —
   colour values to tune live; layout / spacing / type-scale unchanged. The chat /
   audit / conflict-detail decorative palettes are deferred to their milestone-3
   per-screen passes (flagged, not faked).
   =========================================================================== */

/* Top-bar toggle — a chrome chip matching the dividend; the relevant glyph is shown
   by CSS per theme (moon in light = "go dark"; sun in dark = "go light"). */
.theme-toggle { display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: 0 0 auto; padding: 0; cursor: pointer;
  background: var(--chrome-deep); color: var(--chrome-text);
  border: 1px solid var(--chrome-border); border-radius: var(--border-radius-md);
  transition: border-color 0.12s, background 0.12s, color 0.12s; }
.theme-toggle:hover { background: #10161B; border-color: var(--color-accent); color: var(--chrome-text-strong); }
.theme-toggle .node-icon { color: inherit; }
.theme-toggle .tt-icon { display: inline-flex; }
.theme-toggle .tt-sun { display: none; }                 /* light mode → show the moon */
:root[data-theme="dark"] .theme-toggle .tt-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .tt-sun { display: inline-flex; }

/* --- the semantic-token flip: the whole light paper canvas goes dark --- */
:root[data-theme="dark"] {
  --memry-paper: #12171C;                          /* canvas — darkest (below the chrome) */
  --memry-accent-tint: #3A2417;                    /* warm dark tint (dragover / soft hovers) */
  --color-background-primary: #1B242C;             /* cards — raised above the canvas */
  --color-background-secondary: #232E37;           /* inset / secondary surface */
  --color-background-tertiary: #2B3640;
  --color-background-info: #15293C;                /* selected row / user bubble (dark blue) */
  --color-text-primary: #E8EBED;
  --color-text-secondary: #A7B0B7;
  --color-text-tertiary: #79828A;
  --color-border-tertiary: rgba(255, 255, 255, 0.07);
  --color-border-secondary: rgba(255, 255, 255, 0.13);
  --color-border-primary: rgba(255, 255, 255, 0.22);
  --color-accent: #E8794A;                          /* on-dark accent (brand spec) */
  --color-accent-dark: #F08D5F;
  --color-danger: #E58A8A;                          /* status hues lightened for dark legibility */
  --color-warn: #E0B062;
  --color-ok: #9FCD72;
  /* Chrome reads as a raised rail over the darker canvas; keep the slate identity. */
  --chrome-base: #1E2A32;
  --chrome-deep: #12171C;
  --chrome-raise: #2C3A44;
  /* Elevation: deepen shadows so cards still separate against the dark canvas. */
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.30), 0 2px 8px rgba(0, 0, 0, 0.38);
  --shadow-card-hover: 0 2px 8px rgba(0, 0, 0, 0.34), 0 8px 22px rgba(0, 0, 0, 0.46);
  color-scheme: dark;                               /* native scrollbars / form controls render dark */
}

/* --- dark retune of the shared status-colour primitives (hard-coded pastels that the
   token flip cannot reach). Cross-cutting families that appear across the walk screens;
   first-cut values. --- */
:root[data-theme="dark"] .demo-banner { background: #2A1C12; color: #E8DACE; border-bottom-color: #4A3320; }

/* Authority badges (locked / draft / proposed / guessed). */
:root[data-theme="dark"] .auth-canonical { background: #E8EBED; color: #12171C; }
:root[data-theme="dark"] .auth-working { background: #16344F; color: #9CC7F0; border-color: #244D6E; }
:root[data-theme="dark"] .auth-provisional { background: #3A2F12; color: #E0B062; border-color: #5A4A1D; }
:root[data-theme="dark"] .auth-inferred { color: var(--color-text-secondary); border-color: rgba(255, 255, 255, 0.32); }

/* Commitment status pills. */
:root[data-theme="dark"] .cs-open { background: #3A2F12; color: #E0B062; }
:root[data-theme="dark"] .cs-met { background: #20330F; color: #9FCD72; }
:root[data-theme="dark"] .cs-failed { background: #3A1B1B; color: #E58A8A; }
:root[data-theme="dark"] .cs-renegotiated, :root[data-theme="dark"] .cs-reneg { background: #16344F; color: #8FC0EE; }

/* Gateway pills (degradation is visible). */
:root[data-theme="dark"] .pill-normal { background: #20330F; color: #9FCD72; }
:root[data-theme="dark"] .pill-passthrough { background: #3A2F12; color: #E0B062; }
:root[data-theme="dark"] .pill-off { background: #232E37; color: var(--color-text-tertiary); }

/* Project-tree selection + alert badges. */
:root[data-theme="dark"] .node-name.selected { color: #9CC7F0; }
:root[data-theme="dark"] .badge-red { background: #3A1B1B; color: #E58A8A; }
:root[data-theme="dark"] .badge-amber { background: #3A2F12; color: #E0B062; }

/* The user message bubble (assistant bubble already uses tokens, so it flips cleanly). */
:root[data-theme="dark"] .msg-user .msg-text { background: var(--color-background-info); color: #DCE9F6; border-color: #244D6E; }

/* Post-write flash banners. */
:root[data-theme="dark"] .flash-ok { background: #1E2F10; color: #9FCD72; border-color: #3A5520; }
:root[data-theme="dark"] .flash-err { background: #361A1A; color: #E58A8A; border-color: #5A2A2A; }

/* Document extraction status + quote-verification chips (Documents is a walk screen). */
:root[data-theme="dark"] .sp-done { background: #20330F; color: #9FCD72; }
:root[data-theme="dark"] .sp-review { background: #3A2F12; color: #E0B062; }
:root[data-theme="dark"] .qv-ok { background: #20330F; color: #9FCD72; }
:root[data-theme="dark"] .qv-warn { background: #3A1B1B; color: #E58A8A; }

/* UR-13: dark retune of the conflict / safe-to-act / audit trust signals — light-only
   pastels (hard-coded background hex) that washed out on the dark canvas. Same deep-tint
   palette as cs-* / sp-* above; the text hues already flip via the lightened --color-*
   tokens, so only the backgrounds (and two hard-coded dark text colours) need a swap.
   (outcome-* / stag / confirmed-badge were on the finding's list but are var-coloured
   TEXT with NO hard-coded background — already legible in dark; verified, no override.) */
:root[data-theme="dark"] .sev-blocking { background: #3A1B1B; }
:root[data-theme="dark"] .sev-advisory { background: #3A2F12; }
:root[data-theme="dark"] .at-conflict { background: #3A1B1B; }
:root[data-theme="dark"] .at-reject { background: #3A2F12; }
:root[data-theme="dark"] .diff-old { background: #3A1B1B; }
:root[data-theme="dark"] .pf-v-green { background: #20330F; }
:root[data-theme="dark"] .pf-v-red { background: #3A1B1B; }
:root[data-theme="dark"] .pf-reminder { background: #3A2F12; }
:root[data-theme="dark"] .highlight-box { background: #2E2510; border-color: #5A4A1D; color: #E6C98A; }
:root[data-theme="dark"] .catch-blocked { background: #2E1717; border-color: #5A2A2A; }
:root[data-theme="dark"] .catch-filed { background: #16263A; border-color: #244D6E; }
:root[data-theme="dark"] .catch-rejected { background: #2E2510; border-color: #5A4A1D; }
:root[data-theme="dark"] .catch-filed .catch-hdr { color: #9CC7F0; }
:root[data-theme="dark"] .gov-contradiction { border-left-color: #C8902E; }
:root[data-theme="dark"] .gov-blocked { border-left-color: #B06A6A; }
/* UR-19 consequence preview — dark tints (the light pastels wash out on the dark canvas). */
:root[data-theme="dark"] .cq-replaces { background: #20242B; }
:root[data-theme="dark"] .cq-conflicts { background: #3A2F12; }

/* ===========================================================================
   Type scale + depth / hierarchy (2026-06-22, milestone 2 §6 — the system layer
   the per-screen milestone-3 redesigns inherit). Theme-agnostic system tokens +
   a stronger display-title hierarchy so every screen leads with an authoritative
   title and the scoreboard numbers read with weight. System-level only; appended
   so it overrides earlier same-specificity rules, and reversible. FIRST CUT —
   values to tune live; layout / spacing rhythm of dense tables unchanged.
   =========================================================================== */
:root {
  /* Spacing rhythm (4px base) — milestone-3 component padding / gaps. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  /* Radius scale (extends the existing md / lg). */
  --border-radius-sm: 5px;
  --border-radius-xl: 16px;
  /* Elevation levels (extends --shadow-card): a flat hairline + a lifted surface. */
  --shadow-sm: 0 1px 2px rgba(30, 42, 50, 0.05);
  --shadow-lg: 0 6px 16px rgba(30, 42, 50, 0.08), 0 16px 40px rgba(30, 42, 50, 0.10);
}
:root[data-theme="dark"] {
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.30);
  --shadow-lg: 0 6px 16px rgba(0, 0, 0, 0.40), 0 16px 40px rgba(0, 0, 0, 0.50);
}

/* Stronger display-title hierarchy (Space Grotesk display face already applied;
   this is the size / weight / tracking step that makes a screen lead with authority). */
.page-title { font-size: 19px; font-weight: 600; letter-spacing: -0.015em; }
.detail-title, .review-title { font-weight: 600; }
.proj-title { font-size: 19px; letter-spacing: -0.01em; }
/* The scoreboard vitals read heavier — measured, confident numerals. */
.vital-value, .v-val { font-weight: 600; }

/* ===========================================================================
   Memory — the trust surface (Max §2, milestone 3 screen 1). Scope picker + search
   over a two-pane list (left) + fact card (right). Reuses .conflict-layout / .conflict-
   list / .citem / .panel / .filter-chip; the .mem-* + .fact-* classes below are
   token-based, so dark mode flips them with no extra rules.
   =========================================================================== */
.mem-top { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-top: 2px; }
.mem-search { display: flex; align-items: center; gap: 8px; }
.mem-search input { width: 280px; max-width: 50vw; font-family: var(--font-sans); font-size: 12.5px;
  color: var(--color-text-primary); background: var(--color-background-primary);
  border: 0.5px solid var(--color-border-secondary); border-radius: var(--border-radius-md); padding: 8px 12px; }
.mem-search input:focus { outline: none; border-color: var(--color-accent); }
.mem-layout { grid-template-columns: 360px minmax(0, 1fr); }
@media (max-width: 1100px) { .mem-layout { grid-template-columns: minmax(0, 1fr); } }
.mem-list { align-self: start; }
.mem-strip { display: flex; flex-direction: column; gap: 7px; padding: 12px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.mem-strip-k { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.07em; color: var(--color-text-tertiary); }
.mem-strip-auth { display: flex; gap: 6px; flex-wrap: wrap; }
.mem-group + .mem-group { border-top: 0.5px solid var(--color-border-tertiary); }
.mem-group-hdr { padding: 9px 16px; font-family: var(--font-display); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-secondary);
  background: var(--color-background-secondary); display: flex; align-items: center; gap: 7px; }
.mem-group-n { font-family: var(--font-mono); font-size: 10px; color: var(--color-text-tertiary); }

/* The fact card — a governed record, not a private summary. */
.fact-card { padding: 18px 20px; gap: 0; position: sticky; top: 16px; }
.fact-placeholder { min-height: 220px; }
/* WF-1 — expand-in-place (master-detail accordion). The focused fact's card now renders
   inline, in-flow, directly beneath its list row in a SINGLE column (replacing the old
   two-pane .mem-layout right pane), so a long register list no longer forces a scroll
   away to read the detail. Structural only: the .fact-* card styling is reused verbatim;
   only the layout (static / in-flow / full-width, not sticky side-pane) changes. Final
   visual taste is the operator's at Walk-2 (UR-21). */
.mem-accordion { display: block; }
.fact-card-inline { position: static; top: auto; border: none; border-radius: 0;
  border-bottom: 0.5px solid var(--color-border-tertiary);
  background: var(--color-background-secondary); }
.fact-card-inline:last-child { border-bottom: none; }
.fact-card-hd { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.fact-lock { font-size: 10px; font-weight: 600; color: var(--color-text-primary); display: inline-flex; align-items: center; gap: 3px; }
.fact-statement { font-family: var(--font-display); font-size: 17px; font-weight: 500; line-height: 1.4; letter-spacing: -0.01em; color: var(--color-text-primary); }
.fact-scope { font-size: 11px; color: var(--color-text-secondary); margin-top: 5px; }
.fact-scope strong { font-family: var(--font-mono); font-weight: 500; color: var(--color-text-primary); }
.fact-trust { font-size: 12px; line-height: 1.5; padding: 9px 12px; border-radius: var(--border-radius-md); margin: 14px 0 4px; border: 0.5px solid; }
.fact-trust a { color: var(--color-accent); font-weight: 500; }
.fact-trust-disputed { background: var(--color-background-secondary); border-color: #FAC775; color: var(--color-warn); }
.fact-trust-unverified { background: var(--color-background-secondary); border-color: var(--color-border-secondary); color: var(--color-text-secondary); }
.fact-trust-verified { background: var(--color-background-secondary); border-color: var(--color-border-tertiary); color: var(--color-text-secondary); }
.fact-trust-withdrawn { background: var(--color-background-secondary); border-color: var(--color-border-secondary); color: var(--color-text-secondary); }
.fact-trust-superseded { background: var(--color-background-secondary); border-color: var(--color-border-secondary); color: var(--color-text-secondary); }
.fact-field { padding-top: 14px; margin-top: 14px; border-top: 0.5px solid var(--color-border-tertiary); }
.fact-field-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.07em; color: var(--color-text-tertiary); margin-bottom: 9px; }
.fact-field-note { font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--color-text-tertiary); }
.fact-prov { display: flex; flex-direction: column; gap: 7px; }
.fact-prov-row { display: grid; grid-template-columns: 76px 1fr; gap: 10px; font-size: 12px; line-height: 1.4; align-items: baseline; }
.fact-prov-k { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-tertiary); }
.fact-prov-row .mono { font-family: var(--font-mono); font-size: 11px; color: var(--color-text-secondary); word-break: break-all; }
.src-chip { display: inline-flex; align-items: center; font-size: 11px; font-weight: 500; padding: 2px 8px; border-radius: var(--border-radius-md); background: var(--memry-accent-tint); color: var(--color-accent-dark); border: 0.5px solid rgba(216, 90, 48, 0.25); }
:root[data-theme="dark"] .src-chip { border-color: rgba(232, 121, 74, 0.35); }
.fact-who { font-size: 12px; line-height: 1.55; color: var(--color-text-secondary); }
.fact-thin { font-size: 11px; color: var(--color-text-tertiary); font-style: italic; }
.fact-hist { display: flex; flex-direction: column; }
.fact-hist-node { padding: 9px 0; border-bottom: 0.5px solid var(--color-border-tertiary); }
.fact-hist-node:last-child { border-bottom: none; }
.fact-hist-when { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); margin-bottom: 4px; display: flex; align-items: center; gap: 6px; }
.fact-hist-now { font-family: var(--font-sans); font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-ok); background: #EAF3DE; padding: 1px 6px; border-radius: 3px; }
:root[data-theme="dark"] .fact-hist-now { background: #20330F; color: #9FCD72; }
.fact-hist-val { font-size: 12.5px; line-height: 1.45; color: var(--color-text-primary); display: flex; gap: 7px; align-items: baseline; }
.fact-hist-all { display: inline-block; margin-top: 10px; font-size: 11px; color: var(--color-accent); font-weight: 500; }

/* --- Read-the-receipt chain (UR-03 / P0): a fact's governance journey rendered as a
   four-step stepper, Source -> Proposed -> Signed off -> Locked. --- */
.receipt { display: flex; flex-direction: column; }
.receipt-step { display: grid; grid-template-columns: 22px 1fr; gap: 10px; padding: 8px 0; position: relative; }
.receipt-step:not(:last-child)::before { content: ""; position: absolute; left: 10px; top: 25px; bottom: -7px; width: 1.5px; background: var(--color-border-secondary); }
.receipt-dot { width: 21px; height: 21px; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; border-radius: 50%; background: var(--color-background-tertiary); border: 1px solid var(--color-border-secondary); z-index: 1; }
.receipt-step-label { font-size: 11px; font-weight: 600; color: var(--color-text-secondary); margin-bottom: 2px; }
.receipt-step-detail { font-size: 12px; line-height: 1.5; color: var(--color-text-primary); }
.receipt-done .receipt-dot { background: #EAF3DE; border-color: var(--color-ok); color: var(--color-ok); }
.receipt-current .receipt-dot { background: var(--memry-accent-tint); border-color: var(--color-accent); color: var(--color-accent-dark); box-shadow: 0 0 0 3px var(--memry-accent-tint); }
.receipt-current .receipt-step-label { color: var(--color-accent-dark); }
.receipt-pending .receipt-dot { opacity: 0.5; }
.receipt-pending .receipt-step-label { color: var(--color-text-tertiary); }
.receipt-quote { font-size: 12px; font-style: italic; color: var(--color-text-secondary); border-left: 2px solid var(--color-border-secondary); padding-left: 9px; margin-bottom: 5px; line-height: 1.45; }
.receipt-open { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; font-weight: 500; color: var(--color-accent); }
.receipt-coming { margin-top: 3px; }
:root[data-theme="dark"] .receipt-done .receipt-dot { background: #20330F; color: #9FCD72; }
/* Beat 2 (OCCm16, BI-OCCM15-F2) — the receipt's terminal WITHDRAW / REPLACE step + a muted authority
   pill on a non-active fact card, so a withdrawn/superseded record never reads as live. */
.receipt-withdrawn .receipt-dot { color: var(--color-danger); }
.receipt-withdrawn .receipt-step-label { color: var(--color-danger); }
.receipt-superseded .receipt-dot { color: var(--color-text-secondary); }
.fact-card-hd-inactive .auth { opacity: 0.5; }

/* --- Document reader (UR-01): the source body + the highlighted cited passage. --- */
.reader-actions { display: flex; gap: 8px; }
.reader-panel { padding: 0; overflow: hidden; }
.reader-body { font-family: var(--font-mono); font-size: 12.5px; line-height: 1.65; color: var(--color-text-primary); white-space: pre-wrap; word-break: break-word; padding: 20px 22px; margin: 0; max-height: 70vh; overflow-y: auto; }
.reader-cite { background: #FBE7C6; color: var(--color-text-primary); padding: 1px 2px; border-radius: 2px; scroll-margin-top: 80px; box-shadow: 0 0 0 2px #FBE7C6; }
.reader-cite-note { color: var(--color-accent-dark); font-weight: 500; }
:root[data-theme="dark"] .reader-cite { background: #4A3A12; box-shadow: 0 0 0 2px #4A3A12; color: #F1EFE8; }

/* --- Decisions register (Max §3): status chips + the prominent, mandatory "Why" --- */
.dec-status { display: inline-flex; align-items: center; font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 3px; white-space: nowrap; letter-spacing: 0.02em; }
.dec-decided { background: #E6F1FB; color: #0C447C; }
.dec-locked { background: var(--memry-ink); color: #F1EFE8; }
.dec-proposed { background: #FAEEDA; color: var(--color-warn); }
.dec-superseded { background: var(--color-background-tertiary); color: var(--color-text-tertiary); }
:root[data-theme="dark"] .dec-decided { background: #16344F; color: #9CC7F0; }
:root[data-theme="dark"] .dec-locked { background: #E8EBED; color: #12171C; }
:root[data-theme="dark"] .dec-proposed { background: #3A2F12; color: #E0B062; }
/* The "Why we decided this" — first-class + prominent (the field rivals make optional). */
.fact-why { font-size: 13.5px; line-height: 1.6; color: var(--color-text-primary);
  background: var(--color-background-secondary); border-left: 3px solid var(--color-accent);
  border-radius: 0 var(--border-radius-md) var(--border-radius-md) 0; padding: 11px 14px; }
.fact-why-empty { color: var(--color-text-tertiary); font-style: italic; border-left-color: var(--color-border-secondary); }
.dec-link { font-family: var(--font-mono); font-size: 11px; color: var(--color-accent); }

/* --- Commitments register (Max §4): sentence rows, status chips, two-party block --- */
.cmt-line { font-size: 12px; color: var(--color-text-secondary); line-height: 1.4; margin: 3px 0 5px; }
.cmt-line strong { color: var(--color-text-primary); font-weight: 600; }
/* WF-6 — the deliverable ("what") leads as the dominant full-width line; the parties /
   due / status / when-added drop to one compact, muted sub-row beneath it. */
.cmt-what-lead { font-size: 13.5px; font-weight: 600; line-height: 1.4; color: var(--color-text-primary); margin-bottom: 4px; }
.cmt-subrow { font-size: 11px; color: var(--color-text-tertiary); line-height: 1.5; display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.cmt-added { color: var(--color-text-tertiary); }
/* WF-9 — denser list rows: a one-line contradiction description + a kind tag so a
   Conflict row (and the thin Link rows) say what they are without being opened. */
.citem-desc { font-size: 11px; color: var(--color-text-secondary); line-height: 1.4; margin: 2px 0 4px; }
.cf-kind { display: inline-block; font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-tertiary); }
/* WF-10 — a plain caption under each History panel header, naming the panel's job. */
.log-caption { padding: 7px 16px 0; font-size: 11px; color: var(--color-text-tertiary); line-height: 1.45; }
/* FIX 4 (2026-06-28) — discoverability cue + selected-row highlight in the History log. */
.log-cue { margin: 8px 16px 0; padding: 5px 10px; font-size: 11px; font-weight: 500;
  color: var(--color-accent-dark); background: var(--memry-accent-tint, var(--color-background-secondary));
  border-radius: var(--border-radius-md); display: inline-block; }
.tbl tbody tr.audit-row-selected td { background: var(--color-background-info); box-shadow: inset 2px 0 0 var(--color-accent); }
.tbl tbody tr.audit-row-selected:hover td { background: var(--color-background-info); }
/* FIX (2026-06-28 re-audit) — the whole left-log event row is a trace target. Rows with an
   entryId carry .audit-row-clickable: a pointer cursor + a stronger hover highlight signal the
   row is interactive (the operator could not tell the rows were clickable). The action + entry
   cells and the "trace →" affordance are real links to /audit?entry=<id>. */
.tbl tbody tr.audit-row-clickable { cursor: pointer; }
.tbl tbody tr.audit-row-clickable:hover td { background: var(--color-background-info); }
.audit-act-link { text-decoration: none; }
.audit-trace { margin-left: 6px; font-size: 11px; font-weight: 600; white-space: nowrap;
  color: var(--color-accent); text-decoration: none; opacity: 0.85; }
.audit-trace:hover { text-decoration: underline; opacity: 1; }
.tbl tbody tr.audit-row-clickable:hover .audit-trace { opacity: 1; }
/* FIX 2 (2026-06-28) — a collapsed run of consecutive briefing_assembled ("Caught up N×"). */
.tbl tbody tr.audit-collapsed-run td { color: var(--color-text-secondary); }
.audit-runcount { display: inline-block; font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  color: var(--color-text-secondary); background: var(--color-background-secondary);
  border-radius: 4px; padding: 0 5px; margin-left: 4px; }
.cmt-due { color: var(--color-text-secondary); }
.cmt-hd-due { font-size: 11px; color: var(--color-text-secondary); margin-left: auto; }
.cmt-status { display: inline-flex; align-items: center; font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 3px; white-space: nowrap; }
.cmt-open { background: #E6F1FB; color: #0C447C; }
.cmt-atrisk { background: #FAEEDA; color: var(--color-warn); }
.cmt-met { background: #EAF3DE; color: var(--color-ok); }
.cmt-failed { background: #FCEBEB; color: var(--color-danger); }
.cmt-reneg { background: #E6F1FB; color: #185FA5; }
/* in_progress list chip (Wave 3A) — info-tinted, reusing the .cs-in_progress blue so the List
   status chip matches the Board "In progress" column + the commitmentStatusPill. */
.cmt-inprogress { background: #E6F1FB; color: #185FA5; }
.cmt-disputed { background: #FCEBEB; color: var(--color-danger); border: 0.5px solid #E0B4B4; }
:root[data-theme="dark"] .cmt-open { background: #16344F; color: #9CC7F0; }
:root[data-theme="dark"] .cmt-atrisk { background: #3A2F12; color: #E0B062; }
:root[data-theme="dark"] .cmt-met { background: #20330F; color: #9FCD72; }
:root[data-theme="dark"] .cmt-failed, :root[data-theme="dark"] .cmt-disputed { background: #3A1B1B; color: #E58A8A; border-color: #5A2A2A; }
:root[data-theme="dark"] .cmt-reneg { background: #16344F; color: #8FC0EE; }
:root[data-theme="dark"] .cmt-inprogress { background: #16344F; color: #8FC0EE; }
.cmt-parties { display: flex; flex-wrap: wrap; gap: 10px; }
.cmt-party { flex: 1 1 200px; display: flex; flex-direction: column; gap: 4px; background: var(--color-background-secondary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); padding: 9px 12px; }
.cmt-party-k { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-tertiary); }
.cmt-party-v { font-size: 13px; color: var(--color-text-primary); line-height: 1.4; }
.cmt-term { font-size: 12px; color: var(--color-text-secondary); line-height: 1.5; padding: 6px 0; border-bottom: 0.5px solid var(--color-border-tertiary); }
.cmt-term:last-child { border-bottom: none; }

/* --- People register (Max §5): sourced profile fields + live commitments join --- */
.person-fields { display: flex; flex-direction: column; }
.person-field { display: grid; grid-template-columns: 110px 1fr; gap: 12px; padding: 7px 0; border-bottom: 0.5px solid var(--color-border-tertiary); font-size: 12.5px; line-height: 1.45; }
.person-field:last-child { border-bottom: none; }
.person-field-k { font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-tertiary); padding-top: 2px; }
.person-field-v { color: var(--color-text-primary); }
.person-cmts { display: flex; flex-direction: column; gap: 7px; }
.person-cmt { display: flex; flex-direction: column; gap: 4px; padding: 9px 12px; background: var(--color-background-secondary); border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); }
.person-cmt:hover { border-color: var(--color-accent); }
.person-cmt-what { font-size: 12.5px; color: var(--color-text-primary); line-height: 1.4; }
.person-cmt-meta { font-size: 10px; color: var(--color-text-tertiary); display: flex; align-items: center; gap: 6px; }
.person-owedby { margin-top: 9px; }
.kind-chip { display: inline-flex; align-items: center; font-size: 9px; font-weight: 600; padding: 2px 7px; border-radius: 3px; text-transform: uppercase; letter-spacing: 0.04em; }
.kind-person { background: var(--color-background-tertiary); color: var(--color-text-secondary); }
.kind-org { background: var(--memry-accent-tint); color: var(--color-accent-dark); }
:root[data-theme="dark"] .kind-org { background: #3A2417; color: var(--color-accent-dark); }

/* --- History — "as of [date]" scrubber (Max §8 point-in-time recall) --- */
.asof { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; padding: 12px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); background: var(--color-background-secondary); }
.asof-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-tertiary); }
.asof input[type="date"] { font-family: var(--font-sans); font-size: 12px; color: var(--color-text-primary); background: var(--color-background-primary); border: 0.5px solid var(--color-border-secondary); border-radius: var(--border-radius-md); padding: 6px 9px; }
.asof input[type="date"]:focus { outline: none; border-color: var(--color-accent); }
.asof-hint { flex: 1 1 100%; font-size: 10px; color: var(--color-text-tertiary); }
.asof-result { padding: 10px 16px; font-size: 12.5px; line-height: 1.5; color: var(--color-text-primary); border-bottom: 0.5px solid var(--color-border-tertiary); background: var(--color-background-info); display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.asof-none { color: var(--color-text-secondary); background: var(--color-background-secondary); }
.node-card.asof-active { border-color: var(--color-accent); box-shadow: inset 2px 0 0 var(--color-accent); }

/* --- Documents §7-depth: per-fact source chips + back-link to the governed record --- */
.doc-fact-src { margin: 7px 0 4px; display: flex; flex-wrap: wrap; gap: 5px; }
.doc-fact-link { display: inline-block; margin-top: 5px; font-size: 11px; color: var(--color-accent); font-weight: 500; }

/* --- Settings: the authority model, in plain words (Max App. B — the wedge visible) --- */
.auth-rules { display: flex; flex-direction: column; gap: 9px; }
.auth-rule { display: grid; grid-template-columns: 84px 1fr; gap: 12px; align-items: start; }
.auth-rule-k { padding-top: 1px; }
.auth-rule-v { font-size: 12.5px; line-height: 1.5; color: var(--color-text-secondary); }
.auth-rule-v strong { color: var(--color-text-primary); font-weight: 600; }
.auth-assistant { display: flex; gap: 9px; align-items: flex-start; margin-top: 14px; padding: 11px 14px; background: var(--memry-accent-tint); border: 0.5px solid rgba(216, 90, 48, 0.25); border-radius: var(--border-radius-md); font-size: 12.5px; line-height: 1.55; color: var(--color-text-primary); }
.auth-assistant .node-icon { color: var(--color-accent-dark); flex-shrink: 0; margin-top: 1px; }
:root[data-theme="dark"] .auth-assistant { background: #3A2417; border-color: rgba(232, 121, 74, 0.30); }
.auth-defaults { margin-top: 12px; font-size: 12px; line-height: 1.6; color: var(--color-text-secondary); }
.auth-coming { color: var(--color-text-tertiary); font-style: italic; }

/* --- Assistant §6: scope picker + citation chip that resolves to the governed fact --- */
.chat-scope { display: inline-flex; gap: 5px; flex-wrap: wrap; }
.cite-fact { display: inline-block; margin-top: 4px; margin-left: 1px; font-size: 10px; font-weight: 500; color: var(--color-accent); }

/* --- Entity hover-card (UR-17): person/org names → on-hover compact card --- */
/* The ref is a subtle link (dotted underline) so a name still reads as text; no-JS it
   navigates to the People card, with-JS it shows the popover below. */
.entity-ref { color: inherit; text-decoration: none; border-bottom: 1px dotted var(--color-border-secondary); cursor: help; }
.entity-ref:hover, .entity-ref:focus { border-bottom-color: var(--color-accent); color: var(--color-accent-dark); }
.entity-pop { position: absolute; z-index: 60; max-width: 280px; pointer-events: auto; }
.entity-card { background: var(--color-background-primary); border: 0.5px solid var(--color-border-secondary); border-radius: var(--border-radius-lg); box-shadow: var(--shadow-card-hover); padding: 12px 14px; font-size: 12px; line-height: 1.5; min-width: 200px; }
.entity-card-empty, .entity-card-thin { color: var(--color-text-tertiary); font-size: 11px; }
.entity-card-hd { display: flex; gap: 6px; align-items: center; margin-bottom: 6px; }
.entity-card-name { font-size: 13.5px; font-weight: 600; color: var(--color-text-primary); }
.entity-card-known { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); margin-top: 2px; }
.entity-card-attrs { margin-top: 8px; display: flex; flex-direction: column; gap: 3px; }
.entity-card-row { display: flex; gap: 8px; }
.entity-card-k { color: var(--color-text-tertiary); text-transform: capitalize; min-width: 56px; }
.entity-card-v { color: var(--color-text-secondary); }
.entity-card-more { display: inline-block; margin-top: 9px; font-size: 11px; font-weight: 500; color: var(--color-accent); }
:root[data-theme="dark"] .entity-card { background: var(--color-background-secondary); }

/* --- Home: "what MEMRY caught" governance band (UR-23 — action/value above the lists) --- */
.hcaught { margin-bottom: 14px; }
/* doc 05 §3.4 — the governance-dividend strip, between the band header and the rows
   (render/home.js caughtDividend). It carried NO rule at all until now, so the cluster sat
   flush against the panel's left edge with nothing dividing it from the first row: .hcaught-row
   suppresses its own separator on :first-child, so the strip is the element that has to draw it.
   Nothing here is invented. The 16px inset is the band's own (.hcaught-row / .panel-header) and
   the 9px is .hcaught-row's; the closing hairline is .panel-header's declaration verbatim —
   `border-bottom: 0.5px solid var(--color-border-tertiary)` — which is the same line
   .hcaught-row draws between rows as its own border-top. `display: flex` is .hcaught-body's,
   and it also keeps the inline-flex pill off the text baseline (no descender gap under it).
   ⚑ THE :last-child RESET IS THE SHEET'S STANDING PAIRING (.hactioned-row / .gov-card /
   .triage-verbs), and it is load-bearing rather than tidiness: caughtPanel renders the strip
   with NO .hcaught-body when the feed is empty but the dividend is not, and a hairline sitting
   against the panel's own bottom edge reads as a double rule. */
.hcaught-dividend { display: flex; padding: 9px 16px;
  border-bottom: 0.5px solid var(--color-border-tertiary); }
.hcaught-dividend:last-child { border-bottom: none; }
.hcaught-body { display: flex; flex-direction: column; }
.hcaught-row { display: flex; align-items: center; gap: 10px; padding: 9px 16px; border-top: 0.5px solid var(--color-border-tertiary); color: var(--color-text-primary); text-decoration: none; }
.hcaught-row:first-child { border-top: 0; }
.hcaught-row:hover { background: var(--color-background-tertiary); }
.hcaught-ic { flex-shrink: 0; width: 18px; text-align: center; }
.hcaught-label { font-size: 12.5px; font-weight: 500; }
.hcaught-sum { font-size: 10px; color: var(--color-text-secondary); font-family: var(--font-mono); }
.hcaught-time { margin-left: auto; font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); }
.hcaught-contradiction .hcaught-ic { color: var(--color-accent-dark); }
.hcaught-blocked .hcaught-ic { color: var(--color-accent-dark); }

/* --- UR-09: change CTAs on fact cards + the corrected-value flow on the Conflict Queue --- */
.change-cta { display: flex; gap: 14px; margin-top: 8px; flex-wrap: wrap; }
.change-cta-link { font-size: 11px; font-weight: 500; color: var(--color-accent); text-decoration: none; }
.change-cta-link:hover { text-decoration: underline; }
.res-correct { margin-top: 14px; padding-top: 14px; border-top: 0.5px solid var(--color-border-tertiary); }
.res-sub { font-weight: 400; color: var(--color-text-tertiary); font-size: 11px; }
.pending-correction { margin-top: 14px; padding: 14px 16px; border-left: 2px solid var(--color-accent); }
.pc-value { font-size: 13px; font-weight: 500; margin: 6px 0; }
.pc-why { font-size: 12px; color: var(--color-text-secondary); margin-bottom: 6px; }
.pc-meta { font-size: 11px; color: var(--color-text-tertiary); margin-bottom: 10px; line-height: 1.5; }

/* ── MEMRY UI completion build — clickability/flow affordances (UX-01..28) ────────── */
/* Per-count dividend drill (UX-01): the counts are links, and `color: inherit` is what keeps
   them reading as part of the cluster rather than taking a link colour of their own. (It said
   "keep the chrome look" until the §3.4 move re-liveried the cluster for Home's light panel;
   the declaration is unchanged — only the palette it inherits moved.) */
.dividend .dv { cursor: pointer; color: inherit; }
.dividend .dv:hover b, .dividend .dv:hover { color: var(--color-accent); }
/* Folder/org scope-tree rows are scaffolding, not destinations (UX-24): visibly inert. */
.node-row.node-static { cursor: default; }
.node-row.node-static:hover { background: transparent; }
/* Clickable source chips (UX-05/09/14/19/27) — the inert chip, now a link to the doc. */
.src-chip-link { cursor: pointer; text-decoration: none; transition: border-color 0.12s, background 0.12s; }
.src-chip-link:hover { border-color: var(--color-accent); background: var(--memry-accent-tint); }
/* Glass-box provenance source link (UX-27/28). */
.src-link { color: var(--color-accent); text-decoration: none; }
.src-link:hover { text-decoration: underline; }
/* History value-node, now openable (UX-06/17). */
a.fact-hist-link { display: block; color: inherit; text-decoration: none; cursor: pointer; }
a.fact-hist-link:hover { background: var(--color-background-secondary); }
/* Breadcrumb parent-scope links (UX-22). */
.crumb-link { color: inherit; text-decoration: none; cursor: pointer; }
.crumb-link:hover { color: var(--color-accent); text-decoration: underline; }
/* Decision statement drill-through (UX-22) + Home sign-off title (UX-03). */
a.dec-stmt-link, a.hq-title-link { color: inherit; text-decoration: none; cursor: pointer; }
a.dec-stmt-link:hover, a.hq-title-link:hover { color: var(--color-accent); }
/* Needs-review badge as a link (UX-23) + Documents "Sourced" status link (UX-18). */
a.badge-link, a.sp-link { cursor: pointer; text-decoration: none; }
a.badge-link:hover, a.sp-link:hover { filter: brightness(0.94); }
/* Commitment list party names — de-emphasised so they no longer read as clickable (UX-11). */
.cmt-party-name { font-weight: 500; color: var(--color-text-secondary); }

/* ── MEMRY UI completion build — assistant UX (AR-1/AR-4/AR-5) ─────────────────────── */
/* AR-1 — the conversation is the star: main column + a collapsible briefing sidekick.
   WF-7 — the conversation viewport is WIDER (the briefing sidebar trimmed 360→320 and the
   conversation grows into the freed room + a taller pane), and assistant answers use the
   full column width so long grounded replies read comfortably. */
.chat-main-layout { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 14px; align-items: start; }
.chat-main-layout .conv-pane { max-height: 78vh; }
.chat-main-layout .conv-thread .msg-assistant { max-width: 100%; }
.brief-collapsible { max-height: 78vh; overflow: hidden; }
.brief-collapsible[open] { overflow: auto; }
.brief-toggle { cursor: pointer; list-style: none; justify-content: space-between; }
.brief-toggle::-webkit-details-marker { display: none; }
.brief-toggle::after { content: '▾'; margin-left: auto; color: var(--color-text-tertiary); font-size: 12px; }
.brief-collapsible:not([open]) .brief-toggle::after { content: '▸'; }
@media (max-width: 900px) { .chat-main-layout { grid-template-columns: 1fr; } }
/* AR-4 / WF-7 — the starter questions are a collapsed <details> DROPDOWN (frees the
   vertical space the always-open chip row used to eat; opens to reveal project-relevant
   starters). */
.prompt-suggestions { padding: 8px 16px 0; }
.prompt-suggestions-hd { font-size: 11px; color: var(--color-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em;
  cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px;
  border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); background: var(--color-background-secondary); }
.prompt-suggestions-hd::-webkit-details-marker { display: none; }
.prompt-suggestions-hd::after { content: '▾'; color: var(--color-text-tertiary); }
.prompt-suggestions[open] .prompt-suggestions-hd::after { content: '▴'; }
.prompt-chip-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.prompt-chip { font: inherit; font-size: 12px; cursor: pointer; padding: 4px 10px; border-radius: 999px;
  border: 0.5px solid var(--color-border-secondary); background: var(--color-background-secondary); color: var(--color-text-secondary); }
.prompt-chip:hover { border-color: var(--color-accent); color: var(--color-accent-dark); background: var(--memry-accent-tint); }
/* WF-7 — the end-session / close control in the chat topbar (clears the conversation). */
.chat-end { display: inline; margin: 0; }
.chat-end-btn { font: inherit; font-size: 11px; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 10px; border-radius: var(--border-radius-md); border: 0.5px solid var(--color-border-secondary);
  background: var(--color-background-secondary); color: var(--color-text-secondary); }
.chat-end-btn:hover { border-color: var(--color-danger); color: var(--color-danger); }
/* WF-11 — the context-aware "Ask" affordance in the dark top bar (every screen).
   FIX 5 (2026-06-28) — it now also carries .act-btn so it matches the sibling topbar
   actions' height/padding; this class only supplies the dark-chrome colour + the
   nowrap, leaving the box model (padding/font-size/radius) to .act-btn.
   FIX (2026-07-17) — this rule now covers ALL THREE topbar quick actions (.ask-
   affordance, .topbar-update, .topbar-catchup), not just Ask: the top bar stays dark
   chrome in BOTH themes, but Update/Catch-up had no explicit colour of their own, so
   in the LIGHT theme they fell through to .act-btn's colourless/borderless base rule
   and rendered invisible label text + invisible border on the dark chrome. Same
   colours as before, no new values invented. */
.ask-affordance, .topbar-update, .topbar-catchup { color: rgba(255, 255, 255, 0.82); border-color: rgba(255, 255, 255, 0.16); white-space: nowrap; }
.ask-affordance:hover, .topbar-update:hover, .topbar-catchup:hover { border-color: var(--color-accent); color: #fff; }
/* W20 (2026-08-27) — THE `Add` CHIP JOINS THE LABEL-HIDE SET. Below 1100px the top bar
   collapsed THREE of its FOUR quick actions to icons and left Add carrying its word, so the
   cluster read as three icons and one label at any laptop width. Add was simply absent from
   this selector list; adding `.topbar-add-label` (render/layout.js — page()) is the whole fix.

   ⛔ AND ONLY FROM THIS LIST — the asymmetry with the two rules above is CORRECT, not an
   oversight to tidy up. Those two exist because .ask-affordance / .topbar-update /
   .topbar-catchup carry no colour of their own and fall through .act-btn's colourless base
   (the 2026-07-17 note above states it). The Add chip carries .act-primary, so it already has
   an explicit orange fill and an explicit white; putting .topbar-add in the colour rule would
   paint over the fill it was given. Label-hiding is about WIDTH and applies to all four;
   dark-chrome colour is about the missing paint and applies only to the three.

   ⚑ tests/cairn/cairn_ui_topbar_chrome.test.js pinned this selector list with an EXACT regex,
   so this line reddens that expectation by construction. Operator-authorised directly,
   2026-08-27 (memry18 operator queue item 22). The test is re-cut in the SAME change to pin
   the PROPERTY — each named label span is in the hide set — instead of the literal list. */
@media (max-width: 1100px) { .ask-affordance-label, .topbar-update-label, .topbar-catchup-label, .topbar-add-label { display: none; } }
/* WF-3 — Home "Just signed off" close-the-loop band + the DRAFT-vs-LOCKED help. */
.hactioned-body { display: flex; flex-direction: column; }
.hactioned-row { display: flex; align-items: center; gap: 10px; padding: 9px 16px; text-decoration: none;
  color: var(--color-text-primary); border-bottom: 0.5px solid var(--color-border-tertiary); }
.hactioned-row:last-child { border-bottom: none; }
.hactioned-row:hover { background: var(--color-background-secondary); }
.hactioned-label { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ha-out { font-size: 11px; font-weight: 500; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.ha-out-ok { color: var(--color-ok); }
.ha-out-no { color: var(--color-text-tertiary); }
.hactioned-time { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); white-space: nowrap; }
.signoff-help { margin: 0 0 10px; font-size: 12px; }
.signoff-help-q { cursor: pointer; color: var(--color-accent); font-size: 12px; list-style: none; }
.signoff-help-q::-webkit-details-marker { display: none; }
.signoff-help-q::before { content: '▸ '; }
.signoff-help[open] .signoff-help-q::before { content: '▾ '; }
.signoff-help-a { margin-top: 6px; color: var(--color-text-secondary); line-height: 1.5; }
.signoff-help-a p { margin: 0 0 6px; }
.signoff-help-a p:last-child { margin-bottom: 0; }
/* AR-5 — rendered assistant markdown inside the bubble (escape-first, bounded subset). */
.md-body { white-space: normal; }
.md-body p { margin: 0 0 8px; }
.md-body p:last-child { margin-bottom: 0; }
.md-body .md-h { font-size: 13px; font-weight: 600; margin: 8px 0 4px; color: var(--color-text-primary); }
.md-body ul.md-ul, .md-body ol.md-ol { margin: 4px 0 8px; padding-left: 20px; }
.md-body li { margin: 2px 0; }
.md-body code.md-code { font-family: var(--font-mono, monospace); font-size: 12px; background: var(--color-background-tertiary, rgba(0,0,0,0.05)); padding: 1px 5px; border-radius: 4px; }
.md-body pre.md-pre { background: var(--color-background-tertiary, rgba(0,0,0,0.05)); border-radius: 6px; padding: 10px 12px; overflow-x: auto; margin: 6px 0; }
.md-body pre.md-pre code { font-family: var(--font-mono, monospace); font-size: 12px; background: none; padding: 0; }
.md-body a.md-link { color: var(--color-accent); text-decoration: underline; }

/* --- WF-8 discoverability (Projects title · Connect-your-AI explainer · clickable
   vital counts · in-project Open Conflicts). Structural only; final colour/spacing/type
   is operator Walk-2 (UR-21). --- */
.page-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.page-sub { font-size: 12px; color: var(--color-text-tertiary); }
/* Vital counts are links into their scoped register; they keep the count typography and
   only gain a link affordance (the inline red on open-conflicts wins by specificity). */
.v-link, .vital-link { text-decoration: none; color: inherit; cursor: pointer; }
.v-link:hover, .vital-link:hover { text-decoration: underline; }
/* Connect-your-AI plain-language explainer. */
.connect-lead { padding: 12px 18px 0; font-size: 12px; color: var(--color-text-secondary); line-height: 1.5; }
.connect-point { display: block; margin-bottom: 5px; }
.connect-point:last-child { margin-bottom: 0; }
/* In-project Open Conflicts list (zoneConflicts). Reuses .panel / .sev / .cf-kind / .empty. */
.oc-row { display: block; padding: 10px 16px; border-bottom: 0.5px solid var(--color-border-tertiary); text-decoration: none; color: inherit; }
.oc-row:last-child { border-bottom: none; }
.oc-row:hover { background: var(--color-background-secondary); }
.oc-title { font-size: 12px; font-weight: 500; color: var(--color-text-primary); line-height: 1.35; margin-bottom: 4px; }
.oc-meta { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-mono); display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }

/* --- Briefing surfaces: Update (/report) + Catch up (/catchup). A scannable, grouped
   briefing — headline, one-line count, UPPERCASE groups (DECIDED / NEEDS ATTENTION /
   CHANGED SINCE), each bullet carrying a subtle inline source arrow (↗). Replaces the old
   unstyled report-* flat dump. --- */
.brief { padding: 18px 22px 20px; gap: 4px; box-shadow: var(--shadow-card); }
.brief-head { font-family: var(--font-display); font-size: 18px; font-weight: 500; color: var(--color-text-primary); line-height: 1.3; }
.brief-count { font-size: 12.5px; color: var(--color-text-secondary); margin-top: 3px; }
.brief-group { display: flex; flex-direction: column; gap: 6px; margin-top: 20px; }
.brief-group-label { font-family: var(--font-mono); font-size: 10.5px; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--color-text-tertiary); }
.brief-rows { display: flex; flex-direction: column; gap: 5px; }
.brief-line { display: flex; align-items: baseline; gap: 8px; font-size: 13.5px; line-height: 1.5; color: var(--color-text-primary); }
.brief-line::before { content: "•"; color: var(--color-text-tertiary); flex: none; }
.brief-line-text { flex: 1 1 auto; min-width: 0; }
.brief-src { flex: none; font-size: 13px; line-height: 1; text-decoration: none; color: var(--color-text-tertiary); padding: 0 2px; }
.brief-src:hover { color: var(--color-accent); }
.brief-empty { font-size: 12.5px; color: var(--color-text-tertiary); font-style: italic; line-height: 1.5; }
.brief-conf { font-size: 10px; font-family: var(--font-mono); color: var(--color-text-tertiary); margin-left: 6px; white-space: nowrap; }
.brief-chip { display: inline-flex; align-items: center; font-size: 10px; font-weight: 500; font-family: var(--font-mono); padding: 1px 6px; border-radius: 3px; margin-left: 6px; white-space: nowrap; }
.brief-chip-soon { background: #FAEEDA; color: var(--color-warn); }
.brief-chip-overdue { background: #F7DEDE; color: var(--color-danger); }
.brief-attn .brief-line::before { color: var(--color-accent); }
.brief-changed .brief-line-text { color: var(--color-text-secondary); }
.brief-actions { margin-top: 22px; padding-top: 16px; border-top: 0.5px solid var(--color-border-tertiary); }
.brief-file { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.brief-file-note { font-size: 11.5px; color: var(--color-text-tertiary); line-height: 1.5; flex: 1 1 240px; }
/* Wave 1 — the DURABLE INLINE ASSISTANT panel: a docked right-side slide-in opened by the
   top-bar "Ask" affordance ON the current screen (instead of navigating to /chat). Reuses the
   streaming composer chrome (.conv-pane/.conv-thread/.input-area/.msg/.prompt-chip/.send-btn),
   so the existing streaming client wires it untouched. NO-JS CONTRACT (re-audit M2): a closed
   panel is hard-hidden by `.ask-panel[hidden] { display:none }` — an AUTHORITATIVE author-origin
   rule (the bare UA `[hidden]{display:none}` would lose to the base `display:flex`, author origin
   winning; this rule restores the attribute as the real hide). display:none also takes the closed
   panel OUT of layout, so its off-canvas box cannot introduce a horizontal scrollbar (re-audit M3).
   visibility:hidden + translateX(100%) is the secondary closed state for the open/close transition.
   JS reveals it by removing [hidden] + adding .ask-open; with JS off the "Ask" link navigates to /chat. */
.ask-panel { position: fixed; top: var(--topbar-h); right: 0; bottom: 0; width: min(400px, 92vw);
  z-index: 50; display: flex; flex-direction: column;
  background: var(--color-background-primary); border-left: 0.5px solid var(--color-border-secondary);
  box-shadow: -8px 0 28px rgba(30, 42, 50, 0.14);
  transform: translateX(100%); visibility: hidden; transition: transform 0.18s ease, visibility 0.18s ease; }
.ask-panel[hidden] { display: none; }
.ask-panel.ask-open { transform: translateX(0); visibility: visible; }
.ask-panel-hdr { display: flex; align-items: center; gap: 8px; padding: 11px 14px;
  border-bottom: 0.5px solid var(--color-border-tertiary); }
.ask-panel-title { font-family: var(--font-display); font-size: 13px; font-weight: 600; color: var(--color-text-primary); }
.ask-panel-scope { white-space: nowrap; }
.ask-panel-full { margin-left: auto; font-size: 11px; color: var(--color-accent); white-space: nowrap; }
.ask-panel-close { font: inherit; font-size: 18px; line-height: 1; cursor: pointer; border: none; background: none;
  color: var(--color-text-tertiary); padding: 0 4px; }
.ask-panel-close:hover { color: var(--color-text-primary); }
.ask-panel-ctx { padding: 8px 14px; font-size: 11px; color: var(--color-text-tertiary);
  border-bottom: 0.5px solid var(--color-border-tertiary); }
.ask-panel .conv-pane { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.ask-panel .conv-thread { flex: 1; overflow-y: auto; min-height: 0; }
.ask-panel .input-area { border-top: 0.5px solid var(--color-border-tertiary); }
@media (max-width: 560px) { .ask-panel { width: 100vw; } }

/* ===========================================================================
   OCCm1 Wave 1 styling round (OCC screenshot-walk findings F1 + F2, 2026-07-04).
   ADDITIVE RULES ONLY — appended last so same-specificity rules win. All colors
   ride the semantic tokens, so the dark theme flips with no per-rule retune.
   =========================================================================== */

/* F1 — Update (/report) template selector + as-of anchor form (W1-A). The
   .brief-template-tabs links were unstyled and ran together ("ProjectBoardInvestor");
   they now wear the projectScopeTabs (.ptab) pill visual — separated, hover, and a
   clear .active (aria-current) state — and the .brief-since date form sits on its
   own line with breathing room from the tabs. */
.brief-controls { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.brief-template-tabs { display: flex; gap: 4px; flex-wrap: wrap; }
.brief-template-tab { padding: 5px 13px; font-size: 12px; color: var(--color-text-secondary);
  border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md);
  background: var(--color-background-secondary); }
.brief-template-tab:hover { border-color: var(--color-accent); color: var(--color-accent-dark); }
.brief-template-tab.active { background: var(--color-background-primary); color: var(--color-text-primary);
  font-weight: 500; border-color: var(--color-border-primary); }
.brief-since { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.brief-since-label { display: inline-flex; align-items: center; gap: 8px; font-size: 11px;
  font-weight: 500; color: var(--color-text-secondary); }
/* Date control mirrors the History "as of" scrubber input idiom (.asof input[type=date]). */
.brief-since input[type="date"] { font-family: var(--font-sans); font-size: 12px;
  color: var(--color-text-primary); background: var(--color-background-primary);
  border: 0.5px solid var(--color-border-secondary); border-radius: var(--border-radius-md);
  padding: 6px 9px; }
.brief-since input[type="date"]:focus { outline: none; border-color: var(--color-accent); }
.brief-since .act-btn { background: var(--color-background-secondary); color: var(--color-text-secondary);
  border-color: var(--color-border-secondary); cursor: pointer; }
.brief-since .act-btn:hover { border-color: var(--color-accent); color: var(--color-accent-dark); }
/* The honest unparseable-?since= note — warn-toned, quiet. */
.brief-since-note { font-size: 11px; color: var(--color-warn); line-height: 1.5; }

/* F2 — Home "Start here" next-step + draft-nudge affordance (W1-C). The .triage-draft
   sibling anchor rendered as an ORPHANED full-width band item: the row's own
   border-bottom drew a separator BETWEEN the row and its draft link. Suppress that
   border on a row followed by its draft link (:has — evergreen-browser fine; without
   it the old separator harmlessly returns), tuck the link up under the row title
   (same 16px left inset), small muted-accent text, and let the link carry the group's
   closing border so band rhythm stays intact. .triage-next reads as muted inline meta
   at the .citem-meta size (sans face — it is prose, not a mono identifier). */
.triage-body .triage-row:has(+ .triage-draft) { border-bottom: none; padding-bottom: 3px; }
.triage-draft { display: block; padding: 0 16px 10px 16px; font-size: 11px; font-weight: 500;
  color: var(--color-accent-dark); border-bottom: 0.5px solid var(--color-border-tertiary); }
.triage-draft:hover { color: var(--color-accent); text-decoration: underline;
  background: var(--color-background-secondary); }
.triage-body .triage-draft:last-child { border-bottom: none; }
.triage-next { font-size: 10px; color: var(--color-text-tertiary); font-family: var(--font-sans); }

/* Feature A — "Save to record" on an assistant reply (chat + docked ask-panel). A quiet,
   secondary affordance under the bubble text; never competes with the reply itself. */
.msg-actions { margin-top: 6px; display: flex; }
.msg-save { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px;
  font-family: var(--font-sans); font-size: 11px; font-weight: 500; cursor: pointer;
  color: var(--color-text-secondary); background: var(--color-background-secondary);
  border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); }
.msg-save:hover { border-color: var(--color-accent); color: var(--color-accent-dark);
  background: var(--color-background-primary); }

/* Feature A — the Assets screen ("what Memry wrote for you"): the assistant-generated
   drafts filed back onto the record, each replayable in the document reader. */
.asset-list { display: flex; flex-direction: column; }
.asset-row { display: flex; flex-direction: column; gap: 5px; padding: 13px 16px;
  border-bottom: 0.5px solid var(--color-border-tertiary); }
.asset-row:last-child { border-bottom: none; }
.asset-row-main { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.asset-title { font-size: 14px; font-weight: 500; color: var(--color-text-primary); }
.asset-row-meta { font-size: 11px; color: var(--color-text-tertiary); font-family: var(--font-sans); }
.asset-row-actions { margin-top: 3px; }
.asset-noread { font-size: 11px; color: var(--color-warn); font-style: italic; }

/* Feature B — the "What's due" screen: the proactive scheduler surface (scanDue findings,
   grouped by kind). Mirrors the Assets/triage row rhythm — subject + muted meta stacked,
   a count pill per section header, hover only on the clickable commitment rows. */
.due-groups { display: flex; flex-direction: column; gap: 18px; }
.due-section { display: flex; flex-direction: column; }
.due-section-hdr { display: flex; align-items: center; gap: 8px; font-family: var(--font-sans);
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--color-text-secondary); margin-bottom: 4px; }
.due-count { display: inline-flex; align-items: center; justify-content: center; min-width: 18px;
  height: 18px; padding: 0 5px; font-size: 10px; font-weight: 600; border-radius: 9px;
  color: var(--color-text-secondary); background: var(--color-background-secondary);
  border: 0.5px solid var(--color-border-tertiary); }
.due-list { display: flex; flex-direction: column; }
.due-row { display: flex; flex-direction: column; gap: 3px; padding: 11px 14px;
  border-bottom: 0.5px solid var(--color-border-tertiary); text-decoration: none; }
.due-row:last-child { border-bottom: none; }
.due-subject { font-size: 14px; font-weight: 500; color: var(--color-text-primary); }
.due-meta { font-size: 11px; color: var(--color-text-tertiary); font-family: var(--font-sans); }
a.due-row:hover { background: var(--color-background-secondary); }
a.due-row:hover .due-subject { color: var(--color-accent-dark); }
.due-partial { font-size: 11px; color: var(--color-text-tertiary); font-family: var(--font-sans);
  margin-bottom: 10px; }
/* Feature D — the ACTIVE affordance on a commitment row: a "Draft a nudge ↗" pre-fill link
   rendered as a sibling under the row's own anchor (an <a> cannot nest in an <a>). Quiet,
   secondary; carries the row group's closing border so band rhythm stays intact. */
.due-draft { display: block; padding: 4px 14px 10px; font-family: var(--font-sans); font-size: 11px;
  font-weight: 500; color: var(--color-accent-dark); text-decoration: none;
  border-bottom: 0.5px solid var(--color-border-tertiary); }
.due-draft:last-child { border-bottom: none; }
.due-draft:hover { text-decoration: underline; }
/* Feature E — the "Record the outcome" resolve form on a prediction_resolution_due row: a
   collapsible <details> (progressive disclosure keeps the list clean) revealing a classification
   <select> + optional outcome text + the Record submit. Mirrors the .due-draft rhythm; reuses the
   .act-btn/.act-primary submit (never restyled here). Rides the semantic tokens (dark theme flips). */
.due-resolve { padding: 2px 14px 10px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.due-resolve:last-child { border-bottom: none; }
.due-resolve > summary { font-family: var(--font-sans); font-size: 11px; font-weight: 500;
  color: var(--color-accent-dark); cursor: pointer; list-style: none; padding: 4px 0; }
.due-resolve > summary::-webkit-details-marker { display: none; }
.due-resolve-form { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 4px; }
.due-resolve-form select, .due-resolve-form input[type="text"] { font-family: var(--font-sans);
  font-size: 12px; padding: 4px 8px; border: 0.5px solid var(--color-border-tertiary);
  border-radius: var(--border-radius-md); background: var(--color-background-primary);
  color: var(--color-text-primary); }
.due-resolve-form input[type="text"] { flex: 1 1 180px; }

/* Feature C — the "Watch" screen: the memory-integrity radar (decision churn + forecast
   reliability) made visible. Same grouped-findings rhythm as /due. */
.watch-groups { display: flex; flex-direction: column; gap: 18px; }
.watch-section { display: flex; flex-direction: column; }
.watch-section-hdr { display: flex; align-items: center; gap: 8px; font-family: var(--font-sans);
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--color-text-secondary); margin-bottom: 4px; }
.watch-count { display: inline-flex; align-items: center; justify-content: center; min-width: 18px;
  height: 18px; padding: 0 5px; font-size: 10px; font-weight: 600; border-radius: 9px;
  color: var(--color-text-secondary); background: var(--color-background-secondary);
  border: 0.5px solid var(--color-border-tertiary); }
.watch-list { display: flex; flex-direction: column; }
.watch-row { display: flex; flex-direction: column; gap: 3px; padding: 11px 14px;
  border-bottom: 0.5px solid var(--color-border-tertiary); text-decoration: none; }
.watch-row:last-child { border-bottom: none; }
.watch-subject { font-size: 14px; font-weight: 500; color: var(--color-text-primary); }
.watch-meta { font-size: 11px; color: var(--color-text-tertiary); font-family: var(--font-sans); }
a.watch-row:hover { background: var(--color-background-secondary); }
a.watch-row:hover .watch-subject { color: var(--color-accent-dark); }
.watch-partial { font-size: 11px; color: var(--color-text-tertiary); font-family: var(--font-sans);
  margin-bottom: 10px; }
/* Feature F — the ACTIVE affordances on a radar row: "Help me settle this ↗" (decision_thrash)
   and "Review your forecasting ↗" (prediction_reliability), each a /chat?q= pre-fill rendered as
   a sibling under the row's own anchor (an <a> cannot nest in an <a>). Mirrors .due-draft: quiet,
   secondary; carries the row group's closing border so band rhythm stays intact. */
.watch-act { display: block; padding: 4px 14px 10px; font-family: var(--font-sans); font-size: 11px;
  font-weight: 500; color: var(--color-accent-dark); text-decoration: none;
  border-bottom: 0.5px solid var(--color-border-tertiary); }
.watch-act:last-child { border-bottom: none; }
.watch-act:hover { text-decoration: underline; }

/* Save-to-Assets (OCCm4, Memry arc) — the SECONDARY affordance on /report + /catchup that files
   the composed body onto Assets as a reusable Memry-drafted draft (POST /…/save-asset). Sits
   beneath the primary file-back inside .brief-actions; reads clearly as secondary to it (outline
   accent vs the solid .act-primary file-back). ADDITIVE ONLY — reuses the .brief-file flex layout
   and the semantic tokens, so the dark theme flips with no per-rule retune. */
.brief-save-asset { margin-top: 10px; }
.act-btn.act-secondary { background: var(--color-background-secondary); color: var(--color-accent-dark);
  border-color: rgba(216, 90, 48, 0.35); }
.act-btn.act-secondary:hover { background: var(--memry-accent-tint); border-color: var(--color-accent);
  color: var(--color-accent); }

/* ===========================================================================
   Wave 3A (OCCm6, Memry arc) — the task-primitive + the BOARD (kanban) view. ADDITIVE
   RULES ONLY, appended last so same-specificity wins. Every colour rides the semantic
   design tokens (--color-*, --border-radius-md, --font-display/mono), so light + dark
   both flip automatically with no per-rule retune. No hard-coded hex.
   =========================================================================== */

/* The List · Board segmented control (shared by the list + board views). Mirrors the
   .filter-chip.active accent-tinted active treatment; a single joined pill group. */
.view-switch { display: inline-flex; gap: 0; margin-bottom: 14px;
  border: 0.5px solid var(--color-border-secondary); border-radius: var(--border-radius-md);
  overflow: hidden; background: var(--color-background-secondary); width: fit-content; }
.view-switch a { padding: 6px 15px; font-size: 12px; font-weight: 500; color: var(--color-text-secondary);
  border-right: 0.5px solid var(--color-border-tertiary); background: transparent; }
.view-switch a:last-child { border-right: none; }
.view-switch a:hover { color: var(--color-text-primary); background: var(--color-background-tertiary); }
.view-switch a.active { background: var(--color-background-primary); color: var(--color-accent-dark);
  font-weight: 600; }

/* The board: a horizontal scroll of status columns. */
.board { display: flex; gap: 14px; align-items: flex-start; overflow-x: auto; padding-bottom: 6px; }
.board-col { flex: 0 0 288px; min-width: 288px; background: var(--color-background-secondary);
  border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg);
  padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.board-col-hd { display: flex; align-items: center; gap: 8px; font-family: var(--font-display);
  font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--color-text-secondary); padding: 2px 2px 8px; border-bottom: 0.5px solid var(--color-border-tertiary); }
.board-col-n { display: inline-flex; align-items: center; justify-content: center; min-width: 18px;
  height: 18px; padding: 0 5px; font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  border-radius: 9px; color: var(--color-text-secondary); background: var(--color-background-tertiary); }
.board-col-closed { opacity: 0.72; }
.board-col-closed .board-col-hd { color: var(--color-text-tertiary); }
.board-col-empty { font-size: 11px; color: var(--color-text-tertiary); font-style: italic; padding: 8px 2px; }
/* FIX C (OCCm9 papercut) — narrower board columns below ~1080px so more columns are visible before
   the .board internal overflow-x scroll (above) kicks in (288px → 240px). */
@media (max-width: 1080px) {
  .board-col { flex-basis: 240px; min-width: 240px; }
}

/* A work-item card. Primary-bg card on the column's secondary surface; subtle lift on hover. */
.board-card { display: flex; flex-direction: column; gap: 8px; padding: 11px 12px;
  background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary);
  border-radius: var(--border-radius-md); box-shadow: var(--shadow-sm);
  color: var(--color-text-primary); transition: border-color 0.12s, box-shadow 0.12s; }
.board-card:hover { border-color: var(--color-accent); box-shadow: var(--shadow-card); }
.board-card-what { font-size: 13px; font-weight: 500; line-height: 1.4; color: var(--color-text-primary); }
.board-card-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 11px; color: var(--color-text-tertiary); }
.bc-assignee { display: inline-flex; align-items: center; gap: 5px; color: var(--color-text-secondary); }
.bc-av { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
  border-radius: 50%; font-size: 9px; font-weight: 600; font-family: var(--font-display);
  color: #fff; background: var(--color-accent); flex-shrink: 0; }
.bc-due { color: var(--color-text-tertiary); }
.board-card-badges { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.board-card-open { display: flex; flex-direction: column; gap: 8px; text-decoration: none; color: inherit; }
.board-card-actions { display: flex; gap: 6px; margin-top: 2px; padding-top: 8px; border-top: 1px solid var(--color-border-tertiary); }
.bc-act { margin: 0; display: inline-flex; }
.bc-act-btn { font-family: inherit; font-size: 11px; font-weight: 600; padding: 3px 10px; border-radius: 5px;
  border: 1px solid var(--color-border-tertiary); background: var(--color-background-secondary); color: var(--color-text-secondary); cursor: pointer; }
.bc-act-btn:hover { border-color: var(--color-accent); color: var(--color-text-primary); }
.bc-act-done { color: var(--color-accent); }
.bc-badge { display: inline-flex; align-items: center; font-size: 9px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em; padding: 2px 7px; border-radius: 3px; }
.bc-atrisk { background: var(--color-background-secondary); color: var(--color-warn);
  border: 0.5px solid rgba(133, 79, 11, 0.35); }
.bc-blocked { background: var(--color-background-secondary); color: var(--color-danger);
  border: 0.5px solid rgba(163, 45, 45, 0.35); }
.bc-disputed { background: var(--color-background-secondary); color: var(--color-accent-dark);
  border: 0.5px solid rgba(216, 90, 48, 0.35); }
/* Beat B (OCCm22) — the APPROVED-flag mini-chip: a human-signed-off risk signal (a DELIBERATE
   flag, not a passive date cue), so it wears the danger tint (the .bc-blocked family). */
.bc-flag { background: var(--color-background-secondary); color: var(--color-danger);
  border: 0.5px solid rgba(163, 45, 45, 0.35); }
.bc-sub { display: inline-flex; align-items: center; font-size: 10px; font-weight: 600;
  font-family: var(--font-mono); padding: 1px 6px; border-radius: 3px;
  color: var(--color-text-secondary); background: var(--color-background-tertiary); }

/* Priority pills (escalate: low → neutral, urgent → danger/accent). Used on the board card
   meta row + the commitment detail card. Class keys on the raw engine enum (pri-low … pri-urgent). */
.pri { display: inline-flex; align-items: center; font-size: 9px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em; padding: 2px 7px; border-radius: 3px; }
.pri-low { background: var(--color-background-tertiary); color: var(--color-text-tertiary); }
.pri-medium { background: var(--color-background-info); color: #185FA5; }
.pri-high { background: var(--color-background-secondary); color: var(--color-warn);
  border: 0.5px solid rgba(133, 79, 11, 0.35); }
.pri-urgent { background: var(--memry-accent-tint); color: var(--color-danger);
  border: 0.5px solid rgba(163, 45, 45, 0.40); }
:root[data-theme="dark"] .pri-medium { background: #16344F; color: #9CC7F0; }

/* The in_progress commitment status pill (extends the .cs chip family — info-tinted blue,
   matching the .cs-renegotiated treatment). */
.cs-in_progress { background: #E6F1FB; color: #185FA5; }
:root[data-theme="dark"] .cs-in_progress { background: #16344F; color: #8FC0EE; }

/* Commitment detail card (Wave 3A additive fields): priority row, read-only subtask checklist,
   and the resolved "Blocked by" dependency line. Reuse the .fact-field rhythm + theme tokens. */
.cmt-priority { display: flex; }
/* Beat B (OCCm22) — APPROVED-flag chips on the task detail card (Step 5 surfacing). A stacked list of
   flag rows; each row is a wrapping flex line — the kind tag + the system-derived line + the [RULE]
   badge + the optional note + the Clear control. Reuses .action-tag/.rule-tag/.muted/.bc-act-btn; only
   the row layout + the danger-tinted kind glyph are new (a human-signed-off flag is a deliberate signal). */
.cmt-flags { display: flex; flex-direction: column; gap: 7px; }
.cmt-flag { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; font-size: 12.5px; line-height: 1.45; }
.cmt-flag-kind { color: var(--color-danger); }
.cmt-flag-line { color: var(--color-text-primary); flex: 1 1 auto; min-width: 0; }
.cmt-flag-note { font-size: 11px; }
.cmt-flag-clear { margin: 0; display: inline-flex; }
/* 3C-a (OCCm7): the structured-money pill on the task surfaces (board card, list sub-row,
   detail "Amount" field). Mono, quiet secondary tint — a fact, not an alarm. */
.cmt-money { display: inline-flex; align-items: center; font-family: var(--font-mono); font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: 5px; background: var(--color-background-secondary); color: var(--color-text-secondary); }
.cmt-money-row { display: flex; }
/* 3C-b (OCCm7): the Tasks-header money rollup ("£X owed · £Y overdue"). The owed total reads as
   a quiet fact; the overdue subset carries the same danger hue as .overdue (var(--color-danger),
   a real token with a dark-theme override) so it flips cleanly in dark. */
.cmt-owed { font-weight: 600; color: var(--color-text-secondary); }
.cmt-owed-overdue { color: var(--color-danger); }
.cmt-subtasks { display: flex; flex-direction: column; gap: 2px; }
.cmt-subtask { display: flex; align-items: baseline; gap: 7px; font-size: 12.5px; line-height: 1.5;
  color: var(--color-text-primary); padding: 3px 0;
  background: none; border: none; padding: 0; color: inherit; cursor: pointer; width: 100%; text-align: left; }
.cmt-subtask-box { color: var(--color-text-tertiary); font-size: 13px; }
.cmt-subtask-done .cmt-subtask-box { color: var(--color-ok); }
.cmt-subtask-done .cmt-subtask-what { color: var(--color-text-tertiary); text-decoration: line-through; }
.cmt-subtask-form { margin: 0; }
.cmt-subtask:hover .cmt-subtask-what { color: var(--color-text-primary); }
.cmt-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cmt-act { margin: 0; display: inline-flex; }
.cmt-reschedule { margin: 0; display: inline-flex; align-items: center; gap: 6px; }
.cmt-reschedule-date { width: auto; padding: 3px 8px; font-size: 12px; }
.cmt-deps { display: flex; flex-direction: column; gap: 4px; }
.cmt-deps-lead { font-size: 11px; color: var(--color-text-tertiary); margin-bottom: 2px; }
.cmt-dep { display: flex; align-items: baseline; gap: 7px; font-size: 12.5px; line-height: 1.45;
  color: var(--color-text-primary); }
.cmt-dep-mark { font-size: 12px; }
.cmt-dep-met { color: var(--color-ok); }
.cmt-dep-unmet { color: var(--color-danger); }
/* Beat 1a (OCCm11) — dependency edges: the off-record "?" mark, the head-row link, and the no-JS
   add/remove forms. Terse, riding the same theme tokens as the .cmt-dep rows above. */
.cmt-dep-unres { color: var(--color-text-tertiary); }
.cmt-dep-link { color: inherit; }
.cmt-dep-link:hover { text-decoration: underline; }
.cmt-dep-remove { display: inline; margin-left: 6px; }
.cmt-dep-x { background: none; border: none; cursor: pointer; color: var(--color-text-tertiary); font-size: 11px; padding: 0 2px; }
.cmt-dep-x:hover { color: var(--color-danger); }
.cmt-dep-add { display: flex; gap: 6px; margin-top: 6px; align-items: center; }
.cmt-dep-select { max-width: 260px; }
/* Beat 1b (OCCm11) — blocked-chain visuals: the "Unblocks" reverse rows, the board ⛓ badge, and
   the visible board-card blocker line. */
.cmt-dep-unblocks { color: var(--color-accent); }
.board-card-chain { font-size: 11px; color: var(--color-text-tertiary); margin-top: 4px; }
.bc-unblocks { background: var(--color-background-secondary); color: var(--color-text-secondary); }
/* Beat 1c (OCCm11) — the "↻ weekly" recurrence chip on the list sub-row + the detail "Repeats"
   field body. Quiet tertiary tint (a fact, not an alarm); the detail field reuses the .fact-field
   rhythm above so no extra structure is needed. */
.cmt-recur { font-size: 11px; color: var(--color-text-tertiary); white-space: nowrap; }
/* Beat 3 (OCCm18, Memry arc) — the forward lineage link to a completed recurring task's spawned
   successor, rendered inside the "Repeats" field. Theme-aware accent (light + dark flip via token). */
.cmt-recur-next { font-size: 11px; margin-top: 3px; }
.cmt-recur-next a { color: var(--color-accent); text-decoration: none; white-space: nowrap; }
.cmt-recur-next a:hover { text-decoration: underline; }

/* Wave 3B B3 (OCCm8, Memry arc) — the Discussion thread on the task detail card: comments +
   @mention→People chips + the no-JS comment form. All colours ride semantic tokens so light +
   dark flip automatically. */
.cmt-c-thread { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.cmt-c { display: flex; flex-direction: column; gap: 3px; padding: 8px 10px; border-radius: var(--border-radius-md);
  background: var(--color-background-secondary); border: 1px solid var(--color-border-tertiary); }
.cmt-c-hd { display: flex; align-items: baseline; gap: 8px; }
.cmt-c-who { font-size: 12px; font-weight: 600; color: var(--color-text-primary); }
.cmt-c-when { font-size: 10.5px; color: var(--color-text-tertiary); }
.cmt-c-body { font-size: 12.5px; line-height: 1.5; color: var(--color-text-primary); white-space: pre-wrap; word-break: break-word; }
.cmt-c-mentions { font-size: 11px; color: var(--color-text-tertiary); margin-top: 2px; display: flex; flex-wrap: wrap; gap: 5px; align-items: baseline; }
.cmt-c-form { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.cmt-c-textarea { width: 100%; box-sizing: border-box; min-height: 46px; resize: vertical; font-family: inherit; font-size: 12.5px; line-height: 1.45; padding: 7px 9px; }
.cmt-c-formrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cmt-c-mention { width: auto; max-width: 260px; }

/* Wave 3D (OCCm8) — the owner track-record cue on the task detail (moat-on-parity). Quiet, a
   fact not an alarm; the risk value picks up the danger hue only when it reads HIGH. */
.cmt-owner-signals { display: flex; flex-direction: column; gap: 3px; }
.cmt-owner-signal { display: flex; gap: 8px; align-items: baseline; font-size: 12px; line-height: 1.45; }
.cmt-owner-sig-k { color: var(--color-text-tertiary); min-width: 118px; flex: 0 0 auto; }
.cmt-owner-sig-v { color: var(--color-text-primary); }
.cmt-owner-sig-v.is-risk { color: var(--color-danger); font-weight: 600; }
/* Wave 3D (OCCm9) — the "likely to slip" detail row: amber (a caution, not the red risk hue). */
.cmt-owner-sig-v.is-warn { color: var(--color-warn); font-weight: 600; }

/* Wave 3D (OCCm8) — the compact owner flag on task cards/rows (present-only, negative signal). */
.owner-flag { display: inline-flex; align-items: center; gap: 3px; font-size: 10.5px; font-weight: 600; padding: 1px 6px; border-radius: 5px; background: var(--color-background-secondary); color: var(--color-danger); white-space: nowrap; }
/* Wave 3D (OCCm9) — the "likely to slip" cue on task cards/rows (present-only). Amber (a caution,
   not the red owner-flag alarm); the text is a fixed literal sourced from the owner's OWN recorded
   optimism_bias (a receipt), never an inference. Same shape as .owner-flag; --color-warn matches .soon. */
.owner-slip { display: inline-flex; align-items: center; gap: 3px; font-size: 10.5px; font-weight: 600; padding: 1px 6px; border-radius: 5px; background: var(--color-background-secondary); color: var(--color-warn); white-space: nowrap; }

/* ===========================================================================
   Wave 3A (OCCm6, Memry arc) — the CALENDAR + TIMELINE Task views. ADDITIVE RULES
   ONLY, appended last so same-specificity wins. Every colour rides the semantic
   design tokens (--color-*, --border-radius-md, --font-display/mono) so light + dark
   both flip automatically. The one info-blue text tint (#185FA5) mirrors the shipped
   .pri-medium / .cs-in_progress precedent above (no semantic token exists for it) and
   carries a matching :root[data-theme="dark"] override; no other hard-coded hex.
   =========================================================================== */

/* --- Calendar (Monday-start month grid) --- */
.cal-nav { display: flex; align-items: center; justify-content: center; gap: 14px; margin-bottom: 12px; }
.cal-nav-label { font-family: var(--font-display); font-size: 14px; font-weight: 600;
  color: var(--color-text-primary); min-width: 150px; text-align: center; }
.cal-nav-link { font-family: var(--font-mono); font-size: 12px; font-weight: 500; padding: 5px 11px;
  color: var(--color-text-secondary); background: var(--color-background-secondary);
  border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); }
.cal-nav-link:hover { color: var(--color-accent-dark); border-color: var(--color-accent); }

.cal-weekhdr { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; margin-bottom: 6px; }
.cal-weekhdr-c { font-family: var(--font-sans); font-size: 10px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--color-text-tertiary); text-align: center; padding: 2px 0; }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal-cell { min-height: 96px; display: flex; flex-direction: column; gap: 3px; padding: 6px;
  background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary);
  border-radius: var(--border-radius-md); overflow: hidden; }
.cal-cell-out { background: var(--color-background-secondary); }
.cal-cell-out .cal-daynum { color: var(--color-text-tertiary); }
.cal-cell-today { border-color: var(--color-accent); box-shadow: inset 0 0 0 1px var(--color-accent); }
.cal-daynum { align-self: flex-end; font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  color: var(--color-text-secondary); line-height: 1; }
.cal-cell-today .cal-daynum { color: var(--color-accent-dark); }

.cal-task { display: flex; align-items: center; gap: 5px; padding: 2px 5px; border-radius: 4px;
  background: var(--color-background-secondary); border: 0.5px solid var(--color-border-tertiary);
  font-size: 10.5px; line-height: 1.3; color: var(--color-text-primary); overflow: hidden; }
.cal-task:hover { border-color: var(--color-accent); }
.cal-task-t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-task-atrisk { border-color: rgba(133, 79, 11, 0.45); }
.cal-task-blocked { border-color: rgba(163, 45, 45, 0.45); }
.cal-dot { flex-shrink: 0; width: 6px; height: 6px; border-radius: 50%; background: var(--color-text-tertiary); }
.cal-dot-open, .cal-dot-low { background: var(--color-text-tertiary); }
.cal-dot-met, .cal-dot-done { background: var(--color-ok); }
.cal-dot-failed, .cal-dot-urgent { background: var(--color-danger); }
.cal-dot-high { background: var(--color-warn); }
.cal-dot-in_progress, .cal-dot-medium { background: #185FA5; }
:root[data-theme="dark"] .cal-dot-in_progress, :root[data-theme="dark"] .cal-dot-medium { background: #6FA8DC; }
.cal-more { font-size: 10px; font-weight: 500; color: var(--color-text-tertiary); padding: 1px 4px; }
.cal-foot { margin-top: 12px; font-family: var(--font-sans); font-size: 11px; color: var(--color-text-secondary); }

/* Meetings v1 — the calendar MEETING chip: the .cal-task shape but visually DISTINCT via a tertiary
   surface + a left accent border + a mono UTC time. Existing semantic tokens ONLY, so light + dark flip
   automatically (no raw hex on any theme-flipping surface). */
.cal-meeting { display: flex; align-items: center; gap: 5px; padding: 2px 5px; border-radius: 4px;
  background: var(--color-background-tertiary); border: 0.5px solid var(--color-border-tertiary);
  border-left: 2px solid var(--color-accent); font-size: 10.5px; line-height: 1.3;
  color: var(--color-text-primary); overflow: hidden; }
.cal-meeting:hover { border-color: var(--color-accent); }
.cal-meeting-time { flex-shrink: 0; font-family: var(--font-mono); font-size: 9.5px; font-weight: 600; color: var(--color-text-secondary); }
.cal-meeting-t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-meeting-held { opacity: 0.62; }
.cal-add-meeting { color: var(--color-accent-dark); }

/* Milestones lane — the calendar MILESTONE chip: the .cal-meeting box shape (tertiary surface) but
   NO left accent border (that is the meeting signature) — the ◆ diamond glyph (.cal-ms-flag) is the
   milestone signature instead. Existing semantic tokens ONLY, so light + dark flip automatically. */
.cal-ms { display: flex; align-items: center; gap: 5px; padding: 2px 5px; border-radius: 4px;
  background: var(--color-background-tertiary); border: 0.5px solid var(--color-border-tertiary);
  font-size: 10.5px; line-height: 1.3; color: var(--color-text-primary); overflow: hidden; }
.cal-ms:hover { border-color: var(--color-accent); }
.cal-ms-flag { flex-shrink: 0; font-size: 9.5px; color: var(--color-accent-dark); }
.cal-ms-t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-ms-past { opacity: 0.62; }
.cal-ms-prov { border-style: dashed; }

/* Meetings v1 — the meeting detail DRAWER (above the grid on ?focus=). Reuses the .panel shell. */
.mtg-drawer { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.mtg-drawer-head { display: flex; align-items: center; gap: 10px; }
.mtg-drawer-title { font-family: var(--font-display); font-size: 15px; font-weight: 600; color: var(--color-text-primary); }
.mtg-drawer-close { margin-left: auto; }
.mtg-drawer-row { display: flex; align-items: baseline; gap: 8px; font-size: 12px; color: var(--color-text-primary); }
.mtg-drawer-k { flex: 0 0 82px; font-size: 10.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--color-text-tertiary); }
.mtg-att-list { display: flex; flex-wrap: wrap; gap: 4px; }
.mtg-att { font-size: 11px; padding: 1px 6px; border-radius: 5px;
  background: var(--color-background-secondary); color: var(--color-text-secondary); }
.mtg-badge { display: inline-flex; align-items: center; font-size: 10.5px; font-weight: 600; padding: 1px 7px; border-radius: 5px; }
.mtg-badge-recur { background: var(--color-background-secondary); color: var(--color-text-secondary); }
.mtg-badge-held { background: var(--color-background-secondary); color: var(--color-ok); }
.mtg-badge-resched { background: var(--color-background-secondary); color: var(--color-warn); }
.mtg-drawer-actions { display: flex; gap: 8px; }
.mtg-edit { margin-top: 6px; border-top: 0.5px solid var(--color-border-tertiary); padding-top: 10px; }

/* --- Timeline (by-due-date roadmap): a month axis + one point-marker lane per project. --- */
.tl-axis { position: relative; height: 22px; margin: 0 0 8px var(--tl-label-w, 128px);
  border-bottom: 0.5px solid var(--color-border-secondary); }
.tl-month { position: absolute; bottom: 4px; transform: translateX(-50%); font-family: var(--font-sans);
  font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--color-text-tertiary); white-space: nowrap; }
.tl-today { position: absolute; top: 0; bottom: 0; width: 0; transform: translateX(-50%);
  border-left: 1.5px solid var(--color-accent); }
.tl-today-lbl { position: absolute; top: -2px; left: 3px; font-family: var(--font-sans); font-size: 9px;
  font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--color-accent);
  white-space: nowrap; }

/* FIX A (OCCm9) — --tl-lane-base / --tl-row-h size a lane by its stacked-row count (set inline
   per lane as --tl-lane-rows by render/timeline.js); the marker row offsets step by --tl-row-h. */
.tl-body { display: flex; flex-direction: column; gap: 8px; --tl-lane-base: 46px; --tl-row-h: 42px; }
.tl-lane-row { display: flex; align-items: stretch; }
.tl-lane-label { flex: 0 0 var(--tl-label-w, 128px); display: flex; align-items: center;
  padding: 8px 10px 8px 0; font-family: var(--font-display); font-size: 12px; font-weight: 600;
  color: var(--color-text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-lane { position: relative; flex: 1 1 auto; min-width: 0;
  /* FIX A (OCCm9) — grow the lane with its stacked-row count so de-occluded markers never clip. */
  min-height: calc(var(--tl-lane-base, 46px) + (var(--tl-lane-rows, 1) - 1) * var(--tl-row-h, 42px));
  background: var(--color-background-secondary); border: 0.5px solid var(--color-border-tertiary);
  border-radius: var(--border-radius-md); }
.tl-todayline { position: absolute; top: 0; bottom: 0; width: 0; transform: translateX(-50%);
  border-left: 1px dashed rgba(216, 90, 48, 0.5); }
.tl-marker { position: absolute; top: 8px; transform: translateX(-50%); max-width: 46%;
  display: inline-flex; flex-direction: column; gap: 1px; padding: 4px 8px; border-radius: var(--border-radius-md);
  background: var(--color-background-primary); border: 0.5px solid var(--color-border-secondary);
  border-left: 3px solid var(--color-border-primary); box-shadow: var(--shadow-card);
  color: var(--color-text-primary); }
.tl-marker:hover { border-color: var(--color-accent); z-index: 3; }
.tl-marker-t { font-size: 11px; font-weight: 500; line-height: 1.25; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.tl-marker-due { font-family: var(--font-mono); font-size: 9px; color: var(--color-text-tertiary); }
.tl-done { border-left-color: var(--color-ok); }
.tl-failed { border-left-color: var(--color-danger); }
.tl-neutral { border-left-color: var(--color-border-primary); }
.tl-atrisk { border-left-color: var(--color-warn); }
.tl-blocked { border-left-color: var(--color-danger); }
/* FIX A (OCCm9) — stacked-row vertical offsets (row 0 = the base .tl-marker top:8px, no rule). Each
   row steps down one --tl-row-h so clustered due-date pills sit on their own line, not occluding. */
.tl-marker.tl-r1 { top: calc(8px + var(--tl-row-h, 42px)); }
.tl-marker.tl-r2 { top: calc(8px + 2 * var(--tl-row-h, 42px)); }
/* Thesis-parity #3 (OCCm10 screenshot fix) — a lane carrying milestone flags reserves a ~28px top
   gutter: the lane grows by 24px and every task pill (all three stack rows) shifts down by 24px so
   the ◆+name flag head (≈28px tall incl. its 3px padding) is never occluded by a pill. Three-class
   selectors outrank the two-class row rules above. */
.tl-lane.tl-lane-ms { min-height: calc(var(--tl-lane-base, 46px) + 24px + (var(--tl-lane-rows, 1) - 1) * var(--tl-row-h, 42px)); }
.tl-lane-ms .tl-marker { top: 32px; }
.tl-lane-ms .tl-marker.tl-r1 { top: calc(32px + var(--tl-row-h, 42px)); }
.tl-lane-ms .tl-marker.tl-r2 { top: calc(32px + 2 * var(--tl-row-h, 42px)); }
/* FIX A (OCCm9) — edge clamp: a rim marker overrides the base translateX(-50%) so it sits INSIDE
   the lane (a near-0% pill grows rightward; a near-100% pill grows leftward) — no half-clip → no
   page-level horizontal scroll. Two-class selectors outrank .tl-marker; :hover sets no transform,
   so these hold on hover too. */
.tl-marker.tl-edge-l { transform: translateX(0); }
.tl-marker.tl-edge-r { transform: translateX(-100%); }
.tl-foot { margin-top: 12px; font-family: var(--font-sans); font-size: 11px; color: var(--color-text-secondary); }

/* ===========================================================================
   Thesis-parity #3 (OCCm10) — Timeline MILESTONE flags + the "Add milestone"
   affordance + the Projects-page portfolio ROLLUP strip. ADDITIVE, appended last;
   every colour rides the semantic tokens so light + dark flip automatically.
   =========================================================================== */

/* --- Milestone flags on the Timeline: a narrow vertical dashed guide + a ◆ flag and clipped name
   at the top of the lane. Positioned by an inline left:% (translateX(-50%) centres it on the date).
   Sits BELOW the task pills (rendered before them in the lane; auto z-index → later pills paint on
   top); hovering the flag raises it above the pills so its label reads. --- */
.tl-ms { position: absolute; top: 0; bottom: 0; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 2px; padding-top: 3px;
  border-left: 1px dashed var(--color-accent); text-decoration: none; white-space: nowrap; }
.tl-ms:hover { z-index: 4; }
.tl-ms-flag { font-size: 10px; line-height: 1; color: var(--color-accent); }
.tl-ms-name { font-size: 9px; font-weight: 600; color: var(--color-text-secondary);
  background: var(--color-background-primary); padding: 0 3px; border-radius: 3px;
  max-width: 92px; overflow: hidden; text-overflow: ellipsis; }
.tl-ms:hover .tl-ms-name { color: var(--color-accent-dark); }
/* Past milestone — muted (a landmark already crossed). */
.tl-ms-past { border-left-color: var(--color-border-secondary); }
.tl-ms-past .tl-ms-flag { color: var(--color-text-tertiary); }
.tl-ms-past .tl-ms-name { color: var(--color-text-tertiary); }
/* Proposed (Provisional) milestone — dashed/hollow: a dotted guide + a dotted-underlined,
   lighter-weight name, visually distinct from a signed-off milestone. */
.tl-ms-prov { border-left-style: dotted; }
.tl-ms-prov .tl-ms-flag { color: var(--color-accent); opacity: 0.7; }
.tl-ms-prov .tl-ms-name { font-weight: 500; text-decoration: underline dotted; }

/* --- Meeting markers on the Timeline (meetings v1): an open-circle marker beside the milestone
   flags, positioned by an inline left:% (translateX(-50%) centres it on the meeting time). Sits in
   the SAME reserved top gutter as the flags and BELOW the task pills; hovering raises it so its
   clipped title reads. There is DELIBERATELY no provisional modifier — Provisional is a meeting's
   resting state, so a dashed class would mark every meeting and carry zero signal. A held / past
   meeting is muted to the tertiary token. --- */
.tl-meet { position: absolute; top: 0; bottom: 0; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 2px; padding-top: 3px;
  text-decoration: none; white-space: nowrap; }
.tl-meet:hover { z-index: 4; }
.tl-meet-flag { font-size: 10px; line-height: 1; color: var(--color-accent); }
.tl-meet-name { font-size: 9px; font-weight: 600; color: var(--color-text-secondary);
  background: var(--color-background-primary); padding: 0 3px; border-radius: 3px;
  max-width: 92px; overflow: hidden; text-overflow: ellipsis; }
.tl-meet:hover .tl-meet-name { color: var(--color-accent-dark); }
/* Held / past meeting — muted (flag + name to the tertiary token). */
.tl-meet-held .tl-meet-flag, .tl-meet-past .tl-meet-flag { color: var(--color-text-tertiary); }
.tl-meet-held .tl-meet-name, .tl-meet-past .tl-meet-name { color: var(--color-text-tertiary); }

/* --- "Add milestone" affordance in the timeline topbar: a no-JS <details> whose summary is the
   act-btn and whose body is a small POST-form dropdown (consistent with the .pc-connect summary-
   button idiom on Projects). Absolutely positioned so opening it never reflows the topbar. --- */
.tl-addms { position: relative; align-self: flex-start; }
.tl-addms > summary { list-style: none; cursor: pointer; white-space: nowrap; }
.tl-addms > summary::-webkit-details-marker { display: none; }
.tl-addms-form { position: absolute; right: 0; top: calc(100% + 6px); z-index: 20;
  display: flex; flex-direction: column; gap: 8px; width: 280px; padding: 14px;
  background: var(--color-background-primary); border: 0.5px solid var(--color-border-secondary);
  border-radius: var(--border-radius-md); box-shadow: var(--shadow-card-hover); }
.tl-addms-form .grant-input { width: 100%; }
.tl-addms-note { font-size: 11px; color: var(--color-text-tertiary); line-height: 1.45; }

/* --- Portfolio rollup strip (Projects page): a horizontal band of measured tiles, wrapping on
   narrow widths. Tone matches the .proj-card-stats / .pc-stat idiom (measured count + muted label).
   Overdue / open-conflicts turn danger only when > 0; the "Next milestone" tile is a wider link. --- */
.rollup-strip { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; }
.ru-tile { display: flex; flex-direction: column; gap: 3px; padding: 10px 14px; min-width: 96px;
  background: var(--color-background-primary); border: 0.5px solid var(--color-border-tertiary);
  border-radius: var(--border-radius-md); box-shadow: var(--shadow-card); }
.ru-num { font-family: var(--font-display); font-size: 20px; font-weight: 600; line-height: 1;
  letter-spacing: -0.01em; color: var(--color-text-primary); }
a.ru-num { text-decoration: none; }
.ru-lbl { font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-tertiary); }
.ru-alert .ru-num { color: var(--color-danger); }
.ru-muted .ru-num { color: var(--color-text-tertiary); }
.ru-next { flex: 1 1 260px; justify-content: center; text-decoration: none;
  font-size: 12.5px; font-weight: 500; color: var(--color-text-primary); }
.ru-next:hover { border-color: var(--color-accent); color: var(--color-accent-dark); }

/* Beat 1 (OCCm16, Memry arc) — manage-my-templates rows on /projects/new. A flex row: name/meta on the
   left, the inline rename form + the delete form on the right, wrapping gracefully on narrow widths. */
.tpl-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 10px 0; border-bottom: 0.5px solid var(--color-border-tertiary); }
.tpl-row:last-of-type { border-bottom: 0; }
.tpl-row-meta { display: flex; flex-direction: column; gap: 2px; min-width: 160px; flex: 1 1 200px; }
.tpl-row-sub { font-size: 11px; color: var(--color-text-secondary); }
.tpl-row-form { display: flex; align-items: center; gap: 6px; }
.tpl-row-form .grant-input { max-width: 200px; }

/* Automation rules v1 (thesis table-stake 10, Memry arc) — the DISTINCT "RULE" badge on a rule-filed
   Home sign-off card (so a standing-order proposal is never blended with a hand-added one) + the
   non-blocking rule-activity FYI block. All colours ride semantic tokens / the brand accent, so light
   + dark flip automatically (the .chg-new precedent: white on the accent reads in both). Nothing global. */
.rule-tag { display: inline-flex; align-items: center; font-size: 9px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; padding: 1px 6px; border-radius: 3px;
  color: #fff; background: var(--color-accent); }
.rule-fyi { margin-top: 10px; padding-top: 10px; border-top: 0.5px solid var(--color-border-tertiary);
  font-size: 11px; line-height: 1.5; color: var(--color-text-tertiary); }
.rule-fyi > div { margin-top: 2px; }

/* Recurring-spawn disclosure (OCCm21, Memry arc) — the DISTINCT "RECURRING" badge on a Home sign-off
   card whose Provisional was AUTO-SPAWNED as the next instance of a recurring task. Same mechanism class
   as the .rule-tag badge (a record MEMRY proposed on its own) → the SAME pill SHAPE, but a DIFFERENT —
   muted, bordered/transparent — treatment so the two mechanisms are never confused: RULE is a filled
   accent pill; RECURRING is a quiet bordered pill in secondary text. Rides semantic tokens
   (--color-text-secondary / --color-border-secondary), so it reads in BOTH themes (the .auth-inferred /
   .pri-low precedent). Nothing global. */
.recurring-tag { display: inline-flex; align-items: center; font-size: 9px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; padding: 1px 6px; border-radius: 3px;
  color: var(--color-text-secondary); background: transparent;
  border: 0.5px solid var(--color-border-secondary); }

/* 3E INTAKE (OCCm26, Memry arc) -- the muted intake-origin pills on a Home sign-off card whose
   Provisional record was IMPORTED on your behalf: "CALENDAR" (a meeting harvested from an
   external calendar) and, slice 3, "MAIL" (a task proposed from Gmail). One mechanism class ->
   ONE rule. Same mechanism class as the .rule-tag / .recurring-tag badges (a record MEMRY brought
   onto the board on your behalf) -> the SAME pill SHAPE, in a QUIET, neutral treatment (a filled
   tertiary chip in secondary text -- distinct from the accent-filled RULE and the bordered-
   transparent RECURRING). Rides the existing semantic tokens (--color-background-tertiary /
   --color-text-secondary), so it reads in BOTH themes with no per-rule retune. Nothing global;
   no new CSS vars. */
.calendar-tag, .mail-tag { display: inline-flex; align-items: center; font-size: 9px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; padding: 1px 6px; border-radius: 3px;
  color: var(--color-text-secondary); background: var(--color-background-tertiary); }

/* Company-department (CD slice) — the quiet "Dept" badge marking a DEPARTMENT (an org unit that nests
   projects) on the scope tree, the corporation-view section header, and the all-projects table name
   cell. Mirrors the .calendar-tag intake-origin pill EXACTLY (a quiet, neutral chip in secondary text
   on the tertiary surface) — same box model + existing semantic tokens, so it reads in BOTH themes with
   no new CSS vars. Nothing global. */
.badge-dept { display: inline-flex; align-items: center; font-size: 9px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; padding: 1px 6px; border-radius: 3px;
  color: var(--color-text-secondary); background: var(--color-background-tertiary); }
/* The corporation-view department section: a header row (dept name link + Dept badge + a compact subtree
   stat line), a muted nested-count caption, spaced above its cards grid. Rides existing tokens only. */
.dept-section { margin-bottom: 6px; }
.dept-section-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: 18px 0 4px; }
.dept-title { font-family: var(--font-display); font-size: 15px; font-weight: 600;
  color: var(--color-text-primary); text-decoration: none; }
.dept-title:hover { color: var(--color-accent-dark); }
.dept-stat { font-size: 12px; color: var(--color-text-secondary); }
.dept-caption { font-size: 11px; color: var(--color-text-tertiary); margin: 0 0 10px; }

/* Memry W4 Slice C -- logged-out onboarding (login/signup) chrome. Centered card on the
   paper canvas; reuses .panel + .grant-input + theme tokens so it themes in light+dark. */
.auth-shell { min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px; background: var(--memry-paper); }
.auth-card { width: 100%; max-width: 380px; box-shadow: var(--shadow-card); }
.auth-body { padding: 20px; }
.auth-form { display: flex; flex-direction: column; gap: 6px; }
.auth-form .field-label { margin-top: 8px; }
.auth-form .grant-input { width: 100%; box-sizing: border-box; }
.auth-submit { width: 100%; margin-top: 16px; justify-content: center; }
.auth-alt { margin: 16px 0 0; font-size: 13px; color: var(--color-text-secondary); text-align: center; }
.auth-alt a { color: var(--color-accent); }
.auth-body .flash { margin-bottom: 12px; }

/* ===========================================================================
   Records hub — the five-door tile grid (render/records.js). ADDITIVE RULES ONLY,
   appended last so same-specificity wins. The box model is the shipped
   .proj-cards-grid / .proj-card summary-card idiom (auto-fill track, 0.5px hairline
   border, --border-radius-lg, column flex). Every colour, radius and spacing value is
   one this file already uses, so light + dark both flip through the semantic tokens
   with no per-rule retune and no new design token is introduced.
   =========================================================================== */

/* The grid. Same auto-fill idiom and the same 14px gap as .proj-cards-grid, at the
   narrower shipped track width — these are five short doors, not per-project cards.
   The grid carries the inset padding because it is the .panel's own child and .panel
   supplies none (the .empty / .np-form convention). */
.rec-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px; padding: 16px; }

/* One door. The enclosing .panel is the PRIMARY surface, so the tile takes the
   SECONDARY (inset) surface — the .vital / .cmt-party idiom — and the two planes read
   as distinct in both themes (paper-tint on white; raised slate on the dark card). The
   tile is an <a>, so colour and underline are pinned here rather than left to the base
   `a` rule, matching the .oc-row / .board-card-open card-link idiom. */
.rec-tile { display: flex; flex-direction: column; gap: 8px; padding: 16px 18px;
  background: var(--color-background-secondary);
  border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-lg);
  color: inherit; text-decoration: none; }

/* The head row: icon · label · count, vertically centred on one line. .node-icon carries
   its own right margin, so it is zeroed inside the row and `gap` stays the single source
   of the icon-to-label distance. */
.rec-tile-hd { display: flex; align-items: center; gap: 8px; }
.rec-tile-hd .node-icon { margin-right: 0; }

/* The door's name — product nouns, so the body sans at .proj-card-title's weight, never
   the mono identifier face. */
.rec-tile-label { font-size: 15px; font-weight: 500; color: var(--color-text-primary); }

/* The count is subordinate to the label and sits at the trailing edge. The trailing push
   lives on the count itself, so a head row with no count is icon + label and lays out
   unchanged. `padding-left` guarantees clearance from the label glyphs even at the
   narrowest track, where the auto margin collapses to nothing. */
.rec-tile-count { margin-left: auto; padding-left: 8px; flex-shrink: 0;
  font-family: var(--font-mono); font-size: 11px; color: var(--color-text-tertiary); }

/* The blurb blockifies as a flex item of the tile's column, the same way .proj-card-path
   does inside .proj-card-head; it wraps freely and holds the secondary text tone. */
.rec-tile-blurb { font-size: 12px; line-height: 1.5; color: var(--color-text-secondary); }

/* Hover takes the label to the accent, matching .proj-card-title:hover. The whole tile is
   the hover target, so the rule reaches the label through it — the a.due-row / a.watch-row
   idiom, needed because the label sets a colour of its own. */
.rec-tile:hover .rec-tile-label { color: var(--color-accent-dark); }

/* ===========================================================================
   W14 (2026-08-27) — the stylesheet half of three affordances that shipped with
   correct class hooks and NO rules: the top-bar unseen-mention bell and the
   account menu (68ea56d4e / 8078d5fd0, render/layout.js) and the queue row's
   inline verbs (fd9814592, render/home.js). Those lanes did not hold this file,
   so each carried its values as a CSP-sanctioned inline style="" stopgap and
   named the rules this pass should absorb them into. Nothing here is invented:
   the chrome chips take .theme-toggle's, the queue rule mirrors .triage-draft's.
   ADDITIVE — every selector below names a class only those three features emit,
   so no other screen moves.
   =========================================================================== */

/* The two chrome icon-chips. They stand in the same row as .theme-toggle and
   take ITS shape and ITS colours — the same --chrome-* tokens, height, radius,
   hover and transition — rather than any value of their own. Three deltas, each
   forced by the markup rather than chosen: the fixed 34px SQUARE becomes an auto
   width with symmetric padding, because these carry TWO children (glyph + badge;
   glyph + caret) where the toggle carries one; `white-space: nowrap` comes from
   the sibling .ask-affordance/.topbar-update/.topbar-catchup rule, for the same
   reason it holds there; and .topbar-account-trigger is a <summary>, so it also
   takes the marker suppression every other <details> affordance in this sheet
   uses (.tl-addms, .dash-settings, .pc-connect-btn, .prov-toggle).
   ⚑ THE HOVER AND THE MARKER SUPPRESSION ARE WHY THIS CANNOT LIVE INLINE, and
   they are the part that was actually MISSING rather than merely misplaced: a
   style="" attribute cannot express a pseudo-class or a pseudo-element, so the
   stopgap shipped two controls with no hover feedback at all, next to a toggle
   that has it. The chrome is dark in BOTH themes (cairn_ui_topbar_chrome.test.js
   states that contract), which is why these are --chrome-* tokens and not the
   canvas tokens that flip. */
.topbar-bell, .topbar-account-trigger {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 34px; flex: 0 0 auto; padding: 0 9px; cursor: pointer;
  background: var(--chrome-deep); color: var(--chrome-text);
  border: 1px solid var(--chrome-border); border-radius: var(--border-radius-md);
  white-space: nowrap;
  transition: border-color 0.12s, background 0.12s, color 0.12s; }
.topbar-bell:hover, .topbar-account-trigger:hover,
.topbar-account[open] .topbar-account-trigger {
  background: #10161B; border-color: var(--color-accent); color: var(--chrome-text-strong); }
.topbar-account-trigger { list-style: none; }
.topbar-account-trigger::-webkit-details-marker { display: none; }

/* The <details> wrapper exists to position the panel it owns, nothing else. */
.topbar-account { position: relative; flex: 0 0 auto; }

/* ⚑ .node-icon PAINTS ITSELF, AND ON THE PERMANENTLY-DARK CHROME THAT IS WRONG.
   The base .node-icon rule sets color: var(--color-text-tertiary) — a CANVAS
   token — and a direct class rule beats the chip's inherited --chrome-text, so
   the bell and the account glyph rendered #888780 in light and #79828A in dark
   beside a .theme-toggle glyph at #AEB9C0 (measured in headless Chrome, both
   themes). This is the same trap `.theme-toggle .node-icon` and `.act-primary
   .node-icon` already name in this sheet, and it takes the same one-word fix.
   .node-icon also carries its own 8px right margin, which stacked with the
   chip's `gap` AND .badge's own 6px left margin to blow the bell out to 73px
   against the toggle's 34px (measured); zeroing both leaves `gap` as the single
   source of the spacing — the `.rec-tile-hd .node-icon` convention. */
.topbar-bell .node-icon, .topbar-account-trigger .node-icon { color: inherit; margin-right: 0; }
.topbar-bell .badge { margin-left: 0; }

/* The account panel. Canvas tokens throughout — unlike the chip that opens it,
   the panel is a card ON the canvas, so it follows the theme like every other
   dropdown body (.tl-addms-form is the idiom it copies, down to the absolute
   right-aligned drop and the card shadow). */
.topbar-account-menu { position: absolute; right: 0; top: calc(100% + 8px); z-index: 50;
  min-width: 220px; padding: 8px; display: flex; flex-direction: column; gap: 2px;
  background: var(--color-background-primary);
  border: 0.5px solid var(--color-border-secondary);
  border-radius: var(--border-radius-md); box-shadow: var(--shadow-card-hover); }

/* Who you are — the panel's quiet header; a long address clips rather than wraps. */
.acct-who { padding: 4px 10px 8px; font-size: 11px; color: var(--color-text-tertiary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The address itself lifts out of the header's tertiary tone. It carries no class of
   its own - it is a bare <span> the stopgap styled inline - so the rule reaches it the
   way .topbar-search reaches its <input>, by element. Without this, stripping the
   stopgap would silently drop the emphasis rather than move it. */
.acct-who span { color: var(--color-text-primary); font-weight: 500; }

/* A menu row. A state-changing entry is a <button> inside a <form>, so the form
   must contribute no box of its own and the button is reset to render as a row —
   the .side-foot / .side-logout idiom, which resets a submit button into a
   .side-link in exactly this way. The hover fill is the .side-link treatment in
   canvas tokens: on a row with no border and no background, hover is the only
   thing that says this is a control. */
.acct-item-form { display: block; margin: 0; }
.acct-item { display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 7px 10px; text-align: left; background: transparent; border: 0;
  border-radius: var(--border-radius-md); font: inherit; cursor: pointer;
  color: var(--color-text-primary); }
.acct-item:hover { background: var(--color-background-secondary); color: var(--color-accent-dark); }
.acct-item .node-icon { margin-right: 0; }

/* The queue row's inline verbs take the SAME pairing .triage-draft has above,
   for the same reason and with the same values. A <form> cannot nest inside the
   row's anchor, so the verb block is a SIBLING rendered after it — which left
   .citem's own border-bottom drawing a separator BETWEEN a row and its own
   buttons, and left the group with no closing border after them. Measured in
   headless Chrome before this rule: a row whose next sibling is .triage-verbs
   still painted its 0.5px border and its 12px bottom padding, and the next queue
   row began with no separator at all. So: suppress the border on the row, inset
   the block to the row's own 16px, and let the block carry the group's closing
   border, exactly as .triage-draft does. :has() is already load-bearing in this
   sheet for this very pairing (the .triage-draft rule above), so this uses that
   mechanism rather than introducing a second one. */
.triage-body .triage-row:has(+ .triage-verbs) { border-bottom: none; padding-bottom: 3px; }
.triage-verbs { padding: 0 16px 10px 16px;
  border-bottom: 0.5px solid var(--color-border-tertiary); }
.triage-body .triage-verbs:last-child { border-bottom: none; }

/* ⭐ W18 (2026-08-27) — AND THE VERBS RENDER ON ONE LINE, WHICH IS THE ENTIRE POINT OF
   THE ITEM. doc 05 §5.1 rule 3 asks for "INLINE verbs, no navigation needed for the
   common case: Approve · Edit · Decline · Ask". They shipped stacked: the block reuses
   .hq-actions, whose `flex-direction: column; align-items: flex-end` is correct for the
   SIGN-OFF BAND (where it is a narrow action column beside a card) and wrong here (where
   it is a full-width block under a queue row). Measured in headless Chrome before this
   rule, identical in both themes at 1440/1280/1024: the block was 163px tall with its
   four children on FOUR separate lines, right-aligned to the far edge — Approve sat
   ~950px from the title it approves. That is a vertical ladder of controls beside a row,
   which is a different design from the one rule 3 names.

   ⚑ THIS BLOCK NOW STATES ITS OWN LAYOUT RATHER THAN INHERITING ONE. Re-using .hq-actions
   for its geometry was the actual defect, so overriding two of its declarations and
   leaving the rest inherited would leave the same coupling in place — a later tune of the
   sign-off band's action column would silently move the queue again. Only the padding and
   the border above are shared with the band idiom; everything positional is declared here.

   ⛔ THE ROW'S OWN TEXT IS NOT TOUCHED, AND THAT WAS THE CONSTRAINT TO CHECK. The verbs
   are a SIBLING block under the row (a <form> cannot nest in the row's anchor), not a
   column beside it, so laying them out horizontally takes NO width from the title: the
   title measured 950px at 1280 both before and after. Putting the verbs on the row's own
   line instead was built and MEASURED before it was rejected, because arithmetic on the
   child widths under-stated it: the group needs 689px, and giving it that at 1024 left the
   row title 92.2px wide and 97.1px TALL — the label wrapped into a six-line sliver — while
   the verb group itself still wrapped onto two lines. That is the dispatch's own stated
   failure condition, so the block stays under the row rather than beside it.

   `wrap` is the honest degrade: the group needs 689px and the narrowest realistic
   container gives it 878px, so it does not wrap today — but a longer verb label or a
   narrower rail should re-flow rather than overflow the panel. Left-aligned at the row's
   own 16px inset, so the first verb starts under the first word of the row it acts on —
   the .triage-draft convention directly above. Colours are untouched: every child carries
   its own theme-aware rule (.act-btn, .grant-input), so this rule introduces no value
   that could differ between themes. */
.triage-verbs { display: flex; flex-direction: row; flex-wrap: wrap;
  align-items: center; justify-content: flex-start; gap: 8px; }

/* ⭐ W19 (2026-08-27) — A CONTROL WHOSE ONLY PAINT IS .act-btn / .bbtn HAS NO COLOUR OF
   ITS OWN, AND ON A <button> THE UA STYLESHEET SUPPLIES ONE. Both base rules (.act-btn
   at :471, .bbtn at :655) set padding, radius and `border: 0.5px solid` but NO background
   and NO color, so the border paints in currentColor and the fill is whatever the element
   already had. On an <a> or a <summary> that is exactly right — inherited ink, transparent
   fill, border in that same ink (MEASURED: light text+border rgb(30, 42, 50), dark
   rgb(232, 235, 237), fill rgba(0, 0, 0, 0) in both). On a <button> it is not, because a
   button does NOT inherit color: the UA stylesheet fills all three gaps with ButtonFace /
   ButtonText. MEASURED before this rule, headless Chrome 149.0.7827.22 at DPR 1:
     light   fill rgb(239, 239, 239) · text rgb(0, 0, 0)       · border rgb(0, 0, 0)
     dark    fill rgb(107, 107, 107) · text rgb(255, 255, 255) · border rgb(255, 255, 255)

   ⛑ THE SHIPPED CONSEQUENCE. "Edit & approve" and "Decline" (render/home.js) render as raw
   OS buttons in every Home queue row and every sign-off row, and in DARK THEME that grey
   ButtonFace slab reads as DISABLED — sitting directly beside the orange Approve it is
   paired with. Note WHY the two greys differ: :root[data-theme="dark"] sets
   `color-scheme: dark`, so the UA re-themes the control itself. The product never got a say
   in either theme; it only looked acceptable in one of them.

   ⚑ THIS PRODUCT HAS SHIPPED THIS DEFECT ONCE BEFORE. The 2026-07-17 fix at :1347-1356 is
   the same sentence about different elements: .topbar-update / .topbar-catchup had no
   colour of their own, fell through this same colourless base, and were invisible in LIGHT
   theme. The class is "a control whose only paint is a colourless base rule survives only
   because the canvas beneath it happens to flip." That fix painted the three named chips.
   This one removes the fall-through itself, so the class stops regenerating.

   ⛔ WHY :where(), AND NOT `button.act-btn` — WHICH IS THE OBVIOUS FORM AND IS WRONG.
   `button.act-btn` is specificity (0,1,1) and therefore BEATS .act-primary (0,1,0),
   .act-danger (0,1,0) and .act-disabled (0,1,0) — every variant that paints itself with a
   single class. MEASURED with that selector in place: the orange Approve fill went
   rgb(216, 90, 48) -> rgba(0, 0, 0, 0) and its text rgb(255, 255, 255) -> rgb(30, 42, 50),
   in BOTH themes; danger and disabled lost their fills the same way. The naive fix repaints
   the one button that was broken by breaking the four that were not. :where() contributes
   ZERO specificity, so this rule is (0,0,1): it outranks the UA stylesheet (an author rule
   always does) and loses to EVERY author rule, including ones not written yet. That is
   precisely the semantics wanted — supply the baseline the <button> never inherited, then
   get out of the cascade's way. No element-level `button` rule exists in this sheet, so
   nothing else competes at (0,0,1) and this block's position is not load-bearing.

   ⭐ NO VALUE IS INVENTED AND NO TOKEN IS NAMED, WHICH IS WHY THERE IS NO DARK COMPANION.
   `inherit` and `transparent` take whatever the theme already resolved one level up, so
   this rule cannot disagree with a token and needs no :root[data-theme="dark"] arm — it is
   correct in both themes for the same reason the <a> is. font-family is in scope because
   the UA `font` shorthand lands on every button too: MEASURED Arial on ALL of them,
   including the .act-primary ones that look correct, so Approve has been rendering in Arial
   beside a system-sans row label. `appearance: none` is defensive and MEASURED INERT here
   (identical computed style, geometry and focus ring with and without it in Chrome); it is
   present because WebKit is the engine where `appearance: auto` can still override an
   authored background, and stopping a UA default from deciding this control's look is the
   whole job of the rule.

   ⚑ .bbtn IS IN THE SELECTOR BECAUSE IT IS THE SAME DEFECT, not because it is tidy. Its
   base rule has the identical shape and MEASURES identically — same two greys, same black /
   white border. Live instances today: "Mark held" (render/calendar.js:148) and the two
   "Rename" controls (render/new-project.js:38, render/projects.js:614). All 20 .bbtn
   usages in the product are on <button>, so unlike .act-btn it has no <a> form to compare
   against; its contract here is "carries no UA fill", not "matches an anchor".

   ⛔ WHAT THIS RULE DELIBERATELY IS NOT: a `color:` on the .act-btn BASE rule.
   tests/cairn/cairn_ui_topbar_chrome.test.js pins that rule colourless, and its stated
   reason is a separation of concerns — the base carries the BOX MODEL, colour belongs to
   the element's variant or its context. This rule honours that reason rather than routing
   around it: `inherit` and `transparent` decide no colour, they restore the deferral a
   <button> should have had. The base rule stays exactly as colourless as the test requires,
   and the fall-through is closed at the ELEMENT, which is where it originates. */
button:where(.act-btn, .bbtn) { background: transparent; color: inherit;
  font-family: inherit; appearance: none; }

/* ===========================================================================
   W20 (2026-08-27) — .muted, four unpainted control clusters, and the /watch
   risk chips. ADDITIVE ONLY, appended last as ONE contiguous block because this
   file's tail is cascade-ordered. Every value below is copied from a NAMED
   sibling rule in this sheet; nothing is invented, and no rule is deleted.
   =========================================================================== */

/* ⭐ .muted HAD NO RULE AT ALL, so everything wearing it rendered at FULL BODY
   INK — the exact opposite of the word. MEASURED by reading every render module
   in server.js's require closure (36 files; this box has no grep for a
   remediator, so the derivation is a full read, file by file):

     26 emission sites across FIVE modules — not twelve.
       render/intake.js      17   attendeesCell · rowHtml · countsLine ·
                                  taskRowHtml · taskCountsLine · ownerNoteHtml ·
                                  importControl · render (honesty, trunc, window)
       render/due.js          4   rulesPreviewSection · render (partialNote)
       render/home.js         3   worthALookPanel · render (heldDeclineNote,
                                  flagNoteLine)
       render/watch.js        1   render (partialNote)
       render/commitments.js  1   detailCard (flagsField's note chip)

   ⚑ THE COUNT IS A MEASUREMENT WITH A DATE, NOT A FACT ABOUT THE TREE. Re-derive
   it — do not quote it — with a substring sweep for `muted` under
   cairn/ui/render/. Function names are cited rather than line numbers for the
   reason cairn/ui/SPEC.md §"Citation convention" gives: a line anchor rots on
   the first insertion above it, and one rotted by 15 inside THIS file during
   this very change.

   ⚑ WHY TERTIARY, AND WHY THE APPEND-ORDER WORRY DISSOLVES. Eight of the 26
   sites carry a second class that ALREADY sets a colour — .due-partial,
   .watch-partial and .hq-why — and all eight of those are
   var(--color-text-tertiary). At equal specificity (0,1,0) this later rule wins,
   and it wins with the value they already had, so those eight render
   byte-identically. The ninth co-class, .cmt-flag-note, sets font-size only.
   The other seventeen are on /intake, where NO .intake-* rule exists in this
   sheet at all — there, this declaration is the only paint on the element.

   ⚑ NOT :where(). The button:where(.act-btn, .bbtn) rule above exists so an
   ELEMENT base rule loses to every class variant. .muted is the opposite shape
   — a modifier that is meant to win over the block class it rides — so it takes
   ordinary class specificity. Do not cargo-cult the zero-specificity form here.

   ⚑ NO DARK COMPANION IS NEEDED and that is checked, not assumed:
   --color-text-tertiary is declared in :root AND re-declared in
   :root[data-theme="dark"], so the token flips on its own. */
.muted { color: var(--color-text-tertiary); }

/* ⭐ THE QUEUE ROW'S SEVERITY TAG WAS THE ONLY BARE-TEXT ITEM IN A ROW OF PILLS.
   render/home.js — triageBand() emits `<span class="triage-tag">needs your
   sign-off</span>` into the same .citem-meta slot where a conflict row emits
   .sev .sev-blocking or .sev .sev-advisory — so one queue meta line carried two
   pills and one run of inherited mono text.

   ⚑ THE BOX IS .sev's, TAKEN VERBATIM, because .sev is the sibling that occupies
   this exact slot. THE TONE IS NEUTRAL, and that is the design call: this row is
   an approval waiting on you, which is neither blocking (red) nor advisory
   (amber), so wearing either severity hue would state a severity the record does
   not carry. The neutral tone is .action-tag's — the chip Home's own sign-off
   cards already use for this class of record.

   ⚑ AND THAT CHOICE IS WHY THERE IS NO :root[data-theme="dark"] ARM. The .sev
   family paints with hard-coded pastels and therefore needs its own
   :root[data-theme="dark"] .sev-blocking / .sev-advisory retune;
   .action-tag's two colours are semantic tokens that flip on their
   own. Matching the box of one sibling and the tone mechanism of another is
   deliberate — it buys the right shape without importing a per-theme override.
   ⛔ .action-tag's `text-transform: uppercase` is NOT taken: this label is a
   four-word sentence, not a one-word tag, and shouting it is a different
   design from the one the row asks for. */
.triage-tag { display: inline-flex; align-items: center; font-size: 9px; font-weight: 500;
  padding: 1px 6px; border-radius: 2px; white-space: nowrap;
  background: var(--color-background-secondary); color: var(--color-text-secondary); }

/* ⭐ THE /discussion PAGER RENDERED AS PLAIN PROSE. render/discussion.js — render()
   emits `<nav class="pager">` holding `<a class="pager-link pager-prev">‹ Newer</a>`
   and `<a class="pager-link pager-next">Older ›</a>`, and neither class had a
   rule — so with the base `a { color: inherit; text-decoration: none }` rule at
   the head of this sheet, the ONLY navigation off page 2 of a comment list was
   indistinguishable from the body text beside it. A control that reads as prose
   is the same defect class as a control that does nothing.

   The sibling is exact rather than approximate: .cal-nav / .cal-nav-link /
   .cal-nav-link:hover IS this product's prev/next pager — the calendar's month
   nav — so every value below is that rule's, unchanged. The one delta is
   positional and forced by where the control sits: the calendar nav sits ABOVE
   its grid and carries margin-bottom; this pager sits BELOW its list, so the
   same 12px is spent on margin-top.

   ⚑ .pager-prev / .pager-next TAKE NO RULE, DELIBERATELY. They are direction
   hooks with no distinct treatment, exactly as .cal-nav-prev / .cal-nav-next
   (render/calendar.js — navLink) carry none in this sheet. Minting empty rules for
   them would be painting to silence a sweep rather than to fix a screen. */
.pager { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 12px; }
.pager-link { font-family: var(--font-mono); font-size: 12px; font-weight: 500; padding: 5px 11px;
  color: var(--color-text-secondary); background: var(--color-background-secondary);
  border: 0.5px solid var(--color-border-tertiary); border-radius: var(--border-radius-md); }
.pager-link:hover { color: var(--color-accent-dark); border-color: var(--color-accent); }

/* ⭐ EVERY .dept-manage-* CONTROL SHIPPED WITH NO RULE, WHICH IS WHY THE WHOLE
   DEPARTMENT RENAME/REMOVE BEAT READS AS ABSENT ON A VISUAL WALK EVEN THOUGH THE
   MECHANISM SHIPS. render/projects.js — departmentManage() emits a
   <details class="dept-manage"> whose <summary class="act-btn dept-manage-btn">
   keeps its NATIVE disclosure triangle (every other summary-as-button in this
   sheet suppresses it), and a .dept-manage-body holding two .dept-manage-form
   forms plus a .dept-manage-note, all with no layout at all — so the rename
   input, its Rename button and the Remove button sat in undifferentiated block
   flow.

   Each rule below names the sibling it copies:
     .dept-manage-btn        ← .dash-settings > summary — the same no-JS
                               summary-as-act-btn idiom, marker suppression
                               included (the convention .tl-addms, .pc-connect-btn
                               and .topbar-account-trigger all follow).
     .dept-manage-body       ← .dash-settings-form — that idiom's own disclosure
                               panel, which is exactly what this is.
     .dept-manage-form       ← .tpl-row-form — the manage-my-templates row on
                               /projects/new is the SAME control, inline input +
                               button, down to the input's max-width.
     .dept-manage-note       ← .asof-hint for the full-width-inside-a-wrapping-row
                               behaviour, and .dept-caption for the type, because
                               it is this family's own quiet caption.
   Every colour is a semantic token, so both themes flip with no per-rule retune. */
.dept-manage-btn { list-style: none; cursor: pointer; white-space: nowrap; display: inline-flex; }
.dept-manage-btn::-webkit-details-marker { display: none; }
.dept-manage-body { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 8px;
  padding: 10px 14px; background: var(--color-background-primary);
  border: 0.5px solid var(--color-border-secondary); border-radius: var(--border-radius-md); }
.dept-manage-form { display: flex; align-items: center; gap: 6px; }
.dept-manage-form .grant-input { max-width: 200px; }
.dept-manage-note { flex: 1 1 100%; font-size: 11px; color: var(--color-text-tertiary); line-height: 1.45; }

/* ⭐ THE /add JUMP-TO ROW IS THE F1 DEFECT AGAIN, IN A SECOND PLACE.
   render/add.js — render() concatenates its five .act-btn anchors with NO
   whitespace between the tags, inside a .add-chooser <div> that has no rule —
   and .act-btn is `display: inline-flex`, so five inline-level boxes with no
   source whitespace and no gap paint with their borders touching. That is the
   same failure the F1 note above .brief-template-tabs records ("were unstyled
   and ran together — 'ProjectBoardInvestor'"), which this sheet already fixed
   once with a flex row + gap. Fixing one instance and leaving the sibling is not
   fixing the class.

   .add-chooser is also the .panel's own child, and .panel supplies no padding
   (the .empty / .np-form / .rec-tiles convention), so the row needs its own
   inset or it sits flush against the card edge.

   Sibling: .filter-row — a label followed by a wrapping row of controls inside a
   panel, which is exactly this. Its border-bottom is NOT taken: that rule is a
   header strip with rows beneath it, and nothing follows this row inside its
   panel, so the line would draw under nothing.
   .add-chooser-label ← .brief-since-label — the sheet's treatment
   for a short sentence-case label preceding a control in a row. (.filter-label
   is not used here: it uppercases, and "Jump to:" is an instruction, not a tag.)
   ⚑ .add-jump NEEDS NO RULE — it rides .act-btn, which paints it. It is listed
   here so a later reader does not add one thinking it was missed. */
.add-chooser { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 11px 16px; }
.add-chooser-label { font-size: 11px; font-weight: 500; color: var(--color-text-secondary); }

/* ⛔ THE /watch RISK CHIPS RENDERED AS FULL-WIDTH COLOURED BARS, AND THE CAUSE IS
   FLEX STRETCH — NOT A MISSING `display`. render/watch.js — atRiskRow() emits the
   reason chips (.badge-red / .badge-amber, built by reasonChip) as DIRECT
   CHILDREN of `<a class="watch-row">`, and the .watch-row rule is
   `display: flex; flex-direction: column`. In a COLUMN flex container the cross
   axis is horizontal, so the default `align-items: stretch` sizes every child to
   the container's full width — and a flex item's `display` is blockified, which
   is why the computed style reads `block` on a <span>. Same class, same rule,
   two widths: on Home the identical chips sit inside .node-row / .citem-meta,
   both ROW-direction flex, where the cross axis is vertical and the chip keeps
   its content width.

   ⚑ SO THE FIX IS align-self, NOT display. Setting `display: inline-flex` on the
   chip would change nothing: blockification would flatten it back to `flex` and
   `align-items: stretch` would still hand it the full width. `align-self:
   flex-start` opts these two children out of the stretch and nothing else.

   ⚑ SCOPED TO THE ROW, at (0,2,0), so it cannot reach the same chips anywhere
   else — the project tree, the all-projects table, the Home "Worth a look" band
   and the ingest contradiction chip all keep exactly what they render today. The
   .badge-red / .badge-amber rules and their :root[data-theme="dark"] retune are
   untouched, so both themes are unchanged apart from the width.

   ⛑ WHAT THIS DOES NOT DO: put multiple chips on ONE line. Each chip becomes its
   own flex line at the row's 3px gap. Reading them as a single cluster the way
   Home does needs a wrapper element around the chips in render/watch.js — that
   file belongs to another lane this session, so the geometry defect is closed
   here and the clustering is reported rather than forced with a :has() rewrite
   of a shipped row's flex direction. */
.watch-row > .badge-red,
.watch-row > .badge-amber { align-self: flex-start; }

/* ===========================================================================
   W21 (2026-08-27) — .side-sublink: the way BACK to a destination the six-door
   collapse absorbed. APPENDED AFTER the W20 block above, not merged into it,
   because this file's tail is cascade-ordered. ADDITIVE ONLY; no rule above is
   touched.
   =========================================================================== */

/* ⭐ WHY A NEW HOOK EXISTS AT ALL, so this is not read as decoration. doc 05 §3.2
   rules that every destination the 16→6 collapse absorbed keeps its route AND
   stays "reachable from these six in one further click". For /watch the second
   half was never built: its ONLY inbound link in the product is the "See all →"
   control INSIDE Home's "Worth a look" band, and that band is REQUIRED to render
   nothing at all when both of its reads come back genuinely empty. So the sole
   carrier of a reachability promise is an element that must disappear on exactly
   the quiet workspace where a reader goes looking. render/layout.js now emits a
   section link beneath the OPEN door; this is its paint.

   ⛔ IT IS NOT A SEVENTH DOOR AND THIS RULE IS WHERE THAT IS MADE VISIBLE. It
   takes NONE of .side-link's identity — no 13px display type, no 500 weight, no
   icon slot, no active fill, no badge. What it takes is the rail's SECONDARY
   tier, which is what a link inside a door is.

   Each value names the sibling it is copied from:
     font-family · font-size · color ·
     overflow/text-overflow/white-space   ← .side-identity (:137-138), the rail's
                                            own secondary-text row. The ellipsis
                                            triple comes with them for the same
                                            reason it is there: the sidebar is a
                                            fixed 248px and a long label must
                                            truncate rather than widen it.
     padding-top / padding-bottom         ← .side-identity, verbatim (4px / 6px),
                                            rather than re-balanced — it is that
                                            row's rhythm and this sits in the same
                                            column.
     padding-right                        ← .side-link / .side-identity (12px).
     padding-left 39px                    ← DERIVED, and it is the one number here
                                            that is arithmetic rather than a copy:
                                            .side-link is padding 9px 12px, its icon
                                            is rendered at size 16, and its gap is
                                            11px — so 12+16+11 = 39 puts this label
                                            under the DOOR LABELS above it instead
                                            of under their icons.
     border-radius · transition           ← .side-link (:121-123).
     :hover background + color            ← .side-link:hover (:124), verbatim.

   ⚑ NO :root[data-theme="dark"] ARM IS NEEDED, AND THE REASON IS STRUCTURAL
   RATHER THAN A LOOKUP. This element sits in the rail, which is PERMANENTLY dark
   chrome in both themes (tests/cairn/cairn_ui_chrome_stylesheet.test.js states
   that contract and is why its arm 1 scopes itself to this surface). Every colour
   below is one of the three --chrome-* tokens .side-link and .side-link:hover
   already use — not a token that merely resembles them. So this link cannot
   diverge from the rail's own links in any theme, present or future: if
   --chrome-text is ever retuned, both move together. That is a stronger guarantee
   than checking today's declaration, which would only be true today.

   ⚑ AND IT DISAPPEARS IN THE COLLAPSED RAIL, WHICH IS NOT OPTIONAL. At ≤1100px
   .app-shell drops to a 64px icon column and the sheet hides .side-label and
   .side-identity outright (:172-183) rather than show a truncated fragment. A
   text-only link is the one thing that would be left overflowing it, so it takes
   the same treatment for the same reason. This is why the media query is part of
   the fix and not a later polish. */
.side-sublink { display: block; padding: 4px 12px 6px 39px;
  font-family: var(--font-display); font-size: 11px; color: var(--chrome-text);
  border-radius: 8px; transition: background 0.12s, color 0.12s;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-sublink:hover { background: var(--chrome-raise); color: var(--chrome-text-strong); }
@media (max-width: 1100px) { .side-sublink { display: none; } }

/* ===========================================================================
   W22 (2026-08-27) — .cmt-subtask-static: a retired task's checklist, SAID
   rather than offered. APPENDED AFTER the W20 + W21 blocks above and merged
   into neither, because this file's tail is cascade-ordered — one builder
   appending one ordered block is conflict-free by construction, where two
   builders appending logically-disjoint rules are not. ADDITIVE ONLY; no rule
   above is touched.

   ⚑ SIBLINGS ARE CITED BY SELECTOR, NOT BY LINE, per the convention the W20
   block above states and gives the reason for. Re-measured here rather than
   trusted: the dispatch that ordered this change cited W21 as ending at :2665
   and it ends at :2669 — a four-line rot, in this file, within one session.
   =========================================================================== */

/* ⭐ THE ROW CARRIES NO BASE CLASS, WHICH IS WHY THIS RULE SUPPLIES LAYOUT
   INSTEAD OF CANCELLING IT. render/commitments.js — detailCard()'s subtaskField
   re-emits a subtask row as `<div class="cmt-subtask-static">` on a retired
   (non-writable) version, DELIBERATELY without .cmt-subtask; that module's own
   note states the reason and states this rule verbatim as the debt it owed to
   this sheet. Toggling a retired version's checkbox posts to
   /commitment/subtask -> updateCommitment -> NOT_ACTIVE, so the control was the
   same dead offer the action row was; the checklist is still worth READING, so
   the content stays and only the control goes.

   ⛔ THE HOUSE PRECEDENT IS THE WRONG SHAPE HERE, AND THAT IS THE POINT.
   .node-row.node-static and .citem-nolink are both SUBTRACTIVE modifiers — each
   rides a base class (.node-row / .citem) that keeps painting the row, and each
   withdraws only `cursor` and the `:hover` fill. Neither shape works here,
   because there is no base class left to subtract from. Reusing .cmt-subtask
   plus a modifier would INVERT the failure mode, which is the whole argument:
   wearing the control class, a MISSING rule still reads as clickable — a false
   affordance on a control the engine will refuse. Wearing a class of its own, a
   missing rule degrades to plain text at body size — wrong typography, never a
   lie.

   Every value below is .cmt-subtask's, and only the five that are layout:
     display · align-items · gap · font-size · line-height   ← .cmt-subtask, verbatim.

   ⛔ WHAT IS DELIBERATELY NOT TAKEN, AND WHY EACH IS SAFE TO DROP.
   `background: none`, `border: none`, `padding: 0`, `width: 100%`,
   `color: inherit` and `text-align: left` are that rule's <button> RESET — they
   exist only to neutralise UA button chrome, and a <div> carries none of it
   (the `* { margin: 0; padding: 0 }` rule at the head of this sheet already
   zeroes the box, and a child of .cmt-subtasks is a COLUMN flex item, so it
   already stretches to the full width the button asked for explicitly).
   `cursor: pointer` and `.cmt-subtask:hover .cmt-subtask-what` are the click
   affordance, and withholding them is the job.

   ⚑ THE DONE STATE SURVIVES THE SWAP UNTOUCHED — checked, not assumed.
   `.cmt-subtask-done .cmt-subtask-box` and `.cmt-subtask-done .cmt-subtask-what`
   are DESCENDANT selectors keyed on .cmt-subtask-done ALONE, never compounded
   with .cmt-subtask, so the ticked glyph and the struck-through label paint
   identically on the <div> — which carries .cmt-subtask-done in exactly the
   same position the <button> did.

   ⚑ NO :root[data-theme="dark"] ARM, AND NO TOKEN IS NAMED. This rule declares
   no colour whatsoever: the row inherits body ink through the cascade in both
   themes, exactly as it does today. A dark companion would have nothing to say,
   and inventing one would be painting to silence a sweep rather than to fix a
   screen. */
.cmt-subtask-static { display: flex; align-items: baseline; gap: 7px;
  font-size: 12.5px; line-height: 1.5; }
