:root {
  --bg: #06060f;
  --surf: #0c0c1c;
  --surf2: #111127;
  --surf3: #161630;
  --brd: #1c1c38;
  --brd2: #252548;
  --text: #e2e2f4;
  --muted: #525278;
  --muted2: #3a3a60;
  --accent: #5b9cf6;
  --accent2: #a78bfa;
  --green: #4ade80;
  --red: #f87171;
  --amber: #fbbf24;
  --pink: #f472b6;
  --fn: 'Syne', sans-serif;
  --fm: 'JetBrains Mono', monospace;

  /* ── Material Design 3 tokens ──────────────────────────────────────
     Shape scale (M3 §Shape: xs/sm/md/lg/xl + full/pill) and elevation
     (M3 §Elevation: 5 levels, expressed as layered shadows since dark
     surfaces here already carry M3's "tonal elevation" via --surf/-2/-3
     rather than a lighter overlay). State layers are the hover/focus/
     press opacity washes M3 asks every interactive surface to show,
     derived from --accent so they automatically follow whatever a skin
     sets --accent to instead of being hardcoded. None of this is a
     color/shape a skin can't already see or override — skins.js's own
     border-radius knob still lands on top of whatever's set here. */
  --sh-xs: 4px;
  --sh-sm: 8px;
  --sh-md: 12px;
  --sh-lg: 16px;
  --sh-xl: 28px;
  --sh-full: 32px;
  --ev1: 0 1px 2px rgba(0,0,0,.3), 0 1px 3px 1px rgba(0,0,0,.15);
  --ev2: 0 1px 2px rgba(0,0,0,.3), 0 2px 6px 2px rgba(0,0,0,.15);
  --ev3: 0 4px 8px 3px rgba(0,0,0,.15), 0 1px 3px rgba(0,0,0,.3);
  --st-hover: color-mix(in srgb, var(--accent) 8%, transparent);
  --st-focus: color-mix(in srgb, var(--accent) 12%, transparent);
  --st-press: color-mix(in srgb, var(--accent) 12%, transparent);
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  background: var(--bg); color: var(--text);
  font-family: var(--fn); font-size: 14px;
  display: flex; flex-direction: column; height: 100vh;
}
body::after {
  content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 500;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.025'/%3E%3C/svg%3E");
}
::-webkit-scrollbar { width: 5px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--brd2); border-radius: var(--sh-full); }
::-webkit-scrollbar-thumb:hover { background: var(--muted2); }

/* ═══════════════ OVERLAYS (mode select / connect / lobby) ═══════════════ */
.overlay {
  display: none; position: fixed; inset: 0; z-index: 400;
  background: var(--bg); align-items: center; justify-content: center; padding: 20px;
}
.overlay.show { display: flex; }
.overlay-box {
  width: 100%; max-width: 420px; background: var(--surf);
  border: 1px solid var(--brd2); border-radius: var(--sh-lg); box-shadow: var(--ev2);
  padding: 28px 26px;
}
.overlay-box.wide { max-width: 480px; }
.overlay-logo {
  font-size: 20px; font-weight: 800; letter-spacing: .1em;
  color: var(--accent); margin-bottom: 4px;
}
.overlay-sub { font-family: var(--fm); font-size: 12px; color: var(--muted); margin-bottom: 22px; }
.mode-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.mode-card {
  background: var(--surf2); border: 1px solid var(--brd2); border-radius: var(--sh-md); color: var(--text);
  padding: 20px 14px; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; gap: 8px; transition: all .15s;
}
.mode-card:hover { border-color: var(--accent); background: var(--st-hover); }
.mode-icon { font-size: 26px; }
.mode-title { font-weight: 700; font-size: 14px; }
.mode-desc { font-family: var(--fm); font-size: 10px; color: var(--muted); line-height: 1.5; }

.overlay-form { display: flex; flex-direction: column; gap: 6px; }
.overlay-form label {
  font-family: var(--fm); font-size: 10px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
  margin-top: 10px;
}
.overlay-form label:first-child { margin-top: 0; }
.hi {
  background: var(--bg); border: 1px solid var(--brd2); border-radius: var(--sh-xs); color: var(--text);
  font-family: var(--fm); font-size: 12px; padding: 9px 12px; outline: none;
  transition: border-color .2s, box-shadow .2s;
}
.hi:focus { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.hi::placeholder { color: var(--muted); }
.hi.full { width: 100%; }
.hi.mono-lg { font-size: 20px; letter-spacing: .3em; text-align: center; font-weight: 700; }

/* M3 filled button: full (pill) shape, solid primary fill, state layer
   on hover via a slightly dimmed overlay rather than a border change. */
.overlay-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--accent); color: #05050f; border: none; border-radius: var(--sh-full);
  font-family: var(--fn); font-weight: 700; font-size: 13px;
  letter-spacing: .01em; text-transform: uppercase; padding: 12px; box-shadow: var(--ev1);
  cursor: pointer; margin-top: 16px; transition: opacity .2s, box-shadow .2s; width: 100%;
}
.overlay-btn .material-symbols-outlined { font-size: 16px; }
.overlay-btn:hover { opacity: .9; box-shadow: var(--ev2); }
.overlay-btn:active { box-shadow: var(--ev1); }
/* M3 outlined button: transparent fill, 1px outline, no elevation. */
.overlay-btn.ghost {
  background: none; border: 1px solid var(--brd2); color: var(--muted); box-shadow: none; margin-top: 8px;
}
.overlay-btn.ghost:hover { border-color: var(--muted); color: var(--text); background: var(--st-hover); opacity: 1; box-shadow: none; }

.radio-row { display: flex; flex-direction: column; gap: 8px; }
.radio-opt {
  display: flex; align-items: center; gap: 8px; font-size: 13px;
  cursor: pointer; padding: 10px 12px; border: 1px solid var(--brd2); border-radius: var(--sh-sm); transition: border-color .15s, background .15s;
}
.radio-opt:hover { border-color: var(--accent); background: var(--st-hover); }
.radio-opt input { accent-color: var(--accent); }
.radio-sub { font-family: var(--fm); font-size: 10px; color: var(--muted); }

.lobby-tabs { display: flex; gap: 4px; margin-bottom: 16px; border-bottom: 1px solid var(--brd); }
.lobby-tab {
  background: none; border: none; border-bottom: 2px solid transparent; border-radius: var(--sh-xs) var(--sh-xs) 0 0;
  color: var(--muted); font-family: var(--fn); font-weight: 700; font-size: 11px;
  letter-spacing: .08em; text-transform: uppercase; padding: 8px 4px 10px;
  margin-right: 16px; cursor: pointer; transition: color .2s, border-color .2s;
}
.lobby-tab:hover { color: var(--text); }
.lobby-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
.lobby-pane { display: none; flex-direction: column; }
.lobby-pane.on { display: flex; }

.join-code-row { display: flex; flex-direction: column; gap: 0; margin-bottom: 14px; }
.join-code-row .hi { width: 100%; box-sizing: border-box; font-family: var(--fm); letter-spacing: .15em; text-transform: uppercase; }
.join-code-row .overlay-btn { margin-top: 10px; }
.join-code-hint { font-family: var(--fm); font-size: 9px; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 6px; }
.public-list { max-height: 280px; overflow-y: auto; scrollbar-width: thin; display: flex; flex-direction: column; gap: 6px; }
.pl-item {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px;
  background: var(--surf2); border: 1px solid var(--brd2); border-radius: var(--sh-md); cursor: pointer; transition: border-color .15s, background .15s;
}
.pl-item:hover { border-color: var(--accent); background: var(--st-hover); }
.pl-mine { border-color: var(--accent); opacity: .75; }
.pl-name { font-weight: 600; font-size: 13px; flex: 1; }
.pl-count { font-family: var(--fm); font-size: 10px; color: var(--muted); }
.empty.small { padding: 20px; }

