/* GuitarScroll app stylesheet.
   DEFAULT THEME = "Steel": the CarConcierge visual system (steel navy, blue
   primary, amber accent over light surfaces). The stage-friendly dark palettes
   remain as user-selectable themes below (picker in the app shell, persisted in
   localStorage by public/js/theme.js). Every colour flows from these tokens;
   no colour literal lives outside the theme blocks. */
:root {
  --bg: #f3f5f8;            /* page ground */
  --panel: #ffffff;         /* cards, bars, drawers */
  --panel2: #eaeef3;        /* inset surfaces: inputs, pills, rows */
  --border: #e0e5ec;
  --border-strong: #cbd5e0;
  --text: #1b232e;
  --dim: #5e6b78;           /* secondary copy, >= 4.5:1 on --panel */
  --chord: #a3600a;         /* chord names on the sheet (amber, readable on white) */
  --accent: #3160b0;        /* primary blue */
  --accent-dim: #274f94;    /* primary hover / deep */
  --accent-soft: #e7eefa;
  --amber: #e08a1e; --amber-2: #f0a53f; --amber-soft: #fdf0dc;
  --danger: #c62828;
  --on-accent: #ffffff;     /* text ON accent/chord fills */
  --on-accent-dim: #ffffff; /* text ON accent-dim fills (buttons, pills) */
  --tabline: #23567d;
  --steel: #1c2637; --steel-d: #131b27; --steel-l: #28364b;
  --on-dark: #ffffff;
  --hero-grad: linear-gradient(140deg, var(--accent) 0%, var(--accent-dim) 55%, var(--steel) 120%);
  --focus: var(--accent);
  --selection-bg: #cbdff2;
  --scrim: rgba(19, 27, 39, 0.55);
  --qr-bg: #ffffff;
  --shadow: 0 4px 16px -6px rgba(27, 35, 46, 0.10);
  --shadow-lift: 0 10px 26px -12px rgba(27, 35, 46, 0.22);
  --scroll-thumb: #c3ccd6; --scroll-thumb-hover: #a9b6c4;
  --radius-xs: 6px; --radius-sm: 9px; --radius: 12px; --radius-lg: 16px; --radius-pill: 999px;
  --shellw: 236px;
  --barh: 58px;             /* page bar height: fixed panels on the play page hang from it */
  --mono: 'Cascadia Mono', 'Consolas', 'Menlo', monospace;
  /* the fretboard (FretView): derived from the theme's own tokens, so every theme keeps the frets legible */
  --fret-wood: color-mix(in srgb, var(--panel2) 74%, var(--chord) 9%);
  --fret-wire: var(--dim);
  --fret-nut: var(--text);
  --fret-string: var(--text);
  --fret-inlay: color-mix(in srgb, var(--dim) 45%, transparent);
  color-scheme: light;
  accent-color: var(--accent);
}

/* ---------- THEMES (picker in the shell; validated for contrast) ---------- */
html[data-theme="midnight"] {
  --bg: #101418; --panel: #1a2027; --panel2: #232b34; --border: #2e3843; --border-strong: #3a4756;
  --text: #e8edf2; --dim: #8b98a5; --chord: #f5b942; --accent: #34c98e;
  --accent-dim: #1f7a57; --accent-soft: rgba(52, 201, 142, 0.16); --danger: #e05d5d; --on-accent: #06281b;
  --on-accent-dim: #ffffff; --tabline: #7fb3d5; --amber: #f5b942; --amber-2: #f8c96a; --amber-soft: rgba(245, 185, 66, 0.16);
  --focus: #34c98e; --selection-bg: #2c4a68; --scrim: rgba(0, 0, 0, 0.6);
  --shadow: 0 4px 16px -6px rgba(0, 0, 0, 0.5); --shadow-lift: 0 10px 26px -12px rgba(0, 0, 0, 0.65);
  --scroll-thumb: #35455c; --scroll-thumb-hover: #465872; --steel: #121924; --steel-d: #0c1119; --steel-l: #1f2a3a;
  color-scheme: dark;
}
html[data-theme="stage"] {
  --bg: #000000; --panel: #0c0c0f; --panel2: #18181d; --border: #33333c; --border-strong: #4a4a55;
  --text: #f4f4f7; --dim: #a2a2ae; --chord: #ffd23e; --accent: #3ee68f;
  --accent-dim: #157a4a; --accent-soft: rgba(62, 230, 143, 0.16); --danger: #ff6b6b; --on-accent: #04170c;
  --on-accent-dim: #ffffff; --tabline: #7fc4ff; --amber: #ffd23e; --amber-2: #ffe07a; --amber-soft: rgba(255, 210, 62, 0.16);
  --focus: #3ee68f; --selection-bg: #2a3a4a; --scrim: rgba(0, 0, 0, 0.7);
  --shadow: 0 4px 16px -6px rgba(0, 0, 0, 0.6); --shadow-lift: 0 10px 26px -12px rgba(0, 0, 0, 0.8);
  --scroll-thumb: #2c2c33; --scroll-thumb-hover: #3d3d47; --steel: #0c0c0f; --steel-d: #000000; --steel-l: #18181d;
  color-scheme: dark;
}
html[data-theme="ocean"] {
  --bg: #0a1420; --panel: #101f30; --panel2: #17293d; --border: #2b4763; --border-strong: #3a5b7d;
  --text: #e8eff7; --dim: #93a9bf; --chord: #f5c542; --accent: #46c2f7;
  --accent-dim: #135f88; --accent-soft: rgba(70, 194, 247, 0.16); --danger: #f07373; --on-accent: #04202f;
  --on-accent-dim: #ffffff; --tabline: #8fd0a8; --amber: #f5c542; --amber-2: #f8d36f; --amber-soft: rgba(245, 197, 66, 0.16);
  --focus: #46c2f7; --selection-bg: #24476a; --scrim: rgba(0, 0, 0, 0.6);
  --shadow: 0 4px 16px -6px rgba(0, 0, 0, 0.5); --shadow-lift: 0 10px 26px -12px rgba(0, 0, 0, 0.65);
  --scroll-thumb: #22364d; --scroll-thumb-hover: #2f4a66; --steel: #101f30; --steel-d: #0a1420; --steel-l: #17293d;
  color-scheme: dark;
}
html[data-theme="paper"] {
  --bg: #faf7f0; --panel: #ffffff; --panel2: #efeadd; --border: #cfc7b2; --border-strong: #b5ab92;
  --text: #26241f; --dim: #63604f; --chord: #8a5f00; --accent: #14603c;
  --accent-dim: #17714a; --accent-soft: rgba(20, 96, 60, 0.12); --danger: #a8231c; --on-accent: #ffffff;
  --on-accent-dim: #ffffff; --tabline: #23567d; --amber: #b8730a; --amber-2: #d08a1e; --amber-soft: #f6e9cf;
  --focus: #14603c; --selection-bg: #dfe8d5; --scrim: rgba(38, 36, 31, 0.5);
  --scroll-thumb: #d6cfbb; --scroll-thumb-hover: #c2b99f; --steel: #3a3428; --steel-d: #26241f; --steel-l: #4d4636;
  color-scheme: light;
}
html[data-theme="sepia"] {
  --bg: #f2e7cf; --panel: #f9f1de; --panel2: #e6d7b5; --border: #b9a67d; --border-strong: #a08c62;
  --text: #372c17; --dim: #6d5f3f; --chord: #7c4a00; --accent: #365c22;
  --accent-dim: #48682f; --accent-soft: rgba(54, 92, 34, 0.12); --danger: #962a24; --on-accent: #ffffff;
  --on-accent-dim: #ffffff; --tabline: #205a70; --amber: #a2620a; --amber-2: #bb7a1c; --amber-soft: #eedcb5;
  --focus: #365c22; --selection-bg: #d9d0a8; --scrim: rgba(55, 44, 23, 0.5);
  --scroll-thumb: #cdbd95; --scroll-thumb-hover: #b9a67d; --steel: #4a3d22; --steel-d: #372c17; --steel-l: #5c4d2d;
  color-scheme: light;
}
html[data-theme="contrast"] {
  --bg: #000000; --panel: #000000; --panel2: #121212; --border: #7a7a7a; --border-strong: #a0a0a0;
  --text: #ffffff; --dim: #cfcfcf; --chord: #ffe100; --accent: #00ff88;
  --accent-dim: #00753c; --accent-soft: rgba(0, 255, 136, 0.16); --danger: #ff6060; --on-accent: #000000;
  --on-accent-dim: #ffffff; --tabline: #7fd4ff; --amber: #ffe100; --amber-2: #fff06a; --amber-soft: rgba(255, 225, 0, 0.16);
  --focus: #ffe100; --selection-bg: #3a3a00; --scrim: rgba(0, 0, 0, 0.75);
  --shadow: none; --shadow-lift: none;
  --scroll-thumb: #4a4a4a; --scroll-thumb-hover: #6a6a6a; --steel: #121212; --steel-d: #000000; --steel-l: #222222;
  color-scheme: dark;
}

/* ---------- base grammar (shared with the marketing site) ---------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
::selection { background: var(--selection-bg); color: var(--text); }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
[hidden] { display: none !important; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font: 15px/1.55 -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}
h1, h2, h3, h4 { line-height: 1.2; letter-spacing: -0.01em; }
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-dim); }
button {
  background: var(--panel); color: var(--accent); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 8px 14px; font-size: 14px; font-weight: 600; font-family: inherit;
  line-height: 1.4; cursor: pointer; transition: border-color .15s ease, background .15s ease, box-shadow .15s ease, transform .15s ease;
}
button:hover { border-color: var(--accent); }
button:active { transform: translateY(1px); }
button:disabled { opacity: .55; cursor: default; transform: none; }
button.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
button.primary:hover { background: var(--accent-dim); border-color: var(--accent-dim); box-shadow: var(--shadow); }
button.danger { color: var(--danger); }
button.danger:hover { border-color: var(--danger); }
input[type=text], input[type=email], input[type=password], input[type=search], input[type=number], textarea, select {
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 8px 10px; font-size: 14px; font-family: inherit;
}
input[type=text]:focus, input[type=email]:focus, input[type=password]:focus, input[type=search]:focus, input[type=number]:focus, textarea:focus, select:focus {
  outline: 2px solid var(--focus); outline-offset: 0; border-color: var(--accent);
}
.themesel {
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 7px 8px; font-size: 13px; font-family: inherit; width: 100%;
}

/* ---------- page bar (the page's own toolbar; the shell carries the brand) ---------- */
header.bar {
  display: flex; align-items: center; gap: 12px; padding: 10px 18px;
  background: var(--panel); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 10; height: var(--barh);
}
header.bar h1 { font-size: 17px; margin: 0; font-weight: 800; letter-spacing: -0.01em; }
header.bar h1 a { color: var(--text); display: inline-flex; align-items: center; gap: 7px; }
header.bar h1 a .mark { width: 22px; height: 22px; object-fit: contain; flex: none; }
header.bar .brand { color: var(--accent); }
header.bar .spacer { flex: 1; }
header.bar .meta { color: var(--dim); font-size: 13px; }
header.bar .backlink {
  color: var(--dim); font-size: 13px; font-weight: 600; text-decoration: none; white-space: nowrap;
  padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--panel);
}
header.bar .backlink:hover { color: var(--accent); border-color: var(--accent); }

