/*
 * Pop Boll — one stylesheet for all three pages.
 *
 * The look: a 1982 home computer that just booted. A solid border colour around a dark
 * "screen", a bitmap display face, inverse-video labels, hard pixel edges everywhere.
 * Rules that keep it coherent:
 *   - every border, gap and offset is a multiple of --u (4px); nothing is rounded,
 *     blurred or smoothly graded
 *   - two type roles only: PBOLL (the 5x7 bitmap face, sizes in multiples of 10px) for
 *     display, labels and buttons; a plain monospace at >= 16px for reading
 *   - the 16 musician colours live only inside the device; the page uses five colours
 *   - every colour is a palette token (docs/PALETTES.md): no hex below the :root block. A fill
 *     X takes its text colour from --X-on, and X as text on a surface is --X-fg
 */

@font-face {
  font-family: "PBOLL";
  src: url("/static/fonts/pboll.woff") format("woff"), url("/static/fonts/pboll.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

:root {
  --u: 4px;

  /* The palette (docs/PALETTES.md): OGPB's tokens, the default. palettes.css overrides them per
     :root[data-palette="..."]; both blocks are generated by tools/build_palettes.py from palettes.py. */
  /* palette:begin */
  --ink: #0d0a3a;
  --well: #0d0a3a;
  --bg: #20175e;
  --panel: #2c2180;
  --line: #5b4fc4;
  --frame: #7c70da;
  --soft: #b9b3f2;
  --text: #ecebff;
  --paper: #ffffff;
  --primary: #ffe45c;
  --secondary: #7deaf2;
  --tertiary: #ff6b9a;
  --live: #ff6b9a;
  --ok: #6fe89a;
  --warn: #ff9f43;
  --error: #ff6b9a;
  --role-drums: #ff6b9a;
  --role-bass: #7deaf2;
  --role-chords: #6fe89a;
  --role-lead: #ffe45c;
  --role-pad: #a78bfa;
  --role-arp: #ff9f43;
  --role-fx: #ecebff;
  --tier-common: #9a9ab8;
  --tier-uncommon: #6fe89a;
  --tier-rare: #7deaf2;
  --tier-epic: #c08cff;
  --tier-legendary: #ffe45c;
  --tier-secret: #ff6b9a;
  --ball: #e4e0ff;
  --bezel: #0a0a12;
  --led: #78afff;
  --ink-hi: #150f45;
  --bg-hi: #261c6f;
  --line-lo: #3d3199;
  --soft-on: #0d0a3a;
  --text-on: #0d0a3a;
  --primary-lo: #c9a914;
  --primary-fg: #ffe45c;
  --primary-on: #0d0a3a;
  --secondary-fg: #7deaf2;
  --secondary-on: #0d0a3a;
  --tertiary-fg: #ff6b9a;
  --tertiary-on: #0d0a3a;
  --live-on: #0d0a3a;
  --ok-fg: #6fe89a;
  --ok-on: #0d0a3a;
  --warn-on: #0d0a3a;
  --error-fg: #ff6b9a;
  --error-on: #0d0a3a;
  --tier-common-on: #0d0a3a;
  --tier-uncommon-on: #0d0a3a;
  --tier-rare-on: #0d0a3a;
  --tier-epic-on: #0d0a3a;
  --tier-legendary-deep: #8a6d00;
  --tier-legendary-on: #0d0a3a;
  --tier-secret-on: #0d0a3a;
  --strong: #ffffff;
  --ink-rgb: 13, 10, 58;
  /* palette:end */

  /* older names (device.js reads the ball's), kept as aliases of the palette tokens */
  --border: var(--frame);
  --yellow: var(--primary);
  --cyan: var(--secondary);
  --pink: var(--tertiary);
  --green: var(--ok);
  --ball-line: var(--ink);
  --ball-shadow: var(--ink-hi);
  --btn-face: var(--primary);
  --btn-shade: var(--primary-lo);
  --led-off: var(--line-lo);
  --turtle: var(--ok);

  --display: "PBOLL", ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --body: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --s: 2;                   /* device scale: CSS pixels per screen pixel */
  --pad: calc(var(--u) * 4); /* the frame's side padding */
}

*, *::before, *::after { box-sizing: border-box; }

/* nothing is pinned to the top of the page (0.2.3): focus and #hash jumps keep a small margin */
html { -webkit-text-size-adjust: 100%; scroll-padding-top: calc(var(--u) * 2); }

body {
  margin: 0;
  background: var(--frame);
  color: var(--text);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.6;
}

h1, h2, p, ol, ul { margin: 0; padding: 0; }
ol, ul { list-style: none; }
canvas { image-rendering: pixelated; image-rendering: crisp-edges; display: block; }
[hidden] { display: none !important; }

a { color: var(--secondary-fg); text-decoration-thickness: 2px; text-underline-offset: 4px; }
a:hover { color: var(--primary-fg); }

:focus-visible { outline: var(--u) solid var(--primary); outline-offset: var(--u); }

.skip {
  position: absolute; left: calc(var(--u) * 2); top: -80px; z-index: 20;
  background: var(--primary); color: var(--primary-on);
  font-family: var(--display); font-size: 20px; line-height: 1; padding: calc(var(--u) * 3);
}
.skip:focus { top: calc(var(--u) * 2); }

/* ── the machine's screen ─────────────────────────────────────────────────────────────── */

.frame {
  background: var(--bg);
  margin: calc(var(--u) * 2);
  min-height: calc(100vh - var(--u) * 4);
  padding: 0 var(--pad) calc(var(--u) * 8);
  display: flex;
  flex-direction: column;
}

main { flex: 1; width: 100%; max-width: 1320px; margin: 0 auto; }

.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: calc(var(--u) * 3);
  padding: calc(var(--u) * 4) 0 calc(var(--u) * 7);
  width: 100%; max-width: 1320px; margin: 0 auto calc(var(--u) * 8);
  /* the early-80s stripe: three hard bands, no blending */
  background: linear-gradient(to bottom, var(--tertiary) 0 4px, var(--primary) 4px 8px, var(--secondary) 8px 12px) left bottom / 100% 12px no-repeat;
}

.wordmark {
  display: inline-flex; align-items: center; gap: calc(var(--u) * 2);
  font-family: var(--display); font-size: 20px; line-height: 1;
  color: var(--text); text-decoration: none; white-space: nowrap;
  padding: var(--u) 0;
}
.wordmark:hover { color: var(--primary-fg); }
.wordmark svg { width: 24px; height: 24px; flex: none; }
.wordmark-mark { width: 32px; height: 32px; flex: none; image-rendering: pixelated; }

.nav { display: flex; align-items: center; gap: var(--u); }
.wide-only { display: none; }
.navlink {
  font-family: var(--display); font-size: 20px; line-height: 1;
  color: var(--text); text-decoration: none; background: none;
  border: var(--u) solid transparent; padding: calc(var(--u) * 2) var(--u);
  cursor: pointer; min-height: 44px; display: inline-flex; align-items: center; white-space: nowrap;
}
.navlink:hover { color: var(--primary-fg); border-color: var(--line); }
.navlink.is-here { background: var(--text); color: var(--bg); }

/* ── type ─────────────────────────────────────────────────────────────────────────────── */

.display {
  font-family: var(--display); font-weight: 400;
  font-size: 40px; line-height: 1.1; letter-spacing: 0;
  color: var(--text);
}
.h2 {
  font-family: var(--display); font-weight: 400; font-size: 20px; line-height: 1;
  color: var(--bg); background: var(--soft);
  display: inline-block; padding: var(--u) calc(var(--u) * 2);
}
.lede { font-size: 18px; line-height: 1.6; max-width: 46ch; color: var(--text); }
.fineprint { font-size: 16px; color: var(--soft); }
.label { font-family: var(--display); font-size: 20px; line-height: 1; display: block; }

.tag {
  font-family: var(--display); font-size: 20px; line-height: 1;
  display: inline-block; padding: var(--u) calc(var(--u) * 2);
  background: var(--text); color: var(--bg); white-space: nowrap;
}

/* ── buttons: inverse-video blocks with a hard offset edge ────────────────────────────── */

.btn {
  font-family: var(--display); font-size: 20px; line-height: 1; font-weight: 400;
  display: inline-flex; align-items: center; justify-content: center; gap: calc(var(--u) * 2);
  min-height: 48px; padding: calc(var(--u) * 3) calc(var(--u) * 4);
  color: var(--text); background: var(--panel);
  border: var(--u) solid var(--text);
  box-shadow: var(--u) var(--u) 0 0 var(--ink);
  text-decoration: none; text-transform: uppercase; white-space: nowrap;
  cursor: pointer; user-select: none; -webkit-user-select: none;
  touch-action: manipulation;
}
.btn:hover { background: var(--text); color: var(--bg); }
.btn:active, .btn.is-down { transform: translate(var(--u), var(--u)); box-shadow: none; }
.btn:disabled { cursor: wait; background: var(--panel); color: var(--soft); border-color: var(--line); box-shadow: none; transform: none; }

.btn-primary { background: var(--primary); color: var(--primary-on); border-color: var(--ink); }
.btn-primary:hover { background: var(--text); color: var(--text-on); }

.btn-ghost { background: transparent; border-color: var(--line); box-shadow: none; }
.btn-ghost:hover { background: var(--panel); color: var(--text); border-color: var(--text); }
.btn-ghost:active { transform: none; }

.btn-big { font-size: 20px; min-height: 64px; padding: calc(var(--u) * 4) calc(var(--u) * 6); border-width: var(--u); }
.btn-small { min-height: 44px; padding: calc(var(--u) * 2) calc(var(--u) * 3); }

.cta-row { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 4); align-items: center; }

/* ── ON AIR lamp ──────────────────────────────────────────────────────────────────────── */

.lamp {
  display: inline-block; width: calc(var(--u) * 3); height: calc(var(--u) * 3);
  background: var(--line); flex: none;
}
.lamp.is-on { background: var(--live); animation: blink 1s steps(1, end) infinite; }
@keyframes blink { 50% { background: var(--line); } }

.onair-line {
  display: flex; align-items: flex-start; gap: calc(var(--u) * 3);
  font-size: 16px; color: var(--soft);
}
.onair-line .lamp { margin-top: 7px; }

/* ── the virtual device ───────────────────────────────────────────────────────────────── */

/* on phones the ball is wider than the page, so it runs out to the frame's edge */
.device-mount { margin-inline: calc(var(--pad) * -1); min-width: 0; }
.pbdev-clip { width: 100%; overflow: hidden; }

.pbdev { display: flex; flex-direction: column; align-items: center; gap: calc(var(--u) * 2); }

.pbdev-stage {
  position: relative; flex: none;
  width: calc(240px * var(--s)); height: calc(254px * var(--s));
  /* centre the ball even when it is wider than the page (phones): it simply bleeds off */
  left: 50%; transform: translateX(-50%);
  align-self: flex-start;
}
.pbdev-body { position: absolute; inset: 0; width: 100%; height: 100%; }
.pbdev-lcd {
  position: absolute; cursor: pointer;
  left: calc(45px * var(--s)); top: calc(60px * var(--s));
  width: calc(150px * var(--s)); height: calc(100px * var(--s));
  background: var(--bezel);
}
.pbdev-lcd:focus-visible { outline-offset: calc(var(--u) * 1); }
/* the Uno Q's 13x8 LED matrix window and its RGB LEDs (matrix-view.js PB.MATRIX_BOX: 98,37 44x18) */
.pbdev-matrix {
  position: absolute; pointer-events: none;
  left: calc(98px * var(--s)); top: calc(37px * var(--s));
  width: calc(44px * var(--s)); height: calc(18px * var(--s));
}

