/* Theme tokens: every color anywhere in this file (and any inline style in js/app.js)
   must reference one of the custom properties below via var(--name) — never a literal
   hex/rgb value. That's what makes light/dark "free": add a new component using these
   tokens and it's automatically correct in both themes, no per-component light-mode
   pass needed. If a new color role is needed, add one token pair here (dark value in
   :root, light value in :root[data-theme="light"]) rather than hardcoding anywhere else.

   Visual identity: a "rack panel" look — warm charcoal/bone grounds (not pure black/white,
   like anodized metal vs. ABS plastic casing), amber as the primary LED accent, three more
   hues (teal/mauve/brass) each permanently assigned to one instrument family so a step's
   color always identifies what's hitting, never just "on". Glow tokens are lighter versions
   of the four instrument colors, used for the LED box-shadow in the step grid. Unbounded
   carries headings/brand, IBM Plex Sans is body text, IBM Plex Mono is anything that reads
   like a hardware data readout (BPM, ms, track numbers, tags). */
:root {
  --bg: #15120e;
  --bg-panel: #1c1913;
  --bg-panel-alt: #241f19;
  --border: #3a3226;
  --text: #f2ead9;
  --text-dim: #c3b8a1;
  --accent: #f0973c;
  --accent-dim: #5c4326;
  --accent-soft: #d9b168;
  --kick: #f0973c;
  --snare: #5fc4b8;
  --hat: #bd7aa6;
  --other: #a39a5c;
  --glow-kick: rgba(240,151,60,0.55);
  --glow-snare: rgba(95,196,184,0.55);
  --glow-hat: rgba(189,122,166,0.55);
  --glow-other: rgba(163,154,92,0.5);
  --dash: rgba(242,234,217,0.5);
  --shadow: rgba(0,0,0,0.45);
  font-size: 17px;
}

:root[data-theme="light"] {
  --bg: #ece4d3;
  --bg-panel: #f6f0e3;
  --bg-panel-alt: #e9e0cb;
  --border: #d1c4a3;
  --text: #241f18;
  --text-dim: #6b5f4d;
  --accent: #b3591a;
  --accent-dim: #e3cfb0;
  --accent-soft: #8a6a35;
  --kick: #b3591a;
  --snare: #227f74;
  --hat: #8f4a72;
  --other: #71642f;
  --glow-kick: rgba(179,89,26,0.4);
  --glow-snare: rgba(34,127,116,0.4);
  --glow-hat: rgba(143,74,114,0.4);
  --glow-other: rgba(113,100,47,0.35);
  --dash: rgba(36,31,24,0.35);
  --shadow: rgba(60,45,20,0.14);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.mono { font-family: 'IBM Plex Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums; }

.app-header {
  position: relative;
  /* No overflow: hidden here — a <canvas> already never paints outside its own box, so this
     was clipping something else instead: the theme menu-panel popover, which intentionally
     extends below the header's own height when open. That clip was silently cutting off (and
     making unclickable) the bottom of the popover, theme-toggle button included. See
     modifications.md Changelog. */
  padding: 1.25rem 1.5rem 0;
  border-bottom: 1px solid var(--border);
}

#scope-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0; /* explicit, not implicit: must always sit behind .header-top/.tabs (both z-index: 1) */
  /* No opacity here: each voice's own --glow-* token already carries its own alpha
     (~0.55). This used to also carry a canvas-level opacity: 0.4 tuned for the old
     single-line design; left on the new multi-voice draw, it compounded to ~0.22
     effective alpha and looked noticeably duller than the mockup the user approved. */
}

.header-top {
  position: relative;
  /* Must outrank .tabs (z-index: 1): the menu-panel dropdown lives inside this stacking
     context and overlaps the tabs row when open. A tie at the same z-index resolves by DOM
     order, which would let .tabs paint (and hit-test) on top of the open menu regardless of
     the menu-panel's own z-index: 30 — that z-index is scoped inside .header-top's context
     and can't escape it to compete with .tabs directly. See modifications.md Changelog. */
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}

.app-header h1.brand {
  margin: 0;
  font-family: 'Unbounded', sans-serif;
  font-weight: 900;
  font-size: 1.3rem;
  letter-spacing: 0.01em;
}

.app-header h1.brand .accent { color: var(--accent); }

.menu-wrap {
  position: relative;
  z-index: 1;
}

.hamburger-btn {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 30px;
  height: 30px;
  padding: 0;
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
}

.hamburger-btn span {
  display: block;
  width: 14px;
  height: 2px;
  background: var(--text);
  margin: 0 auto;
  border-radius: 1px;
}

.hamburger-btn:hover {
  border-color: var(--accent);
}

.menu-panel {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  min-width: 170px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.6rem;
  box-shadow: 0 6px 20px var(--shadow);
  z-index: 30;
}

.menu-panel[hidden] { display: none; }

.menu-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.9rem;
  color: var(--text-dim);
}

