/* ============================================================
   Clarity GTM Console — component CSS

   Loaded AFTER app.css. app.css is the inherited Certifier kit and
   is not edited; everything this console adds lives here.

   Rules carried over from POLISH.md and not renegotiated:
   - No new colours. Every value is a token.
   - No gradients built from the primary ramp. Certifier blue is solid.
   - Only color / background / border / box-shadow / transform animate.
     Never width, height, top or left.
   - Micro-interactions stay under 200ms. The two documented
     exceptions (--dur-chart, --dur-count) are content arriving, not
     interaction feedback.
   - The reduced-motion blanket in app.css uses a universal selector,
     so everything below is covered by it automatically. Nothing here
     opts out with !important.
   ============================================================ */

/* ============================================================
   1. SHELL ADDITIONS
   ============================================================ */

.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: -60px;
  z-index: 200;
  padding: var(--sp-2) var(--sp-4);
  background: var(--primary-600);
  color: var(--text-invert);
  border-radius: var(--radius-control);
  font-family: var(--font-display);
  font-size: var(--fs-control);
  font-weight: 500;
  transition: top var(--dur-fast) var(--ease-out);
}
.skip-link:focus { top: var(--sp-4); }

.sidebar-brand .brand-tag {
  margin-left: auto;
  padding: 2px var(--sp-2);
  border-radius: var(--radius-sm);
  background: var(--primary-50);
  color: var(--primary-700);
  font-family: var(--font-display);
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: 0.06em;
}

/* Nav sections — the five stage names that make eleven doors read as
   one motion instead of a menu of three products. */
.nav-group { display: flex; flex-direction: column; gap: 1px; margin-bottom: var(--sp-4); }
.side-nav .nav-section-label:first-child { margin-top: 0; }

.sidebar-foot .goal-mini {
  display: block;
  margin-bottom: var(--sp-2);
  color: var(--text-2);
  font-size: var(--fs-xs);
  line-height: 1.5;
}
.sidebar-foot .goal-mini strong {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.sidebar-foot .goal-day { display: block; color: var(--text-3); }

/* ---- Topbar live cluster ---- */
.live-cluster {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-shrink: 0;
}
.live-here {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px var(--sp-2-5);
  border-radius: var(--radius-full);
  background: var(--inset);
  font-size: var(--fs-xs);
  color: var(--text-2);
  white-space: nowrap;
}
.live-dot {
  width: 7px; height: 7px;
  border-radius: var(--radius-full);
  background: var(--neutral-400);
  flex-shrink: 0;
}
.live-dot.is-live { background: var(--success-500); animation: live-ping 2.4s var(--ease) infinite; }
@keyframes live-ping {
  0%, 100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.45); }
  60%      { box-shadow: 0 0 0 5px rgba(34, 197, 94, 0); }
}
.live-n { font-weight: 600; color: var(--ink); }
.live-lbl { color: var(--text-3); }

.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-h-sm);
  height: var(--control-h-sm);
  border-radius: var(--radius-control);
  border: 1px solid var(--border-strong);
  background: var(--card);
  color: var(--text-2);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.btn-icon:hover { background: var(--canvas); color: var(--ink); }
.btn-icon[aria-pressed="true"] {
  background: var(--primary-50);
  border-color: var(--primary-200);
  color: var(--primary-700);
}

.search-kbd {
  position: absolute;
  right: var(--sp-2-5);
  top: 50%;
  transform: translateY(-50%);
  padding: 1px 5px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--text-3);
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  pointer-events: none;
}
.topbar-search:focus-within .search-kbd { opacity: 0; }

@media (max-width: 1199px) { .live-lbl { display: none; } }
@media (max-width: 1099px) { .live-here { display: none; } }
@media (max-width: 899px)  { .live-cluster { display: none; } .search-kbd { display: none; } }

/* ============================================================
   2. CHIP ADDITIONS
   ============================================================ */

.chip-info::before, .chip-outline::before, .chip-tier::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: var(--radius-full);
  flex-shrink: 0;
}
.chip-info    { background: var(--info-50); color: var(--info-700); }
.chip-info::before { background: var(--info-500); }

/* Border-only, no fill — the visual language of "this is not solid".
   Used for Guessed and Low confidence, and nothing else. */
.chip-outline {
  background: transparent;
  color: var(--text-2);
  border-color: var(--border-strong);
  border-style: dashed;
}
.chip-outline::before { background: var(--conf-none); }

/* ============================================================
   3. GATE EXPLANATIONS

   Every disabled control in this console is wired to one of these.
   A disabled button with no stated reason is a dead end, so the
   reason travels with the block and is announced via
   aria-describedby, not merely shown.
   ============================================================ */

.gate-explain {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2-5);
  margin-top: var(--sp-3);
}
.gate-explain-icon { flex-shrink: 0; margin-top: 1px; color: var(--warning-700); }
.gate-explain strong { display: block; margin-bottom: 2px; }
.gate-explain ul { margin: 0; padding-left: var(--sp-4); }
.gate-explain li { margin-bottom: 2px; }
.gate-explain li:last-child { margin-bottom: 0; }
.gate-explain .btn { margin-top: var(--sp-2-5); }

/* app.css's .card-header is a "title | action button" flex row. This
   console's cards usually carry an explanatory sub-line instead, and
   as a plain sibling it lands in the action slot and sits BESIDE the
   title. Forcing it onto its own row fixes that everywhere at once,
   without touching the inherited kit or needing :has(). */
.card-header { flex-wrap: wrap; align-items: baseline; }
.card-header > .card-sub { flex: 1 0 100%; margin-top: 2px; }
.card-header > .card-title { margin: 0; }

/* ============================================================
   4. CHARTS
   ============================================================ */

.chart-wrap { position: relative; }
.chart { display: block; width: 100%; height: auto; overflow: visible; }
.chart-axis { fill: var(--chart-muted); font-size: 10px; font-family: var(--font-mono); }

