/* ============================================================
   views-monitor.css — screen-specific styling for the Monitor.
   Builds on the global :root tokens (tokens.css) + components.css.
   The monitor keeps a BLACKER theme (var(--mon-0)/--mon-1/--mon-2).
   All class names are prefixed `m-` (or scoped under .monitor-view)
   to avoid colliding with the shared component classes.
   ============================================================ */

.monitor-view{
  display:flex;flex-direction:column;min-height:100dvh;height:100%;
  background:var(--bg-0);color:var(--text-1);
}

/* ── A. Sub-header ─────────────────────────────────────────── */
/* Compact single row: back · status dot · title + LIVE · tabs · icon cluster.
   (Venue·region meta line was removed; padding trimmed to suit one line.)
   Sticky: the event header (tabs + icon cluster) stays pinned to the top of
   the viewport when the page scrolls (long detections list, spatial config,
   embedded usage…). The intended internal scroller (.m-body) never engages
   because the %-height chain above it isn't definite, so the DOCUMENT scrolls
   — sticky covers both cases. z-index 100: above canvases, sticky table heads
   (z 1–5), map-area overlays (#map-canvas is isolated) and the settings
   backdrop (z 60 — the header intentionally stays usable above it), below
   popovers (800), modals (900+) and toasts (1000). */
