﻿/* =====================================================================
   THE ROCKSTAR GAME - "Backstage" design system
   Handoff stylesheet. Everything is driven by the :root tokens below;
   port these custom properties into site.css in the Razor project and
   the component classes map 1:1 to partials / tag helpers.
   Dark-only. No external CSS deps. Fonts: Google Fonts (see <head>).
   ===================================================================== */

:root {
  /* surfaces (warm near-black) */
  /* D123 "The Galley" - --surface-2 is ALIASED to the page ground in all four theme blocks, so
     a panel's fill dissolves and a block is announced by its rule instead of its box. --surface
     (the sidebar, the topbar, a hovered row) and --surface-3 (the lifted plane: secondary
     buttons, the active nav item) are kept. The retired panel tone survives as --surface-panel,
     which is NOT dead: the public voice (D113a) still boxes six of its own components and this
     batch does not touch a logged-out page, so those keep the old fill by name. */
  --bg:#0d0c0a; --surface:#16140f; --surface-2:var(--bg); --surface-3:#252118; --surface-panel:#1c1a14;
  --line:#322d23; --line-2:#463f31;
  /* text (warm off-white) */
  --paper:#f4efe4; --paper-2:#c4bda9; --paper-3:#908975; --paper-4:#615a49;
  /* accent - swap this one value to re-theme (crimson default) */
  --accent:#e33b2b; --accent-ink:#ffffff;
  /* Amber alt:  --accent:#f0a81e;  Magenta alt: --accent:#e5399b; */
  /* stat hues - muted, cohesive */
  --health:#5fb872; --happiness:#e6b23e; --creativity:#b07de0;
  --ability:#5f8fe0; --songwriting:#e0854f; --pop:#e0604a;
  --up:#5fb872; --down:#e2564a; --hold:#8b8471;
  --good:#5fb872; --warn:#e6b23e; --bad:#e2564a;
  /* semantic tinted-pill backgrounds + one-off inks (D-light - flip per theme) */
  --accent-hover:#c33324;
  --up-bg:#173a25; --down-bg:#3a1512; --good-bg:#173d24; --bad-bg:#3a1713;
  --danger-bg:#4d1c15; --danger-ink:#ffffff;
  --patron:#f2c14e; --patron-glow:0 0 6px rgba(242,193,78,.35);
  --wave:#4da3c7; /* D99 - world events (genre waves): a cold tide-blue, distinct from the action red */
  --lbl:#a87fd8; /* D100 - record labels: a boardroom violet (from the ceremony confetti palette) */
  /* D103 - certification metals. Gold aliases the existing trophy --patron rather than
     inventing a second gold; silver/platinum are both greys, separated by brightness. */
  --cert-silver:#b9bcc4; --cert-platinum:#eef2f8; --cert-diamond:#8fe3ff;
  --era-tan:#d0c890; --era-tan-deep:#685c20; /* D105 - the 2001 site's palette (the story page) */
  --fx-good:#5fb872; --fx-bad:#e2564a; /* D119 - effect figures on the event ledger */
  --logo-shadow:.4;
  /* radius / elevation - D123 "The Galley": every corner is square and nothing floats. The
     retired values were 6/10/14/999px and two layered shadows. Kept as tokens rather than
     deleted so the ~200 component rules that reference them need no edit, and so a future
     direction can move the whole game again by moving these four lines. */
  --r-sm:0; --r-md:0; --r-lg:0; --r-pill:0;
  --shadow-1:none;
  --shadow-2:none;
  /* spacing scale (reference): 4 8 12 16 20 24 32 40 48 64 */
  /* type */
  --ff-disp:'Barlow Condensed',system-ui,sans-serif;
  --ff-body:'IBM Plex Sans',system-ui,sans-serif;
  --ff-mono:'IBM Plex Mono',ui-monospace,monospace;
}

/* ==== LIGHT THEME (D-light) - token overrides only, ported verbatim from
   docs/design/backstage/light-theme.html. Dark stays the :root default; light applies
   from the OS preference unless a manual [data-theme] wins. Warm paper, not clinical white. ==== */
@media (prefers-color-scheme: light){
  :root:not([data-theme="dark"]){
    --bg:#e7e0d0; --surface:#f1ebdd; --surface-2:var(--bg); --surface-3:#fffdf7; --surface-panel:#f8f3e8; /* D123 - surface-2 aliased; the retired tone stays as --surface-panel for the public voice */
    --line:#d8cfba; --line-2:#c3b8a0;
    --paper:#211d16; --paper-2:#4a4335; --paper-3:#696251; --paper-4:#9a917c;
    --accent:#cf3320; --accent-ink:#ffffff; --accent-hover:#b32c1b;
    --health:#3f8f56; --happiness:#a17817; --creativity:#8a52c4;
    --ability:#3f6fc9; --songwriting:#c0631f; --pop:#cf4630;
    --up:#3f8f56; --down:#cc3b2e; --hold:#726a58;
    --good:#3f8f56; --warn:#a17817; --bad:#cc3b2e;
    --up-bg:#e0efe4; --down-bg:#f7e1de; --good-bg:#e0efe4; --bad-bg:#f7e1de; --danger-bg:#f7e1de; --danger-ink:#a8271b;
    --patron:#b8860b; --patron-glow:none;
    --wave:#2a7d9c;
    --lbl:#8a52c4;
    --r-sm:0; --r-md:0; --r-lg:0; --r-pill:0; --shadow-1:none; --shadow-2:none; /* D123 */
    --logo-shadow:.14;
    --cert-silver:#7b8189; --cert-platinum:#5c6672; --cert-diamond:#1d7fa3; /* D103 fix - was missing here: OS-light users got the dark metals */
    --era-tan:#6b6020; --era-tan-deep:#8a7c3a; /* D105 */
  --fx-good:#2f6b41; --fx-bad:#a8271b; /* D119 - effect figures: --good/--bad miss AA on cream */
  }
}
:root[data-theme="light"]{
  --bg:#e7e0d0; --surface:#f1ebdd; --surface-2:var(--bg); --surface-3:#fffdf7; --surface-panel:#f8f3e8; /* D123 - surface-2 aliased; the retired tone stays as --surface-panel for the public voice */
  --line:#d8cfba; --line-2:#c3b8a0;
  --paper:#211d16; --paper-2:#4a4335; --paper-3:#696251; --paper-4:#9a917c;
  --accent:#cf3320; --accent-ink:#ffffff; --accent-hover:#b32c1b;
  --health:#3f8f56; --happiness:#a17817; --creativity:#8a52c4;
  --ability:#3f6fc9; --songwriting:#c0631f; --pop:#cf4630;
  --up:#3f8f56; --down:#cc3b2e; --hold:#726a58;
  --good:#3f8f56; --warn:#a17817; --bad:#cc3b2e;
  --up-bg:#e0efe4; --down-bg:#f7e1de; --good-bg:#e0efe4; --bad-bg:#f7e1de; --danger-bg:#f7e1de; --danger-ink:#a8271b;
  --patron:#b8860b; --patron-glow:none;
  --wave:#2a7d9c;
  --lbl:#8a52c4;
  --cert-silver:#7b8189; --cert-platinum:#5c6672; --cert-diamond:#1d7fa3; /* D103 - darkened for cream */
  --era-tan:#6b6020; --era-tan-deep:#8a7c3a; /* D105 */
  --fx-good:#2f6b41; --fx-bad:#a8271b; /* D119 - effect figures: --good/--bad miss AA on cream */
  --r-sm:0; --r-md:0; --r-lg:0; --r-pill:0; --shadow-1:none; --shadow-2:none; /* D123 */
  --logo-shadow:.14;
}
/* manual dark wins over a light OS preference */
:root[data-theme="dark"]{
  --bg:#0d0c0a; --surface:#16140f; --surface-2:var(--bg); --surface-3:#252118; --surface-panel:#1c1a14; /* D123 - surface-2 aliased; the retired tone stays as --surface-panel for the public voice */
  --line:#322d23; --line-2:#463f31;
  --paper:#f4efe4; --paper-2:#c4bda9; --paper-3:#908975; --paper-4:#615a49;
  --accent:#e33b2b; --accent-ink:#ffffff; --accent-hover:#c33324;
  --health:#5fb872; --happiness:#e6b23e; --creativity:#b07de0;
  --ability:#5f8fe0; --songwriting:#e0854f; --pop:#e0604a;
  --up:#5fb872; --down:#e2564a; --hold:#8b8471;
  --good:#5fb872; --warn:#e6b23e; --bad:#e2564a;
  --up-bg:#173a25; --down-bg:#3a1512; --good-bg:#173d24; --bad-bg:#3a1713; --danger-bg:#4d1c15; --danger-ink:#ffffff;
  --patron:#f2c14e; --patron-glow:0 0 6px rgba(242,193,78,.35);
  --wave:#4da3c7;
  --lbl:#a87fd8;
  /* D103 - certification metals. Gold aliases the existing trophy --patron rather than
     inventing a second gold; silver/platinum are both greys, separated by brightness. */
  --cert-silver:#b9bcc4; --cert-platinum:#eef2f8; --cert-diamond:#8fe3ff;
  --era-tan:#d0c890; --era-tan-deep:#685c20; /* D105 - the 2001 site's palette (the story page) */
  --fx-good:#5fb872; --fx-bad:#e2564a; /* D119 - effect figures on the event ledger */
  --r-sm:0; --r-md:0; --r-lg:0; --r-pill:0; --shadow-1:none; --shadow-2:none; /* D123 */
  --logo-shadow:.4;
}

/* ---------- base ---------- */
*{box-sizing:border-box}
html,body{margin:0}
body{background:var(--bg);color:var(--paper);font-family:var(--ff-body);font-size:14px;line-height:1.5}
a{color:var(--accent);text-decoration:none}
code{font-family:var(--ff-mono);color:var(--paper-2)}
::selection{background:var(--accent);color:#fff}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.mono{font-family:var(--ff-mono)}
.disp{font-family:var(--ff-disp)}
.muted{color:var(--paper-3)}
.wrap{max-width:1320px;margin:0 auto;padding:0 24px}
/* D112 - skip link: off-screen until focused, then a real accent control at the top-left. */
.skip-link{position:absolute;left:-9999px;top:0;z-index:100;font-family:var(--ff-disp);font-weight:700;font-size:14px;letter-spacing:.05em;text-transform:uppercase;background:var(--accent);color:var(--accent-ink);padding:12px 18px;border-radius:0 0 var(--r-sm) 0}
.skip-link:focus{left:0}
#main:focus{outline:none}

/* ---------- brand marks ---------- */
.brand-link{display:flex;align-items:center;gap:9px;color:var(--paper);text-decoration:none}
.kicker{font-family:var(--ff-mono);font-size:12px;letter-spacing:.28em;text-transform:uppercase;color:var(--paper-3)}

/* ---------- app shell ---------- */
.app{display:flex;min-height:100vh}
.app-nav{width:238px;flex:none;background:var(--surface);border-right:1px solid var(--line);padding:18px 0;display:flex;flex-direction:column}
.brand{padding:0 18px 16px;border-bottom:1px solid var(--line);margin-bottom:12px;display:flex;align-items:center;gap:9px}
.nav-scroll{flex:1;overflow:auto;padding:0 10px}
.nav-section{margin:0 0 14px}
.nav-head{font-family:var(--ff-disp);font-size:12px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--paper-4);padding:4px 10px 6px}
/* D125 - the rotated-square bullet is deleted from all 60 links. It was ornament on every
   row and the accent shape was the only work it did; the 2px left rule every link already
   reserves says the same thing in the form language the rest of the shell is written in.
   Active is now that rule PLUS ink weight, so it survives at a glance and in greyscale,
   and keyboard focus stays the accent outline ring, which is nothing like either. */
.nav-link{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:7px 10px;border-radius:var(--r-sm);font-size:13.5px;color:var(--paper-2);border-left:2px solid transparent;margin-bottom:1px}
.nav-link:hover{background:var(--surface-3)}
.nav-link.is-active{color:var(--paper);font-weight:600;background:var(--surface-3);border-left-color:var(--accent)}
.nav-link .label{display:flex;align-items:center;min-width:0}
.nav-badge{font-family:var(--ff-mono);font-size:10.5px;background:var(--accent);color:var(--accent-ink);border-radius:var(--r-pill);padding:1px 7px;min-width:18px;text-align:center}
.app-main{flex:1;min-width:0;display:flex;flex-direction:column;background:var(--bg)}

/* ---------- the nightly update, while it is running (D126) ---------- */
/* Chrome, not page content: it renders between the topbar and the page, so it never enters a
   page's own section stack. The WARN hue rides the 2px top rule and nothing else - Newsprint at
   2px would read as a named section (D124's rule ladder) and the accent may not be spent on an
   informational note. The words stay in paper ink because the light theme's warn (#a17817) is
   3.06:1 on cream: fine for a rule, which is a graphical object, and short of AA for an 11px
   label. No fill, no sides, no radius - the rule is the edge (The Galley). */
.world-update{border-top:2px solid var(--warn);padding:11px 24px 13px;display:flex;align-items:baseline;gap:14px;flex-wrap:wrap}
.world-update__mark{font-family:var(--ff-mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--paper);white-space:nowrap;flex:none}
.world-update__body{margin:0;font-size:13px;line-height:1.5;color:var(--paper-2);max-width:74ch;text-wrap:pretty}
/* The public chrome centres its content in .wrap, which already carries the 24px gutter; inside
   it the strip drops its own so the rule starts on the same vertical as the page below it. */
.wrap>.world-update{padding-left:0;padding-right:0}
@media (max-width:700px){
  .world-update{padding:10px 16px 12px;gap:5px}
  .world-update__body{font-size:12.5px}
}

/* ---------- top stat bar ---------- */
/* D123 - gradient deleted: it was depth on a raised plane, and there is no raised plane now. */
.topbar{border-bottom:1px solid var(--line);background:var(--surface);padding:12px 24px;display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap}
.band-id{display:flex;align-items:center;gap:14px;min-width:0}
.avatar{width:42px;height:42px;flex:none;border-radius:var(--r-md);background:var(--surface-3);border:1px solid var(--line-2);display:flex;align-items:center;justify-content:center;font-family:var(--ff-disp);font-weight:800;font-size:20px;color:var(--accent)}
.band-name{font-family:var(--ff-disp);font-weight:700;font-size:20px;line-height:1}
.band-sub{font-size:12px;color:var(--paper-3);margin-top:3px}
/* overflow:hidden used to clip the cells to the rounded box; D123 put every radius at 0, so all
   it still did was swallow the last figure whole. The bar wraps instead - it never has to choose
   between hiding a number and pushing the page sideways. */
.stat-bar{display:flex;flex-wrap:wrap;align-items:stretch;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface)}
.stat{padding:7px 16px;border-right:1px solid var(--line);text-align:right}
.stat__label{font-family:var(--ff-disp);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4)}
.stat__val{font-family:var(--ff-mono);font-size:15px;color:var(--paper);margin-top:2px}
.stat__val.is-accent{color:var(--accent)}
.topbar-actions{display:flex;align-items:center;gap:12px}
.topbar-controls{display:flex;align-items:center;gap:12px}
.topbar-link{display:flex;align-items:center;padding:0 15px;color:var(--paper-3);font-size:12px}
.topbar-link:hover{color:var(--paper)}
.topbar-link--icon{padding:0 4px}
.topbar-link--icon svg{display:block}
/* Small screens: dissolve the actions wrapper so the band identity + controls share the
   top row and the wide (£-heavy) stat-bar drops to its own full-width row below. */
@media (max-width:640px){
  /* Mobile topbar: band identity on row 1 (with room reserved top-right for the
     controls, which are pinned there out-of-flow), the wide £-heavy stat-bar drops
     to its own row below. Fixes the controls/wording being shoved off-screen. */
  .topbar{position:relative}
  .topbar-actions{display:contents}
  .topbar .band-id{order:1;width:100%;padding-right:64px}
  /* The four figures were one 460px row inside a 342px phone: cash ran 118px past the edge and
     read "£1," with its label gone, behind a scroller nobody can see. They wrap onto a second
     row instead, and the separator rotates with them - a left rule reappears at the page margin
     wherever a row starts, so on a wrapped bar the cells take the top hairline that a wrapped
     grid of figures already uses (see 6, the full-width strips). */
  .topbar .stat-bar{order:2;max-width:100%;border-left:0;column-gap:20px}
  .topbar .stat{border-left:0;border-top:1px solid var(--line);padding:6px 0 5px}
  .topbar .topbar-controls{position:absolute;top:14px;right:20px;z-index:1}
}
.nav-toggle{display:none;width:40px;height:40px;border:1px solid var(--line-2);background:var(--surface-3);color:var(--paper);border-radius:var(--r-sm);cursor:pointer;font-size:18px;align-items:center;justify-content:center}

/* ---------- pinned vitals strip ---------- */
.vitals-strip{display:flex;gap:18px;padding:9px 24px;border-bottom:1px solid var(--line);background:var(--surface-2);flex-wrap:wrap}
.vs-item{display:flex;align-items:center;gap:8px}
.vs-label{font-family:var(--ff-disp);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--paper-3)}
.vs-track{width:52px;height:6px;background:var(--surface);border-radius:var(--r-pill);overflow:hidden}
.vs-fill{display:block;height:100%;width:var(--pct,0%);background:var(--fill,var(--accent))}
.vs-num{font-family:var(--ff-mono);font-size:12px;color:var(--paper-2)}

/* ---------- page content ---------- */
.page{padding:24px}
.page-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:18px;flex-wrap:wrap;gap:10px}
.page-title{font-family:var(--ff-disp);font-weight:700;font-size:32px;text-transform:uppercase;margin:0;letter-spacing:.01em}
.page-sub{font-size:13px;color:var(--paper-3);margin-top:4px}
/* D130 - the wrap. Five small buttons on another band's profile came to 513px inside a 312px
   column and pushed the most linked page in the game 177px sideways under a thumb. Your own
   profile shows three and fits, which is why it survived every desk pass. */
.page-actions{display:flex;flex-wrap:wrap;gap:9px}

/* ---------- buttons ---------- */
.btn{font-family:var(--ff-disp);font-weight:600;text-transform:uppercase;letter-spacing:.05em;font-size:14px;padding:10px 20px;border-radius:var(--r-sm);border:1px solid transparent;background:transparent;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:8px;line-height:1}
.btn--primary{background:var(--accent);color:var(--accent-ink);font-weight:700;border-color:var(--accent)}
.btn--primary:hover{background:var(--accent-hover)}
.btn--secondary{border-color:var(--line-2);background:var(--surface-3);color:var(--paper)}
.btn--secondary:hover{border-color:var(--paper-4)}
.btn--ghost{color:var(--paper-2)}
.btn--ghost:hover{background:var(--surface-3)}
.btn--danger{font-weight:700;border-color:var(--bad);background:var(--danger-bg);color:var(--danger-ink)}
.btn--sm{font-size:13px;padding:9px 16px}
.btn--lg{font-size:16px;padding:14px 30px;font-weight:700}
.btn--block{display:flex;width:100%}
.btn:disabled,.btn.is-disabled{border-color:var(--line);background:var(--surface);color:var(--paper-4);cursor:not-allowed;pointer-events:none}

/* ---------- form controls ---------- */
.field{display:block;margin-bottom:14px}
.field__label{display:block;font-size:12px;color:var(--paper-3);margin-bottom:5px}
.label-strong{font-family:var(--ff-disp);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--paper-3);margin-bottom:6px;display:block;font-weight:600}
.input,.select,.textarea{width:100%;font-family:var(--ff-body);font-size:14px;padding:10px 12px;border-radius:var(--r-sm);border:1px solid var(--line-2);background:var(--surface);color:var(--paper);outline:none}
.input:focus,.select:focus,.textarea:focus{border-color:var(--accent)}
.input.is-mono{font-family:var(--ff-mono)}
.textarea{resize:vertical;min-height:90px}
.input--error{border-color:var(--bad)}
.field-error{font-size:12px;color:var(--bad);margin-top:5px;display:block}
/* Batch 9 - inline validation (data-validate) */
.field--error .input,.field--error .select,.field--error .textarea{border-color:var(--bad)}
/* D137 - a select option the game is advising against, not forbidding (a tour venue far bigger
   than the band's crowd). Option colour is honoured on desktop Chrome/Firefox and ignored by the
   native pickers on iOS and Android, so the option's own TEXT carries the advice and this rule is
   the sighted-desktop bonus, never the message. */
.select option.opt-dim{color:var(--paper-4)}
.field__error{font-size:12px;color:var(--bad);margin-top:5px;display:block;min-height:0}
.field__error:empty{display:none}
.req{color:var(--bad)}
button[disabled],.btn[disabled]{opacity:.5;cursor:not-allowed}
/* Batch 9 - data-confirm dialog */
.dialog-modal{border:none;background:transparent;padding:0;max-width:min(92vw,420px);color:var(--paper)}
.dialog-modal::backdrop{background:rgba(0,0,0,.55)}
.input-affix{display:flex;align-items:center;border:1px solid var(--line-2);border-radius:var(--r-sm);background:var(--surface);overflow:hidden}
.input-affix__pre{padding:10px 12px;font-family:var(--ff-mono);color:var(--paper-3);border-right:1px solid var(--line)}
.input-affix .input{border:none;background:transparent}
.check{display:flex;align-items:center;gap:9px;font-size:13.5px;color:var(--paper-2)}
input[type=checkbox],input[type=radio]{accent-color:var(--accent);width:16px;height:16px}
input[type=range]{accent-color:var(--accent);width:100%}
.range-scale{display:flex;justify-content:space-between;font-family:var(--ff-mono);font-size:11px;color:var(--paper-4);margin-top:4px}

/* ---------- panels / cards / frames ---------- */
.panel{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-1)}
.panel__head{padding:13px 16px;border-bottom:1px solid var(--line);font-family:var(--ff-disp);font-size:14px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-2);display:flex;justify-content:space-between;align-items:center}
.panel__body{padding:16px}
.card{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);padding:16px;box-shadow:var(--shadow-1)}
.card--raised{border-color:var(--line-2);box-shadow:none} /* D123 - gradient deleted */
/* D87 - the gold Patron ★ shown next to band names everywhere (title="Patron"). */
.patron-star{color:var(--patron);font-size:.9em;margin-left:.28em;line-height:1;text-shadow:var(--patron-glow);white-space:nowrap}
/* D-light - light/dark toggle. In the topbar it's a plain icon that sits with the text links;
   the --float variant (public pages, no topbar) is a self-contained button. */
.theme-toggle{font-size:16px;line-height:1;background:none;border:none;color:var(--paper-3);cursor:pointer;padding:0 2px;display:inline-grid;place-items:center}
.theme-toggle:hover{color:var(--paper)}
/* D86 - the Patron CTA: accent-forward so patronage stands out in the support cluster. */
.card--patron{border-color:color-mix(in srgb,var(--accent),transparent 45%)} /* D123 - gradient deleted; the accent moved onto the block rule */
.card--patron .card-title{color:var(--accent)}
.frame{border:1px solid var(--line-2);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--shadow-2);background:var(--bg)}
.breadcrumb{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:13px 20px;border-bottom:1px solid var(--line);background:var(--surface);font-family:var(--ff-mono);font-size:12px;color:var(--paper-3)}
.breadcrumb .muted{color:var(--paper-4)}
.hint{font-size:11.5px;color:var(--paper-3);line-height:1.5}
/* D73 - live release-cost line (selected producer × studio points vs money) */
.cost-line{font-family:var(--ff-mono);font-size:13px;color:var(--paper-2);padding:8px 12px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface-2)}
.cost-line.is-over{color:var(--bad);border-color:color-mix(in srgb,var(--bad),#000 40%)}
.divider{height:1px;background:var(--line);border:none;margin:0}
.divider--dashed{border-top:1px dashed var(--line-2);height:0}

/* ---------- meters ---------- */
.meter__head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:5px}
.meter__label{font-family:var(--ff-disp);font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--paper-3)}
.meter__val{font-family:var(--ff-mono);font-size:13px;color:var(--paper)}
.meter__track{height:9px;background:var(--surface);border-radius:var(--r-pill);overflow:hidden}
.meter__fill{display:block;height:100%;width:var(--pct,0%);background:var(--fill,var(--accent))}
.meter-list{display:flex;flex-direction:column;gap:13px}

