/* MS3404 Dashboard — Design System from DESIGN.md */

@font-face {
  font-family: 'Aptos';
  src: url('/fonts/Inter-Regular.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Aptos';
  src: url('/fonts/Inter-Medium.woff2') format('woff2');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Aptos';
  src: url('/fonts/Inter-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'Aptos Display';
  src: url('/fonts/Inter-Bold.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}
/* Sora ExtraBold is the Ghost wordmark face. Subset to the five glyphs of
   "Ghost" (1KB) and self-hosted, so the lockup renders in the real face rather
   than substituting — the same trap that made the footer wordmark look wrong
   when its font was not installed. Sora is SIL OFL, so embedding is permitted. */
@font-face {
  font-family: 'Sora';
  src: url('/fonts/Sora-ExtraBold-Ghost.woff2') format('woff2');
  font-weight: 800;
  font-display: swap;
}

@font-face {
  font-family: 'Cascadia Code';
  src: url('/fonts/CascadiaCode-Regular.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}

:root {
  /* Surfaces */
  --bg: #0b0f14;
  --surface: #111820;
  --surface-raised: #17212b;
  --surface-border: #26313d;

  /* Text */
  --text-primary: #f3f7fb;
  --text-muted: #94a3b3;
  /* 4.5:1 against --surface (6.02) and --surface-raised (5.44). The prior
     #657385 measured 3.37-3.70, under the DESIGN.md minimum. */
  --text-subtle: #8a97a8;

  /* Accent */
  --accent: #00bcf2;
  --accent-strong: #40d9ff;
  --accent-soft: rgba(0, 188, 242, 0.14);

  /* Semantic */
  --success: #6bb700;
  --warning: #ffb900;
  --error: #d13438;
  --info: #00bcf2;

  /* Domain */
  --legit: #6bb700;
  --pirate: #d13438;
  --evidence: #ffb900;

  /* Interactive */
  --focus-ring: #40d9ff;
  --button-primary-bg: #00bcf2;
  --button-primary-text: #0b0f14;
  --button-primary-hover: #40d9ff;

  /* Typography */
  --font-display: 'Aptos Display', 'Segoe UI', system-ui, sans-serif;
  --font-body: 'Aptos', 'Segoe UI', system-ui, sans-serif;
  --font-mono: 'Cascadia Code', 'Consolas', 'Courier New', monospace;
  --font-mono-features: tabular-nums;

  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 2rem;

  /* Spacing — rem so the whole design scales with the root size (see html below).
     Values are the DESIGN.md px scale divided by the 16px reference root, so at
     full size they compute to exactly 2/4/8/16/24/32/48px. */
  --space-2xs: 0.125rem;
  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  --space-2xl: 3rem;

  /* Radius */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --radius-full: 9999px;

  /* Motion */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --duration-micro: 75ms;
  --duration-short: 150ms;
  --duration-medium: 300ms;
  --duration-pipeline: 500ms;
}

/* Reset */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Fluid root size (MS3404-72).
   The dashboard is a fixed-composition ops view: it is meant to be read whole,
   not scrolled. Rather than re-flow it on smaller screens — which would break the
   33/67 grid and the type scale DESIGN.md fixes — the whole design scales down
   uniformly, the way browser zoom does. Every ratio in DESIGN.md is preserved;
   only the absolute size changes.

   min() takes whichever axis is tighter, so a short laptop drives the scale as
   much as a narrow one — height was the binding constraint in the reported case.
   The divisors put the design at its full 16px root on a 1740x980 viewport and
   above; the 11px floor stops it becoming unreadable on very small screens. */
html {
  /* px, not rem: inside this rule rem still means the inherited 16px root, so
     rem here reads as circular even though it computes the same. */
  font-size: clamp(11px, min(0.92vw, 1.63vh), 16px);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: var(--font-body);
  font-weight: 400;
  line-height: 1.4;
  color: var(--text-primary);
  background: var(--bg);
  /* 80rem is DESIGN.md's 1280px minimum expressed in design units: it holds the
     composition at full size, and shrinks with the root rather than forcing a
     horizontal scrollbar on a smaller screen. dvh so mobile browser chrome
     collapsing does not clip the footer. */
  min-width: 80rem;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Header */
.ghost-banner {
  background: var(--warning);
  color: var(--bg);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-align: center;
  padding: 0.45rem 1rem;
  border-bottom: 1px solid rgba(0, 0, 0, 0.2);
}

.ghost-banner.hidden {
  display: none;
}

.header {
  /* Sized for the Ghost lockup: 30px mark plus its clear space (half a mark
     width top and bottom) needs 60px. max() holds that floor while still
     scaling up with the root. */
  height: max(60px, 3.75rem);
  background: var(--surface);
  border-bottom: 1px solid var(--surface-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--space-lg);
  flex-shrink: 0;
}

.header-left {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.ms-logo { flex-shrink: 0; }

/* Ghost horizontal lockup — the product identity, replacing the MS3404 mark.
   Static by design: the kit forbids alert red on a logo or lockup, and the live
   state (which can go red) is a separate indicator on the pirate panel. */
.ghost-lockup {
  /* Kit minimum for the horizontal lockup is 30px, measured on mark height. */
  --ghost-lockup-size: max(30px, 1.9rem);
  display: inline-flex;
  align-items: center;
  gap: calc(var(--ghost-lockup-size) / 2);   /* clear space: half the mark width */
  flex-shrink: 0;
}

.ghost-lockup-mark {
  width: var(--ghost-lockup-size);
  height: var(--ghost-lockup-size);
  display: block;
}

.ghost-lockup-word {
  font-family: 'Sora', var(--font-display);
  font-weight: 800;
  font-size: calc(var(--ghost-lockup-size) * 0.72);
  letter-spacing: -0.02em;
  line-height: 1;
  color: #F5F6F7;   /* Accent Foreground — the kit's type colour on dark */
}

.header-title {
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 400;
  color: var(--text-primary);
}

.header-id {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--accent);
}

.header-sep {
  color: var(--surface-border);
  margin: 0 var(--space-xs);
}

.header-right {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

/* Ghost product state indicator (MS3404-73).
   The brand kit permits one animated mark on screen at a time, so this is the
   only animated mark in the app. Brand colours stay inside the mark — the
   surrounding UI keeps the DESIGN.md palette. */
.ghost-state {
  /* The kit sets a hard 24px floor for the mark. max() keeps it scaling with
     the root on larger screens without ever dropping under that floor. */
  --ghost-mark-size: max(24px, 1.6rem);
  display: inline-flex;
  align-items: center;
  /* Clear space is half the mark's width on all sides, per the kit. */
  gap: calc(var(--ghost-mark-size) / 2);
  padding-right: calc(var(--ghost-mark-size) / 2);
  margin-right: var(--space-xs);
  border-right: 1px solid var(--surface-border);
}

.ghost-state-mark {
  width: var(--ghost-mark-size);
  height: var(--ghost-mark-size);
  display: block;
  flex-shrink: 0;
}

.ghost-state-label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}

/* Detected is the one state that carries the kit's alert red, and only ever as
   a product state — never on a logo or lockup. */
.ghost-state[data-state="detected"] .ghost-state-label { color: var(--error); }
.ghost-state[data-state="guarding"] .ghost-state-label { color: var(--success); }

/* An <img>-loaded SVG resolves prefers-reduced-motion against the viewer's own
   setting, which we cannot rely on reaching it, so the swap to the static mark
   is done here where it is ours to control. */
@media (prefers-reduced-motion: reduce) {
  .ghost-state-mark { content: url('/brand/ghost-mark.svg'); }
}

.header-meta {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-left: var(--space-sm);
}

.header-meta strong {
  color: var(--text-primary);
  font-weight: 600;
}

/* Badges */
.badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 1;
}

.badge-info    { background: var(--accent-soft); color: var(--accent); }
.badge-success { background: var(--success); color: var(--bg); }
.badge-warning { background: var(--warning); color: var(--bg); }
.badge-error   { background: var(--error); color: var(--text-primary); }

/* Dashboard grid */
.dashboard {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: var(--space-md);
  padding: var(--space-md);
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* Left panel */
.panel-left {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  overflow-y: auto;
}

.section { display: flex; flex-direction: column; gap: var(--space-sm); }

.section-label {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0.02em;
}

/* Scenario dropdown */
.scenario-select {
  width: 100%;
  height: 2.75rem;
  padding: 0 var(--space-md);
  background: var(--surface);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%2394a3b3' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}

.scenario-select:focus {
  outline: 2px solid var(--focus-ring);
  outline-offset: -2px;
}

.scenario-select option {
  background: var(--surface);
  color: var(--text-primary);
}

/* Scenario detail card */
.live-event-blurb {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--text-muted);
}

.scenario-detail {
  background: var(--surface);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  padding: var(--space-md);
}

.scenario-detail.hidden { display: none; }

.detail-header {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
}

.detail-title {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--accent);
}

.detail-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-xs) var(--space-md);
  font-size: var(--text-sm);
}

.detail-grid dt {
  color: var(--text-muted);
  font-weight: 500;
  white-space: nowrap;
}

.detail-grid dd { color: var(--text-primary); }

.mono { font-family: var(--font-mono); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }

.risk-badge {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: 2px 0.5rem;
  border-radius: var(--radius-sm);
  background: var(--error);
  color: var(--text-primary);
}

/* Run Simulation button */
.btn-simulate {
  width: 100%;
  height: 2.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  background: var(--button-primary-bg);
  color: var(--button-primary-text);
  border: none;
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--duration-short) var(--ease);
  flex-shrink: 0;
}

.btn-simulate:hover:not(:disabled) { background: var(--button-primary-hover); }

.btn-simulate:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.btn-simulate:disabled {
  background: var(--surface-border);
  color: var(--text-subtle);
  cursor: not-allowed;
}

.btn-simulate.running { background: var(--surface-border); color: var(--text-muted); }
.btn-simulate.complete { background: var(--success); color: var(--bg); cursor: default; }

.btn-reset {
  width: 100%;
  height: 2.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  transition: background var(--duration-short) var(--ease), border-color var(--duration-short) var(--ease);
  flex-shrink: 0;
  margin-top: var(--space-xs);
}
.btn-reset.hidden { display: none; }
.btn-reset:hover:not(:disabled) { background: var(--surface-raised); border-color: var(--text-muted); }
.btn-reset:disabled { opacity: 0.5; cursor: not-allowed; }

.btn-icon { flex-shrink: 0; }

/* Spinner for running state */
@keyframes spin { to { transform: rotate(360deg); } }

.btn-spinner {
  width: 1rem;
  height: 1rem;
  border: 2px solid var(--text-subtle);
  border-top-color: var(--text-muted);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

/* Pipeline */
.pipeline {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0;
  position: relative;
}

.pipeline-step {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-sm) 0;
  position: relative;
  /* Single source for the mark box. The connector below is positioned from it,
     so the rail cannot drift out of alignment when the mark is resized again. */
  --ghost-mark-size: max(48px, 3rem);
}

/* The rail runs from the bottom of one mark to the top of the next, centred on
   them. Previously hard-coded (left: 0.9375rem, top: 2.5rem) against a 24px
   mark; MS3404-73 doubled the mark to 48px and left these behind, so the line
   sat ~11px left of centre and started inside the mark instead of below it.
   Deriving from --ghost-mark-size and --space-sm keeps it attached (MS3404-83). */
.pipeline-step:not(:last-child)::after {
  content: '';
  position: absolute;
  left: calc(var(--ghost-mark-size) / 2 - 1px);
  top: calc(var(--space-sm) + var(--ghost-mark-size));
  bottom: calc(-1 * var(--space-sm));
  width: 2px;
  background: var(--surface-border);
  transition: background var(--duration-short) var(--ease);
}

/* A connector is the transition INTO the next step, so it takes the NEXT step's
   state, not its own. Colouring it from the upstream step turned the segment
   running into step 6 green the moment step 5 completed, so the rail read as a
   finished run while step 6 was still active (MS3404-83). */
.pipeline-step:has(+ .pipeline-step.complete):not(:last-child)::after { background: var(--success); }
.pipeline-step:has(+ .pipeline-step.active):not(:last-child)::after { background: var(--accent); }

.step-circle {
  width: max(48px, 3rem);
  height: max(48px, 3rem);
  border-radius: var(--radius-full);
  background: var(--surface-border);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background var(--duration-short) var(--ease);
  position: relative;
  z-index: 1;
}

.pipeline-step.active .step-circle { background: var(--accent); }
.pipeline-step.complete .step-circle { background: var(--success); }

/* Each step wears the Ghost state that matches what it does. Only the active
   step runs its animated mark — the kit allows one animated mark on screen, so
   the rest sit on their static twin. The mark is the step's identity, so it
   stays legible at every scale. */
.step-mark {
  /* Doubled from 24px. Every state now shares a 120x132 mark box — guarding and
     working were authored in a 160 box with the mark inset to 62%, so they used
     to render about half the size of the rest. --ghost-mark-size is inherited
     from .pipeline-step so the mark and its rail cannot disagree. */
  width: var(--ghost-mark-size);
  height: var(--ghost-mark-size);
  display: block;
}

/* The circle exists to number the step; the mark carries its own shape, so the
   plate only tints to show progress. */
.pipeline-step .step-circle { background: transparent; }
.pipeline-step.active .step-circle,
.pipeline-step.complete .step-circle { background: transparent; }

.step-mark { opacity: 0.45; transition: opacity var(--duration-short) var(--ease); }
.pipeline-step.active .step-mark,
.pipeline-step.complete .step-mark { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .step-mark { animation: none; }
}

.step-num {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--text-primary);
  line-height: 1;
}

.pipeline-step.active .step-num,
.pipeline-step.complete .step-num { color: var(--bg); }

.pipeline-step.active .step-circle::after {
  content: '';
  position: absolute;
  inset: -3px;
  border: 2px solid transparent;
  border-top-color: var(--accent-strong);
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

.pipeline-step.complete .step-num { font-size: 0; }
.pipeline-step.complete .step-num::after {
  content: '✓';
  font-size: var(--text-sm);
  font-weight: 700;
}

.step-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  flex: 1;
  min-width: 0;
}

.step-label {
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--text-primary);
}

.step-sub {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.step-status {
  flex-shrink: 0;
  width: 1.25rem;
  height: 1.25rem;
}

.pipeline-step.complete .step-status::after {
  content: '';
  display: block;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: var(--success);
  background-image: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2 6L5 9L10 3' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
}

/* Right panel */
.panel-right {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  min-height: 0;
  overflow: hidden;
}

/* Stream panels */
.streams {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-md);
  flex-shrink: 0;
}

/* Act 3: legit stays visible; pirates populate the multiviewer as found */
.streams.act3-mode {
  grid-template-columns: minmax(12.5rem, 0.9fr) minmax(26.25rem, 2.4fr);
  align-items: start; /* don't stretch legit panel to multiviewer height */
  /* Natural height: the wall is sized to a set number of tile rows below, and
     everything left over goes to the event log. */
  flex: 0 0 auto;
  min-height: 0;
}

.streams.act3-mode #streams-pirate-single { display: none; }
.streams.act3-mode #streams-multiviewer { display: flex; }

.streams.act3-mode .stream-legit {
  align-self: start;
  height: fit-content;
  max-height: none;
}

.streams.act3-mode .stream-legit .stream-frame-wrap {
  flex: 0 0 auto; /* keep 16:9 — no empty black under the video */
}

/* Act 3 multiviewer — the red panel scrolls.
   It used to claim min(58vh, 640px) with a 320px floor. Inside a .panel-right
   that cannot scroll, that fixed slice starved the event log below it: on a
   1440x790 laptop the log was left ~57px and cut off mid-row (MS3404-72).
   It is now sized to a set number of tile rows (see --mv-rows-visible) and the
   event log takes everything else. */
.multiviewer-wrap {
  display: none;
  flex-direction: column;
  height: auto;
  min-height: 0;
  border: 2px solid var(--pirate);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface);
}

