/* ============================================================
   PARASOCIALIZE — the video store
   Warm room, bright covers. Every story gets a poster, because a
   wall of covers is what a video store IS and a wall of index
   cards is what a library is. This is the store.
   ============================================================ */

:root{
  /* the room: near-black, barely warm */
  --bg:#130d0a;
  --bg2:#1d1512;
  --bg3:#2a1f1a;
  --bg4:#3a2b23;

  /* hot and electric */
  --hot:#ff5a1f;
  --hot2:#ffa64d;
  /* --warm / --warm-hot are the names older page templates already reference.
     They must exist or every var(--warm) silently falls back to nothing, which
     renders solid buttons invisible. */
  --warm:var(--hot);
  --warm-hot:var(--hot2);
  --neon:#ff2d6f;
  --mint:#00e8c0;
  --sky:#2d8bff;
  --violet:#a04dff;
  --acid:#c8ff2e;

  /* the paper */
  --paper:#fff6ea;
  --dim:#cbb59d;
  --dimmer:#9a8672;
  --line:rgba(255,246,234,.13);
  --line2:rgba(255,246,234,.06);

  --serif:"Fraunces",Georgia,"Times New Roman",serif;
  --sans:"Helvetica Neue",Helvetica,Arial,sans-serif;
  --body:Georgia,"Iowan Old Style","Palatino Linotype",serif;
  --label:"IBM Plex Mono",ui-monospace,"Cascadia Mono",Consolas,monospace;

  --r:14px;
  --w:1240px;
}

*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html{scroll-behavior:smooth}
body{
  background:var(--bg);color:var(--paper);
  font-family:var(--body);font-size:17px;line-height:1.6;
  overflow-x:hidden;-webkit-font-smoothing:antialiased;
  background-image:
    radial-gradient(70% 45% at 50% -8%,rgba(255,90,31,.2),transparent 60%),
    radial-gradient(40% 40% at 8% 60%,rgba(255,79,123,.07),transparent 65%);
  background-attachment:fixed;
}
.mono,.kicker,.fineprint{font-family:var(--label)}
.serif,.wordmark{font-family:var(--serif)}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
::selection{background:var(--warm);color:#1b1410}

.grain{position:fixed;inset:0;z-index:50;pointer-events:none;opacity:.4;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.2'/%3E%3C/svg%3E");
  mix-blend-mode:overlay}
.scanlines{position:fixed;inset:0;z-index:50;pointer-events:none;opacity:.4;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.2'/%3E%3C/svg%3E");
  mix-blend-mode:overlay}

.wrap{max-width:var(--w);margin:0 auto;padding-inline:24px}
.narrow{max-width:780px}

/* ---------- masthead ---------- */
.topbar{
  position:sticky;top:0;z-index:40;
  background:rgba(27,20,16,.94);backdrop-filter:blur(14px);
  border-bottom:1px solid rgba(255,90,31,.22);
}
/* min-height, NOT height. Measured at 1180px and 1100px this bar was rendering
   a two-line nav (72px) inside a 64px box, so the second line sat on top of the
   content instead of pushing it down - the nav was not clipped and it was not
   scrollable, it was simply overlapping, which is worse than either. A fixed
   height can only express "one line or wrong"; min-height lets the bar grow if a
   future item makes the nav wrap, so the failure mode is a taller header rather
   than an overlap. The breakpoint below is what actually keeps it to one line -
   this is the safety net, not the fix. */
.topbar-in{max-width:var(--w);margin:0 auto;padding:0 24px;min-height:64px;
  display:flex;align-items:center;gap:22px}
.wordmark{font-weight:700;font-size:1.15rem;letter-spacing:-.01em;display:inline-flex;align-items:center;gap:9px;white-space:nowrap}
.wordmark b{color:var(--warm)}
.logo-img{width:24px;height:24px;flex:none;transition:transform .45s cubic-bezier(.34,1.5,.64,1)}
.wordmark:hover .logo-img{transform:rotate(-10deg) scale(1.12)}

/* One line, or the menu. An earlier version let this wrap, which fixed a
   clipped nav by creating an overflowing one; and `overflow-x:auto` with a
   hidden scrollbar, which hid items with no affordance saying so - "elsewher"
   rendering as a truncated word is a broken nav, not a smaller one. Wrapping is
   still allowed as a last resort, but `tools/probe_nav.py` fails the build if
   the nav ever takes a second line at any width where it is meant to be the
   desktop row, so this cannot come back quietly. */
.nav{display:flex;align-items:center;gap:16px;row-gap:4px;margin-left:auto;justify-content:flex-end;
  flex-wrap:wrap;overflow:visible}
.nav::-webkit-scrollbar{display:none}
.nav a{
  font-family:var(--label);font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dim);padding:6px 0;position:relative;white-space:nowrap;transition:color .18s;
}
.nav a::after{content:"";position:absolute;left:0;bottom:0;height:2px;width:100%;background:var(--warm);transform:scaleX(0);transform-origin:left;transition:transform .2s}
.nav a:hover,.nav a[aria-current="true"]{color:var(--paper)}
.nav a:hover::after,.nav a[aria-current="true"]::after{transform:scaleX(1)}

/* The nav is grouped into Read / Look up / Elsewhere, matching the two doors the
   masthead offers. These labels are what make the grouping mean anything: an
   unlabelled gap between two links is a divider, and a labelled one is a
   category. Dimmed hard so they read as furniture and not as destinations -
   a label the same weight as a link would be a fourteenth thing to click. */
.nav-lab{
  font-family:var(--label);font-size:.55rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--dimmer);white-space:nowrap;padding:0 2px;flex:none;
}
/* A hairline before every label but the first, so the three groups are visibly
   three groups. Using a border on the label rather than a separate element
   means nothing extra to read in the accessibility tree. */
.nav a+.nav-lab{margin-left:6px;padding-left:14px;border-left:1px solid var(--line2)}

/* ---- the way out of a story, into the encyclopedia --------------------
   A story page used to end at its sources and "More from <aisle>" - other
   stories, all of which are journalism. The 193 encyclopedia entries, where the
   depth is, were unreachable from any of them. These are the doorways, computed
   by tools/crosslink.py and rendered on the standalone radar page.
   Cards, not a list: each one shows the entry's title and the first line of its
   summary, so the reader can see whether it is the thing they want. */
.xlinks{display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}
.xl{
  display:block;text-decoration:none;background:var(--bg2);border:1px solid var(--line);
  border-left:3px solid var(--mint);border-radius:8px;padding:11px 14px;transition:.18s;
}
.xl:hover{border-color:var(--mint);transform:translateY(-2px)}
.xl b{display:block;font-family:var(--serif);font-size:1rem;color:var(--paper);margin-bottom:3px}
.xl span{display:block;font-size:.8rem;color:var(--dim);line-height:1.45}
/* A withdrawn claim leaves the slug retired but the entry standing, so a reader
   following one of these may land on prose that has since been corrected. The
   note under the block says so rather than leaving them to notice. */
.xl-note{font-size:.78rem;color:var(--dimmer);margin-top:10px;line-height:1.5}
/* And on the entry side, a story pointing here may itself have been corrected
   after this entry was written. Saying so is the whole point of a site that
   withdraws claims. */
.xl-corrected{display:block;margin-top:5px;color:var(--hot);font-family:var(--label);
  font-size:.6rem;letter-spacing:.14em;text-transform:uppercase}
/* the name is never uppercased. Every other nav item is set in caps by the
   rule above, which silently turned iYi into IYI - a name is not a label, and
   the lowercase i on both sides is the whole mark. */