/* ---------- layout helpers ---------- */
.grid{display:grid;gap:16px}
.grid--auto{grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.grid--auto-tight{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))} /* 3-up survives a 1024 viewport (736px content) */
.grid--auto-wide{grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.grid--cards{grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.stack{display:flex;flex-direction:column;gap:16px}
.row{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.between{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap}

/* ---------- tables ---------- */
.table-wrap{overflow-x:auto}
.table{width:100%;border-collapse:collapse;font-size:13.5px}
.table th{text-align:left;padding:10px 16px;font-family:var(--ff-disp);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--paper-3);font-weight:600;border-bottom:1px solid var(--line-2)}
.table td{padding:12px 16px;border-bottom:1px solid var(--line)}
.table .num{font-family:var(--ff-mono);text-align:right}
.table th.num{text-align:right}
/* D123 - the hovered row's fill and the "this is you" tint are deleted, not overridden: a row
   whose outer inset is zero cannot carry one (The Galley, section 13, where both states are
   carried by ink and a rule instead). The accent ink below is the half of the old treatment
   that still works, so it stays here. */
.table tr.is-you .rank,.table tr.is-you a{color:var(--accent);font-weight:700}
.table--dense th,.table--dense td{padding:9px 14px}
.tag{font-size:11px;color:var(--paper-4)}
.pill-tag{font-size:11px;color:var(--paper-4);border:1px solid var(--line-2);padding:1px 5px;text-transform:uppercase;font-family:var(--ff-mono)}

/* ---------- chips / badges ---------- */
.chip{font-family:var(--ff-mono);font-size:11px;text-transform:uppercase;letter-spacing:.06em;padding:3px 9px;border-radius:var(--r-pill);background:var(--surface-3);color:var(--paper-3);display:inline-block}
.chip--up{background:var(--up-bg);color:var(--up)}
.chip--down{background:var(--down-bg);color:var(--down)}
.chip--accent{background:var(--accent);color:var(--accent-ink)}
.chip--bad{background:color-mix(in srgb,var(--bad) 14%,var(--surface-3));border-color:color-mix(in srgb,var(--bad) 50%,var(--line-2));color:var(--bad)}

/* ---------- alerts ---------- */
.alert{padding:11px 15px;border:1px solid var(--line-2);border-radius:var(--r-sm);background:var(--surface-2);font-size:13.5px;color:var(--paper-2);display:flex;align-items:center;gap:12px} /* D123 - the coloured left rail is deleted, not overridden: it rotates to a top rule (The Galley). */
.alert--good{border-left-color:var(--good)}
.alert--warn{border-left-color:var(--warn)}
.alert--bad{border-left-color:var(--bad)}
.alert--accent{border-left-color:var(--accent)}

/* ---------- tabs ---------- */
.tabs{display:flex;border-bottom:1px solid var(--line);flex-wrap:wrap}
.tab{font-family:var(--ff-disp);font-size:14px;text-transform:uppercase;letter-spacing:.05em;padding:9px 15px;border:none;border-bottom:2px solid transparent;color:var(--paper-3);cursor:pointer;background:none}
.tab.is-active{border-bottom-color:var(--accent);color:var(--paper);font-weight:600}

/* ---------- pagination ---------- */
.pager{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.pager__item{font-family:var(--ff-mono);font-size:13px;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:var(--r-sm);border:1px solid var(--line-2);color:var(--paper-2)}
.pager__item.is-active{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.pager__item.is-disabled{color:var(--paper-4)}
.pager__ellipsis{font-family:var(--ff-mono);font-size:12px;color:var(--paper-4);padding:0 6px}

/* ---------- dialog / empty ---------- */
/* D123 - a modal is the one thing that genuinely floats, because the page behind it is still
   there. It keeps a fill and an edge, squared, and takes the block rule (see The Galley). */
.dialog{border:1px solid var(--line-2);padding:22px;max-width:400px}
.dialog__title{font-family:var(--ff-disp);font-weight:700;font-size:20px;text-transform:uppercase;letter-spacing:.02em}
.dialog__body{font-size:13.5px;color:var(--paper-2);line-height:1.55;margin:8px 0 18px}
.dialog__actions{display:flex;gap:10px;justify-content:flex-end}
.empty{border:1px dashed var(--line-2);border-radius:var(--r-md);padding:34px 20px;text-align:center}
/* D125 - the hollow rotated square above every empty state is deleted. An empty state in
   this language is the title, the line under it and the room around them; the block above
   has already announced itself with a rule, so nothing has to draw a mark to stand in. */
.empty__title{font-family:var(--ff-disp);font-weight:700;font-size:18px;text-transform:uppercase}

/* ---------- stepper (wizard) ---------- */
.stepper{display:flex;align-items:center;max-width:560px;margin-bottom:26px}
.step{display:flex;align-items:center;gap:10px;flex:1}
.step__num{width:28px;height:28px;flex:none;background:var(--surface-3);color:var(--paper-4);font-family:var(--ff-mono);font-size:13px;display:flex;align-items:center;justify-content:center}
.step__label{font-family:var(--ff-disp);font-size:14px;text-transform:uppercase;letter-spacing:.04em;color:var(--paper-3);white-space:nowrap}
.step__line{flex:1;height:2px;background:var(--line-2);margin:0 4px}
.step.is-active .step__num,.step.is-done .step__num{background:var(--accent);color:var(--accent-ink)}
.step.is-active .step__label{color:var(--paper)}
.step.is-done .step__line{background:var(--accent)}

/* ---------- option cards (radio) ---------- */
.opt-card{display:flex;align-items:center;gap:14px;padding:14px 16px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2);cursor:pointer}
/* D123 - the hovered box's brighter edge and the chosen box's fill are deleted, not overridden:
   both went with the box, and section 13 marks the row with a rule instead. */
.opt-card.is-selected{border-color:var(--accent)}
/* D123 - a KEPT circle. Every other corner in the game squares, but a circle means "choose one
   of these" and a square means "choose any of these" in every operating system there is, and a
   visual direction does not get to overrule an affordance. */
.opt-radio{width:18px;height:18px;flex:none;border-radius:50%;border:2px solid var(--paper-4);display:flex;align-items:center;justify-content:center}
.opt-card.is-selected .opt-radio{border-color:var(--accent)}
.opt-dot{width:8px;height:8px;border-radius:50%;background:transparent}
.opt-card.is-selected .opt-dot{background:var(--accent)}
.opt-name{font-family:var(--ff-disp);font-weight:600;font-size:16px;text-transform:uppercase;letter-spacing:.03em;color:var(--paper);display:block}
.opt-desc{font-size:12.5px;color:var(--paper-3);margin-top:2px;display:block}
.opt-meta{text-align:right;flex:none}
.opt-cost{font-family:var(--ff-mono);font-size:13px;color:var(--paper);display:block}
.opt-cost.is-free{color:var(--good)}
.opt-mult{font-size:11px;color:var(--paper-4);text-transform:uppercase;letter-spacing:.08em;margin-top:2px;display:block}

/* ---------- art placeholder (graceful fallback) ---------- */
/* D123 - a KEPT gradient. This is not a surface: it is the diagonal hatch that stands for
   artwork that does not exist yet, the way a printed page hatches a missing picture. */
.art{border-radius:var(--r-md);border:1px solid var(--line-2);background-image:repeating-linear-gradient(135deg,var(--surface-2),var(--surface-2) 11px,var(--surface-3) 11px,var(--surface-3) 22px);display:flex;align-items:center;justify-content:center}
.art__label{font-family:var(--ff-mono);font-size:11px;color:var(--paper-4);letter-spacing:.1em;text-transform:uppercase}

/* ---------- doc sections (kit / tokens / routes / index) ---------- */
.section{padding:48px 0 0}
.section__head{display:flex;align-items:baseline;gap:16px;margin-bottom:8px}
.section__num{font-family:var(--ff-mono);font-size:13px;color:var(--accent);letter-spacing:.1em}
.section__title{font-family:var(--ff-disp);font-weight:700;font-size:30px;text-transform:uppercase;margin:0}
.section__intro{color:var(--paper-3);font-size:14px;margin:0 0 22px;max-width:760px}
.doc-header{border-bottom:1px solid var(--line);padding:40px 0 34px;background:var(--surface)} /* D123 - gradient deleted */
.swatch{width:34px;height:34px;flex:none;border-radius:var(--r-sm);border:1px solid var(--line-2)}

/* ---------- public / auth ---------- */
.public-nav{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:16px 24px;border-bottom:1px solid var(--line);background:var(--surface);flex-wrap:wrap}
.public-nav .links{display:flex;gap:20px;align-items:center}
.public-nav .links a:not(.btn){font-family:var(--ff-disp);font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:var(--paper-3)}
.hero{padding:56px 32px;text-align:center;background:var(--bg)} /* D123 - the radial haze deleted (kit page only; the live hero is .home-hero, de-hazed in D113a) */
.hero h1{font-family:var(--ff-disp);font-weight:800;font-size:66px;line-height:.9;letter-spacing:-.01em;text-transform:uppercase;margin:16px auto 0;max-width:820px}
.hero p{max-width:560px;margin:18px auto 26px;color:var(--paper-2);font-size:16px}
.stats-strip{display:flex;flex-wrap:wrap;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.stat-cell{flex:1;min-width:130px;padding:20px;text-align:center;border-right:1px solid var(--line)}
.stat-cell .v{font-family:var(--ff-mono);font-size:24px;color:var(--paper)}
.stat-cell .k{font-family:var(--ff-disp);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--paper-4);margin-top:4px}
.moment{display:flex;gap:16px;align-items:center}
.auth-stage{background:var(--bg)} /* D123 - the radial haze deleted */

/* =====================================================================
   PUBLIC RELAUNCH (D88) - logged-out surfaces, ported from
   docs/design/public-logged-out.html (.home-* / new .auth-*). Token-driven,
   so light theme works for free. Logo (.logo-mark, D114) + light tokens already
   live above/in the theme blocks; not re-ported here.
   ===================================================================== */

/* --- theme toggle (shared icon-swap: two spans, CSS-driven by data-theme) --- */
.home-theme{width:40px;height:40px;flex:none;display:grid;place-items:center;border:1px solid var(--line-2);background:transparent;color:var(--paper-3);border-radius:var(--r-sm);cursor:pointer;font-size:16px;line-height:1} /* D115 - a quiet utility, not a third button */
.home-theme:hover{border-color:var(--paper-4);color:var(--paper)}
.theme-toggle__light,.home-theme__light{display:none}
:root[data-theme="light"] .theme-toggle__dark,:root[data-theme="light"] .home-theme__dark{display:none}
:root[data-theme="light"] .theme-toggle__light,:root[data-theme="light"] .home-theme__light{display:inline}

/* --- small-screen "More" menu (zero-JS <details>) --- */
.home-menu{display:none;position:relative}
.home-menu>summary{list-style:none;cursor:pointer}
.home-menu>summary::-webkit-details-marker{display:none}
.home-menu__panel{position:absolute;right:0;top:calc(100% + 8px);min-width:170px;display:flex;flex-direction:column;padding:6px;gap:2px;background:var(--surface-2);border:1px solid var(--line-2);border-radius:var(--r-md);box-shadow:var(--shadow-2);z-index:30}
.home-menu__panel a{font-family:var(--ff-disp);font-weight:600;font-size:14px;letter-spacing:.04em;text-transform:uppercase;color:var(--paper-2);padding:10px 12px;border-radius:var(--r-sm)}
.home-menu__panel a:hover{color:var(--paper);background:var(--surface-3)}
@media (max-width:880px){.home-menu{display:block}} /* D115 - the fold moved up from 720: five links plus the account pair overflow a 760px bar */

/* --- public bar --- */
/* D113a - solid bar, no glass: the blurred translucent header was the first of the generic tells. */
/* D115 - the bar reads as three groups. Inside a group the gap is tight (2px between links, 8px
   between the account pair); between groups it is generous (20px) with a hairline before the
   account pair. Log in is the secondary button so the pair is one decision at one height; the
   theme toggle is a bare outline at the seam. Nothing in the bar wraps. */
.home-nav{position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:space-between;gap:28px;padding:12px 28px;min-height:64px;background:var(--bg);border-bottom:1px solid var(--line-2)}
.home-nav__links{display:flex;align-items:center;gap:20px}
.home-nav__link{font-family:var(--ff-disp);font-weight:700;font-size:15px;letter-spacing:.06em;text-transform:uppercase;color:var(--paper-2);padding:10px 12px;margin:0 -9px;border-radius:var(--r-sm);white-space:nowrap}
.home-nav__link + .home-nav__link{margin-left:-6px}
.home-nav__link:hover{color:var(--paper);background:var(--surface-3)}
.home-nav__account{display:flex;align-items:center;gap:8px;padding-left:20px;border-left:1px solid var(--line-2)}
.home-nav .btn{white-space:nowrap;font-size:14px;padding:11px 16px;line-height:1}
.home-nav .home-nav__login{background:transparent}
@media (max-width:880px){
  .home-nav__hide{display:none}
  /* D115 - the fold: a 13px ticket, tighter seams, smaller buttons; the bar must never wrap or clip */
  .home-nav{padding:12px 16px;gap:14px}
  .home-nav__links{gap:12px}
  .home-nav .logo-mark{font-size:13px}
  .home-nav__account{padding-left:12px}
  .home-nav .btn{padding:11px 12px}
}
@media (max-width:640px){.home-nav .home-nav__login{display:none}} /* Log in lives in the More menu from here down */
@media (max-width:520px){.home-nav__hide-xs{display:none}} /* D112 - History holds on until phone width */
/* tighten the bar on small phones so logo + toggle + Log in + Create account + More
   stay on one row without wrapping or clipping. */
@media (max-width:520px){
  /* D112 - tap targets. These were ~33px tall against the 44px minimum, with Log in and Create
     account 5px apart, so a thumb regularly caught the wrong one. 13px of vertical padding on
     14px/1 text clears 44px, and the gap doubles. The row still fits: History folds out at this
     width (home-nav__hide-xs) and the More menu carries it. */
  .home-nav{padding:10px 12px;gap:10px}
  .home-nav__links{gap:12px}
  .home-nav__link{padding:13px 10px;margin:0}
  .home-nav .btn{padding:13px 14px}
  .home-nav__account{padding-left:0;border-left:0;gap:8px}
  .home-theme{width:44px;height:44px}
}
/* D113b - at 390 the row still clipped its own "More" menu (the finish review caught "MO" at the
   edge): tighter gaps and smaller type below 400px keep logo, toggle, Log in, Create account and
   More on one row with every tap target intact. */
@media (max-width:400px){
  .home-nav{padding:10px 8px;gap:6px}
  .home-nav__links{gap:6px}
  .home-nav__link{padding:13px 6px;font-size:13px}
  .home-nav .btn{padding:13px 10px;font-size:13px}
  .home-nav .logo-mark{font-size:12px}
}

/* --- hero --- */
/* D113a - the hero lost its two radial glows (accent haze above, surface haze below) and took the
   public heading voice (--ff-head, set on body.public). Same composition, plain ground. */
.home-hero{position:relative;overflow:hidden;padding:clamp(48px,8vw,96px) 26px clamp(40px,6vw,72px);background:var(--bg)}
.home-hero__in{max-width:960px;margin:0 auto;text-align:center;position:relative}
.home-hero__h1{font-family:var(--ff-head,var(--ff-disp));font-weight:400;text-transform:uppercase;line-height:.95;letter-spacing:.005em;margin:0;font-size:clamp(38px,7vw,88px);color:var(--paper);text-wrap:balance}
.home-hero__h1 em{font-style:normal;color:var(--accent)}
.home-hero__sub{color:var(--paper-2);font-size:clamp(15px,1.9vw,19px);margin:22px auto 0;max-width:52ch;line-height:1.5}
.home-hero__cta{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-top:30px}
.home-hero__note{font-family:var(--ff-mono);font-size:12.5px;letter-spacing:.02em;color:var(--paper-3);margin-top:18px}

/* --- live stat strip: this world's own numbers, four ruled cells (label over monospaced figure).
   Captions in --paper-3 (4.67:1 on --surface-2 in both themes) where --paper-4 sat at 2.5:1. --- */
/* D113a - the four figures stay (they are the live proof) but the rounded box of cells is now a
   ruled row: two rules, hairlines between, Barlow numerals. The hero-metric template is gone. */
.home-stats{display:grid;grid-template-columns:repeat(4,1fr);max-width:960px;margin:clamp(32px,5vw,52px) auto 0;border-top:1px solid var(--line-2);border-bottom:1px solid var(--line-2)}
.home-stat{padding:16px 12px 14px;text-align:center;border-left:1px solid var(--line)}
.home-stat:first-child{border-left:0}
.home-stat__v{font-family:var(--ff-disp);font-weight:800;font-variant-numeric:tabular-nums;font-size:clamp(26px,3.4vw,38px);color:var(--paper);line-height:1}
.home-stat__k{font-family:var(--ff-mono);font-size:12px;letter-spacing:.02em;color:var(--paper-3);margin-top:6px}
.home-live{display:inline-block;width:8px;height:8px;border-radius:50%;/* D123 - a KEPT circle: a lamp, on the public page, which does not move */background:var(--up);margin-right:7px;vertical-align:baseline;animation:home-pulse 2s ease-in-out infinite}
@keyframes home-pulse{0%,100%{opacity:1}50%{opacity:.35}}
@media (prefers-reduced-motion:reduce){.home-live{animation:none}}
@media (max-width:640px){.home-stats{grid-template-columns:repeat(2,1fr)}.home-stat:nth-child(3){border-left:0}.home-stat:nth-child(n+3){border-top:1px solid var(--line)}}

/* --- section shell --- */
.home-sec{max-width:1180px;margin:0 auto;padding:clamp(48px,7vw,88px) 26px 0}
/* D113a - no eyebrow rule any more: the section heading carries its own weight, in the public
   heading voice, with one word in the accent where the copy earns it. */
.home-sec__h{font-family:var(--ff-head,var(--ff-disp));font-weight:400;font-size:clamp(26px,3.6vw,40px);text-transform:uppercase;letter-spacing:.01em;line-height:1.05;margin:0;color:var(--paper);max-width:24ch;text-wrap:balance}
.home-sec__h em{font-style:normal;color:var(--accent)}
.home-sec__lead{color:var(--paper-2);font-size:16px;margin:14px 0 0;max-width:62ch}

/* --- "on the charts now" (D112): the real Top 10 as ONE full-width ruled table. The first
   cut had a side card for the #1 album and a thumbnail column; rendered, the card floated over
   500px of nothing and the thumbnails were ten empty grey squares. And every title and band
   fell through to the global red link colour - twenty-odd red strings on a page whose rule is
   one red voice. Titles now sit in paper, bands in the secondary ink, red only on hover; the
   album #1 lives in the caption. --- */
.home-chart{margin-top:34px}
.home-chart .empty{padding:28px 16px;border-top:2px solid var(--paper)}
/* D121 - the front-page chart is a RULED LIST, not a table: a 2px paper rule on top and
   hairlines between rows, per the public voice. Replaces a 4-column dense table that went
   ragged in the position column, carried no artwork, and overflowed a phone. */
.home-chart__list{list-style:none;margin:0;padding:0;border-top:2px solid var(--paper);counter-reset:none}
.home-chart__row{display:grid;grid-template-columns:54px 56px minmax(0,1fr) 44px 66px;align-items:center;
  gap:0 16px;padding:11px 4px;border-bottom:1px solid var(--line)}
.home-chart__row:hover{background:var(--surface)}
/* the numeral sits over its last position in a FIXED track, both right-aligned, so the column
   edge stays straight from 1 to 10 - the inline pair it replaces could not */
.home-chart__pos{display:flex;flex-direction:column;align-items:flex-end;gap:1px;line-height:1}
.home-chart__posn{font-family:var(--ff-disp);font-weight:800;font-size:34px;line-height:.85;font-variant-numeric:tabular-nums;color:var(--paper)}
.home-chart__posl{font-family:var(--ff-mono);font-size:10.5px;font-variant-numeric:tabular-nums;color:var(--paper-3)}
.home-chart__art{width:56px;height:56px;object-fit:cover;border:1px solid var(--line-2);border-radius:0;display:block}
/* D123 - the same KEPT hatch, on the public homepage, which does not move. */
.home-chart__art--none{background-image:repeating-linear-gradient(135deg,var(--surface-2),var(--surface-2) 11px,var(--surface-3) 11px,var(--surface-3) 22px)}
.home-chart__meta{min-width:0}
.home-chart__title{display:block;font-family:var(--ff-disp);font-weight:700;font-size:17px;letter-spacing:.01em;text-transform:uppercase;color:var(--paper);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.home-chart__by{font-size:13.5px;color:var(--paper-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.home-chart__band{color:var(--paper-2);font-weight:500}
.home-chart__row:hover .home-chart__title{color:var(--accent)}
.home-chart__title:hover,.home-chart__band:hover{color:var(--accent)}
.home-chart__move{font-size:12.5px;font-weight:500;text-align:center;letter-spacing:.04em}
.home-chart__wks{display:flex;flex-direction:column;align-items:flex-end;line-height:1.15}
.home-chart__wksn{font-family:var(--ff-mono);font-size:13px;font-variant-numeric:tabular-nums;color:var(--paper-2)}
.home-chart__wksk{font-family:var(--ff-mono);font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--paper-4)}
.home-chart__wkin{display:none}
/* Phone: no table, so there is nothing to scroll sideways. The movement flag keeps its OWN
   track - an earlier cut shared the title's cell and the two overlapped. Weeks folds into the
   byline rather than being dropped. */
@media (max-width:640px){
  .home-chart__row{grid-template-columns:40px 52px minmax(0,1fr) auto;gap:0 12px;padding:10px 2px}
  .home-chart__posn{font-size:25px}
  .home-chart__posl{font-size:10px}
  .home-chart__art{width:52px;height:52px}
  .home-chart__title{font-size:15px}
  .home-chart__by{font-size:12.5px}
  .home-chart__move{font-size:11.5px;min-width:22px}
  .home-chart__wks{display:none}
  .home-chart__wkin{display:inline;color:var(--paper-3)}
}
.home-chart__cap{display:flex;justify-content:space-between;gap:8px 16px;flex-wrap:wrap;padding:10px 16px;border-top:1px solid var(--line);font-family:var(--ff-mono);font-size:11px;letter-spacing:.06em;color:var(--paper-3)}
.home-chart__links{display:flex;gap:18px;flex-wrap:wrap}
.home-chart__cap a{color:var(--accent)}

/* --- feature list (D113a: was a 3x2 grid of same-size emoji cards; now a ruled two-column list) --- */
.home-feats{list-style:none;margin:30px 0 0;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:0 44px;border-top:2px solid var(--paper)}
@media (max-width:720px){.home-feats{grid-template-columns:1fr}}
.home-feat{padding:18px 0 20px;border-bottom:1px solid var(--line-2)}
.home-feat__h{font-family:var(--ff-disp);font-weight:800;font-size:22px;text-transform:uppercase;letter-spacing:.02em;color:var(--paper);margin:0;line-height:1.05}
.home-feat__b{color:var(--paper-2);font-size:15px;line-height:1.55;margin:8px 0 0;max-width:52ch}

/* --- in-action tiles --- */
.home-shots{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:34px}
@media (max-width:860px){.home-shots{grid-template-columns:1fr}}
/* D127 - a real <button>, because it opens the viewer. A click handler on a <div> is unreachable
   by keyboard and has nothing to hand focus back to when the dialog closes; the archive gallery
   had already got this right. These lines are the button reset.

   D139 - and the reset is FLEX, not block, which is the fix for a fault D127's own comment used to
   claim it had solved: "back to the div it was". It cannot be. Chromium lays a button's children
   out inside the button's own anonymous content box rather than in normal block flow, so with
   display:block the screenshot's bottom edge sat 11px BELOW the top of its caption on every tile
   at 1100, 1440 and 1920 alike - the caption's first line printed over the image and the caption's
   own top rule was buried under it. A column flex container gives the two children real block flow
   and the overlap is 0px at all three widths. Deliberately not grid: grid clears 1440 and 1920 and
   opens a 9px gap on two of the three tiles at 1100. */
.home-shot{display:flex;flex-direction:column;width:100%;text-align:left;padding:0;font:inherit;color:inherit;cursor:zoom-in;
  border:1px solid var(--line-2);overflow:hidden;background:var(--surface-2)}
.home-shot:hover{border-color:color-mix(in srgb,var(--accent) 45%,var(--line-2))}
/* height:auto matters: the <img> now carries intrinsic width/height attributes (D112, no layout
   shift), and without an author height the browser honours the attribute and ignores aspect-ratio -
   which rendered three 1423px-tall screenshots. */
/* D127 - object-position:top, which the two variants' figures always had and this one never did:
   with the default centring, a 1280x1423 capture cropped to 16:10 showed the MIDDLE of the page
   and hid the masthead that says which page it is. The whole capture is one click away now. */
.home-shot__img{display:block;width:100%;height:auto;aspect-ratio:16/10;object-fit:cover;object-position:top;background-color:var(--surface-3)}
/* The caption strip is also the affordance, the way the archive's .story-shot__bar is. It takes
   its own line rather than sharing one: these captions run to two lines in every tile, so a
   right-aligned hint would have wrapped anyway, and a rule that only sometimes wraps is not a
   layout. Paper 3 and not Paper 4 - at 10px the quietest tier is 2.6:1 on this fill, a real fail. */
.home-shot__cap{padding:12px 15px;font-size:12.5px;color:var(--paper-3);border-top:1px solid var(--line);line-height:1.5}
.home-shot__cap b{color:var(--paper-2);font-weight:600}
.home-shot__zoom{display:block;margin-top:7px;font-family:var(--ff-mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--paper-3)}
.home-shot:hover .home-shot__zoom{color:var(--accent)}
/* D127 - the same trigger where the shot already lives inside a <figure> with its own caption
   (the two homepage variants): the button wraps the image only, so the figure's rules still land
   on the img and nothing about either poster world moves. Reset, and nothing else. */
.shot-btn{display:block;width:100%;padding:0;border:0;background:none;font:inherit;color:inherit;cursor:zoom-in}

/* --- rivalry callout (echoes the dashboard rivalry card) --- */
.home-rivalry{max-width:1180px;margin:clamp(48px,7vw,88px) auto 0;padding:0 26px}
/* D113a - plain ruled panel: no radial glow, no shadow, no radius. */
.home-rivalry__card{position:relative;overflow:hidden;border:1px solid var(--line-2);border-top:2px solid var(--paper);padding:clamp(24px,4vw,44px);text-align:center;background:var(--surface-2)}
/* D112 - the VS line is now the section's heading (an h2 carrying two real band names) and the
   score line a paragraph, so both take explicit margins instead of the inline styles they had. */
.home-rivalry__vs{display:flex;align-items:center;justify-content:center;gap:clamp(16px,4vw,40px);flex-wrap:wrap;margin:0}
.home-rivalry__band{font-family:var(--ff-disp);font-weight:800;font-size:clamp(24px,4vw,44px);text-transform:uppercase;letter-spacing:.01em;color:var(--paper);line-height:.95}
a.home-rivalry__band:hover{color:var(--accent)}
.home-rivalry__mid{font-family:var(--ff-disp);font-weight:800;font-size:14px;letter-spacing:.2em;color:var(--accent)}
.home-rivalry__score{font-family:var(--ff-mono);font-size:16px;color:var(--paper-2);margin:16px 0 0}
.home-rivalry__score b{color:var(--up)}

/* --- final CTA --- */
.home-cta{max-width:1180px;margin:clamp(48px,7vw,88px) auto 0;padding:0 26px}
/* D113a - the red-tinted, red-bordered rounded panel is a ruled block; the button is the one red. */
.home-cta__in{border-top:3px solid var(--paper);border-bottom:1px solid var(--line-2);padding:clamp(32px,5vw,56px) 26px;text-align:center}
.home-cta__h{font-family:var(--ff-head,var(--ff-disp));font-weight:400;font-size:clamp(26px,4vw,44px);text-transform:uppercase;letter-spacing:.01em;line-height:1.05;color:var(--paper);margin:0;text-wrap:balance}
.home-cta__sub{color:var(--paper-2);font-size:15px;margin:12px auto 0;max-width:48ch}

/* --- footer --- */
.home-foot{max-width:1180px;margin:clamp(52px,7vw,90px) auto 0;padding:28px 26px 44px;border-top:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap}
.home-foot__links{display:flex;gap:8px 18px;flex-wrap:wrap}
.home-foot__link{font-family:var(--ff-mono);font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:var(--paper-3)}
.home-foot__link:hover{color:var(--paper)}
.home-foot__note{font-size:12px;color:var(--paper-3);line-height:1.5}

/* --- auth pages (new card shell; replaces the old .auth-frame/.auth-body/.auth-card) --- */
/* D113a - no accent haze behind the card, no shadow, no radius; the heading in the public voice. */
.auth-wrap{min-height:520px;display:grid;place-items:center;padding:56px 24px;background:var(--bg)}
.auth-card{width:100%;max-width:420px;background:var(--surface-2);border:1px solid var(--line-2);border-top:2px solid var(--paper);padding:34px 30px}
.auth-card__h{font-family:var(--ff-head,var(--ff-disp));font-weight:400;font-size:30px;text-transform:uppercase;text-align:center;margin:0 0 6px;color:var(--paper);line-height:1.05}
.auth-card__sub{text-align:center;font-size:13px;color:var(--paper-3);margin:0 0 26px}
.auth-or{display:flex;align-items:center;gap:12px;margin:20px 0}
.auth-or span{flex:1;height:1px;background:var(--line)}
.auth-or b{font-family:var(--ff-mono);font-size:11px;color:var(--paper-4);font-weight:500}
.auth-fine{text-align:center;font-size:11.5px;color:var(--paper-4);margin-top:16px;line-height:1.5}

/* =====================================================================
   ARCHETYPE COMPOSITION LAYER (Phase 2b.1)
   Every per-page inline style="" was lifted here so batched pages inherit
   it. Utilities are a bounded set on the token spacing scale; anything
   multi-property is a semantic component class. Dynamic values (meter
   --pct/--fill/--before/--after) stay inline inside partials only.
   ===================================================================== */

/* --- text utilities --- */
.text-center{text-align:center}
.tc-paper{color:var(--paper)}.tc-paper-2{color:var(--paper-2)}.tc-paper-3{color:var(--paper-3)}.tc-paper-4{color:var(--paper-4)}
.tc-accent{color:var(--accent)}.tc-up{color:var(--up)}.tc-down{color:var(--down)}.tc-warn{color:var(--warn)}
.fs-11{font-size:11px}.fs-12{font-size:12px}.fs-13{font-size:13px}

/* --- spacing utilities (token scale: 4 8 12 16 20 24) --- */
/* mt-4 and mt-8 were missing from a scale whose own comment claims them: seven call sites across
   the app had been writing class="mt-8" against nothing since Batch 10, so every one of them
   rendered flush. Declared here rather than patched per page (the Patreon button pair, 2026-09-10). */
.mt-4{margin-top:4px}.mt-8{margin-top:8px}
.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-20{margin-top:20px}.mt-24{margin-top:24px}
.mb-4{margin-bottom:4px}.mb-8{margin-bottom:8px}.mb-16{margin-bottom:16px}.mb-20{margin-bottom:20px}.mb-24{margin-bottom:24px}
.mx-auto{margin-left:auto;margin-right:auto}

/* --- gap modifiers (apply to .row / .stack / .grid) --- */
.g-8{gap:8px}.g-9{gap:9px}.g-10{gap:10px}.g-11{gap:11px}.g-12{gap:12px}.g-14{gap:14px}.g-16{gap:16px}.g-24{gap:24px}

/* --- flex / grid utilities --- */
.nowrap{flex-wrap:nowrap}
.row--center{justify-content:center}
.row--end{align-items:flex-end}
.row--right{justify-content:flex-end}
.grid--top{align-items:start}
.grid--2{grid-template-columns:1fr 1fr}
/* A figure sets its own cell's width. repeat(auto-fit,minmax(120px,1fr)) cannot express that:
   auto-fit requires a FIXED track minimum, so the track ignored what it was asked to hold and a
   14-digit stream count was laid into a 120px column, spilling 41px across its neighbour once
   D123 took away the opaque card background that had been hiding the spill. A wrapping flex row
   can: a grouped number carries no break opportunity, so min-content IS the figure's own width,
   no cell is ever narrower than what it prints, and the rack takes another row rather than
   overprint or clip. The 120px basis is the retired track width, so the break stays 4-then-3 at
   the measure and 2-up on a phone. */
.grid--stats{display:flex;flex-wrap:wrap}
.grid--stats>*{flex:1 1 120px;min-width:min-content}
.flex-1{flex:1}
.flex-none{flex:none}
.self-start{align-self:flex-start}
.w-110{width:110px}.w-180{width:180px}.w-auto{width:auto}

/* --- shared modifiers --- */
.frame--flat{box-shadow:none}
.kicker--sm{font-size:11px}
.kicker--accent{color:var(--accent)}
.link-muted{font-size:12px;color:var(--paper-3)}
.link-sm{font-size:12px}
.hint--ruled{border-top:1px dashed var(--line-2);padding-top:11px}
.panel--clip{overflow:hidden}
.art--square{aspect-ratio:1/1}
.art--sm{width:84px;height:84px;flex:none}
.btn--flex{flex:1}
.btn--icon{width:36px;height:36px;padding:0;flex:none}
.btn--add{align-self:flex-start;border:1px dashed var(--line-2)}
.is-hyped{color:var(--accent);border-color:var(--accent)} /* Batch 12 - active hype button */

/* --- auth archetype --- */
.auth-frame{max-width:900px;margin:40px auto}
.auth-body{padding:56px 24px}
.auth-title{font-family:var(--ff-disp);font-weight:800;font-size:38px;text-transform:uppercase;text-align:center;margin:0 0 4px}
.auth-tagline{text-align:center;font-size:13px;color:var(--paper-3);margin:0 0 26px}
.auth-aux{text-align:center;margin-top:14px}
.auth-foot{text-align:center;margin-top:16px;font-size:13px;color:var(--paper-3)}
.input--lg{font-size:15px;padding:12px 14px}
.field--last{margin-bottom:20px}
.or-divider{display:flex;align-items:center;gap:12px;margin:22px 0}
.or-divider::before,.or-divider::after{content:"";flex:1;height:1px;background:var(--line)}
.or-divider__label{font-family:var(--ff-mono);font-size:11px;color:var(--paper-4)}

/* --- public archetype --- */
.public-frame{max-width:1100px;margin:32px auto}
.moment-grid{padding:28px 24px}
.moment__eyebrow{font-family:var(--ff-disp);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent)}
.moment__title{font-family:var(--ff-disp);font-weight:700;font-size:20px;text-transform:uppercase;margin-top:3px}
.moment__artist{font-size:13px;color:var(--paper-3)}

/* --- dashboard archetype --- */
.rank-row{display:flex;align-items:baseline;gap:8px;margin-top:4px}
.rank-num{font-family:var(--ff-mono);font-size:30px}
.rank-delta{font-size:12px;color:var(--up)}
.card-title{font-family:var(--ff-disp);font-weight:700;text-transform:uppercase;letter-spacing:.04em;font-size:14px}
.card-copy{font-size:12.5px;color:var(--paper-2);margin:6px 0 11px}
.card-note{font-size:12px;color:var(--paper-3);margin-top:2px}
.activity-list{padding:6px 0}
.activity{display:flex;gap:11px;padding:9px 16px;align-items:flex-start;flex-wrap:nowrap}
.activity__dot{width:6px;height:6px;margin-top:6px;flex:none;background:var(--pop)}
.activity__dot--health{background:var(--health)}
.activity__text{font-size:13px;color:var(--paper-2);line-height:1.45}

/* --- detail archetype --- */
/* D93/D98 - art column capped at 440 CSS px (the -lg variant still covers @2x), and the info
   column gets a REAL minimum (420px): grid track sizing fills a minmax's max before fr tracks
   grow, so the old minmax(260,570) art hogged its 570 while the info column was starved to
   scraps just above the stack breakpoint. The stack point sits at 940 because the two column
   minimums (260+420 + gap) need ~700px of content width - below that we go single column. */
.grid--detail{grid-template-columns:minmax(260px,440px) minmax(420px,1fr)}
/* min-width:0 on the items: a grid item's implicit min-width:auto would otherwise refuse to
   shrink below a table's intrinsic width, defeating .table-wrap's overflow-x and
   stretching the whole page on phones. */
.grid--detail>*{min-width:0}
@media (max-width:940px){.grid--detail{grid-template-columns:minmax(0,1fr)}}
.detail-art-col{width:100%;max-width:440px}
.detail-title{font-family:var(--ff-disp);font-weight:800;font-size:40px;text-transform:uppercase;line-height:.95;margin:0}
.detail-byline{font-size:15px;color:var(--paper-2);margin:6px 0 20px}
.stat-card__val{font-family:var(--ff-mono);font-size:20px;color:var(--paper);margin-top:3px}
.tracklist{display:flex;flex-direction:column;gap:8px}
.track{display:flex;gap:14px;align-items:center;padding:10px 14px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);flex-wrap:nowrap}
.track__side{font-family:var(--ff-mono);font-size:12px;color:var(--paper-4);width:24px;flex:none}
.track__title{flex:1;color:var(--paper);font-size:14px}
.track__bar{width:100px;height:7px;flex:none}
.track__val{font-family:var(--ff-mono);font-size:12px;color:var(--paper-2);width:52px;text-align:right;flex:none}

/* --- action archetype (rest) --- */
.action-split{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:0}
.action-split__form{border-right:1px solid var(--line)}
.action-split__result{background:var(--surface)}
.venue-list{display:flex;flex-direction:column;gap:10px;margin-bottom:24px}
.action-controls{display:flex;gap:24px;align-items:flex-end;flex-wrap:wrap}
.field-grow{flex:1;min-width:200px}
.action-cost{border-top:1px dashed var(--line-2);margin-top:18px;padding-top:14px;font-size:13px}
.meter__track--delta{position:relative;height:8px;background:var(--bg)}
.meter__delta-before{position:absolute;inset:0;width:var(--before,0%);background:var(--fill);opacity:.4}
.meter__delta-after{position:absolute;inset:0;width:var(--after,0%);background:var(--fill)}

/* --- settings archetype --- */
.form-bar{justify-content:flex-end;padding:16px 24px;border-top:1px solid var(--line);background:var(--surface)}

/* --- wizard archetype --- */
.wizard-field{flex:1;min-width:150px}
.projection-row{border-bottom:1px solid var(--line);padding-bottom:9px}
.projection-val{font-family:var(--ff-mono);font-size:14px;color:var(--paper)}
.wizard-nav{margin-top:24px;border-top:1px solid var(--line);padding-top:18px}

/* --- shared partial bits (static; dynamic values stay inline in partials) --- */
.empty__body{font-size:13px;color:var(--paper-3);margin:6px 0 16px}
.form-inline{display:inline}
.opt-body{flex:1}

/* --- shell: band identity links to the manager dashboard (band switcher affordance) --- */
.band-link{display:flex;align-items:center;gap:14px;min-width:0;color:inherit}
.band-link:hover .band-name{color:var(--accent)}
.band-switch-ico{font-size:13px;color:var(--paper-3);margin-left:2px;vertical-align:2px}
.band-link:hover .band-switch-ico{color:var(--accent)}

/* --- status dashboard (A1 live page) --- */
/* D93 - the banner renders as a wide strip: full width, height-clamped, centre-cropped
   (object-fit keeps the middle; upload guidance says "ideal 2400×500, focus centred"). */
.band-banner{width:100%;max-width:100%;max-height:200px;object-fit:cover;object-position:center;border-radius:var(--r-md);border:1px solid var(--line)}
@media (max-width:640px){.band-banner{max-height:100px}}
/* D89 - band identity: uploaded square logo + public bio */
.band-logo{width:84px;height:84px;flex:none;border-radius:var(--r-md);border:1px solid var(--line-2);object-fit:cover;background:var(--surface-3)}
.band-logo--head{width:64px;height:64px}
.avatar--img{object-fit:cover;padding:0}
.bio-text{margin:0;white-space:pre-line;color:var(--paper-2);font-size:14px;line-height:1.6;overflow-wrap:anywhere}
.donate-options{display:flex;flex-direction:column;gap:10px;margin-top:8px}
.local-time-hint{color:var(--paper-3)} /* JS-appended viewer-local time next to UK-anchored times */
/* D79 - Getting Started onboarding checklist (ported verbatim from
   docs/design/backstage/dashboard-onboarding.html - Claude Design handoff) */
.onboard{max-width:1320px}                                   /* full content width; degrades below */
.onboard .onboard-head{gap:14px;flex-wrap:wrap}
.onboard-head__left{display:flex;align-items:baseline;gap:12px;min-width:0}
.onboard-count{font-family:var(--ff-body);font-weight:400;font-size:12px;letter-spacing:0;text-transform:none;color:var(--paper-3)}
.onboard-count .mono{color:var(--paper);font-size:13px}
.onboard-head__right{display:flex;align-items:center;gap:16px}
.onboard-bar{width:132px;height:7px;flex:none;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-pill);overflow:hidden}
.onboard-bar__fill{display:block;height:100%;width:var(--pct,0%);background:var(--accent);transition:width .6s cubic-bezier(.2,.7,.2,1)}
.onboard-dismiss{font-family:var(--ff-body);font-weight:400;font-size:12px;letter-spacing:0;text-transform:none;color:var(--paper-4);background:none;border:none;padding:2px 0;cursor:pointer}
.onboard-dismiss:hover{color:var(--paper-2);text-decoration:underline}
.onboard-steps{display:flex;flex-direction:column}
.onboard-step{display:grid;grid-template-columns:auto 1fr auto;grid-template-areas:"mark body aside";align-items:center;column-gap:16px;row-gap:11px;padding:15px 16px;border-bottom:1px solid var(--line)}
.onboard-step:last-child{border-bottom:none}
.onboard-step.is-done{background:color-mix(in srgb,var(--good),transparent 95%)}
.onboard-mark{grid-area:mark;width:26px;height:26px;flex:none;display:flex;align-items:center;justify-content:center}
.onboard-mark__glyph{font-family:var(--ff-mono);font-size:12px;line-height:1;font-weight:500}
.onboard-mark--pending{border:2px solid var(--paper-4);background:var(--surface)}
.onboard-mark--pending .onboard-mark__glyph{color:var(--paper-3)}
.onboard-mark--done{border:2px solid var(--accent);background:var(--accent)}
.onboard-mark--done .onboard-mark__glyph{color:var(--accent-ink);font-size:13px;font-weight:600}
.onboard-body{grid-area:body;min-width:0}
.onboard-title{font-family:var(--ff-disp);font-weight:600;font-size:17px;text-transform:uppercase;letter-spacing:.03em;line-height:1.1;color:var(--paper)}
.onboard-step.is-done .onboard-title{color:var(--paper-2)}
.onboard-blurb{font-size:13px;color:var(--paper-3);line-height:1.4;margin-top:3px}
.onboard-aside{grid-area:aside;display:flex;align-items:center;justify-content:flex-end;gap:14px}
.onboard-reward{font-family:var(--ff-mono);font-size:13px;color:var(--paper);background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-pill);padding:4px 12px;white-space:nowrap}
.onboard-reward--earned{color:var(--good);background:var(--good-bg);border-color:transparent}
.onboard-cta{white-space:nowrap}
.onboard-flash{margin:0 0 14px}
.onboard-flash .mono{color:var(--paper);font-weight:500}
.onboard-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:13px 16px;border-top:1px solid var(--line);background:var(--surface)}
.onboard-foot__label{font-family:var(--ff-disp);font-weight:600;font-size:14px;letter-spacing:.06em;text-transform:uppercase;color:var(--paper-3)}
.onboard-foot__reward{font-family:var(--ff-mono);font-size:14px;color:var(--paper)}
.onboard-foot.is-complete{background:color-mix(in srgb,var(--accent),transparent 88%);border-top:1px solid var(--accent);padding:16px}
.onboard-foot.is-complete .onboard-foot__label{color:var(--paper);font-size:16px}
.onboard-foot.is-complete .onboard-foot__reward{color:var(--accent);font-size:18px;font-weight:500}
.onboard-foot__note{flex-basis:100%;font-size:12px;color:var(--paper-3);margin-top:4px}
@keyframes onboard-pop{0%{transform:scale(.5);opacity:0}60%{transform:scale(1.18)}100%{transform:scale(1);opacity:1}}
@keyframes onboard-slide{0%{opacity:0;transform:translateY(-6px)}100%{opacity:1;transform:none}}
.onboard-anim .onboard-mark--pop{animation:onboard-pop .5s cubic-bezier(.2,.8,.2,1) both}
.onboard-anim .onboard-flash{animation:onboard-slide .45s ease both}
@media (max-width:600px){
  .onboard-step{grid-template-columns:auto 1fr;grid-template-areas:"mark body" ". aside"}
  .onboard-aside{justify-content:flex-start}
  .onboard-title{font-size:16px}
}

/* --- charts / catalogue (Batch 2) --- */
.art--thumb{width:40px;height:40px;flex:none}
.chart-last{font-size:11px;color:var(--paper-3)}

/* --- uploaded artwork (Batch 4, D32 - one file, CSS-sized) --- */
.art-img{display:block;width:100%;aspect-ratio:1/1;object-fit:cover;border-radius:var(--r-md);border:1px solid var(--line-2)}
.art-img--thumb{width:40px;height:40px;flex:none;border-radius:var(--r-sm)}
.art-img--sm{width:84px;height:84px;flex:none}
.field-hint{font-size:12px;color:var(--paper-4);margin-top:4px;display:block}
.field-hint.is-ok{color:var(--good)}
.field-hint.is-bad{color:var(--bad)}

/* --- auxiliary one-off pages (logout confirm / doc placeholders / status) --- */
.frame--narrow{max-width:520px;margin:60px auto}
.stage-body{padding:40px 24px;text-align:center}
.stage-title{font-family:var(--ff-disp);font-weight:800;font-size:30px;text-transform:uppercase;margin:0 0 8px}
.stage-lead{color:var(--paper-3);font-size:14px;margin:0 0 22px}
.doc-page{padding:40px 24px}
.doc-page--lg{padding:60px 24px}
.doc-title{font-family:var(--ff-disp);font-weight:800;font-size:38px;text-transform:uppercase}
.doc-title--bad{color:var(--bad)}
.doc-lead{color:var(--paper-2)}
.doc-meta{color:var(--paper-4);font-size:12px}
.ml-8{margin-left:8px}

/* ---------- responsive ---------- */
@media (max-width:860px){
  .nav-toggle{display:inline-flex}
  .app-nav{position:fixed;top:0;bottom:0;left:0;z-index:60;transform:translateX(-100%);transition:transform .2s ease}
  .app-nav.is-open{transform:none}
  .nav-scrim{display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:55}
  .nav-scrim.is-open{display:block}
  .hero h1{font-size:44px}
  .page-title{font-size:26px}
}
/* stacked two-pane / two-up grids: drop the vertical rule, restore a horizontal one */
@media (max-width:640px){
  .action-split__form{border-right:none;border-bottom:1px solid var(--line)}
  .grid--2{grid-template-columns:1fr}
}

/* ---------- Batch 9: genre-affinity heatmap (diverging RdBu around ×1.0) ---------- */
/* Cells carry their own diverging palette (fixed, not theme tokens - a heatmap legitimately
   owns its scale). RdBu is CVD- and print-safe. 2px surface gap between cells per marks spec. */