.pbdev-btn {
  position: absolute; width: calc(30px * var(--s)); height: calc(30px * var(--s));
  background: transparent; border: 0; padding: 0; cursor: pointer;
  touch-action: none; -webkit-tap-highlight-color: transparent;
}
.pbdev-btn-1 { left: calc(67px * var(--s)); top: calc(171px * var(--s)); }
.pbdev-btn-2 { left: calc(105px * var(--s)); top: calc(175px * var(--s)); }
.pbdev-btn-3 { left: calc(143px * var(--s)); top: calc(171px * var(--s)); }
.pbdev-btn:focus-visible { outline-offset: 0; }

.pbdev-legend {
  display: grid; gap: calc(var(--u) * 2) calc(var(--u) * 5);
  font-size: 16px; line-height: 1.3; color: var(--soft);
  padding: 0 var(--pad);
}
.pbdev-legend li { display: grid; grid-template-columns: auto auto 1fr; column-gap: calc(var(--u) * 2); align-items: center; }
.pbdev-key {
  font-family: var(--display); font-size: 20px; line-height: 1;
  background: var(--primary); color: var(--primary-on);
  padding: var(--u) calc(var(--u) * 1.5);
}
.pbdev-what { color: var(--text); white-space: nowrap; }
.pbdev-hold { white-space: nowrap; font-size: 14px; }

/* ── landing ──────────────────────────────────────────────────────────────────────────── */

/* minmax(0, 1fr): on phones the ball is wider than the column; the column must not grow with it */
.hero { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--u) * 8); align-items: center; }
.hero-copy { display: grid; gap: calc(var(--u) * 6); justify-items: start; }
.hero-device { display: grid; gap: calc(var(--u) * 3); justify-items: center; min-width: 0; }
.hero-device .onair-line { max-width: 52ch; padding: 0 calc(var(--u) * 2); }
/* the mount spans the column (its clip hides what bleeds), it is not as wide as the ball */
.hero-device > .device-mount { justify-self: stretch; }

.steps { margin-top: calc(var(--u) * 14); border-top: var(--u) solid var(--line); padding-top: calc(var(--u) * 8); }
.listing { display: grid; gap: calc(var(--u) * 4); font-size: 18px; max-width: 64ch; }
.listing li { display: grid; grid-template-columns: 3ch 1fr; column-gap: calc(var(--u) * 3); align-items: baseline; }
.listing .ln { color: var(--soft); }
.listing .kw { font-family: var(--display); font-size: 20px; line-height: 1; background: var(--secondary); color: var(--secondary-on); padding: var(--u) calc(var(--u) * 2); margin-right: calc(var(--u) * 2); }

/* ── device page ──────────────────────────────────────────────────────────────────────── */

/* one column pinned to the page width: a wide child (the corpus drop-down sizes itself to its
   longest option) must not stretch the whole page sideways on phones */
.devicepage { display: flex; flex-direction: column; gap: calc(var(--u) * 6); min-width: 0; }
/* the part below the bar: visitor note, the ball, the modules (a two-column grid on wide screens) */
.devbody { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--u) * 6); min-width: 0; }
.mods { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--u) * 6); min-width: 0; }
.devhead { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: calc(var(--u) * 4); }
.devhead-id { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--u) * 2); justify-items: start; min-width: 0; }
.devname { font-family: var(--display); font-weight: 400; font-size: 30px; line-height: 1.1; overflow-wrap: anywhere; }
.devhead-actions { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 3); }
.devcorpus { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 2); max-width: 100%; min-width: 0; }
.devcorpus .label { font-size: 16px; color: var(--soft); }
.input.select {
  flex: 0 1 auto; min-height: 44px; cursor: pointer; max-width: 100%; text-overflow: ellipsis;
  font-family: var(--display); font-size: 18px;
  appearance: none; -webkit-appearance: none;
  padding-right: calc(var(--u) * 9);
  background-image: linear-gradient(45deg, transparent 50%, var(--text) 50%), linear-gradient(135deg, var(--text) 50%, transparent 50%);
  background-position: right calc(var(--u) * 5) center, right calc(var(--u) * 3) center;
  background-size: calc(var(--u) * 2) calc(var(--u) * 2);
  background-repeat: no-repeat;
}
.input.select:hover { border-color: var(--primary); }
.input.select:disabled { cursor: wait; color: var(--soft); }

.visitor-note {
  display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 3);
  border: var(--u) solid var(--line); padding: calc(var(--u) * 3) calc(var(--u) * 4);
}

.statusline {
  font-size: 16px; line-height: 1.5; min-height: calc(1.5em + var(--u) * 6);
  background: var(--well); color: var(--ok-fg);
  border: var(--u) solid var(--line);
  padding: calc(var(--u) * 2) calc(var(--u) * 3);
  overflow-wrap: anywhere;
}
.statusline::after {
  content: ""; display: inline-block; width: 0.6em; height: 1em; margin-left: 0.4em;
  background: var(--ok-fg); vertical-align: -0.15em; animation: cursor 1s steps(1, end) infinite;
}
@keyframes cursor { 50% { background: transparent; } }

/* ── the action bar (docs/BOLLAWAX_0.2.0_PLAN.md D.1) ──────────────────────────────────────
   The very first thing on the device page: MAKE A NEW SONG (with its ME@PROXY toggle) and ENDLESS,
   big. Not pinned (0.2.3, "remove the lock"): the bar scrolls away with the page like everything
   else, so nothing measures it and nothing judders on a phone. The status line and the hints sit
   in #abnotes right under it. */
.actionbar {
  display: grid; gap: calc(var(--u) * 3); min-width: 0;
  background: var(--bg);
  padding: 0 0 calc(var(--u) * 3);
  border-bottom: var(--u) solid var(--line);
  /* on phones the frame's side padding is narrow: bleed the rule out to the frame's edge */
  margin-inline: calc(var(--pad) * -1); padding-inline: var(--pad);
}
.actionbar-row { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 3); align-items: stretch; min-width: 0; }
/* the labels wrap inside the buttons instead of the row */
.actionbar-row .btn-big { white-space: normal; text-align: center; padding-inline: calc(var(--u) * 3); }
/* the device page's row, phones: [MAKE A NEW SONG][ME@PROXY] / [ENDLESS] / [stop after (i)],
   MAKE and ENDLESS in the display face at 28px and full width; ME@PROXY is a compact toggle
   welded to MAKE's right. SKIP TO THE SONG takes MAKE's cell (and size) during the film. */
.makerow {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "make proxy" "endless endless" "cap cap";
  column-gap: calc(var(--u) * 2);
}
.makerow .btn-make, .makerow .btn-skipfilm { grid-area: make; }
.makerow .btn-proxy { grid-area: proxy; }
.makerow .btn-endless { grid-area: endless; }
.makerow .endless-group { grid-area: cap; }
.makerow .btn-make, .makerow .btn-skipfilm, .makerow .btn-endless { font-size: 28px; line-height: 1.05; min-height: 72px; }
.makerow .btn-make, .makerow .btn-skipfilm { min-height: 88px; }
.btn-proxy { font-size: 16px; min-height: 44px; padding-inline: calc(var(--u) * 2); white-space: nowrap; }
.btn-proxy[aria-pressed="true"] { background: var(--warn); color: var(--warn-on); border-color: var(--ink); }
.proxy-hint { margin: 0; color: var(--warn); }
.btn-endless[aria-pressed="true"] { background: var(--ok); color: var(--ok-on); border-color: var(--ink); }
.btn-endless[aria-pressed="true"]::before { content: "■ "; }
.endless-group { display: flex; align-items: center; gap: calc(var(--u) * 2); flex: 0 0 auto; }
.endless-cap { display: flex; align-items: center; gap: calc(var(--u) * 2); }
.endless-cap .label { font-size: 16px; color: var(--soft); }
.endless-cap .input { width: 4.5em; min-height: 44px; flex: none; }
.endless-unit { font-size: 16px; color: var(--soft); }
.btn-info { min-width: 44px; padding-inline: calc(var(--u) * 2); font-size: 16px; text-transform: none; }
.btn-info[aria-expanded="true"] { background: var(--text); color: var(--bg); }
.endless-hint { margin: 0; }
/* the buttons stay focusable when they cannot act (aria-disabled); the reason sits under them.
   Greyed, dashed and dimmed so WRITING… never reads as a second MAKE. */
.actionbar .btn[aria-disabled="true"] { cursor: not-allowed; background: var(--panel); color: var(--soft); border-color: var(--line); border-style: dashed; opacity: 0.65; box-shadow: none; transform: none; }
.actionbar .btn[aria-disabled="true"]:hover, .actionbar .btn[aria-disabled="true"]:active { background: var(--panel); color: var(--soft); transform: none; box-shadow: none; }
/* the band asks (engage.js; plan A; docs/RELEASE_0.2.3.md 2.5): the prompt lives in the ball. The
   compact card (ABC with three plain options, "still there?", the games) lies over the 150x100
   display at exactly its rect, its three cells above the round buttons 1 · 2 · 3; the list (spectrum,
   more options, options with details) sits in the panel slot directly under the buttons, over the
   ball's lower body, and runs on below it in place of the legend. Both hosts are hidden (no box at
   all) unless a prompt is actually showing. */
.pbdev-prompt-layer {
  /* above the making-of tape (.pbx-tape, z 2), which docks over the screen's corner: a prompt
     is the thing to answer now, the tape can wait under it */
  position: absolute; z-index: 3;
  left: calc(45px * var(--s)); top: calc(60px * var(--s));
  width: calc(150px * var(--s)); height: calc(100px * var(--s));
}
.pbdev-prompt-layer[hidden], .pbdev-panel-slot[hidden] { display: none; }
/* its top edge sits at ball y 208, just under the buttons (button 2 ends at y 205) */
.pbdev-panel-slot {
  position: relative; z-index: 2; min-width: 0;
  width: min(calc(100% - var(--pad) * 2), calc(180px * var(--s)));
  margin-top: calc(-46px * var(--s) - var(--u) * 2);
}
.pbdev[data-prompt="list"] .pbdev-legend { display: none; }
.pbdev[data-prompt="compact"] .pbdev-legend { visibility: hidden; }
.engage-card { display: grid; gap: calc(var(--u) * 2); min-width: 0; padding: calc(var(--u) * 2) calc(var(--u) * 3);
  border: var(--u) solid var(--ink); background: var(--panel); }
.engage-ask { margin: 0; font-size: 18px; color: var(--text); }
.engage-opts { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); min-width: 0; }
.engage-opt { flex: 1 1 0; min-width: 0; min-height: 44px; white-space: normal; text-align: center; display: flex;
  gap: calc(var(--u) * 2); align-items: center; justify-content: center; padding-inline: calc(var(--u) * 2); }
.engage-opt[data-default="true"] { border-style: dashed; }
.engage-opt[aria-pressed="true"] { background: var(--ok); color: var(--ok-on); }
.engage-key { font-size: 20px; }
.engage-label { font-size: 14px; }
.engage-spec[data-v="-2"], .engage-spec[data-v="-1"] { color: var(--error-fg); }
.engage-spec[data-v="1"], .engage-spec[data-v="2"] { color: var(--ok-fg); }
.engage-clock { width: 100%; height: calc(var(--u) * 2); accent-color: var(--primary); }
.engage-keys { margin: 0; }
.engage-card[data-mode="endless"] .engage-keys { display: none; }
.engage-card[data-beat="go"] .engage-gamebtn { background: var(--ok); color: var(--ok-on); }
.engage-card[data-half="true"], .engage-card[data-rung="1"] { border-color: var(--warn); }
.engage-card[data-rung="2"], .engage-card[data-rung="3"] { border-color: var(--warn); animation: engage-pulse 0.5s steps(2) infinite; }
@keyframes engage-pulse { 50% { border-color: var(--ink); } }
/* the round button that answers each option: a chip in the primary of the real buttons */
.engage-btnno {
  font-family: var(--display); font-size: 14px; line-height: 1; flex: none;
  background: var(--primary); color: var(--primary-on); padding: calc(var(--u) / 2) var(--u);
}
/* compact: the card is the display; cells sit in thirds inset 12 screen pixels a side, so each
   cell's centre lands over its round button (ball x 82 · 120 · 158) */
