/* =====================================================================
   TB-303 — Bass Line · Web Edition
   Full-viewport WebGL canvas. Three.js owns the 3D rendering; this
   stylesheet only handles the loading indicator and donate pill.
   ===================================================================== */

/* Self-hosted fonts — Inter + VT323 latin subsets. Inter ships as a
   variable font so a single woff2 covers 300..700 via axis values;
   the older VT323 is a fixed file. Pulled from fonts.gstatic.com on
   2026-05-10 (Inter v20, VT323 v18). Saves ~3 cross-origin requests
   on cold load and lets us drop the googleapis / fonts.gstatic.com
   dependency entirely. */
@font-face {
  font-family: 'Inter';
  font-style:  normal;
  font-weight: 300 700;
  font-display: optional;
  src: url('/assets/fonts/inter-latin.woff2?v=1') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}
@font-face {
  font-family: 'VT323';
  font-style:  normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/vt323-latin.woff2?v=1') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}

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

html, body {
  background: #000;
  color: #fff;
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  user-select: none;
  -webkit-user-select: none;
}
html { height: 100%; }
body {
  position: relative;
  min-height: 100vh;
  overflow-x: hidden;
  overflow-y: auto;          /* scrollbars when content too tall */
}

#tb303-canvas {
  position: fixed;
  top: 48px;                  /* below top-nav */
  left: 0;
  width: 100vw;
  height: calc(100vh - 158px);
  display: block;
  touch-action: none;
  cursor: grab;
}
#tb303-canvas:active { cursor: grabbing; }

/* Loading overlay */
.loading {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  background: #0a0a0a;
  z-index: 100;
  transition: opacity 0.4s ease;
}
.loading.hidden { opacity: 0; pointer-events: none; }
.loading-text {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.3em;
  color: #ff3210;
  text-transform: uppercase;
  text-shadow: 0 0 12px rgba(255,50,16,0.5), 0 0 24px rgba(255,50,16,0.3);
}
.loading-bar {
  width: 200px;
  height: 2px;
  background: rgba(255,255,255,0.08);
  border-radius: 1px;
  overflow: hidden;
}
.loading-fill {
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, #ff3210 0%, #ff8a4a 100%);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.2s ease-out;
  box-shadow: 0 0 8px rgba(255,50,16,0.6);
}

/* Button-labelling overlay (one-time setup wizard).
   Outer is a fixed full-width strip that flex-centers the inner card.
   This avoids the race-condition bug of `left:50%; transform:translateX(-50%)`
   that intermittently put the card far to the right. */
.label-overlay {
  position: fixed;
  top: 16px;
  left: 0;
  right: 0;
  z-index: 200;
  display: none;
  justify-content: center;
  pointer-events: none;
}
.label-overlay.show { display: flex; }
.label-overlay-card {
  background: rgba(20,20,20,0.94);
  border: 1px solid rgba(255,50,16,0.5);
  border-radius: 8px;
  padding: 14px 22px 12px;
  color: #fff;
  font-family: inherit;
  text-align: center;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 6px 24px rgba(0,0,0,0.45);
  min-width: 280px;
  max-width: calc(100vw - 32px);
  pointer-events: auto;
}
.label-overlay-title {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.25em;
  color: #ff6a4a;
  margin-bottom: 8px;
}
.label-overlay-instruction {
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 4px;
}
.label-overlay-instruction strong {
  color: #ff8a4a;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.label-overlay-progress {
  font-size: 10px;
  color: #888;
  margin-bottom: 10px;
}
.label-overlay-buttons {
  display: flex;
  gap: 8px;
  justify-content: center;
}
.label-overlay-buttons button {
  background: #232323;
  color: #fff;
  border: 1px solid #3a3a3a;
  padding: 5px 14px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 11px;
  font-family: inherit;
  transition: background 0.15s, border-color 0.15s;
}
.label-overlay-buttons button:hover {
  background: #2e2e2e;
  border-color: #555;
}

/* =====================================================================
   Top nav: brand (left) + nav links (centre-left).
   The account bar still lives on the top-right.
   ===================================================================== */
.top-nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  /* z-index 85 puts the nav (and its dropdown panels) above the
     #auto-edit-panel + #step-prog-panel layers (both at z:80) so
     opening PATTERN / IMPORT-EXPORT / AUDIO-MIDI doesn't render
     the menu under the editor when EDIT AUTO is hoisted up. */
  z-index: 85;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 16px;
  pointer-events: none;
}
.top-nav > * { pointer-events: auto; }

.brand {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  text-decoration: none;
  font-family: "Inter", sans-serif;
  transition: opacity 0.12s ease;
}
.brand:hover { opacity: 0.85; }
.brand:active { opacity: 0.7; }
.brand-text {
  font-weight: 900;
  font-size: 22px;             /* bigger now that the tagline below is gone */
  letter-spacing: -0.04em;
  color: #fff;
  display: block;
  line-height: 1;
}
.brand-dot { color: #ff3210; }
.brand-tagline {
  /* Tagline removed from the brand button to free up space in the
     top-nav. Kept in About / welcome text. Class retained in case
     we re-introduce it elsewhere. */
  display: none;
  font-weight: 500;
  font-size: 9px;
  letter-spacing: 0.10em;
  color: #ff8a6a;
  text-transform: uppercase;
  margin-top: 2px;
  text-align: left;
}
@media (max-width: 540px) {
  .brand-tagline { display: none; }   /* keep nav tight on phones */
}

.top-nav-links { display: flex; gap: 6px; }

/* "PATTERN:" label that prefixes the action button group. */
.top-nav-section {
  font: 700 9px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.18em;
  color: #888;
  text-transform: uppercase;
  margin: 0 6px 0 18px;   /* breathing room between brand and group */
  user-select: none;
}
/* Pushes everything to its right out to the far edge. */
.top-nav-spacer { flex: 1; min-width: 16px; }
/* Account area in the top-nav (anon buttons or user dropdown). */
.top-nav-account { display: flex; align-items: center; gap: 6px; position: relative; }
.top-nav-account .account-anon { display: flex; gap: 6px; }
.top-nav-account .account-anon[hidden],
.top-nav-account .account-user[hidden] { display: none; }
.top-nav-link {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid rgba(0, 0, 0, 0.45);
  background: linear-gradient(180deg, #d4d8df 0%, #98a0a8 100%);
  color: #1a1a1c;
  font: 700 10px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  padding: 7px 13px;
  min-width: 64px;
  border-radius: 4px;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.55) inset,
    0 -1px 0 rgba(0, 0, 0, 0.25) inset,
    0 1px 4px rgba(0, 0, 0, 0.45);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.top-nav-link {
  cursor: pointer;
  transition: filter 0.12s ease, transform 0.06s ease;
}
.top-nav-link:hover  { filter: brightness(1.08); }
.top-nav-link:active { transform: translateY(1px); filter: brightness(0.95); }
/* Compact "?" tour button: just the glyph + a little breathing room
   on each side. Overrides the default 64px min-width / 7×13 padding
   so it sits tight next to the About button. */
#nav-help {
  min-width: 0;
  padding: 7px 9px;
}

/* =====================================================================
   BPM HUD — discreet bottom-left readout that fades in while the
   tempo knob is being turned (or a tap-tempo lands), then fades
   back out a beat after motion stops. Not interactive.
   ===================================================================== */
.bpm-hud {
  position: fixed;
  left: 12px;
  bottom: 4px;          /* absolute bottom-left, hugs the page edge */
  z-index: 65;
  padding: 2px 8px;
  background: transparent;
  color: rgba(232, 230, 227, 0.5);   /* half brightness */
  font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.10em;            /* matches .knob-hud — same row look */
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.bpm-hud.visible {
  opacity: 1;
  transform: translateY(0);
}
/* Per-knob readout — only the knobs being actively turned are
   visible. Each lives on its own row; rows stack upward as more
   knobs come alive (e.g. an external MIDI controller sweeping
   multiple CCs at once). The container's bottom edge is anchored
   above the BPM HUD so new rows grow up rather than push BPM down. */
.knob-hud {
  position: fixed;
  left: 12px;
  bottom: 22px;         /* directly above bpm-hud (which sits at 4px) */
  z-index: 65;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  background: transparent;
  color: rgba(232, 230, 227, 0.5);
  font: 600 11px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.10em;
  pointer-events: none;
  user-select: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.knob-hud.visible {
  opacity: 1;
  transform: translateY(0);
}
.knob-hud-row {
  padding: 1px 8px;
  white-space: nowrap;
}
.knob-hud .lbl,
.bpm-hud  .lbl {
  color: rgba(255, 138, 74, 0.65);   /* 303-orange label */
  margin-right: 6px;
}

/* Exact-BPM text-entry popup — fired by right-clicking the TEMPO
   knob. Sits near the click point, escapes/blurs to dismiss, Enter
   commits. Styled like the device's accent so it reads as part of
   the TB-303 chrome rather than generic browser UI. */
.bpm-input-popup {
  position: fixed;
  z-index: 200;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: rgba(20, 22, 26, 0.95);
  border: 1px solid rgba(255, 106, 74, 0.55);
  border-radius: 4px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.55);
  font: 600 12px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.14em;
}
.bpm-input-popup input {
  width: 70px;
  background: #0e0e0e;
  border: 1px solid #3a3a3a;
  color: #fff;
  padding: 4px 6px;
  border-radius: 2px;
  font: inherit;
  text-align: center;
}
.bpm-input-popup input:focus {
  outline: none;
  border-color: #ff6a4a;
  box-shadow: 0 0 0 1px rgba(255, 106, 74, 0.30);
}
.bpm-input-popup span { color: #888; letter-spacing: 0.20em; }

/* Live-render HUD — visible while a real-time recording is in flight
   so the user knows automation is being captured + can abort early. */
#recording-overlay {
  position: fixed;
  top: 60px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 18px;
  background: rgba(20, 22, 26, 0.95);
  border: 1px solid rgba(255, 50, 16, 0.55);
  border-radius: 6px;
  box-shadow: 0 8px 28px rgba(255, 50, 16, 0.25);
  font: 600 12px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.10em;
  color: #fff;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  max-width: calc(100vw - 24px);
}
#recording-overlay .rec-dot {
  color: #ff3210;
  font-size: 22px;
  line-height: 1;
  text-shadow: 0 0 14px rgba(255, 50, 16, 0.85);
  animation: rec-blink 1s ease-in-out infinite;
}
@keyframes rec-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.25; }
}
#recording-overlay .rec-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
#recording-overlay .rec-title {
  letter-spacing: 0.20em;
  color: #ff8a4a;
}
#recording-overlay .rec-progress {
  color: #aaa;
  font-size: 11px;
  letter-spacing: 0.04em;
}
#recording-overlay .rec-hint {
  color: #888;
  font-size: 10px;
  font-style: italic;
  letter-spacing: 0;
  font-weight: 400;
}
#recording-overlay .rec-stop {
  appearance: none;
  -webkit-appearance: none;
  background: rgba(255, 50, 16, 0.18);
  border: 1px solid rgba(255, 80, 48, 0.7);
  color: #ffb88a;
  padding: 6px 12px;
  border-radius: 3px;
  cursor: pointer;
  font: inherit;
  letter-spacing: 0.14em;
  white-space: nowrap;
}
#recording-overlay .rec-stop:hover {
  background: rgba(255, 50, 16, 0.40);
  color: #fff;
  border-color: #ff5030;
}
@media (max-width: 640px) {
  #recording-overlay { gap: 10px; padding: 10px 12px; }
  #recording-overlay .rec-hint { display: none; }
}

