/* ==========================================================================
   NITRATE — THE RACKS.  Stylesheet for shelves.js.

   THE ONE JOB
   This is the only surface on the site where the picture is the point.  Every
   other view is an instrument and reads as paperwork on purpose; here the
   posters are 158px wide — the largest object on any NITRATE page — and the
   figures are demoted to one hairline-ruled line above each rail.  If this
   page reads like a report, it has failed.

   The film-lab grammar is unchanged and none of it is invented here: colours
   are tokens.css and only tokens.css, rules are hairlines, there is no
   border-radius anywhere, and safety orange appears exactly twice — the block
   beside a shelf's name (the label you are sorted by) and the tick on a show
   you have already played (the minority fact, and the actionable one).

   The host owns the gutter (--pad-x) and the vertical rhythm, the same
   contract the field and the anime block use, so this drops into the landing
   section without fighting it for margin.
   ========================================================================== */

.shf {
  padding: 0 var(--pad-x, 0px);
  width: 100%;
  /* One knob. The rails, the open-shelf grid and the phone breakpoints all
     read the poster width from here, so they can never disagree. */
  --shf-w: 158px;
  --shf-gap: 14px;
}

/* ===================================================================== head
   A page that files 268 shows into 13 shelves is making a claim, and the
   reader is owed the method — but the method must not BE the page. John's
   whole note was that the series page had become paperwork, so the header is
   held to roughly a fifth of the first screen: title and lede on one line
   with the ledger, the order as chips, the method as five clauses, and the
   argument for it behind a disclosure. The rule's CONSEQUENCES stay in the
   open, on every rack header and every shelf's carry/filed figure. */
.shf-head {
  border-top: var(--hair) solid var(--rule);
  padding: 14px 0 12px;
}
.shf-htop {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 26px;
}

.shf-title {
  font-family: var(--font-marquee);
  font-weight: 800;
  font-size: clamp(34px, 4.4vw, 54px);
  line-height: .9;
  letter-spacing: -.01em;
  text-transform: uppercase;
  flex: 0 0 auto;
}
.shf-lede {
  margin: 0;
  flex: 1 1 30ch;
  max-width: 74ch;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-2);
}
.shf-lede b { color: var(--ink); font-weight: 700; }

/* the method, in the order it is applied — only when asked for */
.shf-more { margin: 9px 0 0; }
.shf-sum {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--muted);
  list-style: none;
}
.shf-sum::-webkit-details-marker { display: none; }
.shf-sum::before { content: "+"; color: var(--accent); font-size: 13px; }
.shf-more[open] .shf-sum::before { content: "\2212"; }
.shf-sum:hover { color: var(--ink); }
.shf-sum:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Opened, this was five long steps at 96ch under a full-width header — 343px
   of list with 621px of nothing beside it, the void John pointed at on NEW
   PRINTS, just folded away by default.  On the house caption grid
   (tokens.css --cap-col) it fills the row it opens into.
   ⚠️ The 20px indent moves from the <ol> to the <li>: a container padding
   only indents the FIRST column, so the numbers in columns two and three
   would hang out into the gutter.  Each step carries its own indent instead,
   and each step stays whole — five items balance across three columns without
   `break-inside: avoid` stranding one, and a numbered step broken in half by
   a column boundary reads as two steps.

   🔴 AND THE INDENT ALONE IS NOT ENOUGH — measured 2026-08-12, steps 1 and 2
   had no numbers at all.  A `list-style-position: outside` marker is laid
   OUTSIDE the item's border box, so moving padding onto the <li> does not
   bring it inside: in column one the marker fell at x=-20 and was clipped away
   by the multicol box, and in columns two and three it printed in the gutter,
   detached from the step it numbers.  The marker has to come INSIDE the item
   and the hanging indent be rebuilt from the text: `inside` puts it in the
   first line box, and a negative text-indent of exactly the padding pulls that
   first line back to the item edge, so the number sits at 0 and every wrapped
   line lands on 20.  Same picture as before, now in every column. */
