/* Online Quality Inspector — dashboard stylesheet.
   Dash auto-loads anything in assets/. Palette mirrors the Python-side
   constants in app.py (FONT, INK, INK_MUTED, BORDER, SURFACE_2, BRAND,
   ACCENT, GOOD, DEFECT_MARK) so the HTML chrome and the Plotly figures
   read as one surface instead of two different apps stitched together. */

:root {
  --ink: #eaeef5;
  --ink-muted: #98a2b3;
  --ink-faint: #5b6474;
  --border: #272e3b;
  --surface-0: #0d1017;
  --surface-1: #151a24;
  --surface-2: #1e2430;
  --brand: #e4002b;
  --accent: #38bdf8;
  --good: #34d399;
  --warn: #f5a524;
  --defect: #ff5468;
  /* Phase 3A: the fourth AI Inspector status colour (ORANGE/PREVENTIVE) --
     distinct from --warn (amber/YELLOW/MONITOR, also reused for "marginal"
     capability ratings elsewhere) and --brand/--defect (RED/URGENT). */
  --preventive: #fb923c;
  --radius: 12px;
  --font: "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--surface-0);
  color: var(--ink);
  font-family: var(--font);
}

.app-shell {
  max-width: 1440px;
  margin: 0 auto;
  padding: 28px 24px 64px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* ---- Main content + AI Inspector sidebar (Phase 3A, D1) ---- */
.main-layout {
  display: flex;
  align-items: flex-start;
  gap: 20px;
}

.main-content {
  flex: 1;
  min-width: 0;   /* let charts/tables shrink instead of forcing sidebar off-screen */
}

.sidebar {
  flex: 0 0 340px;
  position: sticky;
  top: 20px;
  align-self: flex-start;
  /* Phase 22: no max-height/overflow-y here on purpose -- the sidebar
     renders at its full natural content height, with no scrollbar of its
     own. If that height exceeds the viewport, the PAGE scrolls past it
     (sticky positioning releases once .main-layout's bottom is reached),
     rather than trapping the viewer in an internally-clipped scroll pane. */
  display: flex;
  flex-direction: column;
  gap: 10px;
}

@media (max-width: 960px) {
  .main-layout { flex-direction: column; }
  .sidebar { position: static; flex: none; width: 100%; max-height: none; }
}

/* ---- App bar ---- */
.app-bar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border);
}

.brand-mark {
  width: 44px;
  height: 44px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: var(--brand);
  color: #fff;
  font-weight: 800;
  letter-spacing: 0.02em;
}

.app-bar h1 {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  color: var(--ink);
}

.app-bar .subtitle {
  margin: 4px 0 0;
  font-size: 13px;
  color: var(--ink-muted);
  max-width: 560px;
}

.brand-tag {
  margin-left: auto;
  font-size: 12px;
  color: var(--ink-muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 12px;
  white-space: nowrap;
}

.brand-tag b { color: var(--ink); }

/* ---- Persistent status strip (Phase 4, Part F) ----
   Always-on summary row for an unattended/wall-mounted screen: machine
   identity, current shift/time, feed health, DB connection, autonomy
   mode, drift. Every dynamic segment's text ALSO carries a leading
   shape glyph (●/▲/■/◆) alongside its colour, set in app.py's status-
   strip builder -- colour + text + shape together, never colour alone
   (Phase 4 acceptance item 2, verified in greyscale). */
.status-strip {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 10px;
  padding: 10px 4px;
  border-bottom: 1px solid var(--border);
  font-size: 12.5px;
}

.status-seg {
  display: flex;
  align-items: baseline;
  gap: 6px;
  color: var(--ink-muted);
  white-space: nowrap;
}

.status-seg b, .status-seg strong { color: var(--ink); font-weight: 600; }

.status-sep {
  width: 1px;
  height: 14px;
  background: var(--border);
  flex: none;
}

.status-good { color: var(--good); font-weight: 700; }
.status-warn { color: var(--warn); font-weight: 700; }
.status-risk { color: var(--defect); font-weight: 700; }
.status-muted { color: var(--ink-faint); font-weight: 700; }

/* ---- Controls ---- */
.control-row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.control-row .Select-control, .control-row [class*="-control"] {
  min-width: 220px;
}

button {
  font-family: var(--font);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 10px 18px;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}

button:hover { border-color: var(--accent); background: #202836; }

.live-pill {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--ink-muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 7px 14px;
}

.live-pill .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ink-faint);
}