.multiviewer-wrap.hidden { display: none !important; }

.multiviewer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-sm) var(--space-md);
  background: var(--surface);
  border-bottom: 1px solid var(--surface-border);
  flex-shrink: 0;
}

.multiviewer-header-left {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.multiviewer-header .stream-title { color: var(--pirate); }

.multiviewer-count {
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.multiviewer {
  /* Tiles were a flat 240px, so a laptop fitted two per row and eight of twelve
     pirates sat below the fold during the demo. In rem they shrink with the root,
     and the vw term lets a wide monitor run larger tiles rather than more empty
     gutter. Still one fixed size for every tile, so the wall stays a grid. */
  --mv-tile-w: clamp(9.5rem, 13vw, 15rem);
  --mv-meta-h: 3.25rem;
  --mv-tile-h: calc(var(--mv-tile-w) * 9 / 16 + var(--mv-meta-h));

  /* How much of the wall is on screen before it scrolls. The half row is
     deliberate: a clean edge reads as "that is all of them", whereas a sliced
     tile shows there is more to scroll to. Height is derived rather than fixed,
     so it stays exactly this many rows at every scale.
     top padding + 1 row + gap + half a row. */
  --mv-rows-visible: 1.5;
  height: calc(var(--mv-tile-h) * var(--mv-rows-visible) + var(--space-md) * 2);

  /* Flex wrap avoids grid row-size bugs that stacked tiles on top of each other */
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  align-items: flex-start;
  justify-content: flex-start;
  gap: var(--space-md);
  padding: var(--space-md);
  overflow-x: hidden;
  overflow-y: auto;
  min-height: 0;
  flex: 0 0 auto;
  overscroll-behavior: contain;
}

.mv-empty {
  flex: 1 0 100%;
  padding: var(--space-lg);
  text-align: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.mv-tile {
  box-sizing: border-box;
  width: var(--mv-tile-w);
  flex: 0 0 var(--mv-tile-w);
  height: var(--mv-tile-h);
  min-height: var(--mv-tile-h);
  max-height: var(--mv-tile-h);
  margin: 0;
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  background: #0a0a0a;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
  z-index: 0;
  isolation: isolate;
  transition: border-color var(--duration-short) var(--ease), opacity var(--duration-pipeline) var(--ease);
  animation: mv-appear 280ms var(--ease);
}

@keyframes mv-appear {
  from { opacity: 0; }
  to { opacity: 1; }
}

.mv-tile[data-status="detected"] { border-color: var(--warning, #f59e0b); }
.mv-tile[data-status="terminated"],
.mv-tile[data-status="offline"] {
  border-color: var(--text-subtle);
  opacity: 0.85;
}
.mv-tile[data-status="monetised"] { border-color: var(--success); }
.mv-tile[data-status="subscribed"] { border-color: var(--accent); }
.mv-tile[data-status="flagged"] { border-color: var(--warning); }
.mv-tile[data-status="challenged"] { border-color: var(--accent); }

.mv-frame {
  width: 100%;
  height: calc(var(--mv-tile-w) * 9 / 16);
  flex: 0 0 calc(var(--mv-tile-w) * 9 / 16);
  position: relative;
  background: #000;
  overflow: hidden;
}

.mv-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: #111;
}

.mv-feed {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at 30% 40%, rgba(242, 80, 34, 0.35), transparent 55%),
    linear-gradient(135deg, #1a0a08 0%, #0d1117 55%, #1a1520 100%);
}

.mv-feed::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    0deg,
    transparent,
    transparent 2px,
    rgba(255, 255, 255, 0.03) 2px,
    rgba(255, 255, 255, 0.03) 4px
  );
  animation: mv-scan 2.4s linear infinite;
  pointer-events: none;
}

@keyframes mv-scan {
  from { transform: translateY(0); }
  to { transform: translateY(8px); }
}

.mv-tile[data-status="terminated"] .mv-feed::after,
.mv-tile[data-status="offline"] .mv-feed::after { animation: none; opacity: 0.3; }

.mv-overlay {
  position: absolute;
  inset: 0;
  background: rgba(26, 5, 5, 0.92);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  z-index: 2;
  text-align: center;
  padding: var(--space-xs);
}

.mv-overlay.hidden { display: none; }

.mv-overlay-terminated,
.mv-overlay-offline { background: rgba(26, 5, 5, 0.92); }
.mv-overlay-monetised { background: rgba(5, 26, 12, 0.88); }
.mv-overlay-subscribed { background: rgba(0, 40, 56, 0.82); }
.mv-overlay-flagged { background: rgba(26, 18, 5, 0.88); }
.mv-overlay-challenged { background: rgba(5, 14, 26, 0.88); }

/* Advert tiles: keep feed visible — banner strip over remonetised HLS */
.mv-overlay-banner {
  inset: auto 0 0 0;
  padding: 0.375rem 0.5rem;
  gap: 2px;
  background: linear-gradient(180deg, transparent, rgba(5, 26, 12, 0.92));
}
.mv-overlay-banner strong { font-size: 0.625rem; }
.mv-badge-link { cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.link-btn {
  margin-left: 0.5rem;
  padding: 0;
  border: none;
  background: none;
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.mv-overlay strong {
  color: var(--error);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
}
.mv-overlay-monetised strong { color: var(--success); }
.mv-overlay-subscribed strong { color: var(--accent-strong); }
.mv-overlay-flagged strong { color: var(--warning); }
.mv-overlay-challenged strong { color: var(--accent); }

.mv-overlay span {
  color: var(--text-muted);
  font-size: 0.625rem;
}

.mv-meta {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.25rem;
  padding: 0.375rem 0.625rem;
  background: var(--surface);
  height: var(--mv-meta-h);
  min-height: var(--mv-meta-h);
  max-height: var(--mv-meta-h);
  flex: 0 0 var(--mv-meta-h);
  box-sizing: border-box;
  position: relative;
  z-index: 1;
}

.mv-meta-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-width: 0;
}

.mv-meta-sub {
  justify-content: flex-start;
}

.mv-id {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  color: var(--text-primary);
  white-space: nowrap;
  flex-shrink: 0;
}

.mv-role {
  flex-shrink: 0;
  font-size: 0.5625rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 2px 0.375rem;
  border: 1px solid var(--surface-border);
  color: var(--text-muted);
}
.mv-role.backup {
  border-color: var(--warning);
  color: var(--warning);
}
.mv-role.primary {
  border-color: var(--accent);
  color: var(--accent);
}
.mv-camp {
  display: none; /* campaign id in title tooltip on region — avoid footer clip */
}

.mv-region {
  font-size: 0.6875rem;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}

/* Deep link to the per-session dashboard (MS3404-55) */
.mv-session-link {
  flex-shrink: 0;
  font-size: 0.6875rem;
  line-height: 1;
  padding: 2px 0.25rem;
  color: var(--text-subtle);
  text-decoration: none;
  transition: color var(--duration-micro) var(--ease);
}
.mv-session-link:hover { color: var(--accent); }
.mv-session-link:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }

.mv-badge {
  flex-shrink: 0;
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 3px 0.5rem;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

.mv-badge.live { background: var(--error); color: #fff; }
.mv-badge.detected { background: var(--warning, #f59e0b); color: #111; }
.mv-badge.terminated,
.mv-badge.offline { background: var(--text-subtle); color: var(--text-primary); }
.mv-badge.monetised { background: var(--success); color: #04120a; }
.mv-badge.subscribed { background: var(--accent); color: var(--bg); }
.mv-badge.flagged { background: var(--warning); color: #111; }
.mv-badge.challenged { background: var(--accent); color: #041018; }

.stream-panel {
  border-radius: var(--radius-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.stream-legit { border: 2px solid var(--legit); }
.stream-pirate { border: 2px solid var(--pirate); }
.stream-pirate.offline { border-color: var(--text-subtle); }

.stream-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-sm) var(--space-md);
  background: var(--surface);
}

.stream-header-left {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.stream-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
}

.dot-legit { background: var(--legit); }
.dot-pirate { background: var(--pirate); }
.stream-pirate.offline .dot-pirate { background: var(--text-subtle); }

.stream-title {
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.05em;
}

.stream-legit .stream-title { color: var(--legit); }
.stream-pirate .stream-title { color: var(--pirate); }
.stream-pirate.offline .stream-title { color: var(--text-subtle); }

.stream-source {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.stream-frame-wrap {
  background: #000;
  aspect-ratio: 16 / 9;
  position: relative;
  overflow: hidden;
}

.stream-video {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
  background: #000;
}

.stream-overlay {
  position: absolute;
  inset: 0;
  background: rgba(26, 5, 5, 0.95);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  z-index: 2;
}
.stream-overlay h2 {
  color: var(--error);
  font-size: var(--text-lg);
  font-weight: 600;
  font-family: var(--font-display);
  letter-spacing: 0.05em;
}
.stream-overlay p {
  color: var(--text-muted);
  font-size: var(--text-sm);
}
.stream-overlay.hidden { display: none; }

.stream-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-xs) var(--space-md);
  background: var(--surface);
}

.stream-meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* Content tabs */
.content-tabs-section {
  display: flex;
  flex-direction: column;
  /* Takes whatever the streams above do not, with a floor of tab bar + table
     head + ~4 rows so the log never renders a half row. */
  flex: 1 1 auto;
  min-height: 11.5rem;
  background: var(--surface);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.tab-bar {
  height: 2.5rem;
  background: var(--surface);
  border-bottom: 1px solid var(--surface-border);
  display: flex;
  align-items: stretch;
  flex-shrink: 0;
  gap: 0;
}

.tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 0 var(--space-md);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  transition: color var(--duration-short) var(--ease), border-color var(--duration-short) var(--ease);
}

.tab:hover { color: var(--text-primary); }
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.tab.hidden { display: none; }

.tab-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.125rem;
  padding: 0 var(--space-xs);
  border-radius: var(--radius-full);
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}

.tab-dot {
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 50%;
  background: var(--accent);
  display: none;
}

.tab-dot.visible { display: inline-block; }

@keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
.tab-dot.visible { animation: pulse-dot 2s ease-in-out infinite; }

.tab-content {
  display: none;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.tab-content.active {
  display: flex;
  flex-direction: column;
}

/* AI Analysis views — each visible view fills the panel and scrolls when
   its content is taller than the available height. */
#view-list,
#view-detail,
#view-single {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

/* Analytics tab scrolls as a whole when the KPI/chart stack overflows;
   keep child rows at their natural height instead of squishing them. */
#analytics-tab.active {
  overflow-y: auto;
}
#analytics-tab > * {
  flex-shrink: 0;
}

.event-log {
  flex: 1;
  overflow-y: auto;
  overflow-x: auto;
  position: relative;
}

.event-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.event-table thead {
  position: sticky;
  top: 0;
  z-index: 1;
}

.event-table th {
  background: var(--surface-raised);
  padding: var(--space-sm) var(--space-md);
  text-align: left;
  font-weight: 500;
  color: var(--text-muted);
  font-size: var(--text-xs);
  border-bottom: 1px solid var(--surface-border);
  white-space: nowrap;
}

.col-expand { width: 2rem; }
.col-time { width: 12.5rem; }
.col-step { width: 11.25rem; }
.col-status { width: 5.625rem; }

.event-table td {
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--surface-border);
  vertical-align: top;
  white-space: nowrap;
}

.col-detail { white-space: normal; }

.event-table tr:hover td { background: var(--surface-raised); }

.event-table .row-expand-btn {
  width: 1.5rem;
  height: 1.5rem;
  background: none;
  border: none;
  color: var(--text-subtle);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  transition: color var(--duration-micro) var(--ease);
}

.event-table .row-expand-btn:hover { color: var(--text-primary); }
.event-table .row-expand-btn.open { transform: rotate(90deg); }

.row-time {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.row-step { color: var(--text-primary); }

.row-detail {
  color: var(--text-muted);
  font-size: var(--text-sm);
  max-width: 25rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Expanded JSON row */
.row-expanded { display: none; }
.row-expanded td { padding: 0; background: var(--surface-raised); }
.row-expanded.open { display: table-row; }

.row-json {
  padding: var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: 1.6;
  color: var(--text-muted);
  white-space: pre-wrap;
  word-break: break-all;
  max-height: 12.5rem;
  overflow-y: auto;
}

.json-key { color: var(--accent); }
.json-string { color: var(--success); }
.json-number { color: var(--warning); }
.json-bool { color: var(--error); }

.event-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-2xl);
  color: var(--text-subtle);
  font-size: var(--text-sm);
}

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

/* ===== AI Enrichment panel (single-stream, Acts 1-2) ===== */
.enrichment-panel {
  padding: var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  overflow-y: auto;
  flex: 1;
}

.enrichment-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.enrichment-header-left {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.enrichment-title {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: 500;
  color: var(--accent);
}

.enrichment-confidence {
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

.confidence-bar {
  height: 0.25rem;
  background: var(--surface-border);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.confidence-fill {
  height: 100%;
  background: var(--accent);
  border-radius: var(--radius-full);
  width: 0;
  transition: width var(--duration-medium) var(--ease);
}

.metric-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--space-sm);
}

.metric-cell {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  padding: var(--space-md);
}

.metric-value {
  font-family: var(--font-mono);
  font-size: var(--text-3xl);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  line-height: 1.2;
}

.metric-value .unit { font-size: var(--text-sm); color: var(--text-muted); }
.metric-value.error-val { color: var(--error); }
.metric-value.success-val { color: var(--success); }

.metric-currency { color: var(--text-muted); }

.metric-label {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.metric-sub {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  color: var(--text-subtle);
}

.metric-value.legal-ready { color: var(--success); }
.metric-value.legal-pending { color: var(--text-muted); }

.action-badges {
  display: flex;
  gap: var(--space-sm);
}

.action-badge {
  flex: 1;
  height: 2.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  border: 1px solid var(--surface-border);
  background: transparent;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
}

.action-badge.action-terminate  { border-color: var(--error); color: var(--error); }
.action-badge.action-insert_adverts { border-color: var(--success); color: var(--success); }
.action-badge.action-offer_subscribe,
.action-badge.offer_subscribe { border-color: var(--accent); color: var(--accent); }
.action-badge.action-flag_legal { border-color: var(--warning); color: var(--warning); }
.action-badge.action-soft_challenge { border-color: var(--accent); color: var(--accent); }
.action-badge.cls-badge { border-color: var(--accent); color: var(--accent); }

.action-badge.classification {
  border-color: var(--accent);
  color: var(--accent);
}

.rationale-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.rationale-label {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.rationale-text {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: 1.6;
}

.expand-link {
  background: none;
  border: none;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--accent);
  cursor: pointer;
  text-align: left;
  padding: 0;
  transition: color var(--duration-short) var(--ease);
}

.expand-link:hover { color: var(--accent-strong); }
.expand-link.hidden { display: none; }

.narrative-expanded {
  background: var(--surface-raised);
  border-radius: var(--radius-md);
  padding: var(--space-md);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  color: var(--text-primary);
  line-height: 1.6;
  white-space: pre-wrap;
}

.narrative-expanded.hidden { display: none; }

/* ===== Multi-stream aggregate bar ===== */
.agg-bar {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-sm);
  padding: var(--space-md);
  border-bottom: 1px solid var(--surface-border);
}

.agg-cell { text-align: center; }

.agg-value {
  font-family: var(--font-mono);
  font-size: var(--text-2xl);
  font-weight: 400;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.agg-value.error { color: var(--error); }

.agg-label {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 2px;
}

/* ===== Multi-stream table ===== */
.stream-table { width: 100%; border-collapse: collapse; }

.stream-table th {
  text-align: left;
  padding: 0.375rem var(--space-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-muted);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--surface-border);
  position: sticky;
  top: 0;
  background: var(--surface);
  z-index: 1;
  white-space: nowrap;
}

.stream-table th.right,
.stream-table td.right { text-align: right; }

.stream-table td {
  padding: 0.375rem var(--space-sm);
  font-size: var(--text-xs);
  border-bottom: 1px solid var(--surface-border);
  vertical-align: middle;
  white-space: nowrap;
}

.stream-table tr:hover td { background: var(--surface-raised); cursor: pointer; }
.stream-table tr.selected td { background: var(--accent-soft); }

.stream-id { font-family: var(--font-mono); color: var(--accent); }
.col-exposure { font-family: var(--font-mono); color: var(--error); font-weight: 600; }
.col-remont { font-family: var(--font-mono); color: var(--success); }
.col-confidence { font-family: var(--font-mono); }

.action-pill {
  font-size: 0.625rem;
  font-weight: 600;
  padding: 2px 0.375rem;
  border-radius: var(--radius-sm);
  border: 1px solid;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.action-pill.terminate { color: var(--error); border-color: var(--error); }
.action-pill.insert_adverts { color: var(--success); border-color: var(--success); }
.action-pill.flag_legal { color: var(--warning); border-color: var(--warning); }
.action-pill.soft_challenge { color: var(--accent); border-color: var(--accent); }

.class-pill {
  font-size: 0.625rem;
  padding: 2px 0.375rem;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  border: 1px solid var(--surface-border);
}

.tier-pill { font-size: 0.625rem; padding: 1px 0.3125rem; border-radius: var(--radius-sm); }
.tier-pill.premier { color: var(--warning); border: 1px solid var(--warning); }
.tier-pill.gold { color: var(--accent); border: 1px solid var(--accent); }
.tier-pill.silver { color: var(--text-primary); border: 1px solid var(--text-muted); }
.tier-pill.bronze { color: var(--text-muted); border: 1px solid var(--surface-border); }

/* ===== Stream detail panel (drill-down) ===== */
.enrich-panel { padding: var(--space-md); overflow-y: auto; flex: 1; }

.enrich-back {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--text-sm);
  color: var(--accent);
  cursor: pointer;
  margin-bottom: var(--space-md);
  border: none;
  background: none;
  font-family: var(--font-body);
}
.enrich-back:hover { color: var(--accent-strong); }

/* ===== Support Partners attribution footer (MS3404-67) ===== */
.sp-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  flex-wrap: wrap;
  padding: var(--space-md) var(--space-lg);
  background: var(--surface);
  border-top: 1px solid var(--surface-border);
  flex-shrink: 0;
}

.sp-footer-credits {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  flex-wrap: wrap;
}

.sp-footer-credit {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.sp-footer-divider {
  width: 1px;
  height: 1.75rem;
  background: var(--surface-border);
  flex-shrink: 0;
}

.sp-footer-label {
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-subtle);
  white-space: nowrap;
}

.sp-footer-logo {
  height: 2.125rem;
  width: auto;
  display: block;
}

/* Optically matched to the Support Partners lockup rather than set to the same
   number: NAGRA Venturi is the wider of the two two-line marks (3.70:1 against
   3.00:1) and reads heavier at an equal height. */
.sp-footer-logo-nagra {
  height: 1.875rem;
}

.ms-lockup {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.ms-lockup-mark {
  height: 1.375rem;
  width: auto;
  display: block;
}

.ms-lockup-word {
  font-family: 'Segoe UI', var(--font-body);
  font-size: 1.25rem;
  font-weight: 400;
  line-height: 1;
  color: var(--text-primary);
}

.sp-footer-copy {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

@media (max-width: 900px) {
  .sp-footer { justify-content: center; text-align: center; }
  .sp-footer-credits { justify-content: center; row-gap: var(--space-md); }
  .sp-footer-divider { display: none; }
}

/* Second-monitor event roll-up (MS3404-62) */
.header-event-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-xs) var(--space-sm);
  font-size: var(--text-xs);
  color: var(--accent);
  text-decoration: none;
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-sm);
  transition: color var(--duration-micro) var(--ease),
              border-color var(--duration-micro) var(--ease);
}
.header-event-link:hover { color: var(--accent-strong); border-color: var(--accent); }
.header-event-link:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

/* Deep link out to the per-session dashboard (MS3404-55) */
.session-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  margin: 0 0 var(--space-md) var(--space-md);
  padding: var(--space-xs) var(--space-sm);
  font-size: var(--text-xs);
  color: var(--accent);
  text-decoration: none;
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-sm);
  transition: color var(--duration-micro) var(--ease),
              border-color var(--duration-micro) var(--ease);
}
.session-link:hover { color: var(--accent-strong); border-color: var(--accent); }
.session-link:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

.enrich-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-sm);
}