.spark { display: block; color: var(--primary-400); overflow: visible; }
.spark-line.is-drawing { animation: spark-draw var(--dur-chart) var(--ease-out) both; }
@keyframes spark-draw { from { stroke-dasharray: 1; stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

.chart-area .is-drawing { animation: spark-draw var(--dur-chart) var(--ease-out) both; }

.chart-donut-wrap { display: flex; align-items: center; gap: var(--sp-6); flex-wrap: wrap; }
.chart-donut { flex-shrink: 0; width: auto; }
.donut-arc { transition: opacity var(--dur-fast) var(--ease-out); }
.donut-center {
  fill: var(--ink);
  font-family: var(--font-display);
  font-size: 22px; font-weight: 700; letter-spacing: -0.025em;
}
.donut-center-sub { fill: var(--text-3); font-size: 11px; }

.chart-legend { list-style: none; margin: 0; padding: 0; flex: 1 1 200px; min-width: 180px; }
.chart-lg {
  display: flex; align-items: center; gap: var(--sp-2-5);
  padding: 5px 0; font-size: var(--fs-sm); color: var(--text-2);
}
.chart-sw { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; box-shadow: inset 0 0 0 1px var(--chart-hairline); }
.chart-lg-label { flex: 1; min-width: 0; }
.chart-lg-val { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ---- Horizontal bars ---- */
.hbars { list-style: none; margin: 0; padding: 0; }
.hbar {
  display: grid;
  grid-template-columns: minmax(90px, 168px) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-3);
  padding: 5px 0;
  font-size: var(--fs-sm);
}
.hbar-label { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hbar-track { height: 8px; border-radius: var(--radius-full); background: var(--chart-track); overflow: hidden; }
.hbar-fill {
  display: block; height: 100%;
  background: var(--chart-1);
  border-radius: var(--radius-full);
  box-shadow: inset 0 0 0 1px var(--chart-hairline);
  animation: bar-grow var(--dur-chart) var(--ease-out) both;
}
.hbar--success .hbar-fill { background: var(--success-600); }
.hbar--warning .hbar-fill { background: var(--warning-600); }
.hbar--danger  .hbar-fill { background: var(--danger-600); }
.hbar-val { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; min-width: 46px; text-align: right; }

/* Growth animates from zero width TO the inline width — the keyframe
   only declares the start, so the element keeps its real size. */
@keyframes bar-grow { from { transform: scaleX(0); transform-origin: left; } }

/* ---- Funnel ----
   Label left, value right, NOTHING inside the bar. */
.funnel { list-style: none; margin: 0; padding: 0; }
.fnl-row {
  display: grid;
  grid-template-columns: minmax(96px, 132px) minmax(0, 1fr) 56px 46px;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
}
.fnl-label { font-size: var(--fs-sm); color: var(--text-2); white-space: nowrap; }
.fnl-track { display: block; }
.fnl-bar {
  display: flex;
  height: 26px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  animation: bar-grow var(--dur-chart) var(--ease-out) both;
}
.fnl-seg {
  display: block; height: 100%; border: 0; padding: 0; cursor: pointer;
  box-shadow: inset 0 0 0 1px var(--chart-hairline);
  transition: filter var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
.fnl-seg:hover { filter: brightness(0.94); }
.fnl-seg:focus-visible { outline: 2px solid var(--primary-600); outline-offset: 2px; }
/* The only place light/dark carries meaning: dark came from a
   directory pull, light was seen on the site. A hairline divider makes
   the boundary legible even at small widths. */
.fnl-seg--dir  { background: var(--funnel-6); }
.fnl-seg--site { background: var(--funnel-3); box-shadow: inset 1px 0 0 var(--card), inset 0 0 0 1px var(--chart-hairline); }
.fnl-val  { font-weight: 700; color: var(--ink); text-align: right; font-variant-numeric: tabular-nums; }
.fnl-conv { font-size: var(--fs-xs); color: var(--text-3); text-align: right; font-variant-numeric: tabular-nums; }

.funnel-key {
  display: flex; gap: var(--sp-4); flex-wrap: wrap;
  margin-top: var(--sp-3); padding-top: var(--sp-3);
  border-top: 1px solid var(--border);
  font-size: var(--fs-xs); color: var(--text-3);
}
.funnel-key span { display: inline-flex; align-items: center; gap: 6px; }
.funnel-key i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }

/* ---- Histogram ---- */
.hist { display: flex; align-items: flex-end; gap: 4px; height: 150px; }
.hist-col {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  background: none; border: 0; padding: 0; cursor: pointer; height: 100%;
}
.hist-stack { position: relative; flex: 1; width: 100%; display: flex; align-items: flex-end; }
.hist-bar {
  position: relative; z-index: 1;
  width: 100%; background: var(--chart-1);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  box-shadow: inset 0 0 0 1px var(--chart-hairline);
  transition: background var(--dur-fast) var(--ease-out);
}
/* The translucent second series: how far this bucket could move if
   the inferred axes are wrong. */
.hist-spread {
  position: absolute; left: 0; bottom: 0; width: 100%;
  background: var(--chart-fill);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.hist-col:hover .hist-bar { background: var(--primary-700); }
.hist-col:focus-visible { outline: 2px solid var(--primary-600); outline-offset: 2px; border-radius: var(--radius-sm); }
.hist-x { font-size: var(--fs-2xs); color: var(--text-3); font-family: var(--font-mono); }

/* ---- Ring, meter, warmup strip ---- */
.ring { display: block; flex-shrink: 0; }

.meter {
  display: block; width: 100%; height: 6px;
  border-radius: var(--radius-full);
  background: var(--chart-track); overflow: hidden;
}
.meter-fill {
  display: block; height: 100%;
  background: var(--chart-1); border-radius: var(--radius-full);
  animation: bar-grow var(--dur-chart) var(--ease-out) both;
}
.meter--success .meter-fill { background: var(--success-600); }
.meter--warning .meter-fill { background: var(--warning-600); }
.meter--danger  .meter-fill { background: var(--danger-600); }

.warm-strip { display: inline-flex; gap: 2px; align-items: flex-end; }
.warm-cell { width: 4px; height: 14px; border-radius: 1px; background: var(--inset); }
.warm-0 { background: var(--inset); }
.warm-1 { background: var(--primary-200); }
.warm-2 { background: var(--primary-400); }
.warm-3 { background: var(--primary-600); }

/* ---- Score ----
   A score never renders as a bare number. The band always rides
   with it, and the mini shows which axes were guessed. */
.score { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.score-val {
  font-family: var(--font-display);
  font-weight: 700; font-size: var(--fs-md);
  letter-spacing: -0.02em; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.score-band { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.score-mini { flex-shrink: 0; margin-left: 2px; }
.score--lg .score-val { font-size: var(--fs-2xl); line-height: 1.05; letter-spacing: -0.03em; }
.score--lg .score-band { font-size: var(--fs-sm); }

.axis-row {
  display: grid;
  grid-template-columns: minmax(110px, 150px) minmax(0, 1fr) 76px;
  align-items: center; gap: var(--sp-3);
  padding: var(--sp-2-5) 0;
  border-bottom: 1px solid var(--border);
}
.axis-row:last-child { border-bottom: 0; }
.axis-label { font-size: var(--fs-control); color: var(--text-2); }
.axis-track {
  position: relative; display: block; height: 10px;
  border-radius: var(--radius-full); background: var(--chart-track); overflow: hidden;
}
.axis-fill {
  position: absolute; left: 0; top: 0; height: 100%;
  background: var(--chart-1); border-radius: var(--radius-full);
}
.axis-band { position: absolute; top: 0; height: 100%; background: var(--chart-fill); }
.axis-track--inferred .axis-fill { background: var(--chart-4); }
.axis-num { text-align: right; font-variant-numeric: tabular-nums; font-size: var(--fs-control); color: var(--ink); }
.axis-num small { color: var(--text-3); font-size: var(--fs-xs); }
.axis-note {
  grid-column: 1 / -1;
  margin-top: -2px;
  font-size: var(--fs-xs); color: var(--text-3); line-height: 1.5;
}
.axis-note--inferred { color: var(--warning-700); }

/* ============================================================
   5. STAT TILE ADDITION
   ============================================================ */

.stat-tile { position: relative; }
.stat-spark { position: absolute; right: var(--card-pad); bottom: var(--card-pad); color: var(--primary-300); }
.stat-target { font-size: var(--fs-xs); color: var(--text-3); }

/* ============================================================
   6. FILTER RAIL  (Directory — the shared query grammar)
   ============================================================ */

.dir-layout { display: grid; grid-template-columns: var(--filter-rail-w) minmax(0, 1fr); gap: var(--sp-6); align-items: start; }
.filter-bar { position: sticky; top: var(--sp-4); }
.filter-group { margin-bottom: var(--sp-5); }
.filter-group > h3 {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-2xs); font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-3);
}
.filter-chips { display: flex; flex-wrap: wrap; gap: 6px; }

.fchip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px var(--sp-2-5);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-full);
  background: var(--card);
  color: var(--text-2);
  font-size: var(--fs-xs); font-weight: 500;
  cursor: pointer; min-height: 28px;
  transition: background var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.fchip:hover { background: var(--canvas); border-color: var(--neutral-300); }
.fchip[aria-pressed="true"] {
  background: var(--primary-600); border-color: var(--primary-600); color: var(--text-invert);
}
.fchip[aria-pressed="true"] .fchip-count { color: rgba(255, 255, 255, 0.72); }
.fchip-count { color: var(--text-3); font-variant-numeric: tabular-nums; }
.fchip:disabled { opacity: 0.45; cursor: not-allowed; }

.filter-summary {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); flex-wrap: wrap;
  padding: var(--sp-2-5) 0 var(--sp-3);
  font-size: var(--fs-control); color: var(--text-2);
}
.filter-summary strong { color: var(--ink); font-variant-numeric: tabular-nums; }

/* Source badges — the only place downstream of Find where a record's
   origin is visible at all. */
.src-badge {
  display: inline-flex; align-items: center;
  padding: 1px 6px; border-radius: var(--radius-sm);
  font-size: var(--fs-2xs); font-weight: 600; letter-spacing: 0.02em;
  background: var(--inset); color: var(--text-3);
}
.src-badge--site { background: var(--primary-50); color: var(--primary-700); }
.src-badge--both { background: var(--success-50); color: var(--success-700); }

@media (max-width: 1099px) {
  .dir-layout { grid-template-columns: 1fr; }
  .filter-bar { position: static; }
}

/* ============================================================
   7. TABLE ADDITIONS
   ============================================================ */

.table-wrap--sticky { max-height: 70vh; overflow: auto; }
.table-wrap--sticky thead th { position: sticky; top: 0; z-index: 2; }

/* The caret is inline-flex inside the header so it sits ON the
   baseline next to the label rather than dropping below it. */
.table th[aria-sort] { cursor: pointer; user-select: none; white-space: nowrap; }
.table th[aria-sort] .sort-caret {
  display: inline-flex; align-items: center;
  vertical-align: middle; margin-left: 3px;
  opacity: 0; transform: rotate(90deg);
  transition: opacity var(--dur-fast) var(--ease-out);
}
.table th[aria-sort="ascending"] .sort-caret,
.table th[aria-sort="descending"] .sort-caret { opacity: 1; }
.table th[aria-sort="ascending"] .sort-caret { transform: rotate(-90deg); }

/* Directory column widths.

   Under table-layout:fixed the browser hands the clinic name whatever
   is left after the other eight columns, which is how it ended up as
   the narrowest column on the screen wrapping to three lines. Every
   minor column is pinned tight so the name gets the remainder — it is
   the only column anyone reads first. */
.table--directory { table-layout: fixed; width: 100%; }
.table--directory th, .table--directory td { padding-left: var(--sp-2-5); padding-right: var(--sp-2-5); }
.table--directory th:nth-child(1), .table--directory td:nth-child(1) { width: 30px; padding-right: 0; }
.table--directory th:nth-child(2), .table--directory td:nth-child(2) { width: auto; }
.table--directory th:nth-child(3), .table--directory td:nth-child(3) { width: 90px; }
.table--directory th:nth-child(4), .table--directory td:nth-child(4) { width: 64px; }
.table--directory th:nth-child(5), .table--directory td:nth-child(5) { width: 58px; }
.table--directory th:nth-child(6), .table--directory td:nth-child(6) { width: 100px; }
.table--directory th:nth-child(7), .table--directory td:nth-child(7) { width: 62px; }
.table--directory th:nth-child(8), .table--directory td:nth-child(8) { width: 98px; }
.table--directory th:nth-child(9), .table--directory td:nth-child(9) { width: 76px; }

/* The name may wrap to two lines; the sub-line never does. */
.table--directory td:nth-child(2) { white-space: normal; }
.table--directory td:nth-child(2) strong { line-height: 1.35; }
.table--directory .cell-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.table--directory td:nth-child(3) { white-space: normal; line-height: 1.3; }
.table--directory th:nth-child(5) { white-space: normal; line-height: 1.2; }

/* "held" is a marker, not prose — it must not wrap under its count. */
.sig-held {
  display: inline-block; margin-left: 3px;
  font-size: var(--fs-2xs); color: var(--warning-700);
  vertical-align: baseline;
}

/* Below 1280 the per-axis mini is the first thing to go — the number
   and its band matter more than the breakdown at that width. */
@media (max-width: 1279px) {
  .table--directory .score-mini { display: none; }
  .table--directory th:nth-child(6), .table--directory td:nth-child(6) { width: 72px; }
}
.table-dense td, .table-dense th { padding: var(--sp-2) var(--sp-3); }
.table-selectable tr[aria-selected="true"] { background: var(--primary-50); }
.table .cell-sub { display: block; font-size: var(--fs-xs); color: var(--text-3); }

.checkbox {
  width: 16px; height: 16px; flex-shrink: 0;
  accent-color: var(--primary-600); cursor: pointer;
}
.input-sm { min-height: var(--control-h-sm); padding: 4px var(--sp-2-5); font-size: var(--fs-control); }

/* ============================================================
   8. RESEARCH GRID  (the Clay surface)

   table-layout:fixed + <colgroup> means a column resize is a single
   <col> width mutation with no cell reflow. Freezing is position:
   sticky in three z-layers — header 2, frozen column 1, and their
   intersection 3, or the corner cell scrolls under its own header.
   ============================================================ */

.egrid-wrap {
  position: relative;
  overflow: auto;
  max-height: 68vh;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--card);
}
.egrid { table-layout: fixed; border-collapse: separate; border-spacing: 0; font-size: var(--fs-control); }

.egrid th, .egrid td {
  height: var(--egrid-row-h);
  padding: 0 var(--sp-2-5);
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border);
  text-align: left;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  background: var(--card);
}
.egrid thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--inset);
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-3);
  vertical-align: middle;
  /* The header now carries a third line — what one run of the column
     could change. The rule above is nowrap with overflow:hidden, which
     would clip it outright. Height on a table cell is a MINIMUM, so
     relaxing white-space here lets the header grow instead. The name
     keeps its own nowrap below, or its ellipsis stops firing. */
  white-space: normal;
  padding-top: var(--sp-2); padding-bottom: var(--sp-2);
}
.egrid .is-frozen { position: sticky; left: 0; z-index: 1; }
.egrid .is-frozen-2 { position: sticky; z-index: 1; box-shadow: 1px 0 0 var(--border-strong); }
.egrid thead .is-frozen, .egrid thead .is-frozen-2 { z-index: 3; }
.egrid tbody tr:hover td { background: var(--card-subtle); }
.egrid tbody tr:hover .is-frozen, .egrid tbody tr:hover .is-frozen-2 { background: var(--card-subtle); }

