/* ==========================================================================
   NITRATE — THE BILL.  Stylesheet for programme.js.

   THE ONE JOB
   The film catalogue counted in THINGS, not in files.  The picture is still
   the point — posters are the largest object here and the figures are demoted
   to one hairline-ruled line above each rail — but the unit on this page is a
   PROPERTY, not a file, so the one visual invention is the STACK: a card with
   the edges of the other prints showing behind it, which opens in place.

   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 three times —
   the THINGS count beside a shelf's name (the figure the page is ordered by),
   the fill of the distinctness bar (the same figure, drawn), and the tick on
   a film you have played (the minority fact in a library that is 96% unseen).

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

.prg {
  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. */
  --prg-w: 152px;
  --prg-gap: 14px;
}

/* ===================================================================== head
   A page that bills 2,509 films onto 20 complete shelves is making a claim,
   and the reader is owed the method — but the method must not BE the page.
   Title, lede and ledger on one line; the shelves as an index; the method as
   five clauses and the badges as a strip; the argument behind a disclosure.
   The rule's CONSEQUENCES stay in the open, on every shelf header. */
.prg-head {
  border-top: var(--hair) solid var(--rule);
  padding: 14px 0 12px;
}
.prg-htop {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 26px;
}
.prg-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;
}
.prg-lede {
  margin: 0;
  flex: 1 1 30ch;
  max-width: 76ch;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-2);
}
.prg-lede b { color: var(--ink); font-weight: 700; }

/* the sum that makes the whole claim checkable at a glance */
.prg-ledger {
  margin: 0 0 0 auto;
  padding: 6px 10px;
  border: var(--hair) solid var(--rule);
  background: var(--panel);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 4px;
  font-size: 12px;
  color: var(--muted);
  /* 0 1 auto, never 0 0 auto: at 360px this line is 543px of mono and a
     non-shrinking flex item would drag the whole document sideways. */
  flex: 0 1 auto;
  max-width: 100%;
  min-width: 0;
}
.prg-ledger b { color: var(--ink); font-size: 14px; }
.prg-resid-n { color: var(--ink-2); }
.prg-sep { width: 9px; }

/* --- THE SHELVES: index, jump control, and the films-vs-things comparison --
   A rail encodes a count and nothing else, and only one rail is ever on
   screen.  This strip is the single place all 21 shelves can be compared, so
   it carries both figures: ADVENTURE 1,150 / 816 sits beside DRAMA 900 / 830
   and the swap that orders this page is visible without reading a word. */
.prg-index { margin: 11px 0 0; }
.prg-istrip {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 5px;
  align-items: center;
}
.prg-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);
}
.prg-ixn { color: var(--ink-2); text-transform: uppercase; letter-spacing: .04em; }
.prg-ixc { color: var(--ink); }
.prg-ixp { color: var(--accent); }
.prg-ix.is-residue .prg-ixn { color: var(--muted); }
.prg-ix:hover { border-color: var(--accent); }
.prg-ix:hover .prg-ixn { color: var(--accent); }

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

/* --- badges, not shelves: a real part of the scheme, so it stays visible - */
.prg-bstrip {
  margin: 9px 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 5px;
  align-items: center;
}
.prg-bl {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  border: var(--hair) dashed var(--rule);
  padding: 2px 6px;
  font-size: 11px;
  cursor: help;
}
.prg-bln { color: var(--ink-2); letter-spacing: .08em; }
.prg-blc { color: var(--muted); font-variant-numeric: tabular-nums; }

/* --- the argument, one click away -------------------------------------- */
.prg-more-d { margin: 9px 0 0; }
.prg-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;
}
.prg-sum::-webkit-details-marker { display: none; }
.prg-sum::before { content: "+"; color: var(--accent); font-size: 13px; }
.prg-more-d[open] .prg-sum::before { content: "\2212"; }
.prg-sum:hover { color: var(--ink); }
.prg-sum:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.prg-rule {
  margin: 9px 0 2px;
  padding: 0 0 0 20px;
  max-width: 96ch;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}