.heat{border-collapse:separate;border-spacing:2px;font-size:12px}
.heat th{font-weight:600;color:var(--paper-2);text-align:center;padding:4px 6px;white-space:nowrap;font-size:11px}
.heat th.heat__row{text-align:right;position:sticky;left:0;background:var(--bg);z-index:1;padding-right:10px}
.heat td{position:relative;width:46px;height:30px;text-align:center;font-family:var(--ff-mono);font-variant-numeric:tabular-nums}
.aff-1{background:#2166ac;color:#fff}          /* strong penalty */
.aff-2{background:#67a9cf;color:#08243a}       /* penalty */
.aff-3{background:#d1e5f0;color:#0b2230}       /* mild penalty */
.aff-4{background:#e4e6ea;color:#3a3d42}       /* neutral ×1.0 */
.aff-5{background:#fddbc7;color:#5a1a10}       /* mild boost */
.aff-6{background:#ef8a62;color:#3a1206}       /* boost */
.aff-7{background:#b2182b;color:#fff}          /* strong boost */
.heat-legend{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12px;color:var(--paper-2)}
.heat-legend .swatch{display:inline-flex;gap:2px}
.heat-legend .swatch span{width:22px;height:14px}
/* compact single-genre strip (genre pickers) */
.aff-strip{display:flex;gap:2px;flex-wrap:wrap;margin-top:8px}
.aff-strip .cell{min-width:52px;padding:5px 6px;font-size:11px;font-family:var(--ff-mono);text-align:center;line-height:1.3}
.aff-strip .cell b{display:block;font-family:var(--ff-body);font-weight:600;font-size:10px;letter-spacing:.02em}
.shop-genres{display:flex;gap:5px;flex-wrap:wrap}
.shop-genres .chip{font-size:11px;padding:2px 7px;border-color:var(--line);color:var(--paper-2)}

/* ============================================================================
   Rivalry dashboard card (Batch 19/D81) - Claude Design delivery, ported
   verbatim from docs/design/backstage/dashboard-rivalry.html (the .rival- block).
   ============================================================================ */
.rival-card{padding:0;overflow:hidden}
.rival-card--quiet{filter:saturate(.35);opacity:.9}

/* head */
.rival-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:13px 16px;border-bottom:1px solid var(--line)}
.rival-head__title{display:flex;align-items:center;gap:9px;font-family:var(--ff-disp);font-weight:700;font-size:15px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-2)}
.rival-head__title .rival-glove{font-size:14px}

/* streak chip */
.rival-streak{font-family:var(--ff-mono);font-size:11px;font-weight:500;letter-spacing:.05em;text-transform:uppercase;padding:3px 10px;border-radius:var(--r-pill);display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
.rival-streak--win{color:var(--up);background:var(--up-bg);box-shadow:0 0 0 1px color-mix(in srgb,var(--up),transparent 55%),0 0 14px color-mix(in srgb,var(--up),transparent 72%)}
.rival-streak--loss{color:var(--down);background:var(--down-bg)}

/* tale-of-the-tape matchup */
.rival-vs{padding:18px 16px 16px;text-align:center} /* D123 - the arena glow deleted */
.rival-vs__you{font-family:var(--ff-mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--paper-3)}
.rival-vs__you b{color:var(--paper-2);font-weight:500}
.rival-vs__rule{display:flex;align-items:center;gap:10px;margin:9px 0}
.rival-vs__rule::before,.rival-vs__rule::after{content:"";height:1px;flex:1;background:var(--line-2)}
.rival-vs__vs{font-family:var(--ff-disp);font-weight:800;font-size:12px;letter-spacing:.2em;color:var(--accent)}
.rival-vs__name{font-family:var(--ff-disp);font-weight:800;font-size:30px;line-height:.95;letter-spacing:.01em;text-transform:uppercase;color:var(--paper);display:inline-block}
a.rival-vs__name:hover{color:var(--accent)}

/* running record */
.rival-record{display:flex;align-items:center;justify-content:center;gap:0;padding:11px 16px;border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:var(--surface)}
.rival-record__cell{display:flex;align-items:baseline;gap:5px;padding:0 13px;position:relative}
.rival-record__cell+.rival-record__cell::before{content:"";position:absolute;left:0;top:2px;bottom:2px;width:1px;background:var(--line)}
.rival-record__k{font-family:var(--ff-disp);font-weight:700;font-size:12px;letter-spacing:.06em}
.rival-record__v{font-family:var(--ff-mono);font-size:16px;font-weight:500;color:var(--paper)}
.rival-record__cell--w .rival-record__k{color:var(--up)}
.rival-record__cell--l .rival-record__k{color:var(--down)}
.rival-record__cell--d .rival-record__k{color:var(--hold)}
.rival-record__since{font-family:var(--ff-body);font-size:11px;color:var(--paper-4);text-align:center;padding:0 16px 11px;background:var(--surface);margin-top:-1px}

/* last night's rounds */
.rival-rounds{padding:4px 0}
.rival-rounds__cap{font-family:var(--ff-disp);font-weight:600;font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4);padding:11px 16px 6px}
.rival-round{display:grid;grid-template-columns:22px 1fr auto;align-items:center;column-gap:11px;padding:8px 16px}
.rival-round__icon{font-size:15px;text-align:center;line-height:1}
.rival-round__label{font-size:11px;color:var(--paper-3);text-transform:uppercase;letter-spacing:.04em;line-height:1.2}
.rival-round__vals{font-family:var(--ff-mono);font-size:14px;margin-top:2px;color:var(--paper-3);display:flex;align-items:baseline;gap:7px}
.rival-round__vs{font-size:10px;color:var(--paper-4)}
.rival-round__mine{color:var(--paper-3)}
.rival-round--won .rival-round__mine{color:var(--paper);font-weight:500}
.rival-round--lost .rival-round__theirs{color:var(--paper);font-weight:500}
.rival-round__out{font-family:var(--ff-mono);font-size:10px;font-weight:500;letter-spacing:.06em;padding:3px 8px;border-radius:var(--r-pill);display:inline-flex;align-items:center;gap:4px;white-space:nowrap}
.rival-round__out b{font-size:11px}
.rival-round--won .rival-round__out{color:var(--up);background:var(--up-bg)}
.rival-round--lost .rival-round__out{color:var(--down);background:var(--down-bg)}
.rival-round--tied .rival-round__out{color:var(--hold);background:var(--surface-3)}

/* verdict bar */
.rival-verdict{display:flex;align-items:center;justify-content:center;gap:9px;padding:12px 16px;font-family:var(--ff-disp);font-weight:700;font-size:16px;letter-spacing:.03em;text-transform:uppercase;border-top:1px solid var(--line)}
.rival-verdict--won{color:var(--up);background:color-mix(in srgb,var(--up),transparent 88%);border-top-color:color-mix(in srgb,var(--up),transparent 55%)}
.rival-verdict--lost{color:var(--down);background:color-mix(in srgb,var(--down),transparent 90%);border-top-color:color-mix(in srgb,var(--down),transparent 60%)}
.rival-verdict--draw{color:var(--paper-2);background:var(--surface)}
.rival-verdict .mono{font-size:16px}

/* notice (awaiting / quiet) */
.rival-notice{padding:22px 18px;text-align:center;color:var(--paper-3);font-size:13px;line-height:1.5}
.rival-notice__glyph{font-size:22px;display:block;margin-bottom:8px;color:var(--paper-4)}
.rival-notice__stamp{display:block;margin-top:8px;font-family:var(--ff-mono);font-size:11px;color:var(--paper-4);letter-spacing:.05em}

/* footer */
.rival-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:9px 10px 9px 6px;border-top:1px solid var(--line);background:var(--surface)}
.rival-foot__end{font-family:var(--ff-disp);font-weight:600;text-transform:uppercase;letter-spacing:.05em;font-size:12px;color:var(--paper-4);background:none;border:none;padding:8px 10px;border-radius:var(--r-sm);cursor:pointer}
.rival-foot__end:hover{color:var(--down);background:var(--surface-3)}

/* pitch (no-rival) */
.rival-pitch{padding:18px 16px 16px}
.rival-pitch__lead{font-family:var(--ff-disp);font-weight:700;font-size:19px;line-height:1.05;text-transform:uppercase;color:var(--paper);letter-spacing:.01em}
.rival-pitch__body{font-size:13px;color:var(--paper-3);line-height:1.5;margin:8px 0 14px}
.rival-pitch__metrics{display:flex;gap:14px;justify-content:center;margin:0 0 15px;font-family:var(--ff-mono);font-size:11px;color:var(--paper-3)}
.rival-pitch__metrics span{display:flex;align-items:center;gap:5px}
.rival-pitch__form{display:flex;flex-direction:column;gap:9px}

/* one-shot flourish - optional garnish only */
@keyframes rival-pop{0%{transform:scale(.4);opacity:0}55%{transform:scale(1.25)}100%{transform:scale(1);opacity:1}}
@keyframes rival-rise{0%{opacity:0;transform:translateY(6px)}100%{opacity:1;transform:none}}
.rival-anim .rival-verdict{animation:rival-rise .5s ease both}
.rival-anim .rival-verdict .rival-glove{display:inline-block;animation:rival-pop .55s cubic-bezier(.2,.8,.2,1) .1s both}

@media (max-width:380px){
  .rival-vs__name{font-size:26px}
}

/* ============================================================================
   THE ROCKSTAR GAME AWARDS - season ceremony stage (Batch 21/D83).
   Ported verbatim from docs/design/awards-show.html (the .awards-* block; the
   export-only director strip is NOT ported). Rendered full-bleed at /awards/{n}.
   ============================================================================ */
/* D123 - KEPT gradients. The ceremony (D83) is not a page in the shell: it is a stage that
   takes the screen over once a season, and its vignette is authored theatre, not elevation. */
.awards-stage{
  position:relative;overflow:hidden;
  background:
    radial-gradient(120% 80% at 50% -10%, color-mix(in srgb,var(--accent),transparent 90%), transparent 60%),
    radial-gradient(100% 70% at 50% 120%, var(--surface), var(--bg) 70%),
    var(--bg);
  --awards-ease:cubic-bezier(.2,.75,.2,1);
}
.awards-screen{padding:clamp(28px,5vw,72px) clamp(20px,5vw,48px)}
.awards-stage:not(.is-live) .awards-screen{
  display:grid;place-items:center;text-align:center;
  border-bottom:1px solid var(--line);min-height:60vh;
}
.awards-stage:not(.is-live) .awards-title{min-height:78vh}
.awards-stage.is-live{min-height:100vh;display:grid}
.awards-stage.is-live .awards-screen{
  grid-area:1/1;display:grid;place-items:center;text-align:center;min-height:100vh;
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .55s var(--awards-ease);
}
.awards-stage.is-live .awards-screen.is-current{opacity:1;visibility:visible;pointer-events:auto}
.awards-inner{width:min(1080px,100%);margin:0 auto}
/* D125 - two hairlines flanking a diamond become the one rule they were always drawing. */
.awards-title__mark{display:flex;align-items:center;justify-content:center;margin-bottom:22px}
.awards-title__mark span{height:1px;width:min(254px,40vw);background:var(--line-2)}
.awards-kicker{font-family:var(--ff-mono);font-size:clamp(11px,1.4vw,13px);letter-spacing:.34em;text-transform:uppercase;color:var(--paper-3)}
.awards-title__h1{font-family:var(--ff-disp);font-weight:800;text-transform:uppercase;line-height:.9;letter-spacing:.01em;margin:16px 0 0;font-size:clamp(44px,9vw,120px);color:var(--paper)}
.awards-title__h1 .awards-em{color:var(--accent)}
.awards-title__sub{color:var(--paper-2);font-size:clamp(14px,1.6vw,17px);margin:20px auto 30px;max-width:44ch}
.awards-title__nojs{margin-top:8px;font-family:var(--ff-mono);font-size:12px;color:var(--paper-4);letter-spacing:.04em}
.is-live .awards-title__nojs{display:none}
.awards-act__icon{font-size:clamp(30px,4vw,46px);line-height:1}
/* D130 - .awards-act__eyebrow is deleted. It printed AwardMeta.Blurb in tracked caps above the
   category title and the same sentence again under it, so on a phone, where the two collapse
   into one column, the card said the same words twice eight lines apart. It was also the one
   kicker left in the product, which the craft floor bans outright: the heading carries its own
   weight and the blurb under it is the fact line. */
.awards-act__cat{font-family:var(--ff-disp);font-weight:800;text-transform:uppercase;line-height:.95;letter-spacing:.01em;font-size:clamp(30px,5.2vw,64px);margin:6px 0 0;color:var(--paper)}
.awards-act__blurb{color:var(--paper-3);font-size:clamp(13px,1.5vw,16px);margin:12px auto 0;max-width:46ch}
.awards-noms{display:flex;gap:clamp(14px,2vw,28px);justify-content:center;flex-wrap:wrap;margin:clamp(26px,4vh,48px) 0 0;transition:opacity .5s var(--awards-ease),transform .5s var(--awards-ease),filter .5s var(--awards-ease)}
.awards-nom{width:clamp(150px,22vw,210px);max-width:44vw}
.awards-art{position:relative;aspect-ratio:1;border-radius:var(--r-md);border:1px solid var(--line-2);background:var(--surface-3);overflow:hidden;display:grid;place-items:center}
.awards-art img{width:100%;height:100%;object-fit:cover;display:block}
.awards-art__ph{width:30%;height:30%;background:color-mix(in srgb,var(--accent),transparent 55%)}
.awards-nom__name{font-family:var(--ff-disp);font-weight:700;font-size:clamp(16px,1.9vw,20px);text-transform:uppercase;letter-spacing:.02em;line-height:1.05;margin-top:12px;color:var(--paper)}
.awards-nom__by{font-size:12.5px;color:var(--paper-3);margin-top:2px}
.awards-nom__stat{font-family:var(--ff-mono);font-size:13px;color:var(--paper-2);margin-top:8px}
.awards-nom__masked{color:var(--paper-4);letter-spacing:.34em}
.awards-nom__real{display:none}
.awards-runners{display:none;font-family:var(--ff-mono);font-size:11px;letter-spacing:.24em;text-transform:uppercase;color:var(--paper-4);margin-top:clamp(20px,3vh,30px)}
.awards-runlist{display:none;width:min(440px,92%);margin:clamp(16px,2.5vh,24px) auto 0;border-top:1px solid var(--line);text-align:left}
.awards-runlist__cap{font-family:var(--ff-mono);font-size:10px;letter-spacing:.24em;text-transform:uppercase;color:var(--paper-4);padding:11px 2px 5px;text-align:center}
.awards-runrow{display:flex;justify-content:space-between;align-items:baseline;gap:14px;padding:8px 2px;border-bottom:1px solid var(--line)}
.awards-runrow:last-child{border-bottom:none}
.awards-runrow__name{font-family:var(--ff-disp);font-weight:600;font-size:15px;text-transform:uppercase;letter-spacing:.02em;color:var(--paper-2);line-height:1.1}
.awards-runrow__name small{font-family:var(--ff-body);font-weight:400;font-size:12px;text-transform:none;letter-spacing:0;color:var(--paper-4)}
.awards-runrow__stat{font-family:var(--ff-mono);font-size:14px;color:var(--paper-3);white-space:nowrap}
.awards-nom__rank{font-family:var(--ff-mono);font-size:11px;color:var(--paper-4);letter-spacing:.1em;text-transform:uppercase}
.awards-payoff{display:none;width:min(760px,100%);margin:clamp(20px,3vh,34px) auto 0}
.awards-payoff__tag{display:inline-flex;align-items:center;font-family:var(--ff-disp);font-weight:700;font-size:13px;letter-spacing:.24em;text-transform:uppercase;color:var(--accent)}
.awards-payoff__art{width:clamp(148px,22vh,236px);aspect-ratio:1;margin:16px auto 0;box-shadow:var(--shadow-2),0 0 0 1px var(--line-2),0 0 60px color-mix(in srgb,var(--accent),transparent 74%)}
.awards-payoff__name{font-family:var(--ff-disp);font-weight:800;text-transform:uppercase;line-height:.92;letter-spacing:.01em;font-size:clamp(38px,7vw,86px);margin:20px 0 0;color:var(--paper)}
a.awards-payoff__name{text-decoration:none}
a.awards-payoff__name:hover{color:var(--accent)}
.awards-payoff__by{color:var(--paper-2);font-size:clamp(13px,1.6vw,17px);margin-top:8px}
.awards-payoff__by b{color:var(--paper);font-weight:600}
.awards-payoff__stat{font-family:var(--ff-mono);font-weight:500;font-size:clamp(16px,2.2vw,26px);color:var(--accent);margin-top:14px}
.awards-payoff__stat small{color:var(--paper-3);font-weight:400;font-size:.62em;letter-spacing:.06em;text-transform:uppercase}
.awards-act{position:relative}
.awards-act[data-phase="crowned"] .awards-act__blurb{opacity:.5}
.awards-act[data-phase="crowned"] .awards-payoff{display:block;animation:awards-fade .5s var(--awards-ease) both}
.awards-act[data-phase="crowned"] .awards-payoff__art{animation:awards-bloom .7s var(--awards-ease) both}
.awards-act[data-phase="crowned"] .awards-runners{display:block;animation:awards-fade .5s var(--awards-ease) .3s both}
.awards-act[data-phase="crowned"] .awards-noms{display:none}
.awards-act[data-phase="crowned"] .awards-runlist{display:block;animation:awards-fade .5s var(--awards-ease) .34s both}
.awards-act.is-climax .awards-payoff__name{font-size:clamp(44px,9vw,112px)}
.awards-act.is-climax[data-phase="crowned"] .awards-payoff__art{box-shadow:var(--shadow-2),0 0 0 2px var(--accent),0 0 90px color-mix(in srgb,var(--accent),transparent 60%)}
.is-live .awards-screen.is-current .awards-nom{animation:awards-rise .6s var(--awards-ease) both}
.is-live .awards-screen.is-current .awards-nom:nth-child(1){animation-delay:.05s}
.is-live .awards-screen.is-current .awards-nom:nth-child(2){animation-delay:.18s}
.is-live .awards-screen.is-current .awards-nom:nth-child(3){animation-delay:.31s}
.awards-finale__h{font-family:var(--ff-disp);font-weight:800;text-transform:uppercase;letter-spacing:.02em;line-height:.95;font-size:clamp(30px,5vw,60px);margin:0}
.awards-finale__k{font-family:var(--ff-mono);font-size:12px;letter-spacing:.3em;text-transform:uppercase;color:var(--paper-3);margin-bottom:12px}
.awards-board{width:min(760px,100%);margin:clamp(24px,4vh,40px) auto 0;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2);box-shadow:var(--shadow-1);overflow:hidden;text-align:left}
.awards-board__row{display:grid;grid-template-columns:26px 1fr auto;align-items:center;gap:14px;padding:14px 18px;border-bottom:1px solid var(--line)}
.awards-board__row:last-child{border-bottom:none}
.awards-board__row--top{background:color-mix(in srgb,var(--accent),transparent 90%)}
.awards-board__icon{font-size:17px;text-align:center}
.awards-board__cat{font-family:var(--ff-mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-3)}
.awards-board__win{font-family:var(--ff-disp);font-weight:700;font-size:clamp(17px,2vw,22px);text-transform:uppercase;letter-spacing:.01em;color:var(--paper);line-height:1.05;margin-top:2px}
.awards-board__win a{color:inherit}
.awards-board__win a:hover{color:var(--accent)}
.awards-board__by{color:var(--paper-3);font-weight:400;font-size:13px;text-transform:none;letter-spacing:0}
.awards-board__stat{font-family:var(--ff-mono);font-size:14px;color:var(--paper-2);text-align:right;white-space:nowrap}
.awards-finale__actions{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:clamp(22px,4vh,34px)}
.awards-controls{display:flex;gap:10px;justify-content:center;align-items:center;flex-wrap:wrap;margin-top:clamp(26px,4vh,40px)}
.awards-skip{background:none;border:none;font-family:var(--ff-mono);font-size:12px;letter-spacing:.06em;color:var(--paper-4);cursor:pointer;padding:8px 10px}
.awards-skip:hover{color:var(--paper-2);text-decoration:underline}
.awards-auto{display:inline-flex;align-items:center;gap:7px;font-family:var(--ff-mono);font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--paper-4);cursor:pointer;user-select:none}
.awards-auto input{accent-color:var(--accent);width:14px;height:14px}
.awards-progress{position:absolute;top:0;left:0;height:3px;background:var(--accent);width:var(--p,0%);transition:width .5s var(--awards-ease);z-index:4}
.is-live .awards-progress{display:block}
.awards-stage:not(.is-live) .awards-progress{display:none}
.awards-confetti{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:3}
@keyframes awards-rise{from{opacity:0;transform:translateY(26px)}to{opacity:1;transform:none}}
@keyframes awards-bloom{from{transform:scale(.72);opacity:0}to{transform:scale(1);opacity:1}}
@keyframes awards-fade{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .awards-stage *,.awards-stage *::before,.awards-stage *::after{animation:none!important}
}
.awards-stage.is-calm .awards-nom,
.awards-stage.is-calm .awards-payoff,
.awards-stage.is-calm .awards-payoff__art,
.awards-stage.is-calm .awards-runner{animation:none!important}
@media (max-width:640px){
  .awards-noms{gap:14px}
  .awards-nom{width:44vw}
  .awards-payoff{width:94%}
  .awards-board__row{grid-template-columns:22px 1fr;grid-template-areas:"i c" ". w" ". s";row-gap:3px}
  .awards-board__icon{grid-area:i}.awards-board__cat{grid-area:c}
  .awards-board__win{grid-area:w}.awards-board__stat{grid-area:s;text-align:left}
}
/* Light ceremony (Claude Design §2b) - the token stage holds; only the payoff spotlight
   needs help (the accent glow reads faint on paper) + lift the big name off the bright ground. */
:root[data-theme="light"] .awards-payoff__art{
  box-shadow:0 10px 30px rgba(52,42,22,.16),0 0 0 2px var(--accent),0 0 46px color-mix(in srgb,var(--accent),transparent 55%)}
:root[data-theme="light"] .awards-act.is-climax[data-phase="crowned"] .awards-payoff__art{
  box-shadow:0 12px 36px rgba(52,42,22,.18),0 0 0 2px var(--accent),0 0 70px color-mix(in srgb,var(--accent),transparent 45%)}
:root[data-theme="light"] .awards-payoff__name{text-shadow:0 1px 0 rgba(255,255,255,.5)}

/* ==== MANAGER TROPHY CABINET - public manager page (Batch 23/D85). Ported verbatim
   from docs/design/manager-cabinet.html (the .cabinet-* block). Rendered in the normal
   app layout at /managers/{id}. Optional entrance garnish gated behind .cabinet-anim
   (app.js adds it). ==== */
.cabinet{max-width:920px;margin:0 auto;display:flex;flex-direction:column;gap:clamp(20px,3vw,28px)}

/* --- header --------------------------------------------------------------- */
.cabinet-head{display:flex;align-items:center;gap:clamp(16px,3vw,26px);flex-wrap:wrap}
.cabinet-mono{width:66px;height:66px;flex:none;background:var(--surface-3);border:1px solid var(--line-2);display:grid;place-items:center} /* D123 - gradient deleted. D125 - unrotated. */
.cabinet-mono span{font-family:var(--ff-disp);font-weight:800;font-size:26px;text-transform:uppercase;color:var(--accent);line-height:1}
.cabinet-id{min-width:0}
.cabinet-id__handle{font-family:var(--ff-disp);font-weight:800;font-size:clamp(30px,5vw,44px);line-height:.95;text-transform:uppercase;letter-spacing:.01em;color:var(--paper);margin:0}
.cabinet-id__since{font-family:var(--ff-mono);font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-3);margin-top:6px}
.cabinet-stats{display:flex;flex-wrap:wrap;gap:10px 22px;margin-left:auto;padding-left:8px}
.cabinet-stat{display:flex;flex-direction:column;gap:2px;text-align:right}
.cabinet-stat__v{font-family:var(--ff-mono);font-size:22px;font-weight:500;color:var(--paper);line-height:1}
.cabinet-stat__k{font-family:var(--ff-mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4)}

/* --- trophy shelf --------------------------------------------------------- */
.cabinet-season{display:flex;align-items:baseline;gap:11px;padding:16px 16px 9px}
.cabinet-season:first-child{padding-top:4px}
.cabinet-season__n{font-family:var(--ff-disp);font-weight:700;font-size:15px;letter-spacing:.06em;text-transform:uppercase;color:var(--paper-2)}
.cabinet-season__name{font-size:12.5px;color:var(--paper-3);font-style:italic}
.cabinet-season__rule{flex:1;height:1px;background:var(--line);align-self:center}

.cabinet-trophy{display:grid;grid-template-columns:34px 1fr auto;align-items:center;gap:14px;padding:12px 16px;border-top:1px solid var(--line)}
/* D125 - the rotated square drawn behind the drawn icon is deleted. The icon is the mark;
   a plaque behind it was a second one. The pinnacle keeps its row tint and now takes the
   accent in the icon itself. */
.cabinet-trophy__icon{width:34px;height:34px;display:grid;place-items:center;font-size:18px;line-height:1}
.cabinet-trophy__cat{font-family:var(--ff-mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-3)}
.cabinet-trophy__win{font-family:var(--ff-disp);font-weight:700;font-size:clamp(17px,2vw,21px);text-transform:uppercase;letter-spacing:.01em;color:var(--paper);line-height:1.05;margin-top:2px}
.cabinet-trophy__win a{color:inherit}
.cabinet-trophy__win a:hover{color:var(--accent)}
.cabinet-trophy__subj{color:var(--paper-3);font-weight:400;font-size:14px;text-transform:none;letter-spacing:0}
.cabinet-trophy__stat{font-family:var(--ff-mono);font-size:14px;color:var(--paper-2);text-align:right;white-space:nowrap}
/* pinnacle: Artist of the Year echoes the payoff accent */
.cabinet-trophy--top{background:color-mix(in srgb,var(--accent),transparent 91%)}
.cabinet-trophy--top .cabinet-trophy__icon{color:var(--accent)}
.cabinet-trophy--top .cabinet-trophy__stat{color:var(--accent)}

/* --- band roster ---------------------------------------------------------- */
.cabinet-roster{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}
.cabinet-band{display:flex;align-items:center;gap:12px;padding:14px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-3);text-decoration:none;transition:border-color .15s,transform .15s}
.cabinet-band:hover{border-color:var(--paper-4)}
.cabinet-band__name{display:block;font-family:var(--ff-disp);font-weight:700;font-size:17px;text-transform:uppercase;letter-spacing:.01em;color:var(--paper);line-height:1.05}
.cabinet-band__stat{display:block;font-family:var(--ff-mono);font-size:12px;color:var(--paper-3);margin-top:3px}

/* --- also nominated (quiet) ----------------------------------------------- */
.cabinet-nom{display:grid;grid-template-columns:auto 1fr auto auto;align-items:center;gap:12px;padding:10px 16px;border-top:1px solid var(--line);font-size:13px}
.cabinet-nom:first-child{border-top:none}
.cabinet-nom__meta{font-family:var(--ff-mono);font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--paper-4);white-space:nowrap}
.cabinet-nom__who{color:var(--paper-2);min-width:0}
.cabinet-nom__who b{font-family:var(--ff-disp);font-weight:600;font-size:15px;text-transform:uppercase;letter-spacing:.02em;color:var(--paper-2)}
.cabinet-nom__rank{font-family:var(--ff-disp);font-weight:700;font-size:12px;text-transform:uppercase;letter-spacing:.06em;color:var(--paper-3)}
.cabinet-nom__stat{font-family:var(--ff-mono);font-size:12.5px;color:var(--paper-3);text-align:right;white-space:nowrap}

/* --- empty state ---------------------------------------------------------- */
.cabinet-empty{text-align:center;padding:34px 20px}
.cabinet-empty__lead{font-family:var(--ff-disp);font-weight:700;font-size:19px;text-transform:uppercase;letter-spacing:.02em;color:var(--paper-2)}
.cabinet-empty__sub{color:var(--paper-3);font-size:13.5px;margin:8px auto 16px;max-width:42ch}

/* --- optional garnish (only with .cabinet-anim; JS adds it) ---------------- */
@keyframes cabinet-rise{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.cabinet-anim .cabinet-trophy,.cabinet-anim .cabinet-band,.cabinet-anim .cabinet-nom{animation:cabinet-rise .5s cubic-bezier(.2,.75,.2,1) both}
.cabinet-anim .cabinet-band{transition:border-color .15s,transform .15s}
.cabinet-anim .cabinet-band:hover{transform:translateY(-2px)}
.cabinet-anim .cabinet-trophy:hover{background:color-mix(in srgb,var(--surface-3),transparent 40%)}
.cabinet-anim .cabinet-trophy--top:hover{background:color-mix(in srgb,var(--accent),transparent 86%)}

@media (prefers-reduced-motion:reduce){
  .cabinet-anim .cabinet-trophy,.cabinet-anim .cabinet-band,.cabinet-anim .cabinet-nom{animation:none}
  .cabinet-anim .cabinet-band:hover{transform:none}
}

/* --- responsive ----------------------------------------------------------- */
@media (max-width:560px){
  .cabinet-stats{margin-left:0;width:100%;justify-content:space-between;gap:10px}
  .cabinet-stat{text-align:left}
  .cabinet-trophy{grid-template-columns:34px 1fr;grid-template-areas:"i m" ". s";row-gap:7px}
  .cabinet-trophy__icon{grid-area:i}
  .cabinet-trophy__stat{grid-area:s;text-align:left}
  .cabinet-nom{grid-template-columns:1fr;grid-template-areas:"w" "m" "s";row-gap:3px}
  .cabinet-nom__who{grid-area:w}
  .cabinet-nom__meta{grid-area:m}.cabinet-nom__stat{grid-area:s;text-align:left}
}

/* ==== THE ROCKSTAR GAME - logo (D114 "The stub and one line", 2026-09-06). Carl's pick once he
   had the board in front of him (docs/design/backstage/logo-rework.html, candidate A); the
   whole-ticket candidate C was built first that day and replaced by this. The red RG stub with its
   two punch-outs (the favicon) and the name in ONE face at ONE size in ONE colour: Barlow
   Condensed 800, paper. No tracked micro line, no coloured letter, no body panel. Size a lockup by
   setting font-size on .logo-mark; set --logo-bg to the colour BEHIND the mark so the punch-outs
   read as holes. ==== */
/* D123 - KEPT radii. The stub's .15em corner and the two 50% punch-outs are the drawn shape of
   the brand mark (D114), not furniture: they are the favicon and the app icon, they are the same
   geometry on a public page and in the shell, and they are relative to the mark's own font-size
   rather than to the radius scale. Squaring them would redraw the logo, which is not a token
   decision. */
.logo-mark{--logo-bg:var(--bg);display:inline-flex;align-items:center;gap:.7em;font-size:15px;line-height:1;white-space:nowrap}
.logo-mark__stub{position:relative;display:inline-grid;place-items:center;width:2.2em;height:2.2em;flex:none;background:var(--accent);color:var(--accent-ink);border-radius:.15em;font-family:var(--ff-disp);font-weight:800;font-size:1em;line-height:.8}
.logo-mark__stub::before,.logo-mark__stub::after{content:"";position:absolute;top:50%;transform:translateY(-50%);width:.26em;height:.26em;border-radius:50%;background:var(--logo-bg)}
.logo-mark__stub::before{left:-.13em}.logo-mark__stub::after{right:-.13em}
.logo-mark__name{font-family:var(--ff-disp);font-weight:800;font-size:1.55em;text-transform:uppercase;letter-spacing:.02em;color:var(--paper)}
.logo-mark--sm{font-size:13px}
.brand-link:hover .logo-mark__stub{background:var(--accent-hover)}

/* --- app integration: --logo-bg per context ---------------------------------- */
.brand{--logo-bg:var(--surface)}                    /* the sidebar sits on --surface */
.brand .logo-mark{--logo-bg:var(--surface);font-size:13px}
.public-nav{--logo-bg:var(--bg)}                    /* public/auth headers sit on --bg */
.public-nav .logo-mark,.home-nav .logo-mark,.home-foot .logo-mark{--logo-bg:var(--bg)}

/* ===================================================================
   SEASON COMPONENTS - lift verbatim into site.css (D96)
   =================================================================== */

/* ---- the homepage season section (logged-out landing) ---- */
.season-sec{max-width:1180px;margin:0 auto}
/* D113a - the eyebrow is gone and the ticket lost its costume (gradient, shadow, radius, the
   punched perforations); the stub-and-body structure stays because it carries the facts. */
.season-ticket{position:relative;display:grid;grid-template-columns:230px 1fr;background:var(--surface-2);border:1px solid var(--line-2);border-top:2px solid var(--paper)}

.season-ticket__stub{padding:26px 24px 22px;display:flex;flex-direction:column;justify-content:space-between;gap:14px;min-width:0}

/* D112 - the numeral was clamp(84px,10vw,124px): the largest red object on the page, outranking
   both signup buttons, and it pointed at nothing. 72px keeps the ticket's character without the
   shout. The name is the block's h2 now, so it takes an explicit margin. */
.season-ticket__num{font-family:var(--ff-disp);font-weight:800;font-size:clamp(56px,7vw,72px);line-height:.82;color:var(--paper);letter-spacing:-.01em}
.season-ticket__name{font-family:var(--ff-head,var(--ff-disp));font-weight:400;font-size:22px;text-transform:uppercase;letter-spacing:.01em;line-height:1.05;margin:0}

.season-ticket__body{position:relative;border-left:1px solid var(--line-2);padding:26px 28px 22px;display:flex;flex-direction:column;gap:18px;min-width:0}
.season-fields{display:flex;gap:36px;flex-wrap:wrap}
.season-field{min-width:0}
.season-field__k{font-family:var(--ff-mono);font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--paper-2);margin:0 0 4px}
.season-field__v{font-family:var(--ff-disp);font-weight:700;font-size:26px;text-transform:uppercase;line-height:1;margin:0}
.season-field__v small{display:block;font-family:var(--ff-mono);font-weight:400;font-size:11px;text-transform:none;letter-spacing:0;color:var(--paper-3);margin-top:4px}
.season-chip{align-self:flex-start;font-family:var(--ff-disp);font-size:14px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--paper);border:2px solid var(--paper);padding:6px 10px 5px;line-height:1}
.season-chip--quiet{color:var(--paper-2);background:var(--surface-3);border-color:var(--line-2)}
.season-chip--live{color:var(--accent-ink);background:var(--accent);border-color:var(--accent)}

/* opened -> ends progress meter */
.season-meter{margin-top:auto}
.season-meter__track{height:6px;background:var(--line);overflow:hidden}
.season-meter__fill{height:100%;width:var(--pct,0%);background:var(--paper)}
.season-meter__ends{display:flex;justify-content:space-between;font-family:var(--ff-mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-3);margin-top:6px}

/* what-seasons-are: explainer + the three passes + CTA */
.season-below{display:grid;grid-template-columns:minmax(260px,34ch) 1fr;gap:28px;align-items:start;margin-top:26px}
.season-lead{color:var(--paper-2);font-size:15px;line-height:1.65;margin:0}
.season-lead b{color:var(--paper)}
.season-points{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;min-width:0}
/* D113a - the points were three emoji cards; now ruled entries. */
.season-point{border-top:1px solid var(--line-2);padding:12px 0 0}
.season-point__t{font-family:var(--ff-disp);font-weight:800;font-size:18px;text-transform:uppercase;letter-spacing:.02em;margin:0 0 4px;line-height:1}
.season-point__d{font-size:14px;color:var(--paper-2);line-height:1.5;margin:0}
/* D112 - the Awards link wears the system's own secondary button now. Its hand-rolled accent fill
   was a second primary action on the page, pointing away from signup. */
.season-cta{margin-top:22px}

@media (max-width:680px){
  .season-ticket{grid-template-columns:1fr}
  .season-ticket__stub{flex-direction:row;align-items:end;justify-content:flex-start;gap:16px;padding-bottom:18px}
  .season-ticket__num{font-size:56px}
  .season-ticket__body{border-left:0;border-top:1px solid var(--line-2)}
  .season-fields{gap:22px}
  .season-below{grid-template-columns:1fr}
}

/* ---- the dashboard season strip (Status page band) ---- */
.season-strip{position:relative;display:flex;align-items:center;gap:14px;flex-wrap:wrap;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-1);padding:12px 18px 12px 24px;overflow:hidden}
/* D123 - the punched ticket notch that used to hang off this strip is gone: a costume on a
   world with no boxes to punch. The strip is a paper rule now (see The Galley, below). */
.season-strip__name{font-family:var(--ff-disp);font-weight:800;font-size:19px;text-transform:uppercase;letter-spacing:.04em}
.season-strip__name em{font-style:normal;color:var(--accent)}
.season-strip__fact{font-family:var(--ff-mono);font-size:11.5px;color:var(--paper-3)}
.season-strip__fact b{color:var(--paper-2);font-weight:600}
.season-strip__dot{color:var(--paper-4)}
.season-strip__spacer{flex:1}
.season-strip__link{font-family:var(--ff-mono);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--accent);text-decoration:none;white-space:nowrap}
.season-strip__link:hover{text-decoration:underline}
.season-strip .season-chip{font-size:10.5px;padding:4px 11px}
@media (max-width:560px){.season-strip__spacer{display:none}.season-strip{gap:8px 14px}}
/* =================== end SEASON COMPONENTS =================== */

/* ===================================================================
   BATCH 34 COMPONENTS - lift verbatim into site.css (D97)
   =================================================================== */