/* 4-3-2-1 countdown shown before REC AUTO begins. Big translucent
   numerals centred on screen, each pops in then fades out via CSS
   animation so the JS only has to swap the digit + retrigger. */
#countdown-overlay {
  position: fixed;
  inset: 0;
  z-index: 220;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  pointer-events: none;
  /* Fade backdrop out when JS adds .fade-bg (between counts "2" and
     "1") so the user can see the device + park their mouse on the
     knob they're about to record. The numerals themselves keep
     popping at full visibility throughout. */
  transition: background 0.9s ease-out, backdrop-filter 0.9s ease-out;
}
#countdown-overlay.fade-bg {
  background: rgba(0, 0, 0, 0);
  backdrop-filter: blur(0);
  -webkit-backdrop-filter: blur(0);
}
#countdown-overlay .countdown-num {
  font: 900 200px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  color: #fff;
  text-shadow: 0 0 28px rgba(255, 50, 16, 0.65),
               0 0 80px rgba(255, 50, 16, 0.35);
  letter-spacing: -0.04em;
}
#countdown-overlay .countdown-num.pop {
  animation: countdown-pop 1s ease-out;
}
@keyframes countdown-pop {
  0%   { transform: scale(0.4); opacity: 0; }
  20%  { transform: scale(1.10); opacity: 1; }
  60%  { transform: scale(1.00); opacity: 1; }
  100% { transform: scale(1.04); opacity: 0; }
}

/* REC AUTO live overlay — bottom strip while a recording is running.
   Lives above the footer so the device's top knobs are still reachable. */
#auto-live-panel {
  position: fixed;
  bottom: 60px;
  left: 12px;
  right: 12px;
  z-index: 80;
  display: flex;
  flex-direction: column;
  padding: 6px 8px 8px;
  background: rgba(8, 18, 10, 0.92);
  border: 1px solid #2a6a2a;
  border-radius: 4px;
  box-shadow: 0 -8px 28px rgba(0, 60, 30, 0.30);
  color: #00ff66;
  font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.10em;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
#auto-live-panel .auto-live-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 4px;
  flex: 0 0 auto;
}
#auto-live-panel .auto-live-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #ff8a4a;
  letter-spacing: 0.18em;
}
#auto-live-panel .auto-live-dot {
  color: #ff3210;
  font-size: 14px;
  text-shadow: 0 0 10px rgba(255, 50, 16, 0.7);
  animation: rec-blink 1s ease-in-out infinite;
}
#auto-live-panel .auto-live-progress {
  color: #aaa;
  font-size: 11px;
  letter-spacing: 0.04em;
  font-family: "SF Mono", Menlo, Consolas, monospace;
}
#auto-live-panel .auto-live-legend {
  flex: 1 1 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
}
#auto-live-panel .auto-live-chip {
  font-size: 10px;
  letter-spacing: 0.14em;
}
#auto-live-panel .auto-live-stop {
  appearance: none;
  -webkit-appearance: none;
  background: rgba(255, 50, 16, 0.18);
  border: 1px solid rgba(255, 80, 48, 0.7);
  color: #ffb88a;
  padding: 4px 10px;
  border-radius: 3px;
  cursor: pointer;
  font: inherit;
  letter-spacing: 0.14em;
}
#auto-live-panel .auto-live-stop:hover {
  background: rgba(255, 50, 16, 0.40);
  color: #fff;
  border-color: #ff5030;
}
#auto-live-svg {
  display: block;
  width: 100%;
  /* Fill the remaining vertical space in the panel — when the panel
     is anchored to the lower silkscreen mesh, JS sets a fixed panel
     height and the SVG stretches to fill whatever's left after the
     header bar. Bigger curves = easier to read. */
  flex: 1 1 auto;
  min-height: 60px;
  background: #001000;
  border: 1px solid #1a4d1a;
  border-radius: 2px;
}
@media (max-width: 640px) {
  #auto-live-panel { bottom: 80px; padding: 6px 8px; }
  #auto-live-panel .auto-live-legend { font-size: 9px; }
  #auto-live-svg { min-height: 50px; }
}

/* Automation editor — knob picker chips at the top of the modal.
   Each chip's outline + text is the corresponding knob colour;
   the active one fills with that colour and switches to dark text
   so it reads as "selected and editable". */
.auto-edit-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 4px 0 10px;
}
.auto-edit-chip {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid;
  border-radius: 3px;
  padding: 4px 10px;
  font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.12em;
  cursor: pointer;
  transition: background 0.10s ease, color 0.10s ease;
}

/* Automation editor panel — anchored to the lower silkscreen mesh
   on the device (same as the live REC AUTO overlay), sized in pixels
   each frame so it tracks viewport changes. NOT a CRT modal, since
   the CRT max-width cap was the original "only 1.5 bars visible"
   bug. */
#auto-edit-panel {
  position: fixed;
  z-index: 80;
  display: flex;
  flex-direction: column;
  padding: 6px 8px 8px;
  background: rgba(8, 18, 10, 0.94);
  border: 1px solid #2a6a2a;
  border-radius: 4px;
  box-shadow: 0 -8px 28px rgba(0, 60, 30, 0.30);
  color: #00ff66;
  font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.10em;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  /* Smooth the slot-shuffle when a second/third panel pushes us
     between centre / upper-half / lower-half. Ignored when window
     resizes (still tracks pixel-perfect, just animates between
     stable layouts). */
  transition: top 220ms ease-out, height 220ms ease-out;
}
#auto-edit-panel .auto-edit-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
  flex: 0 0 auto;
}
#auto-edit-panel .auto-edit-bar .auto-edit-picker {
  margin: 0;
  flex: 1 1 auto;
}
#auto-edit-panel .auto-edit-title {
  color: #ff8a4a;
  letter-spacing: 0.20em;
  flex: 0 0 auto;
}
#auto-edit-panel .auto-edit-spacer { flex: 1 1 0; }
#auto-edit-panel .auto-edit-bars {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #00ff66;
  font: inherit;
  letter-spacing: 0.14em;
  flex: 0 0 auto;
}
#auto-edit-panel .auto-edit-bars-sel {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid #2a6a2a;
  color: #00ff66;
  padding: 3px 22px 3px 8px;
  border-radius: 3px;
  font: inherit;
  letter-spacing: 0.14em;
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, #00ff66 50%),
                    linear-gradient(135deg, #00ff66 50%, transparent 50%);
  background-position: calc(100% - 12px) 50%, calc(100% - 7px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
#auto-edit-panel .auto-edit-bars-sel:hover { filter: brightness(1.15); }
#auto-edit-panel .auto-edit-bars-sel option { background: #06120a; color: #00ff66; }
#auto-edit-panel .auto-edit-rec,
#auto-edit-panel .auto-edit-add,
#auto-edit-panel .auto-edit-clear,
#auto-edit-panel .auto-edit-bypass,
#auto-edit-panel .auto-edit-help,
#auto-edit-panel .auto-edit-done {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid #2a6a2a;
  color: #00ff66;
  padding: 4px 10px;
  border-radius: 3px;
  cursor: pointer;
  font: inherit;
  letter-spacing: 0.14em;
  flex: 0 0 auto;
}
#auto-edit-panel .auto-edit-help {
  /* Question-mark button — slightly tighter padding so it doesn't
     dominate the row of action buttons next to it. */
  padding: 4px 8px;
  min-width: 24px;
}
#auto-edit-panel .auto-edit-clear-wrap {
  position: relative;
  flex: 0 0 auto;
}
#auto-edit-panel .auto-edit-caret {
  margin-left: 4px;
  font-size: 9px;
  opacity: 0.7;
}
#auto-edit-panel .auto-edit-clear-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  min-width: 180px;
  background: rgba(8, 18, 10, 0.96);
  border: 1px solid #2a6a2a;
  border-radius: 4px;
  box-shadow: 0 8px 28px rgba(0, 60, 30, 0.45);
  padding: 4px 0;
}
#auto-edit-panel .auto-edit-clear-menu[hidden] { display: none; }
#auto-edit-panel .auto-edit-clear-menu button {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  color: #00ff66;
  text-align: left;
  padding: 6px 12px;
  cursor: pointer;
  font: inherit;
  letter-spacing: 0.10em;
  white-space: nowrap;
}
#auto-edit-panel .auto-edit-clear-menu button:hover {
  background: rgba(0, 255, 102, 0.10);
}
#auto-edit-panel .auto-edit-bypass.on {
  /* Engaged state — automation is intercepted (knobs free) */
  background: rgba(255, 200, 50, 0.20);
  border-color: rgba(255, 200, 50, 0.65);
  color: #ffe18a;
}
#auto-edit-panel .auto-edit-rec {
  background: rgba(255, 50, 16, 0.22);
  border-color: rgba(255, 106, 74, 0.65);
  color: #ffb88a;
}
#auto-edit-panel .auto-edit-add {
  background: rgba(255, 138, 74, 0.10);
  border-color: rgba(255, 138, 74, 0.45);
  color: #ffd0a8;
}
#auto-edit-panel .auto-edit-done {
  background: rgba(255, 50, 16, 0.18);
  border-color: rgba(255, 106, 74, 0.55);
  color: #ffb88a;
}
#auto-edit-panel .auto-edit-rec:hover,
#auto-edit-panel .auto-edit-add:hover,
#auto-edit-panel .auto-edit-clear:hover,
#auto-edit-panel .auto-edit-bypass:hover,
#auto-edit-panel .auto-edit-help:hover,
#auto-edit-panel .auto-edit-done:hover { filter: brightness(1.15); }

/* Close-X on STEPS / TRACKS / AUTOMATION panel headers. Was a "DONE"
   word; the × glyph reads as a close-icon, but at the panel's base
   font size it looks anemic, so bump it to render as a clear action
   target. Same scaling rule for all three panels keeps the chrome
   visually consistent across the panel stack. */
#step-prog-panel .step-prog-done,
#tracks-panel    .tracks-done,
#auto-edit-panel .auto-edit-done {
  font-size: 18px;
  line-height: 1;
  padding: 2px 10px 4px;
  min-width: 32px;
  letter-spacing: 0;
}

/* =====================================================================
   Spotlight tour — used by the [?] buttons on STEPS + AUTOMATION.
   Pattern ported from issview.com: a giant box-shadow on the spotlight
   element darkens the whole viewport EXCEPT the cut-out rectangle,
   so the highlighted control is the only thing not dim. A glowing
   bordered ring sits around it and a tooltip bubble auto-positions
   on whichever side has the most room.
   ===================================================================== */
