/* ---------- DESIGN TOKENS ---------- */
:root {
  --accent-primary: #10b981;
  --accent-hover: #34d399;
  --accent-glow: rgba(16, 185, 129, 0.15);
  --bg-base: #09090b;
  --bg-panel: #131316;
  --bg-card: #18181b;
  --bg-card-hover: #1f1f23;
  --danger: #ef4444;
  --ok: #10b981;
  --text-primary: #ffffff;
  --text-secondary: #a1a1aa;
  --text-muted: #52525b;
  --border-subtle: #27272a;
  --border-focus: #3f3f46;
  --radius-lg: 16px;
  --radius-md: 12px;
  --radius-sm: 8px;
  --shadow-panel: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
  --transition: 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  --mono: 'JetBrains Mono', monospace;
}

/* ---------- SVG LOGO PALETTE ---------- */
/* The class contract for exported logo SVGs, so artwork carries classes
   instead of an embedded <style> block. Tag paths in Inkscape's XML
   editor, save, drop the file in — no post-processing.

   ONLY applies to INLINED <svg>. An <img src="…svg">, background-image,
   <object> or <iframe> is a separate document: neither these rules nor
   the custom properties they reference cross that boundary.

   !important because a raw Inkscape export writes style="fill:#333333"
   on every path, and an inline style attribute otherwise outranks a
   class rule. This also overrides the embedded <style> block in older
   exports, so existing artwork keeps working untouched. */
.sv-i  { fill: var(--text-primary)   !important; }
.sv-a  { fill: var(--accent-primary) !important; }
.sv-m  { fill: var(--text-secondary) !important; }

.sv-is, .sv-as, .sv-ms {
  fill: none !important;
  stroke-linecap: round; stroke-linejoin: round;
}
.sv-is { stroke: var(--text-primary)   !important; }
.sv-as { stroke: var(--accent-primary) !important; }
.sv-ms { stroke: var(--text-secondary) !important; }

/* ---------- BASE ---------- */
* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background-color: var(--bg-base);
  color: var(--text-primary);
  font-family: 'Inter', sans-serif;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

body.animdisabled {
  background-image:
    radial-gradient(circle at 100% 0%, var(--accent-glow) 0%, transparent 40%),
    radial-gradient(circle at 0% 100%, rgba(255, 255, 255, 0.02) 0%, transparent 40%);
}

.mono { font-family: var(--mono); }
.hidden { display: none !important; }
.dim { color: var(--text-muted); font-weight: 500; }

::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-focus); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

@media (prefers-reduced-motion: reduce) {
  .fluid-wave { animation: none !important; }
  * { transition-duration: 0.01ms !important; }
}

/* ---------- FLUID BACKGROUND (XMB STYLE) ---------- */
/* BUGFIX: gradient stops were inverted (glow 50%, transparent 0%),
   which CSS clamps into a hard-edged solid disc in the corner.
   Correct order: glow at 0% fading to transparent by 50%. */
.fluid-container {
  position: fixed; inset: 0; z-index: -1; opacity: 0.6; pointer-events: none;
  transition: opacity 0.5s ease;
  background: radial-gradient(circle at 100% 0%, var(--accent-glow) 0%, transparent 50%);
}
.fluid-container.disabled { opacity: 0; }

.fluid-wave {
  position: absolute; bottom: -10vh; left: 0; width: 200vw; height: 70vh;
  fill: var(--accent-primary); transition: fill 0.5s ease;
}
.w1 { animation: flow 25s linear infinite; opacity: 0.6; }
.w2 { animation: flow 18s linear infinite reverse; opacity: 0.3; height: 85vh; }
.w3 { animation: flow 30s linear infinite; opacity: 0.2; height: 100vh; }

@keyframes flow { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } }

/* ---------- LAYOUT ---------- */
.app-container {
  max-width: 100%;
  margin: 0 auto;
  display: flex;
  gap: 32px;
  padding: 0 40px 40px 40px;
}

/* ---------- HEADER ---------- */
.header {
  width: 100%;
  padding: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.brand-group { display: flex; align-items: baseline; gap: 16px; }
.logo { font-size: 36px; font-weight: 900; letter-spacing: -2px; display: flex; align-items: center; gap: 10px; }
.logo-icon { color: var(--accent-primary); transition: color var(--transition); }
.logo .logo-img       { height: 1.4em; width: auto; flex: 0 0 auto; }
.logo svg.logo-img    { display: block; }
.logo svg.logo-img *  { transition: fill var(--transition), stroke var(--transition); }
.subtitle { color: var(--text-secondary); font-size: 14px; font-weight: 500; letter-spacing: 0.5px; text-transform: uppercase; }

.top-controls { display: flex; align-items: center; gap: 16px; }
.fx-toggle {
  display: flex; align-items: center; gap: 6px; background: transparent; border: 1px solid var(--border-subtle);
  color: var(--text-secondary); padding: 6px 12px; border-radius: 99px; font-size: 11px; font-weight: 700;
  text-transform: uppercase; cursor: pointer; transition: all var(--transition);
}
.fx-toggle:hover { background: var(--bg-card); color: var(--text-primary); }

.theme-stack {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  position: relative;
}
/* the one-and-only shift hint, tucked under the theme palette (absolute:
   the header keeps its height, the hint hangs just beneath the pill) */
.theme-stack .header-hint {
  position: absolute; top: 100%; margin-top: 3px;
  white-space: nowrap; opacity: 0.85;
}
.theme-picker {
  display: flex; align-items: center; gap: 12px; background: var(--bg-panel);
  padding: 8px 12px; border-radius: 99px; border: 1px solid var(--border-subtle);
}
.theme-label { font-size: 10px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; }
.theme-btn { width: 16px; height: 16px; border-radius: 50%; border: none; cursor: pointer; transition: transform 0.2s; }
.theme-btn:hover { transform: scale(1.2); }
.theme-btn.active { box-shadow: 0 0 0 2px var(--bg-panel), 0 0 0 4px var(--text-primary); }

/* ---------- LEFT: DECKS ---------- */
.library { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 12px; }

.section-title {
  font-size: 12px; font-weight: 700; color: var(--text-muted); text-transform: uppercase;
  letter-spacing: 1px; margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center;
}

.song-card {
  background: var(--bg-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
  overflow: hidden; transition: border-color var(--transition), box-shadow var(--transition);
}
.song-card:hover { border-color: var(--border-focus); }
.song-card.open { border-color: var(--accent-primary); box-shadow: 0 0 0 1px var(--accent-primary); }

/* Deck cards are always-open song cards with structured contents */
.deck { padding: 20px; display: flex; flex-direction: column; gap: 14px; }

.deck-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.deck-eyebrow {
  font-size: 11px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--accent-primary); display: flex; align-items: center; gap: 8px; transition: color var(--transition);
}
.deck-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--border-focus); transition: all var(--transition); }
.deck-dot.ready { background: var(--accent-primary); box-shadow: 0 0 8px var(--accent-glow); }
.deck-dot.live { background: var(--ok); box-shadow: 0 0 8px rgba(16, 185, 129, 0.5); }
.deck-name {
  font-size: 13px; font-weight: 600; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}

.source-row {
  display: flex; align-items: center; gap: 10px; background: var(--bg-panel);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: 8px 12px;
}
.source-input {
  flex: 1; min-width: 0; background: transparent; border: none; outline: none;
  color: var(--text-primary); font-size: 13px; font-family: var(--mono);
}
.source-input::placeholder { color: var(--text-muted); font-family: 'Inter', sans-serif; }

.mini-btn {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 28px; height: 28px; border-radius: 6px; background: var(--bg-card);
  border: 1px solid var(--border-subtle); color: var(--text-secondary); cursor: pointer;
  transition: all var(--transition);
}
.mini-btn:hover { color: var(--text-primary); border-color: var(--border-focus); }
.mini-btn:disabled { opacity: 0.45; cursor: not-allowed; }

.deck-body { display: flex; flex-direction: column; gap: 14px; }
.deck-empty {
  color: var(--text-muted); font-size: 12px; padding: 18px;
  border: 1px dashed var(--border-subtle); border-radius: var(--radius-sm); text-align: center;
}

.deck-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.stat-box {
  background: var(--bg-panel); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  padding: 10px 12px; display: flex; flex-direction: column; gap: 4px; min-width: 0;
}
.stat-label {
  font-size: 10px; font-weight: 700; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.5px;
}
.stat-value { font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- VISUALIZER ---------- */
.visualizer-header { display: flex; justify-content: space-between; align-items: center; }
.tempogram-label { font-size: 10px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }

.bpm-toggle {
  display: flex; align-items: center; gap: 6px; background: var(--bg-panel); border: 1px solid var(--border-subtle);
  color: var(--text-secondary); font-size: 11px; font-weight: 700; font-family: var(--mono);
  padding: 4px 12px; border-radius: 99px; cursor: pointer; transition: all var(--transition);
}
.bpm-toggle:hover { background: var(--bg-card); border-color: var(--border-focus); color: var(--text-primary); }
.bpm-toggle.active { background: var(--accent-glow); border-color: var(--accent-primary); color: var(--accent-primary); }

.visualizer-wrapper {
  background: var(--bg-panel); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  padding: 16px; height: 114px; position: relative; cursor: pointer; overflow: hidden;
  transition: border-color var(--transition);
}
.visualizer-wrapper:hover { border-color: var(--border-focus); }
.visualizer-view { position: absolute; inset: 16px; display: flex; align-items: flex-end; transition: opacity 0.3s ease, transform 0.3s ease; }
.visualizer-view.hidden { opacity: 0; pointer-events: none; transform: translateY(10px); }

.bar-container { width: 100%; height: 100%; display: flex; align-items: flex-end; gap: 2px; }
.wave-bar { flex: 1; background: var(--accent-primary); border-radius: 2px 2px 0 0; transition: background 0.3s ease; }
.tempogram-svg { width: 100%; height: 100%; display: block; }
.tempo-tick { font-family: var(--mono); font-size: 11px; fill: var(--text-muted); }

/* ---------- DECK TABS ---------- */
.deck-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border-subtle); }
.deck-tab {
  display: flex; align-items: center; gap: 5px; background: transparent; border: none;
  color: var(--text-muted); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;
  padding: 8px 14px; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color var(--transition), border-color var(--transition);
}
.deck-tab:hover { color: var(--text-secondary); }
.deck-tab.active { color: var(--accent-primary); border-bottom-color: var(--accent-primary); }
.deck-tab.locked { opacity: 0.45; cursor: not-allowed; }

.deck-tab-body { display: flex; flex-direction: column; gap: 14px; }

.tags { display: flex; flex-wrap: wrap; gap: 8px; }
.tag {
  padding: 4px 10px; border-radius: 6px; background: var(--bg-panel); border: 1px solid var(--border-subtle);
  font-size: 11px; font-weight: 500; color: var(--text-secondary); white-space: nowrap;
  cursor: pointer; user-select: none; transition: border-color .12s, color .12s, background .12s;
}
.tag:hover { color: var(--text-primary); }
/* selected: the chip's border/color arrive INLINE in the tag's own
   palette hue (matches its timeline wash); the class just lifts it */
.tag.sel { background: rgba(255, 255, 255, 0.05); font-weight: 700; }
.tag.tag-x {
  border-style: dashed; font-weight: 700; padding: 4px 8px;
}
.tag.tag-x:hover { border-color: var(--text-secondary); }

/* ---------- CONTROL BLOCKS (shared by decks + master) ---------- */
.control-block {
  background: var(--bg-panel); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  padding: 12px 14px; display: flex; flex-direction: column; gap: 10px;
}
.control-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.bank-inline {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 6px; border-radius: 6px;
  background: var(--bg-card); border: 1px solid var(--border-subtle);
  color: var(--text-secondary); cursor: pointer;
  font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  transition: all var(--transition);
}
.bank-inline:hover { color: var(--accent-primary); border-color: var(--accent-primary); }
.control-name {
  display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-secondary);
}
.control-readout { font-size: 13px; font-weight: 700; color: var(--text-primary); }
.control-sub { font-size: 10.5px; color: var(--text-muted); }

.pill-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  background: var(--bg-card); border: 1px solid var(--border-focus); color: var(--text-primary);
  font-size: 12px; font-weight: 700; font-family: var(--mono);
  padding: 7px 14px; border-radius: 99px; cursor: pointer; transition: all var(--transition);
}
.pill-btn:hover { border-color: var(--accent-primary); color: var(--accent-primary); }
.pill-btn:active { transform: translateY(1px); }
.pill-btn.wide { width: 100%; border-radius: var(--radius-sm); font-family: 'Inter', sans-serif; }
.pill-btn.nudge { padding: 7px 0; flex: 1; }

.pitch-row { display: flex; gap: 8px; }
.pitch-row .pill-btn { flex: 1; }
.nudge-row { display: flex; gap: 6px; }

/* stem mute chips */
.stem-row { display: flex; flex-wrap: wrap; gap: 8px; }
.stem-chip {
  display: flex; flex-direction: column; align-items: center; gap: 5px; flex: 1; min-width: 62px;
  background: var(--bg-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  color: var(--text-secondary); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px;
  padding: 10px 6px; cursor: pointer; transition: all var(--transition);
}
.stem-chip:hover { border-color: var(--border-focus); color: var(--text-primary); }
.stem-chip.muted {
  background: rgba(239, 68, 68, 0.08); border-color: var(--danger); color: var(--danger);
  text-decoration: line-through;
}

/* switches (extras: beat swap) */
.switch-list { display: flex; flex-direction: column; gap: 6px; }
.switch-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--bg-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  padding: 8px 12px;
}
.switch-label {
  display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 600;
  color: var(--text-secondary); text-transform: capitalize;
}
.switch {
  position: relative; width: 38px; height: 21px; border-radius: 99px; flex-shrink: 0;
  background: var(--border-focus); border: none; cursor: pointer; transition: background var(--transition);
}
.switch .switch-thumb {
  position: absolute; top: 2.5px; left: 3px; width: 16px; height: 16px; border-radius: 50%;
  background: var(--text-primary); transition: transform var(--transition);
}
.switch.on { background: var(--accent-primary); }
.switch.on .switch-thumb { transform: translateX(16px); }
.switch:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 2px; }

