/* =====================================================================
   Night Library — STREAMS: N parallel feeds and one persistent rail.

   This is the mode that is open while a job runs, so its whole layout
   is a promise about motion: the feeds move, the rail does not, and
   nothing under the reader's eye reflows because something landed three
   columns away.

   Three rules are carried in from the Library's rendering pass and none
   of them is stylistic:

     · NO backdrop-filter. Under these panes are live iframes and
       decoding video stills, and a blurred pane re-rasterises every one
       of them on every frame of a scroll.

     · `contain: layout paint style` on every leaf that repeats — never
       `contain: size`, never `content-visibility`. A thumbnail landing
       must not re-lay-out its neighbours; a row whose height the engine
       has to guess is a scroll that jitters.

     · The row is a FIXED height and the number lives in one place, the
       --nslm-streams-row token below. js/nightshift-library-mode-streams.jsx
       hands the SAME number to modes.windowSlice, which does arithmetic
       rather than measurement: if the two ever disagree the spacers
       stop summing to the list's real height and the window drifts a
       few pixels per screen.
   ===================================================================== */

.nslm-streams {
  --nslm-streams-row: 56px;
  --nslm-streams-tile-w: 48px;
  --nslm-streams-tile-h: 30px;
  gap: 0;
}
.nslm-streams[data-density="comfortable"] {
  --nslm-streams-row: 80px;
  --nslm-streams-tile-w: 70px;
  --nslm-streams-tile-h: 44px;
}

/* ---------------------------------------------------------------------
   The frame: feeds beside a rail. `min-height: 0` on both is the trick
   that makes the inner .nsl-pane-body scrollers real — a flex item
   defaults to "never shrink below my content", which would push the
   whole page tall and hand the scroll back to the shell.
--------------------------------------------------------------------- */
.nslm-streams-body {
  display: flex;
  gap: 10px;
  flex: 1 1 auto;
  min-height: 0;
  min-width: 0;
  /* A backstop, not the fix. The stacked rule below is what keeps the
     rail inside the frame; this makes sure that if a future floor ever
     out-grows the frame again the overflow is clipped rather than
     painted on top of whatever the page draws next. It clips nothing
     today: every child here is a .nsl-pane, which already carries
     overflow: hidden of its own. */
  overflow: hidden;
}
.nslm-streams-cols {
  display: flex;
  gap: 10px;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
}
/* Columns share the width EQUALLY (`flex: 1 1 0`, not `1 1 auto`): a
   feed with long filenames must not win space from the feed beside it,
   or the layout would shift every time an attempt landed. */
.nslm-streams-col {
  flex: 1 1 0;
  min-width: 0;
}
.nslm-streams-rail {
  flex: none;
  width: var(--nsl-rail-w);
}

/* Under ~860px the rail and four feeds cannot coexist across the width.
   The JSX drops feeds before it lets one squeeze under 230px; here the
   rail goes UNDER the feeds rather than eating them, so the inspector
   stays reachable instead of disappearing at the size where a phone-ish
   window most needs it. */
/* Both floors here are SHRINKABLE, and that is the whole point of the
   rule. The first draft asked for 220px of feeds plus a rigid 300px
   rail plus the gap — a 530px minimum that nothing could give back —
   while the frame is as short as `--nsl-mode-h`'s own 420px clamp, and
   shorter still inside .nsl-framed, where the mode takes what the
   viewport has left rather than a fixed height. `flex: none` means
   `flex-shrink: 0`, so in a narrow AND short window the rail simply
   ran past the bottom of a frame that sets no overflow of its own.
   `flex: 0 1 300px` keeps 300px as the PREFERENCE and lets the rail
   give way when the frame cannot pay for it; `min-height: 0` is what
   makes that shrink actually reach the rail's own scroller. */
.nslm-streams-body.stacked { flex-direction: column; }
.nslm-streams-body.stacked .nslm-streams-cols {
  flex: 1 1 auto;
  min-height: 150px;
}
.nslm-streams-body.stacked .nslm-streams-rail {
  width: auto;
  flex: 0 1 300px;
  height: auto;
  min-height: 0;
}

/* ---------------------------------------------------------------------
   The modebar controls.
--------------------------------------------------------------------- */
.nslm-streams-seg {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--nsf-glass-border);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.03);
}
.nslm-streams-seg-btn {
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--nsf-haze);
  font: 9.5px var(--nsf-mono);
  letter-spacing: 0.06em;
  padding: 4px 9px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.12s ease, background 0.12s ease;
}
.nslm-streams-seg-btn:hover { color: #fff; background: rgba(255, 255, 255, 0.06); }
.nslm-streams-seg-btn:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: -1px; }
.nslm-streams-seg-btn.on { color: #fff; background: rgba(255, 255, 255, 0.11); }
.nslm-streams-live.on { color: var(--nsf-supported); border-color: rgba(var(--nsl-ok-rgb), 0.45); }
.nslm-streams-live:focus-visible,
.nslm-streams-pause:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 1px; }