.enrich-title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 500;
  color: var(--accent);
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}
.enrich-title svg { width: 1.125rem; height: 1.125rem; }

.enrich-conf-value {
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  color: var(--accent);
}

.conf-bar {
  height: 0.25rem;
  background: var(--surface-border);
  border-radius: var(--radius-full);
  margin-bottom: var(--space-md);
  overflow: hidden;
}
.conf-fill {
  height: 100%;
  background: var(--accent);
  border-radius: var(--radius-full);
  transition: width var(--duration-medium) var(--ease);
}

.action-row {
  display: flex;
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
}

.narrative-box {
  background: var(--surface-raised);
  border-radius: var(--radius-md);
  padding: var(--space-md);
  font-size: var(--text-sm);
  color: var(--text-primary);
  line-height: 1.6;
  margin-bottom: var(--space-md);
  display: none;
}
.narrative-box.open { display: block; }

/* ===== Collapsible sections ===== */
.section-group {
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-sm);
  overflow: hidden;
}

.section-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  background: var(--surface-raised);
  border: none;
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}
.section-toggle svg { width: 0.875rem; height: 0.875rem; flex-shrink: 0; }
.section-toggle .chevron {
  width: 0.625rem;
  height: 0.625rem;
  margin-left: auto;
  transition: transform var(--duration-short) var(--ease);
  color: var(--text-muted);
}
.section-toggle.open .chevron { transform: rotate(180deg); }