.engage-card[data-form="compact"] {
  display: flex; flex-direction: column; width: 100%; height: 100%;
  padding: calc(var(--u) * 2); gap: calc(var(--u) * 1.5); box-shadow: none;
}
.engage-card[data-form="compact"] > * { flex: none; }
.engage-card[data-form="compact"] .engage-ask {
  font-size: calc(var(--s) * 7px); line-height: 1.2; overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.engage-card[data-form="compact"] .engage-opts {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: calc(var(--u) * 2);
  margin-inline: calc(var(--s) * 12px - var(--u) * 3); flex: 1 1 auto; min-height: 0;
}
.engage-card[data-form="compact"] .engage-keys { display: none; font-size: 12px; }
.engage-cell {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--u); min-width: 0; min-height: 44px; padding: var(--u) var(--u) calc(var(--u) * 3); text-align: center;
}
.engage-card[data-form="compact"] .btn.engage-cell { box-shadow: none; }
div.engage-cell { border: var(--u) dashed var(--line); color: var(--soft); }
.engage-cell-empty { border-color: transparent; }
.engage-cell .engage-key { font-size: calc(var(--s) * 10px); line-height: 1; }
.engage-cell .engage-label { font-size: calc(var(--s) * 6px); line-height: 1.15; overflow-wrap: anywhere; }
/* the number hangs off the cell's foot onto the bezel, pointing at its round button */
.engage-cell .engage-btnno { position: absolute; left: 50%; bottom: 0; transform: translate(-50%, 50%); }
.engage-pips { display: flex; gap: var(--u); }
.engage-pip { width: calc(var(--s) * 5px); height: calc(var(--s) * 5px); background: var(--line); }
.engage-card[data-beat="1"] .engage-pip:nth-child(-n+1), .engage-card[data-beat="2"] .engage-pip:nth-child(-n+2),
.engage-card[data-beat="3"] .engage-pip:nth-child(-n+3), .engage-card[data-beat="4"] .engage-pip { background: var(--primary); }
.engage-card[data-beat="go"] .engage-pip { background: var(--ok); }
.engage-card[data-holding="true"] .engage-gamebtn { outline: var(--u) solid var(--primary); }
.engage-taps { font-family: var(--display); font-size: calc(var(--s) * 10px); line-height: 1; color: var(--text); }
/* list: a column of big rows (key chip · label · details), the clock under the ask */
.engage-card[data-form="list"] { box-shadow: var(--u) var(--u) 0 0 var(--ink); }
.engage-card[data-form="list"] .engage-opts { display: grid; grid-template-columns: minmax(0, 1fr); }
.engage-row { justify-content: flex-start; text-align: left; min-height: 48px; padding: calc(var(--u) * 2) calc(var(--u) * 3); }
.engage-row .engage-btnno { min-width: calc(var(--u) * 9); text-align: center; }
.engage-text { display: grid; gap: var(--u); min-width: 0; }
.engage-detail { font-family: var(--body); font-size: 14px; line-height: 1.3; text-transform: none; color: var(--soft); }
/* ME@PROXY: read-only, the pick pressed, a tag on the ask; a tap anywhere skips */
.engage-card[data-proxy="true"] { border-style: dashed; cursor: pointer; }
.engage-proxytag {
  font-family: var(--display); background: var(--tertiary); color: var(--tertiary-on);
  padding: 0 var(--u); margin-right: calc(var(--u) * 2);
}
.engage-card[data-proxy="true"] .engage-keys.engage-verdict { display: block; font-size: 12px; color: var(--text); }
@media (min-width: 800px) and (min-height: 700px) {
  .engage-card[data-form="compact"] .engage-keys { display: block; }
}
@media (max-width: 599px) {
  .engage-keys { display: none; }
  .engage-spec { font-size: 14px; padding-inline: var(--u); }
  .engage-row { padding-inline: calc(var(--u) * 2); }
}
/* button cues (engage.js PB.engage.cues; engagement.py Prompt.cues; the hal): data-cue = off | on |
   pulse | chase and data-cue-role = a | b | c | live | go | warn on each round button (.pbdev-btn-N)
   and on the option it answers. on = a solid ring, pulse = a 2 Hz breathe, chase = a turning ring;
   a / b / c are the neutral highlight, go = ok, warn = warn, live = primary. Reduced motion renders
   pulse and chase exactly as on. */
.pbdev-btn[data-cue="on"]::after, .pbdev-btn[data-cue="pulse"]::after, .pbdev-btn[data-cue="chase"]::after {
  content: ""; position: absolute; inset: calc(var(--u) * -1); pointer-events: none;
  border: var(--u) solid var(--tertiary);
}
.pbdev-btn[data-cue="pulse"]::after { animation: engage-cue-breathe 0.5s ease-in-out infinite; }
.pbdev-btn[data-cue="chase"]::after { border-style: dashed; animation: engage-cue-turn 1s linear infinite; }
.pbdev-btn[data-cue-role="go"]::after { border-color: var(--ok); }
.pbdev-btn[data-cue-role="warn"]::after { border-color: var(--warn); }
.pbdev-btn[data-cue-role="live"]::after { border-color: var(--primary); }
.engage-opt[data-cue="on"], .engage-opt[data-cue="pulse"], .engage-opt[data-cue="chase"] {
  outline: var(--u) solid var(--tertiary); outline-offset: var(--u);
}
.engage-opt[data-cue="pulse"] { animation: engage-cue-fade 0.5s ease-in-out infinite; }
.engage-opt[data-cue="chase"] { outline-style: dashed; animation: engage-cue-fade 1s steps(2) infinite; }
.engage-opt[data-cue-role="go"] { outline-color: var(--ok); }
.engage-opt[data-cue-role="warn"] { outline-color: var(--warn); }
.engage-opt[data-cue-role="live"] { outline-color: var(--primary); }
@keyframes engage-cue-breathe { 50% { opacity: 0.35; } }
@keyframes engage-cue-turn { to { transform: rotate(360deg); } }
@keyframes engage-cue-fade { 50% { outline-color: transparent; } }
@media (prefers-reduced-motion: reduce) { .engage-card { animation: none !important; } }
@media (prefers-reduced-motion: reduce) {
  .pbdev-btn[data-cue]::after, .engage-opt[data-cue] { animation: none !important; transition: none !important; }
  .pbdev-btn[data-cue="chase"]::after { border-style: solid; transform: none; }
  .engage-opt[data-cue="chase"] { outline-style: solid; }
}
/* the notes under the bar: not pinned, so their text can change freely */
.abnotes { display: grid; gap: calc(var(--u) * 3); min-width: 0; margin-bottom: calc(var(--u) * 3); }
.ab-why { margin: 0; color: var(--warn); }
.film-hint { margin: 0; }

/* ── collapsible modules (modules.js; docs/BOLLAWAX_0.2.0_PLAN.md D.2) ────────────────────────
   Every module heading is the .h2 block on a 1u rule in --line with the summary chip as a tag;
   the disclosure is a native button inside the real heading. No expand animation: this screen
   cuts, it never slides, so reduced motion has nothing to turn off. */
.mod { display: grid; gap: calc(var(--u) * 4); min-width: 0; align-content: start; }
.mod-h { margin: 0; border-bottom: var(--u) solid var(--line); padding-bottom: calc(var(--u) * 2); min-width: 0; }
.mod-toggle {
  display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 2) calc(var(--u) * 3);
  width: 100%; min-height: 44px; margin: 0; padding: 0; text-align: left;
  background: none; border: 0; color: var(--text); font: inherit; cursor: pointer; min-width: 0;
}
.mod-title {
  font-family: var(--display); font-weight: 400; font-size: 20px; line-height: 1;
  color: var(--bg); background: var(--soft); display: inline-block; padding: var(--u) calc(var(--u) * 2);
}
.mod-toggle:hover .mod-title { background: var(--text); }
.mod-chip {
  font-family: var(--display); font-size: 20px; line-height: 1; white-space: normal; overflow-wrap: anywhere;
  display: inline-block; padding: var(--u) calc(var(--u) * 2); background: var(--panel); color: var(--text);
}
.mod-new {
  font-family: var(--display); font-size: 20px; line-height: 1;
  display: inline-block; padding: var(--u) calc(var(--u) * 2); background: var(--live); color: var(--live-on);
}
.mod-caret { margin-left: auto; font-family: var(--display); font-size: 20px; line-height: 1; color: var(--soft); padding: 0 var(--u); }
.mod-caret::before { content: "\2013"; }
.mod-toggle[aria-expanded="false"] .mod-caret::before { content: "+"; }
.mod-toggle:hover .mod-caret { color: var(--primary-fg); }
.mod-tools { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 3); min-width: 0; }
.mod-tools:empty { display: none; }
.mod.is-closed > .mod-tools, .mod.is-closed > .mod-body { display: none; }
/* #codex, #riffbook… are the bodies: the browser's own jump lands a heading's height higher */
.mod > .mod-body { scroll-margin-top: calc(var(--u) * 21); }
/* a body with nothing to show yet (the codex before minting, the riff book before the first song)
   keeps its whole module off the page */
.mod:has(> .mod-body[hidden]) { display: none; }
.mods-all { display: flex; align-items: center; justify-content: flex-end; gap: calc(var(--u) * 2); color: var(--soft); font-family: var(--display); font-size: 20px; line-height: 1; }
.linkbtn { background: none; border: 0; padding: calc(var(--u) * 2) 0; min-height: 44px; color: var(--soft); font: inherit; cursor: pointer; }
.linkbtn:hover { color: var(--primary-fg); }

.songs { display: grid; gap: calc(var(--u) * 4); justify-items: start; }
.songlist { width: 100%; display: grid; border-top: var(--u) solid var(--line); }
/* a song row: on phones [play][#][title / meta] with SHARE and the notes on their own lines;
   from 600px a table (the header row below) with # · TITLE · LENGTH · SHARE as columns and the
   16 notes under the title (they are too wide for a column beside the ball) */
.song {
  display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: calc(var(--u) * 3) calc(var(--u) * 3);
  align-items: center; padding: calc(var(--u) * 4) 0;
  border-bottom: var(--u) solid var(--line);
}
.song.is-current { background: var(--panel); box-shadow: calc(var(--u) * -4) 0 0 0 var(--panel), calc(var(--u) * 4) 0 0 0 var(--panel); }
.song-main { display: grid; gap: var(--u); min-width: 0; }
.song-title { font-size: 18px; line-height: 1.35; color: var(--text); overflow-wrap: anywhere; }
.song-title .ln, .song-meta .ln { color: var(--soft); margin-right: 1ch; }
.song-no { font-size: 18px; line-height: 1.35; color: var(--soft); min-width: 3ch; font-variant-numeric: tabular-nums; align-self: start; padding-top: 0.6em; }
.song-meta { font-size: 14px; color: var(--soft); }
.song-len { display: none; font-size: 14px; color: var(--soft); font-variant-numeric: tabular-nums; }
.song-headrow { display: none; }
.btn-play { width: 48px; min-height: 48px; padding: 0; }
.song.is-current .btn-play { background: var(--primary); color: var(--primary-on); border-color: var(--ink); }
.btn-share { grid-column: 1 / -1; justify-self: stretch; }
.btn-share.is-on { background: var(--live); color: var(--live-on); border-color: var(--ink); }
.btn-share.is-on:hover { background: var(--text); color: var(--text-on); }
.tag-onair { grid-column: 1 / -1; justify-self: start; background: var(--live); color: var(--live-on); }
.empty { color: var(--soft); max-width: 46ch; }