.live-pill.is-live .dot {
  background: var(--good);
  box-shadow: 0 0 0 3px rgba(52, 211, 153, 0.18);
}

.live-pill.is-live { color: var(--ink); border-color: rgba(52, 211, 153, 0.35); }

/* FEED LIVE/STALE (Phase 1): the press feed's own liveness, from
   producer.py's heartbeat -- distinct from is-live above, which is just
   this one browser's auto-refresh toggle. */
.live-pill.is-stale .dot {
  background: var(--defect);
  box-shadow: 0 0 0 3px rgba(255, 84, 104, 0.18);
}

.live-pill.is-stale { color: var(--ink); border-color: rgba(255, 84, 104, 0.35); }

.control-note {
  flex-basis: 100%;
  font-size: 12px;
  color: var(--ink-faint);
  margin: -6px 0 0;
}

.model-info {
  font-size: 12px;
  color: var(--ink-muted);
}

/* ---- Warning banners (model drift, degraded DB connection) ---- */
.banner-warn {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 13px;
  color: var(--ink);
  background: rgba(245, 165, 36, 0.10);
  border: 1px solid rgba(245, 165, 36, 0.35);
  border-radius: var(--radius);
  padding: 12px 16px;
}

.banner-warn .banner-tag {
  flex: none;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--warn);
}

/* Phase 3B: persistent "not connected to a real press" notice, shown
   whenever RECOMMENDATION_MODE=auto_apply_simulated. A distinct blue
   (informational, not alarming) rather than --warn's amber -- being in
   simulation mode isn't itself a problem the way model drift is. */
.banner-sim {
  background: rgba(56, 189, 248, 0.10);
  border-color: rgba(56, 189, 248, 0.35);
}

.banner-sim .banner-tag { color: var(--accent); }

/* Phase 5, J1: persistent public-demo notice (DEPLOYMENT_MODE=demo).
   Green/--good rather than --warn's amber or --accent's blue -- this is
   plain informational context about the deployment, not a process status
   or a simulation-mode caveat. */
.banner-demo {
  background: rgba(52, 211, 153, 0.10);
  border-color: rgba(52, 211, 153, 0.35);
}

.banner-demo .banner-tag { color: var(--good); }

/* ---- KPI tiles ---- */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}

.kpi {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px;
  border-left: 3px solid var(--border);
}

.kpi-label {
  font-size: 12px;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.kpi-value {
  font-size: 34px;
  font-weight: 800;
  margin-top: 6px;
  color: var(--ink);
  letter-spacing: -0.01em;
}

/* Overview KPI row reads from a few feet away (Part F) -- a shade larger
   still than the standard .kpi-value, and .kpi-sub gets more weight so a
   unit/caption (e.g. "opportunities: 5/unit") stays legible at distance. */
.kpi-value-lg { font-size: 38px; }
.kpi-sub-strong { color: var(--ink-muted); font-weight: 600; }

.kpi-sub { font-size: 12px; color: var(--ink-faint); margin-top: 2px; }

.kpi-accent { border-left-color: var(--accent); }
.kpi-brand  { border-left-color: var(--brand); }
.kpi-warn   { border-left-color: var(--warn); }
.kpi-good   { border-left-color: var(--good); }

/* ---- Section headers ---- */
.section-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-top: 8px;
}

.section-title h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
}

.section-title span {
  font-size: 12.5px;
  color: var(--ink-muted);
}

/* ---- Cards ---- */
.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  /* Wide tables (Phase 4's 9-column parameter-status table, the shift
     mean/significance table) scroll inside their own card on a narrow
     screen instead of forcing the whole page to scroll horizontally. */
  overflow-x: auto;
}

/* Phase 5, J9: "About this demo" panel, Overview tab, demo mode only. */
.tab-panel-intro {
  margin-bottom: 20px;
}

.about-demo-body p {
  margin: 0 0 10px 0;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink);
}

.about-demo-body p:last-child {
  margin-bottom: 0;
}

.about-repo-placeholder {
  color: var(--ink-faint);
  font-style: italic;
}