.section-body { display: none; padding: var(--space-sm) var(--space-md); }
.section-body.open { display: block; }

.dkv { display: flex; gap: var(--space-sm); padding: 2px 0; font-size: var(--text-xs); }
.dkv-k { color: var(--text-subtle); min-width: 6.875rem; flex-shrink: 0; }
.dkv-v { font-family: var(--font-mono); color: var(--text-primary); }
.dkv-v.accent { color: var(--accent); }
.dkv-v.error { color: var(--error); }
.dkv-v.success { color: var(--success); }
.dkv-v.warning { color: var(--warning); }

/* Agent Activity pipeline stages */
.agent-stage {
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  padding: var(--space-md);
  margin-bottom: var(--space-sm);
}
.agent-stage:last-child { margin-bottom: 0; }

.agent-stage-header { display: flex; align-items: flex-start; gap: var(--space-sm); }
.agent-stage-icon { width: 1.25rem; height: 1.25rem; flex-shrink: 0; margin-top: 1px; }
.agent-stage-info { flex: 1; min-width: 0; }
.agent-stage-title { font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; color: var(--accent); }
.agent-stage-timing { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-muted); flex-shrink: 0; }
.agent-stage-sub { font-size: var(--text-xs); color: var(--text-muted); margin-top: 1px; }

