/* t42:music Terminal — what this product adds to the house layer.
 *
 * house.css carries the taste. This file carries only the objects the taste does not know
 * about: a range, a sufficiency band, a provenance link, a measured bar. Nothing here
 * restates a house rule, and nothing here introduces a radius, a pill or a card.
 */

/* ── a range, which is how every currency figure on this product is shown ─────────── */
.rng{display:inline-flex;flex-direction:column;gap:2px;align-items:flex-end}
.rng b{font:700 14px/1 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums}
.rng .sp{font:400 11px/1.3 var(--sans);color:var(--ink3);font-variant-numeric:tabular-nums;
  white-space:nowrap}
td .rng{align-items:flex-end}

/* ── the evidence-sufficiency band. A rule of colour under a word, never a pill. ──── */
/* The library draws the badge. This draws the state's shape, which section 5.4 requires and
   daisyUI has no opinion about: a reader who cannot separate green from amber still reads a
   different mark. Verified both sides is a turned square, because it is the one state that is
   settled rather than in motion. */
.bnd{white-space:nowrap}
.bnd::before{content:"";width:6px;height:6px;flex:none;background:currentColor}
.bnd.vitality{color:var(--vitality)}.bnd.proven{color:var(--proven)}
.bnd.caution{color:var(--caution)}.bnd.leak{color:var(--leak)}
.bnd.proven::before{transform:rotate(45deg);width:6px;height:6px}
.bnd.dim::before{opacity:.55}
/* Verified both sides is the one state that is settled rather than in motion, and a square
   that has been turned is legible as a different state without relying on the hue. */
.bnd.proven{color:var(--ink)}
.bnd.proven::before{background:var(--proven);transform:rotate(45deg);width:6px;height:6px}
.bnd.caution{color:var(--ink2)}.bnd.caution::before{background:var(--caution)}
.bnd.dim{color:var(--ink3)}

/* ── provenance by hyperlink. Section 9.7: no number without a route to its source. ─ */
.src{color:var(--ink3);font:400 11.5px/1.4 var(--sans);border-bottom:1px solid var(--rule2)}
.src:hover{color:var(--live);border-bottom-color:var(--live)}

/* ── a measured bar. Rule 4 of section 6: every ornament is a measurement. ────────── */
.bars{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule)}
.bars .b{display:grid;grid-template-columns:1fr 240px 96px;gap:16px;align-items:center;
  padding:9px 0;border-bottom:1px solid var(--rule)}
.bars .b span{font:400 12.5px/1.4 var(--sans);color:var(--ink2);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bars .b i{display:block;height:6px;background:var(--rule2)}
.bars .b i u{display:block;height:100%;background:var(--ink2);text-decoration:none}
.bars .b.live i u{background:var(--live)}
.bars .b.leak i u{background:var(--leak)}
.bars .b.caution i u{background:var(--caution)}
.bars .b em{font:500 12.5px/1 var(--sans);font-style:normal;text-align:right;color:var(--ink);
  font-variant-numeric:tabular-nums}

/* ── the ladder. A staged sequence, drawn as one. ────────────────────────────────── */
.steps .s b{display:block;font:500 11.5px/1.5 var(--sans);color:var(--ink3);margin-bottom:10px}
.steps .s .v{font:700 22px/1.1 var(--sans);letter-spacing:-.03em;color:var(--ink);
  font-variant-numeric:tabular-nums}
.steps .s .v.off{color:var(--ink3)}
.steps .s p{margin:9px 0 0;font:400 11.5px/1.5 var(--sans);color:var(--ink3);max-width:34ch}
.steps .s.now .v{color:var(--live)}
.steps .s.now b{color:var(--live)}

/* ── two-column reading layout, for a surface that is one object rather than a wall ── */
.cols{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(280px,.65fr);gap:44px;
  align-items:start}
@media (max-width:1100px){.cols{grid-template-columns:1fr}}

/* ── the notice. Stated once per surface, never decorated. ──────────────────────── */
.notice{border-left:2px solid var(--caution);padding:2px 0 2px 14px;margin:20px 0 0;
  font:400 11.5px/1.6 var(--sans);color:var(--ink2);max-width:80ch}
.notice b{color:var(--ink);font-weight:500;display:block;margin-bottom:4px}
.notice.hard{border-left-color:var(--leak)}
/* Neither a caution nor a leak: a pointer to a figure that lives at another altitude.
   `.notice` defaults to the caution border, so a note with no modifier reads as a
   warning, and `soft` was written without ever being defined. */
.notice.quiet{border-left-color:var(--rule2)}
.notice.ok{border-left-color:var(--vitality)}

/* ── the drawer's evidence chain ─────────────────────────────────────────────────── */
.chain{border-top:1px solid var(--rule);margin-top:6px}
.chain .a{display:grid;grid-template-columns:18px 1fr auto;gap:10px;padding:9px 0;
  border-bottom:1px solid var(--rule);align-items:baseline}
.chain .a .m{font:500 11px/1.4 var(--mono);color:var(--ink)}
.chain .a .k{font:400 11.5px/1.4 var(--sans);color:var(--ink2);min-width:0;word-break:break-word}
.chain .a .t{font:500 11px/1.4 var(--sans);text-align:right;white-space:nowrap}
.chain .a.known .t{color:var(--vitality)}
.chain .a.blocked .t{color:var(--caution)}

/* ── a wall of small rows, for the catalogue ─────────────────────────────────────── */
/* ── the wall and the object, carried from the lab, which is the surface the house style
 * is set against. Rule 9: a surface is either the wall or the single object, and half of one
 * over half of the other is the look of nothing in particular. ───────────────────────────── */
/* ── the releases, at release grain ───────────────────────────────────────────────────
   Not a card. There is no panel, no border and no fill: a cover sits on the ground with its
   own name under it, which is how a sleeve has been presented since sleeves existed. The
   spacing between them is the only thing separating one from the next. */
.rels{display:grid;grid-template-columns:repeat(auto-fill,minmax(184px,1fr));
  gap:clamp(20px,2.2vw,34px) clamp(16px,1.8vw,26px);padding:clamp(22px,2.6vw,34px) 0
  clamp(26px,3vw,40px);border-top:1px solid var(--rule)}
.rel{display:block;text-align:left;width:100%;padding:0}
.rel-art{position:relative;display:block;aspect-ratio:1;background:var(--plate);overflow:hidden;
  border-radius:var(--r-media)}
.rel-art img{width:100%;height:100%;object-fit:cover;
  transition:transform var(--dur) var(--ease),filter var(--dur) var(--ease)}
.rel:hover .rel-art img,.rel:focus-visible .rel-art img{transform:scale(1.04);filter:brightness(1.08)}
.rel-art .none{position:absolute;inset:0;display:flex;align-items:flex-end;padding:14px;
  background:var(--plate)}
.rel-art .none b{font:700 14px/1.25 var(--sans);letter-spacing:-.014em;color:var(--ink2)}
.rel-st{position:absolute;left:0;right:0;bottom:0;height:3px;font-style:normal}
.rel-t{display:block;margin:12px 0 0;font:600 13.5px/1.35 var(--sans);letter-spacing:-.012em;
  color:var(--ink)}
.rel:hover .rel-t,.rel:focus-visible .rel-t{color:var(--live)}
.rel-m{display:block;margin:5px 0 0;font:400 11.5px/1.4 var(--sans);color:var(--ink2);
  font-variant-numeric:tabular-nums}
.rel-m em{font-style:normal;color:var(--ink3);margin-left:9px}
.rel-c{display:block;margin:3px 0 0;font:400 11.5px/1.4 var(--sans);color:var(--ink3)}

.wall{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--cell,150px),1fr));
  gap:1px;background:var(--rule);border-top:1px solid var(--rule);
  border-bottom:1px solid var(--rule)}
.cell{position:relative;background:var(--bg);aspect-ratio:1;overflow:hidden;
  padding:0;text-align:left;width:100%}
.cell img{width:100%;height:100%;object-fit:cover;
  transition:filter var(--dur) var(--ease)}
.cell:hover img{filter:brightness(1.12)}
/* Artwork or nothing. A release with no cover is set, never decorated. */
.cell .none{position:absolute;inset:0;padding:12px;display:flex;flex-direction:column;
  justify-content:flex-end;background:var(--plate)}
.cell .none b{font:700 11.5px/1.25 var(--sans);letter-spacing:-.01em;color:var(--ink)}
.cell .none span{font:400 11px/1.35 var(--sans);color:var(--ink3);margin-top:3px}
.cell .none em{font:400 10px/1 var(--mono);color:var(--ink3);font-style:normal;margin-top:9px}
.cell .st{position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--rule2)}
.cell .cap{position:absolute;inset:auto 0 3px 0;padding:9px 10px 11px;opacity:0;
  background:linear-gradient(transparent,rgba(0,0,0,.92));transition:opacity var(--dur) var(--ease)}