.shf-rule {
  margin: 9px 0 2px;
  padding: 0;
  columns: var(--cap-col);
  column-gap: var(--cap-gap);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}
.shf-rule li {
  margin: 0 0 6px;
  list-style-position: inside;
  padding-left: 20px;
  text-indent: -20px;
  break-inside: avoid;
}
.shf-rule li::marker { color: var(--accent); font-family: var(--font-mono); }

/* --- the five clauses, always visible ---------------------------------- */
.shf-clauses {
  margin: 9px 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 3px 0;
  font-size: 11px;
  color: var(--muted);
}
.shf-cl {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 0 11px;
  border-left: var(--hair) solid var(--rule);
  letter-spacing: .04em;
}
.shf-cl:first-child { padding-left: 0; border-left: 0; }
.shf-cln { color: var(--accent); }

/* --- THE SHELVES: index, jump control, and the count/hours comparison ----
   A rail's length encodes a title count and nothing else. Here the two
   figures sit together, so a short shelf that is a long commitment (live
   Romance: 9 boxes, 379 h) is visible next to a long one that is not. This
   is the only place on the page where all 13 shelves can be compared, which
   is why the count-versus-hours point belongs here and not on a rail. */
.shf-index { margin: 11px 0 0; }
.shf-istrip {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 5px;
  align-items: center;
}
.shf-ix {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  border: var(--hair) solid var(--rule);
  background: var(--panel);
  padding: 2px 7px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.shf-ixn { color: var(--ink-2); text-transform: uppercase; letter-spacing: .04em; }
.shf-ixc { color: var(--ink); }
.shf-ixh { color: var(--muted); }
.shf-ix.is-residue .shf-ixn { color: var(--muted); }
.shf-ix:hover { border-color: var(--accent); }
.shf-ix:hover .shf-ixn { color: var(--accent); }

/* --- the printed order, inside the disclosure ---------------------------
   Chips, not a sentence: the reader is meant to scan along it and check the
   page against it. Each carries its catalogue-wide count so the claim
   "Action is on most of the library" is a figure, not an opinion. */
.shf-order { margin: 11px 0 0; }
.shf-oh {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-marquee);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: .06em;
  color: var(--muted);
  padding-right: 4px;
}
.shf-ostrip {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 5px;
  align-items: center;
}
.shf-ol {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: var(--hair) solid var(--rule);
  padding: 2px 6px;
  font-size: 11px;
  background: var(--panel);
}
.shf-oln { color: var(--ink-2); text-transform: uppercase; letter-spacing: .04em; }
.shf-olc { color: var(--muted); font-variant-numeric: tabular-nums; }

/* the sum that makes the whole claim checkable at a glance */
.shf-ledger {
  margin: 0;
  padding: 6px 10px;
  border: var(--hair) solid var(--rule);
  background: var(--panel);
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 4px;
  font-size: 12px;
  color: var(--muted);
  flex: 0 0 auto;
  margin-left: auto;
}
.shf-ledger b { color: var(--ink); font-size: 14px; }
.shf-ledger .sev-crit { color: var(--crit); }
.shf-sep { width: 9px; }

/* ===================================================================== rack
   Two racks, and the split is the first thing the rule does, so it gets the
   biggest type on the page after the title. */
.shf-rack { margin: 24px 0 0; }
.shf-rhead {
  border-top: 2px solid var(--ink);
  padding: 8px 0 9px;
}
.shf-rname {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 14px;
}
.shf-rtitle {
  font-family: var(--font-marquee);
  font-weight: 800;
  font-size: clamp(30px, 3.6vw, 46px);
  line-height: 1;
  text-transform: uppercase;
}
.shf-rfigs { font-size: 12px; color: var(--muted); }
.shf-rfigs b { color: var(--ink); font-size: 14px; }
/* What the rack is, what files nothing on it, and what dissolved off it — the
   accounting for the rule above, under a header rule that runs the full 1,304px
   while the reading stopped at 96ch: 686px of note with 632px of nothing beside
   it, on both racks.  The house caption grid (tokens.css --cap-col) takes the
   same measure as a column width, so the note fills the row it belongs to.
   ⚠️ ANIMATED balances 3 columns clean; LIVE ACTION carries less text and fills
   two of three at 1440, which is a shorter void, not a new one — the empty
   column is 411px where the old margin was 632px.  ⛔ No `break-inside: avoid`
   here: the note is one paragraph with an inline <span> of blocked labels in
   it, and pinning it would put the whole thing back in one column. */
