/* styles.css
 *
 * Dark cinematic aesthetic for the Experience Lab, per the product brief's
 * "operational equivalent of J.A.R.V.I.S." direction: near-black radial
 * gradient backdrop, glassmorphic panels, cyan/blue accent glow, and the
 * canonical risk color tokens (--green/--yellow/--orange/--red/--gray)
 * that both lenses (and Phase 3's panels) read from a single shared
 * vocabulary rather than each defining their own colors.
 *
 * Phase 2 extended this for the Universe lens's cluster/pulse treatment
 * and (at the time) the Risk Board's constellation layout - a genuinely
 * new layout mechanism (replacing the old CSS-grid .risk-board) that kept
 * the same color tokens, glass panel treatment, and toolbar chrome.
 *
 * V5 Phase 3 replaced that constellation layout again, this time with an
 * editorial severity-band commitment board (docs/V5_DESIGN_SPEC.md §3) -
 * see the "Risk Board lens" section below - still reading from the exact
 * same shared risk color tokens.
 *
 * Phase 3 (this addition, see the "Panels" section far below) gives
 * Dashboard/Passport/Jarvis their OWN clear visual identity as "context
 * surfaces" distinct from the two main-workspace lenses: Dashboard/
 * Passport read as a biography/dossier (structured typography hierarchy,
 * card and section rhythm), Jarvis reads as a persistent copilot readout
 * (a distinct accent treatment - a soft violet-cyan blend - so it never
 * gets mistaken for "just another data visualization" competing with
 * Universe/Risk Board's cinematic attention). All of it still draws from
 * the exact same :root custom properties and risk color tokens defined
 * below - no new color vocabulary invented, only new LAYOUT/TYPOGRAPHY
 * treatment for a different kind of surface (context/biography, not
 * graph/heatmap).
 */

:root {
  /* Risk color tokens - the single shared vocabulary for both lenses and
     future panels (docs/LENS_SPECIFICATIONS.md: critical/elevated/watch/
     green/gray). */
  --green: #35d48a;
  --yellow: #e8c34a;
  --orange: #f0904a;
  --red: #ef5350;
  --gray: #7c8896;

  --cyan-accent: #5ad1ff;
  --edge-color: rgba(150, 180, 210, 0.35);
  --label-color: rgba(230, 240, 250, 0.92);

  /* V1-UX-1b Task 4: relationship-type visual vocabulary - one color per
     semantic category (causes/depends_on/affects/evidences/resolves/
     blocks/ships/changes/escalates), plus a neutral --edge-color-*
     fallback for graph-scaffolding 'structural' edges (unchanged from the
     prior single edge color, so the merged graph's org/commitment/item
     joins don't visually compete with the semantic categories). See
     engine/derive.js's relationshipVisualClass() for the raw
     relationship_type -> category mapping, and
     docs/INTERACTION_MODEL_NOTES.md for the full documented rationale. */
  --rel-causes: #ef5350;
  --rel-depends_on: #5ad1ff;
  --rel-affects: #b39dff;
  --rel-evidences: #35d48a;
  --rel-resolves: #4ac6a6;
  --rel-blocks: #f0904a;
  --rel-ships: #4a90d9;
  --rel-changes: #e8c34a;
  --rel-escalates: #ef5da0;
  --rel-structural: rgba(150, 180, 210, 0.35);

  /* Phase 3: Jarvis's own distinct accent (a soft violet blended with the
     shared cyan) - gives the persistent copilot readout a visually
     distinct identity from Dashboard/Passport (which use the standard
     cyan-accent) without introducing an unrelated color family. */
  --jarvis-accent: #b39dff;
  --jarvis-glow: rgba(179, 157, 255, 0.35);

  /* Phase 3: shared panel-surface tokens (Dashboard/Passport/Jarvis) -
     slightly different from the lens-facing --panel-bg/--panel-border so
     these "context surface" cards read as a distinct material from the
     glass toolbar/panel chrome, per the phase brief's "give Dashboard/
     Passport/Jarvis their own clear visual identity" requirement. */
  --card-bg: rgba(255, 255, 255, 0.035);
  --card-bg-hover: rgba(255, 255, 255, 0.06);
  --card-border: rgba(150, 180, 210, 0.14);
  --section-divider: rgba(150, 180, 210, 0.12);

  --bg-void: #04070c;
  --bg-glow: radial-gradient(ellipse at 50% -10%, rgba(70, 130, 200, 0.16), transparent 55%),
    radial-gradient(ellipse at 85% 110%, rgba(90, 209, 255, 0.08), transparent 45%),
    radial-gradient(ellipse at 0% 100%, rgba(50, 90, 140, 0.1), transparent 50%);

  --panel-bg: rgba(16, 22, 32, 0.6);
  --panel-border: rgba(120, 160, 200, 0.16);
  --panel-blur: 18px;

  --text-primary: #e7eef6;
  --text-secondary: #9aa9b8;

  --font-ui: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
}

body {
  background-color: var(--bg-void);
  background-image: var(--bg-glow);
  color: var(--text-primary);
  font-family: var(--font-ui);
  overflow: hidden;
}

#app {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.boot-error {
  background: rgba(239, 83, 80, 0.15);
  border: 1px solid var(--red);
  color: #ffd8d6;
  padding: 12px 16px;
  margin: 0;
  font-size: 12px;
  white-space: pre-wrap;
  max-height: 30vh;
  overflow: auto;
}

/* ---------------------------------------------------------------------
   Toolbar
   --------------------------------------------------------------------- */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
  padding: 10px 20px;
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  border-bottom: 1px solid var(--panel-border);
  z-index: 10;
  /* Viewport stability fix: this row accumulates a lot of conditional
     content (shared-investigation-state chips, nav history dots, the
     Return to Universe control) that only appears once something is
     selected/focused - Universe Focus Mode included. With the old
     `nowrap` behavior, that extra content pushed the trailing zoom/time
     sliders (and the timeline slider specifically) past the right edge
     of the viewport, where body's `overflow: hidden` clipped them
     entirely rather than just visually compressing the row. Wrapping
     keeps every control on screen (worst case: a taller, 2-row toolbar)
     instead of silently losing controls off the right edge - and since
     `.layout` below is `flex: 1` inside #app's column flexbox, it always
     fills whatever vertical space the toolbar leaves, in BOTH normal and
     Focus Mode, so the workspace viewport calculation itself never
     differs between the two - only the (now harmless) toolbar height
     does. */
}

.brand {
  font-weight: 700;
  letter-spacing: 0.02em;
  font-size: 14px;
  white-space: nowrap;
}

.brand span {
  font-weight: 400;
  color: var(--cyan-accent);
  margin-left: 6px;
}

.control-group {
  display: flex;
  gap: 4px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  padding: 3px;
}

.control-group button {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  padding: 6px 12px;
  font-size: 12.5px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease;
}

.control-group button:hover {
  color: var(--text-primary);
  background: rgba(255, 255, 255, 0.05);
}

.control-group button.active {
  background: rgba(90, 209, 255, 0.14);
  color: var(--cyan-accent);
}

.lens-group-label {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-secondary);
  white-space: nowrap;
}

.spacer {
  flex: 1;
}

.slider-control {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  color: var(--text-secondary);
  white-space: nowrap;
}

.slider-control input[type='range'] {
  width: 120px;
  accent-color: var(--cyan-accent);
}

.slider-value {
  min-width: 92px;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.time-label {
  font-size: 11.5px;
  color: var(--cyan-accent);
  min-width: 160px;
  text-align: right;
  white-space: nowrap;
}

/* V1-UX-3 Timeline Polish: past/current/future tick marks under the Time
   slider, using only existing design tokens. Past ticks read as already-
   traversed (filled, muted), the current tick is the emphasized "now" for
   this investigation's timeline, future ticks are outlined/dim to read as
   not-yet-reached rather than simply identical to the past. */
.time-ticks {
  display: flex;
  align-items: center;
  gap: 2px;
}

.time-tick {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  background: none;
  border: none;
  padding: 2px 5px;
  cursor: pointer;
  font-family: var(--font-ui);
}

.time-tick-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gray);
  border: 1px solid var(--gray);
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.time-tick-label {
  font-size: 9px;
  letter-spacing: 0.03em;
  color: var(--text-secondary);
  white-space: nowrap;
}

.time-tick.is-past .time-tick-dot {
  background: var(--cyan-accent);
  border-color: var(--cyan-accent);
  opacity: 0.55;
}

.time-tick.is-past .time-tick-label {
  color: var(--text-secondary);
}

.time-tick.is-current .time-tick-dot {
  background: var(--cyan-accent);
  border-color: var(--cyan-accent);
  box-shadow: 0 0 0 3px rgba(90, 209, 255, 0.22);
}

.time-tick.is-current .time-tick-label {
  color: var(--text-primary);
  font-weight: 600;
}

.time-tick.is-future .time-tick-dot {
  background: transparent;
  border-style: dashed;
  opacity: 0.6;
}

.time-tick.is-future .time-tick-label {
  color: var(--text-secondary);
  opacity: 0.65;
}

.time-tick:focus-visible .time-tick-dot {
  outline: 2px solid var(--cyan-accent);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------
   Layout
   --------------------------------------------------------------------- */

.layout {
  flex: 1;
  display: grid;
  grid-template-columns: 280px 1fr 300px;
  min-height: 0;
}

/* app.js's applyLensVisibility(): a commitment focused in Universe with
   Passport open reorders the SAME three grid regions (canvas / #leftPanel /
   #jarvisPanel) - canvas moves to track 1 so the node it renders (already
   anchored toward the right portion of that canvas by Universe's own Logo
   Flow Focus Mode) sits immediately next to the Passport detail panel, now
   in track 2, instead of on the opposite side of the screen from it. Track
   WIDTHS stay 280px/1fr/300px either way (a 280px column and a 300px column
   simply trade places relative to the always-1fr canvas track), so the
   canvas never gains or loses space - only which side the detail panel
   reads on changes. */
.layout.commitment-focus-detail-right {
  grid-template-columns: 1fr 280px 300px;
}

.layout.commitment-focus-detail-right .workspace {
  order: 1;
}

.layout.commitment-focus-detail-right .left-panel {
  order: 2;
  border-right: none;
  border-left: 1px solid var(--panel-border);
}

.layout.commitment-focus-detail-right .jarvis-panel {
  order: 3;
}

.panel {
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  overflow-y: auto;
  padding: 16px 18px;
  font-size: 12.5px;
  color: var(--text-secondary);
}

.left-panel {
  border-right: 1px solid var(--panel-border);
}

.jarvis-panel {
  border-left: 1px solid var(--panel-border);
}

.panel h2 {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--cyan-accent);
  margin: 0 0 10px;
}

.panel p {
  margin: 6px 0;
  line-height: 1.5;
}

.panel-note {
  font-style: italic;
  opacity: 0.7;
  font-size: 11px;
}

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

.plain-list li {
  border-left: 2px solid var(--panel-border);
  padding: 4px 8px;
  font-size: 11.5px;
  word-break: break-word;
}

.workspace {
  position: relative;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: radial-gradient(ellipse at 50% 45%, rgba(20, 35, 55, 0.55), transparent 65%);
}

.hidden {
  display: none !important;
}

/* ---------------------------------------------------------------------
   Universe lens (canvas)
   --------------------------------------------------------------------- */

#universeCanvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
}