.egrid-colhead { display: flex; align-items: center; gap: 6px; }
.egrid-colhead .col-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The column menu is now the route to the ladder, the question, the
   gate forecast AND the reason a role cannot run the column. A control
   that only exists on hover cannot be found on a touch screen and
   cannot teach anything, so it rests visible and quiet. */
.egrid-colmenu {
  border: 0; background: none; padding: 2px; cursor: pointer; color: var(--text-3);
  /* No opacity dimming. At 0.55 the effective colour was #A8A8AD on
     --inset = 2.12:1, under the 3:1 floor for a control — and this
     14px icon is the ONLY route to the gate forecast, the handoff
     button, and the aria-label that carries the forecast to a screen
     reader. --text-3 is already the quiet tone (4.72:1); quietness
     comes from the token, not from making it hard to see. */
  border-radius: var(--radius-sm);
  transition: color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.egrid-colmenu:hover { background: var(--neutral-300); color: var(--ink); }

/* What one run of this column could change.
   The top border is a SEPARATOR, not a carrier. It was documented as
   encoding epistemic status (dashed = a ceiling, solid = an exact
   zero), but --border-strong on --inset is 1.23:1 — a 1px dash pattern
   nobody can resolve. The distinction is carried in full by the text
   ("up to 3 could clear the gate" vs "none can clear the gate") and by
   the colour swap to --text-3. Claiming a carrier the pixels cannot
   deliver is the same failure the funnel legend was fixed for. */
.col-unblock {
  display: block;
  margin-top: var(--sp-1);
  padding-top: var(--sp-1);
  border-top: 1px dashed var(--border-strong);
  font-size: var(--fs-2xs);
  font-weight: 500;
  line-height: 1.3;
  white-space: normal;
  text-transform: none;
  letter-spacing: 0;
  color: var(--primary-700);
  font-variant-numeric: tabular-nums;
  transition: background var(--dur-cell) var(--ease-out);
}
.col-unblock--none { border-top-style: solid; color: var(--text-3); }
.col-unblock.is-changed { background: var(--primary-100); }

/* The same reasoning at full length, in the column menu and in the
   peek for a cell nobody has asked yet. */
.col-forecast {
  border-top: 1px solid var(--border);
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
}
.col-forecast h5 { margin: 0 0 var(--sp-2); font-size: var(--fs-xs); color: var(--text-2); }
.col-forecast p { margin: 0 0 var(--sp-2); }
.col-forecast ul { margin: 0 0 var(--sp-2); padding-left: var(--sp-4); }

/* The ladder chain in the header. After a run each rung shows its
   REALISED hit rate — the rungs earning visibly different numbers is
   what proves the waterfall is a mechanism, not decoration. */
.ladder-chain {
  display: flex; align-items: center; gap: 3px;
  font-size: var(--fs-2xs); font-weight: 500; color: var(--text-3);
  text-transform: none; letter-spacing: 0;
}
.ladder-rung { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.ladder-rung::after { content: "→"; color: var(--neutral-400); margin-left: 3px; }
.ladder-rung:last-child::after { content: ""; }
.ladder-hit { color: var(--primary-700); font-variant-numeric: tabular-nums; }

.col-resize {
  position: absolute; top: 0; right: -3px; width: 6px; height: 100%;
  cursor: col-resize; z-index: 4;
}
.egrid th { position: relative; }

/* ---- Cell states ----
   `empty` and `notfound` MUST look different. Conflating "we never
   asked" with "we asked every source and none of them knew" is the
   single most common way a table like this lies. */
.ecell { position: relative; }

.ecell--empty { color: transparent; }
.ecell--empty::after {
  content: "·"; position: absolute; left: var(--sp-2-5); top: 50%;
  transform: translateY(-50%); color: var(--neutral-300); font-size: 16px;
}
.ecell--empty:hover { cursor: pointer; background: var(--primary-50); }

/* A role that cannot fill the grid still reads every cell, and the
   cell still opens and still explains itself. What goes is the
   --primary-50 wash, which is this console's "you can act here" tint
   and here promised a run that would not happen. Not `not-allowed`:
   that is reserved for controls which are dead, and this one is not. */
.egrid-wrap.is-readonly .ecell--empty:hover {
  cursor: default;
  background: var(--card-subtle);
}

.ecell--queued::after {
  content: ""; position: absolute; left: var(--sp-2-5); top: 50%;
  transform: translateY(-50%);
  width: 6px; height: 6px; border-radius: var(--radius-full);
  background: var(--neutral-300);
}
.ecell--running { padding: 0 var(--sp-2-5); }
.ecell--running .skeleton { height: 10px; width: 70%; border-radius: 3px; }
.ecell-stage {
  display: block; font-size: 9px; line-height: 1.2;
  color: var(--text-3); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis;
}

.ecell--notfound { color: var(--text-3); }
.ecell--failed { color: var(--danger-700); }
.ecell--failed::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: var(--evidence-rule); background: var(--danger-500);
}

/* A low-confidence answer wears the SAME dotted underline an unproven
   claim wears in the composer. That shared treatment is what welds
   the two surfaces into one idea: this is not evidence yet. */
.ecell--low .ecell-val {
  border-bottom: 1px dotted var(--warning-600);
  padding-bottom: 1px;
}
.ecell--low::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: var(--evidence-rule); background: var(--warning-500);
}
.ecell--manual::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: var(--evidence-rule); background: var(--success-500);
}