/* ---- Search v2 (search-) - grouped bands + releases results ---- */
.search-groups{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:16px;align-items:start}
.search-group__cap{font-family:var(--ff-mono);font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--paper-3);margin:0 0 10px;display:flex;align-items:center;gap:10px}
.search-group__cap b{color:var(--paper-2)}
.search-group__cap::after{content:"";flex:1;height:1px;background:var(--line)}
.search-list{display:flex;flex-direction:column;gap:8px}
.search-hit{display:flex;align-items:center;gap:12px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);padding:10px 14px;box-shadow:var(--shadow-1);text-decoration:none;color:var(--paper);min-width:0}
.search-hit:hover{border-color:var(--line-2);background:var(--surface-3)}
.search-hit__art{width:42px;height:42px;flex:none;border-radius:var(--r-sm);border:1px solid var(--line-2);object-fit:cover;background:var(--surface-3)}
.search-hit__ph{width:42px;height:42px;flex:none;border-radius:var(--r-sm);border:1px solid var(--line-2);background:var(--surface-3);display:flex;align-items:center;justify-content:center;font-family:var(--ff-disp);font-weight:700;font-size:16px;color:var(--paper-3);text-transform:uppercase}
.search-hit__main{min-width:0;flex:1}
.search-hit__name{font-family:var(--ff-disp);font-weight:700;font-size:17px;text-transform:uppercase;letter-spacing:.02em;line-height:1.1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.search-hit__sub{font-family:var(--ff-mono);font-size:11px;color:var(--paper-3);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.search-hit__meta{font-family:var(--ff-mono);font-size:11px;color:var(--paper-2);text-align:right;flex:none}
.search-hit__meta small{display:block;color:var(--paper-4)}
.search-empty{padding:26px 18px;text-align:center;color:var(--paper-3);background:var(--surface-2);border:1px dashed var(--line-2);border-radius:var(--r-md)}
.search-empty b{color:var(--paper-2)}

/* ---- Compare v2 (cmp-) - the head-to-head header + verdict ---- */
.cmp-head{display:grid;grid-template-columns:1fr auto 1fr;gap:18px;align-items:center;padding:22px 0;margin-bottom:20px} /* D123 - gradient + box deleted; the rule is in The Galley */
.cmp-side{display:flex;align-items:center;gap:14px;min-width:0}
.cmp-side--them{flex-direction:row-reverse;text-align:right}
.cmp-side__logo{width:64px;height:64px;flex:none;border-radius:var(--r-md);border:1px solid var(--line-2);object-fit:cover;background:var(--surface)}
.cmp-side__ph{width:64px;height:64px;flex:none;border-radius:var(--r-md);border:1px solid var(--line-2);background:var(--surface);display:flex;align-items:center;justify-content:center;font-family:var(--ff-disp);font-weight:800;font-size:24px;color:var(--paper-3);text-transform:uppercase}
.cmp-side__who{min-width:0}
.cmp-side__tag{font-family:var(--ff-mono);font-size:10px;letter-spacing:.24em;text-transform:uppercase;color:var(--paper-3);margin:0 0 3px}
.cmp-side__name{font-family:var(--ff-disp);font-weight:800;font-size:24px;text-transform:uppercase;line-height:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cmp-verdict{text-align:center}
.cmp-verdict__vs{font-family:var(--ff-mono);font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--paper-4)}
.cmp-verdict__score{font-family:var(--ff-disp);font-weight:800;font-size:44px;line-height:.95;color:var(--accent);white-space:nowrap}
.cmp-verdict__line{font-family:var(--ff-mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--paper-2);margin-top:4px}
.cmp-row-win{box-shadow:inset 3px 0 0 var(--up)}
.cmp-row-loss{box-shadow:inset 3px 0 0 var(--down)}
@media (max-width:640px){
  .cmp-head{grid-template-columns:1fr;gap:12px;padding:18px}
  .cmp-side--them{flex-direction:row;text-align:left}
  .cmp-verdict{order:3;border-top:1px dashed var(--line-2);padding-top:12px}
}

/* ---- World Tastes country hover card (mkt-) - CSS-only ---- */
.mkt-th{position:relative;cursor:help;outline:none}
.mkt-th:hover,.mkt-th:focus-visible,.mkt-th:focus-within{background:var(--surface-3)}
.mkt-card{position:absolute;top:100%;left:50%;transform:translateX(-50%);z-index:30;min-width:225px;background:var(--surface-3);border:1px solid var(--line-2);border-radius:var(--r-md);box-shadow:var(--shadow-2);padding:12px 14px;text-align:left;display:none;font-weight:400;text-transform:none}
.mkt-th:hover .mkt-card,.mkt-th:focus-visible .mkt-card,.mkt-th:focus-within .mkt-card{display:block}
.mkt-th:last-child .mkt-card,.mkt-th:nth-last-child(2) .mkt-card{left:auto;right:0;transform:none}
.mkt-card__name{font-family:var(--ff-disp);font-weight:700;font-size:17px;text-transform:uppercase;letter-spacing:.03em;margin:0 0 8px}
.mkt-card__row{display:flex;justify-content:space-between;gap:16px;font-family:var(--ff-mono);font-size:11px;color:var(--paper-3);padding:3px 0}
.mkt-card__row b{color:var(--paper);font-weight:600}
.mkt-card__tastes{border-top:1px dashed var(--line-2);margin-top:8px;padding-top:8px;font-size:11.5px;color:var(--paper-2);line-height:1.5}
.mkt-card__tastes b{color:var(--paper)}
/* =================== end BATCH 34 COMPONENTS =================== */

/* ===================================================================
   BATCH 36 COMPONENTS (D99) - lifted verbatim from
   docs/design/backstage/batch36-panels.html (the reviewed artifact)
   =================================================================== */

/* ---- Feed comments (cmt-) - the count pill + thread + form ---- */
.cmt-count{white-space:nowrap}
.cmt-count.has-comments{border-color:var(--line-2);color:var(--paper)}
/* comment-notification text is the only click target on its row (no hype/comment buttons) - underline it */
.feed-note-link{text-decoration:underline;text-decoration-color:var(--paper-3);text-underline-offset:2px}
.feed-note-link:hover{text-decoration-color:var(--accent)}
.cmt-thread{border-left:2px solid var(--line-2);margin-left:6px;padding-left:16px;display:flex;flex-direction:column;gap:0}
.cmt-row{position:relative;display:flex;justify-content:space-between;gap:14px;padding:11px 2px;border-bottom:1px dashed var(--line)}
.cmt-row:last-child{border-bottom:none}
.cmt-row::before{content:"";position:absolute;left:-20px;top:20px;width:8px;height:2px;background:var(--line-2)}
.cmt-row__who{font-size:13px}
.cmt-row__who a{font-family:var(--ff-disp);font-weight:700;font-size:15px;text-transform:uppercase;letter-spacing:.02em;text-decoration:none}
.cmt-row__when{font-family:var(--ff-mono);font-size:10.5px;color:var(--paper-4);margin-left:8px}
.cmt-row__text{color:var(--paper-2);font-size:13px;margin-top:3px;overflow-wrap:anywhere}
.cmt-row__del{flex:none;align-self:flex-start;background:none;border:none;color:var(--paper-4);font-size:13px;cursor:pointer;padding:2px 6px;border-radius:var(--r-sm)}
.cmt-row__del:hover{color:var(--bad);background:var(--surface-2)}
.cmt-empty{color:var(--paper-3);font-size:13px;padding:14px 2px 4px}
.cmt-form{margin-top:14px}
.cmt-input{width:100%;background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-sm);color:var(--paper);font-family:var(--ff-body);font-size:14px;padding:10px 12px;resize:vertical;min-height:64px}
.cmt-input:focus{outline:none;border-color:var(--paper-3)}
.cmt-form__bar{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-top:8px}
.cmt-form__count{font-family:var(--ff-mono);font-size:11px;color:var(--paper-4)}

/* ---- Genre waves (wave-) - banner, dashboard strip, heat badge, admin ---- */
.wave-banner{position:relative;overflow:hidden;display:flex;align-items:center;gap:16px;padding:14px 18px} /* D123 - gradient + box + left rail deleted; the wave rule is in The Galley */
.wave-banner__emoji{font-size:22px;flex:none}
.wave-banner__main{min-width:0;flex:1}
.wave-banner__head{font-family:var(--ff-disp);font-weight:800;font-size:20px;text-transform:uppercase;letter-spacing:.02em;line-height:1.05}
.wave-banner__head b{color:var(--wave)}
.wave-banner__sub{font-size:13px;color:var(--paper-2);margin-top:2px}
.wave-banner__sub .mono{font-family:var(--ff-mono);color:var(--paper)}
.wave-nights{display:flex;gap:4px;align-items:center;flex:none}
.wave-nights i{width:9px;height:9px;background:var(--wave);opacity:.95}
.wave-nights i.spent{background:var(--line-2);opacity:.7}
.wave-nights__label{font-family:var(--ff-mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-3);margin-left:6px}
.wave-strip{display:flex;align-items:center;gap:12px;padding:10px 14px;margin-bottom:20px} /* D123 - the coloured left rail is deleted, not overridden: it rotates to a top rule (The Galley). */
.wave-strip__text{flex:1;min-width:0;font-size:13px;color:var(--paper-2)}
.wave-strip__text b{color:var(--paper)}
.wave-strip__text .mono{font-family:var(--ff-mono);color:var(--paper)}
.heat__cell--wave{position:relative;box-shadow:inset 0 0 0 2px var(--wave)}
/* D123 - the wave marker is the drawn icon, written into the cell by World/Tastes.cshtml.
   It sits INSIDE the cell rather than hanging off its corner (the old emoji overlapped its
   neighbour and needed a drop-shadow to survive it) and takes the cell's own ink, which is
   chosen for contrast against every step of the diverging scale. */
.heat__wavemark{position:absolute;top:2px;right:3px;line-height:0;opacity:.9}
.heat__wavemark .ic{width:10px;height:10px;stroke-width:2.5}
.wave-admin__live{display:flex;flex-wrap:wrap;align-items:center;gap:12px;background:color-mix(in srgb,var(--wave) 8%,var(--surface-2));border:1px solid var(--line-2);border-radius:var(--r-md);padding:10px 14px;margin-bottom:12px}
.chip--wave{background:var(--wave);border-color:var(--wave);color:#fff}
/* Waves polish - the World Tastes recent-waves history (Claude Design, wave-report.html) */
.wavehist{display:flex;flex-direction:column}
.wavehist__row{display:flex;align-items:center;gap:12px;padding:10px 14px;border-top:1px solid var(--line);flex-wrap:wrap}
.wavehist__row:first-child{border-top:0}
.wavehist__row--live{background:color-mix(in srgb,var(--wave) 7%,transparent);box-shadow:inset 3px 0 0 var(--wave)}
.wavehist__status{flex:none;width:64px}
.wavehist__pill{display:inline-block;font-family:var(--ff-mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;padding:2px 8px;border-radius:var(--r-pill);background:var(--wave);color:#fff}
.wavehist__pill--past{background:transparent;border:1px solid var(--line-2);color:var(--paper-3)}
.wavehist__pair{flex:1;min-width:160px;font-size:13px;color:var(--paper-2)}
.wavehist__pair b{color:var(--paper)}
.wavehist__mult{font-family:var(--ff-mono);font-size:13px;color:var(--wave);flex:none}
.wavehist__len{font-family:var(--ff-mono);font-size:12px;color:var(--paper-3);flex:none}
.wavehist__rider{flex:none;max-width:100%;font-size:13px;color:var(--paper-2)}
.wavehist__rider a{color:var(--paper);text-decoration:underline;text-decoration-color:var(--line-2);text-underline-offset:2px}
.wavehist__rider--quiet{color:var(--paper-3);font-style:italic}

/* ---- Collabs (collab-) - offer card, terms sheet, hub rows ---- */
.collab-offer{background:var(--surface-2);border:1px solid var(--line-2);border-radius:var(--r-lg);box-shadow:var(--shadow-2);overflow:hidden}
.collab-offer__head{display:flex;align-items:center;gap:12px;padding:14px 18px;border-bottom:1px solid var(--line)} /* D123 - gradient deleted */
.collab-offer__emoji{font-size:20px;flex:none}
.collab-offer__title{font-family:var(--ff-disp);font-weight:800;font-size:20px;text-transform:uppercase;line-height:1.05;min-width:0}
.collab-offer__title a{text-decoration:none}
.collab-offer__expiry{margin-left:auto;flex:none;font-family:var(--ff-mono);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--warn)}
.collab-terms{padding:14px 18px;display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px 22px}
.collab-terms__item{border-bottom:1px dashed var(--line);padding-bottom:8px;min-width:0}
.collab-terms__label{font-family:var(--ff-mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--paper-4);margin-bottom:2px}
.collab-terms__value{font-family:var(--ff-mono);font-size:14px;color:var(--paper);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.collab-terms__value small{color:var(--paper-3)}
.collab-terms__item--yours .collab-terms__value{color:var(--accent);font-weight:600}
.collab-offer__foot{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:12px 18px;border-top:1px solid var(--line)}
.collab-offer__split{font-size:12px;color:var(--paper-3);margin-left:auto}
.collab-row{display:flex;justify-content:space-between;align-items:center;gap:14px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-1);padding:11px 16px;font-size:13px;color:var(--paper-2)}
.collab-row b{color:var(--paper)}

/* ---- Batch 39 / D102 - the launch upgrade, ported from the user-approved
   docs/design/backstage/collabs-launch.html. Kinds, the split hero, the
   discovery strip, the partner finder, the accept picker. ---- */

/* the format chip - one letterform, three tints escalating with commitment */
.collab-kind{display:inline-flex;align-items:center;font-family:var(--ff-disp);font-weight:700;font-size:12px;letter-spacing:.14em;text-transform:uppercase;padding:2px 10px;border:1px solid var(--line-2);background:var(--surface-3);color:var(--paper-2)}
.collab-kind--single{border-color:color-mix(in srgb,var(--wave) 50%,var(--line-2));color:var(--wave)}
.collab-kind--ep{border-color:color-mix(in srgb,var(--warn) 50%,var(--line-2));color:var(--warn)}
.collab-kind--album{border-color:color-mix(in srgb,var(--accent) 55%,var(--line-2));color:var(--accent)}

/* the discovery strip - ON glows (being findable is a state, not a setting) */
.collab-toggle{display:flex;flex-wrap:wrap;align-items:center;gap:14px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-lg);padding:14px 18px;box-shadow:var(--shadow-1)}
.collab-toggle--on{border-top-color:var(--accent)} /* D123 - gradient deleted; being findable is said by the rule now */
.collab-toggle__emoji{font-size:22px;flex:none}
.collab-toggle__title{font-family:var(--ff-disp);font-weight:700;font-size:17px;text-transform:uppercase;color:var(--paper)}
.collab-toggle__sub{font-size:12.5px;color:var(--paper-3);flex-basis:100%;order:3;margin:0}
.collab-toggle form{margin-left:auto;flex:none}
@media(min-width:700px){.collab-toggle__sub{flex-basis:auto;order:0;flex:1;margin-left:2px}}

/* the partner finder - "big where you're not", bar relative to the top match */
/* The propose wizard's "where it would land" reach preview (design: collab-reach-preview
   canvas). One rule set for both themes - every color is a token; --you carries a --line
   border because surface-3-on-surface-2 alone is too faint on the light paper. */
.reach-sum{font-family:var(--ff-disp);font-weight:800;font-size:26px;text-transform:uppercase;letter-spacing:.02em;line-height:1.1}
.reach-sum small{color:var(--paper-3);font-weight:600;font-size:18px}
.reach-chip{font-family:var(--ff-mono);font-size:11px;letter-spacing:.02em;padding:4px 10px;border-radius:var(--r-pill);display:inline-block;line-height:1.4}
.reach-chip--you{background:var(--surface-3);color:var(--paper-2);border:1px solid var(--line)}
.reach-chip--add{background:var(--good-bg);color:var(--good);font-weight:600}
.reach-chip--out{background:transparent;border:1px dashed var(--line-2);color:var(--paper-4)}
.reach-chip--home{background:var(--surface-3);color:var(--warn);border:1px solid color-mix(in srgb,var(--warn) 40%,var(--line-2))}

.finder-card{display:grid;grid-template-columns:1fr auto;gap:4px 14px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);padding:12px 16px;box-shadow:var(--shadow-1)}
.finder-card__band{font-family:var(--ff-disp);font-weight:700;font-size:17px;text-transform:uppercase;color:var(--paper);display:flex;align-items:center;gap:8px;min-width:0;flex-wrap:wrap}
.finder-card__band .tag{text-transform:none;letter-spacing:0}
.finder-card__markets{font-size:12.5px;color:var(--paper-3)}
.finder-card__markets b{color:var(--paper-2);font-weight:600}
/* The column MUST be explicit: grid auto-placement puts items with a definite row (grid-row:1/3)
   FIRST, starting at column 1 - without grid-column:2 the button claims the 1fr column and
   stretches to half the card, shoving the band name into the narrow side. */
.finder-card__cta{grid-column:2;grid-row:1/3;align-self:center;justify-self:end}
.gain-meter{grid-column:1;display:flex;align-items:center;gap:10px;margin-top:4px}
.gain-meter__track{flex:1;height:7px;border-radius:var(--r-pill);background:var(--surface-3);border:1px solid var(--line);overflow:hidden}
.gain-meter__fill{display:block;height:100%;background:var(--accent)}
.gain-meter__label{font-family:var(--ff-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--paper-4);flex:none}

/* terms sheet v2 - the split IS the headline, read from the featured side */
.collab-offer__title{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.collab-offer__title .muted{color:var(--paper-3);font-weight:600}
.split-hero{display:flex;flex-wrap:wrap;align-items:baseline;gap:14px;padding:14px 18px 12px;border-bottom:1px solid var(--line)} /* D123 - gradient deleted */
.split-hero__pct{font-family:var(--ff-disp);font-weight:800;font-size:44px;line-height:.9;color:var(--accent)}
.split-hero__pct small{font-size:22px;vertical-align:baseline}
.split-hero__copy{font-size:13px;color:var(--paper-2);max-width:52ch}
.split-hero__copy b{color:var(--paper)}
.split-hero__ratio{margin-left:auto;flex:none;font-family:var(--ff-mono);font-size:12px;color:var(--paper-3)}
.collab-tracklist{padding:0 18px 12px;font-size:12.5px;color:var(--paper-3)}
.collab-tracklist b{color:var(--paper-2);font-weight:600}
.collab-decline summary{list-style:none;cursor:pointer}
.collab-decline summary::-webkit-details-marker{display:none}
.collab-decline__form{display:none;gap:8px;margin-top:8px;flex-wrap:wrap}
.collab-decline[open] .collab-decline__form{display:flex}

/* propose wizard - the share slider is the hero control */
.share-field{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);padding:14px 16px}
.share-field__read{display:flex;flex-wrap:wrap;align-items:baseline;gap:10px;margin-bottom:6px}
.share-field__pct{font-family:var(--ff-disp);font-weight:800;font-size:38px;line-height:.9;color:var(--accent)}
.share-field__pct small{font-size:19px;vertical-align:baseline}
.share-field__mirror{font-family:var(--ff-mono);font-size:12px;color:var(--paper-3)}
.share-field__suggested{margin-left:auto;font-family:var(--ff-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--wave)}
.share-field input[type=range]{width:100%;accent-color:var(--accent)}

/* the accept picker - exact-count made visible */
.pick-count{font-family:var(--ff-mono);font-size:12px;color:var(--paper-3)}
.pick-count b{color:var(--accent);font-size:15px}
.pick-list{display:grid;gap:8px}
.pick{display:flex;align-items:center;gap:10px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);padding:9px 12px;cursor:pointer;font-size:13px;color:var(--paper-2)}
.pick input{accent-color:var(--accent)}
/* D123 - the fill is deleted, not overridden (The Galley, section 13); the ink stays. */
.pick:has(input:checked){border-color:color-mix(in srgb,var(--accent) 55%,var(--line-2));color:var(--paper)}
.pick:has(input:disabled){opacity:.4;cursor:not-allowed}
.pick .tag{margin-left:auto}

/* ---- feat. credit (feat-) - bylines + catalogue badge ---- */
.feat-byline{font-family:var(--ff-mono);font-size:.82em;letter-spacing:.06em;text-transform:uppercase;color:var(--paper-3);margin:0 2px}
.feat-badge{background:color-mix(in srgb,var(--accent) 10%,var(--surface-3));border-color:color-mix(in srgb,var(--accent) 45%,var(--line-2));color:var(--paper-2);margin-left:8px;white-space:nowrap}
/* =================== end BATCH 36 COMPONENTS =================== */

/* ===================================================================
   BATCH 37 COMPONENTS (lbl-) - record labels (D100), ported from the
   user-approved docs/design/backstage/record-labels.html
   =================================================================== */

/* ---- the label mark - logo tile / monogram fallback (every surface) ---- */
.lbl-mark{flex:none;width:56px;height:56px;overflow:hidden;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--lbl) 22%,var(--surface-3));border:1px solid color-mix(in srgb,var(--lbl) 40%,var(--line-2))} /* D123 - gradient flattened to one violet tint */
.lbl-mark img{width:100%;height:100%;object-fit:cover;display:block}
.lbl-mark span{font-family:var(--ff-disp);font-weight:800;font-size:26px;color:var(--lbl)}
.lbl-mark--sm{width:38px;height:38px;border-radius:var(--r-sm)}
.lbl-mark--sm span{font-size:18px}

/* ---- public page header (/labels/{id}) ---- */
.lbl-head{display:flex;flex-wrap:wrap;align-items:center;gap:16px;padding:18px 0;margin-bottom:16px} /* D123 - gradient + box deleted; the violet rule is in The Galley */
.lbl-head__name{font-family:var(--ff-disp);font-weight:800;font-size:clamp(24px,3vw,34px);text-transform:uppercase;line-height:.95;letter-spacing:.01em}
.lbl-head__meta{font-size:12.5px;color:var(--paper-3);margin-top:4px}
.lbl-head__meta a{color:var(--paper-2)}
.lbl-head__meta b{color:var(--paper-2);font-weight:600}
/* D123 - a KEPT left rail. This is a pull quote, not a card: italic prose with a rule down its
   side is the oldest typographic device there is, and the public FAQ's answers already use the
   same one. impeccable-disable-next-line side-tab -- pull quote, not a card */
.lbl-mission{font-size:13px;color:var(--paper-2);font-style:italic;border-left:3px solid color-mix(in srgb,var(--lbl) 55%,var(--line-2));padding:2px 0 2px 14px;max-width:62ch}

/* ---- chips: distress (public, >= 3 nights) / signed / seeking / funded ---- */
.lbl-chip-distress{background:color-mix(in srgb,var(--bad) 16%,var(--surface-3));border-color:color-mix(in srgb,var(--bad) 55%,var(--line-2));color:var(--bad);font-weight:600}
.lbl-chip-signed{background:color-mix(in srgb,var(--lbl) 12%,var(--surface-3));border-color:color-mix(in srgb,var(--lbl) 45%,var(--line-2));color:var(--paper-2)}
.lbl-chip-signed a{color:var(--paper);text-decoration:none;font-weight:600}
.lbl-chip-seeking{background:color-mix(in srgb,var(--good) 12%,var(--surface-3));border-color:color-mix(in srgb,var(--good) 45%,var(--line-2));color:var(--good)}
.lbl-funded{background:color-mix(in srgb,var(--lbl) 12%,var(--surface-3));border-color:color-mix(in srgb,var(--lbl) 45%,var(--line-2));color:var(--paper-2);white-space:nowrap}
.lbl-funded b{color:var(--paper)}

/* ---- roster grid (public page) - signee cards with the contract stamp ---- */
.lbl-roster{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}
.lbl-signee{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-1);padding:13px 15px 11px;position:relative}
.lbl-signee__band{font-family:var(--ff-disp);font-weight:700;font-size:18px;text-transform:uppercase;line-height:1.05}
.lbl-signee__band a{text-decoration:none}
.lbl-signee__stats{display:flex;gap:14px;margin-top:7px;font-family:var(--ff-mono);font-size:12px;color:var(--paper-2)}
.lbl-signee__stats small{display:block;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4)}
.lbl-signee__since{position:absolute;top:11px;right:13px;font-family:var(--ff-mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--paper-4);border:1px dashed var(--line-2);border-radius:var(--r-sm);padding:2px 7px;transform:rotate(2deg)}

/* ---- directory card (/labels) ---- */
.lbl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:14px}
.lbl-card{display:block;text-decoration:none;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-1);padding:16px;transition:border-color .15s,transform .15s}
.lbl-card:hover{border-color:color-mix(in srgb,var(--lbl) 50%,var(--line-2));transform:translateY(-1px)}
.lbl-card__top{display:flex;align-items:center;gap:12px;margin-bottom:12px}
.lbl-card__name{font-family:var(--ff-disp);font-weight:800;font-size:21px;text-transform:uppercase;line-height:1;min-width:0}
/* D130 - a long owner handle used to run out of the card and clip with no ellipsis. It wraps
   instead: a name is worth two lines and nothing here is set to a fixed height. */
.lbl-card__owner{font-size:12px;color:var(--paper-3);margin-top:3px;min-width:0;overflow-wrap:anywhere}
.lbl-card__open{margin-left:auto;flex:none}
.chip--open{background:color-mix(in srgb,var(--good) 14%,var(--surface-3));border-color:color-mix(in srgb,var(--good) 50%,var(--line-2));color:var(--good)}
.lbl-card__row{display:flex;justify-content:space-between;gap:10px;border-top:1px dashed var(--line);padding-top:9px;font-family:var(--ff-mono);font-size:12px;color:var(--paper-2)}
.lbl-card__row small{font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--paper-4);display:block;margin-bottom:1px}

/* ---- board table (/labels/board) - season span = the live award race ---- */
.lbl-board{width:100%;border-collapse:collapse}
.lbl-board th{font-family:var(--ff-mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--paper-3);text-align:left;padding:8px 12px;border-bottom:1px solid var(--line-2)}
.lbl-board td{padding:10px 12px;border-bottom:1px solid var(--line);font-size:13px}
.lbl-board .num{text-align:right;font-family:var(--ff-mono)}
.lbl-board__pos{font-family:var(--ff-mono);color:var(--paper-3);width:40px}
.lbl-board__name{font-family:var(--ff-disp);font-weight:700;font-size:17px;text-transform:uppercase}
.lbl-board__name a{text-decoration:none}
.lbl-board tr.is-first td{background:color-mix(in srgb,var(--lbl) 8%,transparent);border-bottom-color:color-mix(in srgb,var(--lbl) 35%,var(--line))}
.lbl-board tr.is-first .lbl-board__pos{color:var(--lbl);font-weight:600}
.lbl-board__trophy{font-size:12px;margin-left:6px}

/* ---- hub treasury + runway ---- */
.lbl-treasury{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px}
.lbl-stat{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-1);padding:12px 15px}
.lbl-stat__k{font-family:var(--ff-mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--paper-4)}
.lbl-stat__v{font-family:var(--ff-mono);font-size:20px;margin-top:3px}
.lbl-stat--money .lbl-stat__v{color:var(--lbl)}
.lbl-stat--runway-low .lbl-stat__v{color:var(--warn)}

/* ---- the distress ladder - 7 nights to bust (hub banner, escalating) ---- */
.lbl-distress{display:flex;flex-wrap:wrap;align-items:center;gap:14px;border-radius:var(--r-md);box-shadow:var(--shadow-1);padding:12px 16px;border:1px solid}
.lbl-distress__nights{display:flex;gap:4px;align-items:center;flex:none}
.lbl-distress__nights i{width:9px;height:9px;background:var(--line-2)}
.lbl-distress__nights i.hit{background:var(--bad)}
.lbl-distress__text{flex:1;min-width:200px;font-size:13px}
.lbl-distress__text b{font-family:var(--ff-disp);font-weight:800;font-size:15px;text-transform:uppercase;letter-spacing:.04em}
.lbl-distress--warn{background:color-mix(in srgb,var(--warn) 9%,var(--surface-2));border-color:color-mix(in srgb,var(--warn) 45%,var(--line-2))}
.lbl-distress--warn b{color:var(--warn)}
.lbl-distress--critical{background:color-mix(in srgb,var(--bad) 12%,var(--surface-2));border-color:color-mix(in srgb,var(--bad) 55%,var(--line-2))}
.lbl-distress--critical b{color:var(--bad)}
.lbl-distress--critical .lbl-distress__nights i.hit{animation:lbl-throb 1.6s ease-in-out infinite}
@keyframes lbl-throb{50%{opacity:.45}}
@media (prefers-reduced-motion: reduce){.lbl-distress--critical .lbl-distress__nights i.hit{animation:none}}

/* ---- the contract card - offer terms + the recoup bar ---- */
.lbl-offer{background:var(--surface-2);border:1px solid color-mix(in srgb,var(--lbl) 30%,var(--line-2));border-radius:var(--r-lg);box-shadow:var(--shadow-2);overflow:hidden}
.lbl-offer__head{display:flex;align-items:center;gap:12px;padding:14px 18px;border-bottom:1px solid var(--line)} /* D123 - gradient deleted */
.lbl-offer__title{font-family:var(--ff-disp);font-weight:800;font-size:20px;text-transform:uppercase;line-height:1.05;min-width:0}
.lbl-offer__title a{text-decoration:none}
.lbl-offer__title .quiet{color:var(--paper-3)}
.lbl-offer__expiry{margin-left:auto;flex:none;font-family:var(--ff-mono);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--warn)}
.lbl-offer__expiry--quiet{color:var(--paper-3)}
.lbl-terms{padding:14px 18px;display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px 22px}
.lbl-terms__item{border-bottom:1px dashed var(--line);padding-bottom:8px;min-width:0}
.lbl-terms__label{font-family:var(--ff-mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--paper-4);margin-bottom:2px}
.lbl-terms__value{font-family:var(--ff-mono);font-size:14px;color:var(--paper);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lbl-terms__value small{color:var(--paper-3)}
.lbl-terms__item--cut .lbl-terms__value{color:var(--accent);font-weight:600}
/* D123 - the same KEPT pull-quote rail: the message a label owner wrote, in their words.
   impeccable-disable-next-line side-tab -- pull quote, not a card */
.lbl-offer__msg{margin:0 18px 14px;font-size:13px;color:var(--paper-2);font-style:italic;border-left:3px solid var(--line-2);padding:2px 0 2px 12px}
.lbl-offer__foot{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:12px 18px;border-top:1px solid var(--line)}
.lbl-offer__fine{font-size:12px;color:var(--paper-3);margin-left:auto}

/* the recoup bar - how much of the advance the label has clawed back */
.lbl-recoup{padding:0 18px 16px}
.lbl-recoup--head{padding-top:14px}
.lbl-recoup__bar{height:8px;border-radius:var(--r-pill);background:var(--surface);border:1px solid var(--line-2);overflow:hidden}
.lbl-recoup__fill{height:100%;background:var(--lbl)}
.lbl-recoup__fill.is-done{background:var(--good)}
.lbl-recoup__row{display:flex;justify-content:space-between;font-family:var(--ff-mono);font-size:10.5px;color:var(--paper-3);margin-top:5px}
.lbl-recoup__row b{color:var(--paper-2)}

/* ---- founding wizard - the patron gate + the fee line ---- */
.lbl-patron-gate{padding:22px 0;text-align:center;max-width:520px} /* D123 - gradient + box deleted; the gold rule is in The Galley */
.lbl-patron-gate__star{font-size:30px;color:var(--patron);line-height:1}
.lbl-patron-gate__h{font-family:var(--ff-disp);font-weight:800;font-size:24px;text-transform:uppercase;margin:8px 0 6px}
.lbl-patron-gate__sub{color:var(--paper-2);font-size:13px;max-width:46ch;margin:0 auto 16px}
.lbl-fee{display:flex;align-items:center;justify-content:space-between;gap:14px;background:var(--surface-3);border:1px dashed var(--line-2);border-radius:var(--r-md);padding:12px 16px;font-size:13px;color:var(--paper-2);margin-bottom:16px}
.lbl-fee .mono{color:var(--paper)}
.lbl-fee__amount{font-family:var(--ff-mono);font-size:20px;color:var(--lbl);flex:none}

/* ---- dashboard cards - owner + signee ---- */
.lbl-dash{padding:14px 16px} /* D123 - the coloured left rail is deleted, not overridden: it rotates to a top rule (The Galley). */
.lbl-dash__title{font-family:var(--ff-disp);font-weight:800;font-size:19px;text-transform:uppercase;line-height:1.05;margin-bottom:9px}
.lbl-dash__row{display:flex;justify-content:space-between;gap:10px;font-size:12.5px;color:var(--paper-2);padding:3px 0;align-items:center}
.lbl-dash__row .mono{color:var(--paper)}
.lbl-dash__alert{color:var(--bad);font-weight:600}
.lbl-dash .btn{display:block;text-align:center;margin-top:11px}

/* ---- ceremony Kind-4 art - the label monogram when there's no logo ---- */
.awards-art--lbl{display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--lbl) 22%,var(--surface-3));border:1px solid color-mix(in srgb,var(--lbl) 40%,var(--line-2))} /* D123 - gradient flattened */
.awards-art__lblmono{font-family:var(--ff-disp);font-weight:800;font-size:42px;color:var(--lbl)}
/* =================== end BATCH 37 COMPONENTS =================== */

/* ---- the Google auth button - official G beside the label (2026-07-19) ---- */
.btn-google{display:flex;align-items:center;justify-content:center;gap:10px}
.btn-google__g{width:18px;height:18px;flex:none;display:block}

/* ===================================================================
   TRACKLIST BUILDER (trk-) - the album/EP wizards (2026-07-22):
   pick tracks AND set their running order. JS enhancement over the
   no-JS checkbox fallback; hidden ordered TrackIds inputs are truth.
   =================================================================== */
.trk-list{list-style:none;margin:0 0 12px;padding:0;border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface-2);box-shadow:var(--shadow-1);overflow:hidden}
.trk-row{display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid var(--line)}
.trk-row:last-child{border-bottom:none}
.trk-row__pos{flex:none;width:26px;font-family:var(--ff-mono);font-size:12px;color:var(--paper-3);text-align:right}
.trk-row__name{flex:1;min-width:0;font-size:13px;color:var(--paper);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.trk-row__rating{flex:none;white-space:nowrap}
.trk-btn{flex:none;width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;background:none;border:1px solid transparent;border-radius:var(--r-sm);color:var(--paper-3);cursor:pointer;font-size:11px;line-height:1;padding:0}
.trk-btn:hover{color:var(--paper);border-color:var(--line-2);background:var(--surface-3)}
.trk-btn:disabled{opacity:.25;cursor:default;pointer-events:none}
.trk-btn--remove:hover{color:var(--bad)}
.trk-empty{padding:16px 14px;font-size:12.5px;color:var(--paper-4);text-align:center;border:1px dashed var(--line-2);border-radius:var(--r-md);margin-bottom:12px}
.trk-add{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);padding:7px 12px;cursor:pointer;color:var(--paper-2);font-size:13px;font-family:var(--ff-body)}
.trk-add:hover{border-color:var(--line-2);color:var(--paper)}
.trk-add:disabled{opacity:.45;cursor:default}
.trk-add__plus{flex:none;color:var(--accent);font-weight:700}
.trk-add.is-used{display:none}
/* =================== end TRACKLIST BUILDER =================== */

/* ===================================================================
   CHART MASTHEAD + COUNTDOWN (chart-) - ported from the user-approved
   docs/design/backstage/chart-masthead.html (2026-07-19)
   =================================================================== */

/* ---- the format rack - Singles / EPs / Albums / Streaming (the page's IDENTITY) ---- */
.chart-kinds{display:inline-flex;background:var(--surface-2);border:1px solid var(--line-2);border-radius:var(--r-md);box-shadow:var(--shadow-1);overflow:hidden}
.chart-kind{position:relative;font-family:var(--ff-disp);font-weight:700;font-size:16px;text-transform:uppercase;letter-spacing:.04em;color:var(--paper-3);padding:9px 18px 8px;border-right:1px solid var(--line);text-decoration:none;transition:color .12s}
.chart-kind:last-child{border-right:none}
.chart-kind:hover{color:var(--paper-2)}
.chart-kind.is-active{color:var(--paper);background:var(--surface-3)}
.chart-kind.is-active::after{content:"";position:absolute;left:10px;right:10px;bottom:4px;height:3px;background:var(--accent)}

/* ---- the market dial - a FILTER, deliberately half the rack's voice ---- */
.chart-regions{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-top:12px}
.chart-regions__k{flex:none;font-family:var(--ff-mono);font-size:9.5px;letter-spacing:.22em;text-transform:uppercase;color:var(--paper-4)}
.chart-region{font-family:var(--ff-mono);font-size:11px;letter-spacing:.04em;color:var(--paper-3);padding:3px 10px;border:1px solid transparent;border-radius:var(--r-pill);text-decoration:none;transition:color .12s,border-color .12s}
.chart-region:hover{color:var(--paper-2);border-color:var(--line-2)}
.chart-region.is-active{color:var(--accent-ink);background:var(--accent);border-color:var(--accent);font-weight:600}
.chart-region--note{color:var(--paper-4);cursor:default}
.chart-mast{margin-bottom:16px}

/* ---- the countdown - No.1 throne, top-10 weight, the pack ---- */
.chart-no1{display:flex;flex-wrap:wrap;align-items:center;gap:18px;padding:16px 0 18px;margin-bottom:12px} /* D123 - gradient + box deleted; the accent rule is in The Galley */
.chart-no1__art{width:96px;height:96px;flex:none;overflow:hidden;border:1px solid var(--line-2);background:var(--surface-3)} /* D123 - gradient + hardcoded drop shadow deleted; a hairline holds the sleeve instead */
.chart-no1__art img{width:100%;height:100%;object-fit:cover;display:block}
.chart-no1__main{min-width:0;flex:1}
.chart-no1__tag{font-family:var(--ff-mono);font-size:10px;letter-spacing:.26em;text-transform:uppercase;color:var(--accent);font-weight:600}
.chart-no1__title{font-family:var(--ff-disp);font-weight:800;font-size:clamp(22px,3vw,32px);text-transform:uppercase;line-height:.95;margin-top:2px}
.chart-no1__title a{text-decoration:none}
.chart-no1__by{font-size:13px;color:var(--paper-2);margin-top:4px}
.chart-no1__by a{font-weight:600;text-decoration:none}
.chart-no1__stats{flex:none;text-align:right;font-family:var(--ff-mono);font-size:11.5px;color:var(--paper-3);line-height:1.9}
.chart-no1__stats b{color:var(--paper);font-size:13px}

/* tiered rows inside the standard chart table */
.chart-pos{font-family:var(--ff-disp);font-weight:800;font-size:22px;line-height:1;color:var(--paper)}
.chart-pos--pack{font-size:14px;font-weight:700;color:var(--paper-3)}
tr.chart-top10 td{padding-top:12px;padding-bottom:12px}
tr.chart-top10 .chart-title{font-size:15px}
tr.chart-top10 .art-img--thumb,tr.chart-top10 .art--thumb{width:44px;height:44px}
.chart-break td{padding:5px 12px;font-family:var(--ff-mono);font-size:9.5px;letter-spacing:.24em;text-transform:uppercase;color:var(--paper-4);background:var(--surface)}
/* =================== end CHART MASTHEAD + COUNTDOWN =================== */

/* ===================================================================
   BATCH 38 COMPONENTS (D101) — ported verbatim from
   docs/design/backstage/achievements-hall.html (ach- / hall-)
   =================================================================== */

/* ---- The rarity ladder (ach-tier) - the venue climb, commonest → rarest.
       Each tier keys --tier to an EXISTING token; Stadium alone gets presence. ---- */
.ach-tier{display:inline-flex;align-items:center;gap:6px;font-family:var(--ff-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;padding:2px 9px;border:1px solid var(--line-2);background:none;color:var(--paper-2);white-space:nowrap} /* D123 - outline, like .chip */
.ach-tier i{width:7px;height:7px;background:var(--tier,var(--paper-3));flex:none}
.ach-tier--garage{--tier:var(--paper-3)}
.ach-tier--club{--tier:var(--wave)}
.ach-tier--theatre{--tier:var(--lbl)}
.ach-tier--arena{--tier:var(--patron)}
.ach-tier--stadium{--tier:var(--accent);border-color:color-mix(in srgb,var(--accent) 45%,var(--line-2));color:var(--paper)}
.ach-tier--unclaimed{--tier:var(--paper-4);border-style:dashed;color:var(--paper-3)}

/* ---- The gallery masthead (ach-mast): the tally + the ladder legend ---- */
.ach-mast{display:flex;flex-wrap:wrap;align-items:center;gap:14px 22px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-1);padding:14px 18px;margin-bottom:20px}
.ach-mast__count{font-family:var(--ff-mono);font-size:13px;color:var(--paper-2)}
.ach-mast__count b{font-size:24px;color:var(--paper);font-weight:600}
.ach-mast__count .of{color:var(--paper-3)}
.ach-ladder{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-left:auto}
.ach-ladder__arrow{font-family:var(--ff-mono);font-size:11px;color:var(--paper-4)}