.theme-toggle-btn {
  background: var(--bg-panel-alt);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 0.44rem 0.88rem;
  border-radius: 6px;
  cursor: pointer;
  font-size: 1.09rem;
  white-space: nowrap;
}

.theme-toggle-btn:hover {
  border-color: var(--accent);
}

.tabs {
  position: relative;
  z-index: 1;
  display: flex;
  gap: 0.25rem;
}

.tab-btn {
  /* Opaque, matching the header's own surface — not "none". The scope canvas sits behind
     every tab (z-index: 0 vs .tabs' z-index: 1), but a transparent background here would
     still let its lines show through the inactive tab's own footprint, reading as if they
     crossed over it rather than flowing cleanly underneath. */
  background: var(--bg);
  border: 1px solid var(--border);
  border-bottom: none;
  color: var(--text-dim);
  padding: 0.6rem 1rem;
  border-radius: 6px 6px 0 0;
  cursor: pointer;
  font-family: 'Unbounded', sans-serif;
  font-weight: 500;
  font-size: 0.73rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.tab-btn::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--border);
  flex: none;
}

.tab-btn.active {
  color: var(--text);
  background: var(--bg-panel);
  border-color: var(--border);
}

.tab-btn.active::before {
  background: var(--accent);
  box-shadow: 0 0 5px 1px var(--accent);
}

main {
  padding: 1.5rem;
  max-width: 1100px;
  margin: 0 auto;
}

.tab-panel { display: none; }
.tab-panel.active { display: block; }

.picklist {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

/* Technique filter — same tile mechanic as .pick-btn but a *toggle* (optional, clears on
   re-click), not an exclusive picker — sound type/synth pickers require a selection,
   technique narrows the current picker's results and defaults to "any". */
.technique-filter-label {
  font-family: 'Unbounded', sans-serif;
  font-size: 0.65rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 0.5rem;
}

.technique-picklist {
  margin-bottom: 1.25rem;
}

.technique-picklist .pick-btn {
  padding: 0.4rem 0.75rem 0.4rem 1.6rem;
  font-size: 0.68rem;
}

.pick-btn {
  position: relative;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 0.55rem 0.9rem 0.55rem 1.75rem;
  border-radius: 6px;
  cursor: pointer;
  font-family: 'Unbounded', sans-serif;
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.pick-btn::before {
  content: '';
  position: absolute;
  left: 0.85rem;
  top: 50%;
  margin-top: -3px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--border);
}

.pick-btn:hover:not(:disabled) {
  border-color: var(--accent);
}

.pick-btn.selected {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--text);
}

.pick-btn.selected::before {
  background: var(--accent);
  box-shadow: 0 0 5px 1px var(--accent);
}

.pick-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.pick-btn .badge {
  display: block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-dim);
  margin-top: 0.15rem;
}

/* Searchable patch selector — scales to a large, growing list of patch
   concepts without a wall of tiles. */
.patch-select {
  position: relative;
  max-width: 420px;
  margin-bottom: 1.5rem;
}

.patch-select-input {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  padding: 0.65rem 0.9rem;
  font-size: 0.9rem;
  font-family: 'IBM Plex Mono', monospace;
}

.patch-select-input::placeholder {
  color: var(--text-dim);
}

.patch-select-input:focus {
  outline: none;
  border-color: var(--accent);
}

.patch-select-input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.patch-select-list {
  position: absolute;
  top: calc(100% + 0.4rem);
  left: 0;
  right: 0;
  max-height: 320px;
  overflow-y: auto;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px var(--shadow);
  padding: 0.3rem;
  z-index: 25;
}

.patch-select-list[hidden] { display: none; }

.patch-select-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.5rem 0.65rem;
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.92rem;
  color: var(--text);
}

.patch-select-option:hover,
.patch-select-option.highlighted {
  background: var(--bg-panel-alt);
}

.patch-select-option.disabled {
  color: var(--text-dim);
  cursor: not-allowed;
}

.patch-select-option.disabled:hover {
  background: none;
}

.patch-select-option .badge {
  font-size: 0.75rem;
  color: var(--text-dim);
  white-space: nowrap;
}