/* ---------- editor flow panel ---------- */
.flowpanel { display: none; background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 8px 12px; margin: 8px 0; font-size: 13px; }
.flowpanel.show { display: block; }
.flowpanel .flowhead { font-weight: 600; margin-bottom: 4px; }
.flowpanel .flowrow { display: flex; align-items: center; gap: 8px; padding: 3px 0; flex-wrap: wrap; }
.flowpanel .fname { min-width: 110px; font-weight: 600; color: var(--accent); }
.flowpanel .arrow { color: var(--dim); }
.flowpanel select { background: var(--panel2); color: var(--text); border: 1px solid var(--border); border-radius: 7px; padding: 3px 6px; font-size: 12.5px; }
.flowpanel button.frounds { font-size: 11px; padding: 2px 8px; }
.flowpanel button.frounds.on { border-color: var(--accent); color: var(--accent); }
.flowpanel .froundset { display: none; gap: 8px; margin-left: 4px; }
.flowpanel .froundset.show { display: inline-flex; }
.flowpanel .rnd { color: var(--dim); font-size: 12px; display: inline-flex; align-items: center; gap: 3px; }
.takebtn { font-size: 11px; padding: 2px 7px; margin-right: 4px; border-radius: 7px; }
.takebtn.on { background: var(--danger); color: var(--on-accent-dim); border-color: var(--danger); }
.sttsel {
  background: var(--panel2); color: var(--text); border: 1px solid var(--border);
  border-radius: 7px; font: inherit; font-size: 11px; padding: 2px 4px; max-width: 130px;
}

.wrap { max-width: 980px; margin: 0 auto; padding: 20px; }

/* ---------- library ---------- */
.songlist { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.songcard {
  display: flex; align-items: center; gap: 14px; padding: 14px 18px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
  transition: box-shadow .15s ease, border-color .15s ease;
}
.songcard:hover { box-shadow: var(--shadow-lift); border-color: var(--border-strong); }
.songcard .t { font-size: 16px; font-weight: 600; }
.songcard .a { color: var(--dim); font-size: 13px; }
.songcard .grow { flex: 1; }

/* ---------- the sheet ---------- */
.sheet {
  font-family: var(--mono); font-size: 18px; line-height: 1.35;
  padding: 24px 20px 55vh; /* deep bottom pad so the last line can sit mid-screen */
  white-space: pre; overflow-x: auto;
}
.sheet .section {
  font-family: system-ui, sans-serif; font-weight: 700; font-size: 15px;
  color: var(--accent); text-transform: uppercase; letter-spacing: .08em;
  margin: 18px 0 4px;
}
.sheet .chordrow { color: var(--chord); font-weight: 600; }
.sheet .note { color: var(--dim); font-style: italic; font-family: system-ui, sans-serif; white-space: normal; }
.sheet .note.goto { color: var(--accent); font-style: normal; font-weight: 600; }
.sheet .tab { color: var(--tabline); font-size: 15px; }
.sheet .blank { height: .6em; }
.sheet .line { border-left: 3px solid transparent; padding-left: 10px; margin-left: -13px; }
.sheet .line.current { border-left-color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, transparent); }
/* THE LIVE LINE IS SACRED: whatever else it is (sung earlier, retired),
   the line being sung NOW is always full-strength and unmistakable */
.sheet .line.current { opacity: 1 !important; }
.sheet .line.current .lyrics::after { content: none; }
.sheet .line.current .w.done { color: var(--text); opacity: .85; }
.sheet .w { border-radius: 4px; padding: 0 1px; }
.sheet .w.done { color: var(--dim); }
.sheet .w.current { background: var(--accent); color: var(--on-accent); font-weight: 700; }

/* ---------- play chrome ---------- */
.playbar { display: flex; align-items: center; gap: 10px; }
.capoctl { color: var(--dim); font-size: 13px; display: flex; align-items: center; gap: 5px; }
.capoctl select {
  background: var(--panel2); color: var(--text); border: 1px solid var(--border);
  border-radius: 8px; padding: 6px 8px; font-size: 13px;
}
.sheet .chord { cursor: help; }
.sheet .chord:hover { text-decoration: underline dotted; }

/* ---------- live output side panel: word / note / rhythm tracking ---------- */
:root { --sidew: 30vw; }
.side {
  position: fixed; right: 0; top: var(--barh); bottom: 0; width: var(--sidew);
  background: var(--bg); border-left: 1px solid var(--border);
  padding: 12px; overflow-y: auto; font-size: 13px; z-index: 15;
}
/* the sheet is its OWN scroll container (auto-scroll happens inside it, with
   its own styled bar and its own zoom) — the page itself never scrolls */
body.playpage .sheet {
  position: fixed; left: 0; right: var(--sidew); top: var(--barh); bottom: 0;
  overflow-y: auto; overflow-x: auto; margin: 0;
}
body.sideCollapsed .side, body.sideCollapsed .sideHandle { display: none; }
body.sideCollapsed .sheet { right: 0; }
body.sideCollapsed .sideToggle { right: 0; }
.zoomctl { display: flex; gap: 4px; }
.zoomctl button { padding: 8px 10px; font-size: 12px; }
/* the chart chord we believe is SOUNDING right now */
.sheet .chord.sounding {
  background: color-mix(in srgb, var(--chord) 22%, transparent); outline: 1px solid var(--chord);
  border-radius: 4px; text-decoration: none;
}

/* drag-to-resize handle on the panel's left edge */
.sideHandle {
  position: fixed; top: var(--barh); bottom: 0; right: var(--sidew); width: 7px;
  cursor: ew-resize; z-index: 17; background: transparent;
}
.sideHandle:hover, .sideHandle.dragging { background: var(--accent-dim); opacity: .5; }

/* collapse/expand tab, always reachable */
.sideToggle {
  position: fixed; top: 50%; right: var(--sidew); transform: translateY(-50%);
  width: 22px; height: 64px; padding: 0; z-index: 18;
  border: 1px solid var(--border); border-right: none; border-radius: 8px 0 0 8px;
  background: var(--panel); color: var(--dim); font-size: 13px; line-height: 1;
}
.sideToggle:hover { color: var(--accent); border-color: var(--accent-dim); }