.cell:hover .cap,.cell:focus-visible .cap{opacity:1}
.cell .cap b{display:block;font:700 11.5px/1.25 var(--sans);letter-spacing:-.01em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--on-media)}
.cell .cap span{display:block;font:400 11px/1.3 var(--sans);color:var(--on-media-2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Dormancy is drawn by the absence of light, never by a hue. */
.cell.dim{opacity:.34}

.more{padding:22px 0 40px;display:flex;gap:16px;align-items:center;
  font:500 11.5px/1 var(--sans);color:var(--ink3)}
.more button{font:500 11.5px/1 var(--sans);color:var(--ink);border-bottom:2px solid var(--live);padding-bottom:4px}

.obj{display:grid;grid-template-columns:minmax(280px,40%) 1fr;gap:0;
  border-top:1px solid var(--rule)}
@media (max-width:900px){.obj{grid-template-columns:1fr}}
.obj .art{position:relative;background:var(--plate);border-right:1px solid var(--rule);
  aspect-ratio:1}
.obj .art img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0}
.obj .art .none{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font:500 11.5px/1 var(--sans);color:var(--ink3)}
.obj .side{padding:30px 0 40px 32px;min-width:0}
@media (max-width:900px){.obj .side{padding-left:0}}
.obj h2{font-family:var(--narrow);font-weight:700;text-transform:uppercase;font-size:28px;
  line-height:1;letter-spacing:-.02em;margin:0 0 6px;text-wrap:balance;color:var(--ink)}
.obj .by{font:400 14px/1.4 var(--sans);color:var(--ink2);margin:0 0 22px}
.obj .stline{display:inline-flex;align-items:center;gap:8px;font:500 11.5px/1 var(--sans);
  margin:0 0 24px}
.obj .stline i{width:9px;height:9px;font-style:normal;flex:none}
.sig{margin:26px 0 0}
.sig h3{font:500 11.5px/1 var(--sans);color:var(--ink3);margin:0 0 12px}
.sig p{display:flex;gap:11px;align-items:baseline;margin:0;padding:10px 0;
  border-top:1px solid var(--rule);font:400 12.5px/1.5 var(--sans);color:var(--ink)}
.sig p i{width:3px;height:13px;flex:none;font-style:normal;position:relative;top:2px}
.sig p small{display:block;color:var(--ink3);font:400 11.5px/1.5 var(--sans);margin-top:3px}
.back{font:500 11.5px/1 var(--sans);color:var(--ink3);margin-bottom:20px;display:inline-block}
.back:hover{color:var(--ink)}
.prov{margin:30px 0 0;padding-top:16px;border-top:1px solid var(--rule);
  font:400 11.5px/1.65 var(--sans);color:var(--ink3);max-width:62ch}

/* the poster, used once, on the front door only */
/* Rule 3: large type is allowed uppercase, in the condensed cut, at negative tracking, over
 * media. Never over a panel and never as a lone number. The media is a real cover from this
 * catalogue and the caption says which, so the ornament is still a measurement. */
.poster{position:relative;margin:0 calc(var(--gutter) * -1);
  height:clamp(280px,33vw,392px);overflow:hidden;border-bottom:1px solid var(--rule);
  background:#0A0A0A}   /* media, not the page. Dark in both themes. */
.poster>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  filter:grayscale(1) contrast(1.08) brightness(.6);transform:scale(1.03)}
.poster .veil{position:absolute;inset:0;
  background:linear-gradient(90deg,rgba(0,0,0,.92) 0%,rgba(0,0,0,.6) 54%,rgba(0,0,0,.22) 100%)}
.poster .in{position:relative;height:100%;display:flex;flex-direction:column;
  justify-content:flex-end;padding:0 var(--gutter) 26px;max-width:1060px}
.poster h1{font-family:var(--narrow);font-weight:700;text-transform:uppercase;
  font-size:clamp(28px,5.6vw,61px);line-height:.94;letter-spacing:-.022em;margin:0;
  max-width:none;color:var(--on-media);text-wrap:balance}
.poster h1 em{font-style:normal;color:var(--live)}
.poster .sub{margin:16px 0 0;font:400 14px/1.5 var(--sans);color:var(--on-media-2);max-width:60ch}
.poster .meta{margin:18px 0 0;font:500 11.5px/1 var(--sans);color:var(--on-media-2);display:flex;gap:16px;flex-wrap:wrap;
  align-items:center}
.poster .meta a{color:var(--on-media-2);border-bottom:1px solid rgba(255,255,255,.28)}
.poster .meta a:hover{color:var(--live)}
.poster.noart>img{display:none}
.poster.noart .veil{background:none}

/* The companion figure. The recurring rate is the poster and the one-time back-claim is the
   other half of the same exposure, so it sits directly under the poster on the ground rather
   than as a fifth cell in a strip where it would read as one more score. It is not a poster of
   its own: rule 3 allows one per surface, and this is a figure with a sentence beside it. */
.second{display:grid;grid-template-columns:minmax(220px,auto) 1fr;gap:24px;align-items:baseline;
  padding:20px 0 22px;border-bottom:1px solid var(--rule)}
.second .fig b{display:block;font:700 clamp(22px,2.6vw,28px)/1.05 var(--sans);
  letter-spacing:-.03em;color:var(--ink);font-variant-numeric:tabular-nums}
.second .fig span{display:block;margin-top:7px;font:500 11.5px/1 var(--sans);color:var(--ink2)}
.second p{margin:0;font:400 11.5px/1.6 var(--sans);color:var(--ink3);max-width:78ch}
@media (max-width:760px){.second{grid-template-columns:1fr;gap:12px}}

/* A group heading inside a panel of bars. The two value types are different commercial
   objects and were rendered as one undifferentiated list. */
.poolhead{display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  margin:20px 0 2px;padding:0 0 8px;border-bottom:1px solid var(--rule);
  font:500 11.5px/1.4 var(--sans);color:var(--ink)}
.poolhead:first-of-type{margin-top:4px}
.poolhead span{font:400 11px/1.4 var(--sans);letter-spacing:0;text-transform:none;
  text-align:right}

/* Rows and headers, loosened. 8px of vertical padding on a row carrying a cover, a title and
   a credit put three lines of content in 56px, and 9.5px headers over it were below the size at
   which a column name is read rather than decoded. */
.tight td,.tight th{padding-top:var(--s3);padding-bottom:var(--s3)}
.right{text-align:right}
.nowrap{white-space:nowrap}

/* an ordered list of asks. Numbered by the rule, not by a marker. */
ol.todo{list-style:none;margin:0;padding:0;counter-reset:t}
ol.todo li{counter-increment:t;padding:14px 0 14px 34px;border-bottom:1px solid var(--rule);
  position:relative}
ol.todo li:last-child{border-bottom:0}
ol.todo li::before{content:counter(t);position:absolute;left:0;top:15px;
  font:500 11px/1 var(--mono);color:var(--ink3)}
ol.todo b{display:block;font:700 12.5px/1.35 var(--sans);color:var(--ink);margin-bottom:5px}
ol.todo span{display:block;font:400 11.5px/1.55 var(--sans);color:var(--ink2);margin-top:4px}
ol.todo span.faint{color:var(--ink3)}

/* the search bar sits on its own rule so the filter chips can scroll without squeezing it */
#qbar{border-bottom:1px solid var(--rule)}
#qbar .h-q{flex:1;border-left:1px solid var(--rule)}

ul.rules{margin:0;padding-left:16px;list-style:none}
ul.rules li{position:relative;font:400 11.5px/1.6 var(--sans);color:var(--ink3);margin:6px 0}
ul.rules li::before{content:'';position:absolute;left:-16px;top:9px;width:7px;height:1px;
  background:var(--rule2)}

/* a bar row whose label carries a sentence rather than a name */
.bars.wrap .b{grid-template-columns:1fr 200px 60px;align-items:start;padding:12px 0}
.bars.wrap .b span{white-space:normal;overflow:visible;line-height:1.5}
.bars.wrap .b i{margin-top:5px}

/* ── accessibility overrides on the house layer ───────────────────────────────────────
 * Measured against the committed ground with the sRGB relative-luminance formula, on
 * 2026-08-29:
 *
 *   --ink   #FFFFFF  21.00 : 1
 *   --ink2  #8A8A8A   6.08 : 1
 *   --ink3  #575757   2.91 : 1   fails WCAG 2.2 AA for text at any size
 *   --live  #00E08A  12.03 : 1
 *
 * The PRD makes WCAG 2.2 AA including a dark theme a non-functional requirement, and --ink3
 * carries a large share of the secondary text on every surface here. It is raised to the
 * lowest value that clears 4.5 : 1 and no further, so the three-step ink ladder the house
 * layer sets up is preserved. This is an override rather than an edit to house.css, because
 * house.css is a copy of the workbench layer and the change belongs upstream. It is recorded
 * in the known gaps in README.md as one to raise.
 */
/* --ink3 is measured against the ground it is actually drawn on, which is the panel at
   #080808 and not the page at #000000. #767676 clears 4.62 : 1 on pure black and only
   4.41 : 1 here, so it failed AA everywhere it is actually used. #7C7C7C is 4.80 : 1 on
   #080808 and keeps headroom for the next panel that is a shade lighter again. */
/* The quiet ink is calculated against the real ground rather than the page: see the dark
   block in house.css, where #7C7C7C is 4.80 : 1 on the #080808 panels it is used over.
   It lives there because on paper that number measures nothing. */

/* The rail's foot. `.runbar` takes margin-top:auto from the house layer and everything after
   it was left unstyled, so the signed-in name and the sign-out control ran together as one
   string against the bottom edge of the viewport on every page. */
.rail .whoami{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:12px 16px 16px;border-top:1px solid var(--rule)}
.rail .whoami b{font:600 11.5px/1.4 var(--sans);color:var(--ink2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail .whoami button{flex:none;background:none;border:0;padding:0;cursor:pointer;
  font:500 11px/1.4 var(--sans);color:var(--ink3);
  border-bottom:1px solid transparent;transition:color var(--dur) var(--ease)}
.rail .whoami button:hover{color:var(--ink);border-bottom-color:var(--rule2)}
.rail .runbar{margin-top:auto}

/* every clickable row is reachable and operable from the keyboard */
tbody tr[tabindex],.wall button,.chip,.h-chip{cursor:pointer}
tbody tr[tabindex]:focus-visible{outline:2px solid var(--live);outline-offset:-2px}

/* ── the rail head, matching the world model viewer's ─────────────────────────────── */
.rail .r-whose{padding:12px 16px;border-bottom:1px solid var(--rule)}
.rail .r-whose b{display:block;font:700 11.5px/1.3 var(--sans);color:var(--ink)}
.rail .r-whose span{display:block;font:400 11px/1.5 var(--sans);color:var(--ink3);margin-top:2px}
/* The ground, at the foot of the rail, which is where a reader looks for it. The swap is the
   library's; this only gives it room in a row that already holds a name and a way out. */
.rail .whoami .r-theme{flex:none;width:26px;height:26px;min-height:0;color:var(--ink3);
  cursor:pointer;transition:color var(--dur) var(--ease)}
.rail .whoami .r-theme:hover{color:var(--ink)}
.rail .whoami .r-theme input{position:absolute;opacity:0;width:0;height:0}
body.railfold .rail .whoami .r-theme{display:none}

/* ── artwork. Content at the identity position, never chrome. ─────────────────────── */
.cov{flex:none;border-radius:var(--r-media);background:var(--bg2);object-fit:cover;
  display:block}
.cov.none{border:1px solid var(--rule);background:
  repeating-linear-gradient(135deg,var(--bg) 0 5px,var(--bg2) 5px 10px)}
.idrow{display:flex;align-items:center;gap:12px;min-width:0}
.idrow .t{min-width:0}
td .idrow{gap:14px;align-items:flex-start}
td .idrow .t b{display:block;font:600 13.5px/1.35 var(--sans);letter-spacing:-.012em;
  color:var(--ink)}
td .idrow .t small{display:block;margin-top:3px;font:400 11.5px/1.45 var(--sans);color:var(--ink3)}
td .idrow .t small.rel{color:var(--ink2)}
.wall button{padding:0 0 14px}
.wall .top{display:block;width:100%;aspect-ratio:1/1;background:var(--bg2);
  border-bottom:1px solid var(--rule)}
.wall .top img{width:100%;height:100%;object-fit:cover;display:block}
.wall .top.none{background:repeating-linear-gradient(135deg,var(--bg) 0 8px,var(--bg2) 8px 16px)}
.wall .in{padding:13px 16px 0}
.objhead{display:flex;gap:20px;align-items:flex-start;padding:20px 0}
.objhead .cov{border:1px solid var(--rule)}
.drawer .dhead{display:flex;gap:14px;align-items:flex-start;margin:10px 0 0}
.drawer .dhead .cov{border:1px solid var(--rule2)}

/* a run of covers, for a counterparty who controls more than one release */
.stackcov{display:flex;gap:3px;flex:none}
.covgrid{display:flex;flex-wrap:wrap;gap:5px;margin:16px 0 0}

/* ── the measured field. One mark per subject, and the caption names what it measures. ─ */
.field{display:flex;flex-wrap:wrap;gap:3px;margin:30px 0 0;max-width:760px}
.field i{width:7px;height:7px;flex:none;background:var(--rule);font-style:normal}
.field i.half{background:var(--rule2)}
.field i.on{background:var(--live)}
.fieldcap{margin:14px 0 0;font:400 11.5px/1.6 var(--sans);color:var(--ink3);max-width:76ch}
.fieldcap b{color:var(--ink2);font-weight:500}

/* the measured field sits under the poster, on the ground, not inside it */
.fieldwrap{padding:26px 0 4px;border-bottom:1px solid var(--rule)}
.fieldwrap .field{margin-top:0}

/* ── activation ──────────────────────────────────────────────────────────────────────
 * The council streaming its work. A log rather than a spinner, because a customer watching
 * eight agents read a 43 GB identity spine and a world model graph learns more about the
 * product in ninety seconds than a deck conveys.
 */
.log{border-top:1px solid var(--rule);max-height:62vh;overflow-y:auto}
.lg{display:grid;grid-template-columns:16px 1fr;gap:11px;padding:9px 0;
  border-bottom:1px solid var(--rule);align-items:baseline;
  font:400 12.5px/1.5 var(--sans);color:var(--ink2)}
.lg i{width:7px;height:7px;background:var(--rule2);font-style:normal;position:relative;top:5px;
  justify-self:center}
.lg b{color:var(--ink);font-weight:700}
.lg em{font-style:normal;color:var(--ink3);font:500 11.5px/1 var(--sans);margin-left:9px}
.lg span span{display:block;margin-top:3px;font-size:11.5px;line-height:1.5}
.lg.a{border-top:1px solid var(--rule);margin-top:6px;padding-top:14px}
.lg.a i{background:var(--ink)}
.lg.f i{background:var(--live)}
.lg.f{color:var(--ink)}
.lg.ok i{background:var(--rule2)}
.lg.ok{color:var(--ink3);font-size:11.5px}
.lg.p{color:var(--ink3)}
.lg.bad i{background:var(--leak)}
.lg.bad{color:var(--leak)}
.lg.done i{background:var(--live)}
.lg.done{color:var(--ink);border-bottom:0;padding-top:14px}

.fld{width:100%;background:none;border:1px solid var(--rule2);border-radius:var(--r-input);
  padding:11px 12px;font:400 12.5px/1 var(--sans);color:var(--ink)}
.fld::placeholder{color:var(--ink3)}
.fld:focus{outline:none;border-color:var(--live)}

.drop{display:block;border:1px dashed var(--rule2);padding:30px 20px;text-align:center;
  cursor:pointer;transition:border-color var(--dur) var(--ease)}
.drop:hover,.drop.over{border-color:var(--live)}
.drop b{display:block;font:700 12.5px/1.3 var(--sans);color:var(--ink)}
.drop span{display:block;margin:8px auto 0;font:400 11.5px/1.6 var(--sans);color:var(--ink3);
  max-width:56ch}

.cell.actor{background:var(--bg);transition:background var(--dur) var(--ease)}
.cell.actor:hover{background:var(--bg2)}
.cell.actor.on{background:var(--ink)}
.cell.actor.on .none b,.cell.actor.on .none span{color:var(--bg)}
.cell.actor.on .none .faint{color:rgba(0,0,0,.6)}

/* ── the conversation ────────────────────────────────────────────────────────────── */
.talk{max-width:74ch;padding:8px 0 20px}
.msg{padding:16px 0;border-bottom:1px solid var(--rule)}
.msg .who{font:500 11.5px/1 var(--sans);color:var(--ink3);margin-bottom:10px}
.msg.me .who{color:var(--live)}
.msg .txt{font:400 13.5px/1.65 var(--sans);color:var(--ink)}
.msg .txt p{margin:0 0 10px}
.msg .txt p:last-child{margin:0}
.msg .txt ul{margin:6px 0;padding-left:18px}
.msg .txt li{margin:4px 0;color:var(--ink2)}
.msg .txt code{font:500 11.5px/1.5 var(--mono);color:var(--ink);
  border-bottom:1px solid var(--rule2)}
.msg .txt strong{color:var(--ink);font-weight:700}
.msg .cite{margin-top:12px;display:flex;gap:14px;flex-wrap:wrap}
.asks{display:flex;flex-wrap:wrap;gap:0;border-top:1px solid var(--rule);
  border-bottom:1px solid var(--rule)}
.asks button{padding:11px 14px 11px 0;margin-right:14px;text-align:left;
  font:400 11.5px/1.4 var(--sans);color:var(--ink3);border-bottom:1px solid transparent}
.asks button:hover{color:var(--ink)}
.askbar{position:sticky;bottom:0;background:var(--bg);border-top:1px solid var(--rule2);
  display:flex;align-items:stretch;margin:0 calc(var(--gutter) * -1);padding:0 var(--gutter)}
.askbar input{flex:1;background:none;border:0;height:56px;font:400 13.5px/1 var(--sans);
  color:var(--ink)}
.askbar input:focus{outline:none}
.askbar input::placeholder{color:var(--ink3)}
.askbar button{padding:0 18px;font:500 11.5px/1 var(--sans);color:var(--live)}

/* a primary action that cannot yet be taken says so, rather than looking ready */
.h-go[disabled]{background:var(--rule2);color:var(--ink3);cursor:not-allowed}
.h-go[disabled]:hover{filter:none}


/* ── the front door ──────────────────────────────────────────────────────────────────
 * A wall of covers and a form. Rule 6 of the taste: images are the page, and the measured
 * count on a music surface is bimodal, either a wall or a handful at size. This is the wall.
 * Rule 9: no glass, no glow, no gradient mesh. The covers sit on the ground at full bleed and
 * one hairline separates them from the form.
 */
/* ── The front door. Rule 9 in one screen: the wall on the left, the object on the right.
      The wall was on the right and the form on the left, and the class names said the
      opposite of the layout, which is how it read as an admin screen with a picture beside
      it rather than as the catalogue with a way in. ──────────────────────────────────── */
/* The column is capped as well as floored. At 32% of a wide display it reaches past 600px
   while the block inside it stays at 372, and the extra goes nowhere: the fields sit flush
   left against a growing empty right half. Past 520px the wall takes the width instead. */
.signin{display:grid;grid-template-columns:1fr minmax(400px,min(32%,520px));height:100dvh;
  overflow:hidden;padding:0;margin:0}
@supports not (height:100dvh){.signin{height:100vh}}
/* ── the wall, and the mark on it ────────────────────────────────────────────────── */
.swall{position:relative;overflow:hidden;background:#000}   /* media, not the page */
/* Square tiles. `grid-auto-rows:1fr` stretched every row to fill the panel height and every
   sleeve came out cropped to a letterbox, which is the one thing a cover must not be. The
   wall overflows the bottom instead and is clipped there, which is what a wall does.
   Larger tiles than the first build: a fine mosaic reads as texture, and at this size each
   sleeve is still a record you can recognise, which is the whole point of showing them. */
.wall-bleed{position:absolute;inset:0;display:grid;gap:1px;background:var(--rule);
  grid-template-columns:repeat(auto-fill,minmax(clamp(132px,13vw,208px),1fr));
  grid-auto-rows:min-content;align-content:start}
.wt{position:relative;overflow:hidden;background:var(--bg2);opacity:0;aspect-ratio:1;
  animation:wt-in 620ms cubic-bezier(.4,0,.2,1) forwards;animation-delay:var(--d,0ms)}
/* Held a little back so the form on the ground beside it stays the thing being looked at.
   A dim, not a desaturation: the artwork keeps its colour, which is most of what it is. */
.wt img{width:100%;height:100%;object-fit:cover;display:block;filter:brightness(.6)}
/* The sheet variant. One image behind every tile, positioned per tile, so the dim goes on the
   tile itself: there is no element inside it to carry it. */
.wt-sheet{background-image:var(--sheet);background-repeat:no-repeat;filter:brightness(.6)}
/* And no per-tile entrance. The stagger was written when a tile really was its own request
   and it read as the wall assembling itself, which was true. It is one image now, and
   seventy two tiles fading in one after another says something about the page that stopped
   being the case: it looks like seventy two things arriving when one thing has arrived. The
   wall comes up as the composition it is, once, after the sheet has arrived. */
.wall-bleed.sheeted .wt{animation:none;opacity:1}
/* The transition is declared on the lit state only. Declared on `.sheeted` it also applies
   the moment that class goes on, and the wall's resting opacity is 1, so the first thing it
   did was fade itself out. */
.wall-bleed.sheeted{opacity:0}
.wall-bleed.sheeted.up{opacity:1;transition:opacity 520ms cubic-bezier(.4,0,.2,1)}
@keyframes wt-in{to{opacity:1}}
.swall.nofig .wall-bleed,.swall.nofig .wveil{display:none}

/* Two gradients doing two jobs. Down the page so the mark has ground to sit on, and across to
   the right so the wall meets the form on a fade rather than on a seam. Without the second
   one the join is a hard vertical edge between colour and black, and that edge is the first
   thing the eye goes to on a page whose subject is two fields. */
.wveil{position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(180deg,rgba(0,0,0,.46) 0%,rgba(0,0,0,.22) 24%,rgba(0,0,0,.58) 62%,
                          rgba(0,0,0,.88) 84%,rgba(0,0,0,.97) 100%),
    linear-gradient(90deg,rgba(0,0,0,.34) 0%,rgba(0,0,0,0) 18%,rgba(0,0,0,.10) 58%,
                          rgba(0,0,0,.88) 100%)}

/* Rule 1: Archivo Narrow 700 is for a poster and this is the poster. Uppercase, condensed,
   negative tracking, on the ground the veil made. Rule 5 puts the one accent on the single
   character that separates the platform from the domain, and nowhere else on the surface. */
.wmark{position:absolute;left:clamp(28px,3.4vw,56px);bottom:clamp(26px,3.2vw,52px);
  font-family:var(--narrow);font-weight:700;text-transform:uppercase;
  font-size:clamp(33px,5.6vw,85px);line-height:.86;letter-spacing:-.03em;
  color:var(--on-media);
  text-wrap:nowrap;z-index:2}
.wmark em{font-style:normal;color:var(--live)}

/* ── the object ─────────────────────────────────────────────────────────────────── */
.sform{position:relative;display:flex;flex-direction:column;justify-content:center;
  padding:clamp(36px,3.4vw,64px) clamp(32px,3.2vw,60px);
  background:var(--bg);border-left:1px solid var(--rule);overflow-y:auto;min-height:0}
.sbox{width:100%;max-width:372px;margin:auto 0}
/* Rule 2 holds here: the poster is the only thing above 32px. Weight and air carry this, not
   size. Sentence case and one full stop, because it is a statement of what the page does. */
.sh{font:400 clamp(22px,2.3vw,28px)/1.2 var(--sans);letter-spacing:-.03em;
  margin:0 0 clamp(34px,3.6vw,50px);color:var(--ink);max-width:14ch;text-wrap:balance}
/* Rule 7: a label is sans, never mono. */
/* --ink3 on this ground is about 3.3:1, and a 10px bold label is exactly the size that
   cannot afford it. --ink2 clears 4.5:1 and reads as considered rather than as switched off. */
.slab{display:block;font:500 11.5px/1 var(--sans);color:var(--ink2);margin:0 0 10px}
.slab+.fld{margin-bottom:22px}
/* --rule2 is an edge between panels and it disappears as a field: the input reads as absent
   rather than as empty, and someone looking for where to type has to hunt. --ink3 is a line
   you can see without it becoming a box. */
.sbox .fld{padding:13px 0;border:0;border-bottom:1px solid var(--ink3);border-radius:0;
  font:400 14px/1.2 var(--sans);
  transition:border-color var(--dur) var(--ease)}
/* A field is a line, not a box. Four boxed inputs stacked on a black ground is the shape of
   an admin form; a rule that lights up is the shape of a page that was designed. */
.sbox .fld:hover{border-bottom-color:var(--ink2)}
.sbox .fld:focus{outline:none;border-bottom-color:var(--live)}
.sbox .fld:focus-visible{outline:none}
.serr{min-height:18px;margin:2px 0 0;font:400 11.5px/1.4 var(--sans);color:var(--leak)}
.sgo{width:100%;margin-top:12px;padding:16px;letter-spacing:0;font-size:13.5px}

/* The hairline and the attribution under it, pinned to the foot of the column rather than
   trailing the form, so the column has a top, a middle and a bottom. */
.smeta{position:absolute;left:clamp(32px,3.2vw,60px);right:clamp(32px,3.2vw,60px);
  bottom:clamp(26px,2.6vw,40px);display:flex;justify-content:space-between;
  margin:0;padding-top:14px;border-top:1px solid var(--rule);
  font:500 11.5px/1 var(--sans);color:var(--ink3)}
@media (max-height:620px){.smeta{display:none}}

/* Everything above is the wide composition. Everything below narrows it, and it is below for
   that reason: this block sat above the rules it overrides, and at equal specificity the base
   won every time. Only the two selectors that happened to carry an extra class were taking
   effect, so the band appeared while the column it sits above kept its desktop centring, its
   desktop tile size and its desktop mark. A media query that reads correctly and does almost
   nothing is worse than one that is obviously absent.
   ------------------------------------------------------------------------------------- */
/* Narrow turns the composition through ninety degrees rather than throwing half of it away.
   Dropping the wall left a bare form on black with no mark on it and no artwork anywhere,
   which is not a smaller version of this page, it is a different and worse one. It was also
   still fetching the sheet to show nothing. */
@media (max-width:900px){
  .signin{grid-template-columns:1fr;grid-template-rows:minmax(210px,32dvh) auto;
    height:auto;min-height:100dvh;overflow:visible}
  .signin .swall{border-bottom:1px solid var(--rule)}
  /* Smaller tiles in a band. At the desktop minimum two sleeves fill the width and it reads
     as two pictures rather than as a wall. */
  .signin .wall-bleed{grid-template-columns:repeat(auto-fill,minmax(clamp(88px,26vw,132px),1fr))}
  .wmark{font-size:clamp(28px,11.5vw,52px);left:clamp(20px,6vw,32px);bottom:clamp(18px,5vw,28px)}
  .sform{border-left:0;justify-content:flex-start;
    padding:clamp(32px,9vw,48px) clamp(20px,6vw,32px) clamp(24px,7vw,36px)}
  .sbox{max-width:none;margin:0}
  /* In flow, not pinned: the column is as tall as its content now, so an absolute foot would
     sit over the button on a short screen. */
  .smeta{position:static;left:auto;right:auto;bottom:auto;margin-top:clamp(36px,12vw,64px)}
}


@media (prefers-reduced-motion:reduce){
  .wt{animation:none;opacity:1}
  .wall-bleed.sheeted{transition:none;opacity:1}
}

/* ── The works grid. A database view, so it behaves like one: the header stays, the body
      scrolls, and a sorted column says so without a second colour. ───────────────────── */
.dg-wrap{overflow:auto;max-height:calc(100dvh - 380px);border-top:1px solid var(--rule)}
/* The wrapper scrolls; the table does not compress. A column asked for 300px and given
   132 renders a recording title three characters wide, which is a table nobody can read. */
.dg{min-width:1120px}
.dg thead th{position:sticky;top:0;z-index:2;background:var(--panel,var(--plate));
  border-bottom:1px solid var(--rule2);white-space:nowrap;user-select:none;
  padding-top:var(--s3);padding-bottom:var(--s3)}
.dg thead th:hover{color:var(--ink)}
.dg thead th .sortmark{display:inline-block;width:0;margin-left:6px;opacity:0}
.dg thead th.sorted .sortmark{opacity:1;width:auto}
.dg thead th.sorted[data-dir="up"] .sortmark::after{content:"\2191"}
.dg thead th.sorted[data-dir="down"] .sortmark::after{content:"\2193"}
.dg tbody tr{cursor:pointer}
.dg tbody td{vertical-align:middle;padding-top:var(--s3);padding-bottom:var(--s3)}
.drawer .clm{margin:0 0 10px;padding-left:10px;border-left:1px solid var(--rule2)}
.drawer .clm b{display:block;font:600 11.5px/1.5 var(--mono);color:var(--ink);
  word-break:break-word}
.drawer .clm span{display:block;font:400 11px/1.6 var(--sans);color:var(--ink3);margin-top:2px}
/* A database view stays scannable only if the row height is predictable. Client titles run
   to a full sentence ("1. \"Teach Your Children\" performed by ..."), so the cell clamps and
   the drawer carries the whole string. */
.dg .idrow .t b{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;line-height:1.35;max-width:34ch}
.dg .idrow .t span{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  max-width:34ch}
.dg tbody td{padding-top:8px;padding-bottom:8px}
/* The one action on this surface. It was an 11.5px transparent chip with a near-black
   border at the far right edge, which reads as a status label and not a control: the first
   person to look for it could not find it. This is the page's single electric accent and
   this is what it is for. */
.h-chip.lead{background:var(--live);border-color:var(--live);color:var(--bg);
  font:600 11.5px/1 var(--sans);padding:10px 16px;letter-spacing:-.01em;border-radius:0}
.h-chip.lead:hover{background:var(--ink);border-color:var(--ink);color:var(--bg)}
.h-chip.lead:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
/* While it runs it must stay the same control in the same place, not disappear. */
.h-chip.lead[disabled]{background:none;color:var(--live);border-color:var(--live);
  opacity:1;cursor:default}
.h-chip.lead[disabled]::after{content:"";display:inline-block;width:5px;height:5px;
  margin-left:8px;background:var(--live);animation:pb-beat 1.1s var(--ease) infinite}
@keyframes pb-beat{0%,100%{opacity:1}50%{opacity:.25}}
@media (prefers-reduced-motion:reduce){.h-chip.lead[disabled]::after{animation:none}}
.h-chip.danger{color:var(--leak);border-color:var(--leak)}
.h-chip[disabled]{opacity:.5;cursor:default}
/* `hidden` loses to the bar's own display:flex, so the probe log leaked its label. */
.bar[hidden]{display:none}

/* ── The probe. Watching the catalogue get assembled, rather than watching a log scroll.
      The field is the same one Position uses, because it is the same question: one mark per
      recording, lit when it first reaches a work. ────────────────────────────────────── */
.probe{border-top:1px solid var(--rule2)}
.pb-head{display:flex;gap:36px;align-items:flex-start;justify-content:space-between;
  padding:22px 22px 16px;border-bottom:1px solid var(--rule)}
.pb-head h2{font:600 18px/1.25 var(--sans);letter-spacing:-.015em;color:var(--ink);
  margin:6px 0 0;border:0;padding:0}
.pb-head .kicker{margin:8px 0 0;max-width:60ch;font:400 11.5px/1.65 var(--sans);
  color:var(--ink2)}
.pb-nums{display:flex;gap:30px;flex:none;text-align:right}
.pb-nums .k{margin:0;font:500 11.5px/1 var(--sans);color:var(--ink3)}
.pb-nums .v{margin:8px 0 0;font:600 22px/1 var(--mono);color:var(--ink);
  font-variant-numeric:tabular-nums}

.pb-field{display:flex;flex-wrap:wrap;gap:3px;padding:22px}
.pb-field i{width:7px;height:7px;flex:none;background:var(--rule);font-style:normal;
  transition:background 220ms var(--ease)}
.pb-field i.on{background:var(--live)}
/* One pulse when a mark lights, and only for the source that lit it. A field that flickers
   whenever a second source agrees is a field telling you something that did not happen. */
.pb-field i.just{animation:pb-pop 900ms var(--ease)}
@keyframes pb-pop{
  0%{transform:scale(1);box-shadow:0 0 0 0 color-mix(in srgb,var(--live) 70%,transparent)}
  30%{transform:scale(1.9);box-shadow:0 0 0 3px color-mix(in srgb,var(--live) 22%,transparent)}
  100%{transform:scale(1);box-shadow:0 0 0 0 transparent}}
@media (prefers-reduced-motion:reduce){.pb-field i.just{animation:none}}

.pb-ledger{border-top:1px solid var(--rule)}
.pb-src{display:grid;grid-template-columns:190px 1fr 128px;gap:18px;align-items:baseline;
  padding:11px 22px;border-bottom:1px solid var(--rule)}
.pb-src:last-child{border-bottom:0}
.pb-src b{font:600 11.5px/1.4 var(--sans);color:var(--ink3)}
.pb-src span{font:400 11.5px/1.5 var(--sans);color:var(--ink3)}
.pb-src em{font:500 11.5px/1.4 var(--mono);color:var(--ink3);text-align:right;
  font-style:normal;font-variant-numeric:tabular-nums}
.pb-src.reading b{color:var(--ink)}
.pb-src.reading em{color:var(--live)}
.pb-src.done b{color:var(--ink2)}
.pb-src.done em{color:var(--ink2)}
/* A mark that lit and was taken back: the recording reached a work and then two sources of
   equal standing named different ones, so nothing was chosen. Neither lit nor dark. */
.pb-field i.half{background:var(--rule2)}

/* ── Atlas ────────────────────────────────────────────────────────────────────────────
   A positioned field, borrowed from t42:music-atlas. Position carries meaning, the legend
   states what it carries in plain words, and the caption states what is missing from the
   picture before the picture is read. Nothing here is decoration: a mark with no measured
   value sits in a stated band rather than at zero, because zero is a measurement. */
.strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  gap:clamp(20px,3vw,52px);padding:clamp(20px,2.2vw,28px) 0;
  border-bottom:1px solid var(--rule);background:none}
.strip .s{min-width:0;padding:0}
.strip .s .k{font:500 11.5px/1.4 var(--sans);color:var(--ink3);margin:0}
.strip .s .v{font:700 22px/1.15 var(--sans);letter-spacing:-.03em;color:var(--ink);margin:6px 0 0}
.strip .s .v small{font-size:13.5px;color:var(--ink3);font-weight:500;letter-spacing:0}
.strip .s .n{font:400 11.5px/1.5 var(--sans);color:var(--ink3);margin:8px 0 0;max-width:34ch}
.strip .s .pill{display:inline-block;margin-top:10px;padding:4px 9px;
  border:1px solid var(--caution);font:500 11.5px/1.2 var(--sans);color:var(--caution)}

.field{position:relative;border-top:1px solid var(--rule);background:var(--bg)}
.field svg{display:block;width:100%;height:auto}
.field .mk{cursor:pointer}
.field .mk:hover{stroke:var(--ink);stroke-width:1.5}
/* The reading, stated beside the field rather than floated over it. A legend that covers the
   marks it explains is a legend that costs more than it gives in a column this narrow. */
.legend-bar{align-items:flex-start;padding-top:11px;padding-bottom:11px;gap:22px}
.rd{display:grid;grid-template-columns:auto 1fr;gap:3px 12px;margin:0;flex:1 1 auto;
  padding-left:14px;border-left:1px solid var(--rule)}
.rd dt{font:500 11.5px/1.5 var(--sans);color:var(--ink3);white-space:nowrap}
.rd dd{font:400 11.5px/1.5 var(--sans);color:var(--ink2);margin:0}
.legend-bar .key{display:flex;flex-direction:column;gap:5px;flex:0 0 auto;
  padding-left:16px;border-left:1px solid var(--rule)}
.legend-bar .key span{font:400 11px/1.35 var(--sans);color:var(--ink2);white-space:nowrap}
.legend-bar .key b{color:var(--ink);font-weight:600}
.legend-bar .key i{display:inline-block;width:8px;height:8px;border-radius:50%;
  vertical-align:-1px;margin-right:6px}
.caption{padding:14px 20px;border-top:1px solid var(--rule);
  font:400 11.5px/1.6 var(--sans);color:var(--ink2);margin:0}
.caption b{color:var(--ink);font-weight:500}
/* ── The landing. The answer first, the story under it. ───────────────────────────────
 *
 * Almost all of this is gone. Two hundred and seventeen lines of hand-written landing rules
 * became these forty: hero, stats, progress and steps are the library's now, and what is left
 * is the handful of decisions the library has no opinion about. The measured taste still
 * governs which components are used and how, and radius zero is enforced in the theme rather
 * than reasserted per rule.
 */

/* The opening screen, and it is not a `hero`.
 *
 * It was one for an hour. `hero` centres its content in a full viewport, which is right for a
 * splash and wrong for the first paragraph of a document: on a tall window the answer floated
 * in the middle of fourteen hundred empty pixels and the story was pushed off the bottom.
 * Reaching for a component because it exists is the failure mode of adopting a library, and
 * the correct answer here is a section with padding.
 *
 * The one-screen property still holds, and it holds because the content is short rather than
 * because a height is asserted. */
.lopen{padding:clamp(18px,2.4vw,30px) 0 clamp(30px,4vw,52px)}
.lopen-in{width:100%;max-width:1180px}
.lmeta{display:flex;flex-wrap:wrap;gap:14px;align-items:baseline;margin:0 0 10px;
  font:400 13.5px/1.4 var(--sans)}
.lmeta b{font-weight:700;color:var(--ink);letter-spacing:-.01em}
.lmeta span{color:var(--ink2)}
/* house.css caps every h1 at 24ch, which is right for a heading and wrong for a sentence. */
.lh1{font:400 clamp(19px,1.9vw,24px)/1.4 var(--sans);letter-spacing:-.014em;margin:0 0 clamp(20px,3vw,34px);
  color:var(--ink);max-width:none;text-wrap:normal}

/* The two figures, which is the thing the surface is for. `stats` supplies the frame; the size
   is ours, because the library's stat-value is a dashboard number and this is the answer. */
.lstats{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));
  gap:0 clamp(28px,4vw,64px);background:none;border:0}
.lstats .lstats .stat-title{font:500 13px/1.4 var(--sans);color:var(--ink2);opacity:1;margin-bottom:8px}
.lmoney{font:700 clamp(30px,4.4vw,56px)/1.05 var(--sans);letter-spacing:-.035em;color:var(--ink);
  font-variant-numeric:tabular-nums;white-space:normal}
.lmoney i{display:inline-block;font:400 clamp(15px,1.5vw,20px)/1 var(--sans);font-style:normal;
  color:var(--ink3);margin:0 .34em;letter-spacing:0}
.lstats .stat-desc{font:400 14.5px/1.55 var(--sans);color:var(--ink2);white-space:normal;
  max-width:44ch;margin-top:10px;opacity:1}
.lcaveat{margin:0 0 clamp(20px,2.6vw,30px);font:400 13.5px/1.5 var(--sans);color:var(--ink3)}
.lacts{display:flex;flex-wrap:wrap;gap:12px 20px;align-items:center}

/* Everything below the first screen. */
.lstory{padding:clamp(30px,5vw,64px) 0 0;border-top:1px solid var(--rule)}
.lsh{margin:clamp(30px,4vw,52px) 0 clamp(14px,1.6vw,20px);font:600 clamp(17px,1.8vw,21px)/1.3 var(--sans);
  letter-spacing:-.016em;color:var(--ink)}
.lsh:first-child{margin-top:0}
.lsay{margin:0;font:400 clamp(15px,1.5vw,17px)/1.6 var(--sans);color:var(--ink);max-width:72ch}
.lsay b{font-weight:700}
.lsay-q{color:var(--ink2)}
.lmore{margin:14px 0 0;font:400 14.5px/1.5 var(--sans)}
.lmore a{color:var(--ink);border-bottom:1px solid var(--ink3)}
.lmore a:hover{color:var(--live);border-bottom-color:var(--live)}

/* The identifier split. One bar, two parts, each labelled inside itself. */
.lsplit{display:grid;gap:16px}
.lsplit-bar{display:flex;height:34px;background:var(--rule);overflow:hidden}
.lsplit-on{display:flex;align-items:center;padding:0 12px;background:var(--live);
  color:var(--live-ink);font:700 13px/1 var(--sans);white-space:nowrap}
.lsplit-off{display:flex;align-items:center;justify-content:flex-end;flex:1 1 auto;padding:0 12px;
  color:var(--ink2);font:500 13px/1 var(--sans);white-space:nowrap}

/* The causes, ranked. `progress` draws the bar; the row is a grid so the figures align. */
.lcauses{list-style:none;margin:0;padding:0}
.lcauses li{display:grid;grid-template-columns:minmax(180px,22ch) 1fr auto;
  gap:0 16px;align-items:center;padding:11px 0;border-bottom:1px solid var(--rule)}
.lcause-n{font:400 14.5px/1.4 var(--sans);color:var(--ink)}
.lcause-bar{width:100%;height:6px}
/* One figure per unit, so the column holds one or several pairs rather than a single number
   with a single word after it. Three columns, not four: a cause carrying a run-rate and a
   back-claim has two figures and two units, and a fixed unit column could only ever name one
   of them. It wraps between pairs and never inside one, because the figure and its unit are
   joined by a non-breaking space in the markup: "$475k" can never end a line with "once"
   starting the next, and `pro_blackbox_pool` carries three pairs. */
.lcause-v{font:400 12.5px/1.7 var(--sans);color:var(--ink3);text-align:right}
.lcause-v b{font:700 15px/1 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums}
.lcause-v em{font-style:normal;color:var(--ink3)}
.lcause-v i{font-style:normal;color:var(--ink3);margin:0 .6ch}
/* Narrow: the name on its own line and the figures under it, left aligned. Held in two
   columns the figure column takes what it needs and the name is squeezed to four lines, and a
   cause carrying three units needs the whole width. */
@media (max-width:720px){.lcauses li{grid-template-columns:1fr;gap:4px 0}
  .lcause-bar{display:none}.lcause-v{text-align:left}}

/* ── the drill-down panel, over the content area ──────────────────────────────────────
      The landing's second principle is that a detail opens in the same frame: the panel takes
      the content area and leaves the header and the rail where they were, so a reader who
      opened one question has not lost his place answering it. It carries no measurements of
      its own. --rail and --railtop are the two offsets the shell already declares, and the
      rail rewrites --rail when it folds, so the panel follows it to 56px for free. z-index
      sits above the rail and under the header and the drawer, both of which stay reachable
      from inside a panel.

      The [hidden] rule is here for the same reason .bar carries one: the panel is a flex
      column, and a display an author sets outclasses the attribute on any ground where the
      preflight's !important is not in the sheet. */
.fpanel{position:fixed;top:var(--railtop,0px);left:var(--rail,0px);right:0;bottom:0;z-index:50;
  background:var(--bg);display:flex;flex-direction:column}
.fpanel[hidden]{display:none}
/* The way back reads first, then what this is, then the surface that owns the whole of it. */
.fphead{flex:none;display:flex;flex-wrap:wrap;gap:6px 18px;align-items:baseline;
  padding:15px var(--gutter);border-bottom:1px solid var(--rule)}
.fphead b{flex:1 1 auto;min-width:16ch;font:600 clamp(16px,1.7vw,20px)/1.3 var(--sans);
  letter-spacing:-.016em;color:var(--ink)}
.fpback,.fpfull{flex:none;font:400 13px/1.5 var(--sans);color:var(--ink2);
  transition:color var(--dur) var(--ease)}
.fpback:hover,.fpfull:hover{color:var(--live)}
/* Escape is the other way out and nothing on the surface says so, so the one that is written
   carries a mark as well as a word. */
.fpback::before{content:"";display:inline-block;width:6px;height:6px;margin-right:9px;
  border-left:1px solid currentColor;border-bottom:1px solid currentColor;
  transform:rotate(45deg);vertical-align:.1em}
/* The body scrolls and the page does not: openPanel resets fpb.scrollTop, which means nothing
   unless this is the element that holds the overflow. */
.fpbody{flex:1 1 auto;min-height:0;overflow-y:auto;
  padding:clamp(20px,2.6vw,32px) var(--gutter) clamp(40px,5vw,64px)}
.fpbody>:first-child{margin-top:0}
/* The same 1180px column .lopen-in holds the answer in, so a list of causes on a wide screen
   is a column and not a run of figures a foot away from the name they belong to. Every block
   that wants a reading measure instead of the column states its own below, and states it
   later, which is what lets one rule stand for all of them. */
.fpbody>*{max-width:1180px}

/* Panel prose. One measure for anything set as a sentence, because the panel is narrower than
   the surface behind it and the story's 72ch is still the line a reader can follow. */
.ppara{margin:0 0 clamp(16px,1.8vw,22px);font:400 15px/1.6 var(--sans);color:var(--ink);
  max-width:72ch}
.ph3{margin:clamp(24px,3vw,34px) 0 10px;font:600 16px/1.3 var(--sans);letter-spacing:-.015em;
  color:var(--ink)}
/* The dash marker the release drawer already uses, rather than a disc: these are conditions
   on a figure and not steps to take. */
.plist{margin:0 0 clamp(16px,1.8vw,22px);padding:0;list-style:none;max-width:72ch}
.plist li{position:relative;padding:6px 0 6px 15px;font:400 14px/1.6 var(--sans);color:var(--ink2)}
.plist li::before{content:"";position:absolute;left:0;top:17px;width:6px;height:1px;
  background:var(--rule2)}
/* Provenance closes the panel the way it closes a surface. .src carries its own type. */
.psrc{margin:clamp(24px,3vw,34px) 0 0;padding-top:14px;border-top:1px solid var(--rule)}

/* One step of the derivation: the label and its range on a line, the range drawn under them,
   and what the step means under that. The figures are allowed to wrap below the label, because
   "What the catalogue earns" and a pair of millions do not both fit at the folded width. */
.bstep{margin:0 0 clamp(20px,2.4vw,28px);max-width:72ch}
.bsl{display:flex;flex-wrap:wrap;gap:2px 16px;align-items:baseline;margin:0 0 9px}
.bsl b{flex:1 1 auto;min-width:14ch;font:600 15px/1.4 var(--sans);color:var(--ink)}
.bsl span{flex:0 1 auto;font:700 15px/1.4 var(--sans);color:var(--ink);
  font-variant-numeric:tabular-nums}
.bstep p{margin:9px 0 0;font:400 13.5px/1.55 var(--sans);color:var(--ink2)}
/* The range itself. `u` is the low-to-high span and `i` the middle of it, both placed by a
   percentage in the markup, so the track is what makes those percentages mean anything. The
   middle mark is cut in the ground rather than drawn in ink, which is the only colour that
   reads against --live on both grounds.
   Scoped to the step, and it has to be: the foot of the rail carries a .rb of its own for the
   build identifier, and a bare rule here would give that span a height and a ground. */
.bstep .rb{position:relative;height:8px;background:var(--rule);overflow:hidden}
.bstep .rb u{position:absolute;top:0;bottom:0;min-width:2px;background:var(--live);
  text-decoration:none}
.bstep .rb i{position:absolute;top:0;bottom:0;width:2px;margin-left:-1px;background:var(--bg)}

/* Every cause, ranked. A rule between entries and no box around any of them: this is a list of
   findings, and a card each would read as thirteen tiles rather than one list.
   .pch holds the name left and the figures right on one line, and lets the figures wrap under
   the name where the width will not carry both. The figures are .lcause-v and take the figure
   and unit typography from it, above, so none of that is restated here. */
.pcauses{margin:0}
.pc{padding:14px 0;border-bottom:1px solid var(--rule)}
.pc:first-child{padding-top:0}
.pc:last-child{border-bottom:0}
.pch{display:flex;flex-wrap:wrap;gap:2px 16px;align-items:baseline}
.pch b{flex:1 1 auto;min-width:14ch;font:600 15px/1.4 var(--sans);letter-spacing:-.012em;
  color:var(--ink)}
.pch .lcause-v{flex:0 1 auto}
.pc p{margin:6px 0 0;font:400 13.5px/1.55 var(--sans);color:var(--ink2);max-width:72ch}
/* A cause with no sentence written for it yet must not leave a gap where one was. */
.pc p:empty{display:none}
/* Two classes deep because .pc p would otherwise win on the count. */
.pc .pcm{margin:7px 0 0;font:400 11.5px/1.5 var(--mono);color:var(--ink3);max-width:none}

/* Where the money sits, with the covers doing the work. */
.lreleases{list-style:none;margin:0;padding:0;counter-reset:r}
.lreleases li{display:grid;grid-template-columns:auto 64px 1fr auto;gap:0 16px;align-items:center;
  padding:12px 0;border-bottom:1px solid var(--rule)}
.lrel-rank{font:400 13px/1 var(--mono);color:var(--ink3)}
.lrel-art{display:block;width:64px;height:64px;overflow:hidden;border-radius:var(--r-media);
  background:var(--plate)}
.lrel-art img{width:100%;height:100%;object-fit:cover;transition:transform var(--dur) var(--ease)}
.lrel-art:hover img{transform:scale(1.05)}
.lrel-t b{display:block;font:600 15px/1.3 var(--sans);letter-spacing:-.014em;color:var(--ink)}
.lrel-t small{display:block;margin-top:3px;font:400 12.5px/1.4 var(--sans);color:var(--ink3)}
.lrel-v{font:700 16px/1 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums}

/* What would move it. `steps` is the library's; the two lines inside a step are ours. */
.lsteps{width:100%;margin:0}
.lsteps .step{gap:2px}
.lstep-n{display:block;font:700 20px/1.1 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums}
.lstep-l{display:block;font:400 12.5px/1.4 var(--sans);color:var(--ink2);max-width:18ch}

.lonward{display:flex;flex-wrap:wrap;gap:8px 26px;margin:clamp(30px,4vw,52px) 0 0;
  padding-top:20px;border-top:1px solid var(--rule)}
.lonward a{padding:4px 0;font:400 14.5px/1.5 var(--sans);color:var(--ink2)}
.lonward a:hover{color:var(--live)}


/* ── the release, at the foot of the rail on every surface ────────────────────────────
      Two identifiers because they answer two questions: the version says what this surface
      can now do, the build says exactly which tree is serving it. Quiet by default, because
      it is provenance rather than navigation, and it is the last thing in the rail. */
.rail .relrow{display:flex;align-items:baseline;gap:8px;width:100%;margin-top:9px;
  padding:0;text-align:left}
.rail .relrow .rv{font:500 11.5px/1.4 var(--mono);color:var(--ink2);letter-spacing:-.01em;
  border-bottom:1px solid var(--rule2);transition:color var(--dur) var(--ease)}
.rail .relrow:hover .rv{color:var(--ink);border-bottom-color:var(--live)}
.rail .relrow .rb{flex:1 1 auto;min-width:0;font:400 10.5px/1.4 var(--mono);color:var(--ink3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* the release drawer */
.drawer .rmeta{margin:6px 0 0;font:400 11.5px/1.6 var(--mono);color:var(--ink3)}
.drawer .rscheme{margin:14px 0 0;font:400 12.5px/1.6 var(--sans);color:var(--ink2)}
.drawer .rl{margin:22px 0 8px;font:500 11.5px/1 var(--sans);color:var(--ink3)}
.drawer .rul{margin:0;padding:0;list-style:none}
.drawer .rul li{position:relative;padding:7px 0 7px 14px;font:400 12.5px/1.6 var(--sans);
  color:var(--ink)}
.drawer .rul li::before{content:"";position:absolute;left:0;top:15px;width:5px;height:1px;
  background:var(--rule2)}
.drawer .rhist{border-top:1px solid var(--rule)}
.drawer .rh{padding:14px 0;border-bottom:1px solid var(--rule)}
.drawer .rhh{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
.drawer .rhh b{font:500 12.5px/1.3 var(--mono);color:var(--ink)}
.drawer .rhh span{font:400 11px/1.3 var(--mono);color:var(--ink3)}
.drawer .rht{margin:5px 0 0;font:400 12.5px/1.5 var(--sans);color:var(--ink2)}
.drawer .rh .rl{margin:14px 0 4px}

/* ── the rail, folded ─────────────────────────────────────────────────────────────────
      236px of rail on every surface, on a catalogue that wants the width. Folded it is a strip
      of marks at 56px, which is 180px back to the table. Nothing is lost: the labels return on
      hover and on focus, so the rail is still operable from the keyboard with no mouse. */
.r-fold{flex:none;width:22px;height:22px;margin-left:auto;position:relative;
  border:1px solid var(--rule2);background:none;cursor:pointer;
  transition:border-color var(--dur) var(--ease)}
.r-fold:hover{border-color:var(--live)}
.r-fold span{position:absolute;inset:4px auto 4px 6px;width:1px;background:var(--ink3)}
.r-fold:hover span{background:var(--live)}
.rail .r-top{gap:10px}

body.railfold .rail{overflow:visible}
/* The real structure, read off the rendered rail rather than guessed at: a group is a
   `button.nv-grp` heading followed by a `nav.nv-n` of `a.nv-a` links. Guessing produced a rail
   that folded to 56px with the group headings still printing their words into it. */
body.railfold .rail .brand,
body.railfold .rail .r-whose,
body.railfold .rail .runbar,
body.railfold .rail .whoami b,
body.railfold .rail #out{display:none}
/* Folded, the rail is the five stages and nothing else. It used to fold to eighteen marks over
   eleven shapes, so the same shape stood for four destinations and the column was unreadable
   at 56px. Five stages, five distinct marks, and the destinations are one click behind the one
   you pick. */
body.railfold .rail .nv-grp{grid-template-columns:1fr;justify-items:center;padding:13px 0}
body.railfold .rail .nv-grp b,
body.railfold .rail .nv-gl,
body.railfold .rail .nv-n{display:none !important}
/* The library draws the disclosure on the summary itself. Folded there is nothing to disclose
   in the column, so the arrow is the one mark that would mean nothing. */
body.railfold .rail .menu li > details > .nv-grp::after{display:none}
body.railfold .rail .nv-grp .nv-i{width:17px;height:17px;margin:0}
/* Which stage you are in. Open, the destination carries that as a filled row; folded, the
   destinations are not drawn, so the stage takes the same treatment rather than the column
   losing the one thing it has to say about where you are. */
body.railfold .rail details[open] > .nv-grp{background:var(--ink)}
body.railfold .rail details[open] > .nv-grp .nv-i{color:var(--bg)}
/* Sign out keeps its place as a mark, because losing the way out is not a saving. */
body.railfold .rail .whoami{justify-content:center;padding:12px 0 16px}
body.railfold .rail .whoami::after{content:"\21A9";font:400 13.5px/1 var(--sans);
  color:var(--ink3)}
body.railfold .rail .nv-a > span,
body.railfold .rail .nv-a > b{
  position:absolute;left:calc(100% + 1px);top:0;height:100%;display:flex;align-items:center;
  padding:0 14px;background:var(--bg2);border:1px solid var(--rule);border-left:0;
  white-space:nowrap;opacity:0;pointer-events:none;z-index:40;
  transition:opacity var(--dur) var(--ease)}
body.railfold .rail .nv-a{position:relative;justify-content:center;
  padding-left:0;padding-right:0}
/* :focus as well as :focus-visible. The visible heuristic does not fire on programmatic focus,
   and a folded rail whose labels appear only for some ways of arriving at a link is a rail that
   is unreachable for the others. */
body.railfold .rail .nv-a:hover > span,
body.railfold .rail .nv-a:focus > span,
body.railfold .rail .nv-a:focus-visible > span{opacity:1}
body.railfold .rail .r-fold span{inset:4px 6px 4px auto}
/* The grouping survives losing its words, as a rule between the runs of marks. */
body.railfold .rail .r-grp+.r-grp{border-top:1px solid var(--rule);margin-top:8px;padding-top:8px}

/* ── the decision palette ─────────────────────────────────────────────────────────────
   Eight decisions, and they are not eight equal things: three are answered here, four in
   part, and one not at all. The ones this reader owns carry a rule down their left edge and
   the rest are set quieter, because a palette that shows all eight identically is claiming
   the product answers all eight. */
.dnote{margin:clamp(16px,2vw,24px) 0 0;font:400 13.5px/1.6 var(--sans);color:var(--ink2);
  max-width:92ch}
.dnote b{color:var(--ink);font-weight:600}
.dswap{margin-left:10px;font:500 12.5px/1.4 var(--sans);color:var(--ink);
  border-bottom:1px solid var(--rule2);padding:0}
.dswap:hover{color:var(--live);border-bottom-color:var(--live)}

.dgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));
  gap:0 clamp(24px,3vw,48px);margin:clamp(18px,2.2vw,28px) 0 0;
  border-top:1px solid var(--rule)}
.dcard{padding:clamp(18px,2vw,24px) 0;border-bottom:1px solid var(--rule);min-width:0}
/* Not a border on four sides. The rule says whose decision it is, which is the one thing on
   the card a reader scans for, and a box would say only that a card exists. */
.dcard.yours{padding-left:16px;box-shadow:inset 2px 0 0 var(--live)}
.dcard.yours .dhead b{color:var(--live)}
.dhead{display:flex;align-items:center;justify-content:space-between;gap:14px;margin:0}
.dhead b{font:600 12.5px/1 var(--mono);letter-spacing:-.01em;color:var(--ink2)}
.dcard h2{margin:10px 0 0;font:600 16.5px/1.25 var(--sans);letter-spacing:-.016em;color:var(--ink)}
.dq{margin:5px 0 0;font:400 13.5px/1.5 var(--sans);color:var(--ink2)}
.dmeta{display:grid;grid-template-columns:auto 1fr;gap:4px 14px;margin:16px 0 0}
.dmeta dt{font:400 11.5px/1.5 var(--sans);color:var(--ink3);white-space:nowrap}
.dmeta dd{margin:0;font:400 11.5px/1.5 var(--sans);color:var(--ink2)}
.dmeta .none{color:var(--leak);font-weight:600}
.dwhy{margin:14px 0 0;font:400 12.5px/1.6 var(--sans);color:var(--ink3);max-width:64ch}
.dgo{display:flex;flex-wrap:wrap;gap:0 18px;margin:14px 0 0}
.dgo a{font:500 13.5px/1.5 var(--sans);color:var(--ink);border-bottom:1px solid var(--ink3)}
.dgo a:hover{color:var(--live);border-bottom-color:var(--live)}
.dgo.none{font:400 12.5px/1.5 var(--sans);color:var(--ink3)}

/* ── the council ──────────────────────────────────────────────────────────────────────
   Nine agents, in the order they ran, each against a named source. An agent that produced
   nothing is set quieter and still listed: a shorter list reads as a smaller job, and what
   the council could not determine is half of why the figures are believable. */
.cgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));
  gap:0 clamp(24px,3vw,48px);margin:clamp(18px,2.2vw,28px) 0 0;
  border-top:1px solid var(--rule)}
