/*
  Squirrel Away — the one stylesheet.
  Theme: autumn neumorphism — "pressed into warm clay."
  Every surface is molded from the same clay; depth comes from dual opposing
  shadows (warm-tan dark toward bottom-right, candlelight highlight toward
  top-left). No borders anywhere. Light = "harvest clay" and is ALWAYS the
  default; dark = "fireside", only via html[data-theme=dark] (theme cookie).
  No framework. No third-party assets. Two self-hosted variable fonts.
*/

@font-face {
  font-family: "Plus Jakarta Sans";
  src: url("plus-jakarta-sans.woff2") format("woff2-variations");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "DM Sans";
  src: url("dm-sans.woff2") format("woff2-variations");
  font-weight: 100 1000;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */
:root {
  /* Spacing tokens (8px grid, owner-approved 2026-08-17) — the only spacing
     vocabulary. --measure caps prose at ~68ch. */
  --space-1: .25rem; --space-2: .5rem; --space-3: .75rem; --space-4: 1rem;
  --space-5: 1.5rem; --space-6: 2rem; --space-7: 3rem; --space-8: 4rem; --space-9: 6rem;
  --measure: 42rem;
  --clay: #ECE2D0;          /* harvest clay — page and every surface */
  --ink: #43301F;           /* walnut text */
  --muted: #6F604B;         /* secondary text — never lighter than this */
  /* Pumpkin is 3.98:1 on clay: it fills buttons, draws marks and underlines
     and carries large text, but it must NEVER color small text — that is
     what --eyebrow is for. See the note on --eyebrow below. */
  --accent: #B54F23;        /* pumpkin */
  --accent-ink: #FFF6EA;    /* text on pumpkin — 4.8:1 */
  --honey: #C98D1B;         /* acorn honey — 2.2:1, decoration only, never words */
  --placeholder: #74624D;   /* input placeholders — 4.6:1 */
  /* Darkened pumpkin, 5.7:1 on clay. The accent for every piece of TEXT below
     the large-text threshold (18.66px bold / 24px regular): eyebrows, active
     sort and pagination states, flash and form errors, the live seeder count,
     stat figures, link hovers. Pumpkin itself fails AA at those sizes, and on
     2026-09-01 it was still coloring thirteen of them — including
     .flash-alert and .form-errors, the two strings a reader most needs when
     something has gone wrong. In the dark theme this is ember, the same value
     as --accent, so the distinction costs the fireside palette nothing. */
  --eyebrow: #8F3E1B;
  --shadow-dark: rgba(201, 185, 159, .7);
  --shadow-light: rgba(255, 253, 246, .65);

  /* shadow recipes — the entire physics system */
  --sh-out: 9px 9px 16px var(--shadow-dark), -9px -9px 16px var(--shadow-light);
  --sh-out-sm: 5px 5px 10px var(--shadow-dark), -5px -5px 10px var(--shadow-light);
  --sh-in-deep: inset 10px 10px 20px var(--shadow-dark), inset -10px -10px 20px var(--shadow-light);
  --sh-in: inset 6px 6px 10px var(--shadow-dark), inset -6px -6px 10px var(--shadow-light);
  --sh-in-sm: inset 3px 3px 6px var(--shadow-dark), inset -3px -3px 6px var(--shadow-light);

  --font-display: "Plus Jakarta Sans", system-ui, sans-serif;
  --font-body: "DM Sans", system-ui, sans-serif;

  color-scheme: light;
}

html[data-theme="dark"] {
  --clay: #33281C;          /* roasted clay */
  --ink: #F0E4D0;           /* lamplight */
  --muted: #B5A488;
  --accent: #E2884C;        /* ember */
  --accent-ink: #2A1F13;
  --eyebrow: #E2884C;       /* ember is already 5.4:1 on roasted clay */
  --placeholder: #A5947A;   /* 4.9:1 on roasted clay */
  --shadow-dark: rgba(18, 12, 6, .75);
  --shadow-light: rgba(94, 76, 52, .4);
  color-scheme: dark;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body, h1, h2, h3, h4, p, figure { margin: 0; }
img, svg, video { max-width: 100%; display: block; }
a { color: inherit; }

/* ---------- Base ---------- */
body {
  background: var(--clay);
  color: var(--ink);
  font-family: var(--font-body);
  line-height: 1.6;
  font-size: 1rem;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.15;
}
h1 { font-size: 2.1rem; }
h2 { font-size: 1.5rem; }
h3 { font-size: 1.05rem; }
p + p { margin-top: 1em; }
.cta { margin-top: 1.75rem; }
main section { margin-top: var(--space-7); }
main section.strip { margin-top: var(--space-6); }
main section.strip .section-head { margin-top: 0; }
a.plain { text-decoration: none; }
a { text-decoration-color: var(--accent); text-underline-offset: 3px; }

/* ---------- Focus & motion ---------- */
a:focus-visible, button:focus-visible, [tabindex]:focus-visible,
input:focus-visible, textarea:focus-visible, summary:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ---------- Header ---------- */
.site-head { background: var(--clay); }
.site-head-inner {
  max-width: 68rem;
  margin: 0 auto;
  padding: 1rem 1.25rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .75rem 1.5rem;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: .65rem;
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.15rem;
  letter-spacing: -.02em;
}
.brand-chip {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--sh-out-sm);
  color: var(--ink);
}
.brand-chip img { height: 2rem; width: auto; }
[data-theme="dark"] .brand-chip img {
  /* walnut ink outlines vanish into fireside clay without a soft cream halo */
  filter: drop-shadow(0 0 4px rgba(240, 228, 208, .45));
}

nav[aria-label="Primary"] {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem 1.2rem;
  font-size: .88rem;
  font-weight: 500;
}
nav[aria-label="Primary"] a:not(.ticket-btn) {
  text-decoration: none;
  color: var(--muted);
  padding: .35em 0;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
nav[aria-label="Primary"] a:not(.ticket-btn):hover,
nav[aria-label="Primary"] a:not(.ticket-btn):focus-visible { color: var(--ink); }
/* Where you are. Every nav item looked identical on every page, so the header
   never answered "which of these am I reading?" — the underline carries it as
   well as the color, because color alone is not a signal. */
nav[aria-label="Primary"] a[aria-current] {
  color: var(--ink);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 5px;
}

/* Native disclosure keeps the navigation usable without JavaScript. */
.site-menu { margin-left: auto; }
.site-menu summary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .65rem;
  min-height: 44px;
  padding: .55rem .9rem;
  border-radius: 999px;
  font-size: .88rem;
  font-weight: 700;
  cursor: pointer;
  list-style: none;
  box-shadow: var(--sh-out-sm);
}
.site-menu summary::-webkit-details-marker { display: none; }
.menu-indicator::before { content: "+"; font-size: 1.15rem; line-height: 1; }
.site-menu[open] .menu-indicator::before { content: "−"; }
@media (min-width: 75rem) {
  .site-menu[open] summary { display: none; }
}
@media (max-width: 74.999rem) {
  .site-head-inner { position: relative; align-items: flex-start; gap: .75rem; padding: .85rem 1.25rem; }
  .brand { min-height: 44px; }
  .site-menu[open] { flex-basis: 100%; }
  .site-menu[open] summary { position: absolute; top: .85rem; right: 1.25rem; }
  .site-menu nav[aria-label="Primary"] {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .35rem .75rem;
    padding-top: .75rem;
  }
  .site-menu nav[aria-label="Primary"] a { padding: .5rem .6rem; }
  .site-menu .theme-toggle { justify-self: start; }
  .site-menu .ticket-btn { text-align: center; }
}
@media (max-width: 23rem) {
  .site-head-inner { padding-right: .85rem; padding-left: .85rem; }
  .site-menu[open] summary { right: .85rem; }
  .brand { gap: .45rem; font-size: 1rem; }
  .brand-chip { width: 2.3rem; }
}

.theme-toggle {
  font: inherit;
  font-weight: 700;
  font-size: .8rem;
  color: var(--ink);
  background: var(--clay);
  border: none;
  border-radius: 999px;
  padding: .55em 1.1em;
  min-height: 44px;
  cursor: pointer;
  box-shadow: var(--sh-out-sm);
  transition: box-shadow .15s ease;
}
html[data-theme="dark"] .theme-toggle { box-shadow: var(--sh-in-sm); }

/* ---------- Buttons ----------
   .ticket-btn keeps its legacy class name (used across views/tests) but is
   now a neumorphic press-button: raised at rest, lifted on hover, pressed
   flat on :active — like pushing an acorn into soft clay. */
.ticket-btn, button.ticket-btn, input[type="submit"].ticket-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  font: inherit;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: .9rem;
  background: var(--accent);
  color: var(--accent-ink);
  border: none;
  border-radius: 16px;
  padding: .7em 1.6em;
  min-height: 44px;
  text-decoration: none;
  cursor: pointer;
  box-shadow: var(--sh-out);
  transition: box-shadow .15s ease, transform .15s ease, filter .15s ease;
}
.ticket-btn:hover, .ticket-btn:focus-visible { filter: brightness(1.06); }
.ticket-btn:active {
  transform: translateY(1px);
  box-shadow: var(--sh-in-sm);
  filter: brightness(.97);
}