/* ---------------------------------------------------------------------
   Risk Board lens (V5 Phase 3) - an editorial commitment board, the
   deliberate visual OPPOSITE of the Universe lens's spatial/ambient
   constellation this replaces (docs/V5_DESIGN_SPEC.md §3): horizontal
   severity bands (Critical/Elevated/Watch/Normal/Dormant), top to bottom,
   each a row of typographic commitment cards sorted by revenue_at_risk.
   Structured and document-like where Universe is cinematic - two visibly
   different lenses over the same operational dataset, not two variations
   on one theme. Still explicitly NOT Kanban (docs/LENS_SPECIFICATIONS.md):
   cards are not draggable; a band is a computed severity state.
   --------------------------------------------------------------------- */

.risk-board {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

.risk-editorial-surface {
  padding: 22px 26px 40px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 100%;
}

.risk-editorial-empty {
  text-align: center;
  color: var(--text-secondary);
  font-size: 13px;
  padding: 40px 0;
}

.risk-editorial-empty.hidden {
  display: none;
}

.risk-band-row {
  border-top: 1px solid var(--panel-border);
  padding: 14px 0 18px;
}

.risk-band-row:first-child {
  border-top: none;
}

.risk-band-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

.risk-band-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--risk-band-color, var(--gray));
  box-shadow: 0 0 10px 1px var(--risk-band-color, var(--gray));
  flex-shrink: 0;
}

.risk-band-name {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-primary);
}

.risk-band-count {
  font-size: 11px;
  color: var(--text-secondary);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  padding: 1px 8px;
}

.risk-band-row.is-empty .risk-band-header {
  opacity: 0.45;
}

.risk-band-row.is-empty .risk-band-cards::after {
  content: 'No commitments currently in this band.';
  font-size: 11.5px;
  color: var(--text-secondary);
  opacity: 0.55;
  padding: 2px 0 4px;
}

.risk-band-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}

.risk-card {
  appearance: none;
  text-align: left;
  width: 264px;
  border: 1px solid var(--panel-border);
  border-left: 3px solid var(--risk-card-color, var(--gray));
  border-radius: 10px;
  background: var(--card-bg);
  color: var(--text-primary);
  cursor: pointer;
  padding: 12px 14px 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  transition: border-color 0.25s ease, box-shadow 0.25s ease, background 0.25s ease, opacity 0.25s ease;
}

.risk-card:hover,
.risk-card:focus-visible {
  background: var(--card-bg-hover);
  outline: none;
  box-shadow: 0 0 0 1px var(--risk-card-color, var(--gray));
}

.risk-card.is-selected {
  border-color: var(--cyan-accent);
  box-shadow: 0 0 0 1.5px var(--cyan-accent), 0 0 24px -6px var(--cyan-accent);
}

.risk-card.is-dormant {
  opacity: 0.55;
  filter: saturate(0.6);
}

.risk-card.is-critical {
  animation: risk-card-pulse 2.4s ease-in-out infinite;
}

@keyframes risk-card-pulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 transparent;
  }
  50% {
    box-shadow: 0 0 16px -4px var(--risk-card-color, var(--red));
  }
}

/* Dashboard KPI "focus objects" cross-lens highlight (see
   lenses/risk-board.js's getHighlightIds option and app.js's
   highlightedIds transient state) - same figure/ground split
   lenses/universe.js applies to its own nodes for the same flow. */
.risk-card.is-highlighted {
  border-color: var(--cyan-accent);
  box-shadow: 0 0 0 1.5px var(--cyan-accent), 0 0 28px -4px var(--cyan-accent);
  animation: risk-card-spotlight-pulse 0.9s ease-out 1;
}

.risk-card.is-dimmed-by-highlight {
  opacity: 0.4;
  filter: saturate(0.5);
}

@keyframes risk-card-spotlight-pulse {
  0% {
    box-shadow: 0 0 0 2px var(--cyan-accent), 0 0 40px 4px var(--cyan-accent);
  }
  100% {
    box-shadow: 0 0 0 1.5px var(--cyan-accent), 0 0 28px -4px var(--cyan-accent);
  }
}

.risk-card-top {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.risk-card-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--risk-card-color, var(--gray));
  flex-shrink: 0;
  margin-bottom: 1px;
}

.risk-card-id {
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--text-secondary);
  white-space: nowrap;
}

.risk-card-customer {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}

/* Sprint UX-2C: the item now sits in the prominent top row (beside the
   customer), so it reads as part of the "who + what" headline rather than
   a secondary meta line. */
.risk-card-top .risk-card-item {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.risk-card-revenue {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--risk-card-color, var(--text-primary));
  white-space: nowrap;
}

.risk-card-meta {
  font-size: 11px;
  color: var(--text-secondary);
  display: flex;
  gap: 6px;
  overflow: hidden;
}

/* Sprint UX-2C: the ERP reference id, demoted to the secondary meta line
   ("Reference RB-CPP-HORIZON") so the customer + item headline leads.
   Muted, mono, no weight — visually secondary, still available. */
.risk-card-ref {
  white-space: nowrap;
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  color: var(--text-secondary);
  opacity: 0.85;
}

.risk-card-item {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.risk-card-required {
  white-space: nowrap;
}

.risk-card-sparkline-wrap {
  line-height: 0;
}

.risk-sparkline {
  width: 100%;
  height: 26px;
  display: block;
}

.risk-card-counts {
  font-size: 10.5px;
  color: var(--text-secondary);
}

.risk-card-rootcause {
  font-size: 11px;
  color: var(--text-primary);
  line-height: 1.4;
  padding-top: 6px;
  border-top: 1px solid var(--section-divider);
  opacity: 0.9;
}

/* Inline "drill into sub-detail" drawer, shown only on the selected card
   (V5 Phase 2.6 item F - see lenses/risk-board.js's buildExpandedDetail()). */
.risk-card-expanded {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 10.5px;
  color: var(--text-secondary);
  padding-top: 8px;
  margin-top: 2px;
  border-top: 1px solid var(--cyan-accent);
}

.risk-card-expanded-row {
  display: flex;
  gap: 6px;
  line-height: 1.4;
}

.risk-card-expanded-label {
  flex-shrink: 0;
  min-width: 84px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 9px;
  color: var(--cyan-accent);
}

.risk-card-expanded-evidence span:last-child {
  color: var(--text-primary);
}

/* ---------------------------------------------------------------------
   Workbench lens (V5 Phase 4.5, docs/V5_HANDOVER.md §9.2/§11.6) - an
   analytical workspace: root-type + domain selectors build a joined
   dataset (engine/relationship-dataset.js), a field/column picker chooses
   which resolved columns to show, engine/filterable-table.js's REUSABLE
   sort/filter table renders the rows, and a minimal bar/line chart sits
   below. Editorial/document material (like Risk Board), not spatial -
   reads as a workbench, not a third variation on Universe's canvas.
   --------------------------------------------------------------------- */

.workbench {
  position: absolute;
  inset: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.workbench-toolbar {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--panel-border);
  background: rgba(255, 255, 255, 0.02);
  flex-wrap: wrap;
}

.workbench-field {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  color: var(--text-secondary);
}

.workbench-field label,
.workbench-field-label {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 10.5px;
  color: var(--cyan-accent);
  white-space: nowrap;
}

.workbench-toolbar select,
.workbench-chart-controls select {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--panel-border);
  color: var(--text-primary);
  border-radius: 6px;
  padding: 5px 8px;
  font-size: 12px;
  font-family: inherit;
}

.workbench-domains {
  flex-wrap: wrap;
}

.workbench-domain-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.workbench-domain-chip,
.workbench-column-toggle {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  color: var(--text-secondary);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  padding: 3px 10px 3px 8px;
  cursor: pointer;
  white-space: nowrap;
}

.workbench-domain-chip:has(input:checked),
.workbench-column-toggle:has(input:checked) {
  color: var(--cyan-accent);
  border-color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.1);
}

.workbench-toolbar-spacer {
  flex: 1;
}

.workbench-ghost-btn {
  appearance: none;
  border: 1px solid var(--panel-border);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-secondary);
  padding: 6px 14px;
  font-size: 12px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}

.workbench-ghost-btn:hover {
  color: var(--text-primary);
  border-color: var(--cyan-accent);
}

.workbench-ghost-btn.is-flashing {
  color: var(--cyan-accent);
  border-color: var(--cyan-accent);
}

.workbench-body {
  flex: 1;
  display: grid;
  grid-template-columns: 200px 1fr;
  min-height: 0;
}

.workbench-columns {
  border-right: 1px solid var(--panel-border);
  padding: 14px 14px 40px;
  overflow-y: auto;
}

.workbench-columns h3 {
  margin: 0 0 10px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--cyan-accent);
}

.workbench-column-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.workbench-column-list .workbench-column-toggle {
  border-radius: 6px;
}

.workbench-main {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.workbench-meta {
  padding: 10px 18px 0;
  font-size: 11px;
  color: var(--text-secondary);
}

.workbench-table-container {
  flex: 1 1 55%;
  overflow: auto;
  padding: 10px 18px;
  min-height: 120px;
}

.filterable-table-root {
  position: relative;
}

.filterable-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 11.5px;
}

.filterable-table th,
.filterable-table td {
  border-bottom: 1px solid var(--panel-border);
  padding: 6px 10px;
  text-align: left;
  white-space: nowrap;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.filterable-table-sort-btn {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-primary);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
  padding: 0;
}

.filterable-table-sort-btn:hover {
  color: var(--cyan-accent);
}

.filterable-table-filter-input {
  width: 100%;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--panel-border);
  color: var(--text-primary);
  border-radius: 4px;
  padding: 3px 6px;
  font-size: 11px;
  font-family: inherit;
}

.filterable-table-row.is-clickable {
  cursor: pointer;
}

.filterable-table-row:hover {
  background: var(--card-bg-hover);
}

.filterable-table-empty {
  text-align: center;
  color: var(--text-secondary);
  font-size: 12px;
  padding: 24px 0;
}

.filterable-table-empty.hidden {
  display: none;
}

/* ---------------------------------------------------------------------
   engine/filterable-table.js's governed multi-select filter (UX hardening
   item 2, opt-in per column via `filterType: 'multiselect'` - Functional
   Radar List View's Risk/Type/Owner columns): an "Excel filter" style
   dropdown instead of the plain `.filterable-table-filter-input` free-text
   box every other column keeps. `.filterable-table th.filterable-table-
   filter-cell` overrides the generic `.filterable-table th` rule's
   overflow/white-space/max-width (needed so the OPEN dropdown panel, a
   fixed-position popover, is never visually clipped by its own header
   cell - the exact class of bug the toolbar overflow fix elsewhere in this
   sprint also addresses).
   --------------------------------------------------------------------- */

.filterable-table th.filterable-table-filter-cell {
  overflow: visible;
  white-space: normal;
  max-width: none;
}

.filterable-table-multiselect {
  position: relative;
}

.filterable-table-multiselect-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  width: 100%;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--panel-border);
  color: var(--text-secondary);
  border-radius: 4px;
  padding: 3px 6px;
  font-size: 11px;
  font-family: inherit;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  cursor: pointer;
  text-align: left;
}

.filterable-table-multiselect-toggle:hover {
  border-color: var(--cyan-accent);
}

.filterable-table-multiselect-toggle.is-active {
  color: var(--cyan-accent);
  border-color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.1);
}