.cagent{padding:clamp(16px,1.8vw,22px) 0;border-bottom:1px solid var(--rule);
  min-width:0;cursor:pointer}
.cagent:hover b,.cagent:focus-visible b{color:var(--live)}
.cagent:focus-visible{outline:2px solid var(--live);outline-offset:2px}
.cagent.idle{opacity:.62}
.chead{display:flex;align-items:baseline;gap:11px;margin:0}
.chead i{font:400 11.5px/1 var(--mono);font-style:normal;color:var(--ink3);flex:none}
.chead b{flex:1 1 auto;font:600 14px/1.3 var(--sans);letter-spacing:-.014em;color:var(--ink);
  transition:color var(--dur) var(--ease)}
.creads{margin:8px 0 0 23px;font:400 11.5px/1.5 var(--sans);color:var(--ink3)}
.csays{margin:8px 0 0 23px;font:400 13.5px/1.55 var(--sans);color:var(--ink2);max-width:56ch}

/* The alert centres its children even when told to align its own content left, because the
   rule is on the item rather than the box. A notice here is prose with a heading. */
.alert.notice > *{width:100%;text-align:left}

/* The rail's own register. The menu draws the row; these are the two sizes it cannot know:
   a group heading in a 236px column is a label rather than a heading, and a nav label clips
   rather than wraps. */