.shf-rnote {
  margin: 7px 0 0;
  columns: var(--cap-col);
  column-gap: var(--cap-gap);
  orphans: 2;
  widows: 2;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}
.shf-rnote-1 { color: var(--ink-2); }
/* the measured percentages that disqualify a label on this rack */
.shf-blocked {
  font-size: 11px;
  color: var(--ink-2);
  border-bottom: var(--hair) solid var(--rule);
}
.shf-dis { display: block; margin-top: 3px; }

/* ==================================================================== shelf */
/* SAFARICSS_20260905 — a shelf off-screen skips layout and paint (see landing.css) */
.shf-shelf { margin: 22px 0 0; content-visibility: auto; contain-intrinsic-size: auto 1px 390px; }
.shf-shead {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  border-bottom: var(--hair) solid var(--rule);
  padding-bottom: 7px;
}
.shf-sname { min-width: 0; }

/* THE ONE ORANGE: the label you are sorted by, marked the way the house marks
   a sort key everywhere else. */
.shf-label {
  font-family: var(--font-marquee);
  font-weight: 700;
  font-size: clamp(22px, 2.5vw, 32px);
  line-height: 1.05;
  text-transform: uppercase;
  letter-spacing: -.005em;
  display: flex;
  align-items: center;
  gap: 9px;
}
.shf-label::before {
  content: "";
  width: 9px;
  height: 9px;
  flex: 0 0 9px;
  background: var(--accent);
}
.is-residue .shf-label::before { background: var(--rule); }
.is-residue .shf-label { color: var(--ink-2); }

.shf-figs {
  margin: 4px 0 0;
  font-size: 11.5px;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  gap: 0 12px;
}
.shf-figs b { color: var(--ink); font-size: 14px; }
.shf-n + .shf-u { margin-left: -9px; }
.shf-unseen { color: var(--ink-2); }
/* the overlap, on every shelf: how many carry the tag, how many were filed
   here. The gap between the two numbers IS the seven-tags-per-show problem,
   printed rather than hidden. */
.shf-carry {
  color: var(--ink-2);
  border-bottom: var(--hair) dotted var(--rule);
  cursor: help;
}
/* hours per box — the figure a rail cannot draw */
.shf-dens {
  color: var(--ink-2);
  border-bottom: var(--hair) dotted var(--rule);
  cursor: help;
}
.shf-dev { color: var(--muted); }

/* jumped to, from the index or from the genre lens: a moment's hairline so
   the eye lands on the right shelf. It fades on its own and leaves nothing. */
.shf-shelf.is-lit .shf-shead { box-shadow: inset 0 -2px 0 0 var(--accent); }
.shf-shelf.is-lit .shf-label::before { outline: 3px solid var(--accent); outline-offset: 2px; }

.shf-why {
  margin: 4px 0 0;
  max-width: 92ch;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--muted);
}