/* ---- Next up (ach-next): the signed-in hero - the three closest unlocks ---- */
.ach-next{padding:12px 16px;margin-bottom:20px} /* D123 - the coloured left rail is deleted, not overridden: it rotates to a top rule (The Galley). */
.ach-next__head{font-family:var(--ff-mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--paper-3);margin-bottom:10px}
.ach-next__row{display:grid;grid-template-columns:minmax(140px,240px) minmax(90px,300px) auto;justify-content:start;gap:12px;align-items:center;padding:5px 0}
.ach-next__title{font-family:var(--ff-disp);font-weight:700;font-size:15px;text-transform:uppercase;letter-spacing:.02em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ach-next__meter{overflow:hidden}
.ach-next__meter i{display:block;height:100%;width:var(--pct,0%);background:var(--tier,var(--accent))}
.ach-next__nums{font-family:var(--ff-mono);font-size:12px;color:var(--paper-2);white-space:nowrap}
@media (max-width:560px){.ach-next__row{grid-template-columns:1fr auto}.ach-next__meter{grid-column:1 / -1}}

/* ---- Category headers (ach-cat) ---- */
.ach-cat{display:flex;align-items:baseline;gap:10px;margin:30px 0 12px;font-family:var(--ff-disp);font-weight:700;font-size:19px;text-transform:uppercase;letter-spacing:.03em}
.ach-cat__n{font-family:var(--ff-mono);font-size:11px;letter-spacing:.1em;color:var(--paper-3)}
.ach-cat::after{content:"";flex:1;height:1px;background:var(--line);align-self:center}

/* ---- The achievement card (ach-card) - tier rail, meter, rarity line ---- */
.ach-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:12px}
.ach-card{display:flex;flex-direction:column;gap:8px;padding:12px 14px;min-width:0;scroll-margin-top:80px} /* D123 - the coloured left rail is deleted, not overridden: it rotates to a top rule (The Galley). */
.ach-card--earned{background:color-mix(in srgb,var(--tier,var(--line-2)) 8%,var(--surface-2));border-color:color-mix(in srgb,var(--tier,var(--line-2)) 30%,var(--line));border-left-color:var(--tier,var(--line-2))}
.ach-card--unclaimed{border-left-style:dashed}
.ach-card__top{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
.ach-card__title{font-family:var(--ff-disp);font-weight:700;font-size:16.5px;line-height:1.05;text-transform:uppercase;letter-spacing:.02em}
.ach-card__desc{font-size:12px;line-height:1.4;color:var(--paper-3)}
.ach-card__meter{overflow:hidden}
.ach-card__meter i{display:block;height:100%;width:var(--pct,0%);background:var(--tier,var(--paper-3))}
.ach-card__nums{display:flex;justify-content:space-between;align-items:baseline;gap:10px;font-family:var(--ff-mono);font-size:11.5px;color:var(--paper-2)}
.ach-card__earned{color:var(--tier,var(--good));font-weight:600;white-space:nowrap}
.ach-card__best{font-family:var(--ff-mono);font-size:11.5px;color:var(--paper-2)}
.ach-card__best b{color:var(--paper)}
.ach-card__rar{display:flex;justify-content:space-between;gap:10px;font-family:var(--ff-mono);font-size:10.5px;letter-spacing:.04em;color:var(--paper-4)}
.ach-card__rar .unclaimed{color:var(--paper-3);font-style:italic}

/* ---- Dashboard strip (ach-strip) - the wave-strip shape in trophy gold ---- */
.ach-strip{display:flex;align-items:center;gap:12px;padding:10px 14px;margin-bottom:20px} /* D123 - the coloured left rail is deleted, not overridden: it rotates to a top rule (The Galley). */
.ach-strip__text{flex:1;min-width:0;font-size:13px;color:var(--paper-2)}
.ach-strip__text b{color:var(--paper)}
.ach-strip__text .mono{font-family:var(--ff-mono);color:var(--paper)}
.ach-strip__meter{flex:none;width:110px;overflow:hidden}
.ach-strip__meter i{display:block;height:100%;width:var(--pct,0%);background:var(--patron)}

/* ---- The band cabinet additions (reuses cabinet-*) ---- */
.cabinet-mono--img{padding:0;overflow:hidden;background:var(--surface-2)}
/* D125 - the counter-rotation and the 1.45 blow-up it needed to fill a tilted box go with
   the rotation; the band photo is no longer cropped to make a diamond work. */
.cabinet-mono--img img{width:100%;height:100%;object-fit:cover}
.cabinet-showcase{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:12px}

/* ---- The drill-through page (ach-hero) - /achievements/{id} ---- */
.ach-hero{display:flex;flex-direction:column;gap:12px;padding:18px 22px;margin-bottom:20px} /* D123 - the coloured left rail is deleted, not overridden: it rotates to a top rule (The Galley). */
.ach-hero--earned{background:color-mix(in srgb,var(--tier,var(--line-2)) 8%,var(--surface-2))}
.ach-hero__top{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;flex-wrap:wrap}
.ach-hero__title{font-family:var(--ff-disp);font-weight:800;font-size:clamp(24px,3.4vw,34px);line-height:.95;text-transform:uppercase;letter-spacing:.01em}
.ach-hero__desc{font-size:14px;line-height:1.5;color:var(--paper-2);max-width:70ch;margin-top:6px}
.ach-hero__stats{display:flex;flex-wrap:wrap;gap:8px 22px;font-family:var(--ff-mono);font-size:12px;color:var(--paper-2)}
.ach-hero__stats b{color:var(--paper);font-size:15px}
.ach-hero__you{display:grid;grid-template-columns:auto minmax(90px,320px) auto;justify-content:start;gap:12px;align-items:center;border-top:1px solid var(--line);padding-top:12px}
.ach-hero__you-label{font-family:var(--ff-mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--paper-3);white-space:nowrap}
.ach-hero__meter{overflow:hidden}
.ach-hero__meter i{display:block;height:100%;width:var(--pct,0%);background:var(--tier,var(--paper-3))}
.ach-more{padding:9px 14px;border-top:1px solid var(--line);font-family:var(--ff-mono);font-size:11px;color:var(--paper-4)}
.ach-card__title a{text-decoration:none;color:inherit}
.ach-card__title a:hover{color:var(--tier,var(--paper))}

/* ---- Hall of Fame (hall-) ---- */
.hall-champs{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:12px}
.hall-champ{display:flex;flex-direction:column;gap:8px;padding:14px 0} /* D123 - gradient + box deleted; the gold rule is in The Galley */
.hall-champ__season{font-family:var(--ff-mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--paper-3)}
.hall-champ__row{display:flex;align-items:center;gap:10px}
.hall-champ__mark{width:44px;height:44px;flex:none;border-radius:var(--r-md);border:1px solid var(--line-2);background:var(--surface-3);display:flex;align-items:center;justify-content:center;font-family:var(--ff-disp);font-weight:800;font-size:19px;color:var(--patron);overflow:hidden}
.hall-champ__mark img{width:100%;height:100%;object-fit:cover}
.hall-champ__name{font-family:var(--ff-disp);font-weight:700;font-size:18px;line-height:1;text-transform:uppercase;letter-spacing:.02em}
.hall-champ__cat{font-size:11.5px;color:var(--paper-3)}
.hall-champ__stat{font-family:var(--ff-mono);font-size:11.5px;color:var(--paper-2);margin-top:auto}
.hall-board{display:flex;flex-direction:column}
.hall-board__row{display:grid;grid-template-columns:34px 1fr auto auto;gap:10px;align-items:baseline;padding:8px 14px;border-top:1px solid var(--line)}
.hall-board__row:first-child{border-top:0}
.hall-board__rank{font-family:var(--ff-mono);font-size:12px;color:var(--paper-3)}
.hall-board__row--first .hall-board__rank{color:var(--patron)}
.hall-board__name{font-family:var(--ff-disp);font-weight:700;font-size:15.5px;text-transform:uppercase;letter-spacing:.02em;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hall-board__name a{text-decoration:none}
.hall-board__wins{font-family:var(--ff-mono);font-size:12.5px;color:var(--paper)}
.hall-board__extra{font-family:var(--ff-mono);font-size:11px;color:var(--paper-4)}
.hall-rare{display:flex;flex-direction:column}
.hall-rare__row{display:grid;grid-template-columns:auto 1fr auto;gap:12px;align-items:center;padding:9px 14px;border-top:1px solid var(--line)}
.hall-rare__row:first-child{border-top:0}
.hall-rare__title{font-family:var(--ff-disp);font-weight:700;font-size:15.5px;text-transform:uppercase;letter-spacing:.02em;min-width:0}
.hall-rare__who{font-size:12px;color:var(--paper-3);grid-column:2 / -1}
.hall-rare__who a{color:var(--paper-2)}
.hall-rare__pct{font-family:var(--ff-mono);font-size:11.5px;color:var(--paper-3);white-space:nowrap}
.hall-recent{display:flex;flex-direction:column}
.hall-recent__row{display:flex;gap:9px;align-items:baseline;padding:7px 14px;border-top:1px solid var(--line);font-size:13px;color:var(--paper-2)}
.hall-recent__row:first-child{border-top:0}
.hall-recent__row b{color:var(--paper)}
/* =================== end BATCH 38 COMPONENTS =================== */

/* ===================================================================
   BATCH 40 COMPONENTS (cert-) - release certifications (D103), ported
   from the user-approved docs/design/backstage/certifications.html.
   NB deliberately NOT the retired ".diamond" ornament (deleted in D125).
   =================================================================== */

/* The badge. Same shape language as .ach-tier: a coloured pip plus the tier
   SPELLED OUT, so colour is reinforcement and never the only signal. */
.cert{display:inline-flex;align-items:center;gap:6px;font-family:var(--ff-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;padding:2px 9px;border-radius:var(--r-pill);border:1px solid var(--line-2);background:var(--surface-3);color:var(--paper-2);white-space:nowrap}
/* D123 - a KEPT circle, and the pill above it is kept too (restated at the foot of this file).
   Carl's call: a certification is an award from outside the game's own furniture and is allowed
   to look like one, the way a stamp on a sleeve does. */
.cert i{width:7px;height:7px;border-radius:50%;background:var(--tier,var(--paper-3));flex:none}
.cert--silver{--tier:var(--cert-silver)}
.cert--gold{--tier:var(--patron);border-color:color-mix(in srgb,var(--patron) 40%,var(--line-2))}
.cert--platinum{--tier:var(--cert-platinum);border-color:color-mix(in srgb,var(--cert-platinum) 40%,var(--line-2));color:var(--paper)}
/* Diamond alone gets presence - the same restraint .ach-tier--stadium shows.
   D123 - a KEPT glow, and the last box-shadow in the signed-in game. It belongs to the
   certification badge, which is this batch's declared exception: an award from outside the
   game's own furniture, allowed to look like one. It is ink on a stamp, not elevation. */
.cert--diamond{--tier:var(--cert-diamond);border-color:color-mix(in srgb,var(--cert-diamond) 55%,var(--line-2));color:var(--paper);box-shadow:0 0 10px color-mix(in srgb,var(--cert-diamond) 30%,transparent)}
/* Row variant, for catalogue/profile/discography tables. */
.cert--sm{font-size:9.5px;padding:1px 7px;margin-left:8px}
.cert--sm i{width:6px;height:6px}

/* The units explainer under the release-page stat cards - the maths is never a mystery. */
.cert-note{font-size:12.5px;color:var(--paper-3);border:1px dashed var(--line-2);border-radius:var(--r-md);background:var(--surface);padding:11px 15px}
.cert-note b{color:var(--paper-2)}
/* =================== end BATCH 40 COMPONENTS =================== */

/* ==== D105 - /about/history, "The Story" (design: the-story-page canvas). Scoped under
   .story-page; the era-tan tokens carry the 2001 site's palette in both themes. ==== */
.story-page{max-width:960px;margin:0 auto;padding:40px 24px 64px;display:flex;flex-direction:column;gap:44px;font-size:15px;line-height:1.7;color:var(--paper-2)}
.story-page h1{font-family:var(--ff-head,var(--ff-disp));font-weight:400;font-size:clamp(38px,7vw,60px);text-transform:uppercase;color:var(--paper);margin:0 0 8px;letter-spacing:.01em;line-height:1}
.story-sub{color:var(--paper-3);font-size:15px}
.story-spine{position:relative;display:flex;flex-direction:column;gap:38px}
.story-spine::before{content:"";position:absolute;left:46px;top:8px;bottom:-34px;border-left:2px dotted var(--line-2)}
.story-era{display:grid;grid-template-columns:96px 1fr;gap:0 24px}
.story-year{font-family:var(--ff-disp);font-weight:800;font-size:28px;color:var(--paper);background:var(--bg);position:relative;z-index:1;padding:2px 0;text-align:right;width:92px}
.story-year small{display:block;font-family:var(--ff-mono);font-weight:400;font-size:10px;letter-spacing:.14em;color:var(--paper-4);text-transform:uppercase}
.story-page h2{font-family:var(--ff-disp);font-weight:700;font-size:26px;text-transform:uppercase;color:var(--paper);margin:0 0 8px;letter-spacing:.03em}
.story-page h2.lg{font-size:32px}
.story-era p{margin:0 0 12px}
.story-shot{background:var(--surface-2);border:1px solid var(--line-2);overflow:hidden;margin:6px 0 14px;cursor:zoom-in;padding:0;width:100%;text-align:left;display:block}
.story-shot img{display:block;width:100%;height:auto}
.story-shot__bar{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:8px 12px;border-top:1px solid var(--line)}
.story-shot__cap{font-family:var(--ff-mono);font-size:11px;color:var(--paper-3)}
.story-shot__zoom{font-family:var(--ff-mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--paper-4);flex:none}
.story-shot--tan .story-shot__bar{border-top-color:color-mix(in srgb,var(--era-tan-deep) 70%,var(--line))}
.story-shot--tan .story-shot__cap{color:var(--era-tan)}
.story-quote{font-family:var(--ff-mono);font-size:13px;color:var(--paper-2);border-top:1px solid var(--line-2);border-bottom:1px solid var(--line-2);padding:12px 0;margin:0 0 12px}
.story-quote b{color:var(--era-tan);font-weight:600}
.story-quote .d{color:var(--paper-4);font-size:11px;display:block;margin-bottom:4px}
.story-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin:14px 0}
.story-stat{border-top:1px solid var(--line-2);padding:12px 0 0}
.story-stat b{display:block;font-family:var(--ff-disp);font-weight:800;font-size:34px;color:var(--paper);line-height:1.1}
.story-stat b.md{font-size:20px}
.story-stat span{font-family:var(--ff-mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--paper-4)}
.story-never{border:1px dashed var(--line-2);border-radius:var(--r-md);padding:16px}
.story-never ul{list-style:none;padding:0;margin:0}
.story-never li{margin-bottom:8px;color:var(--paper-3)}
.story-never s{color:var(--paper-4)}
.story-never .until{color:var(--warn);font-family:var(--ff-mono);font-size:12px}
.story-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}
.story-grid .story-shot{margin:0}
/* D127 - THE VIEWER (Kit/_Lightbox). D123 kept this component's 10px radius and its 80px drop
   shadow, and wrote down why: the archive gallery was only ever on /about/history, and The
   Galley was the signed-in game. Putting it behind the homepage screenshots retires that
   argument, so the ruling is the one both registers already share - square, and no elevation.
   D113a's Square Corner Rule says a logged-out page has no rounded corner anywhere; DESIGN.md's
   Dialog says "the one genuinely floating object: square edge, the block's 2px Newsprint rule
   on top", and the Nothing Floats Rule says a floating thing earns its FILL, never a shadow. A
   rounded plate under a soft 80px shadow is also the default of every lightbox plugin since
   2010, which is exactly the assembled-not-built tell the public pages spent D113a deleting.
   What the shadow was doing, the edge now does: an opaque ground, the 2px paper rule, a Rule
   Strong hairline, and a heavier veil behind.
   The colours stay LITERAL rather than tokenised, and that is a decision and not an oversight:
   a viewer is a dark room in both themes, the way a projection booth does not repaint itself
   for the matinee. Every value below is the dark theme's own token, spelled out - and the
   counter moved off Newsprint 4 (3.2:1 at 11px, a real failure) onto Newsprint 3. */
.lightbox{border:1px solid #463f31;border-top:2px solid #f4efe4;border-radius:0;background:#0d0c0a;padding:28px 30px 18px;max-width:min(1400px,94vw);box-shadow:none;color:#f4efe4}
.lightbox::backdrop{background:rgba(4,3,2,.88)}
.lightbox figure{margin:0}
.lightbox img{display:block;max-width:100%;max-height:76vh;width:auto;height:auto;margin:0 auto;border:1px solid #322d23;border-radius:0}
.lightbox figcaption{display:flex;justify-content:space-between;align-items:baseline;gap:14px;margin-top:12px;flex-wrap:wrap}
.lightbox .t{font-family:var(--ff-disp);font-weight:800;font-size:22px;color:#f4efe4;text-transform:uppercase}
.lightbox .c{font-family:var(--ff-mono);font-size:12px;color:#908975}
.lightbox .n{font-family:var(--ff-mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:#908975}
/* An opaque ground, not `background:none`: the control sits in the plate's top padding and the
   image's top edge runs under it, so over a light capture (every archive one is cream) the label
   was reading dark-on-light and half vanishing. */
.lightbox .x{position:absolute;top:12px;right:14px;background:#0d0c0a;border:1px solid #463f31;border-radius:0;color:#c4bda9;font-family:var(--ff-mono);font-size:12px;padding:6px 12px;cursor:pointer}
.lightbox .nav{position:absolute;top:46%;background:#16140f;border:1px solid #463f31;border-radius:0;color:#f4efe4;font-size:16px;width:38px;height:38px;cursor:pointer}
.lightbox .nav--prev{left:10px}.lightbox .nav--next{right:10px}
.lightbox .x:hover,.lightbox .nav:hover{border-color:#f4efe4;background:#252118}
/* One authored moment: the plate arrives. Entry only, and with no fill-mode - the D113 finish
   review caught a row left at opacity 0 because its animation never fired, and a dialog that
   did that would be a blank screen. */
@media (prefers-reduced-motion:no-preference){
  .lightbox[open]{animation:lb-plate .18s cubic-bezier(.2,.7,.3,1)}
  .lightbox[open]::backdrop{animation:lb-veil .18s ease-out}
}
@keyframes lb-plate{from{opacity:0;transform:translateY(10px)}}
@keyframes lb-veil{from{opacity:0}}
@media (max-width:640px){.story-era{grid-template-columns:1fr;gap:4px}.story-spine::before{display:none}.story-year{text-align:left;width:auto}}

/* D105 follow-up - the About page's story feature card ("honestly, it's not boring"). The
   dotted top/bottom borders are the ticket perforation; the whole card is one link. */
.story-cta{display:flex;flex-direction:column;gap:8px;align-items:flex-start;background:var(--surface-2);border:1px solid var(--line-2);border-top:2px solid var(--paper);padding:26px 28px;margin:10px 0;text-decoration:none;color:var(--paper-2)}
.story-cta:hover{border-color:color-mix(in srgb,var(--accent) 45%,var(--line-2));color:var(--paper-2)}
.story-cta__kicker{font-family:var(--ff-mono);font-size:12.5px;letter-spacing:.02em;color:var(--paper-3)} /* D113a - a fact line under the title now, not an eyebrow above it */
.story-cta__title{font-family:var(--ff-head,var(--ff-disp));font-weight:400;font-size:clamp(28px,5vw,40px);line-height:1;text-transform:uppercase;color:var(--paper)}
.story-cta__promise{font-family:var(--ff-disp);font-weight:600;font-size:18px;text-transform:uppercase;letter-spacing:.08em;color:var(--warn)}
.story-cta__tease{font-size:14px;line-height:1.6;color:var(--paper-3)}
.story-cta__btn{margin-top:8px}

/* D105 follow-up - the FAQ, "backstage signage" treatment (faq-directions canvas, option B
   structure with option A's asked-tags grafted on). */
.faq-cat{font-family:var(--ff-head,var(--ff-disp));font-weight:400;font-size:22px;letter-spacing:.01em;text-transform:uppercase;color:var(--paper);margin:38px 0 0;padding-top:14px;border-top:2px solid var(--paper);line-height:1.05} /* D113a - a real heading, not a red mono eyebrow */
.faq-q{font-family:var(--ff-disp);font-weight:700;font-size:26px;text-transform:uppercase;color:var(--paper);letter-spacing:.02em;margin:18px 0 2px;line-height:1.15}
.faq-tag{font-family:var(--ff-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--paper-4);margin-bottom:6px}
.faq-a{color:var(--paper-2);max-width:62ch;border-left:2px solid var(--line-2);padding-left:14px;font-size:14px;line-height:1.65}
.faq-a strong{color:var(--paper)}

/* ===================================================================
   BATCH 44 COMPONENTS (hq-) - Label HQ (D107). Ported verbatim from the
   user-approved docs/design/backstage/label-hq.html. The owner section
   (/label + roster/deals/finances/settings + the Offer/Fund wizards'
   chrome) and the band-side /my/label masthead. Extends the lbl- family;
   the violet stays the ink of the industry. No new tokens.
   =================================================================== */

/* ---- the letterhead - the HQ masthead on every section page ---- */
/* Double top rule (3px + a 1px hairline beneath, via inset shadow) = printed letterhead. */
.hq-head{display:flex;flex-wrap:wrap;align-items:center;gap:16px 20px;padding:18px 0 16px} /* D123 - gradient, box and the inset double-rule deleted; the violet rule is in The Galley */
.hq-head--compact{padding:14px 22px 12px}
.hq-head__id{min-width:0;flex:1}
.hq-head__kicker{font-family:var(--ff-mono);font-size:9.5px;letter-spacing:.3em;text-transform:uppercase;color:color-mix(in srgb,var(--lbl) 75%,var(--paper-3))}
.hq-head__name{font-family:var(--ff-disp);font-weight:800;font-size:clamp(26px,3.6vw,40px);text-transform:uppercase;line-height:.95;letter-spacing:.01em;margin-top:2px}
.hq-head--compact .hq-head__name{font-size:24px}
.hq-head__strap{font-size:12.5px;font-style:italic;color:var(--paper-3);margin-top:4px;max-width:60ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hq-head__meta{font-size:12px;color:var(--paper-3);margin-top:6px;display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px}
.hq-head__meta b{color:var(--paper-2);font-weight:600}
.hq-head__stats{display:flex;gap:22px;flex:none;text-align:right;margin-left:auto}
.hq-stat__v{font-family:var(--ff-mono);font-size:19px;color:var(--paper);display:block}
.hq-stat--money .hq-stat__v{color:var(--lbl)}
.hq-stat--warn .hq-stat__v{color:var(--warn)}
.hq-stat__k{font-family:var(--ff-mono);font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:var(--paper-4)}
/* band-side variant: same letterhead, the band's standing in big type */
.hq-head--band .hq-head__kicker{color:var(--paper-3)}

/* ---- the rack - the five-room office directory ---- */
/* chart-kinds language, violet underline; scrolls sideways on phones, never wraps. */
.hq-rack{display:flex;align-items:stretch;border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface-2);box-shadow:var(--shadow-1);margin:14px 0 22px;overflow-x:auto;scrollbar-width:none;max-width:100%}
.hq-rack::-webkit-scrollbar{display:none}
.hq-rack__link{position:relative;flex:none;display:flex;align-items:center;gap:8px;padding:10px 20px;font-family:var(--ff-disp);font-weight:600;font-size:16px;text-transform:uppercase;letter-spacing:.05em;color:var(--paper-3);text-decoration:none;border-right:1px solid var(--line);white-space:nowrap}
.hq-rack__link:last-child{border-right:0}
.hq-rack__link:hover{color:var(--paper-2)}
.hq-rack__link.is-active{color:var(--paper);background:var(--surface-3)}
.hq-rack__link.is-active::after{content:"";position:absolute;left:10px;right:10px;bottom:0;height:3px;background:var(--lbl)}
.hq-rack__badge{font-family:var(--ff-mono);font-size:10px;letter-spacing:.04em;background:color-mix(in srgb,var(--lbl) 18%,var(--surface-3));border:1px solid color-mix(in srgb,var(--lbl) 50%,var(--line-2));color:var(--paper);border-radius:var(--r-pill);padding:1px 8px}

/* ---- the morning memos - Overview's needs-attention strip ---- */
.hq-attn{display:flex;flex-direction:column;gap:8px}
.hq-attn__item{display:flex;align-items:center;gap:12px;padding:10px 14px;font-size:13px;color:var(--paper-2)} /* D123 - the coloured left rail is deleted, not overridden: it rotates to a top rule (The Galley). */
.hq-attn__item b{color:var(--paper);font-weight:600}
.hq-attn__item--warn{border-left-color:var(--warn)}
.hq-attn__item--bad{border-left-color:var(--bad)}
.hq-attn__go{margin-left:auto;flex:none;font-family:var(--ff-mono);font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--paper-3);text-decoration:none}
.hq-attn__go:hover{color:var(--paper)}

/* ---- the roster wall strip (Overview snapshot) ---- */
.hq-wall{display:flex;flex-wrap:wrap;gap:8px}
.hq-wall__act{display:flex;align-items:center;gap:9px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-1);padding:7px 12px 7px 8px;text-decoration:none}
.hq-wall__act:hover{border-color:color-mix(in srgb,var(--lbl) 45%,var(--line-2))}
.hq-wall__name{font-family:var(--ff-disp);font-weight:700;font-size:15px;text-transform:uppercase;line-height:1}
.hq-wall__cut{font-family:var(--ff-mono);font-size:10.5px;color:var(--paper-3)}

/* ---- the ink stamp (generalised from .lbl-signee__since) ---- */
.hq-stamp{flex:none;font-family:var(--ff-mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--paper-4);border:1px dashed var(--line-2);border-radius:var(--r-sm);padding:2px 7px;transform:rotate(2deg)}
.hq-contract__head .hq-stamp{margin-left:auto}

/* ---- the roster contract card (owner side) ---- */
.hq-contract{background:var(--surface-2);border:1px solid color-mix(in srgb,var(--lbl) 26%,var(--line-2));border-radius:var(--r-lg);box-shadow:var(--shadow-1);overflow:hidden}
.hq-contract__head{display:flex;align-items:center;gap:12px;padding:13px 18px;border-bottom:1px solid var(--line)} /* D123 - gradient deleted */
.hq-contract__band{font-family:var(--ff-disp);font-weight:800;font-size:20px;text-transform:uppercase;line-height:1.05;min-width:0}
.hq-contract__band a{text-decoration:none}
.hq-contract__earned{padding:12px 18px 2px;display:flex;align-items:baseline;gap:10px}
.hq-contract__earned b{font-family:var(--ff-mono);font-size:22px;font-weight:500;color:var(--lbl)}
.hq-contract__earned small{font-family:var(--ff-mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--paper-4)}
.hq-contract__foot{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:12px 18px;border-top:1px solid var(--line)}
.hq-contract__fine{font-size:12px;color:var(--paper-3);margin-left:auto}
.hq-chip-inert{background:var(--surface-3);border-color:var(--line-2);color:var(--paper-3)}

/* ---- the deal history - resolved paperwork, quiet by design ---- */
.hq-history__row{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 14px;padding:9px 4px;border-bottom:1px solid var(--line);font-size:12.5px;color:var(--paper-2)}
.hq-history__row:last-child{border-bottom:0}
.hq-history__status{flex:none;width:86px;font-family:var(--ff-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4)}
.hq-history__status--signed{color:var(--good)}
.hq-history__status--declined{color:var(--bad)}
.hq-history__who{font-family:var(--ff-disp);font-weight:700;font-size:15px;text-transform:uppercase}
.hq-history__who a{text-decoration:none}
.hq-history__terms{font-family:var(--ff-mono);font-size:11px;color:var(--paper-3)}
.hq-history__reason{font-style:italic;color:var(--paper-3)}
.hq-history__when{margin-left:auto;font-family:var(--ff-mono);font-size:10.5px;color:var(--paper-4)}

/* ---- the books - Finances in/out summary + the ledger ---- */
.hq-sum{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}
.hq-sum__col{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-1);padding:14px 16px}
.hq-sum__h{font-family:var(--ff-mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--paper-4);margin-bottom:8px}
.hq-sum__h--in{color:var(--good)}
.hq-sum__h--out{color:var(--paper-3)}
.hq-sum__row{display:flex;justify-content:space-between;gap:12px;padding:4px 0;border-bottom:1px dashed var(--line);font-size:12.5px;color:var(--paper-2)}
.hq-sum__row .mono{color:var(--paper)}
.hq-sum__row--net{border-bottom:0;border-top:1px solid var(--line-2);margin-top:6px;padding-top:8px;font-weight:600;color:var(--paper)}
.hq-sum__row--net .mono{color:var(--lbl);font-size:14px}
.hq-ledger{width:100%;border-collapse:collapse}
.hq-ledger th{font-family:var(--ff-mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--paper-4);text-align:left;padding:7px 10px;border-bottom:1px solid var(--line-2)}
.hq-ledger td{padding:7px 10px;border-bottom:1px solid var(--line);font-size:12.5px}
.hq-ledger .num{text-align:right;font-family:var(--ff-mono)}
.hq-ledger__date{font-family:var(--ff-mono);font-size:11px;color:var(--paper-4);white-space:nowrap}
.hq-ledger__in{color:var(--good)}
.hq-ledger__out{color:var(--paper-3)}

/* ---- the certificate - the Founder's Licence strip (Settings) ---- */
.hq-cert{display:flex;flex-wrap:wrap;align-items:center;gap:12px;border:2px dashed color-mix(in srgb,var(--lbl) 45%,var(--line-2));border-radius:var(--r-md);background:color-mix(in srgb,var(--lbl) 5%,var(--surface-2));padding:12px 16px}
.hq-cert__seal{flex:none;font-size:20px}
.hq-cert__text{font-size:12.5px;color:var(--paper-2)}
.hq-cert__text b{font-family:var(--ff-mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--lbl)}

/* ---- the danger zone (Settings) ---- */
.hq-danger{padding:14px 16px} /* D123 - the coloured left rail is deleted, not overridden: it rotates to a top rule (The Galley). */
.hq-danger__h{font-family:var(--ff-disp);font-weight:800;font-size:16px;text-transform:uppercase;letter-spacing:.04em;color:var(--bad);margin-bottom:6px}
.hq-narrow{max-width:680px}

/* ---- responsive: the letterhead stacks, the rack scrolls ---- */
@media (max-width: 640px){
  .hq-head__stats{margin-left:0;width:100%;justify-content:space-between;text-align:left;border-top:1px dashed var(--line);padding-top:10px}
  .hq-rack__link{padding:10px 14px;font-size:15px}
}
/* ================= end BATCH 44 COMPONENTS ================= */

/* =====================================================================
   D113a - THE PUBLIC VOICE (de-AI pass, 2026-09-05). Scoped to body.public, which only
   _PublicLayout sets, so the signed-in game is untouched. One heading face the game does not
   load (Archivo Black, linked in _PublicLayout), hard edges instead of radii, no shadows on
   panels, and the browser surfaces themed. Both themes ride the existing tokens.
   ===================================================================== */
body.public{--ff-head:'Archivo Black','Arial Black',Impact,sans-serif}
body.public .btn,body.public .chip,body.public .home-theme,body.public .input,body.public input,body.public select,body.public textarea,
body.public .panel,body.public .table-wrap,body.public .home-nav__link,body.public .home-menu__panel,body.public .home-menu__panel a,
body.public .skip-link,body.public .empty{border-radius:0}
body.public .panel,body.public .home-menu__panel{box-shadow:none}
body.public .doc-title{font-family:var(--ff-head);font-weight:400;letter-spacing:.01em;line-height:1.05}
body.public .doc-page h2.disp{font-family:var(--ff-head);font-weight:400;letter-spacing:.01em;line-height:1.05}
body.public ::selection{background:var(--paper);color:var(--bg)}
body.public :focus-visible{outline:2px solid var(--accent);outline-offset:2px}
body.public .home-nav .btn--primary{font-weight:800}

/* =====================================================================
   BATCH 55 (D119) - THE RANDOM EVENT CARD, "Front Page"
   The approved direction C from docs/design/backstage/random-event-card.html. Not a card at
   all: the event takes the whole screen. A red rule and a dateline across the top, the story
   set large with room around it, the three answers as full-width bands along the bottom where
   a chart table would be, and, on the outcome, the effects in a ledger strip across the foot
   (the stat-bar's caption-over-figure pairing, which is the product's most repeated device).
   Blocking on purpose: no Escape, no backdrop dismiss, the page behind inert, and every other
   page GET redirected server-side. The last answer is always the walk-away.
   ===================================================================== */
body.is-event-open{overflow:hidden}

/* The element paints the whole viewport itself, because a bare <dialog open> is not modal and
   gets no ::backdrop. Identical pixels whether app.js upgraded it to showModal() or not. */
.ev{position:fixed;inset:0;z-index:120;width:100%;max-width:none;height:100%;max-height:none;margin:0;padding:0;
    border:0;border-top:3px solid var(--accent);background:var(--bg);color:var(--paper);
    display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr) auto;overflow:hidden}
.ev::backdrop{background:var(--bg)}
.ev__rule{display:flex;justify-content:space-between;gap:12px;min-width:0;padding:11px 34px;
    border-bottom:1px solid var(--line);font-family:var(--ff-mono);font-size:11px;letter-spacing:.12em;
    text-transform:uppercase;color:var(--paper-3)}
.ev__rule>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* the dateline shortens rather than truncates on a phone (the board's own phone rendering) */
.ev__narrow{display:none}
.ev__story{padding:34px 34px 22px;align-self:center;max-width:900px;overflow:auto}
.ev__title{font-family:var(--ff-disp);font-weight:700;font-size:clamp(34px,4.6vw,52px);line-height:1;
    text-transform:uppercase;letter-spacing:.01em;margin:0 0 14px;text-wrap:balance}
.ev__lede{margin:0;color:var(--paper-2);font-size:15px;line-height:1.5;max-width:50ch}

/* the answers: one form per choice, the button filling it edge to edge */
.ev__bands{border-top:1px solid var(--line-2)}
.ev__band{display:grid;grid-template-columns:56px minmax(0,1fr) auto;align-items:center;gap:16px;width:100%;
    text-align:left;padding:17px 34px;background:transparent;border:0;border-bottom:1px solid var(--line);
    cursor:pointer;font:inherit;color:var(--paper)}
.ev__form:last-child .ev__band{border-bottom:0}
.ev__band:hover{background:var(--surface)}
.ev__band:focus-visible{outline:2px solid var(--accent);outline-offset:-4px}
.ev__bno{font-family:var(--ff-mono);font-size:20px;color:var(--paper-3)}
.ev__band:hover .ev__bno,.ev__band:focus-visible .ev__bno{color:var(--accent)}
.ev__blabel{font-family:var(--ff-disp);font-weight:700;font-size:20px;text-transform:uppercase;
    letter-spacing:.04em;line-height:1.15;min-width:0;overflow-wrap:break-word}
.ev__go{font-family:var(--ff-mono);font-size:14px;color:var(--paper-3)}
.ev__band:hover .ev__go{color:var(--paper-2)}
/* the word, never the odds (Carl, 2026-09-08): the game does not price a gamble for you */
.ev__gamble{display:inline-block;margin-left:9px;vertical-align:2px;font-family:var(--ff-mono);font-size:11px;
    letter-spacing:.08em;text-transform:uppercase;color:var(--warn);border:1px solid var(--warn);
    border-radius:var(--r-pill);padding:1px 7px}

/* the outcome: what you said, what came of it, and the books */
.ev__said{font-family:var(--ff-disp);font-weight:600;font-size:13px;letter-spacing:.12em;text-transform:uppercase;
    color:var(--paper-3);margin:0 0 10px}
.ev__result{font-family:var(--ff-disp);font-weight:700;font-size:clamp(28px,3.4vw,40px);line-height:1.08;
    text-transform:none;letter-spacing:0;margin:0;max-width:26ch;text-wrap:balance}
.ev__ledger{display:flex;flex-wrap:wrap;border-top:1px solid var(--line-2);background:var(--surface)}
.ev__ledger>div{flex:1 1 170px;min-width:0;padding:15px 20px;border-left:1px solid var(--line)}
.ev__ledger>div:first-child{border-left:0;padding-left:34px}
.ev__ledger .k{font-family:var(--ff-disp);font-size:10.5px;font-weight:600;letter-spacing:.14em;
    text-transform:uppercase;color:var(--paper-3)}
.ev__ledger .v{font-family:var(--ff-mono);font-size:20px;margin-top:4px;line-height:1.2}
.ev__ledger .v--good{color:var(--fx-good)}
.ev__ledger .v--bad{color:var(--fx-bad)}
.ev__ledger .ev__act{flex:0 0 auto;display:flex;align-items:center;padding-right:34px}

/* the rest of the day, on /status: the same red rule, nothing boxed */
.ev-after{display:flex;align-items:center;flex-wrap:wrap;gap:12px;border-top:2px solid var(--accent);
    padding:11px 0;margin-bottom:20px;font-size:13.5px;color:var(--paper-2)}
.ev-after b{color:var(--paper)}
.ev-after .mono{font-family:var(--ff-mono);color:var(--paper)}
.ev-after__spacer{flex:1}

/* The ledger stacks earlier than the rest of the card: seven catalogue outcomes carry four
   effects, and four cells plus the button will not hold one line much under 900. */
@media (max-width:900px){
  .ev__ledger{display:grid;grid-template-columns:1fr 1fr}
  .ev__ledger>div{border-left:0;border-top:1px solid var(--line);padding:13px 20px}
  .ev__ledger>div:first-child{padding-left:34px}
  /* An odd number of effects leaves the last one alone in column one with a rule that stops
     halfway across. The action cell is always last, so this selects exactly that orphan. */
  .ev__ledger>div:nth-last-child(2):nth-child(odd){grid-column:1/-1}
  .ev__ledger .ev__act{grid-column:1/-1;padding:13px 34px}
  .ev__ledger .ev__act .btn{width:100%}
}
@media (max-width:640px){
  .ev__wide{display:none}
  .ev__narrow{display:inline}
  .ev__rule{padding:10px 18px;letter-spacing:.08em}
  .ev__story{padding:24px 18px 18px}
  .ev__title{font-size:32px}
  .ev__lede{font-size:15.5px}
  .ev__band{padding:15px 18px;grid-template-columns:34px minmax(0,1fr) auto}
  .ev__bno{font-size:16px}
  .ev__blabel{font-size:17px}
  .ev__result{font-size:26px}
  .ev__ledger>div{padding:12px 18px}
  .ev__ledger>div:first-child{padding-left:18px}
  .ev__ledger .ev__act{padding:12px 18px}
}
/* ================= end BATCH 55 COMPONENTS ================= */

/* =====================================================================
   D122 (BATCH 58) - THE DRAWN ICON SET
   36 icons live as <symbol> geometry in Kit/_IconSprite.cshtml and are
   rendered through Kit/_Icon.cshtml. Every stroke attribute lives HERE,
   not in the sprite, so one icon is currentColor at whatever size the
   label beside it is. Square terminals: The Galley is hard-edged, and
   this is the set's one deliberate departure from the sign-out icon.
   ===================================================================== */
.icon-sprite{position:absolute;width:0;height:0;overflow:hidden}
.ic{display:inline-block;vertical-align:-.15em;flex:none;width:1em;height:1em;
  fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4}

/* The first .sr-only in the codebase (there was none before D122). Standard clip-rect: gone
   from the page, present in the accessibility tree. Used wherever an icon now stands alone. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* The hover explanation, desktop only (D122). The rule that keeps it from becoming noise: an
   icon gets a tooltip ONLY where the picture is the only signal. Beside its own word - a panel
   head reading "Honours", a chip reading "Playlist pitch" - it gets nothing, because a tooltip
   there just repeats the word next to it. Never a native title= as well, or the browser draws
   a second tooltip on top of this one. The bubble is a panel in the game's own language:
   hairline border, flat lifted ground, hard corners, no shadow. */
/* D130 - the bubble itself is no longer scoped to a fine pointer, only its TRIGGER is. D122's
   scoping was right as far as it went (a hover explanation cannot fire on a touch screen and
   this one provably did not), but it left a phone player with a drawing and 382 written
   explanations none of which could be read anywhere in the product. The appearance is declared
   once here; a mouse opens it on hover, a finger opens it on a tap (app.js sets .is-tip-open). */
.ic-t{display:inline-flex;align-items:center}
.ic-t[data-tip]{position:relative}
/* D130 - display:none, not visibility:hidden. A closed bubble used to sit in the layout at
   opacity 0, and an absolutely positioned box that is merely invisible STILL counts toward the
   page's scrollable width: with the bubble live on a touch device, a 17rem line hanging off an
   icon dragged every signed-in page 76px sideways at 360. It is laid out only while it is open,
   which is also why the fade is an animation rather than a transition - a transition cannot run
   out of display:none. */
.ic-t[data-tip]::after{
  content:attr(data-tip);
  display:none;
  position:absolute;bottom:calc(100% + 8px);left:0;
  z-index:40;width:max-content;max-width:min(17rem,58vw);
  padding:7px 10px;
  background:var(--surface-3);border:1px solid var(--line-2);border-radius:0;box-shadow:none;
  font-family:var(--ff-body);font-size:12.5px;font-weight:400;line-height:1.4;
  letter-spacing:normal;text-transform:none;text-align:left;white-space:normal;
  color:var(--paper-2);
  pointer-events:none;
}
/* Alternative text of "" so the generated bubble is never announced: the accessible name is
   the .sr-only word inside the wrapper, and nothing announces its meaning twice. */
@supports (content:"a" / "b"){
  .ic-t[data-tip]::after{content:attr(data-tip) / ""}
}
/* A control sitting at the right edge of its panel anchors the bubble to that edge instead,
   or a 17rem line centred on a 30px button would run off the side of the window. */
.ic-t--end[data-tip]::after{left:auto;right:0}
/* A finger opens it (app.js). A mouse keeps the fade, because the pointer arrives before the
   bubble does and an instant one reads as a flicker; a tap does not have that problem. */
.ic-t[data-tip].is-tip-open::after{display:block}
@media (hover:hover) and (pointer:fine){
  .ic-t[data-tip]:hover::after{display:block;animation:tip-in .12s ease-out}
}
@keyframes tip-in{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion:reduce){
  .ic-t[data-tip]:hover::after{animation:none}
}
/* Contextual sizes and inks. An icon is 1em of the block it sits in, which is right almost
   everywhere; these are the places where the glyph it replaced was deliberately larger or
   quieter than its own text, and the block keeps that presence. The three system hues appear
   only where the block's own rail already names that system. */
.feed-ic{display:flex;align-items:center;align-self:flex-start;flex:none;padding-top:2px;color:var(--paper-3)}
.feed-ic .ic{width:17px;height:17px}
.wave-strip>.ic-t,.wave-strip>.ic{flex:none;color:var(--wave)}
.wave-strip>.ic-t .ic,.wave-strip>.ic{width:20px;height:20px}
.ach-strip>.ic{width:20px;height:20px;flex:none;color:var(--patron)}
.hall-recent__row>.ic{width:15px;height:15px;align-self:center;color:var(--patron)}
.hq-attn__item>.ic{width:16px;height:16px;flex:none;color:var(--lbl)}
.hq-attn__item--warn>.ic{color:var(--warn)}
.lbl-dash__title .ic{color:var(--lbl)}
.lbl-dash__row .ic{color:var(--bad)}
.rival-round__icon .ic{color:var(--paper-4)}
.rival-notice__glyph .ic{width:1em;height:1em}
.page-title .ic{width:26px;height:26px}
.btn .ic{width:1.05em;height:1.05em}
.btn--sm .ic{width:15px;height:15px}
.chip .ic,.reach-chip .ic{width:14px;height:14px;vertical-align:-.25em}
.stat__label .ic,.cabinet-nom__meta .ic{width:13px;height:13px;vertical-align:-.2em}
.lbl-board__trophy{font-size:14px;margin-left:6px}
/* A panel head is a space-between flex row, so a leading icon would be flung to the far left
   with its own words stranded at the far right. Where a head carries one, the row packs from
   the start and only a trailing control keeps the right edge. Same for .between rows. */
.panel__head:has(>.ic),.between:has(>.ic){justify-content:flex-start;gap:9px}
.panel__head:has(>.ic)>:last-child:not(.ic),.between:has(>.ic)>:last-child:not(.ic){margin-left:auto}
/* ================= end D122 ICON SET ================= */

/* =====================================================================
   BATCH 59 (D123) - "THE GALLEY", the whole signed-in game
   Carl's pick from docs/design/backstage/in-game-direction.html (direction A). The box is
   deleted. A panel stops being a container and becomes a region of the page: a 2px paper rule
   announces it, hairlines separate its rows, and one flat ground runs from the sidebar to the
   edge. The three dashboard stacks are held apart by vertical column rules, which is the trade
   paper's own device and the thing that replaces the borders. It is the grammar of the random
   event card (D119) at page scale, so the newest surface stops being the exception.

   Most of the direction rides the four theme blocks at the top of this file (the radii to 0,
   both shadows to none, --surface-2 aliased to --bg). Sections 1-11 are the component rules the
   board named, plus the places a flat, boxless language needs a real answer rather than a token:
   a dense table with no container, a form that loses the grouping the box was doing, two blocks
   whose rules would otherwise stack into a 4px bar, and a wrapping grid whose column rule would
   land in the wrong place.

   Section 12 is what the RUNNING APP showed that the CSS could not: a-f from the first pass,
   g-k from the second, and g is the big one - twenty-odd components that never used .panel or
   .card at all, wrote the box out longhand, and were left by the token pass as empty hairline
   rectangles ruled onto the page with nothing inside them.

   Scope. body.public (D113a) is the sibling voice on the same tokens and must not move. It
   rarely uses .panel or .card, but --surface-2 is a TOKEN, so the alias reached every longhand
   `background: var(--surface-2)` in the file including six logged-out components. Section 13
   restores them by name from --surface-panel, and the public captures are pixel-identical
   before and after this batch.
   ===================================================================== */

/* ---- 1. The block: a rule, not a box -------------------------------------
   .panel and .card lose their border, their fill and their padding. What is left is a 2px
   paper rule on top, the head as a ruled caption under it, and the body running to the
   block's own edges, which is why the padding is vertical only: on a flat ground the page's
   left margin is the only left edge there is, and every block shares it.
   More space above a rule than below it - the 20px foot plus the stack's 16px gap opens 36px
   before the next block announces itself, against 16px from the rule down to its first line.

   THE CLEARANCE UNDER THE RULE (padding audit, 2026-09-09). This block's top edge went from a
   1px hairline to a 2px paper rule, and the caption's clearance went the other way: measured
   live, the rule sat 10px off the caption where the hairline had sat 15px off it. Twice the
   weight and a third less air, on the component that repeats more than any other in the game.
   The note above claimed 14px, and that was only ever true of a HEADLESS panel - a panel WITH
   a head got 9px, which is the case the note did not cover and the reason it was not caught.
   A heavier rule needs more distance, not less, so the whole block goes back to the pre-pass
   scale and the four shapes now share one body rhythm (16 down from the rule, 20 to the foot,
   the same numbers .frame .page already used). The caption keeps more room above it than below
   it, because that is the rule this direction is built on. */
.panel,.card{background:none;border:0;border-top:2px solid var(--paper);padding:0}
.panel__head{padding:13px 0 9px;font-size:12.5px;border-bottom:1px solid var(--line)}
.panel__body{padding:16px 0 20px}
.card{padding:16px 0 20px}
/* A block inside a block drops to a hairline. Two paper rules stacked read as one 4px bar and
   the nesting disappears; a hairline says "still inside the block above". */
.panel__body .panel,.panel__body .card,.card .panel,.card .card,
.frame .panel,.frame .card{border-top:1px solid var(--line-2)}
/* The gradients the box used to need. Every one of these was depth on a raised plane and there
   is no raised plane any more. (The artwork hatch and the awards ceremony keep theirs: see the
   note on kept strays in D123.) */
.card--raised{background:none}
.card--patron{background:none;border-top-color:color-mix(in srgb,var(--accent),transparent 55%)}
.doc-header,.hero,.auth-stage{background:var(--bg)}
/* A modal is the one thing that genuinely floats, because the page behind it is still there.
   It keeps a fill and an edge, squared, and takes the block's rule so it speaks the language. */
.dialog{background:var(--surface);border-top:2px solid var(--paper)}

/* ---- 2. A dense table with no container ---------------------------------
   /charts/singles is forty rows in a .panel that no longer has sides. The cells' own 16px
   inset was measured from a border that is gone, so the first column floated a centimetre in
   from the page margin while the block's rule started at it. Zeroing the outer inset lands the
   rank column on the same left edge as every heading on the page, which is what a chart table
   in a trade paper actually does. The rule above the head, the hairline under it and the row
   hairlines then read as one ruled column of record. */
.panel .table th:first-child,.panel .table td:first-child{padding-left:0}
.panel .table th:last-child,.panel .table td:last-child{padding-right:0}
/* The pack divider spans every column, so it is both first and last child: give it its inset
   back, or the caption starts under the rank numerals instead of beside them. */
.panel .table .chart-break td{padding-left:12px;padding-right:12px}

/* ---- 3. The feed: a list, not twenty blocks -----------------------------
   The feed is a .stack of headless panels nine pixels apart. Twenty 2px paper rules at that
   spacing is a zebra, not a page. A tight stack of headless blocks IS a list, so it takes the
   list's grammar instead: no gap, a hairline under each row, the last rule closing it. */
.feed-list{gap:0}
.feed-row{border-top:0;border-bottom:1px solid var(--line)}
.feed-row>.panel__body{padding:10px 0}

/* ---- 4. The dashboard column rules --------------------------------------
   The board's own honest risk: with no borders the three stacks depend entirely on the column
   rules, and a column rule cannot be drawn correctly on an auto-fit grid, because the rule
   lands on the first item of every wrapped row as well. The answer is the explicit column
   count the board offered - three, two, one - so the rule can be switched off per row.
   The 3-up threshold moves from ~1008px to 1100px: the column padding is real width, and at
   1024 three columns leave 216px of content each, under the 230px the layout was built for. */
.grid--auto-tight{grid-template-columns:repeat(3,minmax(0,1fr));gap:0}
.grid--auto-tight>*{padding:0 22px;border-left:1px solid var(--line)}
.grid--auto-tight>*:first-child{padding-left:0;border-left:0}
.grid--auto-tight>*:last-child{padding-right:0}
@media (max-width:1100px){
  .grid--auto-tight{grid-template-columns:repeat(2,minmax(0,1fr));row-gap:26px}
  .grid--auto-tight>*:nth-child(odd){padding-left:0;border-left:0}
  .grid--auto-tight>*:nth-child(even){padding-right:0}
}
@media (max-width:640px){
  .grid--auto-tight{grid-template-columns:minmax(0,1fr);gap:26px 0}
  .grid--auto-tight>*{padding:0;border-left:0}
}

/* ---- 5. The shell on a flat ground --------------------------------------
   The sidebar keeps --surface and the hovered row keeps --surface-3, so the two planes that
   are genuinely not the page stay legible. Everything between them flattens. */
.topbar{background:var(--surface)}
.avatar{background:var(--surface-3)}
.vitals-strip{background:none;padding:8px 24px}
/* The stat bar stops being a boxed group and becomes ruled cells, which is the same device as
   the dashboard columns and the event card's ledger strip. */
.stat-bar{border:0;border-left:1px solid var(--line);background:none}
.stat{border-right:0;border-left:1px solid var(--line);padding:5px 18px}
.stat:first-child{border-left:0}

/* ---- 6. The full-width strips -------------------------------------------
   Several components were the same shape: a boxed strip with a 3-4px coloured rail down its
   left side. In this language a block is announced from the top, so the rail rotates: same
   hue, same meaning, 2px across the top, no box. */
.season-strip,.ach-strip,.wave-strip,.ach-next,.hq-attn__item,.lbl-dash,.wave-banner,.hq-danger{
  background:none;border:0;padding-left:0;padding-right:0}
.season-strip{border-top:2px solid var(--paper);padding:11px 0 12px}
.season-strip::before{display:none} /* the fake ticket notch: a punched circle on a squared world */
.ach-strip{border-top:2px solid var(--patron);padding:11px 0 12px}
.wave-strip,.wave-banner{border-top:2px solid var(--wave);padding:11px 0 12px}
.ach-next{border-top:2px solid var(--accent);padding:11px 0 13px}
.lbl-dash{border-top:2px solid var(--lbl);padding:13px 0 16px}
.hq-attn{gap:0}
.hq-attn__item{border-top:1px solid var(--lbl);padding:10px 0}
.hq-attn__item--warn{border-top-color:var(--warn)}
.hq-attn__item--bad{border-top-color:var(--bad)}
.hq-danger{border-top:2px solid var(--bad);padding:14px 0 16px}
/* The alert is the last of that family: same strip, same left rail, same answer. It keeps its
   ink and gains the rule, so a warning still reads as a warning without a box around it. */
.alert{background:none;border:0;border-top:2px solid var(--paper-4);padding:11px 0;align-items:flex-start}
.alert--good{border-top-color:var(--good)}
.alert--warn{border-top-color:var(--warn)}
.alert--bad{border-top-color:var(--bad)}
.alert--accent{border-top-color:var(--accent)}

/* ---- 7. Meters ----------------------------------------------------------
   A 9px track with a pill cap was a capsule. Four pixels of --line with a square end is a
   printed bar. Every meter in the game is one of nine shapes; they all take the same one. */
.meter__track,.vs-track,.onboard-bar,.gain-meter__track,.lbl-recoup__bar,
.ach-next__meter,.ach-card__meter,.ach-strip__meter,.ach-hero__meter{
  height:4px;background:var(--line);border:0;border-radius:0}
.meter__track--delta{height:8px;background:var(--bg)} /* the before/after comparison keeps its mass */
.gain-meter__fill{background:var(--accent);border-radius:0}
.lbl-recoup__fill{background:var(--lbl);border-radius:0}
.lbl-recoup__fill.is-done{background:var(--good)}
.track__bar{height:4px}

/* ---- 8. Chips: an outline, not a capsule --------------------------------
   The pill is gone with --r-pill, and a filled grey rectangle reads as a button. An outlined
   chip is a tag. The tinted states keep their fill and lose the outline, because a fill and an
   outline on the same 11px object is two signals for one fact. */
.chip{background:none;border:1px solid var(--line-2);color:var(--paper-2)}
.chip--up,.chip--down,.chip--accent{border-color:transparent}
.chip--accent{background:var(--accent);color:var(--accent-ink)}

/* ---- 9. The form, which is what the box was really holding together -----
   /settings/band is a 15-page archetype: .frame wraps a two-column field grid and a footer of
   actions. Delete the box and the fields float, so the grouping moves onto the type and the
   rules. The frame keeps a paper rule on top; each column's .label-strong becomes a ruled
   caption exactly like a panel head; the action bar loses its fill and closes the block with a
   hairline. The controls themselves stay boxed: a box you can type in is an affordance, not
   decoration, and the public voice kept its inputs boxed for the same reason. */
.frame{background:none;border:0;border-top:2px solid var(--paper);box-shadow:none}
.frame .page{padding:16px 0 20px}
/* The first page's own 14px under the frame's 2px rule is gone with it: every block in the
   game now opens 16px under its rule, and an override that argues for less on the heaviest
   rule of the lot is the same mistake the panel head made. */
.frame .label-strong{border-bottom:1px solid var(--line);padding-bottom:6px;margin-bottom:12px}
.form-bar{background:none;border-top:1px solid var(--line-2);padding:16px 0 0}
/* An option list is the event card's answer bands at a smaller size: full-bleed rows with a
   hairline between them. The hovered and chosen states are in section 13: this line originally
   reached for tone, and a row with no side inset cannot hold one. */
.stack:has(>.opt-card){gap:0}
.opt-card{background:none;border:0;border-bottom:1px solid var(--line);padding:13px 0}
/* The wizard's step marker squares with everything else. The radio's circle does NOT: a circle
   means "choose one of these" and a square means "choose any of these" in every operating
   system there is, and a direction does not get to overrule an affordance. */
.step__num{border-radius:0}

/* ---- 10. The bespoke slabs ----------------------------------------------
   Seven components were built as their own raised card: a tinted gradient, a hairline box, a
   radius and a shadow. Their gradients are deleted where they are declared (each one carries a
   D123 note there, so the reason is next to the rule that lost it); what is left here is the
   replacement, which is the same one every other block gets - a rule on top, in the hue that
   already names that system, and nothing else. */
.cmp-head,.lbl-head,.chart-no1,.hall-champ,.hq-head,.lbl-patron-gate,.collab-toggle,.ach-mast{
  background:none;border:0;border-top:2px solid var(--line-2);box-shadow:none;
  padding-left:0;padding-right:0}
.lbl-head,.hq-head{border-top-color:var(--lbl)}
.chart-no1{border-top-color:var(--accent)}
.hall-champ{border-top-color:var(--patron)}
.lbl-patron-gate{border-top-color:var(--patron)}
.ach-mast{border-top-color:var(--paper);padding-top:12px;padding-bottom:13px}
/* The achievement cards and their drill-through hero carried the same 4-6px coloured left rail
   as the dashboard strips, and get the same answer: the rail rotates to the top and the box
   goes. The earned tint stays, because on a grid of forty entries the fill is what lets you
   see at a glance how much of the wall you own. */
.ach-card{border:0;border-top:3px solid var(--tier,var(--line-2));padding:12px 0 14px}
.ach-card--unclaimed{border-top-style:dashed}
.ach-hero{border:0;border-top:3px solid var(--tier,var(--line-2));padding:16px 0 18px}
/* The earned tint goes with the box that held it. A card with no side padding cannot carry a
   fill: on the wall the earned entry's title started ON the tint's left edge and its "Earned"
   line ended ON the right one. It is not needed either - across forty entries the tier's SOLID
   coloured rule against an unclaimed DASHED grey one is a stronger at-a-glance read than an
   eight-percent wash, and it is the read this direction is built on. */
.ach-card--earned,.ach-hero--earned{background:none}
/* The label distress ladder is an alert wearing a card. Same family, same rule. */
.lbl-distress{background:none;border:0;border-top:2px solid var(--warn);padding:12px 0;box-shadow:none}
.lbl-distress--critical{border-top-color:var(--bad)}

/* ---- 11. The two deliberate exceptions ----------------------------------
   The certification badge keeps its pill and its 7px round pip. Carl decided that: a certifi-
   cation is an award from outside the game's own furniture and it is allowed to look like one,
   the way a stamp on a sleeve does. It is the one round object left in the signed-in game, and
   it is round on purpose rather than by omission. (.cert i is already a literal 50%.)
   The second exception is not CSS: the typographic glyphs - the arrows and triangles in the
   chart movement column, the hold circle, the brand diamond, the check marks, the cross, the
   theme toggle's sun and moon, the patron star - are type, not icons, and were left alone in
   D122 and again here. */
.cert{border-radius:999px}

/* ---- 12. What the inspection round found --------------------------------
   Six places where the flat language broke on a real page rather than in theory. Each one is a
   fix, not a softening: the direction stands and the page was wrong.

   a. The two-pane action archetype (/practice, /rest, /tour). A .page inside a frame loses its
   side padding so the fields line up with the frame's rule - but both halves of the split ARE
   .page, so the left column's right-hand figures ("Free", "uses health") ran straight into the
   divider and were painted over by the right pane. The gutter comes back around the rule, and
   the right pane's raised fill goes with every other raised plane: the column rule separates
   them now, exactly as it does on the dashboard. */
.frame .action-split__form{padding-right:24px}
.frame .action-split__result{padding-left:24px;background:none}

/* b. Two lists that were still stacks of boxes. An option list and a tracklisting are lists;
   with the box gone they were hairline rectangles floating eight pixels apart. Closed up, they
   are the ruled rows the rest of the game reads in. */
.venue-list{gap:0}
.tracklist{gap:0}
.track{background:none;border:0;border-bottom:1px solid var(--line);border-radius:0;padding:11px 0}

@media (max-width:640px){
  /* c. The two-pane split stacks, so the gutter is not needed and the room is. */
  .frame .action-split__form{padding-right:0}
  .frame .action-split__result{padding-left:0}
  /* d. The dashboard strips. At 390 the sentence was crushed into a two-word column beside a
     fixed 110px meter and a button. Icon and sentence take the first row; the meter and the
     control share the second. (The board called this one before the batch started.) */
  .ach-strip,.wave-strip{flex-wrap:wrap}
  .ach-strip__text,.wave-strip__text{flex:1 1 240px}
  .ach-strip .btn,.wave-strip .btn{order:4;flex:none;margin-left:auto}
  /* The meter goes rather than wraps. Its sentence already ends "(82 / 90)", so on a phone the
     bar is the same fact drawn twice and the row is 40px shorter without it. */
  .ach-strip__meter{display:none}
  /* e. The chart's No.1 throne. Three flex children on a 342px line left the title 56px wide
     and it spilled out of its own column. The run of figures takes the second row. */
  .chart-no1__art{width:72px;height:72px}
  .chart-no1__stats{flex:1 1 100%;text-align:left;line-height:1.7}
  /* f. The wizard stepper (/tour). Three uppercase labels that must not wrap need 325px of the
     342 there are, so the last one hung off the edge. On a phone the numerals carry the
     sequence and only the step you are on says its name - which the page sub-heading is
     already saying in words anyway ("Step 1 of 3 - where, and how many gigs?"). */
  .stepper{max-width:none}
  .step{flex:none;gap:9px}
  .step__label{display:none}
  .step.is-active{flex:1;min-width:0}
  .step.is-active .step__label{display:block;overflow:hidden;text-overflow:ellipsis}
  .step__line{flex:0 0 14px;margin:0 2px}
}

/* g. THE BOXES THE TOKENS COULD NOT REACH, and the biggest find of the pass.
   Twenty-odd components were never built as a .panel or a .card: each wrote the box out
   longhand, as a --surface-2 fill, a hairline all the way round, a radius and a shadow. The
   token pass took the radius, the shadow and the fill (--surface-2 IS the ground now) and left
   the hairline behind, so on a real page they rendered as empty rectangles ruled onto the page
   with nothing inside them - the one thing a boxless language has no room for. They sort into
   three shapes and take the three answers the rest of this batch already uses.

   A repeated row in a stack is a LIST ROW: no box, a hairline underneath, the stack closed up.
   Same grammar as the feed and the tracklisting, and it is what /collabs, /search and a label's
   public roster were all reaching for. */
.stack:has(>.collab-row),.stack:has(>.finder-card),.stack:has(>.lbl-signee),.pick-list{gap:0}
.collab-row,.finder-card,.search-hit,.lbl-signee,.pick{
  background:none;border:0;border-bottom:1px solid var(--line);box-shadow:none}
.collab-row{padding:11px 0}
/* The partner finder's own rhythm was leaning on the card (padding audit, 2026-09-09). Its
   4px row gap was tuned to sit inside 12px of card padding; with the padding gone the gap is
   doing all the work and three lines of a list row sat four pixels apart. It is also why the
   "Propose" button crowded the band name at 390: the button spans all three rows and centres
   itself in them, so a card that lost 18px of height pulled it up level with the name. Nine
   pixels between the rows is the row's own rhythm and gives the button its centre back. */
.finder-card{padding:13px 0;row-gap:9px}
.search-hit{padding:11px 0}
.lbl-signee{padding:13px 0 12px}
.lbl-signee__since{right:0}
.pick{padding:10px 0}
/* The chosen row is marked in section 13. It takes the accent hairline but not the rule on top
   that .opt-card gets: this list is "choose any of these", not "choose one". */

/* A block with its own head and foot is a BLOCK: the 2px rule on top in the hue that already
   names it, the sides gone, the inner strips keeping their vertical rhythm and losing their
   horizontal inset so every line starts on the page's own left edge. */
.collab-offer,.lbl-offer,.hq-contract,.trk-list{
  background:none;border:0;border-top:2px solid var(--paper);box-shadow:none;overflow:visible}
.lbl-offer,.hq-contract{border-top-color:var(--lbl)}
.collab-offer__head,.collab-terms,.collab-offer__foot,.collab-tracklist,.split-hero,
.lbl-offer__head,.lbl-offer__foot,.hq-contract__head,.hq-contract__earned,.hq-contract__foot,
.trk-row{padding-left:0;padding-right:0}
.lbl-offer__msg{margin-left:0;margin-right:0}
.trk-list{margin-bottom:12px}

/* A cell in a grid of cells is a CELL: the same rule on top, the grid gap doing the separating.
   Side by side their rules line up into one ruled row across the page, which is the rack the
   dashboard columns already make - the zebra only happens when blocks STACK. */
.lbl-card,.cabinet-band,.hq-sum__col,.lbl-stat{
  background:none;border:0;border-top:2px solid var(--paper);box-shadow:none;padding:13px 0 15px}
.lbl-card{border-top-color:var(--lbl)}
/* Nested, every one of these drops to a hairline for the reason .panel and .card do: two rules
   twelve pixels apart read as one bar and the nesting disappears. */
:is(.panel__body,.card,.frame) :is(.collab-offer,.lbl-offer,.hq-contract,.trk-list,.lbl-card,
  .cabinet-band,.hq-sum__col,.lbl-stat){border-top:1px solid var(--line-2)}
/* The split slider is a CONTROL GROUP inside a panel body, not a block: its panel head has
   already ruled it, so a rule of its own was the double bar this batch keeps hunting. */
.share-field{background:none;border:0;box-shadow:none;padding:10px 0 0}
/* A hover that lifted a card by a pixel has nothing left to lift, so it moves to the ink. */
.lbl-card:hover,.cabinet-band:hover{transform:none}
.lbl-card:hover{border-top-color:var(--lbl)}
.lbl-card:hover .lbl-card__name{color:var(--lbl)}
.cabinet-band:hover{border-top-color:var(--paper-4)}
/* A single mono readout is a LINE, so it takes a hairline and no box at all. */
.cost-line{background:none;border:0;border-top:1px solid var(--line);padding:8px 0}
.wave-admin__live{background:none;border:0;border-top:2px solid var(--wave);padding:10px 0}

/* h. The promotion list, and every other tight stack of headless blocks. The feed was fixed by
   name in section 3, but the shape is general: /promote, /admin, /changelog and the label pages
   all stack headless panels nine pixels apart, and nine 2px paper rules down a page is a zebra
   rather than a list. A headless panel in a tight stack is a list row and takes the list's
   grammar; a panel WITH a head is a real block and keeps its rule. */
.stack.g-9:has(>.panel:not(:has(>.panel__head))){gap:0}
.stack.g-9>.panel:not(:has(>.panel__head)){border-top:0;border-bottom:1px solid var(--line)}
.stack.g-9>.panel:not(:has(>.panel__head))>.panel__body{padding:11px 0}

/* i. The empty state was mostly box: a dashed rectangle whose fill has gone, floating on the
   ground. A rule of its own would only double the one above it - an empty state is always
   inside a block that has already announced itself, and on the eight pages that show one it sat
   twelve pixels under a panel head. So the rectangle goes and nothing replaces it: the rotated
   mark and the centred line are the whole state, and the room around them is the signal. Same
   for the release wizard's "no tracks yet" placeholder, and for the dashed callouts that were
   the same shape - the certification note under a release and the label founding fee. */
.empty{border:0;padding:26px 0 30px}
.trk-empty{border:0;border-radius:0;padding:16px 0}
.search-empty{background:none;border:0;padding:24px 0}
.cert-note{background:none;border:0;border-top:1px dashed var(--line-2);padding:11px 0}
.lbl-fee{background:none;border:0;border-top:1px dashed var(--line-2);padding:12px 0}
/* The licence gate is a whole page saying one thing. Its 520px cap left a short gold rule flush
   with the page margin and the copy centred under it, which agreed with nothing; the block runs
   the full measure like every other block and the copy stays centred inside it. */
.lbl-patron-gate{max-width:none}
/* A grid of figures is the stat bar's job, not a rack of blocks: five 2px paper rules with gaps
   between them, wrapping to two more, read as a broken line rather than a row of cells. The
   hairline says "cell" and survives the wrap. */
.grid--stats>.card{border-top:1px solid var(--line-2);padding:9px 0 12px}

/* j. The alert stops borrowing the accent. A 3px rail forty pixels tall could afford to be red;
   the same rail rotated to 2px across the full measure cannot, and on /status it landed
   directly above the event card's own red rule, which is the signature this whole direction is
   built from. An informational note is not the product's one raised voice (DESIGN.md, The One
   Voice Rule), so a loud note takes the paper rule every block gets and a quiet one keeps the
   dimmest neutral. Good, warn and bad keep their hues: a warning has to be seen. */
.alert--accent{border-top-color:var(--paper)}

/* k. The native file button was the only white object left in the dark theme. Nothing in this
   batch created it, but flattening everything around it is what made it shout, and a control
   the browser drew still has to carry the design (it is the secondary button, in miniature). */
input[type=file]{font-size:13px;color:var(--paper-3);max-width:100%}
input[type=file]::file-selector-button{font-family:var(--ff-disp);font-weight:600;font-size:12.5px;
  letter-spacing:.05em;text-transform:uppercase;background:var(--surface-3);border:1px solid var(--line-2);
  color:var(--paper);padding:7px 14px;margin-right:12px;cursor:pointer}
input[type=file]::file-selector-button:hover{border-color:var(--paper-4)}
/* The range slider carries a 2px UA margin on each side. A boxed form had padding to hide it
   in; a form whose fields start at the page's own left edge does not, so the slider sat two
   pixels off the rule above it and lost two off its right end inside the frame's clip. Found by
   the DOM sweep at 390 on /practice, /rest and the release wizard, not by eye. */
input[type=range]{margin-left:0;margin-right:0;max-width:100%}

/* ---- 13. The marked row: ink and a rule, not a fill ---------------------
   Sections 2 and 9 zeroed the outer inset of a table cell and of an option row so the rank
   numeral would land on the page's own left margin. Four states went on painting a fill across
   that same measure, so on /rankings the numeral sat ON the tint's left edge and the money
   figure ON its right, and on /practice the radio pip sat on top of the chosen row's accent
   tick. This batch had already written the governing line for the achievement wall - A CARD
   WITH NO SIDE PADDING CANNOT CARRY A FILL - and then applied it to that one component.
   Carl's decision (2026-09-09): finish the move. Restoring the inset on the tinted row only
   was the option to avoid, because it would have pushed the marked row's numerals out of line
   with every other row's down the column, which is worse than the defect.

   So a marked row is announced the way a block is: a rule in the hue that names the state, and
   the row's own ink. Two steps of one grammar -
     hovered      a 1px --paper-3 rule above and below, a reader's ruler laid on the line;
     yours        a 2px --accent rule above, an accent hairline below, the row lifted to full
                  ink at 500 (on /rankings the numeral is a muted tc-paper-3, so brightening
                  it IS the colour half of the signal - the band link was never one, since
                  every link in the table is already accent);
     chosen       the same accent rule and hairline, plus the radio or checkbox that was
                  always the real answer.
   The 2px accent tick that used to run down the chosen row's left edge is not deleted, it is
   rotated: "every coloured left rail rotates to the top" was this batch's own rule, and the
   option row is the one place it was not applied - which is how it ended up under the radio.
   Nothing moves. A collapsed table recolours the border it already shares with its neighbour;
   a row that owns only a bottom border draws its top one as an inset rule, the way every other
   tick in this direction is drawn, and the row above stands its hairline down so the two do
   not stack into one thick line. */
.table tbody tr:where(:hover,:has(+tr:hover))>td{border-bottom-color:var(--paper-3)}
.table thead:where(:has(+tbody>tr:first-child:hover)) th{border-bottom-color:var(--paper-3)}
.table tbody tr.is-you>td{border-top:2px solid var(--accent);border-bottom-color:var(--accent);
  color:var(--paper);font-weight:500}
.opt-card:where(:has(+.opt-card.is-selected)){border-bottom-color:transparent}
.opt-card:where(:hover,:has(+.opt-card:hover)){border-bottom-color:var(--paper-3)}
.opt-card:hover .opt-radio{border-color:var(--paper-2)}
.opt-card.is-selected{border-bottom-color:var(--accent);box-shadow:inset 0 2px 0 var(--accent)}
/* A pick list is "choose any of these", so several rows can be chosen at once and a rule on
   top of each would read as a barcode. It takes the accent hairline and the brighter ink only,
   and the checkbox - which is the affordance, already accent when it is checked - says the
   rest. (Nested :has() is illegal, so the stand-down above has no equivalent here anyway.) */
.pick:has(input:checked){border-bottom-color:var(--accent)}

/* ---- 14. The public voice, restored -------------------------------------
   body.public rides the same tokens and gains the squared corners for free, but a few of the
   rules above would reach it. Its own D113a decisions win: the FAQ's jump chips stay filled,
   its captions are already ruled by .faq-cat, and the auth pages keep their card. */
/* The alias that dissolved a panel's fill reaches further than .panel: it is a token, so every
   longhand `background: var(--surface-2)` in the file went to the ground with it - and six of
   those are logged-out components that D113a deliberately left as boxes. A public page must not
   move in this batch, so they take the retired panel tone back BY NAME (--surface-panel), which
   is why that token exists. Caught by diffing the public captures against the pre-batch set:
   the About story card and the auth card had quietly lost their fill, and the mobile menu had
   gone transparent over the page behind it. */
.auth-card,.home-menu__panel,.home-rivalry__card,.home-shot,.season-ticket,.story-shot,.story-cta{
  background:var(--surface-panel)}
.home-chart__art--none{background-image:repeating-linear-gradient(135deg,var(--surface-panel),
  var(--surface-panel) 11px,var(--surface-3) 11px,var(--surface-3) 22px)}
/* border:0, not border-color:transparent - the incumbent public chip has no border at all, and
   a transparent one still takes its two pixels, which grew the FAQ's jump row and with it the
   whole page by 2px. Caught by the same pixel diff. */
body.public .chip{background:var(--surface-3);border:0;color:var(--paper-3)}
body.public .frame .label-strong{border-bottom:0;padding-bottom:0;margin-bottom:6px}
/* impeccable-disable-next-line side-tab -- the incumbent public alert, held still by D123's scope */
body.public .alert{background:var(--surface-2);border:1px solid var(--line-2);border-left:3px solid var(--paper-4);padding:11px 15px;align-items:center}
body.public .alert--good{border-left-color:var(--good)}
body.public .alert--warn{border-left-color:var(--warn)}
body.public .alert--bad{border-left-color:var(--bad)}
body.public .alert--accent{border-left-color:var(--accent)}
body.public .frame{border-top:0}
body.public .frame .page{padding:24px}
/* ================= end D123 THE GALLEY ================= */

/* =====================================================================
   BATCH 60 (D124) - "THE FRONT PAGE", the band dashboard
   Carl's pick from docs/design/backstage/status-rethink.html (layout A). Not a restyle: The
   Galley is settled and not one token moves here. What moves is what is on the page, in what
   order, and who owns it. The audit that justified it, measured on the live render at 1440:
   the page was 2318px tall, the band's own first number sat at y=1164, and 802 of the 1030
   pixels above it were blocks whose destination page renders strictly more of the same thing.

   The shape is five named full-measure sections, top to bottom, and nothing is in a column
   until you are inside one, so importance is carried by width and order rather than by a
   heavier rule. That is also what rights the ladder D123's review found upside down: the
   loudest mark in the system had been spent sixteen times on this one page, ten of them on leaf
   cards three levels deep, while the biggest division on it was carried by the faintest hairline
   in the system. With sections it is spent five times, once each, and the ladder falls out on
   its own as the trade paper's, where a rule is a masthead and something is always set under it:

       2px Newsprint, with a NAME set under it  a section starts here, and nothing else
       1px Newsprint 4                          a column rule inside a section
       1px Rule Strong                          a block inside a section
       1px Rule                                 a row inside a block

   And the interval-of-one goes with it: 34px above a section rule, 14px under it, 10-14px
   between blocks inside one. More space above a heading than below it, as everywhere else.

   Scope. The section furniture is the shared half and is written to be picked up rather than
   reinvented: .page-sec, .ruled-cols, .fact-line and .elsewhere. This batch puts it on two
   pages, the dashboard and /awards, which received the season the dashboard gave up. The
   .dash-* rules and the .dash wrapper are the dashboard's own and go nowhere else. Nothing
   under body.public is touched: neither page renders under it.
   ===================================================================== */

/* ---- 1. The named section: the only 2px rule on the page ----------------
   A rule with a name set under it, a hairline closing the name, then the body. The hairline is
   load-bearing: it is the rule over whatever starts underneath, in every column, which is why
   no block inside a section draws its own top edge. */
.page-sec{border-top:2px solid var(--paper);margin-top:34px}
.page-sec:first-of-type{margin-top:0}
.page-sec__head{
  display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;
  margin:0;padding:10px 0 9px;border-bottom:1px solid var(--line);
  font-family:var(--ff-disp);font-weight:700;font-size:15px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--paper)}
/* The fact after the name is a sentence, not a second label: caps strip the word shapes a
   reader navigates by, so it takes the body face and none of the tracking. */
.page-sec__head em{
  font-style:normal;font-family:var(--ff-body);font-weight:400;font-size:12.5px;
  letter-spacing:0;text-transform:none;color:var(--paper-3)}
.page-sec__act{margin-left:auto;display:flex;gap:8px;align-items:center}
.page-sec__body{padding:14px 0 4px}

/* Inside a section every block demotes: a section is already the loudest thing on the page. */
.page-sec .panel,.page-sec .card,.page-sec .lbl-dash{border-top:1px solid var(--line-2)}
.page-sec .panel__head{padding:10px 0 7px;font-size:11.5px;color:var(--paper-3)}
.page-sec .card-title{font-size:13px}
.page-sec .card-copy{margin-bottom:13px}
/* ...and the first block in each column takes no rule at all, because the section head's own
   hairline (or the fact line's, below) is already sitting directly above it. */
.page-sec__body>:first-child,
.page-sec .ruled-cols>*>:first-child{border-top:0;padding-top:0}
.page-sec .ruled-cols>*>:first-child>.panel__head{padding-top:0}

/* ---- 2. A ruled column grid --------------------------------------------
   Columns held apart by a rule one rank above a block's, which is the trade paper's device and
   the thing that replaced the borders in D123. grid-auto-flow:column so the rack sizes itself
   to however many cells actually render: the refer cell, the label cells and the campaigns
   panel are each conditional, and an explicit repeat(3) would leave a ruled void where one of
   them is off. */
.ruled-cols{display:grid;gap:0;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr)}
.ruled-cols>*{padding:0 24px;border-left:1px solid var(--paper-4);min-width:0}
.ruled-cols>*:first-child{padding-left:0;border-left:0}
.ruled-cols>*:last-child{padding-right:0}
/* A lone block does not stretch to the full measure. "Your work" is three conditional cells and
   a band with one label and no campaigns would otherwise get a key-and-value row 1200px wide,
   with a metre of nothing between the two halves of one fact. */
.ruled-cols:has(>:only-child){grid-template-columns:minmax(0,620px)}
/* A lead figure against the measure, and a measure against a fixed aside. */
.ruled-cols--lead{grid-auto-flow:row;grid-template-columns:minmax(0,236px) minmax(0,1fr)}
.ruled-cols--aside{grid-auto-flow:row;grid-template-columns:minmax(0,1fr) minmax(0,392px)}

/* ---- 3. One ruled fact line ---------------------------------------------
   What a strip becomes once the section above it has a name: the icon, the sentence, and the
   destination pushed to the right margin. It is a lede for the columns under it, so the rule
   goes under the line rather than over it. */
.fact-line{
  display:flex;align-items:flex-start;gap:10px;flex-wrap:wrap;
  margin:0;padding:0 0 9px;font-size:13px;color:var(--paper-2)}
.fact-line>.ic,.fact-line>.ic-t{flex:none;margin-top:1px}
.fact-line .ic{width:17px;height:17px}
.fact-line b{color:var(--paper);font-weight:600}
.fact-line .mono{font-family:var(--ff-mono);font-size:12.5px;color:var(--paper)}
.fact-line a{
  margin-left:auto;color:var(--paper-2);text-decoration:none;font-family:var(--ff-disp);
  font-size:11.5px;font-weight:700;letter-spacing:.13em;text-transform:uppercase}
.fact-line a:hover{color:var(--accent)}
.fact-line--wave .ic{color:var(--wave)}
.fact-line--ach .ic{color:var(--patron)}
.fact-line+.ruled-cols{margin-top:6px;border-top:1px solid var(--line);padding-top:14px}

/* ---- 4. Elsewhere -------------------------------------------------------
   The page's last rule, and the receipt for everything it gave away: one hairline row of
   pointers to the pages that now carry the feed, the waves, the gallery and the season. */
.elsewhere{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:9px 28px;
  margin-top:34px;padding:11px 0 0;border-top:1px solid var(--line);
  font-size:13px;color:var(--paper-3)}
.elsewhere>b{
  font-family:var(--ff-disp);font-size:11px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--paper-3)}
.elsewhere__item{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
.elsewhere a{color:var(--paper-2);text-decoration:none;border-bottom:1px solid var(--line-2);padding-bottom:1px}
.elsewhere a:hover{color:var(--accent);border-bottom-color:var(--accent)}
.elsewhere__item span{font-size:12.5px;color:var(--paper-3)}

/* ---- 5. The dashboard's own blocks --------------------------------------
   Popularity across the measure instead of down a 260px column: seven markets and World are
   one glance at three across rather than a scroll. The five vitals go five across for the same
   reason, and neither is a new component - both are the meter list, given a grid. */
.dash-pop{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 34px}
.dash-pop .meter__label{font-size:11px}
.dash-vitals{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px 26px}
/* The rank leads the page, so it is set at the scale a lead figure deserves. */
.dash-rank .rank-num{font-size:52px;line-height:1;letter-spacing:-.02em}
.dash-rank .rank-row{margin:2px 0 4px}

/* The season, beside the rank it judges. The tall strip that used to sit above the band's own
   numbers is gone to /awards; what comes back is one ruled footnote under the rank, saying that
   the rank is on a clock and opening the door to the page that holds the rest. The link is
   marked as a link and named in words, so a screen reader is not handed a bare date. */
.dash-season{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 14px;
  margin:14px 0 0;padding-top:12px;border-top:1px solid var(--line);
  font-size:12.5px;color:var(--paper-3)}
.dash-season b{color:var(--paper-2);font-weight:600}
.dash-season .mono{font-family:var(--ff-mono);color:var(--paper-2)}
.dash-season__link{
  font-family:var(--ff-disp);font-size:11.5px;font-weight:700;letter-spacing:.13em;
  text-transform:uppercase;color:var(--paper-2);text-decoration:none;
  border-bottom:1px solid var(--line-2);padding-bottom:1px}
.dash-season__link:hover{color:var(--accent);border-bottom-color:var(--accent)}

/* An alert is an interruption, not a section. On this page only it keeps its hue and loses a
   pixel, so 2px means "a section starts here" and nothing else is allowed to say it. */
.dash .alert{border-top-width:1px}

/* ---- 6. The feud, relaid as a row ---------------------------------------
   Carl asked for the rivalry to take a row and it earns one: 596px stacked in a 1fr column was
   also what put the old three-column grid 626px out of balance. Identity left, last night's
   best of three across the middle, the verdict and the two actions right. Its own "Rivalry"
   caption is gone - the section head is the name now - and the streak badge rides up into it.

   The row is a CONTAINER query, not a media query, because the block is the thing that runs out
   of room, not the window: the same markup then still works if this card is ever put back in a
   1fr column somewhere else. */
.dash-rival{container-type:inline-size}
.dash-rival .rival-card{
  display:grid;grid-template-columns:minmax(0,268px) minmax(0,1fr) minmax(0,224px);
  column-gap:32px;align-items:start;padding:0;border-top:0;overflow:visible}
.rival-card__id{grid-column:1;grid-row:1}
.rival-card__rounds{grid-column:2;grid-row:1;min-width:0}
.rival-card__out{grid-column:3;grid-row:1;display:flex;flex-direction:column}
/* In a row the identity block is set left, like every other heading on the page. */
.dash-rival .rival-vs{padding:0 0 13px;text-align:left;border-bottom:1px solid var(--line)}
.dash-rival .rival-vs__name{font-size:26px}
.dash-rival .rival-vs__rule{justify-content:flex-start}
.dash-rival .rival-vs__rule::before{display:none}
.dash-rival .rival-vs__rule::after{flex:1}
.dash-rival .rival-record{
  justify-content:flex-start;padding:11px 0;background:none;border-top:0;border-bottom:0}
.dash-rival .rival-record__cell:first-child{padding-left:0}
.dash-rival .rival-record__since{margin:0;padding:0;background:none;text-align:left}
/* Three rounds across the middle, each a two-line cell: the fact, then what it did to the week. */
/* The three rounds share their rows through a subgrid, so the label, the pair of figures and
   the verdict each sit on one line across all three cells. Without it the middle label wraps to
   two lines on its own and its figures drop half a line below its neighbours', which in a block
   whose entire job is comparison is the one misalignment that actually costs the reader. */
.dash-rival .rival-rounds{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  grid-template-rows:auto auto auto auto;column-gap:24px;align-content:start;padding:0}
.dash-rival .rival-rounds__cap{grid-column:1/-1;grid-row:1;padding:0 0 9px}
/* Three rounds side by side leaves each cell about 190px, and the pair of figures it exists to
   compare is the widest thing in it: on band 3, the production-maxima seed, "4,182,600 vs
   5,904,118" is 185px on its own. So the icon indents the LABEL only and the figures take the
   whole cell (display:contents lifts the partial's wrapper out of the way), which buys back the
   30px the icon column was costing them. A point off the figure buys the rest. Wrap stays on as
   the fallback for a band whose sales outgrow even that. */
.dash-rival .rival-round{
  grid-row:2/5;display:grid;grid-template-rows:subgrid;
  grid-template-columns:20px minmax(0,1fr);column-gap:10px;row-gap:6px;
  align-items:start;padding:11px 0 0;border-top:1px solid var(--line)}
.dash-rival .rival-round__icon{grid-column:1;grid-row:1}
.dash-rival .rival-round>div{display:contents}
.dash-rival .rival-round__label{grid-column:2;grid-row:1;min-width:0}
.dash-rival .rival-round__vals{grid-column:1/-1;grid-row:2;flex-wrap:wrap;gap:6px;font-size:13px}
.dash-rival .rival-round__out{grid-column:1/-1;grid-row:3;justify-self:start}
.dash-rival .rival-notice{margin:0;padding:14px 0 0;text-align:left}
.dash-rival .rival-verdict{margin:0;padding:11px 14px;border-top:0;justify-content:flex-start}
.dash-rival .rival-foot{margin-top:14px;padding:12px 0 0;border-top:1px solid var(--line);background:none}
/* On a quiet feud or a night not yet run there is no verdict, so the actions are the column. */
.rival-card__out>.rival-foot:first-child{margin-top:0;padding-top:0;border-top:0}
/* The empty state is an invitation, not a scoreboard: it never takes the three-column row. */
.dash-rival .rival-card--pitch{display:block}
.dash-rival .rival-pitch{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,360px);column-gap:34px;
  align-items:end;padding:14px 0 0;max-width:none}
.dash-rival .rival-pitch__metrics{justify-content:flex-start}
@container (max-width:940px){
  .dash-rival .rival-card{grid-template-columns:minmax(0,236px) minmax(0,1fr)}
  .rival-card__out{
    grid-column:1/-1;grid-row:2;display:grid;grid-template-columns:minmax(0,240px) minmax(0,1fr);
    align-items:center;column-gap:24px;margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
  .dash-rival .rival-foot{margin-top:0;padding-top:0;border-top:0}
}
@container (max-width:600px){
  .dash-rival .rival-card{grid-template-columns:minmax(0,1fr)}
  .rival-card__rounds{grid-column:1;grid-row:2;margin-top:16px}
  .rival-card__out{grid-row:3;grid-template-columns:minmax(0,1fr)}
  /* One round per row: the shared rows have nothing left to share, and a subgrid over a single
     implicit row would stack the label, the figures and the verdict on top of each other. */
  .dash-rival .rival-rounds{grid-template-columns:minmax(0,1fr);grid-template-rows:none}
  .dash-rival .rival-rounds__cap{grid-column:1;grid-row:auto}
  .dash-rival .rival-round{grid-row:auto;grid-template-rows:auto auto auto}
  .dash-rival .rival-pitch{grid-template-columns:minmax(0,1fr);row-gap:14px}
}

/* ---- 7. The collapse ----------------------------------------------------
   Desktop is this batch's brief and the phone is a later job; this is here so the page does not
   ship known-broken on one. A section is a section at every width; what gives way is the number
   of columns inside it, and a column rule becomes a rule above the block instead. */
@media (max-width:1100px){
  .dash-pop{grid-template-columns:repeat(2,minmax(0,1fr))}
  .dash-vitals{grid-template-columns:repeat(3,minmax(0,1fr))}
  .ruled-cols--aside{grid-template-columns:minmax(0,1fr) minmax(0,320px)}
}
@media (max-width:860px){
  .ruled-cols{grid-auto-flow:row;grid-template-columns:minmax(0,1fr)}
  .ruled-cols>*{padding:0;border-left:0}
  .ruled-cols>*+*{margin-top:14px;padding-top:13px;border-top:1px solid var(--line-2)}
  .page-sec .ruled-cols>*+*>:first-child{border-top:0;padding-top:0}
  .dash-pop,.dash-vitals{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:520px){
  .page-sec{margin-top:26px}
  .page-sec__head{gap:4px 12px;font-size:14px}
  .dash-pop,.dash-vitals{grid-template-columns:minmax(0,1fr)}
  .dash-rank .rank-num{font-size:44px}
  .elsewhere{flex-direction:column;align-items:flex-start;gap:9px}
}
/* The current-season marker. A filled accent chip here would be a second red beside the one
   button on the page that is an action, so the marker takes the loudest outline in the system
   instead: paper on paper, which is also the season chip's own edge one rank down. */
.chip--now{border-color:var(--paper);color:var(--paper)}

/* ---- 8. /awards, the season's home --------------------------------------
   The dashboard gave up a 74px season strip and this page had to be able to receive it: before
   D124 /awards listed the seasons with their dates and had no countdown, no SeasonClock and no
   way of saying which season you were in. It now opens on the live season at the scale the
   thing deserves, and every component here is one the game already owns - the ticket's numeral,
   the season fields, the season chip and the opened-to-ends meter, which is also what keeps
   this page and the homepage ticket saying the same thing in the same shapes. */
.season-now__num{
  font-family:var(--ff-disp);font-weight:800;font-size:clamp(56px,7vw,72px);line-height:.82;
  letter-spacing:-.01em;color:var(--paper);margin:0}
.season-now__name{
  font-family:var(--ff-disp);font-weight:400;font-size:22px;line-height:1.05;
  letter-spacing:.01em;text-transform:uppercase;margin:8px 0 0}
.season-now__note{
  margin:16px 0 0;max-width:68ch;font-size:13px;line-height:1.6;color:var(--paper-3)}
.season-meter--page{margin-top:18px}
@media (max-width:520px){
  .season-now__num{font-size:52px}
  .season-now__name{font-size:19px}
}
/* ================= end D124 THE FRONT PAGE ================= */

/* =====================================================================
   D130 "ON A PHONE" (Batch 66, 2026-09-10). The mobile audit walked all 92 routes at 360 and
   390 in both themes under a real coarse pointer and found twenty-two defects, seventeen of
   them older than The Galley and live on production right now. This section answers them.

   Nothing here introduces a language: every fix is made out of what the game already has - a
   rule where a box would have gone, a hairline where a column rule cannot follow, the label
   voice for a caption, and the drawn set's own bubble. Two of them are not CSS at all, and
   they are the ones that mattered most: the More menu now carries the theme toggle
   (Kit/_PublicNav), and app.js opens an icon's explanation on a tap.

   Breakpoints are the ones already in the sheet - 860 where the nav becomes a drawer, 640 where
   the shell reflows, 520 where the phone starts. No new one was needed.
   ===================================================================== */

/* ---- 1. The public bar, which had no navigation on a phone at all ------
   The worst thing the audit found, and the oldest. .home-nav is a flex row of four groups and
   nothing inside it was allowed to shrink, so its intrinsic width was 422px at EVERY phone
   size. At 390 the More menu sat at x365 to 422; at 360 it started five pixels past the right
   edge and did not render on the screen at all. Charts, About, History, FAQ, Contact and Log in
   all live inside that menu below 640, on all sixteen public routes, so a visitor landing on
   the homepage from a search result had the wordmark, a theme toggle and Create account, and no
   way to reach another page unless they guessed the page scrolled sideways.

   Three things, in order of how much room each buys. The theme toggle folds into the menu, the
   way Log in already does (Kit/_PublicNav); the mark takes one more step down the scale D114
   already put it on (15px bar, 13px sidebar, 12px below 400); and the bar is allowed to wrap.
   The wrap does not fire at 360 or 390 - it is there so that the failure mode at any width
   narrower than this batch can measure is a second row, which you can see, rather than a
   destination off the side of the screen, which you cannot. */
@media (max-width:520px){
  .home-nav{flex-wrap:wrap;gap:8px}
  .home-nav__links{min-width:0;flex:1 1 auto;justify-content:flex-end;gap:8px}
  .home-nav .logo-mark{font-size:11px}
  .home-theme{display:none}
  .home-menu{order:1}
  .home-nav__account{order:2}
  .home-menu__theme{display:flex}
  /* A menu that is now the only way to six destinations gets rows a thumb can land on. */
  .home-menu__panel a{min-height:44px;display:flex;align-items:center}
}
@media (max-width:400px){
  .home-nav{gap:6px}
  .home-nav__links{gap:6px}
  .home-nav .logo-mark{font-size:10px}
  .home-nav .btn{padding:13px 9px;font-size:12.5px}
  .home-nav__link{font-size:12.5px}
}
/* The toggle in the menu. It is the panel's own link, set as a button: the glyph reports which
   theme is on and the word says what the control is, because a moon on its own beside five
   destinations reads as a sixth destination. */
.home-menu__theme{
  display:none;align-items:center;gap:.55em;width:100%;min-height:44px;
  font-family:var(--ff-disp);font-weight:600;font-size:14px;letter-spacing:.04em;
  text-transform:uppercase;text-align:left;color:var(--paper-2);
  background:none;border:0;border-radius:var(--r-sm);padding:10px 12px;cursor:pointer}
.home-menu__theme:hover{color:var(--paper);background:var(--surface-3)}

/* ---- 2. The homepage chart, which truncated the first game content anyone sees ----
   349px of title into 154px, and the byline the same. It is the front page: half of it was
   unreadable. D121's four tracks become three below 520 and the movement flag takes the row
   under the byline, which is the only spare room on the row, so the title gets the measure and
   stops ellipsising. */
@media (max-width:520px){
  .home-chart__row{grid-template-columns:40px 52px minmax(0,1fr);gap:2px 12px;align-items:start}
  .home-chart__pos,.home-chart__art{grid-row:1 / span 2;align-self:center}
  .home-chart__meta{grid-column:3;grid-row:1}
  .home-chart__move{grid-column:3;grid-row:2;text-align:left;min-width:0}
  .home-chart__title{white-space:normal;overflow:visible;text-overflow:clip}
}

/* ---- 3. The two topbar controls, one of which logs you out --------------
   13x16 and 25x17 against a 44px minimum: four percent and twenty-two percent of the area, on
   every one of the 75 signed-in pages, twelve pixels apart in the top right corner, and the
   right hand one signs the player out with no confirmation. They were pinned out of the flow so
   the wide stat bar could not shove them off screen, and the band block reserved 64px for them
   by hand. At 44px each that reservation would have to be kept in step with a button size in
   another rule, which is how it went wrong the first time, so the controls come back into the
   row and the reservation goes. */
@media (max-width:640px){
  .topbar{gap:10px 12px}
  /* flex-basis 0, not auto: a wrapped flex line is broken using each item's HYPOTHETICAL main
     size, so with an auto basis the band block asks for its max-content width first and the
     controls are on a row of their own before min-width:0 ever gets a chance to shrink it. */
  .topbar .band-id{order:1;flex:1 1 0;width:auto;min-width:0;padding-right:0}
  /* The band block has to be ALLOWED to shrink or the controls wrap to a row of their own: the
     unclassed div holding the name and the sub-line has min-width:auto, so its min-content width
     is the longest unbreakable run in it, and once the sub-line stopped wrapping (below) that
     run was the whole sentence. */
  .topbar .band-link>div{min-width:0}
  .topbar .topbar-controls{order:1;position:static;flex:none;gap:6px}
  .topbar-controls .theme-toggle,.topbar-link--icon{
    width:44px;height:44px;padding:0;display:grid;place-items:center}
  /* The hamburger declared 40x40 and measured 29 wide, because it sat in a flex row with no
     flex:none and a long band name shrank it. The width of the one control that opens the
     game's navigation depended on what the player had called their band. */
  .nav-toggle{flex:none;width:44px;height:44px}
}
@media (max-width:860px){
  .nav-toggle{flex:none}
  /* 42 links at 34px, on the primary navigation, on every page: the largest population of
     undersized targets in the product. The drawer already scrolls, so the height costs nothing. */
  .nav-link{padding:12px 10px}
}

/* ---- 4. The topbar took 267px of an 800px screen before the page started ----
   Four things stacked up: the band name wrapped, the switch glyph dropped to a line of its own,
   the band's own line wrapped to three, and the stat bar wrapped to two rows. The line says the
   same thing on one, and the name is set at the size the rest of the shell uses on a phone. */
@media (max-width:520px){
  /* What is left of the row after a 44px menu button, a 42px sleeve and two 44px controls is
     about a hundred pixels, so the band block tightens its own seams to give the name as much
     of that as it can get. The page gutter is NOT touched: the topbar's 24px is the same left
     margin every block below it starts on, and that margin is the whole left edge in a
     language with no boxes. */
  .band-id,.band-link{gap:10px}
  .band-name{font-size:16px}
  /* D139 - the line says the genre and stops. The ellipsis below was doing the whole job on its
     own and doing it badly: 290px of "Punk - based in Australia & NZ - managed by seeduser" into
     100px at 360 rendered as "Punk - based i", cut mid-word, with two thirds of the sentence
     unreachable. A clipped line is not a shorter line, it is a line the reader cannot finish. The
     genre alone is nine characters at its longest in this world and fits at 360 with room; the
     other two facts are one tap away in the destination this whole block links to. The nowrap and
     the clip stay as the guard, so a longer genre than any that exists degrades to an ellipsis
     rather than pushing the two topbar controls onto a row of their own. */
  .band-sub__more{display:none}
  .band-sub{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
}
@media (max-width:640px){
  /* D123 stopped the stat bar swallowing the cash figure and let it wrap instead, which was
     right and the number is readable. The side effect at 360 was four cells each taking a top
     hairline sized to its own CONTENT, so the bar read as four unequal ticks and the second
     row's rule stopped 150px in and gave up. The cells grow to fill their line and the 20px
     column gap goes, so the hairlines meet and every row of the bar carries one rule the width
     of the page. It is also why the bar wraps less often: the gap was 60px of the reason it
     could not hold four figures at 360 in the first place. A fixed grid was the other way to
     do this and it was worse - two columns at 390, where the bar has always fitted on one. */
  .topbar .stat-bar{width:100%;column-gap:0}
  .topbar .stat{flex:1 1 auto}
}

/* ---- 5. The two racks that lost a destination off the side --------------
   .chart-kinds is 345px of inline-flex starting at a 24px gutter, so its right edge landed at
   369 in a 360px viewport: nine pixels, which is enough to slide all four chart pages sideways
   under a thumb on every vertical swipe, with the fourth tab hard against the cut. Four
   destinations become two by two, ruled rather than boxed, at a size a thumb can land on. The
   rule on top is Rule Strong, not paper: the ladder spends the loudest mark on a named section
   and this is a block inside one. */
@media (max-width:520px){
  .chart-kinds{
    display:grid;grid-template-columns:1fr 1fr;width:100%;
    background:none;border:0;border-top:1px solid var(--line-2);overflow:visible}
  .chart-kind{
    display:flex;align-items:center;justify-content:center;min-height:44px;
    padding:12px 10px;border-right:1px solid var(--line);border-bottom:1px solid var(--line)}
  .chart-kind:nth-child(2n),.chart-kind:last-child{border-right:0}
}
/* Label HQ was worse, because it hid a whole room. 433px of rack inside 310: Finances was
   severed mid word to "FINAN" and Settings was entirely off screen, behind a bare
   overflow-x:auto with scrollbar-width:none, so there was no scrollbar until a finger was
   already dragging and no reason to believe there was anything further right. One of five
   destinations was unreachable unless the owner guessed. It wraps, and takes the block grammar
   every other rack in the game already has: the violet rule on top, hairlines inside. */
@media (max-width:640px){
  .hq-rack{
    flex-wrap:wrap;overflow-x:visible;
    background:none;border:0;border-top:2px solid var(--lbl)}
  .hq-rack__link{flex:1 1 auto;justify-content:center;min-height:44px;border-bottom:1px solid var(--line)}
  .hq-rack__link:last-child{border-right:0}
  /* The label's motto is the one piece of personality on the page and it read "Four bands, one
     van, no A and R depart...". Two lines beats an ellipsis. And the runway set as "22112" on
     one line with "wks" on the next, its caption two lines below the number it belongs to. */
  .hq-head__strap{white-space:normal;overflow:visible;text-overflow:clip;max-width:none}
  .hq-head__stats{flex-wrap:wrap;gap:12px 20px}
  .hq-stat__v,.hq-stat__k{white-space:nowrap}
}

/* ---- 6. Thirty-three tables that hid their data with nothing to say so ----
   .table-wrap was overflow-x:auto and nothing else. /my/singles hid six of eight columns,
   /my/discography six of eight, /rankings four of seven, /world/tastes nine of sixteen markets:
   a player could not see how a record was selling from the page whose job is to say how records
   are selling. And because the cut column's box straddles the boundary, the last visible figure
   ended EXACTLY on the clip with no gutter, so on /rankings a complete "1,403,965,855" looked
   truncated, which turns a layout defect into a reason to doubt the number.

   A soft fade at the edge is the usual answer and it is the wrong one here twice over: this
   direction deleted every gradient it had, and a fade says "more" without ever saying WHAT. The
   paper's own device is a line of type, so the table says what is off to the right in words
   (app.js), and the first column is pinned while the rest slides, which /world/tastes was
   already doing and nothing else in the game was. */
.table-note{
  font-family:var(--ff-body);font-size:12.5px;line-height:1.5;font-weight:400;
  letter-spacing:normal;text-transform:none;color:var(--paper-3);margin:0 0 8px}
@media (max-width:640px){
  .table-wrap .table thead th:first-child,
  .table-wrap .table tbody td:first-child:not([colspan]){
    position:sticky;left:0;z-index:1;background:var(--bg);
    box-shadow:1px 0 0 var(--line)}
}

/* ---- 7. The feed gave 44% of its row to two counters that read 0 --------
   A 167px sentence column against a 133px action pair, on the page whose entire content is
   sentences: a band name wrapped to two lines and a headline to five so that two buttons
   showing nothing could keep their natural size. D123 relaid the feed as a ruled list and that
   pass was good work; this row was not on its list. The actions take the line under the
   sentence and stay on the right margin, so they still read as a column down the page. */
@media (max-width:640px){
  .feed-row>.panel__body{flex-wrap:wrap;row-gap:7px}
  .feed-row>.panel__body>.flex-1{flex:1 1 100%}
  .feed-row>.panel__body>.flex-none{margin-left:auto}
}

/* ---- 8. Where the ruled language ran out --------------------------------
   /collabs stacks three regions - offers for you, your outgoing offers, find a partner - and at
   1440 the column rules do the separating. Collapsed into one column there is nothing left
   doing that job and the three read as one long grey run with occasional capitals in it. This
   is the risk The Galley took, showing up exactly where the direction predicted it would. A
   region head takes the hairline that a block inside a section takes, at every width, so the
   boundary survives the collapse. */
main>.label-strong{border-top:1px solid var(--line-2);padding-top:13px;margin-top:22px}
@media (max-width:640px){
  /* The history rows were the one page in the walk a player would call broken without being
     able to say why: two chips, a run-on sentence naming two bands, and a button at the right
     that the sentence wrapped around in an L. Stacked, the button is the row's last line. */
  .collab-row{flex-direction:column;align-items:stretch;gap:9px}
  .collab-row form{width:100%}
  .collab-row .btn{width:100%}
}

/* ---- 9. The Hall of Fame truncated the only thing it is for -------------
   244px of band name into a 108px box: "The Catastrophic Reunion of Saint Nic" became "THE
   CATASTROP...", on the board whose entire content is names, while the figures beside them were
   given more room than the band. The name takes the row and the two figures take the line
   under it. */
@media (max-width:640px){
  .hall-board__row{
    grid-template-columns:34px minmax(0,1fr) auto;
    grid-template-areas:"rank name name" ". wins extra";
    row-gap:3px}
  .hall-board__rank{grid-area:rank}
  .hall-board__name{grid-area:name;white-space:normal;overflow:visible;text-overflow:clip}
  .hall-board__wins{grid-area:wins}
  .hall-board__extra{grid-area:extra;text-align:right}
}

/* ---- 10. The rest of the small print ------------------------------------ */
@media (max-width:640px){
  /* An empty state cost about 300px of height for three lines of copy, which on a phone is most
     of a screen, and its only action was 31px tall on a screen whose whole purpose is getting
     the player to press it. D125's frameless state reads correctly at 360; this is the room
     around it and the size of the one button. */
  .empty{padding:18px 0 22px}
  .empty .btn{width:100%}
  /* Every small button in the game, which is most of the buttons on a phone. */
  .btn--sm{min-height:44px}
  /* You are choosing songs by name and the name was cut at 214px. Two lines, not an ellipsis. */
  .trk-row__name{white-space:normal;overflow:visible;text-overflow:clip}
}

/* ---- 11. The 382 explanations a phone could not reach -------------------
   The bubble itself moved out of the fine-pointer media query further up this sheet; app.js
   opens it on a tap. All that is left here is the size of the thing you are tapping. An icon
   with a tip is an inline mark in a line of type, not a control, so it does not take a 44px box
   of its own - at 44 it would reach into the sentence beside it in the feed, where the gap is
   twelve pixels - but the area that answers is bigger than the drawing. */
@media (hover:none){
  .ic-t[data-tip]::before{content:"";position:absolute;inset:-11px}
}
/* ================= end D130 ON A PHONE ================= */

/* ================= D132 THE END OF A BAND (Batch 68) =====================
   A retired band's profile, and the page that gets one there. Deliberately no fill, no accent
   bar, no icon and no badge anywhere in here: a filled block with a coloured edge is the tell
   whichever edge it sits on, and this is the one place in the game where an alert would be
   exactly the wrong voice. The words carry it, ink and rules do the rest. */

/* The line under a dead band's name: "2026 to 2027. Met an untimely death." Full ink rather than
   --paper-3, because it outranks the facts line beneath it. */
.memorial{margin:6px 0 0;font-family:var(--ff-disp);font-size:15px;font-weight:600;
  letter-spacing:.01em;color:var(--paper)}

/* Findable, and honest about what you will find. An outline, not a capsule (D123 rule 6). */
.search-hit__gone{margin-left:8px;font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--paper-3);border:1px solid var(--line-2);padding:1px 5px;white-space:nowrap}

/* /settings/retire. Two ruled blocks side by side on a desk, stacked on a phone. */
.retire-lede{max-width:66ch;font-size:14.5px;color:var(--paper-2);margin:0 0 20px;text-wrap:pretty}
.retire-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:28px;
  align-items:start;margin-bottom:24px}
.retire-cols .panel__body{font-size:13.5px;color:var(--paper-2);padding-top:9px;padding-bottom:9px}
/* The last block runs the width of the page like the two above it, so its rule reads as the third
   beat rather than as a footnote hanging off the left column. Its BODY is a column: on a flat
   ground the page margin is the only left edge, and a field stretched to 1180px would be absurd. */
.retire-confirm{max-width:none}
.retire-confirm .page{max-width:560px}
.retire-confirm__input{max-width:340px}
/* Two short sentences that must not break mid-word: pretty keeps the orphan off line 2. */
.retire-note{max-width:60ch;font-size:13px;color:var(--paper-3);margin:4px 0 0;text-wrap:pretty}

/* The way out, at the foot of Band Settings. */
.retire-out{margin-top:24px}
.retire-out__row{gap:20px;align-items:center;flex-wrap:wrap}
.retire-out__text{flex:1 1 320px;min-width:0;font-size:13.5px;color:var(--paper-2);margin:0}

@media (max-width:640px){
  /* D132 - when a rival dies this button stops being a way out of a feud and becomes the only way
     INTO a new one, so it has to be pressable. It shipped at 30px, under Batch 66's 44px floor. */
  .rival-foot__end{min-height:44px;display:inline-flex;align-items:center}
  .retire-cols{gap:20px}
  /* The field you have to type into, and the buttons either side of it, are the whole point of
     the page. All three clear the 44px floor Batch 66 set (the input shipped at 40). */
  .retire-confirm__input{max-width:none;min-height:44px}
  .retire-confirm .form-bar .btn,.retire-out .btn{flex:1 1 100%;min-height:44px}
}
/* ================= end D132 ================= */

/* ================= D133 THE MANAGER DASHBOARD (Batch 70) =================
   The page is a decision, not a browse. It ships in two forms of one roster, because Carl wants
   both and which one wins depends on how many bands you hold: the call sheet, which is one
   full-measure entry a band with the sentence saying why it is where it is, and the list, which is
   the same roster and the same figures one ruled row a band. The page around them does not move.

   Everything here is inside The Galley (D123) and the named-section grammar (D124): no radius, no
   shadow, no box, and only .page-sec draws 2px. Blocks inside a section demote to 1px and the
   columns are held apart by a rule rather than by a border. No colour and no typeface is added:
   the tokens are the ones the rest of the sheet already defines.
   ===================================================================== */

/* ---- 1. The section head, and the switch that sits on its rule ----------
   The switch belongs to this section and to nothing else, so it belongs on this section's own
   hairline rather than up in the page head beside Create Band, where it would read as an action on
   the whole page. It marks its choice by TAKING that hairline: the chosen word owns the piece of
   rule underneath it in full ink, the other one has the faint version. That is why it is a wrapper
   here rather than the shipped .page-sec__act - the rule has to belong to the row, not to the h2,
   and a form is not phrasing content and may not live inside a heading. */
.md-sechead{
  display:flex;align-items:baseline;gap:10px 16px;flex-wrap:wrap;
  padding:10px 0 9px;border-bottom:1px solid var(--line)}
.md-sechead>.page-sec__head{padding:0;border-bottom:0;flex:1 1 auto;min-width:0}

.viewsw{display:flex;align-items:baseline;gap:20px;margin-bottom:-10px}
.viewsw__opt{
  appearance:none;background:none;border:0;border-bottom:1px solid var(--line-2);
  margin:0;padding:5px 1px 9px;cursor:pointer;position:relative;
  font-family:var(--ff-disp);font-size:11px;font-weight:700;letter-spacing:.13em;
  text-transform:uppercase;color:var(--paper-4)}
/* The hit area is bigger than the drawing, the way D130 gave the icon tips a tap without giving
   them a 44px box: the mark is a word on a rule and must stay one, and 44px of visible control in
   a section head would push the head down on every width. The 20px gap keeps the two apart. */
.viewsw__opt::after{content:"";position:absolute;left:-8px;right:-8px;top:50%;height:44px;transform:translateY(-50%)}
.viewsw__opt:hover{color:var(--accent);border-bottom-color:var(--accent)}
.viewsw__opt.is-on{color:var(--paper);border-bottom-color:var(--paper);cursor:default}

/* ---- 2. Shared: a figure cell ------------------------------------------
   The four things that decide whether a band gets played tonight. A label above, the figure, and
   one line of what the figure is measured against. The old page had all four numbers and said what
   none of them meant, and three of the four were already in the top bar for the band you were
   signed in as, 168px higher up the same screen. */
.md-fig__k{
  display:block;font-family:var(--ff-disp);font-size:10.5px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4);margin-bottom:5px}
.md-fig__v{
  display:block;font-family:var(--ff-mono);font-size:22px;line-height:1.05;
  color:var(--paper);letter-spacing:-.01em;font-variant-numeric:tabular-nums}
.md-fig__v .u{font-size:13px;color:var(--paper-3)}
.md-fig__n{display:block;margin-top:5px;font-size:12px;color:var(--paper-3)}
.md-fig__n b{color:var(--paper-2);font-weight:600}
.md-fig__n b.up{color:var(--up)}
.md-fig__n b.dn{color:var(--down)}
/* The nightly clips points to 2,500 and has done since the legacy, so a band sitting on the
   ceiling is throwing away three an hour while you read the page. It is the one number here that
   is costing the manager something, and the old page drew it in the same grey as any other. */
.md-fig--stop .md-fig__v,.md-fig--stop .md-fig__n,.md-fig--stop .md-fig__n b{color:var(--accent)}

/* ---- 3. Shared: a state said in words -----------------------------------
   D125 - a mark has to carry information. "You are playing this one" is the information; a
   coloured left rule on the row was not, and it spent the system's one raised voice saying it. */
.md-chip{
  font-family:var(--ff-disp);font-size:10.5px;font-weight:600;letter-spacing:.13em;
  text-transform:uppercase;color:var(--paper-3);border:1px solid var(--line-2);
  padding:2px 8px;white-space:nowrap}
.md-chip--here{color:var(--paper);border-color:var(--paper-4)}
/* D132 - a retired band is still one of yours and still on your roster. It is not a warning and it
   gets no fill, no icon and no coloured edge: it is a name in the quieter ink, and the sentence
   under it says the rest. */
.is-gone{color:var(--paper-3)}

/* ---- 4. The call sheet --------------------------------------------------
   One full-measure entry a band, in the order they need you tonight rather than the order you made
   them, and a sentence under each one saying why it is where it is. */
.md-entry{padding:15px 0 16px;border-top:1px solid var(--line)}
.md-entry:first-child{border-top:0;padding-top:0}
.md-entry__head{display:flex;align-items:baseline;gap:10px 14px;flex-wrap:wrap;margin-bottom:13px}
.md-entry__sub{font-size:12.5px;color:var(--paper-3)}
.md-entry__act{margin-left:auto;display:flex;align-items:center;gap:10px}
.md-figs{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:0}
.md-figs>*{padding:0 22px;border-left:1px solid var(--paper-4);min-width:0}
.md-figs>*:first-child{padding-left:0;border-left:0}
.md-figs>*:last-child{padding-right:0}
/* The whole argument of the rework in one element: the page always had the numbers. */
.md-say{
  margin:13px 0 0;padding:11px 0 0;border-top:1px solid var(--line);
  font-size:13px;color:var(--paper-2);text-wrap:pretty}
.md-say--stop{color:var(--accent)}

/* ---- 5. The list -------------------------------------------------------
   The same roster and the same four figures, one ruled row a band. What it gives up is the
   sentence; what it buys is ten bands in the height four take on the call sheet, which is the
   reason both ship and the reason the choice is worth storing. */
.md-ledhead,.md-row{
  display:grid;grid-template-columns:minmax(0,1fr) 104px 96px 104px 148px 168px;gap:0 20px}
.md-ledhead{
  padding:0 0 8px;border-bottom:1px solid var(--line-2);align-items:end;
  font-family:var(--ff-disp);font-size:10.5px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--paper-4)}
.md-ledhead>*+*{text-align:right}
.md-row{align-items:baseline;padding:12px 0;border-top:1px solid var(--line)}
.md-row:first-of-type{border-top:0;padding-top:10px}
.md-row__id{min-width:0}
.md-row__sub{display:block;margin-top:3px;font-size:12px;color:var(--paper-3)}
.md-row__sub .md-chip{margin-left:6px}
.md-row__f{
  font-family:var(--ff-mono);font-size:13.5px;color:var(--paper);text-align:right;
  font-variant-numeric:tabular-nums;min-width:0}
.md-row__f .u{font-size:11.5px;color:var(--paper-3)}
.md-row__f>span{
  display:block;margin-top:3px;font-family:var(--ff-body);font-size:11.5px;color:var(--paper-3);
  white-space:nowrap}
/* Only the movement itself takes the colour, the way the call sheet does it and the way the board
   drew it. A whole phrase in red four rows running would spend the loud voice on trivia. */
.md-row__f>span b{color:var(--paper-2);font-weight:600}
.md-row__f>span b.up{color:var(--up)}
.md-row__f>span b.dn{color:var(--down)}
.md-row__f.is-stop,.md-row__f.is-stop>span,.md-row__f.is-stop>span b{color:var(--accent)}
.md-row__a{text-align:right}

/* ---- 6. The band name IS the switch ------------------------------------
   Every arrival on this page is a manager choosing which band to be, so the name posts the switch
   rather than a secondary button at the far right of a 1,202px row posting it. The button stays
   too, for anyone who wants to see a button. */
.md-entry__name,.md-row__name,.md-tail__name{
  appearance:none;background:none;border:0;padding:0;margin:0;text-align:left;
  font-family:var(--ff-disp);font-weight:700;letter-spacing:.02em;color:var(--paper);
  line-height:1.1;position:relative}
button.md-entry__name,button.md-row__name,button.md-tail__name{cursor:pointer}
/* DESIGN.md's Item Title step: the title of one item inside a list, which is what a call-sheet
   entry is. The board drew it at 19px and 17px is the documented step, so it takes the step. Not
   uppercase, unlike the rest of that rank: a band's name is a name and the game sets it as one. */
.md-entry__name{font-size:17px;line-height:1.05}
.md-row__name,.md-tail__name{font-size:16px}
button.md-entry__name:hover,button.md-row__name:hover,button.md-tail__name:hover{color:var(--accent)}
/* The same trick as the switch: the area that answers is bigger than the lettering, without a
   44px box shoving a 19px name around on a desk. */
button.md-entry__name::after,button.md-row__name::after,button.md-tail__name::after{
  content:"";position:absolute;left:-4px;right:-4px;top:50%;height:44px;transform:translateY(-50%)}

/* ---- 7. The find, and the tail -----------------------------------------
   Two production managers hold 103 and 40 bands. No layout answers a roster that size, and the
   ordering cannot do the cutting either: a neglected roster is neglected UNIFORMLY, because every
   band left alone drifts to the points cap with nothing on sale, which is two of the four terms in
   the order. So the cut is a fixed count and the answer past it is a different job, finding one
   band by name, which is the same answer at 1440 and at 390. */
.md-find{
  display:flex;align-items:center;gap:10px 14px;flex-wrap:wrap;
  margin:0 0 18px;padding:0 0 14px;border-bottom:1px solid var(--line)}
.md-find__l{
  display:flex;align-items:center;gap:7px;font-family:var(--ff-disp);font-size:11px;
  font-weight:700;letter-spacing:.13em;text-transform:uppercase;color:var(--paper-3)}
.md-find__l .ic{width:15px;height:15px}
.md-find__i{width:auto;flex:1 1 260px;max-width:420px;min-width:0}
.md-find__clear{
  font-size:12.5px;color:var(--paper-3);text-decoration:none;
  border-bottom:1px solid var(--line-2);padding-bottom:1px}
.md-find__clear:hover{color:var(--accent);border-bottom-color:var(--accent)}
.md-none{margin:2px 0 0;font-size:13.5px;color:var(--paper-2)}

.md-tail{margin-top:20px;padding-top:14px;border-top:1px solid var(--paper-4)}
.md-tail__h{
  margin:0 0 4px;font-family:var(--ff-disp);font-size:11px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--paper-3)}
.md-tail__row{
  display:flex;align-items:baseline;gap:10px 16px;flex-wrap:wrap;
  padding:9px 0;border-top:1px solid var(--line)}
.md-tail__row>.form-inline{flex:1 1 auto;min-width:0}
.md-tail__f{margin-left:auto;font-family:var(--ff-mono);font-size:12.5px;color:var(--paper-3);
  font-variant-numeric:tabular-nums;white-space:nowrap}

/* ---- 8. The manager's own affairs --------------------------------------
   The page is called the Manager Dashboard and the manager was not on it: not the handle, not the
   year they started, not their honours, not their label, not their support status. All five
   already render on other pages, one of which is PUBLIC and shows this same roster. */
.md-mgr__k{
  display:block;font-family:var(--ff-disp);font-size:10.5px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4);margin-bottom:6px}
.md-mgr p{margin:0 0 8px;font-size:13px;color:var(--paper-2);line-height:1.5;text-wrap:pretty}
.md-mgr p b{color:var(--paper);font-weight:600}
.md-mgr .mono{font-family:var(--ff-mono);font-size:12.5px;color:var(--paper)}
.md-mgr .ic{width:15px;height:15px;vertical-align:-2px}
.md-mgr__big{
  font-family:var(--ff-mono);font-size:22px;line-height:1.05;color:var(--paper);
  display:block;margin-bottom:5px;font-variant-numeric:tabular-nums}
.md-mgr__act{
  display:inline-block;margin-top:2px;font-family:var(--ff-disp);font-size:11px;
  font-weight:700;letter-spacing:.13em;text-transform:uppercase;color:var(--paper-2);
  text-decoration:none;border-bottom:1px solid var(--line-2);padding-bottom:1px}
.md-mgr__act:hover{color:var(--accent);border-bottom-color:var(--accent)}
/* One control for one manager-level setting. It used to be a button on every row that was not
   already the default, drawn three times to set one value, and the only sentence explaining what
   default meant was a browser tooltip on the button that is hidden on the row it describes. What
   it actually decides is said in the two lines above it. */
.md-mgr__set{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:2px 0 10px}
.md-mgr__sel{width:auto;flex:1 1 180px;min-width:0}

/* ---- 9. Narrower --------------------------------------------------------
   A section is a section at every width. What gives way is the number of columns inside it, and a
   column rule becomes a rule above the block, which is what site.css already does to .ruled-cols
   at 860, so the manager section folds for free. */
@media (max-width:1100px){
  .md-figs{grid-auto-flow:row;grid-template-columns:repeat(2,minmax(0,1fr));row-gap:16px}
  .md-figs>*:nth-child(odd){padding-left:0;border-left:0}
  .md-ledhead,.md-row{grid-template-columns:minmax(0,1fr) 92px 84px 92px 128px 150px;gap:0 14px}
}

/* ---- 10. The phone ------------------------------------------------------
   Nothing scrolls sideways at any width. The page as built only fitted a phone because 579px of
   table hid inside a 342px wrapper, so the points, the rank and the switch were off-screen until
   you dragged them there, which is not fitting on a phone but hiding on one.

   A phone reads one band at a time, so the comparison a column buys is worth nothing there. What
   survives the fold is prose: on the call sheet the figures become a run of facts and their second
   lines go, because the sentence underneath already says what they mean and saying it twice on a
   342px measure costs a screen a band. The one note that stays is the one that is costing the
   manager something while they read it. */
@media (max-width:520px){
  .md-chip{font-size:10px;padding:2px 7px}

  .md-entry{padding:14px 0 15px}
  .md-entry__head{margin-bottom:10px;gap:6px 10px}
  .md-entry__name{flex:1 1 100%}
  .md-entry__act{margin-left:auto}
  .md-figs{display:flex;flex-wrap:wrap;gap:5px 16px}
  .md-figs>*{padding:0;border-left:0;display:flex;align-items:baseline;gap:6px}
  .md-fig__k{display:inline;margin:0}
  .md-fig__v{display:inline;font-size:15px}
  .md-fig__n{display:none}
  .md-fig--stop .md-fig__n{display:inline;margin:0;font-size:11.5px}
  .md-say{padding-top:9px;margin-top:10px;font-size:12.5px}

  /* The list folds the same way a ledger has to: each row becomes a block and each figure carries
     the column name it lost, because a six-column grid cannot be read on a 342px measure and must
     not be dragged to be read. */
  .md-ledhead{display:none}
  .md-row,.md-row:first-of-type{display:block;padding:14px 0 15px}
  .md-row__id{margin-bottom:9px}
  .md-row__f{
    display:inline-flex;align-items:baseline;gap:6px;text-align:left;margin:0 16px 5px 0;font-size:15px}
  .md-row__f::before{
    content:attr(data-l);font-family:var(--ff-disp);font-size:10.5px;font-weight:600;
    letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4)}
  .md-row__f>span{display:none}
  /* Two survive the fold. The cap, because it is costing the manager something while they read;
     and the overnight movement, because it is the only note here that is a fact of its own rather
     than a restatement of the label above it ("of 2,500" under POINTS says nothing new). The list
     has no sentence to fall back on, which is exactly why it cannot lose this one. */
  .md-row__f.is-stop>span,.md-row__f[data-l="Rank"]>span{display:inline;margin:0}
  .md-row__a{text-align:left;margin-top:9px}

  .md-tail__f{margin-left:0;flex-basis:100%}
}