.nav a.nav-iyi{
  text-transform:none;letter-spacing:.01em;font-size:.82rem;
  color:var(--hot);font-weight:600;
}
.nav a.nav-iyi::after{background:var(--neon)}
.nav .cta{background:var(--warm);color:#1b1410;border-radius:99px;padding:9px 15px;font-weight:500}
.nav .cta::after{display:none}
.nav .cta:hover{background:var(--warm-hot);color:#1b1410}
.onair{display:flex;align-items:center;gap:7px;font-family:var(--label);font-size:.6rem;letter-spacing:.14em;color:var(--dimmer);white-space:nowrap}
.dot{width:7px;height:7px;border-radius:50%;background:var(--mint);box-shadow:0 0 9px var(--mint);flex:none}
.dot.stale{background:var(--neon);box-shadow:0 0 9px var(--neon)}
.menu-btn{display:none;background:none;border:0;cursor:pointer;padding:14px;margin-left:auto;position:relative;z-index:70}
.menu-btn span{display:block;width:22px;height:2px;background:var(--paper);margin:5px 0;transition:.3s}

/* ---------- buttons ---------- */
.btn{display:inline-block;padding:12px 24px;border-radius:99px;
  font-family:var(--label);font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;
  transition:.2s;cursor:pointer;border:1px solid transparent;line-height:1.1}
.btn-solid{background:var(--warm);color:#1b1410;font-weight:500}
.btn-solid:hover{background:var(--warm-hot);transform:translateY(-2px);box-shadow:0 10px 26px rgba(255,90,31,.3)}
.btn-ghost{border-color:rgba(255,90,31,.38);color:var(--paper)}
.btn-ghost:hover{border-color:var(--warm);color:var(--warm);background:rgba(255,90,31,.08)}
.btn-dark{background:#1b1410;color:var(--warm)}
.btn-dark:hover{background:#0f0a07}

/* ---------- the masthead: the whole intro, nothing more ---------- */
/* ---- filed under: a story page's two real doors -------------------------
   Was three taxonomies in three identical pills: a shouted section sign that
   linked nowhere while its own page sat unused, an editorial register note in
   the same shape as a category, and the law - the only thing that looked like
   a link - pointing at "#laws", an anchor that does not exist. Identical
   styling told the reader they were looking at the same kind of thing, which is
   why the row read as incoherent rather than merely wrong.

   Now the shape carries the meaning: a labelled row, each item stating what it
   is ("Filed under", "Which law it tests") before saying what it is, and each
   one carrying the blurb that explains the category in a sentence. The law
   links to #law-N, which build_cards.py has always emitted as id="law-N". */
.fu{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;
  margin:0 0 26px;padding:0;list-style:none}
.fu-filed,.fu-law{display:grid;gap:5px;padding:13px 15px;border-radius:10px;
  background:var(--bg2);border:1px solid var(--line);text-decoration:none;
  border-left:3px solid var(--c,var(--hot));transition:border-color .15s,background .15s}
.fu-filed:hover,.fu-law:hover{background:var(--bg3,#241c17);border-color:var(--line2)}
.fu-filed{border-left-color:var(--hot)}
.fu-law{border-left-color:var(--mint)}
.fu-k{font-family:var(--label);font-size:.5rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dimmer);line-height:1}
.fu b{font-family:var(--serif);font-size:1.02rem;font-weight:700;color:var(--paper);
  line-height:1.2}
.fu-blurb{font-size:.82rem;color:var(--dim);line-height:1.4}
.fu-od{grid-column:1/-1;font-family:var(--label);font-size:.6rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--hot);padding:2px 0}
/* The kicker moved here from the pill row. It is a note about register
   ("The big one", "Evergreen"), not a category, and sitting under the headline
   it reads as a note instead of competing with two real destinations. */
.regnote{font-family:var(--label);font-size:.62rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--hot);margin:-14px 0 10px}
@media (max-width:620px){
  .fu{grid-template-columns:1fr}
}

.masthead{padding:62px 0 8px;position:relative;overflow:hidden}

/* ---- the thesis, as a pair rather than a paragraph --------------------
   This was three prose blocks - 144 words, 778 characters - under the h1, and
   it read as a wall rather than an opening. The whole argument is a contrast
   between a date and an age, so it is now set as one: two figures, side by
   side, each with one line under it. Twenty-two words instead of a hundred and
   forty-four, and the shape of the claim carries the claim. */
/* The two figures are links to the entries they are taken from, so a number on
   the front page has somewhere to go rather than being decoration. `.masthead a`
   would otherwise colour both hot - the specificity has to beat it, or the
   contrast the block is built on disappears. */
/* The two figures are 1956 and -70,000 and a reader arriving cold has no way
   to know they belong together, or why either is on a site about one-sided
   attachment. Asking each door to carry its own justification made one of them
   twice the length of the other - 4 lines against 8, with 120px of dead space
   under the short one, because the two are forced into equal columns.

   So the shared reason is stated once, below the pair, and each door is left
   to be a plain fact. It spans both columns and sits on the block's own
   baseline rule, so it reads as a caption on the pair rather than a third
   thing competing with them. */
@media (max-width:760px){
}
.masthead h1{
  font-family:var(--serif);font-size:clamp(3rem,10vw,7.5rem);font-weight:900;
  letter-spacing:-.05em;line-height:.86;margin:0 0 20px;
  background:linear-gradient(96deg,var(--hot) 0%,var(--neon) 42%,var(--violet) 78%,var(--mint) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  -webkit-text-fill-color:transparent;
}
/* The standfirst is the sentence that says what the site IS, so it gets a real
   measure and a step up in size. At 62ch and 1.1rem it sat at the same visual
   weight as every other paragraph on the page and read as a caption on the
   wordmark rather than as the argument. */
.masthead .line{max-width:54ch;font-size:1.2rem;line-height:1.55;color:var(--dim)}
.masthead .line b,.masthead .line strong{color:var(--paper);font-weight:600}
.masthead a{color:var(--hot)}

/* the mascot in the masthead: a flex item, not an image, so it scales with
   the wordmark and never needs a second asset */
/* ---------- the iYi logotype ----------
   The name is the drawing: i-Y-i. Two lowercase i for the two selves, a Y for
   the fork where they diverge, and the dots on the i's do the work of the
   catchlights. It is asymmetric for the same reason the face is - the left i is
   the side that is present, the right i is smaller and dimmer - so the mark and
   the mascot carry one idea in two registers.

   It replaced a mascot in the nav for a measured reason rather than a taste one.
   At 30px the mascot collapses into one smudge: the lobes merge, the pupils
   merge with them, and the asymmetry that is the whole concept disappears. Type
   has no such floor. So the nav carries the name, and the mascot is only used
   where it is large enough to be a character. */
/* the mascot as a figure, at sizes where it is a character rather than a
   texture. overflow:visible matters - the bloom is a radial gradient larger
   than the lobes, and without it the glow clips to the SVG box. The 30px nav
   stamp is deliberately NOT this: it measures as an unreadable smudge, which is
   why the nav carries the logotype instead. */
.mascot{display:block;flex:none;overflow:visible}

.iyiw{
  display:inline-flex;align-items:baseline;line-height:.82;
  font-family:var(--serif);font-weight:900;letter-spacing:-.02em;
  font-size:1.02rem;
}
.iyiw-l{color:var(--hot)}
.iyiw-y{
  color:var(--neon);
  /* the conduit: the fork is the point of the letter, so let it carry the
     gradient the wordmark uses elsewhere and sit slightly proud of the i's */
  background:linear-gradient(180deg,var(--hot) 0%,var(--neon) 55%,var(--violet) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  padding:0 .04em;
}
.iyiw-r{
  /* the second side. Scale carries most of this, not opacity: at .5 the hot
     orange turned muddy brown against the dark ground and read as a rendering
     fault rather than as the dimmer half. Staying in the same hue at .72 keeps
     it legibly the same letter, just less of it - which is the whole idea. */
  color:var(--hot);opacity:.72;
  transform:scale(.82);transform-origin:50% 62%;
}

.iyiw-hero{font-size:clamp(4.2rem,17vw,10.5rem);display:flex;justify-content:center}
.iyiw-hero .iyiw-r{opacity:.7;transform:scale(.8)}
/* ---- the masthead lockup: copy column, clerk column -------------------
The mark used to be `display:flex;justify-content:center` in a full-width band,
which `probe_front.py` measured as a 1192px box containing 150px of drawing:
1042px of nothing either side of two disembodied eyes, sitting between the doors
and the top 8 with no copy attached. The gate was green because nothing it
checks is about a mark having a job.

So the mascot is a column now, not a stamp: it shares a row with the line and
the thesis, carries its own caption, and breaks the top edge of its card so it
is layered into the composition rather than plopped on it. The doors are a full
row of their own underneath, which is what closes the masthead - with the doors
inside the left column the clerk card ran a hundred pixels past them and the
empty space just moved to the bottom left. */
.clerk{display:flex;flex-direction:column;position:relative;
  border:1px solid var(--line2);border-radius:14px;
  background:linear-gradient(180deg,var(--bg3),var(--bg2));
  padding:6px 18px 14px;text-align:left}
/* The mascot was 168px of eyes in a 330px card, breaking the top edge by 52px
   behind a 30px orange glow - more than half the card's width, and the second
   loudest thing on the page after the wordmark. It is a caption-bearing detail
   on this page, not a second headline, so it is 116px now, overlapping by 28,
   and the glow is pulled back to something that reads as depth rather than as
   light.

   The negative bottom margin is the other half: iYi's rig draws two eyes inside
   a taller box, so a face sized to its element leaves roughly 50px of nothing
   between the drawing and the first line of copy - which read as a gap in the
   card rather than as air around a picture. */
.clerk-face{display:flex;justify-content:center;margin:-28px 0 -20px}
.clerk-face .mascot-hero{filter:drop-shadow(0 8px 16px rgba(255,90,31,.20))}
.clerk-kick{font-family:var(--label);font-size:.56rem;letter-spacing:.22em;
  text-transform:uppercase;color:var(--warm);margin:8px 0 8px}
.clerk-line{font-size:.95rem;line-height:1.5;color:var(--dim);margin:0 0 12px}
.clerk-line b{color:var(--paper);font-weight:600}
.clerk-more{font-family:var(--label);font-size:.56rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--hot)}
.clerk-more:hover{color:var(--paper)}
/* The three masthead modules - read, research, and the clerk - in one row.
   `minmax(0,1.35fr)` on the clerk lets the copy column take what it needs and
   the card take the rest, so the two doors keep equal width whatever the
   clerk's caption does. These three were previously split across two grid
   columns with the 1956/-70,000 pair between them, so the doors a reader was
   just told about were not adjacent to the thing that introduced them. */
.masthead-row{display:grid;grid-template-columns:1fr 1fr minmax(0,1.35fr);
  gap:16px;margin-top:26px;align-items:stretch}
.masthead-row .fdoor{padding:18px 20px;border-radius:var(--r);
  border-left-width:4px;flex-direction:column;align-items:flex-start;
  justify-content:center;gap:2px}
.masthead-row .fdoor-body strong{font-size:1.24rem;letter-spacing:-.015em}
.masthead-row .fdoor-body span{font-size:.86rem;line-height:1.45}
.masthead-row .clerk{margin:0}
/* ---- <code>: the author's machine keys, in the site's own label face -------
The corpus marks classification values in backticks - `persona/idol`,
`simulated`, `split_from` - and 468 of them, 412 on /taxonomy/, were reaching
the page as literal backticks. `--label` is IBM Plex Mono, which is already the
face this site uses whenever a machine is speaking, so a key looks like a key
rather than arriving in the browser's default monospace.

`overflow-wrap:break-word` rather than `nowrap`: a key like
`character/fictional-protagonist` is 30 characters and the taxonomy sub-category
cards are narrow, so a rule that refuses to break is a rule that overflows. The
gate for that is verify_narrow.py, not this comment. */
code{font-family:var(--label);font-size:.88em;letter-spacing:0;
  color:var(--warm);background:rgba(255,90,31,.09);
  border:1px solid rgba(255,90,31,.18);border-radius:3px;
  padding:.06em .32em;overflow-wrap:break-word;white-space:normal}
@media (max-width:900px){
  /* This was a two-column grid: a 104px mascot in column one spanning three
     rows, the copy in column two. On a 390px phone that leaves the copy about
     200px, so "I keep the record. Every claim here carries its source, and the
     ones nobody has opened say so. I do not remember you, and nothing here
     pretends to." wrapped to seven lines beside two eyes - and a card with a
     104px picture in it is not a caption, it is a second hero on a phone.

     Stacked instead: the mascot sits centred above the copy, which then gets
     the full width and reads in four lines. Same direction as the desktop
     column, so it stops being a different layout at a smaller size. */
  .clerk{display:flex;flex-direction:column;align-items:center;
    text-align:center;padding:14px 20px 16px}
  .clerk-face{margin:-22px 0 -16px}
  .clerk-face .mascot-hero{width:92px;height:92px}
  .clerk-kick{margin:4px 0 7px}
  .clerk-line{margin:0 0 10px}
  .clerk-more{margin-top:0}
}
/* The wordmark is 7.5rem at desktop and the clamp bottoms out at 3rem, which at
   390px wraps "Parasocialize." onto three lines and leaves the period alone on
   the last one - measured, not guessed: the h1 box was 107px tall for a 48px
   font at .86 line-height, i.e. 2.6 lines. 10.5vw keeps it on one at 320px. */
@media (max-width:900px){
  .masthead h1{font-size:clamp(2.2rem,10.5vw,4.6rem)}
}

.masthead-mark{margin:26px 0 6px;display:flex;justify-content:center}

/* the wordmark strip: iYi, then the publication name as a quiet subtitle */
.wordmark{display:inline-flex;align-items:center;gap:9px;text-decoration:none}
.wordmark b{
  color:var(--paper);font-weight:700;letter-spacing:.04em;
  font-family:var(--label);font-size:.62rem;text-transform:uppercase;
  padding-bottom:1px;
}

/* Iyi in a section head: the section's own expression, at a size that reads */
/* .sec-head is a two-column row: a text block and the mascot. Six pages put
   three block elements straight into it - kicker, h1, standfirst - and flex
   then laid them out side by side in a row. On /credits/ that put three pieces
   of prose shoulder to shoulder and pushed the document 33px past a 320px
   viewport, where body's overflow-x:hidden clipped it.
   So: stack by default, and go two-column only when there is actually a text
   block and a mascot to sit beside. A browser without :has() gets the stack,
   which is the sensible reading of those three elements anyway. */
.sec-head{display:block}
.sec-head:has(.sec-head-txt){display:flex;align-items:flex-start;justify-content:space-between;gap:26px}
.sec-head-txt{min-width:0;flex:1}
.sec-head-iyi{flex:none;opacity:.9;margin-top:2px}
@media (max-width:640px){
  .sec-head{gap:14px}
  .sec-head-iyi svg{width:62px;height:62px}
}


/* ---------- the hub: ten tiles ---------- */
/* Labels were the problem here, not the layout. Four tiers of tiny mono caps
   ("AISLE 01 / IDOL / 6 stories / more in IDOL") read as noise and none of it
   was legible. Now: one name, one number, and the name is set large. */
.hubs{display:grid;grid-template-columns:repeat(2,1fr);gap:16px;margin-top:6px}
/* Ten of these at full saturation were 55% of the page and the loudest thing on
   it, while the wordmark and the thesis - the first thing anybody should read -
   were the dimmest. The hierarchy was exactly backwards, and colour was doing
   the work that size and position should do.

   So the section colour stops flooding the tile and becomes an accent: a 3px
   rule along the top, a tinted ground, a coloured border. Ten hues still read as
   ten different shelves, but as a set they sit behind the page instead of
   shouting over it. */
.hub{
  position:relative;overflow:hidden;border-radius:var(--r);
  padding:22px 22px 18px;min-height:132px;
  display:flex;flex-direction:column;
  background:linear-gradient(178deg,
    color-mix(in srgb,var(--c) 17%,var(--bg2)) 0%,
    color-mix(in srgb,var(--c) 6%,var(--bg2)) 44%,
    var(--bg2) 100%);
  border:1px solid color-mix(in srgb,var(--c) 26%,var(--line));
  box-shadow:0 10px 26px rgba(0,0,0,.42);
  transition:transform .24s cubic-bezier(.34,1.25,.64,1),box-shadow .24s,
    border-color .24s;
}
.hub::before{
  content:"";position:absolute;left:0;right:0;top:0;height:3px;z-index:3;
  background:var(--c);
}
.hub:hover{transform:translateY(-4px);
  border-color:color-mix(in srgb,var(--c) 72%,var(--hot));
  box-shadow:0 22px 44px rgba(0,0,0,.55)}
/* the art: a real photo of the subject matter, credited. It was the tile's
   ground; it is now a texture behind the card, held down to 20% so ten of them
   do not become ten competing pictures. The section colour stays legible because
   the card's own ground is a mix of it. */
.hub-art{position:absolute;inset:0;z-index:0;overflow:hidden;opacity:.2}
.hub-art::after{content:"";position:absolute;inset:0;background:
  linear-gradient(176deg,color-mix(in srgb,var(--c) 30%,transparent) 0%,
    rgba(20,11,6,.72) 62%,rgba(20,11,6,.94) 100%)}
/* The credit used to sit here, on every homepage tile. Ten identical
   strings made the front page read like a stock library and turned a
   licence obligation into decoration. It lives on the section front,
   where each photograph appears at size, and on /credits/. */
.hub-glyph{
  position:absolute;right:-6px;bottom:-18px;z-index:0;
  font-family:var(--serif);font-weight:900;font-size:6.5rem;line-height:.7;
  letter-spacing:-.08em;pointer-events:none;
  color:color-mix(in srgb,var(--c) 46%,transparent);
}
.hub-name{
  position:relative;z-index:2;
  font-family:var(--serif);font-size:1.42rem;font-weight:700;
  letter-spacing:-.02em;color:var(--paper);margin-bottom:9px;
  padding-bottom:8px;
  border-bottom:1px solid color-mix(in srgb,var(--c) 52%,transparent);
}
.hub h3{
  position:relative;z-index:2;font-family:var(--serif);font-weight:700;
  font-size:clamp(1.02rem,1.35vw,1.18rem);line-height:1.22;letter-spacing:-.01em;
  color:var(--paper);margin:0 0 7px;max-width:34ch;
}
/* These were `rgba(18,10,5,.72)` and `.6` - hierarchy carried by alpha, over
   TEN different background colours. Measured off the pixels (two renders, text
   hidden, sampled where the text sits) that put the deck below 4.5:1 on seven
   of the ten tiles and the "N MORE" link below it on nine, worst 2.64:1.

   The tiles are now dark, so alpha over a variable ground is no longer the
   question at all: the deck is a solid `--dim` on `--bg2` and the link is a
   solid `--hot2`, both measured again by probe_hub_contrast rather than
   assumed. **Alpha is not a way to express hierarchy on a variable background**
   - that much survived the redesign.

   The link was first written as `color-mix(in srgb,var(--c) 62%,var(--paper))`
   and measured 1.21:1 on all ten tiles - mixing most of the way to the section
   colour walks it straight back down toward the ground it sits on. Ten out of
   ten, worst 1.21, so the whole colour scheme for one element was wrong in the
   same direction ten times. */
.hub p{
  position:relative;z-index:2;font-size:.87rem;line-height:1.5;flex:1;
  color:var(--dim);max-width:52ch;
}
.hub-go{
  position:relative;z-index:2;margin-top:12px;
  font-family:var(--label);font-size:.55rem;letter-spacing:.18em;
  color:var(--hot2);
}
.hub:hover .hub-name{color:#fff}
.hub:hover .hub-go{color:var(--paper)}

/* ---- entry landmarks: h2 promoted from the author's own bold lead --------
227 entries carried zero <h2>, which was reported as a corpus-wide reading
problem. It is not: the entry BODY is a median of 43 words and 171 entries run
under 150, so almost none of them need a landmark. Four are long enough
(american-gothic 1,266 words, marvel-club 984, queen-for-a-day 938,
krapp-last-tape 720) and those four already open their paragraphs on the
author's own bolded claims - 23 between them - so the structure promoted here is
structure the author wrote. `prose(..., heads=True)` changes its rendering and
invents nothing.

A lead over 90 characters stays bold rather than becoming a heading: 27 of the
96 leads are that long, and a sentence is not a heading. Measured, not tuned. */
.ent-h{font-family:var(--serif);font-weight:700;letter-spacing:-.02em;
  font-size:1.28rem;line-height:1.18;color:var(--paper);
  margin:34px 0 10px;padding-top:16px;
  border-top:1px solid var(--line2);scroll-margin-top:88px}
.article .body > .ent-h:first-child{margin-top:26px}
/* The rail appears only where there are three or more headings, which is a
   different question from "are there any" - two links in a list is not a table
   of contents, it is a menu. */
.ent-toc{border:1px solid var(--line2);border-radius:12px;
  background:linear-gradient(180deg,var(--bg3),var(--bg2));
  padding:14px 20px 16px;margin:0 0 26px}
.ent-toc-h{font-family:var(--label);font-size:.54rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--warm);margin:0 0 9px}
.ent-toc ol{margin:0;padding-left:1.15em;font-size:.9rem;line-height:1.5}
.ent-toc li{margin:0 0 5px;color:var(--dim)}
.ent-toc a{color:var(--dim);text-decoration:none}
.ent-toc a:hover,.ent-toc a:focus-visible{color:var(--paper);text-decoration:underline}

/* ---- /cases/ - the Case Files collection ---------------------------------
Generated from cases/*.md frontmatter by build_cases(). It exists because three
Case Files were indexable, absent from sitemap.xml and linked from nothing, so
no reader and no crawler could reach them. The page is generated rather than
written because a hand-made index drifts the moment a fourth .md is added. */
.case-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
  gap:14px;margin-top:26px}
.case-card{display:flex;flex-direction:column;gap:7px;padding:20px 22px 18px;
  border:1px solid var(--line);border-radius:var(--r);background:var(--bg2);
  color:inherit;text-decoration:none}
.case-card:hover{border-color:var(--hot);background:var(--bg3);transform:translateY(-2px)}
.case-no{font-family:var(--label);font-size:.52rem;letter-spacing:.2em;color:var(--hot)}
.case-title{font-family:var(--serif);font-size:1.14rem;font-weight:700;
  line-height:1.2;letter-spacing:-.02em;color:var(--paper)}
.case-teaser{font-size:.88rem;line-height:1.5;color:var(--dim);flex:1}
.case-foot{font-family:var(--label);font-size:.5rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dimmer);margin-top:4px}
.shelf-more{margin-top:38px;padding-top:22px;border-top:1px solid var(--line2)}

/* ---- the same-shelf strip on an entry page -------------------------------
Two related blocks sit here and they answer different questions, so they are
labelled differently rather than merged. `.ent-seq` is derived from the entries'
NAMES (ids sharing a significant word). This one is derived from the
CLASSIFICATION - the attachment sub-category - so it finds `the-dog` from
`alf`, which the name heuristic cannot, because nothing about those two ids
resembles anything.

It only renders where the shelf is deep enough to be a way of finding
something: 195 of 227 entries have three or more siblings, and two links in a
row is a menu rather than a shelf. Ordered nearest-in-time first, because on a
site laid out along a timeline the neighbours in time are the ones that make a
shape; sorted by year alone the block is just a list. */
.ent-shelf{margin:30px 0 6px;padding-top:20px;border-top:1px solid var(--line2)}
.shelfcards{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));
  gap:10px;margin-top:12px}
.shelfcard{display:flex;flex-direction:column;gap:4px;padding:13px 15px;
  border:1px solid var(--line);border-radius:10px;background:var(--bg2);
  color:inherit;text-decoration:none}
.shelfcard:hover{border-color:var(--mint);background:var(--bg3)}
.shelfcard-y{font-family:var(--label);font-size:.5rem;letter-spacing:.14em;color:var(--mint)}
.shelfcard b{font-family:var(--serif);font-size:.94rem;font-weight:700;
  line-height:1.2;color:var(--paper)}
.shelfcard-k{font-size:.68rem;color:var(--dimmer);margin-top:2px}

/* ---------- editorial images: real, credited, cached locally ---------- */
.fig{margin:0 0 18px}
.fig img{width:100%;border-radius:6px;box-shadow:0 10px 26px rgba(0,0,0,.5)}
.fig figcaption{
  font-family:var(--label);font-size:.52rem;letter-spacing:.1em;color:var(--dimmer);
  margin-top:6px;line-height:1.5;
}
.fig figcaption a{color:var(--dimmer);border-bottom:1px solid var(--line)}
.fig figcaption a:hover{color:var(--hot)}

/* ---------- the rotating top 8 column ---------- */
.t8col-wrap{margin-bottom:8px}
.t8col-list{
  display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:6px 0 18px;
}
.t8col{
  display:flex;gap:12px;align-items:center;background:var(--bg2);
  border:1px solid var(--line);border-radius:10px;padding:12px;transition:.2s;
}
.t8col:hover{border-color:var(--hot);transform:translateY(-3px);background:rgba(255,90,31,.06)}
.t8col-art{
  width:52px;height:52px;flex:none;border-radius:6px;overflow:hidden;
  background:var(--bg3);display:flex;align-items:center;justify-content:center;
}
.t8col-art img{width:100%;height:100%;object-fit:cover}
/* The front page showed a bare orange square where /top8/ shows a designed
   plate. Two of the eight are in that state, so in a grid of eight where the
   other six are photographs, two read as broken images - which is the one thing
   this site should not put on a page. Same idea as /top8/, at 52px: the show in
   display type on its own colour. The hatch behind it is gone for the same
   reason as on the big plate: a diagonal texture is the grammar of a
   placeholder, so it announced itself as one. A lit field and a hairline say
   "this is a designed card" instead. The art box is a fixed 52px at every
   width, so the type is sized against the box rather than the viewport - a
   vw-based size fitted "DRAGON" at desktop and broke it to "DRAGO N" on a
   phone. */
.t8col-plate{width:100%;height:100%;display:flex;align-items:center;
  justify-content:center;text-align:center;padding:3px;line-height:1;
  font-family:var(--serif);font-weight:900;font-size:10px;letter-spacing:-.01em;
  color:#fff6ea;white-space:nowrap;overflow:hidden;
  background:radial-gradient(120% 110% at 50% 10%,
    color-mix(in srgb,var(--c) 62%,#000) 0%,
    color-mix(in srgb,var(--c) 26%,#170e08) 62%,#140c07 100%);
  box-shadow:inset 0 0 0 1px rgba(255,246,234,.14)}
.t8col-body{min-width:0}
/* Two of the eight titles wrapped to two lines and six did not, so the cards in
   a row had ragged bottoms and the ranks did not line up. Two lines of room for
   every one of them - the grid is rank-ordered, and a ranked list whose rows do
   not align reads as unordered. */
.t8col-body b{display:block;font-family:var(--serif);font-size:.94rem;font-weight:700;
  line-height:1.18;min-height:2.36em}
.t8col-body span{font-family:var(--label);font-size:.53rem;letter-spacing:.12em;color:var(--dimmer)}

/* ---------- feature doors: history / moments / figures ---------- */
.fdoors{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.fdoor{
  display:flex;gap:14px;align-items:center;background:var(--bg2);
  border:1px solid var(--line);border-left:3px solid var(--c,var(--hot));
  border-radius:10px;padding:14px 16px;transition:.2s;
}
.fdoor:hover{border-color:var(--c);background:color-mix(in srgb,var(--c) 7%,var(--bg2));transform:translateY(-3px)}
.fdoor-art{width:56px;height:56px;flex:none;border-radius:6px;overflow:hidden;background:var(--bg3);display:flex;align-items:center;justify-content:center;font-family:var(--label);font-size:.5rem;letter-spacing:.14em;color:var(--dimmer)}
.fdoor-art img{width:100%;height:100%;object-fit:cover}
.fdoor-body{min-width:0}
.fdoor-body b{font-family:var(--label);font-size:.52rem;letter-spacing:.2em;text-transform:uppercase;color:var(--c);display:block}
.fdoor-body strong{font-family:var(--serif);font-size:1.1rem;font-weight:700;display:block;margin:1px 0 2px}
.fdoor-body span{font-size:.8rem;color:var(--dim);line-height:1.35;display:block}
/* the numbered art box, when a door has no photograph to put in it. The box is
   styled for a label, so a bare <b> inherits .5rem mono and reads as a smudge;
   it gets the same numerals as the top 8 list, which is the site's existing
   answer to "a count with no picture". */
.fdoor-art b{font-family:var(--serif);font-weight:900;font-size:1.3rem;
  line-height:1;color:var(--hot)}

/* ---------- the top 8 list ---------- */
.t8{list-style:none;counter-reset:none;display:grid;gap:22px}
.t8-item{
  background:var(--bg2);border:1px solid var(--line);border-radius:var(--r);
  padding:24px 26px;position:relative;overflow:hidden;
}
.t8-item::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--hot)}
.t8-head{display:flex;gap:18px;align-items:flex-start;margin-bottom:16px}
.t8-rank{
  font-family:var(--serif);font-weight:900;font-size:3rem;line-height:.8;
  color:var(--hot);flex:none;min-width:52px;
}
.t8-art{width:92px;height:92px;flex:none;border-radius:6px;object-fit:cover;box-shadow:0 8px 20px rgba(0,0,0,.5)}
/* .t8-art-none was a no-image plate designed for this list and never wired to
   anything - it is one of the orphans `check_css --orphans` reported. The
   front page now uses .t8col-plate and /top8/ uses .t8-plate, so the third
   version of the same idea is removed rather than left to drift again. */
.t8-titles{min-width:0;flex:1}
.t8-titles h3{font-family:var(--serif);font-size:clamp(1.2rem,2.2vw,1.6rem);font-weight:700;line-height:1.1;letter-spacing:-.02em}
.t8-show{font-family:var(--label);font-size:.6rem;letter-spacing:.16em;color:var(--hot);margin:5px 0 8px}
.t8-law{font-family:var(--label);font-size:.53rem;letter-spacing:.14em;color:var(--dimmer)}
.t8-law:hover{color:var(--hot)}
.t8-what{font-size:1rem;color:var(--dim);line-height:1.55;margin-bottom:12px}
.t8-what b{color:var(--paper)}
.t8-why{font-family:var(--serif);font-size:1.06rem;line-height:1.55;color:var(--paper)}
.t8-why b{color:var(--warm-hot);font-family:var(--label);font-size:.58rem;letter-spacing:.16em;text-transform:uppercase;display:block;margin-bottom:6px}
.t8-cite{
  margin-top:16px;padding:14px 16px;border-radius:8px;
  background:rgba(255,90,31,.08);border:1px solid rgba(255,90,31,.25);
}
.t8-cite-l{font-family:var(--label);font-size:.5rem;letter-spacing:.22em;color:var(--hot);margin-bottom:4px}
.t8-cite a{font-family:var(--serif);font-weight:700;font-size:1.02rem}
.t8-cite a:hover{color:var(--hot)}
.t8-cite p:last-child{font-size:.84rem;color:var(--dim);line-height:1.4;margin-top:3px}
.t8-hero-fig{margin:24px 0 0}
.t8-hero-fig img{max-height:380px;object-fit:cover;width:100%}

/* ---------- the history course ---------- */
.h-title{
  font-family:var(--serif);font-size:clamp(1.9rem,5vw,3.4rem);font-weight:900;
  letter-spacing:-.035em;line-height:1.02;margin:0 0 16px;max-width:22ch;
}
.h-outline{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px;margin-top:22px}
.hlaw{
  background:var(--bg2);border:1px solid var(--line);border-radius:8px;padding:11px 13px;
  display:flex;gap:10px;align-items:baseline;transition:.2s;
}
.hlaw:hover{border-color:var(--hot);background:rgba(255,90,31,.07)}
.hlaw b{font-family:var(--serif);font-size:1.3rem;font-weight:900;color:var(--hot);line-height:1}
.hlaw span{font-family:var(--serif);font-size:.9rem;font-weight:600;line-height:1.2}
.hmod{margin-bottom:44px;padding-bottom:36px;border-bottom:1px solid var(--line)}
.hmod:last-child{border-bottom:0}
.hmod-head{display:flex;gap:18px;align-items:flex-start;margin-bottom:18px}
.hmod-head>div{min-width:0}
.hmod-n{
  font-family:var(--serif);font-weight:900;font-size:3.2rem;line-height:.8;
  color:transparent;-webkit-text-stroke:1.5px var(--hot);flex:none;min-width:56px;
}
.hmod-years{font-family:var(--label);font-size:.58rem;letter-spacing:.2em;color:var(--hot);margin-bottom:5px}
.hmod h2{font-family:var(--serif);font-size:clamp(1.4rem,2.8vw,2rem);font-weight:700;line-height:1.1;letter-spacing:-.02em;margin-bottom:8px}
.hmod-claim{font-family:var(--serif);font-size:1.06rem;font-style:italic;color:var(--warm-hot);line-height:1.45}
/* Module layout: prose full width, figure as a wide band under the claim.
   An earlier version put the figure in a side grid column and every
   paragraph collapsed into a ribbon - grid items size to the row, and a
   tall figure forces a tall text column. Single column, no ribbon. */
.hmod-titles{min-width:0}
.hmod-prose{max-width:70ch}
.hmod-prose p{font-size:1.04rem;line-height:1.68;margin-bottom:15px}
.hmod-prose p:first-of-type::first-letter{
  font-family:var(--serif);font-size:2.9em;line-height:.82;float:left;
  padding:.05em .09em 0 0;color:var(--hot);font-weight:700;
}
.hfig{margin:20px 0 4px;max-width:520px}
.h-cite{font-family:var(--label)!important;font-size:.58rem!important;letter-spacing:.12em;color:var(--dimmer);border-top:1px dashed var(--line);padding-top:10px}
.h-cite a{color:var(--hot)}
.h-laws{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:12px}
.hlaw-card{background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:16px 18px;display:flex;gap:14px}
.hlaw-n{font-family:var(--serif);font-weight:900;font-size:1.6rem;color:var(--hot);line-height:1;flex:none}
.hlaw-card h3{font-family:var(--serif);font-size:1.02rem;font-weight:700;margin-bottom:4px}
.hlaw-card p{font-size:.88rem;color:var(--dim);line-height:1.4}
.hlaw-card .h-cite{margin-top:8px}

/* ---------- figures ---------- */
.fcards{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:14px}
.fcard{background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:20px;transition:.22s}
.fcard:hover{border-color:var(--violet);transform:translateY(-3px)}
.fcard-when{font-family:var(--label);font-size:.55rem;letter-spacing:.2em;color:var(--violet)}
.fcard h3{font-family:var(--serif);font-size:1.3rem;font-weight:700;margin:5px 0 3px;letter-spacing:-.015em}
.fcard-lane{font-family:var(--label);font-size:.52rem;letter-spacing:.18em;color:var(--dimmer);margin-bottom:10px}
.fcard-what{font-size:.92rem;color:var(--dim);line-height:1.5}

/* ---------- moments ---------- */
.moments{display:grid;gap:20px}
.moment{
  display:grid;grid-template-columns:260px 1fr;gap:24px;align-items:start;
  background:var(--bg2);border:1px solid var(--line);border-radius:var(--r);overflow:hidden;
  transition:.22s;
}
.moment:hover{border-color:var(--mint)}
.moment-art{height:100%;min-height:150px;background:var(--bg3)}
.moment-art img{width:100%;height:100%;object-fit:cover;display:block}
.moment-body{padding:20px 22px 20px 0}
.moment-meta{display:flex;gap:10px;align-items:center;margin-bottom:7px}
.moment-year{font-family:var(--serif);font-weight:900;font-size:1.1rem;color:var(--mint)}
.moment-dom{font-family:var(--label);font-size:.52rem;letter-spacing:.2em;color:var(--dimmer);border:1px solid var(--line);padding:2px 7px;border-radius:99px}
.moment h3{font-family:var(--serif);font-size:1.3rem;font-weight:700;line-height:1.15;margin-bottom:8px;letter-spacing:-.015em}
.moment-what{font-size:1rem;color:var(--dim);line-height:1.55}
.moment-credit{font-family:var(--label);font-size:.52rem;letter-spacing:.1em;color:var(--dimmer);margin-top:10px}
.moment-credit a{color:var(--dimmer);border-bottom:1px solid var(--line)}

/* ---------- the mascot page ---------- */
.mascot-hero{filter:drop-shadow(0 18px 40px rgba(255,90,31,.28))}
.moods{display:grid;grid-template-columns:repeat(auto-fill,minmax(214px,1fr));gap:18px}
.mood{
  margin:0;background:var(--bg2);border:1px solid var(--line);border-radius:var(--r);
  padding:20px;text-align:center;transition:.22s;
}
.mood:hover{border-color:var(--hot);transform:translateY(-4px)}
.mood-art{
  display:flex;align-items:center;justify-content:center;
  min-height:132px;margin-bottom:12px;
}
.mood figcaption b{
  display:block;font-family:var(--label);font-size:.6rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--hot);margin-bottom:6px;
}
.mood figcaption span{font-size:.82rem;color:var(--dim);line-height:1.42;display:block}

/* ---------- THE ENCYCLOPEDIA ---------- */
/* Three across on desktop, one on a phone. repeat(3,1fr) cannot do that on its
   own: a bare 1fr track's automatic minimum is its min-content, so three cards
   held a 412px floor inside a 339px column and pushed the page 55px past a
   390px viewport. auto-fit with a floor is what actually responds. */
.lanecards{display:grid;gap:12px;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,232px),1fr))}
.lanecard{background:var(--bg2);border:1px solid var(--line);
  border-top:3px solid var(--c);border-radius:10px;padding:16px 18px}