/* --- shelf controls ----------------------------------------------------- */
.shf-ctl {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  padding-bottom: 2px;
}
.shf-arrow {
  width: 30px;
  height: 30px;
  line-height: 1;
  font-size: 17px;
  color: var(--ink-2);
  background: var(--panel);
  display: flex;
  align-items: center;
  justify-content: center;
}
.shf-arrow:hover:not(:disabled) { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.shf-arrow:disabled { color: var(--rule); cursor: default; background: transparent; }
.shf-open {
  height: 30px;
  padding: 0 11px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .05em;
  color: var(--ink-2);
  background: var(--panel);
  white-space: nowrap;
}
.shf-open:hover { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* ===================================================================== rail
   A horizontal rail, which John likes and which is right here — but a rail
   that only ever scrolls is what he stopped liking elsewhere, so every rail
   has a name, four figures, and a control that pulls the whole shelf out into
   a grid. `position: relative` makes the rail the offsetParent for the single
   parked play/cast pair. */
.shf-rail {
  position: relative;
  display: flex;
  gap: var(--shf-gap);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  padding: 12px 0 14px;
  /* the scrollbar is the affordance on a trackpad; the arrows are for a mouse */
  scrollbar-width: thin;
}
.shf-rail:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* OPEN SHELF — the rail becomes the whole shelf, wrapped. */
.is-open .shf-rail {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--shf-w), 1fr));
  overflow: visible;
  scroll-snap-type: none;
}

/* ==================================================================== card */
.shf-cardw {
  position: relative;
  flex: 0 0 var(--shf-w);
  min-width: 0;
  scroll-snap-align: start;
}
.is-open .shf-cardw { flex: initial; }

.shf-card {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  text-align: left;
  color: inherit;
}
.shf-art {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 2 / 3;
  background: var(--panel-2);
  border: var(--hair) solid var(--rule);
  overflow: hidden;
}
.shf-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.shf-noart {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  padding: 8px;
  font-family: var(--font-marquee);
  font-size: 15px;
  line-height: 1.05;
  text-transform: uppercase;
  color: var(--ink);
  background: linear-gradient(to top, rgba(0,0,0,.55), transparent 60%);
}
/* the poster lifts on hover; a hairline, never a border — a border would
   resize the box and shift the whole rail */
.shf-card:hover .shf-art { outline: 2px solid var(--accent); outline-offset: -2px; }
.shf-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.shf-marks {
  position: absolute;
  left: 0;
  bottom: 0;
  display: flex;
  align-items: stretch;
  gap: 0;
}
/* THE SECOND ORANGE: you have played this one. On a shelf where 90% are
   unplayed, the minority mark is the one worth printing. */
.shf-tick {
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 9px;
  line-height: 1;
  padding: 4px 5px;
  display: flex;
  align-items: center;
}
.shf-fmt {
  background: var(--panel);
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: .06em;
  padding: 4px 5px;
  border-top: var(--hair) solid var(--rule);
  border-right: var(--hair) solid var(--rule);
}

.shf-cap { display: block; padding: 6px 1px 0; }
/* Two lines, always — a title that wraps must not push its own figures out of
   line with the card beside it. A rail whose mono line zig-zags reads as a
   broken table, which is the exact opposite of what this page is for. */
.shf-t {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: calc(2 * 1.25em);
  font-size: 12.5px;
  line-height: 1.25;
  color: var(--ink);
}
.shf-m {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  color: var(--muted);
}
.shf-air {
  display: inline-block;
  margin-top: 3px;
  font-size: 9.5px;
  letter-spacing: .08em;
  color: var(--ink-2);
  border: var(--hair) solid var(--rule);
  padding: 0 4px;
}

/* --- the parked play/cast pair -----------------------------------------
   One pair for the page, moved onto whatever card the pointer is over. It
   rides in the rail, not in the card, because the card is a <button> and an
   <a> cannot live inside one. */
.shf-rail > .nact.shf-act {
  position: absolute;
  z-index: 3;
  gap: 4px;
  background: var(--panel);
  border: var(--hair) solid var(--rule);
}
.shf-act .plexlink:hover, .shf-act .plexlink:focus-visible,
.shf-act .nstream-btn:hover, .shf-act .nstream-btn:focus-visible {
  background: var(--accent);
}

/* ================================================================== phones
   Desktop is the priority — this page is a wall — but it must not break. The
   poster shrinks, the figures wrap, the controls grow to a thumb. */