@media (max-width:640px){
  /* Batch 66 set the floor at 44px and the find field is the whole point of the page past eight
     bands, so the thing you type into and the thing you press both clear it. */
  .md-find__i,.md-mgr__sel{min-height:44px;flex-basis:100%;max-width:none}
  .md-find .btn,.md-mgr__set .btn{min-height:44px}
}
/* ================= end D133 ================= */

/* ================= D134 CLOSING AN ACCOUNT (Batch 69) =================
   Four pages, one grammar, and it is deliberately the plainest in the game. This is somebody
   deciding to leave: the interface has no business being clever about it, and no business trying
   to talk them out of it with colour either.

   The Galley (D123) and the named section (D124) do all the work. A block is a 2px rule with its
   name set under it, hairlines rule the facts inside it, and everything runs to the page's own
   left margin. There is no fill, no radius, no shadow, no icon and no accent anywhere on these
   pages except the two buttons at the bottom, because the one moment a raised voice is warranted
   is the moment you press the thing. A left bar on a callout would be exactly the wrong device
   here on top of being the AI tell: the words are already grave enough.

   The pages share it across both shells - /settings/close is inside the app, and /close,
   /undo-close and /account-closed are on the logged-out layout - so every rule below is written
   against the shared tokens rather than either shell's furniture. */