/* ---------------------------------------------------------------------
   A column head. The <select> IS the label — the channel's name is the
   thing you change, and a separate title beside a picker showing the
   same word is a word wasted at 230px.
--------------------------------------------------------------------- */
.nslm-streams-idx {
  flex: none;
  width: 15px;
  height: 15px;
  border-radius: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.07);
  color: var(--nsf-bone);
  font: 9px var(--nsf-mono);
}
.nslm-streams-pick {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 160px;
  font-size: 9.5px;
  padding: 3px 4px;
  text-transform: none;
  letter-spacing: 0;
}
.nslm-streams-pick:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 1px; }
.nslm-streams-held { color: var(--nsf-amber); }
.nslm-streams-pause { padding: 2px 6px; flex: none; }
.nslm-streams-col.paused .nsl-pane-head { background: rgba(var(--nsl-amber-rgb), 0.07); }

/* A note strip, not a row in the list: the truncation and first-read
   states must not scroll away from the reader who needs them. */
.nslm-streams-note {
  flex: none;
  padding: 4px 12px;
  border-bottom: 1px solid var(--nsf-glass-border);
  font: 9.5px var(--nsf-mono);
  color: rgba(var(--nsl-haze-rgb), 0.75);
}
.nslm-streams-empty-hint { font-size: 10px; opacity: 0.8; }

/* ---------------------------------------------------------------------
   A feed row.

   Fixed height, border-box, and the separator INSIDE that height —
   a margin or an outside border would make the real row taller than
   the number the windower is doing arithmetic with.
--------------------------------------------------------------------- */
.nslm-streams-list { display: block; }
.nslm-streams-row {
  position: relative;
  display: flex;
  align-items: stretch;
  height: var(--nslm-streams-row);
  box-sizing: border-box;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  contain: layout paint style;
}
.nslm-streams-row:hover { background: rgba(255, 255, 255, 0.035); }
.nslm-streams-row.picked { background: rgba(var(--nsl-amber-rgb), 0.1); }
.nslm-streams-row.sel { background: rgba(var(--nsl-amber-rgb), 0.06); }
.nslm-streams-row.picked.sel { background: rgba(var(--nsl-amber-rgb), 0.13); }

/* The kind's hue as a 2px edge — the same vocabulary the grid card's
   .nsl-accent speaks, at the width a 56px row can spare. */
.nslm-streams-edge {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  opacity: 0.75;
  pointer-events: none;
}
.nslm-streams-edge-err { background: var(--nsf-contradicted); }

.nslm-streams-hit {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px 6px 10px;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
}
.nslm-streams-hit:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: -2px; }

.nslm-streams-tile {
  width: var(--nslm-streams-tile-w);
  height: var(--nslm-streams-tile-h);
}
/* A failure has no artifact, so it gets no thumbnail — a dashed box
   rather than a picture is the point, not a missing asset. */
.nslm-streams-errtile {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed rgba(212, 87, 107, 0.45);
  border-radius: 5px;
  color: var(--nsf-contradicted);
  font-size: 13px;
}

.nslm-streams-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  overflow: hidden;
}
.nslm-streams-l1 {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
  font: 11px/1.25 var(--nsf-mono);
}
.nslm-streams-seq { flex: none; font-weight: 600; }
.nslm-streams-name {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--nsf-bone);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nslm-streams-errreason {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--nsf-contradicted);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nslm-streams-when {
  flex: none;
  color: rgba(var(--nsl-haze-rgb), 0.8);
  font-size: 9.5px;
}
/* The durable-library mark, on line one rather than line two: line two
   is nowrap at compact density and already has the provenance and the
   channel's own metric competing for the width, so a third thing there
   would ellipsize one of the two facts the row exists to state. */
.nslm-streams-kept {
  flex: none;
  color: var(--nsf-amber);
  font-size: 9.5px;
  line-height: 1;
}

/* Provenance and the channel's own metric share one line. At compact
   they compete for it and both ellipsize; at comfortable the line
   WRAPS, so the metric drops to a line of its own rather than being cut
   — which is the whole difference between the two densities. */