/* Stale: the value is still readable, and its age is visible. We do
   not clear prior work. */
.ecell--stale .ecell-val { opacity: 0.62; }
.ecell--stale::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(45deg,
    transparent 0 5px, var(--chart-hairline) 5px 6px);
}

.ecell-val { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; }

/* Provenance pip — which rung answered. Solid = tier 1, half = tier 2,
   hollow = the weakest source that had anything at all. */
.wf-pip {
  position: absolute; top: 5px; right: 5px;
  width: 5px; height: 5px; border-radius: var(--radius-full);
  border: 1px solid var(--primary-600);
}
.wf-pip--1 { background: var(--primary-600); }
.wf-pip--2 { background: var(--primary-300); }
.wf-pip--3 { background: transparent; }
.wf-pip--ai { border-color: var(--violet-700); background: var(--violet-100); }

.ecell-land { animation: cell-land var(--dur-cell) var(--ease-out); }
@keyframes cell-land {
  from { background: var(--primary-100); }
  to   { background: var(--card); }
}

/* ---- Run bar ---- */
.run-bar {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  padding: var(--sp-2-5) var(--sp-4);
  border: 1px solid var(--primary-200);
  border-radius: var(--radius-md);
  background: var(--primary-50);
  margin-bottom: var(--sp-3);
  font-size: var(--fs-control);
}
.run-bar .meter { flex: 1 1 180px; min-width: 120px; }
.run-status { color: var(--primary-700); font-weight: 500; }
.run-count { font-variant-numeric: tabular-nums; color: var(--ink); font-weight: 600; }
.run-bar--done { border-color: var(--success-500); background: var(--success-50); }
.run-bar--done .run-status { color: var(--success-700); }
.run-bar--warn { border-color: var(--warning-500); background: var(--warning-50); }
.run-bar--warn .run-status { color: var(--warning-700); }