/* ═══════════════ APP HEADER ═══════════════ */
.hdr {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 18px; border-bottom: 1px solid var(--brd);
  background: var(--surf); flex-wrap: wrap; flex-shrink: 0; z-index: 10;
}
.logo { gap: 10px; display: flex; font-size: 17px; font-weight: 800; letter-spacing: .18em; text-transform: uppercase; color: var(--accent); flex-shrink: 0; }
.pcm-badge {
  font-family: var(--fm); font-size: 9px; font-weight: 600; letter-spacing: .12em;
  background: color-mix(in srgb, var(--accent) 12%, transparent); border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: var(--sh-full);
  color: var(--accent); padding: 4px 9px; flex-shrink: 0;
}
.hdr-fill { flex: 1; }
/* M3 outlined button — used for header actions (Copy/Disconnect/Leave). */
.hdr-btn {
  background: none; border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--text);
  font-family: var(--fn); font-weight: 700; font-size: 11px;
  letter-spacing: .04em; text-transform: uppercase; padding: 7px 16px;
  cursor: pointer; transition: all .15s; flex-shrink: 0;
}
.hdr-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--st-hover); }
.hdr-btn.ghost { border-color: transparent; padding: 0;}
.hdr-btn.danger:hover { border-color: var(--red); color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); }
#sdot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted2); flex-shrink: 0; }
#sdot.ok { background: var(--green); animation: blink 2.4s ease-in-out infinite; }
#sdot.err { background: var(--red); }
@keyframes blink { 0%,100%{opacity:1} 50%{opacity:.5} }
#stxt { font-family: var(--fm); font-size: 11px; color: var(--muted); white-space: nowrap; }

.lobby-code-badge {
  font-family: var(--fm); font-size: 14px; font-weight: 700; letter-spacing: .25em;
  background: var(--surf2); border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--accent2);
  padding: 5px 12px; flex-shrink: 0;
}
#participants-strip { display: flex; align-items: center; gap: -6px; flex-shrink: 0; }
.pchip {
  width: 26px; height: 26px; border-radius: 50%; background: var(--surf3);
  border: 2px solid var(--surf); display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 700; color: var(--text); margin-left: -8px; position: relative;
}
.pchip:first-child { margin-left: 0; }
.pchip.is-host { border-color: var(--accent); }

#cors-note {
  display: none; align-items: flex-start; gap: 8px;
  background: color-mix(in srgb, var(--amber) 7%, transparent); border: 1px solid color-mix(in srgb, var(--amber) 25%, transparent);
  border-left: 3px solid var(--amber); border-radius: var(--sh-xs); padding: 8px 14px; font-family: var(--fm);
  font-size: 11px; color: var(--amber); flex-shrink: 0; line-height: 1.5;
}
#cors-note.show { display: flex; }
#cors-note .material-symbols-outlined { font-size: 15px; margin-top: 1px; flex-shrink: 0; }

/* ═══════════════ MAIN LAYOUT ═══════════════ */
#main { display: flex; flex: 1; overflow: hidden; }

#left {
  width:480px; flex-shrink: 0; border-right: 1px solid var(--brd);
  display: flex; flex-direction: column; background: var(--surf);
  overflow-y: auto; scrollbar-width: thin;
}
#art-wrap { position: relative; aspect-ratio: 1; background: var(--surf2); overflow: hidden; flex-shrink: 0; }
/* Groups info/progress/ctrls so they can be treated as one block —
   on mobile this whole panel gets overlaid on top of the album art instead
   of stacking below it (see the max-width:1000px query). On desktop it's
   just a plain flex column, identical to the old unwrapped layout. */
#player-panel { display: flex; flex-direction: column; min-width: 0; }
#art-img { width: 100%; height: 100%; object-fit: cover; display: block; opacity: 0; transition: opacity .5s; }
#art-img.vis { opacity: 1; }
#art-empty {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 10px; color: var(--muted2);
}
#art-empty .material-symbols-outlined { font-size: 52px; opacity: .4; }
#art-empty span { font-family: var(--fm); font-size: 10px; letter-spacing: .1em; }
#eq {
  position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 3px; align-items: flex-end; height: 22px; opacity: 0; transition: opacity .3s;
}
#eq.active { opacity: 1; }
.eb { width: 4px; border-radius: var(--sh-full); background: var(--accent); transform-origin: bottom; animation: eq .7s ease-in-out infinite alternate; }
.eb:nth-child(1){height:6px; animation-delay:0s} .eb:nth-child(2){height:13px;animation-delay:.12s}
.eb:nth-child(3){height:20px;animation-delay:.24s} .eb:nth-child(4){height:10px;animation-delay:.06s}
.eb:nth-child(5){height:17px;animation-delay:.18s}
@keyframes eq { from{transform:scaleY(1)} to{transform:scaleY(.25)} }
.eb.paused { animation-play-state: paused; }
#buf-ring {
  display: none; position: absolute; top: 8px; right: 8px; width: 18px; height: 18px;
  border: 2px solid var(--brd2); border-top-color: var(--accent); border-radius: 50%; animation: spin .7s linear infinite;
}
#buf-ring.show { display: block; }
@keyframes spin { to{ transform: rotate(360deg); } }
#pcm-meter { position: absolute; top: 8px; left: 8px; display: flex; flex-direction: column; gap: 2px; opacity: 0; transition: opacity .3s; }
#pcm-meter.active { opacity: 1; }
.pm-bar { width: 3px; background: var(--brd2); border-radius: var(--sh-full); height: 40px; position: relative; overflow: hidden; }
.pm-fill { position: absolute; bottom: 0; left: 0; right: 0; background: var(--green); border-radius: var(--sh-full); height: 0%; transition: height .1s; }

#info { padding: 14px 16px; border-bottom: 1px solid var(--brd); }
#info-src { font-family: var(--fm); font-size: 9px; font-weight: 600; letter-spacing: .2em; text-transform: uppercase; color: var(--accent2); margin-bottom: 5px; display: flex; align-items: center; gap: 6px; }
#lock-badge { background: color-mix(in srgb, var(--red) 12%, transparent); border: 1px solid color-mix(in srgb, var(--red) 30%, transparent); border-radius: var(--sh-full); color: var(--red); font-size: 8px; padding: 2px 7px; display: none; }
#lock-badge.show { display: inline-block; }
#info-title { font-size: 16px; font-weight: 700; line-height: 1.3; margin-bottom: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#info-artist { font-family: var(--fm); font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* M3 slider track: full-round track + thumb, matching the volume/filter
   sliders below so every draggable range in the app reads the same. */
#prog-wrap { padding: 10px 16px 6px; border-bottom: 1px solid var(--brd); }
#prog-bar { position: relative; height: 4px; background: var(--brd2); cursor: pointer; border-radius: var(--sh-full); margin-bottom: 5px; transition: height .15s; }
#prog-bar:hover { height: 7px; }
#prog-bar.locked { cursor: not-allowed; }
#prog-fill { height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent2)); border-radius: var(--sh-full); pointer-events: none; }
#prog-thumb { position: absolute; top: 50%; transform: translate(-50%,-50%); width: 12px; height: 12px; border-radius: 50%; background: var(--text); box-shadow: var(--ev1); opacity: 0; pointer-events: none; transition: opacity .15s; }
#prog-bar:hover #prog-thumb { opacity: 1; }
#prog-times { display: flex; justify-content: space-between; font-family: var(--fm); font-size: 10px; color: var(--muted); }

#ctrls { padding: 12px 16px; border-bottom: 1px solid var(--brd); }
#ctrls-main { display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 10px; }
/* M3 icon button: circular hit area, no fill by default, a tinted state
   layer on hover instead of the old plain border/bg swap. */
.cb {
  background: none; border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--text);
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: background .15s, border-color .15s, transform .1s, box-shadow .15s;
}
.cb:hover { background: var(--st-hover); border-color: var(--accent); }
.cb:active { transform: scale(.93); }
.cb:disabled { opacity: .3; cursor: not-allowed; }
.cb:disabled:hover { background: none; border-color: var(--brd2); }
.cb.sm { width: 36px; height: 36px; }
/* M3 FAB: filled primary circle, elevated, for the one high-emphasis
   action in the row (play/pause). */