/* styled scrollbars everywhere (the panel scrolls; OS-default bars look broken) */
* { scrollbar-width: thin; scrollbar-color: var(--scroll-thumb) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: 5px; border: 2px solid transparent; background-clip: padding-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); background-clip: padding-box; }
.playbar .meta { max-width: 26vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* the panel is a flex column: the two log cards absorb spare height and
   their LOGS shrink first, so the panel itself needs no scrollbar */
.side { display: flex; flex-direction: column; }
.side .card {
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  padding: 12px 14px; margin-bottom: 12px; flex: none;
}
.side .card.grow { flex: 1 1 0; min-height: 96px; display: flex; flex-direction: column; overflow: hidden; }
.side .card.grow .evlog { flex: 1 1 0; max-height: none; min-height: 28px; }
#cardWords .evlog { max-height: 84px; }
.side h3 {
  margin: -2px 0 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border);
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .09em; color: var(--dim); display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
/* the engine pill can read "listening (AI base·wasm·15T)": wrap onto its own row rather than clip at the panel edge */
.side h3 .pill { max-width: 100%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side .spacer { flex: 1; }
.dim { color: var(--dim); }
.mono { font-family: var(--mono); }

.statusline { display: flex; align-items: center; gap: 10px; padding: 2px 2px 0; }
.statusline .statsec { font-weight: 600; }
.statusline .statwords { font-size: 12px; color: var(--dim); }
.statusline .statwords b { color: var(--text); font-family: var(--mono); font-weight: 600; }
.statussub { font-size: 11.5px; padding: 2px 2px 10px; }

.side .evlog {
  font-family: var(--mono); font-size: 11px; line-height: 1.6; color: var(--dim);
  max-height: 132px; overflow-y: auto; margin-top: 8px;
  border-top: 1px solid var(--border); padding-top: 6px;
}
.side .evlog.short { max-height: 76px; }
.side .evlog .jump { color: var(--chord); }
.side .evlog .advance, .side .evlog .agree { color: var(--accent); }
.side .evlog .nomatch, .side .evlog .seeking, .side .evlog .disagree { color: var(--danger); }
.side .evlog .pending { color: var(--dim); font-style: italic; }
.side .heard {
  font-family: var(--mono); font-size: 12px; color: var(--dim);
  background: var(--panel2); border-radius: 8px; padding: 7px 9px; word-wrap: break-word;
  min-height: 33px;
}
.side .heard b { color: var(--accent); }
.side details.card summary {
  cursor: pointer; color: var(--dim); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .09em;
}
.side .simsec { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
.side label { color: var(--dim); font-size: 12px; }
.side .ctlrow { display: flex; align-items: center; gap: 8px; margin: 8px 0 0; flex-wrap: wrap; row-gap: 6px; }
.statusline { flex-wrap: wrap; row-gap: 4px; }
.chordrowhud { flex-wrap: wrap; row-gap: 6px; }
.side input[type=range] { flex: none; width: 76px; accent-color: var(--accent-dim); }

.chordrowhud { display: flex; align-items: center; gap: 14px; margin-bottom: 10px; }
.cslot { display: flex; align-items: baseline; gap: 5px; }
.cslot .hudlbl { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; }
.cslot .det { font-size: 26px; min-width: 34px; }
.cslot small { font-size: 10px; color: var(--dim); font-family: var(--mono); }
.hudlbl { color: var(--dim); font-size: 11px; }
.det { font-size: 36px; font-weight: 800; color: var(--chord); min-width: 54px; line-height: 1; }
.det.expect { color: var(--text); font-size: 22px; min-width: 40px; }
.dot { width: 11px; height: 11px; border-radius: 50%; background: var(--border); flex: none; }
.dot.good { background: var(--accent); }
.dot.bad { background: var(--danger); }
.bpmbig { font-size: 20px; font-weight: 700; color: var(--accent); font-family: var(--mono); }
.beat { width: 11px; height: 11px; border-radius: 50%; background: var(--accent); opacity: .15; display: inline-block; flex: none; }
.beat.hit { opacity: 1; }

/* Note matrix: memory row on top, then the waterfall (now / −1s … −4s).
   CSS grid with shared columns — a pitch class sits EXACTLY under itself in
   every row. #hudNotes uses display:contents so its 12 cells join the grid. */
.notegrid { margin: 2px 0 2px; }
.notegrid .hrow {
  display: grid; grid-template-columns: 46px repeat(12, minmax(0, 1fr));
  gap: 2px; align-items: stretch; margin: 2px 0;
}
.notegrid #hudNotes { display: contents; }
.notegrid .lbl { font-size: 9px; color: var(--dim); text-align: right; padding-right: 4px; align-self: center; }
.notegrid i {
  font-style: normal; font-size: 9.5px; color: var(--dim); text-align: center;
  padding: 2px 0; border-radius: 3px; border: 1px solid var(--border);
}
.notegrid .memrow i { font-size: 10.5px; padding: 4px 0; opacity: .45; }
.notegrid .memrow i.on { color: var(--on-accent); background: var(--chord); border-color: var(--chord); opacity: 1; font-weight: 700; }
.notegrid .memrow { margin-bottom: 5px; }

.micbar { position: relative; }
.micbar u { position: absolute; top: -2px; bottom: -2px; width: 2px; background: var(--danger); text-decoration: none; }
.dynbar { width: 70px; height: 8px; background: var(--panel2); border: 1px solid var(--border); border-radius: 4px; overflow: hidden; display: inline-block; flex: none; }
.dynbar i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .12s; }
.hud .dot { width: 11px; height: 11px; border-radius: 50%; background: var(--border); }
.hud .dot.good { background: var(--accent); }
.hud .dot.bad { background: var(--danger); }
.hud .beat { width: 11px; height: 11px; border-radius: 50%; background: var(--accent); opacity: .15; }
.hud .beat.hit { opacity: 1; }
.hud .spacer { flex: 1; }

/* last word actually HEARD: green + check (check floats so columns don't shift) */
.sheet .w.current { position: relative; }
.sheet .w.current::after {
  content: '✓'; position: absolute; top: 0.05em; right: -0.95em;
  font-size: 12px; color: var(--accent); font-weight: 700;
  text-shadow: 0 0 4px var(--bg);
}
/* chords carry the flow: each chart chord gets a small green ✓ as it's hit */
.sheet .chord { position: relative; }
.sheet .chord.hit { color: var(--accent); }
.sheet .chord.hit::after {
  content: '✓'; position: absolute; top: -0.8em; right: -0.55em;
  font-size: 9px; color: var(--accent); font-weight: 700;
}
/* line-level progress: finished lines are marked off; the highlighted line
   is the one being sung NOW */
.sheet .line.sung { opacity: .5; }
.sheet .line.sung .lyrics::after { content: ' ✓'; color: var(--accent); }
/* retired flow instances dim without claiming a ✓ they didn't earn */
.sheet .line.past { opacity: .5; }
/* the upcoming section, already printed below (Dynamic) */
.flowsec.pendingsec { opacity: .8; border-left: 2px dashed var(--accent-dim); padding-left: 8px; margin-left: -10px; }

/* ---------- song views: Uniform (whole sheet) / Dynamic (explore timeline) ---------- */
.viewtabs {
  position: sticky; top: 0; z-index: 6; display: flex; gap: 6px;
  padding: 8px 0 10px; background: var(--bg);
  font-family: system-ui, sans-serif; white-space: normal;
}
.viewtabs button { padding: 6px 16px; font-size: 12.5px; color: var(--dim); border-radius: 999px; }
.viewtabs button.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.viewtabs .vtspacer { flex: 1; }
.viewtabs #zoomOut, .viewtabs #zoomIn, .viewtabs #chordMode { padding: 6px 12px; border-radius: 8px; }
.viewtabs .capoctl { margin-right: 2px; }
.viewtabs { flex-wrap: wrap; row-gap: 6px; align-items: center; }
body[data-songview="full"] #flowView { display: none; }
body:not([data-songview="full"]) #fullView { display: none; }
/* the options row belongs to Free Style only — Dynamic flows by itself */
body:not([data-songview="free"]) .flowopts { display: none !important; }

/* ---------- flow mode: the performance timeline + where-next options ---------- */
.flowsec { margin-bottom: 4px; }
.flowopts { display: none; }
.flowopts.show {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch;
  padding: 14px 4px 30vh; white-space: normal; font-family: system-ui, sans-serif;
}
.flowopts .optlbl { width: 100%; color: var(--dim); font-size: 12.5px; }
.optchip {
  border: 1px dashed var(--border); border-radius: 12px; padding: 10px 14px;
  cursor: pointer; background: var(--panel); width: 100%; max-width: 720px;
  overflow: hidden;
  /* at the choose moment the row re-renders — chips hold back for a beat so
     the CHOSEN section populating is the only text that appears */
  animation: optIn .35s ease .9s backwards;
}
@keyframes optIn { from { opacity: 0; transform: translateY(8px); } }
.optchip b {
  display: block; color: var(--accent); font-size: 11px;
  text-transform: uppercase; letter-spacing: .07em; margin-bottom: 3px;
}
/* the two-row mini-sheet: chords column-aligned OVER the words, like the
   real sheet — monospace + pre keeps the columns honest */
.optchip .optch {
  display: block; font-style: normal; font-family: var(--mono);
  font-size: 12.5px; line-height: 1.3; color: var(--chord); font-weight: 600;
  white-space: pre; overflow: hidden; text-overflow: ellipsis;
}
.optchip span {
  display: block; font-family: var(--mono); font-size: 12.5px; line-height: 1.3;
  color: var(--text); white-space: pre; overflow: hidden; text-overflow: ellipsis;
}
.optchip:hover { border-color: var(--accent); background: var(--panel2); }
/* armed = the section is complete: the choice is live NOW */
.flowopts.armed .optchip { border-style: solid; border-color: var(--accent-dim); }
.flowopts.armed .optlbl { color: var(--accent); }
.pill {
  font-size: 12px; padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--dim);
}
.pill.live { border-color: var(--accent); color: var(--accent); animation: pulse 1.6s infinite; }
@keyframes pulse { 50% { opacity: .55; } }
.jumpflash {
  position: fixed; top: calc(var(--barh) + 12px); left: 50%; transform: translateX(-50%);
  background: var(--accent-dim); color: var(--on-accent-dim); padding: 8px 18px; border-radius: 999px;
  font-size: 14px; opacity: 0; pointer-events: none; transition: opacity .25s; z-index: 20;
}
.jumpflash.show { opacity: 1; }

/* ---------- editor ---------- */
.editgrid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 0;
  height: calc(100vh - var(--barh));
}
.editleft { display: flex; flex-direction: column; border-right: 1px solid var(--border); min-width: 0; }
.editleft .fields { display: flex; gap: 8px; padding: 10px; border-bottom: 1px solid var(--border); }
.editleft .fields input { flex: 1; min-width: 0; }
#src {
  flex: 1; resize: none; border: 0; border-radius: 0; background: var(--bg);
  font-family: var(--mono); font-size: 14px; line-height: 1.35; white-space: pre; overflow: auto;
}
.editright { display: flex; flex-direction: column; min-width: 0; }
.preview { flex: 1; overflow: auto; }
.preview .sheet { font-size: 14px; padding-bottom: 40px; }
.chat { border-top: 1px solid var(--border); display: flex; flex-direction: column; height: 40%; }
.chat .msgs { flex: 1; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 8px; }
.chat .msg { max-width: 85%; padding: 7px 11px; border-radius: 10px; font-size: 13.5px; white-space: pre-wrap; }
.chat .msg.user { align-self: flex-end; background: var(--accent-dim); color: var(--on-accent-dim); }
.chat .msg.ai { align-self: flex-start; background: var(--panel2); }
.chat .msg.sys { align-self: center; color: var(--dim); font-size: 12px; background: none; }
.chat form { display: flex; gap: 8px; padding: 10px; border-top: 1px solid var(--border); }
.chat input { flex: 1; }

/* ---------- paste / convert overlay ---------- */
.overlay {
  position: fixed; inset: 0; background: var(--scrim); z-index: 40;
  display: flex; align-items: center; justify-content: center;
}
.overlay .box {
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  width: min(760px, 92vw); padding: 18px; display: flex; flex-direction: column; gap: 12px;
}
.overlay textarea { height: 320px; font-family: var(--mono); font-size: 13px; white-space: pre; }
.overlay .row { display: flex; gap: 10px; justify-content: flex-end; align-items: center; }
.hidden { display: none !important; }
.spin { color: var(--accent); }

/* ---------- mobile: bottom tabs, fit-to-width sheet, floating mini-HUD ---------- */
.mtabbar { display: none; }
.minihud { display: none; }

@media (max-width: 900px) {
  /* the performance view owns the whole phone screen; every other page scrolls normally */
  body.playpage { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
  header.bar { flex-wrap: wrap; gap: 6px; padding: 8px 10px; position: static; flex: none; height: auto; min-height: 0; }
  header.bar .meta { display: none; }
  button { padding: 8px 10px; font-size: 13px; }
  .sideToggle, .sideHandle { display: none !important; }

  /* one view at a time: the sheet, or ONE tracking card, chosen by the tabs.
     position:relative keeps child offsets sheet-relative for scrolling */
  body.playpage .sheet { position: relative; flex: 1; min-height: 0; margin: 0; padding: 12px 10px 40vh; }
  .side {
    position: static; width: 100%; flex: 1; min-height: 0;
    border-left: none; display: none; box-shadow: none;
  }
  body.playpage:not([data-mtab="sheet"]) .sheet { display: none; }   /* play page only: the editor's preview is a .sheet too */
  body:not([data-mtab="sheet"]) .side { display: flex; flex-direction: column; }
  .side .card, .side details { display: none !important; }
  body[data-mtab="words"] #cardWords { display: flex !important; flex: 1; flex-direction: column; }
  body[data-mtab="chords"] #cardChords { display: flex !important; flex: 1; flex-direction: column; }
  body[data-mtab="rhythm"] #cardRhythm { display: block !important; }

  .mtabbar {
    display: flex; flex: none; z-index: 30;
    background: var(--panel); border-top: 1px solid var(--border);
    padding: 6px 8px calc(6px + env(safe-area-inset-bottom));
    gap: 6px;
  }
  .mtabbar button { flex: 1; border-radius: 8px; padding: 10px 0; font-size: 13px; color: var(--dim); }
  .mtabbar button.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

  /* live-detection peek floating over the sheet */
  body[data-mtab="sheet"] .minihud {
    display: block; position: fixed; right: 8px;
    bottom: calc(64px + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--panel) 95%, transparent); border: 1px solid var(--border);
    border-radius: 999px; padding: 7px 14px; font-size: 13px; z-index: 25;
    max-width: 70vw; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  }
  .minihud b { color: var(--chord); }
  .minihud #mhWord { color: var(--accent); }
  .minihud.min { padding: 7px 10px; }
  .minihud.min #mhWord, .minihud.min .dim { display: none; }

  .jumpflash { top: auto; bottom: calc(110px + env(safe-area-inset-bottom)); }
  .capoctl { font-size: 12px; }
  /* editor stacks vertically */
  .editgrid { grid-template-columns: 1fr; grid-template-rows: auto auto; height: auto; min-height: calc(100dvh - 60px); }
  .editleft { border-right: none; border-bottom: 1px solid var(--border); }
  /* stacked: the source and the preview each get real height (percent rows of an auto grid collapsed the preview to nothing) */
  #src { min-height: 42vh; }
  .preview { min-height: 40vh; }
  .chat { height: auto; flex: none; }
}