/* The GOAL outcome, beside the mechanical count. "7 cells filled" is
   what the machine did; "3 clinics can now be contacted" is what
   changed. Zero is deliberately NOT styled as a failure — a run that
   cleared nobody is the most useful thing this bar ever says, and an
   alarm colour would train people to look away from exactly the case
   they need to read. */
.run-outcome { font-weight: 600; color: var(--success-700); }
.run-outcome::before {
  content: "·"; margin-right: var(--sp-2);
  color: var(--text-3); font-weight: 400;
}
.run-outcome--zero { font-weight: 500; color: var(--text-2); }

/* ---- Handoff: who can run a column, and asking them ----
   The one surface where a role sees work it cannot do. The gate names
   the person; the strip is the same record read from the other side. */
.grid-handoff:empty { display: none; }
/* .gate-explain carries only a top margin, and the grid sits directly
   under this block with nothing of its own to pay the gap. */
.grid-handoff .gate-explain { margin-bottom: var(--sp-3); }
.ask-list { list-style: none; margin: 0 0 var(--sp-3); padding: 0; display: grid; gap: var(--sp-2); }
.ask-row {
  display: grid; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--primary-200);
  border-left-width: 3px;
  border-radius: var(--radius-md);
  background: var(--primary-50);
  font-size: var(--fs-control);
}
.ask-row--done   { border-color: var(--success-500); background: var(--success-50); }
.ask-row--closed { border-color: var(--border-strong); background: var(--inset); }
.ask-who  { color: var(--ink); font-weight: 500; }
.ask-meta { color: var(--text-2); }
.ask-note {
  margin: 0; color: var(--text-2);
  border-left: 2px solid var(--primary-300); padding-left: var(--sp-2-5);
}
.ask-actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

/* Inside the amber gate block, where the same two lines set up the ask. */
.gate-explain .ask-who,
.gate-explain .ask-scope { margin: var(--sp-2) 0 0; font-weight: 400; }

/* A never-asked cell in the peek wears the SAME neutral dot the grid
   cell wears, and never the failed treatment. "Nobody asked" and "we
   asked and nobody knew" stay two facts on both surfaces. */
.research-answer--empty { background: var(--inset); color: var(--text-3); }
.research-answer--empty::before {
  content: "·"; color: var(--neutral-400); margin-right: var(--sp-2);
}

/* ---- Provenance popover body ---- */
.provenance { min-width: 260px; }
.provenance h4 { margin: 0 0 var(--sp-2); }
.prov-attempts { list-style: none; margin: var(--sp-2) 0 0; padding: 0; }
.prov-attempt {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 4px 0; font-size: var(--fs-xs); color: var(--text-2);
  border-top: 1px solid var(--border);
}
.prov-attempt:first-child { border-top: 0; }
.prov-outcome { margin-left: auto; font-variant-numeric: tabular-nums; }
.prov-hit  { color: var(--success-700); font-weight: 600; }
.prov-miss { color: var(--text-3); }
.prov-err  { color: var(--danger-700); }

/* ---- The AI research transcript ---- */
.research-stages { list-style: none; margin: 0 0 var(--sp-4); padding: 0; }
.research-stage {
  display: flex; align-items: center; gap: var(--sp-2-5);
  padding: var(--sp-2) 0; font-size: var(--fs-control); color: var(--text-3);
  border-bottom: 1px solid var(--border);
}
.research-stage:last-child { border-bottom: 0; }
.research-stage.is-done { color: var(--text); }
.research-stage.is-active { color: var(--primary-700); }
.research-tick { width: 16px; flex-shrink: 0; color: var(--success-600); }
.research-answer {
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface-cool);
  border-radius: var(--radius-md);
  font-size: var(--fs-base); line-height: 1.6;
}
.research-answer--low { background: var(--warning-50); }
.research-answer--failed { background: var(--inset); color: var(--text-2); }

/* ============================================================
   9. SEQUENCE BUILDER
   ============================================================ */

.seq-flow { position: relative; padding-left: var(--sp-6); }
.seq-flow::before {
  content: ""; position: absolute; left: 11px; top: 12px; bottom: 12px;
  width: 2px; background: var(--border);
}
.seq-node { position: relative; margin-bottom: var(--sp-2); }
.seq-node::before {
  content: ""; position: absolute; left: calc(var(--sp-6) * -1 + 6px); top: 22px;
  width: 12px; height: 12px; border-radius: var(--radius-full);
  background: var(--card); border: 2px solid var(--primary-600);
}
.seq-step { padding: var(--sp-4); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--card); }
.seq-step-head { display: flex; align-items: center; gap: var(--sp-2-5); margin-bottom: var(--sp-3); }
.seq-kind {
  font-family: var(--font-display); font-size: var(--fs-control);
  font-weight: 500; color: var(--ink);
}
.seq-step-actions { margin-left: auto; display: flex; gap: 4px; }

.seq-variant {
  display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; align-items: center;
  gap: var(--sp-2-5); padding: var(--sp-2) 0;
  border-top: 1px solid var(--border); font-size: var(--fs-control);
}
.seq-variant:first-of-type { border-top: 0; }
.seq-variant-tag {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: var(--radius-sm);
  background: var(--inset); color: var(--text-2);
  font-family: var(--font-mono); font-size: var(--fs-2xs); font-weight: 600;
}
.seq-variant--winner .seq-variant-tag { background: var(--success-100); color: var(--success-700); }
/* The middle cell must be a block with min-width:0, or the nowrap
   subject line has nothing to be clipped against and text-overflow
   never fires — it just pushes the row wider instead. */
.seq-variant-main { display: block; min-width: 0; overflow: hidden; }
.seq-variant-subject {
  display: block; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ink);
}
.seq-variant-stats { display: flex; gap: var(--sp-3); font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }

.seq-weight { display: flex; align-items: center; gap: var(--sp-2); }
.seq-weight input[type="range"] { width: 96px; accent-color: var(--primary-600); }
.seq-weight-val { font-variant-numeric: tabular-nums; font-size: var(--fs-xs); color: var(--text-2); min-width: 34px; text-align: right; }
.seq-weight--locked { opacity: 0.7; }

/* The delay connector — editing it recomputes every downstream
   projected send date, which is what makes this a builder rather
   than a diagram. */
.seq-delay {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  margin: var(--sp-2) 0;
  font-size: var(--fs-control); color: var(--text-2);
}
.seq-delay input[type="number"] { width: 58px; }
.seq-delay .select { width: auto; min-width: 92px; }
.proj-date { margin-left: auto; font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }

.seq-add { display: flex; justify-content: center; padding: var(--sp-2) 0; }

.seq-card-stats {
  display: flex; gap: var(--sp-5); flex-wrap: wrap;
  padding-top: var(--sp-3); margin-top: var(--sp-3);
  border-top: 1px solid var(--border);
  font-size: var(--fs-xs); color: var(--text-3);
}
.seq-card-stats b { display: block; font-size: var(--fs-md); color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }

/* ============================================================
   10. INBOX ROSTER / SENDING HEALTH
   ============================================================ */