/* The stage is the unit of navigation now, so it carries the weight the destinations used to.
   Four bare verbs in one register made four identical rows: the mark and the gloss are what
   separate them, and both belong to the stage rather than being repeated under it. */
.rail .menu .nv-grp{display:grid;grid-template-columns:15px 1fr 14px;align-items:start;
  column-gap:11px;padding:13px 16px 12px;min-height:0;color:var(--ink2);
  border-top:1px solid var(--rule)}
.rail .menu li:first-child .nv-grp{border-top:0}
.rail .menu .nv-grp .nv-i{width:15px;height:15px;margin-top:1px;color:var(--ink3);
  transition:color var(--dur) var(--ease)}
.rail .menu .nv-grp b{display:block;font:600 13.5px/1.2 var(--sans);letter-spacing:-.01em;
  color:var(--ink)}
.nv-gl{display:block;margin-top:3px;font:400 11.5px/1.35 var(--sans);color:var(--ink3)}
.rail .menu .nv-grp:hover{background:none}
.rail .menu .nv-grp:hover .nv-i{color:var(--ink)}
/* The chevron is drawn absolutely at the left by the module, which is right for a rail whose
   heading is a bare word and wrong for one whose heading is two lines and a mark. It takes the
   third column instead, on the first line, where a disclosure is looked for. */
.rail .menu .nv-grp .nv-ch{position:static;grid-column:3;margin:3px 0 0;width:11px;height:11px}
/* An open stage brightens its mark and nothing else. A tint here fought the black bar on the
   destination inside it, and two things claiming to be the current thing is worse than one
   quiet one: the open chevron and the visible children already say which stage is open. */
.rail .menu details[open] > .nv-grp .nv-i{color:var(--ink)}
/* Destinations step in from their stage rather than starting at the same edge, so the stage
   reads as their parent instead of as another row in the same list. */
.rail .menu .nv-a{font:500 13px/1.2 var(--sans);border-radius:0;padding:7px 16px}
.rail .menu .nv-n{padding:0;margin:0}
.rail .menu li > *{border-radius:0}

/* The role, top right in the header. `join` groups the pair; the header is a fixed-height row
   of full-height cells, so the control is centred in one rather than stretched to fill it. */
.t-slot{display:flex;align-items:center;padding:0 16px}
.t-mode .btn{border-radius:0}
@media (max-width:720px){.t-slot{display:none}}

/* ── Actions: the instrument, not the finding ─────────────────────────────────────────
   A row rather than a card, because six of them is a list and not a gallery, and each one is a
   decision rather than an object. The figure is the right-hand column throughout so the six
   can be compared down the page without reading a word. */
.insts{list-style:none;margin:clamp(18px,2.2vw,28px) 0 0;padding:0;
  border-top:1px solid var(--rule)}
.inst{display:grid;grid-template-columns:1fr auto;gap:0 clamp(20px,3vw,48px);
  padding:clamp(16px,1.8vw,22px) 0;border-bottom:1px solid var(--rule);cursor:pointer;
  transition:background var(--dur) var(--ease)}
.inst:hover,.inst:focus-visible{background:var(--bg2)}
.inst:focus-visible{outline:2px solid var(--live);outline-offset:-2px}
.inst-name{margin:0;font:600 clamp(15px,1.6vw,17px)/1.3 var(--sans);letter-spacing:-.014em;
  color:var(--ink)}
.inst-do{margin:5px 0 0;font:400 14px/1.5 var(--sans);color:var(--ink2);max-width:62ch}
.inst-who{margin:8px 0 0;font:400 12.5px/1.5 var(--sans);color:var(--ink3)}
.inst-who b{color:var(--ink2);font-weight:500}
.inst-parties{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0 0}
.inst-parties em{font-style:normal;color:var(--ink3);margin-left:4px}
.inst-r{text-align:right;min-width:9ch}
.inst-v{margin:0;font:700 clamp(19px,2vw,24px)/1.1 var(--sans);letter-spacing:-.03em;
  color:var(--ink);font-variant-numeric:tabular-nums}
.inst-rng{margin:4px 0 0;font:400 12px/1.4 var(--sans);color:var(--ink3);
  font-variant-numeric:tabular-nums}
/* The unit a figure is in. An instrument that carries both a run-rate and a back-claim shows
   two figures, and they are not added, so each one says what it is denominated in rather than
   leaving the reader to assume both are the same kind of money. */
.inst-u{display:block;margin-top:2px;font:500 11.5px/1.4 var(--sans);color:var(--ink3);
  letter-spacing:0}
.inst-rng + .inst-v{margin-top:13px}
/* A stat that has something to say under the figure. daisyUI holds `.stat-desc` on one line,
   which is right for a two-word unit and wrong for a sentence that qualifies the number above
   it: at anything narrower than a wide desktop the qualification was the part that ran off the
   edge, so the surface showed the figure and hid the caveat on it. */
/* A mark on a destination as well as on its stage. It was dropped from the open rail because
   eleven marks covered eighteen destinations and one stood for four of them, which is a mark
   that says nothing. The answer was never to hide them: it was to make them distinct. Every
   destination now carries a mark no sibling shares and no stage above it shares, so the shape
   is a second way to find a row. Across two stages a mark may repeat, because the stage has
   already told the reader where they are; inside one it never does.
   The step in is the hierarchy. A stage sets its mark at 16 and its label at 42; a destination
   sets its mark at 30 and its label at 52, which is far enough to read as beneath it and near
   enough to leave a 236px rail room for the words. */
body:not(.railfold) .rail .menu .nv-a{padding-left:30px;gap:8px}
body:not(.railfold) .rail .menu .nv-a .nv-i{width:14px;height:14px;flex:none;
  color:var(--ink3);transition:color var(--dur) var(--ease)}
body:not(.railfold) .rail .menu .nv-a:hover .nv-i,
body:not(.railfold) .rail .menu .nv-a.on .nv-i{color:currentColor}

/* What a surface shows before its own data arrives. daisyUI draws the shimmer; these are the
   four sizes it cannot know, which are the shapes every surface here opens with: an eyebrow, a
   heading, a kicker and a run of rows. Aria-hidden, because a screen reader is told the region
   is busy and does not also need to hear six empty boxes described. */
.tskel{padding:clamp(26px,3vw,38px) 0 0;max-width:900px}
.tskel-eyebrow{height:10px;width:120px}
.tskel-h1{height:30px;width:min(460px,70%);margin-top:16px}
.tskel-kicker{height:13px;width:min(620px,88%);margin-top:16px}
.tskel-rows{margin-top:34px;display:grid;gap:11px}
.tskel-row{height:34px}
.tskel-row:nth-child(2n){width:92%}
.tskel-row:nth-child(3n){width:84%}
@media (prefers-reduced-motion:reduce){.tskel .skeleton{animation:none}}

/* The brief. Beats down a page rather than a wall of statistics: each is a number worth
   stopping on, the line that says what it is, and at most one shape. Numbered, because the
   order carries the argument and a reader who reads only the figures should still get it in
   sequence. */
.beats{list-style:none;margin:clamp(26px,3vw,38px) 0 0;padding:0;max-width:860px}
.beat{display:grid;grid-template-columns:38px 1fr;gap:0 20px;padding:clamp(20px,2.4vw,28px) 0;
  border-top:1px solid var(--rule)}
.beat:first-child{border-top:0;padding-top:0}
.beat-i{margin:6px 0 0;font:700 11px/1 var(--sans);letter-spacing:.08em;color:var(--ink3);
  font-variant-numeric:tabular-nums}
.beat-f{margin:0;font:700 clamp(30px,4.4vw,46px)/1 var(--sans);letter-spacing:-.035em;
  color:var(--ink);font-variant-numeric:tabular-nums}
.beat-f em{display:block;margin-top:9px;font-style:normal;letter-spacing:0;
  font:500 13px/1.4 var(--sans);color:var(--ink2)}
.beat-l{margin:13px 0 0;font:400 14.5px/1.65 var(--sans);color:var(--ink2);max-width:64ch}
.beat-l b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.beat .psplit{margin-top:16px;max-width:620px}
.beat .psplit-h{display:none}
/* The chain, compressed to fit inside a beat: the steps and the counts, without the shares. */
.gch-tight{margin-top:16px;max-width:620px}
.gch-tight .gch-r{grid-template-columns:1fr 34% 62px;gap:14px;padding:8px 0}
.gch-tight .gch-s{font-size:12.5px}
.gch-tight .gch-n b{font-size:13.5px}
/* Faces, where the record can name one. Artwork or nothing: no placeholder for the rest. */
.beat-strip{display:flex;flex-wrap:wrap;gap:5px;margin:16px 0 0;max-width:620px}
.beat-strip img{width:34px;height:34px;border-radius:4px;object-fit:cover;background:var(--rule)}
@media (max-width:640px){.beat{grid-template-columns:1fr}.beat-i{margin:0 0 6px}}

/* A term the surface leads with, said once before it is used. Set apart by a rule and a
   quieter register rather than by a panel, because it is an aside and not a card: rule 8 asks
   a panel to earn its edge and this one has not. */
.tdef{margin:clamp(20px,2.4vw,28px) 0 0;padding:0 0 0 16px;border-left:2px solid var(--rule2);
  max-width:76ch}
.tdef-t{margin:0;font:700 10px/1.6 var(--sans);letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink3)}
.tdef-b{margin:7px 0 0;font:400 13.5px/1.6 var(--sans);color:var(--ink2)}
.tdef-b b{font-weight:600;color:var(--ink)}
.tdef-not{color:var(--ink3)}

/* A population split three ways, which is a shape rather than a sentence. Prose with every
   figure bolded gave the eye eight numbers in four lines and no sense of any proportion
   between them; a bar carries the proportion without being asked and the counts sit under it
   where two can be compared. Extends the two-part split the position surface already uses. */
.psplits{display:grid;gap:26px;margin:22px 0 0;max-width:760px}
.psplit-h{margin:0 0 9px;font:600 13px/1.4 var(--sans);color:var(--ink)}
.psplit-h em{display:block;margin-top:2px;font-style:normal;font:400 12px/1.5 var(--sans);
  color:var(--ink3)}
.psplit-bar{display:flex;height:12px;background:var(--rule);overflow:hidden}
.psplit-bar i{display:block;height:100%;background:var(--ink3)}
.psplit-bar i.on{background:var(--live)}
/* The ambiguous share takes the caution hue rather than another grey. It sat between two
   neutrals a shade apart and disappeared, and it is the segment worth seeing: a name the
   register holds several parties under is the one case where the money exists and cannot be
   addressed. */
.psplit-bar i.mid{background:var(--caution)}
.psplit-bar i.faintest{background:var(--rule2)}
.psplit-key{list-style:none;display:flex;flex-wrap:wrap;gap:0 26px;margin:10px 0 0;padding:0}
.psplit-key li{display:flex;align-items:baseline;gap:7px;position:relative;padding-left:14px}
/* The mark ties a count to its segment. It is the one place colour carries meaning here, so
   nothing else in the block is coloured. */
.psplit-key li::before{content:"";position:absolute;left:0;top:50%;margin-top:-4px;
  width:8px;height:8px;background:var(--ink3)}
.psplit-key li.on::before{background:var(--live)}
.psplit-key li.mid::before{background:var(--caution)}
.psplit-key li.faintest::before{background:var(--rule2)}
.psplit-key b{font:600 15px/1.2 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums}
.psplit-key span{font:400 12.5px/1.4 var(--sans);color:var(--ink2)}
@media (max-width:640px){.psplit-key{gap:0 18px}}

/* A contributor, with the face the record names where there is one. The column keeps its
   width whether or not a portrait was found, so the names stay on one edge; what it does not
   do is put a mark there instead, because rule 6 is artwork or nothing and a placeholder face
   is a claim the data has not earned. Media takes the 4px the taste allows and nothing else in
   the table is rounded. */
.psp-who{display:flex;align-items:center;gap:11px}
.psp-face{flex:none;width:30px;height:30px;border-radius:4px;display:block}
img.psp-face{object-fit:cover;background:var(--rule)}
.psp-noface{border:1px solid var(--rule);border-radius:4px}
.psp-nil .psp-face{opacity:.55}

/* The chain. Five reaches of one total, drawn as type and rule: five numbers do not need a
   library, and a funnel would imply a containment these do not have. */
.gch{list-style:none;margin:20px 0 0;padding:0}
.gch-r{display:grid;grid-template-columns:1fr 30% 130px 52px;gap:18px;align-items:center;
  padding:13px 0;border-top:1px solid var(--rule)}
.gch-r:first-child{border-top:0}
.gch-s{margin:0;font:500 13.5px/1.4 var(--sans);color:var(--ink)}
.gch-b{margin:0;height:8px;background:var(--rule)}
.gch-b i{display:block;height:100%;background:var(--ink3)}
.gch-n{margin:0;text-align:right;font-variant-numeric:tabular-nums}
.gch-n b{display:block;font:600 15px/1.2 var(--sans);color:var(--ink)}
.gch-n em{display:block;margin-top:2px;font-style:normal;font:400 11.5px/1.4 var(--sans);
  color:var(--ink3)}
.gch-p{margin:0;text-align:right;font:500 13px/1.2 var(--sans);color:var(--ink2);
  font-variant-numeric:tabular-nums}
/* The row that is the point carries the accent, and it is the only one that does. */
.gch-last .gch-s{font-weight:600}
.gch-last .gch-b i{background:var(--live)}
.gch-last .gch-n b{color:var(--ink)}
@media (max-width:820px){.gch-r{grid-template-columns:1fr 110px}.gch-b,.gch-p{display:none}}

/* The network. A fixed frame, because a graph that grows with its content pushes the page
   around every time a label wraps. */
.gnet-wrap{margin:18px 0 0;border:1px solid var(--rule);background:var(--bg2)}
#gnet{width:100%;height:clamp(420px,58vh,720px)}
.gtip{position:fixed;z-index:80;max-width:290px;padding:10px 12px;background:var(--bg2);
  border:1px solid var(--rule2);pointer-events:none;box-shadow:0 2px 14px rgba(0,0,0,.09)}
.gtip b{display:block;font:600 13px/1.3 var(--sans);color:var(--ink)}
.gtip span{display:block;margin-top:2px;font:500 10.5px/1.4 var(--sans);color:var(--ink3);
  text-transform:uppercase;letter-spacing:.06em}
.gtip em{display:block;margin-top:6px;font-style:normal;font:400 12px/1.45 var(--sans);
  color:var(--ink2)}

/* ── the network, read ────────────────────────────────────────────────────────────────────
 * The picture and what it says, side by side. They are one artefact: a reader who has to
 * scroll away from the graph to find out what a colour means is reading two things.
 */
.gcols{margin-top:18px;align-items:start}
.gcols .gnet-wrap{margin:0}
/* The legend sits under the frame and not inside it. Inside, anchored to the corner the
   layouts were expected to leave emptiest, it covered the third of the drawing that held the
   people with no route, and the scene scale covered half. A key that hides what it is a key to
   is worse than a key the reader has to look below the picture for. */
.gkey{padding:10px 0 0}
.gkey-s{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:4px 20px}
.gkey-s li{display:flex;align-items:baseline;gap:7px;font:400 11.5px/1.5 var(--sans);
  color:var(--ink2);min-width:0}
.gkey-s i{flex:none;width:8px;height:8px;position:relative;top:1px}
.gkey-s b{font-weight:600;color:var(--ink);white-space:nowrap}
.gkey-s em{font-style:normal;color:var(--ink3);min-width:0}
.gkey-n{margin:8px 0 0;font:400 11px/1.5 var(--sans);color:var(--ink3);text-wrap:pretty}
.gkey-n b{font-weight:600;color:var(--ink2)}

/* Four control groups in one strip. Without a separator the label of one group reads as the
   last item of the group before it, and "Colour" sat hard against "10+" as though it were a
   sixth tie strength. */
.gctl{display:flex;align-items:stretch}
.gctl+.gctl{border-left:1px solid var(--rule);padding-left:16px;margin-left:16px}
.gctl .lbl{align-self:center}

.gread-h{margin:0 0 4px;font:500 10.5px/1.5 var(--sans);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink3)}
/* One reading per row, the label quiet and the sentence loud, because the label is a heading
   for something already short and the figure inside the sentence is the thing being read. */
.grd{padding:12px 0;border-top:1px solid var(--rule)}
.grd-l{margin:0;font:600 11.5px/1.4 var(--sans);color:var(--ink)}
.grd-s{margin:4px 0 0;font:400 12.5px/1.6 var(--sans);color:var(--ink2);text-wrap:pretty}
.grd-s b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.gread-f{margin:14px 0 0;flex:none;text-wrap:pretty}

/* The route, as a word rather than a dot, because three states with names are three states a
   reader can repeat and three dots are a key to memorise. */
.gpill{display:inline-block;padding:1px 7px;font:500 11px/1.6 var(--sans);white-space:nowrap;
  border:1px solid var(--rule2);color:var(--ink2)}
.gpill.g-payable{border-color:var(--live);color:var(--live);font-weight:600}
.gpill.g-one-hop{border-color:var(--caution);color:var(--caution)}
/* Two hundred and sixty rows under a graph, a panel and a strip made the surface four screens
   long and buried the split identities under all of it. The list scrolls in its own frame, the
   way every other long list on this application does, and the head stays put while it does. */
.gtb-wrap{max-height:min(56vh,520px);border-top:0}
.gtb thead th{position:sticky;top:0;z-index:2;background:var(--bg)}
.gtb tbody th{white-space:nowrap}
/* The face beside the name, at the size a name is set. Small enough that the column still
   reads as a list of people rather than a contact sheet, and the same circle as the page it
   opens, so the reader recognises what they clicked when it arrives. */
.gtb-who{display:inline-flex;align-items:center;gap:9px;min-width:0}
.gsp tbody [data-go]{cursor:pointer}
.gsp tbody [data-go]:hover{color:var(--ink)}
.gtb.click tbody tr{cursor:pointer}
.gtip-go{color:var(--ink3)!important;font-size:11px!important;margin-top:8px!important}

.gtb td.num,.gtb th.num{font-variant-numeric:tabular-nums}
.gsp td em{font-style:normal;color:var(--ink3)}

@media (max-width:820px){
  /* The separators become misleading once the strip wraps: a group that has fallen to the next
     line carries a rule on its left that points at nothing. */
  .gctl+.gctl{border-left:0;padding-left:0;margin-left:0}
}

/* Perspectives. One shape per lens, so six different questions read the same way down the
   page and the differences between them are the figures rather than the furniture. */
.psp{margin-top:clamp(20px,2.6vw,32px)}
.psp .tab-content{padding:clamp(20px,2.6vw,30px) 0 0}
.psp-ask{margin:0;font:600 clamp(15px,1.7vw,18px)/1.35 var(--sans);letter-spacing:-.014em;
  color:var(--ink);max-width:60ch}
.psp .lsay{margin:7px 0 0;max-width:68ch}
.psp-n{margin:16px 0 0;font:400 14px/1.6 var(--sans);color:var(--ink2);max-width:68ch}
.psp-n b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.psp-h{margin:clamp(22px,2.6vw,32px) 0 0;font:600 13px/1.4 var(--sans);color:var(--ink2)}
.psp-t{margin-top:14px}
.psp-t .psp-v{font-variant-numeric:tabular-nums;white-space:nowrap}
/* The bar is the comparison and the figure is the fact, so the bar is quiet and sits behind a
   number rather than replacing it. */
.psp-bar{display:inline-block;vertical-align:middle;width:calc(100% - 56px);height:7px;
  background:var(--rule);margin-right:8px}
.psp-bar i{display:block;height:100%;background:var(--ink3)}
.psp-t tr:hover .psp-bar i{background:var(--ink)}
.psp-t em{font-style:normal;font-variant-numeric:tabular-nums;color:var(--ink3);font-size:12px}

/* The table, held to the measured taste rather than to the library's defaults.
   Rule 2 takes hierarchy from weight, case, position and rule and never from scale, and daisyUI
   ships a 14px bold header over 12px data, so the column names were larger than the figures
   they head. The header is the quietest thing in the table now and the row is the loudest.
   Rule 8 keeps content on the ground, so rows are separated by a hairline and never by a
   stripe. Soundcharts is the peer the taste file names and its table is dense: 7px of padding
   on 13px text is a 32px row, which puts a third more of a 585-row list on a screen.
   Figures line up under each other or a column cannot be read downward at all. */