/* ---------- fretboard page ---------- */
.fbwrap { max-width: 1400px; margin: 0 auto; padding: 14px 18px 40px; }
.fbctl { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; font-size: 13px; color: var(--dim); margin: 6px 0 10px; }
.fbctl label { display: inline-flex; align-items: center; gap: 6px; }
.fbctl select, .fbctl input[type=range] { background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 5px 8px; font-size: 13px; }
.fbctl input[type=range] { padding: 0; width: 90px; }
.fbctl .chk input { accent-color: var(--accent); }
.fbctl button { padding: 5px 10px; font-size: 13px; }
.fbsep { width: 1px; height: 22px; background: var(--border); }
.fbboard { overflow-x: auto; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 10px 6px; }
.fbboard svg { width: 100%; min-width: 900px; height: auto; display: block; font-family: system-ui, sans-serif; }
.fb-wood { fill: color-mix(in srgb, var(--panel2) 70%, var(--chord) 8%); stroke: var(--border); }
.fb-nut { fill: var(--dim); }
.fb-fret { stroke: var(--border); stroke-width: 2; }
.fb-inlay { fill: color-mix(in srgb, var(--dim) 45%, transparent); }
.fb-fretnum { fill: var(--dim); font-size: 11px; }
.fb-string { stroke: var(--dim); opacity: .8; }
.fb-open { fill: var(--dim); font-size: 12px; font-weight: 600; }
.fb-dot { cursor: pointer; }
.fb-dot circle { fill: color-mix(in srgb, var(--panel) 80%, transparent); stroke: transparent; stroke-width: 2; transition: r .12s; }
.fb-dot text { font-size: 10px; fill: var(--dim); pointer-events: none; }
.fb-dot.off circle { opacity: .18; } .fb-dot.off text { opacity: 0; }
.fb-dot.scale circle { fill: color-mix(in srgb, var(--accent) 22%, var(--panel)); stroke: color-mix(in srgb, var(--accent) 60%, transparent); }
.fb-dot.scale text { fill: var(--text); }
.fb-dot.root circle { fill: var(--accent); } .fb-dot.root text { fill: var(--on-accent); font-weight: 700; }
.fb-dot.cand circle { stroke: var(--chord); stroke-width: 3; opacity: 1; } .fb-dot.cand text { opacity: 1; fill: var(--text); }
.fb-dot.guess circle { fill: var(--chord); stroke: var(--chord); opacity: 1; } .fb-dot.guess text { fill: var(--on-accent); font-weight: 700; opacity: 1; }
.fb-dot.target circle { stroke: var(--tabline); stroke-width: 4; stroke-dasharray: 4 3; opacity: 1; } .fb-dot.target text { opacity: 1; fill: var(--text); }
.fb-dot.truth circle { stroke: var(--accent); stroke-width: 4; opacity: 1; }
.fbstatus { display: flex; flex-wrap: wrap; align-items: center; gap: 18px; margin: 12px 0; font-size: 15px; }
.fbheard b { font-size: 26px; color: var(--chord); margin-right: 6px; }
.fbguess { flex: 1; min-width: 260px; }
.fbfeedback button { padding: 6px 12px; font-size: 13px; }
.fbtabs { margin: 6px 0 10px; }
.fbpanel { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 14px 18px; font-size: 14px; box-shadow: var(--shadow); }
.fbpanel.hidden { display: none; }
.fbprofile { font-size: 12.5px; margin-top: 6px; }
.trainbig { font-size: 20px; margin: 10px 0; }
.trainlist { padding-left: 22px; line-height: 1.7; }
.trainlist li.now { color: var(--chord); font-weight: 600; }
.trainlist li.done { color: var(--dim); }
.analysis table { border-collapse: collapse; font-size: 12px; font-family: var(--mono); margin-top: 8px; }
.analysis th, .analysis td { border: 1px solid var(--border); padding: 3px 7px; text-align: right; }
.analysis th.hot { color: var(--chord); }
.analysis td:first-child, .analysis th:first-child { text-align: left; }
.samplelist { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.samplerow { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; font-size: 13px; padding: 6px 10px; background: var(--panel2); border-radius: 8px; }
.samplerow button { padding: 3px 8px; font-size: 12px; }
.fbheard b.faded { opacity: .45; }
.fb-dot.guess circle { filter: drop-shadow(0 0 6px var(--chord)); transition: r .15s, fill-opacity .15s, stroke-width .15s; }
.fb-dot.ringing circle { fill: var(--chord); stroke: transparent; opacity: 1; } .fb-dot.ringing text { fill: var(--on-accent); font-weight: 700; opacity: 1; }
.fb-dot.latest circle { stroke: var(--accent); filter: drop-shadow(0 0 7px var(--accent)); }

.dbggrid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.dbggrid .wide { grid-column: 1 / -1; }
.dbggrid h4 { margin: 4px 0; font-size: 12px; color: var(--dim); text-transform: uppercase; letter-spacing: .06em; }
.dbggrid pre { margin: 0; background: var(--panel2); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; font: 12px/1.45 var(--mono); min-height: 60px; max-height: 220px; overflow: auto; white-space: pre; }

/* ---- string lab ---- */
.stnotes { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.strow { display: grid; grid-template-columns: 52px 170px 1fr 90px 110px; gap: 10px; align-items: center; padding: 6px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel2); font-size: 14px; }
.strow.latest { border-color: var(--accent); }
.strow b { font-size: 18px; color: var(--chord); }
.stmap { overflow-x: auto; margin-top: 8px; }
.stmap table { border-collapse: collapse; font: 12px/1.2 var(--mono); }
.stmap th { color: var(--dim); font-weight: 500; padding: 4px 6px; text-align: center; white-space: nowrap; }
.stmap td { padding: 4px 5px; text-align: center; border: 1px solid var(--border); min-width: 44px; }
.stmap td.none { color: var(--dim); opacity: .5; }
.stmap td.sharp { background: color-mix(in srgb, var(--danger) calc(var(--mag) * 70%), var(--panel2)); }
.stmap td.flat { background: color-mix(in srgb, var(--accent) calc(var(--mag) * 70%), var(--panel2)); }
.fb-dot.measured circle { stroke: var(--dim); stroke-opacity: .6; stroke-dasharray: 2 2; }
#mapUseCentres.on { border-color: var(--accent); color: var(--accent); }

/* ---- model training dashboard ---- */
.trcards { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 6px 0 14px; }
.trcard { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; box-shadow: var(--shadow); }
.trcard .k { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--dim); }
.trcard .v { font-size: 24px; font-weight: 600; margin: 4px 0 2px; font-variant-numeric: tabular-nums; color: var(--text); }
.trcard .s { font-size: 12px; color: var(--dim); }
.trpage .fbpanel { margin-bottom: 12px; }
.trchart svg { min-width: 700px; }
.trchart .grid { stroke: var(--border); stroke-width: 1; }
.trchart .ref { stroke: var(--dim); stroke-dasharray: 5 4; }
.trchart .tick { font: 11px var(--mono); fill: var(--dim); }
.trchart .lbl { font: 12px var(--mono); fill: var(--text); }
.trpage .legend { display: flex; flex-wrap: wrap; gap: 6px 18px; font: 12px var(--mono); color: var(--dim); margin: 8px 2px 0; }
.trpage .legend i { display: inline-block; width: 12px; height: 12px; border-radius: 2px; vertical-align: -1px; margin-right: 6px; }
.tablewrap { overflow-x: auto; }
.trtable { border-collapse: collapse; width: 100%; font: 13px var(--mono); font-variant-numeric: tabular-nums; }
.trtable th, .trtable td { text-align: right; padding: 6px 10px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.trtable th { color: var(--dim); font-weight: 500; font-size: 12px; }
.trtable th:first-child, .trtable td:first-child, .trtable td:nth-child(2), .trtable td:nth-child(3), .trtable td:nth-child(4) { text-align: left; }
.trtable tr.avg td { font-weight: 600; border-top: 2px solid var(--border); }
.trhelp h4 { margin: 0 0 6px; font-size: 13px; text-transform: uppercase; letter-spacing: .06em; color: var(--dim); }
.trhelp ul { padding-left: 20px; margin: 6px 0; } .trhelp li { margin: 4px 0; }

/* ---- training dashboard on phones ---- */
@media (max-width: 900px) {
  header.bar .pill { margin-left: auto; }
}
@media (max-width: 700px) {
  .trpage .fbwrap { padding: 10px 10px 40px; }
  .trpage .fbpanel { padding: 10px 12px; }
  .trcards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .trcard { padding: 9px 10px; min-width: 0; }
  .trcard .v { font-size: 21px; }
  .trcard .s { overflow-wrap: anywhere; }
  .trpage .fbctl { gap: 8px 12px; }
  .trpage .fbctl label { flex: 1 1 100%; min-width: 0; }
  .trpage .fbctl select { width: 100%; min-width: 0; font-size: 16px; padding: 9px 10px; }
  .trpage .fbctl button { font-size: 16px; padding: 9px 14px; }
  .trpage .fbctl .mono { overflow-wrap: anywhere; }
  .trpage .trchart { padding: 6px 2px; }
  .trpage .trchart svg { min-width: 0; }
  .trpage .legend { gap: 6px 14px; }
  .trtable { font-size: 12px; }
  .trtable th, .trtable td { padding: 7px 5px; }
  .trtable th { white-space: normal; vertical-align: bottom; line-height: 1.2; }
  /* phones keep fold, status and the four scores; train, test, epochs, best epoch and time go */
  .trtable th:nth-child(3), .trtable td:nth-child(3),
  .trtable th:nth-child(4), .trtable td:nth-child(4),
  .trtable th:nth-child(5), .trtable td:nth-child(5),
  .trtable th:nth-child(6), .trtable td:nth-child(6),
  .trtable th:nth-child(11), .trtable td:nth-child(11) { display: none; }
  .trtable th:first-child, .trtable td:first-child { position: sticky; left: 0; background: var(--panel); }
  .trhelp ul { padding-left: 18px; }
}

/* ---------- nav (session.js): logged-out bar links ---------- */
.ssnav { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ssnav .ssWho { color: var(--dim); font-size: 13px; padding: 0 2px; }
.ssnav .backlink.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.ssnav .backlink.primary:hover { background: var(--accent-dim); border-color: var(--accent-dim); }

/* ---------- auth pages: signup / verify / login / reset ----------
   The split shell: a brand panel on the left (the tied scroll mark, the
   headline, a rotating line and the Leonardo illustration on the hero
   gradient) and the card on the right. One column under 861 px, with
   minmax(0, 1fr) tracks so no input's intrinsic width can widen the page. */
body.authpage { min-height: 100vh; }
.auth { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); min-height: 100vh; }
.auth-brand {
  position: relative; display: flex; flex-direction: column; gap: 26px; min-width: 0; overflow: hidden;
  padding: 40px 48px 44px; color: var(--on-dark); background: var(--hero-grad);
}
.auth-logo { display: inline-flex; align-items: center; gap: 10px; font-weight: 800; font-size: 21px; letter-spacing: -0.01em; color: var(--on-dark); text-decoration: none; width: fit-content; }
.auth-logo .mark { width: 32px; height: 32px; object-fit: contain; flex: none; }
.auth-logo .name { font-weight: 800; }
.auth-logo .name span { color: var(--amber-2); }
.auth-logo:hover { text-decoration: none; opacity: .92; }
.auth-pitch { max-width: 500px; }
.auth-pitch h1 { margin: 0 0 12px; font-size: clamp(24px, 2.6vw, 32px); line-height: 1.18; letter-spacing: -0.02em; font-weight: 800; color: var(--on-dark); }
.auth-pitch h1 em { font-style: normal; color: var(--amber-2); }
.auth-pitch p { margin: 0; font-size: 15.5px; line-height: 1.55; color: color-mix(in srgb, var(--on-dark) 86%, transparent); }
.auth-rotator { min-height: 78px; max-width: 500px; }
.auth-rotator .slide { display: none; margin: 0; font-size: 18px; line-height: 1.4; font-weight: 600; animation: auth-fade .5s ease; }
.auth-rotator .slide.active { display: block; }
@keyframes auth-fade { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
.auth-dots { display: flex; gap: 8px; margin-top: 14px; }
.auth-dots button { width: 10px; height: 10px; padding: 0; border-radius: 50%; border: none; cursor: pointer; background: color-mix(in srgb, var(--on-dark) 35%, transparent); transition: background .15s ease; }
.auth-dots button:hover, .auth-dots button.active { background: var(--on-dark); }
.auth-dots button:focus-visible { outline: 2px solid var(--on-dark); outline-offset: 2px; }
.auth-art { margin: auto 0 0; max-width: 560px; border-radius: var(--radius-lg); overflow: hidden; border: 1px solid color-mix(in srgb, var(--on-dark) 28%, transparent); box-shadow: var(--shadow-lift); background: var(--panel2); }
.auth-art img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; object-position: 25% 45%; }
.auth-form { display: grid; place-items: center; grid-template-columns: minmax(0, 1fr); min-width: 0; padding: 40px 24px; background: var(--bg); }
.auth .authwrap { width: 100%; max-width: 440px; margin: 0 auto; padding: 0; }
.auth .authcard { min-width: 0; }
@media (max-width: 860px) {
  .auth { grid-template-columns: minmax(0, 1fr); min-height: 0; }
  .auth-brand { padding: 20px 18px 22px; gap: 16px; }
  .auth-pitch h1 { font-size: 21px; margin-bottom: 8px; }
  .auth-pitch p { font-size: 14.5px; }
  .auth-rotator { display: none; }
  .auth-art { max-width: none; margin: 4px 0 0; }
  .auth-art img { aspect-ratio: 5 / 2; object-position: 20% 28%; }
  .auth-form { padding: 22px 16px 44px; }
  .auth .authcard { box-shadow: var(--shadow); }
}
@media (prefers-reduced-motion: reduce) { .auth-rotator .slide { animation: none; } }
.authwrap { max-width: 440px; margin: 7vh auto 10vh; padding: 0 16px; }
.authcard {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 30px 28px; display: flex; flex-direction: column; gap: 16px; box-shadow: var(--shadow-lift);
}
.authcard h2 { margin: 0; font-size: 24px; font-weight: 800; letter-spacing: -0.01em; }
.authcard p.sub { margin: -10px 0 0; color: var(--dim); font-size: 14px; line-height: 1.55; }
.authcard form { display: flex; flex-direction: column; gap: 14px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field label { font-size: 12.5px; font-weight: 600; color: var(--dim); letter-spacing: .02em; }
.field input {
  background: var(--panel); color: var(--text); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm); padding: 11px 12px; font-size: 16px; width: 100%; font-family: inherit;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field input:focus { outline: 2px solid var(--focus); outline-offset: 0; border-color: var(--accent); }
.authcard button.primary { width: 100%; padding: 12px 16px; font-size: 15.5px; border-radius: var(--radius); margin-top: 4px; }
.authcard button.primary:hover { transform: translateY(-1px); }
.authcard button.primary:disabled { opacity: .6; cursor: default; transform: none; box-shadow: none; }
.authcard > button:not(.primary) { width: 100%; padding: 11px 16px; font-size: 14.5px; border-radius: var(--radius); }
.strength { height: 5px; border-radius: 3px; background: var(--panel2); overflow: hidden; }
.strength i { display: block; height: 100%; width: 0%; background: var(--danger); transition: width .15s, background .15s; }
.strength.ok i { background: var(--amber); }
.strength.strong i { background: var(--accent); }
.hint { font-size: 12.5px; color: var(--dim); }
.formerr {
  color: var(--danger); font-size: 13.5px; background: color-mix(in srgb, var(--danger) 10%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent); border-radius: var(--radius-sm); padding: 10px 12px;
}
.formmsg {
  color: var(--text); font-size: 13.5px; background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent); border-radius: var(--radius-sm); padding: 10px 12px;
}
.authcard .altrow { display: flex; justify-content: space-between; gap: 10px; flex-wrap: wrap; font-size: 13.5px; padding-top: 4px; border-top: 1px solid var(--border); margin-top: 2px; }
.authcard .altrow a { color: var(--accent); font-weight: 600; }
.authcard .altrow .dim { color: var(--dim); }
.authcard .linkbtn { background: none; border: none; color: var(--accent); padding: 0; font-size: 13.5px; font-weight: 600; cursor: pointer; }
.authcard .linkbtn:hover { text-decoration: underline; border: none; }

/* ---------- account page ---------- */
.acctwrap { max-width: 720px; margin: 0 auto; padding: 20px 16px 60px; }
.tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 16px; border-bottom: 1px solid var(--border); padding-bottom: 10px; }
.tabs button { border-radius: var(--radius-pill); padding: 7px 15px; font-size: 13.5px; color: var(--dim); background: var(--panel); }
.tabs button.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.tabpanel { display: none; flex-direction: column; gap: 16px; }
.tabpanel.on { display: flex; }
.acctcard {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 18px 20px; display: flex; flex-direction: column; gap: 12px; box-shadow: var(--shadow);
}
.acctcard h3 { margin: 0; font-size: 15px; }
.acctcard p.sub { margin: -6px 0 0; color: var(--dim); font-size: 12.5px; }
.acctcard .row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.qrbox { background: var(--qr-bg); padding: 10px; border-radius: 10px; display: inline-block; width: fit-content; }
.reccodes {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px;
  font-family: var(--mono); font-size: 14px; background: var(--panel2);
  border: 1px solid var(--border); border-radius: 8px; padding: 12px;
}
.sessrow {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  background: var(--panel2); border: 1px solid var(--border); border-radius: 10px; font-size: 13.5px;
}
.sessrow .grow { flex: 1; min-width: 0; }
.sessrow .grow .k { font-weight: 600; }
.sessrow .grow .d { color: var(--dim); font-size: 12px; overflow-wrap: anywhere; }
.sessrow .pill.live { border-color: var(--accent); color: var(--accent); }
.plancard .plan { font-size: 22px; font-weight: 700; }
.plancard .status { color: var(--dim); font-size: 13px; }
.dangerzone { border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); }