.filterable-table-multiselect-summary {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.filterable-table-multiselect-caret {
  flex: none;
  opacity: 0.7;
  font-size: 9px;
}

/* `position: fixed` (with top/left set in JS against the toggle button's
   live viewport rect - see positionMultiselectPanel()) escapes every
   scrollable/clipping ancestor, including Functional Radar's own
   scrollable List View container - the panel is never clipped the way the
   toolbar used to clip the timeline slider before this sprint's item-4 fix. */
.filterable-table-multiselect-panel {
  position: fixed;
  min-width: 220px;
  max-width: 280px;
  background: var(--bg-void);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
  padding: 8px;
  z-index: 500;
  white-space: normal;
}

.filterable-table-multiselect-panel.hidden {
  display: none;
}

.filterable-table-multiselect-search-input {
  width: 100%;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--panel-border);
  color: var(--text-primary);
  border-radius: 4px;
  padding: 4px 8px;
  font-size: 11.5px;
  font-family: inherit;
  margin-bottom: 6px;
}

.filterable-table-multiselect-actions {
  display: flex;
  gap: 6px;
  margin-bottom: 6px;
}

.filterable-table-multiselect-actions button {
  appearance: none;
  border: 1px solid var(--panel-border);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-secondary);
  padding: 3px 8px;
  font-size: 10.5px;
  border-radius: 4px;
  cursor: pointer;
}

.filterable-table-multiselect-actions button:hover {
  color: var(--text-primary);
  border-color: var(--cyan-accent);
}

.filterable-table-multiselect-list {
  max-height: 200px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.filterable-table-multiselect-option {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--text-primary);
  padding: 3px 4px;
  border-radius: 4px;
  cursor: pointer;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  white-space: normal;
}

.filterable-table-multiselect-option:hover {
  background: rgba(255, 255, 255, 0.05);
}

.filterable-table-multiselect-empty {
  font-size: 11px;
  color: var(--text-secondary);
  padding: 6px 4px;
  font-style: italic;
}

.workbench-chart-panel {
  flex: 1 1 40%;
  border-top: 1px solid var(--panel-border);
  padding: 10px 18px 18px;
  display: flex;
  flex-direction: column;
  min-height: 120px;
}

.workbench-chart-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.workbench-chart-canvas {
  flex: 1;
  width: 100%;
  min-height: 100px;
}

/* --- Shared: view-actions row + naming popover ------------------------
   V5 Phase 4.6 (docs/V5_HANDOVER.md §9.2/§9.4): Save Current View / Save
   Report / Save Dashboard / Duplicate View / Share View / Manage Saved
   Views. Used by both panels/dashboard.js (in its panel-heading) and
   lenses/workbench.js (in its toolbar) - one shared visual language for
   "this button reserves a future save/share action," per
   engine/saved-views.js. */

.view-actions-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.panel-heading .view-actions-bar {
  margin-top: 10px;
}

.view-action-btn {
  appearance: none;
  border: 1px solid var(--panel-border);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-secondary);
  padding: 5px 12px;
  font-size: 11.5px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}

.view-action-btn:hover:not(:disabled) {
  color: var(--text-primary);
  border-color: var(--cyan-accent);
}

.view-action-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* The naming popover itself (Save Current View / Save Report / Save
   Dashboard / Duplicate View all share this one component). Positioned
   inline, right under whichever action bar opened it, rather than a
   floating overlay - this is a lightweight confirm, not a modal. */
.save-name-prompt {
  margin-top: 10px;
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  padding: 14px;
  max-width: 320px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  box-shadow: 0 10px 30px -8px rgba(0, 0, 0, 0.5);
}

.save-name-prompt.hidden {
  display: none;
}

/* Workbench places its copy right after the toolbar (in normal document
   flow, pushing workbench-body down while open) rather than Dashboard's
   margin-top spacing - the toolbar is a horizontal strip, not a heading
   block, so a top margin would look like stray whitespace there. */
.workbench-toolbar + .save-name-prompt {
  margin: 10px 20px 0;
}

.save-name-prompt-label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--cyan-accent);
}

.save-name-prompt input[type='text'] {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--panel-border);
  color: var(--text-primary);
  border-radius: 6px;
  padding: 6px 8px;
  font-size: 12px;
  font-family: inherit;
  text-transform: none;
  letter-spacing: normal;
}

.save-name-prompt-actions {
  display: flex;
  gap: 8px;
}

.save-name-prompt-note {
  margin: 2px 0 0;
  font-size: 11px;
  color: var(--text-secondary);
  line-height: 1.4;
}

/* ---------------------------------------------------------------------
   Scrollbars (subtle, matches the glassmorphic dark aesthetic)
   --------------------------------------------------------------------- */

.panel::-webkit-scrollbar {
  width: 8px;
}

.panel::-webkit-scrollbar-thumb {
  background: rgba(150, 180, 210, 0.2);
  border-radius: 4px;
}

.panel::-webkit-scrollbar-track {
  background: transparent;
}

/* ===========================================================================
   Panels (Phase 3): Dashboard / Passport / Jarvis
   ===========================================================================
   Shared building blocks first (risk dots/badges, section rhythm,
   citation chips, empty states - reused across all 3 panel modules), then
   panel-specific rules. Dashboard/Passport share the #leftPanel host
   element (panels/dashboard.js and panels/passport.js each fully replace
   its innerHTML depending on state.leftPanelMode - see app.js), Jarvis
   owns #jarvisPanel exclusively.
   =========================================================================== */

.panel-surface {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.panel-heading h2 {
  margin: 0;
}

.panel-subhead {
  margin: 2px 0 0;
  font-size: 11px;
  color: var(--text-secondary);
  opacity: 0.85;
}

/* --- Shared: risk dot / badge vocabulary -----------------------------------
   One small colored dot/badge language shared by Dashboard KPI cards,
   Passport's Current Risk section, and the Top Commitment Risks list -
   all keyed off the exact same --green/--yellow/--orange/--red/--gray
   tokens the lenses already use, so risk color reads identically no
   matter which surface you're looking at. */

.risk-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.risk-dot--critical {
  background: var(--red);
  box-shadow: 0 0 8px 1px rgba(239, 83, 80, 0.55);
}

.risk-dot--elevated {
  background: var(--orange);
  box-shadow: 0 0 8px 1px rgba(240, 144, 74, 0.5);
}

.risk-dot--watch {
  background: var(--yellow);
  box-shadow: 0 0 6px 1px rgba(232, 195, 74, 0.45);
}

.risk-dot--neutral {
  background: var(--gray);
}

.risk-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  text-transform: capitalize;
  letter-spacing: 0.01em;
  width: fit-content;
  border: 1px solid transparent;
}

.risk-badge--critical {
  color: #ffd9d7;
  background: rgba(239, 83, 80, 0.14);
  border-color: rgba(239, 83, 80, 0.4);
}

.risk-badge--elevated {
  color: #ffe0c7;
  background: rgba(240, 144, 74, 0.14);
  border-color: rgba(240, 144, 74, 0.4);
}

.risk-badge--watch {
  color: #fbeeb9;
  background: rgba(232, 195, 74, 0.14);
  border-color: rgba(232, 195, 74, 0.4);
}

.risk-badge--neutral {
  color: var(--text-secondary);
  background: rgba(124, 136, 150, 0.14);
  border-color: rgba(124, 136, 150, 0.35);
}

/* --- Shared: section rhythm / empty states ---------------------------------- */

.dash-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 16px;
  border-top: 1px solid var(--section-divider);
}

.dash-section-title,
.passport-section-title,
.jarvis-section-title {
  margin: 0;
  font-size: 10.5px;
  text-transform: uppercase;
  /* V1-UX-3: standardized to 0.08em - matches .kpi-card-title and the
     newer .functional-workspace-eyebrow/.risk-site-strip-header, which all
     share this exact same 10.5px "section eyebrow" role but had drifted to
     three different letter-spacing values (0.09em/0.07em/0.08em). */
  letter-spacing: 0.08em;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 8px;
}

.passport-section-count {
  font-size: 9.5px;
  font-weight: 700;
  color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.12);
  border-radius: 999px;
  padding: 1px 7px;
  letter-spacing: normal;
  text-transform: none;
}

.dash-section-empty {
  font-size: 11.5px;
  color: var(--text-secondary);
  opacity: 0.7;
  font-style: italic;
  padding: 10px 0;
}

/* --- Shared: monospace source-citation vocabulary ---------------------------
   Used by Passport's Evidence/Source-Records sections and Jarvis's
   Evidence Reference block - "cite evidence/source record IDs when
   visible" (PANEL_SPECIFICATIONS.md) reads as real, verifiable lineage
   rather than paraphrased-away prose, so these get a distinct monospace/
   compact treatment wherever they appear. */

.source-cite {
  font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 10px;
  color: var(--text-secondary);
  letter-spacing: 0.01em;
}

.citation-chip {
  display: inline-block;
  font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 9.5px;
  color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.08);
  border: 1px solid rgba(90, 209, 255, 0.22);
  border-radius: 5px;
  padding: 3px 7px;
  line-height: 1.4;
  word-break: break-all;
}

.dormant-tag {
  font-size: 9.5px;
  color: var(--text-secondary);
  opacity: 0.65;
  font-style: italic;
}

/* V1-CONTENT-1: honest empty-state navigation. renderEmptySectionState()
   (panels/passport.js) wraps its message text in .dash-section-empty
   unchanged (same muted/italic treatment as every other empty state
   already had) and, only when a real destination exists, adds one inline
   button styled like a link rather than a full button - a low-emphasis
   affordance appropriate for "here's somewhere useful to look next," not a
   primary action competing with the section content above it. */
.passport-inline-link {
  appearance: none;
  background: none;
  border: none;
  padding: 0;
  margin-top: 4px;
  display: block;
  font: inherit;
  font-size: 11.5px;
  font-style: normal;
  color: var(--cyan-accent);
  cursor: pointer;
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 2px;
  opacity: 1;
}
.passport-inline-link:hover,
.passport-inline-link:focus-visible {
  color: var(--text-primary);
}

/* Evidence entries sourced from a real NR04 uses_evidence graph citation
   (engine/derive.js buildPassportViewModel 5b) carry an honest "Supporting
   evidence" tag distinct from the pre-existing evidence.json entries'
   implicit "Direct evidence" - see engine/business-language.js
   evidenceRelationLabel(). Reuses the citation-chip's muted secondary
   register rather than a new visual language. */
.passport-evidence-relation {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  opacity: 0.75;
}

/* ---------------------------------------------------------------------------
   Dashboard panel
   ---------------------------------------------------------------------------
   "Answer what deserves attention now" (PANEL_SPECIFICATIONS.md). Revenue
   at Risk renders as the headline metric per the founder's own example -
   a single large card above the KPI grid - with the remaining 6 cards in
   a compact 2-column grid below, each colored by its own severity
   classification (panels/dashboard.js's riskBucketForCard()). A "Top
   Commitment Risks" list closes the panel, satisfying
   PANEL_SPECIFICATIONS.md's explicit "show top commitment risks"
   requirement.
   --------------------------------------------------------------------- */

.kpi-headline {
  margin-bottom: -6px;
}

.kpi-card {
  appearance: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  width: 100%;
  text-align: left;
  padding: 14px 16px;
  border-radius: 12px;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  color: var(--text-primary);
  cursor: default;
  transition: background 0.16s ease, border-color 0.16s ease, transform 0.12s ease;
}

.kpi-card.is-clickable {
  cursor: pointer;
}

.kpi-card.is-clickable:hover {
  background: var(--card-bg-hover);
  transform: translateY(-1px);
}

.kpi-card.is-clickable:active {
  transform: translateY(0);
}

.kpi-card:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.kpi-card-title {
  font-size: 10.5px;
  text-transform: uppercase;
  /* V1-UX-3: standardized to 0.08em - see .dash-section-title's comment. */
  letter-spacing: 0.08em;
  color: var(--text-secondary);
}