.agent-tool-list { margin-top: var(--space-sm); padding-left: 1.75rem; }
.agent-tool-row { display: flex; align-items: center; gap: var(--space-xs); padding: 2px 0; font-size: var(--text-xs); font-family: var(--font-mono); }
.agent-tool-check { color: var(--success); flex-shrink: 0; font-size: 0.8125rem; }
.agent-tool-pending .agent-tool-check { color: var(--text-subtle); }
.agent-tool-active .agent-tool-check { color: var(--accent); }
.agent-tool-pending { opacity: 0.55; }
.agent-tool-active { opacity: 1; }
.agent-tool-complete { opacity: 1; }
.agent-tool-name { color: var(--accent); font-weight: 500; }
.agent-tool-arrow { color: var(--text-subtle); }
.agent-tool-target { color: var(--text-muted); }
.agent-tool-result { color: var(--success); margin-left: auto; font-weight: 600; white-space: nowrap; }

/* Agent 365 branding */
.agent365-section { margin-top: var(--space-md); }
.agent365-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-sm) var(--space-md);
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  margin-bottom: 0;
}
.agent365-brand { display: flex; align-items: center; gap: var(--space-sm); }
.agent365-logo { width: 1.125rem; height: 1.125rem; flex-shrink: 0; }
.agent365-title { font-family: var(--font-body); font-size: var(--text-base); font-weight: 600; color: var(--text-primary); }
.agent365-badge {
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  padding: 2px 0.375rem;
  border-radius: var(--radius-sm);
  letter-spacing: 0.08em;
}
.agent365-meta { display: flex; align-items: center; gap: var(--space-md); }
.agent365-duration { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-muted); }
.agent365-incident { font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; }