.close-page{max-width:980px;margin:0 auto}

/* The one paragraph everything else hangs off. 66ch because it is read once, carefully. */
.close-lede{max-width:66ch;font-size:14.5px;color:var(--paper-2);margin:20px 0;text-wrap:pretty}
.doc-page .close-lede{margin-top:26px}

/* Two blocks on a desk, stacked on a phone. Same measure as the retire page (D132), because it
   is the same decision one level up and it should feel like the same room. */
.close-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:28px;
  align-items:start;margin-bottom:8px}

/* The block. D124's ladder: the paper rule on top, the name set under it, a hairline below the
   name. Nothing else on these pages is allowed to draw 2px. */
.close-block{border-top:2px solid var(--paper);margin-top:28px}
.close-cols>.close-block{margin-top:0}
.close-block__name{
  margin:0;padding:10px 0 9px;border-bottom:1px solid var(--line);
  font-family:var(--ff-disp);font-weight:700;font-size:15px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--paper);line-height:1.2}

/* The facts. One per ruled row, and the last row does not draw, so the block ends on the
   preceding rule rather than on a line with nothing under it. */
.close-list{padding:4px 0 0}
.close-list__row{padding:10px 0;border-bottom:1px solid var(--line);
  font-size:13.5px;line-height:1.55;color:var(--paper-2);text-wrap:pretty}