/* ---------- library page ---------- */
.libtoolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 14px 0; }
.libtoolbar input[type=text] { flex: 1; min-width: 160px; font-size: 16px; }
.libempty { color: var(--dim); text-align: center; padding: 48px 16px; background: var(--panel); border: 1px dashed var(--border-strong); border-radius: var(--radius-lg); }
.libempty-mark { display: block; margin: 0 auto 14px; width: 48px; height: 48px; object-fit: contain; opacity: .85; }
.toast {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  background: var(--panel2); border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 16px; display: flex; gap: 12px; align-items: center; font-size: 13.5px;
  box-shadow: var(--shadow-lift); z-index: 30;
}
.toast button { padding: 5px 10px; font-size: 12.5px; }

/* ---------- list pages (library, practice sessions): CRM layout ----------
   Page header row = the page bar (title left, primary actions right, full width).
   Toolbar row = search left; result count, Grid/Cards toggle and page size right.
   Results fill the full content width with 24 px gutters, left-aligned; the
   pagination bar sits at the bottom of the results area. On desktop the results
   area takes the remaining viewport height and scrolls inside itself (sticky grid
   header); on phones the page scrolls normally. */
.pagetitle { display: none; font-size: 19px; font-weight: 800; letter-spacing: -0.01em; color: var(--text); white-space: nowrap; }
body.listpage .wrap { max-width: none; margin: 0; padding: 16px 24px 20px; }
body.listpage .libtoolbar { margin: 0 0 12px; gap: 10px 12px; }
body.listpage .libtoolbar input[type=search] { flex: 0 1 420px; min-width: 200px; font-size: 15px; padding: 8px 12px; }
body.listpage .formerr { margin-bottom: 12px; }
body.listpage .practintro { margin: 0 0 12px; }
.libviewctl { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-left: auto; }
.lvcount { color: var(--dim); font-size: 13px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lvcount:empty { display: none; }
.viewtoggle { display: inline-flex; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); padding: 2px; background: var(--panel2); }
.viewtoggle .viewBtn { display: inline-flex; align-items: center; gap: 6px; border: none; background: transparent; padding: 5px 12px; font-size: 13px; border-radius: 7px; color: var(--dim); }
.viewtoggle .viewBtn svg { width: 16px; height: 16px; }
.viewtoggle .viewBtn:hover { border: none; color: var(--text); }
.viewtoggle .viewBtn.on { background: var(--panel); color: var(--text); font-weight: 600; box-shadow: var(--shadow); }
.pagesizesel { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--dim); white-space: nowrap; }
.pagesizesel select { font-size: 13px; padding: 6px 8px; width: auto; }

.lvresults { display: flex; flex-direction: column; min-width: 0; }
.lvresults[data-view="grid"] { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; }
.lvresults .libempty { margin: 0; border: none; border-radius: 0; }
.lvresults[data-view="cards"] .libempty { border: 1px dashed var(--border-strong); border-radius: var(--radius-lg); }
.libpagebar { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 10px 14px; border-top: 1px solid var(--border); background: var(--panel); }
.lvresults[data-view="cards"] .libpagebar { border: 1px solid var(--border); border-radius: var(--radius-sm); margin-top: 12px; }
.libpagebar .pageinfo { color: var(--dim); font-size: 13px; font-variant-numeric: tabular-nums; }
.libpagebar .pagebtns { display: inline-flex; gap: 8px; }
.libpagebar button { padding: 6px 12px; font-size: 13px; }

/* the data grid */
.gridwrap { overflow: auto; min-width: 0; }
.datagrid { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13.5px; }
.datagrid th, .datagrid td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.datagrid th:first-child, .datagrid td:first-child { padding-left: 16px; }
.datagrid thead th {
  position: sticky; top: 0; z-index: 2; background: var(--panel2); color: var(--dim);
  font-size: 11.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; white-space: nowrap;
  border-bottom: 1px solid var(--border-strong);
}
.datagrid th .sortBtn {
  display: inline-flex; align-items: center; gap: 5px; border: none; background: none; padding: 2px 0; margin: -2px 0;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; border-radius: 4px;
}
.datagrid th .sortBtn:hover { color: var(--text); border: none; }
.datagrid th.on .sortBtn { color: var(--accent); }
.datagrid th .sortmark { width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-bottom: 5px solid currentColor; opacity: .35; }
.datagrid th[aria-sort="ascending"] .sortmark { opacity: 1; }
.datagrid th[aria-sort="descending"] .sortmark { opacity: 1; border-bottom: none; border-top: 5px solid currentColor; }
.datagrid tbody tr { transition: background .1s ease; }
.datagrid tbody tr:hover, .datagrid tbody tr:focus-within { background: color-mix(in srgb, var(--accent-soft) 60%, var(--panel)); }
.datagrid tbody tr:last-child td { border-bottom: none; }
.datagrid td { color: var(--dim); }
.datagrid td.c-main { color: var(--text); font-weight: 600; }
.datagrid td.c-main .t { display: block; max-width: 44ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.datagrid .c-num { text-align: right; font-variant-numeric: tabular-nums; width: 1%; white-space: nowrap; }
.datagrid .c-date { white-space: nowrap; width: 1%; font-variant-numeric: tabular-nums; }
.datagrid .c-licks .licks { display: block; max-width: 48ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.datagrid .c-licks .arrow { color: var(--accent); padding: 0 2px; }
.datagrid th.c-actions, .datagrid td.c-actions { text-align: right; width: 1%; white-space: nowrap; padding-right: 16px; }
.datagrid .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.rowactions { display: inline-flex; align-items: center; justify-content: flex-end; gap: 6px; }
.rowactions button { padding: 4px 10px; font-size: 12.5px; min-height: 30px; }
.rowactions .cardmenu > summary { width: 30px; height: 30px; font-size: 16px; }

/* Cards view: tiles in a responsive card layout sharing the same actions as the grid. */
.tilegrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; min-width: 0; }
.tilecard {
  display: flex; flex-direction: column; gap: 6px; padding: 16px; min-width: 0;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
  transition: box-shadow .15s ease, border-color .15s ease;
}
.tilecard:hover { box-shadow: var(--shadow-lift); border-color: var(--border-strong); }
.tilecard .gt { font-size: 15px; font-weight: 600; overflow-wrap: anywhere; }
.tilecard .ga, .tilecard .gs, .tilecard .gu { color: var(--dim); font-size: 12.5px; overflow-wrap: anywhere; }
.tilecard .gmeta { flex: 1; display: flex; flex-direction: column; gap: 2px; margin-bottom: 6px; }
.tilecard .gactions { display: flex; align-items: center; gap: 8px; margin-top: auto; }
.tilecard .gactions .playBtn, .tilecard .gactions .continueBtn { flex: 1; }
.cardmenu { position: relative; }
.cardmenu > summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--panel); font-size: 18px; line-height: 1; color: var(--text); }
.cardmenu > summary::-webkit-details-marker, .cardmenu > summary::marker { display: none; content: ''; }
.cardmenu > summary:hover, .cardmenu[open] > summary { border-color: var(--accent); color: var(--accent); }
.cardmenu .menu {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 6; min-width: 150px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lift); display: flex; flex-direction: column; gap: 2px; padding: 6px;
}
.cardmenu .menu button { text-align: left; border: none; background: none; padding: 8px 10px; border-radius: 7px; font-size: 13.5px; min-height: 0; }
.cardmenu .menu button:hover { background: var(--panel2); border: none; }
.cardmenu .menu button.danger:hover { background: color-mix(in srgb, var(--danger) 12%, var(--panel2)); }
/* the last rows' menus open upwards so the results panel does not clip them */
.datagrid tbody tr:nth-last-child(-n+2):not(:first-child) .cardmenu .menu { top: auto; bottom: calc(100% + 6px); }