.prg-rule li { margin: 0 0 6px; }
.prg-rule li::marker { color: var(--accent); font-family: var(--font-mono); }

/* every label with its share, so the scheme can be checked rather than taken
   on trust — which is also where the genre lens lands a pick that is a badge */
.prg-ostrip {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 5px;
  align-items: center;
  padding: 4px 0;
}
.prg-ostrip.is-lit { box-shadow: inset 0 -2px 0 0 var(--accent); }
.prg-ol {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  border: var(--hair) solid var(--rule);
  padding: 2px 6px;
  font-size: 11px;
  background: var(--panel);
  cursor: help;
}
.prg-oln { color: var(--ink-2); text-transform: uppercase; letter-spacing: .04em; }
.prg-olc { color: var(--ink); font-variant-numeric: tabular-nums; }
.prg-olp { color: var(--muted); font-variant-numeric: tabular-nums; }
.prg-ol.is-badge { border-style: dashed; }
.prg-ol.is-badge .prg-oln, .prg-ol.is-thin .prg-oln { color: var(--muted); }
.prg-ol.is-thin { opacity: .75; }
.prg-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;
}

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

.prg-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: baseline;
  flex-wrap: wrap;
  gap: 0 10px;
}
/* THE FIRST ORANGE: the figure this page is ordered by, marked the way the
   house marks a sort key everywhere else. */
.prg-things {
  font-size: 11px;
  letter-spacing: .1em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.is-residue .prg-label { color: var(--ink-2); }

.prg-figs {
  margin: 4px 0 0;
  font-size: 11.5px;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 12px;
}
.prg-figs b { color: var(--ink); font-size: 14px; }
.prg-n + .prg-u { margin-left: -9px; }
.prg-unseen { color: var(--ink-2); }
.prg-seq { color: var(--ink-2); }
.prg-lead, .prg-carry {
  color: var(--ink-2);
  border-bottom: var(--hair) dotted var(--rule);
  cursor: help;
}

/* --- the distinctness bar ------------------------------------------------
   Track = this shelf's films, fill = its distinct things.  A full bar is a
   shelf with no sequels at all (Documentary, Western); a two-thirds bar is
   Animation.  Decorative only — both numbers are printed beside it, so
   nothing on this page is bar-only. */
.prg-meterw {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  cursor: help;
}
.prg-meter {
  position: relative;
  display: block;
  width: 78px;
  height: 8px;
  background: var(--panel-2);
  border: var(--hair) solid var(--rule);
  flex: 0 0 78px;
}
/* THE SECOND ORANGE: the same figure as the heading, drawn. */
.prg-mfill {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  background: var(--accent);
}
.prg-mfig { color: var(--ink-2); font-variant-numeric: tabular-nums; }

/* 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. */
.prg-shelf.is-lit .prg-shead { box-shadow: inset 0 -2px 0 0 var(--accent); }

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

/* --- shelf controls ----------------------------------------------------- */
.prg-ctl {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  padding-bottom: 2px;
}
.prg-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;
}
.prg-arrow:hover:not(:disabled) {
  background: var(--accent); color: var(--accent-ink); border-color: var(--accent);
}
.prg-arrow:disabled { color: var(--rule); cursor: default; background: transparent; }
.prg-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;
}
.prg-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, its figures, and a control that pulls the whole shelf out into
   a grid. */
.prg-rail {
  display: flex;
  gap: var(--prg-gap);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  padding: 12px 0 14px;
  scrollbar-width: thin;
}
.prg-rail:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

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

/* SHOW MORE — only with the shelf open.  A closed rail grows as you scroll
   it; an opened one must never paint a thousand posters in one frame, so it
   reveals a page at a time and says how far it has got. */