/* The secondary of a pair: same size, same tap target, quieter surface. Clay
   rather than pumpkin, so exactly one filled button reads as the primary
   action wherever two sit side by side. */
.ticket-btn-quiet, button.ticket-btn-quiet {
  background: var(--clay);
  color: var(--ink);
  box-shadow: var(--sh-out-sm);
}
.ticket-btn-quiet:hover, .ticket-btn-quiet:focus-visible { filter: none; box-shadow: var(--sh-out); }
.ticket-btn-quiet:active { box-shadow: var(--sh-in-sm); filter: none; }

/* ---------- Main ---------- */
main {
  flex: 1;
  max-width: 68rem;
  width: 100%;
  margin: 0 auto;
  padding: 2.5rem 1.25rem 4rem;
}

/* ---------- Hero ---------- */
.hero { text-align: center; margin-bottom: 2.5rem; }
.hero h1 { font-size: 2.7rem; letter-spacing: -.03em; }
.hero-lede { color: var(--muted); font-size: 1.02rem; margin-top: .6rem; }
.hero-lede::before { content: "— "; color: var(--accent); }

/* ---------- Page banners & section headings ----------
   Headings are type and space, never a surface. This replaced a raised clay
   panel (itself a leftover of the retired picture-palace theme, where a
   silent-film intertitle card was the right metaphor). Three reasons it had to
   go, recorded so nobody re-boxes them:

   1. A container around a heading alone is the strongest grouping signal CSS
      has — NN/g's "common region" beats proximity — so it grouped the heading
      with nothing and visually severed it from the text it introduced.
   2. Raised-but-not-clickable is neumorphism's canonical failure: a fake
      affordance. Every practitioner guide scopes elevation to interactive or
      content-bearing surfaces.
   3. Spacing was inverted — 0px above and 32px below on film pages — so each
      heading bound to the section it ended rather than the one it began.

   Elevation now means exactly one thing: raised = interactive or content
   bearing, pressed = active/input, flat + type = structure. */
.page-banner,
.section-head { margin: var(--space-7) 0 var(--space-3); }  /* ~4:1 — binds DOWN to its content */
.page-banner { margin-top: 0; }
.section-head:first-child { margin-top: 0; } /* section already carries 3rem */

.eyebrow {
  display: block;
  font-family: var(--font-body);
  font-size: .75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .12em;
  /* --eyebrow, not --accent: pumpkin is 3.98:1 on clay, which fails AA at this
     size. The mark beside it is decorative and contrast-exempt. */
  color: var(--eyebrow);
  margin-bottom: .3rem;
}
.eyebrow-mark { color: var(--accent); margin-right: .45em; }

.page-banner h1 { font-size: 2.4rem; }
.section-head h2 { font-size: 1.75rem; letter-spacing: -.01em; }
.section-sub { margin-top: .5rem; color: var(--muted); font-size: .92rem; }

/* A seam pressed into the clay rather than a rule drawn on top of it: no border
   property, just the same two opposing shadows every other surface uses, at
   1px. A deliberate, owner-approved exception to "no borders anywhere"
   (2026-08-16) — it is the one physical artifact left in the heading. */
.seam {
  width: 56px;
  height: 3px;
  border-radius: 2px;
  margin-top: .75rem;
  box-shadow: inset 1px 1px 2px var(--shadow-dark),
              inset -1px -1px 2px var(--shadow-light);
}

/* ---------- Film lists ---------- */
.film-list { list-style: none; padding: 0; margin: 0 0 2rem; }
.film-list li {
  padding: .7rem 0 .7rem 1.6rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .35rem .75rem;
  position: relative;
}
/* acorn bullet: pure CSS, cap + nut */
.film-list li::before {
  content: "";
  position: absolute;
  left: .15rem;
  top: 1.05rem;
  width: .7rem;
  height: .7rem;
  border-radius: 50% 50% 50% 50% / 62% 62% 38% 38%;
  background: radial-gradient(circle at 50% 28%, var(--ink) 46%, var(--accent) 48%);
}
.film-list .meta { font-size: .85rem; color: var(--muted); }

/* ---------- The Cache listing (/films) ----------
   Not fifty raised slabs: one pressed-in trough holding rows divided by a
   hairline of the same shadow color, each row lifting on hover. The divider
   lives on a pseudo-element so hover's box-shadow has nothing to fight. */
.sort-strip {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin: 0 0 1.4rem;
}
.sort-strip a {
  padding: .4rem .95rem;
  border-radius: 16px;
  box-shadow: var(--sh-out-sm);
  text-decoration: none;
  color: var(--muted);
  font-family: var(--font-display);
  font-size: .85rem;
  font-weight: 600;
}
.sort-strip a:hover, .sort-strip a:focus-visible { color: var(--ink); }
.sort-strip a[aria-current="true"] { box-shadow: var(--sh-in-sm); color: var(--eyebrow); }

/* Same pressed-clay pills as the sort strip, centered under the listing. The
   ends of the range and the elision are spans, not links, so they are styled
   as flat text rather than given a shadow that invites a click. */