.kpi-card-value {
  font-size: 20px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
  line-height: 1.15;
}

.kpi-card-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  color: var(--text-secondary);
  min-height: 8px;
}

/* Headline card (Revenue at Risk): larger type, a subtle risk-colored
   border glow, and a full-bleed card rather than sharing the 2-col grid -
   this is the one KPI the founder's brief explicitly singles out as
   deserving headline treatment. */
.kpi-card--headline {
  padding: 18px 18px 16px;
  border-radius: 14px;
}

.kpi-card--headline .kpi-card-title {
  font-size: 11px;
}

.kpi-card--headline .kpi-card-value {
  font-size: 32px;
  letter-spacing: -0.01em;
}

.kpi-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

/* Per-severity accent: a colored top border + faint tinted background,
   readable at a glance without needing to parse the number itself. */
.kpi-card--critical {
  border-color: rgba(239, 83, 80, 0.4);
  box-shadow: inset 0 1px 0 0 rgba(239, 83, 80, 0.5);
}

.kpi-card--critical .kpi-card-value {
  color: #ffb3b0;
}

.kpi-card--elevated {
  border-color: rgba(240, 144, 74, 0.35);
  box-shadow: inset 0 1px 0 0 rgba(240, 144, 74, 0.45);
}

.kpi-card--elevated .kpi-card-value {
  color: #ffc999;
}

.kpi-card--watch {
  border-color: rgba(232, 195, 74, 0.3);
  box-shadow: inset 0 1px 0 0 rgba(232, 195, 74, 0.4);
}

.kpi-card--watch .kpi-card-value {
  color: #f3e0a0;
}

.dash-toplist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.dash-toplist-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 6px;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.14s ease;
}

.dash-toplist-item:hover,
.dash-toplist-item:focus-visible {
  background: var(--card-bg-hover);
  outline: none;
}

.dash-toplist-label {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.dash-toplist-label strong {
  font-size: 12px;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dash-toplist-sub {
  font-size: 10px;
  color: var(--text-secondary);
}

.dash-toplist-value {
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   Passport panel
   ---------------------------------------------------------------------------
   "The biography of the selected operational object"
   (PANEL_SPECIFICATIONS.md). Overview reads as a header/masthead block;
   Current Risk is a prominent badge (shared .risk-badge styles above);
   Relationships/Recommendations/Evidence/Operational History are clearly
   delineated sections with their own internal rhythm; Source Records
   closes the panel as a compact monospace lineage footer.
   --------------------------------------------------------------------- */

.passport-overview {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--section-divider);
}

.passport-overview-type {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--cyan-accent);
}

.passport-overview-label {
  margin: 0;
  font-size: 19px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

.passport-overview-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin: 2px 0 0;
}

.passport-overview-meta div {
  display: flex;
  gap: 5px;
  font-size: 11px;
}

.passport-overview-meta dt {
  color: var(--text-secondary);
}

.passport-overview-meta dd {
  margin: 0;
  color: var(--text-primary);
  font-weight: 600;
}

.passport-overview-summary {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.55;
  color: var(--text-secondary);
}

/* Sprint UX-2C: progressive-detail overview lines — operational meaning
   (why it matters / next action) rendered as a primary line above the
   ERP-metadata <dl>, so a first-time reader sees what is happening and
   what to do before any identifier. Reuses the existing summary register
   (same size/line-height) with a slightly stronger weight on the lead-in
   label, and no new color token. */
.passport-overview-impact,
.passport-overview-next {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.55;
  color: var(--text-secondary);
}
.passport-overview-impact strong,
.passport-overview-next strong {
  color: var(--text-primary);
  font-weight: 600;
}

/* The ERP reference row in the overview meta <dl> is visually secondary:
   muted color + lighter weight, so the identifier stays available but
   never competes with the operational fields above it. */
.passport-overview-meta-erp dt,
.passport-overview-meta-erp dd {
  color: var(--text-secondary);
  font-weight: 400;
}
.passport-overview-meta-erp dd {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 11px;
}

/* V1-UX-1b Task 3: the canonical Probe CTA, reused by the Passport Overview
   header and the Hover Passport Preview (.hover-preview-probe-btn) - same
   cyan-accent "investigative action" look, distinct from the neutral
   .view-action-btn used for non-investigative view/report actions. */
.passport-probe-btn {
  appearance: none;
  align-self: flex-start;
  margin-top: 10px;
  border: 1px solid var(--cyan-accent);
  background: rgba(90, 209, 255, 0.1);
  color: var(--cyan-accent);
  padding: 6px 12px;
  font-size: 11.5px;
  font-weight: 600;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.18s ease;
}

.passport-probe-btn:hover {
  background: rgba(90, 209, 255, 0.22);
}

/* V1-UX-1B: this canonical Probe CTA had no explicit keyboard-focus style
   (every OTHER interactive element in this codebase does - see
   .risk-card/.dash-toplist-item/.jarvis-next-step-button/.spider-vertex.
   is-clickable/.text-view-ref/.passport-collection-member/.cs-action-btn's
   own :focus-visible rules) - adding one here benefits every existing
   Probe button (Passport, Hover Preview) plus the newly-added ones below
   (Text View, Workbench, Conductor Studio), all of which share this one
   class. */
.passport-probe-btn:focus-visible {
  outline: 2px solid var(--cyan-accent);
  outline-offset: 2px;
}

/* V1-UX-1B: Text View's/Workbench's/Conductor Studio's explicit "Probe
   {Type} ->" CTA now reuses .passport-probe-btn above verbatim (see
   lenses/text-view.js's probeButtonMarkup() and engine/
   filterable-table.js's getRowProbeType/onProbe contract) rather than a
   new button style - closing docs/UNSUPPORTED_UI_FIELD_REPORT.md's
   Remaining UX Backlog #2 ("Explicit Probe buttons in Text View /
   Workbench / Conductor Studio - currently these 3 lenses support
   select-through only"). These two small table-specific touches keep the
   shared button from making a dense filter/sort table row noticeably
   taller/wider than it needs to be - the button itself needs zero new
   CSS to render or work correctly without these. */
.filterable-table-probe-th,
.filterable-table-probe-td {
  white-space: nowrap;
  text-align: right;
}

.filterable-table-probe-btn {
  margin-top: 0;
  padding: 4px 10px;
  font-size: 11px;
}

/* V1-UX-1B: Text View's Probe button sits directly under the existing
   .text-view-ref/.text-view-hierarchy-ref button inside the same list
   item - a small top margin keeps the two from visually touching. */
.text-view-probe-btn {
  margin-top: 6px;
}

/* V1-UX-1b Task 7: the "Demo-derived Detail" section + its always-visible
   badge - a distinct amber/warning tint (not the cyan Probe/investigative
   color, not a risk color) so it reads as its own honest classification,
   never mistaken for real governed data or a risk signal. */
.demo-derived-badge {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #f0904a;
  background: rgba(240, 144, 74, 0.14);
  border: 1px solid rgba(240, 144, 74, 0.4);
  vertical-align: middle;
  cursor: help;
}

.passport-drilldown-note {
  margin: 0;
  font-size: 11px;
  color: var(--text-secondary);
  font-style: italic;
  opacity: 0.85;
}

.passport-drilldown-fields {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 8px 16px;
  margin: 4px 0 0;
}

.passport-drilldown-fields div {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.passport-drilldown-fields dt {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}

.passport-drilldown-fields dd {
  margin: 0;
  font-size: 12px;
  color: var(--text-primary);
  font-weight: 600;
}

.passport-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 16px;
  border-top: 1px solid var(--section-divider);
}

.passport-current-risk {
  border-top: none;
  padding-top: 0;
}

.passport-relationship-list,
.passport-entry-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.passport-relationship-item {
  appearance: none;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 9px;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease;
}

.passport-relationship-item:hover,
.passport-relationship-item:focus-visible {
  background: var(--card-bg-hover);
  border-color: var(--cyan-accent);
  outline: none;
}

.passport-relationship-dir {
  color: var(--cyan-accent);
  font-weight: 700;
  flex-shrink: 0;
}

.passport-relationship-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.passport-relationship-body strong {
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.passport-relationship-type {
  font-size: 10px;
  color: var(--text-secondary);
  text-transform: capitalize;
}

.passport-relationship-kind {
  font-size: 9.5px;
  color: var(--text-secondary);
  background: rgba(150, 180, 210, 0.1);
  border-radius: 999px;
  padding: 2px 8px;
  white-space: nowrap;
  flex-shrink: 0;
}

.passport-entry {
  padding: 10px 12px;
  border-radius: 9px;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: opacity 0.4s ease, filter 0.4s ease;
}

/* Dormant (not yet visible at the current time slice) recommendations/
   evidence: muted, not hidden - "reveal over time, don't hard-cut," the
   same principle Phase 2's lenses already apply to time-gated nodes. */
.passport-entry.is-dormant {
  opacity: 0.5;
  filter: saturate(0.6);
}

/* V1-UX-3: Evidence and Recommendations entries are real, selectable
   Universe graph nodes (see engine/derive.js's node building), but were
   previously rendered as plain, non-interactive <li> cards - a click-
   through dead end distinct from every other Passport section (Relationships,
   Collection members), which already use exactly this button-wrapped
   pattern. `.passport-entry` keeps its existing card box model unchanged;
   this only adds the interactive-element resets a <button> needs to look
   identical to the previous <li>, plus the same hover/focus affordance
   `.passport-relationship-item` already has. */
.passport-entry-select {
  appearance: none;
  width: 100%;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.passport-entry-select:hover,
.passport-entry-select:focus-visible {
  background: var(--card-bg-hover);
  border-color: var(--cyan-accent);
  outline: none;
}

.passport-entry-select:disabled {
  cursor: default;
}

.passport-entry-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.passport-entry-tag {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: capitalize;
  color: var(--text-primary);
}

.passport-entry-status {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--cyan-accent);
}

.passport-entry-summary {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-secondary);
}

.passport-entry-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 10px;
  color: var(--text-secondary);
}

.passport-effective-dating {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-size: 10.5px;
  color: var(--text-secondary);
  margin-top: -2px;
}

.passport-eff-label {
  color: var(--text-secondary);
  opacity: 0.7;
  margin-right: 4px;
}

/* Operational History: a real vertical timeline (distinct from the
   toolbar's GLOBAL time slider) - a left rail with markers, matching the
   "Timeline" step of the required exploration flow. */
.passport-history-list {
  list-style: none;
  margin: 0;
  padding: 0 0 0 4px;
  display: flex;
  flex-direction: column;
  gap: 0;
  position: relative;
}

.passport-history-item {
  display: flex;
  gap: 12px;
  padding: 0 0 16px 0;
  position: relative;
}

.passport-history-item:last-child {
  padding-bottom: 0;
}

.passport-history-marker {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--cyan-accent);
  margin-top: 5px;
  position: relative;
}

.passport-history-item:not(:last-child) .passport-history-marker::after {
  content: '';
  position: absolute;
  top: 12px;
  left: 3.5px;
  width: 1px;
  height: calc(100% + 10px);
  background: var(--section-divider);
}

.passport-history-body {
  flex: 1;
  min-width: 0;
}

.passport-history-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.passport-history-head strong {
  font-size: 12px;
  color: var(--text-primary);
}

.passport-history-time {
  font-size: 9.5px;
  color: var(--text-secondary);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.passport-history-summary {
  margin: 3px 0 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-secondary);
}

.passport-source-records {
  padding-bottom: 4px;
}

.source-record-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.source-record-item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.02);
}