.prg-more {
  display: none;
  height: 34px;
  margin: 0 0 6px;
  padding: 0 14px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .05em;
  color: var(--ink-2);
  background: var(--panel);
}
.prg-more:hover { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.prg-shelf.is-open > .prg-more { display: inline-flex; align-items: center; }
.prg-more[hidden] { display: none; }

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

.prg-card {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  text-align: left;
  color: inherit;
}
.prg-art {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 2 / 3;
  background: var(--panel-2);
  border: var(--hair) solid var(--rule);
  overflow: hidden;
}
.prg-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.prg-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 */
.prg-card:hover .prg-art { outline: 2px solid var(--accent); outline-offset: -2px; }
.prg-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.prg-marks {
  position: absolute;
  left: 0;
  bottom: 0;
  display: flex;
  align-items: stretch;
  gap: 0;
  max-width: 100%;
}
/* THE THIRD ORANGE: you have played this one.  In a library that is 96%
   unplayed, the minority mark is the one worth printing. */
.prg-tick {
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 11px;
  line-height: 1;
  padding: 3px 5px;
  display: flex;
  align-items: center;
}
/* a label that can only ever be a subset of a bigger shelf: it marks here */
.prg-badge {
  background: var(--panel);
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .02em;
  padding: 3px 5px;
  border-top: var(--hair) solid var(--rule);
  border-right: var(--hair) solid var(--rule);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.prg-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. */
.prg-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);
}
.prg-m {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-top: 2px;
  font-size: 11px;
  color: var(--muted);
}
.prg-r { white-space: nowrap; }

/* =================================================================== stack
   THE ONE VISUAL INVENTION ON THIS PAGE.  A property that holds more than one
   film is drawn as ONE card with the edges of the other prints showing behind
   it — 42 Scooby-Doo films are one object, not forty-two.  It opens in place,
   which is the same gesture as OPEN SHELF one level down. */
/* The print edges live in the rail's GAP (7px into 14px), never in the card's
   own box. Padding the card instead made every stacked poster ~13px narrower,
   and since the art is a 2:3 ratio that made it ~19px shorter — so its caption
   sat out of line with the film card beside it, which is the one thing a rail
   of mono figures must never do. */
/* No negative z-index here: `.prg-art` is position:relative WITHOUT a z-index,
   so it opens no stacking context, and a -1 pseudo-element falls all the way
   behind the page background and vanishes. They sit outside the poster box,
   so they never need to go behind it — plain flow order is enough. */
.prg-art.is-stacked::before,
.prg-art.is-stacked::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  border: var(--hair) solid var(--rule);
  background: var(--panel-2);
}
/* the edges sit OUTSIDE the poster, so nothing is covered up */
.prg-cardw.is-stack .prg-art { overflow: visible; }
.prg-cardw.is-stack .prg-art > .prg-img,
.prg-cardw.is-stack .prg-art > .prg-noart { position: relative; z-index: 1; }
.prg-cardw.is-stack .prg-art { background: var(--panel-2); }
.prg-cardw.is-stack .prg-art::before { right: -4px; left: auto; width: 4px; }
.prg-cardw.is-stack .prg-art::after  { right: -7px; left: auto; width: 4px; top: 4px; bottom: 4px; }
/* the poster itself must still clip its image */
.prg-cardw.is-stack .prg-art > .prg-img { height: 100%; object-fit: cover; }

.prg-count {
  position: absolute;
  right: 0;
  top: 0;
  background: var(--panel);
  border-left: var(--hair) solid var(--rule);
  border-bottom: var(--hair) solid var(--rule);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .02em;
  padding: 3px 5px;
  z-index: 2;
}
.prg-cardw.is-stack .prg-card { position: relative; }
.prg-open-hint { color: var(--ink-2); letter-spacing: .08em; }
.prg-cardw.is-stack.is-open .prg-art { outline: 2px solid var(--accent); outline-offset: -2px; }