.rename { display: grid; gap: calc(var(--u) * 3); border: var(--u) solid var(--primary); padding: calc(var(--u) * 4); }
.rename-row { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 3); }
.at { font-family: var(--display); font-size: 20px; line-height: 1; }
.input {
  font-family: var(--body); font-size: 18px; line-height: 1.2;
  background: var(--well); color: var(--text);
  border: var(--u) solid var(--text); border-radius: 0;
  padding: calc(var(--u) * 2) calc(var(--u) * 3); min-height: 48px; min-width: 0; flex: 1 1 14ch;
}

/* ── FM page ──────────────────────────────────────────────────────────────────────────── */

.fmpage { display: flex; flex-direction: column; gap: calc(var(--u) * 6); min-width: 0; }
.fmbody { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--u) * 6); min-width: 0; }
.fmhead { display: grid; gap: calc(var(--u) * 3); justify-items: start; }
.nowplaying, .upnext { display: grid; gap: calc(var(--u) * 3); justify-items: start; }
.np-title { font-family: var(--display); font-size: 30px; line-height: 1.15; overflow-wrap: anywhere; }
.np-from { font-size: 16px; color: var(--soft); }
.nextlist { width: 100%; display: grid; border-top: var(--u) solid var(--line); counter-reset: nx; }
.next {
  display: grid; grid-template-columns: 3ch 1fr; column-gap: calc(var(--u) * 3);
  padding: calc(var(--u) * 3) 0; border-bottom: var(--u) solid var(--line); counter-increment: nx 10;
}
.next::before { content: counter(nx); color: var(--soft); grid-row: span 2; }
.next-title { font-size: 18px; line-height: 1.35; overflow-wrap: anywhere; }
.next-from { font-size: 14px; color: var(--soft); }
.btn.is-on { background: var(--live); color: var(--live-on); border-color: var(--ink); }
.fm-cta { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 3); border: var(--u) solid var(--line); padding: calc(var(--u) * 3) calc(var(--u) * 4); }

/* ── not found ────────────────────────────────────────────────────────────────────────── */

.notfound { display: grid; gap: calc(var(--u) * 6); justify-items: start; padding: calc(var(--u) * 10) 0; }

/* ── footer & toast ───────────────────────────────────────────────────────────────────── */

.foot {
  width: 100%; max-width: 1320px; margin: calc(var(--u) * 16) auto 0;
  border-top: var(--u) solid var(--line); padding-top: calc(var(--u) * 6);
  display: grid; gap: calc(var(--u) * 4); font-size: 16px; color: var(--soft);
}
.foot p { max-width: 64ch; }
.foot-links { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 6); font-family: var(--display); font-size: 20px; line-height: 1; }
.foot-links a { color: var(--soft); text-decoration: none; padding: calc(var(--u) * 3) 0; }
.foot-links a:hover { color: var(--primary-fg); }
.foot-ver { color: var(--soft); opacity: 0.6; padding: calc(var(--u) * 3) 0; margin-left: auto; }

.notice {
  position: fixed; left: 50%; bottom: calc(var(--u) * 6); z-index: 30;
  transform: translateX(-50%);
  width: max-content; max-width: calc(100vw - var(--u) * 12);
  background: var(--text); color: var(--text-on);
  border: var(--u) solid var(--ink); box-shadow: var(--u) var(--u) 0 0 var(--ink);
  padding: calc(var(--u) * 3) calc(var(--u) * 4);
  font-size: 16px; line-height: 1.45;
  display: none;
}
.notice.is-on { display: block; }
.notice-good { background: var(--ok); color: var(--ok-on); }
.notice-bad { background: var(--error); color: var(--error-on); }

.is-signing-in [data-action="signin"] { cursor: wait; }

/* ── bigger screens ───────────────────────────────────────────────────────────────────── */

@media (min-width: 560px) {
  :root { --pad: calc(var(--u) * 8); }
  .wide-only { display: inline; }
  .nav { gap: calc(var(--u) * 2); }
  .navlink { padding: calc(var(--u) * 2); }
  .wordmark { gap: calc(var(--u) * 3); }
  .pbdev-legend { grid-template-columns: repeat(3, auto); justify-content: center; }
  .pbdev-legend li { grid-template-columns: auto auto; align-items: start; }
  .pbdev-key { grid-row: span 2; margin-top: 2px; }
  /* the songs table: play · # · title · length · share */
  /* fixed widths, not ch: the header row's display face would size its columns differently */
  .song { grid-template-columns: auto calc(var(--u) * 8) minmax(0, 1fr) calc(var(--u) * 14) calc(var(--u) * 42); column-gap: calc(var(--u) * 4); }
  .song-no { padding-top: 0; align-self: center; }
  .song-len { display: block; }
  .song-meta-len { display: none; }
  .btn-share, .tag-onair { grid-column: auto; justify-self: end; }
  .song-len { justify-self: end; }
  .song-headrow .sh-len { justify-self: end; }
  .song-headrow {
    display: grid; grid-template-columns: auto calc(var(--u) * 8) minmax(0, 1fr) calc(var(--u) * 14) calc(var(--u) * 42); column-gap: calc(var(--u) * 4);
    padding: calc(var(--u) * 2) 0; border-bottom: var(--u) solid var(--line);
    font-family: var(--display); font-size: 20px; line-height: 1; color: var(--soft);
  }
  .song-headrow .sh-play { width: 48px; }
  .song-headrow .sh-air { justify-self: end; }
  .frame { margin: calc(var(--u) * 4); min-height: calc(100vh - var(--u) * 8); padding-bottom: calc(var(--u) * 10); }
  .display { font-size: 60px; }
  .actionbar { margin-inline: 0; padding-inline: 0; }
  .actionbar-row .btn-big { white-space: nowrap; padding-inline: calc(var(--u) * 6); }
  .endless-cap .input { width: 5.5em; }
}

/* wide screens: one confident row, [MAKE A NEW SONG][ME@PROXY] [ENDLESS] [stop after (i)]; the
   stop-after group wraps under them first when the row runs out of room. Below 800px the phone
   grid stays, so ME@PROXY can never wrap away from MAKE. */
@media (min-width: 800px) {
  .makerow { display: flex; flex-wrap: wrap; }
  .makerow .btn-make, .makerow .btn-skipfilm { order: -1; }   /* SKIP stands where MAKE stood, left of ME@PROXY */
  .makerow .btn-make, .makerow .btn-skipfilm, .makerow .btn-endless { flex: 0 0 auto; font-size: 32px; min-height: 80px; }
  .makerow .btn-proxy { flex: 0 0 auto; font-size: 20px; min-height: 80px; margin-left: calc(var(--u) * -1); margin-right: calc(var(--u) * 3); }
}

@media (min-width: 800px) and (min-height: 700px) {
  :root { --s: 3; }
}

@media (min-width: 1240px) {
  .frame { margin: calc(var(--u) * 6); min-height: calc(100vh - var(--u) * 12); }
  .hero { grid-template-columns: minmax(0, 1fr) auto; gap: calc(var(--u) * 8); }
  /* beside a column of text the ball's ray tips may poke into the gutter */
  .device-mount { margin-inline: 0; }
  .pbdev-clip { overflow: visible; }
  .hero-device, .devbody > .device-mount, .fmbody > .device-mount { width: calc(224px * var(--s)); }
  /* action bar, notes and head run the full width; below them the ball keeps the left column
     (not pinned: it scrolls with the page) */
  .devbody {
    grid-template-columns: auto minmax(0, 1fr); column-gap: calc(var(--u) * 10);
    grid-template-areas: "dev note" "dev mods" "dev .";
    grid-template-rows: auto auto 1fr; align-items: start;
  }
  .devbody > .device-mount { grid-area: dev; }
  .devbody > .visitor-note { grid-area: note; }
  .devbody > .mods { grid-area: mods; }
  .fmbody {
    grid-template-columns: auto minmax(0, 1fr); column-gap: calc(var(--u) * 10);
    grid-template-areas: "dev lede" "dev now" "dev next" "dev cta" "dev apps" "dev .";
    grid-template-rows: auto auto auto auto auto 1fr; align-items: start;
  }
  .fmbody > .device-mount { grid-area: dev; }
  .fmbody > .lede { grid-area: lede; }
  .fmbody > .nowplaying { grid-area: now; }
  .fmbody > .upnext { grid-area: next; }
  .fmbody > .fm-cta { grid-area: cta; }
  .fmbody > .fm-apps { grid-area: apps; }
}

@media (prefers-reduced-motion: reduce) {
  .lamp.is-on, .statusline::after { animation: none; }
  .btn:active, .btn.is-down { transform: none; }
}

/* ── social: public pages, pillnames, Music Notes, avatars (social.js) ───────────────── */

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.social-namerow { display: flex; align-items: center; gap: calc(var(--u) * 3); min-width: 0; }
.social-avatar { flex: none; line-height: 0; }
.avatar {
  display: block; width: 48px; height: 48px; image-rendering: pixelated;
  background: var(--ink); border: var(--u) solid var(--text); box-shadow: var(--u) var(--u) 0 0 var(--ink);
}
.social-bar { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 3); max-width: 100%; min-width: 0; }
.social-avatar-tools { display: inline-flex; align-items: center; }
.tag-public { background: var(--ok); color: var(--ok-on); text-decoration: none; white-space: normal; overflow-wrap: anywhere; }
.tag-public:hover { background: var(--text); color: var(--text-on); }
.tag-private { background: var(--soft); color: var(--soft-on); }
.btn-gopublic .tag { padding: 0 var(--u); }
.btn-gopublic:hover .tag { background: var(--bg); color: var(--text); }
.avatar-progress { font-size: 14px; color: var(--soft); letter-spacing: 0.02em; }

/* the 16 Music Notes: the creator's big, the community's small line beneath */
.rating { grid-column: 1 / -1; display: grid; gap: var(--u); justify-items: start; min-width: 0; }
.rating-creator { display: flex; flex-wrap: wrap; align-items: center; gap: var(--u) calc(var(--u) * 3); }
.notes {
  font-family: var(--display); line-height: 1; display: inline-flex; white-space: nowrap;
  user-select: none; -webkit-user-select: none; touch-action: manipulation;
}
.notes-big { font-size: 30px; }
.notes-small { font-size: 20px; }
.note { color: var(--line); }
.note.is-on { color: var(--primary-fg); }
.note.is-preview { color: var(--secondary-fg); }
.notes.is-live { cursor: pointer; }
.notes.is-live:focus-visible { outline: var(--u) solid var(--secondary); outline-offset: var(--u); }
.notes.is-saving { cursor: wait; }
.notes.is-saving .note.is-on { color: var(--soft); }
.rating-score { font-family: var(--display); font-size: 20px; line-height: 1; color: var(--text); }
.rating-community { font-size: 14px; color: var(--soft); }
.rating-mine { display: flex; flex-wrap: wrap; align-items: center; gap: var(--u) calc(var(--u) * 2); }
.rating-label, .rating-mine-score { font-family: var(--display); font-size: 20px; line-height: 1; color: var(--soft); }

.np-social { display: flex; flex-wrap: wrap; align-items: flex-start; gap: calc(var(--u) * 4); }
.np-social .rating { grid-column: auto; }

