/* ONE NOTE AT A TIME — Ink.
   One skin, two moods. Flat, warm, typographic: no bevel, no gradient, no
   glass, no recessed screen. Surfaces separate by two tones and by space;
   displays are always dark slabs; numbers are big and rounded. Every colour
   that reaches a canvas is a token too, so the mood repaints the pictures. */

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

:root, [data-theme="ink"] {
  --bg: #141210; --bg1: #1a1816; --bg2: #1e1c19; --bg3: #262320; --bg4: #33302a;
  --border: #2a2622; --border2: #3a3530;
  --text: #ebe5de; --text2: #a99d92; --text3: #8b8077;
  --accent: #8f7bf2; --accent-soft: rgba(143,123,242,.16);
  --bev-hi: transparent; --bev-lo: transparent; --bev-drop: 0 0 0 transparent;
  --scr: none; --scr-hi: transparent;
  --glass-bg: #141210; --glass-blur: 0px; --glass-sat: 1;
  --amb-a: transparent; --amb-b: transparent; --amb: 0;
  --deg1: #34c77b; --deg2: #e0705c; --deg3: #e3c34e; --deg4: #38b8a8; --deg5: #4f8fe0; --deg6: #cf9a3f; --deg7: #e04555;
  --good: #35c77b; --warn: #e0a53c; --bad: #e05a4e;
  --card-bg: #1e1c19; --card-hi: #1e1c19; --card-shadow: none;
  --canvas-bg: #0b0a09;
  --trace: #35c77b; --trace-glow: rgba(53,199,123,.45);
  --lane: rgba(235,229,222,.06); --lane-key: rgba(235,229,222,.04);
  --lane-tonic: rgba(143,123,242,.16); --lane-text: rgba(235,229,222,.42);
  --grid: #232019;
  --heat-0: #0b0a09; --heat-1: #2b2168; --heat-2: #8f7bf2; --heat-3: #efeaff;
  --heat-alpha: off; --ink-on-light: off;
  --key-white: #e9e3da; --key-white-in: #f4eee5; --key-black: #1c1916; --key-black-in: #2b251e;
  --elev: none; --elev-sm: none;
  --btn-hi: #262320; --btn-lo: #262320;
  --dock-bg: #141210;
  --font: -apple-system, 'SF Pro Text', 'SF Pro Display', system-ui, sans-serif;
  --mono: ui-monospace, 'SF Mono', Menlo, monospace;
  /* Numbers and controls speak in the rounded system face: friendly, legible
     from the floor, and already on the phone. */
  --num: ui-rounded, -apple-system, 'SF Pro Rounded', system-ui, sans-serif;
  --r: 10px; --r2: 14px; --r3: 20px;
  --hair: 1px solid transparent;
  --display: var(--font);
  --serif: ui-serif, 'New York', 'Iowan Old Style', Georgia, serif;
  --texture: none; --texture-opacity: 0; --texture-blend: normal;
}

/* Lights on: warm paper and warm linen. The slabs stay dark — a display is
   always a screen, whatever the room is doing. */
[data-theme="ink-light"] {
  --bg: #f8f3ee; --bg1: #fbf8f4; --bg2: #efeae3; --bg3: #e6e0d8; --bg4: #d9d1c7;
  --border: #ddd5cc; --border2: #c6bcb0;
  --text: #1c1916; --text2: #5f554c; --text3: #7a6f66;
  --accent: #7b66e8; --accent-soft: rgba(123,102,232,.14);
  --deg1: #2f7d4e; --deg2: #b25a44; --deg3: #a8862f; --deg4: #2f7d74; --deg5: #3a6ea8; --deg6: #8a6b28; --deg7: #b23a3f;
  --good: #2e8b52; --warn: #b0741f; --bad: #c03a33;
  --card-bg: #efeae3; --card-hi: #efeae3;
  --glass-bg: #f8f3ee; --dock-bg: #f8f3ee;
  --key-white: #fbf7f2; --key-white-in: #ffffff; --key-black: #26221e; --key-black-in: #3a332c;
  --btn-hi: #e6e0d8; --btn-lo: #e6e0d8;
}

:root {
  --inset-top: max(env(safe-area-inset-top, 0px), var(--safe-top, 0px));
  --inset-bottom: max(env(safe-area-inset-bottom, 0px), var(--safe-bottom, 0px));
}


/* Titles carry the theme's typographic voice; body text stays legible-first. */
h2, .brand, .page-title, .key-hero-name, .welcome-card h1, .about-name,
.w-title, .guide h3 { font-family: var(--display); }
/* …except where the sibling's serif voice speaks: the working key, the welcome,
   the wordmark's tail. Declared after the title rule so it wins. */
.key-hero-name, .kn-main, .welcome-card h1, .w-lede, .about-name { font-family: var(--serif); }
.key-hero-name, .kn-main { font-weight: 500; letter-spacing: 0; }
.w-lede { font-style: italic; font-size: 14px; }
html { background: var(--bg); }

/* ══ the visual beat: silent practice ══
   The screen edge breathes on every beat, the accent in the theme's own
   colour. Driven from the main loop, so it works on any page. */
.beat-flash { position: fixed; inset: 0; z-index: 95; pointer-events: none; opacity: 0; }
.beat-flash.on, .beat-flash.acc { animation: beat-pulse .16s ease-out; }
.beat-flash.on  { background: radial-gradient(ellipse at center, transparent 58%, color-mix(in srgb, var(--text) 30%, transparent) 100%); }
.beat-flash.acc { background: radial-gradient(ellipse at center, transparent 48%, color-mix(in srgb, var(--accent) 62%, transparent) 100%); }
@keyframes beat-pulse { from { opacity: 1; } to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .beat-flash.on, .beat-flash.acc { animation-duration: .3s; } }

/* One focus ring for the whole app (keyboard navigation): the accent at half
   strength, offset so it never fights a control's own border. */
:focus-visible { outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent); outline-offset: 2px; }


body {
  height: 100dvh; overflow: hidden;
  /* The page ground is painted by <html>; body stays clear so the ambient
     layer below can show through behind the content. */
  background: transparent; color: var(--text);
  font-family: var(--font); font-size: 14px;
  display: flex; flex-direction: column; align-items: center;
  -webkit-font-smoothing: antialiased; -webkit-tap-highlight-color: transparent;
  transition: background .2s, color .2s;
}
.mono, .num { font-family: var(--num); font-variant-numeric: tabular-nums; }
/* An author `display` rule outranks the UA stylesheet's [hidden] { display: none },
   so anything given `display: flex` here would ignore the attribute entirely. */
[hidden] { display: none !important; }
/* This is an instrument, not a document: nothing is selectable, nothing pops
   a magnifier on a long press. Typing fields are the one exception. */
/* No callout, no selection, no double-tap zoom, no loupe: nothing here is text
   to be picked up. The shell also turns text interaction off at the web view. */
html { touch-action: manipulation; }
*, *::before, *::after { -webkit-touch-callout: none; }
body { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
/* Scrolling surfaces scroll; they do not grow a bar that pops and fades. */
.keys-scroll, main, .lib, .view { scrollbar-width: none; -ms-overflow-style: none; }
.keys-scroll::-webkit-scrollbar, main::-webkit-scrollbar, .lib::-webkit-scrollbar, .view::-webkit-scrollbar { display: none; width: 0; height: 0; }
input, textarea { -webkit-user-select: text; user-select: text; }
/* Rows that only mean something inside the native shell (haptics). */
.native-only { display: none !important; }
html.native .native-only { display: flex !important; }
html.native .poly-block { flex-direction: column; margin-top: 14px; }
html.native p.native-only { display: block !important; }
.viz.poly-roll { height: 150px; }
/* The host picks the input inside the shell. */
html.native #inputDevice { display: none; }

/* ── chrome ────────────────────────────────────────────── */
.topbar {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px;
  width: 100%; max-width: 880px; flex-shrink: 0;
  padding: calc(8px + var(--inset-top)) 12px 8px;
}
.tb-left { display: flex; justify-content: flex-start; min-width: 0; }
.tb-mid { display: flex; justify-content: center; min-width: 0; }
.tb-right { display: flex; align-items: center; justify-content: flex-end; gap: 7px; }
.back-btn {
  display: none; align-items: center; gap: 2px; background: none; border: none;
  color: var(--accent); font-family: inherit; font-size: 15px; cursor: pointer; padding: 2px 0;
  min-height: 40px; padding-block: 0;
}
.back-btn svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2.4; }
body.detail .back-btn { display: flex; }
body.detail .brand { display: none; }
.brand { display: flex; align-items: center; gap: 7px; font-size: 15px; font-weight: 600;
  letter-spacing: .02em; color: var(--text3); white-space: nowrap; }
/* The o of "one" is the mark: the ring, drawn a touch heavier so it reads as a
   letter, with the note inside. The mic light now lives in the name. */
.brand-mark.o { display: inline-block; width: .82em; height: .82em; vertical-align: -.1em; margin-right: -.08em; }
.brand-mark.o .bm-ring { stroke-width: 2.2; opacity: .85; }
.brand .brand-mark.o .bm-ring { stroke-width: 2.4; }
.brand-mark.o .bm-dot { r: 3.4px; }
.about-name b, .welcome-card h1 b { font-family: var(--display); letter-spacing: .01em; }
.brand-word { display: inline; }
/* Serif italics read smaller than the sans bold beside them: size the tail up
   a touch and pull it in, so "one note at a time" is one breath, not two. */
/* The tail at book weight: the bold it inherited from .brand read too heavy (the owner, round 94). */
.brand i { font-size: 1.1em; margin-left: .06em; color: var(--text2); font-weight: 400; }
/* The sibling cue: One Day at a Time sets its title's tail in italic serif.
   Same family, same gesture — system serif only, nothing fetched. */
.brand i, .about-name i, .welcome-card h1 i {
  font-style: italic; font-family: ui-serif, 'New York', Georgia, serif;
  letter-spacing: 0;
}
.brand b { color: var(--text); font-weight: 600; }
/* The mark: an open tuning ring holding one note. It doubles as the mic light —
   status you glance at lives in the identity, not beside it. */
.brand-mark { width: 19px; height: 19px; flex-shrink: 0; }
.brand-mark.md { width: 26px; height: 26px; margin-bottom: 3px; }
.brand-mark.lg { width: 34px; height: 34px; margin-bottom: 5px; }
.bm-ring {
  /* An almost-closed circle: the gap is 42 degrees at the upper right — enough
     to read as an opening, not enough to read as broken. Finer stroke and a
     smaller dot than v1; the mark should whisper. */
  fill: none; stroke: var(--accent); stroke-width: 1.7; stroke-linecap: round;
  opacity: .6; stroke-dasharray: 47.2 6.2;
  transform: rotate(-36deg); transform-origin: center;
  transition: stroke .4s;
}
.brand-mark.lg .bm-ring, .brand-mark.md .bm-ring { stroke-width: 1.5; }
.bm-dot { r: 3.1px; }
.bm-dot { fill: var(--accent); transition: fill .4s; }
.brand-mark.live .bm-dot { fill: var(--good); }
.brand-mark.live .bm-ring { stroke: var(--good); }
.page-title { font-size: 16px; font-weight: 600; display: none; }
body.detail .page-title { display: block; }

.spacer { flex: 1; }
.level-pill { display: none; }
body.mic-live .level-pill { display: block; }
/* Brut speaks in corners; the one pill in the top bar was a foreign accent. */
/* Mic and Record are icon buttons in the bar, the same weight as Setup: the
   mic mostly starts itself from a dead display now, and Record from anywhere
   is the one control worth a permanent place. */
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.tb-right .mic-btn.on { color: var(--good); }
/* Record reads as a key, not a dot: a ring round it, as on a tape deck. Idle the
   dot is a dim red (this is record, from any page); armed it is full red; recording
   it is the blinking square; the ring takes the colour of the state. */
.tb-right .rec-top { position: relative; }
.tb-right .rec-top::before { content: ''; position: absolute; inset: 5px; border-radius: 50%;
  border: 1.5px solid var(--text3); opacity: .8; transition: border-color .2s, opacity .2s; }
.tb-right .rec-top .rec-dot { width: 12px; height: 12px; background: var(--bad); opacity: .55; transition: opacity .2s; }
.tb-right .rec-top.armed .rec-dot { opacity: 1; }
.tb-right .rec-top.armed::before { border-color: var(--bad); }
.tb-right .rec-top.on .rec-dot { border-radius: 3px; width: 11px; height: 11px; opacity: 1; animation: rec-blink 1.1s ease-in-out infinite; }
.tb-right .rec-top.on::before { border-color: var(--bad); opacity: 1; }
@keyframes rec-blink { 50% { opacity: .35; } }
.icon-btn {
  background: none; border: none; color: var(--text3); cursor: pointer;
  display: flex; align-items: center; justify-content: center; padding: 0; width: 40px; height: 40px; margin: -6px;
}
.icon-btn svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.7; }

/* The status line floats over the page instead of pushing it down, and only
   exists while it has something to say. */
.status { font-size: 12px; color: var(--text3); line-height: 1.45; }
#status { position: fixed; left: 50%; transform: translateX(-50%); top: calc(var(--inset-top) + 50px); z-index: 60;
  max-width: 88vw; padding: 6px 14px; border-radius: 100px; background: var(--bg4); box-shadow: var(--elev-sm);
  font-size: 12px; color: var(--text2); text-align: center; line-height: 1.4; pointer-events: none; }
#status:empty { display: none; }
.status.err { color: var(--warn); }
.btn.arm { color: var(--bad); border-color: var(--bad); }

main {
  flex: 1; width: 100%; max-width: 880px;
  overflow-y: auto; overflow-x: hidden; padding: 0 16px 16px;
  /* --kb: what the on-screen keyboard covers while a field is being typed in
     (app.js); the page grows by that much so the field can come into view. */
  padding-bottom: calc(16px + var(--kb, 0px));
  -webkit-overflow-scrolling: touch;
}
.view { display: none; flex-direction: column; gap: 12px; }
.view.active { display: flex; }
/* Thumb pages: the whole stack sits at the foot of the screen when the page
   is short — the shelf right above the transport, the library right above the
   recorder — and the page opens at its foot when it is tall (see pinBottom). */
.view.thumb { min-height: 100%; }
.view.thumb > :first-child { margin-top: auto; }
/* Flex children shrink below their content by default, which silently clips a
   card mid-row inside a scrolling column. Nothing here should ever shrink. */
.view > *, .keys-scroll > * { flex-shrink: 0; }

.card {
  background: var(--card-bg);
  border: none; border-radius: var(--r3); padding: 14px;
}
.card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.card-head h2 {
  font-size: 12px; font-weight: 600; letter-spacing: .09em;
  text-transform: uppercase; color: var(--text3);
}
.card-tools { margin-left: auto; display: flex; align-items: center; gap: 8px; }
/* Zones: a page in the bench's grammar. Its sections sit on the ground like the
   bench's four zones — named by the same small caps head, with the slabs,
   rails and knobs as the only surfaces, and space rather than plates between
   them. A page opts in with .zoned on its view (Notes first). */
.view.zoned { gap: 30px; }
.view.zoned[data-view="notes"] { gap: 16px; }
/* The recorder on a faint ground of its own, a shade up from the library's. */
.view.zoned[data-view="notes"] > .card.at-thumb { background: color-mix(in srgb, var(--bg2) 55%, var(--bg)); padding: 10px 12px 12px; border-radius: 18px; }
.view.zoned > .card, .view.zoned .keys-scroll > .card { background: none; padding: 0; border-radius: 0; }
/* The Theory page fits one view (owner, 2026-10-07): the same 12 px between
   every block, a flatter tab bar, the rail right on the dock. */
.view.zoned .keys-scroll { gap: 12px; }
.keys-view .tabbar .tab { padding: 4px 3px 3px; gap: 2px; }
.keys-view .card.tight .card-head { margin-bottom: 8px; }
.keys-view .hrow-label { margin: 9px 0 4px; }
.keys-dock { padding-top: 6px; }
.keys-dock .dock-row { margin-bottom: 8px !important; }
.view.zoned .card-head { min-height: 30px; margin-bottom: 8px; }
.view.zoned .card-head.foot { margin: 10px 0 0; }
.view.zoned .card-head h2 { color: var(--text2); letter-spacing: .08em; }
.view.zoned .mix-labels { background: var(--bg); }

/* ── controls ──────────────────────────────────────────── */
.seg { display: inline-flex; background: var(--bg3); border-radius: 100px; padding: 3px; gap: 2px; }
.seg button {
  background: none; border: none; color: var(--text2);
  font-family: inherit; font-size: 12px; font-weight: 500;
  padding: 0 12px; min-height: 30px; border-radius: 100px; cursor: pointer; white-space: nowrap;
}
.seg button.on { background: var(--text); color: var(--bg); }
.seg.accent button.on { background: var(--accent); color: #fff; }
.seg button:disabled { opacity: .35; cursor: default; pointer-events: none; }

/* Extension (how tall a chord stacks) and Type (sus2/sus4/power) share one
   row: each seg carries its own tiny label as its first cell, buttons flex to
   share the remaining width, so the pair reads as two named instruments on a
   single rail. */
.seg .seg-label {
  align-self: center; padding: 0 3px 0 7px; flex-shrink: 0;
  font-size: 11px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text3); font-weight: 700;
}
/* Theory's row above the chips is the Desk's (ui/desk-row.js): round marks at the Desk's 36 px, the ? at the left.
   The chord button reads the rung every chip stands on; `live` while a slide holds a chip elsewhere. */