.pagination {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: .5rem;
  margin: 0 0 2rem;
}
.pagination a, .pagination span {
  min-width: 2.4rem;
  padding: .4rem .8rem;
  border-radius: 16px;
  text-align: center;
  text-decoration: none;
  font-family: var(--font-display);
  font-size: .85rem;
  font-weight: 600;
  color: var(--muted);
}
.pagination a { box-shadow: var(--sh-out-sm); }
.pagination a:hover, .pagination a:focus-visible { color: var(--ink); }
.pagination a[aria-current="page"] { box-shadow: var(--sh-in-sm); color: var(--eyebrow); }
/* The inactive ends of the range and the gap ellipsis. No opacity: .45 here
   took --muted to #b4a894, lighter than the token whose own comment says
   "never lighter than this", and 1.82:1 on clay (found by axe 2026-09-01).
   They are already told apart from the links without it — a link is raised
   clay (--sh-out-sm), these are flat in it, which is the whole vocabulary. */
.pagination .pagination-gap, .pagination .pagination-off { box-shadow: none; }

/* Off-screen for sighted readers, still announced. The clip-rect pair is the
   version screen readers actually read out; display:none would silence it. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Search ("Dig Around"). The field is the widest thing on the page on purpose
   — it is the only reason anyone is here. */
.dig-form {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin: 0 0 1.8rem;
}
.dig-form input[type="search"] {
  flex: 1 1 22rem;
  max-width: none;
  font-size: 1.05rem;
  padding: .85em 1.1em;
}
/* Safari paints its own rounded box and a decoration that ignores the clay. */
.dig-form input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
.dig-form button { flex: 0 0 auto; }

.dig-empty {
  padding: 1.6rem 1.8rem;
  border-radius: 32px;
  box-shadow: var(--sh-in);
  color: var(--muted);
  max-width: 46rem;
}
.dig-empty p { margin: 0 0 .8rem; }
.dig-empty p:last-child { margin-bottom: 0; }
.dig-empty strong { color: var(--ink); }

.dig-count { color: var(--muted); margin: 0 0 1rem; }
.dig-count strong { color: var(--ink); }

.dig-facets {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin: 0 0 1.4rem;
}
.dig-facets a {
  padding: .4rem .95rem;
  border-radius: 16px;
  box-shadow: var(--sh-out-sm);
  text-decoration: none;
  color: var(--muted);
  font-family: var(--font-display);
  font-size: .85rem;
  font-weight: 600;
}
.dig-facets a:hover, .dig-facets a:focus-visible { color: var(--ink); }
.dig-facets a[aria-current="true"] { box-shadow: var(--sh-in-sm); color: var(--eyebrow); }
/* No opacity (house rule): at .6 this took --muted to #a19480, 2.32:1 — a
   number a reader is meant to actually read. It is already subordinate to the
   facet name beside it, which carries the weight. */
.dig-facet-count { font-variant-numeric: tabular-nums; }

/* ---------- Swarm ticker ----------
   Motion is the whole point and also the whole risk: this is decoration over
   data that moves on a 1800s announce interval, so it must never cost anything
   a reader did not ask for. It is CSS only, it pauses on hover so a link can
   actually be clicked, and it stops dead under prefers-reduced-motion. */
.ticker {
  overflow: hidden;
  border-radius: 32px;
  box-shadow: var(--sh-in-sm);
  padding: .6rem 0;
  margin: 0 0 1.6rem;
  /* Fades the beats in and out at the edges instead of clipping them mid-word. */
  mask-image: linear-gradient(to right, transparent, #000 3rem, #000 calc(100% - 3rem), transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 3rem, #000 calc(100% - 3rem), transparent);
}
.ticker-track {
  display: flex;
  width: max-content;
  animation: ticker-scroll 75s linear infinite;
}
.ticker:hover .ticker-track, .ticker:focus-within .ticker-track { animation-play-state: paused; }
.ticker-run {
  display: flex;
  align-items: center;
  gap: 2.4rem;
  list-style: none;
  margin: 0;
  padding: 0 1.2rem;
  white-space: nowrap;
}
.ticker-run li {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  color: var(--muted);
  font-size: .85rem;
}
.ticker-run a { color: var(--ink); text-decoration: none; font-weight: 600; }
.ticker-run a:hover, .ticker-run a:focus-visible { color: var(--eyebrow); }
.ticker-mark { opacity: .8; }
/* Exactly half the track, because the run is rendered twice — the second copy
   arrives under the cursor as the first leaves, so the loop has no seam. */
@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* A live swarm breathes; an empty one does not. Opacity only, so nothing
   reflows and the line costs no layout. */
.feature-swarm.is-live::before {
  content: "";
  display: inline-block;
  width: .5rem;
  height: .5rem;
  margin-right: .45rem;
  border-radius: 50%;
  background: var(--accent);
  animation: swarm-pulse 2.4s ease-in-out infinite;
}
@keyframes swarm-pulse {
  0%, 100% { opacity: .35; }
  50% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  /* The global rule above collapses every animation to nothing, which would
     freeze the track mid-translate. Give the ticker a still, scrollable form
     instead: one run, no mask, and the reader's own scrollbar. */
  .ticker { overflow-x: auto; mask-image: none; -webkit-mask-image: none; }
  .ticker-track { animation: none; }
  .ticker-run[aria-hidden="true"] { display: none; }
  .feature-swarm.is-live::before { animation: none; opacity: 1; }
}

/* The grid lives on the LIST, and each row maps onto it with subgrid.
   Until 2026-09-01 every <li> was its own grid, so the `auto` columns were
   sized per row and only lined up when neighboring rows happened to hold
   text the same width. They usually did not: a seeded row and a webseed-only
   row carry different swarm strings, and on /search the year column sat at
   two different x-positions eleven rows apart. Mixed swarm states are the
   normal case in production, so the misalignment was the normal case too. */
.cache-list {
  list-style: none;
  margin: 0 0 2rem;
  padding: .8rem;
  border-radius: 32px;
  box-shadow: var(--sh-in);
  display: grid;
  grid-template-columns: 1fr auto auto auto auto;
  /* The column gutter belongs to the parent: a subgrid inherits the gutters
     of the axis it subgrids, so re-declaring them on the row would put its
     tracks back out of step with the list they are meant to follow. */
  column-gap: 1.1rem;
}
.cache-row {
  position: relative;
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: baseline;
  row-gap: .2rem;
  padding: .85rem 1rem;
  border-radius: 16px;
}
.cache-row + .cache-row::before {
  content: "";
  position: absolute;
  inset-inline: 1rem;
  top: 0;
  height: 1px;
  background: var(--shadow-dark);
}
.cache-row:hover { box-shadow: var(--sh-out-sm); }
.cache-row:hover::before, .cache-row:hover + .cache-row::before { background: none; }
.cache-row-title {
  font-family: var(--font-display);
  font-weight: 700;
  text-decoration: none;
}
.cache-row-year, .cache-row-size, .cache-row-swarm, .cache-row-done {
  font-size: .85rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.cache-row-size { min-width: 5rem; text-align: right; }
.cache-row-swarm { min-width: 14rem; text-align: right; }
/* Completions, not the live swarm. The text stays --muted, which the token
   comment fixes as the floor for secondary text: honey is 2.2:1 on clay and
   must never carry words. Only the tick is honey, and it is aria-hidden, so
   the color is pure decoration and the meaning lives in the text. */
.cache-row-done { text-align: right; color: var(--muted); white-space: nowrap; }
.done-mark { color: var(--honey); }
.cache-row-meta {
  grid-column: 1 / -1;
  font-size: .85rem;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  gap: .2rem .6rem;
}
.cache-row-meta > * + *::before { content: "· "; }

@media (max-width: 48rem) {
  /* One column on a phone, so the row stops subgridding and the list stops
     being a grid of five — otherwise the single track would still be shared
     out five ways. */
  .cache-list { grid-template-columns: 1fr; }
  .cache-row {
    grid-template-columns: 1fr;
    gap: .3rem;
  }
  .cache-row-size, .cache-row-swarm, .cache-row-done { min-width: 0; text-align: left; }
}

/* ---------- Featured card (Tonight's Pick) ---------- */
.now-showing {
  background: var(--clay);
  border-radius: 32px;
  box-shadow: var(--sh-out);
  padding: 1.7rem 1.8rem;
  margin-bottom: 2rem;
}
.now-showing h3 { font-size: 1.3rem; margin-bottom: .5rem; }
.now-showing h3 a { text-decoration: none; }

/* ---------- Card grids (hoards, pairings, den wall) ---------- */
.collections-grid {
  list-style: none;
  padding: 0;
  margin: 0 0 2rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.6rem;
}
.collections-grid li {
  background: var(--clay);
  border-radius: 32px;
  box-shadow: var(--sh-out);
  padding: 1.5rem 1.6rem;
}
.collections-grid h3 { margin-bottom: .5rem; }
.collections-grid h3 a { text-decoration: none; }
.collections-grid p { color: var(--muted); font-size: .92rem; }
.double-features-grid .meta { color: var(--muted); font-size: .85rem; }
.mystery-link { color: var(--muted); margin-bottom: 2rem; }

/* ---------- Acorn meter (swarm health) ---------- */
.acorn-meter { margin: .9rem 0; max-width: 26rem; }
.acorn-meter-track {
  height: 1.1rem;
  border-radius: 999px;
  background: var(--clay);
  box-shadow: var(--sh-in-sm);
  position: relative;
  overflow: hidden;
}
.acorn-meter-fill {
  position: absolute;
  inset: 3px auto 3px 3px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--honey), var(--accent));
}
.acorn-meter-label {
  margin-top: .45rem;
  font-size: .82rem;
  font-weight: 700;
  color: var(--muted);
}

