/*!
 * Tablight — tablight.app
 * © 2026 Tablight. All rights reserved.
 * Unauthorised copying, redistribution or derivative works prohibited.
 * Contact: legal@tablight.app
 */
/* ── Self-hosted fonts (same families as before — served locally for speed,
      offline support, and no third-party request). Files live in /fonts. ── */
@font-face { font-family:'JetBrains Mono'; font-style:normal; font-weight:400; font-display:swap; src:url('/fonts/jetbrains-mono-400.woff2') format('woff2'); }
@font-face { font-family:'JetBrains Mono'; font-style:normal; font-weight:600; font-display:swap; src:url('/fonts/jetbrains-mono-600.woff2') format('woff2'); }
@font-face { font-family:'JetBrains Mono'; font-style:normal; font-weight:700; font-display:swap; src:url('/fonts/jetbrains-mono-700.woff2') format('woff2'); }
@font-face { font-family:'DM Sans'; font-style:normal; font-weight:400; font-display:swap; src:url('/fonts/dm-sans-400.woff2') format('woff2'); }
@font-face { font-family:'DM Sans'; font-style:normal; font-weight:500; font-display:swap; src:url('/fonts/dm-sans-500.woff2') format('woff2'); }
@font-face { font-family:'DM Sans'; font-style:normal; font-weight:700; font-display:swap; src:url('/fonts/dm-sans-700.woff2') format('woff2'); }

/* ══════════════════════════════════════════════════════════════════════════
   tl_shell.css — shared shell styles for all Tablight pages
   Covers: tokens, reset, topbar, transport bar, common components
══════════════════════════════════════════════════════════════════════════ */

/* ── Tokens ─────────────────────────────────────────────────────────────── */
:root {
  --bg:       #f5f4f0;
  --surface:  #ffffff;
  --raised:   #faf9f7;
  --raised-hover: #f3f1ec;
  --border:   #dddbd4;
  --border2:  #c8c5bc;
  --text:     #1a1916;
  --muted:    #7a776e;
  --accent:   #1a6b3c;
  --accent-l: #e6f2ec;
  --amber:    #8a5a00;
  --amber-l:  #fdf3dc;
  --blue:     #1a4d7a;
  --blue-l:   #e6eef6;
  --warn:     #b83232;
  --warn-l:   #fdeaea;
  --mono:     'JetBrains Mono', monospace;
  --sans:     'DM Sans', sans-serif;
  --bar-h:    52px;
  --transport-h: 56px;
  color-scheme: light;
}

/* ── Dark theme ───────────────────────────────────────────────────────────────
   Applies when the OS prefers dark AND the user hasn't forced light, OR when the
   user has explicitly chosen dark via the settings toggle (html[data-theme]).
   Only the colour tokens change; layout tokens are untouched. The dark token
   list is duplicated across the two triggers below (CSS can't share a block). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:       #14130f;
    --surface:  #1d1c18;
    --raised:   #26251e;
    --raised-hover: #2f2e25;
    --border:   #33312b;
    --border2:  #46433a;
    --text:     #ece9e2;
    --muted:    #9a968c;
    --accent:   #46a86e;
    --accent-l: #1e3a2b;
    --amber:    #d6a544;
    --amber-l:  #3a2f17;
    --blue:     #6fa8d8;
    --blue-l:   #182a3a;
    --warn:     #e06b6b;
    --warn-l:   #3a1f1f;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:       #14130f;
  --surface:  #1d1c18;
  --raised:   #26251e;
  --raised-hover: #2f2e25;
  --border:   #33312b;
  --border2:  #46433a;
  --text:     #ece9e2;
  --muted:    #9a968c;
  --accent:   #46a86e;
  --accent-l: #1e3a2b;
  --amber:    #d6a544;
  --amber-l:  #3a2f17;
  --blue:     #6fa8d8;
  --blue-l:   #182a3a;
  --warn:     #e06b6b;
  --warn-l:   #3a1f1f;
}

/* ── Reset ───────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
  scroll-behavior: smooth;
  /* Prevent iOS Safari from auto-enlarging text in wide elements (tab lines) */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--mono);
  font-size: 13px;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  overscroll-behavior: none;   /* no pull-to-refresh / rubber-band bounce — app-like */
}

