/* =====================================================================
   Night Library — STORYBOARD.

   A collections rail, a board of sequence rows, a deliverables tray at
   the top of the board. The mode is NOT framed: it scrolls with the
   page, so the rail is sticky rather than a pane with its own scroller,
   and the board's rows are windowed against the page's scroller.

   Three things here are load-bearing rather than cosmetic:

     · .nslm-storyboard-strip declares `overflow-y: hidden` EXPLICITLY.
       CSS computes an omitted `overflow-y: visible` to `auto` as soon
       as overflow-x is not visible, and the Library's shared
       nslScrollerOf() picks its IntersectionObserver root by reading
       exactly that property. A strip that computed to `auto` would
       become the observer root for its own tiles, and then all forty
       filmstrips on the board would report their tiles as on-screen at
       once — the one thing the shared thumbnail budget exists to stop.

     · .nslm-storyboard-row has NO height here. The row's height is the
       pitch modes.windowSlice() is doing arithmetic with, so it is set
       inline from the one constant in the .jsx; a second copy in this
       file is a second copy that can drift, and a drifted pitch is a
       board that scrolls to the wrong sequence.

     · No backdrop-filter, on the sticky rail or anywhere else. Under
       these panes are live iframes and decoding video stills, and a
       blur re-rasterises all of it every frame it scrolls.
   ===================================================================== */

.nslm-storyboard {
  /* One place for the tile geometry: the strip's height, the tile and
     the "+N more" placeholder all have to agree, and they only stay
     agreed if they are reading the same number. */
  --nslm-sb-tile-w: 160px;
  --nslm-sb-tile-h: 148px;
  --nslm-sb-thumb-h: 90px;
  --nslm-sb-rail-w: 240px;
  /* clears the Library's sticky filter toolbar */
  --nslm-sb-sticky-top: 62px;
}

/* ---------------------------------------------------------------------
   Board + rail
--------------------------------------------------------------------- */
.nslm-storyboard-body {
  display: grid;
  grid-template-columns: minmax(0, var(--nslm-sb-rail-w)) minmax(0, 1fr);
  gap: 16px;
  /* The grid items STRETCH, and that is the whole reason the rail
     sticks. `align-items: start` would shrink-wrap the <aside> to its
     own content, and a sticky element's travel is the height of its
     containing block minus its own — so the sticky rail inside a
     shrink-wrapped aside has a range of exactly zero px and scrolls
     away with the page like a static box. On a forty-sequence board
     that is the rail gone after the first screen, which is the failure
     the narrow-width rule below is written to avoid. The aside is a
     block box and the sticky div inside it is height:auto, so nothing
     else is stretched by this. */
  align-items: stretch;
}
.nslm-storyboard-rail { min-width: 0; align-self: stretch; }
/* Sticky, not fixed and not its own scrollport: the page is the
   scroller in this mode, and a rail that scrolled independently would
   put two scrollbars an inch apart. */
.nslm-storyboard-rail-sticky {
  position: sticky;
  top: var(--nslm-sb-sticky-top);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.nslm-storyboard-rail-pane { flex: none; }
.nslm-storyboard-rail-list {
  list-style: none;
  margin: 0;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  /* The rail is capped in the markup, so this bound is only ever hit
     by a reader who asked to see all of them. */
  max-height: min(46vh, 460px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}
.nslm-storyboard-rail-list::-webkit-scrollbar { width: 8px; }
.nslm-storyboard-rail-list::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.14);
  border-radius: 999px;
}
.nslm-storyboard-rail-list::-webkit-scrollbar-track { background: transparent; }

.nslm-storyboard-rail-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--nsf-haze);
  font: 11px var(--nsf-mono);
  text-align: left;
  padding: 5px 7px;
  cursor: pointer;
  transition: color 0.12s ease, background 0.12s ease;
}
.nslm-storyboard-rail-btn:hover { color: #fff; background: rgba(255, 255, 255, 0.06); }
.nslm-storyboard-rail-btn:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: -2px; }
.nslm-storyboard-rail-btn.active {
  color: var(--nsf-bone);
  background: rgba(255, 255, 255, 0.09);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
}
.nslm-storyboard-rail-caret { flex: none; opacity: 0.5; font-size: 9px; }
.nslm-storyboard-rail-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nslm-storyboard-rail-n {
  flex: none;
  font-size: 10px;
  color: rgba(var(--nsl-haze-rgb), 0.8);
  background: rgba(255, 255, 255, 0.05);
  border-radius: 999px;
  padding: 1px 6px;
}
/* A sequence holding a recorded failure gets a mark, never a colour
   over the whole row — the count and its wording live in the title. */