@media (min-width: 901px) {
  body.listpage header.bar { padding: 10px 24px; }
  body.has-shell.listpage .pagetitle { display: block; }
  body.listpage .wrap { display: flex; flex-direction: column; height: calc(100dvh - var(--barh)); }
  body.listpage .libtoolbar, body.listpage .formerr, body.listpage .practintro { flex: none; }
  body.listpage .lvresults { flex: 1; min-height: 0; }
  body.listpage .lvresults .gridwrap, body.listpage .lvresults .tilegrid { flex: 1; min-height: 0; overflow: auto; }
  body.listpage .lvresults .tilegrid { align-content: start; padding: 2px; }
  body.listpage .lvresults .libempty, body.listpage .lvresults .pagebarhost { flex: none; }
}

/* phones: the grid degrades to stacked rows with labels; never a sideways page scroll */
@media (max-width: 700px) {
  body.listpage .wrap { padding: 12px 12px 20px; }
  body.listpage .libtoolbar input[type=search] { flex: 1 1 100%; font-size: 16px; }
  .libviewctl { width: 100%; justify-content: space-between; gap: 8px; }
  .lvcount { order: 3; width: 100%; }
  .pagesizesel select { font-size: 16px; }
  .gridwrap { overflow: visible; }
  .datagrid, .datagrid tbody, .datagrid tr, .datagrid td { display: block; }
  .datagrid thead { display: none; }
  .datagrid tbody tr { padding: 10px 14px; border-bottom: 1px solid var(--border); }
  .datagrid tbody tr:last-child { border-bottom: none; }
  .datagrid td, .datagrid td:first-child { display: flex; gap: 10px; align-items: baseline; padding: 2px 0; border: none; min-width: 0; }
  .datagrid td:not(.c-main):not(.c-actions)::before { content: attr(data-label); flex: 0 0 96px; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--dim); }
  .datagrid td:empty { display: none; }   /* a blank Section / Artist earns no label on a phone */
  .datagrid td.c-main { font-size: 15.5px; padding-bottom: 4px; }
  .datagrid td.c-main .t { white-space: normal; max-width: none; }
  .datagrid td.c-num, .datagrid td.c-date { text-align: left; width: auto; white-space: normal; }
  .datagrid td.c-licks .licks { white-space: normal; max-width: none; }
  .datagrid td.c-actions { display: block; width: auto; padding: 8px 0 0; text-align: left; white-space: normal; }
  .rowactions { display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 8px; }
  .rowactions button { min-height: 40px; font-size: 14px; padding: 7px 14px; }
  .rowactions .cardmenu > summary { width: 40px; height: 40px; }
  .rowactions .cardmenu .menu { right: auto; left: 0; }
  .datagrid tbody tr:nth-last-child(-n+2):not(:first-child) .cardmenu .menu { top: calc(100% + 6px); bottom: auto; }
  .tilegrid { grid-template-columns: 1fr; }
  .libpagebar { flex-wrap: wrap; }
  .libpagebar button { min-height: 40px; font-size: 14px; }
}

@media (max-width: 480px) {
  .authwrap { margin: 3vh auto 6vh; }
  .authcard { padding: 22px 18px; border-radius: var(--radius); }
  .reccodes { grid-template-columns: 1fr; }
  /* library rows: title first, action buttons wrap onto their own row —
     the library page's cards carry one more button (Export) than the
     3-button rows .songcard was designed for on index.html */
  .songcard { flex-wrap: wrap; row-gap: 8px; }
  .songcard .grow { flex-basis: 100%; }
}

/* ---- learn page: the tab that waits for the right note ---- */
.learnpage .songlist { margin-bottom: 14px; }
.addtab h4 { margin: 0 0 6px; font-size: 13px; text-transform: uppercase; letter-spacing: .06em; color: var(--dim); }
.addrow { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; align-items: center; }
.addrow input { flex: 1 1 180px; min-width: 0; }
.addtab textarea { width: 100%; box-sizing: border-box; font: 13px/1.4 var(--mono); white-space: pre; overflow: auto; }
.nowpanel { position: sticky; top: 0; z-index: 5; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 10px 14px; margin-bottom: 12px; }
.nowhead { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.nowhead .t { font-weight: 600; font-size: 16px; }
.nowhead .a { font-size: 12px; }
.nowmain { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 8px 0; }
.nownote, .nowheard { background: var(--panel2); border: 1px solid var(--border); border-radius: 10px; padding: 8px 12px; min-width: 0; }
.nownote .k, .nowheard .k { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--dim); }
.nownote .v, .nowheard .v { font-size: 30px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.15; margin: 2px 0; overflow-wrap: anywhere; }
.nownote .v { color: var(--accent); }
.nownote.finished .v { color: var(--chord); }
.nowheard.ok .v { color: var(--accent); }
.nowheard.bad .v { color: var(--danger); }
.nownote .s, .nowheard .s { font-size: 13px; }
.nowctl { margin: 4px 0 0; }
.tabsheet { display: flex; flex-direction: column; gap: 10px; }
.tabsheet .txt { color: var(--dim); font-size: 13px; margin: 2px 4px; white-space: pre-wrap; }
.tabsys { margin: 0; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 10px 12px 10px 0; overflow-x: auto; font: 15px/1.45 var(--mono); color: var(--dim); }
.tabsys .lab { position: sticky; left: 0; background: var(--panel); color: var(--dim); padding: 0 1px 0 12px; }   /* carries the left padding so nothing scrolls under it */
.tabsys .n { color: var(--text); font-weight: 600; border-radius: 3px; padding: 0 1px; margin: 0 -1px; }
.tabsys .n.done { color: var(--accent-dim); font-weight: 500; }
.tabsys .n.cur { background: var(--accent); color: var(--on-accent); animation: pulse 1.6s infinite; }
.tabsys .n.bad { background: var(--danger); color: var(--on-accent); animation: none; }
.tabsys .n.done.slip { color: var(--chord); }                 /* right note, wrong string */
.nowheard .stringmsg { color: var(--accent); min-height: 1.2em; }
.nowheard .stringmsg.slip { color: var(--chord); }
@media (max-width: 700px) {
  .nowpanel { padding: 8px 10px; border-radius: 10px; }
  .nownote .v, .nowheard .v { font-size: 24px; }
  .nowctl button { font-size: 16px; padding: 9px 12px; min-width: 44px; }
  .nowctl .lbl { display: none; }
  .nowctl select { font-size: 16px; }
  .nowctl input[type=range] { width: 70px; }
  .addrow input, .addtab textarea { font-size: 16px; }
  .tabsys { font-size: 14px; padding: 8px 8px 8px 0; }
  .tabsys .lab { padding-left: 8px; }
}

/* ---------- home page pricing block (Phase 2a) ---------- */
.pricingblock { margin-top: 18px; max-width: 420px; }
.pricingblock .plan { font-size: 20px; font-weight: 700; }

/* ---------- app shell (session.js renders it): sidebar on desktop, drawer on phones ----------
   Desktop: a fixed left sidebar (brand, primary links, theme, account, sign out); the page's
   own header.bar keeps its toolbar and drops its brand. Phones: the same panel becomes a
   drawer opened from a burger in the page bar. A drawer rather than a bottom tab bar
   because the play and practice views already own the bottom of a phone screen (mode
   tabs, the "now" panel) and the sheet needs the full height; the drawer costs no
   screen space while performing. */