/* ---------- Film page extras ---------- */
.viewing-well {
  padding: 1rem;
  border-radius: 32px;
  box-shadow: var(--sh-in-deep);
  margin: 1.4rem 0;
}
.viewing-well video { width: 100%; border-radius: 20px; background: #000; }
/* Poster. Floated so the editorial wraps around it rather than being pushed
   below a tall image, and molded into the clay like every other surface —
   raised shadow, 16px radius, no border. */
.film-poster-figure {
  float: right;
  width: 260px;
  margin: 0 0 var(--space-4) var(--space-4);
}
.poster-credit {
  font-size: .68rem;
  line-height: 1.35;
  color: var(--muted);
  margin-top: var(--space-2);
  text-align: center;
}
.film-poster {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 16px;
  box-shadow: var(--sh-out);
  background: var(--clay);
}
/* Below the two-column threshold a 210px float leaves the title in a narrow
   gutter, so the poster goes full-width and leads instead. */
@media (max-width: 34rem) {
  .film-poster-figure {
    float: none;
    width: min(220px, 60%);
    margin: 0 auto var(--space-4);
  }
}

.film .actions { display: flex; flex-wrap: wrap; gap: .8rem; align-items: center; margin: 1.6rem 0; }
.film .actions form { display: inline-flex; }
.top-seeders {
  background: var(--clay);
  border-radius: 32px;
  box-shadow: var(--sh-out);
  padding: 1.3rem 1.6rem;
  margin: 1.6rem 0;
}
.top-seeders ol { margin: .5rem 0 0; padding-left: 1.3rem; }
.own-it {
  display: flex;
  flex-wrap: wrap;
  gap: .8rem 1.6rem;
  margin: 1.6rem 0;
  color: var(--muted);
  font-size: .92rem;
}

/* ---------- Account forms ---------- */
.login-page { width: 100%; max-width: 30rem; margin: 1rem auto 2rem; text-align: center; }
.login-intro { margin-bottom: 2rem; }
.login-mascot { margin: 0 auto 1.25rem; object-fit: contain; }
.login-eyebrow { color: var(--eyebrow); font-size: .75rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; margin-bottom: .5rem; }
.login-intro h1 { font-size: clamp(2rem, 5vw, 2.6rem); letter-spacing: -.04em; line-height: 1.15; margin-bottom: .8rem; }
.login-intro > p:last-child { color: var(--muted); max-width: 27ch; margin: 0 auto; }
.login-panel { padding: 2rem; border-radius: 28px; box-shadow: var(--sh-out); text-align: left; }
.login-form { display: grid; gap: 1.5rem; }
.login-field { display: grid; gap: .6rem; min-width: 0; }
.account-field-hint { margin: 0; color: var(--muted); font-size: .8rem; line-height: 1.5; }
.login-field label { font-weight: 700; font-size: .9rem; }
.login-label-row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: .3rem 1rem; }
.login-label-row a { font-size: .85rem; color: var(--muted); text-underline-offset: .2em; }
.login-form input { min-height: 52px; font-size: 1rem; }
.login-submit { width: 100%; min-height: 52px; margin-top: .25rem; }
.login-join { margin: 1.8rem 0 .6rem; color: var(--muted); }
.login-join a { color: var(--ink); font-weight: 700; text-underline-offset: .2em; }
.login-browse { display: inline-flex; align-items: center; min-height: 44px; color: var(--muted); font-size: .9rem; text-underline-offset: .2em; }
.login-error { margin: 0 0 1.5rem; }
.login-error p { margin: 0; }
@media (max-width: 34rem) {
  .login-page { margin-top: 0; }
  .login-panel { padding: 1.5rem 1.25rem; }
}