.nslm-storyboard-rail-dot { flex: none; color: var(--nsf-contradicted); font-size: 13px; line-height: 1; }
.nslm-storyboard-rail-all {
  border: 0;
  border-top: 1px solid var(--nsf-glass-border);
  background: transparent;
  color: rgba(var(--nsl-haze-rgb), 0.85);
  font: 10px var(--nsf-mono);
  padding: 7px 9px;
  cursor: pointer;
  text-align: left;
}
.nslm-storyboard-rail-all:hover { color: #fff; background: rgba(255, 255, 255, 0.05); }
.nslm-storyboard-rail-all:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: -2px; }
.nslm-storyboard-rail-tray { margin: 4px; width: auto; }
.nslm-storyboard-rail-kv { padding: 2px 11px 11px; grid-template-columns: minmax(56px, auto) 1fr; }

/* ---------------------------------------------------------------------
   The deliverables tray
--------------------------------------------------------------------- */
.nslm-storyboard-board { min-width: 0; }
.nslm-storyboard-tray-anchor { scroll-margin-top: var(--nslm-sb-sticky-top); }
.nslm-storyboard-tray {
  margin-bottom: 16px;
  background: var(--nsf-panel);
}
.nslm-storyboard-tray-counts {
  font: 10px var(--nsf-mono);
  color: rgba(var(--nsl-haze-rgb), 0.85);
  text-transform: none;
  letter-spacing: 0;
}
.nslm-storyboard-tray-why {
  margin: 0;
  padding: 9px 12px 4px;
  font-family: var(--nsf-sans);
  font-size: 11.5px;
  line-height: 1.55;
  color: rgba(var(--nsl-haze-rgb), 0.9);
  max-width: 96ch;
}
/* Outside the fixed-pitch board, so the strip states its own height
   rather than inheriting one from a row that is not there. */
.nslm-storyboard-tray .nslm-storyboard-strip {
  flex: none;
  height: calc(var(--nslm-sb-tile-h) + 18px);
  padding: 0 12px 8px;
}

/* ---------------------------------------------------------------------
   Sequence rows
--------------------------------------------------------------------- */
.nslm-storyboard-list { position: relative; }
/* Height comes from the .jsx — see the header. The gap between rows is
   padding rather than a margin so that the pitch windowSlice() assumes
   and the box the browser lays out are the same number. */
.nslm-storyboard-row { padding-bottom: 16px; }
.nslm-storyboard-seq {
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 9px 12px 10px;
  border: 1px solid var(--nsf-glass-border);
  border-radius: 10px;
  background: var(--nsf-panel-2);
  scroll-margin-top: var(--nslm-sb-sticky-top);
  /* Layout and paint island: a thumbnail landing inside one sequence
     cannot re-lay-out the thirty below it. Never `contain: size` — the
     row's height is declared, so the engine measures it, and a guessed
     height is what turns a scroll into a jitter. */
  contain: layout paint style;
}
.nslm-storyboard-seq.active { border-color: rgba(255, 255, 255, 0.3); }

.nslm-storyboard-seq-head {
  flex: none;
  height: 28px;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  overflow: hidden;
}
/* The label and the stat line SHRINK; the chips and the reorder buttons
   do not. A header where every child was flex:none pushed the [↑][↓]
   past the clip on any sequence with a long cluster name — and a
   control you cannot reach is worse than a label you cannot finish. */
.nslm-storyboard-seq-name {
  font: 600 12px var(--nsf-mono);
  color: var(--nsf-bone);
  letter-spacing: 0.02em;
  max-width: 40ch;
  min-width: 6ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 0 1 auto;
}
.nslm-storyboard-seq-stat {
  font: 10px var(--nsf-mono);
  color: rgba(var(--nsl-haze-rgb), 0.78);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 0 1 auto;
}
.nslm-storyboard-seq-head .nsl-flag { flex: none; line-height: 1.5; }
.nslm-storyboard-move {
  flex: none;
  min-width: 24px;
  text-align: center;
  font-size: 11px;
  padding: 2px 6px;
}
.nslm-storyboard-move:disabled { opacity: 0.3; cursor: default; }
.nslm-storyboard-move:disabled:hover { color: rgba(232, 228, 218, 0.8); background: none; }
.nslm-storyboard-seq-head .nsa-act-btn:focus-visible,
.nslm-storyboard-more:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 1px; }

/* ---------------------------------------------------------------------
   The filmstrip.

   overflow-y: hidden is NOT tidiness — see the file header.
--------------------------------------------------------------------- */
.nslm-storyboard-strip {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}
.nslm-storyboard-strip::-webkit-scrollbar { height: 8px; }
.nslm-storyboard-strip::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.14);
  border-radius: 999px;
}
.nslm-storyboard-strip::-webkit-scrollbar-track { background: transparent; }