/* GO PUBLIC dialog */
.pill-dialog {
  width: min(560px, calc(100vw - var(--u) * 8)); max-height: calc(100vh - var(--u) * 8);
  padding: 0; color: var(--text); background: var(--bg); font-family: var(--body);
  border: var(--u) solid var(--primary); box-shadow: calc(var(--u) * 2) calc(var(--u) * 2) 0 0 var(--ink);
}
.pill-dialog::backdrop { background: rgba(var(--ink-rgb), 0.85); }
.pill-form { display: grid; gap: calc(var(--u) * 3); padding: calc(var(--u) * 5); }
.pill-title { font-family: var(--display); font-weight: 400; font-size: 30px; line-height: 1; }
.pill-copy { font-size: 16px; line-height: 1.5; }
.pill-copy b { color: var(--primary-fg); font-weight: 400; }
.pill-preview {
  font-family: var(--display); font-size: 20px; line-height: 1.2; color: var(--secondary-fg);
  background: var(--well); padding: calc(var(--u) * 2) calc(var(--u) * 3); overflow-wrap: anywhere;
}
.pill-row { display: grid; gap: calc(var(--u) * 2); }
.pill-status { font-size: 16px; min-height: 1.5em; color: var(--soft); }
.pill-status.is-good { color: var(--ok-fg); }
.pill-status.is-bad { color: var(--error-fg); }
.pill-agree { display: flex; align-items: center; gap: calc(var(--u) * 2); font-size: 16px; cursor: pointer; }
.pill-agree input { width: 20px; height: 20px; accent-color: var(--primary); flex: none; }

@media (min-width: 560px) {
  .rating { grid-column: 3 / -1; }
}

/* ── player mode: MORPHUS (the band's songs) / CORPUS (the corpus's recordings) ─────────── */
.songs-head { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 3); width: 100%; }
.btn-mode { gap: calc(var(--u) * 2); padding-left: calc(var(--u) * 2); }
.btn-mode .pxicon { display: block; width: 28px; height: 28px; image-rendering: pixelated; flex: 0 0 auto; }
/* the pixel icons' layers are palette tokens (corpus-player.js pixelSvg) */
.pxicon .px-ink { fill: var(--ink); }
.pxicon .px-line { fill: var(--line); }
.pxicon .px-soft { fill: var(--soft); }
.pxicon .px-primary { fill: var(--primary); }
.pxicon .px-secondary { fill: var(--secondary); }
.pxicon .px-tertiary { fill: var(--tertiary); }
.pxicon .px-ok { fill: var(--ok); }
.btn-mode[aria-pressed="true"] { border-color: var(--primary); }
.btn-mode .mode-sub { font-size: 14px; color: var(--soft); }
.btn-mode:hover .mode-sub { color: inherit; }
/* CORPUS is for subscribers (docs/ACCESS_TIERS.md): a padlock on the MODE button, SUBSCRIBE beside it */
.btn-mode .pxicon[data-icon="lock"] { width: 16px; height: 16px; }
.btn-mode.is-locked .mode-sub { text-decoration: line-through; }
.btn-subscribe { white-space: nowrap; }
/* The Basic Square mark (docs/RELEASE_0.2.3.md 2.2-2.3): by the MODE button where the padlock shows
   for free, and beside the edition label of a square_edition device. Existing tokens only. */
.square-mark { display: inline-flex; align-items: center; flex: 0 0 auto; line-height: 0; }
.square-mark .pxicon[data-icon="square"] { display: block; width: 16px; height: 16px; image-rendering: pixelated; }
.btn-mode .pxicon[data-icon="square"] { width: 16px; height: 16px; }
.tag-square { display: inline-flex; align-items: center; gap: var(--u); }
.track .song-title .ln { display: inline-block; min-width: 3ch; }
.songlist.is-corpus .song { grid-template-columns: auto 1fr; }

/* triple-tap combos in the button legend, and the corpus POOL ALL switch */
.pbdev-x3 { grid-column: 2 / -1; color: var(--secondary-fg); }
@media (min-width: 560px) { .pbdev-legend li:has(.pbdev-x3) .pbdev-key { grid-row: span 3; } .pbdev-x3 { grid-column: 2; } }
.devcorpus .btn-pool { min-height: 40px; font-size: 16px; }
.devcorpus .btn-pool[aria-pressed="true"] { border-color: var(--ok); color: var(--ok-fg); }

/* ── the making-of videotape and its export dialog (export.js) ─────────────────────────── */
/* docked over the screen's FM-mast corner, half on the bezel: always on screen, even on
   phones where the ball's rim is clipped; the glow is a hard-edged halo that steps */
.pbx-tape {
  position: absolute; z-index: 2;
  left: calc(152px * var(--s)); top: calc(116px * var(--s));
  width: calc(44px * var(--s)); height: calc(30px * var(--s));
  padding: 0; border: 0; background: transparent; cursor: pointer;
  box-shadow: 0 0 0 calc(var(--s) * 1px) var(--ink), 0 0 0 calc(var(--s) * 3px) var(--primary);
  animation: pbx-glow 0.8s steps(1, end) infinite;
  -webkit-tap-highlight-color: transparent;
}
.pbx-tape-art { display: block; width: 100%; height: 100%; image-rendering: pixelated; }
.pbx-tape:hover, .pbx-tape:focus-visible { box-shadow: 0 0 0 calc(var(--s) * 1px) var(--ink), 0 0 0 calc(var(--s) * 3px) var(--text); animation: none; }
.pbx-tape:focus-visible { outline: var(--u) solid var(--secondary); outline-offset: calc(var(--s) * 4px); }
.pbx-tape:active { transform: translate(calc(var(--s) * 1px), calc(var(--s) * 1px)); }
.pbx-tape.is-still { animation: none; }
@keyframes pbx-glow {
  50% { box-shadow: 0 0 0 calc(var(--s) * 1px) var(--ink), 0 0 0 calc(var(--s) * 3px) var(--text), 0 0 0 calc(var(--s) * 5px) var(--primary); }
}

.pbx-dialog {
  width: min(560px, calc(100vw - var(--u) * 8)); padding: calc(var(--u) * 6);
  color: var(--text); background: var(--bg);
  border: var(--u) solid var(--text); box-shadow: calc(var(--u) * 2) calc(var(--u) * 2) 0 0 var(--ink);
  font-family: var(--body); font-size: 16px; line-height: 1.4;
}
.pbx-dialog::backdrop { background: rgba(var(--ink-rgb), 0.78); }
.pbx-h { font-family: var(--display); font-size: 30px; line-height: 1; margin: 0 0 calc(var(--u) * 3); color: var(--primary-fg); }
.pbx-song { margin: 0 0 calc(var(--u) * 4); color: var(--soft); }
.pbx-scales { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); border: 0; padding: 0; margin: 0 0 calc(var(--u) * 4); }
.pbx-scales legend { font-size: 16px; color: var(--soft); margin-bottom: calc(var(--u) * 2); }
.pbx-scale {
  display: inline-flex; align-items: center; gap: calc(var(--u) * 2); cursor: pointer;
  padding: calc(var(--u) * 2) calc(var(--u) * 3); border: var(--u) solid var(--line);
  font-family: var(--display); font-size: 20px; line-height: 1;
}
.pbx-scale:has(input:checked) { border-color: var(--primary); color: var(--primary-fg); }
.pbx-scale input { accent-color: var(--primary); margin: 0; }
.pbx-dim { font-family: var(--body); font-size: 14px; color: var(--soft); }
.pbx-choices { display: grid; gap: calc(var(--u) * 3); }
.pbx-go { flex-direction: column; align-items: flex-start; white-space: normal; text-align: left; }
.pbx-est { font-family: var(--body); font-size: 14px; text-transform: none; }
.pbx-note { margin: calc(var(--u) * 3) 0 0; color: var(--secondary-fg); }
.pbx-progress { margin-top: calc(var(--u) * 4); }
.pbx-bar {
  -webkit-appearance: none; appearance: none; display: block; width: 100%; height: calc(var(--u) * 5);
  border: var(--u) solid var(--text); background: var(--well); color: var(--primary);
}
.pbx-bar::-webkit-progress-bar { background: var(--well); }
.pbx-bar::-webkit-progress-value { background: var(--primary); }
.pbx-bar::-moz-progress-bar { background: var(--primary); }
.pbx-bartext { margin: calc(var(--u) * 2) 0 0; font-family: var(--display); font-size: 20px; line-height: 1; }
.pbx-result { margin: calc(var(--u) * 2) 0 0; color: var(--ok-fg); min-height: 1em; }
.pbx-actions { display: flex; justify-content: flex-end; gap: calc(var(--u) * 3); margin-top: calc(var(--u) * 5); }
@media (prefers-reduced-motion: reduce) {
  .pbx-tape { animation: none; }
  .pbx-tape:active { transform: none; }
}

/* developer specs */
/*
 * /spec: long-form reading. The PBOLL face is for headings and labels only; body text is the
 * system UI sans at 17px / 1.6 with a ~72ch measure. Tables and code may use the full column
 * and scroll sideways inside their own box, never the page.
 */

.specpage {
  --read: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --zebra: var(--bg-hi);
  display: grid; gap: calc(var(--u) * 6); min-width: 0;
}
.spec-main { display: grid; gap: calc(var(--u) * 12); min-width: 0; }

/* contents: a collapsible block on phones, a sticky sidebar on wide screens */
.spec-side { min-width: 0; }
.spec-toc { border: var(--u) solid var(--line); background: var(--panel); }
.spec-toc > summary {
  display: flex; align-items: center; justify-content: space-between; gap: calc(var(--u) * 3);
  min-height: 48px; padding: calc(var(--u) * 3) calc(var(--u) * 4);
  font-family: var(--display); font-size: 20px; line-height: 1; cursor: pointer; list-style: none;
}
.spec-toc > summary::-webkit-details-marker { display: none; }
.spec-toc > summary::after { content: "+"; font-family: var(--display); }
.spec-toc[open] > summary::after { content: "\2013"; }
.spec-toc ol {
  display: grid; gap: var(--u); padding: 0 calc(var(--u) * 4) calc(var(--u) * 4);
  font-family: var(--read); font-size: 16px; line-height: 1.35;
}
.spec-toc a {
  display: block; padding: var(--u) 0 var(--u) calc(var(--u) * 3);
  border-left: var(--u) solid transparent; color: var(--soft); text-decoration: none;
}
.spec-toc a:hover { color: var(--primary-fg); }
.spec-toc a[aria-current] { color: var(--text); border-left-color: var(--primary); }

/* the article */
.spec-article {
  font-family: var(--read); font-size: 17px; line-height: 1.6; color: var(--text);
  min-width: 0; overflow-wrap: break-word;
}
.spec-article > * + * { margin-top: calc(var(--u) * 4); }
.spec-article p, .spec-article ul, .spec-article ol, .spec-article blockquote,
.spec-article h1, .spec-article h2, .spec-article h3, .spec-article h4 { max-width: 72ch; }
.spec-article h1, .spec-article h2, .spec-article h3, .spec-article h4 {
  font-family: var(--display); font-weight: 400; letter-spacing: 0; color: var(--text);
  scroll-margin-top: calc(var(--u) * 6); overflow-wrap: break-word;
}
/* scale with the screen so long words ("Specification") wrap between words, not inside them */
.spec-article h1 { font-size: clamp(26px, 8.4vw, 40px); line-height: 1.1; }
.spec-article h2 {
  font-size: clamp(22px, 6.4vw, 30px); line-height: 1.15; margin-top: calc(var(--u) * 12);
  padding-top: calc(var(--u) * 6); border-top: var(--u) solid var(--line);
}
.spec-article h3 { font-size: 20px; line-height: 1.2; margin-top: calc(var(--u) * 8); color: var(--primary-fg); }
.spec-article h4 { font-size: 20px; line-height: 1.2; margin-top: calc(var(--u) * 6); color: var(--soft); }
.spec-article h2 + *, .spec-article h3 + *, .spec-article h4 + * { margin-top: calc(var(--u) * 3); }
.h-anchor {
  margin-left: 0.4em; color: var(--soft); text-decoration: none; opacity: 0;
  font-family: var(--display);
}
.spec-article :is(h2, h3, h4):hover .h-anchor, .h-anchor:focus-visible { opacity: 1; }
.h-anchor:hover { color: var(--primary-fg); }
@media (hover: none) { .h-anchor { opacity: 0.6; } }