/* ---------- Guestbook ---------- */
.guestbook-page .page-banner { margin-bottom: 2rem; }
.guestbook-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 25rem); align-items: start; gap: 3rem; }
.guestbook-layout h2 { font-size: 1.5rem; letter-spacing: -.03em; margin-bottom: 1rem; }
.guestbook-welcome { padding: 2.5rem 1.5rem; text-align: center; border-radius: 28px; box-shadow: var(--sh-in); }
.guestbook-welcome img { margin: 0 auto 1.25rem; object-fit: contain; }
.guestbook-welcome h3 { font-size: 1.25rem; margin-bottom: .75rem; }
.guestbook-welcome p { color: var(--muted); max-width: 32ch; margin: 0 auto; }
.guestbook-notes { list-style: none; padding: 0; margin: 0; display: grid; gap: 1.5rem; }
.guestbook-note { padding: 1.5rem; border-radius: 24px; box-shadow: var(--sh-out-sm); overflow-wrap: anywhere; }
.guestbook-note header { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .4rem 1rem; margin-bottom: .8rem; }
.guestbook-note h3 { font-size: 1rem; }
.guestbook-note time { font-size: .8rem; color: var(--muted); }
.guestbook-note p { margin: 0; white-space: pre-wrap; }
.guestbook-compose h2 { margin-bottom: .6rem; }
.guestbook-form-intro { margin-bottom: 1.5rem; color: var(--muted); font-size: .9rem; }
.guestbook-compose textarea { max-width: none; min-height: 10rem; resize: vertical; font-size: 1rem; }
.guestbook-notice { padding: 1rem 1.5rem; margin-bottom: 2rem; border-radius: 16px; box-shadow: var(--sh-in); color: var(--eyebrow); }
.guestbook-trap { position: absolute; left: -9999px; }
@media (max-width: 48rem) {
  .guestbook-layout { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
  .guestbook-compose { padding: 1.5rem 1.25rem; }
}

/* ---------- Forms ---------- */
.better-print { margin-top: 2rem; }
.better-print summary, details summary {
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 700;
}
.better-print-nudge { margin-top: 2rem; color: var(--muted); }
input[type="text"], input[type="url"], input[type="email"],
input[type="password"], input[type="search"], textarea {
  width: 100%;
  max-width: 30rem;
  font: inherit;
  color: var(--ink);
  background: var(--clay);
  border: none;
  border-radius: 16px;
  padding: .7em .95em;
  box-shadow: var(--sh-in-deep);
  caret-color: var(--accent);
}
input::placeholder, textarea::placeholder { color: var(--placeholder); }
textarea { min-height: 6rem; }
label { font-weight: 700; font-size: .9rem; }
.form-errors {
  padding: 1rem 1.3rem;
  border-radius: 16px;
  box-shadow: var(--sh-out-sm);
  color: var(--eyebrow);
  margin: 0 0 1.5rem;
}
.form-errors:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.form-errors-head { font-weight: 700; margin-bottom: .3rem; }
.form-errors ul { margin: 0; padding-left: 1.2rem; }
.form-errors li { font-weight: 700; }

/* What a field expects, said before the reader has a chance to get it wrong.
   The password minimum has been 10 since 2026-09-01 and the form never
   mentioned it: the only way to find out was to fail a submit. */
.field-hint {
  display: block;
  margin-top: .35rem;
  font-size: .82rem;
  color: var(--muted);
}

.flash-wrap { max-width: 68rem; margin: var(--space-4) auto 0; padding: 0 var(--space-5); }
.flash-notice, .flash-alert {
  padding: .8em 1.3em;
  border-radius: 999px;
  box-shadow: var(--sh-out-sm);
  display: inline-block;
  font-weight: 700;
  margin: 0;
}
.flash-alert { color: var(--eyebrow); }

/* Honeypot: hidden from sighted humans, still reachable to bots that fill
   every field blindly. Off-screen, not display:none, so naive bots that
   skip display:none fields still trip it. */
.hp { position: absolute; left: -9999px; }

/* ---------- Den Wall cards ---------- */
.lobby-cards {
  list-style: none;
  padding: 0;
  margin: 2rem 0 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.6rem;
}
.lobby-card {
  background: var(--clay);
  border-radius: 32px;
  box-shadow: var(--sh-out);
  padding: 1.4rem 1.5rem;
}
.lobby-card-message { font-weight: 500; }
.lobby-card-name { margin-top: .5em; color: var(--muted); font-size: .9rem; }
.guestbook-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding: 3rem 1rem;
  color: var(--muted);
  text-align: center;
}

/* ---------- Tables (profile stats) ---------- */
.profile-stats { border-collapse: collapse; width: 100%; max-width: 40rem; }
.profile-stats th, .profile-stats td { text-align: left; padding: .55rem .8rem; }
.profile-stats thead th {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--muted);
}
.profile-stats tbody tr { box-shadow: 0 1px 0 var(--shadow-dark); }

/* ---------- Admin moderation ---------- */
.moderation-section { margin-top: 2rem; }
.moderation-list { list-style: none; padding: 0; }
.moderation-list li {
  background: var(--clay);
  border-radius: 16px;
  box-shadow: var(--sh-out-sm);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
}

/* ---------- Cache artwork (retro-cartoon raster identity, 2026-08-17) ---------- */
.home-hero {
  border-radius: 32px;
  overflow: hidden;
  box-shadow: var(--sh-out);
  margin-bottom: 2rem;
}
.home-hero img { display: block; width: 100%; height: auto; }
.empty-cache-art {
  display: block;
  width: min(16rem, 70%);
  height: auto;
  margin: 0 auto 1rem;
  border-radius: 16px;
  box-shadow: var(--sh-out-sm);
}
.page-cache-card {
  display: block;
  width: min(24rem, 90%);
  height: auto;
  margin: 1.5rem auto;
  border-radius: 16px;
  box-shadow: var(--sh-out);
}

/* ---------- Prose measure ---------- */
article.film p, article.film ul:not(.top-seeders):not(.cand),
article.page p, article.page ul, .collection-blurb p { max-width: var(--measure); }
/* Legal/info pages read as one centered column: the measure-wide text used to
   hug the left edge of the 68rem container, and markdown h2s sat flush against
   the previous paragraph (owner report, 2026-08-17). */
/* A work with no art has nothing holding the right-hand side of the shell, so
   it centers instead of hugging the left edge of 68rem. 48rem rather than
   --measure because a series' episode list is 46rem wide and must still fit. */
article.film.no-poster { max-width: 48rem; margin-left: auto; margin-right: auto; }
article.page { max-width: var(--measure); margin-left: auto; margin-right: auto; }
article.page h2 { margin-top: var(--space-6); margin-bottom: var(--space-3); }
article.page h3 { margin-top: var(--space-5); margin-bottom: var(--space-2); }

/* ---------- Tracker-first homepage (D2, 2026-08-17) ---------- */
.split-hero { display: grid; grid-template-columns: 1.15fr .85fr; gap: var(--space-6);
  align-items: start; margin-top: var(--space-5); }
.split-hero-feature .eyebrow { margin-bottom: var(--space-2); }
.feature-title { font-size: 2.2rem; line-height: 1.12; margin: 0 0 var(--space-3); letter-spacing: -.01em; }
.feature-title a { text-decoration: none; color: inherit; }
/* Poster beside the blurb, not above it: the hero's left column was a stack of
   type with a large empty patch under the button. The link is aria-hidden and
   out of the tab order — the title above and the CTA below already go to the
   same page, and a third stop on the way there is noise for a keyboard user. */