/* ---------- RIGHT: MASTER RACK ---------- */
.player-wrapper { width: 35%; min-width: 340px; flex-shrink: 0; }
.player-panel {
  position: sticky; top: 24px; background: var(--bg-panel); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow-panel);
  display: flex; flex-direction: column; gap: 18px;
  max-height: calc(100vh - 48px); overflow-y: auto;
}
/* the rack's sticky chrome: title + transport + tabs pin to the top of
   the panel's own scroll. Full-bleed (negative margins matched by
   padding) so scrolled panes can't peek around it, panel background so
   they can't show through, top radii so it doesn't square the panel's
   corners off. */
.rack-sticky {
  position: sticky; top: -24px; z-index: 20;   /* was `-24` (unitless =
     invalid CSS = declaration dropped = sticky never pinned) */
  display: flex; flex-direction: column; gap: 18px;
  margin: -24px -24px 0; padding: 24px 24px 0;
  background: var(--bg-panel);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.player-header { display: flex; justify-content: space-between; align-items: center; }
.player-title { font-size: 16px; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.engine-badge {
  font-size: 10px; font-weight: 700; color: var(--accent-primary); background: var(--accent-glow);
  padding: 4px 8px; border-radius: 4px; text-transform: uppercase; transition: all var(--transition);
}

/* pipeline stepper */
.stepper {
  display: flex; align-items: center; gap: 4px; background: var(--bg-base);
  border: 1px solid var(--border-subtle); border-radius: 99px; padding: 5px;
}
.step {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 6px;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;
  color: var(--text-muted); padding: 5px 2px; border-radius: 99px; transition: all var(--transition);
}
.step-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--border-focus); transition: all var(--transition); }
.step.active { color: var(--text-primary); background: var(--bg-card); }
.step.active .step-dot { background: var(--accent-primary); box-shadow: 0 0 6px var(--accent-glow); }
.step.done { color: var(--text-secondary); }
.step.done .step-dot { background: var(--ok); }

.rack-section { display: flex; flex-direction: column; gap: 10px; }
.rack-section.locked { opacity: 0.45; pointer-events: none; filter: saturate(0.4); }
.lock-label { display: flex; justify-content: space-between; align-items: center; }
.lock-hint { display: flex; align-items: center; gap: 4px; font-size: 10px; color: var(--text-muted); text-transform: none; letter-spacing: 0; }

.output-row { display: flex; align-items: center; gap: 10px; }
.output-row .source-input {
  background: var(--bg-base); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: 9px 12px;
}
.check-row {
  display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700;
  color: var(--text-secondary); cursor: pointer; user-select: none; font-family: var(--mono);
}
.check-row input { accent-color: var(--accent-primary); }

/* negotiation readout */
.target-row {
  display: flex; gap: 16px; align-items: center; background: var(--bg-base);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: 14px 16px;
}
.target-bpm-block { text-align: center; flex-shrink: 0; }
.target-bpm { font-size: 30px; font-weight: 700; color: var(--accent-primary); line-height: 1; transition: color var(--transition); }
.target-bpm-label { font-size: 9px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1.5px; margin-top: 4px; }
.target-meta { flex: 1; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.target-meta-line { display: flex; justify-content: space-between; font-size: 11px; color: var(--text-muted); }
.target-meta-line .mono { color: var(--text-secondary); font-weight: 700; }

/* master knobs (Mix pitch + Speed): their own centered band between the
   negotiated-target box and the ratio rows — knobs sit at 1/3 and 2/3
   of the rack width (space-evenly on two items). */
#master-knob-wrap { width: 100%; margin: 8px 0; }
#master-knob-wrap.locked { opacity: 0.45; pointer-events: none; filter: saturate(0.4); }
#master-knob-wrap > .extra-knobs { width: 100%; justify-content: space-evenly; }

/* the speed⇄pitch lock, seated between the two master knobs */
.knob-lock-btn {
  align-self: center; width: 32px; height: 32px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-base); border: 1px dashed var(--border-focus);
  color: var(--text-muted); cursor: pointer; flex-shrink: 0;
  transition: all var(--transition);
}
.knob-lock-btn:hover { color: var(--text-secondary); border-color: var(--text-muted); }
.knob-lock-btn.on {
  border-style: solid; border-color: var(--accent-primary);
  color: var(--accent-primary); background: var(--accent-glow);
  box-shadow: 0 0 12px var(--accent-glow);
}

.steps-row { display: flex; gap: 10px; }
.deck-steps { margin-top: 10px; }
.deck-steps .steps-block { max-width: none; }
/* ratio knob + follow/lead toggle, space-evenly like the master
   pitch/speed pair on the Mixer tab */
.ratio-row {
  display: flex; align-items: center; justify-content: space-evenly;
  width: 100%; padding: 4px 0;
}
.follow-toggle {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-width: 96px; padding: 9px 16px; border-radius: 99px;
  background: transparent; border: 1px dashed var(--border-focus);
  color: var(--text-muted); font-size: 11px; font-weight: 700; font-family: var(--mono);
  text-transform: uppercase; letter-spacing: 0.5px; cursor: pointer;
  transition: all var(--transition);
}
.follow-toggle:hover { color: var(--text-secondary); border-color: var(--text-muted); }
.follow-toggle.on { border-style: solid; color: var(--text-secondary); }
.follow-toggle:not(.on) {
  border-style: solid; border-color: var(--accent-primary);
  color: var(--accent-primary); background: var(--accent-glow);
}
.steps-block { flex: 1; display: flex; flex-direction: column; gap: 5px; }
.steps-label { font-size: 9px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px; }
.seg { display: flex; background: var(--bg-base); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: 3px; gap: 3px; }
.seg-btn {
  flex: 1; background: transparent; border: none; border-radius: 6px; color: var(--text-muted);
  font-size: 12px; font-weight: 700; font-family: var(--mono); padding: 6px 0; cursor: pointer;
  transition: all var(--transition);
}
.seg-btn:hover { color: var(--text-secondary); }
.seg-btn.active { background: var(--accent-glow); color: var(--accent-primary); }

/* actions */
.rack-actions { display: flex; flex-direction: column; gap: 10px; }

/* the analyze row: the big button gives up a sliver of its width to a
   small gear that opens the analysis options. The mash row mirrors it
   (its gear wears the mash button's fill, per the mockup). Button text
   stays CENTERED in the remaining width. */
.analyze-row, .mash-row { display: flex; align-items: stretch; gap: 8px; }
.analyze-row .analyze-main, .mash-row .mash-main { flex: 1 1 auto; width: auto; }
.analyze-row .analyze-gear, .mash-row .mash-gear {
  flex: 0 0 auto; width: auto; padding: 14px 16px;
}
.analyze-row .analyze-gear.tinkered {   /* any stage off: a quiet hint */
  border-style: solid; border-color: var(--accent-primary);
  color: var(--accent-primary);
}
/* item 6: while a mash runs, the main button is the CANCEL button */
.mash-btn.cancel {
  background: rgba(239, 68, 68, 0.15);
  border-color: var(--danger); color: var(--danger);
}

.btn {
  display: flex; align-items: center; justify-content: center; gap: 8px; border: none; cursor: pointer;
  border-radius: var(--radius-sm); padding: 14px 24px; font-size: 14px; font-weight: 700;
  transition: all var(--transition);
}
.btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none !important; }
.ghost-btn { background: transparent; color: var(--text-secondary); border: 1px dashed var(--border-focus); width: 100%; }
.ghost-btn:hover:not(:disabled) { background: var(--bg-card); color: var(--text-primary); border-color: var(--text-secondary); }
.mash-btn { background: var(--accent-primary); color: #fff; width: 100%; box-shadow: 0 4px 14px var(--accent-glow); }
.mash-btn:hover:not(:disabled) { background: var(--accent-hover); transform: translateY(-1px); }
.mash-btn:active:not(:disabled) { transform: translateY(1px); }

/* transport + speed */
.transport-row { display: flex; align-items: center; gap: 8px; }
.transport-btn {
  padding: 10px 14px; background: var(--bg-card); border: 1px solid var(--border-focus); color: var(--text-primary);
}
.transport-btn:hover { border-color: var(--accent-primary); color: var(--accent-primary); }
.transport-note { font-size: 10px; color: var(--text-muted); margin-left: auto; text-align: right; }

.speed-row { display: flex; align-items: center; gap: 10px; }
input[type="range"] {
  flex: 1; appearance: none; -webkit-appearance: none; height: 4px; border-radius: 99px;
  background: linear-gradient(to right, var(--border-focus), var(--accent-primary)); outline: none; cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
  appearance: none; -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%;
  background: var(--text-primary); border: 3px solid var(--accent-primary); cursor: pointer;
  transition: transform 0.15s ease;
}
input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.15); }
input[type="range"]::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%; background: var(--text-primary);
  border: 3px solid var(--accent-primary); cursor: pointer;
}

/* ---------- STEREO FIELD CROSSFADER (3-way) ---------- */
.xfader-panel { display: flex; align-items: flex-end; gap: 10px; }
.xf-col { flex: 1; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.xf-col.spread { flex: 1.15; }
.xf-divider { width: 1px; align-self: stretch; background: var(--border-subtle); }
.xf-label {
  font-size: 9px; font-weight: 700; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 1px; text-align: center;
}
.xf-label.accent { color: var(--accent-primary); }
.xf-read { font-size: 11px; font-weight: 700; color: var(--text-secondary); text-align: center; }
.xfader-panel .mini-btn { margin-bottom: 22px; }

/* crossfader tracks: notched rail with a flat grip-lined thumb */
input[type="range"].xfader {
  appearance: none; -webkit-appearance: none; width: 100%; height: 16px;
  border-radius: 4px; border: 1px solid var(--border-subtle); cursor: pointer;
  background:
    linear-gradient(to right, transparent 49.2%, var(--text-muted) 49.2%, var(--text-muted) 50.8%, transparent 50.8%),
    repeating-linear-gradient(to right,
      var(--border-subtle) 0, var(--border-subtle) 1px, transparent 1px, transparent 12.5%),
    var(--bg-base);
}
input[type="range"].xfader.spread {
  background:
    linear-gradient(to right, var(--accent-glow), var(--accent-glow)),
    repeating-linear-gradient(to right,
      var(--border-subtle) 0, var(--border-subtle) 1px, transparent 1px, transparent 10%),
    var(--bg-base);
}
input[type="range"].xfader::-webkit-slider-thumb {
  appearance: none; -webkit-appearance: none; width: 14px; height: 26px;
  border-radius: 3px; border: 1px solid var(--border-focus); cursor: ew-resize;
  background:
    repeating-linear-gradient(to right,
      transparent 0, transparent 4px, rgba(0,0,0,0.55) 4px, rgba(0,0,0,0.55) 5px),
    linear-gradient(to bottom, #fafafa, #c9c9cf 45%, #8f8f98);
  box-shadow: 0 2px 6px rgba(0,0,0,0.6);
  transition: transform 0.12s ease;
}
input[type="range"].xfader::-webkit-slider-thumb:hover { transform: scaleY(1.08); }
input[type="range"].xfader.spread::-webkit-slider-thumb {
  background:
    repeating-linear-gradient(to right,
      transparent 0, transparent 4px, rgba(0,0,0,0.45) 4px, rgba(0,0,0,0.45) 5px),
    linear-gradient(to bottom, var(--accent-hover), var(--accent-primary));
  border-color: var(--accent-primary);
}
input[type="range"].xfader::-moz-range-thumb {
  width: 14px; height: 26px; border-radius: 3px; border: 1px solid var(--border-focus);
  background: linear-gradient(to bottom, #fafafa, #8f8f98); cursor: ew-resize;
}
input[type="range"].xfader.spread::-moz-range-thumb {
  background: linear-gradient(to bottom, var(--accent-hover), var(--accent-primary));
  border-color: var(--accent-primary);
}

/* ---------- MIX TIMELINE ---------- */
.tl-wrapper {
  position: relative; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  background: var(--bg-base); overflow: hidden; cursor: crosshair; height: 68px;
}
.tl-wrapper:hover { border-color: var(--border-focus); }
#tl-canvas { display: block; }
.tl-lane-labels {
  position: absolute; left: 6px; top: 0; bottom: 0; display: flex; flex-direction: column;
  justify-content: space-around; pointer-events: none;
}
.tl-lane-labels span {
  font-family: var(--mono); font-size: 10px; font-weight: 700; color: rgba(255,255,255,0.75);
  text-shadow: 0 1px 3px rgba(0,0,0,0.9);
}
.tl-cursor {
  position: absolute; top: 0; bottom: 0; left: 0; width: 2px;
  background: var(--text-primary); box-shadow: 0 0 8px rgba(255,255,255,0.6);
  pointer-events: none;
  /* NO left-transition: the cursor rides the dead-reckoned clock at
     frame rate (tlGlideEnsure), so a CSS lerp here just re-adds the
     catch-up lag it replaced. Seeks land instantly by design. */
}
.tl-cursor.playing::after {
  content: ""; position: absolute; top: -1px; left: -3px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--accent-primary); box-shadow: 0 0 8px var(--accent-primary);
}
/* item 6: the draggable dot — a generous invisible hit disc riding the
   cursor top; the visible dot stays the ::after above */
.tl-cursor-dot {
  position: absolute; top: -6px; left: -8px; width: 18px; height: 18px;
  border-radius: 50%; pointer-events: auto; cursor: grab;
}
.tl-cursor-dot:active { cursor: grabbing; }

/* ---------- STEM TIMELINES (stacked mute rows) ---------- */
.stemline-list { display: flex; flex-direction: column; gap: 5px; }
.stemline { display: flex; align-items: center; gap: 8px; }
.stemline-btn {
  display: flex; align-items: center; gap: 6px; width: 96px; flex-shrink: 0;
  background: var(--bg-card); border: 1px solid var(--border-subtle); border-radius: 6px;
  color: var(--text-secondary); font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.4px; padding: 5px 8px; cursor: pointer; transition: all var(--transition);
}
.stemline-btn:hover { border-color: var(--border-focus); color: var(--text-primary); }
.stemline-btn.muted {
  background: rgba(239, 68, 68, 0.08); border-color: var(--danger); color: var(--danger);
  text-decoration: line-through;
}
.stemline-strip {
  flex: 1; height: 18px; min-width: 0; border: 1px solid var(--border-subtle);
  border-radius: 4px; background: var(--bg-base); overflow: hidden; cursor: crosshair;
}
.stemline-strip:hover { border-color: var(--border-focus); }
.stemline.muted .stemline-strip { opacity: 0.55; }
.stemline-canvas { display: block; }

/* ---------- BUSY / IN-FLIGHT EDIT STATE ---------- */
body.live-busy .deck-tab-body button,
body.live-busy #live-master button,
body.live-busy #live-master input,
body.live-busy .stemline-strip {
  opacity: 0.45; pointer-events: none;
}
body.live-busy .switch.busy {
  opacity: 1; pointer-events: none;
  background: var(--accent-primary);
  animation: busyPulse 0.9s ease-in-out infinite;
}
body.live-busy .switch.busy .switch-thumb { transform: translateX(8px); }
@keyframes busyPulse { 50% { filter: brightness(1.6); box-shadow: 0 0 10px var(--accent-glow); } }
.working-note { font-size: 9px; color: var(--accent-primary); text-transform: none; letter-spacing: 0; }

/* ---------- ARMED ANALYZE ---------- */
.ghost-btn.armed {
  border-style: solid; border-color: var(--accent-primary); color: var(--accent-primary);
  box-shadow: 0 0 14px var(--accent-glow), inset 0 0 14px var(--accent-glow);
}
.ghost-btn.armed:hover:not(:disabled) { background: var(--accent-glow); color: var(--accent-primary); }

/* console */
.console {
  background: var(--bg-base); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  padding: 12px 14px; height: 170px; overflow-y: auto; font-family: var(--mono);
  font-size: 11px; line-height: 1.7; color: var(--text-secondary);
}
.console-line { word-break: break-word; }
.console-line.head { color: var(--text-primary); font-weight: 700; margin-top: 4px; }
.console-line.ok { color: var(--ok); }
.console-line.err { color: var(--danger); }
.console-line.muted { color: var(--text-muted); }

/* ---------- FOCUS VISIBILITY ---------- */
button:focus-visible, input:focus-visible {
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
}

/* ---------- RESPONSIVE ---------- */
@media (max-width: 1024px) {
  .app-container { flex-direction: column; padding: 0 20px 40px 20px; }
  .player-wrapper { width: 100%; }
  .player-panel { position: static; max-height: none; }
  .rack-sticky { position: static; }   /* the panel doesn't scroll here */
  .header { flex-direction: column; align-items: flex-start; gap: 24px; padding: 30px 20px 20px 20px; }
  .top-controls { width: 100%; justify-content: space-between; }
}

@media (max-width: 600px) {
  .deck-stats { grid-template-columns: repeat(2, 1fr); }
  .nudge-row { flex-wrap: wrap; }
  .nudge-row .pill-btn { min-width: 52px; }
  .stem-row { gap: 6px; }
  .target-row { flex-direction: column; align-items: stretch; text-align: center; }
}

/* ---------- HIDE UI (admire the background) ---------- */
#app-container, #brand-group {
  transition: opacity 0.6s ease;
}
body.ui-hidden #app-container,
body.ui-hidden #brand-group {
  opacity: 0;
  pointer-events: none;
}
body.ui-hidden .top-controls {
  opacity: 1;
}