.mbx-row {
  display: grid;
  grid-template-columns: 30px minmax(180px, 1.6fr) 110px 120px repeat(3, 74px) 96px;
  align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-control);
}
.mbx-row:last-child { border-bottom: 0; }
.mbx-row--risk { background: var(--danger-50); }
.mbx-head { font-size: var(--fs-xs); font-weight: 600; color: var(--text-3); background: var(--inset); }
.mbx-address { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mbx-address b { display: block; color: var(--ink); font-weight: 600; }
.mbx-address span { font-size: var(--fs-xs); color: var(--text-3); }
.mbx-num { font-variant-numeric: tabular-nums; text-align: right; }
.mbx-cap { display: flex; flex-direction: column; gap: 4px; }
.mbx-cap-label { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }

/* ---- Rotation ribbon ----
   Renders the RULE, not just the list. Held-out inboxes are greyed
   with the reason stated, and the winner is captioned in plain words. */
.rot-ribbon { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: var(--sp-4); }
.rot-chip {
  flex: 1 1 168px; min-width: 148px;
  padding: var(--sp-3);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--card);
  transition: border-color var(--dur-mid) var(--ease-out), box-shadow var(--dur-mid) var(--ease-out);
}
.rot-chip--next { border-color: var(--primary-600); box-shadow: var(--ring-soft); }
.rot-chip--out { background: var(--inset); opacity: 0.78; }
.rot-chip-addr { font-size: var(--fs-xs); color: var(--ink); font-weight: 600; word-break: break-all; }
.rot-chip-load { margin: var(--sp-2) 0 4px; }
.rot-chip-why { font-size: var(--fs-2xs); color: var(--danger-700); }
.rot-chip-pos { font-size: var(--fs-2xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.rot-caption {
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface-cool);
  border-radius: var(--radius-md);
  font-size: var(--fs-control); line-height: 1.6; color: var(--ink);
}
.rot-caption code { font-family: var(--font-mono); font-size: var(--fs-xs); }

.dns-check { list-style: none; margin: 0; padding: 0; }
.dns-check li {
  display: flex; align-items: center; gap: var(--sp-2-5);
  padding: var(--sp-2) 0; border-bottom: 1px solid var(--border);
  font-size: var(--fs-control);
}
.dns-check li:last-child { border-bottom: 0; }
.dns-mark { flex-shrink: 0; }
.dns-ok   { color: var(--success-600); }
.dns-warn { color: var(--warning-600); }
.dns-bad  { color: var(--danger-600); }
.dns-note { margin-left: auto; font-size: var(--fs-xs); color: var(--text-3); text-align: right; }

@media (max-width: 1199px) {
  .mbx-row { grid-template-columns: 30px minmax(0, 1fr) 110px 96px; }
  .mbx-row > :nth-child(n+5) { display: none; }
  .mbx-row .mbx-state { display: block; }
}

/* ============================================================
   11. UNIBOX  (Replies)
   ============================================================ */

.unibox {
  display: grid;
  grid-template-columns: var(--unibox-rail-w) var(--unibox-list-w) minmax(0, 1fr);
  gap: var(--sp-4);
  align-items: start;
  min-height: 60vh;
}
.thread-rail { position: sticky; top: var(--sp-4); }
.thread-list {
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--card); overflow: hidden;
  max-height: 72vh; overflow-y: auto;
}
.thread-row {
  display: block; width: 100%; text-align: left;
  padding: var(--sp-3) var(--sp-4);
  border: 0; border-bottom: 1px solid var(--border);
  background: var(--card); cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out);
}
.thread-row:hover { background: var(--card-subtle); }
.thread-row[aria-current="true"] { background: var(--primary-50); }
.thread-row-top { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: 3px; }
.thread-name { font-weight: 600; color: var(--ink); font-size: var(--fs-control); }
.thread-age { margin-left: auto; font-size: var(--fs-2xs); color: var(--text-3); white-space: nowrap; }
.thread-clinic { font-size: var(--fs-xs); color: var(--text-2); }
.thread-snippet {
  margin-top: 4px; font-size: var(--fs-xs); color: var(--text-3);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  line-clamp: 2; overflow: hidden;
}
.thread-dot {
  width: 7px; height: 7px; border-radius: var(--radius-full);
  background: var(--primary-600); flex-shrink: 0;
}

.msg-reader { min-width: 0; }
.msg-bubble {
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius-md);
  margin-bottom: var(--sp-3);
  font-size: var(--fs-base); line-height: 1.65;
  white-space: pre-wrap;
}
.msg--out { background: var(--surface-cool); margin-right: var(--sp-8); }
.msg--in  { background: var(--inset); margin-left: var(--sp-8); }
.msg-meta {
  display: flex; gap: var(--sp-2); align-items: center;
  margin-bottom: var(--sp-2); font-size: var(--fs-xs); color: var(--text-3);
}
.reply-box { margin-top: var(--sp-4); }

@media (max-width: 1439px) {
  .unibox { grid-template-columns: var(--unibox-list-w) minmax(0, 1fr); }
  .thread-rail { grid-column: 1 / -1; position: static; }
}
@media (max-width: 899px) {
  .unibox { grid-template-columns: 1fr; }
  /* Push navigation: the list hides once a thread is open, so the
     reader gets the whole width rather than a 40% column. */
  .unibox.is-reading .thread-list { display: none; }
  .unibox:not(.is-reading) .msg-reader { display: none; }
  .msg--out { margin-right: 0; }
  .msg--in  { margin-left: 0; }
}

/* ============================================================
   12. COMPOSER + CITATIONS  (Message Review)

   The most important CSS in this file. A claim that cannot be proved
   is visually distinct from one that can, everywhere, always.
   ============================================================ */

.msg-split { display: grid; grid-template-columns: var(--draft-list-w) minmax(0, 1fr); gap: var(--sp-4); align-items: start; }

.draft-row {
  display: block; width: 100%; text-align: left;
  padding: var(--sp-3) var(--sp-4);
  border: 0; border-bottom: 1px solid var(--border);
  background: var(--card); cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out);
}
.draft-row:hover { background: var(--card-subtle); }
.draft-row[aria-current="true"] { background: var(--primary-50); }
/* These are <span>s inside a <button> (a button may not contain block
   elements), so they need display:block or every line runs together. */
.draft-row-clinic {
  display: block;
  font-weight: 600; color: var(--ink); font-size: var(--fs-control);
  padding-right: var(--sp-6);   /* clears the floated checkbox */
}
.draft-row-meta { display: block; font-size: var(--fs-xs); color: var(--text-3); margin-top: 2px; }
.thread-row .thread-clinic, .thread-row .thread-snippet { display: block; }

/* Three lights: evidence · claims · voice. The queue is scannable
   for "what is blocked" without opening anything. */
.gate-strip { display: flex; gap: var(--sp-2); align-items: center; margin-top: var(--sp-2); }
.gate-dot {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-2xs); color: var(--text-3);
}
.gate-dot::before {
  content: ""; width: 6px; height: 6px; border-radius: var(--radius-full);
  background: var(--neutral-400);
}
.gate-dot--ok::before   { background: var(--success-500); }
.gate-dot--bad::before  { background: var(--danger-500); }
.gate-dot--warn::before { background: var(--warning-500); }