.feature-body { display: flex; gap: var(--space-5); align-items: flex-start; }
.feature-body-text { min-width: 0; }
.feature-poster-link { flex: none; display: block; }
.feature-poster {
  width: 150px;
  height: auto;
  border-radius: 16px;
  box-shadow: var(--sh-out);
}
.feature-blurb { color: var(--muted); max-width: 34rem; margin: 0 0 var(--space-5); }
.feature-swarm { font-size: .85rem; color: var(--muted); margin-top: var(--space-3); }
.rail-head { font-size: .72rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--eyebrow); margin: 0 0 var(--space-3); }
.rail-head-feed { margin-top: var(--space-5); }
.rail-cache { height: 2.4rem; width: auto; float: right; margin-top: -0.5rem; }
.stat-cards { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.stat-card { background: var(--clay); border-radius: 16px; padding: var(--space-3) var(--space-4);
  box-shadow: var(--sh-out-sm); }
.stat-card .n { font-family: var(--font-display); font-weight: 800; font-size: 1.35rem;
  display: block; letter-spacing: -.01em; }
.stat-card .l { font-size: .72rem; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
.den-feed { list-style: none; margin: 0; padding: 0; font-size: .88rem; }
.den-feed li { padding: var(--space-2) 0; box-shadow: 0 1px 0 var(--shadow-dark); }
.den-feed li:last-child { box-shadow: none; }
.den-feed time { color: var(--muted); font-size: .75rem; margin-left: var(--space-2); }
.needs-seeds { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap;
  background: var(--clay); border-radius: 16px; padding: var(--space-3) var(--space-5);
  box-shadow: var(--sh-out-sm); margin-top: var(--space-6); }
.needs-seeds .tag { font-size: .7rem; font-weight: 800; letter-spacing: .08em;
  color: var(--eyebrow); text-transform: uppercase; }
.needs-seeds .pill { border-radius: 999px; padding: var(--space-1) var(--space-3);
  font-size: .85rem; text-decoration: none; box-shadow: var(--sh-out-sm); }
.needs-seeds .pill-cta { font-weight: 700; }
.stat-split { display: flex; gap: var(--space-2); flex-wrap: wrap; margin: var(--space-3) 0 0; }
.stat-split .pill { border-radius: 999px; padding: var(--space-1) var(--space-3);
  font-size: .8rem; text-decoration: none; color: inherit; box-shadow: var(--sh-out-sm); }
.stat-split .pill strong { color: var(--eyebrow); }
.stat-split .pill:hover { color: var(--eyebrow); }
@media (max-width: 56rem) { .split-hero { grid-template-columns: 1fr; } }
/* Same threshold the film poster uses. At 375px the shell leaves ~335px of
   content: a 150px poster beside the blurb would put a 220-character
   standfirst in a 215px gutter, about nine lines of five words. The poster
   leads instead and the text gets the full width. */
@media (max-width: 34rem) {
  .feature-body { flex-direction: column; gap: var(--space-4); }
  .feature-poster { width: 120px; }
}
.rail-head a { color: inherit; text-decoration: none; }
.rail-head a:hover { color: var(--eyebrow); }

/* ---------- Fast follows (2026-08-17): weekly top, hoard progress, userbar ---------- */
.weekly-top { margin: 0; padding-left: var(--space-5); font-size: .95rem; }
.weekly-top li { padding: var(--space-1) 0; }
.weekly-top li::marker { color: var(--honey); font-weight: 700; }
.weekly-top .meta { color: var(--muted); font-size: .8rem; margin-left: var(--space-2); }
.hoard-count { color: var(--muted); font-size: .8rem; margin: var(--space-3) 0 var(--space-1); }
.hoard-progress { height: 10px; border-radius: 999px; box-shadow: var(--sh-in-sm);
  overflow: hidden; max-width: var(--measure); }
.hoard-progress-fill { height: 100%; border-radius: 999px; background: var(--honey);
  min-width: 4px; }
.hoard-progress-fill[style="width: 0%"] { min-width: 0; }
.userbar { display: flex; gap: var(--space-4); align-items: center; flex-wrap: wrap;
  max-width: 68rem; margin: var(--space-3) auto 0; padding: var(--space-2) var(--space-5);
  background: var(--clay); border-radius: 999px; box-shadow: var(--sh-in-sm);
  font-size: .82rem; color: var(--muted); }
.userbar-name { font-weight: 700; color: var(--ink); }
.userbar-tier { font-size: .7rem; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--honey); }
.passkey-panel { max-width: var(--measure); }
.passkey-panel code { display: inline-block; padding: var(--space-1) var(--space-3);
  border-radius: 10px; box-shadow: var(--sh-in-sm); font-size: .88rem;
  overflow-wrap: anywhere; }
.passkey-panel .inline-form { display: inline; }
/* Queue alert. Only ever rendered when something is actually waiting, so it
   can afford to be loud — accent ink rather than the muted gray the rest of
   the bar uses. */
.userbar-queue a {
  color: var(--eyebrow);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: .2em;
}
.userbar-out { margin-left: auto; }
.userbar .inline-form { display: inline; }

/* A button that has to read as a link. button_to always emits a real <button>,
   so "Sign out", "Rotate passkey" and "resend the confirmation email" arrived
   as unstyled browser chrome — a gray beveled box sitting inside warm clay.
   Strip the native button surface and take the ink/underline of a link, while
   keeping a 44px tap target so it still meets the touch minimum the .ticket-btn
   rule holds to. */
.linklike {
  font: inherit;
  font-family: var(--font-body);
  color: var(--ink);
  background: none;
  border: none;
  padding: 0;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  text-decoration: underline;
  text-underline-offset: .2em;
  text-decoration-thickness: 1px;
  cursor: pointer;
}
.linklike:hover, .linklike:focus-visible { color: var(--eyebrow); }
/* In the userbar the sign-out control is secondary to the stats beside it. */
.userbar .linklike { color: var(--muted); font-size: .85rem; min-height: 0; }
.userbar .linklike:hover, .userbar .linklike:focus-visible { color: var(--ink); }

/* ---------- Film page take-home panel + extras ---------- */
/* Restoration credit. Quieter than the editorial but not hidden — it is an
   acknowledgment, and burying it would defeat the point. */
.restoration-credit {
  font-size: .82rem;
  line-height: 1.5;
  color: var(--muted);
  background: var(--clay);
  border-radius: 16px;
  box-shadow: var(--sh-in-sm);
  padding: .75rem 1.1rem;
  margin-top: var(--space-3);
}
.spec-line { color: var(--muted); font-size: .82rem; letter-spacing: .05em;
  text-transform: uppercase; margin-top: var(--space-2); }
.take-home-panel { margin-bottom: var(--space-4); }
/* Download essentials stay together beside the poster and stack on small screens. */
.download-card {
  display: flow-root;
  min-width: 0;
  padding: clamp(1rem, 3vw, 1.5rem);
  margin: var(--space-6) 0;
  border-radius: 24px;
  box-shadow: var(--sh-out);
  overflow-wrap: anywhere;
}
.download-card .section-head { margin-top: 0; }
.download-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr)); gap: var(--space-4); margin: var(--space-4) 0; }
.download-facts dt { color: var(--muted); font-size: .8rem; }
.download-facts dd { margin: .25rem 0 0; font-weight: 700; font-size: 1.05rem; }
.download-edition, .download-help, .download-sharing { font-size: .88rem; line-height: 1.6; }
.download-edition { margin: var(--space-4) 0; }
.download-availability { box-shadow: var(--sh-in-sm); border-radius: 16px; padding: var(--space-3) var(--space-4); }
.download-availability p { margin: 0; font-size: .85rem; }
.download-availability p + p { margin-top: .35rem; color: var(--muted); }
.film .download-actions { margin: var(--space-5) 0 var(--space-3); }
.download-actions .ticket-btn { flex: 1 1 12rem; text-align: center; white-space: normal; }
.download-help, .download-sharing { color: var(--muted); }
.download-magnet { font-size: .85rem; margin-top: var(--space-4); }
.download-magnet summary { cursor: pointer; padding: .5rem 0; }
.download-magnet label { display: block; margin: .5rem 0; }
.download-magnet input { width: 100%; min-width: 0; box-sizing: border-box; }
.download-sharing { margin: var(--space-4) 0 0; }
/* Long source filenames in the report must fit narrow screens too. */
.film code { overflow-wrap: anywhere; }
@media (max-width: 48rem) { .download-card { clear: both; } }
.film-extras { margin-top: var(--space-8); }
.film-extras > * { margin-top: var(--space-4); }

/* ---------- Admin desk ---------- */
.admin-queues { list-style: none; padding: 0; margin: 0 0 var(--space-3); display: grid; gap: var(--space-3); }
.admin-queues li {
  background: var(--clay);
  border-radius: 16px;
  box-shadow: var(--sh-out-sm);
  padding: 1rem 1.3rem;
}
.admin-queues a { text-decoration: none; color: var(--ink); display: block; }
.admin-queues strong { font-size: 1.5rem; margin-right: .4em; }
/* A queue with something in it is the only thing on this page that should
   pull the eye — everything else is reference. */