/* ---------- RACK TABS + PANES ---------- */
.rack-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border-subtle); }
.rack-pane { display: flex; flex-direction: column; gap: 18px; }
.rack-pane.hidden { display: none; }

/* ---------- DUMMY / COMING-SOON MODULES ---------- */
.soon-badge {
  font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px;
  color: var(--text-muted); border: 1px dashed var(--border-focus);
  padding: 2px 8px; border-radius: 99px;
}
.soon-block { opacity: 0.75; }
.switch-row.dummy { opacity: 0.55; }
.switch:disabled { cursor: not-allowed; }

/* ---------- DECK HEAD (badge + remove) ---------- */
.deck-head-right { display: flex; align-items: center; gap: 8px; min-width: 0; }
.deck-remove { width: 24px; height: 24px; }
.deck-remove:hover { color: var(--danger); border-color: var(--danger); }

/* ---------- N-WAY XFADER LAYOUT ---------- */
.xf-decks { display: flex; flex: 2.2; gap: 8px; min-width: 0; }
.xf-decks .xf-col { min-width: 0; }
.deck-tabs { flex-wrap: wrap; }


/* ---------- PER-DECK SHADES (#2) ---------- */
.song-card.deck.open {
  border-color: var(--deck-accent, var(--accent-primary));
  box-shadow: 0 0 0 1px var(--deck-accent, var(--accent-primary));
}
.deck .wave-bar { background: var(--deck-accent, var(--accent-primary)); }
.deck .deck-dot.ready,
.deck .deck-dot.live { background: var(--deck-accent, var(--accent-primary)); box-shadow: 0 0 8px var(--accent-glow); }
.deck .deck-tab.active { color: var(--deck-accent, var(--accent-primary)); border-bottom-color: var(--deck-accent, var(--accent-primary)); }
.deck .bpm-toggle.active { color: var(--deck-accent, var(--accent-primary)); border-color: var(--deck-accent, var(--accent-primary)); }

/* ---------- TIMELINE ROW GRID (#1/#1a) ---------- */
.tl-grid { position: relative; display: flex; flex-direction: column; }
#tl-rows { display: flex; flex-direction: column; gap: 4px; }
.tl-row { display: flex; align-items: center; gap: 8px; }
.tl-row.muted .tl-strip { opacity: 0.5; }
.tl-label {
  display: flex; align-items: center; gap: 5px; width: 150px; flex-shrink: 0; min-width: 0;
}
.tl-label.indent { padding-left: 20px; width: 150px; }
.tl-btn {
  display: flex; align-items: center; justify-content: center; width: 20px; height: 20px;
  flex-shrink: 0; background: var(--bg-card); border: 1px solid var(--border-subtle);
  border-radius: 5px; color: var(--text-secondary); cursor: pointer; transition: all var(--transition);
}
.tl-btn:hover { color: var(--text-primary); border-color: var(--border-focus); }
.tl-btn.muted { color: var(--danger); border-color: rgba(239, 68, 68, 0.4); background: rgba(239, 68, 68, 0.08); }
.tl-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.tl-name {
  font-size: 10.5px; font-weight: 700; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; min-width: 0;
}
.tl-name.stem { color: var(--text-secondary); text-transform: capitalize; font-weight: 600; }
/* virtual master track: combined-energy view (its FX fans out to every deck) */
.tl-name.master { color: var(--text-primary); text-transform: uppercase; letter-spacing: 0.1em; font-size: 9px; }
.tl-strip {
  flex: 1; min-width: 0; border: 1px solid var(--border-subtle); border-radius: 4px;
  background: var(--bg-base); overflow: hidden; cursor: crosshair; line-height: 0;
}
.tl-strip:hover { border-color: var(--border-focus); }
.tl-row .tl-strip { height: 62px; }   /* deck buses read prominent (2x) */
.tl-row.stem .tl-strip { height: 32px; }

/* ---------- SWAP CHIPS (#9) ---------- */
.swap-chip-row { display: flex; gap: 8px; }
.swap-chip {
  flex: 1; display: flex; align-items: center; justify-content: center; height: 38px;
  background: var(--bg-card); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  color: var(--text-secondary); cursor: pointer; transition: all var(--transition);
}
.swap-chip:hover { border-color: var(--border-focus); color: var(--text-primary); }
.swap-chip.on {
  background: var(--accent-glow); border-color: var(--deck-accent, var(--accent-primary));
  color: var(--deck-accent, var(--accent-primary));
}
.swap-chip.busy {
  pointer-events: none; color: var(--accent-primary);
  animation: busyPulse 0.9s ease-in-out infinite;
}

/* ---------- FLATTEN TEMPO TOGGLE (#10) ---------- */
.flatten-toggle {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  margin-top: 5px; padding: 3px 8px; border-radius: 99px;
  background: transparent; border: 1px dashed var(--border-focus);
  color: var(--text-muted); font-size: 9px; font-weight: 700; font-family: var(--mono);
  text-transform: uppercase; letter-spacing: 0.5px; cursor: pointer; transition: all var(--transition);
}
.flatten-toggle:hover { color: var(--text-secondary); border-color: var(--text-muted); }
.flatten-toggle.on { border-style: solid; color: var(--text-secondary); }
.flatten-toggle:not(.on) {
  border-style: solid; border-color: var(--accent-primary);
  color: var(--accent-primary); background: var(--accent-glow);
}

/* metronome block lock */
#metronome-block.locked { opacity: 0.45; pointer-events: none; filter: saturate(0.4); }
#rain-block.locked { opacity: 0.45; pointer-events: none; filter: saturate(0.4); }

/* transport state lights: faint fill while playing / paused */
.transport-btn.lit {
  background:
    radial-gradient(circle at 50% 120%, var(--accent-glow), transparent 60%),
    var(--accent-glow);
  color: var(--text-primary);
  box-shadow: 0 0 18px var(--accent-glow), inset 0 0 10px var(--accent-glow);
}

/* recommended ±3 pitch jump (stays in the negotiated pair) */
.pill-btn.rec {
  border-color: var(--accent-primary);
  color: var(--accent-primary);
  background: var(--accent-glow);
}

/* ---------- ROTARY KNOBS (sidechain / extras / smart mix) ---------- */
.knob-wrap {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  width: 64px; flex-shrink: 0; user-select: none;
}
.knob {
  position: relative; width: 42px; height: 42px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--bg-card-hover), var(--bg-base) 75%);
  border: 1px solid var(--border-focus); cursor: ns-resize; touch-action: none;
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.55), 0 1px 0 rgba(255,255,255,0.04);
  transition: border-color var(--transition);
}
.knob:hover { border-color: var(--accent-primary); }
.knob .knob-pointer {
  position: absolute; left: 50%; top: 50%; width: 2px; height: 15px;
  margin-left: -1px; background: var(--accent-primary); border-radius: 2px;
  transform-origin: 50% 0%;
  transform: rotate(var(--deg, 0deg)) translateY(-19px) rotate(180deg);
  box-shadow: 0 0 6px var(--accent-glow);
}
.knob-label {
  font-size: 9px; font-weight: 700; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 1px;
}
.knob-read { font-size: 10px; font-weight: 700; color: var(--text-secondary); }

/* ---------- SIDECHAIN TAB ---------- */
.sc-body { display: flex; flex-direction: column; gap: 12px; }
.sc-body.sc-dim { opacity: 0.5; }
.sc-body.sc-dim .sc-row, .sc-body.sc-dim .knob { pointer-events: none; }
.sc-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sc-word { font-size: 11px; color: var(--text-muted); font-weight: 600; flex-shrink: 0; }
.sc-select {
  flex: 1; min-width: 110px; background: var(--bg-base); color: var(--text-secondary);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
  font-family: var(--mono); font-size: 11px; font-weight: 700; padding: 7px 8px;
  cursor: pointer; outline: none; transition: border-color var(--transition);
}
.sc-select:hover, .sc-select:focus { border-color: var(--border-focus); color: var(--text-primary); }
.sc-select option { background: var(--bg-panel); color: var(--text-primary); }
.pill-btn.sc-impact { min-width: 62px; text-transform: uppercase; letter-spacing: 0.5px; }
.pill-btn.sc-impact.duck { border-color: var(--danger); color: var(--danger); }
.pill-btn.sc-impact.boost { border-color: var(--accent-primary); color: var(--accent-primary); background: var(--accent-glow); }
.sc-knob-row { display: flex; align-items: center; gap: 14px; }
.sc-note { flex: 1; }

/* ---------- DISTORTION CHIPS (Extras) ---------- */
.swap-chip.dist.on {
  background: rgba(244, 63, 94, 0.12);
  border-color: var(--danger);
  color: var(--danger);
  box-shadow: 0 0 10px rgba(244, 63, 94, 0.18) inset;
}



/* ---------- EXTRAS: thin horizontal bars (mockup layout) ---------- */
/* The deck card is a size container; when it's wide enough, the thin
   extras bars flow into two columns. The master mixer's bars are plain
   .control-block rows and stay full width regardless. */
.song-card.deck { container-type: inline-size; }
/* multicol (not grid): bars pack vertically, so a short bar (Beat swap)
   doesn't inherit its row-mate's height. Flow is down-then-across. */
/* ---------- extras chip bar (collapsed cards) ---------- */
.extras-chipbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: 10px 0 4px;
}
.extra-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 8px 14px; border-radius: 999px; cursor: pointer;
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.02em;
  color: var(--text-secondary);
  background: var(--bg-card); border: 1px solid var(--border-subtle);
  transition: border-color var(--transition), color var(--transition);
}
.extra-chip:hover { border-color: var(--border-focus); color: var(--text-primary); }
.extra-chip.active { border-color: var(--accent-primary); color: var(--text-primary); }
.extra-chip.open {
  border-color: var(--accent-primary);
  color: var(--text-primary);
  background: color-mix(in srgb, var(--accent-primary) 14%, var(--bg-card));
  box-shadow: 0 0 10px var(--accent-glow), inset 0 0 5px var(--accent-glow);
}
.chip-dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent-primary);
  box-shadow: 0 0 5px var(--accent-primary);
}
.chipbar-spacer { flex: 1; }
.chipbar-btn { width: auto; padding: 0 8px; font-size: 9px; }
/* an open card's name is the collapse handle */
.extra-label.clickable { cursor: pointer; }
.extra-label.clickable:hover { color: var(--accent-primary); }