.cb.lg { width: 56px; height: 56px; background: var(--accent); border-color: var(--accent); color: #05050f; box-shadow: var(--ev2); }
.cb.lg:hover { background: var(--accent2); border-color: var(--accent2); box-shadow: var(--ev3); }
.cb.lg:active { box-shadow: var(--ev1); }
.cb.lg:disabled { background: var(--brd2); border-color: var(--brd2); color: var(--muted); box-shadow: none; }
.cb.on { color: var(--accent); border-color: var(--accent); background: var(--st-hover); }
.cb .material-symbols-outlined { pointer-events: none; }
#ctrls-sec { display: flex; align-items: center; gap: 8px; }
.hsep { width: 1px; height: 18px; background: var(--brd2); flex-shrink: 0; }
#loop-btn { font-family: var(--fm); font-size: 9px; font-weight: 600; letter-spacing: .05em; padding: 0 10px; width: auto; min-width: 44px; justify-content: center; }
#gapless-btn { font-family: var(--fm); font-size: 9px; font-weight: 600; letter-spacing: .05em; padding: 0 10px; width: auto; min-width: 44px; justify-content: center; }
#vol-row { flex: 1; display: flex; align-items: center; gap: 6px; }
.vol-ico { color: var(--muted); flex-shrink: 0; }

/* ── Material Symbols (player controls) ─────────────────────────────
   Google's standard boilerplate for the variable icon font (see
   https://fonts.google.com/icons), plus per-context sizing so these
   drop into the same button/row layouts the old inline SVGs used. */
.material-symbols-outlined {
  font-family: 'Material Symbols Outlined';
  font-weight: normal;
  font-style: normal;
  font-size: 20px;
  display: inline-block;
  line-height: 1;
  text-transform: none;
  letter-spacing: normal;
  word-wrap: normal;
  white-space: nowrap;
  direction: ltr;
  -webkit-font-smoothing: antialiased;
}
.cb.sm .material-symbols-outlined { font-size: 18px; }
.cb.lg .material-symbols-outlined { font-size: 26px; }
.vol-ico.material-symbols-outlined { font-size: 16px; }
#vol-sl { flex: 1; -webkit-appearance: none; appearance: none; height: 4px; background: var(--brd2); outline: none; cursor: pointer; border-radius: var(--sh-full); }
#vol-sl::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: var(--accent); cursor: pointer; }
#vol-lbl { font-family: var(--fm); font-size: 10px; color: var(--muted); width: 30px; text-align: right; }

#right { flex: 1; display: flex; flex-direction: column; overflow: hidden; min-width: 0; background: var(--bg); }
#tabs { display: flex; border-bottom: 1px solid var(--brd); background: var(--surf); flex-shrink: 0; overflow-x: auto; }
/* M3 primary tab: bottom indicator bar + a tinted state layer on hover
   (rather than only a text-color change) so the row reads as a proper
   M3 tab strip instead of plain nav links. */
.tab {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: none; border-bottom: 3px solid transparent; color: var(--muted);
  font-family: var(--fn); font-weight: 700; font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  padding: 11px 18px; cursor: pointer; transition: color .2s, border-color .2s, background .2s; white-space: nowrap;
}
.tab .material-symbols-outlined { font-size: 16px; }
.tab:hover { color: var(--text); background: var(--st-hover); }
.tab.on { color: var(--accent); border-bottom-color: var(--accent); background: var(--st-hover); }
.pane { display: none; flex: 1; flex-direction: column; overflow: hidden; min-height: 0; }
.pane.on { display: flex; }

#search-bar { display: flex; gap: 8px; padding: 12px; border-bottom: 1px solid var(--brd); background: var(--surf); flex-shrink: 0; }
#si { flex: 1; background: var(--bg); border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--text); font-family: var(--fn); font-size: 14px; padding: 8px 16px; outline: none; transition: border-color .2s, box-shadow .2s; }
#si:focus { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
#si::placeholder { color: var(--muted); }
#src-sel { background: var(--bg); border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--text); font-family: var(--fm); font-size: 11px; padding: 7px 10px; outline: none; cursor: pointer; flex-shrink: 0; }
#src-sel option { background: var(--surf2); }
/* M3 filled button. */
#btn-srch { background: var(--accent); color: #05050f; border: none; border-radius: var(--sh-full); font-family: var(--fn); font-weight: 700; font-size: 12px; letter-spacing: .02em; text-transform: uppercase; padding: 8px 20px; cursor: pointer; box-shadow: var(--ev1); transition: opacity .2s, box-shadow .2s; flex-shrink: 0; white-space: nowrap; }
#btn-srch:hover { opacity: .9; box-shadow: var(--ev2); }
#sres { flex: 1; overflow-y: auto; padding: 8px; scrollbar-width: thin; }
.si { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid transparent; border-radius: var(--sh-sm); cursor: pointer; transition: background .15s, border-color .15s; margin-bottom: 2px; }
.si:hover { background: var(--surf2); border-color: var(--brd); }
.si-th { width: 46px; height: 46px; object-fit: cover; flex-shrink: 0; background: var(--surf2); border-radius: var(--sh-xs); }
.si-nth { width: 46px; height: 46px; flex-shrink: 0; background: var(--surf2); border-radius: var(--sh-xs); display: flex; align-items: center; justify-content: center; color: var(--muted); font-size: 16px; }
.si-nth .material-symbols-outlined { font-size: 20px; }
.si-meta { flex: 1; min-width: 0; }
.si-t { font-weight: 600; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.si-a { font-family: var(--fm); font-size: 10px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }
.si-d { font-family: var(--fm); font-size: 10px; color: var(--muted); flex-shrink: 0; }
.si-acts { display: flex; gap: 5px; flex-shrink: 0; opacity: 0; transition: opacity .15s; }
.si:hover .si-acts { opacity: 1; }
/* M3 tonal button — the small in-row action buttons throughout (Play,
   +Queue, download, presets, etc.) all share this treatment now: pill
   shape, filled on the primary action, otherwise a quiet outline. */
.add-btn { display: inline-flex; align-items: center; gap: 4px; background: none; border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--text); font-family: var(--fm); font-size: 9px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; padding: 5px 10px; cursor: pointer; transition: background .15s, border-color .15s; white-space: nowrap; }
.add-btn .material-symbols-outlined { font-size: 13px; }
.add-btn:hover { background: var(--accent); border-color: var(--accent); color: #05050f; }
.add-btn.pnow:hover { background: var(--green); border-color: var(--green); color: #05050f; }
.add-btn:disabled { opacity: .3; cursor: not-allowed; }

#q-hdr { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--brd); background: var(--surf); flex-shrink: 0; }
#q-info { font-family: var(--fm); font-size: 10px; color: var(--muted); flex: 1; }
/* M3 outlined button (small, icon+label) — queue toolbar actions. */
.qa { display: inline-flex; align-items: center; gap: 4px; background: none; border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--muted); font-family: var(--fm); font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; padding: 5px 10px; cursor: pointer; transition: all .15s; }
.qa .material-symbols-outlined { font-size: 14px; }
.qa:hover { border-color: var(--accent); color: var(--accent); background: var(--st-hover); }
.qa.d:hover { border-color: var(--red); color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); }
.qa:disabled { opacity: .3; cursor: not-allowed; }
#ql { flex: 1; overflow-y: auto; padding: 6px; scrollbar-width: thin; }
.qi { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border: 1px solid transparent; border-radius: var(--sh-sm); transition: background .15s, border-color .15s; margin-bottom: 2px; }
.qi:hover { background: var(--surf2); border-color: var(--brd); }
.qi.cur { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 6%, transparent); }
.qi[draggable="true"] { cursor: grab; }
.qi.dragging { opacity: .4; }
.qi.drag-over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.qi-drag { color: var(--muted2); font-size: 13px; flex-shrink: 0; cursor: grab; line-height: 1; opacity: 0; transition: opacity .15s; }
.qi:hover .qi-drag { opacity: 1; }
.qi[draggable="false"] .qi-drag { display: none; }
.qi-n { font-family: var(--fm); font-size: 10px; color: var(--muted2); width: 20px; text-align: right; flex-shrink: 0; }
.qi-th { width: 34px; height: 34px; object-fit: cover; flex-shrink: 0; background: var(--surf2); border-radius: var(--sh-xs); }
.qi-nth { width: 34px; height: 34px; flex-shrink: 0; background: var(--surf2); border-radius: var(--sh-xs); display: flex; align-items: center; justify-content: center; color: var(--muted); font-size: 12px; }
.qi-nth .material-symbols-outlined { font-size: 16px; }
.qi-m { flex: 1; min-width: 0; }
.qi-t { font-weight: 600; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qi-a { font-family: var(--fm); font-size: 10px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qi-d { font-family: var(--fm); font-size: 10px; color: var(--muted); flex-shrink: 0; }
.qi-bs { display: flex; gap: 1px; opacity: 0; transition: opacity .15s; flex-shrink: 0; }
.qi:hover .qi-bs { opacity: 1; }
/* M3 standard icon button — no container, just a circular state layer. */
.qib { background: none; border: none; border-radius: 50%; color: var(--muted); cursor: pointer; padding: 5px; font-size: 13px; display: flex; align-items: center; transition: color .15s, background .15s; line-height: 1; }
.qib .material-symbols-outlined { font-size: 16px; }
.qib:hover { color: var(--text); background: var(--st-hover); }
.qib.del:hover { color: var(--red); background: color-mix(in srgb, var(--red) 10%, transparent); }
.qib.dl:hover { color: var(--accent); }
.qib:disabled { opacity: .3; cursor: not-allowed; }

/* Download format picker — a tiny fixed-position menu spawned next to
   whichever download button was clicked (now-playing or a queue item).
   See UI.openDownloadMenu/closeDownloadMenu in ui.js. */
.dl-menu {
  position: fixed; z-index: 500; background: var(--surf3); border: 1px solid var(--brd2); border-radius: var(--sh-sm);
  box-shadow: var(--ev3); min-width: 150px; padding: 4px; display: flex; flex-direction: column;
}
.dl-opt {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  background: none; border: none; border-radius: var(--sh-xs); color: var(--text); font-family: var(--fn); font-size: 12px;
  padding: 8px 10px; cursor: pointer; text-align: left; transition: background .15s, color .15s;
}
.dl-opt:hover { background: var(--st-hover); color: var(--accent); }
.dl-opt small { font-family: var(--fm); font-size: 9px; color: var(--muted); }
.dl-opt:hover small { color: var(--accent); }

#lyr-hdr { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--brd); background: var(--surf); flex-shrink: 0; }
#lyr-src-lbl { font-family: var(--fm); font-size: 10px; color: var(--muted); flex: 1; }
#lyr-body { flex: 1; overflow-y: auto; padding: 20px 24px; scrollbar-width: thin; scroll-behavior: smooth; }
.ll { font-size: 18px; font-weight: 600; line-height: 1.7; color: var(--muted); border-radius: var(--sh-xs); transition: color .3s, font-size .2s; cursor: pointer; padding: 2px 6px; margin: 0 -6px; }
.ll-note { font-size: 16px !important; opacity: .5; vertical-align: -2px; }
.ll:hover { color: var(--text); background: var(--st-hover); }
.ll.active { color: var(--text); font-size: 20px; }
.lp { font-size: 14px; line-height: 1.8; color: var(--muted); white-space: pre-wrap; }

.flt-label { font-family: var(--fm); font-size: 9px; font-weight: 600; letter-spacing: .15em; text-transform: uppercase; color: var(--muted); margin-bottom: 10px; display: flex; align-items: center; gap: 3px; }
.flt-label .material-symbols-outlined { font-size: 12px; }
/* M3 outlined → filled-tonal on select: presets behave like a chip/toggle
   group — quiet outline at rest, tonal (accent2-tinted) fill when active. */
.preset-btn { background: none; border: 1px solid var(--brd2); border-radius: var(--sh-md); color: var(--text); font-family: var(--fn); font-weight: 600; font-size: 12px; padding: 10px 8px; cursor: pointer; text-align: center; transition: all .15s; line-height: 1.3; }
.preset-btn:hover { border-color: var(--accent2); background: color-mix(in srgb, var(--accent2) 8%, transparent); }
.preset-btn.active { border-color: var(--accent2); background: color-mix(in srgb, var(--accent2) 15%, transparent); color: var(--accent2); }
.preset-btn:disabled { opacity: .3; cursor: not-allowed; }
.flt-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.flt-row label { font-family: var(--fm); font-size: 10px; color: var(--muted); width: 80px; flex-shrink: 0; }
.flt-slider { flex: 1; -webkit-appearance: none; appearance: none; height: 4px; background: var(--brd2); outline: none; cursor: pointer; border-radius: var(--sh-full); }
.flt-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: var(--accent2); cursor: pointer; }
.flt-slider:disabled { opacity: .3; }
.flt-val { font-family: var(--fm); font-size: 10px; color: var(--muted); width: 36px; text-align: right; }

/* CHAT */
#pane-chat { }
#chat-log { flex: 1; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; scrollbar-width: thin; }
.chat-msg { display: flex; flex-direction: column; gap: 3px; max-width: 88%; background: var(--surf2); border-radius: var(--sh-md); padding: 7px 11px; }
.chat-msg .cm-name { font-family: var(--fm); font-size: 10px; font-weight: 700; color: var(--accent2); }
.chat-msg .cm-text { font-size: 13px; line-height: 1.4; word-break: break-word; }
.chat-msg.mine { align-self: flex-end; align-items: flex-end; background: color-mix(in srgb, var(--accent) 12%, var(--surf2)); }
.chat-msg.mine .cm-name { color: var(--green); }
.chat-msg.system { align-self: center; background: none; padding: 2px; }
.chat-msg.system .cm-text { font-family: var(--fm); font-size: 10px; color: var(--muted); font-style: italic; }
#chat-input-row { display: flex; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--brd); background: var(--surf); flex-shrink: 0; }
#chat-input { flex: 1; background: var(--bg); border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--text); font-family: var(--fn); font-size: 13px; padding: 9px 16px; outline: none; transition: border-color .2s, box-shadow .2s; }
#chat-input:focus { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
#chat-send { background: var(--accent); color: #05050f; border: none; border-radius: var(--sh-full); font-family: var(--fn); font-weight: 700; font-size: 11px; letter-spacing: .02em; text-transform: uppercase; padding: 9px 18px; cursor: pointer; box-shadow: var(--ev1); transition: opacity .2s, box-shadow .2s; }
#chat-send:hover { opacity: .9; box-shadow: var(--ev2); }

/* ═══════════════ Chat pane: log + input (left) / user list (right) ═══════════════ */
#pane-chat { flex-direction: row; }
#chat-main { flex: 1; display: flex; flex-direction: column; min-width: 0; min-height: 0; border-right: 1px solid var(--brd); }
#chat-main #chat-log { flex: 1; }
#chat-users { width: 168px; flex-shrink: 0; overflow-y: auto; padding: 14px 10px; scrollbar-width: thin; }
#chat-users-hdr { font-family: var(--fm); font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); padding: 0 6px 10px; }
#chat-users-hdr span { color: var(--muted2); }
.cu-item { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: var(--sh-sm); transition: background .15s; }
.cu-item:hover { background: var(--surf2); }
.cu-avatar {
  width: 24px; height: 24px; flex-shrink: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--surf3); border: 1px solid var(--brd2);
  font-family: var(--fm); font-weight: 700; font-size: 11px; color: var(--muted);
}
.cu-avatar.is-host { border-color: var(--accent); color: var(--accent); }
.cu-meta { min-width: 0; }
.cu-name { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cu-tag { font-family: var(--fm); font-size: 9px; color: var(--accent); letter-spacing: .05em; }
.cu-empty { padding: 10px 6px; font-family: var(--fm); font-size: 11px; color: var(--muted); }

/* ═══════════════ Config tab ═══════════════ */
#pane-config { overflow-y: auto; scrollbar-width: thin; }
/* container-type so the card grid below reacts to the width of the Config pane
   itself (which is the viewport minus the side-by-side player on desktop),
   not the viewport — two columns when there's room, one when there isn't. */
#cfg-body { padding: 18px; display: flex; flex-direction: column; gap: 20px; container-type: inline-size; }
.cfg-mode-row { display: flex; gap: 8px; }
/* M3 outlined → tonal on select (segmented-button style). */
.cfg-mode-btn {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  flex: 1; background: var(--surf2); border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--muted);
  font-family: var(--fn); font-weight: 700; font-size: 12px; padding: 10px; cursor: pointer;
  transition: all .15s;
}
.cfg-mode-btn .material-symbols-outlined { font-size: 15px; }
.cfg-mode-btn:hover { border-color: var(--accent); color: var(--text); background: var(--st-hover); }
.cfg-mode-btn.on { border-color: var(--accent); color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.cfg-section { display: none; flex-direction: column; gap: 20px; }
.cfg-section.on { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: stretch; }   /* stretch: cards in the same row share a height instead of leaving ragged gaps */
@container (min-width: 820px) {
  .cfg-section.on { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.cfg-hint { font-family: var(--fm); font-size: 10px; color: var(--muted); line-height: 1.5; margin-bottom: 6px; }
.dj-list { display: flex; flex-direction: column; gap: 4px; }
.dj-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 6px 10px; background: none; border: 1px solid transparent; border-radius: var(--sh-md, var(--sh-sm)); color: var(--text); font: inherit; text-align: left; cursor: pointer; transition: background .15s, border-color .15s; }
.dj-item:hover:not(:disabled) { background: var(--st-hover); border-color: var(--brd2); }
.dj-item:disabled { cursor: default; }
.dj-item.is-dj { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.dj-name { flex: 1; min-width: 0; font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dj-you { color: var(--muted); font-size: 10px; }
.dj-tag { font-family: var(--fm); font-size: 9px; color: var(--accent); letter-spacing: .05em; }
.dj-ico { font-size: 18px; color: var(--muted); }
.dj-item.is-dj .dj-ico { color: var(--accent); }
.dj-item:hover:not(:disabled) .dj-ico { color: var(--accent); }
.pchip.is-dj { border-color: var(--accent2, var(--accent)); }
/* M3 filled card (surface-container). */
.cfg-block { display: flex; flex-direction: column; gap: 6px; padding: 18px; background: var(--surf); border: 1px solid var(--brd); border-radius: var(--sh-lg); }
.cfg-block .overlay-form { gap: 6px; }
.cfg-block label { font-family: var(--fm); font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
.cfg-label { font-family: var(--fn); font-weight: 700; font-size: 12px; color: var(--text); margin-bottom: 4px; }
.cfg-row { display: flex; align-items: center; gap: 10px; }
.cfg-row label { margin-top: 0; }
.mono-sm, .mono-lg.sm { font-family: var(--fm); font-size: 13px; letter-spacing: .1em; color: var(--accent); }
.radio-row.inline { flex-direction: row; }
.radio-row.inline .radio-opt { flex: 1; }
#cfg-lobby-name:disabled, #cfg-display-name:disabled { opacity: .5; cursor: not-allowed; }
.radio-row.inline input:disabled { cursor: not-allowed; }

/* EMPTY / LOADING */
.empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; padding: 48px 20px; color: var(--muted); text-align: center; flex: 1; }
.empty .material-symbols-outlined { font-size: 44px; opacity: .3; }
.empty p { font-family: var(--fm); font-size: 11px; }
.dots { display: inline-flex; gap: 4px; align-items: center; }
.dots span { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); animation: dp 1.2s ease-in-out infinite; }
.dots span:nth-child(2){animation-delay:.2s} .dots span:nth-child(3){animation-delay:.4s}
@keyframes dp { 0%,80%,100%{transform:scale(.55);opacity:.4} 40%{transform:scale(1);opacity:1} }

/* TOAST — M3 Snackbar: extra-small shape, single elevated surface. */
#toasts { position: fixed; bottom: 20px; right: 20px; display: flex; flex-direction: column; gap: 8px; z-index: 600; pointer-events: none; }
.toast { display: flex; align-items: flex-start; gap: 8px; background: var(--surf3); border: 1px solid var(--brd2); border-left: 3px solid var(--accent); border-radius: var(--sh-xs); color: var(--text); font-family: var(--fm); font-size: 11px; padding: 10px 14px; min-width: 220px; max-width: 340px; animation: tin .25s ease; box-shadow: var(--ev3); line-height: 1.4; }
.toast-ico { flex-shrink: 0; font-size: 16px; margin-top: 1px; color: var(--accent); }
.toast-msg { flex: 1; }
.toast.err { border-left-color: var(--red); }
.toast.err .toast-ico { color: var(--red); }
.toast.ok  { border-left-color: var(--green); }
.toast.ok .toast-ico { color: var(--green); }
.toast.warn{ border-left-color: var(--amber); }
.toast.warn .toast-ico { color: var(--amber); }
@keyframes tin { from{transform:translateX(16px);opacity:0} to{transform:translateX(0);opacity:1} }

/* MEANING MODAL — M3 Dialog: extra-large shape, high elevation. */
#meaning-modal { display: none; position: fixed; inset: 0; background: color-mix(in srgb, var(--bg) 85%, transparent); z-index: 300; align-items: center; justify-content: center; padding: 20px; }
#meaning-modal.show { display: flex; }
#meaning-box { background: var(--surf2); border: 1px solid var(--brd2); border-radius: var(--sh-xl); box-shadow: var(--ev3); max-width: 560px; width: 100%; max-height: 80vh; overflow-y: auto; padding: 26px; scrollbar-width: thin; }
#meaning-title { font-size: 18px; font-weight: 700; margin-bottom: 4px; }
#meaning-sub { font-family: var(--fm); font-size: 11px; color: var(--muted); margin-bottom: 16px; }
#meaning-body { font-size: 13px; line-height: 1.75; color: var(--muted); }
#meaning-body p { margin-bottom: 12px; }
#meaning-close { display: flex; align-items: center; justify-content: center; gap: 5px; margin-top: 16px; background: none; border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--muted); font-family: var(--fm); font-size: 11px; text-transform: uppercase; padding: 8px 16px; cursor: pointer; transition: all .15s; }
#meaning-close .material-symbols-outlined { font-size: 14px; }
#meaning-close:hover { border-color: var(--red); color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); }

@media (max-width: 1000px) {
  #main { flex-direction: column; }

  /* The whole player becomes a single square: art fills it edge-to-edge as
     a background layer, and player-panel (info/progress/ctrls)
     is overlaid on top of it, anchored to the bottom. Nothing here scrolls
     or grows past the square — overflow is just clipped — so there's never
     a scrollbar inside the player on small screens. */
  #left {
    width: 100%; border-right: none; border-bottom: 1px solid var(--brd);
    max-height: none; overflow: hidden; position: relative; aspect-ratio: 1;
  }
  #art-wrap {
    position: absolute; inset: 0; max-height: none; aspect-ratio: auto; z-index: 0;
  }
  #player-panel {
    position: absolute; left: 0; right: 0; bottom: 0; top: auto; z-index: 2;
    max-height: 100%; overflow: hidden;
    background: linear-gradient(to top, color-mix(in srgb, var(--bg) 94%, transparent) 0%, color-mix(in srgb, var(--bg) 82%, transparent) 60%, transparent 100%);
  }
  #info, #prog-wrap, #ctrls { border-bottom-color: rgba(255,255,255,.08); }
  .mode-grid { grid-template-columns: 1fr; }

  /* Tabs: a bit tighter so more of them fit before you have to scroll. */
  .tab { padding: 10px 12px; font-size: 10px; }

  /* Search bar: input+select+button no longer fit on one line at phone
     widths (the button was getting clipped off the right edge) — put the
     search term on its own row and let source/button share the second. */
  #search-bar { flex-wrap: wrap; }
  #si { flex: 1 1 100%; min-width: 0; }
  #src-sel { flex: 1; min-width: 0; }
  #btn-srch { flex: 0 0 auto; }

  /* Chat: the log+input column and the participants sidebar no longer fit
     side by side — stack the (short) participants list above the log
     instead of squeezing both into half-width columns. */
  #pane-chat { flex-direction: column; }
  #chat-main { border-right: none; border-bottom: 1px solid var(--brd); min-height: 0; }
  #chat-users { width: 100%; max-height: 96px; padding: 8px 10px; border-bottom: 1px solid var(--brd); }
  #chat-users-list { display: flex; flex-wrap: wrap; gap: 4px; }
  .cu-item { padding: 4px 8px; background: var(--surf2); border-radius: var(--sh-full); }
  .cu-meta { display: flex; align-items: center; }
  .cu-tag { margin-left: 4px; }
}