.source-record-identifier {
  font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 10px;
  color: var(--text-primary);
}

.source-record-via {
  font-size: 9.5px;
  color: var(--text-secondary);
  opacity: 0.75;
}

.passport-empty-state .panel-note {
  margin-top: 4px;
}

/* ---------------------------------------------------------------------------
   Jarvis panel
   ---------------------------------------------------------------------------
   "Persistent deterministic intelligence. Jarvis is not a chatbot in the
   lab" (PANEL_SPECIFICATIONS.md). This is intentionally styled as a
   readout/instrument panel, not a chat surface - no input affordance
   anywhere, no message-bubble visual language. The --jarvis-accent violet
   (blended with the shared cyan) gives it a distinct identity from
   Dashboard/Passport while still living in the same dark-glass material
   language.
   --------------------------------------------------------------------- */

.jarvis-heading {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.jarvis-badge {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--jarvis-accent);
  box-shadow: 0 0 10px 2px var(--jarvis-glow);
  flex-shrink: 0;
  animation: jarvis-badge-breathe 3.4s ease-in-out infinite;
}

@keyframes jarvis-badge-breathe {
  0%,
  100% {
    box-shadow: 0 0 8px 1px var(--jarvis-glow);
    opacity: 0.85;
  }
  50% {
    box-shadow: 0 0 16px 4px var(--jarvis-glow);
    opacity: 1;
  }
}

.jarvis-heading h2 {
  color: var(--jarvis-accent);
}

.jarvis-heading .panel-subhead {
  width: 100%;
}

.jarvis-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 16px;
  border-top: 1px solid var(--section-divider);
}

.jarvis-context:first-of-type {
  border-top: none;
  padding-top: 0;
}

.jarvis-context-grid {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin: 0;
}

.jarvis-context-grid div {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-size: 11.5px;
}

.jarvis-context-grid dt {
  color: var(--text-secondary);
}

.jarvis-context-grid dd {
  margin: 0;
  color: var(--text-primary);
  font-weight: 600;
  text-align: right;
}

.jarvis-selected-object {
  margin-top: 4px;
  padding: 10px 12px;
  border-radius: 9px;
  background: rgba(179, 157, 255, 0.06);
  border: 1px solid rgba(179, 157, 255, 0.2);
}

.jarvis-selected-label {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--jarvis-accent);
}

.jarvis-selected-summary {
  margin: 4px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-primary);
}

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

.jarvis-change-item {
  padding: 9px 11px;
  border-radius: 9px;
  background: var(--card-bg);
  border-left: 2px solid var(--jarvis-accent);
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.jarvis-change-customer {
  font-size: 10.5px;
  font-weight: 700;
  color: var(--text-primary);
}

.jarvis-change-summary {
  margin: 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--text-secondary);
}

.jarvis-change-revenue {
  font-size: 10px;
  font-weight: 600;
  color: var(--orange);
}

.jarvis-next-step-button {
  appearance: none;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 10px;
  background: linear-gradient(135deg, rgba(179, 157, 255, 0.12), rgba(90, 209, 255, 0.08));
  border: 1px solid rgba(179, 157, 255, 0.35);
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.16s ease, transform 0.12s ease, background 0.16s ease;
}

.jarvis-next-step-button:hover,
.jarvis-next-step-button:focus-visible {
  border-color: var(--jarvis-accent);
  background: linear-gradient(135deg, rgba(179, 157, 255, 0.18), rgba(90, 209, 255, 0.12));
  transform: translateY(-1px);
  outline: none;
}

.jarvis-next-step-icon {
  font-size: 15px;
  color: var(--jarvis-accent);
  flex-shrink: 0;
}

.jarvis-next-step-text {
  font-size: 12px;
  line-height: 1.5;
}

.jarvis-citation-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.jarvis-citation-label {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-secondary);
}

.jarvis-citation-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

/* ---------------------------------------------------------------------
   Operational Scope (V5 Phase 3.5, docs/V5_HANDOVER.md §9.1-§9.3): the
   Scope Bar (a persistent strip floating over the top of the workspace,
   above whichever lens is active - same glass-panel material as the
   toolbar) and the Scope Explorer (a centered modal over a dim backdrop,
   browsing the real org -> site -> customer -> program -> commitment
   hierarchy). Reads from the exact same --panel-bg/--cyan-accent/
   --card-bg vocabulary every other surface in this app already uses - no
   new color language invented for scope.
   --------------------------------------------------------------------- */

.scope-bar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 6;
  display: flex;
  justify-content: center;
  padding: 10px 0 0;
  pointer-events: none;
}

.scope-bar-inner {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px 6px 14px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  box-shadow: 0 8px 24px -12px rgba(0, 0, 0, 0.6);
}

.scope-bar-kicker {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-secondary);
}

.scope-bar-current {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-primary);
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px;
  border-radius: 999px;
  font-size: 12px;
  cursor: pointer;
  transition: background 0.18s ease;
}

.scope-bar-current:hover {
  background: rgba(255, 255, 255, 0.06);
}

.scope-bar-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gray);
  flex-shrink: 0;
}

.scope-bar-dot.is-narrowed {
  background: var(--cyan-accent);
  box-shadow: 0 0 8px 1px rgba(90, 209, 255, 0.55);
}

.scope-bar-label {
  font-weight: 600;
  white-space: nowrap;
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.scope-bar-caret {
  color: var(--text-secondary);
  font-size: 10px;
}

.scope-bar-reset {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: 11px;
  padding: 5px 10px 5px 4px;
  border-left: 1px solid var(--panel-border);
  cursor: pointer;
  transition: color 0.18s ease;
}

.scope-bar-reset:hover {
  color: var(--cyan-accent);
}

.panel-subhead--scope {
  color: var(--cyan-accent);
  opacity: 1;
}

/* --- Scope Explorer modal -------------------------------------------- */

.scope-explorer-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
}

.scope-explorer-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(4, 7, 12, 0.72);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.scope-explorer-dialog {
  position: relative;
  z-index: 1;
  width: min(520px, 92vw);
  max-height: 82vh;
  overflow-y: auto;
  padding: 18px 20px 22px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: 0 24px 60px -16px rgba(0, 0, 0, 0.75);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
}

.scope-explorer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}

.scope-explorer-header h2 {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--cyan-accent);
  margin: 0;
}

.scope-explorer-close {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: 13px;
  cursor: pointer;
  padding: 4px 6px;
}

.scope-explorer-close:hover {
  color: var(--text-primary);
}

.scope-explorer-hint {
  font-size: 11.5px;
  color: var(--text-secondary);
  line-height: 1.5;
  margin: 4px 0 14px;
}

.scope-explorer-whole-org {
  width: 100%;
  margin-bottom: 10px;
}

.scope-explorer-search {
  width: 100%;
  box-sizing: border-box;
  appearance: none;
  padding: 7px 10px;
  margin-bottom: 12px;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 8px;
  color: var(--text-primary);
  font-size: 12px;
  font-family: inherit;
}

.scope-explorer-search:focus {
  outline: none;
  border-color: var(--cyan-accent);
}

.scope-explorer-search::placeholder {
  color: var(--text-secondary);
}

.scope-explorer-no-results {
  font-size: 11.5px;
  color: var(--text-secondary);
  font-style: italic;
  margin: 8px 0 0;
}

.scope-tree,
.scope-tree-children {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.scope-tree-children {
  margin: 4px 0 4px calc(14px + var(--scope-depth, 0) * 2px);
  padding-left: 12px;
  border-left: 1px solid var(--section-divider);
}

.scope-tree-item {
  display: flex;
  flex-direction: column;
}

.scope-tree-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.scope-tree-node {
  appearance: none;
  width: 100%;
  min-width: 0;
  flex: 1;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 10px;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 8px;
  color: var(--text-primary);
  font-size: 12px;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.scope-tree-node:hover {
  background: var(--card-bg-hover);
  border-color: var(--cyan-accent);
}

.scope-tree-node.is-current {
  border-color: var(--cyan-accent);
  box-shadow: 0 0 0 1px var(--cyan-accent);
  color: var(--cyan-accent);
}

.scope-tree-node.is-in-collection {
  border-color: var(--jarvis-accent);
  color: var(--jarvis-accent);
}

.scope-tree-node.is-pending {
  border-style: dashed;
  border-color: var(--jarvis-accent);
  box-shadow: 0 0 0 1px var(--jarvis-accent);
}

.scope-tree-icon {
  color: var(--text-secondary);
  font-size: 11px;
  flex-shrink: 0;
}

.scope-tree-node.is-current .scope-tree-icon {
  color: var(--cyan-accent);
}

.scope-tree-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.scope-tree-type {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
  flex-shrink: 0;
}

.scope-tree-add {
  appearance: none;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  border: 1px solid var(--card-border);
  background: var(--card-bg);
  color: var(--text-secondary);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.scope-tree-add:hover {
  background: var(--card-bg-hover);
  border-color: var(--jarvis-accent);
  color: var(--jarvis-accent);
}

.scope-collection-bar {
  position: sticky;
  bottom: -22px;
  margin: 14px -20px -22px;
  padding: 10px 20px;
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--panel-bg);
  border-top: 1px solid var(--jarvis-accent);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
}

.scope-collection-count {
  font-size: 11.5px;
  color: var(--jarvis-accent);
  font-weight: 600;
  flex: 1;
}

.scope-collection-build,
.scope-collection-clear {
  appearance: none;
  border: none;
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 11.5px;
  cursor: pointer;
}

.scope-collection-build {
  background: rgba(179, 157, 255, 0.18);
  color: var(--jarvis-accent);
}

.scope-collection-build:hover {
  background: rgba(179, 157, 255, 0.28);
}

.scope-collection-clear {
  background: transparent;
  color: var(--text-secondary);
}

.scope-collection-clear:hover {
  color: var(--text-primary);
}

/* ---------------------------------------------------------------------
   Navigation History rail (V5 Phase 2.6 item E) - a vertical control in
   the toolbar, deliberately separate from the Depth (zoom) slider next to
   it: dots are investigation STEPS (focusTrail entries + the current
   selection), not zoom levels. Kept visually quiet (small dots, no
   labels) so it doesn't compete with the toolbar's primary controls -
   the step identity surfaces only on hover, via each dot's native
   title="" tooltip.
   --------------------------------------------------------------------- */

.nav-history-rail {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 10.5px;
  color: var(--text-secondary);
}

.nav-history-rail.is-empty {
  display: none;
}

.nav-history-kicker {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  white-space: nowrap;
}

.nav-history-dots {
  display: flex;
  align-items: center;
  gap: 5px;
}

.nav-history-dot {
  appearance: none;
  width: 8px;
  height: 8px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--panel-border);
  background: rgba(255, 255, 255, 0.12);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}

.nav-history-dot:hover:not(:disabled) {
  border-color: var(--cyan-accent);
  transform: scale(1.25);
}

.nav-history-dot.is-current {
  background: var(--cyan-accent);
  border-color: var(--cyan-accent);
  cursor: default;
}

.nav-history-dot:disabled {
  cursor: default;
}

/* ---------------------------------------------------------------------
   Return to Universe (V1-UX-1B) - a labeled, always-discoverable full
   reset, distinct from the Navigation History rail above (one step at a
   time) - see panels/return-to-universe.js's header comment. Sits in the
   toolbar next to #navHistoryRail; hidden (is-empty) when there is
   nothing to return from.
   --------------------------------------------------------------------- */

.return-to-universe.is-empty {
  display: none;
}

.return-to-universe-btn {
  appearance: none;
  border: 1px solid var(--panel-border);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-secondary);
  padding: 6px 12px;
  font-size: 11.5px;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}