.extras-grid {
  column-count: 1;
}
@container (min-width: 720px) {
  .extras-grid { column-count: 2; column-gap: 8px; }
}
.extra-block {
  position: relative;               /* anchors the active-light dot */
  break-inside: avoid;              /* never split a bar across columns */
  margin-bottom: 8px;               /* was the grid gap */
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 8px 12px 10px;
  background: rgba(255, 255, 255, 0.015);
  transition: border-color var(--transition);
}
.extra-head-row {
  display: flex; align-items: center; gap: 8px;
  color: var(--text-secondary);
  margin-bottom: 2px;
}
.extra-label {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 1px 6px; border-radius: 6px;
  transition: color var(--transition), text-shadow var(--transition),
              background var(--transition);
}
/* tiny status light, top-right of a bar with >=1 active stem */
.extra-live-dot {
  position: absolute; top: 9px; right: 11px;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent-primary);
  box-shadow: 0 0 6px var(--accent-glow), 0 0 12px var(--accent-glow);
}

/* backlit label = the extra is running */
.extra-block.active .extra-label {
  color: var(--accent-primary);
  background: var(--accent-glow);
  text-shadow: 0 0 12px var(--accent-glow);
}
.extra-block.active .extra-head-row > i:first-child { color: var(--accent-primary); }

/* one band for dials + mid controls; the stems take their own full row */
.extra-flex {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 18px;   /* clearance: knob pointers peak above the cap --
                         one number to tweak if it still kisses the title */
}
.extra-knobs { display: flex; gap: 12px; flex-wrap: wrap; }
.extra-mid { min-width: 0; }
/* when the mid slot holds a mini switch (gate NUDGE), grow into the free
   band between dials and edge and center the switch in it.
   :has() — Chrome/Edge 105+, same floor as the container query above. */
.extra-mid:has(> .switch-row.mini) {
  flex: 1; display: flex; justify-content: center;
}
.extra-stems {
  flex-basis: 100%;             /* own row, spanning the card */
  display: flex; gap: 8px;
  align-items: stretch;
  margin-top: 8px;
}
.extra-stems .stem-btn { flex: 1 1 0; width: auto; }

/* sidechain: stem tile + short logic button stacked per column */
.sc-stem-col {
  flex: 1 1 0; display: flex; flex-direction: column; gap: 4px;
}
.sc-stem-col .stem-btn { flex: 0 0 auto; width: 100%; }
.logic-btn {
  height: 20px; width: 100%;
  border-radius: 7px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text-muted);
  font-size: 9px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  cursor: pointer;
  transition: border-color var(--transition), color var(--transition),
              background var(--transition), box-shadow var(--transition);
}
.logic-btn:hover { border-color: var(--accent-primary); color: var(--text-secondary); }
/* stem's rule is RUNNING: white text + the play button's thin accent
   outline (quiet confidence; the glow belongs to the open menu now) */
.logic-btn.lit {
  color: var(--text-primary);
  border-color: var(--accent-primary);
}
/* rule menu is OPEN: glows like a lit stem tile */
.logic-btn.editing {
  border-color: var(--accent-primary);
  color: var(--text-primary);
  background: var(--accent-glow);
  box-shadow: 0 0 8px var(--accent-glow);
}

/* header-row logic button (beat router) — same states, content-sized */
.logic-btn.swap-logic { width: auto; height: 18px; padding: 0 8px; }

/* bank-to-preset bookmark: TOP-RIGHT of the tile, just left of the
   active light's spot (fixed there whether the light is on or not),
   revealed on hover — invisible in the resting UI, discoverable the
   moment you mouse the card */
.bank-btn {
  position: absolute; right: 26px; top: 5px;
  width: 22px; height: 20px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg-card);          /* legible over whatever it floats on */
  color: var(--text-muted);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition), color var(--transition),
              border-color var(--transition);
  z-index: 2;
}
.extra-block:hover .bank-btn,
.bank-btn:focus-visible { opacity: 1; pointer-events: auto; }
.bank-btn:hover { color: var(--accent-primary); border-color: var(--accent-primary); }

/* ---------- BEAT ROUTER (generalized swap) ---------- */
/* The router owns a full row of the bar and is centered in it: width is
   a fixed 10% of the row PER BEAT (8 beats = 80%, scaling down to 3), so
   the cells stay roomy and consistent across window sizes. */
.extra-mid:has(> .swap-router-wrap) {
  flex-basis: 100%; min-width: 0;
  display: flex; flex-direction: column; gap: 10px;   /* router, then the bake slot */
}
.swap-router-wrap {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
}
/* beat-router toolbar head: dice + logic, holding the card's top-left
   corner (mirrors the stutter head) */
.swap-head { display: flex; align-items: center; gap: 8px; }
.swap-router {
  position: relative;               /* anchors the wire overlay */
  width: min(100%, calc(var(--swap-w, 8) * 10%));
  display: flex; align-items: center; gap: 8px;
  padding: 10px;
  border: 1px solid var(--accent-primary);
  border-radius: 10px;
  background: var(--bg-card);
  box-shadow: 0 0 10px var(--accent-glow);
}
.swap-rows { flex: 1; display: flex; flex-direction: column; gap: 30px; }
.swap-row { display: flex; gap: 6px; }
.swap-cell {
  flex: 1 1 0; height: 26px; min-width: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 7px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text-secondary);
  font-size: 11px; font-weight: 700;
  font-family: 'JetBrains Mono', monospace;
  transition: border-color var(--transition), color var(--transition),
              background var(--transition), box-shadow var(--transition);
}
.swap-cell.top { cursor: grab; touch-action: none; }  /* pointer-drag source */
.swap-cell.top:hover { border-color: var(--accent-primary); color: var(--text-primary); }
.swap-cell.bot { cursor: default; color: var(--text-muted); }
/* connected output: lights up pleasantly */
.swap-cell.bot.routed {
  cursor: pointer;
  border-color: var(--accent-primary);
  color: var(--text-primary);
  background: var(--accent-glow);
  box-shadow: 0 0 10px var(--accent-glow), inset 0 0 6px var(--accent-glow);
}
.swap-wires {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  overflow: visible;
}
.swap-wires .swap-wire {
  fill: none;
  stroke: var(--accent-primary);
  stroke-width: 1.5;
  opacity: 0.8;
}
.swap-wires .swap-wire.drag { stroke-dasharray: 4 3; opacity: 1; }
.swap-size {
  width: 22px; height: 22px; flex-shrink: 0;
  border-radius: 7px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text-muted);
  font-size: 13px; font-weight: 700; line-height: 1;
  cursor: pointer;
  transition: border-color var(--transition), color var(--transition);
}
.swap-size:hover { border-color: var(--accent-primary); color: var(--text-primary); }

/* ---------- PRESET BANK (Editor tab) + modal input ---------- */
.modal-input { width: 100%; margin: 12px 0 4px; }
.preset-list { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.preset-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 6px 10px;
  border: 1px solid var(--border-subtle);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.015);
}
.preset-name { font-size: 12px; font-weight: 600; color: var(--text-secondary); }
.preset-meta { font-size: 10px; color: var(--text-muted); }
.preset-empty { font-size: 11px; color: var(--text-muted); margin-top: 8px; }

/* the tiny per-stem rule window (inline, appears when logic is clicked) */
.sc-rules {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 8px 10px;
  border: 1px solid var(--accent-primary);
  border-radius: 10px;
  background: var(--bg-card);
  box-shadow: 0 0 10px var(--accent-glow);
}
/* stem tiles: wider-than-square icon buttons, lit like the transport
   play button when engaged */
.stem-btn {
  width: 56px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text-muted);
  cursor: pointer;
  transition: border-color var(--transition), color var(--transition),
              background var(--transition), box-shadow var(--transition);
}
.stem-btn:hover { border-color: var(--accent-primary); color: var(--text-secondary); }
.stem-btn.lit {
  border-color: var(--accent-primary);
  color: var(--text-primary);
  background:
    radial-gradient(circle at 50% 120%, var(--accent-glow), transparent 60%),
    var(--accent-glow);
  box-shadow: 0 0 14px var(--accent-glow), inset 0 0 8px var(--accent-glow);
}
.stem-btn.busy { opacity: 0.5; cursor: wait; }

/* ---------- MIXER: horizontal bars (knobs left, switch right) ---------- */
.mixer-flex {
  display: flex; align-items: center; gap: 16px;
  margin-top: 14px;   /* same pointer clearance as the extras bars */
}
.mixer-knobs { display: flex; gap: 12px; flex-shrink: 0; }
.switch-row.grow { flex: 1; }
.switch-row.mini {
  padding: 6px 10px; gap: 8px;
  border: 1px solid var(--border); border-radius: 10px;
}
.switch-row.mini .switch-label {
  font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-muted);
}

/* ---------- SHIFT-FOR-HELP ---------- */
.help-tip {
  position: fixed; z-index: 9999;
  max-width: 320px;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--accent-primary);
  background: var(--bg-card);
  color: var(--text-secondary);
  font-size: 12px; line-height: 1.5;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5), 0 0 14px var(--accent-glow);
  opacity: 0; pointer-events: none;
  transition: opacity 120ms ease;
}
.help-tip.show { opacity: 1; }
.help-hint {
  font-size: 10px; color: var(--text-muted);
  letter-spacing: 0.04em; margin-top: 2px;
  opacity: 0.7;
}

/* ---------- SMART MIX BLOCK ---------- */
#smartmix-block.locked { opacity: 0.45; pointer-events: none; filter: saturate(0.4); }
#voxfocus-block.locked .vox-decks,
#voxfocus-block.locked .vox-ctl { opacity: 0.45; pointer-events: none; filter: saturate(0.4); }
#smx-knobs { margin-top: 4px; gap: 20px; }
#smx-knobs:empty { display: none; }

/* ---------- TRANSPORT: prominent + theme glow (overrides base rule) ---------- */
.transport-btn {
  width: 44px; height: 44px; padding: 0; border-radius: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--accent-primary);
  color: var(--accent-primary);
  background:
    radial-gradient(circle at 50% 120%, var(--accent-glow), transparent 70%),
    var(--bg-card);
  box-shadow: 0 0 14px var(--accent-glow), inset 0 0 8px rgba(0,0,0,0.35);
  transition: box-shadow var(--transition), transform var(--transition),
              background var(--transition), color var(--transition);
}
.transport-btn:hover {
  color: var(--text-primary);
  background: var(--accent-primary);
  box-shadow: 0 0 22px var(--accent-glow), 0 0 44px var(--accent-glow);
  transform: translateY(-1px);
}
.transport-btn:active { transform: translateY(0) scale(0.96); }
.locked .transport-btn { box-shadow: none; border-color: var(--border-subtle); color: var(--text-muted); background: var(--bg-card); }
/* smaller secondary transport controls (repeat / render), set a little
   apart from play·pause·stop */
.transport-btn.small { width: 32px; height: 32px; border-radius: 9px; }
.transport-btn.tp-repeat { margin-left: 20px; }

/* ---------- SECTION HEADER RIGHT + RESTART ---------- */
.section-title-right { display: inline-flex; align-items: center; gap: 8px; }
.restart-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 7px; cursor: pointer;
  background: transparent; border: 1px solid var(--border-subtle);
  color: var(--text-muted); transition: all var(--transition);
}
.restart-btn:hover:not(:disabled) {
  border-color: var(--danger); color: var(--danger);
  box-shadow: 0 0 10px rgba(244, 63, 94, 0.25);
}
.restart-btn:disabled { opacity: 0.35; cursor: default; }

/* ---------- CONFIRM MODAL ---------- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(3, 6, 10, 0.65); backdrop-filter: blur(4px);
  animation: modal-in 0.14s ease-out;
}
@keyframes modal-in { from { opacity: 0; } to { opacity: 1; } }
.modal-card {
  width: min(360px, calc(100vw - 48px));
  background: var(--bg-panel); border: 1px solid var(--border-focus);
  border-radius: var(--radius-lg); padding: 20px;
  box-shadow: 0 0 40px rgba(0,0,0,0.6), 0 0 18px var(--accent-glow);
  animation: modal-pop 0.16s ease-out;
}
@keyframes modal-pop { from { transform: scale(0.94); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.modal-msg { font-size: 13px; color: var(--text-primary); line-height: 1.5; margin-bottom: 16px; }
.modal-actions { display: flex; gap: 8px; justify-content: flex-end; }
.modal-btn { padding: 8px 14px; font-size: 11px; }
/* stem picker (bank source / load targets): tiles that light when chosen */
.modal-stems { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; margin: 4px 0 14px; }
.modal-stem {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 8px 12px; border-radius: 8px;
  border: 1px solid var(--border-subtle); background: var(--bg-card);
  color: var(--text-secondary); cursor: pointer; transition: all var(--transition);
}
.modal-stem:hover { border-color: var(--border-focus); color: var(--text-primary); }
.modal-stem.lit {
  border-color: var(--accent-primary); color: var(--accent-primary);
  background: var(--accent-glow); box-shadow: 0 0 8px var(--accent-glow);
}
.modal-stem-lab { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; }

/* ---------- SMART MIX ENGINE DIALS (compact) ---------- */
.smx-params {
  display: flex; flex-wrap: wrap; gap: 8px 12px; margin-top: 10px;
  padding-top: 10px; border-top: 1px dashed var(--border-subtle);
}
.smx-params .knob-wrap { width: 52px; }
.smx-params .knob { width: 30px; height: 30px; }
.smx-params .knob .knob-pointer {
  height: 10px;
  transform: rotate(var(--deg, 0deg)) translateY(-13px) rotate(180deg);
}
.smx-params .knob-label { font-size: 8px; letter-spacing: 0.6px; }
.smx-params .knob-read { font-size: 9px; }

/* ============================================================
   LOGO PICKER
   ============================================================ */