.lanecard b{font-family:var(--label);font-size:.58rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--c)}
.lanecard p{font-size:.86rem;color:var(--dim);line-height:1.45;margin-top:7px}

/* the database table */
.dbwrap{overflow-x:auto;margin-top:18px;border:1px solid var(--line);border-radius:var(--r)}
table.db{width:100%;border-collapse:collapse;font-size:.92rem}
table.db td{padding:9px 12px;border-bottom:1px solid var(--line2);vertical-align:top}
table.db tr:hover td{background:rgba(255,90,31,.06)}
.db-y{font-family:var(--label);font-size:.62rem;letter-spacing:.1em;color:var(--dimmer);
  white-space:nowrap;width:1%}
.db-k{font-family:var(--label);font-size:.56rem;letter-spacing:.12em;color:var(--dimmer);
  text-transform:uppercase;white-space:nowrap;width:1%}
.db-l{width:1%;white-space:nowrap}
.db-v{width:1%;color:var(--neon);font-family:var(--label);text-align:center}
table.db a{font-family:var(--serif);font-weight:600}
table.db a:hover{color:var(--hot)}
.lane-dot{display:inline-block;width:8px;height:8px;border-radius:50%;
  background:var(--c);margin-right:4px;vertical-align:middle}
.tog{font-family:var(--label);font-size:.62rem;letter-spacing:.1em;color:var(--dim);
  display:flex;align-items:center;gap:7px;white-space:nowrap}