.agent365-header + .agent-tool-list {
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-top: none;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  padding: var(--space-sm) var(--space-md) var(--space-md);
  margin-top: 0;
}

/* Defender for Cloud incident */
.defender-incident-section { margin-top: var(--space-md); }
.defender-incident-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-sm) var(--space-md);
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.defender-incident-brand { display: flex; align-items: center; gap: var(--space-sm); }
.defender-incident-logo { width: 1.125rem; height: 1.125rem; flex-shrink: 0; }
.defender-incident-title { font-family: var(--font-body); font-size: var(--text-base); font-weight: 600; color: var(--text-primary); }
.defender-incident-badge {
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  font-weight: 600;
  color: var(--error);
  background: rgba(209, 52, 56, 0.14);
  padding: 2px 0.375rem;
  border-radius: var(--radius-sm);
  letter-spacing: 0.08em;
}
.defender-incident-meta { display: flex; align-items: center; gap: var(--space-md); }
.defender-incident-severity {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--error);
  background: rgba(209, 52, 56, 0.14);
  padding: 2px 0.375rem;
  border-radius: var(--radius-sm);
}
.defender-incident-id { font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; color: var(--error); }
.defender-incident-body {
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-top: none;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  padding: var(--space-sm) var(--space-md) var(--space-md);
}
.defender-portal-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--accent);
  text-decoration: none;
  transition: color var(--duration-short) var(--ease);
}
.defender-portal-link:hover { color: var(--accent-strong); }
.defender-kql-section { margin-top: var(--space-md); }
.defender-kql-block {
  background: var(--bg);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  padding: var(--space-md);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--accent);
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-all;
  overflow-x: auto;
  margin-top: var(--space-xs);
}

/* Intervene button */
.intervene-btn-lg {
  height: 2.75rem;
  padding: 0 var(--space-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  transition: all var(--duration-short) var(--ease);
}
.intervene-btn-lg.terminate { background: transparent; border: 2px solid var(--error); color: var(--error); }
.intervene-btn-lg.terminate:hover { background: var(--error); color: var(--text-primary); }
.intervene-btn-lg.insert_adverts { background: transparent; border: 2px solid var(--success); color: var(--success); }
.intervene-btn-lg.insert_adverts:hover { background: var(--success); color: var(--bg); }
.intervene-btn-lg.offer_subscribe { background: transparent; border: 2px solid var(--accent); color: var(--accent); }
.intervene-btn-lg.offer_subscribe:hover { background: var(--accent); color: var(--bg); }
.remonet-actions { margin-top: var(--space-sm); }
.remonet-btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-top: var(--space-xs);
}
.remonet-btn-row .intervene-btn-lg { flex: 1 1 12rem; }
.intervene-btn-lg.flag_legal { background: transparent; border: 2px solid var(--warning); color: var(--warning); }
.intervene-btn-lg.flag_legal:hover { background: var(--warning); color: var(--bg); }
.intervene-btn-lg.soft_challenge { background: transparent; border: 2px solid var(--accent); color: var(--accent); }
.intervene-btn-lg.soft_challenge:hover { background: var(--accent); color: var(--bg); }
.intervene-btn-lg.acted { background: var(--error); border-color: var(--error); color: var(--text-primary); cursor: default; }

/* ===== Analytics tab ===== */
.time-tabs {
  display: flex;
  gap: var(--space-xs);
  padding: var(--space-md) var(--space-md) var(--space-sm);
}

.time-tab {
  padding: 0.25rem 0.75rem;
  font-size: var(--text-xs);
  font-weight: 500;
  border-radius: var(--radius-sm);
  border: 1px solid var(--surface-border);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  font-family: var(--font-body);
  transition: all var(--duration-short) var(--ease);
}
.time-tab:hover { border-color: var(--accent); color: var(--text-primary); }
.time-tab.active { background: var(--accent); border-color: var(--accent); color: var(--bg); }

.analytics-date {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  padding: 0 var(--space-md) var(--space-sm);
}

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-sm);
  padding: 0 var(--space-md) var(--space-sm);
}

.kpi-card {
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  padding: var(--space-md);
}

.kpi-label {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-bottom: var(--space-xs);
}

.kpi-row {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
}

.kpi-value {
  font-family: var(--font-mono);
  font-size: var(--text-2xl);
  font-weight: 400;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.kpi-change {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--success);
}

.bottom-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-sm);
  padding: 0 var(--space-md) var(--space-md);
}

.chart-card {
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  padding: var(--space-md);
}

.chart-title {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-bottom: var(--space-xs);
}

.chart-value {
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  color: var(--text-primary);
  margin-bottom: var(--space-sm);
  font-variant-numeric: tabular-nums;
}

.chart-canvas { width: 100%; height: 7.5rem; }

.region-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 0.25rem 0;
  font-size: var(--text-xs);
}

.region-name { min-width: 3.75rem; color: var(--text-muted); }
.region-bar-track { flex: 1; height: 0.375rem; background: var(--surface-border); border-radius: 3px; overflow: hidden; }
.region-bar-fill { height: 100%; border-radius: 3px; background: var(--accent); }
.region-count { font-family: var(--font-mono); color: var(--text-primary); min-width: 0.75rem; text-align: right; }

/* ===== Location tab ===== */
.location-wrap { padding: var(--space-md); overflow-y: auto; flex: 1; min-height: 0; }
.map-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: var(--space-sm); }
.map-title { font-size: var(--text-lg); font-weight: 600; color: var(--text-primary); }
.map-subtitle { font-size: var(--text-xs); color: var(--text-muted); }

#world-map {
  width: 100%;
  height: 23.75rem;
  border-radius: var(--radius-md);
  background: var(--bg);
  border: 1px solid var(--surface-border);
}

/* ===== Interactive piracy origin map (MS3404-64) ===== */
.pm-root { position: relative; width: 100%; height: 100%; }
.pm-svg { width: 100%; height: 100%; display: block; cursor: grab; touch-action: none; }
.pm-svg:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.pm-root.pm-dragging .pm-svg { cursor: grabbing; }

/* Zoom controls */
.pm-controls {
  position: absolute;
  top: var(--space-sm);
  right: var(--space-sm);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.pm-btn {
  width: 1.75rem;
  height: 1.75rem;
  display: grid;
  place-items: center;
  background: var(--surface);
  color: var(--text-primary);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1;
  cursor: pointer;
  transition: border-color var(--duration-micro) var(--ease),
              color var(--duration-micro) var(--ease);
}
.pm-btn:hover { border-color: var(--accent); color: var(--accent); }
.pm-btn:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.pm-btn-reset { width: auto; padding: 0 var(--space-sm); font-size: var(--text-xs); }

.pm-zoom-badge {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--text-subtle);
  min-width: 2.125rem;
  text-align: right;
}

/* Labels appear as there is room for them: region at 2x, stream id at 4x */
.pm-label {
  text-anchor: middle;
  font-family: var(--font-body);
  font-size: 3.2px;
  fill: var(--text-muted);
  paint-order: stroke;
  stroke: var(--bg);
  stroke-width: 1.1;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--duration-short) var(--ease);
}
.pm-label-id { font-family: var(--font-mono); fill: var(--text-primary); }
.pm-root[data-zoom-level="2"] .pm-label-region,
.pm-root[data-zoom-level="3"] .pm-label-region { opacity: 1; }
.pm-root[data-zoom-level="3"] .pm-label-id { opacity: 1; }

.pm-graticule line { stroke: var(--surface-border); stroke-width: 0.15; opacity: 0.5; }

.pm-land {
  fill: var(--surface-raised);
  stroke: var(--surface-border);
  stroke-width: 0.25;
  stroke-linejoin: round;
}

