/* =====================================================================
   Night Library — TIMELINE.

   A left time gutter, a vertical rule, and a column of batch cards: the
   night in the batches it produced, read top to bottom on the PAGE's own
   scroller. This is the one worked mode that is not framed, so nothing
   here sets a height, and the only inner scroller in the file is the
   sideways strip of attempt cards — which has to own that overflow
   because the app shell clips overflow-x above it.

   The two rules from the Library's rendering pass hold here as well, and
   they are not stylistic:

     · NO backdrop-filter. Under these cards are live iframes and
       decoding video stills; a blurred surface re-rasterises all of it
       every frame the page scrolls.

     · `contain: layout paint style` on the card-like leaves, and never
       `contain: size` or `content-visibility`. A batch card's height
       comes from its content, so the page's own scroll anchoring has a
       real number to measure instead of a guess.
   ===================================================================== */

.nslm-timeline {
  display: block;
  min-width: 0;
}

/* The gutter width is a token so the rule, the dot and the cards cannot
   drift apart when one of them is edited. */
.nslm-timeline {
  --nslm-timeline-gutter: 92px;
  --nslm-timeline-rulecol: 26px;
  --nslm-timeline-dot-y: 17px;
}

/* The plain statement a timeline has to make when there is no clock to
   lay anything out on. It is a sentence, not a chip: the reader needs to
   know the ORDER below is attempt order, not time order. */
.nslm-timeline-note {
  margin: 0 0 14px;
  padding: 10px 13px;
  border: 1px solid var(--nsf-glass-border);
  border-left: 2px solid var(--nsf-split);
  border-radius: 6px;
  background: var(--nsf-panel-2);
  font: 11px/1.65 var(--nsf-mono);
  color: rgba(232, 228, 218, 0.82);
}

/* ---------------------------------------------------------------------
   Modebar bits. The order pair is a two-button radiogroup rather than a
   select: it is one click either way and it never covers the row the
   reader is comparing against.
--------------------------------------------------------------------- */
.nslm-timeline-order { display: flex; gap: 2px; }
.nslm-timeline-order .nsf-filter-btn {
  font: 9px var(--nsf-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 4px 9px;
  border-radius: 3px;
}
.nslm-timeline-order .nsf-filter-btn:focus-visible,
.nslm-timeline .nsa-act-btn:focus-visible {
  outline: 2px solid var(--nsf-haze);
  outline-offset: 1px;
}

/* ---------------------------------------------------------------------
   The rows.
--------------------------------------------------------------------- */
.nslm-timeline-list { display: block; }

.nslm-timeline-row {
  display: grid;
  grid-template-columns: var(--nslm-timeline-gutter) var(--nslm-timeline-rulecol) minmax(0, 1fr);
  align-items: start;
}

.nslm-timeline-gutter {
  text-align: right;
  padding: 10px 10px 0 0;
  min-width: 0;
}
.nslm-timeline-clock {
  font: 600 13px var(--nsf-mono);
  color: var(--nsf-bone);
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.nslm-timeline-day {
  font: 9.5px var(--nsf-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--nsf-haze);
  margin-top: 2px;
  white-space: nowrap;
}
.nslm-timeline-ago {
  font: 9.5px var(--nsf-mono);
  color: rgba(var(--nsl-haze-rgb), 0.6);
  margin-top: 3px;
  white-space: nowrap;
}
/* An untimed batch says so. It never borrows a neighbour's clock and it
   never prints the epoch. */
.nslm-timeline-untimed {
  font: 10px/1.4 var(--nsf-mono);
  cursor: help;
}

/* The rule column: one continuous hairline down the night, a node at
   each batch, and a short elbow into the card. Decorative — the row is
   readable without it, so it is aria-hidden in the markup. */
/* The gap between two rows belongs to the CARD, as a margin, not to the
   row as padding. A grid item stretched to the track (the rule) reaches
   the bottom of the TRACK, and the track includes the card margin — so
   the hairline runs the whole way down and meets the next row’s rule.
   As row padding the gap sat outside the stretched item and broke the
   line into dashes, once per batch, all the way down the night. */
.nslm-timeline-rule { position: relative; align-self: stretch; min-height: 46px; }
.nslm-timeline-rule::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  margin-left: -0.5px;
  background: var(--nsf-glass-border);
}
.nslm-timeline-rule::after {
  content: '';
  position: absolute;
  left: 50%;
  right: 0;
  top: var(--nslm-timeline-dot-y);
  height: 1px;
  background: var(--nsf-glass-border);
}
/* the line starts at the first node and stops just past the last */
.nslm-timeline-row:first-child .nslm-timeline-rule::before { top: var(--nslm-timeline-dot-y); }
.nslm-timeline-row:last-child .nslm-timeline-rule::before {
  bottom: auto;
  height: 34px;
}
.nslm-timeline-row:first-child:last-child .nslm-timeline-rule::before { height: 34px; }
.nslm-timeline-dot {
  position: absolute;
  left: 50%;
  top: var(--nslm-timeline-dot-y);
  width: 9px;
  height: 9px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  background: var(--nsf-panel-2);
  border: 1px solid var(--nsf-haze);
}
.nslm-timeline-row.open .nslm-timeline-dot {
  background: var(--nsf-bone);
  border-color: var(--nsf-bone);
}

/* ---------------------------------------------------------------------
   The batch card.
--------------------------------------------------------------------- */
.nslm-timeline-card {
  border: 1px solid var(--nsf-glass-border);
  border-radius: 10px;
  background: var(--nsf-panel-2);
  min-width: 0;
  margin-bottom: 14px;
  /* its own layout and paint island: a thumbnail landing inside one
     batch cannot re-lay-out the batches below it */
  contain: layout paint style;
}
.nslm-timeline-row.open .nslm-timeline-card { border-color: rgba(255, 255, 255, 0.2); }

.nslm-timeline-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  padding: 10px 11px 0;
  font: 9px var(--nsf-mono);
}
.nslm-timeline-no {
  font: 600 11.5px var(--nsf-mono);
  letter-spacing: 0.06em;
  color: var(--nsf-bone);
  white-space: nowrap;
}
.nslm-timeline-headspacer { flex: 1 1 auto; }