.shell { display: none; }
.shell-backdrop { display: none; }
.shell-burger { display: none; }
.shell-head { display: flex; align-items: center; gap: 6px; padding: 0 0 12px; }
.shell-brand { display: flex; align-items: center; gap: 9px; font-weight: 800; font-size: 18px; letter-spacing: -0.01em; color: var(--text); padding: 6px 8px 0; min-width: 0; }
.shell-collapse { display: none; }
.shell-avatar { display: none; }
.shell-theme { position: relative; }
.shell-theme .ico { display: none; }
.shell-foot #ssLogout { display: flex; align-items: center; justify-content: center; gap: 8px; }
.shell-foot #ssLogout .ico { width: 18px; height: 18px; flex: none; }
.shell-brand .mark { width: 26px; height: 26px; object-fit: contain; flex: none; }
.shell-brand .name span { color: var(--accent); }
.shell-nav { display: flex; flex-direction: column; gap: 2px; }
.shell-nav a {
  display: flex; align-items: center; gap: 11px; padding: 10px 12px; border-radius: var(--radius-sm);
  color: var(--dim); font-size: 14.5px; font-weight: 600; line-height: 1.3; min-height: 44px;
  transition: background .15s ease, color .15s ease;
}
.shell-nav a svg { width: 20px; height: 20px; flex: none; }
.shell-nav a:hover { background: var(--bg); color: var(--text); }
.shell-nav a.on { background: var(--accent-soft); color: var(--accent); }
.shell-sec { font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--dim); padding: 16px 12px 6px; }
.shell-foot { margin-top: auto; display: flex; flex-direction: column; gap: 10px; padding-top: 14px; border-top: 1px solid var(--border); }
.shell-foot label { font-size: 11.5px; font-weight: 700; color: var(--dim); letter-spacing: .04em; text-transform: uppercase; display: flex; flex-direction: column; gap: 5px; }
.shell-who { font-size: 13px; color: var(--dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 2px; }
.shell-who b { display: block; color: var(--text); font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.shell-foot button { width: 100%; min-height: 40px; }

@media (min-width: 901px) {
  body.has-shell { padding-left: var(--shellw); }
  body.has-shell .shell {
    display: flex; flex-direction: column; position: fixed; left: 0; top: 0; bottom: 0; width: var(--shellw);
    background: var(--panel); border-right: 1px solid var(--border); padding: 16px 12px 14px; z-index: 40; overflow-y: auto; overflow-x: hidden;
  }
  /* the width transition is armed only once the shell is on screen (html.shell-anim), so a remembered
     mini state paints collapsed at once and never animates on load */
  html.shell-anim body.has-shell { transition: padding-left .2s ease; }
  html.shell-anim body.has-shell .shell { transition: width .2s ease, padding .2s ease; }
  html.shell-anim body.has-shell .sheet { transition: left .2s ease; }
  body.has-shell header.bar h1 { display: none; }
  .shell-close { display: none; }
  .shell-collapse {
    display: inline-flex; align-items: center; justify-content: center; flex: none; margin-left: auto;
    width: 32px; height: 32px; padding: 0; border-radius: var(--radius-sm); color: var(--dim); background: var(--panel);
  }
  .shell-collapse svg { width: 18px; height: 18px; transition: transform .2s ease; }
  .shell-collapse:hover { color: var(--accent); }

  /* ---- the mini rail: icons only, about 64 px, brand mark alone at the top, theme + sign out compacted in the foot ---- */
  html.shell-mini { --shellw: 64px; }
  html.shell-mini body.has-shell .shell { padding: 12px 8px 12px; align-items: center; }
  html.shell-mini .shell-head { flex-direction: column; gap: 6px; padding-bottom: 8px; width: 100%; }
  html.shell-mini .shell-brand { padding: 4px 0 0; justify-content: center; }
  html.shell-mini .shell-brand .name { display: none; }
  html.shell-mini .shell-collapse { margin: 0; }
  html.shell-mini .shell-collapse svg { transform: rotate(180deg); }
  html.shell-mini .shell-nav { width: 100%; align-items: center; }
  html.shell-mini .shell-nav a { width: 48px; justify-content: center; padding: 12px 0; gap: 0; }
  html.shell-mini .shell-nav a span { display: none; }
  html.shell-mini .shell-foot { width: 100%; align-items: center; padding-top: 10px; gap: 8px; }
  html.shell-mini .shell-theme { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--dim); background: var(--panel); }
  html.shell-mini .shell-theme:hover { color: var(--accent); border-color: var(--accent); }
  html.shell-mini .shell-theme .lbl { display: none; }
  html.shell-mini .shell-theme .ico { display: block; width: 20px; height: 20px; }
  html.shell-mini .shell-theme .themesel { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; cursor: pointer; }
  html.shell-mini .shell-theme:focus-within { outline: 2px solid var(--focus); outline-offset: 2px; }
  html.shell-mini .shell-who { display: none; }
  html.shell-mini .shell-avatar {
    display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 50%;
    background: var(--accent-soft); color: var(--accent); font-size: 13px; font-weight: 800; letter-spacing: .02em;
  }
  html.shell-mini .shell-foot #ssLogout { width: 40px; min-height: 40px; padding: 0; }
  html.shell-mini .shell-foot #ssLogout span { display: none; }
  /* fixed, full-height views start after the sidebar */
  body.has-shell .sheet { left: var(--shellw); }
  body.has-shell .jumpflash { left: calc(50% + var(--shellw) / 2); }
  body.has-shell .toast { left: calc(50% + var(--shellw) / 2); }
}
@media (max-width: 900px) {
  .shell-burger {
    display: inline-flex; flex-direction: column; justify-content: center; gap: 4px; width: 42px; height: 42px; flex: none;
    padding: 9px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--panel); cursor: pointer; order: -1;
  }
  .shell-burger span { display: block; height: 2px; background: var(--text); border-radius: 2px; }
  body.has-shell header.bar h1 { font-size: 16px; }
  body.has-shell header.bar { row-gap: 8px; }
  body.shell-open { overflow: hidden; }
  body.shell-open .shell-backdrop { display: block; position: fixed; inset: 0; background: var(--scrim); z-index: 59; }
  body.shell-open .shell {
    display: flex; flex-direction: column; position: fixed; left: 0; top: 0; bottom: 0; width: min(300px, 84vw);
    background: var(--panel); border-right: 1px solid var(--border); padding: 16px 12px calc(14px + env(safe-area-inset-bottom));
    z-index: 60; overflow-y: auto; box-shadow: var(--shadow-lift);
  }
  .shell-close { position: absolute; top: 12px; right: 10px; width: 36px; height: 36px; padding: 0; font-size: 20px; line-height: 1; border-radius: var(--radius-sm); }
  .shell-nav a { min-height: 48px; font-size: 16px; }
  .shell-foot button, .themesel { min-height: 44px; font-size: 16px; }
}

/* ---------- Practice v2: sessions list + the session canvas ---------- */
.practintro { margin: 0 0 6px; font-size: 14px; max-width: 70ch; }
.sesscard .licks { margin-top: 2px; }
.sesscard .licks .arrow { color: var(--accent); padding: 0 2px; }
.sesscard .sessmeta { margin-top: 4px; font-variant-numeric: tabular-nums; }
.sessionpage .fbwrap { max-width: 1400px; }
.sessionpage .formerr { margin-bottom: 10px; }
/* The session page fills the viewport: bar, canvas strip, the "now" panel, then the tab — which is the
   only thing that scrolls (inside itself). The page never scrolls; Add lick is a popup, the licks are
   managed in a drawer, so nothing stacks below the tab. */