/* ── Sticky top bar ──────────────────────────────────────────────────────── */
#topbar {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--surface);
  border-bottom: 1px solid var(--border2);
  height: var(--bar-h);
  display: flex;
  align-items: center;
  gap: 0;
  padding: 0 16px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.07);
  transition: transform 0.25s ease;
}
#topbar.hide { transform: translateY(-100%); }
.tb-brand {
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.3px;
  white-space: nowrap;
  margin-right: 4px;
}
.tb-divider { width: 1px; height: 22px; background: var(--border2); margin: 0 12px; flex-shrink: 0; }
.tb-nav { display: flex; gap: 2px; }
.tb-nav a {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  text-decoration: none;
  padding: 6px 11px;
  border-radius: 5px;
  white-space: nowrap;
  transition: background 0.12s, color 0.12s;
}
.tb-nav a:hover { background: var(--bg); color: var(--text); }
.tb-nav a.active { background: var(--accent-l); color: var(--accent); font-weight: 700; }
.tb-nav a.dead { opacity: 0.45; cursor: default; pointer-events: none; }
.tb-server {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.tb-server input {
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: var(--mono);
  font-size: 11px;
  padding: 5px 8px;
  border-radius: 4px;
  width: 168px;
  outline: none;
}
.tb-server input:focus { border-color: var(--accent); }
.dot {
  display: inline-block; vertical-align: middle;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--border2); flex-shrink: 0;
  transition: background 0.3s, box-shadow 0.3s;
}
.dot.alive   { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-l); }
.dot.pending { background: #d4a800; box-shadow: 0 0 0 3px #fdf3c0; }  /* yellow — request in flight */

/* ── Jump pills ──────────────────────────────────────────────────────────── */
.tb-jumps {
  display: none;  /* hidden by default — only shown in mobile-mode */
  gap: 4px;
  margin-left: auto;
  flex-shrink: 1;
  min-width: 0;
  flex-wrap: nowrap;
}
body.mobile-mode .tb-jumps { display: flex; }
.tb-jump {
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  padding: 5px 13px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: transparent;
  white-space: nowrap;
  letter-spacing: 0.02em;
  transition: color 0.12s, border-color 0.12s, background 0.12s;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none; user-select: none;
}
.tb-jump:hover { color: var(--accent); border-color: var(--border2); }
/* Live "you are here" state, driven by the scroll-spy in tl_common.js */
.tb-jump.active {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-l);
  font-weight: 700;
}

/* ── Bottom transport bar ────────────────────────────────────────────────── */
#transport {
  display: none;
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 200;
  height: calc(var(--transport-h) + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--border2);
  box-shadow: 0 -2px 8px rgba(0,0,0,0.08);
  align-items: center;
  padding: 0 14px;
  padding-bottom: env(safe-area-inset-bottom);
  gap: 6px;
  overflow: hidden;
  flex-shrink: 0;
}
#transport.visible { display: flex; }
body.transport-on { padding-bottom: calc(var(--transport-h) + env(safe-area-inset-bottom)); }

.tp-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: 13px;
  height: 34px;
  min-width: 34px;
  padding: 0 9px;
  border-radius: 5px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  white-space: nowrap;
  transition: color 0.12s, border-color 0.12s, background 0.12s;
  flex-shrink: 0;
  font-family: var(--mono);
  /* These are tap/hold targets, never text. Suppress the iOS long-press
     callout menu, the selection loupe, and the grey tap flash. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.tp-btn:hover  { color: var(--text); border-color: var(--border2); }
.tp-btn:active { background: var(--bg); }
.tp-btn:disabled { opacity: 0.3; cursor: default; }
/* Sustain (hold) button — only visible while auto-play is running. A bit larger
   for an easy press-and-hold target, and gestures fully disabled since it's held
   continuously (no scroll/zoom/callout interference). */