/* Chips are inline by default; a line-height gives them the same box as
   the .nsl-flag chips everywhere else in the Library. */
.nslm-timeline .nsl-flag {
  display: inline-block;
  line-height: 15px;
  white-space: nowrap;
}
.nslm-timeline-chip-live { color: var(--nsf-spread); border-color: rgba(181, 126, 220, 0.45); }
.nslm-timeline-chip-good { color: var(--nsf-supported); border-color: rgba(var(--nsl-ok-rgb), 0.42); }
.nslm-timeline-chip-bad { color: var(--nsf-contradicted); border-color: rgba(212, 87, 107, 0.42); }

.nslm-timeline-toggle {
  flex: none;
  border: 1px solid var(--nsf-glass-border);
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.03);
  color: var(--nsf-haze);
  font: 11px/1 var(--nsf-mono);
  padding: 4px 9px;
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease;
}
.nslm-timeline-toggle:hover { color: #fff; border-color: rgba(255, 255, 255, 0.3); }
.nslm-timeline-toggle:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 1px; }

.nslm-timeline-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  padding: 7px 11px 10px;
  font: 10px var(--nsf-mono);
  color: var(--nsf-haze);
}
.nslm-timeline-fact { white-space: nowrap; cursor: help; }
.nslm-timeline-fact b { color: var(--nsf-bone); font-weight: 600; }

/* ---------------------------------------------------------------------
   Collapsed: a thin strip of thumbnails. This is what keeps a long night
   cheap — the tiles still go through the shared visibility hook, so an
   off-screen collapsed batch paints nothing at all.
--------------------------------------------------------------------- */
.nslm-timeline-strip {
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 0 11px 11px;
  overflow-x: auto;
  overflow-y: hidden;
  /* a flick past the end of a horizontal strip must not be handed to the
     browser as a back-navigation gesture */
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}
.nslm-timeline-strip::-webkit-scrollbar { height: 7px; }
.nslm-timeline-strip::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.14); border-radius: 999px; }
.nslm-timeline-strip::-webkit-scrollbar-track { background: transparent; }