.spec-pill { margin: 0 0 calc(var(--u) * 4); }
.pill-draft {
  display: inline-block; padding: var(--u) calc(var(--u) * 2);
  font-family: var(--display); font-size: 20px; line-height: 1;
  background: var(--tertiary); color: var(--tertiary-on);
}
.spec-article .spec-version { font-family: var(--body); font-size: 16px; color: var(--soft); margin-top: calc(var(--u) * 3); }

.spec-article a { color: var(--secondary-fg); }
.spec-article a:hover { color: var(--primary-fg); }
.spec-article strong { color: var(--strong); }
.spec-article ul { list-style: square; padding-left: 1.4em; }
.spec-article ol { list-style: decimal; padding-left: 1.6em; }
.spec-article li + li { margin-top: calc(var(--u) * 2); }
.spec-article li > ul, .spec-article li > ol { margin-top: calc(var(--u) * 2); }
.spec-article li::marker { color: var(--soft); }
.spec-article hr { border: 0; border-top: var(--u) solid var(--line); margin: calc(var(--u) * 10) 0; max-width: 72ch; }

.spec-article code {
  font-family: var(--body); font-size: 0.9em; background: var(--panel);
  padding: 0 0.3em; overflow-wrap: anywhere;
}
.spec-article pre.code {
  max-width: 100%; overflow-x: auto; margin-left: 0; margin-right: 0; margin-bottom: 0;
  background: var(--well); border: var(--u) solid var(--line);
  padding: calc(var(--u) * 4); font-family: var(--body); font-size: 16px; line-height: 1.5;
}
.spec-article pre.code[data-lang]::before {
  content: attr(data-lang); display: block; margin-bottom: calc(var(--u) * 2);
  font-size: 14px; color: var(--soft); text-transform: uppercase;
}
.spec-article pre.code code { background: none; padding: 0; font-size: inherit; white-space: pre; overflow-wrap: normal; }

.spec-article .table-wrap { max-width: 100%; overflow-x: auto; border: var(--u) solid var(--line); }
.spec-article table { border-collapse: collapse; width: 100%; font-size: 16px; line-height: 1.45; }
.spec-article th, .spec-article td { padding: calc(var(--u) * 2) calc(var(--u) * 3); text-align: left; vertical-align: top; }
/* identifiers in a cell keep their shape; a table that gets too wide scrolls in its box instead */
.spec-article td code, .spec-article th code { overflow-wrap: normal; }
.spec-article thead th { background: var(--panel); border-bottom: var(--u) solid var(--line); font-weight: 700; }
.spec-article tbody tr:nth-child(even) { background: var(--zebra); }
.spec-article .al-left { text-align: left; }
.spec-article .al-center { text-align: center; }
.spec-article .al-right { text-align: right; font-variant-numeric: tabular-nums; }

.spec-article blockquote {
  margin-left: 0; margin-right: 0; margin-bottom: 0;
  border-left: var(--u) solid var(--line); padding-left: calc(var(--u) * 4); color: var(--soft);
}
.spec-article blockquote > * + * { margin-top: calc(var(--u) * 3); }
.spec-article .callout {
  border: var(--u) solid var(--secondary); background: var(--panel); color: var(--text);
  padding: calc(var(--u) * 4);
}
.spec-article .callout-tip { border-color: var(--ok); }
.spec-article .callout-important, .spec-article .callout-draft { border-color: var(--primary); }
.spec-article .callout-warning, .spec-article .callout-caution { border-color: var(--error); }

/* the coming-soon page */
.specpage.is-soon .spec-article { padding: calc(var(--u) * 6) 0 0; }

/* download, previous / next */
.spec-pager { display: grid; gap: calc(var(--u) * 4); border-top: var(--u) solid var(--line); padding-top: calc(var(--u) * 6); }
.spec-download { justify-self: start; }
.spec-prevnext { display: grid; gap: calc(var(--u) * 3); }
.spec-pn {
  display: grid; gap: calc(var(--u) * 2); padding: calc(var(--u) * 3) calc(var(--u) * 4);
  border: var(--u) solid var(--line); color: var(--text); text-decoration: none; min-width: 0;
}
.spec-pn:hover { border-color: var(--primary); color: var(--primary-fg); }
.pn-dir { font-family: var(--display); font-size: 20px; line-height: 1; color: var(--soft); }
.pn-title { font-family: var(--read); font-size: 17px; line-height: 1.35; overflow-wrap: anywhere; }
.spec-pn.is-next { text-align: right; }

/* the contact box */
.contact {
  display: grid; gap: calc(var(--u) * 4); max-width: 72ch; min-width: 0;
  border: var(--u) solid var(--line); padding: calc(var(--u) * 5) calc(var(--u) * 4);
  font-family: var(--read); font-size: 17px; line-height: 1.5;
  scroll-margin-top: calc(var(--u) * 6);
}
.contact-title {
  justify-self: start; padding: var(--u) calc(var(--u) * 2);
  font-family: var(--display); font-weight: 400; font-size: 20px; line-height: 1;
  color: var(--bg); background: var(--soft);
}
.contact-signin { display: grid; gap: calc(var(--u) * 4); justify-items: start; }
.contact-lede { color: var(--soft); }
.contact-form { display: grid; gap: calc(var(--u) * 5); }
.field { display: grid; gap: calc(var(--u) * 2); min-width: 0; }
.field label { font-weight: 600; font-size: 16px; }
.field .opt { font-weight: 400; color: var(--soft); }
.contact .input { width: 100%; flex: none; font-family: var(--read); font-size: 17px; }
.contact .input.select { font-family: var(--read); font-size: 17px; }
.contact textarea.input { min-height: 200px; resize: vertical; line-height: 1.5; }
.contact .input[readonly] { background: var(--panel); border-color: var(--line); color: var(--soft); }
.contact .input[aria-invalid="true"] { border-color: var(--error); }
.field-note { font-size: 15px; color: var(--soft); }
.field-err { font-size: 16px; color: var(--error-fg); }
.form-err { border: var(--u) solid var(--error); padding: calc(var(--u) * 3) calc(var(--u) * 4); }
.hp { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }
.contact-done { display: grid; gap: calc(var(--u) * 2); border: var(--u) solid var(--ok); padding: calc(var(--u) * 4); }
.contact-done:focus { outline: none; }
.contact-done-title { font-size: 20px; font-weight: 700; color: var(--ok-fg); }

@media (min-width: 560px) {
  .spec-prevnext { grid-template-columns: 1fr 1fr; }
  .spec-pn.is-next { grid-column: 2; }
  .contact { padding: calc(var(--u) * 6); }
  .spec-article h1 { font-size: 60px; }
}

@media (min-width: 1000px) {
  .specpage.has-toc { grid-template-columns: 240px minmax(0, 1fr); gap: calc(var(--u) * 12); align-items: start; }
  .spec-side { position: sticky; top: calc(var(--u) * 6); max-height: calc(100vh - var(--u) * 12); overflow-y: auto; }
  .spec-toc { border: 0; background: none; }
  .spec-toc > summary { pointer-events: none; padding: 0 0 calc(var(--u) * 4); min-height: 0; color: var(--soft); }
  .spec-toc > summary::after { content: none; }
  .spec-toc ol { padding: 0; }
}

/* ── the codex: blind-box cards, odds and every pull (codex.js; docs/SOULS_AND_RARITY.md) ── */

/* minmax(0, 1fr): the column follows the page, not its widest unbreakable child (phones) */
.codex { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--u) * 4); justify-items: start; min-width: 0; }
/* long codex buttons (VERIFY EVERY PULL HERE, SEE MY RECOVERY CARD) wrap on narrow phones */
.codex .btn { white-space: normal; max-width: 100%; }
.codex .codex-series { white-space: normal; max-width: 100%; overflow-wrap: anywhere; }
.codex[hidden] { display: none; }
.codex-series { background: var(--panel); color: var(--text); font-size: 20px; }
.codex-lede { font-size: 16px; line-height: 1.6; max-width: 60ch; color: var(--text); margin: 0; }
.codex-actions { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 3); }
.codex-tally { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 3); margin: 0; font-size: 16px; color: var(--soft); }
.codex-tallyitem { display: inline-flex; gap: var(--u); align-items: center; }

.codex-badge {
  font-family: var(--display); font-size: 10px; line-height: 1; letter-spacing: 0;
  display: inline-block; padding: var(--u) calc(var(--u) * 1.5); color: var(--tier-common-on); background: var(--tier-common);
  white-space: nowrap;
}
.codex-badge.tier-uncommon { background: var(--tier-uncommon); color: var(--tier-uncommon-on); }
.codex-badge.tier-rare { background: var(--tier-rare); color: var(--tier-rare-on); }
.codex-badge.tier-epic { background: var(--tier-epic); color: var(--tier-epic-on); }
.codex-badge.tier-legendary { background: var(--tier-legendary); color: var(--tier-legendary-on); }
/* the secret prism: every other tier, in the hot-to-cool order of OGPB's badge */
.codex-badge.tier-secret { background: linear-gradient(90deg, var(--tier-secret) 0 20%, var(--tier-legendary) 20% 40%, var(--tier-uncommon) 40% 60%, var(--tier-rare) 60% 80%, var(--tier-epic) 80% 100%); color: var(--tier-secret-on); }
.codex-badge.tier-original { background: var(--line); color: var(--text); }