#autoHoldBtn {
  min-width: 50px;
  height: 40px;
  font-size: 17px;
  touch-action: none;
}
.tp-play {
  background: var(--accent); color: #fff; border-color: var(--accent);
  font-size: 18px; width: 63px; height: 42px; border-radius: 7px;
}
.tp-play:hover  { background: #155c33; border-color: #155c33; color: #fff; }
.tp-play:active { background: #0e4025; }
/* Loading state: shown while a sampled instrument's soundfont downloads/decodes.
   Informational only — the button stays pressable (the note plays as soon as the
   buffers arrive). Reuses the @keyframes spin defined further down. */
.tp-play.is-loading { color: transparent; position: relative; }
.tp-play.is-loading::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 16px; height: 16px; margin: -8px 0 0 -8px;
  border: 2px solid rgba(255,255,255,0.35); border-top-color: #fff;
  border-radius: 50%; animation: spin 0.7s linear infinite;
}
.tp-rec { border-color: var(--warn); background: var(--warn-l); color: var(--warn); }
.tp-rec:hover  { background: var(--warn-l); color: var(--warn); border-color: var(--warn); }
.tp-rec.active { background: #b83232; border-color: #b83232; color: #fff; animation: recpulse 1s ease-in-out infinite; }
.tp-loop.active { background: var(--accent-l); border-color: var(--accent); color: var(--accent); }
.tp-ploop.active { background: var(--accent-l); border-color: var(--accent); color: var(--accent); }
.tp-counter { font-size: 11px; color: var(--muted); font-family: var(--mono); min-width: 48px; text-align: center; flex-shrink: 0; }
/* Interval readout pill — shown only when Settings > display > intervals is on
   AND there is a value to show (first note / after a jump renders empty). */
.tp-interval { display: none; }
body.intervals-on .tp-interval.filled {
  display: inline-flex; align-items: baseline; gap: 6px;
  font-family: var(--mono); flex-shrink: 0; line-height: 1;
  padding: 2px 8px; border-radius: 5px;
  border: 1px solid var(--border2); background: var(--raised);
}
.tp-interval .tpi-step { font-size: 12px; font-weight: 700; letter-spacing: -0.3px;
  font-variant-numeric: tabular-nums; }   /* digits keep a fixed width on fast clicks */
.tp-interval .tpi-name { font-size: 9px; color: var(--muted); }
/* Direction colour-coding — a tinted block reads faster at a glance than tinted text.
   Up = green, down = blue, equal = amber; all have dark-mode variants. */
.tp-interval.up   { border-color: var(--accent); background: var(--accent-l); }
.tp-interval.up   .tpi-step { color: var(--accent); }
.tp-interval.down { border-color: var(--blue);   background: var(--blue-l); }
.tp-interval.down .tpi-step { color: var(--blue); }
.tp-interval.same { border-color: var(--amber);  background: var(--amber-l); }
.tp-interval.same .tpi-step { color: var(--amber); }
.tp-nav-label {
  font-size: 10px; font-weight: 600; color: var(--muted);
  font-family: var(--sans); letter-spacing: 0.06em; text-transform: uppercase;
  flex-shrink: 0; user-select: none;
}
body.mobile-mode .tp-nav-label { display: none; }
/* Mobile landscape: keep the transport speed slider but drop its % readout to
   save room. In portrait the whole speed group is hidden anyway. */
body.mobile-mode #recSpeedPctTb { display: none; }
.tp-recinfo { font-size: 10px; color: var(--muted); font-family: var(--mono); white-space: nowrap; }
.tp-recinfo .rec-dot { color: #b83232; }
.tp-sep { width: 1px; height: 24px; background: var(--border2); margin: 0 4px; flex-shrink: 0; }
.tp-spacer { flex: 1; }

/* ── Portrait mobile: hide record label ──────────────────────────────────── */
@media (orientation: portrait) {
  /* .tp-nav-label is already hidden for all of mobile-mode above; here we only
     need to clear the counter/recinfo/settings and re-center the buttons. */
  body.mobile-mode .mobile-portrait-hide { display: none !important; }
  body.mobile-mode #transport { justify-content: center; }

  /* Compact portrait: the BPM slider + sustain button only appear with
     auto-play armed, which crowds the narrower bar. Drop the captions then —
     the same buttons-only treatment mobile mode uses. Captions stay when
     auto-play is off (the bar has room). */
  body.compact-mode.autoplay-on .tp-nav-label { display: none; }
}
.tp-settings-wrap { position: relative; flex-shrink: 0; }
#tpSettingsPanel {
  display: none;
  position: fixed;
  bottom: calc(var(--transport-h) + 8px);
  right: 14px;
  background: var(--surface);
  border: 1px solid var(--border2);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.13);
  padding: 12px 14px;
  min-width: 200px;
  flex-direction: column;
  gap: 10px;
  z-index: 400;
  /* Never taller than the space above the transport bar — scroll if it is
     (e.g. mobile landscape), so the top rows stay reachable. */
  max-height: calc(100vh - var(--transport-h) - 24px);
  max-height: calc(100dvh - var(--transport-h) - 24px - env(safe-area-inset-top, 0px));
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}
#tpSettingsPanel.open { display: flex; }

/* Falling-notes lead cap (ms). JS (key.html) reads this to bound the "lead"
   slider; smaller screens get a shorter lane, so a smaller cap. */
body              { --tl-synth-lead-max: 6000; }   /* full    */
body.compact-mode { --tl-synth-lead-max: 4500; }   /* compact */
body.mobile-mode  { --tl-synth-lead-max: 3000; }   /* phone (incl. landscape) */

/* ── Topbar settings gear (shared across pages) ──────────────────────────────
   A bare gear icon at the far right of the topbar (inside .tb-server), in the
   server-LED's place, so it can never wrap onto its own row. Any topbar that
   carries a gear hides its LED, and its panel drops down from the top bar
   instead of up from the transport bar.                                      */
#topbar #tpSettingsBtn {
  background: none; border: none; box-shadow: none; padding: 0; margin: 0;
  width: auto; height: auto; min-width: 0; line-height: 1;
  font-size: 13px; opacity: 0.75; color: var(--muted); cursor: pointer;
}
#topbar .tp-settings-wrap { display: flex; align-items: center; }
#topbar #tpSettingsBtn:hover, #topbar #tpSettingsBtn.active { color: var(--accent); opacity: 1; }
/* Touch vs mouse, not screen size: iPads run this page in full-mode, so a
   compact-only bump missed them. Key off a coarse (touch) pointer instead. */