.logo { cursor: pointer; user-select: none; }
.brand-group { position: relative; }

/* lockups — all tinted by the live accent */
.lk-heavy {
  font-weight: 900; text-transform: lowercase; letter-spacing: -2.5px;
}
.lk-oo { height: 30px; width: auto; margin: 0 1px; align-self: center; }
.lk-term {
  font-family: var(--mono); font-weight: 700; font-size: 30px;
  text-transform: lowercase; letter-spacing: -1px;
}
.lk-cursor { color: var(--accent-primary); animation: lk-blink 1.1s steps(1) infinite; }
@keyframes lk-blink { 50% { opacity: 0; } }
.lk-round {
  font-family: 'Baloo 2', 'Inter', sans-serif; font-weight: 800;
  font-size: 38px; text-transform: lowercase; letter-spacing: -1px;
  background: linear-gradient(120deg, var(--text-primary) 30%, var(--accent-primary));
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}
.lk-outline {
  font-family: 'Unbounded', 'Inter', sans-serif; font-weight: 900;
  font-size: 28px; text-transform: lowercase; letter-spacing: 0;
  color: transparent;
  -webkit-text-stroke: 1.5px var(--accent-primary);
  text-shadow: 0 0 14px var(--accent-glow);
}

/* the dropdown */
.logo-menu {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 950;
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55), 0 0 16px var(--accent-glow);
}
.logo-option {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 6px 12px;
  border-radius: 8px;
  cursor: pointer;
  border: 1px solid transparent;
}
.logo-option:hover { background: var(--bg-card); border-color: var(--border); }
.logo-option.active { border-color: var(--accent-primary); }
.logo-option-name {
  font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.8px;
  color: var(--text-muted); white-space: nowrap;
}
.lk-preview { font-size: 26px; pointer-events: none; }
.lk-preview .lk-term { font-size: 22px; }
.lk-preview .lk-round { font-size: 27px; }
.lk-preview .lk-outline { font-size: 20px; }
.lk-preview .lk-oo { height: 21px; }
.lk-preview .logo-icon { width: 20px; }
.logo[data-logo="waveoo"], .lk-preview[data-logo="waveoo"] { gap: 2px; }

/* 12/16-beat windows: the router hits full card width, so the cells
   tighten up instead of overflowing */
.swap-router.dense { padding: 8px 6px; gap: 5px; }
.swap-router.dense .swap-row { gap: 3px; }
.swap-router.dense .swap-cell { height: 22px; font-size: 9px; border-radius: 5px; }
.swap-router.dense .swap-size { width: 18px; height: 18px; font-size: 11px; }

/* designed-pack lockups: white chip so the light artwork reads on the
   dark UI; the caption replaces the stripped "smart mixer" line */
.lk-chip {
  display: inline-flex; flex-direction: column; align-items: center; gap: 1px;
  background: #fff; border-radius: 10px; padding: 6px 12px 5px;
}
.lk-img { height: 26px; width: auto; display: block; }
.lk-engine {
  font-size: 7.5px; font-weight: 700; letter-spacing: 3px;
  text-transform: lowercase; color: #16a34a;
}
/* 31 options: the menu becomes a scrollable grid */
.logo-menu {
  display: grid; grid-template-columns: repeat(3, minmax(150px, 1fr));
  max-height: min(60vh, 520px); overflow-y: auto; gap: 4px; width: max-content;
}
.logo-option { flex-direction: column; gap: 6px; justify-content: center; }
.lk-preview .lk-img { height: 20px; }
.lk-preview .lk-chip { padding: 4px 8px 3px; }
.lk-preview .lk-engine { font-size: 6px; letter-spacing: 2px; }

/* global transport strip: above the tabs, present on every pane */
/* the transport sits between the Master Rack title and the tabs — no
   dividing line (task 9), just breathing room */
.global-transport {
  padding: 6px 0 8px;
}
.global-transport.locked { opacity: 0.45; pointer-events: none; }

/* riser row */
.riser-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.riser-beats { width: 64px; text-align: center; }
.riser-unit { font-size: 10px; color: var(--text-muted); }
.riser-knob { margin-left: auto; }

/* ============================================================
   SAMPLE PADS — even 4-wide stacks per deck, deck-color glow
   ============================================================ */
.pads-grid {
  display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px;
  container-type: inline-size;
}
.pads-block {
  display: grid; grid-template-columns: repeat(4, 56px); gap: 6px;
}
@container (max-width: 560px) {
  .pads-block { grid-template-columns: repeat(2, 56px); }
}
.pad {
  width: 56px; height: 46px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--bg-card);
  color: var(--text-secondary);
  cursor: pointer;
  transition: border-color var(--transition), box-shadow var(--transition),
              background var(--transition), color var(--transition);
}
.pad:hover { border-color: var(--deck-accent, var(--accent-primary)); }
.pad.playing {
  border-color: var(--deck-accent, var(--accent-primary));
  color: var(--text-primary);
  background: color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 18%, var(--bg-card));
  box-shadow: 0 0 12px color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 55%, transparent);
}
.pad.latched {
  border-color: var(--deck-accent, var(--accent-primary));
  box-shadow: inset 0 0 0 1px var(--deck-accent, var(--accent-primary)),
              0 0 12px color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 55%, transparent);
}
.pad.assigning {
  border-style: dashed; border-color: var(--text-primary);
  animation: lk-blink 1.1s steps(1) infinite;
}
.pad-key { font-size: 11px; font-weight: 700; color: var(--text-primary); }
.pads-legend {
  flex-basis: 100%;
  font-size: 10px; color: var(--text-muted); letter-spacing: 0.2px;
}

/* ============================================================
   STUTTER EDITOR — the beat router's look, stacked underneath it
   ============================================================ */
.swap-slot { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: stretch; gap: 1px; }
.swap-slot .swap-cell { width: 100%; }
.swap-notch {
  height: 11px; border: none; background: transparent;
  color: var(--text-muted); font-size: 8px; font-weight: 800; line-height: 1;
  font-family: var(--mono);
  cursor: pointer; padding: 0;
  opacity: 0.55; transition: opacity var(--transition), color var(--transition);
}
.swap-notch:hover { opacity: 1; color: var(--text-primary); }
.swap-notch.lit { opacity: 1; color: var(--accent-primary); }   /* shows the place count */
.swap-notch.editing { color: var(--text-primary); text-shadow: 0 0 6px var(--accent-glow); }

/* the popup IS a .swap-router (same border, glow, background); it takes
   the full row width below the router for elbow room */
.stutter-pop { width: 100%; flex-direction: column; align-items: stretch; gap: 8px; }
/* the beat router as a card with its own toolbar head — mirrors
   .stutter-pop's column layout. Compact per-window width, floored so the
   toolbar never cramps (a 3-beat router hits this floor). The logic drawer
   widens the whole card to fill its column instead of stacking the dials
   into extra rows; the number cells stretch to fit, like the stutter card. */
.swap-pop {
  flex-direction: column; align-items: stretch; gap: 8px;
  width: min(100%, max(40%, calc(var(--swap-w, 8) * 10%)));
}
.swap-pop.logic-open { width: 100%; }
.swap-pop .swap-head { margin-bottom: 2px; }
.stutter-head { display: flex; align-items: center; gap: 8px; }
/* the word "stutter" wears the card-title dress, one size down */
.stutter-title {
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-secondary);
  white-space: nowrap;
}
/* preset menu + save/load: quiet pills beside the select */
.stut-preset-sel { max-width: 150px; }
.stut-preset-btn {
  height: 20px; padding: 0 8px;
  font-size: 9px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.stut-preset-btn.icon { padding: 0 7px; }   /* in/out arrows, no label */
/* size buttons flank the rows, mirroring the beat router above. Grid so
   the − / + center on the NUMBER rows only (row 1); the bulk endpoints
   (conns, stutter only) drop to row 2, aligned under the places. Shared
   by the stutter editor and the beat router (which has no conns). */
.sg-flex {
  display: grid;
  grid-template-columns: auto 1fr auto;   /* −  |  rows  |  + */
  align-items: center;
  column-gap: 8px;
  row-gap: 26px;                          /* numbers → conns gutter */
}
.sg-flex > .sg-body,
.sg-flex > .swap-rows { min-width: 0; }
.sg-flex > .sg-conns { grid-column: 2; grid-row: 2; }
.sg-body { display: flex; flex-direction: column; gap: 26px; }
/* generator logic window: the dice's tendencies on dials + generate */
.stut-gen {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 8px 6px 2px;
  border-top: 1px solid var(--border-subtle);
}
.sg-body .swap-row { gap: 4px; }

/* grain cells: the router's cells, one size down */
.sg-cell {
  flex: 1 1 0; min-width: 0; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text-secondary);
  font-size: 10px; font-weight: 700;
  font-family: 'JetBrains Mono', monospace;
  transition: border-color var(--transition), color var(--transition),
              background var(--transition), box-shadow var(--transition);
}
.sg-cell.top { cursor: grab; touch-action: none; }
.sg-cell.top:hover { border-color: var(--accent-primary); color: var(--text-primary); }
.sg-cell.bot { cursor: default; color: var(--text-muted); }
.sg-cell.bot.routed {
  cursor: pointer;
  border-color: var(--accent-primary);
  color: var(--text-primary);
  background: var(--accent-glow);
  box-shadow: 0 0 10px var(--accent-glow), inset 0 0 6px var(--accent-glow);
}
.stutter-pop.dense .sg-cell { height: 18px; font-size: 8px; border-radius: 4px; }
.stutter-pop.dense .sg-body .swap-row { gap: 2px; }

/* bulk endpoints: dashed router cells, centered under the places */
.sg-conns { display: flex; gap: 8px; justify-content: center; margin-top: -14px; }
.sg-conn {
  padding: 3px 14px;
  border: 1px dashed var(--border); border-radius: 7px;
  background: var(--bg-card);
  font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.6px;
  font-family: 'JetBrains Mono', monospace;
  color: var(--text-muted);
  transition: border-color var(--transition), color var(--transition), box-shadow var(--transition);
}
.sg-conn:hover {
  border-color: var(--accent-primary); color: var(--text-primary);
  box-shadow: 0 0 8px var(--accent-glow);
}

/* ============================================================
   TAPE STOP TILE
   ============================================================ */
.tape-knobs { transition: opacity var(--transition), filter var(--transition); }
.tape-win { display: flex; align-items: center; gap: 6px; font-weight: 800; }
.tape-edge {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 8px;
}
.tape-opt { font-size: 9px; }
.tape-opt:disabled { opacity: 0.4; cursor: not-allowed; }

/* ============================================================
   BATCH 5 — arm & bake (1.9), quick-edit glow (1.9a), slim tiles
   (1.9b), tape knobs (1.5a), pads rework (4), vocal focus (12)
   ============================================================ */

/* ---- task 1.9: armed stems + the bake button ---- */
.stem-btn.armed {
  border-color: var(--accent-primary);
  color: var(--text-secondary);
  box-shadow: inset 0 0 0 1px var(--accent-primary);
}
.bake-btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 20px;
  font-size: 11px; font-weight: 800; letter-spacing: 0.8px;
  text-transform: uppercase;
  border-radius: 999px;
  border: 1px solid var(--border-subtle);
  background: var(--bg-card);
  color: var(--text-muted);
  cursor: pointer;
  transition: border-color var(--transition), color var(--transition),
              box-shadow var(--transition), background var(--transition);
}
.bake-btn.ready {
  border-color: var(--accent-primary);
  color: var(--accent-primary);
  background: var(--accent-glow);
  box-shadow: 0 0 10px var(--accent-glow);
}
.bake-btn.ready:hover { color: var(--text-primary); }

/* the rotating pleasant pulse: a soft glow that orbits while baking */
@keyframes shmoov-bake-orbit {
  0%   { box-shadow: 3px 0 12px var(--accent-glow), inset 0 0 6px var(--accent-glow); }
  25%  { box-shadow: 0 3px 12px var(--accent-glow), inset 0 0 9px var(--accent-glow); }
  50%  { box-shadow: -3px 0 12px var(--accent-glow), inset 0 0 6px var(--accent-glow); }
  75%  { box-shadow: 0 -3px 12px var(--accent-glow), inset 0 0 9px var(--accent-glow); }
  100% { box-shadow: 3px 0 12px var(--accent-glow), inset 0 0 6px var(--accent-glow); }
}
.stem-btn.baking, .bake-btn.baking, .knob-arm.baking,
.fx-toggle.baking, .btn.baking {
  border-color: var(--accent-primary);
  animation: shmoov-bake-orbit 1.6s linear infinite;
}
/* a disabled loader still pulses — the pulse IS the "working" signal,
   so it must survive the :disabled opacity drop */
.fx-toggle.baking:disabled, .btn.baking:disabled { opacity: 0.85; }

/* ---- switch end labels (pad engine): the words at each end of the
   switch name its two positions; the selected side glows. ---- */
.switch-end {
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-muted);
  transition: color var(--transition), text-shadow var(--transition);
  user-select: none; cursor: pointer;
}
.switch-end.lit {
  color: var(--accent-primary);
  text-shadow: 0 0 8px var(--accent-glow);
}
.extra-block.baking {
  border-color: var(--accent-primary);
  animation: shmoov-bake-orbit 2.2s linear infinite;
}

/* ---- task 1.9a: quick edits glow instead of locking the page ---- */
.extra-block.adjusting {
  border-color: color-mix(in srgb, var(--accent-primary) 55%, var(--border));
  box-shadow: 0 0 14px var(--accent-glow);
}