.admin-queue-hot { box-shadow: var(--sh-out); }
.admin-queue-hot strong { color: var(--accent); }
.admin-links { margin: 0; padding-left: 1.1rem; }
.admin-links li { margin-bottom: var(--space-2); }
.admin-code {
  background: var(--clay);
  border-radius: 16px;
  box-shadow: var(--sh-in-sm);
  padding: 1rem 1.2rem;
  font-size: .8rem;
  overflow-x: auto;
  white-space: pre;
}

/* Left, with the h1 it belongs to — not `margin: 0 auto`, which centered the
   block and started /films' standfirst 173px right of its own heading while
   every other line on the page began at the same left edge. Matches
   .section-sub, which is the same role inside shared/_page_banner. */
.browse-blurb { max-width: var(--measure); margin: 0 0 var(--space-4); color: var(--muted); }

.year-nav { margin-top: var(--space-4); color: var(--muted); font-size: .85rem; }
.year-nav a { color: var(--ink); }

.related-films { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-2); }
.related-films li { display: flex; gap: .6rem; align-items: baseline; flex-wrap: wrap; }
.related-films .meta { font-size: .75rem; text-transform: uppercase; letter-spacing: .05em; }

/* ---------- Cache index rows ---------- */
.cache-row { padding-top: var(--space-3); padding-bottom: var(--space-3); }
.cache-row .cache-row-title { margin-bottom: var(--space-2); }
/* No opacity on the swarm figure. It was .55, and .8 on a has-print row, which
   took --muted to #887963 — 3.12:1 on the tinted row (axe, 2026-09-01), and
   below the floor its own token comment sets. It also had the emphasis
   backwards: swarm health is what a tracker is for, and it was the one column
   dimmed below the year and the size. It is --muted like its neighbors now.
   The honey wash is 5%, not 7%: at 7% it put plain --muted at 4.50:1, close
   enough to the line that Chrome measured the composited pixel at 4.49. The
   two tints are two hex values apart and the margin is real. */
.cache-row.has-print { background: color-mix(in srgb, var(--honey) 5%, transparent);
  border-radius: 12px; }

/* ---------- Error pages ---------- */
.error-page { max-width: 34rem; margin: var(--space-6) auto var(--space-8); text-align: center; }
.error-art {
  width: min(20rem, 80%);
  height: auto;
  margin: 0 auto var(--space-5);
  border-radius: 32px;
  box-shadow: var(--sh-out);
}
.error-page h1 { font-size: 1.8rem; margin-bottom: var(--space-3); }
.error-lede { color: var(--muted); margin-bottom: var(--space-5); }
.error-page .dig-form { margin-bottom: var(--space-4); }
.error-ways { color: var(--muted); font-size: .9rem; }
.error-ways a { color: var(--ink); }

/* ---------- Footer ---------- */
footer { background: var(--clay); margin-top: var(--space-8); }
.footer-inner {
  max-width: 68rem;
  margin: 0 auto;
  padding: 2rem 1.25rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  color: var(--muted);
}
footer .tagline { font-family: var(--font-display); font-weight: 700; color: var(--ink); }
footer nav[aria-label="Footer"] {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem 1rem;
  font-size: .85rem;
}
footer nav[aria-label="Footer"] a { text-decoration: none; color: var(--muted); }
footer nav[aria-label="Footer"] a:hover,
footer nav[aria-label="Footer"] a:focus-visible { color: var(--ink); text-decoration: underline; }

/* ---------- Responsive ---------- */
@media (max-width: 40rem) {
  h1 { font-size: 1.7rem; }
  .hero h1 { font-size: 2rem; }
  .page-banner h1 { font-size: 2rem; }
  .section-head h2 { font-size: 1.5rem; }
  .now-showing, .collections-grid li, .lobby-card, .top-seeders { border-radius: 24px; }
}

/* The Cache (/torrents): a real table, pressed into the same clay as the
   cache list. Rows are the torrents; the swarm columns carry the tracker's
   pulse, so a living swarm is the accented number and a quiet one is muted.
   Titles wrap to fit the available width; compact screens use stacked rows. */
.torrent-table-wrap {
  margin: 0 0 1.2rem;
  padding: .6rem;
  border-radius: 32px;
  box-shadow: var(--sh-in);
  overflow-x: auto;
}
.torrent-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: .95rem;
}
.torrent-table th, .torrent-table td {
  padding: .7rem .8rem;
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
}
.torrent-table th {
  font-family: var(--font-display);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}
.torrent-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.torrent-table tbody tr { border-radius: 16px; }
.torrent-table tbody tr:hover td { background: color-mix(in srgb, var(--honey) 10%, transparent); }
.torrent-table tbody td:first-child { border-radius: 16px 0 0 16px; }
.torrent-table tbody td:last-child { border-radius: 0 16px 16px 0; }
/* Override the general cell nowrap rule so long episode titles can shrink
   and wrap without pushing the other columns outside the screen. */
.torrent-table .torrent-title { white-space: normal; min-width: 0; max-width: 26rem; overflow-wrap: anywhere; }
.torrent-title a { font-family: var(--font-display); font-weight: 700; text-decoration: none; }
.torrent-title a:hover, .torrent-title a:focus-visible { text-decoration: underline; }
.torrent-year, .torrent-file { color: var(--muted); font-size: .85rem; margin-left: .4rem; }
.torrent-shelf { color: var(--muted); text-decoration: none; }
.torrent-shelf:hover, .torrent-shelf:focus-visible { color: var(--ink); }
.torrent-table tr.is-live td:nth-child(4) { color: var(--eyebrow); font-weight: 700; }
.torrent-table tr.is-quiet td:nth-child(4), .torrent-table tr.is-quiet td:nth-child(5) { color: var(--muted); }
/* The grab, in the table and on a series' episode row. 44px square: it was
   .3rem/.6rem of padding around a glyph — about 26x22 — while the nav links
   two elements away already carried min-height 44px. */
.torrent-dl, .episode-dl {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  border-radius: 12px;
  box-shadow: var(--sh-out-sm);
  text-decoration: none;
  color: var(--muted);
  transition: box-shadow .15s ease, color .15s ease;
}
.torrent-dl:hover, .torrent-dl:focus-visible,
.episode-dl:hover, .episode-dl:focus-visible {
  box-shadow: var(--sh-in-sm);
  color: var(--eyebrow);
}
.dl-icon { display: block; }
.torrent-note { max-width: var(--measure); color: var(--muted); font-size: .9rem; margin: 0 auto 2rem; }

/* Column labels: only ever visible in the stacked mobile layout below, where
   the header row is gone and a bare "2" names nothing. */
.cell-label { display: none; color: var(--muted); }

/* Compact screens stack the primary title, size and seeds beside the download
   button. Secondary columns remain on the work page. Switch before the full
   table's columns would crowd the title or require horizontal scrolling. */