.table thead th{font:500 10.5px/1.5 var(--sans);letter-spacing:.07em;text-transform:uppercase;
  color:var(--ink3);padding:0 12px 8px;white-space:nowrap;
  border-bottom:1px solid var(--rule2)}
.table :where(tbody th,tbody td){padding:7px 12px;font:400 13px/1.45 var(--sans);
  color:var(--ink2)}
.table tbody th{font-weight:600;color:var(--ink)}
.table tbody tr:hover{background:var(--bg2)}
/* Every figure in every table, not only the ones a surface remembered to mark. Lining digits
   are what let a column be read downward, and a table is where that matters most. */
.table{font-variant-numeric:tabular-nums}
.table .num{text-align:right;white-space:nowrap}
.table thead th.num{text-align:right}

/* Finding one contributor in 585, which is what a reader does with a list this long far more
   often than they page through it. */
.psp-find{margin:16px 0 0}
.psp-find .input{border-radius:0;width:min(320px,100%);font:400 13px/1.4 var(--sans)}
/* The number a society pays, and where the register that holds it came from. */
.psp-ipi code{font:400 12.5px/1.4 var(--mono);color:var(--ink);letter-spacing:-.01em}
.psp-src{display:block;font-style:normal;font:400 11px/1.4 var(--sans);color:var(--ink3);
  margin-top:2px;text-transform:uppercase;letter-spacing:.05em}
/* More than one party under one name. Not a failed lookup: the register holds several and the
   name cannot say which of them is owed, which is the finding rather than the gap. */
.psp-many{font:500 12.5px/1.4 var(--sans);color:var(--caution,var(--ink2))}

/* Paging a list that is a list rather than a top ten. The count sits beside the control, so a
   reader knows where they are in 585 without counting pages. */
.psp-page{display:flex;align-items:center;justify-content:space-between;gap:16px;
  flex-wrap:wrap;margin:16px 0 0}
.psp-of{font:400 12.5px/1.4 var(--sans);color:var(--ink3);font-variant-numeric:tabular-nums}
.psp-page .btn{border-radius:0;font-variant-numeric:tabular-nums}
/* A contributor the organisation publishes and the catalogue found nothing against. Present
   because the absence is the fact, and quiet because there is nothing to read across the row. */
.psp-nil th{color:var(--ink2);font-weight:500}
.psp-nil td{color:var(--ink3)}

/* A pass: what a set of instruments is still waiting on. The heading carries the ask and the
   figures, so a reader who stops at the heading has the whole of it, and the instruments under
   it are the detail. Ordered by what settles them rather than by size, so the section that can
   be sent today sits above the one that cannot. */
.ipass{margin:clamp(26px,3.4vw,44px) 0 0}
.ipass:first-of-type{margin-top:0}
.ipass-h{display:grid;grid-template-columns:1fr auto;gap:20px;align-items:start;
  padding:0 0 14px;border-bottom:1px solid var(--rule)}
.ipass-n{margin:0 0 6px;font:700 10px/1.6 var(--sans);letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink3)}
.ipass-h .lsh{margin:0}
.ipass-h .lsay{margin:6px 0 0;max-width:64ch}
.ipass-v{text-align:right;min-width:9ch}
.ipass-v .inst-v + .inst-v{margin-top:10px}
.ipass-c{margin:9px 0 0;font:400 12px/1.4 var(--sans);color:var(--ink3)}
@media (max-width:640px){.ipass-h{grid-template-columns:1fr}.ipass-v{text-align:left}}
/* daisyUI holds `.stat-desc` on one line, which is right for a two-word unit and wrong for the
   sentence that qualifies the figure above it. Scoping this to one surface was the wrong size
   of fix: the catalogue carries four captions of 253 to 311px in a 218px column, so the first
   screen of the journey ran each one into the next. A caption that qualifies a number wraps,
   everywhere it appears. */
.stat-desc{white-space:normal;text-wrap:pretty}
.stats-say{flex-wrap:wrap}
.stats-say .stat-desc{max-width:34ch}
.inst-band{display:flex;flex-wrap:wrap;gap:5px;justify-content:flex-end;margin:9px 0 0}
/* Worth nothing is a different kind of thing, not a small one. */
.insts-nil .inst{opacity:.72}
.insts-nil .inst-v{color:var(--ink3);font-size:15px;font-weight:500;letter-spacing:0}
.inil{margin:clamp(30px,4vw,52px) 0 0}
@media (max-width:640px){.inst{grid-template-columns:1fr}.inst-r{text-align:left;margin-top:12px}
  .inst-band{justify-content:flex-start}}

/* ---------------------------------------------------------------- the checks
   The reading behind Decide. Nothing here is a new component: the beats come from the briefs,
   the bar and the table from the perspectives, and the only additions are the two states this
   surface has to carry that no other one does. A stream is held, stood in for, or absent, and
   a check is either speaking or quiet. Both are said in words as well as in tone, because a
   colour that carries the whole meaning is a colour a reader has to be taught. */
.ck-h{max-width:72ch}
.ck-lede{margin:12px 0 0;font:400 15px/1.65 var(--sans);color:var(--ink2);max-width:62ch}
.ck-s{margin:clamp(34px,4vw,52px) 0 0;padding-top:clamp(26px,3vw,34px);
  border-top:1px solid var(--rule)}
.ck-s h2{margin:0;font:600 15px/1.3 var(--sans);letter-spacing:-.01em;color:var(--ink)}
.ck-p{margin:10px 0 0;font:400 14px/1.65 var(--sans);color:var(--ink2);max-width:68ch}
.ck-p b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.ck-t{margin-top:18px}
/* The stream and what it is, on two lines, because the name alone does not tell a rights owner
   which of their own artefacts we mean. */
.ck-t tbody th em{display:block;margin-top:2px;font-style:normal;
  font:400 11.5px/1.5 var(--sans);color:var(--ink3);text-transform:none;letter-spacing:0}
.ck-st{display:inline-block;font:500 10.5px/1.6 var(--sans);letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink3);padding:1px 7px;border:1px solid var(--rule2)}
.ck-st.on{color:var(--ink);border-color:var(--ink3)}
.ck-st.off{color:var(--ink3);border-style:dashed}
.ck-cov.off .psp-bar{background:transparent;border:1px dashed var(--rule2);height:9px}
/* A stream that is absent is not a small bar, it is no bar, and the row says so in words. */
.ck-cov.off td:nth-child(3){color:var(--ink3)}
/* A quiet check is dimmed and never hidden. The sixty-one are the product's claim about what it
   checks, and dropping the fifty-three that said nothing would make the claim unfalsifiable. */
.ck-61 tr.quiet th b{font-weight:500;color:var(--ink2)}
.ck-61 tr.quiet .ck-w{color:var(--ink3)}
.ck-61 tbody th b{display:block;font-weight:600;color:var(--ink)}
.ck-61 tbody th em{display:block;margin-top:2px;font-style:normal;
  font:400 11px/1.5 var(--sans);color:var(--ink3);text-transform:uppercase;letter-spacing:.05em}
.ck-61 tbody tr{cursor:pointer}
.ck-w{display:inline-block;margin:0 6px 0 0;font:400 12px/1.5 var(--sans);color:var(--ink2)}
.ck-w + .ck-w::before{content:"+ ";color:var(--ink3)}
.ck-w.on{color:var(--ink3)}
.ck-tabs{margin-top:18px}
.drawer .dr-sub{margin:4px 0 0;font:400 11px/1.4 var(--sans);color:var(--ink3);
  text-transform:uppercase;letter-spacing:.06em}
.drawer h4{margin:20px 0 5px;font:500 11.5px/1 var(--sans);color:var(--ink3)}
.drawer h4 + p{margin:0;font:400 13px/1.65 var(--sans);color:var(--ink2)}
.drawer h4 + p b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}

/* ------------------------------------------------------- one recording, checked
   The audit sheet. Everything on it is a table because everything on it is evidence, and the
   only new shape is the pair of rows: a check, and the questions it asked folded under it.
   Rule 8 keeps content on the ground, so an opened check is marked by a rule down its left
   edge rather than by a panel floating above the page. */
.sh-h{display:flex;gap:clamp(18px,2.4vw,26px);align-items:flex-start;max-width:78ch}
.sh-art{flex:0 0 auto}
.sh-art .cov{border:1px solid var(--rule2)}
.sh-k{margin:0;font:500 10.5px/1 var(--sans);letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink3)}
.sh-h h1{margin:9px 0 0;font:600 clamp(21px,2.6vw,27px)/1.2 var(--sans);letter-spacing:-.02em;
  color:var(--ink)}
.sh-by{margin:6px 0 0;font:400 14px/1.5 var(--sans);color:var(--ink2)}
.sh-by span{color:var(--ink3)}
.sh-meta{display:flex;flex-wrap:wrap;gap:0 clamp(20px,3vw,34px);margin:16px 0 0}
.sh-meta dt{font:500 10.5px/1.5 var(--sans);letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink3)}
.sh-meta dd{margin:2px 0 0;font:400 13px/1.5 var(--sans);color:var(--ink);
  font-variant-numeric:tabular-nums}
.sh-meta i{font-style:normal;color:var(--ink3)}
.sh-s{margin:clamp(34px,4vw,52px) 0 0;padding-top:clamp(26px,3vw,34px);
  border-top:1px solid var(--rule)}
.sh-s h2{margin:0;font:600 15px/1.3 var(--sans);letter-spacing:-.01em;color:var(--ink)}
.sh-g{margin:clamp(26px,3vw,36px) 0 0}
.sh-g h3{display:flex;align-items:baseline;gap:10px;margin:0;
  font:600 12px/1.4 var(--sans);letter-spacing:.02em;color:var(--ink2)}
.sh-g h3 em{font-style:normal;font:400 11.5px/1 var(--sans);color:var(--ink3);
  font-variant-numeric:tabular-nums}
/* A check and its questions are one unit, so the group is a tbody and the border belongs to it
   rather than to either row. */
.sh-t tbody{border-bottom:1px solid var(--rule)}
.sh-t .sh-sum{cursor:pointer}
.sh-t .sh-sum th b{display:block;font-weight:600;color:var(--ink)}
.sh-t .sh-sum th em{display:block;margin-top:2px;font-style:normal;
  font:400 11px/1.5 var(--sans);color:var(--ink3);text-transform:uppercase;letter-spacing:.05em}
.sh-t .sh-sum.open th b{color:var(--ink)}
.sh-rep{display:inline-block;margin-left:8px;font:500 10.5px/1.6 var(--sans);letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink);border-bottom:2px solid var(--ink3)}
.sh-ev span{display:block;font:400 10.5px/1.4 var(--sans);color:var(--ink3)}
/* The questions. Marked down the left rather than boxed, so the evidence sits on the page at the
   same level as the check it belongs to. */
.sh-det > td{padding:0 12px 16px 12px;background:var(--bg2)}
.sh-words{margin:0 0 10px;padding:10px 0 0;font:400 12.5px/1.6 var(--sans);color:var(--ink2);
  max-width:78ch}
.sh-atoms{width:100%;border-collapse:collapse;border-left:2px solid var(--rule2)}
.sh-atoms td{padding:5px 12px;font:400 12.5px/1.5 var(--sans);color:var(--ink2);
  vertical-align:baseline}
.sh-q{width:46%;color:var(--ink)}
.sh-v{width:22%;font-variant-numeric:tabular-nums;color:var(--ink)}
.sh-r{color:var(--ink3);font-size:11.5px}
.sh-no{font-style:normal;color:var(--ink3)}
.sh-nil{font-style:normal;color:var(--ink3)}
.sh-a.unanswerable{opacity:.72}
.sh-a.contradicted .sh-r{color:var(--ink2)}
.sh-close{margin:12px 0 0;font:400 12.5px/1.6 var(--sans);color:var(--ink2);max-width:78ch}
.sh-close b{display:block;font:500 10.5px/1.6 var(--sans);letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink3)}

/* ── a person's own page ──────────────────────────────────────────────────────────────────
 * The atlas's walk, in the drawer. The circle does the work: two hundred and forty three
 * photographs of wildly different crops, aspect ratios and backgrounds sit in one grid only
 * because every one of them is cropped to the centre of a face at the same diameter. A square
 * grid of the same files reads as a scrapbook.
 */
.pv{padding-top:6px}
.pv-head{text-align:center;padding-bottom:6px}
.pv h3{margin:0;font:700 clamp(21px,2.4vw,27px)/1.2 var(--sans);letter-spacing:-.02em;
  color:var(--ink);text-wrap:balance}
.pv-id{margin:6px 0 0;font:400 13px/1.55 var(--sans);color:var(--ink2)}
.pv-id b{color:var(--rule2);font-weight:400;margin:0 5px}
.pv-cred{margin:8px 0 0;font:400 10.5px/1.5 var(--sans);color:var(--ink3)}
.pv-off-say{margin:12px auto 0;max-width:46ch;font:400 11.5px/1.55 var(--sans);
  color:var(--ink3);border-top:1px solid var(--rule);padding-top:10px;text-wrap:pretty}

/* The portrait, and the half of the catalogue that has no photograph. The initial is set in
   the same circle at the same diameter rather than left as a hole, because with 243 portraits
   against 544 people the fallback is most of what any grid shows. */
.pv-ph{display:grid;place-items:center;overflow:hidden;border-radius:50%;flex:none;
  background:var(--plate);border:1px solid var(--rule);margin:0 auto}
.pv-ph img{width:100%;height:100%;object-fit:cover;display:block}
/* A photograph is held for 224 of the 544, so a grid of these is mostly initials and the
   initial has to carry itself. Light rather than bold, and wide rather than tight: at 600
   weight in the page's own text colour it read as a missing image with a label stamped on it,
   and at 300 with the letters spaced it reads as a plate that was made this way. */
.pv-ph i{font-style:normal;font:300 1em/1 var(--sans);letter-spacing:.04em;color:var(--ink3);
  opacity:.72}
.pv-big{margin-bottom:16px}
.pv-big i{font-size:52px}

.pv-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:7px;margin:16px 0 0}
.pv-c{display:inline-flex;align-items:baseline;gap:7px;border:1px solid var(--rule);
  padding:5px 10px;font:400 11.5px/1.4 var(--sans);color:var(--ink2)}
.pv-c b{font:600 12.5px/1.2 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums}

.pv-h{margin:30px 0 0;font:500 10.5px/1.5 var(--sans);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink3);border-bottom:1px solid var(--rule);
  padding-bottom:8px}
.pv-say{margin:12px 0 0;font:400 11.5px/1.55 var(--sans);color:var(--ink3);text-wrap:pretty}

.pv-rel{list-style:none;margin:0;padding:0}
.pv-rel li{display:flex;align-items:center;gap:12px;padding:9px 0;
  border-bottom:1px solid var(--rule)}
.pv-rn{flex:1;min-width:0;font:500 13px/1.4 var(--sans);color:var(--ink)}
.pv-rc{flex:none;font:400 11.5px/1.4 var(--sans);color:var(--ink3);white-space:nowrap}
.pv-rc b{font:600 13px/1.2 var(--sans);color:var(--ink2);margin-right:5px;
  font-variant-numeric:tabular-nums}

/* Six across at the drawer's width, which is what makes it read as a roster rather than as a
   list with pictures glued to it. */
.pv-with{list-style:none;margin:16px 0 0;padding:0;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:18px 10px}
/* The name is given the two lines the longest of them needs, so a "Johann Sebastian Bach"
   beside a "Sun Ra" does not shunt one count down a line and leave the row looking broken. */
.pv-with li{text-align:center;cursor:pointer;min-width:0;display:flex;flex-direction:column}
.pv-with .pv-wn{flex:1}
.pv-with .pv-ph{margin-bottom:8px;transition:border-color var(--dur) var(--ease),
  transform var(--dur) var(--ease)}
.pv-with li:hover .pv-ph{border-color:var(--live);transform:translateY(-2px)}
.pv-with .pv-ph i{font-size:26px}
.pv-wn{display:block;font:500 11.5px/1.35 var(--sans);color:var(--ink);overflow-wrap:anywhere}
.pv-wc{display:block;margin-top:3px;font:400 10.5px/1.4 var(--sans);color:var(--ink3)}
.pv-wc b{color:var(--ink2);font-weight:600;font-variant-numeric:tabular-nums}
/* Somebody the cap left out of the drawing has no measures, so there is no page to open. The
   face stays, because they are still a real collaborator and hiding them would understate the
   list, but it does not pretend to be a link. */
.pv-with li.pv-off{cursor:default;opacity:.62}
.pv-with li.pv-off:hover .pv-ph{border-color:var(--rule);transform:none}
@media (prefers-reduced-motion:reduce){.pv-with li:hover .pv-ph{transform:none}}

/* ------------------------------------------------- choosing a row, and what it costs
   The picker is a filter rather than a list, because 633 is too many to scan and too few to
   need anything cleverer. It opens on what carries the most, so a reader who does not have a
   recording in mind is still shown the ones worth opening first. */
.sh-pick{position:relative;max-width:560px;margin:0 0 clamp(22px,2.6vw,30px)}
.sh-find .input{border-radius:0;width:100%;font:400 13px/1.4 var(--sans)}
.sh-hits{position:absolute;z-index:20;left:0;right:0;top:calc(100% + 4px);background:var(--bg);
  border:1px solid var(--rule2);max-height:56vh;overflow:auto;padding:0 10px 8px}
.sh-hit tbody tr{cursor:pointer}
.sh-hit tbody tr.here{background:var(--bg2)}
.sh-hit tbody th b{display:block;font-weight:600;color:var(--ink)}
.sh-hit tbody th em{display:block;margin-top:1px;font-style:normal;
  font:400 11px/1.4 var(--sans);color:var(--ink3)}
.sh-hit .sh-hr{color:var(--ink);font-weight:600}
.sh-hint,.sh-none{margin:8px 2px 4px;font:400 11.5px/1.5 var(--sans);color:var(--ink3)}
/* The money. One figure is the answer and the split is the detail, so the answer is the only
   thing at size and the two beside it are the same weight as each other. */
.sh-money{display:flex;flex-wrap:wrap;gap:clamp(20px,3.4vw,44px);margin:20px 0 0;
  padding:18px 0 0;border-top:1px solid var(--rule)}
.sh-lbl{margin:0 0 7px;font:500 10.5px/1.4 var(--sans);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink3)}
.sh-money{align-items:flex-start}
.sh-big{flex:0 0 auto;min-width:210px}
.sh-fig{display:block;font:700 clamp(26px,3.6vw,36px)/1 var(--sans);letter-spacing:-.035em;
  color:var(--ink);font-variant-numeric:tabular-nums}
.sh-sp{margin:7px 0 0;font:400 12px/1.4 var(--sans);color:var(--ink3);
  font-variant-numeric:tabular-nums}
/* The figure is the claim and this is the argument for reading it correctly, so it sits beside
   the figure rather than under it: a reader who takes the number and leaves has still passed
   the sentence saying it is counted once. */
.sh-said{flex:1 1 340px;max-width:66ch}
.sh-said p{margin:0 0 9px;font:400 13px/1.65 var(--sans);color:var(--ink2)}
.sh-said p:last-child{margin-bottom:0}
.sh-said b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.sh-caveat{margin:18px 0 0;font:400 12.5px/1.65 var(--sans);color:var(--ink3);max-width:78ch}
.sh-caveat b{font-weight:600;color:var(--ink2)}
/* What to do. The instrument leads because it is the sentence somebody acts on; the party and
   the clock are the two facts that decide whether they can. */
.sh-do tbody th b{display:block;font-weight:600;color:var(--ink)}
.sh-do tbody th em{display:block;margin-top:2px;font-style:normal;
  font:400 11.5px/1.5 var(--sans);color:var(--ink3)}
.sh-sub{display:block;margin-top:2px;font:400 11px/1.4 var(--sans);color:var(--ink3)}
.sh-do tbody tr{border-bottom:1px solid var(--rule)}
/* Which kinds of claim the one exposure falls under. A list and not a sentence: both phrases
   carry their own commas and joining them with "and" ran them into one another. */
.sh-kinds{list-style:none;margin:0 0 9px;padding:0}
.sh-kinds li{position:relative;padding:2px 0 2px 14px;font:400 13px/1.6 var(--sans);
  color:var(--ink2)}
.sh-kinds li::before{content:"";position:absolute;left:0;top:13px;width:6px;height:1px;
  background:var(--ink3)}
.sh-kinds b{font-weight:600;color:var(--ink)}
.sh-kinds span{color:var(--ink3)}

/* ── the records and the people ───────────────────────────────────────────────────────────
 * The landing. Covers and faces at a size worth looking at, because the reader this leads with
 * is the founder rather than the analyst and what he recognises is the record and the person,
 * not a node. Everything that reads the catalogue is one link below, and it is a link rather
 * than a tab so that nothing on this page competes with the photographs.
 */
.rx-h{display:flex;align-items:baseline;gap:12px;margin:clamp(26px,3vw,40px) 0 0;
  font:600 13px/1.4 var(--sans);color:var(--ink);border-bottom:1px solid var(--rule);
  padding-bottom:10px}
.rx-h em{font-style:normal;font:500 10.5px/1.5 var(--sans);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink3)}
/* Beside the count, not under the grid: it selects what the grid is, so it belongs where the
   grid is named. */
.rx-sw{margin-left:auto;background:none;border:1px solid var(--rule);padding:4px 10px;
  font:500 11px/1.4 var(--sans);color:var(--ink2);cursor:pointer}
.rx-sw:hover{border-color:var(--ink2);color:var(--ink)}
.rx-sw[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--bg)}
.rx-say{margin:14px 0 0;font:400 11.5px/1.6 var(--sans);color:var(--ink3);max-width:74ch;
  text-wrap:pretty}
.rx-more{background:none;border:0;padding:0;margin-left:6px;font:500 11.5px/1.6 var(--sans);
  color:var(--ink);border-bottom:1px solid var(--rule2);cursor:pointer}
.rx-more:hover{border-color:var(--ink)}

/* A cover is the thing itself and gets the room to be one. Nothing is cropped to a circle
   here: a square record stays square, and only a face is cropped to its centre. */