/* ---- task 1.9a1: armed smart-mix dials ---- */
.knob-arm { display: inline-flex; border-radius: 12px; transition: box-shadow var(--transition); }
.knob-arm.armed {
  box-shadow: inset 0 0 0 1px var(--accent-primary), 0 0 8px var(--accent-glow);
}
.smx-params { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.bake-btn.smx-bake { margin-left: 4px; padding: 3px 10px; font-size: 10px; }

/* the bake slot lives in the tile's mid area, centered in the free band
   between the controls and the card edge — the gate-nudge precedent
   (same :has() floor, Chrome/Edge 105+). */
.bake-slot { display: flex; justify-content: center; }
.extra-mid:has(> .bake-slot) { flex: 1; }

/* ---- task 1.9b: slim tiles with corner dots ---- */
.control-block.slim { position: relative; padding: 9px 14px; gap: 7px; }
.control-block.slim .extra-live-dot { top: 8px; right: 10px; }

/* ---- task 1.5a: tape edge dials enable with their switch ---- */
.tape-knobs { transition: opacity var(--transition), filter var(--transition); }
.tape-knobs.dials-off {
  opacity: 0.35; filter: saturate(0.4);
  pointer-events: none;
}
.tape-edge { display: flex; align-items: center; gap: 10px; }

/* ---- per-stem tape logic fold-out: start/end tiles STACKED ---- */
.tape-edges-stack {
  display: flex; flex-direction: column; gap: 8px;
  align-items: stretch;
  padding: 10px;
  border: 1px solid var(--accent-primary);   /* open editor = glow language */
  border-radius: var(--radius-sm);
  background: var(--bg-base);
  box-shadow: 0 0 10px var(--accent-glow);
}
.tape-edges-stack .tape-edge { justify-content: space-between; }
.tape-edges-title {
  font-size: 9px; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-muted);
}
/* mid slot with the fold-out: stack editor above the bake slot, centered */
.extra-mid:has(> .tape-edges-stack) {
  flex-basis: 100%; min-width: 0;
  display: flex; flex-direction: column; gap: 10px; align-items: center;
}
.extra-mid:has(> .tape-edges-stack) > .tape-edges-stack { align-self: center; min-width: 60%; }

/* ---- task 12: vocal focus deck buttons ---- */
.vox-decks { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* the params row: play-window + drop knobs beside the crossover option */
.vox-ctl {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  margin-top: 10px;   /* knob pointer clearance, the extra-flex precedent */
}
.vox-leadin { display: flex; flex-direction: column; gap: 5px; }
.vox-leadin .seg-btn { padding: 6px 10px; }
.vox-leadin .seg-btn.vox-li-out { opacity: 0.35; cursor: not-allowed; }
.vox-deck {
  min-width: 44px; justify-content: center;
  border-color: color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 45%, var(--border));
  color: var(--text-secondary);
}
.vox-deck:hover { border-color: var(--deck-accent, var(--accent-primary)); }
.vox-deck.active {
  border-color: var(--deck-accent, var(--accent-primary));
  color: var(--text-primary);
  background: color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 20%, var(--bg-card));
  box-shadow: 0 0 12px color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 50%, transparent);
}

/* ---- task 4: pads — stem rows, sample-pad glow at rest ---- */
.pads-table { display: flex; flex-direction: column; gap: 6px; }
.pads-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.pads-row-label {
  width: 18px; display: inline-flex; justify-content: center;
  color: var(--text-muted); flex: 0 0 auto;
}
/* at rest: the pressed glow, lighter, WITHOUT the edge glow */
.pad {
  border-color: color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 40%, var(--border));
  color: var(--text-secondary);
  background: color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 10%, var(--bg-card));
}
.pad:hover {
  background: color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 16%, var(--bg-card));
}
/* pressed/playing: darken + the edge glow */
.pad.playing, .pad:active {
  border-color: var(--deck-accent, var(--accent-primary));
  color: var(--text-primary);
  background: color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 26%, #000 12%);
  box-shadow: 0 0 12px color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 60%, transparent),
              inset 0 0 10px color-mix(in srgb, var(--deck-accent, var(--accent-primary)) 35%, transparent);
}

/* fx-toggle lit state (vox decks etc.) */
.fx-toggle.active {
  border-color: var(--accent-primary); color: var(--text-primary);
  background: var(--accent-glow);
}

/* ============================================================
   JULY BATCH: preset load · timeline FX regions · re-metric
   ============================================================ */

/* ---- task 1: save (→) / load (←) preset arrows on extras tiles ----
   Save keeps the classic top-right spot; load sits directly BELOW it,
   same hover-reveal rhythm. */
.bank-btn.load { top: 27px; }
.extra-block:hover .bank-btn.load,
.bank-btn.load:focus-visible { opacity: 1; pointer-events: auto; }
/* menu open: glow like a lit stem (the logic-button language) */
.bank-btn.load.editing {
  opacity: 1; pointer-events: auto;
  border-color: var(--accent-primary);
  color: var(--text-primary);
  background: var(--accent-glow);
  box-shadow: 0 0 8px var(--accent-glow);
}

/* the load popover: anchored under the arrows, quiet card */
.preset-pop {
  position: absolute; right: 26px; top: 49px;
  z-index: 6;
  min-width: 180px; max-width: 260px;
  max-height: 180px; overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-card);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  padding: 4px;
}
.preset-pop-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%;
  padding: 5px 8px;
  border: none; border-radius: 7px;
  background: transparent;
  color: var(--text-secondary);
  font-size: 11px;
  cursor: pointer;
  text-align: left;
  transition: background var(--transition), color var(--transition);
}
.preset-pop-row:hover { background: var(--accent-glow); color: var(--text-primary); }
.preset-pop .preset-empty { margin: 6px 8px; }

/* ---- task 2: timeline zoom + beat regions + FX bake ---- */
.tl-head-right { display: flex; align-items: center; gap: 8px; }
.tl-zoom-badge {
  font-size: 10px; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 6px;
  padding: 1px 6px;
}
/* the timeline's bake button rides the extras' bake language */
#tl-fx-bake, #tl-fx-clear { height: 20px; }

.tl-fx-shelf {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 8px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.02);
}
.tl-shelf-label {
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-secondary);
}
.tl-chip { border-color: var(--fx-c); }
.tl-chip:hover { box-shadow: 0 0 8px var(--fx-c); }
/* the shelf's "no presets yet" hint: it inherits nothing useful from the
   flex row, so unstyled it rendered as raw wrapping text jammed against
   the uppercase label — give it the quiet-hint treatment */
.ed-shelf-empty {
  flex: 1 1 auto; min-width: 0;
  font-size: 10px; line-height: 1.45;
  color: var(--text-muted);
  text-transform: none; letter-spacing: 0; font-weight: 400;
}
/* the ring mod clean-×sin / true-diode A/B: two words don't fit a square
   mini-btn — let it size to its label */
.mini-btn.ring-mode {
  width: auto; height: auto;
  padding: 3px 8px;
  font-size: 9px; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase;
  white-space: nowrap; line-height: 1.2;
}
.mini-btn.ring-mode.true-ring {
  color: var(--accent-primary); border-color: var(--accent-primary);
}
.tl-basket-chip { border-color: var(--accent-primary); color: var(--accent-primary); }
.tl-basket-chip:hover { box-shadow: 0 0 8px var(--accent-glow); }

/* FX basket bar: the accumulated configs, dropped onto a region together */
.tl-fx-basket {
  display: flex; flex-direction: column; align-items: stretch; gap: 2px;
  margin-top: 6px; padding: 5px 8px;
  border: 1px dashed var(--border-focus); border-radius: 10px;
  background: rgba(255, 255, 255, 0.015);
}
.tl-basket-label {
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--accent-primary);
}
.tl-basket-item {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 10px; color: var(--text-secondary);
  border: 1px solid var(--fx-c, var(--border)); border-radius: 8px; padding: 2px 6px;
}
.tl-basket-x, .tl-basket-clear {
  border: none; background: transparent; color: var(--text-muted);
  cursor: pointer; font-size: 10px; padding: 0 2px;
}
.tl-basket-x:hover { color: var(--danger); }
.tl-basket-clear {
  margin-left: auto; text-transform: uppercase; letter-spacing: 0.06em;
  font-weight: 700; font-size: 9px;
}
.tl-basket-clear:hover { color: var(--text-primary); }
/* a global control whose target is OVERRIDDEN by a timeline FX inside that
   FX's beats. It still works everywhere else, so this is a hint, not a
   disabled state — hence the light touch rather than a greyed-out look. */
.dimmed-by-fx { opacity: 0.82; transition: opacity var(--transition); }
.dimmed-by-fx .xf-read, .dimmed-by-fx .xf-label { color: var(--text-muted); }
/* stereo-field rearrange buttons (swap / rotate / shuffle) */
.xf-rearrange { display: flex; gap: 6px; margin-left: 6px; }
.xf-rebtn {
  display: inline-flex; align-items: center; gap: 4px; width: auto;
  padding: 4px 9px; font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
}
.xf-stems-btn {
  display: inline-flex; align-items: center; gap: 3px; margin-top: 4px;
  padding: 2px 6px; border-radius: 5px; cursor: pointer;
  background: var(--bg-card); border: 1px solid var(--border-subtle);
  color: var(--text-muted); font-size: 8px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
  transition: all var(--transition);
}
.xf-stems-btn:hover, .xf-stems-btn.open { color: var(--accent-primary); border-color: var(--accent-primary); }
.xf-stem-panel {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 8px; padding: 8px 10px;
  border: 1px dashed var(--border-focus); border-radius: 10px;
  background: rgba(255, 255, 255, 0.015);
}
.xf-stem-faders { display: flex; gap: 10px; flex-wrap: wrap; }
.xf-col.stem { min-width: 44px; }
.xf-col.stem .xf-label { font-size: 9px; }
.xfader.stem { height: 90px; }
/* the + add-to-basket button on an extra tile head */
.basket-add {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 4px;
  background: var(--bg-card); border: 1px solid var(--border-subtle);
  color: var(--text-muted); cursor: pointer; transition: all var(--transition);
}
.basket-add:hover { color: var(--accent-primary); border-color: var(--accent-primary); }

.tl-fx-list {
  display: flex; gap: 6px; flex-wrap: wrap;
  margin-top: 6px;
}
.tl-fx-item {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 10px;
  color: var(--text-secondary);
  border: 1px solid var(--fx-c, var(--border));
  border-radius: 8px;
  padding: 2px 6px;
  opacity: 0.85;
}
.tl-fx-item.baked { box-shadow: 0 0 6px var(--fx-c); opacity: 1; }
.tl-fx-x {
  border: none; background: transparent;
  color: var(--text-muted);
  font-size: 10px; cursor: pointer; padding: 0 1px;
}
.tl-fx-x:hover { color: var(--text-primary); }

/* ---- task 3: re-metric panel ---- */
.rmx-goal-row {
  display: flex; align-items: center; gap: 12px;
  margin: 10px 0 12px;
}
.rmx-row {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 8px 12px 10px;
  margin-bottom: 8px;
  background: rgba(255, 255, 255, 0.015);
}
.rmx-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-bottom: 6px;
}
.rmx-detect { font-size: 10px; color: var(--text-secondary); }
.rmx-controls {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.rmx-lab {
  font-size: 9px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-muted);
}
/* the wiring reuses the swap-router look; it just sits in a rack pane,
   so let it size to the row instead of the 10%/beat card rule */
.rmx.swap-router-wrap { margin-top: 10px; }
.rmx .swap-router { width: min(100%, calc(var(--swap-w) * 44px)); margin: 0 auto; }
.rmx-cut {
  text-align: center;
  font-size: 10px; color: var(--text-muted);
  margin-top: 4px;
}
.rmx-foot { margin-top: 10px; }

.xf-stem-note {
  font-size: 9px; color: var(--text-muted); margin-left: auto;
  text-transform: uppercase; letter-spacing: 0.05em;
}

/* export modal: pick a destination (preset / existing basket / new basket) */
.modal-select, .modal-input {
  width: 100%; margin-top: 10px; padding: 8px 10px;
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: 8px; color: var(--text-primary); font-size: 12px;
  font-family: inherit;
}
.modal-select:focus, .modal-input:focus {
  outline: none; border-color: var(--accent-primary);
}
.modal-hint {
  margin-top: 8px; font-size: 10px; color: var(--text-muted); line-height: 1.5;
}
/* one row per named basket */
.tl-basket-row {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  width: 100%; padding: 2px 0;
}
.tl-basket-row + .tl-basket-row { border-top: 1px solid var(--border-subtle); margin-top: 4px; padding-top: 6px; }

/* mini FX lane: the whole-mix effects (rain, metronome, stereo, vocal
   focus, risers) live here — an indicator strip, not an audio lane */
.tl-row.fxlane .tl-strip {
  border-color: var(--border-focus);
  background: rgba(255, 255, 255, 0.02);
  height: 12px;                 /* indicator strip: 25% shorter */
}
/* fx label hugs its strip: icon + name right-justified against the lane */
.tl-row.fxlane .tl-label,
.tl-row.smplane .tl-label { justify-content: flex-end; }
.tl-name.fxlane {
  color: var(--text-muted); text-transform: uppercase;
  letter-spacing: 0.08em; font-size: 9px; font-weight: 700;
}

/* #3: mixer export buttons reveal on hover, matching the deck extras'
   .bank-btn behaviour — they're an occasional action, not chrome */
.control-block .bank-inline {
  opacity: 0; pointer-events: none;
  transition: opacity var(--transition), color var(--transition),
              border-color var(--transition);
}
.control-block:hover .bank-inline,
.control-block .bank-inline:focus-visible { opacity: 1; pointer-events: auto; }
.control-block .bank-inline:hover {
  color: var(--accent-primary); border-color: var(--accent-primary);
}

/* deck fader dimmed while the stems drawer owns the field (#6) */
.xf-col.inactive { opacity: 0.4; pointer-events: none; }
.xf-rebtn.on { color: var(--accent-primary); border-color: var(--accent-primary); }

/* stems button sits below the deck faders, on its own line */
.xf-stems-row {
  display: flex; justify-content: flex-start;
  margin-top: 8px; padding-left: 2px;
}

/* stem-pan grid: a row per STEM TYPE, decks across (so the same
   instrument lines up between decks) */