@media (pointer: coarse) {
  /* The gear is a small glyph; give a thumb something bigger to aim at. */
  #topbar #tpSettingsBtn { font-size: 20px; }
  /* No mouse to place precisely, so hide the server URL box next to the gear —
     it stops a thumb landing in the field instead of on the gear, and the box
     has no purpose for a normal user. It stays on fine-pointer (desktop). */
  .tb-server > input, .tb-server-label { display: none; }
}
/* ...but a phone (mobile-mode) is coarse too, and 20px is oversized on a phone
   topbar — keep the phone gear at its original small size. */
body.mobile-mode #topbar #tpSettingsBtn { font-size: 13px; }
#topbar:has(.tp-settings-wrap) #pingDot { display: none; }
#topbar #tpSettingsPanel {
  top: calc(var(--bar-h) + 8px); bottom: auto;
  max-height: calc(100dvh - var(--bar-h) - 24px);
}
/* When a song is loaded the transport bar appears at the bottom; a top-anchored
   settings panel must stop above it (and scroll if there is not enough room) so
   the last rows (e.g. dark mode) stay reachable instead of hiding behind it. */
body.transport-on #topbar #tpSettingsPanel {
  max-height: calc(100dvh - var(--bar-h) - var(--transport-h) - 24px - env(safe-area-inset-bottom, 0px));
}
body.mobile-mode #topbar #tpSettingsPanel,
body.compact-mode #topbar #tpSettingsPanel { top: 56px; }
.tp-setting-row { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--muted); }
.tp-setting-row label { min-width: 44px; text-transform: uppercase; letter-spacing: 0.06em; }
.tp-speed-slider {
  -webkit-appearance: none; appearance: none;
  flex: 1; height: 3px; border-radius: 2px; background: var(--border); outline: none; cursor: pointer;
}
.tp-speed-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--accent); cursor: pointer; border: 2px solid var(--bg);
}
.tp-speed-slider:disabled { opacity: 0.3; }
.tp-speed-pct { font-size: 11px; font-family: var(--mono); color: var(--accent); min-width: 34px; text-align: right; }
.tp-wave-select {
  flex: 1; background: var(--bg); border: 1px solid var(--border); border-radius: 4px;
  font-size: 11px; padding: 3px 5px; color: var(--text);
}
.tp-clear-btn {
  font-family: var(--mono); font-size: 11px; padding: 4px 10px;
  border-radius: 4px; cursor: pointer; width: 100%;
  border: 1px solid var(--border); background: transparent; color: var(--muted);
  transition: color 0.12s, border-color 0.12s;
}
.tp-clear-btn:hover { color: var(--warn); border-color: var(--warn); }
/* Named section separator: ── sound ── */
.tp-section {
  display: flex; align-items: center; gap: 6px;
  margin: 8px 0 4px;
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--border2);
}
.tp-section::before, .tp-section::after {
  content: ''; flex: 1; height: 1px; background: var(--border);
}
/* Auto-play toggle row */
.tp-toggle-row {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; color: var(--muted);
}
.tp-toggle-row > span { min-width: 44px; text-transform: uppercase; letter-spacing: 0.06em; }
/* Keep toggle switches in one right-aligned column so rows like "learn mode" /
   "dark mode" line up under each other regardless of label width. Scoped to
   rows with a switch so dropdown rows (type, labels) are left untouched. */