.tog input{accent-color:var(--hot)}

/* the timeline */
.tl{margin-top:22px;position:relative;padding-left:22px}
.tl::before{content:"";position:absolute;left:5px;top:6px;bottom:6px;
  width:2px;background:linear-gradient(180deg,var(--hot),var(--violet),var(--mint));opacity:.5}
.tl-era{margin-bottom:34px}
.tl-era-h{font-family:var(--serif);font-size:1.3rem;font-weight:700;letter-spacing:-.01em;
  margin:0 0 12px;color:var(--warm-hot)}
.tl-era-h span{font-family:var(--label);font-size:.56rem;letter-spacing:.14em;
  color:var(--dimmer);margin-left:10px}
.tl-list{list-style:none}
.tl-item{display:grid;grid-template-columns:64px 1fr;gap:14px;
  padding:10px 0;border-bottom:1px solid var(--line2)}
.tl-item:last-child{border-bottom:0}
.tl-year{font-family:var(--label);font-size:.64rem;letter-spacing:.1em;
  color:var(--hot);padding-top:3px;white-space:nowrap}
.tl-body{min-width:0;position:relative}
.tl-title{font-family:var(--serif);font-size:1.04rem;font-weight:700;letter-spacing:-.01em}
.tl-title:hover{color:var(--hot)}
.tl-kind{font-family:var(--label);font-size:.54rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dimmer);margin-left:9px}
.tl-dots{display:inline-block;margin-left:4px;vertical-align:middle}
.tl-sum{font-size:.87rem;color:var(--dim);line-height:1.45;margin-top:3px}
.check{display:inline-block;margin-left:6px;font-family:var(--label);font-size:.58rem;
  color:var(--neon);border:1px solid rgba(255,45,111,.4);border-radius:2px;
  padding:0 4px;vertical-align:middle}
/* .checknote went with the per-entry "Not yet stood behind" banner. The state
   it described is still tracked - `verified` in the data, citation_audit.py,
   and the count published on /citations/ - it is just not printed on the
   reading surface any more. */
.lane{display:inline-block;font-family:var(--label);font-size:.55rem;letter-spacing:.16em;
  text-transform:uppercase;padding:4px 10px;border-radius:99px;margin-right:7px;
  color:var(--c);border:1px solid color-mix(in srgb,var(--c) 45%,transparent);
  background:color-mix(in srgb,var(--c) 12%,transparent)}
.xrefs{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px}
.xref{background:var(--bg2);border:1px solid var(--line);border-radius:9px;
  padding:13px 15px;transition:.2s}
.xref:hover{border-color:var(--hot);transform:translateY(-2px)}
.xref b{display:block;font-family:var(--serif);font-size:.98rem;font-weight:700;line-height:1.2}
.xref span{font-family:var(--label);font-size:.54rem;letter-spacing:.12em;color:var(--dimmer)}

/* ---------- the shelf: cover, name, one line, doors. nothing else ---------- */
.works{display:grid;grid-template-columns:repeat(auto-fill,minmax(198px,1fr));gap:22px}
.work{display:flex;flex-direction:column}
.work-art{display:block;border-radius:8px;overflow:hidden;box-shadow:0 12px 26px rgba(0,0,0,.5)}
.work-art img{width:100%;aspect-ratio:2/3;object-fit:cover;display:block}
.work-art .tileb{width:100%;aspect-ratio:2/3;display:flex;align-items:center;
  justify-content:center;font-family:var(--label);font-size:.6rem;letter-spacing:.2em;
  color:var(--dimmer);background:linear-gradient(160deg,var(--bg3),var(--bg))}
.work-kind{font-family:var(--label);font-size:.52rem;letter-spacing:.22em;
  color:var(--hot);margin-top:11px}
.work h3{font-family:var(--serif);font-size:1.06rem;font-weight:700;line-height:1.18;margin:3px 0 5px;letter-spacing:-.01em}
.work h3 a:hover{color:var(--hot)}
.work-bl{font-size:.82rem;color:var(--dim);line-height:1.4}
.work-cite{font-family:var(--label);font-size:.53rem;letter-spacing:.13em;
  color:var(--dimmer);margin-top:8px}
.work-cite.on{color:var(--mint)}
.work-doors{display:flex;flex-wrap:wrap;gap:5px;margin-top:11px}

/* ---------- legacy sections the cut pages used to need ---------- */
.aisle{display:block;padding:16px 17px;border-radius:var(--r);
  background:var(--bg2);border:1px solid var(--line);position:relative;
  overflow:hidden;transition:.2s}
.aisle::before{content:"";position:absolute;inset:0;background:var(--c);opacity:.12;transition:.2s}
.aisle:hover{transform:translateY(-3px);border-color:var(--c)}
.aisle:hover::before{opacity:.24}
.aisle b{position:relative;display:block;font-family:var(--serif);font-size:1.12rem;
  font-weight:700;margin:5px 0;letter-spacing:-.01em}
.aisle p{position:relative;font-size:.8rem;color:var(--dim);line-height:1.38;margin-bottom:8px}
.aisle .count{position:relative;font-family:var(--label);font-size:.54rem;letter-spacing:.14em;color:var(--dimmer)}
.aisle .count b{font-size:1rem;color:var(--c);display:inline;margin:0}
.aisles{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:12px}

/* the plain-language explainer. this is the "what am I looking at" box. */
.explain{
  background:var(--bg2);border:1px solid var(--line);border-left:3px solid var(--warm);
  border-radius:var(--r);padding:22px 24px;
}
.explain p{font-size:.98rem;color:var(--dim);margin-bottom:10px}
.explain p b{color:var(--paper)}
.explain .q{font-family:var(--serif);font-size:1.06rem;color:var(--paper);line-height:1.35;margin-bottom:12px}

/* ---------- section furniture ---------- */
.section{max-width:var(--w);margin:0 auto;padding:52px 24px}
.kicker{font-size:.6rem;letter-spacing:.24em;text-transform:uppercase;color:var(--warm);
  margin-bottom:14px;display:flex;align-items:center;gap:12px}
.kicker::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,rgba(255,90,31,.35),transparent);max-width:150px}
.kicker .more:hover{color:var(--warm)}
.sec-head h2{font-family:var(--serif);font-size:clamp(1.6rem,3.4vw,2.3rem);font-weight:700;
  letter-spacing:-.02em;line-height:1.1;margin-bottom:10px;max-width:26ch}
.sec-lede{color:var(--dim);max-width:66ch;font-size:1.02rem}
.sec-lede a,.sec-lede strong{color:var(--warm)}
.countline{font-family:var(--label);font-size:.58rem;letter-spacing:.16em;color:var(--dimmer);margin-top:14px}
.countline a{color:var(--warm)}

/* ---------- THE FRONT PAGE ---------- */
.lead{
  display:grid;grid-template-columns:.85fr 1.15fr;gap:36px;align-items:center;
  background:linear-gradient(140deg,var(--bg2),var(--bg3));
  border:1px solid var(--line);border-radius:18px;padding:28px;margin-bottom:26px;
  position:relative;overflow:hidden;
}
.lead .cover{border-radius:12px;overflow:hidden;box-shadow:0 18px 46px rgba(0,0,0,.6)}
.lead h2{
  font-family:var(--serif);font-size:clamp(1.7rem,3.6vw,2.7rem);font-weight:700;
  letter-spacing:-.025em;line-height:1.03;margin:18px 0 12px;max-width:22ch;
}
.lead h2 a:hover{color:var(--warm)}
.lead .dek{font-size:1.06rem;color:var(--dim);margin-bottom:14px;max-width:56ch}
.lead .take{
  font-family:var(--serif);font-size:1.02rem;line-height:1.55;color:var(--paper);
  border-left:2px solid var(--warm);padding-left:16px;margin:0 0 18px;max-width:62ch;
}

.front{
  display:grid;grid-template-columns:repeat(3,1fr);gap:20px;
}
.front-2{grid-template-columns:repeat(2,1fr)}
.front-3{grid-template-columns:repeat(3,1fr)}
.rack-2{grid-template-columns:repeat(2,1fr)}
.rack-3{grid-template-columns:repeat(3,1fr)}
.one{color:var(--dim)}

/* a story: small poster, loud headline, take inline */
.story{
  display:flex;gap:15px;align-items:flex-start;
  background:var(--bg2);border:1px solid var(--line);border-radius:var(--r);
  padding:15px;transition:.22s;position:relative;overflow:hidden;
}
.story:hover{border-color:rgba(255,90,31,.5);transform:translateY(-3px);
  box-shadow:0 14px 34px rgba(0,0,0,.4)}
.story::before{
  content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--c,var(--warm));
}
.story .cover{width:78px;flex:none;border-radius:8px;overflow:hidden;box-shadow:0 8px 20px rgba(0,0,0,.5)}
.story .body{min-width:0;flex:1}
.story .tags{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-bottom:6px}
.story h3{font-family:var(--serif);font-size:1.06rem;font-weight:700;line-height:1.16;
  letter-spacing:-.01em;margin-bottom:6px}
.story h3 a:hover{color:var(--warm)}
.story p.dek{font-size:.88rem;color:var(--dim);line-height:1.45;margin-bottom:8px}
.story p.take{
  font-family:var(--serif);font-size:.94rem;line-height:1.5;color:var(--paper);
  border-top:1px dashed var(--line);padding-top:8px;margin-bottom:8px;
}
.story .foot{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  font-family:var(--label);font-size:.56rem;letter-spacing:.12em;color:var(--dimmer);margin-top:auto}
.story .foot a{color:var(--warm)}
.story .foot .src{color:var(--dim)}

/* a story with a big square cover, for the first rows */
.story-lg{flex-direction:column;gap:12px}
.story-lg .cover{width:100%;border-radius:10px}
.story-lg h3{font-size:1.2rem}

/* tags */
/* Not nowrap. The short labels (GRIEF, WORTH YOUR TIME) stay on one line and
   the pill looks identical, but a tag that also carries a headline runs ~48
   characters, and at 320px nowrap meant the pill was clipped by body's
   overflow-x:hidden with the reader none the wiser. Wrapping keeps the
   information, which is the whole point of the pill. */