/* Arc from a dead origin to where the campaign came back up */
.pm-link {
  fill: none;
  stroke: var(--text-subtle);
  stroke-width: 0.45;
  stroke-dasharray: 2 1.6;
  opacity: 0.55;
}
.pm-link.killed {
  stroke: var(--warning);
  opacity: 0.95;
  animation: pm-flow 1.4s linear infinite;
}
@keyframes pm-flow { to { stroke-dashoffset: -7.2; } }

.pm-node { cursor: pointer; }
.pm-node:focus { outline: none; }
.pm-node:focus .pm-dot { stroke: var(--focus-ring); stroke-width: 1.2; }
.pm-node:hover .pm-dot { stroke: var(--text-primary); stroke-width: 0.9; }

.pm-dot { fill: var(--warning); stroke: var(--bg); stroke-width: 0.4; }
.pm-node.detected .pm-dot,
.pm-node.live .pm-dot      { fill: var(--warning); }
.pm-node.intervening .pm-dot { fill: var(--accent); }
.pm-node.terminated .pm-dot,
.pm-node.offline .pm-dot   { fill: none; stroke: var(--error); stroke-width: 0.8; }
.pm-node.monetised .pm-dot,
.pm-node.subscribed .pm-dot { fill: var(--success); }
.pm-node.flagged .pm-dot   { fill: var(--evidence); }
.pm-node.challenged .pm-dot { fill: var(--accent-strong); }

/* Still-live origins breathe; taken-down ones go quiet */
/* transform rather than the `r` attribute — Firefox does not animate CSS `r` */
.pm-pulse {
  fill: var(--warning);
  opacity: 0.28;
  transform-box: fill-box;
  transform-origin: center;
  animation: pm-breathe 2.2s var(--ease) infinite;
}
.pm-node.intervening .pm-pulse { fill: var(--accent); }
.pm-node.monetised .pm-pulse,
.pm-node.subscribed .pm-pulse { fill: var(--success); }
.pm-node.flagged .pm-pulse { fill: var(--evidence); }
@keyframes pm-breathe {
  0%, 100% { opacity: 0.30; transform: scale(1); }
  50%      { opacity: 0.06; transform: scale(1.8); }
}

/* One-shot ripple at the moment of takedown */
.pm-ripple {
  fill: none;
  stroke: var(--error);
  stroke-width: 0.6;
  transform-box: fill-box;
  transform-origin: center;
  animation: pm-ripple 900ms var(--ease) 1 forwards;
}
@keyframes pm-ripple {
  from { transform: scale(1);   opacity: 0.9; stroke-width: 0.9; }
  to   { transform: scale(5.5); opacity: 0;   stroke-width: 0.2; }
}

@media (prefers-reduced-motion: reduce) {
  .pm-pulse, .pm-ripple, .pm-link.killed { animation: none; }
}

/* Hop number on a resurfaced feed: 2 = first backup, 3 = second, … */
.pm-hop {
  font-family: var(--font-mono);
  font-size: 3.4px;
  fill: var(--warning);
  paint-order: stroke;
  stroke: var(--bg);
  stroke-width: 0.9;
}

.pm-tip {
  position: absolute;
  z-index: 5;
  min-width: 12.5rem;
  max-width: 17.5rem;
  padding: var(--space-sm);
  background: var(--surface);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
  pointer-events: none;
  font-size: var(--text-xs);
}

.pm-tip-head {
  display: flex;
  justify-content: space-between;
  gap: var(--space-sm);
  margin-bottom: var(--space-xs);
}
.pm-tip-id { font-family: var(--font-mono); color: var(--text-primary); }
.pm-tip-status { font-weight: 600; letter-spacing: 0.03em; }
.pm-tip-status.detected   { color: var(--warning); }
.pm-tip-status.terminated { color: var(--error); }
.pm-tip-status.monetised,
.pm-tip-status.subscribed { color: var(--success); }
.pm-tip-status.flagged    { color: var(--evidence); }
.pm-tip-status.challenged { color: var(--accent-strong); }

.pm-tip-row { display: flex; justify-content: space-between; gap: var(--space-sm); color: var(--text-muted); }
.pm-tip-row span:last-child { color: var(--text-primary); text-align: right; }
.pm-tip-mono { font-family: var(--font-mono); font-size: 0.625rem; word-break: break-all; }
.pm-tip-hint { margin-top: var(--space-xs); color: var(--text-subtle); font-style: italic; }

.legend-key {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: var(--radius-full);
  display: inline-block;
  flex-shrink: 0;
}
.legend-key.detected   { background: var(--warning); }
.legend-key.terminated { background: none; border: 1.5px solid var(--error); }
.legend-key.monetised  { background: var(--success); }
.legend-key.flagged    { background: var(--evidence); }
.legend-key.challenged { background: var(--accent-strong); }
.legend-key.link {
  width: 1rem;
  height: 0;
  border-radius: 0;
  border-top: 2px dashed var(--warning);
}

#map-legend {
  display: flex;
  gap: var(--space-lg);
  margin-top: var(--space-sm);
  justify-content: center;
  flex-wrap: wrap;
}

.map-legend-item {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.legend-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--radius-full);
}

.region-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11.25rem, 1fr));
  gap: var(--space-sm);
  margin-top: var(--space-md);
}

.region-card {
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  padding: var(--space-sm) var(--space-md);
}

.region-card-name {
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 2px;
}

.region-card-row { display: flex; justify-content: space-between; align-items: baseline; }
.region-card-streams { font-family: var(--font-mono); font-size: var(--text-lg); color: var(--accent); font-weight: 600; }
.region-card-exposure { font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-muted); }

/* ===== Utility ===== */
.hidden { display: none !important; }

/* Footer */
.footer {
  height: 2.25rem;
  background: var(--surface);
  border-top: 1px solid var(--surface-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--space-lg);
  font-size: var(--text-xs);
  color: var(--text-muted);
  flex-shrink: 0;
}

.footer-left,
.footer-right {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
}

.footer-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
}

.footer-item strong {
  color: var(--text-primary);
  font-weight: 500;
}

.footer-dot {
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 50%;
  background: var(--text-subtle);
}

.footer-dot.online { background: var(--success); }
.footer-dot.offline { background: var(--error); }

/* Focus & accessibility */
:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* Scrollbar styling */
::-webkit-scrollbar { width: 0.375rem; height: 0.375rem; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--surface-border);
  border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover { background: var(--text-subtle); }

/* Tablet breakpoint */
@media (max-width: 768px) {
  body { min-width: auto; }

  .dashboard {
    grid-template-columns: 1fr;
    overflow-y: auto;
  }

  .panel-left { order: 1; }
  .panel-right { order: 2; }

  .pipeline {
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: var(--space-md);
    scrollbar-width: thin;
    scrollbar-color: var(--surface-border) transparent;
    padding-bottom: var(--space-sm);
  }

  .pipeline::-webkit-scrollbar { height: 0.25rem; }
  .pipeline::-webkit-scrollbar-track { background: transparent; }
  .pipeline::-webkit-scrollbar-thumb {
    background: var(--surface-border);
    border-radius: 2px;
  }

  .pipeline-step { flex-direction: column; text-align: center; padding: 0; min-width: 5rem; }
  .pipeline-step:not(:last-child)::after { display: none; }
  .step-text { align-items: center; }

  .streams,
  .streams.act3-mode { grid-template-columns: 1fr; }
  /* Columns stack and the page scrolls here, so blocks take natural height and
     the wall keeps its row-derived size — one row plus a half on a narrow
     screen, where a single column of tiles makes the wall taller per pirate. */
  .content-tabs-section { flex: 0 0 auto; min-height: 0; }
  .multiviewer { --mv-tile-w: 12.5rem; --mv-meta-h: 3.25rem; }

  .event-table .row-expand-btn {
    width: 2.75rem;
    height: 2.75rem;
  }
}

/* Modals — dossier review + Teams Adaptive Card preview */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.72);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: var(--space-lg);
}
.modal-backdrop.hidden { display: none !important; }
.modal-panel {
  background: var(--surface);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-lg);
  width: min(35rem, 100%);
  max-height: min(85vh, 45rem);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.modal-panel-wide { width: min(45rem, 100%); }
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md) var(--space-lg);
  border-bottom: 1px solid var(--surface-border);
}
.modal-header h2 {
  margin: 0;
  font-size: var(--text-lg);
  color: var(--text-primary);
}
.modal-close {
  background: transparent;
  border: none;
  color: var(--text-muted);
  /* Without this the button is the one rendered element falling back to the
     browser default stack (computed: Arial). */
  font-family: var(--font-body);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}