/* Row-action buttons (search results' Play/Queue, queue items' reorder/
   remove, the drag handle) are opacity:0-until-:hover, which on a touch
   screen never fires — they'd be invisible and effectively unusable.
   Keep them always visible wherever there's no hover capability at all,
   phone or tablet, regardless of viewport width. */
@media (hover: none) {
  .si-acts, .qi-bs, .qi-drag { opacity: 1; }
}
/* ═══════════════ Queue: requester chips ═══════════════ */
.qi-req {
  font-family: var(--fm); font-size: 9px; letter-spacing: .04em;
  color: var(--muted2); border: 1px solid var(--brd2); padding: 1px 7px;
  margin-left: 7px; border-radius: var(--sh-full); white-space: nowrap;
}
.qi-req.mine { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.qi-req.auto { color: var(--accent2); border-color: color-mix(in srgb, var(--accent2) 30%, transparent); }
.chip-ico { font-size: 10px !important; vertical-align: -1px; margin-right: 2px; }
.qa.on { border-color: var(--green); color: var(--green); }

/* ═══════════════ Skins tab ═══════════════ */
#pane-skins { overflow: hidden; }
#skins-hdr {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px;
  border-bottom: 1px solid var(--brd); background: var(--surf); flex-shrink: 0;
}
.skins-tabs { display: flex; gap: 4px; flex: 1; }
.skin-tab {
  background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--muted); font-family: var(--fn); font-weight: 700; font-size: 11px;
  letter-spacing: .08em; text-transform: uppercase; padding: 5px 4px 7px;
  margin-right: 14px; cursor: pointer; transition: color .2s, border-color .2s;
}
.skin-tab:hover { color: var(--text); }
.skin-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
#skins-mine-count { color: var(--muted2); }