.mail {
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--card); overflow: hidden;
}
.mail-head { padding: var(--sp-4); border-bottom: 1px solid var(--border); background: var(--card-subtle); }
.mail-kv { display: grid; grid-template-columns: 68px minmax(0, 1fr); gap: 4px var(--sp-3); font-size: var(--fs-control); }
.mail-kv dt { color: var(--text-3); }
.mail-kv dd { margin: 0; color: var(--ink); }
.mail-subject {
  width: 100%; margin-top: var(--sp-3);
  font-family: var(--font-display); font-size: var(--fs-md); font-weight: 500;
}
.mail-body {
  padding: var(--sp-5);
  font-size: var(--fs-base); line-height: 1.72; color: var(--text);
  white-space: pre-wrap;
}
.mail-body p { margin: 0 0 var(--sp-3); }
.mail-body p:last-child { margin-bottom: 0; }

/* A proven claim carries a citation chip. */
.claim { background: var(--primary-50); border-radius: 3px; padding: 0 2px; }
.cite {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 15px; height: 15px; margin-left: 2px; padding: 0 3px;
  vertical-align: super;
  border: 0; border-radius: 3px;
  background: var(--primary-600); color: var(--text-invert);
  font-family: var(--font-mono); font-size: 9px; font-weight: 600;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out);
}
.cite:hover { background: var(--primary-700); }
.cite:focus-visible { outline: 2px solid var(--primary-600); outline-offset: 2px; }

/* An UNPROVEN claim. The same dotted underline the research grid uses
   for a low-confidence cell — one treatment, one meaning, two
   surfaces: this is not evidence. */
.unsourced {
  border-bottom: 1px dotted var(--warning-600);
  background: var(--warning-50);
  border-radius: 3px; padding: 0 2px;
}

/* A banned word. Wavy, not dotted — a different problem needs a
   different mark or the two blur together. */
.voice-flag {
  text-decoration: underline wavy var(--danger-500);
  text-underline-offset: 3px;
  background: var(--danger-50);
  border-radius: 3px; padding: 0 2px;
}

.ledger { border-top: 1px solid var(--border); padding: var(--sp-4); background: var(--card-subtle); }
.ledger-count {
  display: flex; align-items: center; gap: var(--sp-2);
  font-family: var(--font-display); font-size: var(--fs-md); font-weight: 700;
  letter-spacing: -0.015em; color: var(--ink); margin-bottom: var(--sp-3);
}
.ledger-count.is-clean { color: var(--success-700); }
.ledger-row {
  display: flex; align-items: flex-start; gap: var(--sp-2-5);
  padding: var(--sp-2-5) 0; border-top: 1px solid var(--border);
  font-size: var(--fs-control);
}
.ledger-row:first-of-type { border-top: 0; }
.ledger-mark { flex-shrink: 0; margin-top: 2px; }
.ledger-mark--ok  { color: var(--success-600); }
.ledger-mark--bad { color: var(--warning-600); }
.ledger-text { flex: 1; min-width: 0; color: var(--text-2); line-height: 1.55; }
.ledger-text .cell-sub { display: block; margin-top: 2px; }
.ledger-actions { display: flex; gap: 4px; flex-shrink: 0; }

.mail-actions {
  display: flex; align-items: center; gap: var(--sp-2-5); flex-wrap: wrap;
  padding: var(--sp-4); border-top: 1px solid var(--border);
}

.voice-word-list { display: flex; flex-wrap: wrap; gap: 6px; }
.voice-word {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px var(--sp-2-5); border-radius: var(--radius-full);
  background: var(--danger-50); color: var(--danger-700);
  font-size: var(--fs-xs); font-weight: 500;
}
.voice-word button { border: 0; background: none; padding: 0; cursor: pointer; color: inherit; line-height: 1; }
.voice-example { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); margin-top: var(--sp-2); }
.voice-good, .voice-bad { padding: var(--sp-2-5) var(--sp-3); border-radius: var(--radius-sm); font-size: var(--fs-sm); line-height: 1.5; }
.voice-good { background: var(--success-50); color: var(--success-700); }
.voice-bad  { background: var(--danger-50);  color: var(--danger-700); }

@media (max-width: 1099px) {
  .msg-split { grid-template-columns: 1fr; }
  .voice-example { grid-template-columns: 1fr; }
}

/* ============================================================
   13. PIPELINE BOARD
   ============================================================ */

.board { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(212px, 1fr); gap: var(--sp-3); overflow-x: auto; padding-bottom: var(--sp-3); }
.board-col { background: var(--inset); border-radius: var(--radius-md); padding: var(--sp-2-5); min-height: 220px; }
.board-head { display: flex; align-items: baseline; gap: var(--sp-2); padding: var(--sp-2) var(--sp-2) var(--sp-3); }
.board-head h3 { margin: 0; font-size: var(--fs-control); font-weight: 600; }
.board-head .board-n { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--text-3); font-size: var(--fs-xs); }
.board-card {
  display: block; width: 100%; text-align: left;
  padding: var(--sp-3); margin-bottom: var(--sp-2);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--card); cursor: pointer;
  transition: border-color var(--dur-mid) var(--ease-out), box-shadow var(--dur-mid) var(--ease-out), transform var(--dur-mid) var(--ease-out);
}
.board-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-lift); transform: translateY(-2px); }
.board-card-name { font-weight: 600; font-size: var(--fs-control); color: var(--ink); }
.board-card-meta { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2); font-size: var(--fs-xs); color: var(--text-3); }
.stage-age { margin-left: auto; font-variant-numeric: tabular-nums; }

/* ============================================================
   14. TERRITORIES / MISC
   ============================================================ */

.terr-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: var(--sp-4); }
.terr-card { padding: var(--card-pad); border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--card); }
.terr-head { display: flex; align-items: baseline; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.terr-head h3 { margin: 0; font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 700; letter-spacing: -0.02em; }
.terr-target { margin-left: auto; font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.terr-nums { display: flex; gap: var(--sp-5); margin: var(--sp-3) 0; }
.terr-num b { display: block; font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.03em; color: var(--ink); font-variant-numeric: tabular-nums; }
.terr-num span { font-size: var(--fs-xs); color: var(--text-3); }

.mini-funnel { display: flex; gap: 2px; height: 6px; margin-top: var(--sp-3); }
.mini-funnel i { display: block; border-radius: 1px; }

/* Key/value list — clinic facts, inbox facts, campaign facts. */
.kv { display: grid; grid-template-columns: minmax(96px, 132px) minmax(0, 1fr); gap: var(--sp-2) var(--sp-4); font-size: var(--fs-control); margin: 0; }
.kv dt { color: var(--text-3); }
.kv dd { margin: 0; color: var(--ink); }

/* Session rows on Site Signals */
.visit-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-3); padding: var(--sp-3) 0; border-bottom: 1px solid var(--border); }
.visit-row:last-child { border-bottom: 0; }
.conf-bar { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); color: var(--text-3); }
.conf-bar .meter { width: 62px; }
.match-basis { list-style: none; margin: var(--sp-2) 0 0; padding: 0; font-size: var(--fs-xs); color: var(--text-3); }
.match-basis li { padding: 1px 0; }
.match-basis li::before { content: "· "; }
.path-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px var(--sp-2); margin: 2px 4px 2px 0;
  border-radius: var(--radius-sm);
  background: var(--inset); color: var(--text-2);
  font-family: var(--font-mono); font-size: var(--fs-2xs);
}
.path-chip--hot { background: var(--primary-50); color: var(--primary-700); }