/* the squad: a 4x4 grid of cards, 2 columns on phones */
.codex-grid {
  list-style: none; margin: 0; padding: 0; width: 100%;
  display: grid; gap: calc(var(--u) * 2); grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 600px) { .codex-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.codex-about { width: 100%; }
.codex-about > summary { font-family: var(--display); font-size: 20px; line-height: 1; cursor: pointer; color: var(--soft); min-height: 44px; display: flex; align-items: center; }
.codex-about > summary:hover { color: var(--primary-fg); }
.codex-about > * + * { margin-top: calc(var(--u) * 3); }
.codex-card {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: calc(var(--u) * 3); align-items: start;
  padding: calc(var(--u) * 2); background: var(--panel); border: var(--u) solid var(--line);
}
.codex-card.tier-rare { border-color: var(--tier-rare); }
.codex-card.tier-epic { border-color: var(--tier-epic); }
.codex-card.tier-legendary { border-color: var(--tier-legendary); box-shadow: var(--u) var(--u) 0 0 var(--tier-legendary-deep); }
.codex-card.tier-secret { border-color: var(--tier-secret); box-shadow: var(--u) var(--u) 0 0 var(--tier-rare); }
.codex-sprite { width: 55px; height: 70px; image-rendering: pixelated; background: var(--ink); }
.codex-card-body { display: grid; gap: var(--u); min-width: 0; }
.codex-card-top { display: flex; gap: calc(var(--u) * 2); align-items: center; flex-wrap: wrap; }
.codex-where { font-family: var(--display); font-size: 10px; color: var(--soft); }
.codex-name { font-size: 15px; line-height: 1.3; color: var(--text); overflow-wrap: anywhere; }
.codex-form, .codex-bits, .codex-born { font-size: 13px; line-height: 1.35; color: var(--soft); overflow-wrap: anywhere; }
.codex-trade { font-family: var(--display); font-size: 10px; line-height: 1; }
.codex-trade.is-free { color: var(--ok-fg); }
.codex-trade.is-bound { color: var(--primary-fg); }

.codex-more { width: 100%; border-top: var(--u) solid var(--line); padding-top: calc(var(--u) * 3); }
.codex-more > summary {
  font-family: var(--display); font-size: 20px; line-height: 1; cursor: pointer; color: var(--text);
  min-height: 44px; display: flex; align-items: center;
}
.codex-more > * + * { margin-top: calc(var(--u) * 3); }
.codex-scroll { width: 100%; overflow-x: auto; }
.codex-table { border-collapse: collapse; font-size: 14px; color: var(--text); min-width: 100%; display: block; max-width: 100%; overflow-x: auto; }
.codex-table th { font-family: var(--display); font-size: 10px; font-weight: 400; color: var(--soft); text-align: left; padding: var(--u) calc(var(--u) * 2); }
.codex-table td { padding: var(--u) calc(var(--u) * 2); border-top: 1px solid var(--line); white-space: nowrap; }
.codex-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.codex-table tr.is-dud td { color: var(--soft); }
.codex-proof code { font-size: 12px; color: var(--secondary-fg); }
.codex-check.is-ok { color: var(--ok-fg); }
.codex-check.is-bad { color: var(--error-fg); }
.codex-dl { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--u) calc(var(--u) * 3); margin: 0; font-size: 14px; }
.codex-dl dt { font-family: var(--display); font-size: 10px; color: var(--soft); padding-top: var(--u); }
.codex-dl dd { margin: 0; min-width: 0; }
.codex-wrap { overflow-wrap: anywhere; word-break: break-all; }
.codex-events { margin: 0; padding-left: calc(var(--u) * 6); font-size: 14px; line-height: 1.5; color: var(--text); max-height: 360px; overflow-y: auto; }
.codex-when { color: var(--soft); }
.codex-kind { font-family: var(--display); font-size: 10px; color: var(--secondary-fg); text-transform: uppercase; }

/* the series calendar, the owner's corner, favourite tracks and the binder (owner decisions 2026-11-07) */
.codex-cal { margin: 0; font-size: 14px; line-height: 1.5; color: var(--soft); max-width: 70ch; overflow-wrap: anywhere; }
.codex-cal .codex-count { color: var(--primary-fg); font-weight: 400; font-variant-numeric: tabular-nums; white-space: nowrap; }
.codex-owner { display: grid; gap: calc(var(--u) * 2); width: 100%; min-width: 0; }
.codex-ownerrow {
  margin: 0; display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); align-items: center;
  font-size: 14px; line-height: 1.4; color: var(--text); padding: calc(var(--u) * 2) calc(var(--u) * 3);
  background: var(--panel); border-left: var(--u) solid var(--line);
}
.codex-ownerrow .codex-kind { min-width: 13ch; }
.codex-link { font-family: var(--display); font-size: 10px; line-height: 1; padding: calc(var(--u) * 2) 0; }
.codex-fav { font-size: 13px; line-height: 1.35; color: var(--tertiary-fg); overflow-wrap: anywhere; }
.codex-retired { border-style: dashed; }
.codex-retired .codex-sprite { width: 44px; height: 56px; filter: grayscale(0.35); }

.codex-dialog {
  width: min(92vw, 560px); max-width: calc(100vw - var(--u) * 8); padding: calc(var(--u) * 6);
  background: var(--bg); color: var(--text); border: var(--u) solid var(--frame);
  box-shadow: calc(var(--u) * 2) calc(var(--u) * 2) 0 0 var(--ink);
}
.codex-dialog::backdrop { background: rgba(var(--ink-rgb), 0.82); }
.codex-dialog > * + * { margin-top: calc(var(--u) * 4); }
.codex-dialog .h2 { margin: 0; }
.codex-dlg-lede { margin: 0; font-size: 16px; line-height: 1.6; }
.codex-cardcode {
  display: block; padding: calc(var(--u) * 3); background: var(--well); color: var(--primary-fg);
  font-family: var(--body); font-size: 16px; line-height: 1.7; letter-spacing: 0.04em;
  overflow-wrap: anywhere; word-break: break-all; user-select: all; border: var(--u) dashed var(--line);
}

/* /rarity: the rarest-bands board (page-rarity.js) */
.boardpage { display: grid; gap: calc(var(--u) * 6); justify-items: start; min-width: 0; }
.board-list { list-style: none; margin: 0; padding: 0; width: 100%; display: grid; gap: calc(var(--u) * 3); }
.board-empty { font-size: 16px; color: var(--soft); }
.board-row {
  display: grid; grid-template-columns: auto auto minmax(0, 1fr); gap: calc(var(--u) * 3); align-items: center;
  padding: calc(var(--u) * 3); background: var(--panel); border: var(--u) solid var(--line);
}
.board-row:first-child { border-color: var(--primary); }
.board-rank { font-family: var(--display); font-size: 20px; color: var(--primary-fg); min-width: 3ch; }
.board-avatar { width: 48px; height: 48px; image-rendering: pixelated; background: var(--ink); display: inline-flex; align-items: center; justify-content: center; font-family: var(--display); color: var(--soft); }
.board-who { display: grid; gap: var(--u); min-width: 0; }
.board-name { font-size: 18px; overflow-wrap: anywhere; }
.board-score { font-family: var(--display); font-size: 10px; color: var(--soft); }
.board-tally { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); margin: 0; font-size: 13px; color: var(--soft); }
.board-cards { grid-column: 1 / -1; list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: calc(var(--u) * 3); }
.board-card { display: grid; justify-items: center; gap: var(--u); max-width: 12ch; }
.board-card .codex-sprite { width: 33px; height: 42px; }
.board-cardname { font-size: 12px; line-height: 1.3; color: var(--soft); text-align: center; overflow-wrap: anywhere; }
@media (min-width: 720px) {
  .board-row { grid-template-columns: auto auto minmax(0, 1fr) auto; }
  .board-cards { grid-column: auto; }
}

/* ── the Series Premiere: every series opens with a ceremony (premiere.js; docs/SOULS_AND_RARITY.md §15) ──
   A box, then each card (old name -> new name, the glow-up, the personalization), then the band
   portrait. Classes only (CSP style-src 'self'); calm under reduced motion. */
.premiere-cta {
  display: grid; gap: calc(var(--u) * 2); width: 100%; min-width: 0; padding: calc(var(--u) * 3);
  background: var(--panel); border: var(--u) solid var(--primary); box-shadow: var(--u) var(--u) 0 0 var(--ink);
}
.premiere-cta.is-quiet { border-color: var(--line); box-shadow: none; }
.premiere-cta-h { margin: 0; font-family: var(--display); font-size: 20px; line-height: 1.2; color: var(--primary-fg); overflow-wrap: anywhere; }
.premiere-cta-p { margin: 0; font-size: 14px; line-height: 1.5; color: var(--text); max-width: 64ch; }
.premiere-cta .codex-actions .btn { white-space: normal; max-width: 100%; }
.premiere-banner { margin: 0; display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); align-items: center; }
.premiere-banner .btn { white-space: normal; max-width: 100%; }
.premiere-hist { list-style: none; margin: 0; padding: 0; display: grid; gap: calc(var(--u) * 2); width: 100%; }
.premiere-hist-item {
  display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); align-items: center; min-width: 0;
  padding: calc(var(--u) * 2) calc(var(--u) * 3); background: var(--panel); border-left: var(--u) solid var(--primary);
  font-size: 14px; line-height: 1.4;
}
.premiere-hist-name { font-family: var(--display); font-size: 10px; color: var(--primary-fg); overflow-wrap: anywhere; }
.codex-edition { font-size: 13px; line-height: 1.35; color: var(--primary-fg); overflow-wrap: anywhere; }

.premiere-dlg {
  width: min(720px, calc(100vw - var(--u) * 4)); max-width: calc(100vw - var(--u) * 4);
  max-height: calc(100vh - var(--u) * 8); overflow-x: hidden; overflow-y: auto;
  padding: calc(var(--u) * 4); color: var(--text); background: var(--bg);
  border: var(--u) solid var(--frame); box-shadow: calc(var(--u) * 2) calc(var(--u) * 2) 0 0 var(--ink);
  font-family: var(--body); font-size: 16px; line-height: 1.4;
}
.premiere-dlg::backdrop { background: rgba(var(--ink-rgb), 0.88); }
.premiere-dlg > * + * { margin-top: calc(var(--u) * 4); }
.premiere-top { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); align-items: center; justify-content: space-between; }
/* OPEN ALL (SKIP THE CEREMONY) is long: it wraps inside the 375px dialog instead of poking out */
.premiere-top .btn { white-space: normal; max-width: 100%; text-align: center; }
.premiere-title { margin: 0; font-family: var(--display); font-size: 20px; line-height: 1.2; color: var(--primary-fg); overflow-wrap: anywhere; min-width: 0; }
.premiere-flag {
  font-family: var(--display); font-size: 10px; line-height: 1; padding: var(--u) calc(var(--u) * 2);
  background: var(--tertiary); color: var(--tertiary-on); white-space: nowrap;
}
.premiere-flag.is-replay { background: var(--secondary); color: var(--secondary-on); }
.premiere-stage { display: grid; gap: calc(var(--u) * 3); justify-items: center; text-align: center; min-width: 0; }
.premiere-stage > * { max-width: 100%; }
.premiere-progress { margin: 0; font-family: var(--display); font-size: 10px; color: var(--soft); }
.premiere-bar { display: block; width: 100%; height: calc(var(--u) * 2); background: var(--well); border: 0; }
.premiere-bar::-webkit-progress-bar { background: var(--well); }
.premiere-bar::-webkit-progress-value { background: var(--primary); }
.premiere-bar::-moz-progress-bar { background: var(--primary); }
.premiere-actions { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 3); justify-content: flex-end; }
.premiere-actions .btn { white-space: normal; max-width: 100%; }

.premiere-box { width: 192px; height: 192px; image-rendering: pixelated; cursor: pointer; background: transparent; }
.premiere-box.is-shaking { animation: premiere-shake 0.36s steps(2, end) infinite; }
.premiere-box.is-open { animation: premiere-pop 0.6s steps(6, end) 1 both; }
@keyframes premiere-shake { 50% { transform: translate(var(--u), 0) rotate(2deg); } }
@keyframes premiere-pop { 0% { transform: scale(1); } 40% { transform: scale(1.12); } 100% { transform: scale(1); } }
.premiere-series { margin: 0; font-family: var(--display); font-size: 20px; line-height: 1.2; color: var(--text); overflow-wrap: anywhere; }
.premiere-lede { margin: 0; font-size: 16px; line-height: 1.5; color: var(--soft); max-width: 52ch; }