.patch-select-empty {
  padding: 0.6rem 0.65rem;
  color: var(--text-dim);
  font-size: 0.9rem;
}

/* Favorites / recently-viewed quick-access chips, and the per-item favorite toggle next to a
   detail view's title — both backed by localStorage only (see loadFavorites/loadRecents in
   app.js), no backend involved. */
.quick-access:empty { display: none; }

.quick-access {
  margin-bottom: 1rem;
}

.chip-group {
  margin-bottom: 0.6rem;
}

.chip-group-label {
  font-family: 'Unbounded', sans-serif;
  font-size: 0.65rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 0.4rem;
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.chip-btn {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  cursor: pointer;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.78rem;
}

.chip-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.detail-title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.detail-title-row h2 {
  margin: 0;
}

.fav-toggle-btn {
  flex-shrink: 0;
  background: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-dim);
  font-size: 1.15rem;
  line-height: 1;
  padding: 0.3rem 0.6rem;
  cursor: pointer;
}

.fav-toggle-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.fav-toggle-btn.active {
  color: var(--accent);
  border-color: var(--accent);
}

.detail-panel:empty { display: none; }

.detail-panel {
  position: relative;
  background:
    radial-gradient(circle at 14px 14px, var(--border) 0 1.5px, transparent 1.6px),
    radial-gradient(circle at calc(100% - 14px) 14px, var(--border) 0 1.5px, transparent 1.6px),
    var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1.5rem;
  box-shadow: 0 6px 18px -8px var(--shadow);
}

.detail-panel h2 {
  margin-top: 0;
  font-family: 'Unbounded', sans-serif;
  font-weight: 700;
  font-size: 1.1rem;
}

.meta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.2rem;
  color: var(--text-dim);
  font-size: 0.9rem;
  margin-bottom: 1rem;
}

.meta-row strong {
  color: var(--text);
  font-family: 'IBM Plex Mono', monospace;
  font-weight: 500;
}

.tag {
  position: relative;
  display: inline-block;
  background: var(--bg-panel-alt);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.1rem 0.5rem 0.1rem 1.15rem;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.75rem;
  color: var(--text-dim);
  margin: 0 0.3rem 0.3rem 0;
}

.tag::before {
  content: '';
  position: absolute;
  left: 0.45rem;
  top: 50%;
  margin-top: -2px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent);
}

/* Step grid */
.step-grid-wrap {
  overflow-x: auto;
  margin: 1rem 0 1.5rem;
  padding-bottom: 0.5rem;
}

.step-grid {
  display: grid;
  border-left: 1px solid var(--border);
  width: max-content;
}

.grid-row {
  display: contents;
}

.row-label {
  position: sticky;
  left: 0;
  background: var(--bg-panel);
  padding: 0.3rem 0.6rem;
  font-size: 0.8rem;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 0.4rem;
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border);
  white-space: nowrap;
}

.row-label-name { color: var(--text); }

.row-swatch {
  width: 7px;
  height: 7px;
  border-radius: 2px;
  flex: none;
}

.row-badge {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.68rem;
  padding: 0.1rem 0.4rem;
  border-radius: 3px;
  cursor: help;
  white-space: nowrap;
}

.row-badge.swing-badge {
  background: var(--accent-dim);
  color: var(--text);
}

.row-badge.prob-badge {
  background: transparent;
  border: 1px dashed var(--dash);
  color: var(--text-dim);
}

.grid-header-cell {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  color: var(--text-dim);
  text-align: center;
  padding: 0.2rem 0;
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border);
}

.grid-header-cell.beat-start {
  border-left: 1px solid var(--accent-dim);
}

.step-cell {
  width: 26px;
  height: 28px;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  position: relative;
  cursor: default;
}

.step-cell.beat-start {
  border-left: 1px solid var(--accent-dim);
}

.step-cell .hit {
  position: absolute;
  inset: 3px;
  border-radius: 3px;
  cursor: help;
}

.step-cell .hit.low-prob {
  border: 1px dashed var(--dash);
}

/* The "exceptions" sub-row: shorter than a normal row, vertical grid lines kept so each
   value still lines up under the hit above it — just centered small text per column. */
.sub-row-label {
  height: 20px;
}

.step-cell.sub-row-cell {
  height: 20px;
  overflow: visible;
}

.dev-value {
  position: absolute;
  left: 50%;
  top: 1px;
  transform: translateX(-50%);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  line-height: 1;
  color: var(--text-dim);
  white-space: nowrap;
  cursor: default;
}

.dev-value.tag-late { color: var(--accent); }
.dev-value.tag-early { color: var(--snare); }