/* Conflicts — the strongest available proof that the two lead sources
   really do write to one record. */
.conflict {
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--warning-500); border-radius: var(--radius-md);
  background: var(--warning-50); margin-bottom: var(--sp-3);
}
.conflict-pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); margin: var(--sp-3) 0; }
.conflict-side { padding: var(--sp-2-5) var(--sp-3); background: var(--card); border-radius: var(--radius-sm); font-size: var(--fs-control); }
.conflict-side b { display: block; font-size: var(--fs-lg); font-family: var(--font-display); }
.conflict-side span { font-size: var(--fs-xs); color: var(--text-3); }

/* ============================================================
   15. OVERLAY ADDITIONS
   ============================================================ */

.modal--wide .modal { max-width: 820px; }
.peek-head { padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--card); z-index: 2; }
.peek-body { padding: var(--sp-5); }
.peek-foot { padding: var(--sp-4) var(--sp-5); border-top: 1px solid var(--border); position: sticky; bottom: 0; background: var(--card); }
.peek-nav { display: flex; align-items: center; gap: var(--sp-2); }
.peek-pos { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }

/* ============================================================
   16. GUIDED WALKTHROUGH
   ============================================================ */

.demo-bar {
  position: fixed; left: 50%; bottom: var(--sp-5);
  transform: translateX(-50%);
  z-index: 90;
  width: min(660px, calc(100vw - var(--overlay-inset)));
  display: flex; align-items: flex-start; gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  background: var(--surface-inverse); color: var(--text-invert);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-4);
  animation: demo-in var(--dur-slow) var(--ease-sheet) both;
}
@keyframes demo-in { from { opacity: 0; transform: translate(-50%, 12px); } }
.demo-n {
  flex-shrink: 0; width: 26px; height: 26px; border-radius: var(--radius-full);
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, 0.14);
  font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 600;
}
.demo-t { font-family: var(--font-display); font-weight: 700; letter-spacing: -0.015em; margin-bottom: 3px; }
.demo-b { font-size: var(--fs-control); line-height: 1.55; color: rgba(255, 255, 255, 0.82); }
.demo-actions { margin-left: auto; display: flex; gap: var(--sp-2); flex-shrink: 0; align-self: center; }
.demo-bar .btn-ghost { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.2); color: var(--text-invert); }
.demo-bar .btn-ghost:hover { background: rgba(255, 255, 255, 0.2); }
body.demo-on .content { padding-bottom: 132px; }

/* Four-rect cutout — reads far better over a dense table than a
   box-shadow ring, which gets lost against striped rows. */
.demo-cut { position: fixed; background: rgba(23, 23, 23, 0.52); z-index: 88; pointer-events: none; }
.demo-ring {
  position: fixed; z-index: 89; pointer-events: none;
  border: 2px solid var(--primary-400);
  border-radius: var(--radius-md);
  box-shadow: 0 0 0 4px rgba(21, 101, 216, 0.24);
}

@media (max-width: 899px) {
  .demo-bar { bottom: calc(var(--bottom-tabs-h) + var(--sp-3)); flex-wrap: wrap; }
  .demo-actions { margin-left: 0; width: 100%; }
  body.demo-on .content { padding-bottom: 190px; }
}

/* ============================================================
   17. REGION ROWS (Growth Pulse)
   ============================================================ */

.pulse-region {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr) 76px 96px auto;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border);
}
.pulse-region:last-child { border-bottom: 0; }
.pr-num, .pr-cov { text-align: right; }

/* ============================================================
   18. RESPONSIVE FLOORS

   Wide content scrolls INSIDE its own container. The page body never
   scrolls horizontally at any width — that rule is verified, not
   assumed.
   ============================================================ */

/* min-width:0 is the load-bearing part: a grid or flex child defaults
   to min-content, so a 1300px-wide table refuses to let its scroll
   container shrink and pushes the whole page sideways instead. */
.chart-wrap, .egrid-wrap, .board, .table-wrap, .thread-list, .mail {
  max-width: 100%;
  min-width: 0;
}
.egrid-wrap { width: 100%; }
.dir-layout > *, .msg-split > *, .unibox > * { min-width: 0; }

@media (max-width: 899px) {
  .egrid-wrap { max-height: 60vh; }
  .board { grid-auto-columns: minmax(196px, 82vw); }
  .terr-grid { grid-template-columns: 1fr; }
  .conflict-pair { grid-template-columns: 1fr; }
  .hbar { grid-template-columns: minmax(0, 1fr) auto; }
  .hbar-track { grid-column: 1 / -1; }
  .fnl-row { grid-template-columns: minmax(0, 1fr) 52px 42px; row-gap: 4px; }
  .fnl-track { grid-column: 1 / -1; grid-row: 2; }
  .visit-row { grid-template-columns: 1fr; }
  .mbx-row { grid-template-columns: 30px minmax(0, 1fr) auto; }
}

@media (max-width: 640px) {
  /* Region rows: name over meter, numbers on one line beneath. */
  .pulse-region { grid-template-columns: minmax(0, 1fr) auto auto; row-gap: var(--sp-2); gap: var(--sp-3); }
  .pr-name { grid-column: 1 / -1; }
  .pr-meter { grid-column: 1 / -1; grid-row: 2; }
  .pr-num { grid-column: 1; text-align: left; }
  .pr-cov { grid-column: 2; }
  .pr-link { grid-column: 3; }

  /* Sequence variants: the subject needs the whole width; the weight
     slider drops beneath it rather than squeezing both. */
  .seq-variant { grid-template-columns: 28px minmax(0, 1fr); row-gap: var(--sp-2); }
  .seq-variant > :last-child { grid-column: 1 / -1; }
  .seq-weight input[type="range"] { width: 100%; }
  .seq-variant-stats { flex-wrap: wrap; gap: var(--sp-2); }
  .seq-flow { padding-left: var(--sp-5); }
  .seq-flow::before { left: 7px; }
  .seq-node::before { left: calc(var(--sp-5) * -1 + 3px); }

  .gate-strip { flex-wrap: wrap; }
  .chart-donut-wrap { gap: var(--sp-4); }
  .voice-example { grid-template-columns: 1fr; }
}

/* A segmented control is already a horizontal thing, so at narrow
   widths it scrolls sideways inside itself rather than wrapping into a
   ragged block or pushing the page over. The saved-view names in the
   research grid are long enough to need this. */
@media (max-width: 780px) {
  .seg {
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .seg::-webkit-scrollbar { display: none; }
  .seg-btn { flex: 0 0 auto; white-space: nowrap; }
  .row.row-between { min-width: 0; }
  .row.row-between > * { min-width: 0; }
}

/* The slider is inside a flex row; without min-width:0 it holds its
   intrinsic size and overflows instead of shrinking. */
.seq-weight { min-width: 0; max-width: 100%; }
.seq-weight input[type="range"] { min-width: 0; }