@media (max-width: 900px) {
  .shf { --shf-w: 132px; --shf-gap: 10px; }
  .shf-shead { flex-wrap: wrap; align-items: flex-start; }
  .shf-ctl { order: 2; }
}
/* ==================================================================== 760
   THE MOBILE TIER.  2026-08-11: this was three separate queries — 700 for the
   swipeable strips, 560 for the smaller poster, and a lone 760 at the foot of
   the file for the rack qualifier — invented at three different times for the
   same device.  MOBILE_SPEC §1 folds 460–720 into 760, so they are one block
   now and there is one number to change.  Nothing above 760 moved: the 900
   block above is untouched.

   On a phone the printed order wrapped to six rows and pushed every poster
   below the fold — which is the exact fault this page was built to fix. It
   stays complete and stays visible, but as one swipeable row. */
@media (max-width: 760px) {
  .shf-ostrip {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 3px;
  }
  .shf-ostrip::-webkit-scrollbar { display: none; }
  .shf-istrip {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 3px;
  }
  .shf-istrip::-webkit-scrollbar { display: none; }
  .shf-ol, .shf-oh, .shf-ix { flex: 0 0 auto; }
  .shf-cl { padding: 0 8px; }

  /* was the 560 tier */
  .shf { --shf-w: 118px; }
  /* one column at the house mobile tier, and the step indent follows the <li>
     it moved to when the list joined the caption grid (tokens.css).  ⚠️ The
     text-indent has to move with the padding or the number stops lining up
     with the text it numbers — the two are one measure, not two. */
  .shf-rule { columns: 1; }
  .shf-rule li { padding-left: 17px; text-indent: -17px; }
  .shf-rnote { columns: 1; }
  .shf-figs { gap: 0 9px; }
  .shf-t { font-size: 12.5px; }
  .shf-m { font-size: 11px; }
  .shf-head { padding-top: 10px; }

  /* the rack qualifier on an index chip: the chip is already carrying a name,
     a count and an hours figure into a 44px box on a 390px screen */
  .shf-ixr { display: none; }
}

/* TOUCH — no hover, so nothing may hide behind one.
   The parked pair is only ever built by a mouseover, so a finger never meets
   it; the sheet is where a phone acts, exactly as on the wall and the landing
   strips. What a finger DOES meet here — the arrows and OPEN SHELF — grows to
   a real target. */
@media (hover: none) {
  .shf-rail > .nact.shf-act { display: none; }
  .shf-arrow { width: 44px; height: 44px; font-size: 20px; }
  .shf-open { height: 44px; padding: 0 14px; }
  /* 🔴 THE SHELF INDEX WAS 22px HIGH.  It is the ONE control on this page that
     reaches all thirteen shelves, and on a phone it sits in a strip that now
     scrolls sideways — so a near miss drags the strip instead of opening the
     shelf, and nothing on screen tells you which of the two happened.  44 is
     the floor (spec §4.2); the chip keeps its type and its hairline, the BOX
     grows (§10.5).  The disclosure that opens the method was 19px.
     ⚠️ TOUCH, not the 760 tier: a phone in landscape is 844px wide and above
     the mobile tier entirely (§10.3), and the finger is still a finger.
     .shf-ol is a label, not a control, and is deliberately left alone. */
  .shf-ix { min-height: var(--tap, 44px); align-items: center; padding: 2px 10px; }
  .shf-sum { min-height: var(--tap, 44px); align-items: center; }
  .shf-card:hover .shf-art { outline: none; }
}

/* Reduced motion: tokens.css already forces scroll-behavior to auto, so the
   arrows jump instead of gliding and nothing else here animates at all. */

/* The rack qualifier. Six of the thirteen shelf names exist in both racks, so a
   heading or an index row that gives only the name is ambiguous — it reads as
   the live-action one every time. Quiet enough to stay a qualifier rather than
   competing with the shelf's own name. */
.shf-rackof {
  margin-left: .6em;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
  vertical-align: middle;
  white-space: nowrap;
}
.shf-ixr {
  margin-left: .45em;
  font-size: 9.5px;
  letter-spacing: .1em;
  color: var(--muted);
  opacity: .85;
}
/* ⛔ Its `display: none` on a phone lives in the 760 tier above, with the rest
   of the mobile rules — do not re-open a second query for it down here. */