.close-list__row:last-child{border-bottom:0}
.close-list__row b{color:var(--paper);font-weight:600}
/* A band name, a label name: full ink, because these are the words that stop somebody. */
.close-list__row--name{color:var(--paper);font-family:var(--ff-disp);font-weight:600;
  font-size:16px;letter-spacing:.02em}
.close-list__aside{margin-left:8px;font-family:var(--ff-disp);font-size:10.5px;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4)}
.close-list .mono{font-family:var(--ff-mono);color:var(--paper)}

/* The aside under a block. Quieter than the rows it follows, and never wider than it can be read. */
.close-note{max-width:62ch;font-size:13px;color:var(--paper-3);margin:12px 0 0;text-wrap:pretty}

/* The last block on the page: the same full measure as the two above, with a column of a body,
   because a page margin is the only left edge on a flat ground and a field stretched to 980px
   would be absurd. */
.close-confirm .close-confirm__body{max-width:560px;padding:16px 0 4px}
.close-confirm__input{max-width:340px}
.close-confirm__body .close-note{margin-bottom:4px}

/* Buttons at the end of a page that has no form on it. */
.close-actions{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-top:22px}
.close-actions form{margin:0}

@media (max-width:640px){
  /* Batch 66's 44px floor. The field you type your own login into and the button that closes the
     account are the two most consequential targets in the game, so they get it first. */
  .close-cols{gap:20px}
  .close-confirm__input{max-width:none;min-height:44px}
  .close-confirm .form-bar .btn,.close-actions .btn{flex:1 1 100%;min-height:44px}
  .close-actions form{flex:1 1 100%}
  .close-actions form .btn{width:100%}
  .close-list__row--name{font-size:15px}
}
/* ================= end D134 ================= */

/* The way out, at the foot of Manager Settings. The retire-out row one level up (D132). */
.close-out__row{gap:20px;align-items:center;flex-wrap:wrap}
.close-out__text{flex:1 1 320px;min-width:0;font-size:13.5px;color:var(--paper-2);margin:0}
@media (max-width:640px){.close-out__row .btn{flex:1 1 100%;min-height:44px}}

/* ================= D136 MY MUSIC (Batch 72, 2026-09-10) =================
   Seven pages became two. Approved board: docs/design/backstage/my-music-rethink.html,
   proposal B, and this sheet is that board's own stylesheet with the mock names taken out.

   Nothing here is a new language. The four things the game did not already own are all made out
   of what it does: a figure group inside a table is the column rule D124 holds sections apart
   with, turned on its side inside a thead; a written order is the label voice; the on-sale line
   is the outline chip and a run of mono; and the phone form is the ruled list the feed and the
   tracklisting already are. No radius, no fill, no shadow, no ornament: a mark here either
   carries a figure or it is not drawn.
   ===================================================================== */

/* ---- 1. The control row -------------------------------------------------
   A counted filter on the left, the written controls on the right. The counts are the point:
   "have I got three free songs for a single" is the release wizard's own gate, and it is
   answered by the control rather than by pressing it. */
.cat-controls{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:14px 26px;flex-wrap:wrap;margin-bottom:14px}
.cat-controls .tabs{border-bottom:0;margin-bottom:0;flex:1 1 auto}
.cat-controls .tab{padding:6px 14px 7px}
.cat-controls .tab:first-child{padding-left:0}
.cat-controls__written{display:flex;align-items:flex-end;gap:8px 26px;flex-wrap:wrap}
.tab__n{font-family:var(--ff-mono);font-size:11px;letter-spacing:0;margin-left:7px;color:var(--paper-4)}
.tab.is-active .tab__n{color:var(--paper-2)}
/* The short label the filter takes on a phone, where the section name above it has already said
   what the list is and the long form would only wrap. */
.tab .sm{display:none}

/* An order set as type, not as buttons. The old Discography spent the page's only raised voice
   on a filled accent sort toggle; a sort is not the action on a page (The One Voice Rule), so
   the chosen one is marked with ink and a rule and the rest are quiet. */
.sortbar{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;padding-bottom:7px}
.sortbar__k{
  font-family:var(--ff-disp);font-size:10.5px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--paper-4)}
.sortbar__o{
  font-family:var(--ff-disp);font-size:13px;font-weight:600;letter-spacing:.05em;
  text-transform:uppercase;color:var(--paper-3);text-decoration:none;
  border-bottom:1px solid transparent;padding-bottom:2px}
.sortbar__o:hover{color:var(--paper)}
.sortbar__o.is-on{color:var(--paper);border-bottom-color:var(--paper)}
.sortbar__n{font-family:var(--ff-mono);font-size:11px;letter-spacing:0;margin-left:5px;color:var(--paper-4)}
.sortbar__o.is-on .sortbar__n{color:var(--paper-2)}

/* ---- 2. The records table -----------------------------------------------
   One row per record carrying both stories, which is the whole reason five pages became one. */
.cat-tbl{table-layout:auto;width:100%}
.cat-tbl td,.cat-tbl th{padding-right:14px}
.cat-tbl td:last-child,.cat-tbl th:last-child{padding-right:0}
.cat-tbl .c-art{width:40px;padding-right:0}
.cat-tbl .c-fmt{width:70px}
.cat-tbl .c-cert{width:112px}
.cat-tbl .c-act{width:62px;text-align:right}
.cat-tbl .c-act .btn{padding:3px 9px;font-size:11px}
.cat-tbl td.num,.cat-tbl th.num{white-space:nowrap}
.cat-tbl .c-title a{font-weight:500}
/* A title and a partner band are both things a player typed, so neither may set the width of the
   row. The collab chip is an inline-block, which means a 37-character band name inside it is one
   unbreakable box: it took the merged row 60px past the measure at 390 on the first band that had
   one. It wraps, and both names break rather than push. */
.cat-tbl .c-title,.song-tbl .c-song,.song-tbl .c-where{overflow-wrap:anywhere}
.cat-tbl .feat-badge{margin-left:4px;max-width:100%;white-space:normal}

/* The figure groups. A column rule one rank above a row's hairline, which is what has held the
   dashboard's columns apart since D123, standing up inside a table head. It separates what a
   record did last night from what it did over its life so that one row can carry both without
   the reader losing which is which, and it is why the season span is printed in the group's own
   name: only that half of the row follows it. The group name sits ABOVE the column names and
   draws no rule of its own, because the column rule under it is already the division. */
.cat-tbl thead .grp th{
  border-bottom:0;padding-bottom:3px;
  font-family:var(--ff-disp);font-size:10.5px;font-weight:700;letter-spacing:.16em;
  text-transform:uppercase;color:var(--paper-3);text-align:left}
.cat-tbl thead .grp th.g-start{padding-left:16px}
.cat-tbl .g-start{border-left:1px solid var(--paper-4)}
.cat-tbl td.g-start,.cat-tbl th.num.g-start{padding-left:16px}

/* ---- 3. The on-sale line ------------------------------------------------
   Chart Watch, in the row it describes. It was the least visited page of the core set (88 views,
   2.3 per manager) and these are the figures a player opens the game to read. The chip is the
   outline, never the fill: a state marker is not an action, and a filled accent chip on eleven
   rows would be eleven reds on a page that has one. */
.now-line{display:flex;align-items:baseline;gap:8px 14px;flex-wrap:wrap;margin-top:6px}
.now-pos{
  font-family:var(--ff-mono);font-size:11.5px;letter-spacing:.02em;
  color:var(--paper-3);white-space:nowrap}
.now-pos b{color:var(--paper);font-weight:400}
/* The markets a record is on sale in but not charting, counted rather than listed. A record out
   in all fifteen would otherwise carry fifteen positions and run to six lines on a phone; the
   board found this and did not solve it, and this is the answer it said it would give. */
.now-pos--quiet{font-family:var(--ff-body);font-size:12px;color:var(--paper-4)}
/* The sentence takes the room left over beside the icon and wraps inside it. Without a basis it
   is sized to its own content, so on a phone it drops to the line below and leaves the icon
   standing alone on a line, which reads as ornament (D125) rather than as the mark on a lede. */
.fact-line__say{flex:1 1 200px;min-width:0}

/* ---- 4. The songbook ----------------------------------------------------
   One row per song where three overlapping panels rendered 41 rows for 17 songs. */
.song-tbl .c-where{color:var(--paper-3);max-width:430px}
.song-tbl .c-where a{color:var(--paper-2)}
.song-tbl .c-free{width:168px}
.song-tbl .c-act{width:150px;text-align:right;white-space:nowrap}
.song-tbl .c-act .btn{padding:3px 9px;font-size:11px}
.song-tbl .went{display:block}
.song-tbl .went+.went{margin-top:3px}
.song-tbl .side{font-family:var(--ff-mono);font-size:10.5px;color:var(--paper-4);margin-left:6px}
.song-tbl .sng-del:hover{color:var(--bad);border-color:var(--bad)}
/* Two outline chips, both on the standard chip's own padding. .chip--now is D124's own current
   state marker and it has never actually drawn its outline: .chip carries no border at all, so a
   lone border-color set nothing and the loudest chip in the system has been rendering as a filled
   Lifted block since Batch 60. The rule is stated in DESIGN.md and this is it: Newsprint border,
   Newsprint ink, no fill. It corrects the season chips on /awards as a side effect, which is the
   page it was written for. */
.chip--now{background:none;border:1px solid var(--paper);color:var(--paper)}
.chip--free{background:none;border:1px solid var(--line-2);color:var(--paper-2);margin-right:6px}
/* Rename, which used to be twelve always-open text boxes down the page and is now one field on
   the row you asked for it on. */
.rename-live{display:inline-flex;align-items:center;gap:8px;margin:0}
.rename-live .input{width:260px;padding:5px 9px;font-size:13px}
.rename-live .btn{padding:4px 11px;font-size:11px}

/* ---- 5. The artwork action, on the record's own page --------------------
   The dependency this batch had to build first: until now the only route to a sleeve anywhere in
   the game was the last column of three tables, and the merged list drops that column on a
   phone. It sits under the sleeve it changes. */
.detail-art-act{display:block;margin-top:12px;text-align:center}

/* =====================================================================
   THE PHONE. Not a caveat: the same information in the shape a hand can read. Batch 66 made the
   whole game work at 360 and 390 and this family was the worst of it - five of the eight pages
   needed a sideways swipe, because an eight-column table cannot be made to fit and only the
   merge removes it. The wide table becomes a run of ruled entries; the figures that rank a
   record survive and the rest go to the record's own page, which carries every one of them.
   760 rather than 640: the eleven-column row runs out of measure well before the shell does.
   ===================================================================== */
@media (max-width:760px){
  .cat-controls{gap:10px 16px;margin-bottom:12px}
  /* The filter scrolls in place rather than wrapping to three lines and pushing the first row
     off the screen, which is what the nine-item strip did on the pages this replaced. */
  .cat-controls .tabs{
    flex-wrap:nowrap;overflow-x:auto;width:100%;
    -webkit-overflow-scrolling:touch;scrollbar-width:none}
  .cat-controls .tabs::-webkit-scrollbar{display:none}
  .cat-controls .tab{white-space:nowrap;padding:6px 12px 7px;font-size:13px}
  .cat-controls__written{width:100%;gap:8px 20px}
  .tab .lg{display:none}
  .tab .sm{display:inline}
  .sortbar{padding-bottom:0;gap:12px}
  .sortbar__o{font-size:12.5px}
  /* The section head's own act slot stops pushing to the right margin, which at this width is
     four pixels away from the name. */
  .page-sec__act{margin-left:0;width:100%}

  /* The table stops being a table: one ruled entry per record, the sleeve beside it, and the
     figures that rank it set as a mono line under the title. */
  .cat-tbl,.cat-tbl tbody,.cat-tbl tr,.cat-tbl td{display:block;width:auto}
  .cat-tbl thead{display:none}
  .cat-tbl tr{
    display:flex;flex-wrap:wrap;align-items:flex-start;
    column-gap:12px;row-gap:7px;padding:13px 0 15px;border-top:1px solid var(--line)}
  .cat-tbl tbody tr:first-child{border-top:0;padding-top:4px}
  .cat-tbl td{padding:0;border:0}
  .cat-tbl .c-art{flex:0 0 44px;order:1;overflow:hidden}
  .cat-tbl .art-img--thumb,.cat-tbl .art--thumb{width:44px;height:44px}
  .cat-tbl .c-title{order:2;flex:1 1 0;min-width:calc(100% - 56px);font-size:14.5px;line-height:1.3}
  .cat-tbl .c-title a{font-weight:600}
  .cat-tbl .c-fmt{order:3;margin-left:56px}
  .cat-tbl .c-cert{order:4}
  /* An uncertified record prints a hyphen in the desktop column because the column has a heading
     to answer. On a phone the heading is gone and the hyphen is a mark carrying nothing, so the
     cell goes with it. */
  .cat-tbl td.c-cert:has(> .tc-paper-4){display:none}
  .cat-tbl td.num{
    order:5;font-family:var(--ff-mono);font-size:11.5px;color:var(--paper-2);white-space:nowrap}
  /* Of the figures a record carries, three come to the phone: how old it is, what it sold, and
     where it got to. The rest are one tap away on the record's own page, which has them all.
     Choosing three instead of squeezing in eight is why nothing scrolls sideways. */
  .cat-tbl td[data-l="week"],.cat-tbl td[data-l="streams"],
  .cat-tbl td[data-l="rating"],.cat-tbl .c-act{display:none}
  .cat-tbl td.num::before{
    content:attr(data-l) " ";font-family:var(--ff-disp);font-weight:600;font-size:10px;
    letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4)}
  .cat-tbl .now-line{margin-top:7px;width:100%}
  .cat-tbl .feat-badge{display:inline-block;margin:5px 0 0}
  /* No column rule survives a single column: there is nothing either side of it to hold apart. */
  .cat-tbl .g-start{border-left:0}
  /* The sticky first cell D130 gave every table is for a table that scrolls sideways. This one
     no longer is one, and a sticky block-level cell would paint over the row beside it. */
  .table-wrap .cat-tbl tbody td:first-child,.table-wrap .song-tbl tbody td:first-child{
    position:static;box-shadow:none;background:none}

  /* The songbook, the same way. A song is either pressed or free, so the empty half collapses
     rather than holding a line open: two lines a row, not three. */
  .song-tbl,.song-tbl tbody,.song-tbl tr,.song-tbl td{display:block;width:auto}
  .song-tbl thead{display:none}
  .song-tbl tr{
    display:flex;flex-wrap:wrap;align-items:baseline;
    column-gap:10px;row-gap:6px;padding:12px 0 13px;border-top:1px solid var(--line)}
  .song-tbl tbody tr:first-child{border-top:0;padding-top:4px}
  .song-tbl td{padding:0;border:0}
  /* The title takes everything but the rating, so line one is always the title and the rating and
     the marks always start line two. Left to size itself, a short title let the chips and the two
     actions ride up beside it and the rating landed in a different place on every third row. */
  .song-tbl .c-song{order:1;flex:1 1 auto;min-width:calc(100% - 96px);font-size:14.5px;font-weight:600}
  .song-tbl td.num{
    order:2;flex:0 0 auto;font-family:var(--ff-mono);font-size:12.5px;color:var(--paper-2)}
  .song-tbl td.num::before{
    content:"rated ";font-family:var(--ff-disp);font-weight:600;font-size:10px;
    letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4)}
  .song-tbl .c-where{order:3;flex:1 1 100%;max-width:none;font-size:12.5px}
  .song-tbl .c-where--none,.song-tbl .c-free--none{display:none}
  .song-tbl .c-free{order:4;flex:1 1 auto;width:auto}
  .song-tbl .c-act{order:5;flex:0 0 auto;width:auto;text-align:right}
  /* Batch 66's 44px floor: two of these are the only way to rename or delete a song. */
  .song-tbl .c-act .btn,.cat-tbl .c-act .btn{min-height:44px;padding:6px 12px;font-size:12.5px}
  .rename-live{display:flex;flex-wrap:wrap;gap:7px;width:100%}
  .rename-live .input{width:100%;flex:1 1 100%;min-height:44px}
  .rename-live .btn{flex:1 1 auto;min-height:44px}
}
/* ================= end D136 MY MUSIC ================= */

/* ================= D138 (Batch 73) INBOX RETENTION + TOUR HISTORY =================
   Two surfaces, one argument: a message should mean "something important". The inbox gains the
   two bulk controls it never had, and the tour receipt that was drowning it moves to /tour as a
   ruled list of what each tour actually did. */

/* ---------- the inbox bulk bar ----------
   A row of controls, not a block, and it draws NO rule of its own. The list underneath already
   announces itself with the panel's 2px paper rule, and a hairline here landed a pixel above it
   and read as one 3px bar - the stacked-rule fault D123 names. Space separates them instead, and
   the panel's rule stays the one edge in this part of the page. The count sits left and is the
   reason either button is live or dead. */
.bulk-bar{
  display:flex;align-items:center;flex-wrap:wrap;gap:9px;margin:0 0 20px}
.bulk-bar form{margin:0}
.bulk-bar__count{
  margin-right:auto;font-size:13px;color:var(--paper-3);white-space:nowrap}
.bulk-bar__count b{font-family:var(--ff-mono);font-weight:400;color:var(--paper)}
.bulk-bar__sep{color:var(--paper-4);padding:0 3px}
/* Batch 66's 44px floor. These are bulk actions reached by thumb as often as by mouse, and the
   base button is 36px, so the size is set here rather than borrowed from .btn--sm. */
.btn--bulk{min-height:44px;padding:12px 18px;font-size:13px}

/* ---------- /tour: Recent tours ---------- */
.tourh__none{font-size:13.5px;color:var(--paper-3);margin:0;max-width:62ch}
/* Caption and row share one template, which is the only reason the captions sit over their own
   figures without a table to hold them there. */
.tourh-grid{
  display:grid;grid-template-columns:106px minmax(0,1fr) auto auto;
  column-gap:20px;row-gap:5px;align-items:baseline}
.tourh__cap{
  padding-bottom:7px;border-bottom:1px solid var(--line);
  font-family:var(--ff-disp);font-weight:600;font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--paper-4)}
.tourh__rows{list-style:none;margin:0;padding:0}
.tourh__row{padding:12px 0 13px;border-bottom:1px solid var(--line)}
.tourh__row:last-child{border-bottom:0}
.tourh__when{font-family:var(--ff-mono);font-size:12px;color:var(--paper-3);white-space:nowrap}
.tourh__id{min-width:0}
.tourh__where{font-weight:600;color:var(--paper)}
.tourh__nights{font-size:12.5px;color:var(--paper-3);margin-left:9px}
.tourh__fig{
  font-family:var(--ff-mono);font-size:13px;color:var(--paper-2);
  text-align:right;white-space:nowrap}
.tourh__fig--money{color:var(--paper)}
/* What the tour moved, under the ledger it earned. Starts in the identity column so the figures
   above keep a clean right edge and the line reads as a note on the tour, not a fifth column. */
.tourh__moved{
  grid-column:2 / -1;display:flex;flex-wrap:wrap;column-gap:16px;row-gap:4px;margin-top:2px}
.tourh__d{font-size:12.5px;white-space:nowrap}
.tourh__dn{color:var(--paper-4)}
.tourh__dv{font-family:var(--ff-mono);color:var(--paper-2)}

@media (max-width:640px){
  /* The captions cannot follow the reflow, so they go and each figure carries its own
     micro-label - the .cat-tbl convention, so a phone reads the same way across the game. */
  .tourh__cap{display:none}
  .tourh-grid{grid-template-columns:minmax(0,1fr) auto;column-gap:12px;row-gap:6px}
  .tourh__row{padding:13px 0 14px}
  /* Line one is the tour and what it paid; line two is when and how many came. Explicit
     placement, because auto-flow would put the date first and the date is the least of it.
     ORDER MATTERS HERE: the money cell carries both .tourh__fig and .tourh__fig--money at the
     same specificity, so the modifier has to come AFTER the base rule or the base wins on source
     order and both figures land in row 2 on top of each other. That is the exact defect Carl
     caught on the D121 chart board, and it looks like this: "TICKETS 1£855". */
  .tourh__id{grid-column:1;grid-row:1}
  .tourh__when{grid-column:1;grid-row:2}
  .tourh__fig{grid-column:2;grid-row:2}
  .tourh__fig--money{grid-column:2;grid-row:1;font-size:13.5px}
  .tourh__moved{grid-column:1 / -1;grid-row:3;margin-top:4px;column-gap:14px}
  .tourh__fig::before{
    content:attr(data-l) " ";font-family:var(--ff-disp);font-weight:600;font-size:10px;
    letter-spacing:.14em;text-transform:uppercase;color:var(--paper-4)}
  .tourh__fig--money::before{content:none}
  .tourh__nights{display:block;margin-left:0;margin-top:2px}
  /* The count is the bar's own line once the buttons need the width, and each button takes half
     the row rather than shrinking below the thumb target. */
  .bulk-bar__count{flex:1 1 100%;margin-right:0;white-space:normal}
  .bulk-bar form{flex:1 1 0;min-width:0}
  .btn--bulk{width:100%;padding:12px 10px}
}
/* ================= end D138 ================= */

/* ===========================================================================
   D139 (Batch 74) - THE RUNDOWN.

   The nightly digest stopped being a message and became a page. This block is
   the component the approved board specified, appended whole with nothing above
   it edited: docs/design/backstage/last-night.html, placement B's markup, hosted
   by /rundown instead of by the status page. The board's own section 1, a block
   head for placement A, is not here, because placement A is not what shipped.

   The grammar is D123 "The Galley" and D124 "The front page", unchanged: no
   radius, no shadow, no box. A rule with a name under it announces a block,
   hairlines rule the rows inside it, and figures are mono so a column of them
   compares down the page. This component defines no colour of its own; both
   themes are the game's tokens.
   ========================================================================= */

/* The section head's pointer at the catalogue. A marked link and not a button:
   no other section head in the game carries a control, and a boxed one beside a
   2px rule becomes the loudest thing in the section. */
.page-sec__head .ln__go{
  color:var(--paper-2);text-decoration:none;font-family:var(--ff-disp);
  font-size:11.5px;font-weight:700;letter-spacing:.13em;text-transform:uppercase}
.page-sec__head .ln__go:hover{color:var(--accent)}

/* The status page's one line about last night sits under the season line, so
   the two ruled lines share a seam rather than each opening their own. */
.dash-season+.dash-season{margin-top:11px}

/* ---- 2. The lede --------------------------------------------------------
   The Rundown's own opening sentence, kept word for word. It is the one piece
   of prose in the component; everything under it is a column of record. */
.ln__lede{margin:11px 0 0;font-size:13.5px;color:var(--paper-2)}
.ln__lede b{color:var(--paper);font-weight:600}

/* ---- 3. The ledger ------------------------------------------------------
   Every field the Rundown composes, in the order it composes them: the title
   and its kind, this week's units, the lifetime total, the world chart
   position with its move, and the week's streams. The title stays in the body
   face and in the case the player typed it. Release titles in this world run
   to sixty characters, and a condensed-caps setting of one would eat the block
   that this whole change exists to keep short. */
.ln-led{width:100%;border-collapse:collapse;font-size:13.5px;margin-top:12px;
  font-variant-numeric:tabular-nums}
.ln-led th{
  text-align:left;padding:0 0 7px;font-family:var(--ff-disp);font-size:11px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--paper-4);font-weight:600;
  border-bottom:1px solid var(--line-2);white-space:nowrap}
.ln-led td{padding:9px 0;border-bottom:1px solid var(--line);color:var(--paper-2);vertical-align:baseline}
.ln-led th+th,.ln-led td+td{padding-left:22px}
.ln-led .n{font-family:var(--ff-mono);text-align:right;white-space:nowrap;color:var(--paper)}
.ln-led th.n{text-align:right}
.ln-led__t{color:var(--paper);font-weight:600}
.ln-led__k{font-family:var(--ff-disp);font-size:11px;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:var(--paper-4);white-space:nowrap;margin-left:9px}
/* A collab line names the partner, and every figure on it is this band's share (D102). */
.ln-led__with{color:var(--paper-3);font-weight:400}
.ln-led__share{font-family:var(--ff-mono);font-size:11px;color:var(--paper-4);white-space:nowrap}
/* The chart cell: the position, then the move in words. The Rundown says "up 6",
   "down 3", "no change" and "new entry", and words are what it keeps here. An
   arrow glyph would be a second icon system beside a drawn set that has none. */
/* The position and its move are one statement, so they are one flex item on a
   phone rather than two the row can push apart. */
.ln-led__chart{display:inline-flex;align-items:baseline;white-space:nowrap}
.ln-led__pos{font-family:var(--ff-mono);color:var(--paper)}
.ln-mv{font-family:var(--ff-mono);font-size:11.5px;margin-left:8px;white-space:nowrap}
.ln-mv--up{color:var(--up)}
.ln-mv--down{color:var(--down)}
.ln-mv--hold{color:var(--hold)}
/* A new entry is the loudest thing a row can say, and the accent is spoken for on
   this page, so it is marked in full strength ink over a rule instead of a fill. */
.ln-mv--new{color:var(--paper);border-bottom:1px solid var(--paper-4);padding-bottom:1px}
.ln-led__none{color:var(--paper-4)}
/* The catalogue cap. Forty releases on sale is a real shape in this world, and a
   forty row ledger is the tall block this change exists to avoid, so the ledger
   runs to twelve and the rest is summed into one honest row. */
.ln-led__rest td{color:var(--paper-3)}
.ln-led__rest a{color:var(--paper-2)}
.ln-led tfoot td{
  border-bottom:0;border-top:1px solid var(--line-2);padding-top:10px;
  color:var(--paper-3);font-size:12.5px}
.ln-led tfoot .n{color:var(--paper)}

/* ---- 4. The money line --------------------------------------------------
   The Rundown's earnings and streaming totals, set as the fact line D124
   already uses for the wave and the achievements tally. Same component. */
.ln__money{margin-top:12px}
.ln__money .ic{color:var(--paper-3)}

/* ---- 5. Campaigns -------------------------------------------------------
   One row per live campaign: the type, what it is on, what it returned, and
   the lift it is applying. The engine's own note rides underneath in the quiet
   tier, because it is colour rather than a figure. */
.ln-promo{margin-top:16px}
.ln-promo__cap{
  font-family:var(--ff-disp);font-size:11px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--paper-4);padding:0;margin:0}
.ln-promo__row{
  display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:4px 22px;align-items:baseline;
  padding:9px 0;border-bottom:1px solid var(--line);font-size:13.5px;color:var(--paper-2)}
.ln-promo__row:first-of-type{border-top:1px solid var(--line-2);margin-top:8px}
.ln-promo__what{display:flex;align-items:baseline;gap:9px;min-width:0}
.ln-promo__what .ic{color:var(--paper-3);flex:none;align-self:center;width:16px;height:16px}
.ln-promo__what b{color:var(--paper);font-weight:600}
.ln-promo__n{font-family:var(--ff-mono);color:var(--paper);white-space:nowrap;
  font-variant-numeric:tabular-nums}
.ln-promo__lift{font-family:var(--ff-mono);font-size:12px;color:var(--paper-3);white-space:nowrap}
.ln-promo__note{grid-column:1/-1;font-size:12.5px;color:var(--paper-3);margin:0}
.ln-promo__more{padding:9px 0 0;font-size:12.5px;color:var(--paper-3)}
.ln-promo__more a{color:var(--paper-2)}

/* ---- 6. The quiet night and the first night -----------------------------
   Two states, both of them copy the game already writes. Neither is an empty
   state in the usual sense: something did happen, it just did not happen to
   this band, and the section says so in the Rundown's own words. */
.ln__quiet{margin:12px 0 0;font-size:13.5px;color:var(--paper-2);max-width:74ch}
.ln__quiet+.ln__quiet{margin-top:10px;color:var(--paper)}
.ln__first{margin:12px 0 0;font-size:13.5px;color:var(--paper-2);max-width:74ch}
.ln__first+.ln__first{margin-top:10px}
.ln__first b{color:var(--paper);font-weight:600}

/* ---- 7. The seven night trail -------------------------------------------
   The reason this can leave the inbox at all: a player away for three days
   still gets the trail. Six one line nights under last night's ledger,
   collapsed, with no read state and no dismiss, because a page section has
   neither. The marker is hidden and the summary says its own state in words:
   the disclosure triangle is a browser default and belongs to no design
   system, which is the cheapest tell there is. */
.ln-trail{margin-top:18px;border-top:1px solid var(--line-2)}
.ln-trail>summary{
  list-style:none;cursor:pointer;display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;
  padding:9px 0 8px;font-size:13px;color:var(--paper-2)}
.ln-trail>summary::-webkit-details-marker{display:none}
.ln-trail>summary b{
  font-family:var(--ff-disp);font-size:11.5px;font-weight:700;letter-spacing:.13em;
  text-transform:uppercase;color:var(--paper-2)}
.ln-trail>summary .mono{font-family:var(--ff-mono);font-size:12px;color:var(--paper-4)}
.ln-trail>summary:hover b,.ln-trail>summary:hover .ln-trail__cue{color:var(--accent)}
.ln-trail__cue{
  margin-left:auto;font-family:var(--ff-disp);font-size:11.5px;font-weight:700;
  letter-spacing:.13em;text-transform:uppercase;color:var(--paper-4)}
.ln-trail:not([open]) .ln-trail__cue--open,
.ln-trail[open] .ln-trail__cue--shut{display:none}
.ln-trail>summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.ln-trail__list{list-style:none;margin:0;padding:0 0 4px}
.ln-trail__row{
  display:grid;grid-template-columns:minmax(0,116px) minmax(0,1fr) minmax(0,112px) minmax(0,150px);
  gap:0 22px;align-items:baseline;padding:8px 0;border-top:1px solid var(--line);
  font-size:13px;color:var(--paper-2);font-variant-numeric:tabular-nums}
.ln-trail__d{font-family:var(--ff-mono);font-size:12.5px;color:var(--paper-3);white-space:nowrap}
.ln-trail__n{font-family:var(--ff-mono);color:var(--paper);text-align:right;white-space:nowrap}
.ln-trail__c{font-family:var(--ff-mono);font-size:12.5px;color:var(--paper-2);text-align:right;white-space:nowrap}
.ln-trail__q{color:var(--paper-4);grid-column:2/-1}

/* ---- 8. Placement B -----------------------------------------------------
   The same markup hosted by a .page-sec instead of a block. Nothing here is a
   new look: it is the section furniture already shipped in D124, and the only
   rule this file adds stops the ledger drawing a second top edge under a
   section head that has already drawn one. */
.page-sec .ln>.ln-led:first-child,
.page-sec .ln>.ln__lede:first-child{margin-top:2px}

/* ---- 9. Phones ----------------------------------------------------------
   At 390 and 360 the ledger stops being a table and becomes what it always was
   underneath: one release per ruled row, its title on the first line and its
   figures on a second, labelled in the quiet tier so no column heading is
   needed. Nothing is hidden and nothing scrolls sideways. */
@media (max-width:640px){
  .ln-led thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .ln-led,.ln-led tbody,.ln-led tfoot,.ln-led tr,.ln-led td{display:block;width:auto}
  .ln-led tr{border-bottom:1px solid var(--line);padding:10px 0}
  .ln-led td{border-bottom:0;padding:0}
  .ln-led td:empty{display:none}
  .ln-led td+td{padding-left:0}
  .ln-led td.ln-led__cell{display:flex;justify-content:space-between;gap:14px;align-items:baseline;
    padding-top:5px;font-size:13px}
  .ln-led__cell::before{
    content:attr(data-k);font-family:var(--ff-disp);font-size:10.5px;font-weight:600;
    letter-spacing:.13em;text-transform:uppercase;color:var(--paper-4);flex:none}
  .ln-led .n{text-align:right}
  .ln-led tfoot td{border-top:1px solid var(--line-2);padding-top:10px}
  .ln-led tfoot .ln-led__cell{padding-top:3px}
  .ln-promo__row{grid-template-columns:minmax(0,1fr);gap:5px}
  .ln-promo__n,.ln-promo__lift{text-align:left}
  /* One night becomes one wrapping run rather than a grid: four columns inside
     360px would set each figure on a line of its own. */
  .ln-trail__row{display:flex;flex-wrap:wrap;gap:2px 16px;align-items:baseline}
  .ln-trail__d{flex:0 0 100%}
  .ln-trail__n,.ln-trail__c{text-align:left}
}
/* ================= end D139 ================= */