body.sessionpage { height: 100dvh; display: flex; flex-direction: column; overflow: hidden; }
body.sessionpage header.bar { flex: none; position: static; }
.sessionpage .fbwrap.sessmain { flex: 1; min-height: 0; width: 100%; display: flex; flex-direction: column; padding: 10px 18px 12px; overflow: hidden; }
.sessionpage .formerr { flex: none; }
.sessionpage .canvas { flex: none; margin: 0 0 10px; padding: 10px 14px; }
.sessionpage #trainView { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.sessionpage .nowpanel { position: static; flex: none; margin-bottom: 10px; }
.sessionpage .tabsheet { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 2px 2px 32px; overscroll-behavior: contain; }
.canvashead { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; }
.canvashead .sessname { flex: 1 1 200px; min-width: 0; font-size: 16px; font-weight: 600; }
.canvasbtns { display: inline-flex; gap: 8px; flex: none; margin-left: auto; }
.canvasbtns .cnt { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 6px; margin-left: 4px; border-radius: 999px; background: var(--accent-soft); color: var(--accent); font-size: 12px; font-variant-numeric: tabular-nums; }
/* the strip: the licks in order, at a glance — a chip each; click = jump the cursor to that lick */
.lickstrip { flex: 3 1 320px; min-width: 0; display: flex; gap: 6px; overflow-x: auto; overflow-y: hidden; padding: 2px 0; scrollbar-width: none; }
.lickstrip::-webkit-scrollbar { display: none; }
.lickstrip .lickempty { margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lickchip {
  display: inline-flex; align-items: center; gap: 7px; flex: none; max-width: 220px; padding: 4px 10px 4px 4px;
  background: var(--panel2); border: 1px solid var(--border); border-radius: 999px; color: var(--text); font-weight: 500; font-size: 13px;
}
.lickchip:hover { border-color: var(--accent); }
.lickchip.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.lickchip.notab { opacity: .7; }
.lickchip .num { width: 22px; height: 22px; border-radius: 999px; background: var(--panel); border: 1px solid var(--border-strong); color: var(--dim); font-size: 11.5px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; flex: none; font-variant-numeric: tabular-nums; }
.lickchip.on .num { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.lickchip .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.lickchip .s { color: var(--dim); font-size: 11.5px; font-variant-numeric: tabular-nums; flex: none; }
.lickchip.on .s { color: var(--accent); }
/* the drawer: manage the licks in the flow (reorder, remove, jump). Right-hand panel on desktop, bottom sheet on a phone. */
.drawerback { position: fixed; inset: 0; background: var(--scrim); z-index: 44; }
.lickdrawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(460px, 92vw); z-index: 45;
  background: var(--panel); border-left: 1px solid var(--border); box-shadow: var(--shadow-lift);
  display: flex; flex-direction: column; padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
  transform: translateX(100%); visibility: hidden; transition: transform .22s ease, visibility 0s linear .22s;
}
.lickdrawer.open { transform: none; visibility: visible; transition: transform .22s ease; }
.drawerhead { display: flex; align-items: center; gap: 8px; }
.drawerhead h2 { margin: 0; flex: 1; font-size: 16px; font-weight: 700; }
.drawerhint { margin: 8px 0 0; font-size: 12.5px; }
.licklist { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; margin-top: 10px; padding-right: 2px; }
.lickempty, .tabempty { margin: 4px 0; font-size: 14px; }
.lick {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px; background: var(--panel2);
  border: 1px solid var(--border); border-radius: var(--radius-sm); min-width: 0;
}
.lick.on { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent); }
.lick.notab { opacity: .75; }
.lick .num { flex: none; width: 24px; height: 24px; border-radius: 999px; background: var(--panel); border: 1px solid var(--border-strong); color: var(--dim); font-size: 12px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; font-variant-numeric: tabular-nums; }
.lick.on .num { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.lick .grow { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.lick .t { font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lick .s { font-size: 12px; }
.lickbtns { display: flex; gap: 6px; flex: none; flex-wrap: wrap; justify-content: flex-end; }
.lickbtns button { padding: 4px 9px; font-size: 12.5px; }
/* Add lick: a popup over the canvas (reuses the editor's overlay/box) that scrolls inside itself */
.pickbox { max-height: min(86dvh, 720px); gap: 10px; }
.pickhead { display: flex; gap: 8px 10px; align-items: center; flex-wrap: wrap; }
.pickhead h2 { margin: 0; font-size: 17px; font-weight: 700; }
.pickhead .pickhint { flex: 1; font-size: 12.5px; min-width: 0; }
.pickbox input[type=search] { font-size: 16px; width: 100%; }
.picklist { flex: 1; min-height: 120px; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; padding-right: 2px; }
.pickrow { border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--panel); }
.picksong { width: 100%; text-align: left; display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; border: 0; background: none; padding: 9px 12px; color: var(--text); font-weight: 600; font-size: 14px; border-radius: var(--radius-sm); }
.picksong:hover { background: var(--panel2); }
.picksong[aria-expanded="true"] { color: var(--accent); }
.picksong .a { font-weight: 500; font-size: 12.5px; }
.pickcomps { padding: 4px 12px 10px; display: flex; flex-direction: column; gap: 4px; }
.pickcomp { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-top: 1px solid var(--border); font-size: 14px; }
.pickcomp .grow { flex: 1; min-width: 0; }
.pickcomp .a { font-size: 12.5px; }
.pickcomp.notab .t { color: var(--dim); }
.pickcomp button { padding: 4px 12px; font-size: 13px; flex: none; }
.pickcomp button.added { background: var(--accent-dim); border-color: var(--accent-dim); }
/* required accuracy: the slider and its "?" popover */
.acclbl { display: inline-flex; align-items: center; gap: 6px; position: relative; flex-wrap: wrap; }
.acclbl input[type=range] { width: 90px; }
.whatbtn { width: 26px; height: 26px; padding: 0; border-radius: 999px; font-size: 13px; font-weight: 800; line-height: 1; display: inline-flex; align-items: center; justify-content: center; color: var(--accent); }
.whatbtn[aria-expanded="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.popover {
  position: absolute; left: 0; top: calc(100% + 8px); z-index: 30; width: min(360px, 88vw);
  background: var(--panel); color: var(--text); border: 1px solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow-lift);
  padding: 12px 14px; font-size: 13.5px; line-height: 1.5; white-space: normal;
}
.popover p { margin: 0; } .popover p + p { margin-top: 8px; font-size: 12.5px; }
.popover b { color: var(--text); }
.tabsys .n.missed { color: var(--danger); text-decoration: line-through; font-weight: 500; }   /* a note the piece moved past without hearing */
/* the fretboard above the tab (FretView): frets you can actually see, the next note lit */
.fretpanel { flex: none; margin-bottom: 10px; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 6px 6px 2px; overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; }
.fretpanel svg { display: block; width: 100%; min-width: 900px; height: auto; font-family: system-ui, sans-serif; }
.fretview .fv-wood { fill: var(--fret-wood); stroke: var(--border-strong); stroke-width: 1; }
.fretview .fv-nut { fill: var(--fret-nut); }
.fretview .fv-fret { stroke: var(--fret-wire); stroke-width: 3.2; stroke-linecap: round; }
.fretview .fv-inlay { fill: var(--fret-inlay); }
.fretview .fv-fretnum { fill: var(--dim); font-size: 11px; font-variant-numeric: tabular-nums; }
.fretview .fv-fretnum.key { fill: var(--text); font-weight: 700; font-size: 12px; }
.fretview .fv-string { stroke: var(--fret-string); opacity: .72; }
.fretview .fv-open { fill: var(--dim); font-size: 12px; font-weight: 700; }
.fretview .fv-dot circle { fill: color-mix(in srgb, var(--panel) 40%, transparent); stroke: transparent; stroke-width: 2; transition: r .12s, fill .12s; }
.fretview .fv-dot text { font-size: 11px; font-weight: 700; fill: var(--on-accent); opacity: 0; pointer-events: none; }
.fretview .fv-dot.next circle { fill: var(--accent); stroke: var(--on-accent); animation: pulse 1.6s infinite; }
.fretview .fv-dot.next text { opacity: 1; }
.fretview .fv-dot.ok circle { fill: var(--accent-dim); animation: none; }
.fretview .fv-dot.ok text { opacity: 1; }
.fretview .fv-dot.bad circle { fill: var(--danger); stroke: var(--on-accent); animation: none; }
.fretview .fv-dot.bad text { opacity: 1; }
.fretview .fv-dot.heard circle { stroke: var(--danger); fill: color-mix(in srgb, var(--danger) 22%, transparent); }
.fretbtn.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
/* repeat markers: every line (system) of the tab has "from here" / "to here"; the loop runs only the marked chunk */
.sysblock { display: flex; flex-direction: column; gap: 3px; }
.sysmarks { display: flex; align-items: center; gap: 6px; padding: 0 4px; font-size: 12px; color: var(--dim); }
.sysmarks .ln { font-weight: 700; text-transform: uppercase; letter-spacing: .06em; font-size: 11px; margin-right: auto; }
.sysmarks button { padding: 3px 9px; font-size: 12px; color: var(--dim); min-height: 28px; }
.sysmarks button:hover { color: var(--accent); }
.sysmarks button[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.sysblock.inrange .tabsys { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent); }
.sysblock.inrange .sysmarks .ln { color: var(--accent); }
.tabsheet.repeating .sysblock:not(.inrange) { opacity: .55; }
.repeatbtn { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); font-size: 12.5px; padding: 5px 11px; }
.repeatbtn:hover { color: var(--danger); border-color: var(--danger); background: var(--panel); }
.passbox { display: inline-flex; align-items: baseline; gap: 6px; padding: 4px 12px; border: 1px solid var(--border); border-radius: 999px; background: var(--panel2); font-size: 13px; }
.passbox .k { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--dim); }
.passbox b { font-size: 18px; color: var(--accent); font-variant-numeric: tabular-nums; line-height: 1; }
.nowctl.transport { align-items: center; }
.nowctl.settings { margin-top: 6px; padding-top: 8px; border-top: 1px dashed var(--border); }
.nowctl.settings label.off { opacity: .55; }
.settingsbtn { display: none; margin-left: auto; }
.tabsheet .lickhead { font-size: 13px; font-weight: 700; color: var(--dim); text-transform: uppercase; letter-spacing: .06em; margin: 8px 4px 0; }
.tabsheet .lickhead.on { color: var(--accent); }
@media (max-width: 700px) {
  .practintro { font-size: 13.5px; }
  .sesscard { flex-wrap: wrap; row-gap: 8px; }
  .sesscard .grow { flex-basis: 100%; }
  .sessionpage header.bar .meta { display: none; }
  .sessionpage .fbwrap.sessmain { padding: 8px 10px 8px; }
  .sessionpage .canvas { padding: 8px 10px; margin-bottom: 8px; }
  .canvashead { gap: 8px; }
  .canvashead .sessname { flex-basis: calc(100% - 190px); }
  .canvasbtns { margin-left: 0; }
  .canvasbtns button { min-height: 40px; font-size: 14px; }
  .lickstrip { flex-basis: 100%; order: 3; }
  .lickchip { min-height: 36px; }
  .sessionpage .nowpanel { margin-bottom: 8px; }
  .sessionpage .tabsheet { padding-bottom: 16px; }
  .sessionpage .nowhead .a { display: none; }
  .sessionpage .nownote .s.dim, .sessionpage .nowheard .s.dim { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .lickdrawer {
    top: auto; left: 0; width: auto; max-height: 82dvh; border-left: none; border-top: 1px solid var(--border);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding: 12px 12px calc(12px + env(safe-area-inset-bottom));
    transform: translateY(100%);
  }
  .lickdrawer.open { transform: none; }
  .drawerhead button, .pickhead button { font-size: 16px; min-height: 44px; }
  .lick { flex-wrap: wrap; }
  .lick .grow { flex-basis: calc(100% - 34px); }
  .lickbtns { width: 100%; justify-content: flex-end; }
  .lickbtns button { font-size: 14px; padding: 7px 12px; min-height: 44px; }
  .overlay { align-items: flex-end; }
  .overlay .pickbox { width: 100%; max-height: 88dvh; border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding: 14px 12px calc(14px + env(safe-area-inset-bottom)); }
  .pickcomp button { font-size: 16px; min-height: 44px; }
  .picksong { min-height: 44px; }
  .sysmarks { gap: 8px; }
  .sysmarks button { min-height: 44px; min-width: 44px; font-size: 14px; padding: 8px 12px; }
  .sysmarks button .lbl { display: none; }
  .repeatbtn { min-height: 44px; font-size: 14px; }
  .fretbtn { min-height: 44px; font-size: 14px; }
  .acclbl { flex: 1 1 100%; }
  .acclbl input[type=range] { flex: 1; width: auto; }
  .whatbtn { width: 44px; height: 44px; font-size: 16px; }
  .popover { left: 0; right: 0; width: auto; font-size: 16px; }
  .fretpanel { padding: 4px 4px 0; margin-bottom: 8px; }
  .fretpanel svg { min-width: 980px; }
  .nowhead .passbox { order: 2; }
  .nowctl .settingsbtn { display: inline-block; }
  .nowctl.settings:not(.open) { display: none; }
  .nowctl.settings label { flex: 1 1 100%; }
  .nowctl.settings select { flex: 1; min-width: 0; }
  .nowctl.settings input[type=range] { flex: 1; width: auto; }
  .nowctl.transport #stats { flex-basis: 100%; }
}
/* Practice v2 polish: Restart keeps its word on phones */
@media (max-width: 700px) {
  .sessionpage .nowctl #restartBtn .lbl { display: inline; }
}

/* ---------- song icons (plan §3.10 `icon`; drawn by public/js/songicon.js from /vendor/tabler/sprite.svg) ----------
   currentColor + stroke from the sprite's own symbols, so an icon takes the colour of the text it sits in. */
.song-icon { width: 1.25em; height: 1.25em; vertical-align: -0.28em; flex: none; color: inherit; }
.song-icon.lg { width: 1.7em; height: 1.7em; }

/* song icon beside the title in the data grid and on tiles */
.datagrid td.c-main .song-icon { color: var(--accent); margin-right: 0.5rem; vertical-align: middle; }
.datagrid td.c-main .t { display: inline-block; vertical-align: middle; }
.tilecard .gt { display: flex; align-items: center; gap: 0.5rem; }
.tilecard .gt .song-icon { color: var(--accent); }

/* ---------- mobile pass (docs/progress/mobile.md): iPhone-friendly, no focus zoom, no floaty fixed layout ----------
   Every rule here is a phone override that comes LAST in the cascade on purpose. */
@media (max-width: 900px) {
  /* 1. no iOS focus zoom: anything you can type or pick in is 16px */
  input:not([type=range]):not([type=checkbox]):not([type=radio]):not([type=file]):not([type=color]), textarea, select, [contenteditable="true"] { font-size: 16px; }
  /* 2. tap targets: every button and bar link is at least 44px tall */
  button, header.bar .backlink, .shell-foot button, .canvasbtns button, .rowactions button, .libpagebar button, .themesel,
  .cardmenu .menu button, .viewtoggle .viewBtn, .lickchip, .sysmarks button, .pickcomp button, .lickbtns button, .zoomctl button, .mtabbar button {
    min-height: 44px;
  }
  header.bar .backlink { display: inline-flex; align-items: center; }
  .shell-burger { width: 44px; height: 44px; }
  .shell-close { width: 44px; height: 44px; }
  .rowactions .cardmenu > summary, .cardmenu > summary { width: 44px; height: 44px; }
  .viewtoggle { padding: 0; }
  .viewtoggle .viewBtn { padding: 5px 14px; }
  .whatbtn { width: 44px; height: 44px; }
  /* the row menu opens to the LEFT of its button so it never pokes past the screen edge */
  .rowactions .cardmenu .menu { left: auto; right: 0; }
  /* 3. no floatiness on the performance view: the live-detection peek is a strip above the tabs, the jump
        toast hangs inside the page column, both follow the flex column instead of floating over it */
  body.playpage { position: relative; height: 100dvh; height: var(--vvh, 100dvh); }
  body[data-mtab="sheet"] .minihud {
    position: static; display: flex; flex: none; order: 9; align-self: flex-end; margin: 0 8px 6px auto; min-height: 36px; align-items: center; gap: 4px;
  }
  .mtabbar { order: 10; }
  .jumpflash { position: absolute; left: 50%; right: auto; bottom: calc(96px + env(safe-area-inset-bottom)); }
  /* full-height pages follow the VISUAL viewport (session.js sets --vvh), so the bottom bar and the
     composer sit right above the iPhone keyboard instead of the page panning under it */
  body.sessionpage { height: 100dvh; height: var(--vvh, 100dvh); }
  /* transient toasts respect the home-indicator inset */
  .toast { bottom: calc(16px + env(safe-area-inset-bottom)); max-width: calc(100vw - 24px); }
  .toast button { min-height: 40px; }
  /* one scroll container: the page body scrolls on list/account pages, never the html AND a pane */
  html, body { overscroll-behavior-y: none; }
}
@media (max-width: 900px) {
  /* selects that carried their own small size (play key/capo/engine, fretboard controls, flow, paging) */
  .capoctl select, .viewtabs select, .fbctl select, select.sttsel, .side select, .flowpanel select, .nowctl select, .pagesizesel select, .themesel, .trpage .fbctl select { font-size: 16px; min-height: 44px; }
  .viewtabs #zoomOut, .viewtabs #zoomIn, #instrNew { min-width: 44px; }
  .fbctl .chk { min-height: 44px; display: inline-flex; align-items: center; padding: 0 4px; }
  .fbctl .chk input { width: 22px; height: 22px; }
  .fbctl button { min-height: 44px; }
}