.xf-stem-grid { display: flex; flex-direction: column; gap: 6px; width: 100%; }
.xf-stem-typerow {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 0;
}
.xf-stem-typerow + .xf-stem-typerow { border-top: 1px solid var(--border-subtle); }
.xf-stem-typename {
  min-width: 52px; font-size: 9px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-secondary);
}
.xf-col.stem.empty { min-width: 44px; }

/* ---------- TURNTABLE ---------- */
/* NOTE: .sc-row is shared with the sidechain rules UI (its earlier block
   relies on this later override, historically gap 10 + margin-top 10) —
   so the legacy spacing stays global and the turntable's mixer, which
   spaces itself with its own column gap, zeroes the margin locally. */
.sc-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 10px;
}
.sc-select { width: auto; min-width: 0; flex: 1; margin-top: 0; }
.sc-wave-wrap {
  position: relative;
  border: 1px solid var(--border-subtle);
  border-radius: 8px; background: rgba(0, 0, 0, 0.25); overflow: hidden;
}
.sc-wave-wrap canvas { display: block; width: 100%; height: 64px; }
/* BOTH decks' readouts, stacked full-width so the two needles sit on one
   vertical line — synced decks read as the same audio passing both */
.tt-waves {
  display: flex; flex-direction: column; gap: 4px; margin-top: 12px;
}
.sc-wave-tag {
  position: absolute; top: 3px; left: 6px; z-index: 1;
  font-size: 8px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-muted); pointer-events: none;
}
.sc-drift { color: #f87171; }
.sc-lock { color: #4ade80; }
/* the drift number sits in a fixed-width right-aligned cell with air
   before the unit, and the whole transport readout uses tabular digits —
   rapid ms flutter no longer reflows the row */
.sc-drift-n {
  display: inline-block; min-width: 4ch; text-align: right;
  margin-right: 3px;
}
.tt-transport .control-readout { font-variant-numeric: tabular-nums; }

/* TWO decks, side by side like a 2-channel pair. Each column is a
   self-contained deck card: wave, source row, platter, its own
   crossfader DIRECTLY UNDERNEATH at the platter's width, transport.
   Wraps to stacked on narrow panes. */
.tt-decks {
  display: flex; flex-direction: row; align-items: flex-start;
  justify-content: center; gap: 14px; flex-wrap: nowrap; margin-top: 12px;
}
.tt-deck {
  flex: 1 1 0; min-width: 0; max-width: 420px;
  border-radius: 10px; padding: 4px;
  border: 1px solid transparent;
  transition: border-color var(--transition);
}
/* the FOCUSED deck (last touched) is the one the arrow keys drive */
.tt-deck.focused { border-color: var(--border-focus); }
.sc-deckcard {
  display: flex; flex-direction: column; align-items: stretch; gap: 12px;
}
.sc-deckcard .sc-row { margin-top: 0; justify-content: center; }
.sc-loaded-lbl {
  font-size: 9px; color: var(--text-muted); text-align: center;
  letter-spacing: 0.04em;
}
/* the crossfader sits directly under the platter, AT the platter's
   width — a channel fader, not a console-wide strip */
.tt-deck .sc-xf-block { width: min(200px, 100%); margin: 0 auto; }
.tt-guest-row { margin-top: 10px; justify-content: center; }
.tt-guest-row .sc-select { max-width: 340px; }
.tt-shared-row { margin-top: 12px; justify-content: center; }

/* the deck column: platter, hint and sens dial, all centered (§19) */
.tt-deckcol {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 6px 24px 2px;               /* room for the corner-mounted pot */
}
/* status LED rides the platter's shoulder now the plinth is gone */
.tt-led {
  position: absolute; top: 4px; right: 4px; z-index: 2;
  width: 7px; height: 7px; border-radius: 50%;
  background: #3a3a42; box-shadow: inset 0 0 2px rgba(0,0,0,0.8);
  transition: background var(--transition), box-shadow var(--transition);
}
.sc-deckcard.loaded .tt-led {
  background: var(--accent-primary);
  box-shadow: 0 0 8px var(--accent-primary), 0 0 2px var(--accent-primary);
}
/* sens trim, tucked at the vinyl's bottom-right like a pitch pot */
.tt-sens {
  position: absolute; right: -18px; bottom: -8px; z-index: 2;
  display: flex; align-items: center;
  transform: scale(0.92); transform-origin: bottom right;
}
.sc-platter-hint {
  font-size: 8px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-muted);
}

/* the well centers the platter AND the reach ring on the same point,
   so the ring's radius is exactly the cursor's distance from the spindle */
.tt-well {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  /* a DEFINITE width: the platter sizes as min(200px, 100%) of THIS —
     without it the well shrink-wraps the platter, the percentage
     resolves against nothing, and the disc collapses to 0 */
  width: 100%; max-width: 200px;
}

/* ---- the platter ---- */
.sc-platter {
  position: relative; z-index: 1;
  width: min(200px, 100%); aspect-ratio: 1 / 1; height: auto;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  cursor: grab; user-select: none; touch-action: none; flex: 0 0 auto;
  border: 1px solid var(--border);
  background:
    /* machined edge ticks — reads as a strobe rim, purely decorative */
    repeating-conic-gradient(rgba(255,255,255,0.06) 0deg 1.2deg,
                             rgba(255,255,255,0) 1.2deg 6deg),
    radial-gradient(circle at 50% 42%,
                    rgba(255,255,255,0.07), rgba(0,0,0,0.5) 72%);
  box-shadow: inset 0 0 28px rgba(0,0,0,0.6), 0 4px 14px rgba(0,0,0,0.45);
  transition: border-color var(--transition), opacity var(--transition);
  opacity: 0.45; pointer-events: none;
}
/* the edge ticks belong to the housing: keep the inner face clean */
.sc-platter::after {
  content: ""; position: absolute; inset: 7px; border-radius: 50%;
  background: radial-gradient(circle at 50% 42%,
              rgba(255,255,255,0.05), rgba(0,0,0,0.45) 74%);
  pointer-events: none;
}
.sc-deckcard.loaded .sc-platter { opacity: 1; pointer-events: auto; }
.sc-platter:active { cursor: grabbing; border-color: var(--accent-primary); }
.sc-platter-face { color: var(--text-muted); }
.sc-deckcard.loaded .sc-platter-face { color: var(--accent-primary); }

/* ---- the reach overlay: your cursor IS a bigger platter (§19) ----
   While grabbed, the ring grows from the spindle out to the cursor —
   further out = less rotation per hand-inch = finer control, and it now
   lives on document.body (position: fixed, centered on the spindle's
   true screen point by JS) so it spans the whole page instead of
   clipping at the old well. The hub is the spindle mark: a small disc
   with a radial tick the rAF loop spins at the platter angle, so the
   record's motion reads even when your eyes are out at the rim. */
#sc-reach-overlay {
  position: fixed; z-index: 800;           /* under modals (900+) */
  width: 0; height: 0;
  opacity: 0; transition: opacity 0.14s ease;
  pointer-events: none;
}
#sc-reach-overlay.on { opacity: 1; }
#sc-reach-overlay .sc-reach-ring {
  position: absolute; left: 0; top: 0;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}
#sc-reach-overlay .sc-reach-ring {
  border: 1px solid rgba(16, 185, 129, 0.32);
  box-shadow: 0 0 14px rgba(16, 185, 129, 0.10),
              inset 0 0 22px rgba(16, 185, 129, 0.05);
}
/* NOTE: the rotor spins via inline transform (rotate), so its centering
   translate lives in the same property — re-assert it with the spin */
/* the rotor: three stepped arcs around half the ring radius, spun by
   the rAF loop at the platter angle — non-scaling strokes keep them
   hairline however big the virtual record grows */
#sc-reach-overlay .sc-reach-rot {
  position: absolute; left: 0; top: 0;
  transform: translate(-50%, -50%);
  overflow: visible;
  will-change: transform;
}
#sc-reach-overlay .sc-reach-rot path {
  fill: none;
  stroke: rgba(16, 185, 129, 0.55);
  stroke-width: 1.5;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

/* the disc wrapper the rAF loop rotates — whichever face is up spins
   with the audio, so a backspin visibly runs backwards */
.sc-disc {
  position: relative; z-index: 1;
  width: calc(100% - 14px); height: calc(100% - 14px); border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  will-change: transform;
}

/* face 1: vinyl — concentric grooves + a centre label */
.sc-vinyl {
  width: 100%; height: 100%; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background:
    repeating-radial-gradient(circle at 50% 50%,
      rgba(255,255,255,0.055) 0 1px, rgba(0,0,0,0) 1px 4px),
    radial-gradient(circle at 50% 50%, #2a2a30 0 30%, #141418 30% 100%);
}
.sc-vinyl-label {
  width: 42%; height: 42%; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(140deg, var(--accent-primary), rgba(0,0,0,0.6));
  box-shadow: 0 0 0 1px rgba(0,0,0,0.5);
}
.sc-vinyl-label span {
  font-size: 10px; font-weight: 800; letter-spacing: 0.08em;
  color: rgba(0,0,0,0.75); text-transform: lowercase;
}
.sc-vinyl-label i {                       /* spindle hole */
  position: absolute; width: 8px; height: 8px; border-radius: 50%;
  background: #0b0b0e; box-shadow: inset 0 0 3px rgba(0,0,0,0.9);
}

/* face 2: the jogwheel (item 7 — the shmoov card, retired; now a real
   photo). The SVG is only the ROTATING layer — scalloped edge + brushed
   platter, lighting unbaked. Everything that must stay put while it
   spins is painted here on the platter's ::after (which renders above
   the disc): the centre display cap and a fixed light — top sheen,
   diagonal specular sweep, edge vignette. The texture turns under a
   stationary light source, which is what sells the rotation. */
.sc-jog {
  width: 100%; height: 100%; border-radius: 50%; display: block;
  -webkit-user-drag: none; user-select: none;
}
.sc-platter.jog-face::after {
  /* same inset as .sc-disc (7px each side) so the overlay's circle is
     exactly the wheel's circle */
  background:
    url("/static/jogwheel_hub.png") center / 41.4% auto no-repeat,
    radial-gradient(circle at 50% 30%,
                    rgba(255,255,255,0.10), rgba(255,255,255,0) 52%),
    linear-gradient(155deg,
                    rgba(255,255,255,0.06), rgba(255,255,255,0) 42%),
    radial-gradient(circle at 50% 50%,
                    rgba(0,0,0,0) 58%, rgba(0,0,0,0.34) 97%);
}
/* item 2: the ⏻ REAPER power button lights when REAPER is running */
#reaper-power.lit { color: var(--accent-primary);
  border-color: var(--accent-primary);
  box-shadow: 0 0 6px var(--accent-primary); }

/* ---- transport row (centered under the crossfader) ---- */
.tt-transport { margin-top: 0; justify-content: center; }
.tt-sync { display: inline-flex; align-items: center; gap: 5px; }
.tt-kbd {
  font-size: 9px; line-height: 1; padding: 2px 4px; border-radius: 3px;
  border: 1px solid var(--border-focus); color: var(--text-muted);
  background: rgba(0,0,0,0.35); font-family: inherit;
}

/* skeuomorphic crossfader */
.sc-xf-block { margin-top: auto; }
.sc-xf-head { display: flex; justify-content: space-between; align-items: center; }
.sc-xfader {
  position: relative; height: 40px; margin-top: 6px; cursor: pointer;
  border-radius: 8px; touch-action: none;
  background: linear-gradient(180deg, rgba(0,0,0,0.45), rgba(0,0,0,0.2));
  border: 1px solid var(--border);
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.6);
}
.sc-xf-track {
  position: absolute; top: 50%; left: 10px; right: 10px; height: 5px;
  transform: translateY(-50%); border-radius: 3px;
  background: linear-gradient(180deg, #0a0a0c, #1e1e24);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.9), 0 1px 0 rgba(255,255,255,0.04);
}
.sc-xf-cap {
  position: absolute; top: 50%; left: 100%;
  transform: translate(-50%, -50%);
  width: 18px; height: 35px; border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  background: #85858f;                 /* solid grey, no chrome */
  box-shadow: 0 2px 5px rgba(0,0,0,0.65), inset 0 1px 0 rgba(255,255,255,0.22);
  /* no CSS transition: the arrow keys have to land INSTANTLY to transform */
}
/* the theme stripe down the cap's center */
.sc-xf-cap::after {
  content: ""; width: 2px; height: 72%;
  background: var(--accent-primary); border-radius: 1px;
}
.sc-xfader.cut .sc-xf-cap { background: #4a4a52; }
.sc-xf-legend {
  display: flex; justify-content: space-between; margin-top: 4px;
  font-size: 8px; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--text-muted);
}

/* ---- the MASTER deck crossfader: wider, centered under the pair ---- */
.sc-mxf-block { width: min(300px, 100%); margin: 14px auto 0; }
.sc-mxfader .sc-xf-cap { left: 50%; }

/* the playhead-lock toggle in the timeline header */
.tl-follow-btn.lit {
  color: var(--accent-primary);
  border-color: var(--accent-primary);
}

/* ---------- REGION -> PAD (timeline sampler) ---------- */
.tl-pad-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 22px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--border-subtle);
  background: transparent; color: var(--text-muted);
  opacity: 0.5;                       /* dim until a region qualifies */
  transition: opacity var(--transition), color var(--transition),
              border-color var(--transition), box-shadow var(--transition);
}
.tl-pad-btn:hover { opacity: 0.85; }
.tl-pad-btn.glow {
  opacity: 1; color: var(--accent-primary);
  border-color: var(--accent-primary);
  box-shadow: 0 0 10px var(--accent-glow), inset 0 0 6px var(--accent-glow);
}