.nslm-streams-l2 {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
  flex-wrap: nowrap;
  overflow: hidden;
  font: 10px/1.3 var(--nsf-mono);
}
.nslm-streams[data-density="comfortable"] .nslm-streams-l2 { flex-wrap: wrap; row-gap: 3px; }
.nslm-streams[data-density="comfortable"] .nslm-streams-l1 { font-size: 12px; line-height: 1.3; }
.nslm-streams[data-density="comfortable"] .nslm-streams-hit { padding: 9px 4px 9px 10px; gap: 10px; }

.nslm-streams-prov {
  flex: 0 1 auto;
  min-width: 0;
  color: rgba(var(--nsl-haze-rgb), 0.78);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nslm-streams-chip {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 100%;
  border: 1px solid var(--nsf-glass-border);
  border-radius: 4px;
  padding: 0 5px;
  font: 9px var(--nsf-mono);
  color: var(--nsf-haze);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nslm-streams-t-haze { color: var(--nsf-haze); }
.nslm-streams-t-supported { color: var(--nsf-supported); border-color: rgba(var(--nsl-ok-rgb), 0.4); }
.nslm-streams-t-split { color: var(--nsf-split); border-color: rgba(224, 180, 80, 0.4); }
.nslm-streams-t-contradicted { color: var(--nsf-contradicted); border-color: rgba(212, 87, 107, 0.4); }
.nslm-streams-t-spread { color: var(--nsf-spread); border-color: rgba(181, 126, 220, 0.4); }
.nslm-streams-t-amber { color: var(--nsf-amber); border-color: rgba(var(--nsl-amber-rgb), 0.4); }
/* An absence is a word in italics with a dashed edge — never a zero,
   never an empty chip that reads as "fine". */
.nslm-streams-t-none {
  color: rgba(var(--nsl-haze-rgb), 0.55);
  border-style: dashed;
  font-style: italic;
}

/* The verbs. Dim until the row is under the pointer or holds focus, so
   a still feed reads as content rather than as four hundred buttons —
   but never display:none, or they would leave the tab order and the
   keyboard reader would lose them. */
/* The row's verbs float over its right edge on hover or focus. They
   used to sit in the flow at opacity 0 - invisible, but still ~150px
   wide (cluster link, select, preview, open), which left a four-column
   feed a few characters of text per row. */
.nslm-streams-acts {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 0 6px 0 22px;
  background: linear-gradient(to right, transparent, var(--nsf-panel, #10131c) 18px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
}
.nslm-streams-row:hover .nslm-streams-acts,
.nslm-streams-acts:focus-within { opacity: 1; pointer-events: auto; }
.nslm-streams-act {
  width: 19px;
  height: 19px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--nsf-glass-border);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.35);
  color: rgba(232, 228, 218, 0.85);
  font: 10px var(--nsf-mono);
  cursor: pointer;
  padding: 0;
}
.nslm-streams-act:hover { color: var(--nsf-amber); border-color: rgba(var(--nsl-amber-rgb), 0.5); }
.nslm-streams-act:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 1px; }
.nslm-streams-act.on { color: var(--nsf-amber); border-color: rgba(var(--nsl-amber-rgb), 0.6); }

/* ---------------------------------------------------------------------
   The inspector rail.
--------------------------------------------------------------------- */
.nslm-streams-hero {
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: 0;
  border-bottom: 1px solid var(--nsf-glass-border);
}
.nslm-streams-sec {
  padding: 10px 12px;
  border-bottom: 1px solid var(--nsf-glass-border);
}
.nslm-streams-sec:last-child { border-bottom: 0; }
.nslm-streams-sec-h {
  font: 9px var(--nsf-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--nsf-haze);
  margin-bottom: 7px;
}
.nslm-streams-heroname {
  font: 12px var(--nsf-mono);
  color: var(--nsf-bone);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nslm-streams-errhead {
  font: 600 12.5px var(--nsf-mono);
  color: var(--nsf-contradicted);
  overflow-wrap: anywhere;
}
.nslm-streams-say {
  margin: 6px 0 0;
  font: 11px/1.6 var(--nsf-sans);
  color: rgba(232, 228, 218, 0.86);
  overflow-wrap: anywhere;
}
.nslm-streams-fine {
  margin: 7px 0 0;
  font: 10px/1.55 var(--nsf-sans);
  color: rgba(var(--nsl-haze-rgb), 0.75);
}
.nslm-streams-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.nslm-streams-actions .nsa-act-btn:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 1px; }
.nslm-streams-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 7px;
}

/* The rail's own metric tiles want to fill the 320px rather than sit in
   a ragged row of minimums. */
.nslm-streams-rail .nsl-metrics .nsl-metric { flex: 1 1 84px; }