.tag{
  display:inline-flex;align-items:center;gap:5px;font-family:var(--label);
  font-size:.53rem;letter-spacing:.16em;text-transform:uppercase;
  padding:3px 8px;border-radius:99px;
  white-space:normal;max-width:100%;overflow-wrap:break-word;
}
.tag-aisle{background:color-mix(in srgb,var(--c,var(--warm)) 20%,transparent);
  color:var(--c,var(--warm));border:1px solid color-mix(in srgb,var(--c,var(--warm)) 42%,transparent)}
.tag-kick{background:var(--neon);color:#fff;font-weight:500}
.tag-od{background:var(--neon);color:#fff;font-weight:500}
.tag-law{background:rgba(253,246,234,.08);color:var(--dimmer);border:1px solid var(--line)}
.tag-age{background:rgba(253,246,234,.08);color:var(--dim);border:1px solid var(--line)}

/* ---------- POSTER ART ---------- */
/* Every story gets a cover, like a tape or a DVD. Deterministic from the
   slug so a story always looks the same, and bright, because a wall of
   bright covers is the entire point of a video store. */
.poster{
  position:relative;width:100%;aspect-ratio:2/3;overflow:hidden;
  display:flex;align-items:flex-end;padding:10px;
  background:var(--bg3);
}
.poster::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(190deg,rgba(255,255,255,.18),transparent 45%),
             linear-gradient(0deg,rgba(0,0,0,.6),transparent 60%);
}
.poster .glyph{
  position:absolute;top:6%;right:6%;z-index:1;
  font-family:var(--serif);font-weight:900;line-height:.72;
  font-size:clamp(2.2rem,5vw,4.4rem);
  color:rgba(255,255,255,.28);letter-spacing:-.06em;
  text-shadow:0 3px 18px rgba(0,0,0,.4);
}
.poster .stripe{
  position:absolute;left:0;right:0;top:0;height:6px;background:var(--c,var(--warm));
  z-index:1;
}
.poster .foot{position:relative;z-index:2;width:100%}
.poster .foot b{
  display:block;font-family:var(--label);font-size:.5rem;letter-spacing:.2em;
  text-transform:uppercase;color:rgba(255,255,255,.82);margin-bottom:3px;
}
.poster .foot span{
  display:block;font-family:var(--serif);font-size:.72rem;font-weight:700;
  line-height:1.14;color:#fff;text-shadow:0 1px 6px rgba(0,0,0,.7);
}
.poster.wide{aspect-ratio:16/9}

/* ---------- AISLE BANNERS ---------- */
.aisles{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:12px}
.aisle{
  display:block;padding:16px 17px;border-radius:var(--r);
  background:var(--bg2);border:1px solid var(--line);
  position:relative;overflow:hidden;transition:.2s;
}
.aisle::before{content:"";position:absolute;inset:0;background:var(--c);
  opacity:.1;transition:.2s}
.aisle:hover{transform:translateY(-3px);border-color:var(--c)}
.aisle:hover::before{opacity:.2}
.aisle b{position:relative;display:block;font-family:var(--serif);font-size:1.12rem;
  font-weight:700;margin:5px 0 5px;letter-spacing:-.01em}
.aisle p{position:relative;font-size:.8rem;color:var(--dim);line-height:1.38;margin-bottom:9px}
.aisle .count{position:relative;font-family:var(--label);font-size:.55rem;letter-spacing:.14em;color:var(--dimmer)}
.aisle .count b{font-size:1rem;color:var(--c);margin:0}

/* ---------- TICKER ---------- */
.ticker{overflow:hidden;white-space:nowrap;padding:9px 0;background:var(--bg2);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.ticker-track{display:inline-flex;width:max-content;animation:tick 48s linear infinite}
.ticker-track span{font-family:var(--label);font-size:.62rem;letter-spacing:.2em;color:var(--dimmer);padding-right:22px}
@keyframes tick{to{transform:translateX(-50%)}}

/* ---------- shelf / clerk's own work ---------- */
.shelf-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(158px,1fr));gap:18px}
.shelf-item{display:block;transition:transform .22s}
.shelf-item .kind{font-family:var(--label);font-size:.52rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--warm);margin-top:8px}
.shelf-item .nm{font-family:var(--serif);font-size:.95rem;font-weight:700;line-height:1.2;margin-top:2px}
.shelf-item .bl{font-size:.76rem;color:var(--dimmer);line-height:1.35;margin-top:3px}
.bookwrap{position:relative}
.album{padding:0;gap:8px}
.album h3{font-size:.9rem}
.pod-card{gap:12px}
.video-card{padding:0}
.link-card{display:block}
.logo-img.lg{width:38px;height:38px}
.tile-f{background:linear-gradient(150deg,#3a3a42,#0c0d10)}
.cta-link{color:var(--warm)}
.lede{max-width:56ch;color:var(--dim);font-size:1.05rem;margin-bottom:28px}
.lede strong{color:var(--paper);font-weight:600}
.equalizer{display:flex;gap:5px;align-items:flex-end;height:40px;margin-top:36px;opacity:.7}
.equalizer span{width:5px;background:linear-gradient(to top,var(--warm),var(--neon));
  border-radius:3px;height:20%;animation:eq 1.4s ease-in-out infinite alternate}
.equalizer span:nth-child(odd){animation-duration:1.1s}
@keyframes eq{from{height:12%}to{height:100%}}
/* ---------- laws ---------- */
.law-list{display:grid;gap:9px}
.law{display:grid;grid-template-columns:auto 1fr auto;gap:16px;align-items:center;
  padding:14px 17px;border:1px solid var(--line);border-radius:10px;
  background:var(--bg2);transition:.2s}
.law span{font-size:.84rem;color:var(--dim);line-height:1.4}
.law .go{font-family:var(--label);font-size:.54rem;letter-spacing:.16em;color:var(--dimmer);white-space:nowrap}
/* ---------- interactive: reason to come back ---------- */
.quiz-sec{padding-top:0}
.quiz{margin-top:26px}
.quiz h3{font-family:var(--serif);font-size:1.4rem;font-weight:700;margin-bottom:8px;letter-spacing:-.015em}
.quiz p{color:var(--dim);margin-bottom:18px;max-width:56ch}
.qs{display:grid;gap:10px;margin-bottom:20px}
.qs .d{font-size:.82rem;color:var(--dimmer);line-height:1.35}
.result{background:linear-gradient(150deg,rgba(255,90,31,.14),transparent);
  border:1px solid rgba(255,90,31,.35);border-radius:12px;padding:20px;display:none}
.result.show{display:block}
.result .you{font-family:var(--label);font-size:.56rem;letter-spacing:.2em;color:var(--warm);margin-bottom:8px}
.result h4{font-family:var(--serif);font-size:1.25rem;font-weight:700;margin-bottom:8px}
.result p{color:var(--dim);margin-bottom:12px;font-size:.96rem}

/* A "THE CLERK" block used to live here for a /shelf/ component that no longer
   exists. It styled `.clerk .face`, `.clerk h3`, `.clerk .role` and `.clerk p`
   - none of which any page emits any more - but its bare `.clerk{...}` selector
   matched the front page's mascot card and silently won, because it came later
   in the file. Measured, not guessed: the card asked for `display:flex` and a
   single 330px column and got `display:grid` with `auto 1fr`, which resolved to
   197px + 50px inside a 330px card. The card's own copy then wrapped to EIGHT
   lines at a 191px measure (~24 characters) and "WHAT THE MASCOT IS FOR" sat in
   a 50px column, three words to a line.

   Nothing caught it and nothing could have: the defect produces no overflow, so
   verify_narrow cannot see it; it overlaps nothing, so probe_front cannot see
   it; and every class in it is a real class, so check_css reports it as styled.
   A dead component's stylesheet outliving the component is the same shape as the
   25 drifted title plates and the stale mascot sheet - a generated artefact
   quietly describing an older version of its source - except that here the stale
   copy was the one being applied. `check_css.py --orphans` now holds it.

   The name `.clerk` belongs to the masthead card alone. If a second component
   ever needs it, give it its own name rather than sharing this one. */

/* ---------- newsletter ---------- */
.signal-sec{text-align:center;background:
  radial-gradient(60% 70% at 50% 0%,rgba(255,90,31,.1),transparent 70%)}
.signal-sec .sec-head h2{margin-inline:auto}
.signal-form{display:flex;gap:11px;justify-content:center;margin:26px auto 14px;max-width:520px}
.signal-form input[type=email]{flex:1;min-width:0;padding:14px 20px;border-radius:99px;
  border:1px solid var(--line);background:var(--bg2);color:var(--paper);
  font-family:var(--label);font-size:.76rem}
.signal-form input[type=email]:focus{outline:none;border-color:var(--warm)}
.fineprint{font-size:.56rem;letter-spacing:.16em;color:var(--dimmer);line-height:2}
.fineprint a{color:var(--warm)}

/* ---------- price / offer ---------- */
.money{display:grid;grid-template-columns:repeat(auto-fit,minmax(256px,1fr));gap:18px}
.price{background:var(--bg2);border:1px solid var(--line);border-radius:var(--r);
  padding:24px;display:flex;flex-direction:column;gap:9px;transition:.22s;position:relative;overflow:hidden}
.price:hover{border-color:rgba(255,90,31,.4);transform:translateY(-3px)}
.price.hot{border-color:var(--warm);background:linear-gradient(165deg,rgba(255,90,31,.1),var(--bg2))}
.price h3{font-family:var(--serif);font-size:1.35rem;font-weight:700}
.price .amt{font-family:var(--serif);font-size:2.1rem;font-weight:700;color:var(--warm);line-height:1}
.price ul{list-style:none;color:var(--dim);font-size:.88rem;display:flex;flex-direction:column;gap:6px;margin:4px 0 12px;flex:1}
.price ul li::before{content:"▸ ";color:var(--warm)}
.price ul li b{color:var(--paper);font-weight:600}
.price .flag{font-family:var(--label);font-size:.54rem;letter-spacing:.2em;text-transform:uppercase;color:var(--warm)}

/* ---------- punch card ---------- */
.punchcard{background:linear-gradient(165deg,var(--warm-hot),var(--warm));
  color:#1b1410;border-radius:16px;padding:24px;box-shadow:0 16px 40px rgba(255,90,31,.22)}
.punch-head{font-family:var(--label);font-size:.56rem;letter-spacing:.22em;
  text-align:center;margin-bottom:16px;opacity:.75}
.punch-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:14px;justify-items:center;margin-bottom:16px}
.hole{width:30px;height:30px;border-radius:50%;background:rgba(27,20,16,.9);
  box-shadow:inset 0 3px 5px rgba(0,0,0,.5)}
.hole.stamped{background:radial-gradient(circle at 42% 38%,#6b5636,#2a2116)}
.punch-foot{text-align:center;font-family:var(--label);font-size:.56rem;letter-spacing:.14em;line-height:1.8;opacity:.8}

/* ---------- ledger / lists ---------- */
.ledger{background:var(--bg2);border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.log-row{display:grid;grid-template-columns:auto 1fr auto;gap:15px;align-items:center;
  padding:13px 17px;border-bottom:1px solid var(--line2);transition:background .18s}
.log-row:last-child{border-bottom:0}
a.log-row:hover{background:rgba(255,90,31,.06)}
.log-row:hover b{color:var(--warm)}
.log-row .tick{width:3px;align-self:stretch;min-height:32px;border-radius:2px;background:var(--c,var(--warm))}
.log-row b{font-family:var(--serif);font-weight:700;font-size:.98rem;transition:color .18s}
.log-row .meta{font-family:var(--label);font-size:.55rem;letter-spacing:.12em;color:var(--dimmer);margin-top:3px}
.side{display:flex;flex-direction:column;gap:14px;min-width:0}
.sidebox{border:1px solid var(--line);border-radius:var(--r);padding:17px;background:var(--bg2)}
.sidebox h4{font-family:var(--label);font-size:.56rem;letter-spacing:.22em;color:var(--warm);margin-bottom:11px}
.sidebox p,.sidebox li{font-size:.85rem;color:var(--dim)}
.sidebox a{color:var(--warm)}

/* ---------- the clerk's voice block ---------- */
.note{
  background:linear-gradient(165deg,var(--bg3),var(--bg2));
  border:1px solid var(--line);border-left:3px solid var(--warm);
  border-radius:var(--r);padding:24px 26px;
  font-family:var(--serif);font-size:1.06rem;line-height:1.6;color:var(--paper);
}
.note p+p{margin-top:12px}
.note b{color:var(--warm-hot)}

/* ---------- search / filters ---------- */
.bar{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:20px 0 4px}
.search{flex:1;min-width:180px;padding:11px 16px;border-radius:99px;border:1px solid var(--line);
  background:var(--bg2);color:var(--paper);font-family:var(--label);font-size:.72rem}
.search:focus{outline:none;border-color:var(--warm)}
.chips{display:flex;gap:7px;flex-wrap:wrap;margin:12px 0 0}
.chip{font-family:var(--label);font-size:.58rem;letter-spacing:.14em;text-transform:uppercase;
  border:1px solid var(--line);background:transparent;color:var(--dim);
  border-radius:99px;padding:7px 14px;cursor:pointer;transition:.18s}
.chip:hover{border-color:var(--warm);color:var(--warm)}
.chip.on{background:var(--c,var(--warm));border-color:var(--c,var(--warm));color:#1b1410;font-weight:500}

/* ---------- footer ---------- */
.footer{border-top:1px solid var(--line);background:var(--bg2);padding:46px 0 34px;margin-top:40px}
.foot-grid{max-width:var(--w);margin:0 auto;padding:0 24px;
  display:flex;flex-wrap:wrap;gap:32px;align-items:flex-start;justify-content:space-between}
.foot-mark{font-size:1.2rem;margin-bottom:12px;display:inline-block}
.foot-note,.foot-tag{font-family:var(--label);font-size:.56rem;letter-spacing:.13em;color:var(--dimmer);line-height:2.1}
/* A donation link, kept in the same register as the line it sits under: same
   face, same size, same muted colour as the surrounding footer text. It becomes
   legible on hover and on keyboard focus, and nothing else about it moves - a
   link that announces itself in the footer is not a subtle one. It carries
   rel="noopener nofollow" because it is the only outbound link on the page that
   is not a citation. */
.foot-kofi{color:var(--dimmer);border-bottom:1px solid transparent;
  transition:color .16s,border-color .16s}
.foot-kofi:hover,.foot-kofi:focus-visible{color:var(--warm);
  border-bottom-color:color-mix(in srgb,var(--hot) 45%,transparent)}
.foot-tag{text-align:right}
.foot-nav{display:flex;gap:18px;flex-wrap:wrap;padding-top:5px}
.foot-nav a{font-family:var(--label);font-size:.6rem;letter-spacing:.16em;color:var(--dim);transition:.18s}
.foot-nav a:hover{color:var(--warm)}

/* ---------- utility ---------- */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.skip{position:absolute;left:-9999px;top:0;background:var(--warm);color:#1b1410;
  padding:11px 20px;font-family:var(--label);font-size:.68rem;z-index:100;letter-spacing:.12em}
.skip:focus{left:0}
:focus-visible{outline:2px solid var(--warm);outline-offset:3px}
.rule{height:1px;background:var(--line);border:0;margin:0}
.dim{color:var(--dim)}.mono-s{font-family:var(--label);font-size:.58rem;letter-spacing:.14em;color:var(--dimmer)}

/* ---------- story page (single article) ---------- */
.article{max-width:720px;margin:0 auto;padding:44px 24px 20px}
.article .kicker{margin-bottom:16px}
.article h1{font-family:var(--serif);font-size:clamp(1.9rem,5vw,3.1rem);font-weight:700;
  letter-spacing:-.03em;line-height:1.03;margin-bottom:16px}
.article .dek{font-size:1.2rem;color:var(--dim);margin-bottom:26px;line-height:1.45}
.article .byline{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  font-family:var(--label);font-size:.56rem;letter-spacing:.16em;color:var(--dimmer);
  padding-bottom:20px;border-bottom:1px solid var(--line);margin-bottom:26px}
.article .body p{font-size:1.08rem;line-height:1.68;margin-bottom:18px}
.article .body p.lede2::first-letter{font-family:var(--serif);font-size:3.2em;line-height:.8;
  float:left;padding:.06em .09em 0 0;color:var(--warm);font-weight:700}
.pull{font-family:var(--serif);font-size:1.3rem;line-height:1.4;font-style:italic;
  color:var(--warm-hot);border-left:3px solid var(--warm);padding-left:20px;margin:26px 0}
.srcline{font-family:var(--label);font-size:.56rem;letter-spacing:.14em;color:var(--dim);margin-bottom:6px}
.srcbox a{color:var(--warm);font-family:var(--sans);font-size:.98rem;font-weight:600;letter-spacing:-.01em}
.srcbox a:hover{text-decoration:underline}
.srcbox .pub{font-family:var(--label);font-size:.55rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dimmer);margin-top:4px}

/* ---------- legacy pages ---------- */
.card{background:var(--bg2);border:1px solid var(--line);border-radius:var(--r);
  padding:18px;display:flex;flex-direction:column;gap:13px;transition:.24s}
.card:hover{border-color:rgba(255,90,31,.5);transform:translateY(-3px)}
.card h3{font-size:1rem;font-weight:700}
.grid{display:grid;gap:20px}
.grid-video,.grid-pod{grid-template-columns:repeat(2,1fr)}
.grid-books{grid-template-columns:repeat(4,1fr)}
.grid-albums{grid-template-columns:repeat(3,1fr)}
.grid-links{grid-template-columns:repeat(4,1fr)}
.mini-card{border:1px solid var(--line);border-radius:var(--r);padding:17px;
  display:flex;flex-direction:column;gap:5px;background:var(--bg2);transition:.2s}
.mini-card b{font-family:var(--label);font-size:.62rem;letter-spacing:.16em;font-weight:500}
.mini-card span{font-family:var(--label);font-size:.6rem;letter-spacing:.08em;color:var(--dim)}
.mini-card:hover{border-color:var(--warm)}
.book-img{width:100%;display:block;border-radius:6px;box-shadow:0 18px 40px rgba(0,0,0,.55)}
.album-art{width:100%;aspect-ratio:1/1;object-fit:cover;border-radius:6px;box-shadow:0 12px 30px rgba(0,0,0,.5)}
.pod-art{width:62px;height:62px;border-radius:6px;flex:none;box-shadow:0 8px 20px rgba(0,0,0,.5)}
.pod-head{display:flex;align-items:center;gap:14px}
.cover{aspect-ratio:2/3;border-radius:6px;padding:16px 13px;display:flex;flex-direction:column;
  justify-content:space-between;text-align:center;border:1px solid rgba(253,246,234,.1)}
.cover small{font-family:var(--label);font-size:.48rem;letter-spacing:.2em;opacity:.75}
.cover strong{font-size:1.02rem;font-weight:700;line-height:1.22}
.cover em{font-style:normal;font-family:var(--label);font-size:.52rem;letter-spacing:.16em;opacity:.8}
.cover-c{background:linear-gradient(165deg,#7a1f2e,#2a0810);color:#ffd9cf}
.cover-d{background:linear-gradient(165deg,#2e2260,#0a0618);color:#ddd6ff}
.cover-e{background:linear-gradient(165deg,#1a5f56,#04120f);color:#ccfff5}
.cover-f{background:linear-gradient(165deg,#4a4a54,#101014);color:var(--paper)}
.buy{font-family:var(--label);font-size:.56rem;letter-spacing:.16em;color:var(--warm);margin-top:auto}
.book-card p{color:var(--dim);font-size:.85rem}
.pill{font-family:var(--label);font-size:.58rem;letter-spacing:.14em;text-transform:uppercase;
  border:1px solid var(--line);border-radius:99px;padding:6px 13px;color:var(--dim);transition:.18s}
.pill:hover{border-color:var(--warm);color:var(--warm)}
.pill-row{display:flex;flex-wrap:wrap;gap:7px}
.tile{aspect-ratio:1/1;border-radius:6px;display:flex;align-items:center;justify-content:center;
  font-family:var(--label);font-size:.9rem;letter-spacing:.14em;background:linear-gradient(150deg,var(--bg3),var(--bg))}
.about-grid{display:grid;grid-template-columns:1.6fr 1fr;gap:44px;align-items:start}
.bio p{color:var(--dim);margin-bottom:18px;max-width:64ch}
.stats{list-style:none;display:grid;grid-template-columns:repeat(2,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:var(--r);overflow:hidden}
.stats li{background:var(--bg2);padding:22px}
.stats b{display:block;font-size:1.9rem;color:var(--warm);font-family:var(--serif)}
.stats span{font-family:var(--label);font-size:.58rem;letter-spacing:.16em;color:var(--dim);text-transform:uppercase}
.reveal{opacity:0;transform:translateY(20px);transition:opacity .6s ease,transform .6s ease}
.reveal.in{opacity:1;transform:none}

/* long-form reading blocks */
/* A slash-separated enumeration is one unbreakable token to a browser:
   (idol/character/creator/companion/brand/universe) is 47 characters with no
   break opportunity anywhere in it. In a 273px column on a phone that is 80px
   too wide, and because body carries overflow-x:hidden the excess is *clipped*
   rather than scrolled - the reader loses the end of the sentence and never
   finds out. overflow-wrap:break-word only breaks a word that would otherwise
   overflow, so ordinary prose is untouched. Set on the containers because the
   property inherits. */
.page,.ws,.try,.chap,.buybox,.ref,.tier{overflow-wrap:break-word}
.page> p:first-of-type::first-letter{font-family:var(--serif);font-size:3em;line-height:.82;
  float:left;padding:.06em .09em 0 0;color:var(--warm);font-weight:700}
.chap{font-family:var(--serif);font-size:clamp(1.25rem,2.5vw,1.7rem);font-weight:700;
  letter-spacing:-.01em;line-height:1.2;margin:2.2em 0 .2em;padding-top:1em;border-top:1px solid var(--line)}
.kicker2{font-family:var(--label);font-size:.56rem;letter-spacing:.22em;text-transform:uppercase;
  color:var(--dimmer);margin:1.5em 0 .7em}
.try{background:var(--bg3);border:1px solid rgba(255,90,31,.3);border-radius:10px;
  padding:17px 19px;margin:1.5em 0;font-size:.95rem}
.try::before{content:"TRY THIS";display:block;font-family:var(--label);font-size:.52rem;
  letter-spacing:.22em;color:var(--warm);margin-bottom:8px}
.ws{border:1px dashed var(--line);border-radius:10px;padding:17px 19px;margin:1.5em 0;
  background:rgba(0,0,0,.2);font-size:.93rem;line-height:2}
.ref{font-size:.89rem;color:var(--dim);padding-left:1.1em;margin:1.2em 0}
.ref a{color:var(--warm)}
.buybox{border:1px solid rgba(255,90,31,.4);background:rgba(255,90,31,.06);
  border-radius:var(--r);padding:24px;margin:1.8em 0;text-align:center}
.nobuy{color:var(--dimmer);font-size:.74rem;font-family:var(--label);letter-spacing:.1em;margin-top:9px}
.lesson{border:1px solid var(--line);border-left:3px solid var(--warm);border-radius:10px;
  padding:19px 21px;margin:1.4em 0;background:var(--bg2)}
.lesson h3{font-family:var(--serif);font-size:1.05rem;font-weight:700;margin-bottom:7px}
.tier{display:inline-block;font-family:var(--label);font-size:.52rem;letter-spacing:.2em;
  text-transform:uppercase;padding:4px 9px;border:1px solid var(--warm);color:var(--warm);
  border-radius:2px;margin-bottom:10px}
.deliv{border:1px solid var(--line);border-radius:var(--r);padding:19px 21px;margin:1.6em 0;background:var(--bg2)}
.deliv b{font-family:var(--label);font-size:.58rem;letter-spacing:.2em;color:var(--warm)}
.row2{display:grid;grid-template-columns:repeat(2,1fr);gap:15px;margin:1.2em 0}
.eyebrow{font-family:var(--label);font-size:.6rem;letter-spacing:.24em;color:var(--warm);margin-bottom:22px}
.hero-mark{position:absolute;top:5%;right:-30px;width:min(32vw,360px);opacity:.08;pointer-events:none}
.yt-facade{position:relative;width:100%;aspect-ratio:16/9;border:0;padding:0;cursor:pointer;
  border-radius:6px;overflow:hidden;background:#000}
.yt-facade img{width:100%;height:100%;object-fit:cover;opacity:.85}
.play{position:absolute;top:50%;left:50%;width:52px;height:52px;transform:translate(-50%,-50%);
  border-radius:50%;background:rgba(255,90,31,.94)}
.play::after{content:"";position:absolute;top:50%;left:53%;transform:translate(-50%,-50%);
  border-left:15px solid #1b1410;border-top:9px solid transparent;border-bottom:9px solid transparent}
.yt-facade iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.thumb{position:relative;display:block;aspect-ratio:16/9;border-radius:6px;overflow:hidden;background:#000}
.play-sm{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:44px;height:44px;
  border-radius:50%;background:rgba(255,90,31,.94)}
.play-sm::after{content:"";position:absolute;top:50%;left:54%;transform:translate(-50%,-50%);
  border-left:13px solid #1b1410;border-top:8px solid transparent;border-bottom:8px solid transparent}
.sublabel{font-size:.56rem !important;letter-spacing:.18em;color:var(--dim)}

@media (max-width:1080px){
  .front{grid-template-columns:repeat(2,1fr)}
  .hubs{grid-template-columns:repeat(2,1fr)}
  .t8col-list{grid-template-columns:repeat(2,1fr)}
/* Two lines of title room is only there so the four-across row aligns its ranks.
   At two columns the cards are wide enough that most titles fit on one line,
   and reserving two made every card carry a visible gap under its caption. */
.t8col-body b{min-height:0}
  .fdoors{grid-template-columns:1fr 1fr}
  .hmod-body{grid-template-columns:1fr}
  .hfig{position:static;max-width:280px}
  .moment{grid-template-columns:1fr}
  .moment-body{padding:0 20px 20px}
  .moment-art{min-height:190px;max-height:230px}
}
/* The nav becomes a menu at 1024px, not 760px. Measured, not guessed: the
   desktop nav needs 835px plus 48px of bar padding, the wordmark and a 22px gap,
   so it fits one line down to about 1000px and wrapped below that - two lines
   inside a 64px bar, which is not a clipped nav and not a scrollable one but an
   overlapping one. **Every viewport between 761px and 1024px had a broken
   header**, and nothing in this project could see it: `verify_narrow.py` measures
   only at 390px, where the nav *is* this overlay. `tools/probe_nav.py` now
   measures the desktop row across a width ladder and is the gate for it. */
@media (max-width:1024px){
  /* THE MOBILE MENU WAS 130px TALL AND NOT A FULL-SCREEN OVERLAY AT ALL, for
     an undeclared reason. `.topbar` carries `backdrop-filter: blur(14px)`, and
     **`backdrop-filter` makes an element a containing block for its
     `position:fixed` descendants** - exactly as `transform`, `filter`,
     `contain` and `will-change` do. So the overlay's `inset:0` was resolving
     against the 65px header instead of against the viewport, and its height
     became `max(65px, 90px top padding + 40px bottom padding)` = **130px**: a
     strip at the top of the page. Measured, not inferred -
     `tools/probe_overlay.py` prints computed height 130px at viewport heights
     900, 700, 480 and 844 alike, which is the signature of a fixed element whose
     containing block is a short ancestor.

     It stayed invisible to every gate because the menu is CLOSED by default: it
     is translated off-screen until you press the button, so `verify_narrow.py`
     measured a hidden element and reported a clean 390px. **A closed menu proves
     nothing about whether it opens correctly**, and this project had been
     reporting a phone header as fine on that basis.

     The blur is dropped below the breakpoint and the background goes opaque.
     That is the smallest fix that does not move the nav out of `<header>` (which
     would cost the skip-link order and a24 of the call sites for a blur), and it
     reads better anyway: a translucent bar over a 390px screen shows the reader
     more of what is scrolling underneath, which is the distraction the blur was
     partly hiding. */
  .topbar{backdrop-filter:none;background:rgba(27,20,16,.98)}
  /* THE PAGE SHOWED THROUGH THE OPEN MENU, and neither the nav's z-index nor its
     opacity could fix it. `.grain` is `position:fixed; z-index:50;
     mix-blend-mode:overlay; opacity:.4` and it is a SIBLING of `.topbar`, not a
     descendant - while `.topbar` is `position:sticky; z-index:40`, and a
     positioned element with a z-index creates a stacking context. So the nav's
     `z-index:65` is scoped *inside* the header's context and cannot lift it above
     a sibling at 50. The grain blended the page content over the open menu, which
     is why "Parasocialize", "1956" and a masthead line were all legible through a
     menu with a 99%-opaque background.

     Confirmed by breaking the input on purpose: painting the nav solid red
     removed every trace of the bleed (`tools/probe_bleed.py`). The tell was that
     `elementFromPoint` returned an element inside the nav at every point while
     the screenshot disagreed - **the nav was painting on top and something else
     was painting over it**, which is the only situation in which both can be
     true at once.

     Closed, the grain over the header is the intended film texture and is left
     alone. Open, the menu is the entire screen and a full-page overlay-blend
     texture over it does nothing but reduce contrast. */
  body.nav-open .grain{display:none}
  .menu-btn{display:block}
  body.nav-open{overflow:hidden}
  .nav{position:fixed;inset:0;z-index:65;margin:0;background:#1b1410;
    flex-direction:column;justify-content:flex-start;justify-content:safe center;
    align-items:center;gap:2px;padding:90px 24px 40px;
    /* `flex-wrap:nowrap` is the fix for a real defect found by screenshotting
       the overlay at a SHORT height. The desktop row is `flex-wrap:wrap`, and
       this rule did not reset it - so in the column overlay the items flowed
       into a *second column*, and the last one, Support, ran off the right edge
       (measured: left 708px, right 1048px, in a 1000px viewport). A wrap set for
       a horizontal row is not harmless in a vertical one. */
    flex-wrap:nowrap;
    transform:translateY(-102%);transition:transform .36s cubic-bezier(.4,0,.2,1);overflow-y:auto}
  /* `justify-content:center` on a flex column whose content is TALLER than the
     box puts the first items in unreachable space above the scroll origin - you
     cannot scroll up to them. On a 1000x420 window the twelve links are ~680px,
     so this was reachable-but-broken on any short screen. Declared twice on
     purpose: `flex-start` first as the fallback for anything without `safe`,
     then `safe center`, which centres when it fits and starts at the top when
     it does not. */
  @supports not (justify-content:safe center){.nav{justify-content:flex-start}}
  body.nav-open .nav{transform:translateY(0)}
  /* Stacked, the same labels become headings for each run of links. The
     left hairline is dropped - a vertical rule beside centred text reads as a
     mistake rather than as a divider - and the gap above them opens up so each
     group is announced rather than merely listed. */
  .nav-lab{padding:14px 0 4px;letter-spacing:.24em}
  .nav a+.nav-lab{border-left:0;margin-left:0;padding-left:0}
  .nav-lab:first-child{padding-top:0}
  .nav a{font-size:.72rem;width:min(340px,84vw);text-align:center;padding:15px;border-radius:8px}
  .nav .cta{margin-top:12px}
  body.nav-open .menu-btn span:nth-child(1){transform:translateY(7px) rotate(45deg)}
  body.nav-open .menu-btn span:nth-child(2){opacity:0}
  /* Was written twice, identically, in a copy-paste slip. */
  body.nav-open .menu-btn span:nth-child(3){transform:translateY(-7deg) rotate(-45deg)}
}
@media (max-width:760px){
  .hubs{grid-template-columns:1fr}
  .t8col-list{grid-template-columns:1fr}
.t8col-body b{min-height:0}
  .fdoors{grid-template-columns:1fr}
  .h-outline{grid-template-columns:1fr 1fr}
  .t8-item{padding:18px 16px}
  .t8-head{gap:12px}
  .t8-rank{font-size:2.2rem;min-width:38px}
  .t8-art{width:64px;height:64px}
  .onair{display:none}
  .front,.front-2,.lead{grid-template-columns:1fr}
  .grid-pod,.grid-video,.story{flex-direction:column}
  .story .cover{width:100%}
  .grid-books,.grid-albums,.grid-links{grid-template-columns:repeat(2,1fr)}
  .signal-form{flex-direction:column}
  .section{padding:40px 18px}
  .wrap{padding-inline:18px}
  .foot-tag{text-align:left}
  .punch-grid{gap:10px}.hole{width:24px;height:24px}
  .row2{grid-template-columns:1fr}
}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important}
  .reveal{opacity:1;transform:none}
}




/* ------------------------------------------------- /credits/ and section masthead
   Every photograph on the site is listed once here, with the person who made
   it. The homepage tiles carry none of this, which is why they can look like a
   page instead of a stock library. */
.cr-list{list-style:none;margin:0;padding:0;display:grid;gap:2px}
.cr{display:grid;grid-template-columns:132px 1fr;gap:18px;align-items:center;
  padding:14px 0;border-top:1px solid var(--line)}
.cr-thumb{display:block;border-radius:6px;overflow:hidden;line-height:0;
  box-shadow:0 8px 22px rgba(0,0,0,.5)}
.cr-thumb img{width:100%;height:92px;object-fit:cover;display:block}
.cr-thumb:hover img{filter:brightness(1.18)}
.cr-cap{margin:0 0 5px;font-size:.92rem;line-height:1.4}
.cr-by{margin:0;font-family:var(--label);font-size:.5rem;letter-spacing:.1em;
  color:var(--dimmer);text-transform:uppercase;display:flex;gap:9px;
  align-items:center;flex-wrap:wrap}
.cr-by a{color:var(--dim);border-bottom:1px solid var(--line)}
.cr-by a:hover{color:var(--hot)}
/* the section front's photograph, which is where the credit now lives */
.fig.sec-mast{margin:26px 0 6px;max-width:880px}
/* ------------------------------------------------- photographic card covers
   A card used to always be a gradient with a letter on it. Where a reviewed
   photograph exists the card is the photograph, with a veil at the bottom so
   the kicker stays legible over any frame. The veil is a fixed darkening at
   the foot rather than a colour wash, because the section tiles already carry
   the section colour and a second wash turned every card into a colour field
   with a picture faintly behind it. */
.poster.shot{padding:0}
.poster.shot img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;display:block}
.poster.shot .veil{position:absolute;inset:0;pointer-events:none}
.poster.shot::after{background:linear-gradient(0deg,rgba(0,0,0,.42),transparent 46%)}
/* the photograph at the top of an article, where the credit is discharged */
.fig.article-photo{margin:0 0 26px;max-width:760px}
.fig.article-photo img{max-height:460px;object-fit:cover;width:100%}
.fig.article-photo.borrowed img{filter:saturate(.72) brightness(.9)}
/* ------------------------------------------------- the top 8, as a set piece
   The eight entries run down a rank spine and get smaller as the numbers get
   worse, so the list reads as a ranking at a glance without a single number
   having to be counted. The photographs are all of the audience rather than of
   the cartoons - see the frame note on /top8/ - so the caption sits under the
   picture at full contrast rather than being hidden in a credit line. */
.t8-item[data-rank="1"] .t8-fig img,
.t8-item[data-rank="1"] .t8-plate{height:250px}
.t8-item[data-rank="2"] .t8-fig img,
.t8-item[data-rank="2"] .t8-plate{height:210px}
.t8-item[data-rank="3"] .t8-fig img,
.t8-item[data-rank="3"] .t8-plate{height:180px}
.t8-fig{margin:0;flex:none;width:min(300px,38%)}
.t8-fig img{width:100%;height:150px;object-fit:cover;border-radius:8px;
  box-shadow:0 12px 30px rgba(0,0,0,.55);display:block}
.t8-fig figcaption{font-family:var(--label);font-size:.48rem;letter-spacing:.08em;
  color:var(--dimmer);margin-top:7px;line-height:1.5}
.t8-fig figcaption a{color:var(--dim);border-bottom:1px solid var(--line)}

/* The designed plate. Three of the eight have no freely-licensed photograph and
   this is what they get: the show set in display type, the rank large, and the
   reason it is blank stated rather than disguised with a photograph of
   something adjacent. */
/* A designed title card, not a picture that failed to arrive. It used to carry
   a 45-degree hatch, which is the visual grammar of a placeholder - it says
   "texture standing in for content". Replaced with a lit colour field, an inner
   hairline and the show set in the same display face as the entry titles, so a
   reader's eye reads it as a slug for a moment that has no still, not as a hole
   where an image should be. */
.t8-plate{height:150px;flex:none;width:min(300px,38%);border-radius:8px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:3px;text-align:center;padding:14px 12px;
  background:
    radial-gradient(130% 100% at 50% 4%,
      color-mix(in srgb,var(--c) 58%,#000) 0%,
      color-mix(in srgb,var(--c) 20%,#170e08) 58%,#120b07 100%);
  box-shadow:inset 0 0 0 1px rgba(255,246,234,.10),0 14px 34px rgba(0,0,0,.55)}
.t8-plate-n{font-family:var(--label);font-size:.46rem;letter-spacing:.2em;
  text-transform:uppercase;color:color-mix(in srgb,var(--c) 70%,#fff6ea)}
.t8-plate-t{font-family:var(--serif);font-weight:900;font-size:clamp(1.5rem,4vw,2.3rem);
  line-height:1;color:#fff6ea;letter-spacing:-.03em;max-width:11ch}
.t8-plate-y{font-family:var(--label);font-size:.5rem;letter-spacing:.24em;
  color:rgba(255,246,234,.62);margin-top:6px;
  padding-top:6px;border-top:1px solid rgba(255,246,234,.18)}

/* the frame note - the page's argument, before the list rather than in a
   footnote at the bottom where a licensing caveat belongs and nobody reads */
.t8-frame{margin:30px 0 0;padding:22px 24px;border:1px solid var(--line2);
  border-radius:12px;background:
  linear-gradient(150deg,rgba(255,90,26,.07),transparent 58%),
  rgba(255,246,234,.022);max-width:74ch}
.t8-frame .kicker{margin:0 0 10px;color:var(--hot)}
.t8-frame p{margin:0 0 11px;font-size:1.02rem;line-height:1.6}
.t8-frame p:last-child{margin:0}
.t8-frame b{color:#fff6ea}
.t8-frame-s{font-family:var(--label);font-size:.56rem;letter-spacing:.11em;
  text-transform:uppercase;color:var(--dimmer);line-height:1.65}

/* the homepage strip, photo-led */
.t8col-art{background:linear-gradient(150deg,#2a1a10,#140c07)}
.t8col-photo{position:relative}
.t8col-photo::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to top,rgba(10,6,4,.8),rgba(10,6,4,.05) 60%)}
.t8-sharedlaw{margin:0 0 30px;padding:14px 18px;border:1px solid var(--line2);
  border-radius:9px;background:rgba(255,246,234,.022);font-size:.95rem;line-height:1.6;
  max-width:78ch;color:var(--dim)}
.t8-sharedlaw b{color:#fff6ea}
.t8-sharedlaw a{color:var(--hot);border-bottom:1px solid rgba(255,90,31,.4)}
.t8-sharedlaw-n{font-family:var(--label);font-size:.55rem;letter-spacing:.18em;
  color:var(--hot);margin-right:10px}

/* ------------------------------------------------- /citations/
   The sourcing backlog, in public. Four numbers first, because a table of 122
   rows is a filing cabinet and four numbers are an argument. The degree
   column is the useful part: it says how much of the atlas points at each
   entry, which is what makes the order a fix order rather than a list. */
.cit-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));
  gap:2px;margin:30px 0 0;border-top:1px solid var(--line)}
.cit-stats>div{padding:18px 16px;border-bottom:1px solid var(--line)}
.cit-stats b{display:block;font-family:var(--serif);font-weight:900;
  font-size:clamp(1.8rem,4vw,2.6rem);line-height:1;color:var(--hot)}
.cit-stats span{display:block;margin-top:7px;font-family:var(--label);
  font-size:.52rem;letter-spacing:.13em;text-transform:uppercase;color:var(--dim);
  line-height:1.5}
.cit{width:100%;border-collapse:collapse;margin:16px 0 0;font-size:.92rem}
.cit th{text-align:left;font-family:var(--label);font-size:.5rem;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dimmer);padding:0 12px 9px 0;
  border-bottom:1px solid var(--line2);font-weight:400}
.cit td{padding:10px 12px 10px 0;border-bottom:1px solid var(--line);
  vertical-align:top}
.cit-d{font-family:var(--serif);font-weight:900;font-size:1.15rem;color:var(--hot);
  width:52px;text-align:right;padding-right:14px}
.cit-y{display:block;font-family:var(--label);font-size:.5rem;letter-spacing:.11em;
  text-transform:uppercase;color:var(--dimmer);margin-top:3px}
.cit-k{font-family:var(--label);font-size:.55rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--dim);width:110px}
.cit-m{color:var(--dim);font-size:.86rem;width:38%}
.cit-ok{color:#7bd88f;font-family:var(--label);font-size:.55rem;letter-spacing:.11em;
  text-transform:uppercase}
.cit tbody tr:hover{background:rgba(255,90,26,.045)}
@media (max-width:700px){.cit-k,.cit-m{width:auto;display:block}
  .cit th:nth-child(3),.cit td:nth-child(3){display:none}}

/* ============================================================ encyclopedia
   The entry sub-pages went from a title, two sentences and two links to
   something you can actually read. These are the new blocks. */

/* --- the neighbourhood diagram, redrawn from the atlas relations --- */
.ent-graph{margin:30px 0 8px;padding:18px 14px 12px;border:1px solid var(--line);
  border-radius:14px;background:linear-gradient(180deg,rgba(255,255,255,.022),transparent)}
.ent-graph svg{display:block;width:100%;max-width:340px;height:auto;margin:0 auto}
.ent-graph svg a text{font-family:var(--label)}
.ent-graph svg a:hover circle{opacity:1;stroke:var(--ink);stroke-width:1.6}
.ent-graph-cap{display:flex;flex-wrap:wrap;gap:14px;justify-content:center;
  margin-top:10px;font-family:var(--label);font-size:.52rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dim)}
.ent-graph-cap .lg{display:inline-flex;align-items:center;gap:6px}
.ent-graph-cap .dot{width:8px;height:8px;border-radius:50%;display:inline-block}
.ent-graph-cap i{width:16px;height:0;border-top:1px solid var(--line2);display:inline-block}
.ent-graph-cap .lg-in{border-top-style:dashed}

/* --- same story, in sequence --- */
.ent-seq{margin:30px 0;padding:16px 18px;border-left:2px solid var(--gold);
  background:rgba(255,207,92,.045);border-radius:0 10px 10px 0}
.ent-seq .seq{margin:0;font-size:1.02rem;line-height:2.1;color:var(--ink)}
.ent-seq .seq a{border-bottom:1px solid var(--line2)}
.ent-seq .seq a:hover{color:var(--gold);border-color:var(--gold)}
.ent-seq .seq-y{color:var(--dim);font-family:var(--label);font-size:.62rem;
  letter-spacing:.1em;margin:0 7px 0 3px}

/* --- where it sits in the century --- */
.ent-era{margin:30px 0}
.era-bar{position:relative;height:2px;background:var(--line2);border-radius:2px;
  margin:16px 0 9px}
.era-here{position:absolute;top:50%;width:11px;height:11px;margin:-5.5px 0 0 -5.5px;
  border-radius:50%;background:var(--gold);box-shadow:0 0 0 4px rgba(255,207,92,.16)}
.era-lab{display:flex;justify-content:space-between;gap:12px;margin:0;
  font-family:var(--label);font-size:.58rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--dim)}
.era-lab b{color:var(--gold);font-weight:600}

/* --- provenance --- */
.ent-prov{margin:30px 0}
.prov{list-style:none;margin:12px 0 0;padding:0;border-top:1px solid var(--line)}
.prov li{display:grid;grid-template-columns:88px 1fr;gap:6px 14px;padding:12px 0;
  border-bottom:1px solid var(--line);font-size:.88rem;line-height:1.6}
.prov-status{grid-row:1/3;font-family:var(--label);font-size:.53rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--dim);padding-top:3px}
.prov-claim{color:var(--ink)}
.prov-cite{color:var(--dim);font-size:.8rem}
.prov-cite a{color:var(--teal)}
.prov-ok .prov-status{color:#7bd88f}
.prov-warn .prov-status{color:var(--gold)}
.prov-dim .prov-status{color:var(--dim);opacity:.7}

/* --- lanes with their own argument, not just a label --- */
.lane-note{margin:16px 0 0;font-size:.94rem;line-height:1.7;color:var(--dim);
  padding-left:14px;border-left:2px solid var(--line2)}
.lane-note b{color:var(--ink)}

/* --- media chips --- */
.chip-m{text-transform:capitalize;opacity:.78}

/* --- incoming edges marked as such --- */
.xref-in{border-left:2px dashed var(--line2)}
.xref-in span::after{content:" → here";color:var(--dim);opacity:.7}

/* ============================================ encyclopedia: ways in
   The index had one entrance. These are the medium chips and the same-story
   clusters, so the 175 entries are reachable as "the AI ones" and "the Replika
   ones" and not only as "everything, by year". */

/* --- medium chips: count as a bar, click to filter the table below --- */
.medchips{display:grid;grid-template-columns:repeat(auto-fill,minmax(158px,1fr));
  gap:8px;margin-top:14px}
.medchip{display:block;padding:11px 13px;border:1px solid var(--line);border-radius:10px;
  text-decoration:none;background:rgba(255,255,255,.014);transition:border-color .13s,background .13s}
.medchip:hover{border-color:var(--line2);background:rgba(255,255,255,.035)}
.medchip.on{border-color:var(--gold);background:rgba(255,207,92,.09)}
.medchip b{display:block;color:var(--ink);font-weight:600;font-size:.92rem;line-height:1.25}
.medchip-bar{display:block;height:2px;background:var(--line);border-radius:2px;
  margin:8px 0 6px;overflow:hidden}
.medchip-bar i{display:block;height:100%;background:var(--teal);opacity:.72}
.medchip-n{font-family:var(--label);font-size:.55rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dim)}

/* --- same-story clusters --- */
.waysin{margin:34px 0 6px}
.waysin-note{max-width:60ch;margin:0 0 16px;font-size:.92rem;line-height:1.7;color:var(--dim)}
.clus{margin:0 0 12px;padding:13px 15px;border:1px solid var(--line);border-radius:11px;
  background:linear-gradient(180deg,rgba(255,255,255,.016),transparent)}
.clus-h{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin:0 0 8px;
  font-size:1rem;color:var(--ink)}
.clus-n{font-family:var(--label);font-size:.55rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dim)}
.clus-seq{margin:0;line-height:1.95;font-size:.95rem}
.clus-seq a{display:inline-block;color:var(--ink);border-bottom:1px solid transparent}
.clus-seq a:hover{color:var(--gold);border-bottom-color:var(--gold)}
.clus-seq a i{font-style:normal;font-family:var(--label);font-size:.56rem;
  letter-spacing:.08em;color:var(--dim);margin-left:5px}

/* ============================================ the timeline gets a shape
   It was a flat list with era headings, which is a list. The density strip
   shows where the record is thick and thin, and each era is labelled with what
   that band is actually made of, computed from the data rather than asserted. */

/* minmax(0,1fr), not 1fr: a bare 1fr track has an automatic minimum of
   min-content, so the nowrap decade labels below set the floor and 11 of them
   overflowed a 390px viewport by 125px. The labels wrap to two lines instead,
   which keeps the decade range readable rather than hiding it. */
.tl-density{display:grid;grid-template-columns:repeat(11,minmax(0,1fr));gap:3px;
  align-items:end;height:96px;margin:22px 0 8px;padding:0 2px}
.tl-den{flex:1;display:flex;flex-direction:column;justify-content:flex-end;
  align-items:center;height:100%;text-decoration:none;position:relative;
  min-width:0}
.tl-den i{display:block;width:100%;background:linear-gradient(180deg,var(--teal),rgba(0,232,192,.22));
  border-radius:2px 2px 0 0;min-height:2px;transition:background .13s}
.tl-den:hover i{background:linear-gradient(180deg,var(--gold),rgba(255,207,92,.3))}
.tl-den b{font-family:var(--label);font-size:.5rem;letter-spacing:.06em;color:var(--dim);
  margin-top:5px;font-weight:400;line-height:1.2;text-align:center;overflow-wrap:anywhere}
.tl-den em{position:absolute;top:-15px;font-style:normal;font-family:var(--label);
  font-size:.55rem;color:var(--teal)}
.tl-den:hover b{color:var(--gold)}

/* --- era character: what this band is mostly made of --- */
.tl-era-note{display:block;margin:2px 0 14px;font-size:.88rem;line-height:1.65;
  color:var(--dim);max-width:74ch}
.tl-era-note b{color:var(--ink);font-weight:600}
.tl-era-h .tl-era-shape{font-family:var(--label);font-size:.58rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dim);font-weight:400}

/* ============================================ the entry hero
   A reviewed photograph, or the entry's own title plate. Same slot either way,
   so the 175 pages have a picture without any of them pretending to be a photo
   of a television show. */
.ent-hero{margin:26px 0 6px}
.ent-hero img{display:block;width:100%;height:auto;border-radius:12px;
  border:1px solid var(--line);background:var(--ink)}
.ent-hero.plate img{border-color:var(--line2)}
.ent-hero figcaption{margin-top:9px;font-size:.8rem;line-height:1.6;color:var(--dim);
  display:flex;gap:10px;flex-wrap:wrap;justify-content:space-between}
.ent-hero .ent-by{font-family:var(--label);font-size:.58rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dimmer);white-space:nowrap}

/* A title plate is 16:9 and is the only picture on the page, so it can afford
   to be large. Below the phone breakpoint it keeps the ratio rather than
   cropping, because the mark and the year are the composition. */
@media (max-width:640px){.ent-hero{margin:20px 0 4px}
  .ent-hero img{border-radius:9px}}

/* ------------------------------------------------------------- the taxonomy
   A generated page with no hand-written layout, so everything here is generic
   enough to survive the taxonomy changing: cards, summaries, and a list of
   entries with the reason for the placement underneath. --c is supplied per
   category by the generator, same convention as the story cards. */
.tx-cat{margin:0 0 30px;padding-left:14px;border-left:3px solid var(--c)}
.tx-cat h2{font-size:clamp(1.15rem,2.6vw,1.6rem);line-height:1.2;margin:0 0 8px;
  max-width:34ch;font-weight:800}
.tx-note-big{color:var(--dim);font-size:.92rem;line-height:1.6;margin:0 0 16px;max-width:60ch}
.tx-sub{border:1px solid var(--line);border-radius:8px;margin:0 0 8px;
  background:var(--ink)}
.tx-sub>summary{display:flex;align-items:baseline;gap:10px;padding:11px 14px;
  cursor:pointer;list-style:none}
.tx-sub>summary::-webkit-details-marker{display:none}
.tx-sub[open]>summary{border-bottom:1px solid var(--line)}
.tx-name{font-weight:700;font-size:.98rem;flex:1}
.tx-n{font-family:var(--label);font-size:.62rem;letter-spacing:.1em;
  color:var(--c);background:color-mix(in srgb,var(--c) 15%,transparent);
  padding:2px 7px;border-radius:2px;min-width:26px;text-align:center}
.tx-def,.tx-note,.tx-empty,.tx-anchor{padding:0 14px;margin:12px 0 0;
  font-size:.88rem;line-height:1.62;max-width:66ch}
.tx-note{color:var(--dim)}
/* test / not / mechanism. Three cells rather than three paragraphs: the
   difference between a sub-category and its neighbour is usually a single
   discriminator, and a reader comparing two should be able to scan one
   column rather than re-read prose. */
.tx-triad{display:grid;gap:1px;margin:14px 0 0;padding:0 14px;
  grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.tx-triad-c{background:var(--ink2);border-top:2px solid var(--line);
  padding:10px 12px}
.tx-triad-c p{margin:6px 0 0;font-size:.84rem;line-height:1.6;color:var(--dim)}
.tx-test{border-top-color:var(--c)}
.tx-not{border-top-color:var(--dimmer)}
.tx-mech{border-top-color:var(--c);opacity:.96}
.tx-triad-k{font-family:var(--label);font-size:.58rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--c)}
.tx-not .tx-triad-k{color:var(--dimmer)}
.tx-anchor{display:inline-block;font-family:var(--label);font-size:.6rem;
  letter-spacing:.09em;text-transform:uppercase;color:var(--dimmer)}
.tx-anchor a{color:inherit;text-decoration:none;border-bottom:1px solid var(--line)}
.tx-anchor a:hover{color:var(--ink);border-bottom-color:var(--c)}
.tx-empty{color:var(--dimmer);font-style:italic}
.tx-entries{list-style:none;margin:12px 0 0;padding:0 0 4px}
.tx-entries li{border-top:1px solid var(--line2)}
.tx-entries a{display:block;padding:9px 14px;text-decoration:none;color:inherit}
.tx-entries a:hover{background:var(--ink2)}
.tx-entries b{font-weight:600;margin-right:10px}
.tx-why{font-family:var(--label);font-size:.6rem;letter-spacing:.09em;
  text-transform:uppercase;color:var(--dimmer)}
.tx-r{display:block;margin-top:3px;color:var(--dim);font-size:.82rem;line-height:1.5}
.tx-regs{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
.tx-reg{border:1px solid var(--line);border-radius:8px;background:var(--ink);
  padding:12px 14px}
.tx-reg>summary{cursor:pointer;font-size:.95rem;list-style:none}
.tx-reg>summary::-webkit-details-marker{display:none}
.tx-reg .tx-def,.tx-reg .tx-note,.tx-reg .tx-anchor{padding:0;margin:8px 0 0}
/* inside a register card the cells must line up with the card's own text.
   The attachment axis wants the 14px gutter; here it would indent the triad
   away from the definition it belongs to. The grid also collapses to one
   column at this width, which is correct - three narrow columns of prose
   would be worse. */
.tx-reg .tx-triad{padding:0;margin:11px 0 0}
.tx-reg .tx-triad-c{padding:9px 11px}
.tx-reg .tx-triad-c p{font-size:.82rem}
/* The otherness shelf prints its own population on the summary line, because a
   member shown to a reader with nothing on it has to say so where the reader
   can see it before opening it. A bare 0 would read as a tally of something
   else, so an empty shelf says the words instead. */
.tx-reg>summary{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.tx-reg>summary>b{flex:1 1 auto;min-width:0}
.tx-count{font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--dimmer);font-variant-numeric:tabular-nums}
.tx-count-0{color:var(--dimmer);opacity:.75;letter-spacing:.04em;
  text-transform:none;font-style:italic}
.tx-lit{list-style:none;margin:12px 0 0;padding:0;max-width:78ch}
.tx-lit li{border-top:1px solid var(--line2);padding:10px 0;
  font-size:.84rem;line-height:1.6;color:var(--dim)}
.tx-lit b{color:var(--ink)}
/* anchor targets must not be hidden under the sticky nav when linked to */
.tx-lit li:target{background:var(--ink2);
  box-shadow:-14px 0 0 var(--ink2),14px 0 0 var(--ink2)}
.ent-tx{margin:22px 0 0}
.ent-tx a{display:inline-flex;align-items:baseline;gap:10px;padding:7px 13px;
  border:1px solid var(--line);border-left:3px solid var(--c);border-radius:6px;
  text-decoration:none;color:var(--ink);background:var(--ink)}
.ent-tx a:hover{background:var(--ink2)}
.ent-tx b{font-family:var(--label);font-size:.6rem;letter-spacing:.1em;
  color:var(--c);font-weight:500}
.ent-tx span{font-size:.86rem}
.tx-mig{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.tx-migr{border:1px solid var(--line);border-radius:8px;background:var(--ink);padding:11px 14px}
.tx-migr>summary{cursor:pointer;font-size:.88rem;list-style:none;
  display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.tx-migr>summary::-webkit-details-marker{display:none}
.tx-migr b{font-family:var(--label);font-size:.62rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--dimmer);font-weight:500}
.tx-arrow{color:var(--dimmer)}
.tx-migr .tx-def{padding:0;margin:9px 0 0;color:var(--dim)}