/* ---------------------------------------------------------------------
   Tiles. The base .nsl-card look and its corner controls come from the
   Library's own stylesheet — a tile here and a card in the grid are the
   same object from a different angle, and should not have to be learned
   twice. What is set here is the geometry the strip needs.
--------------------------------------------------------------------- */
.nslm-storyboard-tile {
  flex: none;
  width: var(--nslm-sb-tile-w);
  height: var(--nslm-sb-tile-h);
  display: flex;
  flex-direction: column;
  background: rgba(255, 255, 255, 0.02);
}
.nslm-storyboard-tile-hit {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
/* Two hits per tile: the picture (fixed thumb height, previews) and
   the caption (takes the rest, inspects). */
.nslm-storyboard-tile-pic { flex: none; }
.nslm-storyboard-tile-pic.nsl-previewable { cursor: zoom-in; }
.nslm-storyboard-tile-thumb {
  width: 100%;
  height: var(--nslm-sb-thumb-h);
}
.nslm-storyboard-tile-meta {
  flex: 1 1 auto;
  min-height: 0;
  display: block;
  padding: 4px 7px 0;
  overflow: hidden;
}
.nslm-storyboard-tile-top {
  display: flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
}
.nslm-storyboard-tile-seq {
  font: 10px var(--nsf-mono);
  color: rgba(var(--nsl-haze-rgb), 0.85);
  flex: none;
}
.nslm-storyboard-tile-name {
  display: block;
  margin-top: 2px;
  font: 10px var(--nsf-mono);
  color: var(--nsf-bone);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nslm-storyboard-tile-flags {
  flex: none;
  height: 20px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 7px 5px;
  overflow: hidden;
}
.nslm-storyboard-tile-flags > * { flex: none; white-space: nowrap; }

/* The cap's own tile. Dashed, so it reads as "there is more here" and
   not as another artifact. */
.nslm-storyboard-more {
  flex: none;
  width: calc(var(--nslm-sb-tile-w) * 0.55);
  height: var(--nslm-sb-tile-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  border: 1px dashed var(--nsf-glass-border);
  border-radius: 8px;
  background: transparent;
  color: var(--nsf-haze);
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease;
}
.nslm-storyboard-more:hover { color: #fff; border-color: rgba(255, 255, 255, 0.3); }
.nslm-storyboard-more-n { font: 600 15px var(--nsf-mono); }
.nslm-storyboard-more-t {
  font: 9px var(--nsf-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ---------------------------------------------------------------------
   The "this axis has nothing to divide" hint.
--------------------------------------------------------------------- */
.nslm-storyboard-hint {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 12px;
  padding: 9px 12px;
  border: 1px solid rgba(224, 180, 80, 0.35);
  border-radius: 8px;
  background: rgba(224, 180, 80, 0.06);
  font-family: var(--nsf-sans);
  font-size: 12px;
  line-height: 1.5;
  color: var(--nsf-bone);
}
.nslm-storyboard-hint .nsa-act-btn { flex: none; }
.nslm-storyboard-hint .nsa-act-btn:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 1px; }

/* ---------------------------------------------------------------------
   Narrow: the rail stops being a column and becomes a band above the
   board. It keeps its sticky top — a jump target you cannot reach
   without scrolling back up is not navigation.
--------------------------------------------------------------------- */
@media (max-width: 1180px) {
  .nslm-storyboard-body { grid-template-columns: minmax(0, 1fr); }
  .nslm-storyboard-rail-sticky {
    position: static;
    flex-direction: row;
    align-items: flex-start;
    gap: 12px;
    flex-wrap: wrap;
  }
  .nslm-storyboard-rail-pane { flex: 1 1 280px; min-width: 0; }
  .nslm-storyboard-rail-list { max-height: 200px; }
}

/* ---------------------------------------------------------------------
   Focus.

   The Library's own corner controls reveal themselves on focus but do
   not RING — which is enough in a grid where the card underneath is
   already outlined, and not enough here, where a tile is 160px wide and
   the corner buttons sit on top of a picture. Every control this mode
   puts on the page gets a visible focus ring, including the ones it
   borrowed.
--------------------------------------------------------------------- */
.nslm-storyboard .nsl-select-btn:focus-visible,
.nslm-storyboard .nsl-inspect-btn:focus-visible,
.nslm-storyboard .nsl-keep-btn:focus-visible,
.nslm-storyboard .nsl-modebar .nsa-act-btn:focus-visible {
  outline: 2px solid var(--nsf-haze);
  outline-offset: 1px;
}