.rx-rel{list-style:none;margin:20px 0 0;padding:0;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:24px 18px}
.rx-rel li{cursor:pointer;min-width:0}
.rx-cov{display:block;margin-bottom:9px}
.rx-cov .cov{width:100%!important;height:auto!important;aspect-ratio:1;object-fit:cover;
  display:block;background:var(--plate);transition:transform var(--dur) var(--ease)}
.rx-rel li:hover .cov{transform:translateY(-2px)}
.rx-t{display:block;font:500 12.5px/1.35 var(--sans);color:var(--ink);overflow-wrap:anywhere}
.rx-s{display:block;margin-top:3px;font:400 11px/1.45 var(--sans);color:var(--ink3)}
.rx-s b{color:var(--rule2);font-weight:400}
.rx-s i{font-style:normal;color:var(--caution)}

.rx-face{list-style:none;margin:20px 0 0;padding:0;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(112px,1fr));gap:26px 12px}
.rx-face li{text-align:center;cursor:pointer;min-width:0;display:flex;flex-direction:column}
.rx-face .pv-ph{margin-bottom:10px;transition:border-color var(--dur) var(--ease),
  transform var(--dur) var(--ease)}
.rx-face li:hover .pv-ph{border-color:var(--live);transform:translateY(-2px)}
.rx-face .pv-ph i{font-size:34px}
.rx-fn{flex:1;font:500 12px/1.35 var(--sans);color:var(--ink);overflow-wrap:anywhere}
.rx-fc{display:block;margin-top:3px;font:400 10.5px/1.4 var(--sans);color:var(--ink3)}

/* The way down to everything the analyst wants. A block rather than a line, because it is the
   only route off this page and a reader who wants it should not have to hunt for a word. */
.rx-drill{display:block;margin:clamp(30px,3.4vw,46px) 0 0;padding:18px 0;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);text-decoration:none}
.rx-dh{display:block;font:600 13.5px/1.3 var(--sans);color:var(--ink)}
.rx-dh::after{content:" \203a";color:var(--ink3)}
.rx-drill:hover .rx-dh{color:var(--live)}
.rx-dn{display:block;margin-top:5px;font:400 12px/1.6 var(--sans);color:var(--ink2);
  max-width:74ch;text-wrap:pretty}

/* The trail. Where this sits, not a back button: a reader who arrived on a link has no back. */
.rx-trail{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;margin:0 0 clamp(16px,2vw,24px);
  font:500 11.5px/1.5 var(--sans)}
.rx-trail a{color:var(--ink3);text-decoration:none}
.rx-trail a:hover{color:var(--ink)}
.rx-trail a::after{content:" \203a";margin-left:8px;color:var(--rule2)}
.rx-trail b{color:var(--ink);font-weight:600}

/* One record. */
.rv-head{display:flex;flex-wrap:wrap;gap:clamp(20px,3vw,38px);align-items:flex-start}
.rv-cov{flex:none}
.rv-cov .cov{width:clamp(180px,26vw,260px)!important;height:auto!important;aspect-ratio:1;
  object-fit:cover;display:block;background:var(--plate)}
.rv-head>div{flex:1 1 300px;min-width:0}
.rv-head h1{margin:0;font:700 clamp(24px,3vw,34px)/1.15 var(--sans);letter-spacing:-.022em;
  color:var(--ink);text-wrap:balance}
.rv-s{margin:9px 0 0;font:400 12.5px/1.6 var(--sans);color:var(--ink2)}
.rv-chips{justify-content:flex-start;margin-top:18px}
.rv-with{margin-top:18px}
.pv-rel li[data-rel]{cursor:pointer}
.pv-rel li[data-rel]:hover .pv-rn{color:var(--live)}

/* ------------------------------------------------------- the decomposition tree
   A treegrid and not an accordion. Every row carries three figures that have to be read down a
   column, and a nested <details> loses the columns at the first indent: the whole point of a
   decomposition is that a child's figure sits under its parent's, so the alignment is the
   argument rather than the decoration. */
.tv-s{margin:clamp(38px,4.4vw,58px) 0 0;padding-top:clamp(26px,3vw,34px);
  border-top:1px solid var(--rule)}
.tv-s h2{margin:0;font:600 15px/1.3 var(--sans);letter-spacing:-.01em;color:var(--ink)}
.tv-p{margin:10px 0 0;font:400 14px/1.65 var(--sans);color:var(--ink2);max-width:72ch}
.tv-p b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.tv-head{display:flex;justify-content:flex-end;margin:18px 0 0}
.tv-lv .btn{border-radius:0;font:500 11.5px/1 var(--sans);letter-spacing:.01em}
.tv-lv .btn-active{background:var(--ink);color:var(--bg)}
.tv{margin-top:12px}
.tv tbody tr{border-bottom:1px solid var(--rule)}
.tv .tv-r[aria-expanded]{cursor:pointer}
.tv .tv-r:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}
/* Depth is indentation and weight, never a colour or a rule of its own: rule 2 takes hierarchy
   from weight, case and position. A label is the loudest row on the table and a check the
   quietest, and nothing between them changes size. */
.tv-in{display:flex;align-items:baseline;gap:7px;padding-left:calc(var(--d) * 20px)}
.tv-t{flex:0 0 auto;width:13px;font:400 9px/1 var(--sans);color:var(--ink3);
  background:none;border:0;padding:0;cursor:pointer}
.tv-nub{flex:0 0 auto;width:13px}
.tv .tv-d0 th b{font-weight:700;color:var(--ink)}
.tv .tv-d1 th b{font-weight:600;color:var(--ink)}
.tv .tv-d2 th b{font-weight:500;color:var(--ink)}
.tv .tv-d3 th b{font-weight:400;color:var(--ink2)}
.tv th em{display:block;margin:2px 0 0 20px;font-style:normal;font:400 11px/1.4 var(--sans);
  color:var(--ink3)}
.tv .tv-d1 th em{margin-left:40px}
.tv .tv-d2 th em{margin-left:60px}
.tv .tv-d3 th em{margin-left:80px}
/* A check row carries no money, and the blank is the statement. Nothing is greyed out to look
   disabled, because the row is not disabled: there is genuinely no figure that belongs there. */
.tv .tv-d3{background:var(--bg2)}
.tv .tv-d3 td{color:var(--ink3)}
.tv td.num{font-variant-numeric:tabular-nums}
/* Five levels now: the total, the labels, the releases, the recordings, the checks. */
.tv .tv-d4 th b{font-weight:400;color:var(--ink2)}
.tv .tv-d4 th em{margin-left:100px}
.tv .tv-d4{background:var(--bg2)}
.tv .tv-d4 td{color:var(--ink3)}
.tv .tv-d0 th b{font-weight:700;letter-spacing:-.01em}
.tv .tv-d0 td{font-weight:600;color:var(--ink)}
/* Six columns and a name that indents four levels does not fit a narrow window. The table
   scrolls inside its own box rather than taking the page sideways with it. */
.tv-scroll{overflow-x:auto;margin-top:12px}
.tv-scroll .tv{margin-top:0;min-width:660px}
.tv th[scope="row"]{min-width:280px}

/* ----------------------------------------------------------------- the icicle
   The decomposition as width, above the same decomposition as figures. Monochrome, because the
   only thing being encoded is depth and the quantity is already the width: colour would be a
   second channel carrying nothing. Depth reads lighter as it goes down, so the total is the
   most solid thing on it and a recording the least. */
.ic{margin:20px 0 0;padding:0}
.ic svg{display:block;width:100%;height:clamp(120px,15vw,142px)}
/* Four depths off one ink, stepped by opacity rather than by four named greys. The palette's
   --ink2 and --ink3 are #8A8A8A and #7C7C7C in dark, six points apart, so a label band and a
   release band were the same colour on that ground and the picture lost a level. Opacity steps
   are even in both themes by construction and cannot drift when the palette moves. */
.ic rect{fill:var(--ink);transition:opacity .12s var(--ease)}
.ic .ic-d0 rect{opacity:1}
.ic .ic-d1 rect{opacity:.82}
.ic .ic-d2 rect{opacity:.62}
.ic .ic-d3 rect{opacity:.32}
.ic text{fill:var(--bg);font-family:var(--sans);font-weight:500;pointer-events:none;
  letter-spacing:.005em}
.ic .ic-b{cursor:pointer}
.ic .ic-b:hover rect,.ic .ic-b:focus-visible rect{opacity:1}
.ic .ic-b:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.ic figcaption{margin:9px 0 0;font:400 11.5px/1.6 var(--sans);color:var(--ink3);max-width:76ch}
/* The bar sits under the figure rather than beside it: the figure is the fact and the bar is
   the comparison, and a column of numbers has to stay readable downward. */
.tv-bar{display:block;height:3px;margin:3px 0 0;background:var(--rule)}
.tv-bar i{display:block;height:100%;background:var(--ink3)}
.tv tr:hover .tv-bar i{background:var(--ink)}
.tv .tv-lit{background:var(--bg2);box-shadow:inset 2px 0 0 var(--ink)}
/* The spacer rows the virtualiser uses to hold the height of everything above and below the
   window. They carry no content and no rule, so the table reads as one continuous list. */
.tv .tv-pad{border:0}
.tv .tv-pad td{padding:0;border:0}

/* ------------------------------------------- the contributor table's own controls
   A sortable heading is a button in a cell, so it takes focus and answers the keyboard without
   anything being added to make it do so. The mark is the direction and the label carries it too,
   because an arrow is not a thing a screen reader can announce. */
.psp-sort{background:none;border:0;padding:0;cursor:pointer;font:inherit;color:inherit;
  display:inline-flex;align-items:baseline;gap:5px;letter-spacing:inherit;
  text-transform:inherit}
.psp-sort:hover{color:var(--ink)}
.psp-sort.on{color:var(--ink)}
.psp-sort i{font-style:normal;font-size:10px;color:var(--ink3)}
.psp-sort.on i{color:var(--ink)}
.psp-sort:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
/* The four states of the register, each carrying its own count. A filter that does not say how
   many it will leave you with is a filter you have to click to find out about. */
.psp-facets{display:flex;flex-wrap:wrap;gap:6px;margin:14px 0 0}
.psp-facet{border-radius:0;font:500 11.5px/1 var(--sans);gap:7px}
.psp-facet em{font-style:normal;font-weight:400;color:var(--ink3);
  font-variant-numeric:tabular-nums}
.psp-facet.btn-active em{color:var(--bg)}
/* The stage name, when the stage is also the way into its brief. It is a link inside a
   disclosure, so it carries no underline and no colour of its own: what marks it is that the
   pointer changes and that it lights when you are on it, the same as every other destination. */
.nv-gh{display:block;text-decoration:none;color:inherit}
.nv-gh:hover b{text-decoration:underline;text-underline-offset:3px}
.nv-gh.on b{color:var(--live,currentColor)}
.nv-gh:focus-visible{outline:2px solid currentColor;outline-offset:3px}

/* ------------------------------------------------------------------------ charts
   One ink, and the data is the only thing allowed to be loud. Marks carry the ink; every piece
   of text wears a text token, because a mark's colour on a label is unreadable at label size
   and identity belongs to the shape beside the words rather than to the words. */
/* The chart hue is Spotify's green, stepped per ground rather than flipped between them.
   #1DB954 reads at 8.12 to 1 on the black ground and at 2.31 on the paper one, which is under
   the three to one a mark needs, so the light theme takes a deeper step of the same hue and the
   dark theme takes the brand value itself. The ramp is one hue light to dark because every job
   on this page is magnitude: nothing here is categorical, so nothing needs a second hue. */
:root,[data-theme="t42light"]{
  --ch-mark:#0E7A38;                                    /* 4.86 : 1 on #F3F2EF */
  /* Six steps that every one of them stays visible on paper. The first ramp ran out to
     #8AEFB5, which is 1.24 to 1 here: the second largest slice of the catalogue, a quarter of
     it, was drawn in a green a reader cannot see. A ramp is only a ramp as far as its palest
     step is still a mark. */
  --ch-1:#04361A; --ch-2:#075023; --ch-3:#0A6B2E;
  --ch-4:#0E7A38; --ch-5:#128A3E; --ch-6:#159944;
}
[data-theme="t42dark"]{
  --ch-mark:#1DB954;                                    /* 8.12 : 1 on #000000 */
  /* Capped at the other end for the same reason: the deepest step of the first dark ramp was
     2.69 to 1 on black. Each ground gets the half of the hue that is legible on it, which is
     what selecting a dark palette means rather than inverting the light one. */
  --ch-1:#B9F7D3; --ch-2:#8AEFB5; --ch-3:#5BE596;
  --ch-4:#34D67A; --ch-5:#1DB954; --ch-6:#159944;
}
.ch{margin:0;padding:0}
.ch-t{font:600 12.5px/1.4 var(--sans);color:var(--ink);margin:0 0 10px;
  display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.ch-t em{font-style:normal;font-weight:400;font-size:11.5px;color:var(--ink3)}
.ch svg{display:block;width:100%;height:auto;overflow:visible}
.ch-m rect:not(.ch-hit){fill:var(--ch-mark);transition:opacity .12s var(--ease)}
.ch-m:hover rect:not(.ch-hit){opacity:.78}
.ch-m.faint rect:not(.ch-hit){opacity:.42}
.ch-hit{fill:transparent}
/* A hairline, solid, and one step off the surface. Dashing a gridline adds ink that is not
   data and reads as a series of its own. */
.ch-grid{stroke:var(--rule);stroke-width:1}
.ch-base{stroke:var(--rule2);stroke-width:1}
.ch-ax{font:400 10px/1 var(--sans);fill:var(--ink3)}
.ch-ay{text-anchor:end}
.ch-peak{font:600 11px/1 var(--sans);fill:var(--ink)}
.ch-peak.inside{fill:#FFFFFF}
.ch-rl{font:400 11.5px/1 var(--sans);fill:var(--ink2)}
.ch-rv{font:400 11px/1 var(--sans);fill:var(--ink3);font-variant-numeric:tabular-nums}
.ch-say{margin:9px 0 0;font:400 12.5px/1.65 var(--sans);color:var(--ink2);max-width:74ch}
.ch-say b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
/* The dashboard grid. Two across where there is room, one where there is not. */
/* Stacked, not side by side. A 1000-unit viewBox squeezed into a 340px column scales its text
   down with it, and an 11px label renders at four. Full width is the only way the labels on a
   ranked chart are readable without inventing a second type scale for charts alone. */
.ch-stack{display:flex;flex-direction:column;gap:clamp(30px,4vw,52px);
  margin:clamp(24px,3vw,34px) 0 0}
.ch-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:clamp(16px,2.4vw,30px);margin:clamp(22px,2.6vw,30px) 0 0;
  padding-bottom:clamp(22px,2.6vw,30px);border-bottom:1px solid var(--rule)}
/* A prose section under the charts, and its opening paragraph. Both were used by three
   surfaces and defined by none, so a heading sat hard against whatever preceded it and read as
   a continuation of it rather than as the start of something. Found by measuring every class in
   the markup against every rule in the stylesheets, and confirmed by looking at the page: on
   the anatomy surface "Where the catalogue thins" ran straight on from the legend above it. */
.ch-s{margin:clamp(30px,4vw,50px) 0 0}
.ch-s>h2{margin:0 0 10px;font:600 15px/1.35 var(--sans);color:var(--ink);
  letter-spacing:-.01em}
.ch-s>h2 em{font-style:normal;font-weight:400;font-size:12px;color:var(--ink3);
  margin-left:9px}
.ch-p{margin:0;font:400 12.5px/1.7 var(--sans);color:var(--ink2);max-width:82ch}
.ch-p b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
/* The wrapper `tile()` emits. Its three children were styled and it was not, so a tile had no
   box of its own and only held together because the grid above it placed them. */
.ch-tile{display:flex;flex-direction:column;min-width:0}
.ch-tl{margin:0;font:500 10.5px/1.4 var(--sans);letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink3)}
/* No tabular numerals on a figure this size: equal-width digits make 121 look gappy when it is
   set large, and there is nothing beneath it to line up with. */
.ch-tv{display:block;margin:7px 0 0;font:700 clamp(26px,3.6vw,34px)/1 var(--sans);
  letter-spacing:-.035em;color:var(--ink)}
.ch-ts{margin:7px 0 0;font:400 12px/1.55 var(--sans);color:var(--ink3)}
/* The pie. Slices separated by a gap in the surface colour rather than by a stroke, which is
   the same mechanism the bars use: a border around a mark is ink that is not data. */
.ch-pie{display:flex;gap:clamp(20px,3vw,40px);align-items:center;flex-wrap:wrap}
.ch-pie svg{width:clamp(180px,26vw,230px);flex:0 0 auto;height:auto}
.ch-sl{stroke:var(--bg);stroke-width:3;transition:opacity .12s var(--ease)}
.ch-sl:hover{opacity:.78}
.ch-key{list-style:none;margin:0;padding:0;flex:1 1 240px;min-width:220px}
.ch-key li{display:flex;align-items:baseline;gap:9px;padding:4px 0;
  font:400 12.5px/1.5 var(--sans);color:var(--ink2)}
.ch-key i{flex:0 0 auto;width:10px;height:10px;border-radius:0;transform:translateY(1px)}
.ch-key b{margin-left:auto;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.ch-key span{color:var(--ink3);font-variant-numeric:tabular-nums;min-width:46px;text-align:right}

/* The catalogue owner's own mark. The square the rail used to draw is 7px, which is a dot; a
   real mark needs room to be a mark, so the slot grows only when one is actually loaded. */
.rail .mark.has-mark,.s-rail .mark.has-mark{width:26px;height:26px;background:none;
  display:inline-flex;align-items:center;justify-content:center;color:var(--ink)}
.rail .mark.has-mark svg,.s-rail .mark.has-mark svg{width:100%;height:100%;display:block}

/* ------------------------------------------------- the brief, and its panel of figures
   The charts take the width they need and the figures ride beside them, so a reader who wants
   the numbers does not have to read four charts to collect them. It is a summary of the same
   figures the charts plot and never a source of its own: nothing appears here that is not
   drawn beside it, or the two drift and only one of them is checked. */
.bf-cols{display:grid;grid-template-columns:minmax(0,1fr) 300px;
  gap:clamp(26px,3.4vw,52px);align-items:start}
.bf-main{min-width:0}
/* Sticky, because the panel is a reference while the charts are scrolled past. It stops being
   sticky when the column is too short to be worth it. */
.bf-side{position:sticky;top:24px;border-left:1px solid var(--rule);
  padding:2px 0 2px clamp(18px,2vw,26px)}
.bf-sh{margin:0 0 4px;font:500 10.5px/1.4 var(--sans);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink3)}
.bf-dl{margin:0}
.bf-dl > div{padding:13px 0;border-bottom:1px solid var(--rule)}
.bf-dl > div:last-child{border-bottom:0}
.bf-dl dt{font:400 11.5px/1.4 var(--sans);color:var(--ink3)}
.bf-dl dd{margin:3px 0 0}
.bf-dl dd b{font:600 17px/1.2 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums}
.bf-dl dd em{display:block;margin-top:3px;font-style:normal;font:400 11.5px/1.5 var(--sans);
  color:var(--ink3)}
.bf-sf{margin:14px 0 0;font:400 11px/1.55 var(--sans);color:var(--ink3)}
/* Under 1100px the panel goes below the charts rather than squeezing them: a 300px column taken
   out of a narrow page leaves the charts too thin to read, which is the failure this panel was
   supposed to help with. */
@media (max-width:1100px){
  .bf-cols{grid-template-columns:minmax(0,1fr)}
  .bf-side{position:static;border-left:0;border-top:1px solid var(--rule);
    padding:clamp(20px,3vw,26px) 0 0}
  .bf-dl{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));
    gap:0 clamp(20px,3vw,30px)}
}

/* ------------------------------------------------------------- the flow, and the swarm
   Monochrome on purpose. A sankey with named nodes carries identity in its labels and
   magnitude in its widths; a hue would be a third channel saying nothing that is not already
   said twice. */
.fl-l{fill:none;stroke:var(--ch-mark);stroke-opacity:.28;
  transition:stroke-opacity .12s var(--ease)}
.fl-l:hover{stroke-opacity:.62}
.fl-n rect{fill:var(--ch-mark)}
.fl-t{font:400 11px/1 var(--sans);fill:var(--ink2)}
.fl-v{fill:var(--ink3);font-variant-numeric:tabular-nums}
/* Small multiples. One shared scale, so the axis is drawn once on the first panel and the
   others inherit the comparison rather than restating it. */
.pn{display:flex;flex-direction:column;gap:2px;margin-top:6px}
.pn-p{display:flex;flex-direction:column}
.pn-h{margin:6px 0 0;font:500 11.5px/1.3 var(--sans);color:var(--ink);
  display:flex;align-items:baseline;gap:9px}
.pn-h em{font-style:normal;font-weight:400;font-size:11px;color:var(--ink3);
  font-variant-numeric:tabular-nums}
/* What is missing, said in the panel heading rather than left to be inferred from a blank. */
.pn-h i{font-style:normal;font-size:10.5px;color:var(--ink3);
  padding-left:9px;border-left:1px solid var(--rule)}
.pn-p svg{display:block;width:100%;height:auto;overflow:visible}
/* A panel of a different quantity: a gross where the others are a net. Outlined rather than
   faded, because the shared scale puts this payor's tallest year at under seven pixels and a
   fade takes a one pixel bar to nothing. An outline holds its shape at any height. */
.pn-p .ch-m.hollow rect:not(.ch-hit){fill:none;stroke:var(--ch-mark);stroke-width:1}
.pn-p .ch-m.hollow:hover rect:not(.ch-hit){fill:var(--ch-mark);fill-opacity:.24;opacity:1}
/* A year no statement covers, hatched. The contrast is in the line and the lightness in the
   area, because a flat band pale enough to sit under the bars measured 1.12 to 1 against the
   page and a band that cleared three to one outread the bars themselves. The same diagonals a
   release with no cover art wears. */
.pn-gh{stroke:var(--ink3);stroke-width:.7}
/* The zeros get a band of their own, because a log scale cannot place them and dropping them
   would delete the largest group on the chart. */
.sw-zone{fill:var(--bg2);stroke:var(--rule);stroke-width:1}
.sw-zl{font:700 19px/1 var(--sans);fill:var(--ink);letter-spacing:-.02em}
.sw-zs{font:400 10.5px/1 var(--sans);fill:var(--ink3)}
.sw-d{fill:var(--ch-mark);fill-opacity:.72;stroke:var(--bg);stroke-width:1;
  transition:fill-opacity .12s var(--ease)}
.sw-d:hover{fill-opacity:1}