.m-subhdr{
  display:flex;align-items:center;gap:var(--s4);
  padding:5px 16px;
  background:var(--bg-1);border-bottom:1px solid var(--border-subtle);
  flex-wrap:wrap;
  position:sticky;top:0;z-index:100;
}
.m-subhdr .m-evtitle{
  font-size:14px;font-weight:600;letter-spacing:-.2px;color:var(--text-1);line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:42vw;
  text-decoration:none;
}
/* The event title is the (only) link back to the events list — subtle until hover. */
a.m-evtitle:hover{text-decoration:underline;color:var(--text-0,#fff)}
/* compact controls so the bar stays a short single row */
.m-subhdr .segmented{padding:0;align-items:center}
.m-subhdr .seg-btn,.m-subhdr .m-tabghost{padding:0 10px;height:20px;font-size:11.5px}
.m-subhdr .seg-count{padding:0 6px}
.m-subhdr .spacer{margin-left:auto}
.m-iconcluster{display:flex;align-items:center;gap:4px;flex-wrap:wrap}
.m-iconbtn{
  width:28px;height:22px;display:inline-flex;align-items:center;justify-content:center;
  border-radius:var(--r-sm);background:transparent;border:1px solid transparent;
  color:var(--text-2);cursor:pointer;transition:.13s;
}
.m-iconbtn svg{width:13px;height:13px}
.m-iconbtn.m-countbtn svg{width:15px;height:15px} /* Sources dish a touch larger for clarity */
.m-iconbtn:hover{background:var(--bg-raised);color:var(--text-1);border-color:var(--border)}
.m-iconbtn.on{color:var(--accent);border-color:var(--accent-soft);background:var(--accent-soft)}
.m-iconbtn:focus-visible{outline:none;box-shadow:var(--ring)}
/* Usage tab inside the Live/Replay/Analyzers segmented control — native seg-btn
   styling; its count font is monospace to match the old chip's "0 / 251". */
.m-segusage .seg-count{font-family:var(--font-mono)}

/* ── Scroll body ───────────────────────────────────────────── */
.m-body{flex:1;min-height:0;overflow:auto;padding:8px 12px 20px;display:flex;flex-direction:column;gap:8px}

/* ── Live chrome fill chain (issue 1 — v1 parity) ──────────────
   The Live spectrum chart must grow to fill the viewport with the
   DETECTIONS/INTERFERENCE/UNIFIED/CLEAN-FREQ bar docked at the bottom,
   instead of the chart sitting at a fixed ~240px with dead space below.
   This mirrors v1's .chart-wrap-outer / .chart-wrap / .chart-panel /
   .chart-panel-canvas-wrap flex chain: every link is flex:1; min-height:0
   so the chart panel(s) absorb the available height and the pane bar +
   alerts stay pinned below. The panel only takes a fixed pixel height when
   the operator picks a >1× size (buildChartCanvas sets the inline height
   then); at 1× it flex-fills. */
.m-livechrome{flex:1;min-height:0;display:flex;flex-direction:column}
.m-chart-wrap-outer{flex:1;min-height:0;position:relative;display:flex}
.m-scrollhost{flex:1;min-height:0;display:flex;flex-direction:column;gap:8px;overflow-y:auto;padding-right:14px;scrollbar-width:none}
.m-scrollhost::-webkit-scrollbar{display:none;width:0;height:0}
/* Custom always-visible scroll indicator — overlays the right edge (absolute)
   so it never consumes flex width from the chart. Hidden by JS when no overflow. */
.m-scrolltrack{position:absolute;top:0;right:0;width:10px;height:100%;background:#0a0a0a;border-left:1px solid #1c1c1c;z-index:5;user-select:none;cursor:pointer}
.m-scrollthumb{position:absolute;left:1px;right:1px;background:#3a3a3a;border-radius:4px;min-height:28px}
.m-scrollthumb:hover{background:#6a6a6a}

/* ── Chart / detections splitter ───────────────────────────────
   The bottom detections section docks below the chart stack. Default COLLAPSED:
   .m-detsection is natural height (just the pane bar) and the chart stack
   flex-fills the whole live chrome, so the spectrum monitor takes the full
   viewport. When a pane is EXPANDED, JS adds .expanded and sets an explicit,
   clamped section height (monitor-split.js); the chart stack flex-fills the rest
   and the alerts body scrolls internally. The drag bar (.m-split) is shown only
   while expanded (and never in embedded monitors). */
.m-detsection{flex:0 0 auto;min-height:0;display:flex;flex-direction:column}
.m-detsection.expanded{overflow:hidden}
.m-detsection.expanded .m-alerts{flex:1;min-height:0;overflow-y:auto}
/* The active pane body must keep its natural content height so .m-alerts can
   scroll it. Without this it's a flex child of the column and shrinks to the
   clamped section height; combined with .m-subpanel's own overflow:hidden that
   CLIPPED the overflow instead of scrolling — tall panes (Clean Freq results +
   ranked alternatives, long Detections lists) had their tail unreachable. */
.m-detsection.expanded .m-alerts > .m-subpanel{flex:0 0 auto}
.m-split{
  flex:none;height:8px;position:relative;cursor:row-resize;
  background:var(--bg-1);border-top:1px solid var(--border-subtle);border-bottom:1px solid var(--border-subtle);
  touch-action:none;user-select:none;
}
/* grab-handle pip — brightens on hover/drag */
.m-split::before{
  content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:36px;height:3px;border-radius:2px;background:var(--border-strong);transition:background .12s;
}
.m-split:hover::before,.m-split.dragging::before{background:var(--accent)}
.m-split:focus-visible{outline:none;box-shadow:var(--ring)}

/* ── B. Chart panel ────────────────────────────────────────── */
.m-chartpanel{
  background:var(--mon-1);border:1px solid #161b22;border-radius:var(--r-sm);overflow:hidden;
  /* Flex-fill the scroll host so a single Live trace fills the viewport.
     A >1× panel switches to an explicit pixel height (set inline by
     buildChartCanvas) — .m-chartpanel.accented opts out of flex-grow so the
     fixed height wins and the stack scrolls, matching v1's applyPanelSizing. */
  flex:1 1 0;min-height:180px;display:flex;flex-direction:column;
}
/* A sized (>1×) panel uses its inline pixel height and does not stretch. */
.m-chartpanel.accented{flex:0 0 auto;min-height:0}

/* ── Live trim grips (issue 2) ─────────────────────────────────
   The draggable per-trace display-offset handle (DOM overlay; most styling is
   inline in trim-handles.js so the trace color drives the fill). These add the
   hover/drag affordances + reveal the dB readout. */
.trim-grip{box-shadow:0 1px 3px rgba(0,0,0,.5);transition:transform .08s,box-shadow .1s}
.trim-grip:hover{transform:scaleX(1.12)}
.trim-grip.dragging{box-shadow:0 0 0 2px rgba(255,255,255,.35),0 2px 6px rgba(0,0,0,.6);z-index:7}
.trim-grip:hover .trim-grip-readout,
.trim-grip.dragging .trim-grip-readout,
.trim-grip:focus-visible .trim-grip-readout{opacity:1 !important}
.trim-grip:focus-visible{outline:none;box-shadow:0 0 0 2px var(--accent)}
.m-panelhdr{
  display:flex;align-items:center;gap:6px;padding:3px 10px;flex-wrap:wrap;row-gap:4px;min-height:26px;
  border-bottom:1px solid #14181f;
}
/* Every interactive control in the chart-panel header shares ONE height +
   font so the bar reads as a single, evenly-sized row (matches the original
   app's uniform ~one-line header). Tune --m-ctrl-h to rescale the whole bar. */
.m-panelhdr{--m-ctrl-h:20px}
.m-panelhdr .m-cyc,
.m-panelhdr .m-jump,
.m-panelhdr .m-histtoggle,
.m-panelhdr .m-star,
.m-panelhdr .btn{
  height:var(--m-ctrl-h);box-sizing:border-box;flex:none;
}
/* View ▾ is a full-size .btn (.btn-sm is never defined) — pull its font + side
   padding down to the bar's scale so it sits level with the toggle controls
   instead of towering over them. Height comes from the shared rule above. */
.m-panelhdr .btn{font-size:11px;padding:0 12px;gap:5px}
.m-panelhdr.accented{border-left:3px solid var(--accent)}
.m-disclosure{
  background:none;border:none;color:var(--text-muted);cursor:pointer;font-size:12px;
  padding:2px 3px;border-radius:var(--r-sm);line-height:1;
}
.m-disclosure:hover{color:var(--text-1)}
.m-srcdot{width:8px;height:8px;border-radius:50%;background:var(--live);box-shadow:0 0 8px var(--live);flex:none}
.m-srcname{font-family:var(--font-mono);font-weight:600;font-size:12.5px;white-space:nowrap;color:var(--text-1)}
.m-srcstate{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.05em;color:var(--live);text-transform:uppercase;flex:none}
.m-cyc{
  font-family:var(--font-mono);font-size:11px;font-weight:600;color:#bfdbfe;
  background:var(--accent-soft);border:1px solid var(--accent-soft);border-radius:var(--r-sm);
  padding:0 10px;cursor:pointer;display:inline-flex;align-items:center;gap:5px;flex:none;transition:.13s;line-height:1;
}
.m-cyc:hover{border-color:var(--accent);color:#fff}
.m-cyc:focus-visible{outline:none;box-shadow:var(--ring)}
.m-cyc.def{color:var(--text-2);background:var(--bg-input);border-color:var(--border)}
.m-panelhdr .spacer{margin-left:auto}
.m-jump{
  background:var(--bg-input);border:1px solid var(--border);color:var(--text-2);
  border-radius:var(--r-sm);padding:0 10px;font-size:11px;width:104px;font-family:var(--font-mono);line-height:1;
}
.m-jump::placeholder{color:var(--text-faint)}
.m-jump:focus-visible{outline:none;border-color:var(--accent);box-shadow:none}
.m-hdrgrp{display:flex;gap:6px;align-items:center;padding-left:10px;border-left:1px solid var(--border-subtle)}
.m-star{
  width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--r-sm);
  background:transparent;border:1px solid transparent;color:var(--text-2);cursor:pointer;font-size:14px;line-height:1;
}
.m-star:hover{background:var(--bg-raised);color:var(--text-1);border-color:var(--border)}
.m-star.on{color:var(--warn);border-color:var(--warn-dim)}
.m-star:focus-visible{outline:none;box-shadow:var(--ring)}

/* chart canvas — edge-to-edge, no inset gap. Flex-fills the panel below the
   header so the chart grows to the panel's height (issue 1). When the panel is
   sized (>1×) buildChartCanvas sets an explicit inline height that wins. */
/* Waterfall stack — display:contents keeps .m-chartwrap's layout relationship
   with its host untouched; the strip is just an extra block above it. */
.m-wfstack{display:contents}
/* Opt-in waterfall strip (View ▾ → "Waterfall history"): newest sweep at the
   top, scrolling down. The canvas is absolutely inset to the chart's plot area
   (left/right set per frame from chartArea) so columns line up with the
   spectrum's frequency axis; the bitmap is native-resolution, CSS-stretched. */
.m-wfpane{position:relative;height:96px;background:var(--mon-0);border-top:1px solid #10141b;overflow:hidden}
/* canvas is a replaced element — width/height must be EXPLICIT (auto resolves
   to the intrinsic bitmap size, ignoring a left/right or top/bottom pair).
   setInsetsFromChart overrides left/width inline to track the chart plot area. */
.m-wfpane canvas{position:absolute;top:0;left:0;width:100%;height:100%;cursor:crosshair}
/* Frequency cursor line — a continuation of the chart's tap crosshair up through
   the waterfall, frequency-aligned to the strip's full-span mapping. 1px dashed
   [4,4] to match the chart line; positioned by setCursor (left set inline).
   The .preview variant (hover, not yet locked) is dimmer. pointer-events:none so
   the strip below still receives clicks. */
.m-wf-cursor{position:absolute;top:0;height:100%;width:1px;pointer-events:none;z-index:3;
  background:repeating-linear-gradient(to bottom,rgba(255,255,255,.6) 0 4px,transparent 4px 8px)}
.m-wf-cursor.preview{opacity:.5}
.m-chartwrap{position:relative;background:var(--mon-0);border-top:1px solid #10141b;margin:0;padding:0;flex:1 1 0;min-height:0}
.m-chartwrap svg{display:block;width:100%;height:100%}
.m-chartwrap .m-chart-svg{cursor:crosshair}
/* Ported Chart.js canvas — fill the wrap (Chart.js sizes it via ResizeObserver;
   display:block avoids the inline-canvas baseline gap). crosshair matches the
   old SVG affordance for the tap-readout. */
.m-chartwrap canvas{display:block;cursor:crosshair}
.m-tapcallout{
  position:absolute;z-index:5;transform:translate(-50%,-100%);
  background:var(--bg-raised);border:1px solid var(--border-strong);border-radius:var(--r-sm);
  padding:4px 8px;font-family:var(--font-mono);font-size:10.5px;color:var(--text-1);white-space:nowrap;
  box-shadow:0 6px 18px rgba(0,0,0,.55);pointer-events:none;
}
.m-tapcallout .f{color:var(--live)}
.m-tapcallout .d{color:var(--warn)}
/* hint row removed — tooltip on scroll host instead */
.m-chart-hint{display:none}

/* View ▾ popover panel */
.m-viewmenu{display:flex;flex-direction:column;gap:2px;min-width:248px;font-size:12px}
.m-viewmenu .grp-h{
  font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-muted);margin:8px 2px 4px;
}
.m-viewmenu .grp-h:first-child{margin-top:0}
.m-checkrow{
  display:flex;align-items:center;gap:9px;padding:5px 6px;border-radius:var(--r-sm);cursor:pointer;color:var(--text-1);
}
.m-checkrow:hover{background:var(--bg-raised)}
.m-checkrow input{width:14px;height:14px;accent-color:var(--accent);cursor:pointer;flex:none}
.m-checkrow .sub{margin-left:auto;font-family:var(--font-mono);font-size:10px;color:var(--text-muted)}
.m-viewmenu .divider{height:1px;background:var(--border-subtle);margin:7px 0}
.m-viewmenu .menu-btn{
  width:100%;text-align:left;background:var(--bg-input);border:1px solid var(--border);color:var(--text-2);
  border-radius:var(--r-sm);padding:6px 9px;font-size:11.5px;cursor:pointer;font-family:var(--font-ui);
}
.m-viewmenu .menu-btn:hover{border-color:var(--border-strong);color:var(--text-1)}

/* ── C. Bottom panels — single merged pane bar ─────────────────── */
/* One flex row: pane toggles interleaved with their inline sub-controls */
.m-panebar{
  display:flex;align-items:center;gap:2px;flex-wrap:wrap;
  padding:3px 6px;background:var(--bg-1);border-bottom:1px solid var(--border-subtle);
  min-height:32px;
}
/* Pane toggle buttons (▼/▶ LABEL count) — bolder/boxed */
.m-paneltoggle{
  display:inline-flex;align-items:center;gap:5px;background:var(--bg-card);border:1px solid var(--border-subtle);
  border-radius:var(--r-sm);padding:3px 9px;cursor:pointer;color:var(--text-2);font-size:11.5px;font-weight:600;
  transition:.13s;line-height:1;flex:none;white-space:nowrap;
}
.m-paneltoggle:hover{border-color:var(--border);color:var(--text-1)}
.m-paneltoggle.open{color:var(--text-1);border-color:var(--border)}
.m-paneltoggle .car{color:var(--text-muted);font-size:10px;width:10px}
.m-paneltoggle .cnt{
  font-family:var(--font-mono);font-size:10px;font-weight:600;background:var(--border);color:var(--text-2);
  border-radius:var(--r-pill);padding:1px 7px;
}
.m-paneltoggle.open .cnt{background:var(--accent-soft);color:var(--accent)}

/* Inline slot — sub-tabs/controls that immediately follow the open pane's toggle */
.m-panebar-inline{
  display:flex;align-items:center;gap:2px;flex-wrap:wrap;
  border-left:1px solid var(--border-subtle);padding-left:6px;margin-left:2px;
}
/* Right-side slot — auto-margin pushes it to far end */
.m-panebar-right{margin-left:auto;display:flex;align-items:center;gap:0}
.m-panebar-right-inner{display:flex;align-items:center;gap:4px;flex-wrap:wrap}

/* Sub-panel body — head bar lives in the pane bar now */
.m-subpanel{
  background:var(--mon-1);border:1px solid var(--border-subtle);border-radius:var(--r-md);overflow:hidden;
}
/* .m-subpanel-head kept for any future use but suppressed */
.m-subpanel-head{display:none}
.m-sort{
  display:inline-flex;align-items:center;gap:5px;font-family:var(--font-mono);font-size:11px;
  background:var(--bg-input);border:1px solid var(--border);color:var(--text-2);border-radius:var(--r-sm);
  padding:3px 8px;cursor:pointer;line-height:1;
}
.m-sort:hover{border-color:var(--border-strong);color:var(--text-1)}

/* detections table */
.m-dt-wrap{overflow-x:auto}
.m-dt{width:100%;border-collapse:collapse;font-size:12.5px}
.m-dt th{
  font-family:var(--font-mono);font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:var(--text-2);
  text-align:left;padding:8px 10px;background:var(--mon-2);border-bottom:1px solid var(--border-subtle);
  font-weight:600;white-space:nowrap;user-select:none;vertical-align:middle;
}
.m-dt th.sortable{cursor:pointer}
.m-dt th.sortable:hover{color:var(--text-1)}
.m-dt th .sar{color:var(--accent);margin-left:3px}
.m-dt th.num,.m-dt td.num{text-align:right}
/* Top-align row cells so the checkbox + line-1 values sit on the FREQUENCY line;
   a row's comment hangs below (line 2) only inside the freq cell. */
.m-dt td{padding:10px;border-bottom:1px solid #11151c;vertical-align:top;color:var(--text-1)}
.m-dt tbody tr.det-row{transition:background .1s}
.m-dt tbody tr.det-row:hover{background:#0e141d}
.m-dt tbody tr.det-row.sel{background:#0e1c33}
.m-dt-freq{font-family:var(--font-mono);font-weight:600;color:var(--text-1)}
.m-dt-tagrow{display:flex;gap:4px;margin-top:3px;flex-wrap:wrap}
.m-dt-tagrow.inline{margin-top:0}
.m-dt-tag{
  font-family:var(--font-mono);font-size:8.5px;letter-spacing:.06em;text-transform:uppercase;
  padding:1px 5px;border-radius:var(--r-sm);border:1px solid;line-height:1.5;
}
.m-dt-lv{font-family:var(--font-mono);color:var(--text-2);font-size:11.5px;white-space:nowrap}
.m-dt-lv .pk{color:var(--text-1)}
.m-dt-lv .drop{color:var(--danger)}
.m-dt-seen{font-family:var(--font-mono);font-size:11px;color:var(--text-muted);white-space:nowrap}
.m-dt-trace{
  font-family:var(--font-mono);font-size:11px;color:var(--text-1);background:none;border:1px solid transparent;
  border-radius:var(--r-sm);cursor:pointer;display:inline-flex;align-items:center;gap:6px;padding:3px 6px;margin:-3px -6px;
}
.m-dt-trace .tl{color:var(--text-2)}
.m-dt-trace .more{
  color:var(--text-muted);font-size:10px;background:var(--mon-2);border:1px solid var(--border-subtle);
  border-radius:var(--r-pill);padding:0 5px;
}
.m-dt-trace .car{color:var(--text-faint)}
.m-dt-trace:hover{border-color:var(--border);color:#fff}
.m-dt-trace:hover .more{color:var(--accent);border-color:var(--accent-soft)}
.m-dt-trace:focus-visible{outline:none;box-shadow:var(--ring)}
.m-dt-note{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--warn);margin-top:4px}
/* Per-row actions are ALWAYS visible (not hover-gated) — required for touch/mobile,
   where there is no hover. Quiet by default (transparent icon buttons), brighten on
   hover/focus. */
.m-dt-actions{display:flex;gap:3px;justify-content:flex-end;opacity:1}
.m-rowbtn{
  width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--r-sm);
  background:transparent;border:1px solid transparent;color:var(--text-2);cursor:pointer;font-size:13px;line-height:0;
}
.m-rowbtn svg{display:block;width:14px;height:14px}
.m-rowbtn:hover{background:var(--bg-raised);color:var(--text-1);border-color:var(--border)}
.m-rowbtn:focus-visible{outline:none;box-shadow:var(--ring)}
.m-check{width:14px;height:14px;accent-color:var(--accent);cursor:pointer;margin:0}
/* checkbox column: identical left padding on header + body cells so the
   tri-state select-all sits directly above the per-row checkboxes. */
.m-dt th.m-cbcol,.m-dt td.m-cbcol{padding-left:12px;padding-right:6px}
.m-dt td.m-cbcol .m-check{display:block}
/* nudge the per-row checkbox to sit centered on the frequency line (line 1) */
.m-dt tbody td.m-cbcol .m-check{margin-top:4px}

/* dot status mini */
.m-statdot{width:7px;height:7px;border-radius:50%;display:inline-block;flex:none}
.m-statdot.active{background:var(--live);box-shadow:0 0 6px var(--live)}
.m-statdot.paused{background:var(--warn)}
.m-statdot.muted{background:var(--text-muted)}
.m-statdot.finished{background:var(--text-faint)}

/* bulk-action bar */
.m-bulk{
  display:flex;align-items:center;gap:12px;padding:9px 12px;background:var(--accent-soft);
  border-bottom:1px solid #24487e;font-size:12px;
}
.m-bulk .n{font-weight:600;color:#bfdbfe;font-family:var(--font-mono)}
.m-bulk .spacer{margin-left:auto}

/* triangulation popover — reads as a real panel */
/* The .popover card is capped at max-width:320px (components.css), but this
   content's widest line (the header) needs ~500px. Without lifting the cap the
   card stays 320px and the bars/hint/header spill past its right border. So:
   lift the cap only for popovers holding a .m-tri, and give .m-tri a fixed
   510px so the header fits on one line and the card hugs the content exactly. */
.popover:has(.m-tri){max-width:none}
/* Sources popover holds wide rows (name + tag/band chips + 4 dots + status word);
   the default .popover max-width:320px clipped it (its content wants 340–440px).
   Lift the cap so .m-sources' own width governs. */
.popover:has(.m-sources){max-width:none}
.m-tri{width:510px;max-width:510px;padding:2px}
.m-tri .tri-h{
  font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted);
  margin-bottom:13px;line-height:1.45;
}
.m-tri .tri-row{display:flex;align-items:center;gap:10px;margin-bottom:11px;font-family:var(--font-mono);font-size:12px}
.m-tri .tri-row .nm{display:inline-flex;align-items:center;gap:4px;width:158px;color:var(--text-1);white-space:nowrap;overflow:hidden}
.m-tri .tri-row .nm .lead{display:inline-flex;align-items:center;flex:none}
.m-tri .tri-row .nm .lead svg{display:block;width:14px;height:14px}
.m-tri .tri-row .nm b{font-weight:600;overflow:hidden;text-overflow:ellipsis}
.m-tri .tri-row .nm .arr{color:var(--text-faint);flex:none}
.m-tri .tri-row .nm .tr{color:var(--text-muted);overflow:hidden;text-overflow:ellipsis}
.m-tri .tri-row .lv{width:54px;color:var(--text-2);text-align:right;flex:none}
.m-tri .tri-row .pk{width:62px;color:var(--text-muted);text-align:right;flex:none}
.m-tri .tri-row .age{width:40px;color:var(--text-faint);text-align:right;flex:none}
.m-tri .tri-row .bar{flex:1;min-width:48px;height:8px;border-radius:4px;background:#16202f;overflow:hidden}
.m-tri .tri-row .bar i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),#60a5fa)}
.m-tri .tri-row .recdot{flex:none;width:14px;height:14px;border-radius:50%;border:1px solid var(--border);background:transparent;cursor:pointer;padding:0;position:relative}
.m-tri .tri-row .recdot.on{background:#ef4444;border-color:#ef4444;box-shadow:0 0 0 2px color-mix(in srgb,#ef4444 28%,transparent)}
.m-tri .tri-row .recdot:not(.on){cursor:default;opacity:.5}
.m-tri .tri-row .recdot:focus-visible{outline:none;box-shadow:var(--ring)}
.m-tri .tri-recs{margin:-4px 0 11px 24px;display:flex;flex-direction:column;gap:3px}
.m-tri .tri-rec{font-family:var(--font-mono);font-size:10.5px;color:var(--text-muted);line-height:1.4}
.m-tri .tri-row.top .nm b{color:#6ee7b7}
.m-tri .tri-row.top .bar i{background:linear-gradient(90deg,#22c55e,#4ade80)}
.m-tri .tri-hint{font-family:var(--font-mono);font-size:11.5px;color:var(--text-2);margin-top:13px;line-height:1.5;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.m-tri .tri-hint b{color:#6ee7b7}

/* interference sub-panel (lighter) — sub-tabs use the shared .m-statuschip
   styling (see renderStatusTabs / monitor.js injected CSS) to match Detections. */
.m-iface-list{display:flex;flex-direction:column}
.m-iface-row{
  display:flex;align-items:center;gap:12px;padding:10px 12px;border-bottom:1px solid #11151c;font-size:12px;
}
.m-iface-row:last-child{border-bottom:none}
.m-iface-row .freq{font-family:var(--font-mono);font-weight:600;color:var(--text-1);width:96px}
.m-iface-row .desc{color:var(--text-2);flex:1;min-width:0}
.m-iface-row .desc .sub{color:var(--text-muted);font-size:11px;font-family:var(--font-mono)}
.m-iface-row .acts{display:flex;gap:6px;flex-shrink:0}
.m-iface-empty{padding:18px 12px;text-align:center;color:var(--text-muted);font-size:12px}

/* responsive: mobile-first compatibility */
@media(max-width:760px){
  .m-subhdr .m-evtitle{max-width:100%;font-size:15px}
  .m-subhdr{gap:10px}
  /* chart-panel header: ~10 controls crammed into one row clip/overflow on
     phones. The bar already declares flex-wrap:wrap — make sure it wraps
     CLEANLY: drop the margin-left:auto spacer (it forces a full-width row and
     pushes the right-hand group off-screen) so controls flow onto extra rows
     instead of overflowing, and neutralize the inner group's left border. */
  .m-panelhdr{gap:5px 6px}
  .m-panelhdr .spacer{margin-left:0;flex-basis:0}
  .m-panelhdr .m-hdrgrp{padding-left:0;border-left:none}
  .m-jump{width:84px}
  .m-tri{width:510px;min-width:0;max-width:88vw}
  .m-sources{min-width:0;max-width:92vw}
  /* triangulation rows: let the name+stats wrap above the bar on phone widths so
     the analyzer→trace label and age column stay legible in a narrow card. */
  .m-tri .tri-row{flex-wrap:wrap;gap:8px 10px}
  .m-tri .tri-row .nm{width:auto;flex:1 1 100%;min-width:0}
  .m-tri .tri-row .bar{flex:1 1 100px;order:5}
  .m-tri .tri-row .recdot{order:6}
  /* Pane bar wraps naturally on narrow widths */
  .m-panebar{gap:3px;padding:3px 4px}
  .m-panebar-inline{border-left:none;padding-left:0;margin-left:0;flex-wrap:wrap}
  .m-panebar-right{margin-left:0;flex-wrap:wrap}
  .m-cf-target{min-width:120px}

  /* Replay detection feed: the 5-column grid (Time/Freq/Peak/Source/Band ≈
     406px) overflows phones. Reflow each detection into a compact stacked card
     with inline field labels. The grid is declared inline in replay.js, so the
     override needs !important. The column header row is hidden — each card now
     carries its own labels via data-label. */
  .rd-feed-head{display:none !important;}
  .rd-feed-row{
    display:flex !important;
    flex-direction:column;
    gap:2px;
    padding:8px 10px !important;
    grid-template-columns:none !important;
  }
  .rd-feed-row>span{
    white-space:normal !important;
    overflow:visible !important;
    text-overflow:clip !important;
    display:flex;
    justify-content:space-between;
    gap:10px;
    min-width:0;
  }
  .rd-feed-row>span[data-label]::before{
    content:attr(data-label);
    color:var(--text-muted);
    font-weight:600;
    font-size:0.66rem;
    text-transform:uppercase;
    letter-spacing:0.05em;
    flex:0 0 auto;
  }
  /* Source/Band can be long — let their value wrap & stay readable */
  .rd-feed-row>span{text-align:right;}
  .rd-feed-row>span[data-label]::before{text-align:left;}
}

/* ── Marker-info popup ───────────────────────────────────────────────────────
   Ported from the original SPA's callout: a floating card keyed to the clicked
   marker's color (--mk, set inline; falls back to the accent). The marker's own
   color rings the card (border + glow) so it reads as "this marker", on the
   app's dark surface, opened beside the clicked marker (see openMarkerInfoPopup).
   Values are clean read-only text that swap to an input on click. */
.popover.popover--marker{
  --mk:var(--accent);
  border:1.5px solid var(--mk);
  /* Deep marker-tinted card (the original's saturated callout) over a near-black
     base, so the marker color IS the card's identity — not a faint wash. */
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--mk) 7%, transparent), transparent 70px),
    color-mix(in srgb, var(--mk) 15%, #070a09);
  /* Crisp marker ring + a soft colored glow so the card visibly pops off the chart. */
  box-shadow:
    0 0 0 1px var(--mk),
    0 0 22px -3px color-mix(in srgb, var(--mk) 60%, transparent),
    0 14px 40px rgba(0,0,0,.72);
  min-width:222px; max-width:344px;
}
.m-markerinfo{ display:flex; flex-direction:column; gap:var(--s2); }
.m-markerinfo .mi-name{ font-weight:700; font-size:15px; line-height:1.2; letter-spacing:.1px; word-break:break-word; }
.popover--marker .m-markerinfo .mi-name{ text-shadow:0 0 16px color-mix(in srgb, var(--mk) 45%, transparent); }
.m-markerinfo .mi-meta{ color:var(--text-1); font-size:12px; margin-top:-4px; font-family:var(--font-mono); }
.m-markerinfo .mi-meta span+span{ margin-left:4px; }
.m-markerinfo .mi-sync{ display:flex; align-items:center; gap:6px; font-size:11px; color:var(--text-2); }
.m-markerinfo .mi-sync .dot{ width:7px; height:7px; border-radius:50%; background:var(--ok); flex:0 0 auto; }
.m-markerinfo .mi-sync .mini{ background:none; border:none; color:var(--accent); cursor:pointer; font:inherit; font-size:11px; display:inline-flex; align-items:center; gap:3px; padding:0; }
.m-markerinfo .mi-sync .mini:hover{ text-decoration:underline; }
.m-markerinfo .mi-cat{ margin:1px 0; }
/* Category chip — a vivid marker-colored pill (the original's filled chip) so
   the card's identity reads at a glance, instead of the muted grey band chip. */
.popover--marker .mi-cat .m-bandchip{
  font-size:10px; font-weight:700; letter-spacing:.05em; padding:2px 8px;
  color:var(--mk);
  background:color-mix(in srgb, var(--mk) 20%, transparent);
  border:1px solid color-mix(in srgb, var(--mk) 55%, transparent);
}
.m-markerinfo .mi-linkrow{ display:flex; align-items:center; gap:var(--s2); flex-wrap:wrap; }
.m-markerinfo .mi-extlink{ font-size:12px; color:var(--accent); text-decoration:none; display:inline-flex; align-items:center; gap:4px; }
.m-markerinfo .mi-extlink:hover{ text-decoration:underline; }
.m-markerinfo .mi-details{ border-top:1px solid var(--border-subtle); padding-top:var(--s2); margin-top:2px; }
.m-markerinfo .mi-details>summary{ cursor:pointer; font-size:12px; color:var(--text-2); list-style:none; user-select:none; }
.m-markerinfo .mi-details>summary::-webkit-details-marker{ display:none; }
.m-markerinfo .mi-details>summary::before{ content:'▸ '; color:var(--text-muted); }
.m-markerinfo .mi-details[open]>summary::before{ content:'▾ '; }
.m-markerinfo .mi-details>summary:focus-visible{ outline:1px solid var(--accent); outline-offset:2px; border-radius:3px; }
.m-markerinfo .mi-field{ display:grid; grid-template-columns:84px 1fr auto; align-items:center; gap:3px 10px; font-size:12px; min-height:22px; margin-top:4px; }
.m-markerinfo .mi-field .k{ color:var(--text-muted); font-family:var(--font-mono); font-size:10px; letter-spacing:.02em; }
.m-markerinfo .mi-field .v{ color:var(--text-1); word-break:break-word; }
.m-markerinfo .mi-field .v.mi-editable{ cursor:pointer; border-radius:4px; padding:1px 4px; margin:-1px -4px; }
.m-markerinfo .mi-field .v.mi-editable:hover{ background:color-mix(in srgb, var(--mk, #fff) 14%, transparent); }
.m-markerinfo .mi-field .v.mi-editable:focus-visible{ outline:1px solid var(--mk, var(--accent)); outline-offset:0; }
.m-markerinfo .mi-inp,
.m-markerinfo .mi-sel{ width:100%; padding:2px 6px; background:var(--bg-input); border:1px solid var(--border-strong); border-radius:5px; color:var(--text-1); font:inherit; font-size:12px; }
.m-markerinfo .mi-sel{ cursor:pointer; }
.m-markerinfo .mi-inp:focus,
.m-markerinfo .mi-sel:focus{ outline:none; border-color:var(--mk, var(--accent)); box-shadow:0 0 0 2px color-mix(in srgb, var(--mk, var(--accent)) 30%, transparent); }
.m-markerinfo .mi-resetdot{ background:none; border:none; color:transparent; cursor:pointer; font-size:16px; line-height:1; padding:0 2px; width:auto; }
.m-markerinfo .mi-resetdot.on{ color:var(--warn); }
.m-markerinfo .mi-resetdot:hover{ color:var(--text-1); }
.m-markerinfo .mi-foot{ margin-top:2px; border-top:1px solid var(--border-subtle); padding-top:var(--s2); display:flex; justify-content:flex-end; }

/* ── A1 signal-label chip + explain popover ─────────────────────────────── */
.siglabel{display:inline-flex;align-items:center;gap:6px;border-radius:999px;
  padding:2px 4px 2px 9px;font-size:11.5px;font-weight:500;border:1px solid var(--border);
  background:var(--bg-raised);cursor:default;line-height:1.5;white-space:nowrap}
.siglabel .sig-icn{font-family:var(--font-mono);opacity:.8}
.siglabel .sig-conf{font-family:var(--font-mono);font-size:10px;font-weight:600;padding:0 3px}
.siglabel .sig-qm{width:16px;height:16px;border-radius:50%;border:1px solid var(--border);
  display:inline-flex;align-items:center;justify-content:center;font-size:10px;
  color:var(--text-muted);cursor:pointer;background:var(--bg-1);padding:0;line-height:1}
.siglabel .sig-qm:hover{color:var(--accent);border-color:var(--accent)}
.siglabel.high{border-color:rgba(52,211,153,.4);color:#bff3df;background:rgba(15,59,48,.5)}
.siglabel.high .sig-conf{color:var(--ok)}
.siglabel.med{border-color:rgba(251,191,36,.38);color:#f5e2b0;background:rgba(61,47,8,.5)}
.siglabel.med .sig-conf{color:var(--warn)}
.siglabel.low{border-color:var(--border);color:var(--text-2);background:var(--bg-raised)}
.siglabel.low .sig-conf{color:var(--text-muted)}
.siglabel.det{border-color:rgba(94,106,210,.4);color:#c7ccf2;background:var(--accent-soft)}
.siglabel.det .sig-conf{color:var(--accent)}
.popover.sig-pop{width:320px}
.sig-pop .sig-prov{font-size:10.5px;color:var(--text-muted);margin:0 0 10px;font-family:var(--font-mono)}
.sig-pop .sig-why{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);margin:0 0 6px}
.sig-pop .sig-reasons{list-style:none;margin:0 0 4px;padding:0;display:flex;flex-direction:column;gap:5px}
.sig-pop .sig-reasons li{display:flex;gap:8px;font-size:12px;color:var(--text-2);align-items:baseline}
.sig-pop .sig-k{font-family:var(--font-mono);font-size:10px;color:var(--accent);flex:none;width:92px}
.sig-pop .sig-actions{display:flex;gap:8px;border-top:1px solid var(--border);padding-top:10px;margin-top:8px}
.sig-pop .sig-btn{font-size:11.5px;border-radius:6px;padding:5px 10px;cursor:pointer;
  border:1px solid var(--accent);background:var(--accent-soft);color:#c7ccf2}
/* A1 operator relabel menu — a compact vertical family picker in a popover. */
.popover.m-sigcorrect-pop{width:180px;padding:4px}
.m-sigcorrect{display:flex;flex-direction:column;gap:1px}
.m-sigcorrect .m-menu-item{display:block;width:100%;text-align:left;font-size:12px;
  border:0;background:transparent;color:var(--text-1);padding:6px 9px;border-radius:5px;cursor:pointer}
.m-sigcorrect .m-menu-item:hover,
.m-sigcorrect .m-menu-item:focus-visible{background:var(--accent-soft);color:#c7ccf2;outline:none}