#skins-body { flex: 1; overflow-y: auto; scrollbar-width: thin; padding: 16px; }
.skin-pane { display: none; flex-direction: column; }
.skin-pane.on { display: flex; }
.skin-section { margin-bottom: 22px; }
.skin-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.skin-row label {
  font-family: var(--fm); font-size: 10px; color: var(--muted);
  width: 96px; flex-shrink: 0; text-transform: uppercase; letter-spacing: .06em;
}
.skin-row .hi { flex: 1; min-width: 0; }
.hi.bad { border-color: var(--amber); }

.skin-preset-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 6px; }

.skin-color-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 8px; }
.skin-color { display: flex; align-items: center; gap: 8px; }
.skin-swatch {
  -webkit-appearance: none; appearance: none; width: 34px; height: 34px;
  padding: 0; border: 1px solid var(--brd2); border-radius: var(--sh-sm); background: none; cursor: pointer; flex-shrink: 0;
}
.skin-swatch::-webkit-color-swatch-wrapper { padding: 2px; }
.skin-swatch::-webkit-color-swatch { border: none; border-radius: var(--sh-xs); }
.skin-color-meta { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.skin-color-label { font-family: var(--fm); font-size: 9px; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
.skin-color-text { font-size: 10px !important; padding: 3px 6px !important; width: 100%; }

.skin-css {
  width: 100%; min-height: 120px; resize: vertical; line-height: 1.5;
  font-size: 11px; white-space: pre; overflow-x: auto;
}
.skin-warn { color: var(--amber); font-weight: 400; letter-spacing: 0; text-transform: none; margin-left: 6px; }
.skin-note {
  font-family: var(--fm); font-size: 10px; color: var(--muted);
  line-height: 1.6; margin-top: 8px; padding: 9px 11px;
  border-left: 2px solid var(--brd2); border-radius: var(--sh-xs); background: var(--surf2);
}
.skin-note code { color: var(--accent2); }

.skin-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 8px; }
.skin-actions .overlay-btn { margin-top: 0; }

.skin-browse-bar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.skin-sort { display: flex; gap: 4px; flex: 1; }

.skin-list { display: flex; flex-direction: column; gap: 6px; }
.skin-card {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  background: var(--surf); border: 1px solid var(--brd); border-radius: var(--sh-md); transition: border-color .15s;
}
.skin-card:hover { border-color: var(--accent); }
.skin-card-swatches { display: flex; flex-shrink: 0; border: 1px solid var(--brd2); border-radius: var(--sh-xs); overflow: hidden; }
.skin-sw { width: 16px; height: 34px; display: block; }
.skin-card-meta { flex: 1; min-width: 0; }
.skin-card-name { font-weight: 600; font-size: 13px; display: flex; align-items: center; gap: 6px; }
.skin-card-author { font-family: var(--fm); font-size: 10px; color: var(--muted); margin-top: 2px; }
.skin-badge {
  font-family: var(--fm); font-size: 8px; letter-spacing: .08em;
  padding: 2px 6px; border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--muted);
}
.skin-badge.pub { color: var(--green); border-color: color-mix(in srgb, var(--green) 30%, transparent); }
.skin-badge.css { color: var(--amber); border-color: color-mix(in srgb, var(--amber) 30%, transparent); }
.skin-card-acts { display: flex; gap: 5px; flex-shrink: 0; }