.return-to-universe-btn:hover {
  color: var(--cyan-accent);
  border-color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.1);
}

.return-to-universe-btn:focus-visible {
  outline: 2px solid var(--cyan-accent);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------
   Relationship-color legend (V1-UX-1B) - the on-screen key for Universe's
   9 semantic relationship-type colors + the neutral "structural" fallback
   (see panels/relationship-legend.js's header comment; colors read
   directly from the same --rel-* custom properties declared at the top of
   this file, so the legend can never visually drift from the real edges).
   Floats over the bottom-left of the Universe canvas; renders nothing
   (is-empty) in any other lens.
   --------------------------------------------------------------------- */

.relationship-legend {
  position: absolute;
  left: 16px;
  bottom: 16px;
  z-index: 15;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.relationship-legend.is-empty {
  display: none;
}

.relationship-legend-toggle {
  appearance: none;
  border: 1px solid var(--panel-border);
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  color: var(--text-secondary);
  padding: 6px 10px;
  font-size: 10.5px;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}

.relationship-legend-toggle:hover {
  color: var(--text-primary);
  border-color: var(--cyan-accent);
}

.relationship-legend-toggle:focus-visible {
  outline: 2px solid var(--cyan-accent);
  outline-offset: 2px;
}

.relationship-legend-panel {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  max-width: 220px;
}

.relationship-legend-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 10.5px;
  color: var(--text-secondary);
}

.relationship-legend-swatch {
  flex: 0 0 auto;
  width: 16px;
  height: 0;
  border-top: 2px solid var(--swatch-color);
}

.relationship-legend-swatch.is-dashed {
  border-top-style: dashed;
}

.relationship-legend-label {
  white-space: nowrap;
}

/* ---------------------------------------------------------------------
   Node tooltip (V5 Phase 2.6 item D) - click-for-detail surface anchored
   to the selected node's on-screen position. A lightweight peek; the
   full record lives in the Passport panel (see the tooltip's own
   "Full detail in Passport" hint line, produced by
   lenses/universe.js's updateTooltip()).
   --------------------------------------------------------------------- */

.node-tooltip {
  position: absolute;
  z-index: 20;
  max-width: 240px;
  padding: 10px 30px 10px 12px;
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  /* V1-UX-4: this card is draggable (see lenses/universe.js's
     tooltip pointerdown/move/up handlers) - pointer-events must be enabled
     (the card used to be display-only) so it can receive its own pointer
     events instead of passing them through to the canvas underneath. */
  pointer-events: auto;
  cursor: grab;
  font-size: 11.5px;
  color: var(--text-secondary);
  touch-action: none;
}

.node-tooltip:focus-visible {
  outline: 2px solid var(--accent, #4fa3ff);
  outline-offset: 2px;
}

.node-tooltip.is-dragging {
  cursor: grabbing;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}

.node-tooltip-reset {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--panel-border);
  border-radius: 5px;
  color: var(--text-secondary);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

.node-tooltip-reset:hover {
  color: var(--text-primary);
  border-color: var(--text-secondary);
}

.node-tooltip-title {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 4px;
}

.node-tooltip-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
}

.node-tooltip-risk {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
}

.node-tooltip-risk--critical {
  background: rgba(239, 83, 80, 0.18);
  color: var(--red);
}

.node-tooltip-risk--elevated {
  background: rgba(240, 144, 74, 0.18);
  color: var(--orange);
}

.node-tooltip-risk--watch {
  background: rgba(232, 195, 74, 0.18);
  color: var(--yellow);
}

.node-tooltip-risk--neutral {
  background: rgba(124, 136, 150, 0.18);
  color: var(--gray);
}

.node-tooltip-type {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
}

.node-tooltip-line {
  margin: 3px 0;
}

.node-tooltip-hint {
  margin-top: 6px;
  font-style: italic;
  opacity: 0.7;
  font-size: 10.5px;
}

/* ---------------------------------------------------------------------
   Hover Passport Preview (V1-UX-1b Task 2) - a compact, cross-lens popover
   that follows the pointer. Deliberately reuses .node-tooltip's visual
   language (panel-bg/blur/border/shadow, .node-tooltip-risk/-type/-hint
   element classes) so it reads as the same family of surface, just with
   its own richer content + a Probe CTA the click-for-detail tooltip does
   not have.
   --------------------------------------------------------------------- */

.hover-preview {
  position: fixed;
  z-index: 30;
  max-width: 280px;
  padding: 12px 14px;
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
  /* Interactive (not the plain pointer-events:none of .node-tooltip) - it
     carries a real Probe button, and needs mouseenter/mouseleave to pin
     itself open while the cursor travels from the source lens onto it (see
     panels/hover-preview.js's HIDE_GRACE_MS). */
  pointer-events: auto;
  font-size: 11.5px;
  color: var(--text-secondary);
}

.hover-preview.hidden {
  display: none;
}

.hover-preview-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 6px;
}

.hover-preview-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.hover-preview-line {
  margin: 4px 0;
  line-height: 1.4;
}

.hover-preview-line strong {
  color: var(--text-primary);
  font-weight: 600;
  margin-right: 4px;
}

.hover-preview-impact {
  color: var(--text-primary);
  font-style: italic;
  opacity: 0.9;
}

.hover-preview-counts {
  display: flex;
  gap: 12px;
  font-size: 10.5px;
  opacity: 0.85;
}

.hover-preview-next-action {
  border-top: 1px solid var(--panel-border);
  padding-top: 6px;
  margin-top: 8px;
}

.hover-preview-probe-btn {
  pointer-events: auto;
  appearance: none;
  width: 100%;
  margin-top: 10px;
  border: 1px solid var(--cyan-accent);
  background: rgba(90, 209, 255, 0.1);
  color: var(--cyan-accent);
  padding: 6px 10px;
  font-size: 11.5px;
  font-weight: 600;
  border-radius: 6px;
  cursor: pointer;
  text-align: center;
  transition: background 0.18s ease;
}

.hover-preview-probe-btn:hover {
  background: rgba(90, 209, 255, 0.22);
}

/* V1-UX-3: every other Probe button (.passport-probe-btn and its
   documented "benefits every existing Probe button" comment above) already
   has a keyboard focus ring; this one - a separate, fully duplicated rule
   block rather than sharing that class - never got one. */
.hover-preview-probe-btn:focus-visible {
  outline: 2px solid var(--cyan-accent);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------
   "Manage Saved Views" modal (V5 Phase 4.6, engine/saved-views.js) -
   same visual pattern as the Scope Explorer modal above (backdrop +
   centered dialog), kept as its own namespace rather than sharing the
   .scope-explorer-* classes since the two modals are opened by unrelated
   features and this repo's convention (per this file's own header
   comment) is one clear visual language, not one shared abstraction
   forced across unrelated concepts.
   --------------------------------------------------------------------- */

.saved-views-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
}

.saved-views-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(4, 7, 12, 0.72);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.saved-views-dialog {
  position: relative;
  z-index: 1;
  width: min(560px, 92vw);
  max-height: 82vh;
  overflow-y: auto;
  padding: 18px 20px 22px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: 0 24px 60px -16px rgba(0, 0, 0, 0.75);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
}

.saved-views-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}

.saved-views-header h2 {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--cyan-accent);
  margin: 0;
}

.saved-views-close {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: 13px;
  cursor: pointer;
  padding: 4px 6px;
}

.saved-views-close:hover {
  color: var(--text-primary);
}

.saved-views-hint {
  font-size: 11.5px;
  color: var(--text-secondary);
  line-height: 1.5;
  margin: 4px 0 14px;
}

.saved-views-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.saved-views-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--card-border);
  border-radius: 8px;
  background: var(--card-bg);
}

.saved-views-item-kind {
  flex-shrink: 0;
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 999px;
  color: var(--text-secondary);
  background: rgba(124, 136, 150, 0.14);
}

.saved-views-item-kind--dashboard {
  color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.14);
}

.saved-views-item-kind--report {
  color: var(--jarvis-accent);
  background: rgba(179, 157, 255, 0.14);
}

.saved-views-item-name {
  flex: 1;
  font-size: 12.5px;
  color: var(--text-primary);
}

.saved-views-item-example-badge {
  flex-shrink: 0;
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
  opacity: 0.7;
  font-style: italic;
}

/* ---------------------------------------------------------------------
   Spider lens (V5 Phase 4, docs/V5_DESIGN_SPEC.md §4) - a radar chart over
   the existing operational domains. Structured/centered like Risk Board,
   not spatial like Universe: one static SVG chart, centered in the
   workspace, with a small header above it.
   --------------------------------------------------------------------- */

.spider-chart {
  position: absolute;
  inset: 0;
  overflow: auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

.spider-surface {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 32px;
  width: 100%;
  max-width: 560px;
}

.spider-header {
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.spider-kicker {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--cyan-accent);
}

.spider-title {
  margin: 0;
  font-size: 19px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

.spider-subtitle {
  margin: 2px 0 0;
  font-size: 11.5px;
  color: var(--text-secondary);
  opacity: 0.85;
}

.spider-slice {
  font-size: 11px;
  color: var(--text-secondary);
}

.spider-svg-wrap {
  width: 100%;
  max-width: 440px;
  aspect-ratio: 1 / 1;
}

.spider-svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

.spider-ring {
  fill: none;
  stroke: var(--panel-border);
  stroke-width: 1;
}

.spider-spoke {
  stroke: var(--panel-border);
  stroke-width: 1;
}

.spider-polygon {
  --spider-fill-color: var(--gray);
  fill: var(--spider-fill-color);
  fill-opacity: 0.22;
  stroke: var(--spider-fill-color);
  stroke-width: 2;
  transition: fill 0.25s ease, stroke 0.25s ease;
}

.spider-vertex {
  --spider-vertex-color: var(--gray);
  fill: var(--bg-void);
  stroke: var(--spider-vertex-color);
  stroke-width: 2.5;
}

.spider-vertex.is-clickable {
  cursor: pointer;
}

.spider-vertex.is-clickable:hover,
.spider-vertex.is-clickable:focus-visible {
  fill: var(--spider-vertex-color);
}

.spider-axis-label {
  fill: var(--text-secondary);
  font-size: 11px;
  text-transform: capitalize;
  letter-spacing: 0.02em;
  /* V1-UX-3 fix: this text has no click handler (lenses/spider.js's
     drawLabels() never wires one) but SVG text still captures pointer
     events over its glyph area by default. When a spoke's score positions
     its .spider-vertex circle near the outer label ring, the label's own
     hit area sat on top of the vertex in real browser hit-testing (not a
     test-tool artifact - confirmed via direct DOM click dispatch bypassing
     the occluded coordinate), silently blocking a real mouse click on a
     primary Probe affordance. pointer-events: none lets clicks pass
     through to whatever's actually underneath - the vertex circle - with
     zero visual or layout change. */
  pointer-events: none;
}

.spider-empty {
  text-align: center;
  color: var(--text-secondary);
  font-size: 13px;
  padding: 40px 0;
}

.spider-empty.hidden {
  display: none;
}

/* ---------------------------------------------------------------------
   Text View lens (V5 Phase 4, docs/V5_DESIGN_SPEC.md §5) - the same
   investigation as a structured, keyboard-navigable outline: collapsible
   <details> sections in the exact §5.2 order, typographic rather than
   spatial (same "document, not diagram" register as Risk Board/Passport).
   --------------------------------------------------------------------- */

.text-view-container {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

.text-view-surface {
  max-width: 720px;
  margin: 0 auto;
  padding: 28px 32px 60px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.text-view-header {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--section-divider);
  margin-bottom: 8px;
}

.text-view-kicker {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--cyan-accent);
}

.text-view-title {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

.text-view-time {
  font-size: 11.5px;
  color: var(--text-secondary);
}

/* Sprint UX-2C: the operational lede under the Text View title — the
   selected object's summary (what is happening) rendered before any
   section or identifier, matching the Passport overview's progressive-
   detail register. */
.text-view-lede {
  margin: 4px 0 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-secondary);
}

.text-view-empty {
  color: var(--text-secondary);
  font-size: 13px;
  padding: 20px 0;
}

.text-view-section {
  border-top: 1px solid var(--section-divider);
  padding: 14px 0;
}

.text-view-section:first-of-type {
  border-top: none;
}

.text-view-section-title {
  cursor: pointer;
  list-style: none;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--text-secondary);
  padding: 2px 0;
  display: flex;
  align-items: center;
  gap: 6px;
}

.text-view-section-title::-webkit-details-marker {
  display: none;
}

.text-view-section-title::before {
  content: '▸';
  display: inline-block;
  transition: transform 0.15s ease;
  color: var(--cyan-accent);
}

.text-view-section[open] > .text-view-section-title::before {
  transform: rotate(90deg);
}

.text-view-section-body {
  padding: 10px 0 2px 4px;
}

.text-view-empty-line {
  margin: 0;
  color: var(--text-secondary);
  font-size: 12px;
}

.text-view-hierarchy {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.text-view-hierarchy-item {
  padding-left: calc(var(--depth, 0) * 18px);
  position: relative;
}

.text-view-hierarchy-item:not(:last-child)::before {
  content: '';
  position: absolute;
  left: calc(var(--depth, 0) * 18px + 8px);
  top: 26px;
  bottom: -4px;
  width: 1px;
  background: var(--section-divider);
}

.text-view-hierarchy-ref {
  gap: 8px;
}

.text-view-hierarchy-type {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
  min-width: 66px;
}

.text-view-hierarchy-label {
  flex: 1;
}

.text-view-hierarchy-current {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--cyan-accent);
}

.text-view-hierarchy-item.is-selected .text-view-hierarchy-ref {
  border-color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.08);
}