.keys-view .chord-head.dock-read { gap: 6px; min-height: 36px; }
.keys-view .chord-head.dock-read .seg.tiny { flex: 0 0 auto; }
.keys-view .chord-head.dock-read .btn { height: 36px; }
.keys-view .chord-head.dock-read .btn.ico-btn, .keys-view .chord-head.dock-read .btn.ped-btn { width: 36px; min-width: 36px; flex: 0 0 36px; padding: 0; }
.btn.rung-btn b { font-family: var(--num); font-weight: 600; font-size: 14px; }
.btn.rung-btn.live b { color: var(--accent); }
/* Prog's bar under the key: the tab at the left, its quick actions at the right; the pane unfolds below. */
.keys-view .tabbar.prog-bar { align-items: center; gap: 6px; }
.keys-view .tabbar.prog-bar .tab { flex: 1 1 auto; min-width: 0; align-items: flex-start; padding-left: 10px; }
.prog-quick { display: flex; align-items: center; gap: 6px; padding-right: 2px; flex: 0 0 auto; }
.prog-quick .btn { height: 36px; }
.prog-quick .btn.ico-btn { width: 36px; min-width: 36px; padding: 0; border-radius: 50%; justify-content: center; }
.prog-quick .prog-rec .rec-dot { width: 12px; height: 12px; background: var(--accent); }   /* purple: red ● is for audio only (the owner, 2026-11-10) */
.prog-quick .prog-rec.accent .rec-dot { background: #fff; }
.prog-quick .prog-play .ico { width: 18px; height: 18px; fill: currentColor; }
.prog-quick .prog-play .stop, .prog-quick .prog-play.playing .play { display: none; }
.prog-quick .prog-play.playing .stop { display: block; }
/* Prog's pane: the sections strip and the ? on one line, the click row under it. */
.prog-tools { justify-content: space-between; }
#progSections button.play { color: var(--accent); }
.pane-row.prog-clock { gap: 6px; }
#progClick b { font-family: var(--num); font-weight: 600; margin-left: 5px; }
.prog-clock .seg.fill { flex: 1; min-width: 0; }
.hrow-label.with-help { display: flex; align-items: center; gap: 8px; }
.hrow-label.with-help .qhelp { margin-left: auto; }

/* One text-button, four sizes: sm 30 · default 38 · row 46 · hero 54.
   Heights are fixed and flex-centred so mixed rows always share a centreline. */
.btn {
  background: linear-gradient(180deg, var(--btn-hi), var(--btn-lo));
  color: var(--text); border: var(--hair);
  border-radius: 100px; font-size: 14px; font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center;
  height: 40px; padding: 0 16px;
  font-family: inherit; cursor: pointer; white-space: nowrap;
  box-shadow: var(--elev-sm);
  transition: transform .06s, box-shadow .06s, background .12s;
}
.btn:active:not(:disabled) { transform: translateY(1px); box-shadow: none; }
.btn:disabled { opacity: .35; cursor: default; }
.btn.accent { background: var(--accent); border-color: var(--accent); color: #fff; }
/* A toggle that is on is filled with the text colour, like a segment cell; the accent is for actions. */
.btn.on:not(.accent):not(.rec-cap) { background: var(--text); border-color: var(--text); color: var(--bg); }
.ring-read.hint { color: var(--text3); font-weight: 500; font-size: 12px; line-height: 1.2; white-space: normal; text-align: center; }
.btn.round { border-radius: 100px; }
.btn.tap-square { width: 54px; height: 54px; padding: 0; flex: 0 0 54px; font-weight: 600; }
.btn.sm { height: 32px; padding: 0 12px; font-size: 13px; }
.btn.icon { padding: 0 12px; font-family: var(--mono); font-size: 15px; }

select, input[type=text], input[type=number], input[type=search], textarea {
  background: var(--bg3); color: var(--text); border: var(--hair);
  border-radius: var(--r); padding: 6px 8px; font-size: 13px;
  font-family: inherit; outline: none;
}
select:focus, input:focus, textarea:focus { border-color: var(--accent); }
/* Dropdowns in the rail language: no system arrow, a drawn chevron, 10px corners. */
select {
  -webkit-appearance: none; appearance: none; border-radius: 10px;
  padding-right: 26px; min-height: 32px; font-weight: 500;
  background-image: linear-gradient(45deg, transparent 50%, var(--text3) 50%), linear-gradient(135deg, var(--text3) 50%, transparent 50%);
  background-position: calc(100% - 15px) 52%, calc(100% - 10px) 52%;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}
select[hidden] { display: none; }
input[type=range] { accent-color: var(--accent); }
.label { font-size: 12px; letter-spacing: .07em; text-transform: uppercase; color: var(--text3); font-weight: 600; }

.key-bar .label { flex-shrink: 0; }
.key-name {
  flex: 1; background: var(--bg3); border: var(--hair); border-radius: var(--r2);
  color: var(--text); font-family: inherit; font-size: 16px; font-weight: 600;
  padding: 8px 10px; cursor: pointer; text-align: center;
}

/* ── module footer actions ─────────────────────────────── */
.module-actions {
  display: flex; align-items: center; gap: 8px; margin-top: 12px;
  padding-top: 10px; border-top: var(--hair);
}
.module-actions .peek { font-family: var(--num); font-size: 12px; color: var(--text3); margin-right: auto; }
.btn.go {
  display: inline-flex; align-items: center; gap: 3px;
  background: none; border: none; color: var(--accent);
  font-size: 13px; font-weight: 500; padding: 6px 2px;
}
.btn.go svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.4; }

/* ── tap tempo: deliberately the biggest target on the module ── */
.metro-row { display: flex; align-items: center; gap: 14px; }
.bpm-stepper { flex: 1; display: flex; align-items: center; gap: 8px; }
.bpm-stepper .big-num { flex: 1; text-align: center; font-size: 36px; cursor: ns-resize; }

/* ── settings sliders ──────────────────────────────────── */
.slider-row { padding: 10px 0; border-top: var(--hair); }
.slider-row:first-of-type { border-top: none; padding-top: 0; }
.slider-label { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 6px; font-size: 13px; }
.slider-label span:last-child { color: var(--accent); font-size: 12px; }
.slider-row input[type=range] { width: 100%; }
.slider-row .adv-note { margin: 6px 0 0; }

/* ── key picker and related keys ───────────────────────── */
.key-picker { display: flex; gap: 6px; align-items: center; }
.key-picker[hidden] { display: none; }
/* Key arms: the next note is the root. The bar is ui/key-bar.js — the Desk's, the Tuner's, Theory's. */
.key-picker .set-key { flex: 0 0 auto; min-width: 84px; }
.key-picker .set-key.arm { background: var(--accent); border-color: var(--accent); color: #fff; }
.strip-head .prep-gap { flex: 1; }
.scale-maker .label { flex: 0 0 auto; }
.scale-maker .sm-notes { flex: 1; min-width: 0; font-family: var(--num); font-size: 14px; font-weight: 600; color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.related-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.related { padding: 9px 4px; }
.related {
  background: var(--bg3); border: var(--hair); border-radius: var(--r2);
  padding: 9px 4px; text-align: center; cursor: pointer;
}
.related .rk { font-family: var(--num); font-size: 15px; }
.related .rr { font-size: 12px; color: var(--text3); text-transform: capitalize; margin-top: 1px; }
.related .rs { font-size: 11px; color: var(--text3); font-family: var(--num); }

/* ── one button vocabulary: rounded squares, one size ──── */
.sq-btn {
  width: 46px; height: 46px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; border: none; cursor: pointer;
  background: var(--bg3);
  color: var(--text);
  font-family: var(--num); font-size: 20px; font-weight: 500; line-height: 1;
  transition: transform .06s, box-shadow .06s, filter .12s;
}
.sq-btn:active:not(:disabled) { transform: translateY(1px); box-shadow: none; }
.sq-btn:disabled { opacity: .35; cursor: default; }
.sq-btn svg { width: 20px; height: 20px; fill: currentColor; }
.sq-btn.lg { width: 54px; height: 54px; }
.sq-btn.sm { width: 34px; height: 34px; font-size: 16px; }
.sq-btn.ghost { background: none; box-shadow: none; color: var(--text2); }
.sq-btn.accent { background: var(--accent); color: #fff; }
.sq-btn.rec { background: var(--bg3); }
.rec-dot { width: 16px; height: 16px; border-radius: 50%; background: var(--bad); transition: border-radius .15s, width .15s, height .15s; }
.sq-btn.rec.on { background: color-mix(in srgb, var(--bad) 22%, var(--bg3)); }
.sq-btn.rec.on .rec-dot { border-radius: 3px; width: 14px; height: 14px; }

/* One row, one height: the square stays square and its partner matches it. */
.btn-row { display: flex; align-items: center; gap: 8px; width: 100%; }
.btn-row > .btn, .btn-row > .tap-btn { flex: 1; height: 46px; }
.btn-row > .tap-btn { justify-content: center; padding: 6px 10px; }
.btn-row > .sq-btn { height: 46px; }
/* The tempo stepper is a compact group in the middle of the widget, not a bar
   pinned to its edges: two 40px buttons either side of a modest number. */
.stepper { display: flex; align-items: center; justify-content: center; gap: 8px; width: auto; }
.stepper .w-hero { flex: 0 0 auto; justify-content: center; min-width: 66px; }
.stepper .sq-btn { width: 34px; height: 34px; font-size: 18px; border-radius: 50%; background: var(--bg3); color: var(--text); }
.w-hero .big-num { font-size: 26px; }
/* The tuner's hero keeps one box whether it shows a note or an idle dash. */
#wTune .w-hero { height: 40px; align-items: baseline; }
.wide-btn { display: flex; align-items: center; justify-content: center; }

/* ── cents meter: the tuner's use of its extra room ────── */
.cents-num { font-family: var(--num); font-size: 15px; color: var(--text2); text-align: center; }
.cents-num.good { color: var(--good); }
/* "tap to listen": the one place the accent means "start here". */
.cents-num.cta, .strobe-legend .cta { color: var(--accent); }
.cents-num.cta { cursor: pointer; }
.cents-meter { width: 100%; display: flex; flex-direction: column; gap: 3px; }
.cm-track {
  position: relative; height: 14px; border-radius: 7px;
  background: var(--canvas-bg);
  overflow: hidden;
}
.cm-zone {
  position: absolute; left: 46%; right: 46%; top: 0; bottom: 0;
  background: color-mix(in srgb, var(--good) 22%, transparent);
}
.cm-mid { position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: var(--border2); }
.cm-dot {
  position: absolute; top: 2px; width: 10px; height: 10px; border-radius: 50%;
  background: var(--text3); left: 50%; margin-left: -5px;
  transition: left .08s linear, background .2s;
}
.cm-dot.good { background: var(--good); }
.cm-dot.warn { background: var(--warn); }
.cm-dot.bad { background: var(--bad); }
.cm-scale { display: flex; justify-content: space-between; font-family: var(--num); font-size: 11px; color: var(--text3); }

/* ── probe readout: what the scope is actually showing ─── */
.probe-bar {
  display: flex; align-items: center; gap: 10px; margin-top: 8px; min-height: 36px;
  padding: 7px 10px; border-radius: var(--r2);
  background: var(--bg2); border: var(--hair);
  font-family: var(--num); font-size: 12px; color: var(--text2);
}
.probe-bar span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.circle-canvas { width: 100%; height: 220px; display: block; touch-action: none; }   /* a touch is a touch, not a scroll: delivered at once */
.fret-canvas { width: 100%; height: 190px; display: block; touch-action: none; }
.ctl-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 10px; }
.ctl-grid label { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ctl-grid select, .ctl-grid input { width: 100%; }

/* ── progression ───────────────────────────────────────── */
.prog-strip { display: flex; flex-wrap: wrap; gap: 5px; min-height: 34px; }
.prog-chip {
  display: flex; flex-direction: column; align-items: center;
  padding: 5px 10px; border-radius: 8px; background: var(--bg3);
  border: var(--hair); font-family: var(--num); font-size: 12px; cursor: pointer;
}
.prog-chip .beats { font-size: 11px; color: var(--text3); }
.prog-chip.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.prog-chip.on .beats { color: rgba(255,255,255,.75); }
.prog-empty { color: var(--text3); font-size: 12px; padding: 8px 0; }
.prog-lib { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.prog-row {
  display: flex; align-items: center; gap: 8px; padding: 7px 10px;
  background: var(--bg2); border-radius: 8px; font-size: 12px; cursor: pointer;
}
.prog-row .pr-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prog-row .pr-meta { font-family: var(--num); font-size: 12px; color: var(--text3); }
.preset-cat {
  font-size: 12px; letter-spacing: .08em; text-transform: uppercase; font-weight: 700;
  color: var(--text3); margin: 10px 0 4px; }
.preset-cat:first-child { margin-top: 2px; }
.prog-row .pr-name b { font-weight: 600; }
.prog-row .pr-sum { font-family: var(--num); font-size: 12px; color: var(--text3); }
/* Preset categories fold: 28 progressions browse as six lines. */
.preset-fold { border-top: var(--hair); }
.preset-fold:first-child { border-top: none; }
.preset-fold > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px;
  padding: 9px 2px; font-size: 12px; letter-spacing: .07em; text-transform: uppercase;
  font-weight: 700; color: var(--text2);
}
.preset-fold > summary::-webkit-details-marker { display: none; }
.preset-fold > summary::after { content: '›'; margin-left: auto; font-size: 14px; color: var(--text3); transition: transform .15s; }
.preset-fold[open] > summary::after { transform: rotate(90deg); }
.pf-count { font-family: var(--num); font-size: 12px; color: var(--text3); font-weight: 400; }
.preset-fold .prog-row { margin: 0 0 4px; }

/* ── keys page: sections above, keyboard under the thumb ── */
.keys-view { height: 100%; min-height: 0; gap: 0; position: relative; }
/* The scroll reserves the dock's height (measured, since the instrument sets
   it) so the anchored resting state clears the glass; scrolled content passes
   behind it. */
.keys-scroll { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; }
/* The dock floats over the scroll, so the scroll reserves the dock's height at
   its end. As a *spacer element*, not padding: WebKit does not count a flex
   scroll container's bottom padding as scrollable overflow (Chrome does), so on
   the phone the reserve vanished, nothing scrolled, and the chord rail sat
   behind the keyboard. */
.keys-scroll::after { content: ''; display: block; flex-shrink: 0; height: calc(var(--dock-h, 230px) - 6px); }
/* When the page is shorter than the view, it sits at its foot: the slack goes
   above the hero, not between the rail and the keys. An auto margin is zero
   once the page overflows, so scrolling is untouched. */
/* The key holds the top of the page; the chips keep the dock, and the row sits in the dock's head
   under them (the owner, 2026-11-10: the rung changes the chips' height — with the row above them the
   button moved under the thumb; under them it stays put and the chips grow upward). The gap between
   the key and the surface takes up the slack, so switching Key · Rings moves only the surface's top
   edge — nothing below it jumps — and an open Prog pane grows up into that gap. */
.keys-scroll > .card.tight { margin-top: auto; }   /* the auto margin is the page's slack, above the surface */
.keys-dock > .chord-head { margin: 0 0 8px; }
/* The page anchors at its bottom, so once scrolled the top edge slices a card;
   a short fade turns the slice into a horizon — and only once scrolled, so the
   first card is whole when the reader is actually at the top. */
.keys-view::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 26px; z-index: 2;
  background: linear-gradient(var(--bg), transparent); pointer-events: none;
  opacity: 0; transition: opacity .15s;
}
.keys-view.scrolled::before { opacity: 1; }
/* Liquid-glass, the part WebKit actually ships: a translucent surface with
   backdrop blur and saturation, per-look tokens. Brut and Retro set blur 0
   and an opaque surface — glass is not their dialect. */
.keys-dock {
  position: absolute; bottom: -5px; left: 0; right: 0;   /* a touch into main's inset: the keys sit lower, the page above breathes */
  padding-top: 14px; padding-bottom: 0; border-top: var(--hair);   /* main holds the inset; a second one here sat the keys too high */
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
}
@media (prefers-reduced-transparency: reduce) {
  .keys-dock { background: var(--dock-bg); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
details.panel {
  background: linear-gradient(180deg, var(--card-hi), var(--card-bg));
  border: var(--hair); border-radius: var(--r3); box-shadow: var(--elev);
  overflow: hidden;
}
details.panel > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px;
  padding: 12px 14px; font-size: 12px; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--text3);
}
details.panel > summary::-webkit-details-marker { display: none; }
details.panel > summary::after { content: '›'; margin-left: auto; font-size: 16px; transition: transform .15s; }
details.panel[open] > summary::after { transform: rotate(90deg); }
details.panel .panel-body { padding: 0 14px 14px; }
.sum-val { margin-left: auto; font-family: var(--num); font-size: 12px; color: var(--text2); text-transform: none; letter-spacing: 0; }
details.panel > summary::after { margin-left: 8px; }

/* ── settings rows ─────────────────────────────────────── */
.setting-row {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 0; border-top: var(--hair);
}
.setting-row:first-of-type { border-top: none; padding-top: 0; }
.setting-row > div:first-child { flex: 1; min-width: 0; }
.setting-name { font-size: 14px; margin-bottom: 0; }
.setting-row .adv-note { margin: 0; }
.setting-row .seg { flex-shrink: 0; }

/* ── bench: four widgets, one screen, no scrolling ─────── */
.view[data-view="bench"] { height: 100%; min-height: 0; }
.grid2 {
  display: grid; grid-template-columns: 1fr 1fr;
  grid-auto-rows: 1fr; gap: 10px; height: 100%; min-height: 0;
}
.widget {
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
  background: none; border: none; border-radius: 0; box-shadow: none;
}
.w-head {
  display: flex; align-items: center; gap: 6px;
  padding: 0 2px; min-height: 30px; border-bottom: none; flex-shrink: 0;
}
.w-title {
  flex: 1; display: flex; align-items: center; gap: 3px; min-width: 0; align-self: stretch;
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--text2); font-family: inherit; font-size: 12px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; text-align: left;
}
.w-title svg { width: 11px; height: 11px; fill: none; stroke: var(--accent); stroke-width: 2.8; flex-shrink: 0; }
/* The doors sit under the thumb that holds the phone: on the right by default,
   on the left for a left hand (Setup → Doors). The head simply runs backwards. */
body:not(.hand-left) .w-head { flex-direction: row-reverse; }
body:not(.hand-left) .w-title { justify-content: flex-end; text-align: right; }

.w-body {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: space-between; gap: 8px; padding: 4px 0 6px;
}
/* One rhythm for the four widgets: a hero block at the top, a display in the
   middle, a foot at the bottom, the space between them shared evenly. */
.w-block { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 100%; }
.w-block > .strobe-row, .w-block > .pc-strip, .w-block > .cents-meter { width: 100%; }
.w-chord { font-family: var(--num); font-size: 12px; color: var(--accent); min-height: 14px; line-height: 14px; text-align: center; }
/* The bench tuner's row: three fixed columns, so nothing hops. */
.tune-grid { display: grid; grid-template-columns: 96px 1fr 96px; align-items: baseline; height: 56px; margin-bottom: 6px; }
.tune-grid .cents-num { justify-self: start; text-align: left; }
.tune-grid .w-hero { justify-self: center; }
.tune-grid .w-chord { justify-self: end; text-align: right; font-size: 13px; }
.needle-lane { display: block; width: 100%; height: 26px; border-radius: var(--r) var(--r) 0 0; background: var(--canvas-bg); }
.needle-lane.page { height: 34px; border-radius: var(--r); margin-top: 8px; }
/* The chord, named, under the keys: one line of fixed height — the keyboard never hops. */
.chord-read { height: 22px; margin-top: 8px; display: flex; align-items: center; justify-content: center; white-space: nowrap; overflow: hidden; }
/* On the Desk the line borrows the dock's bottom inset instead of growing the
   dock: the widgets above share a fixed height, and a taller dock squeezed the
   tuner's note against its top. */
#dock .chord-read { height: 20px; margin: 2px 0 -27px; }
/* Theory's and the Tuner's keys end where the Desk's do (measured on the phone,
   round 94: 831 of 874): their readout takes the Desk's place in the foot. */
#keysRead, #tuneRead { height: 20px; margin: 7px 0 -22px; }   /* 7 under the keys, as the Desk's line sits */
#tuneRead { margin-bottom: -27px; }   /* its card nests differently: measured, the Tuner's keys sat 5 px high otherwise */
#keysRead:has(+ #dockProg:not([hidden])) { margin-bottom: 0; }   /* a progression strip below: the line keeps its room */
.chord-read b { font-family: var(--num); font-size: 15px; font-weight: 600; color: var(--accent); }
.chord-read.empty b { color: var(--text3); font-weight: 500; }
.groove-key { margin: 8px 0 0; }
/* Played · Words · Analysis in one row; the chosen one opens under it. */
.take-pages { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.take-pages .lane-of { margin-left: auto; }
.lane-block { margin-top: 10px; }
.mark-head { margin-top: 8px; }
/* The tuner page's reading row: note · interval · degree, in fixed columns. */
/* The note on the left, the interval on the right, nothing centred between
   them: a wider name no longer shoves the degree about. */
.tune-read { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; column-gap: 14px; align-items: center; margin-top: 10px; min-height: 64px; }
.tune-read .nr-mid { text-align: right; min-width: 0; }
.tune-read .nr-ivname { font-size: 15px; font-weight: 500; }
.tune-read .nr-sub { font-size: 12px; color: var(--text3); margin-top: 2px; }
.tune-read .nr-right { display: flex; flex-direction: column; align-items: flex-end; line-height: 1; }
.tune-read .nr-degree { font-family: var(--num); font-size: 30px; font-weight: 600; }
.tune-read .nr-degree.out { color: var(--text3); }
.tune-read .nr-short { font-family: var(--num); font-size: 12px; color: var(--accent); margin-top: 3px; }
.strobe-row.slab { height: 30px; border-radius: 0 0 var(--r) var(--r); }
.drum-hero { display: flex; align-items: baseline; justify-content: center; gap: 8px; margin-top: 6px; }
.drum-hero .note-name { font-size: 44px; }
.drum-ring { display: block; width: 100%; height: 230px; margin-top: 8px; }
.w-hero.idle .note-name { font-size: 26px; color: var(--text3); font-weight: 500; }
.w-body > .strobe-row, .w-body > .pc-strip, .w-body > .beat-row,
.w-body > .seg, .w-body > .w-foot, .w-body > .scope-holder { width: 100%; }
.w-hero { display: flex; align-items: baseline; gap: 4px; line-height: 1; }
.w-hero .note-name { font-size: 44px; }
.w-hero .note-oct { font-size: 17px; }
.w-hero.small { font-family: var(--num); font-size: 15px; color: var(--accent); }
.w-unit { font-size: 11px; letter-spacing: .12em; color: var(--text3); }
.w-sub { font-size: 12px; color: var(--text3); font-family: var(--num); text-align: center; }
.w-sub.good { color: var(--good); }
.w-foot { font-size: 12px; color: var(--text3); font-family: var(--num); text-align: center;
  min-height: 24px; display: flex; align-items: center; justify-content: center; gap: 8px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.foot-row .mini-sel { min-height: 24px; padding: 0 6px; }
.scope-holder { flex: 1; min-height: 28px; display: flex; }
.scope-holder canvas { width: 100%; height: 100%; display: block; border-radius: var(--r); }
.widget .beat { height: 28px; font-size: 12px; border-radius: 100px; }
.widget .beat-row { gap: 3px; }
.metro-row { display: flex; align-items: center; justify-content: center; gap: 10px; }
.listen-row { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.listen-row .qhelp { margin-left: 0; }
.mic-chip { min-width: 64px; gap: 4px; justify-content: center; }
.prep.source { min-width: 64px; color: var(--text); }
.prep.source.on { color: var(--accent); }
.mic-chip svg { width: 18px; height: 18px; }
.mic-chip span { font-family: var(--num); font-size: 13px; }
.mic-chip.on { color: var(--text); background: color-mix(in srgb, var(--accent) 18%, var(--bg3)); }
.mic-chip.on svg { stroke: var(--accent); }
#recLoop.on { background: color-mix(in srgb, var(--accent) 28%, var(--bg3)); color: var(--text); }
#recLoop.on svg { stroke: var(--accent); }
#recLoopOff { min-width: 30px; padding: 0 4px; margin-left: -4px; color: var(--text3); }
/* Played notes in the marks list are the event track, not marks: quieter, named. */
.mk.played .mk-who { margin-left: auto; font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); }
.route-line { margin: 6px 0 0; text-transform: none; letter-spacing: 0; font-size: 11px; }
.route-line[hidden] { display: none; }
#alignRow { margin-top: 8px; }
#alignBtn { text-transform: none; font-family: inherit; font-weight: 600; font-size: 12px; }
#alignBtn.on { color: var(--good); }
#alignInfo { text-transform: none; letter-spacing: 0; font-size: 11px; }
.mic-chip[hidden] { display: none; }
.room-row { margin-top: 8px; }
.seg.tiny { padding: 2px; }
.seg.tiny button { padding: 3px 9px; font-size: 12px; }
.seg.fill { display: flex; width: 100%; }
.seg.fill button { flex: 1; text-align: center; }
.widget .strobe-row { height: 18px; }

/* ── dock: keys, key, tempo, mic, setup ────────────────── */
.dock {
  width: 100%; max-width: 880px; flex-shrink: 0;
  background: var(--dock-bg);
  border-top: none;
  padding: 9px 12px calc(9px + var(--inset-bottom));
  display: flex; flex-direction: column; gap: 8px;
}
body.detail .dock { display: none; }
/* The recorder can call the keys up: the bench's dock, without its key bar, so
   a loop can be played from the page it is kept on. */
body.detail.keys-up .dock { display: flex; }
body.detail.keys-up .dock .key-bar { display: none; }
/* On Records the dock is always up, as the pedal's row at the foot of the page:
   ● ■ ✓ (a wide ●, so the closing tap does not miss). With the keys down, the
   row holds only the pedal; with them up, the octave stepper and Hold join it
   and the chords and keys hang right under. Sound would leave the page for
   the Keys tab, so it never shows here. */
.dock-pedal { display: none; align-items: center; gap: 6px; }
body.detail.on-notes .dock { display: flex; }
body.detail.on-notes .dock .key-bar, body.detail.on-notes #bSound { display: none; }
body.detail.on-notes .dock-pedal { display: flex; }
body.detail.on-notes:not(.keys-up) .dock .dock-chords, body.detail.on-notes:not(.keys-up) .dock .dock-keys,
body.detail.on-notes:not(.keys-up) .oct-step, body.detail.on-notes:not(.keys-up) #bHold, body.detail.on-notes:not(.keys-up) #bBass { display: none; }
body.detail.on-notes:not(.keys-up) .dock-pedal { margin-left: auto; }   /* keys down with a loop running: the pedal alone, at the right (■ ✓ live here) */
/* Keys down: no dock at all — the pedal stands in the Recorder card, over
   Loop · Count-in · Mark (see .rec-slot). Keys up: it moves to the dock, over the chords. */
body.detail.on-notes:not(.keys-up) .dock { display: none; }
.rec-slot { display: flex; margin-bottom: 10px; }
.rec-slot:empty { display: none; }
.rec-slot .dock-pedal { display: flex; width: 100%; gap: 8px; }
.rec-slot #recToggle { flex: 1; width: auto; height: 48px; border-radius: 13px; }
.rec-slot #recToggle .rec-dot { width: 18px; height: 18px; }
.rec-slot #recToggle.on .rec-dot { width: 16px; height: 16px; border-radius: 4px; }
.rec-slot .dock-pedal .prep { height: 48px; min-width: 60px; border-radius: 13px; }
/* Keys up: octave hugs the left, Set and Hold hug the right, ● takes the clean middle. */
body.detail.on-notes.keys-up #dockPedal { margin: 0 auto; }
body.detail.on-notes.keys-up #bHold, body.detail.on-notes.keys-up #bBass { margin-left: 0; }
/* Bass stands beside Hold here too (the owner: "the bass note feature is missing on
   the recorder page's keyboard"); the octave's letter gives way so the row fits. */
body.detail.on-notes.keys-up .dock-read { gap: 8px; }
body.detail.on-notes.keys-up #bOctLabel { display: none; }
#dock .dock-pedal #recToggle { width: 64px; height: 40px; border-radius: 12px; }
#dock .dock-pedal .prep { min-width: 40px; height: 40px; padding: 0; }
/* The chords sit on the keys; the row of controls stands clear above them. */
body.detail.on-notes .dock { gap: 4px; }
body.detail.on-notes .dock .dock-read { margin-bottom: 6px; }
body.detail.on-notes .dock .dock-chords { margin: 0 0 2px; }
/* With no dock under it, a page ends at the home indicator: reserve that inset
   and a notch more, so the last row clears the display's rounded corners. */
body.detail main { padding-bottom: calc(9px + var(--inset-bottom)); }
/* On Records the dock is under main and carries the inset itself: main ends short. */
body.detail.on-notes main { padding-bottom: 4px; }
body.detail.on-notes .dock { padding-top: 4px; }
.key-bar { display: flex; align-items: center; gap: 6px; }
.key-name {
  flex: 1; border: none; border-radius: 100px;
  background: var(--bg3);
  color: var(--text); font-family: inherit; font-size: 15px; font-weight: 600;
  padding: 7px 10px; cursor: pointer; text-align: center;
}
.key-name:active { transform: translateY(1px); box-shadow: none; }
.dock-read { display: flex; align-items: center; gap: 8px; min-height: 44px; }
.dock-read.empty .kb-chord, .dock-read.empty .kb-notes, .empty > .kb-chord, .empty > .kb-notes, .empty > .kb-hint { display: none; }
/* Tuner page with the mic off: the readouts have nothing to say yet, so the
   strobe's "tap to listen" is the whole message and the page does not reserve
   a hundred pixels of dashes under the needle. */
#noteTune.mic-off .cents-big, #noteTune.mic-off .note-row { display: none; }
.dock-read .btn { height: 44px; padding: 0 12px 0 16px; font-size: 14px; gap: 2px; }
/* Symbols where words no longer fit the row (round 94): the clef, the pedal mark, the speaker. */
.dock-read .btn.ico-btn { padding: 0 10px; }
.dock-read .btn.ico-btn .ico { width: 20px; height: 20px; fill: currentColor; flex-shrink: 0; }
/* The Desk's theory part (the owner, 2026-11-10): the key bar and the hand's row as one
   toolbar — every capsule 40 px tall, 6 px apart; the row's marks as circles (the clef,
   the fit mark, the lock, the speaker) with Ped. and the octave stepper between; it fits
   375 px with the lock in. The words for the marks live in the tour and the Guide. */
.dock-read { gap: 6px; min-height: 40px; }
.dock-read .btn { height: 40px; padding: 0 12px; }
.dock-read .btn.ico-btn, .dock-read .btn.ped-btn { width: 40px; min-width: 40px; flex: 0 0 40px; padding: 0; justify-content: center; border-radius: 50%; }
/* One stroke set for the marks: 2 px lines, round ends, no fills — the clef, the fit mark, the lock, the speaker. */
.dock-read .btn.ico-btn .ico.line { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.dock-read .btn.ped-btn .ped { font-size: 13px; }
/* The octave stepper as one capsule: − C3 + inside, the marks' height. */
.dock-read .oct-step { gap: 0; flex-shrink: 0; height: 40px; padding: 0 2px; border-radius: 100px; background: var(--bg3); }
#dock .dock-read .oct-step .sq-btn { width: 34px; height: 34px; }
.key-bar .btn { height: 40px; }
.key-bar .key-name { height: 40px; padding: 0 10px; display: inline-flex; align-items: center; justify-content: center; }
/* The lock: the padlock over its word — Triad, Carry, Each — a tap cycles it; filled while it holds (Carry, Each). */
.dock-read .btn.lock-btn .ico.lock { width: 19px; height: 19px; }
.lock-btn .mark { display: none; }   /* the state's glyph: nothing for Triad (the open lock), an arrow for Carry, a dot for Each */
.lock-btn.carry .mark.carry { display: block; }
.lock-btn.each .mark.each { display: block; fill: currentColor; stroke: none; }
.lock-pane .lock-note { margin: 8px 0 0; }
.lock-btn .shackle { transform-origin: 7.5px 11px; transition: transform .15s; }
.lock-btn.free .shackle { transform: translateX(-1.5px) rotate(-24deg); }   /* open: the shackle lifts */
.lock-btn .lock-cap { font-size: 7.5px; letter-spacing: .04em; text-transform: uppercase; font-weight: 700; line-height: 1; }

/* The Tuner's pitch and temperament, as small chips in the Notes head beside Set key. */
#tuneA4, #tuneTemp { height: 28px; padding: 0 9px; font-size: 12px; font-family: var(--num); }
/* ms·Hz keeps its case: units, not a name. */
.tab[data-tab="subdiv"] .tab-name { text-transform: none; letter-spacing: 0; }
/* The key bar's door to Theory, like the four tool rows' doors. */
.key-bar .w-title { flex: 0 0 auto; order: 9; }   /* at the row's end, the side the other doors are on */
/* The lock in the key bar: the same circle as the row's marks, the word under the padlock. */
.key-bar .btn.ico-btn, .key-bar .btn.lock-btn { width: 40px; min-width: 40px; flex: 0 0 40px; padding: 0; justify-content: center; border-radius: 50%; }
.key-bar .btn.lock-btn { flex-direction: column; gap: 1px; }
.key-bar .btn.lock-btn .ico.line { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; width: 15px; height: 15px; }
.key-bar .btn.lock-btn .lock-cap { font-size: 7.5px; letter-spacing: .04em; text-transform: uppercase; font-weight: 700; line-height: 1; }
body.hand-left .key-bar .w-title { order: -1; }
/* Dub, in a word: the red dot and its name. */
.sq-btn.rec.wide { width: auto; padding: 0 13px 0 11px; gap: 6px; border-radius: 100px; }
.sq-btn.rec.wide .rec-word { font-size: 13px; font-weight: 600; font-family: var(--num); }
.ico .line { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.dock-read .btn.ped-btn { padding: 0 11px; }
.ped { font-family: var(--serif); font-style: italic; font-weight: 600; font-size: 15px; letter-spacing: .01em; line-height: 1; }
/* The bench scope's one-button mode walk, and the scope page's grid of views. */
.mode-cycle { width: 100%; justify-content: space-between; padding: 0 8px 0 12px; gap: 4px; }
.mode-cycle .chev { width: 12px; height: 12px; fill: none; stroke: var(--accent); stroke-width: 2.6; }
.scope-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.sg-cell { position: relative; aspect-ratio: 4 / 3; border-radius: var(--r); overflow: hidden; background: var(--canvas-bg); cursor: pointer; }
.sg-cell canvas { width: 100%; height: 100%; display: block; }
.sg-name { position: absolute; left: 8px; bottom: 6px; font-size: 12px; letter-spacing: .07em; text-transform: uppercase; font-weight: 600; color: var(--text2); pointer-events: none; }
.dock-read .btn .chev { width: 12px; height: 12px; fill: none; stroke: var(--accent); stroke-width: 2.6; }
.oct-step { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.oct-step .sq-btn { width: 44px; height: 44px; }
.oct-label { min-width: 30px; text-align: center; font-size: 14px; color: var(--text2); }
.dock-row { display: flex; align-items: center; gap: 8px; }
.tap-btn {
  flex: 1; padding: 9px 10px; border-radius: 100px;
  background: var(--bg3);
  border: none;
  color: var(--text); font-family: inherit; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  transition: background .08s, transform .06s;
}
/* The Metronome's Tap (.tap-square) lights at the press, for a beat's worth, from the page — never from :active, which on iOS comes with the lift. */
.tap-square { touch-action: none; }
.tap-square.hit { background: var(--accent); color: #fff; transform: scale(.97); transition: none; }
.tap-square.hit .tap-read { color: rgba(255,255,255,.85); }
.tap-btn:active, .tap-btn.hit {
  background: var(--accent); border-color: var(--accent); color: #fff;
  transform: translateY(1px); box-shadow: none;
}
.tap-label { font-size: 13px; font-weight: 700; letter-spacing: .18em; }
.tap-read { font-family: var(--num); font-size: 12px; color: var(--text3); }
.tap-btn:active .tap-read, .tap-btn.hit .tap-read { color: rgba(255,255,255,.85); }

/* ── shared display pieces ─────────────────────────────── */
.big-num { font-family: var(--num); font-weight: 600; letter-spacing: -.02em; line-height: 1; font-variant-numeric: tabular-nums; }
.note-name { font-family: var(--num); font-size: 60px; font-weight: 600; line-height: 1; letter-spacing: -.03em; }
.note-name.good { color: var(--good); }
.note-oct { font-family: var(--num); font-size: 22px; font-weight: 500; color: var(--text3); }
.cents-big { font-family: var(--num); font-size: 15px; color: var(--text2); }
.cents-big.good { color: var(--good); }

.strobe-row { position: relative; height: 22px; border-radius: var(--r); overflow: hidden; background: var(--canvas-bg); }
.strobe-row canvas { width: 100%; height: 100%; display: block; }
.strobe { display: flex; flex-direction: column; gap: 5px; }
.strobe-legend { display: flex; justify-content: space-between; font-size: 12px; color: var(--text3); font-family: var(--num); }

.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; padding-top: 12px; border-top: var(--hair); }
.stat-grid > div { display: flex; flex-direction: column; gap: 2px; align-items: center; }
.stat-grid .label { font-size: 11px; }
.stat-grid .val { font-family: var(--num); font-size: 14px; }

.level-pill { width: 54px; height: 4px; background: var(--bg3); border-radius: 2px; overflow: hidden; }
.level-pill > div { height: 100%; width: 0%; background: var(--good); transition: width .06s linear; }
.level-pill > div.hot { background: var(--warn); }
.level-pill > div.clip { background: var(--bad); }

canvas.viz { width: 100%; display: block; background: var(--canvas-bg); border-radius: var(--r2); }
#scopeCanvas { height: 320px; cursor: crosshair; }

.pc-strip { display: flex; gap: 2px; }
.pc-strip div {
  flex: 1; text-align: center; padding: 5px 0; border-radius: 6px;
  font-family: var(--num); font-size: 12px; font-weight: 600; background: transparent; color: var(--text3);
}
.pc-strip div.in { background: var(--bg3); color: var(--text); }
.pc-strip div.tonic { color: var(--accent); }
.pc-strip div.live { background: var(--accent); color: #fff; }

.inkey-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.inkey-degree { font-size: 28px; font-weight: 300; min-width: 38px; text-align: center; font-family: var(--num); }
.inkey-degree.out { color: var(--warn); }
.inkey-text .a { font-size: 13px; display: block; }
.inkey-text .b { font-size: 12px; color: var(--text3); }

/* disclosure */
details.adv { border-top: var(--hair); margin-top: 12px; padding-top: 10px; }
details.adv > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 6px;
  font-size: 12px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text3); font-weight: 600;
}
details.adv > summary::-webkit-details-marker { display: none; }
details.adv > summary::after { content: '›'; margin-left: auto; font-size: 15px; transition: transform .15s; }
details.adv[open] > summary::after { transform: rotate(90deg); }
details.adv .adv-body { padding-top: 12px; }
.adv-note { font-size: 12px; color: var(--text3); line-height: 1.5; margin-bottom: 10px; }

/* ══ strum view: one column per open string, dot above/below the line ══ */
.strum-grid { display: flex; gap: 8px; margin-top: 4px; }
.st-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.st-track { position: relative; width: 100%; max-width: 44px; height: 150px; background: var(--bg2); border-radius: var(--r2); border: var(--hair); overflow: hidden; }
.st-mid { position: absolute; left: 10%; right: 10%; top: 50%; height: 1px; background: var(--text3); opacity: .6; }
.st-dot { position: absolute; left: 50%; top: 50%; width: 12px; height: 12px; border-radius: 50%;
  background: var(--warn, #d9a04d); transform: translate(-50%, -50%); transition: top .09s linear, background .15s; }
.st-name { font-family: var(--num); font-size: 12px; color: var(--text2); }
.st-col.good .st-dot { background: var(--good); }
.st-col.good .st-name { color: var(--good); }
.st-col.idle .st-dot { opacity: 0; }
.st-col.idle .st-track { opacity: .55; }

/* ══ the practice plan: one row per step ══ */
.seq-list { display: flex; flex-direction: column; gap: 6px; }
.seq-row { display: flex; align-items: center; gap: 6px; }
.seq-row .seq-n { font-family: var(--num); font-size: 12px; color: var(--text3); width: 14px; text-align: right; flex-shrink: 0; }
.seq-row select { flex: 0 0 76px; }
.seq-row .sq-bars { min-width: 20px; text-align: center; font-size: 13px; }
.seq-row input[type=number] { width: 62px; margin-left: auto; }
.seq-row .sq-btn.sm { width: 28px; height: 28px; flex-shrink: 0; }
.seq-row .sq-btn.sm:last-child { margin-left: auto; }
.seq-step { display: flex; flex-direction: column; gap: 4px; padding: 6px 0; border-top: var(--hair); }
.seq-step:first-child { border-top: none; padding-top: 0; }
.seq-tempo { padding-left: 20px; flex-wrap: wrap; }
.seq-tempo select { flex: 1 1 120px; min-width: 0; }
.seq-tempo input[type=number] { width: 54px; margin-left: 0; }
.seq-tempo .label { flex-shrink: 0; }

/* The reference keyboard on the tuner page owns its height explicitly. */
.keyboard.ref-keys { height: 126px; }

/* ── scope ─────────────────────────────────────────────── */
.scope-foot { display: flex; align-items: center; margin-top: 8px; gap: 6px; }
.scope-foot .foot-gap { flex: 1; }
/* Five labels and the help dot share one row: the seg gives up .fill's hard
   width so the head never wraps the dot onto an orphan line. */
.scope-modes.fill { width: auto; flex: 1; min-width: 0; }
.scope-modes button { min-width: 0; padding: 6px 2px; font-size: 12px; }
/* Six names never fit a phone-width segment: it becomes a strip that scrolls
   sideways (no bar), each name whole, the active one scrolled into view. */
@media (max-width: 520px) {
  .scope-modes.fill { display: flex; overflow-x: auto; scroll-snap-type: x proximity; scrollbar-width: none; }
  .scope-modes.fill::-webkit-scrollbar { display: none; }
  .scope-modes.fill button { flex: 0 0 auto; padding: 0 11px; scroll-snap-align: center; }
}
/* Live values change width every frame ("—" one moment, "F♯m7♭5" the next);
   a wrapping flex row re-flowed on every change and the whole pane jumped.
   Fixed grid tracks and fixed value heights: readings change, geometry never. */
.detect-row { display: grid; grid-template-columns: 1fr 1.2fr 1.3fr auto; align-items: center; gap: 10px; }
.detect-item { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.detect-val {
  font-size: 19px; font-family: var(--num); min-height: 24px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.detect-val.dim { color: var(--text3); font-size: 13px; min-height: 24px; line-height: 24px; }
.conf { width: 52px; height: 3px; background: var(--bg3); border-radius: 2px; overflow: hidden; }
.conf > div { height: 100%; width: 0%; background: var(--accent); transition: width .2s; }

/* ── keys ──────────────────────────────────────────────── */
.keyboard { position: relative; user-select: none; touch-action: none; background: transparent; border-radius: 0; overflow: hidden; height: 180px; }
.keyboard.mini { height: 104px; }
/* Same class, two contexts: the bench dock is auto-height, so a bare 100% there
   resolves against nothing and the keyboard collapses to a sliver. The bench gets
   a fixed height; inside .inst-stage the stage owns the dimension. */
.keyboard.dock-keys { height: 148px; }
.inst-stage .keyboard.dock-keys { height: 100%; }
.kb-key { position: absolute; top: 0; cursor: pointer; display: flex; align-items: flex-end; justify-content: center; padding-bottom: 8px; font-family: var(--num); font-size: 12px; }
.kb-key.white {
  background: var(--key-white);
  color: #6b6157; height: 100%;
  border-right: 3px solid var(--bg); border-radius: 0 0 10px 10px;
}
.kb-key.black {
  background: var(--key-black);
  color: var(--text3); height: 60%; z-index: 2; border-radius: 0 0 8px 8px;
  border-left: 2px solid var(--bg); border-right: 2px solid var(--bg);
}
/* Latched (press-and-hold): ringing on its own. A ring at the foot says "held". */
.kb-key.latched::before {
  content: ''; position: absolute; left: 50%; bottom: 22px; transform: translateX(-50%);
  width: 8px; height: 8px; border-radius: 50%; border: 2px solid #fff; box-sizing: border-box;
}
.kb-key.black.latched::before { bottom: 12px; }
.kb-key.inkey.white { background: var(--key-white-in); }
.kb-key.inkey.black { background: var(--key-black-in); }
/* In-key flags: a line along the top of every key that is in the key, in its
   degree's colour — the chord chips above carry the same colours — so the key
   reads at a glance. The tonic's is thicker; out-of-key keys have none. Drawn as
   an inset shadow, so the tonic's dot and the held/echo rings keep their
   pseudo-elements. */
.kb-key.inkey:not(.down):not(.heard) { box-shadow: inset 0 3px 0 var(--fam, var(--accent)); }
.kb-key.tonic.inkey:not(.down):not(.heard) { box-shadow: inset 0 5px 0 var(--fam, var(--accent)); }
/* The note heard (the tuner's reading) on the reference keys: lit in the
   in-tune green, so the eye finds the note while the ear finds the pitch. */
.kb-key.heard.white, .kb-key.heard.black { background: var(--good); color: #fff; font-weight: 700; z-index: 1; }
.kb-key.heard.black { z-index: 2; }
.kb-key[data-deg="1"] { --fam: var(--deg1); } .kb-key[data-deg="2"] { --fam: var(--deg2); } .kb-key[data-deg="3"] { --fam: var(--deg3); }
.kb-key[data-deg="4"] { --fam: var(--deg4); } .kb-key[data-deg="5"] { --fam: var(--deg5); } .kb-key[data-deg="6"] { --fam: var(--deg6); }
.kb-key[data-deg="7"] { --fam: var(--deg7); }
/* A pressed key must read from arm's length: filled accent, lit from within,
   glowing past its own edges. The old flat fill vanished against ivory keys. */
.kb-key.down.white, .kb-key.down.black {
  background: var(--accent);
  color: #fff; font-weight: 700;
}
/* A lit white key keeps the shape of a white key: it stays under the black
   keys (which sit at z-index 2), so its glow never swallows them. A lit black
   key rises above its neighbours. */
.kb-key.down.white { z-index: 1; }
.kb-key.down.black { z-index: 3; }
/* Outside the key, as on the neck: a sounding note from outside fills amber; a
   root from outside keeps its violet under an amber edge. The flags along the
   top already say which keys are in the key. */
.kb-key.down.foreign:not(.root) { background: var(--warn); }
.kb-key.down.foreign.root { box-shadow: inset 0 0 0 3px var(--warn); }
.kb-key.echo.foreign.white { background: color-mix(in srgb, var(--warn) 30%, var(--key-white)); }
.kb-key.echo.foreign.black { background: color-mix(in srgb, var(--warn) 40%, var(--key-black)); }
.kb-ld.off { display: none; }   /* a key's dot with nothing to say (the dots are kept, not rebuilt, per press) */
.kb-ld.held.foreign { border-color: var(--warn); }
.kb-ld.root.foreign { box-shadow: 0 0 0 2px var(--warn); }
.kb-ld.echo.foreign { background: color-mix(in srgb, var(--warn) 70%, var(--text3)); }
/* Echo: the chord's pitch classes in every other octave on screen — the
   accent drained of most of its colour, and a small dot. Clearly not a
   pressed key, clearly the same note. */
.kb-key.echo.white { background: color-mix(in srgb, color-mix(in srgb, var(--accent) 45%, var(--text3)) 34%, var(--key-white)); }
.kb-key.echo.black { background: color-mix(in srgb, color-mix(in srgb, var(--accent) 45%, var(--text3)) 45%, var(--key-black)); }
.kb-key.echo::before {
  content: ''; position: absolute; left: 50%; bottom: 22px; transform: translateX(-50%);
  width: 7px; height: 7px; border-radius: 50%; background: color-mix(in srgb, var(--accent) 55%, var(--text3)); opacity: .9;
}
.kb-key.black.echo::before { bottom: 12px; }
/* The tonic has no dot of its own: its flag is the thick one and its key is tinted. */
.kb-read { display: flex; align-items: baseline; gap: 12px; margin-top: 10px; min-height: 26px; flex-wrap: wrap; }
.kb-chord { font-size: 22px; font-family: var(--num); color: var(--accent); }
.kb-notes { font-family: var(--num); font-size: 12px; color: var(--text2); }
.kb-ivs { font-family: var(--num); font-size: 12px; color: var(--text3); }
/* What the chord is doing, in words. The whole point of a theory page is that it
   explains, and an explanation you have to hover for is not one. */
.kb-hint { font-size: 12px; color: var(--text3); margin-left: auto; text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.dock-read { flex-wrap: nowrap; }

.chord-row { display: flex; flex-wrap: wrap; gap: 5px; }
.chord-btn { background: var(--bg3); border: var(--hair); border-radius: 8px; padding: 7px 11px; font-family: var(--num); font-size: 12px; color: var(--text); cursor: pointer; }
.chord-btn.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.dia-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.dia {
  background: linear-gradient(180deg, var(--btn-hi), var(--btn-lo));
  border: var(--hair); border-radius: var(--r2); padding: 11px 2px; text-align: center;
  cursor: pointer; box-shadow: var(--elev-sm);
}
.dia:active { transform: translateY(1px); box-shadow: none; }
.dia.on { background: var(--accent); border-color: var(--accent); }
.dia .r { font-family: var(--num); font-size: 12px; color: var(--text3); }
.dia.on .r, .dia.on .s { color: #fff; }
.dia .s { font-family: var(--num); font-size: 16px; margin-top: 2px; }
.ref-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ref-hz { font-family: var(--num); font-size: 24px; font-weight: 300; }
.ref-quick { display: flex; flex-wrap: wrap; gap: 4px; }
.ref-quick button { background: var(--bg3); border: var(--hair); border-radius: 7px; padding: 5px 9px; font-family: var(--num); font-size: 12px; color: var(--text2); cursor: pointer; }

/* ── time ──────────────────────────────────────────────── */
.bpm-row { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 14px; }
/* At the head of the card: the tempo hugs the left, Tap and Play the right. */
.bpm-row.head { justify-content: flex-start; gap: 6px; margin-top: 0; }
.bpm-row.head .bpm-val { font-size: 44px; min-width: 96px; }
.bpm-row.head .btn.icon { width: 40px; padding: 0; }
.bpm-row.head .tap-square { flex-direction: column; gap: 0; line-height: 1.1; margin-right: 4px; }
.bpm-row.head .tap-read { font-family: var(--num); font-size: 10px; color: var(--text3); font-weight: 500; }
.bpm-val { font-size: 56px; min-width: 132px; text-align: center; cursor: ns-resize; }
.bpm-unit { font-size: 12px; letter-spacing: .12em; color: var(--text3); text-align: center; margin-top: -4px; }
.transport { display: flex; align-items: center; justify-content: center; gap: 12px; margin-top: 10px; }
/* Tap and Play are one gesture pair: same height, same optical weight. */
.transport .btn.round { height: 54px; min-width: 88px; font-size: 14px; }
.transport > div:last-child { display: flex; flex-direction: column; justify-content: center; }
.play-btn {
  width: 52px; height: 52px; border-radius: 50%; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  background: radial-gradient(120% 120% at 30% 22%, color-mix(in srgb, var(--accent) 78%, #fff), var(--accent));
              inset 0 1px 0 rgba(255,255,255,.35);
  transition: transform .07s, box-shadow .07s;
}
.play-btn:active { transform: scale(.97); }
.play-btn svg { width: 21px; height: 21px; fill: #fff; }
.beat-row { display: flex; gap: 4px; margin-top: 10px; }
.beat { flex: 1; height: 40px; border-radius: 100px; cursor: pointer; background: var(--bg3); border: 1px solid transparent; display: flex; align-items: center; justify-content: center; font-family: var(--num); font-size: 12px; color: var(--text3); }
.beat.accent { border-color: var(--accent); color: var(--accent); }
.beat.soft { color: var(--text3); background: transparent; border-color: var(--bg4); }
.beat-row.count-in .beat.on { background: var(--bg4); color: var(--text); }
.beat-row.count-in .beat.on.accent { background: var(--bg4); color: var(--accent); }
/* The prep rail: count-in, timer and click as symbols with a number, and the
   row/ring segment — one rail language (36px, --bg3, 10px radius). Off is dim,
   set is lit, a running timer counts down in green. */
.prep-rail { display: flex; align-items: center; gap: 6px; margin-top: 12px; }
.prep-gap { flex: 1; }
.prep {
  height: 36px; min-width: 44px; padding: 0 10px; border-radius: 10px; border: none;
  background: var(--bg3); color: var(--text3); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  font-family: var(--num); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.prep svg { width: 18px; height: 18px; flex-shrink: 0; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.prep svg .d { fill: currentColor; stroke: none; }
.prep svg .slash { display: none; }
.prep span:empty { display: none; }
.prep.on { color: var(--text); }
.prep.live span { color: var(--good); }
.prep.muted { color: var(--text3); }
.prep.muted svg .slash { display: block; }
.prep:active:not(:disabled) { transform: translateY(1px); }
.prep:disabled { opacity: .35; cursor: default; }
.prep.ghost { background: none; }
/* The pedal's strip under a running loop: the same rail language. */
.loop-strip { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.loop-row { display: flex; align-items: center; gap: 6px; }
.loop-row .label { margin-right: 4px; }
/* ● as the pedal's light: a red circle records, a green triangle plays, an
   orange circle dubs, a grey circle waits. The square is a plain take's stop. */
.sq-btn.rec.play, .sq-btn.rec.dub, .sq-btn.rec.stopped, .sq-btn.rec.on.armed { background: var(--bg3); }
.sq-btn.rec.on.armed .rec-dot, .sq-btn.rec.on.dub .rec-dot, .sq-btn.rec.on.stopped .rec-dot { border-radius: 50%; width: 16px; height: 16px; }
.sq-btn.rec.play .rec-dot { width: 0; height: 0; border-radius: 2px; background: none; margin-left: 4px;
  border-left: 17px solid var(--good); border-top: 10px solid transparent; border-bottom: 10px solid transparent; }
.sq-btn.rec.dub { background: color-mix(in srgb, var(--warn) 24%, var(--bg3)); }
.sq-btn.rec.dub .rec-dot { background: var(--warn); animation: rec-blink 1.1s ease-in-out infinite; }
.sq-btn.rec.stopped .rec-dot { background: var(--text3); }
.loop-strip .seg.tiny button { min-width: 36px; }
#loopBounce.on { color: var(--accent); }
#trimBtn.arm, #trackSnap.arm { background: var(--bad); color: #fff; }
.prep-rail .seg.tiny { padding: 2px; border-radius: 10px; }
.prep-rail .seg.tiny button { border-radius: 8px; min-height: 32px; padding: 0 9px; display: inline-flex; align-items: center; }
.seg.icons svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; }
.seg.icons svg .d { fill: currentColor; stroke: none; }
.beat-lanes { display: block; width: 100%; height: 18px; margin-top: 6px; }
.groove-bols { font-family: var(--display); font-size: 14px; color: var(--text2); margin-top: 10px; line-height: 1.4; }
.ggrid { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.ggrid-row { display: flex; align-items: center; gap: 8px; }
.ggrid-name { width: 52px; flex-shrink: 0; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); font-weight: 600; }
.ggrid-cells { flex: 1; display: grid; gap: 2px; }
.gcell { height: 18px; border-radius: 4px; background: var(--bg3); }
.gcell.beat { margin-left: 4px; }
.gcell.hit { background: var(--text3); }
.gcell.acc { background: var(--text2); }
.gcell.now { box-shadow: inset 0 0 0 1.5px var(--accent); }
.gcell.now.hit, .gcell.now.acc { background: var(--accent); }
.poly-ratio { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; flex-basis: 100%; }
/* A count you set by steps: − n +, one rail. */
.ratio-step { display: inline-flex; align-items: center; height: 36px; border-radius: 10px; background: var(--bg3); padding: 2px; }
.ratio-step button { width: 34px; height: 32px; border: none; border-radius: 8px; background: none; color: var(--text2); font-size: 18px; cursor: pointer; }
.ratio-step button:active { background: var(--bg4); }
.ratio-step span { min-width: 22px; text-align: center; font-family: var(--num); font-size: 17px; font-weight: 600; color: var(--text); }
/* Ticks to a beat: a row of numbers across the layer. */
.count-seg { flex-basis: 100%; display: flex; }
.count-seg button { flex: 1; font-family: var(--num); font-weight: 600; }
.groove-pattern { font-family: var(--num); font-size: 12px; white-space: pre; color: var(--text2); line-height: 1.5; margin-top: 10px; overflow-x: auto; letter-spacing: .06em; }
.pane-section { border-top: var(--hair); margin-top: 12px; padding-top: 10px; }
.section-head { display: flex; align-items: center; gap: 10px; }
.beat-lanes[hidden] { display: none; }
.beat-ring { display: block; width: 100%; height: 240px; margin-top: 12px; border-radius: var(--r); background: var(--canvas-bg); }
.beat-ring[hidden] { display: none; }
.sq-btn.rec.armed .rec-dot { animation: rec-arm .5s ease-in-out infinite alternate; }
@keyframes rec-arm { from { opacity: .35; } to { opacity: 1; } }
.beat.mute { opacity: .32; }
.beat.on { background: var(--text2); color: var(--bg); }
.beat.on.accent { background: var(--accent); color: #fff; }
.layer { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-top: var(--hair); flex-wrap: wrap; }
.layer select { min-width: 0; }
.layer-name { width: 76px; font-size: 12px; font-weight: 500; }
.layer-name small { display: block; color: var(--text3); font-size: 12px; font-weight: 400; }
.toggle { width: 40px; height: 24px; border-radius: 100px; background: var(--bg4); border: none; cursor: pointer; position: relative; flex-shrink: 0; }
.toggle::after { content: ''; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 50%; background: #fff; transition: transform .15s; }
.toggle.on { background: var(--good); }
.toggle.on::after { transform: translateX(16px); }
.layer input[type=range] { flex: 1; min-width: 50px; }
.tempo-table { width: 100%; border-collapse: collapse; font-family: var(--num); font-size: 12px; }
.tempo-table th { font-size: 11px; letter-spacing: .07em; text-transform: uppercase; color: var(--text3); font-weight: 600; padding: 5px 6px; text-align: right; border-bottom: var(--hair); }
.tempo-table th:first-child, .tempo-table td:first-child { text-align: left; }
.tempo-table td { padding: 5px 6px; text-align: right; border-bottom: 1px solid var(--bg2); }
.tempo-table td:first-child { color: var(--accent); }
.tempo-table td.d { color: var(--text3); }

/* ── notes ─────────────────────────────────────────────── */
.cap-row { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
.cap-row > div:first-child { min-width: 0; flex: 1; }
.cap-row .rec-time { white-space: nowrap; }
.cap-row .label { white-space: nowrap; }
.cap-row .prep { min-width: 40px; padding: 0 8px; }
.cap-row .btn.round { padding: 0 14px; min-height: 40px; }
.rec-btn { width: 52px; height: 52px; border-radius: 50%; flex-shrink: 0; background: var(--bad); border: 3px solid var(--bg3); cursor: pointer; transition: border-radius .15s; }
.rec-btn.on { border-radius: 12px; }
.rec-btn:disabled { opacity: .35; cursor: default; }
/* The recorder's hero speaks as the bench's does — the rounded face, bold, big. */
.rec-time { font-family: var(--num); font-size: 40px; }
#liveWave, #detailWave { height: 88px; }
#detailWave { height: 110px; cursor: pointer; touch-action: none; }
.detail-name { cursor: text; }
.detail-name input.rename { font: inherit; width: 100%; min-width: 160px; background: var(--bg3); border: none; border-radius: 8px; padding: 2px 8px; color: var(--text); }
/* The tape's rails: one rail language (36px, --bg3, 10px radius), the play
   and dub circles a touch larger. The chosen lane's row uses the same pills. */
/* The slab: a column of lane buttons on the left, one per lane and the
   lane's height, then the waves. The buttons choose; the wave places. */
.viz-wrap.slab { display: flex; align-items: stretch; margin-top: 10px; }
.viz-wrap.slab > canvas { flex: 1; min-width: 0; border-radius: 0; }
.lane-tabs { display: flex; flex-direction: column; width: 38px; flex-shrink: 0; background: var(--bg3); z-index: 2; }
.lane-tab { flex: 0 0 auto; }
.lane-tab.small { font-size: 11px; background: color-mix(in srgb, var(--good) 10%, var(--bg3)); }
.lane-tab.layer { color: var(--text2); }
.lane-tabs[hidden] { display: none; }
.lane-tab {
  flex: 1; min-height: 0; border: none; border-bottom: 1px solid var(--bg); border-radius: 0; padding: 0; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  background: transparent; color: var(--text3); font-family: var(--num); font-size: 13px; font-weight: 600;
}
.lane-tab:last-child { border-bottom: none; }
.lane-tab.on { background: var(--accent); color: #fff; }
.lane-tab.beat { color: var(--good); }
.lane-tab.beat.on { color: #fff; }
.lane-tab.muted { opacity: .45; }
.lane-tab.rec { color: var(--bad); }
.lane-tab.rec.on { background: color-mix(in srgb, var(--bad) 70%, var(--accent)); color: #fff; }
.lane-tab .lt-s { font-size: 9px; font-weight: 600; letter-spacing: .04em; opacity: .85; }
.lane-tab .lt-s:empty { display: none; }
/* The take's head: three small marks on the left, the name, Dub and Play at the right. */
.tape-head { flex-wrap: nowrap; gap: 6px; margin-bottom: 0; }
.tape-head .detail-name, .view.zoned .tape-head .detail-name { flex: 0 1 auto; text-align: left; font-size: 17px; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--text); font-family: var(--num); }
.tape-rail { flex-wrap: nowrap; gap: 5px; }
.tape-rail .prep-gap { flex: 1 1 0; min-width: 0; }
.tape-rail .prep { min-width: 40px; padding: 0 8px; }
.tape-rail .sq-btn { width: 40px; height: 40px; }
.tape-rail.tight .qhelp { width: 30px; height: 30px; flex-shrink: 0; }
.tape-head .prep-gap { flex: 1; }
.tape-head .sq-btn.rec, .tape-head .sq-btn.accent { width: 40px; height: 40px; flex-shrink: 0; }
.tape-head .prep.sm { background: var(--bg3); }
.tape-head .prep.sm.ghost { background: none; margin-left: -4px; }
.btn.sm.arm { background: var(--bad); border-color: var(--bad); color: #fff; }
.prep.sm { min-width: 30px; width: 30px; height: 30px; padding: 0; border-radius: 8px; }
.prep.sm svg { width: 16px; height: 16px; }
.prep.arm { background: var(--bad); color: #fff; }
.lane-of { font-weight: 400; color: var(--text3); margin-left: 6px; }
.lane-of:empty { display: none; }
.prep.armed svg { animation: rec-arm .5s ease-in-out infinite alternate; }
.sq-btn.rec.armed { animation: none; }
.tape-rail { display: flex; align-items: center; gap: 6px; margin-top: 10px; }
.tape-rail .sq-btn { width: 40px; height: 40px; flex-shrink: 0; }
.tape-rail .sq-btn.rec.on .rec-dot { animation: rec-arm .5s ease-in-out infinite alternate; }
.meter-chip { font-size: 11px; padding: 0 8px; white-space: nowrap; }
#waveZoom { padding: 0 6px; min-width: 40px; gap: 2px; font-size: 12px; }
#waveZoom svg { width: 16px; height: 16px; }
#speedSeg button { padding: 0 8px; }
.tape-time { min-width: 50px; font-size: 13px; color: var(--text2); }
.tape-rail .seg.tiny { padding: 2px; border-radius: 10px; }
.tape-rail .seg.tiny button { border-radius: 8px; min-height: 32px; padding: 0 10px; display: inline-flex; align-items: center; font-family: var(--num); font-weight: 600; }
.tape-rail .seg.tiny button.on { background: var(--text); color: var(--bg); }
.tape-rail .seg.tiny button:disabled { opacity: .35; }
/* The lane's strip: one block, a head line and a row of knobs. */
.lane-strip { margin-top: 10px; padding: 10px 12px 8px; background: var(--bg2); border-radius: var(--r2); }
.lane-head { display: flex; align-items: center; gap: 6px; }
.lane-head .tr-name { flex: 0 1 auto; min-width: 0; margin-right: 6px; font-size: 13px; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lane-head .prep.sm { background: var(--bg3); }
.lane-head .prep.on { background: var(--text); color: var(--bg); }
.lane-head .room-sel { height: 30px; border-radius: 8px; font-size: 12px; padding: 0 8px; }
.lane-head .tr-name { cursor: text; }
.lane-head .tr-name input, .mix-name input { font: inherit; width: 100%; min-width: 80px; background: var(--bg3); border: none; border-radius: 8px; padding: 2px 8px; color: var(--text); }
.prep.del { text-transform: none; font-family: inherit; font-weight: 600; font-size: 12px; }
/* The mixer: strips across, scrolling sideways; one column of labels on the
   left stays put; every row the same height so the labels line up. */
.mixer { display: flex; gap: 4px; margin-top: 10px; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; padding-bottom: 4px; }
.mixer::-webkit-scrollbar { display: none; }
.mix-labels { position: sticky; left: 0; z-index: 1; flex: 0 0 44px; display: flex; flex-direction: column; gap: 4px; padding: 6px 0; background: var(--card-bg); }
.mix-labels span { height: 44px; display: flex; align-items: center; font-size: 9px; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); font-weight: 600; }
.mix-labels span.head { height: 28px; }
.mix-labels span.row-btn { height: 22px; }
.mix-strip { flex: 0 0 52px; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 6px 2px; background: var(--bg2); border-radius: 10px; border: 1.5px solid transparent; }
.mix-strip.on { border-color: var(--accent); }
.mix-strip.click { background: color-mix(in srgb, var(--good) 8%, var(--bg2)); }
.mix-strip.muted .knob { opacity: .45; }
.mix-name { width: 100%; height: 28px; border: none; border-radius: 7px; background: var(--bg3); color: var(--text2); font-family: var(--num); font-size: 12px; font-weight: 600; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 3px; }
.mix-strip.on .mix-name { background: var(--accent); color: #fff; }
.mix-strip.click .mix-name { color: var(--good); }
.mix-strip .prep { min-width: 0; width: 40px; height: 22px; padding: 0; border-radius: 6px; font-size: 11px; background: var(--bg3); }
.mix-strip .prep svg { width: 14px; height: 14px; }
.mix-strip .prep.arm { background: var(--bad); color: #fff; }
.mix-strip .prep svg { width: 11px; height: 11px; }
.mix-strip .prep.on { background: var(--text); color: var(--bg); }
.knob.mini { width: 48px; height: 44px; gap: 1px; justify-content: flex-start; }
.knob.mini .knob-name { display: none; }
.knob.mini .knob-dial { width: 30px; height: 30px; }
.knob.mini .knob-dial::before { inset: 4px; }
.knob.mini .knob-mark { height: 9px; margin: -12px 0 0 -1px; transform-origin: 1px 12px; }
.knob.mini .knob-val { font-size: 10px; min-height: 12px; }
.knob.mini .knob-name { font-size: 9px; }
.knob.mini.level .knob-dial { width: 32px; height: 32px; }
.knob.mini.level .knob-dial::before { inset: 4px; }
.knob.mini.level .knob-mark { height: 10px; margin: -13px 0 0 -1px; transform-origin: 1px 13px; }
/* Knobs: a dial each, the value under it, the name under that. */
.knob-row { display: flex; align-items: flex-end; gap: 6px; margin-top: 10px; }
.knob-row.five { justify-content: space-between; margin-top: 8px; }
.knob-row.five .knob { flex: 1; width: auto; }
.knob { display: flex; flex-direction: column; align-items: center; gap: 2px; width: 56px; flex-shrink: 0; cursor: ns-resize; user-select: none; -webkit-user-select: none; touch-action: none; }
.knob-dial {
  --deg: -135deg; --lo: 0deg; --hi: 0deg;
  position: relative; width: 40px; height: 40px; border-radius: 50%;
  background:
    conic-gradient(from 225deg, transparent var(--lo), var(--accent) var(--lo), var(--accent) var(--hi), transparent var(--hi)),
    conic-gradient(from 225deg, var(--bg4) 0 270deg, transparent 270deg);
}
.knob-dial::before { content: ''; position: absolute; inset: 5px; border-radius: 50%; background: var(--bg3); }
.knob-mark { position: absolute; left: 50%; top: 50%; width: 2px; height: 13px; margin: -16px 0 0 -1px; border-radius: 1px; background: var(--text); transform-origin: 1px 16px; transform: rotate(var(--deg)); }
.knob-val { font-family: var(--num); font-size: 11px; color: var(--text2); min-height: 13px; }
.knob-name { font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); font-weight: 600; }
#detailPitch { height: 130px; }
/* One row of tags that scrolls sideways; + adds your own at the end. */
.tag-row { display: flex; gap: 5px; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; padding-bottom: 2px; }
.tag-row::-webkit-scrollbar { display: none; }
/* Tags are hashtags, not pills — the pill is spent elsewhere in this design.
   Quiet text; the ones on the take in the accent, bolder. */
.tag { background: none; border: none; border-radius: 6px; padding: 6px 5px; font-size: 13px; color: var(--text3); font-weight: 500; cursor: pointer; white-space: nowrap; flex-shrink: 0; user-select: none; -webkit-user-select: none; }
.tag.add { color: var(--text3); font-weight: 600; min-width: 28px; text-align: center; }
.tag.edit { padding: 0 5px; display: inline-flex; align-items: center; color: var(--text3); }
.tag.edit::before { content: '#'; }
.tag.edit input { font: inherit; width: 84px; background: none; border: none; padding: 6px 2px; color: var(--text); outline: none; }
.tag.on { color: var(--accent); font-weight: 700; }
.lib { display: flex; flex-direction: column; gap: 5px; max-height: 236px; overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
.lib-day { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; font-weight: 600; color: var(--text3); padding: 8px 2px 2px; }
.lib-day:first-child { padding-top: 0; }
.lib-wave { width: 56px; height: 26px; flex-shrink: 0; border-radius: 6px; background: var(--canvas-bg); }
.mark-head { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.mark-head .seg.tiny { padding: 2px; border-radius: 10px; }
.mark-head .seg.tiny button { border-radius: 8px; min-height: 28px; padding: 0 8px; display: inline-flex; align-items: center; }
.mark-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 4px; margin-top: 8px; }
.mark-chip {
  height: 30px; border-radius: 8px; min-width: 0; padding: 0 5px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg3); border-left: 2px solid var(--warn); color: var(--text2);
  font-family: var(--num); font-size: 12px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mark-chip.on { background: var(--warn); color: var(--bg); }
.transcript { font-size: 13px; line-height: 1.6; color: var(--text2); white-space: pre-wrap; user-select: text; -webkit-user-select: text; }
.mark-read { display: flex; align-items: center; gap: 10px; margin-top: 8px; min-height: 36px; }
.mark-name { flex: 1; min-width: 0; font-size: 13px; cursor: text; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mark-name input { font: inherit; width: 100%; background: var(--bg3); border: none; border-radius: 8px; padding: 4px 8px; color: var(--text); }
.detail-name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card-head > #detailRename { width: 28px; height: 28px; font-size: 13px; }
.lib-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; background: var(--bg2); border-radius: var(--r2); cursor: pointer; }
.lib-main { flex: 1; min-width: 0; }
.lib-name { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lib-sub { font-family: var(--num); font-size: 12px; color: var(--text3); margin-top: 2px; }
.lib-empty { color: var(--text3); font-size: 12px; text-align: center; padding: 22px; line-height: 1.5; }
.marker-list { display: flex; flex-direction: column; gap: 3px; margin: 10px 0; }
.mk { display: flex; gap: 10px; align-items: center; padding: 7px 10px; background: var(--bg2); border-radius: 8px; cursor: pointer; font-size: 12px; border-left: 2px solid var(--warn); }
.mk-t { font-family: var(--num); font-size: 12px; color: var(--warn); }
.mk.played { border-left-color: var(--accent); }
.mk.played .mk-t { color: var(--accent); }
.mk.played.soft { border-left-color: var(--text3); color: var(--text2); }
.mk.played.soft .mk-t { color: var(--text3); }
.mk-sub { font-family: var(--num); font-size: 12px; color: var(--text3); margin-left: auto; }

.analysis-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 10px; }
.an-item { display: flex; flex-direction: column; gap: 2px; }
.an-val { font-family: var(--num); font-size: 17px; }
.note-list { display: flex; flex-wrap: wrap; gap: 4px; max-height: 132px; overflow-y: auto; }
.note-chip { font-family: var(--num); font-size: 12px; padding: 3px 7px; border-radius: 5px; background: var(--bg3); color: var(--text2); }
.note-chip.off { color: var(--warn); }

.toast { position: fixed; bottom: 76px; left: 50%; z-index: 100; transform: translateX(-50%) translateY(10px); background: var(--bg4); color: var(--text); border-radius: 100px; padding: 9px 18px; font-size: 12px; opacity: 0; pointer-events: none; transition: opacity .15s, transform .15s; max-width: 90vw; text-align: center; }
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* A message at the top instead — where the keys stay in view below it (Key: "play the root"). */
.toast.top { bottom: auto; top: calc(var(--inset-top, env(safe-area-inset-top, 0px)) + 58px); transform: translateX(-50%) translateY(-10px); }
.toast.top.show { transform: translateX(-50%) translateY(0); }

.sheet-list { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; }
.sheet-opt {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  padding: 11px 6px 9px; border: var(--hair); border-radius: var(--r2);
  cursor: pointer; background: var(--bg2); text-align: center;
}
.sheet-opt.on { border-color: var(--accent); background: var(--accent-soft); }
.sheet-opt .sw { width: 100%; height: 34px; border-radius: 7px; border: var(--hair); }
.sheet-opt .nm { font-size: 12px; font-weight: 600; }
.sheet-opt .ds { display: none; }



/* ══ tuner: strobe on top, needle under it, then the words ══ */
.stat-strip {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;
  padding-bottom: 12px; margin-bottom: 12px; border-bottom: var(--hair);
}
.stat-strip > div { display: flex; flex-direction: column; gap: 2px; align-items: center; }
.stat-strip .label { font-size: 11px; }
.stat-strip .val { font-family: var(--num); font-size: 14px; }

/* The fundamental band gets the height; the harmonic bands taper, so the stack
   reads as one instrument with a hierarchy rather than three equal stripes. */
.strobe.tall { gap: 4px; }
.strobe.tall .band1 { height: 46px; }
.strobe.tall .band2 { height: 30px; }
.strobe.tall .band3 { height: 22px; }

.needle { width: 100%; height: 104px; display: block; margin-top: 4px; }
.cents-big { text-align: center; display: block; font-size: 17px; }

.note-row { display: flex; align-items: center; gap: 16px; margin-top: 2px; }
.nr-note { display: flex; align-items: baseline; gap: 4px; }
.nr-iv { flex: 1; min-width: 0; }
.nr-top { display: flex; align-items: baseline; gap: 8px; }
.nr-degree { font-family: var(--num); font-size: 26px; font-weight: 300; }
.nr-degree.out { color: var(--warn); }
.nr-ivname { font-size: 12px; color: var(--text2); }
.nr-sub { font-size: 12px; color: var(--text3); margin-top: 2px; }

.strip-block { margin-top: 8px; display: flex; flex-direction: column; gap: 4px; }
.strip-head { display: flex; justify-content: space-between; align-items: baseline; margin-top: 6px; }
.pc-strip.iv-strip div { font-size: 11px; }
.pc-strip.mini { display: grid; grid-template-columns: repeat(12, 1fr); gap: 2px; width: 100%; }
.pc-strip.mini { gap: 1px; grid-template-columns: repeat(12, minmax(0, 1fr)); }
.pc-strip.mini div { padding: 4px 0; font-size: 11px; font-weight: 500; letter-spacing: -.04em; }

/* ══ metronome: signature, and the widget's compact picker ══ */
.sig-row { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
/* The meter row opens the transport card, so it wears no top space or rule. */
.at-thumb > .sig-row { margin-top: 12px; padding: 0; border-top: none; }
.sig-note { margin-left: auto; text-transform: none; letter-spacing: 0; font-weight: 400; }
.foot-row { display: flex; align-items: center; justify-content: center; gap: 6px; }
.mini-sel {
  padding: 2px 4px; font-size: 12px; font-family: var(--num);
  border-radius: 5px; background: var(--bg3); color: var(--text2); border: none;
  min-height: 30px;
}

/* ══ scope: how hard to push the picture ══ */
.scope-ctl { display: flex; align-items: flex-end; gap: 14px; margin-top: 10px; }
.ctl-slider { flex: 1; min-width: 0; }
.ctl-slider input[type=range] { width: 100%; }
.ctl-slider .slider-label { margin-bottom: 2px; }

/* ══ keys: the primary key, then two big pictures of it ══ */
/* The key bar on Theory and the Tuner, one row like the Desk's: Key, the stepper with the name (2026-11-10). */
.keys-view .key-bar { gap: 6px; }
.key-bar .key-picker { flex: 1; min-width: 0; gap: 6px; }
.key-bar .key-picker .set-key { min-width: 0; padding: 0 14px; height: 40px; }
.tune-key { margin-top: 4px; }
.key-step { flex: 1 1 auto; min-width: 0; display: inline-flex; align-items: center; height: 40px; padding: 0 2px; border-radius: 100px; background: var(--bg3); }
.key-step .sq-btn.ghost.sm { width: 32px; height: 36px; font-size: 16px; color: var(--text2); flex: 0 0 32px; }
.key-step .key-name { flex: 1; min-width: 0; height: 36px; padding: 0 2px; border: none; background: none; color: var(--text); font-family: var(--serif); font-size: 17px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
/* The scale's notes and degrees in the ladder card's lanes, at the top of the scale list. */
.scale-lanes { display: flex; margin: 2px 0 12px; }
.scale-lanes .lc-lane b { font-size: 15px; }
.scale-lanes .lc-lane i { font-size: 11px; color: var(--accent); }
.viz-card {
  border: var(--hair); border-radius: var(--r3); overflow: hidden;
  background: linear-gradient(180deg, var(--card-hi), var(--card-bg)); box-shadow: var(--elev);
}
.viz-head { padding: 9px 9px 0; }
.viz-stage { position: relative; padding: 6px 9px 0; }
.viz-sel { width: 100%; margin-top: 8px; }
.viz-foot {
  font-size: 12px; color: var(--text3); padding: 6px 12px 8px; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.card.tight { padding: 12px; }
.card.tight .card-head { margin-bottom: 10px; }

/* The arpeggiator's position, marked so it reads at a glance. (The chord's
   root is marked in the lane under the keys, as a filled dot.) */
.kb-key.playing.white, .kb-key.playing.black {
  background: linear-gradient(180deg, color-mix(in srgb, var(--good) 72%, #fff), var(--good));
  color: #06170c; font-weight: 700;
  box-shadow: 0 0 16px color-mix(in srgb, var(--good) 60%, transparent),
              inset 0 -4px 8px rgba(0,0,0,.22);
}
.kb-key.playing.white { z-index: 1; }
.kb-key.playing.black { z-index: 3; }


/* ══ key bar: names the key and says there is more behind it ══ */
.key-name { display: flex; flex-direction: column; align-items: center; gap: 1px; line-height: 1.15; }
.kn-main { font-size: 15px; font-weight: 600; }
.kn-go { display: flex; align-items: center; gap: 2px; font-size: 11px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--accent); font-weight: 600; }
.kn-go svg { width: 9px; height: 9px; fill: none; stroke: currentColor; stroke-width: 3; }

/* ══ progression: sixteen bars you can read at a glance ══ */
.prog-grid { display: flex; flex-direction: column; gap: 4px; }
.pr-row { position: relative; height: 40px; }
.pr-bars { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(4, 1fr); gap: 3px; }
.pr-bar {
  position: relative; display: grid; gap: 0;
  grid-auto-flow: column; grid-auto-columns: 1fr;
  background: var(--bg3); border-radius: var(--r); overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--border);
}
.pr-beat { border-left: 1px solid var(--border); }
.pr-beat:first-child { border-left: none; }
.pr-num {
  position: absolute; top: 2px; left: 4px; font-family: var(--num); font-size: 11px;
  font-style: normal; color: var(--text3); z-index: 1;
}
.pr-blocks { position: absolute; inset: 0; pointer-events: none; }
.pr-block {
  position: absolute; top: 4px; bottom: 4px; pointer-events: auto; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: linear-gradient(180deg, var(--btn-hi), var(--btn-lo));
  border: 1px solid var(--border2); border-radius: var(--r);
  box-shadow: var(--elev-sm); overflow: hidden; min-width: 0;
}
.pr-block.cont { border-left-style: dashed; border-top-left-radius: 0; border-bottom-left-radius: 0; }
.pr-block.sel { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.pr-block.on { background: var(--accent); border-color: var(--accent); }
.pr-block.on .pb-label, .pr-block.on .pb-roman { color: #fff; }
.pb-label { font-family: var(--num); font-size: 12px; color: var(--text); line-height: 1.05;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 3px; }
.pb-label.ghost { color: var(--text3); font-style: italic; }
.pb-roman { font-size: 11px; color: var(--text3); line-height: 1.1; }
.pr-hint { color: var(--text3); font-size: 12px; padding: 6px 2px 0; }
.prog-edit {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 8px; padding: 8px; background: var(--bg2); border-radius: var(--r2);
}
.pe-name { font-family: var(--num); font-size: 14px; color: var(--accent); }
.pe-len { font-family: var(--num); font-size: 12px; color: var(--text3); margin-right: auto; }
.prog-edit { flex-wrap: nowrap; }
.prog-key {
  display: flex; align-items: center; gap: 7px; margin-top: 8px;
  padding-top: 8px; border-top: var(--hair);
}
.prog-key .mono { font-size: 14px; color: var(--accent); margin-right: auto; }
.prog-key .sq-btn.sm { width: 30px; height: 30px; }

/* ══ chord palettes: diatonic, borrowed, applied ══ */
.chord-block { margin-top: 12px; }
.chord-block:first-of-type { margin-top: 0; }
/* A fade at the right edge is the only honest way to say "there is more this way"
   on a touch screen with no scrollbar. */
.chip-scroll {
  display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  mask-image: linear-gradient(90deg, #000 0 92%, transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 92%, transparent 100%);
}
.chip-scroll::-webkit-scrollbar { display: none; }
.dia.chip { flex: 0 0 auto; min-width: 62px; padding: 9px 10px; }

/* ══ keyboard: what the progression touches, quietly ══ */
.kb-key.inprog.white { box-shadow: inset 0 -4px 0 color-mix(in srgb, var(--accent) 55%, transparent); }
.kb-key.inprog.black { box-shadow: inset 0 -4px 0 color-mix(in srgb, var(--accent) 65%, transparent); }


/* A disclosure that carries a card's weight: for things that are usually off and
   should cost one line when they are. */
details.card-fold {
  border: var(--hair); border-radius: var(--r3); overflow: hidden;
  background: linear-gradient(180deg, var(--card-hi), var(--card-bg)); box-shadow: var(--elev);
}
details.card-fold > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px;
  padding: 12px; font-size: 12px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text3); font-weight: 600;
}
details.card-fold > summary::-webkit-details-marker { display: none; }
details.card-fold > summary::after { content: '›'; font-size: 16px; transition: transform .15s; }
details.card-fold > summary .toggle { width: 34px; height: 20px; margin-left: 10px; }
details.card-fold > summary .toggle::after { width: 16px; height: 16px; }
details.card-fold > summary .toggle.on { background: var(--accent); }
details.card-fold > summary .toggle.on::after { transform: translateX(14px); }
details.card-fold[open] > summary::after { transform: rotate(90deg); }
details.card-fold > .panel-body { padding: 0 12px 12px; }

/* ══ compact control rows: labels beside the control, not above it ══ */
.ctl-inline { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 12px; }
/* The tempo under the arpeggio: the label stacked over one row — stepper, number, Tap with its reading inside. */
.ctl-inline label { display: flex; align-items: center; gap: 7px; min-width: 0; }
.ctl-inline .label { flex: 0 0 auto; }
.ctl-inline select, .ctl-inline input { flex: 1; min-width: 0; }
.btn-row.compact > .btn { height: 34px; padding: 0 8px; font-size: 12px; }
.prog-edit .sq-btn.sm { width: 30px; height: 30px; }
.prog-edit .btn.sm { padding: 5px 9px; }


/* ══ first run: one calm card, then never again ══ */
.welcome {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: color-mix(in srgb, var(--bg) 74%, transparent);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
}
.welcome-card {
  max-width: 340px; width: 100%; padding: 28px 22px 22px;
  border: var(--hair); border-radius: var(--r3);
  background: linear-gradient(180deg, var(--card-hi), var(--card-bg)); box-shadow: var(--elev);
  display: flex; flex-direction: column; align-items: center; gap: 11px; text-align: center;
}
.welcome-card h1 { font-size: 24px; font-weight: 400; letter-spacing: .01em; color: var(--text2); margin-bottom: 2px; }
.welcome-card h1 b { color: var(--text); font-weight: 700; }
.w-lede { font-size: 13px; color: var(--text); }
.w-body { font-size: 12px; line-height: 1.55; color: var(--text2); }
.w-local { font-size: 12px; line-height: 1.5; color: var(--text3); }
.welcome-actions { display: flex; flex-direction: column; gap: 8px; width: 100%; margin-top: 7px; }
.welcome-actions .btn { width: 100%; display: flex; justify-content: center; padding: 11px; }

/* ══ the tour (ui/tour.js): six sheets in the welcome's glass, one at a time ══ */
.welcome.tour { padding: 14px; align-items: stretch; }
.tour-card { max-width: 440px; width: 100%; margin: auto; padding: 12px 16px 14px; text-align: left; align-items: stretch; gap: 8px; max-height: 100%; }
.tour-top { display: flex; align-items: center; justify-content: space-between; min-height: 28px; }
.tour-dots { display: flex; gap: 7px; }
.tour-dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--text3); opacity: .35; cursor: pointer; transition: opacity .15s, transform .15s; }
.tour-dots i.on { opacity: 1; background: var(--accent); transform: scale(1.3); }
.tour-skip { background: none; border: none; color: var(--text3); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; padding: 6px 0 6px 12px; }
.tour-body { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; -webkit-overflow-scrolling: touch; touch-action: pan-y; }
.tour-brand { font-size: 24px; font-weight: 400; letter-spacing: .01em; color: var(--text2); margin: 0; font-family: var(--serif); }
.tour-brand b { color: var(--text); font-weight: 700; font-family: var(--display); letter-spacing: .01em; }
.tour-brand i { font-style: italic; font-family: var(--serif); font-weight: 400; }
.tour-lede { font-size: 13px; color: var(--text); margin: -4px 0 6px; font-family: var(--serif); }
.tour-eyebrow { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--text3); }
.tour-title { font-family: var(--display); font-size: 18px; margin: -4px 0 0; color: var(--text); }
.tour-fig { margin: 4px 0 2px; padding: 8px; border-radius: 14px; background: var(--bg); }
.tour-dia { display: block; }
.tour-lead { font-size: 13px; line-height: 1.5; color: var(--text); margin: 0; }
.tour-line { font-size: 12px; line-height: 1.5; color: var(--text2); margin: 0; padding-left: 13px; position: relative; }
.tour-line::before { content: ''; position: absolute; left: 0; top: .62em; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
.tour-line b { color: var(--text); font-weight: 600; }
.tour-local { font-size: 12px; line-height: 1.5; color: var(--text3); margin: 2px 0 0; }
.tour-foot { margin-top: 2px; }
.tour-nav { display: flex; gap: 8px; }
.tour-nav .btn { flex: 1; }
.tour-nav[hidden], .tour-foot .btn[hidden] { display: none; }
/* The same sheets in the Guide's card, which is a shade lighter than the page. */
.guide .tour-fig { background: var(--bg3); }
.guide .tour-eyebrow { margin-top: 10px; }
/* The door in the top bar: a ? in a ring, the size of the other icons. */
.tour-btn span { width: 19px; height: 19px; border-radius: 50%; border: 1.6px solid currentColor; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; line-height: 1; }

/* ══ about ══ */
.about-card { display: flex; flex-direction: column; align-items: center; gap: 7px; text-align: center; }
.about-name { font-size: 17px; letter-spacing: .02em; color: var(--text2); }
.about-name b { color: var(--text); }
.about-line { font-size: 12px; color: var(--text2); line-height: 1.5; max-width: 400px; }
.about-line.dim { font-size: 12px; color: var(--text3); }

/* ══ motion: one reward, one transition, both skippable ══ */
/* The bloom is the app's single celebratory moment: hold a note in tune for half a
   second and the name glows once, softly. currentColor keeps it the semantic green
   without inventing a new token. */
@keyframes bloom {
  0%   { text-shadow: 0 0 0 transparent; }
  30%  { text-shadow: 0 0 26px currentColor; }
  100% { text-shadow: 0 0 0 transparent; }
}
.note-name.bloom { animation: bloom 1.3s ease-out; }
@keyframes viewin { from { opacity: 0; transform: translateY(5px); } }
.view.active { animation: viewin .16s ease; }
@media (prefers-reduced-motion: reduce) {
  .view.active, .note-name.bloom { animation: none; }
  .brand-dot { transition: none; }
}


/* ══ harmony grid: twelve columns, position = distance from the tonic ══ */
.degree-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 4px; }
.degree-grid.ruler { margin-bottom: 6px; }
/* The chord rows the other way up (Setup, the owner 2026-11-10): In the key at the bottom, nearest the row
   and the keys; Borrowed above it; the secondary dominants on top; the ruler under it all. */
.keys-view.rows-up #degreeView { display: flex; flex-direction: column; }
.keys-view.rows-up #labSecondary { order: 1; margin-top: 0; }
.keys-view.rows-up #rowSecondary { order: 2; }
.keys-view.rows-up #labBorrowed { order: 3; }
.keys-view.rows-up #rowBorrowed { order: 4; }
.keys-view.rows-up #labDiatonic { order: 5; }
.keys-view.rows-up #rowDiatonic { order: 6; }
.keys-view.rows-up #degreeRuler { order: 7; margin: 8px 0 0; }
.dr {
  text-align: center; font-family: var(--num); font-size: 11px; padding: 3px 0;
  color: var(--text3); border-radius: 4px;
}
.dr.in { background: var(--bg3); color: var(--text2); }
.dr.tonic { background: var(--accent-soft); color: var(--accent); font-weight: 700; }
.dg-col { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.hchip {
  /* min-height, not padding, carries the touch target: the grid is 12 columns
     wide so width is spoken for — height is where a thumb gets its due. */
  border-radius: 8px; padding: 8px 1px 6px; min-height: 50px; text-align: center; cursor: pointer;
  display: flex; flex-direction: column; justify-content: center;
  background: var(--bg3);
  border: 1px solid transparent;
  user-select: none; -webkit-user-select: none; touch-action: none; min-width: 0;
}
.hchip .hr { font-family: var(--num); font-size: 11px; line-height: 1.15; color: var(--text);
  overflow: hidden; white-space: nowrap; }
/* A name that needs more room than its column has grows into the empty column
   beside it — left if that one is free, right if that one is, both if both —
   and clips when neither is (keys.js fitChip). By half the column, not all of
   it (the owner): two chips either side of one empty column — the secondary
   dominants do this all the time — each take their half and meet in the
   middle with the grid's 4px gap between them, instead of lying over each other. */
.hchip.grow-l, .hchip.grow-r, .hchip.grow-lr { position: relative; z-index: 1; }
.hchip.grow-r { width: calc(150% + 2px); }
.hchip.grow-l { width: calc(150% + 2px); margin-left: calc(-50% - 2px); }
.hchip.grow-lr { width: calc(200% + 4px); margin-left: calc(-50% - 2px); }
.hchip .hl { font-size: 11px; color: var(--text3); line-height: 1.2; }
/* A chip turned over wears the inversion as a small figure after the name, as the Desk's chips do:
   raised, or lowered when the chord was turned down (the owner, 2026-11-10). The name's box keeps
   2px of air above and below so the figure is not clipped with the overflow. */
.hchip .hr { padding: 2px 0; margin: -2px 0; }
.hchip .hr[data-inv]:not([data-inv=""])::after { content: attr(data-inv); font-size: 8px; vertical-align: super; margin-left: 1px; opacity: .85; }
.hchip .hr[data-inv]:not([data-inv=""])[data-low="1"]::after { vertical-align: sub; }
/* The root's pitch-class hue, same mapping as the musical scope — chord and trace
   share a colour language. */
/* Tension spectrum, one hue per degree: home is green, the fourth and fifth
   cool blue-green and blue, the mediant pair two yellows, the tense pair two
   reds. Ghost rows wear the same hue dimmed. */
.hchip.deg-1 { --fam: var(--deg1); }
.hchip.deg-2 { --fam: var(--deg2); }
.hchip.deg-3 { --fam: var(--deg3); }
.hchip.deg-4 { --fam: var(--deg4); }
.hchip.deg-5 { --fam: var(--deg5); }
.hchip.deg-6 { --fam: var(--deg6); }
.hchip.deg-7 { --fam: var(--deg7); }
.hchip { border-top: 3px solid var(--fam, var(--accent)); }
/* Outside the key: present and reachable, visibly not home. */
.hchip.ghost { background: transparent; border-color: var(--border2); box-shadow: none; }
.hchip.ghost .hr { color: var(--text2); }
.hchip.ghost { border-top: 3px solid color-mix(in srgb, var(--fam, var(--accent)) 50%, transparent); }
/* Kept (the Each lock): the chip is not sounding, but it is not its triad
   either — a tint of its family says a slide left it somewhere, and the name
   says where. Lit (.on) wins while it sounds. */
.hchip.kept { background: color-mix(in srgb, var(--fam, var(--accent)) 16%, var(--bg3)); border-color: color-mix(in srgb, var(--fam, var(--accent)) 40%, transparent); }
.hchip.ghost.kept { background: color-mix(in srgb, var(--fam, var(--accent)) 10%, transparent); }
.hchip.on {
  background: var(--accent);
  border-color: var(--accent);
}
.hchip.on .hr, .hchip.on .hl { color: #fff; }
.hchip:active { transform: translateY(1px); }
.hrow-label {
  display: flex; align-items: baseline; gap: 8px; margin: 10px 0 4px;
  font-size: 12px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text3); font-weight: 600;
}
/* Grown one way, the chip still says where its root is: the colour bar and the letter stay over the
   root's column; only the name takes the extra room (the owner, 2026-11-10: the chip's size was not
   lining up with its root). Grown both ways it is centred on its column already. */
.hchip.grow-l, .hchip.grow-r { border-top-color: transparent; }
.hchip.grow-l::before, .hchip.grow-r::before { content: ''; position: absolute; top: -3px; height: 3px; width: calc(100% / 1.5); background: var(--fam, var(--accent)); }
.hchip.grow-r::before { left: -1px; border-top-left-radius: 7px; }
.hchip.grow-l::before { right: -1px; border-top-right-radius: 7px; }
.hchip.ghost.grow-l::before, .hchip.ghost.grow-r::before { background: color-mix(in srgb, var(--fam, var(--accent)) 50%, transparent); }
.hchip.grow-r .hl { width: calc((100% + 2px) / 1.5); align-self: flex-start; }
.hchip.grow-l .hl { width: calc((100% + 2px) / 1.5); align-self: flex-end; }
/* …and the name runs from the root's column into the free one, not centred over both. */
.hchip.grow-r .hr { text-align: left; padding-left: 4px; }
.hchip.grow-l .hr { text-align: right; padding-right: 4px; }
.hrow-label span { text-transform: none; letter-spacing: 0; font-weight: 400; font-size: 12px; }

/* ══ instrument dock: one at a time ══ */
/* The instrument row: one rail language for every control — the Keys/Frets/
   Circle segment, the octave rail and the zoom toggle share the same height,
   ground, radius and inner padding, and sit on one baseline. */
.inst-ctl { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.keys-dock .dock-row { gap: 8px; margin-bottom: 10px !important; }
.keys-dock .seg.tiny { padding: 2px; border-radius: 10px; }
.keys-dock .seg.tiny button { min-height: 32px; padding: 0 11px; font-size: 12px; border-radius: 8px; }
.oct-rail { display: inline-flex; align-items: center; background: var(--bg3); border-radius: 10px; padding: 2px; flex-shrink: 0; }
.oct-rail .sq-btn { width: 34px; height: 32px; border: none; background: none; box-shadow: none; border-radius: 8px; font-size: 17px; color: var(--text2); }
.oct-rail .sq-btn:active { background: var(--card-bg); color: var(--text); transform: none; }
.oct-rail .oct-label { min-width: 38px; text-align: center; font-family: var(--num); font-size: 13px; color: var(--text); }
.inst-ctl select { height: 36px; border-radius: 10px; }
.inst-ctl > .sq-btn.ghost.sm { width: 36px; height: 36px; background: var(--bg3); border: none; box-shadow: none; border-radius: 10px; color: var(--text2); }
.inst-stage { height: 152px; }
.inst-stage.tall { height: 212px; }
.inst-stage > * { height: 100%; }
.inst-stage canvas { width: 100%; display: block; }

/* ══ scope palette row ══ */
.pal-label { display: flex; align-items: center; gap: 8px; flex: 1; }
.pal-label select { flex: 1; min-width: 0; }


/* ══ meters: peak, RMS and loudness in one row ══ */
/* Two by two: a label and its value side by side need ~110px; four across left 85. */
/* The meters as one row: a square that fills from the bottom, the label over
   the number. Height carries nothing here; the number is the reading. */
.meter-row { display: flex; align-items: center; gap: 6px; margin-top: 10px; }
.mt { flex: 1 1 0; min-width: 0; display: flex; align-items: center; gap: 7px; }
.mt > span { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.mt .label { font-size: 10px; letter-spacing: .06em; }
.mt .mono { font-size: 13px; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
.mt-box { position: relative; width: 18px; height: 18px; border-radius: 4px; background: var(--bg3); overflow: hidden; flex-shrink: 0; }
.mt-box > b { position: absolute; left: 0; right: 0; bottom: 0; height: 0%; background: var(--good); transition: height .09s linear; }
.mt-box > b.hot { background: var(--warn); }
.mt-box > b.clip { background: var(--bad); }

/* ══ acoustics ══ */
.ac-row { display: flex; align-items: flex-end; gap: 14px; padding: 8px 0; border-top: var(--hair); }
.ac-row:first-of-type { border-top: none; padding-top: 0; }
.ac-in { display: flex; flex-direction: column; gap: 4px; flex: 0 0 108px; }
.ac-in input { width: 100%; }
.ac-out { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ac-out.wide { flex: 1; }
.ac-modes { font-size: 12px; color: var(--text2); line-height: 1.5; overflow-wrap: break-word; white-space: normal; }


/* ══ fold set: three one-line controls that read as one group ══ */
/* ══ tab shelf: several settings groups sharing one row ══
   A card whose head is a row of tabs and whose body is a single pane. Tapping
   the open tab closes it, so the shelf collapses to one row — each tab keeps a
   live value line, so the shut shelf still reads at a glance. */
.card.tabset { padding: 0; overflow: hidden; }
/* On the Time page the shelf sits right above the transport: its tabs are at
   its foot and the open pane unfolds above them, so the tabs never move. */
.view[data-view="time"] .card.tabset { display: flex; flex-direction: column-reverse; }
.view[data-view="time"] .tabpane { border-top: none; border-bottom: var(--hair); }
.view[data-view="time"] .tab.on { box-shadow: inset 0 2px 0 var(--accent); }
.tabbar { display: flex; }
.tabbar .tab {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 10px 4px 9px; background: none; border: none; cursor: pointer;
  font-family: inherit;
}
.tabbar .tab + .tab { border-left: var(--hair); }
.tab-name {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text3);
}
.tab-val {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--num); font-size: 12px; color: var(--text2);
}
/* The Desk's marks on the Time page's tabs; a tab's switch sits under its name, beside the value. */
.tab-name svg.line { width: 15px; height: 15px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.tab-val .toggle.mini { width: 22px; height: 13px; vertical-align: -2px; margin-right: 3px; }
.tab-val .toggle.mini::after { width: 9px; height: 9px; }
.tab-val .toggle.mini.on::after { transform: translateX(9px); }
.tab.on { box-shadow: inset 0 -2px 0 var(--accent); }
.tab.on .tab-name { color: var(--text); }
.tabpane { padding: 12px 14px 14px; border-top: var(--hair); }
.pane-tools { display: flex; align-items: center; justify-content: flex-end; gap: 6px; margin-bottom: 10px; }

/* The arp switch lives inside its tab: a span, since buttons cannot nest. */
.toggle.mini { display: inline-block; width: 28px; height: 16px; }
.toggle.mini::after { width: 12px; height: 12px; }
.toggle.mini.on { background: var(--accent); }
.toggle.mini.on::after { transform: translateX(12px); }

/* The panes' controls are the instrument's own — rails, picks and knobs — not
   a settings form (the owner, 2026-11-10: "in line with the beauty of the
   rest"). A row is one flex line. A pick is a named capsule whose value the
   system's own list changes: the select lies over it, unseen. A continuous
   value is a knob, as on the mixer. The ? ends the first row. */
.pane-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.pane-row + .pane-row, .pane-row + .knob-row { margin-top: 8px; }
.pane-row > .seg { display: flex; min-width: 0; flex-shrink: 0; }
.pane-row > .seg.fill, .pane-row > .pick { flex: 1 1 0; }
.pane-row > .pick.wide { flex: 1.3 1 0; }
#voiceRange { flex: 1.2 1 0; }   /* Octave · Free beside the Inversion pick: the rail needs the larger share */
.pane-row .seg button { flex: 1 1 0; min-width: 0; padding: 0 7px; font-family: var(--num); font-weight: 600; font-size: 13px; min-height: 32px; }
.pane-row .seg.off { opacity: .45; pointer-events: none; }
.pane-row .qhelp { margin-left: auto; }
.pick { position: relative; display: flex; align-items: center; gap: 7px; height: 38px; padding: 0 28px 0 12px; border-radius: 100px; background: var(--bg3); min-width: 0; }
.pick > b { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--num); font-weight: 600; font-size: 13px; color: var(--text); }
.pick::after { content: ''; position: absolute; right: 14px; top: 50%; width: 6px; height: 6px; margin-top: -5px; border: solid var(--text3); border-width: 0 1.5px 1.5px 0; transform: rotate(45deg); }
.pick > select { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; font-size: 16px; margin: 0; border-radius: 100px; }
.pick.off { opacity: .45; pointer-events: none; }
.pane-row .seg-label, .pick .seg-label { font-size: 11px; letter-spacing: .05em; text-transform: uppercase; color: var(--text3); font-weight: 700; flex-shrink: 0; }
.pane-row.knobs { align-items: center; }
.pane-row.knobs .knob-row { flex: 1; margin-top: 0; justify-content: space-evenly; }
.knob-row.four { justify-content: space-evenly; margin-top: 12px; }
.pane-row.tempo .seg-label { padding: 0 4px 0 6px; }
.pane-row.tempo .btn.sm { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.pane-row.tempo .tap-read { font-family: var(--num); font-size: 11px; color: var(--text3); min-width: 24px; text-align: right; }
.pane-row.tempo .tap-read:empty { display: none; }
.btn.hit { background: var(--accent); border-color: var(--accent); color: #fff; transition: none; }

/* ══ dock progression strip ══ */
.dock-prog {
  display: flex; gap: 4px; overflow-x: auto; padding: 6px 0 2px;
  scrollbar-width: none;
  mask-image: linear-gradient(90deg, #000 0 94%, transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 94%, transparent 100%);
}
.dock-prog::-webkit-scrollbar { display: none; }
.dp-chip {
  flex: 0 0 auto; padding: 4px 9px; border-radius: 6px; cursor: pointer;
  background: var(--bg3); border: 1px solid transparent;
  color: var(--text2); font-family: var(--num); font-size: 12px;
}
.dp-chip.on { background: var(--accent); color: #fff; }


/* Hover is a pointer thing. On touch a tapped control would stay lit — so
   every hover rule lives here, behind the capability query. */
/* The web's own lines (the welcome, About): shown only outside the shell. */
.web-only { display: none; }
html:not(.native) .web-only { display: block; }
/* A wide, tall window: the phone view with room to breathe, never a different
   layout — but the thumb pages anchor at the top, and the chord surface hugs
   its row instead of waiting at the foot for a thumb. */
@media (min-width: 700px) and (min-height: 700px) {
  .view.thumb > :first-child { margin-top: 0; }
  .keys-scroll > .card.tight { margin-top: 0; }
}
@media (hover: hover) {
  button, .btn, .seg button, .prep, .toggle, .kb-key, .pad-sec, .lib-row, .qhelp, .tab, .chip, .related, select { cursor: pointer; }
  .icon-btn:hover { color: var(--text); }
  .btn:hover:not(:disabled) { filter: brightness(1.12); }
  .key-name:hover { background: var(--bg4); }
  .btn.go:hover { background: none; text-decoration: underline; }
  .related:hover { background: var(--bg4); border-color: var(--accent); }
  .sq-btn:hover:not(:disabled) { filter: brightness(1.14); }
  .sq-btn.ghost:hover { background: var(--bg3); color: var(--text); }
  .w-title:hover { color: var(--text); }
  .lib-row:hover { background: var(--bg3); }
  .qhelp:hover { color: var(--text); }
}

/* Setup → Feedback: the picture that goes, shown before it does. */
.fb-pic { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.fb-thumb { width: 40px; height: 72px; object-fit: cover; object-position: top; border-radius: 8px; background: var(--bg3); flex-shrink: 0; }

/* ══ pop: a sheet hovering just above the dock — a tap on the row that needs a few
   controls, without leaving the Desk (ui/pop.js). A plate (DESIGN §1c), no border. ══ */
.pop-back { position: fixed; inset: 0; z-index: 149; background: transparent; }
.pop {
  position: fixed; left: 10px; right: 10px; max-width: 420px; margin: 0 auto; z-index: 150;
  background: var(--bg2); border-radius: 20px; padding: 10px 12px 12px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .35);
  opacity: 0; transform: translateY(8px); transition: opacity .15s, transform .15s;
  max-height: 70vh; max-height: calc(100dvh - var(--pop-bottom, 8px) - env(safe-area-inset-top, 0px) - 10px);   /* never under the Dynamic Island: the head stays, the body scrolls */
  display: flex; flex-direction: column;
}
.pop.show { opacity: 1; transform: none; }
.pop-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.pop-title { flex: 1; font-size: 12px; letter-spacing: .07em; text-transform: uppercase; color: var(--text2); font-weight: 600; }
.pop-tools { display: flex; align-items: center; gap: 8px; }
.pop-switch { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; letter-spacing: .05em; text-transform: uppercase; font-weight: 700; color: var(--text3); }   /* a word and its switch in the head: Bass, for the clef's sheet */
.pop-close { width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0; background: var(--bg3); border: var(--hair); color: var(--text3); font-size: 16px; font-weight: 500; line-height: 1; cursor: pointer; }
.pop-body { overflow: auto; min-height: 0; -webkit-overflow-scrolling: touch; }
.pop-body > .tabpane { padding: 4px 0 2px; border-top: none; }
.pop-group + .pop-group { margin-top: 10px; }
.pop-group > .seg-label { display: block; margin: 0 0 6px 4px; font-size: 11px; letter-spacing: .05em; text-transform: uppercase; color: var(--text3); font-weight: 700; }
/* The scale list: rows in two columns, a dot before each, the current one lit — a menu, not pills (the owner, 2026-11-10). */
/* The arp's bar: a mark a tick, hits raised, accents tall and lit, a breath at each beat — drawn where the Rate was while a rhythm is picked. */
.arp-bar { gap: 8px; }
.arp-strip { display: flex; align-items: flex-end; gap: 2px; flex: 1; height: 26px; padding: 0 4px 3px; }
.arp-strip i { flex: 1; height: 6px; border-radius: 2px; background: color-mix(in srgb, var(--text3) 30%, transparent); }
.arp-strip i.hit { height: 14px; background: var(--text2); }
.arp-strip i.acc { height: 20px; background: var(--accent); }
.arp-strip i.beat { margin-left: 4px; }
.pop-list { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 6px; }
.prow { display: flex; align-items: center; gap: 9px; height: 34px; padding: 0 10px; min-width: 0; border: none; border-radius: 9px; background: transparent; color: var(--text); font-size: 14px; text-align: left; white-space: nowrap; cursor: pointer; }
.prow::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: color-mix(in srgb, var(--text3) 45%, transparent); flex-shrink: 0; }
.prow.on { color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); font-weight: 600; }
.prow.on::before { background: var(--accent); }

/* ══ quick help ══ */
.qhelp {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  background: var(--bg3); border: var(--hair); color: var(--text3);
  font-size: 12px; font-weight: 700; cursor: pointer; line-height: 1;
}
/* Setup: the ? beside a setting's name — the explanation one tap away, not
   printed under every row. */
/* The ? leads, so every one sits in the same column; the name follows. */
.setting-name { display: flex; align-items: center; gap: 10px; }
.qhelp.sm { width: 22px; height: 22px; font-size: 11px; margin: 0; display: inline-flex; align-items: center; justify-content: center; }
.slider-label { align-items: center; gap: 10px; }
.slider-label span:first-of-type { flex: 1; }
.lbl-q { display: inline-flex; align-items: center; gap: 8px; }
.reveal[hidden] { display: none; }
#tempNote.reveal { padding-top: 10px; }
.setting-row .help-tip, .slider-row .help-tip { margin: 8px 0 2px; }
/* The guide: one page at a time. Tabs along the top, a row of sub-pages under
   Tools and Theory, Prev and Next at the foot — a book, not a scroll. */
/* The guide fills the screen under the bar (height set by app.js) and never
   scrolls: the body region is cut into sheets that fit it. */
.card.guide { display: flex; flex-direction: column; overflow: hidden; }
.guide-body { flex: 1; min-height: 0; overflow: hidden; }
.guide-where { font-family: var(--num); font-size: 12px; color: var(--text3); align-self: center; }
.guide-tabs { width: 100%; margin-bottom: 10px; flex-shrink: 0; }
.guide-tabs button { flex: 1; }
.guide-sub { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; flex-shrink: 0; }
.guide-sub button { height: 28px; padding: 0 10px; border-radius: 100px; border: var(--hair); background: var(--bg3); color: var(--text2); font-family: inherit; font-size: 12px; font-weight: 600; cursor: pointer; }
.guide-sub button.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.gpage[hidden] { display: none; }
.g-eyebrow { font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--text3); margin: 2px 0 2px; }
.gpage > h3:first-of-type, .g-eyebrow + h3 { margin-top: 0; font-size: 16px; }
.guide-foot { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-top: 10px; padding-top: 10px; border-top: var(--hair); flex-shrink: 0; }
.guide-foot .btn { min-width: 110px; height: 40px; }
.guide-foot .btn[hidden] { display: none; }
.guide-foot #guideNext { margin-left: auto; }
.g-next-hint { margin-top: 10px; }
/* The note: set in the app's serif voice, a letter rather than a manual. */
.gpage.letter h3 { font-family: var(--serif); font-weight: 500; font-size: 20px; letter-spacing: 0; }
.gpage.letter p { font-family: var(--serif); font-size: 14.5px; line-height: 1.7; color: var(--text); max-width: 46ch; }
.sig { font-family: var(--serif); font-style: italic; font-size: 15px; color: var(--text2); margin-top: 12px; }
/* Diagrams, drawn the way the app draws its keys. */
.gfig { margin: 8px 0 12px; }
.gfig .dia { width: 100%; display: block; border-radius: var(--r); background: var(--bg2); padding: 6px; box-sizing: border-box; }
.gfig .dia text { font-family: var(--font); }
.gfig figcaption { font-size: 11.5px; color: var(--text3); margin-top: 5px; line-height: 1.5; }
.guide h3 { scroll-margin-top: 12px; }
.guide h4 { font-size: 12.5px; font-weight: 700; color: var(--text); margin: 16px 0 5px; }
.guide .try { color: var(--text2); padding: 7px 10px; background: var(--bg2); border-radius: var(--r); }
.guide .try b { color: var(--accent); }
.guide a { color: var(--accent); text-decoration: none; border-bottom: 1px solid var(--accent-soft); }
/* Deeper: the exact version with its sources — prose, not the nerd notes' mono. */
.guide details.nerd.more p { font-family: var(--font); font-size: 12.5px; line-height: 1.6; color: var(--text2); }
.guide .qs { list-style: none; padding: 0; margin: 4px 0 8px; }
.guide .qs li { padding: 6px 0; border-top: var(--hair); font-size: 12.5px; line-height: 1.6; color: var(--text2); }
.guide .qs li:first-child { border-top: none; }
.guide .qs b { color: var(--text); }
.help-tip {
  font-size: 12px; line-height: 1.55; color: var(--text2);
  background: var(--bg2); border-left: 2px solid var(--accent);
  border-radius: 0 var(--r) var(--r) 0; padding: 9px 11px; margin-bottom: 10px;
}
.tip-more { color: var(--accent); cursor: pointer; font-weight: 600; white-space: nowrap; display: inline-block; margin-top: 4px; }
.help-tip h4 { font-size: 12px; font-weight: 700; color: var(--text); margin: 6px 0 4px; }
.help-tip h4:first-child { margin-top: 0; }
.help-tip p { margin: 3px 0; }
.help-tip ul, .help-tip ol { margin: 2px 0 6px; padding-left: 18px; }
.help-tip ul.help-list { list-style: none; padding-left: 0; }
.help-tip li { margin: 2px 0; }
.help-tip li b { color: var(--text); font-weight: 600; }
.help-tip ul.help-tree { list-style: none; padding-left: 10px; border-left: 1px solid var(--bg4); margin-left: 4px; }

/* ══ guide ══ */
.guide h3 { font-size: 13px; margin: 16px 0 6px; color: var(--text); }
.guide h3:first-child { margin-top: 0; }
.guide p { font-size: 12.5px; line-height: 1.65; color: var(--text2); margin-bottom: 8px; }
/* Two registers in one text (round 94): one plain line, the moves, then the prose. */
.guide .g-one { color: var(--text); font-size: 13px; }
.guide .g-one b { color: var(--accent); }
.guide .g-head { margin: 12px 0 4px; }
.guide .g-do { padding-left: 20px; margin: 0 0 8px; }
.guide .g-do li { font-size: 12.5px; line-height: 1.6; color: var(--text2); margin: 0 0 4px; }
.guide .g-do li b, .guide .qs li b { color: var(--text); }
.guide b { color: var(--text); }
/* The nerd layer: hidden until asked for, denser when open. */
.guide details.nerd { margin: 2px 0 14px; border-left: 2px solid var(--accent-soft); }
.guide details.nerd > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; letter-spacing: .08em; text-transform: uppercase; font-weight: 700;
  color: var(--accent); padding: 2px 0 2px 10px;
}
.guide details.nerd > summary::-webkit-details-marker { display: none; }
.guide details.nerd > summary::after { content: '+'; font-size: 13px; }
.guide details.nerd[open] > summary::after { content: '−'; }
.guide details.nerd p {
  font-size: 12px; line-height: 1.6; color: var(--text3);
  padding: 4px 0 2px 10px; margin: 0; font-family: var(--mono); font-variant-numeric: tabular-nums;
}

/* ══ overlay sheet (custom tuning) ══ */
.overlay {
  position: fixed; inset: 0; z-index: 150;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: color-mix(in srgb, var(--bg) 70%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}
.overlay-card {
  width: 100%; max-width: 320px; padding: 16px;
  border: var(--hair); border-radius: var(--r3);
  background: linear-gradient(180deg, var(--card-hi), var(--card-bg)); box-shadow: var(--elev);
}
.tune-strings { display: flex; flex-direction: column; gap: 5px; margin-bottom: 10px; }
.tune-row { display: flex; align-items: center; gap: 8px; }
.tune-row .label { flex: 1; }
.ts-note { min-width: 40px; text-align: center; font-size: 14px; color: var(--accent); }
.ts-iv { min-width: 34px; text-align: right; font-size: 12px; color: var(--text2); }
.tune-all { margin: 2px 0 10px; padding-top: 7px; border-top: 1px solid var(--border); }

@media (max-width: 400px) {
  .note-name { font-size: 54px; }
  .bpm-val { font-size: 48px; min-width: 112px; }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .circle-canvas { height: 208px; }
}

.sheet-opt .sw[data-swatch="night"] { background: linear-gradient(135deg, #000 0 48%, #8f7bf2 48% 100%); }
.sheet-opt .sw[data-swatch="night-light"] { background: linear-gradient(135deg, #f8f7fb 0 48%, #6a4fe0 48% 100%); }
.sheet-opt .sw[data-swatch="brut-dark"] { background: linear-gradient(135deg, #131311 0 48%, #e9e5da 48% 74%, #4f6bff 74% 100%); border-radius: 3px; }
.sheet-opt .sw[data-swatch="brut"]  { background: linear-gradient(135deg, #f2efe7 0 48%, #141414 48% 74%, #0000e0 74% 100%); border-radius: 3px; }
.sheet-opt .sw[data-swatch="cyber"] { background: linear-gradient(135deg, #050011 0 48%, #ff2ea6 48% 74%, #00ffa3 74% 100%); border-radius: 2px; }
.sheet-opt .sw[data-swatch="cyber-light"] { background: linear-gradient(135deg, #f9fafc 0 48%, #d4008e 48% 74%, #00aac8 74% 100%); border-radius: 2px; }
.sheet-opt .sw[data-swatch="retro"] { background: linear-gradient(135deg, #050a06 0 48%, #35e969 48% 100%); border-radius: 2px; }
.sheet-opt .sw[data-swatch="retro-light"] { background: linear-gradient(135deg, #f7f1e1 0 48%, #9c2b21 48% 74%, #2a241a 74% 100%); border-radius: 3px; }

/* ══ hardware: things you press are keys, not regions ══
   Every interactive control wears the same three-part bevel: a light catching
   its top edge, a machined lower edge, and the drop it casts on the panel —
   all tokens, so each look decides its own physics (Night's keys sit in soft
   shadow, Brut's and the typewriter's are hard blocks that visibly travel
   when pressed). Pressing removes the drop and moves the key down by exactly
   the drop's height, which is what makes it read as travel instead of a
   colour change. */
/* Screens are the bevel's counterpart: buttons pop out of the panel, displays
   sink into it. One passive overlay per display — the inner shade under the
   top rim (--scr) and a sheen film falling from the top edge (--scr-hi).
   Brut's dialect is machined: a hard shade line, no sheen. */
.strobe-row, .scope-holder, .viz-wrap, .st-track, .cm-track { position: relative; }
.scope-holder { border-radius: var(--r); overflow: hidden; }
.viz-wrap { border-radius: var(--r2); overflow: hidden; }
.strobe-row::after, .scope-holder::after, .viz-wrap::after, .st-track::after, .cm-track::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: var(--scr);
  background: linear-gradient(180deg, var(--scr-hi), transparent 22%);
}

.btn, .sq-btn, .tap-btn {
  box-shadow: inset 0 1px 0 var(--bev-hi), inset 0 -2px 0 var(--bev-lo), var(--bev-drop);
}
.hchip {
  box-shadow: inset 0 1px 0 var(--bev-hi), inset 0 -2px 0 var(--bev-lo), var(--bev-drop);
}
.btn:active:not(:disabled), .sq-btn:active:not(:disabled), .tap-btn:active, .tap-btn.hit, .hchip:active {
  transform: translateY(2px);
  box-shadow: inset 0 1px 0 var(--bev-lo);
}
/* The lit chip (playing) keeps its accent face but still travels. */
/* A selected segment sits proud of its rail — raised, not just tinted. */
.seg button.on {
  box-shadow: inset 0 1px 0 var(--bev-hi), 0 1px 2px var(--bev-lo);
}
/* The toggle's knob is a physical thing: lit on top, resting in its slot. */

/* ══ phone estate ══
   Under 430px every structural space steps down one notch; nothing interactive
   drops below ~44px. Chrome shrinks — padding, gaps, display type — content and
   touch targets do not. The DESIGN.md spacing scale governs the values. */
@media (max-width: 430px) {
  main { padding: 0 9px 9px; }
  body.detail main { padding-bottom: calc(9px + var(--inset-bottom)); }
  /* Zoned pages have no card padding to hold content off the glass's rounded
     edge, so they take back the 16px gutter the chrome gave up (9 + 7). */
  .view.zoned:not(.keys-view), .keys-view.zoned .keys-scroll { padding-left: 7px; padding-right: 7px; }
  .topbar { padding: calc(7px + var(--inset-top)) 10px 7px; }
  .view { gap: 7px; }
  .keys-scroll { gap: 9px; }
  .keys-scroll::after { height: calc(var(--dock-h, 230px) - 6px); }
  .grid2 { gap: 7px; }
  /* Measured on an iPhone 13: each widget body had 174px and the flexible
     displays gave way first — the tuner's strobe collapsed to 0px, the Notes
     wave to 30px. Chrome shrinks here so the displays get their height back. */
  .w-head { min-height: 34px; }
  .w-body { gap: 4px; padding: 6px 8px 7px; }
  .w-hero .note-name { font-size: 36px; }
  .w-block { gap: 3px; }
  .widget .strobe-row { height: 16px; flex-shrink: 0; }
  .widget .cents-meter { transform: scale(.94); transform-origin: center; }
  .widget .scope-holder { min-height: 44px; }
  #dock { gap: 6px; padding-top: 7px; }
  #dock .dock-keys { height: 122px; }
  #dock .dock-read { min-height: 40px; }
  #dock .dock-read .btn, #dock .oct-step .sq-btn { height: 40px; }
  #dock .oct-step .sq-btn { width: 40px; }
  .card, .card.tight { padding: 10px; }
  .card-head { margin-bottom: 8px; gap: 8px; }
  .card-head h2 { font-size: 12px; }
  .tabbar .tab { padding: 4px 3px 3px; }
  .tabpane { padding: 10px 11px 12px; }
  details.card-fold > summary { padding: 10px 11px; }
  details.card-fold > .panel-body { padding: 0 11px 11px; }
  .hrow-label { margin: 5px 0 2px; }
  .scope-modes button { font-size: 12px; }
  .keys-dock { padding-top: 6px; }
  .dock-read { min-height: 18px; }
  .keys-view .chord-head.dock-read { gap: 5px; }   /* Key · Rings and six marks, inside 343 px */
  .keys-view .chord-head.dock-read .seg.tiny button { padding: 3px 8px; }
  .inst-stage { height: 138px; }
  .inst-stage.tall { height: 196px; }
  .keyboard.dock-keys { height: 138px; }
  .adv-note { font-size: 12px; line-height: 1.45; }
  .btn-row.compact > .btn { height: 32px; }
}

/* The key's chords in the dock: one row, coloured by function like the
   Theory grid; a chip sounds while touched (Hold latches it). */
.dock-chords { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 4px; margin: 6px 0 6px; }
.dchip {
  --fam: var(--text3);
  height: 34px; min-width: 0; border: none; border-radius: 10px; padding: 0 2px; cursor: pointer;
  background: var(--bg3); color: var(--text); position: relative; overflow: hidden;
  font-family: var(--num); font-size: 13px; font-weight: 600; white-space: nowrap; text-overflow: ellipsis;
  -webkit-touch-callout: none; user-select: none; -webkit-user-select: none; touch-action: none;
}
.dchip::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 3px; background: var(--fam); }
/* Turned over, the inversion is a small figure after the name — raised (V7¹),
   or lowered when the chord was turned down, left from root position (V7₃). */
.dchip[data-inv]:not([data-inv=""])::after { content: attr(data-inv); font-size: 9px; vertical-align: super; margin-left: 1px; opacity: .85; }
.dchip[data-inv]:not([data-inv=""])[data-low="1"]::after { vertical-align: sub; }   /* outweighs the rule above; as written before it never applied */

/* The ghost (ui/ghost.js): the ladder a held chip can climb, beside the finger,
   the rung in hand lit; under it the ring of inversions as dots, the one sounding
   lit, a mark under it when the chord was turned down. Takes no touch. */
.slide-ghost { position: fixed; z-index: 150; pointer-events: none; width: 52px; padding: 6px 0; border-radius: 12px;
  background: color-mix(in srgb, var(--bg4) 94%, transparent); box-shadow: var(--elev-sm); border: var(--hair);
  display: flex; flex-direction: column; align-items: center; gap: 4px; opacity: 0; transform: translateY(4px); transition: opacity .12s, transform .12s; }
.slide-ghost.show { opacity: 1; transform: none; }
.slide-ghost[hidden] { display: none; }
.g-ladder { display: flex; flex-direction: column; }
.g-rung { width: 40px; height: 15px; line-height: 15px; text-align: center; border-radius: 6px; font-family: var(--num); font-size: 10px; font-weight: 600; color: var(--text3); }
.g-rung.on { background: var(--accent); color: #fff; }
.g-ring { display: flex; gap: 3px; height: 14px; align-items: center; }
.g-ring i { width: 6px; height: 6px; border-radius: 50%; background: var(--text3); opacity: .45; transition: transform .1s; }
.g-ring i.on { background: var(--accent); opacity: 1; transform: scale(1.35); }
.g-ring i.on.low { box-shadow: 0 4px 0 -2px var(--accent); }

/* ── the ladder card: what a held chip can become, in the top half of the screen,
   under the other thumb (ui/ladder-card.js). Above the pages, under the sheets
   (overlays 150) and the tour (200). ── */
.ladder-card { position: fixed; z-index: 140; left: 50%; top: calc(env(safe-area-inset-top, 0px) + 60px); transform: translate(-50%, -6px);
  width: min(392px, calc(100vw - 20px)); padding: 8px 10px 9px; border-radius: 14px; border: var(--hair);
  background: color-mix(in srgb, var(--bg4) 94%, transparent); box-shadow: var(--elev); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  opacity: 0; transition: opacity .14s, transform .14s, top .22s; touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
.ladder-card.show { opacity: 1; transform: translate(-50%, 0); }
/* Its two buttons: the card in the middle of the screen instead of the top, and see-through — the
   glass thinned and the blur gone so what is under it can be watched (the owner, 2026-11-10). */
.ladder-card.mid { top: 50%; transform: translate(-50%, calc(-50% - 6px)); }
.ladder-card.mid.show { transform: translate(-50%, -50%); }
.lc-tools { position: absolute; right: 10px; bottom: 9px; z-index: 1; display: flex; gap: 4px; }   /* over the grid's empty corner (the owner: "bottom right where there's more space") */
.lc-tool { width: 26px; height: 26px; padding: 0; border-radius: 50%; border: var(--hair); background: color-mix(in srgb, var(--bg3) 70%, transparent); color: var(--text3); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
.lc-tool.on { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.lc-tool .ico { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ladder-card[hidden] { display: none; }
.ladder-card.held { border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
/* Idle under the lock: nothing in hand; the name is the rung the next chord starts on, the cell its turn, outlined as a promise. */
.ladder-card.idle .lc-name { color: var(--text2); }
.ladder-card.idle .lc-name::after { content: ' next'; font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); }
.ladder-card.idle .lc-cell.on, .ladder-card.idle .lc-cell.valid.on { background: transparent; box-shadow: inset 0 0 0 2px var(--accent); }
/* The head: the chord's name, then its notes in two lanes — the letters, and under them the tones (1 · 3 · 5 · 7). */
.lc-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; min-height: 28px; }
.lc-name { font-family: var(--num); font-size: 18px; font-weight: 600; color: var(--accent); flex-shrink: 0; min-width: 40px; }
.lc-name.long { font-size: 15px; }
/* The lanes share the width that is left: a 13th with its bass is eight columns. */
.lc-lanes { display: flex; gap: 0; flex: 1; min-width: 0; }
.lc-lane { display: flex; flex-direction: column; align-items: center; flex: 1; min-width: 0; line-height: 1.1; white-space: nowrap; }
.lc-lanes.many b { font-size: 11px; } .lc-lanes.many i { font-size: 9.5px; }
.lc-lane b { font-family: var(--num); font-size: 12px; font-weight: 600; color: var(--text); }
.lc-lane i { font-family: var(--num); font-style: normal; font-size: 10.5px; color: var(--text3); }
.lc-map { display: flex; gap: 5px; align-items: stretch; }
.lc-rows { display: grid; grid-template-rows: repeat(9, 15px); gap: 2px; flex-shrink: 0; }
.lc-row { width: 24px; height: 15px; line-height: 15px; text-align: right; padding-right: 2px; font-family: var(--num); font-size: 10px; font-weight: 600; color: var(--text3); }
.lc-row.on { color: var(--accent); }
.lc-grid { display: grid; grid-template-columns: repeat(13, 1fr); grid-template-rows: repeat(9, 15px); gap: 2px; flex: 1; min-width: 0; }
.lc-cell { border-radius: 3px; background: color-mix(in srgb, var(--bg3) 40%, transparent); opacity: .3; }
.lc-cell.valid { opacity: 1; background: color-mix(in srgb, var(--bg3) 85%, transparent); }
.lc-cell.valid.row, .lc-cell.valid.col { background: color-mix(in srgb, var(--accent) 16%, var(--bg3)); }
.lc-cell.root.valid { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text3) 55%, transparent); }
.lc-cell.on, .lc-cell.valid.on { background: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent); }
.dchip.kept { background: color-mix(in srgb, var(--fam) 16%, var(--bg3)); }
.dchip.on { background: color-mix(in srgb, var(--fam) 38%, var(--bg3)); }
.dchip.deg-1 { --fam: var(--deg1); } .dchip.deg-2 { --fam: var(--deg2); } .dchip.deg-3 { --fam: var(--deg3); }
.dchip.deg-4 { --fam: var(--deg4); } .dchip.deg-5 { --fam: var(--deg5); } .dchip.deg-6 { --fam: var(--deg6); }
.dchip.deg-7 { --fam: var(--deg7); }

/* ══ the bench, stacked: four full-width zones, the scope takes the slack ══
   Each zone is a title row, one row of hero and controls, and its display.
   Nothing here has a box; the zones separate by space. */
.zones { display: flex; flex-direction: column; gap: 12px; height: 100%; min-height: 0; }
.zone { display: flex; flex-direction: column; gap: 8px; flex-shrink: 0; overflow: visible; }
.zone.grow { flex: 1 1 auto; min-height: 84px; }
.zone .w-head { min-height: 22px; padding: 0; justify-content: space-between; gap: 10px; }
.zone .w-title { flex: 0 1 auto; align-self: center; font-size: 12px; }
.z-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-width: 0; }
.hero-row { justify-content: flex-start; align-items: baseline; gap: 14px; height: 56px; }
#wTune .w-hero { height: auto; align-items: baseline; }
/* The bench tuner reads on its title row: Tuner › | cents | note | chord. */
#wTune .tune-head { min-height: 46px; align-items: center; }
#wTune .tune-head .tune-grid { flex: 1; min-width: 0; height: 46px; margin: 0; grid-template-columns: 96px 1fr 64px; align-items: center; }
#wTune .tune-head .w-hero { justify-self: center; }
#wTune .note-name { font-size: 56px; }
#wTune .note-oct { font-size: 20px; }
#wTune .cents-num { font-size: 18px; text-align: left; }
#wTune .w-chord { min-height: 0; font-size: 13px; font-weight: 600; }
.zone .strobe-row { height: 16px; border-radius: 8px; flex-shrink: 0; }
.zone .cents-meter, .zone .cents-meter[hidden] { display: none !important; }
.caps { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.caps .sq-btn { width: 44px; height: 44px; }
.caps .tap-btn { flex: 0 0 auto; height: 44px; padding: 0 16px; gap: 0; line-height: 1.1; }
.caps .tap-label { font-size: 13px; letter-spacing: .06em; }
.caps .tap-read { font-size: 11px; }
#wTime .w-hero { gap: 6px; }
#wTime .big-num { font-size: 44px; }
#wTime .w-unit { font-size: 11px; }
#wTime .foot-row { gap: 8px; }
#wTime .w-foot { min-height: 0; font-size: 12px; }
#wTime .beat-row { margin: 0; gap: 6px; }
#wTime .beat { height: 30px; font-size: 12px; }
.mode-cycle.link { width: auto; background: none; border: none; box-shadow: none; padding: 0; height: auto; color: var(--accent); font-size: 12px; font-weight: 600; gap: 2px; }
.mode-cycle.link .chev { width: 11px; height: 11px; }
.zone .scope-holder { flex: 1; min-height: 80px; }
.zone .scope-holder canvas { border-radius: var(--r3); }
#wNotes .w-hero { gap: 12px; }
#wNotes .big-num { font-size: 34px; }
#wNotes .w-sub { font-size: 12px; text-align: left; }
#wNotes .w-foot { min-height: 0; font-size: 12px; }
.btn.rec-cap { gap: 8px; padding: 0 16px 0 14px; }
.btn.rec-cap .rec-dot { width: 12px; height: 12px; }
.btn.rec-cap.on { background: color-mix(in srgb, var(--bad) 22%, var(--bg3)); }
.btn.rec-cap.on .rec-dot { border-radius: 3px; animation: rec-blink 1.1s ease-in-out infinite; }
.btn.rec-cap:disabled .rec-dot { background: var(--text3); }
/* The widget's Record in the pedal's states: a red circle armed or recording,
   a green triangle playing, an orange circle dubbing, grey stopped. */
.btn.rec-cap.armed .rec-dot, .btn.rec-cap.rec .rec-dot, .btn.rec-cap.dub .rec-dot, .btn.rec-cap.stopped .rec-dot { border-radius: 50%; }
.btn.rec-cap.armed .rec-dot { animation: rec-arm .5s ease-in-out infinite alternate; }
.btn.rec-cap.play, .btn.rec-cap.stopped, .btn.rec-cap.armed { background: var(--bg3); }
.btn.rec-cap.play .rec-dot { width: 0; height: 0; border-radius: 1px; background: none; animation: none;
  border-left: 12px solid var(--good); border-top: 7px solid transparent; border-bottom: 7px solid transparent; }
.btn.rec-cap.dub { background: color-mix(in srgb, var(--warn) 24%, var(--bg3)); }
.btn.rec-cap.dub .rec-dot { background: var(--warn); }
.btn.rec-cap.stopped .rec-dot { background: var(--text3); animation: none; }
.tb-right .rec-top.loop-armed .rec-dot, .tb-right .rec-top.loop-rec .rec-dot, .tb-right .rec-top.loop-dub .rec-dot, .tb-right .rec-top.loop-stopped .rec-dot { border-radius: 50%; width: 12px; height: 12px; opacity: 1; }
.tb-right .rec-top.loop-play .rec-dot { width: 0; height: 0; border-radius: 1px; background: none; animation: none; opacity: 1; margin-left: 3px;
  border-left: 11px solid var(--good); border-top: 6.5px solid transparent; border-bottom: 6.5px solid transparent; }
.tb-right .rec-top.loop-play::before { border-color: var(--good); }
.tb-right .rec-top.loop-dub .rec-dot { background: var(--warn); }
.tb-right .rec-top.loop-dub::before { border-color: var(--warn); }
.tb-right .rec-top.loop-stopped .rec-dot { background: var(--text3); animation: none; }
.tb-right .rec-top.loop-stopped::before { border-color: var(--text3); }
@media (max-width: 430px) {
  .zones { gap: 10px; }
  #dock .dock-keys { height: 128px; }
  #wTune .note-name { font-size: 42px; }
  #wTune .note-oct { font-size: 16px; }
  #wTune .cents-num { font-size: 15px; }
  .hero-row { height: 50px; }
  #wTime .big-num { font-size: 40px; }
}

/* ══ hygiene: one height per row ══ */
.key-bar { gap: 8px; }
.key-bar .btn, .key-bar .btn.icon { height: 44px; padding: 0 16px; font-size: 15px; }
.key-bar .btn.icon { width: 44px; padding: 0; font-size: 18px; }
.key-name { height: 44px; padding: 0 12px; justify-content: center; }
.caps .tap-btn { padding: 0 18px; }
.caps .tap-label { letter-spacing: .02em; font-size: 14px; font-weight: 600; }
.mini-sel { border-radius: 100px; min-height: 32px; padding: 0 10px; font-size: 13px; font-weight: 600; color: var(--text); }
.zone .w-head .foot-row { gap: 10px; }
.zone .beat-row .beat { font-weight: 600; }
.caps .tap-btn { justify-content: center; }

/* ══ the root is a key you can see from across the room ══ */
.kb-key.tonic.white:not(.down):not(.echo) { background: color-mix(in srgb, var(--accent) 22%, var(--key-white)); color: var(--accent); font-weight: 700; }
.kb-key.tonic.black:not(.down):not(.echo) { background: color-mix(in srgb, var(--accent) 40%, var(--key-black)); }

/* ══ bench dock, compressed: the widgets above get the room ══ */
#dock { gap: 5px; padding-top: 6px; }
#dock .key-bar { gap: 6px; }
#dock .key-bar .btn, #dock .key-bar .btn.icon, #dock .key-name { height: 38px; }
#dock .key-bar .btn.icon { width: 38px; }
#dock .key-name .kn-go { display: none; }
#dock .key-name .kn-main { font-size: 17px; }
#dock .dock-keys { height: 112px; }
#dock .dock-read { min-height: 36px; }
#dock .dock-read .btn, #dock .oct-step .sq-btn { height: 36px; }
#dock .oct-step .sq-btn { width: 36px; }
@media (max-width: 430px) {
  #dock .dock-keys { height: 108px; }
  #dock .dock-read { min-height: 36px; }
  #dock .dock-read .btn, #dock .oct-step .sq-btn { height: 36px; width: auto; }
  #dock .oct-step .sq-btn { width: 36px; }
}
.tabbar .tab .tab-name { letter-spacing: .05em; }

/* ══ key labels: letter over degree, black keys named too ══ */
.kb-key { flex-direction: column; justify-content: flex-end; align-items: center; gap: 1px; line-height: 1; }
.kb-key .kl, .kb-key .kd { pointer-events: none; }
.kb-key .kl { font-size: 12px; font-weight: 600; }
.kb-key .kd { font-size: 11px; font-weight: 600; color: var(--accent); opacity: .85; }
/* A black key is dark in both moods, so its label comes from the key colours,
   not the text tones — those go dark in Ink Light and vanished into the key. */
.kb-key.black { padding-bottom: 7px; color: color-mix(in srgb, var(--key-white) 62%, var(--key-black)); }
.kb-key.black .kl { font-size: 11px; }
.kb-key.black .kd { font-size: 10px; }
.kb-key.black.inkey { color: var(--key-white); }
.kb-key.down .kd, .kb-key.down .kl { color: #fff; opacity: 1; }
.kb-key.tonic.white:not(.down):not(.echo) .kd { color: var(--accent); }
.keyboard.mini .kb-key .kd, .keyboard.mini .kb-key.black .kl { display: none; }
/* Held/echo marks sit above the two-line label, never on it. */
.kb-key.latched::before, .kb-key.echo::before { bottom: auto; top: 26px; }
.kb-key.black.latched::before, .kb-key.black.echo::before { bottom: auto; top: 22px; }
/* The lane (Theory): what sounds is marked in a strip under the keys, not on
   them — a dot under a key being touched, a ring under one held, a faint dot
   under the same note in another octave. The keys give up the strip's height. */
.keyboard.laned { --lane: 16px; }
.keyboard.laned .kb-key.white { height: calc(100% - var(--lane)); }
.keyboard.laned .kb-key.black { height: calc((100% - var(--lane)) * .6); }
.keyboard.laned .kb-key.latched::before, .keyboard.laned .kb-key.echo::before { display: none; }
.kb-lane { position: absolute; left: 0; right: 0; bottom: 0; height: var(--lane); pointer-events: none; }
.kb-ld { position: absolute; top: 50%; transform: translate(-50%, -50%); width: 9px; height: 9px; border-radius: 50%; background: var(--accent); }
.kb-ld.held { background: none; border: 2px solid var(--accent); box-sizing: border-box; }
.kb-ld.echo { width: 5px; height: 5px; background: color-mix(in srgb, var(--accent) 55%, var(--text3)); }

/* ══ signal generator rows ══ */
.sig-row { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-top: 1px solid var(--border); flex-wrap: wrap; }
.sig-row:first-of-type { border-top: none; padding-top: 0; }
.sig-row .btn { min-width: 96px; }
.sig-level { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 160px; }
.sig-level input[type=range] { flex: 1; min-width: 80px; }
.sig-level .mono { font-size: 12px; color: var(--text2); min-width: 64px; text-align: right; }
/* ══ take loop row ══ */
.keyboard.ref-keys .kb-key.black .kl, .keyboard.ref-keys .kb-key.black .kd { display: none; }

/* Records, keys up: Set beside Hold, as on the bench's key bar — and while a key
   is chosen, Done · Maj · Min · ⋯ take the whole row: octave, pedal, Hold and Set. */
#bKeySetBtn, #bKeySet2 { display: none; }
body.detail.on-notes.keys-up #bKeySetBtn { display: inline-flex; }
body.detail.on-notes.keys-up #bKeySet2:not([hidden]) { display: flex; }
#bDockRead.setting .oct-step, #bDockRead.setting #dockPedal, #bDockRead.setting #bHold, #bDockRead.setting #bKeySetBtn { display: none !important; }
.card-head h2[hidden], .card-tools[hidden] { display: none; }
/* Records, keys up, a loop running: ▶ ■ ✓ + octave + Hold + Set must all fit a
   390 px phone — the controls tighten rather than the row clipping Set. */
body.detail.on-notes.keys-up .oct-step .sq-btn { width: 38px; height: 40px; }
body.detail.on-notes.keys-up .oct-step { gap: 2px; }
body.detail.on-notes.keys-up #dock .dock-pedal .prep, body.detail.on-notes.keys-up #dock .dock-pedal .sq-btn { min-width: 38px; width: 38px; height: 40px; }
body.detail.on-notes.keys-up #bHold, body.detail.on-notes.keys-up #bKeySetBtn { padding-inline: 12px; }
body.detail.on-notes.keys-up .dock-read { gap: 4px; }
body.detail.on-notes.keys-up #dock #recToggle { width: 44px; min-width: 44px; }
body.detail.on-notes.keys-up #bHold, body.detail.on-notes.keys-up #bKeySetBtn { padding-inline: 10px; }

/* Theory › Voicing: each row is a label and one control that fills the rest of
   the row, so every control ends on the same right edge. */
/* Every shelf pane builds its rows one way: each cell stacks its label over a
   full-width control, so the controls share both edges and nothing is clipped. */
.tabpane .ctl-inline label > :last-child { flex: 1 1 auto; min-width: 0; width: auto; }
.tabpane .ctl-inline .btn.cyc { justify-content: center; height: 38px; }
.tabpane .pane-tools { justify-content: flex-end; margin-bottom: 6px; }
.tabpane .ctl-inline .btn.cyc:disabled { opacity: .45; }
.tabpane .ctl-inline select { height: 38px; }
.tabpane .ctl-inline label { flex-direction: column; align-items: stretch; gap: 5px; }
.tabpane .ctl-inline label > :last-child { width: 100%; }
.tabpane .ctl-inline input[type=range] { height: 38px; margin: 0; }

/* ── Rings: a chord under two thumbs ── */
.rings { display: flex; gap: 12px; padding: 34px 0 8px; align-items: stretch; position: relative; }   /* the band on top holds the layout button */
/* The layout button keeps the corner under Bass, in a band of its own above
   the rings, out of the thumbs' way whichever way they sit. */
.ring-layout { position: absolute; right: 0; top: 0; width: 36px; height: 26px; padding: 0; display: flex; align-items: center; justify-content: center; border-radius: 13px; background: var(--bg3); border: var(--hair); color: var(--text2); z-index: 1; }
.ring-layout:active { transform: translateY(1px); }
body.hand-left .ring-layout { right: auto; left: 0; }
.ring-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; }
.ring { width: 100%; aspect-ratio: 1; touch-action: none; }
/* The readout on its line, and a gap that is the other ring's offset. A column
   that sits high reads downward (ring, line, readout, gap); one that sits low
   reads upward (gap, readout, line, ring). Every column is the same height, so
   the box never changes size as the layout does. */
.ring-line { width: 1.5px; height: 14px; background: var(--line2); flex-shrink: 0; }
.ring-read { height: 30px; display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 15px; font-weight: 700; color: var(--text); white-space: nowrap; }
.ring-read small { font-size: 11px; font-weight: 600; color: var(--text3); font-family: var(--num); }
.ring-read:empty::before { content: '—'; color: var(--text3); font-weight: 500; }
.ring-gap { height: 56px; flex-shrink: 0; }   /* with the line and the readout, a 100 px offset between the rings */
.ring-col.up .ring { order: 0; } .ring-col.up .ring-line { order: 1; } .ring-col.up .ring-read { order: 2; } .ring-col.up .ring-gap { order: 3; }
.ring-col.down .ring-gap { order: 0; } .ring-col.down .ring-read { order: 1; } .ring-col.down .ring-line { order: 2; } .ring-col.down .ring { order: 3; }
.ring-layout svg { display: block; }
.ring-layout circle { fill: var(--text2); }
/* The other hand: the roots on the left, the qualities on the right (and both mirrored, in rings.js). */
body.hand-left .rings { flex-direction: row-reverse; }
.pad-svg { width: 100%; height: 100%; display: block; overflow: visible; }
.pad-sec { fill: var(--bg3); stroke: var(--bg); stroke-width: 1.5; transition: fill .08s; }
.pad-svg.roots .pad-sec { fill: var(--bg2); opacity: .55; }
.pad-svg.roots .pad-sec.in { fill: var(--bg3); opacity: 1; }
.pad-svg.roots .pad-lbl { fill: var(--text3); }
.pad-svg.roots .pad-lbl.in { fill: var(--text); }
.pad-deg { fill: var(--text3); font-size: 9.5px; font-weight: 600; text-anchor: middle; dominant-baseline: central; pointer-events: none; font-family: var(--num); }
.pad-deg.in { fill: var(--accent); }
.pad-deg.on { fill: #fff; opacity: .85; }
.pad-svg.roots .pad-sec.tonic { stroke: var(--accent); stroke-width: 2; }
.pad-sec.on { fill: var(--accent) !important; }
.pad-lbl { fill: var(--text2); font-size: 15px; font-weight: 600; text-anchor: middle; dominant-baseline: central; pointer-events: none; font-family: inherit; }
.pad-svg.quality .pad-lbl { font-size: 13px; }
.pad-lbl.on { fill: #fff; }
.pad-svg.quality .pad-lbl.long { font-size: 10.5px; }
/* The diatonic mark: a dot by the rim of each family that stays in the key from the root in hand. */
.pad-dot { fill: var(--accent); opacity: 0; pointer-events: none; transition: opacity .12s; }
.pad-dot.on { opacity: 1; }
.pad-dot.lit { fill: #fff; }
.ring-read.in small { color: var(--accent); }

/* The Desk's loop button, where the recorder's sub stood (round 96): the same button as Record and Mark. */
.w-hero .btn.loop-btn { align-self: center; gap: 6px; }
.w-hero .btn.loop-btn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex-shrink: 0; }
.w-hero .btn.loop-btn #bLoopVal:empty { display: none; }   /* an empty value must not keep the gap: the icon alone sits dead centre */
/* The lock in the row above the keys (the owner, 2026-11-10: lock · bass · arp · sound · pedal): a pill, not a circle, for its word. */
body.detail.on-notes #bLock { display: none; }   /* Records: the row is full with the pedal; the lock is Theory's */
/* Line icons on a square button: Groove and Clicks on the Desk (round 96). */
.sq-btn svg.line { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* A narrow phone (375): the recorder's row — time · Loop · Record · Mark — tightens rather than spills. */
@media (max-width: 389px) {
  #wNotes .w-hero .big-num { font-size: 22px; }
  #wNotes .caps { gap: 6px; }
  #wNotes .caps .btn, #wNotes .w-hero .btn.loop-btn { padding-left: 10px; padding-right: 10px; }
}