@media (max-width: 700px) {
  .skin-actions { grid-template-columns: 1fr; }
  .skin-color-grid { grid-template-columns: 1fr 1fr; }
  .skin-card { flex-wrap: wrap; }
}

/* ═══════════════ Visualizer tab ═══════════════ */
#pane-viz { overflow: hidden; }
#viz-hdr {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px;
  border-bottom: 1px solid var(--brd); background: var(--surf); flex-shrink: 0;
}
.viz-tabs { display: flex; gap: 4px; }
.viz-tab {
  background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--muted); font-family: var(--fn); font-weight: 700; font-size: 11px;
  letter-spacing: .08em; text-transform: uppercase; padding: 5px 4px 7px;
  margin-right: 14px; cursor: pointer; transition: color .2s, border-color .2s;
}
.viz-tab:hover { color: var(--text); }
.viz-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
#viz-mine-count { color: var(--muted2); }
.viz-active-name {
  flex: 1; text-align: right; font-family: var(--fm); font-size: 10px;
  color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

#viz-body { flex: 1; overflow-y: auto; scrollbar-width: thin; padding: 16px; min-height: 0; }
.viz-pane { display: none; flex-direction: column; min-height: 0; }
.viz-pane.on { display: flex; }
#vtab-stage { flex: 1; }

#viz-stage {
  position: relative; width: 100%; aspect-ratio: 16 / 9; min-height: 220px;
  background: var(--surf2); border: 1px solid var(--brd); border-radius: var(--sh-lg);
  overflow: hidden; flex-shrink: 0;
}
#viz-stage:fullscreen { aspect-ratio: auto; height: 100%; border: none; border-radius: 0; background: var(--bg); }
.viz-frame { width: 100%; height: 100%; border: 0; display: block; background: transparent; }

.viz-error {
  display: none; margin-top: 10px; padding: 9px 11px;
  border-left: 3px solid var(--red); border-radius: var(--sh-xs); background: color-mix(in srgb, var(--red) 7%, transparent);
  font-family: var(--fm); font-size: 11px; color: var(--red); line-height: 1.5; word-break: break-word;
}
.viz-error.show { display: block; }
.viz-stage-note {
  margin-top: 10px; font-family: var(--fm); font-size: 10px;
  color: var(--muted); line-height: 1.6;
}

.viz-code {
  width: 100%; min-height: 300px; resize: vertical; line-height: 1.55;
  font-family: var(--fm); font-size: 11px; white-space: pre; overflow: auto; tab-size: 2;
}