.text-view-risk-badge {
  display: inline-flex;
}

.text-view-ref {
  appearance: none;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  margin: 2px 0;
  border-radius: 8px;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  color: var(--text-primary);
  text-align: left;
  font-size: 12.5px;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease;
}

.text-view-ref:hover,
.text-view-ref:focus-visible {
  background: var(--card-bg-hover);
  border-color: var(--cyan-accent);
}

.text-view-ref-label {
  flex: 1;
}

.text-view-ref-meta,
.text-view-entry-meta {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
}

.text-view-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.text-view-list-item {
  font-size: 12.5px;
}

.text-view-entry.is-dormant {
  opacity: 0.55;
}

.text-view-entry-summary {
  margin: 4px 0 0 10px;
  font-size: 11.5px;
  color: var(--text-secondary);
  line-height: 1.5;
}

.text-view-entry-foot {
  margin: 4px 0 0 10px;
  display: flex;
  gap: 10px;
  font-size: 10.5px;
  color: var(--text-secondary);
}

.text-view-dating {
  display: flex;
  gap: 14px;
  font-size: 11px;
  color: var(--text-secondary);
  margin-bottom: 6px;
}

.text-view-history li {
  padding: 6px 10px;
}

.text-view-source-records .source-cite {
  font-size: 11px;
}

/* ---------------------------------------------------------------------
   Collection Passport (V5 Phase 4, docs/V5_HANDOVER.md §9.1/§10.2) -
   reuses every .passport-* section style above unchanged; only the
   overview header (member list instead of a single object's fields) is
   new.
   --------------------------------------------------------------------- */

.passport-overview--collection .passport-overview-summary {
  margin-bottom: 4px;
}

.passport-collection-members {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.passport-collection-member {
  appearance: none;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 9px;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  font-size: 12px;
  transition: background 0.14s ease, border-color 0.14s ease;
}

.passport-collection-member:hover,
.passport-collection-member:focus-visible {
  background: var(--card-bg-hover);
  border-color: var(--cyan-accent);
}

.passport-collection-member-label {
  flex: 1;
}

.passport-collection-member-type {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
}

/* ---------------------------------------------------------------------
   Conductor Studio (V5 Phase 4.7, docs/V5_HANDOVER.md §11)

   The 6th workspace lens - a calm, professional "strategic operations
   room," deliberately NOT a chat-bubble/chatbot layout (per the phase
   brief's explicit visual direction). It gets its OWN 3-column layout
   (nav / center / right) rather than slotting into #mainLayout's three
   columns like every other lens does, since its left nav (9 sub-panels)
   and right panel (Scope/Time/Evidence/Related Objects/Jarvis Summary)
   are both distinct from the standing Dashboard/Passport left panel and
   persistent Jarvis panel - see app.js's applyLensVisibility(), which
   swaps #mainLayout and #conductorStudio as a pair rather than hiding one
   column at a time.

   Still draws from the exact same :root tokens as every other surface -
   no new color vocabulary, only new layout for a different kind of room.
   --------------------------------------------------------------------- */

.conductor-studio {
  flex: 1;
  display: grid;
  grid-template-columns: 220px 1fr 300px;
  min-height: 0;
}

.cs-nav {
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  border-right: 1px solid var(--panel-border);
  padding: 14px 10px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.cs-nav-btn {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  text-align: left;
  padding: 9px 12px;
  border-radius: 8px;
  font-size: 12.5px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  transition: background 0.16s ease, color 0.16s ease;
}

.cs-nav-btn:hover {
  color: var(--text-primary);
  background: rgba(255, 255, 255, 0.05);
}

.cs-nav-btn.active {
  background: rgba(90, 209, 255, 0.14);
  color: var(--cyan-accent);
}

.cs-center {
  overflow-y: auto;
  padding: 20px 24px;
}

.cs-section-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 4px;
}

.cs-section-header h2 {
  font-size: 14px;
  margin: 0;
  color: var(--text-primary);
  display: flex;
  align-items: center;
  gap: 8px;
}

.cs-row-count {
  font-size: 11.5px;
  color: var(--text-secondary);
  margin-left: auto;
}

.cs-section-note {
  font-size: 11.5px;
  font-style: italic;
  opacity: 0.75;
  margin: 4px 0 14px;
}

.cs-table-container {
  margin-top: 10px;
  overflow-x: auto;
}

/* --- Recommendation action bar (Approve/Reject/Modify/Request More
   Evidence/Assign/Defer + optional rationale) - UI-only interaction
   capture, no persistence. --------------------------------------------- */

.cs-action-bar {
  margin-top: 16px;
  padding: 14px 16px;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 12px;
}

.cs-action-bar-header {
  font-size: 12.5px;
  color: var(--text-primary);
  margin-bottom: 6px;
}

.cs-action-bar-evidence {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.5;
  margin-bottom: 10px;
}

.cs-rationale-input {
  width: 100%;
  min-height: 52px;
  resize: vertical;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 12px;
  padding: 8px 10px;
  margin-bottom: 10px;
}

.cs-action-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.cs-action-btn {
  appearance: none;
  border: 1px solid var(--panel-border);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-primary);
  padding: 7px 14px;
  border-radius: 999px;
  font-size: 12px;
  cursor: pointer;
  transition: background 0.16s ease, border-color 0.16s ease, color 0.16s ease;
}

.cs-action-btn:hover,
.cs-action-btn:focus-visible {
  border-color: var(--cyan-accent);
  color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.1);
}

.cs-action-confirm {
  margin-top: 10px;
  font-size: 11.5px;
  color: var(--text-secondary);
}

.cs-action-confirm.is-flashing {
  color: var(--cyan-accent);
}

/* --- Mock panel cards (docs/RULES.md §12) ------------------------------ */

.cs-card-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 14px;
}

.cs-card {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 12px;
  padding: 14px 16px;
}

.cs-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.cs-card-top h4 {
  margin: 0;
  font-size: 13px;
  color: var(--text-primary);
  font-weight: 600;
}

.cs-card-meta {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
  margin: 6px 0;
}

.cs-card p {
  margin: 6px 0 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-secondary);
}

.cs-card-status {
  display: inline-block;
  margin-top: 10px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: rgba(179, 157, 255, 0.12);
  color: var(--jarvis-accent);
}

.cs-metric-value {
  font-size: 24px;
  font-weight: 700;
  color: var(--text-primary);
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.cs-metric-delta {
  font-size: 12px;
  font-weight: 600;
  color: var(--green);
}

.cs-trend-arrow {
  font-size: 11px;
}

.cs-trend-up {
  color: var(--orange);
}

.cs-trend-down {
  color: var(--green);
}

.cs-trend-flat {
  color: var(--gray);
}

/* The mandatory "Future" badge (docs/RULES.md §12 condition 2) - a soft
   violet tint (the same --jarvis-accent family already used elsewhere in
   this app for "not a hard data surface, copilot/aspirational-flavored"
   content), deliberately distinct from the risk color vocabulary
   (red/orange/yellow/green/gray) so it is never mistaken for a risk state. */
.cs-future-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: rgba(179, 157, 255, 0.14);
  color: var(--jarvis-accent);
  border: 1px dashed rgba(179, 157, 255, 0.5);
  white-space: nowrap;
}

.cs-future-action-btn {
  appearance: none;
  border: 1px solid var(--panel-border);
  background: transparent;
  color: var(--text-secondary);
  padding: 6px 12px;
  border-radius: 8px;
  font-size: 11.5px;
  margin-left: auto;
  cursor: not-allowed;
  opacity: 0.6;
}

/* --- Right panel: Scope / Time / Evidence / Related Objects / Jarvis
   Summary - real data, normal governance, same "context surface" identity
   as .jarvis-panel/.panel elsewhere in this app. ------------------------- */

.cs-right {
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  border-left: 1px solid var(--panel-border);
  padding: 16px 18px;
  overflow-y: auto;
  font-size: 12.5px;
  color: var(--text-secondary);
}

.cs-right-block {
  margin-bottom: 20px;
}

.cs-right-block h3 {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--cyan-accent);
  margin: 0 0 8px;
}

.cs-right-row {
  padding: 6px 0;
  border-bottom: 1px solid var(--section-divider);
  line-height: 1.5;
}

.cs-right-row:last-child {
  border-bottom: none;
}

.cs-right-row-clickable {
  cursor: pointer;
  transition: color 0.14s ease;
}

.cs-right-row-clickable:hover {
  color: var(--cyan-accent);
}

.cs-jarvis-next {
  padding: 8px 10px;
  background: rgba(179, 157, 255, 0.08);
  border: 1px solid rgba(179, 157, 255, 0.25);
  border-radius: 8px;
}

.cs-mono {
  font-family: 'SF Mono', Consolas, monospace;
  font-size: 10.5px;
  opacity: 0.8;
}

.cs-empty-note {
  font-style: italic;
  opacity: 0.7;
  font-size: 11px;
}

/* ---------------------------------------------------------------------
   Universe Search (V1-UX-2A: Universe Focus + Investigation Flow) - the
   toolbar's "search-to-focus" control (panels/universe-search.js). A
   small pill-shaped text field plus a floating results dropdown, styled
   after the same tokens .scope-bar-inner/.scope-explorer-search/
   .scope-tree-node already use so it reads as part of the same toolbar
   chrome, not a new visual language. position: relative so the dropdown
   below can anchor to this element rather than the page.
   --------------------------------------------------------------------- */