.tp-toggle-row:has(.tp-toggle) { justify-content: space-between; }
.tp-toggle { width: 36px; height: 20px; position: relative; cursor: pointer; flex-shrink: 0; display: inline-block; }
.tp-toggle input { opacity: 0; width: 0; height: 0; position: absolute; }
.tp-toggle-track {
  position: absolute; inset: 0; border-radius: 10px;
  background: var(--border2); transition: background 0.2s;
}
.tp-toggle input:checked ~ .tp-toggle-track { background: var(--accent); }
.tp-toggle-track::after {
  content: ''; position: absolute; width: 14px; height: 14px;
  border-radius: 50%; background: #fff; top: 3px; left: 3px;
  transition: transform 0.2s;
}
.tp-toggle input:checked ~ .tp-toggle-track::after { transform: translateX(16px); }

/* ── Common components ───────────────────────────────────────────────────── */
.sec-label {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 8px;
  scroll-margin-top: calc(var(--bar-h) + 12px);
}
.sec-label::after { content: ''; flex: 1; height: 1px; background: var(--border); }

.btn {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  padding: 7px 15px;
  border-radius: 5px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: all 0.12s;
  white-space: nowrap;
}
.btn-primary   { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn-primary:hover { background: #155c33; }
.btn-outline   { background: transparent; color: var(--accent); border-color: var(--accent); }
.btn-outline:hover { background: var(--accent-l); }
.btn-ghost     { background: transparent; color: var(--muted); border-color: var(--border); }
.btn-ghost:hover { color: var(--text); border-color: var(--border2); }
.btn-blue      { background: transparent; color: var(--blue); border-color: #7aadd4; }
.btn-blue:hover { background: var(--blue-l); }
.btn-sm { font-size: 11px; padding: 5px 10px; }
.btn-row { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}
.card-empty { padding: 16px 14px; color: var(--muted); font-style: italic; font-size: 12px; }

.meta-row {
  display: flex;
  gap: 16px;
  font-size: 12px;
  color: var(--muted);
  flex-wrap: wrap;
}
.meta-row span strong { color: var(--text); font-weight: 600; }

.spill {
  font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 3px;
  font-family: var(--mono); flex-shrink: 0;
}
.spill-ok  { background: var(--accent-l); color: var(--accent); }
.spill-err { background: var(--warn-l);   color: var(--warn); }
.spill-off { background: var(--bg);       color: var(--muted); border: 1px solid var(--border); }

.num-input {
  background: var(--surface); border: 1px solid var(--border); color: var(--text);
  font-family: var(--mono); font-size: 12px; padding: 6px 8px; border-radius: 5px;
  outline: none; width: 68px; text-align: center;
}
.num-input:focus { border-color: var(--accent); }

@keyframes spin { to { transform: rotate(360deg); } }
.spinner { width: 11px; height: 11px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.7s linear infinite; flex-shrink: 0; display: none; }
.spinner.on { display: inline-block; }

@keyframes recpulse { 0%,100%{opacity:1} 50%{opacity:0.6} }

#toast-wrap {
  position: fixed; bottom: calc(var(--transport-h) + 10px); left: 50%; transform: translateX(-50%);
  z-index: 9999; display: flex; flex-direction: column; align-items: center; gap: 8px;
  pointer-events: none;
}
.toast {
  background: var(--warn-l); border: 1px solid #e8b0b0; color: var(--warn);
  font-family: var(--sans); font-size: 13px; font-weight: 500;
  padding: 9px 18px; border-radius: 7px; white-space: nowrap;
  box-shadow: 0 3px 12px rgba(0,0,0,0.12);
  animation: toastin 0.2s ease, toastout 0.3s ease 2.7s forwards;
}
.toast.info { background: var(--blue-l); border-color: #aac4e0; color: var(--blue); }
@keyframes toastin  { from { opacity:0; transform:translateY(8px); } to { opacity:1; transform:none; } }
@keyframes toastout { from { opacity:1; } to { opacity:0; } }

footer {
  border-top: 1px solid var(--border);
  padding: 9px 22px;
  font-size: 10px; color: var(--muted);
  display: flex; gap: 14px; flex-wrap: wrap; align-items: baseline;
  letter-spacing: 0.06em; text-transform: uppercase;
  flex-shrink: 0;
  background: var(--surface);
}
footer > span { white-space: nowrap; }
.footer-support { color: var(--muted); text-decoration: none; transition: color 0.12s; }
.footer-support::before { content: "·"; margin: 0 8px; color: var(--border2); }
.footer-support:hover { color: var(--accent); }
footer .dot { margin-right: 5px; }
#reqCount::before,
#lineCount:not(:empty)::before { content: "·"; margin-right: 8px; color: var(--border2); }

/* ── Responsive topbar (compact & mobile mode) ───────────────────────────── */
/* Wrap the topbar onto two rows when jump pills are present (mobile-mode only,
   handled by .tb-jumps display rules elsewhere). Compact mode never shows
   jump pills, so it stays single-row but still gets the roomier nav sizing. */
body.compact-mode #topbar,
body.mobile-mode #topbar {
  height: auto;
  flex-wrap: wrap;
  padding: 6px 14px;
  gap: 0;
  row-gap: 5px;
}
body.compact-mode .tb-brand, body.compact-mode .tb-divider,
body.compact-mode .tb-nav,   body.compact-mode .tb-server,
body.mobile-mode .tb-brand,  body.mobile-mode .tb-divider,
body.mobile-mode .tb-nav,    body.mobile-mode .tb-server { order: 1; }

body.compact-mode .tb-jumps,
body.mobile-mode .tb-jumps {
  order: 2;
  width: 100%;
  margin-left: 0;
  padding-top: 6px;
  padding-bottom: 4px;
  border-top: 1px solid var(--border);
  justify-content: flex-start;
  gap: 7px;
  flex-wrap: nowrap;
  overflow-x: auto;
  -ms-overflow-style: none;
  scrollbar-width: none;
}
body.compact-mode .tb-jumps::-webkit-scrollbar,
body.mobile-mode .tb-jumps::-webkit-scrollbar { display: none; }

/* Server input hidden, nav links roomier — same sizing for compact & mobile */
body.compact-mode .tb-server > input, body.compact-mode .tb-server-label,
body.mobile-mode .tb-server > input,  body.mobile-mode .tb-server-label { display: none; }
body.compact-mode .tb-brand, body.mobile-mode .tb-brand { font-size: 14px; }
body.compact-mode .tb-nav a, body.mobile-mode .tb-nav a { padding: 6px 8px; font-size: 11px; }

/* Extra-tight horizontal spacing only on the narrowest phones */
body.mobile-mode #topbar { padding-left: 10px; padding-right: 10px; }
body.mobile-mode .tb-divider { margin: 0 8px; }


/* ─── Learn mode: inline hints, "?" badges, explainer popovers ─────────────── */
/* Supplementary learning UI, visible only when <html class="learn"> is set
   (toggled from Settings ▸ display). Off = a clean interface for fluent users. */
.tl-hint { display: none; }
html.learn .tl-hint { display: block; }

.tl-info { display: none; }
html.learn .tl-info {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; padding: 0; border-radius: 50%;
  font: 700 11px/1 var(--mono, inherit);
  color: var(--muted); background: transparent;
  border: 1px solid var(--border2); cursor: pointer;
  vertical-align: middle; -webkit-appearance: none; appearance: none;
}
html.learn .tl-info:hover,
html.learn .tl-info:focus-visible { color: var(--text); border-color: var(--text); outline: none; }

/* the single shared popover — positioned by tl_common.js */
.tl-tip {
  position: fixed; z-index: 1000; max-width: min(280px, 92vw);
  max-height: min(60vh, 380px); overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border2); border-radius: 8px;
  padding: 8px 10px; font-size: 12px; line-height: 1.45;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .18);
  opacity: 0; transform: translateY(2px); pointer-events: none;
  transition: opacity .12s ease, transform .12s ease;
}
.tl-tip.open { opacity: 1; transform: none; pointer-events: auto; }
.tl-tip span { display: block; margin: 2px 0; }
/* Layout-dependent wording inside a popover: show the phrasing that matches the
   current layout. Default (mobile/compact) is stacked; full-mode is two-column. */
.tl-tip .tl-side  { display: none; }
.tl-tip .tl-stack { display: block; }
body.full-mode .tl-tip .tl-side  { display: block; }
body.full-mode .tl-tip .tl-stack { display: none; }
.tl-tip .dot {
  display: inline-block; width: 10px; height: 10px; border-radius: 50%;
  vertical-align: middle; margin-right: 5px;
}

/* key.html neck legend now lives inside its "?" — hide the row when learn is off */
html:not(.learn) .key-neck-legend { display: none; }