.hist-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

@media (max-width: 860px) {
  .kpi-grid { grid-template-columns: repeat(2, 1fr); }
  .hist-grid { grid-template-columns: 1fr; }
}

/* ---- AI Inspector ---- */
.inspector-card { display: flex; flex-direction: column; gap: 16px; }

.insp-empty { color: var(--ink-muted); font-size: 13px; }

.insp-meta {
  font-size: 11.5px;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.insp-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.insp-readout { display: flex; flex-direction: column; gap: 2px; }

.insp-cap {
  font-size: 11px;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.insp-muted { color: var(--ink-faint); }

.insp-prob { font-size: 34px; font-weight: 800; color: var(--ink); line-height: 1.1; }

.insp-status {
  font-size: 12px;
  font-weight: 700;
  padding: 6px 14px;
  border-radius: 999px;
  white-space: nowrap;
}

.insp-ok, .insp-good { color: var(--good); background: rgba(52, 211, 153, 0.12); }
.insp-risk           { color: var(--defect); background: rgba(255, 84, 104, 0.14); }
.insp-warn           { color: var(--warn); background: rgba(245, 165, 36, 0.14); }
.insp-muted.insp-status { color: var(--ink-faint); background: rgba(148, 158, 179, 0.10); }

/* Current Press Parameters: a value moved off nominal by an applied
   recommendation -- informational (the system did this on purpose), so
   the accent color, not the warning color. */
.param-override { color: var(--accent); font-weight: 600; }

/* Phase 17, B3: red-before/green-after, shared by every plain-text
   before -> after pair (recommendation card, Recommendation History
   table, sidebar Recommendation Effectiveness panel). Colour is never
   the only cue -- app._before_after_spans() always positions "before"
   first/left and "after" second/right, so position and the arrow
   between them carry the same information as the colour. */
.before-after-before { color: var(--defect); font-weight: 600; }
.before-after-after  { color: var(--good); font-weight: 600; }

.insp-section { display: flex; flex-direction: column; gap: 8px; }

.insp-bars { display: flex; flex-direction: column; gap: 8px; }

.insp-bar {
  display: grid;
  grid-template-columns: 110px 1fr 44px;
  align-items: center;
  gap: 10px;
  font-size: 12.5px;
}

.insp-bar-label { color: var(--ink-muted); }

.insp-bar-track {
  height: 8px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}

.insp-bar-fill { height: 100%; background: var(--accent); border-radius: 999px; }

.insp-bar-top .insp-bar-fill { background: var(--brand); }
.insp-bar-top .insp-bar-label { color: var(--ink); font-weight: 600; }

.insp-bar-val { text-align: right; color: var(--ink-muted); }

.insp-drivers { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }

.insp-driver { display: flex; align-items: baseline; gap: 10px; font-size: 13px; }

.insp-chip {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 3px 8px;
  border-radius: 6px;
  flex: none;
}

.insp-chip-up   { color: var(--defect); background: rgba(255, 84, 104, 0.14); }
.insp-chip-down { color: var(--good); background: rgba(52, 211, 153, 0.12); }

.insp-driver-text { color: var(--ink-muted); }

.insp-rec {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--surface-2);
  border-radius: 9px;
  padding: 12px 14px;
}

/* ---- AI Inspector: evidence-gated process status (Phase 3A) ---- */
.gate-status-row { margin-top: 4px; }

.gate-status-pill {
  display: inline-block;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.03em;
  padding: 8px 16px;
  border-radius: 999px;
}

.gate-stable     { color: var(--good);       background: rgba(52, 211, 153, 0.14); }
.gate-monitor    { color: var(--warn);       background: rgba(245, 165, 36, 0.14); }
.gate-preventive { color: var(--preventive); background: rgba(251, 146, 60, 0.16); }
.gate-urgent     { color: var(--defect);     background: rgba(255, 84, 104, 0.16); }

.gate-score-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.gate-score-value { font-size: 20px; font-weight: 800; color: var(--ink); }

.gate-subscores { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }

.gate-subscore {
  display: grid;
  grid-template-columns: 108px 1fr 28px;
  align-items: center;
  gap: 10px;
  font-size: 11.5px;
}

.gate-subscore-label { color: var(--ink-muted); }

.gate-subscore-track {
  height: 6px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}

.gate-subscore-fill { height: 100%; background: var(--accent); border-radius: 999px; }

.gate-subscore-val { text-align: right; color: var(--ink-muted); }

.gate-rec-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 13.5px;
}