/* the pad picker rides below the fx shelf, same shelf language */
.tl-pad-pop {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 8px; padding: 6px 8px;
  border: 1px solid var(--accent-primary); border-radius: 10px;
  background: rgba(16, 185, 129, 0.04);
}
.tl-pad-pop.hidden { display: none; }
.tl-pad-warn {
  font-size: 9px; font-weight: 700; letter-spacing: 0.04em;
  color: #fbbf24; text-transform: uppercase;
}
.tl-pad-tiles { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
/* item 2: the pick tiles mirror the pad's own grid — rows/columns
   positional, the KEY carried big so the eye maps picker to keyboard */
.tl-pad-tiles.grid {
  flex-direction: column; align-items: stretch; flex-wrap: nowrap;
  gap: 3px;
}
.tl-pad-grid-row { display: flex; gap: 3px; }
.tl-pad-grid-row .tl-pad-tile { justify-content: center; min-width: 44px; }
.tl-pad-tile-key { font-size: 11px; font-weight: 700; }
.tl-pad-tile {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 7px; border-radius: 7px; cursor: pointer;
  border: 1px solid var(--border); background: var(--bg-card);
  color: var(--text-secondary); font-size: 10px;
  transition: border-color var(--transition), color var(--transition);
}
.tl-pad-tile:hover {
  border-color: var(--deck-accent, var(--accent-primary));
  color: var(--text-primary);
}
.tl-pad-name { width: 140px; margin-top: 0; font-size: 11px; }

/* ---------- PAD LOGIC ---------- */
.pad-wrap { display: inline-flex; flex-direction: column; align-items: center; gap: 1px; }
.pad-notch { width: 100%; }
.pad.region { border-style: dashed; }   /* a re-seated (region/bank) sample */
.pad-logic-pop { margin-top: 10px; }
/* the alt-key cells carry their key label above the slice number */
.sg-cell.bot.pad-alt {
  height: auto; min-height: 30px;
  display: flex; flex-direction: column; gap: 1px;
  padding: 3px 0;
}
.pad-alt-key {
  font-size: 8px; font-weight: 800; letter-spacing: 0.05em;
  color: var(--text-muted);
}
.sg-cell.bot.pad-alt.routed .pad-alt-key { color: var(--accent-primary); }

/* ---------- BEAT PREVIEW ---------- */
.swap-prev-sel { min-width: 120px; max-width: 170px; font-size: 10px; }

/* ---------- SAMPLE BANK ---------- */
.bank-block {
  margin-top: 12px; padding: 8px 10px;
  border: 1px solid var(--border-subtle); border-radius: 10px;
  background: rgba(0, 0, 0, 0.18);
  display: flex; flex-direction: column; gap: 6px;
}
.bank-head { display: flex; align-items: center; gap: 6px; color: var(--text-muted); }
.bank-head .control-readout { margin-left: auto; }
.bank-row {
  display: flex; align-items: center; gap: 6px;
  padding: 3px 4px; border-radius: 7px;
}
.bank-row:hover { background: rgba(255, 255, 255, 0.03); }
.bank-name {
  font-size: 11px; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 40%;
}
.bank-meta {
  font-size: 9px; color: var(--text-muted); flex: 1;
  text-transform: uppercase; letter-spacing: 0.05em;
}

/* ---------- PRESS-AND-HOLD VOLUME ---------- */
.vol-pop {
  position: fixed; z-index: 90;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 6px 8px; border-radius: 9px;
  border: 1px solid var(--border-focus);
  background: var(--bg-panel);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55);
  user-select: none; touch-action: none;
}
.vol-track {
  position: relative; width: 14px; height: 96px; border-radius: 7px;
  overflow: hidden;
  background: linear-gradient(180deg, rgba(0,0,0,0.5), rgba(0,0,0,0.25));
  border: 1px solid var(--border);
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.6);
}
/* the filled (bottom) span carries the theme color */
.vol-fill {
  position: absolute; left: 0; right: 0; bottom: 0; height: 0;
  background: linear-gradient(180deg, var(--accent-primary), var(--accent-glow));
  opacity: 0.85; pointer-events: none;
}
/* unity (0 dB) sits 2/3 up the -24..+12 range */
.vol-zero {
  position: absolute; left: 3px; right: 3px; bottom: 66.67%;
  height: 1px; background: rgba(255, 255, 255, 0.22);
}
.vol-cap {
  position: absolute; left: 0; right: 0; transform: translateY(50%);
  height: 3px; border-radius: 2px;
  background: var(--text-primary);
  box-shadow: 0 0 6px rgba(255, 255, 255, 0.45);
  pointer-events: none;
  /* no transition: the fader must sit under the pointer instantly */
}
.vol-read { font-size: 10px; color: var(--text-muted); }
.vol-read.hot { color: var(--accent-primary); }
.vol-who {
  font-size: 8px; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--text-muted);
}
.tl-vol-badge {
  font-size: 8px; color: var(--accent-primary);
  padding: 0 3px; border-radius: 3px;
  background: var(--accent-glow); flex-shrink: 0;
  cursor: pointer;              /* tap = clear back to 0 dB */
}
.tl-vol-badge:hover { text-decoration: line-through; }


/* ---------- FX BASKET EDITOR ---------- */
.tl-basket-clear.editing { color: var(--accent-primary); border-color: var(--accent-primary); }
.bk-editor {
  width: 100%; margin: 4px 0 8px;
  padding: 8px 10px; border-radius: 10px;
  border: 1px solid var(--border-subtle);
  background: rgba(0, 0, 0, 0.22);
  display: flex; flex-direction: column; gap: 6px;
}
.bk-head { display: flex; align-items: center; gap: 8px; }
.bk-len { min-width: 90px; font-size: 10px; }
.bk-itemrow { display: flex; align-items: center; gap: 8px; }
.bk-name {
  flex: 0 0 92px; font-size: 10px; font-weight: 700;
  color: var(--fx-c, var(--text-secondary));
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-align: right;
}
.bk-strip {
  flex: 1; display: flex; gap: 1px;
  border-radius: 5px; overflow: hidden; cursor: pointer;
  touch-action: none;
}
.bk-cell {
  flex: 1; height: 16px; min-width: 6px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, 0.045);
  font-size: 8px; line-height: 1; color: var(--fx-c, #fff);
  transition: background 0.06s;
}
.bk-cell.bar { box-shadow: inset 1.5px 0 0 rgba(255, 255, 255, 0.14); }
.bk-cell:hover { background: rgba(255, 255, 255, 0.12); }
.bk-cell.in {
  background: color-mix(in srgb, var(--fx-c, #fff) 34%, transparent);
  box-shadow: inset 0 -2px 0 var(--fx-c, #fff);
}
.bk-cell.drag { background: color-mix(in srgb, var(--fx-c, #fff) 52%, transparent); }
.bk-cell.flag { background: color-mix(in srgb, var(--fx-c, #fff) 24%, transparent); }
.bk-flag {
  flex: 0 0 auto; width: 20px; height: 18px; border-radius: 5px;
  border: 1px solid var(--border); background: transparent;
  color: var(--text-muted); font-size: 10px; line-height: 1; cursor: pointer;
  transition: color var(--transition), border-color var(--transition);
}
.bk-flag:hover { color: var(--text-primary); }
.bk-flag.on { color: var(--accent-primary); border-color: var(--accent-primary); }


/* ---------- TURNTABLE TAKE RECORDING ---------- */
.tt-rec { display: inline-flex; align-items: center; gap: 5px; }
.tt-rec-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: #6b7280;
  transition: background var(--transition), box-shadow var(--transition);
}
#sc-deck.recording .tt-rec-dot,
#sc-deck.recording .tt-led {
  background: #ef4444;
  box-shadow: 0 0 8px rgba(239, 68, 68, 0.8);
  animation: tt-rec-pulse 1s ease-in-out infinite;
}
#sc-deck.recording .tt-rec { color: #ef4444; border-color: #ef4444; }
@keyframes tt-rec-pulse {
  50% { box-shadow: 0 0 3px rgba(239, 68, 68, 0.4); }
}

/* ---------- THE SAMPLE TRACK ---------- */
.tl-row.smplane .tl-strip { height: 22px; background: rgba(245, 158, 11, 0.04); }
.tl-smp-shelf { border-color: #f59e0b; background: rgba(245, 158, 11, 0.05); }

/* ---------- GATE PATTERN LOGIC ---------- */
.gate-logic-row {
  display: flex; justify-content: center; gap: 6px;
  width: 100%; margin: 2px 0;
}
/* the gate pattern pop-out: borderless, and the slice bars bleed to the
   tile's edges — the strip IS the tile below the header */
.bk-editor.gate-logic {
  margin: 4px 0 2px; gap: 4px;
  border: none; padding: 0; border-radius: 8px;
  background: rgba(0, 0, 0, 0.22);
  overflow: hidden;
}
.bk-editor.gate-logic .bk-head { margin: 0; padding: 6px 8px 2px; }
.gl-strip { border-radius: 0; }             /* the tile clips the corners */
.gl-cell { height: 30px; cursor: pointer; min-width: 10px; }
.gl-cell.bar { box-shadow: inset 2px 0 0 rgba(255, 255, 255, 0.22); }

/* ---------- numpy render engine (Live · Master) ---------- */
/* ---------- queued live edits (the coalescing scheduler) ----------
   A sync is owed to the backend but the UI already shows the desired
   state — hint it quietly instead of locking anything. */
body.live-queued #live-master .lock-hint,
body.live-queued .deck-tab-body { transition: opacity 0.2s; }
body.live-queued .extra-block.adjusting { animation-duration: 0.6s; }

/* one-shot launch buttons (swap/tape cards) — the logic-btn silhouette
   with a launch accent so it reads as an ACTION, not a fold-out.
   Content-sized (the swap-logic recipe) instead of the base logic-btn's
   width:100%, so it sits SMALL and LEFT in the head row, right beside
   the logic button where the card has one. */
.logic-btn.oneshot-btn {
  width: auto; height: 18px; padding: 0 8px;
  flex: 0 0 auto;
  border-color: var(--accent-primary);
  color: var(--accent-primary);
}
.logic-btn.oneshot-btn:hover {
  background: color-mix(in srgb, var(--accent-primary) 18%, transparent);
  box-shadow: 0 0 6px color-mix(in srgb, var(--accent-primary) 40%, transparent);
}


/* ---- pending-sync pulse: pressed, heard, not yet confirmed ----
   Applied by paintSync() to the exact control being edited; removed the
   moment the backend ack for that edit lands (or the edit fails and the
   optimistic state is reverted). Gentle on purpose: a breath, not an
   alarm. */
@keyframes syncPulse {
  50% {
    box-shadow: 0 0 12px var(--accent-glow), inset 0 0 6px var(--accent-glow);
    filter: brightness(1.35);
  }
}
.syncing {
  animation: syncPulse 0.85s ease-in-out infinite;
}

/* ---------- SETTINGS MODAL (item 12: the gear button) ---------- */
.set-card { width: min(560px, calc(100vw - 40px)); }
.set-scroll { max-height: min(62vh, 560px); overflow-y: auto; padding-right: 6px; margin-bottom: 8px; }
.set-group-label {
  font-size: 10px; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--text-muted); margin: 14px 0 8px; font-weight: 700;
}
.set-group-label:first-child { margin-top: 2px; }
.set-hint-inline { text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--text-muted); }
.set-row { display: flex; align-items: center; gap: 10px; margin: 7px 0; }
.set-label { flex: 0 0 132px; font-size: 11px; color: var(--text-secondary); }
.set-input { flex: 1 1 auto; font-size: 11px; padding: 7px 9px; }
.set-num { flex: 0 0 92px; }
.set-hint { font-size: 10px; color: var(--text-muted); margin: 2px 0 4px 142px; line-height: 1.4; }
.set-cache-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: 6px 12px; margin-top: 4px;
}
.set-check { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--text-secondary); cursor: pointer; }
.set-check input { accent-color: var(--accent); }

/* ---- deck source: filename on show, path underneath, songs-folder list ----
   The field displays the bare FILENAME so a long path can't swamp the row.
   Clicking it reveals the absolute path on a line beneath, and the caret
   expands the songs folder in the same place — a panel under the field
   rather than a native <select>, so both reveals read as one control. */
.source-block { position: relative; }

.src-caret {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 22px; height: 22px; padding: 0; border-radius: 6px;
  background: transparent; border: none;
  color: var(--text-muted); cursor: pointer;
  transition: color var(--transition);
}
.src-caret:hover { color: var(--text-primary); }
.src-caret svg { transition: transform var(--transition); }
.src-caret.open { color: var(--accent); }
.src-caret.open svg { transform: rotate(180deg); }

.src-path {
  font-family: var(--mono); font-size: 10px; line-height: 1.45;
  color: var(--text-muted);
  padding: 5px 12px 0 34px;
  word-break: break-all;
}
.src-path b { color: var(--text-secondary); font-weight: 500; }

/* while a deck's songs-folder list is open, the card lifts its overflow
   clip so the dropdown can extend past the deck and over the cards
   beneath it (it closes on pick / click-away, so nothing stays covered) */
.song-card.deck.lib-open { overflow: visible; }

.src-lib {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 30;
  margin-top: 5px; padding: 4px;
  /* ~8 entries tall (23px rows + container padding), then it scrolls */
  max-height: 194px; overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-card);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}
.src-lib-row {
  display: block; width: 100%;
  padding: 5px 8px;
  border: none; border-radius: 7px;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--mono); font-size: 11px;
  text-align: left; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: background var(--transition), color var(--transition);
}
.src-lib-row:hover { background: var(--accent-glow); color: var(--text-primary); }
.src-lib-empty {
  margin: 6px 8px; font-size: 11px; color: var(--text-muted);
}

/* ============================================================
   TIMELINE BEAT EDITS (tl_edit.js): the shelf's copy / paste /
   delete / mute button group
   ============================================================ */
.tl-edit-group {
  display: inline-flex; align-items: center; gap: 4px;
  padding-right: 8px; margin-right: 4px;
  border-right: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.12));
}
.tl-edit-btn { display: inline-flex; align-items: center; }
.tl-edit-btn.warn:hover { color: #f87171; border-color: #f87171; }
.tl-edit-btn.lit {
  color: var(--accent, #10b981);
  border-color: var(--accent, #10b981);
}