.nslm-timeline-striphit {
  position: relative;
  flex: none;
  border: 0;
  padding: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  border-radius: 5px;
  line-height: 0;
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.nslm-timeline-striphit:hover { transform: translateY(-1px); }
.nslm-timeline-striphit:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 2px; }

/* The strip tile also wears .nsl-card, and not for the look — that is
   the class the host's scroll anchoring searches for, and a collapsed
   batch has to contribute one or a reader scrolled past the single
   expanded batch is anchored to nothing (the note in the .jsx has the
   whole story). What it must NOT inherit is the card's chrome: a
   border and a panel fill would draw a second box around a 76px
   thumbnail and grow the strip by 2px a tile. Written as a descendant
   rather than as more declarations on .nslm-timeline-striphit so it
   outranks the bare .nsl-card rules whatever order the sheets load in.
   `contain: layout paint style` is inherited on purpose and left
   alone: it is the containment rule every card-like leaf here obeys. */
.nslm-timeline-strip .nsl-card {
  border: 0;
  background: none;
  border-radius: 5px;
}
.nslm-timeline-strip .nsl-card:hover { border-color: transparent; }
.nslm-timeline-stripseq {
  position: absolute;
  left: 3px;
  bottom: 3px;
  padding: 0 4px;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.62);
  color: rgba(232, 228, 218, 0.9);
  font: 8.5px/13px var(--nsf-mono);
  pointer-events: none;
}
.nslm-timeline-stripmore {
  flex: none;
  font: 9.5px var(--nsf-mono);
  color: rgba(var(--nsl-haze-rgb), 0.7);
  border: 1px dashed var(--nsf-glass-border);
  border-radius: 4px;
  padding: 3px 7px;
  cursor: help;
}

/* Tile sizes. .nsl-tile-thumb (shared) already supplies position,
   overflow, background and containment; only the box is ours. */
.nslm-timeline-tile-xs { width: 76px; height: 48px; }
.nslm-timeline-tile-md { width: 100%; aspect-ratio: 16 / 10; }

/* ---------------------------------------------------------------------
   Expanded: a sideways row of attempt cards.
--------------------------------------------------------------------- */
.nslm-timeline-attempts {
  display: flex;
  align-items: stretch;
  gap: 10px;
  padding: 1px 11px 12px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
}
.nslm-timeline-attempts::-webkit-scrollbar { height: 8px; }
.nslm-timeline-attempts::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.14); border-radius: 999px; }
.nslm-timeline-attempts::-webkit-scrollbar-track { background: transparent; }

/* The card wears .nsl-card as well, which is where its border, radius,
   background and `contain: layout paint style` come from — and, more to
   the point, what makes the host's scroll anchoring able to find it. */
.nslm-timeline-att {
  flex: none;
  width: 238px;
  display: flex;
  flex-direction: column;
}
/* The tail of a capped expanded row. It stands where the next card
   would, at the card's own height, so the row still reads as a row and
   the reader's eye finds the ask where it expects more. */
.nslm-timeline-attmore {
  flex: none;
  align-self: stretch;
  width: 92px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border: 1px dashed var(--nsf-glass-border);
  border-radius: 8px;
  background: none;
  color: rgba(var(--nsl-haze-rgb), 0.78);
  font: 9.5px/1.4 var(--nsf-mono);
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease;
}
.nslm-timeline-attmore b { font: 600 15px var(--nsf-mono); color: var(--nsf-bone); }
.nslm-timeline-attmore:hover { color: #fff; border-color: rgba(255, 255, 255, 0.3); }
.nslm-timeline-attmore:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 1px; }

.nslm-timeline-att-top {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px 0;
  font: 10px var(--nsf-mono);
}
.nslm-timeline-att-seq {
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--nsf-bone);
  white-space: nowrap;
}
.nslm-timeline-att-clock {
  margin-left: auto;
  color: var(--nsf-haze);
  white-space: nowrap;
}
.nslm-timeline-att-sel {
  flex: none;
  border: 1px solid var(--nsf-glass-border);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.3);
  color: rgba(232, 228, 218, 0.8);
  font: 10px/1 var(--nsf-mono);
  padding: 3px 4px;
  cursor: pointer;
}
.nslm-timeline-att-sel:hover { color: var(--nsf-amber); border-color: rgba(var(--nsl-amber-rgb), 0.5); }
.nslm-timeline-att-sel.on { color: var(--nsf-amber); border-color: rgba(var(--nsl-amber-rgb), 0.6); }
.nslm-timeline-att-sel:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 1px; }