.gate-rec-param { font-weight: 700; color: var(--ink); }

.gate-rec-values { color: var(--preventive); font-weight: 600; }

.gate-rec-risk { font-size: 12.5px; color: var(--ink-muted); margin-top: 2px; }

.gate-criteria-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 12px;
}

.gate-criterion { padding-left: 18px; position: relative; color: var(--ink-muted); }

.gate-criterion::before {
  content: "—";
  position: absolute;
  left: 0;
  color: var(--ink-faint);
}

.gate-criterion-pass { color: var(--ink); }

.gate-criterion-pass::before { content: "✓"; color: var(--good); }

/* ---- Recommendation countdown card (Phase 3B, D4) ---- */
.rec-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  border-color: rgba(251, 146, 60, 0.35);
}

.rec-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}

.rec-card-param { font-size: 14px; font-weight: 700; color: var(--ink); }

.rec-card-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.rec-card-stat { display: flex; flex-direction: column; gap: 3px; }

.rec-card-stat-val { font-size: 13.5px; font-weight: 600; color: var(--ink); }

.rec-card-drivers {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.rec-card-drivers li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 12.5px;
}

.rec-driver-label { color: var(--ink); }
.rec-driver-val { color: var(--ink-muted); white-space: nowrap; }

.rec-countdown { display: flex; flex-direction: column; gap: 6px; }

.rec-countdown-text { margin: 0; font-size: 12.5px; color: var(--ink-muted); }

.rec-countdown-track {
  height: 8px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}

.rec-countdown-fill {
  height: 100%;
  width: 0%;
  background: var(--preventive);
  border-radius: 999px;
  transition: width 0.2s linear;
}

.rec-countdown-remaining {
  font-size: 11px;
  color: var(--ink-faint);
  text-align: right;
}

.rec-card-buttons { display: flex; gap: 8px; }

.rec-btn { flex: 1; padding: 9px 10px; font-size: 12.5px; }

.rec-btn-accept { border-color: rgba(52, 211, 153, 0.4); color: var(--good); }
.rec-btn-accept:hover { background: rgba(52, 211, 153, 0.12); border-color: var(--good); }

.rec-btn-reject { border-color: rgba(255, 84, 104, 0.4); color: var(--defect); }
.rec-btn-reject:hover { background: rgba(255, 84, 104, 0.12); border-color: var(--defect); }

.rec-btn-monitor { border-color: var(--border); color: var(--ink-muted); }
.rec-btn-monitor:hover { background: var(--surface-2); border-color: var(--ink-muted); }

/* ---- Process capability table ---- */
.cap-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.cap-table th, .cap-table td {
  text-align: left;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
}

.cap-table th {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-muted);
  font-weight: 600;
}

.cap-table td { color: var(--ink); }

.cap-table tr:last-child td { border-bottom: none; }

.cap-table .insp-status { padding: 4px 10px; }

/* ---- Tabs (Phase 2, Parts B/C) ---- */
.main-tabs {
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
  /* dash's own bundled tab-container stylesheet switches to
     flex-direction: column below its built-in breakpoint (a "mobile"
     accommodation that assumes its own default vertical-list tab
     styling, not this custom bottom-border-indicator one) -- discovered
     by testing an actual narrow viewport, not assumed. A vertical stack
     under OUR styling reads as broken (each tab full-width with a
     barely-visible underline), so this is pinned to a horizontal row at
     every width; flex-wrap is the safety net if three large touch
     targets ever don't fit on one line instead of silently overflowing
     the page. */
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: wrap;
}

.main-tab {
  background: transparent !important;
  border: none !important;
  border-bottom: 3px solid transparent !important;
  color: var(--ink-muted) !important;
  padding: 16px 10px !important;
  margin-right: 26px;
  font-family: var(--font);
  font-size: 15.5px;
  font-weight: 700;
  min-width: 44px;   /* touch-target floor (Part F: "large and touch-friendly") */
}