.tb303-tour-overlay {
  position: fixed;
  inset: 0;
  z-index: 950;     /* above the editor panels (z:80) and CRT (z:200/220) */
  pointer-events: none;
}
.tb303-tour-backdrop {
  position: absolute;
  inset: 0;
  /* Transparent — the spotlight's huge box-shadow already dims the
     page outside the highlight. Adding darkening here would also dim
     the spotlight target, which defeats the point. */
  background: transparent;
  pointer-events: auto;
  cursor: default;
}
.tb303-tour-spot {
  position: absolute;
  border: 2px solid #ff8a4a;
  border-radius: 6px;
  /* The first shadow is the page-darkening ring (single layer; bumped
     to 0.82 so the bubble is comfortable to read). The second is the
     warm rim-glow that frames the target. */
  box-shadow:
    0 0 0 99999px rgba(0, 0, 0, 0.82),
    0 0 22px rgba(255, 138, 74, 0.55);
  pointer-events: none;
  transition: all 0.35s cubic-bezier(0.25, 0.8, 0.3, 1);
  opacity: 0;
}
.tb303-tour-bubble {
  position: absolute;
  width: 340px;
  max-width: calc(100vw - 24px);
  padding: 14px 16px 12px;
  background: linear-gradient(to bottom, #06120a 0%, #030604 100%);
  border: 1px solid rgba(255, 138, 74, 0.55);
  border-radius: 6px;
  box-shadow:
    0 16px 40px rgba(0, 0, 0, 0.7),
    0 0 18px rgba(255, 138, 74, 0.18);
  color: #cce;
  font: 600 11px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.04em;
  pointer-events: auto;
  transition: all 0.35s cubic-bezier(0.25, 0.8, 0.3, 1);
}
.tb303-tour-num {
  font-size: 9px;
  letter-spacing: 0.20em;
  color: #ff8a4a;
  margin-bottom: 5px;
  opacity: 0.85;
}
.tb303-tour-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: #ffd0a8;
  text-shadow: 0 0 6px rgba(255, 138, 74, 0.30);
  margin-bottom: 8px;
}
.tb303-tour-text {
  font-size: 11.5px;
  line-height: 1.55;
  letter-spacing: 0.02em;
  color: #aab;
  margin-bottom: 14px;
}
.tb303-tour-text em {
  color: #ffe18a;
  font-style: normal;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.tb303-tour-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}
.tb303-tour-nav { display: flex; gap: 6px; }
.tb303-tour-skip,
.tb303-tour-prev,
.tb303-tour-next {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid rgba(200, 209, 220, 0.30);
  color: #aab;
  font: 700 10px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.16em;
  padding: 7px 12px;
  border-radius: 100px;
  cursor: pointer;
  transition: all 0.12s ease;
}
.tb303-tour-skip:hover,
.tb303-tour-prev:not(:disabled):hover {
  color: #fff;
  border-color: #aab;
  background: rgba(255, 255, 255, 0.05);
}
.tb303-tour-prev:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.tb303-tour-next {
  background: rgba(255, 138, 74, 0.18);
  border-color: rgba(255, 138, 74, 0.65);
  color: #ffd0a8;
  padding: 7px 14px;
}
.tb303-tour-next:hover {
  background: rgba(255, 138, 74, 0.32);
  color: #fff;
  box-shadow: 0 0 12px rgba(255, 138, 74, 0.45);
}
#auto-edit-panel #auto-edit-svg {
  flex: 1 1 auto;
  width: 100%;
  min-height: 60px;
  background: #001000;
  border: 1px solid #1a4d1a;
  border-radius: 2px;
  cursor: crosshair;
  user-select: none;
  -webkit-user-select: none;
}

/* Step programmer — same panel chrome as REC AUTO editor + a 16-cell
   grid where each cell stacks pitch / accent / slide controls. */
#step-prog-panel {
  position: fixed;
  z-index: 80;
  display: flex;
  flex-direction: column;
  padding: 6px 8px 8px;
  background: rgba(8, 18, 10, 0.94);
  border: 1px solid #2a6a2a;
  border-radius: 4px;
  box-shadow: 0 -8px 28px rgba(0, 60, 30, 0.30);
  color: #00ff66;
  font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.10em;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  /* Slide between centre / upper-half / lower-half slots when the
     panel stack reshuffles. */
  transition: top 220ms ease-out, height 220ms ease-out;
}
#step-prog-panel .step-prog-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
  flex: 0 0 auto;
}
#step-prog-panel .step-prog-title {
  color: #ff8a4a;
  letter-spacing: 0.20em;
}
#step-prog-panel .step-prog-hint {
  color: #4a8a4a;
  font-size: 10px;
  letter-spacing: 0.04em;
  font-weight: 400;
}
#step-prog-panel .step-prog-spacer { flex: 1 1 0; }
#step-prog-panel .step-prog-timing {
  display: inline-flex;
  gap: 0;
  border: 1px solid #2a6a2a;
  border-radius: 3px;
  overflow: hidden;
}
#step-prog-panel .step-prog-mode {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  color: #4a8a4a;
  padding: 4px 8px;
  cursor: pointer;
  font: 700 9px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.14em;
}
#step-prog-panel .step-prog-mode + .step-prog-mode {
  border-left: 1px solid #2a6a2a;
}
#step-prog-panel .step-prog-mode.on {
  background: rgba(255, 138, 74, 0.20);
  color: #ffb88a;
}
/* Slot-selector button in the STEPS header — looks like a compact
   dropdown trigger but opens the 64-cell pattern picker. */
#step-prog-panel .step-prog-slot {
  appearance: none;
  -webkit-appearance: none;
  background: rgba(255, 138, 74, 0.12);
  border: 1px solid rgba(255, 138, 74, 0.45);
  color: #ffd0a8;
  padding: 4px 9px;
  border-radius: 3px;
  cursor: pointer;
  font: inherit;
  letter-spacing: 0.16em;
  font-weight: 700;
}
#step-prog-panel .step-prog-slot:hover { filter: brightness(1.15); }
#step-prog-panel .step-prog-slot-caret {
  font-size: 9px;
  margin-left: 2px;
  opacity: 0.7;
}

#step-prog-panel .step-prog-clear,
#step-prog-panel .step-prog-help,
#step-prog-panel .step-prog-copy,
#step-prog-panel .step-prog-done {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid #2a6a2a;
  color: #00ff66;
  padding: 4px 10px;
  border-radius: 3px;
  cursor: pointer;
  font: inherit;
  letter-spacing: 0.14em;
}
#step-prog-panel .step-prog-help { padding: 4px 8px; }
#step-prog-panel .step-prog-done {
  background: rgba(255, 50, 16, 0.18);
  border-color: rgba(255, 106, 74, 0.55);
  color: #ffb88a;
}
#step-prog-panel .step-prog-clear:hover,
#step-prog-panel .step-prog-help:hover,
#step-prog-panel .step-prog-copy:hover,
#step-prog-panel .step-prog-done:hover { filter: brightness(1.15); }

#step-prog-panel .step-prog-grid {
  flex: 1 1 auto;
  display: grid;
  grid-template-columns: repeat(16, 1fr);
  gap: 3px;
  background: #001000;
  border: 1px solid #1a4d1a;
  border-radius: 2px;
  padding: 4px;
  user-select: none;
  -webkit-user-select: none;
}
#step-prog-panel .step-prog-col {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  background: #002800;
  border: 1px solid #0a2a0a;
  border-radius: 2px;
  padding: 3px 2px;
  transition: background 0.10s ease, border-color 0.10s ease;
}
#step-prog-panel .step-prog-col.beat {
  /* Subtle highlight on the downbeat columns (1, 5, 9, 13). */
  background: #003800;
  border-color: #1a4d1a;
}
#step-prog-panel .step-prog-col.active {
  /* Currently-playing step lights up red, matching the device's
     step lamps. */
  background: rgba(255, 50, 16, 0.30);
  border-color: #ff5030;
  box-shadow: 0 0 8px rgba(255, 50, 16, 0.55);
}
#step-prog-panel .step-prog-num {
  color: #4a8a4a;
  font-size: 9px;
  text-align: center;
  letter-spacing: 0.05em;
  flex: 0 0 auto;
}
/* Piano-roll lane — vertical strip where the pitch block lives.
   Click empty → place block at that pitch. Drag block → move it
   vertically. Right-click → remove (REST). The lane has subtle
   horizontal hairlines every octave so users can navigate by ear+eye. */
#step-prog-panel .step-prog-lane {
  position: relative;
  flex: 1 1 auto;
  min-height: 40px;
  background:
    repeating-linear-gradient(
      to bottom,
      #001800 0,
      #001800 calc(100% / 24 * 12 - 1px),
      #003a00 calc(100% / 24 * 12 - 1px),
      #003a00 calc(100% / 24 * 12)
    ),
    #001800;
  border: 1px solid #1a4d1a;
  border-radius: 2px;
  cursor: crosshair;
  overflow: hidden;
}
#step-prog-panel .step-prog-lane:hover { background-color: #002400; }
#step-prog-panel .step-prog-block {
  position: absolute;
  left: 1px;
  right: 1px;
  height: 9px;
  margin-top: -4px;            /* visually centre the block on its pitch line */
  background: #00ff66;
  border: 1px solid #003a00;
  border-radius: 2px;
  cursor: ns-resize;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
  transition: background 0.10s ease, border-color 0.10s ease, box-shadow 0.15s ease;
}
#step-prog-panel .step-prog-block-label {
  font-size: 8px;
  letter-spacing: 0.04em;
  font-weight: 700;
  color: #001800;
  pointer-events: none;
}
#step-prog-panel .step-prog-block.accent {
  background: #ff5030;
  border-color: #5a1a0a;
  box-shadow: 0 0 6px rgba(255, 80, 48, 0.6),
              0 1px 2px rgba(0, 0, 0, 0.5);
}
#step-prog-panel .step-prog-block.accent .step-prog-block-label {
  color: #fff;
}
#step-prog-panel .step-prog-block.slide {
  outline: 1px dashed #4adfff;
  outline-offset: 1px;
}
#step-prog-panel .step-prog-flag {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid #1a4d1a;
  border-radius: 2px;
  color: #1a4d1a;
  font: 700 8px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.10em;
  padding: 3px 0;
  cursor: pointer;
  transition: color 0.10s ease, background 0.10s ease, border-color 0.10s ease;
}
#step-prog-panel .step-prog-acc.on {
  color: #ff5030;
  border-color: #ff5030;
  background: rgba(255, 50, 16, 0.18);
}
#step-prog-panel .step-prog-tie.on {
  color: #ffd54a;
  border-color: #ffd54a;
  background: rgba(255, 213, 74, 0.15);
}
#step-prog-panel .step-prog-sld.on {
  color: #4adfff;
  border-color: #4adfff;
  background: rgba(74, 223, 255, 0.12);
}
#step-prog-panel .step-prog-flag:hover { filter: brightness(1.3); }
/* Tied block — diagonal stripes overlay so TIED steps read clearly
   as "no envelope retrigger" while still showing the pitch. */