.nslm-timeline-att-hit {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.nslm-timeline-att-hit:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: -2px; }
.nslm-timeline-att-name {
  display: block;
  padding: 6px 10px 0;
  font: 11px var(--nsf-mono);
  color: var(--nsf-bone);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nslm-timeline-att-nohero {
  padding: 10px;
  font: 10px/1.5 var(--nsf-mono);
}

.nslm-timeline-att-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 7px 10px 0;
}
/* The record's own words. Red because it IS the failure line, clamped
   because a stack trace must not turn one card into a column. */
.nslm-timeline-att-problem {
  padding: 7px 10px 0;
  font: 9.5px/1.45 var(--nsf-mono);
  color: var(--nsf-contradicted);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}
.nslm-timeline-att-metrics { padding: 8px 10px 0; }
.nslm-timeline-att-metrics .nsl-metric { min-width: 60px; padding: 4px 7px; }
.nslm-timeline-att-kv {
  padding: 8px 10px 0;
  font-size: 10px;
  grid-template-columns: minmax(48px, auto) 1fr;
}
.nslm-timeline-att-kv.nsl-none { font: 10px var(--nsf-mono); }
.nslm-timeline-att-note {
  padding: 8px 10px 0;
  font: 10.5px/1.5 var(--nsf-sans);
  color: rgba(232, 228, 218, 0.72);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* margin-top:auto pins the verbs to the bottom edge whatever the card
   above them happens to know — a row of cards with the buttons at
   different heights is a row you cannot run your eye along. */
.nslm-timeline-att-acts {
  margin-top: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px;
  padding: 10px;
  font: 9px var(--nsf-mono);
}
.nslm-timeline-att-acts button { cursor: pointer; background: none; }
.nslm-timeline-att-acts button:focus-visible { outline: 2px solid var(--nsf-haze); outline-offset: 1px; }
.nslm-timeline-att-files {
  margin-left: auto;
  color: rgba(var(--nsl-haze-rgb), 0.72);
  white-space: nowrap;
  cursor: help;
}
.nslm-timeline-flag-ok { color: var(--nsf-supported); border-color: rgba(var(--nsl-ok-rgb), 0.4); }
.nslm-timeline-flag-bad { color: var(--nsf-contradicted); border-color: rgba(212, 87, 107, 0.4); }
.nslm-timeline-flag-keep { color: var(--nsf-bone); font: inherit; }
.nslm-timeline-flag-keep:hover { color: var(--nsf-amber); border-color: rgba(var(--nsl-amber-rgb), 0.5); }
.nslm-timeline-flag-jump { color: var(--nsf-haze); font: inherit; }
.nslm-timeline-flag-jump:hover { color: #fff; border-color: rgba(255, 255, 255, 0.32); }

/* ---------------------------------------------------------------------
   The pager. See the comment beside it in the .jsx for why this mode
   pages instead of windowing.
--------------------------------------------------------------------- */
.nslm-timeline-more {
  display: flex;
  justify-content: center;
  padding: 6px 0 18px;
}
.nslm-timeline-more .nsa-act-btn { padding: 6px 16px; }

/* ---------------------------------------------------------------------
   Narrow: the gutter stops being a column and becomes the card's first
   line. The rule goes with it — a 1px hairline beside a full-width card
   is decoration that costs a column the content needs.
--------------------------------------------------------------------- */
@media (max-width: 760px) {
  .nslm-timeline-row { grid-template-columns: minmax(0, 1fr); }
  .nslm-timeline-card { margin-bottom: 12px; }
  .nslm-timeline-rule { display: none; }
  .nslm-timeline-gutter {
    display: flex;
    align-items: baseline;
    gap: 8px;
    text-align: left;
    padding: 0 2px 6px;
  }
  .nslm-timeline-clock { font-size: 12px; }
  .nslm-timeline-att { width: 210px; }
}