/* ------------------------------------------------------- the column contract
   One table, five column-sets. Identity is marked so a reader who switches lens can see at a
   glance which columns did not move, and the not-held columns are marked so an absence reads
   as a stated absence rather than as an empty cell somebody forgot to fill. */
.c-t{font-weight:500}
.c-nil{color:var(--ink3)}
.c-zero{color:var(--ink3);font-variant-numeric:tabular-nums}
.c-st{color:var(--ink2)}
.c-i{display:block;max-width:190px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--ink2)}
/* Identity: the columns that never leave. A hairline on the right of the last of them, so the
   join between what is always there and what the lens brought is visible without a heading. */
th.c-id,td.c-id{background:color-mix(in oklab,var(--bg2) 55%,transparent)}
th.c-id+th:not(.c-id),td.c-id+td:not(.c-id){border-left:1px solid var(--rule)}
/* Not held. The open circle is the state system's own mark for an absence with no source. */
.c-nh{color:var(--ink3)}
.c-nhl{color:var(--ink3)}
th.c-nhh{color:var(--ink3)}
.c-nhm{opacity:.7}
/* The cell carries the mark and nothing else. A hatch over a whole column read as damage at
   633 rows, and the words repeated per row read as noise; the header and the line above the
   table say it once, in words, with the reason. */
.dg td.c-nhh{text-align:center;background:color-mix(in oklab,var(--bg2) 40%,transparent)}
/* The lens, and what it cannot answer. */
#lens button{white-space:nowrap}
.lens-q{margin:0;padding-left:14px;border-left:1px solid var(--rule);flex:1;min-width:0;
  font:400 11.5px/1.4 var(--sans);color:var(--ink3);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.lens-gap{margin:0;padding:7px 14px;font:400 11.5px/1.5 var(--sans);color:var(--ink2);
  background:var(--bg2);border-bottom:1px solid var(--rule);
  display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.lens-gap b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums}
.lens-x{color:var(--ink3);border-bottom:1px dotted var(--rule2);cursor:help}

/* ------------------------------------------------------------------- the shelf
   Place 6. Outputs grouped by how close each is to being a file, because that is the question
   somebody standing here is actually asking. */
.shelf{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:1px;
  background:var(--rule);border:1px solid var(--rule);margin-top:14px}
.sh-o{background:var(--bg);padding:16px 18px 18px}
.sh-k{margin:0;font:500 10.5px/1 var(--mono,var(--sans));letter-spacing:.06em;color:var(--ink3)}
.sh-n{margin:7px 0 0;font:600 14px/1.35 var(--sans);color:var(--ink)}
.sh-w{margin:6px 0 0;font:400 12.5px/1.6 var(--sans);color:var(--ink2)}
.sh-d{margin:13px 0 0;display:grid;grid-template-columns:auto 1fr;gap:4px 12px;
  font:400 11.5px/1.55 var(--sans)}
.sh-d dt{color:var(--ink3)}
.sh-d dd{margin:0;color:var(--ink2)}
.sh-gap{color:var(--ink3)}
/* A hairline on the left, per state. The state is already the section heading, so this is a
   reminder inside the card and not the way the state is read. */
.sh-on_screen{box-shadow:inset 2px 0 0 var(--ch-mark)}
.sh-partial{box-shadow:inset 2px 0 0 var(--rule2)}
.sh-waiting{box-shadow:inset 2px 0 0 var(--rule)}
.sh-c{margin:14px 0 0;padding-left:20px;font:400 12.5px/1.7 var(--sans);color:var(--ink2);
  max-width:82ch}
.sh-c li{margin:7px 0}

/* ------------------------------------------------------------ the command bar
   One of the two global systems. Over the page rather than beside it, because it is a way to
   somewhere and not a panel to read: it takes the whole of the reader's attention for as long
   as they are typing and then gives all of it back. */
.cb{position:fixed;inset:0;z-index:120;display:none;justify-content:center;
  align-items:flex-start;padding:11vh 20px 20px;
  background:color-mix(in oklab,var(--bg) 62%,transparent);backdrop-filter:blur(3px)}
.cb.on{display:flex}
.cb-box{width:min(660px,100%);background:var(--bg);border:1px solid var(--rule2);
  border-radius:var(--r-panel,6px);box-shadow:0 24px 64px -18px rgba(0,0,0,.45);
  display:flex;flex-direction:column;max-height:74vh;overflow:hidden}
.cb-i{appearance:none;width:100%;border:0;border-bottom:1px solid var(--rule);
  background:transparent;color:var(--ink);padding:15px 18px;
  font:400 15px/1.3 var(--sans)}
.cb-i:focus{outline:none}
.cb-i::placeholder{color:var(--ink3)}
.cb-l{list-style:none;margin:0;padding:6px 0;overflow-y:auto;flex:1}
.cb-r{display:grid;grid-template-columns:74px minmax(0,auto) minmax(0,1fr);
  align-items:baseline;gap:12px;padding:7px 18px;cursor:pointer}
.cb-r.on{background:var(--bg2)}
.cb-r.on .cb-n{color:var(--ch-mark)}
.cb-k{font:500 10px/1.5 var(--sans);letter-spacing:.05em;text-transform:uppercase;
  color:var(--ink3)}
.cb-n{font:500 13px/1.4 var(--sans);color:var(--ink);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.cb-d{font:400 11.5px/1.4 var(--sans);color:var(--ink3);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.cb-none{padding:16px 18px;font:400 12.5px/1.6 var(--sans);color:var(--ink2)}
.cb-f{margin:0;padding:9px 18px;border-top:1px solid var(--rule);background:var(--bg2);
  font:400 11px/1.4 var(--sans);color:var(--ink3)}
@media (prefers-reduced-motion:reduce){.cb{backdrop-filter:none}}

/* A figure that lives at another altitude, pointed at rather than redrawn. The one thing this
   must not look like is a chart. */
.st-elsewhere{margin:0}
.st-elsewhere b a{color:var(--ch-mark)}

/* ------------------------------------------------- Position, block A: the condition strip
   Section 6. The rating, the index and what reached a verdict, each a route to the place that
   owns it and never a second implementation of it. Under them, coverage: every ratio with its
   denominator drawn as one object. */
.lcond{border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);background:var(--bg2)}
.lcond-in{max-width:var(--lw,1180px);margin:0 auto;padding:26px clamp(20px,4vw,54px) 30px}
.lcond-h{margin:0 0 16px;font:500 11px/1 var(--sans);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink3)}
.lcond-t{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
  gap:1px;background:var(--rule);border:1px solid var(--rule)}
.lct{display:block;background:var(--bg);padding:15px 17px 17px;text-decoration:none}
.lct:hover{background:var(--bg2)}
.lct-l{display:block;font:500 11.5px/1.4 var(--sans);color:var(--ink3)}
.lct-v{display:block;margin-top:5px;font:600 30px/1 var(--sans);letter-spacing:-.025em;
  color:var(--ink);font-variant-numeric:tabular-nums}
.lct-v i{font-style:normal;font-size:14px;font-weight:400;color:var(--ink3);margin-left:7px;
  letter-spacing:0}
.lct-d{display:block;margin-top:8px;font:400 11.5px/1.55 var(--sans);color:var(--ink3)}
.lcond-c{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
  gap:18px clamp(20px,3vw,36px);margin-top:22px}
/* The coverage bar. Both halves of the ratio, as one object. */
.cv{display:block;text-decoration:none}
a.cv:hover .cv-l{color:var(--ink)}
.cv-l{margin:0;font:500 11.5px/1.45 var(--sans);color:var(--ink2);
  display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.cv-l em{font-style:normal;font-weight:400;font-size:11px;color:var(--ink3)}
.cv-b{margin-top:7px;height:7px;background:var(--rule);overflow:hidden}
.cv-b i{display:block;height:100%;background:var(--ch-mark)}
.cv-n{margin:6px 0 0;font:400 12px/1.4 var(--sans);color:var(--ink3);
  font-variant-numeric:tabular-nums}
.cv-n b{font-weight:600;color:var(--ink)}
.cv-p{margin-left:7px}
.cv-nh{margin:9px 0 0;font:400 12px/1.5 var(--sans);color:var(--ink3);cursor:help}
.cv-u{display:block;margin-top:3px;font-size:11px}
.cv-off .cv-l{color:var(--ink3)}

/* -------------------------------------------------------- the anatomy of a song
   The three identifiers, then the eight stages as a diagram. The only surface in the
   application that draws a node graph, and it draws a model rather than an instance: the same
   eight stages for every song, with this catalogue's reach measured on each. */
.an-ids{display:grid;grid-template-columns:repeat(auto-fit,minmax(292px,1fr));gap:1px;
  background:var(--rule);border:1px solid var(--rule);margin-top:26px}
.an-i{background:var(--bg);padding:18px 20px 20px;display:flex;flex-direction:column;gap:11px}
.an-ic{margin:0;display:flex;align-items:baseline;gap:9px}
.an-ic code{font:600 15px/1 var(--mono,var(--sans));color:var(--ink);letter-spacing:.01em}
.an-ic span{font:400 11.5px/1 var(--sans);color:var(--ink3)}
.an-iw{margin:0;font:400 12.5px/1.65 var(--sans);color:var(--ink2)}
.an-io{margin:0;padding-top:10px;border-top:1px solid var(--rule);
  font:400 11.5px/1.6 var(--sans);color:var(--ink3)}
/* The frame the diagram is mounted into. A fixed height, because a pannable canvas with an
   auto height collapses to nothing before React Flow measures it. */
.an-flow{height:min(74vh,640px);margin-top:16px;border:1px solid var(--rule);
  background:var(--bg2);position:relative}
.an-fail{margin:0;padding:20px;font:400 12.5px/1.6 var(--sans);color:var(--ink2)}
/* --ink2, not --ink3: the legend is the key to the whole diagram and measured 3.73 to 1 on the
   dark ground, under the floor. It is the one piece of text on the page a reader cannot skip. */
.an-legend{margin:11px 0 0;display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  font:400 11.5px/1.5 var(--sans);color:var(--ink2)}
.an-legend em{font-style:normal;flex:1;min-width:220px}
.an-key{width:10px;height:10px;flex:none;border:1px solid var(--rule2);margin-left:8px}
.an-key:first-child{margin-left:0}
/* Three keys and three distinguishable treatments, which is as many as one ramp can carry:
   the mark, the ground, and the hatch an absence wears everywhere else here. */
.an-kmint{background:var(--ch-mark);border-color:var(--ch-mark)}
.an-kuse{background:var(--bg);border-color:var(--rule2)}
.an-kdark{background:repeating-linear-gradient(135deg,var(--bg) 0 3px,
  color-mix(in oklab,var(--rule) 60%,var(--bg)) 3px 4px)}
/* A stage. React Flow positions the box; everything inside it is this application's. */
.an-n{width:268px;background:var(--bg);border:1px solid var(--rule2);
  border-top:3px solid var(--rule2);padding:12px 14px 14px;
  font:400 12px/1.5 var(--sans);color:var(--ink2)}
/* A stage that mints an identifier carries the mark; one that consumes carries a rule. Binary,
   because that is what one hue can say without a legend a reader has to keep rechecking. */
.an-n.an-mint{border-top-color:var(--ch-mark)}
.an-n.an-use{border-top-color:var(--rule2)}
/* A stage nothing answers. Hatched, the same sign an absence wears everywhere else here. */
.an-n.an-dark{background:repeating-linear-gradient(135deg,var(--bg) 0 5px,
  color-mix(in oklab,var(--rule) 46%,var(--bg)) 5px 6px)}
.an-k{margin:0;font:500 10px/1.4 var(--sans);letter-spacing:.07em;text-transform:uppercase;
  color:var(--ink3)}
.an-q{margin:6px 0 0;font:500 12.5px/1.45 var(--sans);color:var(--ink)}
.an-id{margin:9px 0 0;font:400 11.5px/1.4 var(--sans);color:var(--ink3)}
.an-id code{font:600 11.5px/1 var(--mono,var(--sans));color:var(--ink2)}
.an-mints{color:var(--ink2);font-weight:500}
.an-id.an-uses code{font-weight:400;color:var(--ink3)}
.an-cov{margin-top:11px}
.an-bar{height:6px;background:var(--rule);overflow:hidden}
.an-bar i{display:block;height:100%;background:var(--ch-mark)}
.an-num{margin:5px 0 0;font:400 11.5px/1.3 var(--sans);color:var(--ink3);
  font-variant-numeric:tabular-nums}
.an-num b{font-weight:600;color:var(--ink)}
.an-pct{margin-left:7px}
.an-none{margin:10px 0 0;font:400 11px/1.5 var(--sans);color:var(--ink3)}
.an-h{width:7px;height:7px;background:var(--rule2);border:0}
/* The ladder under the diagram: the same eight, read down as numbers. */
.an-ladder{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  gap:20px clamp(20px,3vw,34px);margin-top:16px}
.an-ll{margin:0 0 7px;font:500 10px/1.4 var(--sans);letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink3)}
/* React Flow's own furniture, brought onto this application's two grounds. The library ships a
   light-only stylesheet, so the dark ground needs saying rather than inheriting. */
.react-flow__edge-path{stroke:var(--rule2);stroke-width:1.4}
.react-flow__arrowhead polyline,.react-flow__arrowhead path{stroke:var(--rule2);
  fill:var(--rule2)}
.react-flow__edge-text{font:400 10.5px/1 var(--sans);fill:var(--ink3)}
.react-flow__edge-textbg{fill:var(--bg2)}
.react-flow__controls{box-shadow:none;border:1px solid var(--rule)}
.react-flow__controls-button{background:var(--bg);border-bottom:1px solid var(--rule);
  fill:var(--ink2)}
.react-flow__controls-button:hover{background:var(--bg2)}
.react-flow__attribution{background:transparent;font:400 10px/1 var(--sans)}
.react-flow__attribution a{color:var(--ink3)}
.react-flow__background pattern circle{fill:var(--rule)}

/* ------------------------------------------- the spine: panel 1 of one recording
   Two chains, because a song earns on two sides and they break independently. A chain and not
   a graph: at this altitude the reader is asking where theirs stops, and a break in a line
   answers that in a second. */
.sh-s>h2 em{font-style:normal;font-weight:400;font-size:12px;color:var(--ink3);
  margin-left:9px}
.sp-two{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
  gap:1px;background:var(--rule);border:1px solid var(--rule);margin-top:16px}
.sp-c{background:var(--bg);padding:16px 18px 18px}
.sp-h{margin:0 0 4px;font:600 12px/1.4 var(--sans);color:var(--ink)}
.sp-h em{display:block;font-style:normal;font-weight:400;font-size:11px;color:var(--ink3);
  margin-top:2px}
.sp-ch{list-style:none;margin:14px 0 0;padding:0}
/* The rule down the left is the chain. It stops where the links stop, which is the point. */
.sp-l{position:relative;padding:0 0 15px 20px;border-left:1px solid var(--rule);
  margin-left:5px}
.sp-l:last-child{border-left-color:transparent;padding-bottom:0}
.sp-m{position:absolute;left:-7px;top:-1px;width:13px;height:18px;line-height:18px;
  text-align:center;font-size:13px;background:var(--bg);color:var(--rule2)}
.sp-held>.sp-n>.sp-m{color:var(--ch-mark)}
.sp-early>.sp-n>.sp-m{color:var(--ch-mark)}
.sp-none>.sp-n>.sp-m{color:var(--ink3)}
.sp-unheld>.sp-n>.sp-m{color:var(--ink3)}
.sp-n{margin:0;font:500 12px/1.35 var(--sans);color:var(--ink2)}
.sp-v{margin:3px 0 0;font:400 12.5px/1.4 var(--sans);color:var(--ink3)}
.sp-v b{font-weight:600;color:var(--ink)}
.sp-w{margin:4px 0 0;font:400 11.5px/1.55 var(--sans);color:var(--ink3);max-width:52ch}
/* A link with claims behind it is operable, and says so on hover rather than by decoration. */
.sp-l[data-f]{cursor:pointer}
.sp-l[data-f]:hover .sp-n,.sp-l[data-f]:focus-visible .sp-n{color:var(--ch-mark)}
.sp-l[data-f]:focus-visible{outline:2px solid var(--ch-mark);outline-offset:2px}
/* A later link held with an earlier one missing. Registered somewhere, nobody nameable: a real
   state on this catalogue and one worth not smoothing into a ladder. */
.sp-early{background:repeating-linear-gradient(135deg,transparent 0 6px,
  color-mix(in oklab,var(--rule) 34%,transparent) 6px 7px)}
.sp-say{margin:12px 0 0;font:400 11.5px/1.65 var(--sans);color:var(--ink3);max-width:96ch}

/* ------------------------------------------- the domain map for one song
   The work at the centre and everything attached to it, in regions rather than as a network:
   the topology is a star, so an arrow would only restate the layout. Colour says one thing and
   one thing only, which is whether this deployment holds the region at all. */
.dm{display:grid;grid-template-columns:repeat(auto-fit,minmax(268px,1fr));gap:1px;
  background:var(--rule);border:1px solid var(--rule);margin-top:16px}
.dm-g{background:var(--bg);padding:14px 16px 16px;border-top:3px solid var(--rule2)}
/* Held, held in part, and no source at all. The third is why the map exists, so it is the one
   that gets the hatch an absence wears everywhere else in this application. */
.dm-g.dm-held{border-top-color:var(--ch-mark)}
.dm-g.dm-part{border-top-color:var(--rule2)}
.dm-g.dm-none{border-top-color:var(--rule);
  background:repeating-linear-gradient(135deg,var(--bg) 0 6px,
    color-mix(in oklab,var(--rule) 40%,var(--bg)) 6px 7px)}
.dm-h{margin:0 0 10px;font:600 12px/1.35 var(--sans);color:var(--ink);
  display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.dm-h span{font-weight:400;font-size:11px;color:var(--ink3);text-align:right;flex:none}
.dm-l{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
/* A party, a recording, a right. One line per thing, with its number beside its name, because
   a name without a number is the finding on most of these. */
.dm-p{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;
  font:400 11.5px/1.45 var(--sans);color:var(--ink2);
  padding-left:9px;border-left:2px solid var(--rule)}
.dm-p.dm-held{border-left-color:var(--ch-mark)}
.dm-p.dm-part{border-left-color:var(--rule2)}
.dm-p.dm-none{border-left-color:var(--rule)}
.dm-p b{font-weight:500;color:var(--ink);flex:0 1 auto;min-width:0;overflow-wrap:anywhere}
.dm-p code{font:400 11px/1.3 var(--mono,var(--sans));color:var(--ink2)}
.dm-p em{font-style:normal;font-weight:600;color:var(--ink);
  font-variant-numeric:tabular-nums}
.dm-p em.dm-bad{color:var(--leak,var(--ink))}
.dm-r{display:block;flex:1 0 100%;font-size:10.5px;color:var(--ink3)}
.dm-no{color:var(--ink3)}
.dm-sev{color:var(--ink3)}
.dm-none>.dm-no{color:var(--ink3)}
.dm-w{margin:11px 0 0;padding-top:9px;border-top:1px solid var(--rule);
  font:400 11px/1.6 var(--sans);color:var(--ink3)}
.dm-none-msg,.dm-g .dm-none:not(.dm-p){margin:0;font:400 11.5px/1.5 var(--sans);
  color:var(--ink3)}

/* ── One song, as a graph ─────────────────────────────────────────────────────────────────
   The instance diagram on /recording, above the domain map. Same three states as the map it
   sits over, drawn the same way: the mark for held, the rule for part, the lighter rule for an
   absence. Nothing categorical, because one ramp cannot carry a category a reader has to keep
   rechecking against a legend. */
.sn-f{height:min(80vh,700px);margin:14px 0 0;border:1px solid var(--rule);
  background:var(--bg2);position:relative}
.sn-f-out{height:auto}
.sn-cap{margin:9px 0 18px;font:400 11.5px/1.6 var(--sans);color:var(--ink2)}
.sn{width:210px;background:var(--bg);border:1px solid var(--rule2);
  border-left:3px solid var(--rule2);padding:9px 11px 10px;
  font:400 11.5px/1.45 var(--sans);color:var(--ink2)}
.sn-held{border-left-color:var(--ch-mark)}
.sn-part{border-left-color:var(--rule2)}
.sn-none{border-left-color:var(--rule);
  background:repeating-linear-gradient(135deg,var(--bg) 0 5px,
    color-mix(in oklab,var(--rule) 45%,var(--bg)) 5px 6px)}
/* The two hubs are the recording and the work, the only nodes anything else hangs off. Wider
   and heavier, because a reader looking for where to start should not have to count edges. */
.sn-hub{width:236px;border-width:1px 1px 1px 4px}
.sn-t{margin:0;font:600 12px/1.35 var(--sans);color:var(--ink);
  display:flex;align-items:baseline;gap:6px}
.sn-m{font-size:9px;line-height:1;color:var(--ch-mark);flex:none}
.sn-none .sn-m,.sn-part .sn-m{color:var(--ink3)}
.sn-v{margin:5px 0 0;color:var(--ink)}
.sn-c{display:block;margin:4px 0 0;font:400 11px/1.4 var(--mono);color:var(--ink2);
  letter-spacing:.02em}
.sn-s{margin:4px 0 0;color:var(--ink3)}
.sn-n{margin:6px 0 0;padding-top:6px;border-top:1px solid var(--rule);
  font:400 11px/1.5 var(--sans);color:var(--ink2)}
.sn-h{width:6px;height:6px;background:var(--rule2);border:none}
/* A join that can be made, and one that cannot. The dash is the whole point of drawing edges
   here rather than a star: it says the route is cut, and at which link. */
.sn-e .react-flow__edge-path{stroke:var(--rule2);stroke-width:1.2}
.sn-e-cut .react-flow__edge-path{stroke:var(--rule)}
.sn-e .react-flow__edge-text{font:400 10px/1.3 var(--sans);fill:var(--ink3)}
.sn-e .react-flow__edge-textbg{fill:var(--bg2)}
/* An identifier line inside a node: the standard's name, then the code spaced the way that
   standard writes it. The name is the smaller of the two, because a reader who knows what an
   ISRC is needs the digits and a reader who does not needs to be told once. */
.sn-id{margin:5px 0 0;display:flex;align-items:baseline;gap:6px}
.sn-ik{font:600 9.5px/1 var(--sans);letter-spacing:.09em;color:var(--ink3);flex:none}
.sn-id code{font:400 11.5px/1.4 var(--mono);color:var(--ink);letter-spacing:.01em}
.sn-inone{font:italic 400 11px/1.4 var(--sans);color:var(--ink3)}
/* The note that says money cannot move. It is the only thing on the diagram that is allowed to
   pull rank on the ramp, and it does it with weight rather than a hue the palette cannot carry. */
.sn-alarm{color:var(--ink);font-weight:500}

/* ── the walk. Thirai's shape: a trail, a subject, a world ──────────────────────────────
   Three regions and no canvas. The trail hides itself when the walk has not started, which is
   the one piece of state this layout needs and the reason `:has(:empty)` is worth the rule. The
   subject is a fixed column because a panel that resizes as you walk makes every step feel like
   a different page; the world scrolls because it is the only part that changes length. */
.wk{display:flex;flex-direction:column;height:calc(100vh - var(--mast,64px));margin:0 -24px -24px}
.wk-bar{flex-shrink:0;display:flex;align-items:center;gap:14px;padding:10px 24px;
  border-bottom:1px solid var(--rule);min-height:52px}
.wk-trail{flex:1;display:flex;align-items:center;gap:7px;overflow-x:auto;min-width:0;
  scrollbar-width:none}
.wk-trail::-webkit-scrollbar{display:none}
.wk-bar:has(.wk-trail:empty) .wk-trail{display:none}
.wk-step{flex-shrink:0;background:none;border:0;cursor:pointer;padding:4px 8px;
  font:400 12.5px/1.3 var(--sans);color:var(--ink2);text-align:left;
  max-width:210px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wk-step span{display:block;font:500 9.5px/1.2 var(--mono,var(--sans));letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink3)}
.wk-step:hover{color:var(--ink);background:var(--raise,transparent)}
.wk-sep{color:var(--ink3);font-style:normal}
.wk-q{flex-shrink:0;width:min(320px,38vw);padding:7px 11px;border:1px solid var(--rule);
  background:var(--bg);color:var(--ink);font:400 13px/1.3 var(--sans)}
.wk-q:focus{outline:2px solid var(--ink);outline-offset:-1px}

.wk-body{flex:1;display:flex;min-height:0}
.wk-subject{width:312px;flex-shrink:0;border-right:1px solid var(--rule);
  padding:24px 22px;overflow-y:auto}
.wk-world{flex:1;overflow-y:auto;padding:24px 26px 64px}

.wk-eyebrow{margin:0;font:500 10.5px/1 var(--mono,var(--sans));letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink3)}
.wk-h1{margin:10px 0 0;font:600 22px/1.22 var(--sans);letter-spacing:-.018em;color:var(--ink)}
.wk-sub2{margin:6px 0 0;font:400 13.5px/1.5 var(--sans);color:var(--ink2)}
.wk-lede{margin:14px 0 0;font:400 13px/1.6 var(--sans);color:var(--ink2)}
.wk-run{margin:16px 0 0;font:400 11px/1 var(--mono,var(--sans));color:var(--ink3)}
.wk-facts{margin:20px 0 0;display:grid;gap:0}
.wk-facts div{padding:11px 0;border-top:1px solid var(--hair,var(--rule))}
.wk-facts dt{font:500 10.5px/1.2 var(--mono,var(--sans));letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink3)}
.wk-facts dd{margin:5px 0 0;font:400 13.5px/1.45 var(--sans);color:var(--ink)}
.wk-restart{margin:22px 0 0;background:none;border:1px solid var(--rule);cursor:pointer;
  padding:7px 12px;font:500 12px/1 var(--sans);color:var(--ink2)}
.wk-restart:hover{border-color:var(--ink);color:var(--ink)}

.wk-group{margin:0 0 34px}
.wk-group h2{margin:0 0 12px;font:600 14px/1.3 var(--sans);letter-spacing:-.008em;color:var(--ink)}
.wk-group h2 em{display:block;margin-top:4px;font:400 12px/1.5 var(--sans);color:var(--ink3);
  max-width:74ch}
.wk-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:1px;
  background:var(--rule);border:1px solid var(--rule)}