#step-prog-panel .step-prog-block.tied {
  background: repeating-linear-gradient(
    45deg,
    #00ff66 0,
    #00ff66 3px,
    #ffd54a 3px,
    #ffd54a 6px
  );
}

/* Generic floating hint that fades in/out under big editor panels.
   Lives at the bottom of the viewport so it doesn't fight with the
   panel that's currently anchored to the lower silkscreen. */
.floating-hint {
  position: fixed;
  /* When showFloatingHint() has an anchor element, JS overrides
     `top` and clears `bottom`; otherwise the hint falls back to
     bottom-of-viewport via this default. */
  bottom: 92px;
  left: 50%;
  z-index: 200;
  padding: 6px 14px;
  background: rgba(20, 22, 26, 0.85);
  color: rgba(232, 230, 227, 0.9);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 4px;
  font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.16em;
  pointer-events: none;
  user-select: none;
  opacity: 0;
  transform: translate(-50%, 8px);
  transition: opacity 0.4s ease, transform 0.4s ease;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.floating-hint.show {
  opacity: 1;
  transform: translate(-50%, 0);
}
/* Anchor variants ("How to program!?!") shouldn't get the default
   underline + visited color — keep them visually identical to the
   button-styled siblings. */
a.top-nav-link,
a.top-nav-link:visited { text-decoration: none; color: inherit; }

/* =====================================================================
   Top-nav dropdowns — used under ?audio to consolidate the long
   flat strip of action buttons into 4 logical groups (PATTERN,
   AUTOMATION, EXPORT, AUDIO/MIDI). Each trigger is a top-nav-link
   that opens an absolutely-positioned panel right below it.
   ===================================================================== */
.nav-drop { position: relative; }
/* Small visual break between the 3 dropdowns and the 3 direct
   toggle buttons in the top-nav. Doesn't affect layout besides
   widening the gap there. */
.nav-direct-gap {
  display: inline-block;
  width: 14px;
  flex: 0 0 auto;
}
.nav-drop-trigger .nav-drop-caret {
  margin-left: 4px;
  font-size: 9px;
  opacity: 0.7;
}
.nav-drop-panel {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 4px;
  min-width: 230px;
  z-index: 90;
  display: none;
  flex-direction: column;
  padding: 6px 0;
  background: rgba(20, 22, 26, 0.96);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 6px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.nav-drop.open .nav-drop-panel { display: flex; }
.nav-drop-item {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  color: #ddd;
  font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.06em;
  text-align: left;
  padding: 8px 14px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  white-space: nowrap;
  transition: background 0.10s ease, color 0.10s ease;
}
.nav-drop-item:hover {
  background: rgba(255, 255, 255, 0.07);
  color: #fff;
}
.nav-drop-item .nav-drop-glyph {
  width: 16px;
  text-align: center;
  font-size: 12px;
  opacity: 0.85;
}
.nav-drop-item .nav-drop-tag {
  margin-left: auto;
  padding: 1px 6px;
  font-size: 9px;
  letter-spacing: 0.10em;
  border-radius: 2px;
  background: rgba(95, 204, 95, 0.15);
  color: #5fcc5f;
  border: 1px solid rgba(95, 204, 95, 0.30);
}
.nav-drop-item.danger:hover {
  background: rgba(255, 80, 64, 0.14);
  color: #ff8a6a;
}
.nav-drop-sep {
  height: 1px;
  margin: 5px 8px;
  background: rgba(255, 255, 255, 0.08);
}
.nav-drop-section {
  padding: 8px 14px 2px;
  font: 700 9px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.20em;
  color: #777;
  text-transform: uppercase;
}

/* =====================================================================
   Saw / Square waveform "buttons" — proxy for the real TB-303's
   back-panel switch (which our front-facing camera can't see). Two
   small black push-buttons floating near the top-left of the device,
   styled to read as physical buttons mounted on the case rather than
   web UI chrome. No text, just the waveform glyph; the active state
   gets a soft red LED-style glow that matches the device's lamps.
   ===================================================================== */
.waveform-toggle {
  position: fixed;
  /* Initial top/left are placeholders — JS projects a 3D anchor onto
     the model each frame and overwrites these so the buttons sit ON
     the device. The translate(-50%,-50%) centres the pair on the
     anchor point. */
  top: 64px;
  left: 22px;
  transform: translate(-50%, -50%);
  z-index: 70;
  display: flex;
  gap: 23px;
  user-select: none;
  pointer-events: auto;
}
.wave-btn {
  appearance: none;
  -webkit-appearance: none;
  width: 32px;
  height: 28px;
  padding: 0;
  border-radius: 0;
  border: 1px solid #000;
  /* Subtle top-lit black plastic — matches the small_butt look on the
     device. The dark inner shadow gives the cap a slight inset so it
     reads as a physical key, not a flat UI tile. */
  background:
    linear-gradient(180deg, #2a2a2c 0%, #161618 55%, #0c0c0e 100%);
  color: #555;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    inset 0 -1px 0 rgba(0, 0, 0, 0.6),
    0 1px 2px rgba(0, 0, 0, 0.5);
  transition: background 0.12s ease, color 0.15s ease,
              box-shadow 0.15s ease, transform 0.06s ease;
}
.wave-btn svg {
  width: 18px;
  height: 9px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: square;
  stroke-linejoin: miter;
}
.wave-btn:hover {
  color: #888;
}
.wave-btn:active {
  transform: translateY(1px);
}
.wave-btn.on {
  /* Inverted state — cap takes on the TB-303 case grey (the same
     0xa8b0b8 that applyBrushedAluminum uses) with a dark symbol on
     it. Reads like a selected-position slide switch rather than a
     backlit indicator, which fits the device's overall matte feel
     better than a glow. */
  color: #1a1a1c;
  background:
    linear-gradient(180deg, #c0c8cf 0%, #a8b0b8 55%, #8e969e 100%);
  border-color: #6a7075;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    inset 0 -1px 0 rgba(0, 0, 0, 0.25),
    0 1px 2px rgba(0, 0, 0, 0.5);
}
@media (max-width: 640px) {
  .waveform-toggle { gap: 18px; }
  .wave-btn { width: 28px; height: 24px; }
  .wave-btn svg { width: 18px; height: 9px; }
}

/* =====================================================================
   Auth UI — top-right account bar, modals, pattern list, admin table.
   ===================================================================== */
/* Account area lives inline in the top-nav now; keep the legacy id
   "account-bar" for JS but drop the old fixed-position styling. */
#account-bar[hidden] { display: none; }

/* Logged-in pill: avatar + display name + caret, all inside a chrome
   top-nav-link button so it matches the rest of the nav. */
.account-toggle {
  display: inline-flex !important;
  align-items: center;
  gap: 6px;
  /* Vertical padding tuned so the chrome pill is the same height as
     plain top-nav-links (4 + 16px avatar + 4 = 24 inner = 26 outer
     with the 1px border). */
  padding: 4px 13px 4px 6px !important;
  max-width: 220px;
}
.account-toggle #account-email {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 140px;
  font-size: 10px;
  letter-spacing: 0.06em;
}
.account-caret {
  font-size: 8px;
  opacity: 0.55;
  margin-left: 2px;
}
.account-avatar {
  width: 16px; height: 16px; border-radius: 50%; object-fit: cover;
  border: none; flex: none;
}

.account-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 280px;
  background: rgba(15,15,15,0.96);
  border: 1px solid rgba(255,106,74,0.3);
  border-radius: 8px;
  padding: 12px 12px 10px;
  box-shadow: 0 8px 28px rgba(0,0,0,0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.account-section { margin-bottom: 10px; }
.account-section-title {
  font: 700 9px/1 "Inter", sans-serif;
  letter-spacing: 0.25em;
  color: #ff6a4a;
  margin-bottom: 8px;
  padding-left: 4px;
}
.pattern-list {
  list-style: none; margin: 0; padding: 0;
  max-height: 260px; overflow-y: auto;
}
.pattern-list:empty::before {
  content: "No saved patterns yet";
  display: block;
  padding: 8px 4px;
  font-size: 11px;
  color: #888;
}
.pattern-list li {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  border-radius: 4px;
}
.pattern-list li:hover { background: rgba(255,106,74,0.10); }
.pattern-list .pat-name {
  flex: 1;
  background: none;
  border: none;
  text-align: left;
  color: #ddd;
  font: 400 12px/1.3 "Inter", sans-serif;
  cursor: pointer;
  padding: 4px 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pattern-list .pat-name:hover { color: #fff; }
.pattern-list .pat-icon {
  background: none; border: none; padding: 4px 6px;
  color: #888; cursor: pointer; font-size: 12px;
}
.pattern-list .pat-icon:hover { color: #ff8a6a; }

.account-actions { display: flex; flex-direction: column; gap: 4px; }
.account-action {
  background: rgba(40,40,40,0.5);
  border: 1px solid rgba(255,255,255,0.05);
  color: #ddd;
  padding: 7px 10px;
  border-radius: 4px;
  cursor: pointer;
  font: 500 11px/1 "Inter", sans-serif;
  text-align: left;
  transition: background 0.15s;
}
.account-action:hover { background: rgba(60,60,60,0.7); color: #fff; }

/* Modals */
.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.7);
  z-index: 300;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.modal-backdrop[hidden] { display: none; }
.modal-card {
  background: #181818;
  border: 1px solid #333;
  border-radius: 10px;
  padding: 28px 28px 24px;
  max-width: 360px;
  width: 100%;
  box-shadow: 0 12px 40px rgba(0,0,0,0.6);
  position: relative;
}
.modal-card-wide { max-width: 720px; }
.modal-card h2 {
  font: 700 12px/1 "Inter", sans-serif;
  letter-spacing: 0.25em;
  color: #ff6a4a;
  text-transform: uppercase;
  margin: 0 0 18px;
}
.modal-close {
  position: absolute; top: 10px; right: 12px;
  background: none; border: none; color: #888;
  font-size: 22px; cursor: pointer; line-height: 1;
}
.modal-close:hover { color: #fff; }
.modal-card form { display: flex; flex-direction: column; gap: 14px; }
.modal-card label {
  display: flex; flex-direction: column; gap: 6px;
  font: 500 11px/1 "Inter", sans-serif;
  letter-spacing: 0.04em;
  color: #aaa;
}
.modal-card input[type=email],
.modal-card input[type=password],
.modal-card input[type=text] {
  background: #0e0e0e;
  border: 1px solid #333;
  border-radius: 5px;
  color: #fff;
  font: 400 13px/1 "Inter", sans-serif;
  padding: 10px 12px;
  outline: none;
  transition: border-color 0.15s;
}
.modal-card input:focus { border-color: #ff6a4a; }
.modal-submit {
  background: #ff3210;
  color: #fff;
  border: none;
  border-radius: 5px;
  padding: 11px 16px;
  font: 700 12px/1 "Inter", sans-serif;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  margin-top: 4px;
  transition: background 0.15s;
}
.modal-submit:hover { background: #ff4520; }
.modal-submit:disabled { background: #555; cursor: wait; }
/* Danger variant — for destructive irreversible actions like account
   self-delete. Outlined dim red instead of filled brand red, so it
   doesn't compete with the primary Save buttons above it. */
.modal-submit-danger {
  background: transparent;
  border: 1px solid #663030;
  color: #ff6060;
}
.modal-submit-danger:hover {
  background: rgba(255, 60, 60, 0.12);
  border-color: #ff6060;
  color: #ff8080;
}
.profile-danger-h2 { color: #ff6060; }
.modal-error {
  color: #ff5040;
  font: 400 12px/1.4 "Inter", sans-serif;
  margin: 0;
}
.modal-info {
  color: #5fcc5f;
  font: 400 12px/1.4 "Inter", sans-serif;
  margin: 0;
}
/* Collapse empty status paragraphs so they don't add a gap above the
   Save button. They get padding-top once they have content. */
.modal-error:empty, .modal-info:empty { display: none; }
.modal-error:not(:empty), .modal-info:not(:empty) { margin-top: 8px; }

/* Two-column password form so the dialog isn't a tall ladder of
   inputs. Labels sit side-by-side; submit + status span both columns. */
#password-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 14px;
  row-gap: 10px;
}
#password-form > button,
#password-form > .modal-error,
#password-form > .modal-info { grid-column: 1 / -1; }

/* Display name input + Save profile button on the same row. The
   button aligns with the bottom of the label so it sits next to the
   actual input (not floating off to the side of the label text). */
#profile-form {
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: 12px;
  row-gap: 8px;
  align-items: end;
}
#profile-form > .modal-error,
#profile-form > .modal-info { grid-column: 1 / -1; }
#profile-form > button { white-space: nowrap; }

@media (max-width: 540px) {
  /* On narrow phones two columns are too tight — collapse to one. */
  #password-form { grid-template-columns: 1fr; }
  #profile-form  { grid-template-columns: 1fr; }
}
.modal-foot {
  margin: 16px 0 0;
  font: 400 12px/1.5 "Inter", sans-serif;
  color: #888;
}
.modal-foot a { color: #ff6a4a; text-decoration: none; }
.modal-foot a:hover { text-decoration: underline; }

.confirm-actions {
  display: flex; gap: 8px; justify-content: flex-end; margin-top: 18px;
}
.modal-action {
  background: #2a2a2a; color: #ddd; border: 1px solid #444;
  padding: 8px 14px; border-radius: 5px; cursor: pointer;
  font: 500 12px/1 "Inter", sans-serif;
}
.modal-action:hover { background: #3a3a3a; color: #fff; }
.modal-action-danger { background: #ff3210; border-color: #ff3210; color: #fff; }
.modal-action-danger:hover { background: #ff4520; }

/* Profile + settings modal */
.profile-grid {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 22px;
  margin-bottom: 8px;
}
@media (max-width: 600px) {
  .profile-grid { grid-template-columns: 1fr; }
}
.profile-avatar-col { text-align: center; }
.profile-avatar-preview {
  width: 110px; height: 110px; border-radius: 50%; object-fit: cover;
  background: #0e0e0e; border: 1px solid #333; display: block; margin: 0 auto 10px;
}
.profile-avatar-actions {
  display: flex; gap: 6px; justify-content: center; margin-bottom: 8px;
}
.profile-avatar-actions .modal-action { padding: 6px 10px; font-size: 11px; }
.profile-avatar-hint {
  font: 400 10px/1.4 "Inter", sans-serif;
  color: #666;
  margin: 0 0 12px;
}
.profile-email-row {
  font: 500 11px/1.4 "Inter", sans-serif;
  color: #aaa; margin: 0; word-break: break-all;
}
.profile-fields-col textarea {
  background: #0e0e0e; border: 1px solid #333; border-radius: 5px;
  color: #fff; font: 400 13px/1.4 "Inter", sans-serif;
  padding: 10px 12px; outline: none; resize: vertical;
  font-family: inherit;
}
.profile-fields-col textarea:focus { border-color: #ff6a4a; }
.profile-section-title {
  font: 700 9px/1 "Inter", sans-serif;
  letter-spacing: 0.25em;
  color: #ff6a4a;
  margin: 16px 0 8px;
}
.profile-links { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.profile-link-row {
  display: grid;
  grid-template-columns: 100px 1fr auto;
  gap: 6px;
  align-items: center;
}
.profile-link-row input {
  background: #0e0e0e; border: 1px solid #333; border-radius: 4px;
  color: #fff; font: 400 12px/1 "Inter", sans-serif;
  padding: 7px 9px; outline: none;
}
.profile-link-row input:focus { border-color: #ff6a4a; }
.profile-link-row .link-remove {
  background: none; border: none; color: #888; cursor: pointer;
  padding: 4px 8px; font-size: 16px;
}
.profile-link-row .link-remove:hover { color: #ff5040; }
.profile-divider {
  border: none; border-top: 1px solid #2a2a2a; margin: 26px 0 18px;
}
.profile-section-h2 { margin-top: 0 !important; }

/* Admin table */
.admin-table {
  width: 100%; border-collapse: collapse; margin-top: 8px;
  font: 400 12px/1.4 "Inter", sans-serif; color: #ccc;
}
.admin-table th, .admin-table td {
  text-align: left; padding: 8px 10px; border-bottom: 1px solid #2a2a2a;
}
.admin-table th { color: #ff6a4a; font-weight: 700; font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; }
.admin-table td.center { text-align: center; }
.admin-table .badge { padding: 2px 8px; border-radius: 10px; font-size: 10px; font-weight: 700; letter-spacing: 0.05em; }
.admin-table .badge-ok    { background: rgba(95,204,95,0.15); color: #5fcc5f; }
.admin-table .badge-no    { background: rgba(255,80,64,0.15); color: #ff5040; }
.admin-table .badge-admin { background: rgba(255,106,74,0.15); color: #ff8a6a; }
.admin-table .row-actions button {
  background: none; border: none; color: #888; cursor: pointer;
  padding: 2px 6px; font-size: 11px;
}
.admin-table .row-actions button:hover { color: #ff8a6a; }
.admin-table .row-actions .danger:hover { color: #ff5040; }

/* About modal — support section */
.about-support {
  margin-top: 22px;
  padding-top: 16px;
  border-top: 1px solid #2a2a2a;
  text-align: center;
}
.about-support-title {
  font: 700 10px/1 "Inter", sans-serif;
  letter-spacing: 0.25em;
  color: #ff6a4a;
  margin: 0 0 10px;
  text-align: left;
}
.about-support .modal-foot { text-align: left; }
.about-donate-btn {
  display: inline-block;
  margin: 22px auto 0;
  transition: transform 0.15s ease;
}
.about-donate-btn:hover { transform: translateY(-1px); }
.about-donate-btn img {
  display: block;
  height: 28px;
  width: auto;
  border-radius: 4px;
}

/* Save dialog "Make public" checkbox */
.checkbox-label {
  flex-direction: row !important;
  align-items: center;
  gap: 8px !important;
  font-size: 12px !important;
  color: #ccc !important;
  letter-spacing: 0 !important;
  cursor: pointer;
}
.checkbox-label input[type=checkbox] {
  width: 16px; height: 16px; accent-color: #ff3210;
}

/* Shared-pattern info card (replaces the old share-banner). Centred
   via auto margins instead of transform-50% — robust against the
   width-not-yet-computed race that put the card far to the right. */
.share-info {
  position: fixed;
  bottom: 130px;
  left: 0;
  right: 0;
  margin: 0 auto;
  width: max-content;
  max-width: calc(100vw - 32px);
  background: rgba(15,15,15,0.95);
  border: 1px solid rgba(255,106,74,0.4);
  border-radius: 12px;
  padding: 12px 36px 12px 14px;
  z-index: 65;
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 12px;
  align-items: center;
  box-shadow: 0 6px 24px rgba(0,0,0,0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.share-info[hidden] { display: none; }
.share-info-avatar {
  width: 44px; height: 44px; border-radius: 50%; object-fit: cover;
  border: 1px solid #333;
}
.share-info-name {
  font: 700 13px/1.2 "Inter", sans-serif; color: #fff;
}
.share-info-author {
  font: 400 11px/1.3 "Inter", sans-serif; color: #ff8a6a;
  margin-top: 2px;
}
.share-info-stats {
  font: 500 10px/1 "Inter", sans-serif; color: #888;
  margin-top: 4px;
}
.share-info-stars {
  display: flex; gap: 1px; margin-top: 4px;
}
.share-info-stars button {
  background: none; border: none; cursor: pointer;
  font-size: 16px; line-height: 1; color: #555;
  padding: 0 1px;
  transition: color 0.1s;
}
.share-info-stars button.on { color: #ff8a4a; }
.share-info-stars button.hov { color: #ffb070; }
.share-info-close {
  position: absolute; top: 6px; right: 8px;
  background: none; border: none; color: #888;
  font-size: 18px; cursor: pointer; line-height: 1;
}
.share-info-close:hover { color: #fff; }

/* Footer (I/O Music logo + fan-project disclaimer) — matches sptfy.se.
   Flex row, centred as a group, logo on the left of the text block.
   Text is left-aligned next to the logo so the three lines stack
   neatly against the logo's vertical centre. */
.footer {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 0.6rem 1rem 0.7rem;
  z-index: 60;
}
.footer p {
  font-size: 11px;             /* matches sptfy.se rendered size, no rem ambiguity */
  font-weight: 400;
  color: #6a6a6a;
  line-height: 1.6;
  letter-spacing: 0;
  text-align: left;
  margin: 0;
}
.footer a {
  color: #ff6a4a;
  text-decoration: none;
}
.footer a:hover { text-decoration: underline; }
.footer-heart { color: #ff3a14; }
.footer-logo {
  flex: none;
  display: flex;
  align-items: center;
}
.footer-logo a {
  display: inline-block;
  opacity: 0.65;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.footer-logo a:hover {
  opacity: 1;
  transform: translateY(-1px);
}
.footer-logo img {
  display: block;
  border-radius: 4px;
}

/* The shortened credit line is hidden on desktop and only used on
   compact mobile / landscape mobile where the 3-line credit + logo
   stack would otherwise overlap the device. */
.footer-text-short { display: none; }

/* Compact mobile footer: short landscape (any phone, even iPhone Pro
   Max which is 932px wide in landscape — width-based queries miss it),
   plus narrow portrait. */
@media (max-height: 500px) and (orientation: landscape),
       (max-width: 540px) {
  .footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 12px;
    gap: 12px;
    text-align: left;
  }
  .footer-text-full { display: none; }
  .footer-text-short {
    display: block;
    flex: 1;
    text-align: center;
    margin: 0;
    font-size: 10px;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: #6a6a6a;
  }
  .footer-logo {
    margin: 0;
    flex: none;
    /* Logo is already first in source order (see _panel.html) so the
       mobile flex row puts it on the left without an explicit order. */
  }
  .footer-logo img { width: 26px; height: 26px; }
  .version-badge {
    position: static;     /* part of the flex row, not absolute */
    flex: none;
    font-size: 8.5px;
    padding: 2px 6px;
  }
  /* Compact footer = ~36px tall, so the canvas can claim more room. */
  #tb303-canvas { height: calc(100vh - 92px); }
}

/* Tighter padding / font for the centered welcome card on small
   landscape phones so all the text fits without scrolling. */
@media (max-height: 500px) and (orientation: landscape) {
  .welcome-overlay { padding: 10px; }
  .welcome-card {
    padding: 12px 16px 10px;
    font-size: 11px;
    line-height: 1.4;
  }
  .welcome-title  { font-size: 12px; margin-bottom: 6px; }
  .welcome-text   { font-size: 11px;  margin-bottom: 6px; }
  .welcome-donate { margin: 4px 0 6px; }
  .welcome-donate img { height: 22px; }
  .welcome-dontshow { font-size: 10px; }
}

/* =============================================================
   GDPR cookie banner — sits just above the footer, dismissed
   once the user picks Accept or Reject. Equal-prominence buttons
   so neither choice is dark-pattern-forced.
   ============================================================= */
.cookie-banner {
  position: fixed;
  bottom: 124px;
  left: 14px;
  right: 14px;
  z-index: 95;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: rgba(20, 22, 26, 0.94);
  -webkit-backdrop-filter: blur(12px);
          backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 8px;
  padding: 12px 16px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
}
.cookie-banner[hidden] { display: none; }
.cookie-banner-text {
  margin: 0;
  font-size: 12px;
  line-height: 1.5;
  color: #cfcfcf;
  flex: 1;
}
.cookie-banner-text strong { color: #fff; }
.cookie-banner-actions { display: flex; gap: 8px; flex: none; }
.cookie-btn {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: transparent;
  color: #ddd;
  font: 600 11px/1 inherit;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 8px 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.cookie-btn:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}
.cookie-btn-secondary {
  color: #999;
  border-color: rgba(255, 255, 255, 0.10);
}
@media (max-width: 640px) {
  .cookie-banner {
    bottom: 132px;
    left: 8px;
    right: 8px;
    flex-direction: column;
    align-items: stretch;
    padding: 10px 12px;
    gap: 10px;
  }
  .cookie-banner-actions { justify-content: flex-end; }
  .cookie-banner-text { font-size: 11.5px; }
}
@media (max-height: 500px) and (orientation: landscape) {
  /* Compact landscape phones — nudge it lower since the footer is
     compact in this mode. */
  .cookie-banner { bottom: 50px; }
}

/* =============================================================
   First-visit welcome card — centered modal with soft backdrop.
   Shows the site backstory + email + donate. Suppressed via
   "Don't show again" checkbox (saves a flag in localStorage).
   Backdrop click also closes (just like a regular modal).
   ============================================================= */
.welcome-overlay {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.55);
  -webkit-backdrop-filter: blur(4px);
          backdrop-filter: blur(4px);
}
.welcome-overlay[hidden] { display: none; }

/* First-visit mobile notice — sits one z-layer above the welcome
   overlay so it lands on top, dismiss-once via localStorage. Visible
   only when the JS deems the visitor mobile (set via .show class). */
.mobile-notice {
  position: fixed;
  inset: 0;
  z-index: 95;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.78);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}
.mobile-notice[hidden] { display: none; }
.mobile-notice-card {
  max-width: 360px;
  width: 100%;
  padding: 22px 24px 20px;
  background: linear-gradient(180deg, #1a1a1c 0%, #0e0e10 100%);
  border: 1px solid rgba(255, 138, 74, 0.45);
  border-radius: 8px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6),
              0 0 24px rgba(255, 138, 74, 0.15);
  color: #cce;
  font: 600 13px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.02em;
  text-align: left;
}
.mobile-notice-title {
  margin: 0 0 10px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #ffd0a8;
}
.mobile-notice-text {
  margin: 0 0 16px;
  color: #aab;
  font-weight: 400;
}
.mobile-notice-text strong {
  color: #ffe18a;
  font-weight: 600;
}
.mobile-notice-ok {
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  background: rgba(255, 138, 74, 0.22);
  border: 1px solid rgba(255, 138, 74, 0.65);
  color: #ffd0a8;
  font: 700 12px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 12px 16px;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}
.mobile-notice-ok:hover,
.mobile-notice-ok:active {
  background: rgba(255, 138, 74, 0.36);
  color: #fff;
}

.welcome-card {
  position: relative;
  width: 380px;
  max-width: 100%;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  background: rgba(20, 22, 26, 0.96);
  border: 1px solid rgba(255, 106, 74, 0.30);
  border-radius: 8px;
  padding: 18px 20px 14px;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.65);
  color: #ddd;
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 12px;
  line-height: 1.5;
}
.welcome-close {
  position: absolute;
  top: 4px;
  right: 8px;
  background: none;
  border: none;
  color: #888;
  font-size: 22px;
  cursor: pointer;
  line-height: 1;
  padding: 4px 8px;
  transition: color 0.12s;
}
.welcome-close:hover { color: #fff; }
.welcome-title {
  margin: 0 26px 4px 0;
  font-size: 13px;
  font-weight: 700;
  color: #ff6a4a;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.welcome-tagline {
  margin: 0 0 12px;
  font-size: 14px;
  font-weight: 500;
  color: #ff8a6a;
  font-style: italic;
}
.welcome-text {
  margin: 0 0 8px;
  color: #c0c0c0;
}
.welcome-text strong { color: #fff; }
.welcome-text a {
  color: #ff8a6a;
  text-decoration: none;
}
.welcome-text a:hover { text-decoration: underline; }
.welcome-donate {
  display: block;
  text-align: center;
  margin: 8px 0 12px;
}
.welcome-donate img {
  display: inline-block;
  height: 28px;
  opacity: 0.95;
  transition: opacity 0.15s, transform 0.06s;
}
.welcome-donate:hover img { opacity: 1; transform: translateY(-1px); }
.welcome-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 4px;
}
.welcome-dontshow {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: #888;
  cursor: pointer;
  user-select: none;
}
.welcome-dontshow input { accent-color: #ff6a4a; }
.welcome-dontshow:hover { color: #b8b8b8; }
.welcome-byline {
  font-size: 11px;
  color: #888;
  text-decoration: none;
  letter-spacing: 0.04em;
  transition: color 0.12s ease;
}
.welcome-byline:hover { color: #ff8a4a; }
/* Centered overlay layout already handles mobile via max-height /
   max-width; no extra responsive rules needed. */

/* =============================================================
   Version badge — bottom-right corner of the footer.
   Signals the project is still being polished pre-release.
   ============================================================= */
.version-badge {
  position: absolute;
  right: 14px;
  bottom: 12px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: #ff6a4a;
  background: rgba(255, 50, 16, 0.10);
  border: 1px solid rgba(255, 106, 74, 0.32);
  padding: 3px 8px;
  border-radius: 3px;
  text-transform: uppercase;
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
}
@media (max-width: 640px) {
  .version-badge {
    right: 10px;
    bottom: 8px;
    font-size: 9px;
    padding: 2px 6px;
  }
}

/* =============================================================
   Bug-report button — small bug icon parked left of the version
   badge. Click pops up a modal form (built dynamically in app.js).
   ============================================================= */
.bug-report-btn {
  position: absolute;
  /* The version badge is anchored at right:14 and ~100 px wide
     with its padding + letter-spacing, so this needs to clear
     ~114 px to sit cleanly to the left of it with a small gap. */
  right: 120px;
  bottom: 11px;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 50, 16, 0.10);
  border: 1px solid rgba(255, 106, 74, 0.32);
  border-radius: 3px;
  color: #ff6a4a;
  cursor: pointer;
  padding: 0;
  transition: background .12s, color .12s, transform .12s;
}
.bug-report-btn:hover {
  background: rgba(255, 50, 16, 0.22);
  color: #fff;
  transform: translateY(-1px);
}
.bug-report-btn svg { display: block; }
@media (max-width: 640px) {
  /* Same math at the mobile breakpoint — version-badge is at
     right:10 and a touch narrower than desktop. */
  .bug-report-btn { right: 105px; bottom: 7px; width: 20px; height: 20px; }
  .bug-report-btn svg { width: 12px; height: 12px; }
}

/* Bug-report modal — dark themed, centred overlay, simple form. */
.bug-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.bug-modal {
  width: 100%;
  max-width: 440px;
  background: #181818;
  border: 1px solid #333;
  border-radius: 8px;
  padding: 22px;
  color: #eee;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.bug-modal h2 {
  margin: 0 0 4px 0;
  color: #ff6a4a;
  font-size: 14px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.bug-modal-intro {
  margin: 0 0 16px 0;
  color: #888;
  font-size: 12px;
  line-height: 1.5;
}
.bug-modal-label {
  display: block;
  margin-top: 10px;
  font-size: 11px;
  color: #aaa;
  letter-spacing: 0.5px;
}
.bug-modal-input,
.bug-modal-textarea {
  display: block;
  width: 100%;
  margin-top: 4px;
  background: #0f0f0f;
  color: #fff;
  border: 1px solid #2a2a2a;
  border-radius: 4px;
  padding: 9px 11px;
  font: 13px/1.4 inherit;
  box-sizing: border-box;
}
.bug-modal-input:focus,
.bug-modal-textarea:focus {
  outline: none;
  border-color: #ff6a4a;
  box-shadow: 0 0 0 1px rgba(255, 106, 74, 0.30);
}
.bug-modal-textarea {
  min-height: 100px;
  resize: vertical;
  font-family: inherit;
}
.bug-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 18px;
}
.bug-modal-btn {
  background: #ff6a4a;
  color: #0a0a0a;
  border: 1px solid #ff6a4a;
  padding: 8px 16px;
  border-radius: 4px;
  font: 600 13px/1 inherit;
  cursor: pointer;
}
.bug-modal-btn:hover { background: #ff8a6a; }
.bug-modal-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.bug-modal-btn-ghost {
  background: transparent;
  color: #888;
  border-color: #333;
}
.bug-modal-btn-ghost:hover { color: #fff; border-color: #555; }
.bug-modal-status {
  margin-top: 10px;
  font-size: 12px;
  min-height: 16px;
}
.bug-modal-status.ok    { color: #6ab26a; }
.bug-modal-status.error { color: #ff6a4a; }

/* Device-action SAVE / LOAD / SHARE buttons live in the top-nav now. */

/* =============================================================
   Filter preference — chromed two-position toggle inside the
   Profile & Settings modal. Lets the user pick which TB-303 filter
   emulation to use (biquad cascade vs AudioWorklet diode ladder).
   ============================================================= */
.filter-pref {
  display: inline-flex;
  gap: 1px;
  background: linear-gradient(180deg, #1a1a1c 0%, #2a2a2c 100%);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 4px;
  padding: 2px;
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.55);
  margin: 6px 0 8px;
  user-select: none;
}
.filter-pref-pos {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid transparent;
  background: transparent;
  color: #888;
  font: 700 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.08em;
  padding: 6px 14px;
  min-width: 88px;
  border-radius: 3px;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, box-shadow 0.12s ease;
}
.filter-pref-pos:hover  { color: #ddd; }
.filter-pref-pos.on {
  background: linear-gradient(180deg, #d4d8df 0%, #98a0a8 100%);
  color: #1a1a1c;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.55) inset,
    0 -1px 0 rgba(0, 0, 0, 0.25) inset,
    0 1px 4px rgba(0, 0, 0, 0.45);
}

/* =============================================================
   CRT-style overlay — phosphor green on black, monospace, faint
   scanlines. Used for save / load / share / auth-prompt dialogs.
   Mid-80s computer terminal aesthetic.
   ============================================================= */
.crt-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.78);
  -webkit-backdrop-filter: blur(2px);
          backdrop-filter: blur(2px);
  font-family: "VT323", "Courier New", "Lucida Console", monospace;
  padding: 16px;
}
.crt-window {
  position: relative;
  background: #000;
  border: 2px solid #1a4d1a;
  box-shadow:
    0 0 0 1px #0a200a,
    0 0 32px rgba(0, 255, 100, 0.18),
    inset 0 0 80px rgba(0, 255, 100, 0.05);
  color: #00ff66;
  padding: 18px 26px 22px;
  min-width: 340px;
  max-width: 600px;
  width: 100%;
  text-shadow: 0 0 4px rgba(0, 255, 100, 0.45);
  overflow: hidden;
}
/* Scanline overlay */
.crt-window::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 255, 100, 0.03) 0,
    rgba(0, 255, 100, 0.03) 1px,
    transparent 1px,
    transparent 3px
  );
  z-index: 1;
}
.crt-window > * { position: relative; z-index: 2; }

.crt-header {
  font-size: 26px;
  letter-spacing: 0.06em;
  margin-bottom: 14px;
  color: #66ffaa;
  text-shadow: 0 0 8px rgba(0, 255, 100, 0.7);
  text-transform: uppercase;
}
.crt-body {
  font-size: 20px;
  line-height: 1.4;
}
.crt-prompt {
  margin: 4px 0 8px;
}
.crt-prompt::before {
  content: "> ";
  color: #66ffaa;
}
.crt-error {
  color: #ff6060;
  text-shadow: 0 0 6px rgba(255, 60, 60, 0.5);
  margin: 6px 0;
  min-height: 1.2em;
}
.crt-error::before {
  content: "! ";
  color: #ff6060;
}
/* Hide the entire row (including the "!" prefix and reserved
   min-height) when there's no error message — placeholder paragraphs
   shouldn't render a stray red exclamation. */
.crt-error:empty {
  display: none;
  min-height: 0;
  margin: 0;
}
.crt-input {
  display: block;
  width: 100%;
  background: #001000;
  border: 1px solid #2a6a2a;
  color: #00ff66;
  font-family: inherit;
  font-size: 22px;
  letter-spacing: 0.04em;
  padding: 6px 10px;
  margin: 6px 0 10px;
  outline: none;
  text-shadow: 0 0 4px rgba(0, 255, 100, 0.5);
  caret-color: #00ff66;
  text-transform: uppercase;
}
.crt-input:focus {
  border-color: #00ff66;
  box-shadow: 0 0 10px rgba(0, 255, 100, 0.35);
}
.crt-checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 6px 0 10px;
  cursor: pointer;
  user-select: none;
}
.crt-checkbox input {
  appearance: none;
  -webkit-appearance: none;
  width: 18px; height: 18px;
  border: 1px solid #2a6a2a;
  background: #001000;
  cursor: pointer;
  position: relative;
}
.crt-checkbox input:checked {
  border-color: #00ff66;
  box-shadow: 0 0 6px rgba(0, 255, 100, 0.4);
}
.crt-checkbox input:checked::after {
  content: "X";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  color: #00ff66;
  text-shadow: 0 0 4px rgba(0, 255, 100, 0.6);
}
.crt-actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  margin-top: 14px;
  flex-wrap: wrap;
}
.crt-button {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid #00ff66;
  color: #00ff66;
  font-family: inherit;
  font-size: 18px;
  padding: 5px 14px;
  cursor: pointer;
  letter-spacing: 0.06em;
  text-shadow: 0 0 4px rgba(0, 255, 100, 0.4);
  transition: background 0.12s ease, color 0.12s ease;
}
.crt-button:hover {
  background: rgba(0, 255, 100, 0.15);
}
.crt-button:active {
  background: #00ff66;
  color: #000;
  text-shadow: none;
}
.crt-button-danger {
  border-color: #ff6060;
  color: #ff6060;
  text-shadow: 0 0 4px rgba(255, 60, 60, 0.5);
}
.crt-button-danger:hover { background: rgba(255, 60, 60, 0.15); }
.crt-button-danger:active { background: #ff6060; color: #000; text-shadow: none; }

/* CLEAR-scope chooser. Each option is a tall full-width button with
   a bold title and a wrapping description below it — title and desc
   are spans, not separate elements, so the whole row is a single
   click target. */
.clear-choices {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.clear-choice {
  appearance: none;
  -webkit-appearance: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  text-align: left;
  width: 100%;
  background: transparent;
  border: 1px solid #00ff66;
  color: #00ff66;
  font-family: inherit;
  padding: 10px 14px;
  cursor: pointer;
  letter-spacing: 0.04em;
  text-shadow: 0 0 4px rgba(0, 255, 100, 0.35);
  transition: background 0.12s ease, color 0.12s ease;
}
.clear-choice-title {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.08em;
}
.clear-choice-desc {
  font-size: 12px;
  line-height: 1.35;
  color: #9aa;
  text-shadow: none;
  font-weight: 400;
  letter-spacing: 0.02em;
}
.clear-choice-desc strong { color: #cce0cc; }
.clear-choice:hover { background: rgba(0, 255, 100, 0.10); }
.clear-choice:hover .clear-choice-desc { color: #b8d0b8; }
.clear-choice:active { background: #00ff66; color: #000; text-shadow: none; }
.clear-choice:active .clear-choice-desc { color: rgba(0,0,0,0.65); }
.clear-choice:active .clear-choice-desc strong { color: #000; }
.clear-choice-danger {
  border-color: #ff6060;
  color: #ff6060;
  text-shadow: 0 0 4px rgba(255, 60, 60, 0.45);
}
.clear-choice-danger:hover { background: rgba(255, 60, 60, 0.12); }
.clear-choice-danger:active { background: #ff6060; color: #000; text-shadow: none; }
.clear-choice-danger:active .clear-choice-desc { color: rgba(0,0,0,0.65); }

.crt-list {
  max-height: 320px;
  overflow-y: auto;
  border: 1px solid #1a4d1a;
  margin: 8px 0 4px;
  padding: 2px 0;
  background: #001000;
}
.crt-list::-webkit-scrollbar { width: 10px; }
.crt-list::-webkit-scrollbar-track { background: #001000; }
.crt-list::-webkit-scrollbar-thumb {
  background: #1a4d1a;
  border: 1px solid #2a6a2a;
}
.crt-list::-webkit-scrollbar-thumb:hover { background: #2a6a2a; }
.crt-list-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px;
  border-bottom: 1px solid #0a2a0a;
}
.crt-list-row:last-child { border-bottom: none; }
.crt-list-row:hover { background: rgba(0, 255, 100, 0.06); }

/* MIDI device rows — entire row is clickable, active state inverts
   the colours so the selection reads at a glance (green fill, dark
   green text instead of green text on dark). Selected MIDI inputs
   get bound to the live message handler in JS. */
.midi-row {
  cursor: pointer;
  transition: background 0.10s ease, color 0.10s ease;
}
.midi-row .midi-row-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  line-height: 1.2;
}
.midi-row .midi-row-name { color: #00ff66; }
.midi-row .midi-row-sub  { color: #4a8a4a; font-size: 80%; }
.midi-row.on {
  background: #00ff66;
}
.midi-row.on .midi-row-name,
.midi-row.on .midi-row-sub {
  color: #001000;
}
.midi-row.on:hover {
  background: #66ffaa;
}

/* Clock sync rows — toggle for receive, dropdown for send. Sits below
   the input picker inside the MIDI CRT. Compact green-on-dark look
   that matches the existing .crt-button styling but without the
   bordered button chrome (these are inline form controls). */
.midi-clock-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 4px;
}
.midi-clock-row .midi-clock-toggle,
.midi-clock-row .midi-clock-out {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #00ff66;
  cursor: pointer;
  font-size: 13px;
}
.midi-clock-row input[type="checkbox"] {
  appearance: auto;   /* keep native checkbox — fast to scan */
  cursor: pointer;
  accent-color: #00ff66;
}
.midi-clock-row select {
  appearance: none;
  -webkit-appearance: none;
  background: #001000;
  color: #00ff66;
  border: 1px solid #2a6a2a;
  padding: 3px 22px 3px 8px;
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, #00ff66 50%),
                    linear-gradient(135deg, #00ff66 50%, transparent 50%);
  background-position: calc(100% - 12px) calc(50% - 2px),
                       calc(100% - 7px)  calc(50% - 2px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.midi-clock-row select:hover { filter: brightness(1.15); }
.midi-clock-row select option { background: #06120a; color: #00ff66; }
.crt-list-name {
  flex: 1;
  background: transparent;
  border: none;
  color: #00ff66;
  font-family: inherit;
  font-size: 20px;
  text-align: left;
  cursor: pointer;
  padding: 4px 0;
  text-shadow: inherit;
  letter-spacing: 0.04em;
}
.crt-list-name:hover {
  color: #66ffaa;
  text-shadow: 0 0 8px rgba(0, 255, 100, 0.6);
}
.crt-list-meta {
  color: #4a8a4a;
  font-size: 16px;
  margin-left: 8px;
}
/* Clickable [pub]/[priv] toggle on each saved-pattern row in LOAD. */
.crt-list-flag {
  background: transparent;
  border: 1px dashed #2a6a2a;
  color: #4a8a4a;
  font-family: inherit;
  font-size: 14px;
  padding: 1px 7px;
  cursor: pointer;
  letter-spacing: 0.04em;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.crt-list-flag:hover {
  color: #66ffaa;
  border-color: #66ffaa;
  background: rgba(0, 255, 100, 0.08);
}
.crt-list-flag.on {
  border-style: solid;
  border-color: #00ff66;
  color: #66ffaa;
  text-shadow: 0 0 4px rgba(0, 255, 100, 0.4);
}
.crt-list-flag.on:hover {
  background: rgba(0, 255, 100, 0.15);
}
/* Inline [↗] share button on each LOAD-list row — same chrome as the
   green CRT theme, sits between the [pub]/[priv] flag and the [X]
   delete so the visual hierarchy reads name → state → action. */
.crt-list-share {
  background: transparent;
  border: 1px solid #2a6a2a;
  color: #4a8a4a;
  font-family: inherit;
  font-size: 14px;
  padding: 2px 8px;
  cursor: pointer;
  letter-spacing: 0.06em;
  margin-right: 4px;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.crt-list-share:hover {
  background: rgba(0, 255, 100, 0.15);
  border-color: #00ff66;
  color: #66ffaa;
  text-shadow: 0 0 4px rgba(0, 255, 100, 0.4);
}
.crt-list-del {
  background: transparent;
  border: 1px solid #663030;
  color: #ff6060;
  font-family: inherit;
  font-size: 14px;
  padding: 2px 8px;
  cursor: pointer;
  letter-spacing: 0.06em;
}
.crt-list-del:hover {
  background: #ff6060;
  color: #000;
}
.crt-empty {
  text-align: center;
  color: #4a8a4a;
  padding: 18px 0;
  font-size: 18px;
}
@media (max-width: 640px) {
  .crt-window { padding: 14px 18px 16px; min-width: 0; }
  .crt-header { font-size: 22px; }
  .crt-body, .crt-input, .crt-list-name { font-size: 18px; }
  .crt-button { font-size: 16px; padding: 4px 10px; }
}

/* =====================================================================
   TRACKS chain editor — same chrome as #step-prog-panel so
   _layoutStackedPanels can swap them in / out interchangeably. Only
   the body content differs: a horizontal strip of chain cells instead
   of a 16-column step grid.
   ===================================================================== */
#tracks-panel {
  position: fixed;
  z-index: 80;
  display: flex;
  flex-direction: column;
  padding: 6px 8px 8px;
  background: rgba(8, 18, 10, 0.94);
  border: 1px solid #2a6a2a;
  border-radius: 4px;
  box-shadow: 0 -8px 28px rgba(0, 60, 30, 0.30);
  color: #00ff66;
  font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.10em;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  /* Slide between centre / upper-half / lower-half slots when the
     panel stack reshuffles. */
  transition: top 220ms ease-out, height 220ms ease-out;
}
#tracks-panel .tracks-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
  flex: 0 0 auto;
}
#tracks-panel .tracks-title {
  color: #ff8a4a;
  letter-spacing: 0.20em;
}
#tracks-panel .tracks-track-sel {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #00ff66;
  letter-spacing: 0.14em;
}
#tracks-panel .tracks-track-select {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid #2a6a2a;
  color: #00ff66;
  padding: 3px 22px 3px 8px;
  border-radius: 3px;
  font: inherit;
  letter-spacing: 0.14em;
  cursor: pointer;
  background-image:
    linear-gradient(45deg, transparent 50%, #00ff66 50%),
    linear-gradient(135deg, #00ff66 50%, transparent 50%);
  background-position: calc(100% - 12px) 50%, calc(100% - 7px) 50%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
}
#tracks-panel .tracks-track-select option {
  background: #06120a;
  color: #00ff66;
}
#tracks-panel .tracks-len {
  color: #4a8a4a;
  font-size: 10px;
  letter-spacing: 0.10em;
}
#tracks-panel .tracks-spacer { flex: 1 1 0; }
#tracks-panel .tracks-add,
#tracks-panel .tracks-pick,
#tracks-panel .tracks-clear,
#tracks-panel .tracks-help,
#tracks-panel .tracks-done {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid #2a6a2a;
  color: #00ff66;
  padding: 4px 10px;
  border-radius: 3px;
  cursor: pointer;
  font: inherit;
  letter-spacing: 0.14em;
}
#tracks-panel .tracks-help { padding: 4px 8px; }
#tracks-panel .tracks-add {
  background: rgba(0, 255, 102, 0.10);
  border-color: rgba(0, 255, 102, 0.55);
}
#tracks-panel .tracks-done {
  background: rgba(255, 50, 16, 0.18);
  border-color: rgba(255, 106, 74, 0.55);
  color: #ffb88a;
}
#tracks-panel .tracks-add:hover,
#tracks-panel .tracks-pick:hover,
#tracks-panel .tracks-clear:hover,
#tracks-panel .tracks-help:hover,
#tracks-panel .tracks-done:hover { filter: brightness(1.15); }

#tracks-panel .tracks-chain {
  flex: 1 1 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-content: flex-start;
  background: #001000;
  border: 1px solid #1a4d1a;
  border-radius: 2px;
  padding: 8px;
  overflow: auto;
}
#tracks-panel .tracks-empty {
  color: #4a8a4a;
  font-weight: 400;
  letter-spacing: 0.04em;
  line-height: 1.5;
  font-size: 12px;
  padding: 12px 6px;
  max-width: 720px;
}
#tracks-panel .tracks-empty strong {
  color: #00ff66;
  letter-spacing: 0.10em;
}
#tracks-panel .tracks-cell {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 10px 4px;
  background: rgba(0, 255, 102, 0.06);
  border: 1px solid rgba(0, 255, 102, 0.30);
  border-radius: 4px;
  min-width: 64px;
}
#tracks-panel .tracks-cell.active {
  background: rgba(255, 138, 74, 0.20);
  border-color: rgba(255, 138, 74, 0.65);
}
/* Chain playhead — the cell whose pattern is currently being scheduled
   in TRACK_PLAY mode. Bright red glow + soft pulse so it's clearly
   distinct from the steady orange "device is parked here" .active hue.
   Cells can be both .active and .playing — .playing wins visually. */
#tracks-panel .tracks-cell.playing {
  background: rgba(255, 50, 16, 0.32);
  border-color: rgba(255, 90, 50, 0.95);
  box-shadow: 0 0 12px rgba(255, 90, 50, 0.55);
  animation: tracks-cell-pulse 1.1s ease-in-out infinite;
}
@keyframes tracks-cell-pulse {
  0%, 100% { filter: brightness(1.00); }
  50%      { filter: brightness(1.28); }
}
#tracks-panel .tracks-cell-num {
  font-size: 9px;
  color: #4a8a4a;
  letter-spacing: 0.10em;
}
#tracks-panel .tracks-cell.active  .tracks-cell-num { color: #ffd0a8; }
#tracks-panel .tracks-cell.playing .tracks-cell-num { color: #ffb09a; }
#tracks-panel .tracks-cell-slot {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 0;
  color: #00ff66;
  font: inherit;
  cursor: pointer;
  letter-spacing: 0.10em;
  padding: 0;
}
#tracks-panel .tracks-cell.active  .tracks-cell-slot { color: #ffe18a; }
#tracks-panel .tracks-cell.playing .tracks-cell-slot { color: #fff; text-shadow: 0 0 6px rgba(255, 90, 50, 0.85); }
#tracks-panel .tracks-cell-x {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 14px;
  height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  appearance: none;
  -webkit-appearance: none;
  background: rgba(255, 50, 16, 0.55);
  border: 0;
  color: #fff;
  font: 700 11px/1 sans-serif;
  border-radius: 50%;
  cursor: pointer;
  opacity: 0.65;
  padding: 0;
}
#tracks-panel .tracks-cell-x:hover { opacity: 1; }

/* Pattern picker grid — used inside the CRT modal by both the TRACKS
   chain editor (pick a slot to enchain) and the STEPS panel COPY
   action (pick a destination slot to duplicate to). */
.patt-picker-grid {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 4px 0 8px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.patt-picker-row {
  display: grid;
  grid-template-columns: 60px repeat(8, 1fr);
  gap: 4px;
  align-items: center;
}
.patt-picker-rowlbl,
.patt-picker-col {
  font-size: 10px;
  color: #4a8a4a;
  letter-spacing: 0.10em;
  text-align: center;
}
.patt-picker-rowlbl { text-align: right; padding-right: 6px; color: #ff8a4a; font-weight: 700; }
.patt-picker-cell {
  appearance: none;
  -webkit-appearance: none;
  height: 30px;
  border: 1px solid rgba(0, 255, 102, 0.20);
  border-radius: 3px;
  cursor: pointer;
  transition: filter 0.10s ease;
}
.patt-picker-cell.has   { background: rgba(0, 255, 102, 0.18); border-color: rgba(0, 255, 102, 0.55); }
.patt-picker-cell.empty { background: rgba(0, 255, 102, 0.04); }
.patt-picker-cell.active {
  background: rgba(255, 138, 74, 0.30);
  border-color: rgba(255, 138, 74, 0.85);
  box-shadow: 0 0 0 1px rgba(255, 138, 74, 0.50);
}
.patt-picker-cell:hover { filter: brightness(1.20); }
.patt-picker-cell:disabled { cursor: not-allowed; opacity: 0.35; }

/* =====================================================================
   Community Hub — v0.96. Replaces the old plain feed modal with a
   tabbed pattern browser. Lives inside the existing .crt overlay so
   we don't introduce a new layer system; just nicer content.
   ===================================================================== */
.community-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 12px;
  border-bottom: 1px solid #2a2a2a;
  padding-bottom: 6px;
}
.community-tab {
  background: transparent;
  border: 1px solid transparent;
  color: #888;
  padding: 6px 14px;
  font: 600 11px/1 ui-monospace, monospace;
  letter-spacing: 1px;
  cursor: pointer;
  border-radius: 3px 3px 0 0;
  transition: color .12s, background .12s, border-color .12s;
}
.community-tab:hover { color: #fff; }
.community-tab.active {
  color: #ff6a4a;
  border-color: #ff6a4a;
  background: rgba(255, 106, 74, 0.08);
}

.community-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 8px;
  max-height: 60vh;
  overflow-y: auto;
  padding-right: 4px;
}
.community-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: rgba(255, 106, 74, 0.06);
  border: 1px solid rgba(255, 106, 74, 0.20);
  border-radius: 4px;
  text-align: left;
  color: inherit;
  cursor: pointer;
  font: inherit;
  transition: background .12s, border-color .12s, transform .12s;
}
.community-card:hover {
  background: rgba(255, 106, 74, 0.15);
  border-color: #ff6a4a;
  transform: translateY(-1px);
}
.community-card-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid #333;
  object-fit: cover;
  flex-shrink: 0;
  background: #1a1a1a;
}
.community-card-main {
  flex: 1;
  min-width: 0;
  overflow: hidden;
}
.community-card-name {
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 13px;
}
.community-card-author {
  color: #888;
  font-size: 11px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.community-card-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  margin-top: 3px;
  color: #aaa;
}
.community-card-stars { letter-spacing: 1px; line-height: 1; }
.community-card-stars .star-filled { color: #ffb04a; }
.community-card-stars .star-empty  { color: #3a3a3a; }
.community-card-rating  { color: #ccc;  font-variant-numeric: tabular-nums; }
.community-card-listens { color: #888;  font-variant-numeric: tabular-nums; }

/* Empty / loading states live inside the existing CRT body, just
   make them centred and a bit larger. */
.crt-body .community-empty,
.crt-body .community-loading {
  text-align: center;
  padding: 24px 0;
  color: #888;
}

/* Trending-tab placeholder note — small ribbon below the tab bar
   that goes away once /api/feed.php grows a real trending query. */
.community-note {
  font-size: 11px;
  color: #888;
  margin: -6px 0 8px 0;
  padding: 4px 8px;
  background: rgba(255, 176, 74, 0.06);
  border: 1px dashed rgba(255, 176, 74, 0.30);
  border-radius: 3px;
}