.viz-card {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  background: var(--surf); border: 1px solid var(--brd); border-radius: var(--sh-md); transition: border-color .15s;
}
.viz-card:hover { border-color: var(--accent); }
.viz-card-meta { flex: 1; min-width: 0; }
.viz-card-name { font-weight: 600; font-size: 13px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.viz-card-author { font-family: var(--fm); font-size: 10px; color: var(--muted); margin-top: 2px; }
.viz-card-acts { display: flex; gap: 5px; flex-shrink: 0; }

@media (max-width: 700px) {
  #viz-stage { aspect-ratio: 4 / 3; min-height: 180px; }
  .viz-card { flex-wrap: wrap; }
}
/* ═══════════════════ DEBUG TAB ═══════════════════ */
#pane-debug { overflow: hidden; }
#dbg-root { flex: 1; overflow-y: auto; min-height: 0; }
.dbg-wrap { display: flex; flex-direction: column; gap: 16px; padding: 16px; }

.dbg-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dbg-title { display: inline-flex; align-items: center; gap: 6px; font-weight: 800; font-size: 15px; color: var(--accent); letter-spacing: .04em; }
.dbg-title .material-symbols-outlined { font-size: 17px; }
.dbg-sub { font-family: var(--fm); font-size: 10px; color: var(--muted); flex: 1; }

.dbg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.dbg-card { background: var(--surf); border: 1px solid var(--brd); border-radius: var(--sh-sm); padding: 10px 12px; min-width: 0; }
.dbg-card-k { font-family: var(--fm); font-size: 9px; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 4px; }
.dbg-card-v { font-family: var(--fm); font-size: 12px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dbg-section { background: var(--surf); border: 1px solid var(--brd); border-radius: var(--sh-md); padding: 13px 15px; min-width: 0; }
.dbg-section-title { font-weight: 700; font-size: 12px; color: var(--text); margin-bottom: 10px; display: flex; align-items: baseline; gap: 6px; }
.dbg-count { font-family: var(--fm); font-size: 10px; color: var(--muted); font-weight: 400; }
.dbg-lane-hint { font-family: var(--fm); font-size: 9px; color: var(--muted); font-weight: 400; }

.dbg-wave-canvas {
  display: block; width: 100%; height: 110px; border-radius: var(--sh-sm);
  background: var(--surf2); border: 1px solid var(--brd);
}
.dbg-wave-canvas-buf { height: 80px; }

.dbg-seg-toggle { display: flex; gap: 4px; margin-left: auto; }
.dbg-seg-btn {
  background: none; border: 1px solid var(--brd2); border-radius: var(--sh-full); color: var(--muted);
  font-family: var(--fm); font-size: 9px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .05em; padding: 4px 10px; cursor: pointer; transition: all .15s;
}
.dbg-seg-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--st-hover); }
.dbg-seg-btn.on { border-color: var(--accent2); color: var(--accent2); background: color-mix(in srgb, var(--accent2) 10%, transparent); }

.dbg-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 900px) { .dbg-cols { grid-template-columns: 1fr; } }

.dbg-scroll { max-height: 240px; overflow-y: auto; }
.dbg-table { width: 100%; border-collapse: collapse; font-family: var(--fm); font-size: 10.5px; }
.dbg-table th {
  position: sticky; top: 0; background: var(--surf); text-align: left; color: var(--muted);
  font-weight: 600; text-transform: uppercase; letter-spacing: .04em; font-size: 9px;
  padding: 4px 6px; border-bottom: 1px solid var(--brd2);
}
.dbg-table td { padding: 4px 6px; border-bottom: 1px solid var(--brd); color: var(--text); white-space: nowrap; }
.dbg-table td.dbg-mono { max-width: 160px; overflow: hidden; text-overflow: ellipsis; }
.dbg-table tr.dbg-row-err td { color: var(--red); }
.dbg-empty-row { color: var(--muted2); text-align: center; padding: 10px !important; }

.dbg-list { display: flex; flex-direction: column; gap: 3px; }
.dbg-list-row {
  display: flex; gap: 10px; align-items: baseline; font-family: var(--fm); font-size: 10.5px;
  padding: 4px 6px; background: var(--surf2); border-radius: var(--sh-xs); border-left: 2px solid var(--brd2);
}
.dbg-list-row.dbg-row-err { border-left-color: var(--red); color: var(--red); }
.dbg-list-row.dbg-row-warn { border-left-color: var(--amber); color: var(--amber); }
.dbg-muted { color: var(--muted); margin-left: auto; }
/* ═══════════════ STICKY PLAYER + TABS ═══════════════
   The tab panes grow with their content and the *page* scrolls (they don't
   scroll internally), so left to itself both the player AND the #tabs bar
   scroll away with them — including a very long search/queue list, or the
   lyrics pane's own auto-scroll to the active line. #tabs is pinned right
   alongside the player so the tab buttons stay reachable no matter how far
   the pane content has scrolled. Two layouts, matching how the player is
   laid out:

   1) Side-by-side (desktop, and any phone/tablet held in landscape): the
      whole player column stays pinned to the side, and #tabs pins to the
      top of the #right column right next to it.
   2) Stacked (portrait phone): the album art scrolls away, but the bottom
      half of the player — title, progress, controls — stays frozen at the
      top of the screen, and #tabs pins directly beneath it.

   Both need #main AND #right to be overflow:visible: overflow:hidden turns
   whichever one still has it into the element sticky positioning is
   measured against, and — since that element never scrolls itself, the
   *page* does — nothing would ever actually stick to the viewport. */

/* ── 1) side-by-side ── */
@media (min-width: 1001px), (max-width: 1000px) and (orientation: landscape) {
  #main {
    --left-w: 480px;
    overflow: visible;
    /* #left is no longer stretched to the full page height, so paint its
       column background here to keep the sidebar look all the way down. */
    background: linear-gradient(to right, var(--surf) var(--left-w), transparent var(--left-w));
  }
  #left {
    position: sticky; top: 0; align-self: flex-start;
    width: var(--left-w);
    max-height: 100vh; max-height: 100dvh;   /* never taller than the screen; scrolls inside itself if it has to */
    border-right: none;
  }
  #right { overflow: visible; border-left: 1px solid var(--brd); }
  #tabs { position: sticky; top: 0; z-index: 20; box-shadow: var(--ev2); }
}

/* Landscape phones / small tablets: side-by-side instead of the portrait
   "art square with the controls overlaid" layout from the 1000px query
   above (which is as tall as the screen is wide — bigger than the whole
   screen when it's on its side). */
@media (max-width: 1000px) and (orientation: landscape) {
  #main { --left-w: clamp(280px, 36vw, 380px); flex-direction: row; }
  #left { aspect-ratio: auto; border-bottom: none; overflow-x: hidden; overflow-y: auto; }
  /* Art shrinks to whatever height is left after the controls. */
  #art-wrap { position: relative; inset: auto; aspect-ratio: 1; z-index: auto; flex: 0 1 auto; min-height: 72px; }
  #player-panel { position: static; max-height: none; overflow: visible; background: none; }
  #info, #prog-wrap, #ctrls { border-bottom-color: var(--brd); }
  /* Narrow column: let the secondary row wrap, volume on its own line. */
  #ctrls-sec { flex-wrap: wrap; row-gap: 8px; }
  #ctrls-sec .hsep { display: none; }
  #vol-row { flex: 1 1 100%; order: 10; }
}

/* ── 2) stacked, portrait ── */
@media (max-width: 1000px) and (orientation: portrait) {
  #main { overflow: visible; }
  /* Sticks once its top edge reaches a *negative* offset: exactly the art's
     height minus the panel's height. So the art scrolls off the top and the
     panel (which sits at the bottom of #left) is what stays on screen.
     The two heights are measured in main.js (_initStickyPlayer) because the
     panel wraps to different heights on different screens. */
  #left {
    position: sticky; z-index: 30;
    top: calc(var(--player-panel-h, 190px) - var(--player-left-h, 100vw));
    box-shadow: var(--ev3);
  }
  #right { overflow: visible; }
  /* Sticks right below the frozen player panel (rather than at the very
     top of the viewport, like the side-by-side layout above) — the panel
     itself already occupies that space once #left has stuck. */
  #tabs {
    position: sticky; z-index: 20;
    top: var(--player-panel-h, 190px);
    box-shadow: var(--ev2);
  }
}

/* buffered-waveform legend (Debug tab) */
.dbg-key { display: inline-flex; align-items: center; gap: 4px; margin-left: 8px; font-family: var(--fm); font-size: 9px; font-weight: 400; color: var(--muted); }
.dbg-key-sw { display: inline-block; width: 8px; height: 8px; border-radius: 2px; }
.dbg-key-sw.played { background: rgba(148,163,184,.55); }
.dbg-key-sw.ready { background: color-mix(in srgb, var(--accent2) 90%, transparent); }