.wk-card{background:var(--bg);border:0;cursor:pointer;text-align:left;padding:13px 15px;
  display:flex;flex-direction:column;gap:4px;min-height:76px}
.wk-card:hover:not([disabled]){background:var(--raise,var(--bg))}
.wk-card[disabled]{cursor:default}
.wk-card b{font:600 13.5px/1.35 var(--sans);color:var(--ink)}
.wk-sub{font:400 11.5px/1.35 var(--mono,var(--sans));color:var(--ink2)}
.wk-note{font:400 11.5px/1.35 var(--sans);color:var(--ink3)}
.wk-said td,.wk-said th{vertical-align:top}
.wk-dis td{background:var(--amber-wash,transparent)}
.wk-flag{display:block;margin-top:3px;font:500 10px/1.2 var(--mono,var(--sans));
  letter-spacing:.08em;text-transform:uppercase;color:var(--caution,var(--ink3))}
.wk-empty{padding:60px 0;color:var(--ink3)}
.wk-empty h1{font:600 18px/1.3 var(--sans);color:var(--ink2);margin:0 0 8px}
@media (max-width:820px){
  .wk-body{flex-direction:column}
  .wk-subject{width:auto;border-right:0;border-bottom:1px solid var(--rule)}
}

/* ── the walk, with pictures ────────────────────────────────────────────────────────────
   A cover is square because a record is; a face is round because Thirai's are and because a
   circle crops a portrait better than a square does. A thing with no picture gets a mark rather
   than a gap: a gap reads as something still loading, and a mark reads as a fact about what is
   held, which is what it is. A Work never gets one at all, because borrowing a cover from one of
   its recordings would assert that the composition and the fixation are the same thing. */
.wk-pic{flex:none;display:block;position:relative;overflow:hidden;background:var(--raise,var(--rule))}
.wk-pic img,.wk-pic .cov{display:block;width:100%;height:100%;object-fit:cover}
.wk-face{border-radius:50%}
.wk-face img{border-radius:50%}
.wk-face i,.wk-work i,.wk-src i{position:absolute;inset:0;display:flex;align-items:center;
  justify-content:center;font:600 42%/1 var(--sans);color:var(--ink3);font-style:normal;
  letter-spacing:-.02em}
.wk-work{border:1px dashed var(--rule);background:none}
.wk-src{border:1px solid var(--rule);background:none}
.wk-none{border:1px solid var(--hair,var(--rule));background:var(--raise,transparent)}

.wk-hero{margin:0 0 18px}
.wk-hero .wk-pic{width:100%!important;height:auto!important;aspect-ratio:1}
.wk-hero .wk-pic img,.wk-hero .wk-pic .cov{width:100%!important;height:100%!important}
.wk-hero-party .wk-pic{width:196px!important;margin:0 auto;border-radius:50%}
.wk-hero-work .wk-pic,.wk-hero-source .wk-pic{aspect-ratio:1;width:120px!important;margin:0}

/* A card is a picture and a column of text beside it, so a list of forty reads down the names
   rather than across the tiles. */
.wk-card{flex-direction:row;align-items:center;gap:12px}
.wk-txt{display:flex;flex-direction:column;gap:3px;min-width:0}
.wk-txt b,.wk-sub,.wk-note{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* The shelf: covers at the size a person browses at, text under and never over. */
.wk-shelf{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:22px 18px}
.wk-tile{background:none;border:0;cursor:pointer;text-align:left;padding:0;
  display:flex;flex-direction:column;gap:8px}
.wk-tile .wk-pic{width:100%!important;height:auto!important;aspect-ratio:1}
.wk-tile b{font:600 13px/1.35 var(--sans);color:var(--ink)}
.wk-tile span{font:400 11.5px/1.35 var(--sans);color:var(--ink3)}
.wk-tile:hover b{text-decoration:underline;text-underline-offset:2px}
.wk-cred{margin:14px 0 0;font:400 10.5px/1.5 var(--sans);color:var(--ink3)}
/* A folder in the data room. The customer's own directory tree, which is how the person who
   sent the documents thinks about them, rather than a storage prefix. */
.fold{font-family:var(--sans);font-size:12px;font-weight:600;letter-spacing:.05em;
  text-transform:uppercase;color:var(--ink2);margin:18px 0 4px;
  display:flex;gap:10px;align-items:baseline}
.fold:first-child{margin-top:0}
.fold span{font-weight:400;letter-spacing:0;text-transform:none}
/* A folder that opens. `details` rather than a click handler: it is keyboard reachable, it is
   announced, and it survives with scripting broken. Two folders hold 138 of this room's 183
   files, so the large ones start closed and a folder small enough to read at a glance does not
   make the reader ask for it. */
.fold-d{border-top:1px solid var(--rule2)}
.fold-d:first-of-type{border-top:0}
.fold-d > summary.fold{cursor:pointer;list-style:none;padding:11px 0;margin:0}
.fold-d > summary.fold::-webkit-details-marker{display:none}
.fold-d > summary.fold::before{content:"›";display:inline-block;width:12px;
  transition:transform .12s ease;color:var(--ink3)}
.fold-d[open] > summary.fold::before{transform:rotate(90deg)}
.fold-d > summary.fold:focus-visible{outline:2px solid var(--live);outline-offset:2px}
@media (prefers-reduced-motion:reduce){.fold-d > summary.fold::before{transition:none}}

/* ── the data room, as a drive ──────────────────────────────────────────────────────────
 * Search, filter chips and a grid of cards, which is the interaction model of every file
 * manager a customer already uses. What it does not borrow is the thumbnail: a preview of a
 * content-addressed object means downloading and rendering 183 documents, so the card carries
 * the format instead and says so plainly rather than showing a grey rectangle pretending to be
 * a page.
 *
 * Colour is not decorative here and is not per format. Drive tints by type because that is all
 * it knows; this room knows something more useful, which is whether a file is in a format the
 * intake can accept. Thirty-four of the held documents are not, and those are the ones tinted.
 */
.rm-bar{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:0 0 16px}
.rm-search{flex:1 1 260px;min-width:200px}
.rm-chips{display:flex;gap:8px;flex-wrap:wrap}
.rm-chip{font-size:12.5px;padding:6px 12px;border-radius:999px;border:1px solid var(--rule2);
  background:var(--bg2);color:var(--ink2);cursor:pointer;white-space:nowrap}
.rm-chip[aria-pressed="true"]{background:var(--ink,#14201F);color:var(--bg,#fff);
  border-color:var(--ink,#14201F)}
.rm-chip:focus-visible{outline:2px solid var(--live);outline-offset:2px}
.rm-view{margin-left:auto;display:flex;gap:4px}

.rm-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(196px,1fr));gap:14px;
  margin:6px 0 0;padding:0;list-style:none}
.rm-card{border:1px solid var(--rule2);border-radius:10px;overflow:hidden;background:var(--bg2);
  display:flex;flex-direction:column}
.rm-card:hover{border-color:var(--rule2)}
.rm-tile{height:104px;display:flex;align-items:center;justify-content:center;
  background:var(--bg2);border-bottom:1px solid var(--rule2)}
.rm-tile b{font-family:var(--mono);font-size:22px;letter-spacing:.06em;
  color:var(--ink2)}
.rm-card.unreadable .rm-tile{background:#FDF1EA}
.rm-card.unreadable .rm-tile b{color:#A63C15}
.rm-meta{padding:11px 12px 12px}
.rm-name{font-size:13.5px;font-weight:600;line-height:1.3;color:var(--ink);
  overflow-wrap:anywhere;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden}
.rm-sub{font-size:11.5px;color:var(--ink2);margin-top:5px;line-height:1.4;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Size on its own line, actions on theirs. Three buttons and a size on one row wrapped at card
   width: the size broke across two lines, the buttons took two rows, and no two cards ended at
   the same height. The meta area grows so every footer sits on the same baseline. */
.rm-meta{display:flex;flex-direction:column;flex:1}
.rm-foot{margin-top:auto;padding-top:9px}
.rm-foot .rm-sz{display:block;font-family:var(--mono);font-size:11.5px;
  color:var(--ink2);margin-bottom:7px}
.rm-none{padding:26px 0;color:var(--ink2);font-size:14px}
.rm-count{font-size:12.5px;color:var(--ink2);margin:0 0 10px}
/* The rendered first page. Cropped to the top of the tile rather than centred: a contract's
   identifying line is its title and its parties, and both are at the top of page one. */
.rm-thumb{width:100%;height:100%;object-fit:cover;object-position:top center;display:block}
/* The actions on a file. Small, quiet, and the same set wherever the file appears, so a reader
   who learns them in the grid does not relearn them in the list. */
.rm-acts{display:inline-flex;gap:5px;flex-wrap:wrap;align-items:center}
.rm-card .rm-acts{display:flex;gap:5px}
.rm-card .rm-acts .btn{flex:1;padding-inline:6px;font-size:11px}
.rm-acts .btn{white-space:nowrap}
/* A file the room holds and this process could not open. Not the same thing as a format the
   intake will not accept, which is `.unreadable` above: that one is a decision, this one is a
   deployment that cannot read a customer's own document, and it is the room's job to say so
   rather than to leave the file looking like every other. */
.rm-noread{color:var(--leak-ink,#A63C15);font-weight:500}

/* ── the room as the customer's own tree ────────────────────────────────────────────────
 * A data room is not a pile of files, and the first version of this drew one: 183 cards, most
 * carrying the same logo, with the folder truncated under each. The tree is the categorisation,
 * and it is the customer's rather than one this application invented. Everything here is built
 * to be scanned down the left edge and read across only when a heading is worth opening.
 *
 * `details` again, for the same reasons the earlier folder list used it: keyboard reachable,
 * announced, and it survives with scripting broken.
 */
.rm-dir{border-top:1px solid var(--rule2)}
.rm-dir:first-child{border-top:0}
.rm-dir > summary{display:flex;align-items:center;gap:10px;padding:9px 8px 9px 4px;
  cursor:pointer;list-style:none;border-radius:6px}
.rm-dir > summary::-webkit-details-marker{display:none}
.rm-dir > summary:hover{background:var(--bg2)}
.rm-dir > summary:focus-visible{outline:2px solid var(--live);outline-offset:-2px}
/* The disclosure arrow, drawn rather than typed, so it lines up with the icon under it. */
.rm-dir > summary::before{content:"";width:0;height:0;flex:none;margin-right:-2px;
  border-left:5px solid var(--ink3);border-top:4px solid transparent;
  border-bottom:4px solid transparent;transition:transform .12s ease}
.rm-dir[open] > summary::before{transform:rotate(90deg)}
@media (prefers-reduced-motion:reduce){.rm-dir > summary::before{transition:none}}

/* A folder the customer made and an archive the customer zipped are both folders and are not
   the same thing, so they do not look the same. Drawn in CSS: two shapes, no image to load. */
.rm-dir-i{flex:none;width:14px;height:11px;border:1.25px solid var(--ink3);
  border-radius:2px;position:relative}
.rm-dir-i.is-dir{border-top-left-radius:0}
.rm-dir-i.is-dir::before{content:"";position:absolute;top:-4px;left:-1.25px;width:6px;height:3px;
  border:1.25px solid var(--ink3);border-bottom:0;border-top-left-radius:2px;
  border-top-right-radius:2px}
.rm-dir-i.is-arc::after{content:"";position:absolute;top:-1.25px;bottom:-1.25px;left:50%;
  width:1.25px;margin-left:-.6px;background:var(--ink3)}

.rm-dir-n{font-size:13.5px;font-weight:600;color:var(--ink);overflow-wrap:anywhere}
.rm-dir-c{margin-left:auto;font:400 11.5px/1 var(--mono);
  color:var(--ink2);white-space:nowrap}
.rm-dir-b{font:400 11.5px/1 var(--mono);color:var(--ink3);
  white-space:nowrap;min-width:62px;text-align:right}
/* What is under a heading, without opening it. */
.rm-tag{font-size:10.5px;letter-spacing:.03em;text-transform:uppercase;color:var(--ink2);
  border:1px solid var(--rule2);border-radius:999px;padding:1px 7px;white-space:nowrap}

/* The rail down the left is the depth. One line, not an indent that leaves the eye guessing
   which heading a row belongs to five rows later. */
.rm-dir-body{margin-left:11px;padding-left:11px;border-left:1px solid var(--rule2)}

.rm-files{list-style:none;margin:0;padding:0}
.rm-f{display:flex;align-items:center;gap:10px;padding:5px 8px 5px 4px;border-radius:6px;
  font-size:13px}
.rm-f + .rm-f{border-top:1px solid var(--rule)}
.rm-f:hover{background:var(--bg2)}
.rm-f-ext{flex:none;width:42px;font:500 9.5px/1 var(--mono);
  letter-spacing:.06em;color:var(--ink3);text-align:right}
.rm-f-name{flex:1 1 auto;min-width:0;color:var(--ink2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rm-f-kind,.rm-f-when{flex:none;font-size:11.5px;color:var(--ink3);white-space:nowrap}
.rm-f-kind{min-width:82px}
.rm-f-when{min-width:78px;text-align:right}
.rm-f-sz{flex:none;min-width:62px;text-align:right;
  font:400 11.5px/1 var(--mono);color:var(--ink2)}
/* Quiet until wanted. Three buttons on every one of 183 rows is the wall again in a thinner
   shape, and a keyboard reaches them because focus-within opens the same door hover does. */
.rm-f-acts{flex:none;display:flex;gap:4px;opacity:0;transition:opacity .1s ease}
.rm-f:hover .rm-f-acts,.rm-f:focus-within .rm-f-acts{opacity:1}
@media (hover:none){.rm-f-acts{opacity:1}}
@media (prefers-reduced-motion:reduce){.rm-f-acts{transition:none}}
.rm-f-bad .rm-f-name{color:var(--leak)}

@media (max-width:860px){
  .rm-f-kind,.rm-f-when{display:none}
  .rm-dir-b{display:none}
}
/* Narrow. The row is a ledger and a ledger needs width, so below this it stops being one: the
   name takes the line, everything that qualifies it takes the next. Measured rather than
   guessed, because at 375 the three actions alone are 119px and the row ran 207px past the
   viewport, which is a horizontal scrollbar on a page that should never have one. The rails
   also thin, since six levels of 22px indent is most of a phone. */
@media (max-width:640px){
  .rm-dir-body{margin-left:6px;padding-left:8px}
  .rm-dir > summary{flex-wrap:wrap;row-gap:2px}
  .rm-dir-c{margin-left:0}
  .rm-dir-n{flex:1 1 100%}
  .rm-f{flex-wrap:wrap;row-gap:2px;padding-bottom:8px}
  .rm-f-name{flex:1 1 auto}
  .rm-f-sz{margin-left:auto}
  .rm-f-acts{flex:1 1 100%;opacity:1;justify-content:flex-start;padding-left:52px}
}
/* The archive as the customer sent it, sitting at the top of the folder its own contents made. */
.rm-f-arc{background:var(--bg2)}
.rm-f-arc .rm-f-name{font-weight:600;color:var(--ink)}
/* Files in no folder. A heading rather than an invented folder, because they were not in one. */
.rm-loose{margin:18px 0 2px;padding:0 4px;font:500 11px/1.4 var(--sans);
  letter-spacing:.05em;text-transform:uppercase;color:var(--ink3)}

/* ── The pipeline diagram ───────────────────────────────────────────────────────────────────
   Five columns, one per role. Three states and they mean different things: held is measured,
   empty is reachable and has nothing in it, gone is a store this deployment cannot see. The
   third is drawn dashed and greyed because a zero and an absence are not the same claim. */
.pipe-flow{height:min(76vh,660px);margin-top:16px;border:1px solid var(--rule);
  border-radius:4px;background:var(--bg2)}
.pipe-flow.pipe-flow-out{height:auto}
.pipe-n{width:216px;min-height:104px;box-sizing:border-box;padding:11px 13px;
  border:1px solid var(--rule2);border-left-width:3px;border-radius:3px;background:var(--bg);
  display:flex;flex-direction:column;gap:0}
.pipe-held{border-left-color:var(--ch-mark)}
.pipe-empty{border-left-color:var(--rule2)}
.pipe-gone{border-left-color:var(--rule);border-style:dashed;border-left-style:solid;
  background:var(--bg2)}
.pipe-gone .pipe-t,.pipe-gone .pipe-l b{color:var(--ink3)}
.pipe-t{margin:0;font:600 12.5px/1.35 var(--sans);letter-spacing:-.01em;color:var(--ink);
  display:flex;align-items:baseline;gap:6px}
.pipe-m{font-size:9px;line-height:1;color:var(--ch-mark);flex:none}
.pipe-empty .pipe-m,.pipe-gone .pipe-m{color:var(--ink3)}
/* The product, not the role. A reader who cannot name the store cannot act on the diagram. */
.pipe-store{margin:3px 0 6px;font:400 10px/1.3 var(--mono,var(--sans));color:var(--ink3);
  letter-spacing:.02em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pipe-l{margin:2px 0 0;display:flex;justify-content:space-between;gap:10px;
  font:400 11px/1.4 var(--sans);color:var(--ink2)}
.pipe-l b{font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums;flex:none}
.pipe-note{margin:7px 0 0;padding-top:6px;border-top:1px solid var(--rule);
  font:400 10.5px/1.4 var(--sans);color:var(--ink3)}
.pipe-alarm{color:var(--caution,var(--ink2))}
.pipe-h{width:6px;height:6px;background:var(--rule2);border:0}
/* The column heading is a node so it pans and zooms with what it labels. */
.pipe-role{width:216px;font:600 10.5px/1.3 var(--sans);letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink2)}
.pipe-role span{display:block;margin-top:3px;font:400 10.5px/1.4 var(--sans);
  letter-spacing:0;text-transform:none;color:var(--ink3)}
.pipe-flow .pipe-e .react-flow__edge-path{stroke:var(--rule2);stroke-width:1.2}
.pipe-flow .react-flow__edge-text{font:400 10px/1.3 var(--sans);fill:var(--ink3)}
.pipe-flow .react-flow__edge-textbg{fill:var(--bg2)}
/* The second door. Drawn across the diagram rather than tucked into a column, because the
   point of it is that it skips two of them. */
.pipe-flow .pipe-e-door .react-flow__edge-path{stroke:var(--ink3);stroke-width:1.4}
.pipe-flow .pipe-e-bad .react-flow__edge-path{stroke:var(--caution,var(--ink2));stroke-width:1.6}
.pipe-flow .pipe-e-bad .react-flow__edge-text{fill:var(--caution,var(--ink2));font-weight:600}