@media (max-width: 64rem) {
  .torrent-table, .torrent-table tbody, .torrent-table tr, .torrent-table td { display: block; }
  /* The header row describes columns that no longer exist visually; the
     .cell-label spans carry its content down into the rows instead. */
  .torrent-table thead { display: none; }
  .torrent-table td:nth-child(2),   /* Shelf */
  .torrent-table td:nth-child(5),   /* Leeches */
  .torrent-table td:nth-child(6),   /* Grabs */
  .torrent-table td:nth-child(7) {  /* Added */
    display: none;
  }
  .torrent-table-wrap { padding: .5rem; overflow-x: visible; }
  .torrent-table tr {
    position: relative;
    padding: .8rem 3.6rem .8rem .8rem;  /* right gutter reserves the grab */
    border-radius: 16px;
  }
  .torrent-table tr + tr { margin-top: .3rem; }
  .torrent-table td { padding: 0; white-space: normal; text-align: left; }
  .torrent-table .torrent-title { max-width: none; }
  /* Size and seeds read as one meta line under the title. Addressed by
     position, not by .num: `.torrent-table td.num` ties on specificity with
     the hide rules above and, coming later, would win — putting Leeches and
     Grabs back on the page as two stray zeroes. */
  .torrent-table td:nth-child(3),
  .torrent-table td:nth-child(4) { display: inline; font-size: .85rem; color: var(--muted); }
  .torrent-table td:nth-child(4)::before { content: " · "; }
  .cell-label { display: inline; }
  /* Centered in the gutter the row padding reserved, so it never overlaps the
     title however many lines that wraps to. */
  .torrent-table td:last-child {
    position: absolute;
    right: .6rem;
    top: 50%;
    transform: translateY(-50%);
  }
  .torrent-table tbody td:first-child, .torrent-table tbody td:last-child { border-radius: 0; }
  .torrent-table tbody tr:hover td { background: none; }
  .torrent-table tr.is-live { box-shadow: var(--sh-out-sm); }
}

/* A series page's episode run, and an episode's place in it. */
.series-crumb { color: var(--muted); font-size: .95rem; margin: -.4rem 0 1rem; }
/* Capped so the row's grab lands near the row it belongs to. Full-width, the
   titles ended around 300px and the buttons sat out at 1230px — a column of
   controls floating free of the list they act on. */
.episode-list { list-style: none; padding: 0; margin: 0 0 2rem; counter-reset: none; max-width: 46rem; }
.episode-list li {
  display: flex; flex-wrap: wrap; align-items: center; gap: .6rem;
  padding: .6rem .8rem; border-radius: 16px;
}
/* The grab sits at the end of the row, hard right, so 55 of them line up. */
.episode-list .episode-dl { margin-left: auto; flex: none; }
.episode-list li:hover { box-shadow: var(--sh-out-sm); }
/* Was opacity: .7, which dimmed the whole row — episode number, title link and
   all — to 2.74:1 (house rule: opacity never dims text). Nothing is lost by
   dropping it, because the row already *says* "not in the stash yet" in words;
   the fade was decoration repeating what the text stated. Latent rather than
   live when found on 2026-09-01: every published episode currently has a
   print, so no page renders this class yet — the first shelf with a missing
   print would have shipped it. */
.episode-list .episode-no { font-family: var(--font-display); font-weight: 700; color: var(--muted); min-width: 2ch; text-align: right; font-variant-numeric: tabular-nums; }
.episode-list a { font-family: var(--font-display); font-weight: 700; text-decoration: none; }
.episode-list a:hover, .episode-list a:focus-visible { text-decoration: underline; }
.episode-list .meta { font-size: .85rem; color: var(--muted); }
/* A withheld episode leaves a gap in the numbering; the gap says so itself. */
.episode-list li.episode-gap { justify-content: center; font-size: .85rem; color: var(--muted);
  font-style: italic; box-shadow: var(--sh-in-sm); background: none; }
.episode-list li.episode-gap:hover { box-shadow: var(--sh-in-sm); }

/* Account recovery and member profiles share the account form clay surfaces. */
.account-message > p { color: var(--muted); margin-bottom: 1.25rem; }
.account-message .login-submit { text-align: center; justify-content: center; }
.account-message > .account-field-hint { margin: 1.25rem 0 0; }
.account-return { margin: 1.25rem 0 0; text-align: center; font-size: .9rem; }
.profile-page { max-width: 60rem; margin: 0 auto; overflow-wrap: anywhere; }
.profile-page .page-banner { margin-bottom: 1.5rem; }
.profile-summary { display: flex; align-items: center; gap: 1rem; margin-bottom: 2rem; }
.profile-summary img { flex-shrink: 0; object-fit: contain; }
.profile-summary p { margin: 0; }
.profile-seeded { font-size: clamp(1.5rem, 5vw, 2rem); font-weight: 700; }
.profile-seeded span { font-size: 1rem; font-weight: 400; color: var(--muted); }
.profile-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem; }
.profile-card { min-width: 0; padding: 2rem; border-radius: 28px; box-shadow: var(--sh-out); }
.profile-card h2 { font-size: 1.5rem; margin-bottom: 1.25rem; letter-spacing: -.03em; }
.profile-card p { color: var(--muted); }
.profile-card .login-eyebrow { color: var(--eyebrow); }
.profile-card form { margin: 1rem 0; }
.profile-card button { white-space: normal; max-width: 100%; }
.profile-details { margin: 0 0 1.5rem; }
.profile-details dt { color: var(--muted); font-size: .8rem; margin-bottom: .25rem; }
.profile-details dd { margin: 0 0 1rem; font-weight: 600; }
.profile-text-link { display: inline-flex; align-items: center; min-height: 44px; text-underline-offset: .2em; }
.profile-passkey { margin-top: 1rem; padding: .3rem 1rem; border-radius: 16px; box-shadow: var(--sh-in); }
.profile-passkey summary { cursor: pointer; padding: .8rem 0; font-weight: 600; }
.profile-passkey code { display: block; padding: .5rem 0 1rem; overflow-wrap: anywhere; font-size: .85rem; }
.profile-passkey p { margin: .5rem 0 1rem; font-size: .9rem; }
.profile-notice { padding: 1.25rem 1.5rem; margin-bottom: 2rem; border-radius: 16px; box-shadow: var(--sh-in); }
.profile-stash { margin-top: 3rem; }
.profile-empty { padding: 2rem; border-radius: 28px; box-shadow: var(--sh-in); text-align: center; }
.profile-empty h3 { font-size: 1.25rem; margin-bottom: .75rem; }
.profile-empty p, .profile-public-note { color: var(--muted); }
@media (max-width: 44rem) {
  .profile-grid { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
  .profile-card, .profile-empty { padding: 1.5rem 1.25rem; }
}

/* Private editorial worklist. */
.admin-review { max-width: 58rem; margin: 0 auto; }
.admin-nav, .admin-review-links { display: flex; flex-wrap: wrap; gap: .75rem 1.25rem; margin: 1rem 0 1.5rem; }
.admin-nav [aria-current="page"] { font-weight: 700; text-decoration-thickness: .15em; }
.admin-review section { margin-top: 2.5rem; }
.admin-review-card { padding: 1.25rem; margin: 1rem 0; border-radius: 12px; background: var(--clay); box-shadow: var(--sh-out-sm); overflow-wrap: anywhere; }
.admin-review-card h3 { margin: .25rem 0 1rem; }
.admin-review-card h4 { margin: 0 0 .5rem; }
.admin-review-count { font-size: .8em; font-weight: normal; }
.admin-review-rationale > :first-child { margin-top: 0; }
.admin-review-links { margin-bottom: 0; font-size: .875rem; }