.main-tab--selected {
  color: var(--ink) !important;
  border-bottom: 3px solid var(--accent) !important;
  background: transparent !important;
}

.tab-panel {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding-top: 20px;
}

/* ---- Shift cards (Phase 2, Part C) ---- */
.shift-card-row {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 14px;
}

.shift-card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.shift-card-current {
  border-color: rgba(56, 189, 248, 0.4);
  background: linear-gradient(180deg, rgba(56, 189, 248, 0.08), var(--surface-1) 60%);
}

.shift-card-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
}

.shift-card-current-tag {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.shift-card-date {
  font-size: 12px;
  color: var(--ink-muted);
}

.shift-card-progress {
  font-size: 12.5px;
  color: var(--ink);
}

.shift-card-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 18px;
  margin-top: 4px;
}

.shift-card-num {
  display: block;
  font-size: 20px;
  font-weight: 700;
  color: var(--ink);
}

.shift-card-unit {
  display: block;
  font-size: 11px;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Phase 17, A1: a shift window with zero shots -- an explicit message
   instead of a 0/0/--/-- stats row that could be mistaken for a shift
   that genuinely just started. */
.shift-card-empty {
  font-size: 12.5px;
  line-height: 1.5;
  margin-top: 2px;
}

/* ---- Inline chart legends (Phase 2, Parts A3/B1) ---- */
.legend-swatch {
  display: inline-block;
  width: 18px;
  text-align: center;
  font-weight: 700;
}

.legend-shift { color: #f43f5e; }
.legend-defect { color: var(--defect); }

.legend-chip {
  display: inline-block;
  font-weight: 700;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11.5px;
}

.legend-chip-neutral { color: var(--accent); background: rgba(56, 189, 248, 0.14); }
.legend-chip-amber   { color: var(--warn); background: rgba(245, 165, 36, 0.14); }
.legend-chip-red     { color: var(--brand); background: rgba(228, 0, 43, 0.14); }

.candle-caption {
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-muted);
  background: var(--surface-2);
  border-radius: 9px;
  padding: 10px 14px;
  margin: 0;
}

@media (max-width: 860px) {
  .shift-card-row { grid-template-columns: 1fr; }
}

/* ============================================================
   Phase 4 — Overview tab, Six Sigma additions, multi-timeframe SPC
   (docs/prompts/04_PHASE4_ui_sixsigma.md)
   ============================================================ */

/* ---- Overview tab ---- */
.overview-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 14px;
}

@media (max-width: 1100px) {
  .overview-grid { grid-template-columns: 1fr; }
}

.shap-disclaimer {
  font-size: 11px;
  line-height: 1.5;
  color: var(--ink-faint);
  margin: 2px 0 0;
  font-style: italic;
}

/* ---- Process parameter status table (Part E) ---- */
.param-status-table .insp-status { padding: 4px 10px; white-space: nowrap; }

/* ---- Press warnings block (Part E) ---- */
.warn-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.warn-item {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 13px;
  padding: 10px 12px;
  border-radius: 9px;
  background: var(--surface-2);
  border-left: 3px solid var(--border);
}

.warn-item-risk { border-left-color: var(--defect); }
.warn-item-warn { border-left-color: var(--warn); }
.warn-item-preventive { border-left-color: var(--preventive); }

.warn-item-shape {
  flex: none;
  font-weight: 800;
  font-size: 14px;
}

.warn-item-body { display: flex; flex-direction: column; gap: 2px; }
.warn-item-title { color: var(--ink); font-weight: 600; }
.warn-item-detail { color: var(--ink-muted); font-size: 12px; }

.warn-empty {
  font-size: 13px;
  color: var(--good);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
}

/* ---- Control plan / reaction plan table (Part G item 5) ---- */
.control-plan-table td { vertical-align: top; }
.control-plan-table .cp-reaction { font-size: 12.5px; color: var(--ink-muted); line-height: 1.5; }

/* ---- Cpk trend section (Part G item 3) ---- */
.period-toggle {
  display: flex;
  gap: 8px;
}

.period-toggle button {
  padding: 7px 14px;
  font-size: 12.5px;
}

.period-toggle button.is-active {
  border-color: var(--accent);
  color: var(--ink);
  background: rgba(56, 189, 248, 0.12);
}