.modal-body {
  padding: var(--space-lg);
  overflow-y: auto;
  flex: 1;
}
.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding: var(--space-md) var(--space-lg);
  border-top: 1px solid var(--surface-border);
}
.modal-lead { color: var(--text-muted); font-size: var(--text-sm); margin: 0 0 var(--space-md); }
.btn-primary, .btn-secondary {
  height: 2.25rem;
  padding: 0 var(--space-md);
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
}
.btn-primary {
  background: var(--button-primary-bg);
  color: var(--button-primary-text);
  border: none;
}
.btn-secondary {
  background: transparent;
  color: var(--text-primary);
  border: 1px solid var(--surface-border);
}
.dossier-heading { margin: var(--space-md) 0 var(--space-sm); font-size: var(--text-base); color: var(--warning); }
.dossier-sub { margin: var(--space-md) 0 var(--space-xs); font-size: var(--text-sm); color: var(--text-muted); }
.dossier-summary { margin: 0; font-size: var(--text-sm); color: var(--text-primary); line-height: 1.45; }
.dossier-word-note { margin-top: var(--space-md); color: var(--text-muted); font-size: var(--text-xs); }
.dossier-meta { display: grid; gap: var(--space-xs); margin-bottom: var(--space-md); }
.dossier-evidence-detail { font-size: var(--text-xs); color: var(--text-subtle); margin: -4px 0 0.5rem 0; padding-left: 2px; }
.teams-card-preview { margin-bottom: var(--space-md); }
.teams-card-surface {
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  padding: var(--space-md);
}
.teams-card-brand {
  font-size: var(--text-xs);
  color: var(--accent);
  font-weight: 600;
  margin-bottom: var(--space-sm);
  letter-spacing: 0.04em;
}
.teams-card-surface h3 { margin: 0 0 var(--space-sm); font-size: var(--text-base); }
.teams-card-surface p { margin: 0 0 var(--space-md); font-size: var(--text-sm); color: var(--text-muted); }
.teams-actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-top: var(--space-md); }
.teams-action {
  display: inline-flex;
  align-items: center;
  padding: 0.375rem 0.75rem;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent-strong);
  font-size: var(--text-xs);
  font-weight: 600;
  text-decoration: none;
}
.teams-json summary {
  cursor: pointer;
  color: var(--text-muted);
  font-size: var(--text-xs);
  margin-bottom: var(--space-sm);
}
.teams-json pre {
  background: var(--bg);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-sm);
  padding: var(--space-sm);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  color: var(--text-muted);
  overflow: auto;
  max-height: 13.75rem;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Same pirate origin IP seen on an earlier feed (MS3404-67) */
.repeat-ip {
  display: inline-block;
  margin-left: var(--space-xs);
  padding: 1px 0.3125rem;
  border: 1px solid var(--error);
  border-radius: var(--radius-sm);
  font-size: 0.5625rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--error);
  white-space: nowrap;
  vertical-align: middle;
}
.pm-tip-repeat { color: var(--error); font-weight: 500; }

/* ── Nagra CDN Security Analytics findings ─────────────────────────────────
   A separate panel from the pirate stream wall because the two are different
   kinds of evidence. A pirate stream is a captured feed; a CDN finding is
   derived from Front Door access logs and has no region, subscriber or video.
   Amber per DESIGN.md: evidence requiring attention, not confirmed abuse. */

.dot-evidence { background: var(--evidence); }

.cdn-findings-wrap {
  background: var(--surface);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  /* Sits between the stream wall and the event log in the .panel-right flex
     column. It must not absorb the space the log needs, nor be crushed when the
     wall is full, so it keeps its natural height and scrolls internally. */
  flex: 0 0 auto;
  /* Three findings is the ghost fixture's full set, so they must all be on
     screen without a scroll during a demo; more than that scrolls. */
  max-height: 16.5rem;
  display: flex;
  flex-direction: column;
}

.cdn-findings-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  background: var(--surface);
  border-bottom: 1px solid var(--surface-border);
  flex-shrink: 0;
}

.cdn-findings-header .stream-source {
  text-align: right;
  cursor: help;
}

.cdn-findings-header-left {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.cdn-findings-header .stream-title { color: var(--evidence); }

.cdn-findings-count {
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.cdn-findings-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  line-height: 1.6;
}

.cdn-findings-table th {
  text-align: left;
  padding: var(--space-xs) var(--space-md);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-subtle);
  border-bottom: 1px solid var(--surface-border);
}

.cdn-findings-table th.right,
.cdn-findings-table td.right { text-align: right; }

.cdn-findings-table td {
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--surface-border);
  color: var(--text-primary);
  vertical-align: top;
}

.cdn-findings-table tbody tr { cursor: pointer; }
.cdn-findings-table tbody tr:hover { background: var(--surface-raised); }
.cdn-findings-table tbody tr:last-child td { border-bottom: none; }

.cdn-finding-type {
  display: inline-block;
  padding: 1px var(--space-sm);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  border: 1px solid var(--evidence);
  color: var(--evidence);
}

.cdn-finding-type.pooling {
  border-color: var(--error);
  color: var(--error);
}

.cdn-finding-sub {
  margin-top: var(--space-2xs);
  font-size: var(--text-xs);
  color: var(--text-muted);
  white-space: nowrap;
}

.cdn-findings-table td:nth-child(2),
.cdn-findings-table td:nth-child(3) { white-space: nowrap; }

/* n/a is deliberately quiet and never a zero. Nagra reports no downstream
   audience for a restreaming origin, and "£0" would read as "costs nothing". */
.cdn-na {
  color: var(--text-subtle);
  font-style: italic;
}

/* Marks a figure as modelled rather than measured. */
.cdn-modelled {
  color: var(--text-subtle);
  margin-left: 2px;
  cursor: help;
}

/* The panel is one of several in a fixed-height column, so the table scrolls
   rather than pushing the event log off screen once findings accumulate. */
.cdn-findings-scroll {
  overflow-y: auto;
  overflow-x: auto;
  min-height: 0;
}

.cdn-findings-table thead th {
  position: sticky;
  top: 0;
  background: var(--surface);
  z-index: 1;
}

/* ── Stated basis: click a figure's mark to see how it was derived ─────────
   A native title needs a held hover, never fires on touch, and cannot be left
   open. In a demo someone points at a number and asks where it came from, so
   the mark is a real control and the answer stays on screen while discussed. */

.has-basis {
  cursor: help;
  position: relative;
}

/* The mark that opens a figure's stated basis. A circled i reads as "there is
   an explanation here" in a way an asterisk does not: an asterisk implies a
   footnote somewhere else on the page, which there isn't. */
.basis-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 0.95rem;
  height: 0.95rem;
  margin-left: var(--space-2xs);
  border: 1px solid var(--accent);
  border-radius: 50%;
  color: var(--accent);
  font-family: var(--font-sans, inherit);
  font-size: 0.65rem;
  font-weight: 700;
  font-style: normal;
  line-height: 1;
  vertical-align: middle;
  cursor: help;
  flex-shrink: 0;
  /* The glyph sits high in most faces; nudge it back onto the centre line. */
  padding-top: 1px;
}

.has-basis:hover .basis-icon,
.has-basis:focus-visible .basis-icon,
.basis-icon:hover {
  background: var(--accent);
  color: var(--button-primary-text);
}

.basis-icon:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--focus-ring);
}

.has-basis:hover,
.has-basis:focus-visible {
  color: var(--accent);
  outline: none;
}

.has-basis:focus-visible {
  box-shadow: 0 0 0 2px var(--focus-ring);
  border-radius: var(--radius-sm);
}

.basis-popover {
  position: absolute;
  z-index: 200;
  max-width: 26rem;
  padding: var(--space-sm) var(--space-md);
  background: var(--surface-raised);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55);
}

.basis-popover-title {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--space-xs);
}

.basis-popover-body {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-primary);
}