/* ═══════════════ GAME CONTROLLER BADGE ═══════════════ */
.pad-badge {
  display: none; align-items: center; gap: 6px; flex-shrink: 0; cursor: help;
  font-family: var(--fm); font-size: 9px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--green); padding: 4px 9px; border-radius: var(--sh-full);
  background: color-mix(in srgb, var(--green) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--green) 30%, transparent);
  transition: background .12s;
}
.pad-badge svg { width: 14px; height: 14px; flex-shrink: 0; }
.pad-badge .material-symbols-outlined { font-size: 15px; }
.pad-badge.hit { background: color-mix(in srgb, var(--green) 32%, transparent); }
@media (max-width: 700px) { .pad-badge .pad-lbl { display: none; } .pad-badge { padding: 4px 7px; } }

/* ═══════════════ BINDINGS TAB ═══════════════ */
#bindings-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; padding: 14px 16px; border-bottom: 1px solid var(--brd); flex-wrap: wrap; }
.bnd-head-txt h3 { margin: 0 0 4px; font-size: 14px; }
.bnd-head-txt p { margin: 0; font-size: 11px; color: var(--muted); max-width: 46ch; }
.bnd-head-acts { display: flex; gap: 8px; flex-shrink: 0; }
.bnd-col-h { display: grid; grid-template-columns: 1fr 140px 140px; gap: 8px; padding: 8px 16px; font-family: var(--fm); font-size: 9px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); border-bottom: 1px solid var(--brd); }
#bindings-list { flex: 1; overflow-y: auto; padding: 4px 0 16px; }
.bnd-group-h { padding: 12px 16px 6px; font-family: var(--fm); font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--accent2); }
.bnd-row { display: grid; grid-template-columns: 1fr 140px 140px; gap: 8px; align-items: center; padding: 6px 16px; }
.bnd-row:hover { background: var(--st-hover); }
.bnd-lbl { font-size: 12px; }
.bnd-cell { display: flex; align-items: center; gap: 4px; min-width: 0; }
.bnd-btn { flex: 1; min-width: 0; background: var(--surf2); border: 1px solid var(--brd2); border-radius: var(--sh-xs); color: var(--text); font-family: var(--fm); font-size: 11px; padding: 6px 8px; cursor: pointer; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: border-color .12s, background .12s; }
.bnd-btn:hover { border-color: var(--accent); }
.bnd-btn.listening { border-color: var(--green); color: var(--green); background: color-mix(in srgb, var(--green) 10%, transparent); animation: bnd-pulse 1s ease-in-out infinite; }
@keyframes bnd-pulse { 0%,100% { opacity: 1; } 50% { opacity: .6; } }
.bnd-x { flex-shrink: 0; width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; background: none; border: none; color: var(--muted); cursor: pointer; border-radius: var(--sh-xs); }
.bnd-x:hover { color: var(--text); background: var(--surf2); }
.bnd-x .material-symbols-outlined { font-size: 15px; }
@media (max-width: 700px) {
  .bnd-col-h, .bnd-row { grid-template-columns: 1fr 100px 100px; }
  .bnd-head-txt p { max-width: none; }
}

/* ═══════════════ ON-SCREEN KEYBOARD ═══════════════ */
/* No floating trigger button — it opens only via a controller's A
   button while a text field has focus (see gamepad.js's _process). */
#vk-overlay {
  position: fixed; inset: 0; z-index: 9995; display: none; align-items: flex-end; justify-content: center;
  background: rgba(4,4,12,.55); backdrop-filter: blur(2px);
}
#vk-overlay.show { display: flex; }
#vk-panel {
  width: 100%; max-width: 620px; background: var(--surf); border: 1px solid var(--brd2); border-bottom: none;
  border-radius: var(--sh-md) var(--sh-md) 0 0; padding: 12px 14px calc(14px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -8px 30px rgba(0,0,0,.4);
}
#vk-preview {
  font-family: var(--fm); font-size: 13px; min-height: 20px; padding: 8px 10px; margin-bottom: 10px;
  background: var(--surf2); border: 1px solid var(--brd); border-radius: var(--sh-xs); color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#vk-preview.empty { color: var(--muted); }
#vk-rows { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.vk-row { display: flex; gap: 6px; justify-content: center; }
.vk-k {
  flex: 1; max-width: 46px; height: 38px; display: flex; align-items: center; justify-content: center;
  background: var(--surf2); border: 1px solid var(--brd2); border-radius: var(--sh-xs); color: var(--text);
  font-family: var(--fm); font-size: 13px; text-transform: none; cursor: pointer; transition: background .1s, border-color .1s;
}
.vk-k:hover { border-color: var(--accent); }
.vk-k.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, transparent); }
#vk-bottom { display: flex; gap: 6px; flex-wrap: wrap; }
#vk-bottom .vk-k { flex: 1; max-width: none; font-size: 11px; font-weight: 600; letter-spacing: .04em; }
#vk-bottom .vk-space { flex: 2; }
#vk-bottom [data-vk="shift"].on { border-color: var(--accent2); color: var(--accent2); }
#vk-bottom .vk-go { border-color: var(--green); color: var(--green); }
@media (max-width: 700px) {
  .vk-k { max-width: none; height: 34px; font-size: 12px; }
}

/* ═══════════════ IN-PLACE CONTROLLER BUTTON PROMPTS ("game controller only") ═══════════════ */
/* Each bound action's real GUI control (play button, a tab, an
   on-screen-keyboard key, ...) grows a small badge naming what's bound
   to it — see Pad.ACTION_EL / Pad._renderElementHints in gamepad.js.
   .pad-hint-host just gives the control `position: relative` so the
   badge can anchor to it without affecting layout; visibility is a
   single class on <body> so no per-badge JS toggling is needed. */
.pad-hint-host { position: relative; }
.pad-hint {
  position: absolute; left: 50%; bottom: 3px; transform: translateX(-50%);
  font-family: var(--fm); font-size: 8px; font-weight: 800; line-height: 1; letter-spacing: 0;
  padding: 2px 4px; border-radius: var(--sh-full);
  background: rgba(10,10,18,.88); color: var(--accent); border: 1px solid var(--brd2);
  pointer-events: none; opacity: 0; transition: opacity .12s;
  white-space: nowrap; z-index: 3;
}
body.pad-active .pad-hint:not(.pad-hint-playeronly) { opacity: 1; }
/* Playback/Queue-group badges (play, seek, loop, ...) only light up
   while the player actually has controller focus — see the focus-zone
   note in gamepad.js. Tab-opening and on-screen-keyboard badges are
   exempt (not .pad-hint-playeronly) and stay lit in either zone. */
body.pad-active:not(.pad-tabs-focused) .pad-hint-playeronly { opacity: 1; }
/* A visible cue for which zone currently has controller focus: the
   player control bar dims and drops its "focused" outline once a tab
   takes over, and picks both back up when focus returns to it. */
body.pad-active #ctrls { transition: opacity .15s, filter .15s, outline-color .15s; }
body.pad-active:not(.pad-tabs-focused) #ctrls { outline: 1px solid var(--accent); outline-offset: 6px; border-radius: var(--sh-md); }
body.pad-active.pad-tabs-focused #ctrls { opacity: .45; filter: saturate(.5); outline: 1px solid transparent; outline-offset: 6px; }
/* Makes it obvious what navUp/navDown/navSelect currently landed on —
   only while actually navigating a tab with the controller, so it
   doesn't add a focus ring for ordinary mouse/keyboard use. */
body.pad-active.pad-tabs-focused .pane :focus {
  outline: 2px solid var(--accent) !important;
  outline-offset: 2px;
}
/* Wide/rectangular controls (tabs, the keyboard trigger) get a corner
   badge instead — a bottom-center one would sit on top of their label. */
.pad-hint.corner { left: auto; right: 1px; top: 1px; bottom: auto; transform: none; }
.cb.sm .pad-hint { font-size: 7px; padding: 1px 3px; bottom: 1px; }