.grid-legend {
  margin-top: 0.6rem;
  font-size: 0.77rem;
  color: var(--text-dim);
  max-width: 65ch;
}

.corner-cell {
  position: sticky;
  left: 0;
  background: var(--bg-panel);
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border);
}

/* Hardware notes */
.hw-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.75rem;
}

.hw-tab-btn {
  position: relative;
  background: var(--bg-panel-alt);
  border: 1px solid var(--border);
  color: var(--text-dim);
  padding: 0.4rem 0.8rem 0.4rem 1.6rem;
  border-radius: 6px;
  cursor: pointer;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.83rem;
}

.hw-tab-btn::before {
  content: '';
  position: absolute;
  left: 0.7rem;
  top: 50%;
  margin-top: -3px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--border);
}

.hw-tab-btn.active {
  color: var(--text);
  border-color: var(--accent);
}

.hw-tab-btn.active::before {
  background: var(--accent);
  box-shadow: 0 0 5px 1px var(--accent);
}

.hw-panel { display: none; position: relative; z-index: 0; }
.hw-panel.active { display: block; }

/* Faint hardware silhouette watermark — sits behind the panel's real content (negative
   z-index inside the panel's own stacking context, established by position+z-index above)
   so it never competes with anything readable. */
.device-icon {
  position: absolute;
  top: -6px;
  right: -6px;
  z-index: -1;
  width: 170px;
  max-width: 48%;
  color: var(--text-dim);
  opacity: 0.3;
  pointer-events: none;
}

.device-icon svg { display: block; width: 100%; height: auto; }
.device-icon svg text { fill: currentColor; font-family: 'IBM Plex Mono', monospace; }

/* Full-size panel reference diagram — real block content, not decoration behind other
   content. Sized to actually be read: the label text in the source art was tuned assuming
   this renders at several hundred px wide, not a 170px corner watermark. */
.panel-diagram {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1rem 1.2rem 1.2rem;
  margin-bottom: 1.25rem;
}

.panel-diagram-label {
  font-family: 'Unbounded', sans-serif;
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 0.7rem;
}

.panel-diagram svg {
  display: block;
  width: 100%;
  max-width: 384px;
  height: auto;
  color: var(--text);
}

.panel-diagram svg text { fill: currentColor; font-family: 'IBM Plex Mono', monospace; }

.track-map-table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 0.75rem;
  font-size: 0.9rem;
}

.track-map-table td {
  padding: 0.3rem 0.5rem;
  border-bottom: 1px solid var(--border);
  font-family: 'IBM Plex Mono', monospace;
}

.track-map-table td:first-child {
  color: var(--text-dim);
  width: 60px;
}

.plock-list {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.9rem;
  color: var(--text-dim);
}

.plock-list li { margin-bottom: 0.3rem; }

/* Patch detail */
.settings-block {
  margin-bottom: 1.25rem;
}

.settings-block h3 {
  font-family: 'Unbounded', sans-serif;
  font-weight: 700;
  font-size: 0.77rem;
  color: var(--accent);
  margin-bottom: 0.5rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.settings-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

.settings-table td, .settings-table th {
  padding: 0.35rem 0.6rem;
  border-bottom: 1px solid var(--border);
  text-align: left;
}

.settings-table th {
  color: var(--text-dim);
  font-weight: normal;
  font-size: 0.8rem;
}

.null-field {
  color: var(--text-dim);
  font-style: italic;
  font-size: 0.9rem;
}

.notes-heading {
  font-family: 'Unbounded', sans-serif;
  font-weight: 700;
  font-size: 0.77rem;
  color: var(--accent-soft);
  margin: 1rem 0 0.5rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.notes-block {
  font-size: 0.85rem;
  color: var(--text-dim);
}

.empty-state {
  color: var(--text-dim);
  font-size: 0.95rem;
  padding: 1rem 0;
}

/* Page-grouped parameter cards — for synths (Digitone II first) whose guide is expressed
   as the real on-device pages/parameters rather than the shared oscillators/filter/
   envelopes prose fields. One card per real hardware page, laid out like that page's own
   cluster of named encoders. */
.page-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.75rem;
}

.page-card {
  background: var(--bg-panel-alt);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.7rem 0.85rem;
}

.page-card h4 {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0 0 0.5rem;
}

.page-param-row {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.85rem;
  padding: 0.15rem 0;
}

.page-param-row .param-name {
  color: var(--text-dim);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.78rem;
}

.page-param-row .param-value {
  font-weight: 600;
  font-family: 'IBM Plex Mono', monospace;
}