.premiere-cards { display: flex; flex-wrap: nowrap; gap: calc(var(--u) * 3); align-items: center; justify-content: center; max-width: 100%; }
.premiere-card { margin: 0; display: grid; justify-items: center; gap: var(--u); padding: calc(var(--u) * 2); background: var(--panel); border: var(--u) solid var(--line); min-width: 0; }
.premiere-card .codex-sprite { width: 88px; height: 112px; }
.premiere-card.is-before { opacity: 0.6; border-style: dashed; }
.premiere-card.is-after { border-color: var(--primary); }
.premiere-card.is-after.glow-1 { box-shadow: var(--u) var(--u) 0 0 var(--line); }
.premiere-card.is-after.glow-2 { box-shadow: var(--u) var(--u) 0 0 var(--primary-lo); }
.premiere-card.is-after.glow-3 { box-shadow: calc(var(--u) * 2) calc(var(--u) * 2) 0 0 var(--primary); }
.premiere-card.is-glowing { animation: premiere-glow 0.9s steps(3, end) 2 both; }
@keyframes premiere-glow { 50% { border-color: var(--text); background: var(--line); } }
.premiere-arrow { font-family: var(--display); font-size: 20px; color: var(--primary-fg); }
.premiere-cap { font-family: var(--display); font-size: 10px; color: var(--soft); }
.premiere-names { display: grid; gap: var(--u); justify-items: center; min-width: 0; }
.premiere-old { margin: 0; font-size: 16px; color: var(--soft); text-decoration: line-through; overflow-wrap: anywhere; }
.premiere-new { margin: 0; font-family: var(--display); font-size: 20px; line-height: 1.3; color: var(--primary-fg); overflow-wrap: anywhere; min-height: 1.3em; }
.premiere-new.is-typing::after { content: "_"; animation: cursor 0.6s steps(1, end) infinite; }
.premiere-who { margin: 0; font-size: 14px; color: var(--text); overflow-wrap: anywhere; }
.premiere-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); justify-content: center; }
.premiere-chip {
  font-family: var(--display); font-size: 10px; line-height: 1.2; padding: var(--u) calc(var(--u) * 2);
  background: var(--well); color: var(--text); border: var(--u) solid var(--line); overflow-wrap: anywhere;
}
.premiere-chip.is-glow { border-color: var(--primary); color: var(--primary-fg); }
.premiere-chip.is-change { border-color: var(--secondary); color: var(--secondary-fg); }
.premiere-chip.is-fair { border-color: var(--ok); color: var(--ok-fg); }
.premiere-chips.is-hidden { visibility: hidden; }
.premiere-record { margin: 0; font-size: 14px; line-height: 1.5; color: var(--soft); max-width: 56ch; }

.premiere-portrait { width: 100%; max-width: 450px; aspect-ratio: 3 / 2; height: auto; image-rendering: pixelated; background: var(--ink); }
.premiere-sum { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--u); font-size: 14px; line-height: 1.5; text-align: left; width: 100%; max-width: 56ch; }
.premiere-grid {
  list-style: none; margin: 0; padding: 0; width: 100%;
  display: grid; gap: calc(var(--u) * 2); grid-template-columns: repeat(auto-fill, minmax(min(100%, 96px), 1fr));
}
.premiere-mini { display: grid; justify-items: center; gap: var(--u); min-width: 0; }
.premiere-mini .codex-sprite { width: 44px; height: 56px; }
.premiere-mini-name { font-size: 12px; line-height: 1.3; color: var(--soft); text-align: center; overflow-wrap: anywhere; max-width: 100%; }
.board-edition { font-family: var(--display); font-size: 10px; color: var(--primary-fg); }
.board-premieres { margin: 0; font-size: 14px; line-height: 1.5; color: var(--soft); max-width: 70ch; }

@media (prefers-reduced-motion: reduce) {
  .premiere-box.is-shaking, .premiere-box.is-open, .premiere-card.is-glowing { animation: none; }
  .premiere-new.is-typing::after { animation: none; }
}

/* ── palettes: the footer picker, the device page, /palettes and the studio ────────────────
   (palette.js, page-palettes.js; docs/PALETTES.md). A [data-palette-scope] element wears another
   palette's tokens, so each card below previews its palette with the site's own classes. */
.foot-pal { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 2) calc(var(--u) * 3); min-width: 0; }
.foot-pal:empty { display: none; }
.foot-pal-label { font-family: var(--display); font-size: 20px; line-height: 1; color: var(--soft); }
.pal-select { flex: 0 1 auto; max-width: 100%; min-width: 0; }
.foot-pal-more { font-family: var(--display); font-size: 20px; line-height: 1; color: var(--soft); text-decoration: none; padding: calc(var(--u) * 3) 0; }
.foot-pal-more:hover { color: var(--primary-fg); }
.foot-pal-note { flex-basis: 100%; }

.pal-sw { display: inline-flex; flex: none; border: var(--u) solid var(--ink); background: var(--ink); }
.pal-sw > i { display: block; width: 12px; height: 24px; }
.pal-canvas { display: block; width: 192px; max-width: 100%; height: 24px; image-rendering: pixelated; border: var(--u) solid var(--ink); }

.palpage { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--u) * 8); min-width: 0; }
.palhead { display: grid; gap: calc(var(--u) * 4); justify-items: start; }
.pal-grid { display: grid; gap: calc(var(--u) * 4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); min-width: 0; }
.pal-card {
  display: grid; gap: calc(var(--u) * 3); align-content: start; min-width: 0;
  padding: calc(var(--u) * 4); background: var(--bg); color: var(--text);
  border: calc(var(--u) * 2) solid var(--frame); box-shadow: var(--u) var(--u) 0 0 var(--ink);
}
.pal-card.is-active { outline: var(--u) solid var(--primary); outline-offset: var(--u); }
.pal-card-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: calc(var(--u) * 3); }
.pal-name { font-family: var(--display); font-weight: 400; font-size: 30px; line-height: 1; color: var(--text); overflow-wrap: anywhere; }
.pal-mood { font-size: 16px; line-height: 1.5; color: var(--soft); }
.pal-specimen { display: grid; gap: calc(var(--u) * 3); padding: calc(var(--u) * 3); background: var(--panel); border: var(--u) solid var(--line); min-width: 0; }
.pal-stripe { height: 12px; background: linear-gradient(to bottom, var(--tertiary) 0 4px, var(--primary) 4px 8px, var(--secondary) 8px 12px); }
.pal-spec-title { font-family: var(--display); font-size: 20px; line-height: 1; display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); align-items: center; }
.pal-spec-text { font-size: 16px; line-height: 1.5; color: var(--text); }
.pal-spec-text strong { color: var(--strong); }
.pal-soft { color: var(--soft); }
.pal-spec-row { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); align-items: center; }
.pal-spec-status { min-height: 0; font-size: 14px; }
.pal-card-actions .btn { white-space: normal; }
.pal-custom { display: grid; gap: calc(var(--u) * 4); justify-items: start; min-width: 0; }
.pal-anchors > summary { font-family: var(--display); font-size: 20px; line-height: 1; cursor: pointer; min-height: 44px; display: flex; align-items: center; }
.pal-anchors > * + * { margin-top: calc(var(--u) * 3); }
.palpage .table-wrap { max-width: 100%; overflow-x: auto; border: var(--u) solid var(--line); }
.pal-table { border-collapse: collapse; font-size: 14px; line-height: 1.35; }
.pal-table th, .pal-table td { padding: var(--u) calc(var(--u) * 2); text-align: left; vertical-align: middle; border-top: 1px solid var(--line); }
.pal-table thead th { font-family: var(--display); font-weight: 400; font-size: 10px; color: var(--soft); white-space: nowrap; }
.pal-chip { display: inline-block; width: 24px; height: 24px; border: 2px solid var(--ink); vertical-align: middle; }

/* the studio, the library and the market (paid) */
.pal-studio, .pal-lib, .pal-market { display: grid; gap: calc(var(--u) * 4); width: 100%; min-width: 0; border: var(--u) solid var(--line); padding: calc(var(--u) * 4); }
.pal-knobs { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 3); align-items: end; min-width: 0; }
.pal-knob { display: grid; gap: var(--u); min-width: 0; max-width: 100%; }
.pal-knob .label { font-size: 16px; color: var(--soft); }
.pal-preview { display: block; width: 100%; max-width: 560px; height: auto; background: var(--ink); border: var(--u) solid var(--ink); }
.pal-anchor-grid { display: grid; gap: calc(var(--u) * 2); grid-template-columns: repeat(auto-fill, minmax(min(100%, 170px), 1fr)); width: 100%; }
.pal-anchor { display: flex; align-items: center; gap: calc(var(--u) * 2); font-size: 14px; min-width: 0; overflow-wrap: anywhere; }
.pal-anchor input[type="color"] { width: 40px; height: 32px; padding: 0; border: 2px solid var(--text); background: var(--well); flex: none; cursor: pointer; }
.pal-anchor.is-locked { color: var(--primary-fg); }
.pal-problems { font-size: 14px; line-height: 1.45; color: var(--error-fg); }
.pal-ok { font-size: 14px; color: var(--ok-fg); }
.pal-list { display: grid; gap: calc(var(--u) * 3); width: 100%; min-width: 0; }
.pal-item { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--u) * 2); padding: calc(var(--u) * 3); background: var(--panel); border: var(--u) solid var(--line); min-width: 0; }
.pal-item.is-active { border-color: var(--primary); }
.pal-item-head { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 2) calc(var(--u) * 3); min-width: 0; }
.pal-item-name { font-family: var(--display); font-size: 20px; line-height: 1; overflow-wrap: anywhere; }
.pal-item-meta { font-size: 14px; color: var(--soft); overflow-wrap: anywhere; }
.pal-item-actions { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); }
.pal-item-actions .btn { white-space: normal; }
.pal-rate { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--u) * 2); }
.pal-rate .input.select { min-height: 40px; font-size: 16px; }

/* the device page's palette block */
.devpal { display: grid; gap: calc(var(--u) * 3); justify-items: start; min-width: 0; }
.devpal-list { display: flex; flex-wrap: wrap; gap: calc(var(--u) * 2); }
.devpal-btn { display: inline-flex; align-items: center; gap: calc(var(--u) * 2); padding: calc(var(--u) * 2); }
.devpal-btn[aria-pressed="true"] { border-color: var(--primary); }
.devpal-note { font-size: 14px; color: var(--soft); max-width: 60ch; }

/* ── the band's talkback: /p/<pill>/studio, /band/<holder>, /talkback/<song> (talkback.pages) ─────── */
.page-talkback .tb-nav { font-family: var(--display); font-size: 18px; margin: 0 0 calc(var(--u) * 4); }
.page-talkback .tb-nav a { color: var(--secondary-fg); text-decoration: none; }
.page-talkback .tb-nav a:hover { color: var(--primary-fg); }
.spec-article .tb-through, .spec-article .tb-days { font-family: var(--body); font-size: 15px; color: var(--soft); }
.spec-article .tb-through a, .spec-article .tb-days a { color: var(--secondary-fg); text-decoration: none; }
.spec-article .tb-through a.tb-on, .spec-article .tb-days a.tb-on { color: var(--text); border-bottom: var(--u) solid var(--primary); }
.spec-article .tb-entry { border-left: calc(var(--u) * 1.5) solid var(--line); padding-left: calc(var(--u) * 4); margin-top: calc(var(--u) * 6); }
.spec-article .tb-entry h3 { margin-top: 0; }
.spec-article .tb-entry > * + * { margin-top: calc(var(--u) * 3); }
.spec-article .tb-footer { font-size: 15px; color: var(--soft); }
.spec-article .tb-read-through { font-family: var(--body); font-size: 14px; color: var(--soft); text-transform: uppercase; letter-spacing: 0.04em; }
.spec-article .tb-lines small, .spec-article .tb-entry small { color: var(--soft); }
.spec-article table.tb-morph { width: auto; min-width: 20em; }
.spec-article table.tb-morph td, .spec-article table.tb-morph th { padding: var(--u) calc(var(--u) * 3); text-align: left; }
/* the TALKBACK tab on the device page (page-device.js): the song's article, sized for a module */
.talkback-tab.spec-article { font-size: 16px; }
.talkback-tab.spec-article h2 { font-size: 20px; margin-top: 0; padding-top: 0; border-top: 0; }
.talkback-tab.spec-article h3 { font-size: 17px; margin-top: calc(var(--u) * 6); }
.talkback-tab.spec-article .tb-empty, .talkback-tab.spec-article .tb-open { font-family: var(--body); font-size: 14px; color: var(--soft); }