.universe-search {
  position: relative;
}

.universe-search-field {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  transition: border-color 0.18s ease, background 0.18s ease;
}

.universe-search-field:focus-within {
  border-color: var(--cyan-accent);
  background: rgba(255, 255, 255, 0.05);
}

.universe-search-icon {
  color: var(--text-secondary);
  font-size: 12px;
  flex-shrink: 0;
}

.universe-search-input {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--text-primary);
  font-size: 12px;
  font-family: inherit;
  width: 168px;
  padding: 0;
}

.universe-search-input:focus {
  outline: none;
}

.universe-search-input::placeholder {
  color: var(--text-secondary);
}

.universe-search-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  width: min(340px, 80vw);
  max-height: 60vh;
  overflow-y: auto;
  list-style: none;
  margin: 0;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  box-shadow: 0 16px 40px -12px rgba(0, 0, 0, 0.7);
}

.universe-search-results.hidden {
  display: none;
}

.universe-search-empty {
  padding: 8px 10px;
  font-size: 11.5px;
  color: var(--text-secondary);
}

.universe-search-result {
  appearance: none;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 10px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 7px;
  color: var(--text-primary);
  font-size: 12px;
  text-align: left;
  cursor: pointer;
}

.universe-search-result:hover,
.universe-search-result.is-active {
  background: var(--card-bg-hover, rgba(255, 255, 255, 0.06));
  border-color: var(--cyan-accent);
}

.universe-search-result-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.universe-search-result-type {
  flex-shrink: 0;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-secondary);
}

/* ---------------------------------------------------------------------
   Functional Radar (V1-UX-2B: Progressive Risk Board + Functional Radar) -
   a toggle button (in the toolbar) + flyout dialog (panels/functional-
   radar.js) grouping the operational graph into Engineering/Planning/
   Manufacturing/Procurement/Quality. Structurally the same
   toggle-button + backdrop + dialog pattern as the Scope Explorer
   (.scope-bar-reset / .scope-explorer-overlay / .scope-explorer-dialog),
   reusing the same tokens so it reads as the same toolbar chrome.
   --------------------------------------------------------------------- */

.functional-radar-toggle-btn {
  appearance: none;
  border: 1px solid var(--panel-border);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-secondary);
  padding: 6px 12px;
  font-size: 11.5px;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}

.functional-radar-toggle-btn:hover {
  color: var(--cyan-accent);
  border-color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.1);
}

.functional-radar-toggle-btn.is-active {
  background: rgba(90, 209, 255, 0.14);
  color: var(--cyan-accent);
  border-color: var(--cyan-accent);
}

.functional-radar-toggle-btn:focus-visible {
  outline: 2px solid var(--cyan-accent);
  outline-offset: 2px;
}

.functional-radar-overlay.hidden {
  display: none;
}

.functional-radar-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 12vh;
}

.functional-radar-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(6, 10, 16, 0.6);
}

.functional-radar-dialog {
  position: relative;
  z-index: 1;
  width: min(720px, 92vw);
  max-height: 76vh;
  overflow-y: auto;
  padding: 20px 22px 24px;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: 0 24px 60px -16px rgba(0, 0, 0, 0.75);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
}

.functional-radar-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

.functional-radar-header h2 {
  margin: 0 0 4px;
  font-size: 16px;
}

.functional-radar-subtitle {
  margin: 0;
  font-size: 12px;
  color: var(--text-secondary);
}

.functional-radar-close {
  appearance: none;
  border: 1px solid var(--panel-border);
  background: transparent;
  color: var(--text-secondary);
  width: 28px;
  height: 28px;
  border-radius: 8px;
  cursor: pointer;
  flex-shrink: 0;
}

.functional-radar-close:hover {
  color: var(--cyan-accent);
  border-color: var(--cyan-accent);
}

.functional-radar-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px;
}

.functional-radar-group {
  padding: 12px 14px;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 10px;
  /* V1-UX-3: this is itself a CSS Grid item of .functional-radar-groups
     (repeat(auto-fit, minmax(280px, 1fr))) - grid items also default to
     min-width: auto, so without this override the SAME nowrap-text sizing
     bug described on .functional-radar-object-row could still force this
     whole column wider than its track. See that rule's comment. */
  min-width: 0;
}

.functional-radar-group.is-empty {
  opacity: 0.65;
}

.functional-radar-group-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.functional-radar-group-label {
  font-weight: 600;
  font-size: 13px;
  flex: 1;
}

.functional-radar-group-count {
  font-variant-numeric: tabular-nums;
  font-size: 11.5px;
  color: var(--text-secondary);
  background: rgba(255, 255, 255, 0.06);
  padding: 1px 7px;
  border-radius: 999px;
}

.functional-radar-group-flag--critical {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--red);
  border: 1px solid var(--red);
  padding: 1px 6px;
  border-radius: 999px;
}

.functional-radar-object-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.functional-radar-object-row {
  display: grid;
  gap: 4px;
  /* V1-UX-3 fix: a grid/flex item's default min-width is "auto" (its
     content's own max-content size), not 0. .functional-radar-object-label
     below sets white-space:nowrap so its intrinsic min-content width IS
     its full unwrapped text width - that width was bubbling up through
     every ancestor here (none of which overrode min-width), forcing this
     row wider than its 280px grid column and visibly overlapping the
     neighboring Functional Radar column. min-width: 0 on every ancestor in
     this chain lets text-overflow: ellipsis on the label actually clip
     instead of pushing the whole row wider than the layout. */
  min-width: 0;
}

.functional-radar-object {
  appearance: none;
  width: 100%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: flex-start;
  padding: 7px 9px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 7px;
  color: var(--text-primary);
  font-size: 12px;
  text-align: left;
  cursor: pointer;
}

.functional-radar-object:hover {
  background: var(--card-bg-hover, rgba(255, 255, 255, 0.06));
  border-color: var(--cyan-accent);
}

.functional-radar-object-top {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-width: 0;
}

.functional-radar-object-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.functional-radar-object-detail {
  font-size: 11px;
  color: var(--text-secondary);
}

.functional-radar-object-detail--owner {
  font-style: italic;
}

/* Sprint UX-2C: the object's operational type noun (ECO / NCR / Work
   Order / ...), shown beside the label inside a Functional Radar row when
   it differs from the function group's own label. Muted + uppercase so it
   reads as a category tag, not a competing title. */
.functional-radar-object-type {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 4px;
  padding: 1px 6px;
}

.functional-radar-continuity-actions,
.risk-card-continuity-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.functional-radar-continuity-btn,
.risk-card-continuity-btn {
  appearance: none;
  border: 1px solid var(--card-border);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-secondary);
  border-radius: 999px;
  padding: 3px 7px;
  font-size: 10px;
  line-height: 1.2;
  cursor: pointer;
}

.functional-radar-continuity-btn:hover,
.functional-radar-continuity-btn.is-default,
.risk-card-continuity-btn:hover {
  color: var(--cyan-accent);
  border-color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.1);
}

.risk-card-continuity-actions .risk-card-probe-btn {
  margin-top: 0;
}

.functional-radar-object-more {
  font-size: 11px;
  color: var(--text-secondary);
  padding: 4px 9px;
}

.functional-radar-empty-note {
  font-size: 11.5px;
  color: var(--text-secondary);
  font-style: italic;
  margin: 4px 0 0;
}

.functional-radar-risk-badge {
  flex-shrink: 0;
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid currentColor;
}

.functional-radar-risk-badge--critical {
  color: var(--red);
}

.functional-radar-risk-badge--elevated {
  color: var(--orange);
}

.functional-radar-risk-badge--watch {
  color: var(--yellow);
}


/* V1-UX-2D recursive investigation foundation. Shared component styling only;
   it renders existing governed layers progressively and terminates naturally
   when deeper relationships do not exist. */
.recursive-investigation-card {
  padding: 12px;
  border-radius: 12px;
  background: rgba(7, 18, 28, 0.72);
  border: 1px solid rgba(83, 210, 255, 0.18);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.02);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.recursive-investigation-header {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.recursive-investigation-kicker,
.recursive-investigation-step {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--cyan-accent);
}

.recursive-investigation-header h3,
.recursive-investigation-layer h4 {
  margin: 0;
  color: var(--text-primary);
}

.recursive-investigation-header h3 {
  font-size: 14px;
}

.recursive-investigation-layers {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.recursive-investigation-layer {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(150, 180, 210, 0.12);
}

.recursive-investigation-layer p,
.recursive-investigation-termination,
.recursive-investigation-list {
  margin: 4px 0 0;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--text-secondary);
}

.recursive-investigation-params {
  margin: 8px 0 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 6px;
}

.recursive-investigation-params div {
  padding: 6px 8px;
  border-radius: 8px;
  background: rgba(150, 180, 210, 0.08);
}

.recursive-investigation-params dt {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
}

.recursive-investigation-params dd {
  margin: 2px 0 0;
  font-size: 11px;
  color: var(--text-primary);
}

.recursive-investigation-list {
  padding-left: 16px;
}

.recursive-investigation-termination {
  padding: 8px 10px;
  border-radius: 9px;
  background: rgba(240, 144, 74, 0.1);
  border: 1px solid rgba(240, 144, 74, 0.24);
  color: rgba(240, 220, 200, 0.9);
}

.passport-section.is-targeted {
  border-color: rgba(83, 210, 255, 0.64);
  background: rgba(83, 210, 255, 0.06);
  border-radius: 12px;
  padding: 12px;
  transition: background 0.2s ease, border-color 0.2s ease;
}

/* ---------------------------------------------------------------------
   V1-UX-2E (Operational Language & Progressive Disclosure) - every rule
   below reuses existing tokens only (--text-secondary, --cyan-accent,
   --panel-border, the existing pill/badge shapes already established by
   .passport-section-count / .demo-derived-badge / .node-tooltip-type) -
   no new color, radius, or shadow language is introduced.
   --------------------------------------------------------------------- */

/* Risk Board: named business-impact tags, leading the card ahead of the
   who/what line - see lenses/risk-board.js's renderCardContent(). */
.risk-card-impact-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 6px;
}

.risk-impact-tag {
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-secondary);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  padding: 1px 8px;
  white-space: nowrap;
}

.risk-impact-tag--primary {
  color: var(--cyan-accent);
  background: rgba(90, 209, 255, 0.12);
  border-color: rgba(90, 209, 255, 0.3);
}

/* Universe hover tooltip: the raw canonical label, once the tooltip title,
   is now a secondary muted line beneath the business headline - see
   lenses/universe.js's updateTooltip(). */
.node-tooltip-line--muted {
  color: var(--text-secondary);
  font-size: 10.5px;
  opacity: 0.85;
}

/* Passport Evidence: a single lead finding sentence ahead of the existing
   supporting entries - see panels/passport.js's renderEvidenceSection(). */
.passport-evidence-conclusion {
  margin: 6px 0 10px;
  font-size: 12px;
  line-height: 1.55;
  color: var(--text-secondary);
}

.passport-evidence-conclusion strong {
  color: var(--text-primary);
  font-weight: 600;
}

/* Passport Source Records: grouped by business-facing system (Planning /
   ERP / OpsConductor) instead of one flat list - see panels/passport.js's
   renderSourceRecordsSection(). */
.source-record-group {
  margin-top: 10px;
}

.source-record-group:first-of-type {
  margin-top: 6px;
}

.source-record-group-label {
  display: block;
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
  margin-bottom: 4px;
}