/* a film revealed out of a stack: tied to its stack by a hairline so the
   fanned-out group reads as one run and not as loose cards */
.prg-cardw.is-infold::before {
  content: "";
  position: absolute;
  left: calc(var(--prg-gap) / -2 - 1px);
  top: 0;
  bottom: 34px;
  border-left: var(--hair) solid var(--accent);
}
.is-open > .prg-rail > .prg-cardw.is-infold::before { bottom: 0; }

/* --- the parked play/cast pair -----------------------------------------
   One pair for the page, moved onto whatever card the pointer is over.  It
   rides in the card WRAPPER, not in the card, because the card is a <button>
   and an <a> cannot live inside one. */
.prg-cardw > .nact.prg-act {
  position: absolute;
  right: 6px;
  top: 6px;
  z-index: 4;
  gap: 4px;
  background: var(--panel);
  border: var(--hair) solid var(--rule);
}
.prg-act .plexlink:hover, .prg-act .plexlink:focus-visible,
.prg-act .nstream-btn:hover, .prg-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) {
  .prg { --prg-w: 132px; --prg-gap: 10px; }
  .prg-shead { flex-wrap: wrap; align-items: flex-start; }
  .prg-ctl { order: 2; }
}
/* ==================================================================== 760
   THE MOBILE TIER.  2026-08-11: 700 (the swipeable strips) and 560 (the
   smaller poster) were two queries for one device, invented separately.
   MOBILE_SPEC §1 folds 460–720 into 760, so they are one block now.  The 900
   block above is untouched, and so is everything else above 760.

   On a phone a wrapping index pushed every poster below the fold — the exact
   fault this page exists to fix. The strips stay complete and stay visible,
   but as one swipeable row each. */
@media (max-width: 760px) {
  .prg-istrip, .prg-ostrip, .prg-bstrip {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 3px;
  }
  .prg-istrip::-webkit-scrollbar,
  .prg-ostrip::-webkit-scrollbar,
  .prg-bstrip::-webkit-scrollbar { display: none; }
  .prg-ix, .prg-ol, .prg-bl, .prg-oh { flex: 0 0 auto; }
  .prg-cl { padding: 0 8px; }
  .prg-ledger { margin-left: 0; }

  /* was the 560 tier */
  .prg { --prg-w: 118px; }
  .prg-rule { padding-left: 17px; }
  .prg-figs { gap: 0 9px; }
  .prg-head { padding-top: 10px; }
  .prg-meter { width: 54px; flex-basis: 54px; }
}

/* 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 racks.
   What a finger DOES meet here — the arrows, OPEN SHELF, SHOW MORE and the
   stacks — grows to a real target. */
@media (hover: none) {
  .prg-cardw > .nact.prg-act { display: none; }
  .prg-arrow { width: 44px; height: 44px; font-size: 20px; }
  .prg-open { height: 44px; padding: 0 14px; }
  .prg-more { height: 44px; }
  /* 🔴 THE INDEX WAS THE LAST 30px CONTROL ON THE PAGE.  It is the only thing
     that reaches all thirteen shelves, and on a phone it sits in a strip that
     scrolls sideways — so a near miss drags the strip instead of jumping the
     shelf, and you cannot tell which happened.  44 is the floor (spec §4.2).
     The chip keeps its type and its hairline; the BOX grows (§10.5).
     ⚠️ This belongs to the TOUCH query and not to the 760 tier: a phone held
     in landscape is 844px wide, above the mobile tier entirely (§10.3), and
     the finger is still a finger. .prg-ol is a label, not a control, and
     stays at 30 — it is not a target and does not need to be one. */
  .prg-ix { min-height: var(--tap, 44px); align-items: center; padding: 2px 10px; }
  .prg-ol { min-height: 30px; align-items: center; }
  .prg-sum { min-height: var(--tap, 44px); align-items: center; }
  .prg-card:hover .prg-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. */