/* ---- Multi-timeframe SPC explorer (Part G2) ---- */
.spc-explorer-caption {
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-muted);
  background: var(--surface-2);
  border-radius: 9px;
  padding: 10px 14px;
  margin: 0;
}

.spc-explorer-caption b { color: var(--ink); }

.baseline-tag {
  display: inline-block;
  font-size: 11px;
  color: var(--accent);
  background: rgba(56, 189, 248, 0.12);
  border-radius: 999px;
  padding: 2px 10px;
  margin-left: 6px;
}

/* ============================================================
   Phase 4B -- Model Effectiveness tab
   (docs/prompts/04B_PHASE4B_model_effectiveness.md)
   ============================================================ */

/* ---- 6-tile KPI row (K2) -- overrides .kpi-grid's 4-column default,
   same "second class wins" pattern as everywhere else two grid classes
   combine on one element in this file. ---- */
.kpi-grid-6 { grid-template-columns: repeat(6, 1fr); }

@media (max-width: 1100px) { .kpi-grid-6 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 700px) { .kpi-grid-6 { grid-template-columns: repeat(2, 1fr); } }

/* ---- Model Status banner (K2) -- reuses .gate-status-pill's existing
   3-colour vocabulary (gate-stable/gate-monitor/gate-urgent), so
   "Effective/Needs Monitoring/Needs Improvement" reads with the SAME
   colour+shape language as the AI Inspector's STABLE/MONITOR/URGENT,
   not a second one a viewer has to learn. ---- */
.model-status-banner {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.model-status-reasons {
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12.5px;
  color: var(--ink-muted);
  flex-basis: 100%;
}

/* ---- Confusion matrix (K3) -- false negatives get a visual callout on
   top of the number, not just a cell in a grid. ---- */
.cm-table th { text-align: left; }
.cm-table td.cm-fn {
  background: rgba(255, 84, 104, 0.16);
  color: var(--defect);
  font-weight: 700;
}
/* Phase 17, B3: TP's green complement to FN's red callout above --
   correct catches highlighted the same way the worst-case miss is. */
.cm-table td.cm-tp {
  background: rgba(52, 211, 153, 0.14);
  color: var(--good);
  font-weight: 700;
}

/* ---- Data Access download rows (L4/L6) ---- */
.download-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.download-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  padding: 12px 14px;
  border-radius: 9px;
  background: var(--surface-2);
}

.download-meta {
  display: block;
  font-size: 12px;
  color: var(--ink-faint);
  margin-top: 2px;
}

.download-links {
  display: flex;
  gap: 8px;
  flex: none;
}

.download-btn {
  font-family: var(--font);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink);
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 8px 14px;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.download-btn:hover { border-color: var(--accent); background: #202836; }

.download-btn-secondary { color: var(--ink-muted); }

/* ============================================================
   Phase 20 -- Model Effectiveness tab: evaluator clarity
   (docs/prompts/20_PHASE20_model_effectiveness_evaluator_clarity.md)
   ============================================================ */

/* Part A: F1 hidden from the KPI grid (its own tile/callback output are
   unchanged, just not rendered) -- the grid drops from 6 to 5 visible
   tiles, same "second class wins" cascade pattern .kpi-grid-6 already
   used, mirroring its own breakpoints one column narrower. */
.kpi-grid-5 { grid-template-columns: repeat(5, 1fr); }
@media (max-width: 1100px) { .kpi-grid-5 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 700px) { .kpi-grid-5 { grid-template-columns: repeat(2, 1fr); } }

.me-kpi-hidden { display: none; }

/* Part C: the Threshold Analysis table's own deployed-threshold row --
   bold + a faint accent tint, so it reads clearly even without the
   "<- currently deployed" text label (colour is never the only cue, per
   this project's own standing principle -- the label stays either way). */
.threshold-row-deployed td {
  font-weight: 700;
  color: var(--ink);
  background: rgba(56, 189, 248, 0.08);
}

.threshold-sweep-heading { margin-top: 10px; }

/* Part E: the weekly-recall CI list -- plain text, not a table, since
   each line is already a complete sentence (recall + CI + defect count)
   rather than tabular columns. */
.threshold-ci-list {
  list-style: none;
  margin: 4px 0 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12.5px;
  color: var(--ink-muted);
}
