/* KaraokeNatin — one stylesheet, two themes, two roles.
 *
 * Palette follows Claude's: warm paper in light, warm charcoal in dark, with a
 * single clay accent doing all the pointing. Headings are serif, everything
 * else is the system sans — the contrast is what keeps it from reading generic.
 *
 * Layout targets: a phone held one-handed (the remote) and a TV or laptop
 * (the host). The host view is deliberately a single screen — see "host stage
 * layout" near the bottom; nothing there scrolls except the side panel's list.
 */

:root {
  color-scheme: light;

  --bg: #faf9f5;
  --bg-2: #ffffff;
  --bg-3: #f0eee6;
  --bg-4: #e9e6dc;
  --line: #e3ded1;
  --line-2: #d5cfbe;
  --ink: #1f1e1d;
  --ink-2: #6b6862;
  --ink-3: #97948c;
  --accent: #c96442;
  --accent-soft: rgba(201, 100, 66, 0.1);
  --accent-ink: #ffffff;
  --ok: #3a8a68;
  --warn: #b0762a;
  --bad: #c0483f;

  --shadow-sm: 0 1px 2px rgba(31, 30, 29, 0.05);
  --shadow: 0 4px 16px -6px rgba(31, 30, 29, 0.14);
  --shadow-lg: 0 24px 60px -20px rgba(31, 30, 29, 0.28);

  --radius: 16px;
  --radius-sm: 10px;
  --tap: 44px;

  --serif: ui-serif, "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* One easing for everything, so motion across the app feels like one hand. */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --fast: 0.16s;
  --mid: 0.26s;
  --slow: 0.42s;
}

html[data-theme="dark"], :root.dark { color-scheme: dark; }

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) {
    color-scheme: dark;

    --bg: #1f1e1d;
    --bg-2: #262624;
    --bg-3: #30302e;
    --bg-4: #3a3a37;
    --line: #3a3936;
    --line-2: #4a4945;
    --ink: #f5f4ee;
    --ink-2: #b2aea5;
    --ink-3: #85827b;
    --accent: #d97757;
    --accent-soft: rgba(217, 119, 87, 0.14);
    --accent-ink: #1f1e1d;
    --ok: #57c79a;
    --warn: #e0a34e;
    --bad: #f08279;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow: 0 4px 18px -6px rgba(0, 0, 0, 0.6);
    --shadow-lg: 0 24px 60px -20px rgba(0, 0, 0, 0.7);
  }
}

/* Explicit dark choice — same values, but winning over the light default
   regardless of what the system prefers. */
html[data-theme="dark"] {
  --bg: #1f1e1d;
  --bg-2: #262624;
  --bg-3: #30302e;
  --bg-4: #3a3a37;
  --line: #3a3936;
  --line-2: #4a4945;
  --ink: #f5f4ee;
  --ink-2: #b2aea5;
  --ink-3: #85827b;
  --accent: #d97757;
  --accent-soft: rgba(217, 119, 87, 0.14);
  --accent-ink: #1f1e1d;
  --ok: #57c79a;
  --warn: #e0a34e;
  --bad: #f08279;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow: 0 4px 18px -6px rgba(0, 0, 0, 0.6);
  --shadow-lg: 0 24px 60px -20px rgba(0, 0, 0, 0.7);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 var(--sans);
  -webkit-text-size-adjust: 100%;
  overscroll-behavior-y: none;
}

body {
  min-height: 100dvh;
  padding-bottom: env(safe-area-inset-bottom);
  transition: background var(--mid) var(--ease), color var(--mid) var(--ease);
}

a { color: var(--accent); text-underline-offset: 2px; }

/* An input carries a default intrinsic width (about 20 characters, and not the
   same 20 in every engine). Inside a flex row that default is a floor, so one
   text field can push a card wider than the phone holding it — the difference
   between a layout that adapts and one that overflows off the right edge. */
button, input { font: inherit; color: inherit; min-width: 0; }
img, svg { max-width: 100%; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

h1, h2, h3 { font-family: var(--serif); font-weight: 600; letter-spacing: -0.01em; }

.view {
  max-width: 940px;
  margin: 0 auto;
  padding: 0 20px 40px;
  animation: view-in var(--slow) var(--ease) both;
}
.view[hidden] { display: none; }

@keyframes view-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* ─────────────── home ─────────────── */

.home-head {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 18px 0 0;
}

#view-home:not([hidden]) {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
.hero {
  text-align: center;
  padding: 32px 0 8px;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* A soft halo behind the mark, so the top of the page has a centre of gravity. */
.mic {
  display: grid;
  place-items: center;
  width: 104px;
  height: 104px;
  margin: 0 auto;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 45%, var(--accent-soft), transparent 68%);
}

.mic svg {
  width: 60px;
  height: 60px;
  fill: var(--accent);
  animation: breathe 6s ease-in-out infinite;
  transform-origin: 50% 60%;
}
.mic .mic-arc { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linecap: round; opacity: 0.75; }

/* A slow, shallow breath — presence, not attention-seeking. */
@keyframes breathe {
  0%, 100% { transform: scale(1); opacity: 0.95; }
  50%      { transform: scale(1.045); opacity: 1; }
}

.hero h1 {
  margin: 14px 0 10px;
  font-size: clamp(38px, 8vw, 60px);
  letter-spacing: -0.03em;
  line-height: 1.05;
}
.hero h1 span { color: var(--accent); }

.tagline { color: var(--ink-2); margin: 0 auto 36px; max-width: 40ch; font-size: 17px; }

.choices {
  display: grid;
  gap: 14px;
  grid-template-columns: 1fr;
  text-align: left;
  margin-bottom: 30px;
}
@media (min-width: 700px) { .choices { grid-template-columns: 1fr 1fr; } }

.choice {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 22px;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--mid) var(--ease), box-shadow var(--mid) var(--ease), transform var(--mid) var(--ease);
}
.choice:hover { border-color: var(--line-2); box-shadow: var(--shadow); transform: translateY(-2px); }
.choice h2 { margin: 0 0 4px; font-size: 21px; }
.choice p { margin: 0 0 18px; color: var(--ink-2); font-size: 14px; }

.join-form { display: flex; flex-wrap: wrap; gap: 8px; }
#join-name {
  flex: 1 1 100%;
  min-width: 0;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0 14px;
  height: var(--tap);
  text-align: center;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
#join-name:focus { border-color: var(--accent); outline: none; }
#join-code {
  flex: 1;
  min-width: 0;
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0 14px;
  height: var(--tap);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  font-weight: 700;
  text-align: center;
  font-family: var(--mono);
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
#join-code:focus { background: var(--bg-2); }
#join-code::placeholder { color: var(--ink-3); letter-spacing: 0.28em; font-weight: 400; }

/* Library sits a step quieter than Host/Join — it is the side door. */
.library-cta {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  background: transparent;
  border: 1px dashed var(--line-2);
  border-radius: var(--radius);
  padding: 16px 20px;
  cursor: pointer;
  text-align: left;
  color: var(--ink);
  transition: background var(--mid) var(--ease), border-color var(--mid) var(--ease);
}
.library-cta:hover { background: var(--bg-2); border-color: var(--accent); }
.library-cta-main { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
.library-cta-title { font-family: var(--serif); font-size: 18px; font-weight: 600; }
.library-cta-go { display: inline-flex; color: var(--ink-3); transition: transform var(--mid) var(--ease), color var(--mid) var(--ease); }
.library-cta:hover .library-cta-go { transform: translateX(4px); color: var(--accent); }

/* The whole "how it works" story, in five words that people actually read. */
.trust {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 0;
  padding: 0;
}
.trust li {
  font-size: 12.5px;
  color: var(--ink-2);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 5px 12px;
  animation: chip-in var(--slow) var(--ease) both;
}
.trust li:nth-child(1) { animation-delay: 0.05s; }
.trust li:nth-child(2) { animation-delay: 0.11s; }
.trust li:nth-child(3) { animation-delay: 0.17s; }
.trust li:nth-child(4) { animation-delay: 0.23s; }
.trust li:nth-child(5) { animation-delay: 0.29s; }

@keyframes chip-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.home-foot { text-align: center; color: var(--ink-3); font-size: 13px; padding-top: 36px; }
.home-foot a { color: var(--ink-3); text-decoration: none; }
.home-foot a:hover { color: var(--ink-2); text-decoration: underline; }
.version-line { margin: 8px 0 0; display: flex; gap: 8px; justify-content: center; align-items: center; font-size: 12px; color: var(--ink-3); }
.version-line [hidden] { display: none; }

/* ─────────────── name gate ─────────────── */

.gate-sub { color: var(--ink-2); font-size: 14px; margin: 0 0 16px; }
.gate-form { display: flex; flex-direction: column; gap: 10px; }
#name-gate-input {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  height: var(--tap);
  padding: 0 14px;
  width: 100%;
  transition: border-color var(--fast) var(--ease);
}
#name-gate-input:focus { border-color: var(--accent); outline: none; }
.gate-code { font-family: var(--mono); letter-spacing: 0.18em; }
.gate-foot { margin: 14px 0 0; text-align: center; font-size: 13px; color: var(--ink-3); }

/* ─────────────── theme toggle ─────────────── */

.theme-btn {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--bg-2);
  cursor: pointer;
  display: inline-grid;
  place-items: center;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.theme-btn:hover { border-color: var(--accent); }

/* Sun that fills in and shrinks into a crescent when the dark theme is on. */
.theme-icon {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2px solid var(--ink-2);
  background: transparent;
  position: relative;
  transition: box-shadow var(--mid) var(--ease), border-color var(--mid) var(--ease);
  box-shadow: 0 0 0 0 var(--bg-2) inset;
}
.theme-icon::after {
  content: "";
  position: absolute;
  inset: -3px -3px auto auto;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--bg-2);
  transform: scale(0);
  transition: transform var(--mid) var(--ease), background var(--mid) var(--ease);
}
html[data-theme="dark"] .theme-icon,
html[data-theme="dark"] .theme-icon { border-color: var(--accent); }
html[data-theme="dark"] .theme-icon::after { transform: scale(1); }
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .theme-icon { border-color: var(--accent); }
  html:not([data-theme="light"]) .theme-icon::after { transform: scale(1); }
}

/* ─────────────── icons ───────────────
   Every icon is a 24×24 line drawing that inherits `currentColor`, so it picks
   up hover, focus and dark mode from whatever it sits in. Size is set by the
   host, never by the drawing. */

.i {
  width: 18px;
  height: 18px;
  flex: none;
  display: block;
  overflow: visible;
}

.icon-btn .i { width: 17px; height: 17px; }
.icon-btn.big .i { width: 19px; height: 19px; }
.icon-btn.primary .i { width: 22px; height: 22px; }
.modal-close .i { width: 16px; height: 16px; }
.pill .i { width: 15px; height: 15px; color: var(--ink-3); }
.fs-btn .i { width: 17px; height: 17px; }
.library-cta-go .i { width: 20px; height: 20px; }
.pl-caret { width: 15px; height: 15px; color: var(--ink-3); }
.picker-tick { width: 16px; height: 16px; color: var(--accent); }

/* ─────────────── buttons ─────────────── */

.btn {
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 0 18px;
  height: var(--tap);
  font-weight: 550;
  cursor: pointer;
  background: var(--bg-3);
  color: var(--ink);
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease),
              color var(--fast) var(--ease), transform var(--fast) var(--ease),
              box-shadow var(--fast) var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn-primary { background: var(--accent); color: var(--accent-ink); box-shadow: var(--shadow-sm); }
.btn-primary:hover { background: var(--accent); filter: brightness(1.06); box-shadow: var(--shadow); }
.btn-ghost { background: transparent; border-color: var(--line-2); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }
.btn-quiet { background: transparent; border-color: var(--line); color: var(--ink-2); }
.btn-quiet:hover { border-color: var(--line-2); color: var(--ink); }
.btn-big { width: 100%; height: 52px; font-size: 16.5px; }
.btn-sm { height: 34px; padding: 0 12px; font-size: 13px; border-radius: 8px; }

.icon-btn {
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: 9px;
  min-width: 34px;
  height: 34px;
  cursor: pointer;
  color: var(--ink-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease),
              border-color var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.icon-btn:hover { color: var(--accent); border-color: var(--accent); transform: translateY(-1px); }
.icon-btn.big { min-width: var(--tap); height: var(--tap); }
.icon-btn.primary {
  background: var(--accent);
  border-color: transparent;
  color: var(--accent-ink);
  min-width: 52px;
  height: 52px;
  box-shadow: var(--shadow-sm);
}
.icon-btn.primary:hover { color: var(--accent-ink); filter: brightness(1.06); box-shadow: var(--shadow); }

/* ─────────────── room chrome ─────────────── */

.room-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 0;
  flex-wrap: wrap;
  flex: none;
}
/* A guest scrolls; the room code and the connection state are the two things
   that must not scroll away with the rest. The host never scrolls at all. */
body.in-room:not(.is-host) .room-head {
  position: sticky;
  top: 0;
  z-index: 5;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(8px);
}
.head-left, .head-right { display: flex; align-items: center; gap: 8px; }
.label { color: var(--ink-3); font-size: 11px; text-transform: uppercase; letter-spacing: 0.14em; }
.code { font-family: var(--mono); font-size: 19px; letter-spacing: 0.16em; font-weight: 700; }

.conn {
  font-size: 12px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--ink-2);
  background: var(--bg-2);
  transition: color var(--mid) var(--ease), border-color var(--mid) var(--ease);
}
.conn-ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.conn-warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); animation: pulse-soft 2.4s ease-in-out infinite; }
.conn-bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }

@keyframes pulse-soft {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.55; }
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--ink-2);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 10px;
}

/* only the host renders the video and broker count */
.host-only { display: none; }
body.is-host .host-only { display: block; }
body.is-host .pill.host-only { display: inline-flex; }

/* ─────────────── stage ─────────────── */

.stage {
  position: relative;
  background: #000;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}
.yt-mount {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  margin: 0 auto;
}
.yt-mount iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.player-error { color: var(--warn); padding: 20px; text-align: center; margin: 0; }

/* Autoplay prompt — sits over the video until the browser is satisfied. */
.tap-to-play {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: rgba(12, 11, 10, 0.86);
  border: 0;
  color: #f5f4ee;
  cursor: pointer;
  padding: 20px;
  text-align: center;
  animation: view-in var(--mid) var(--ease) both;
}
.tap-to-play[hidden] { display: none; }
.tap-icon {
  width: 66px;
  height: 66px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: #fff;
  background: var(--accent);
  margin-bottom: 8px;
  animation: halo 2.8s ease-out infinite;
}
@keyframes halo {
  0%   { box-shadow: 0 0 0 0 rgba(201, 100, 66, 0.45); }
  70%  { box-shadow: 0 0 0 22px rgba(201, 100, 66, 0); }
  100% { box-shadow: 0 0 0 0 rgba(201, 100, 66, 0); }
}
.tap-text { font-size: 17px; font-weight: 600; font-family: var(--serif); }
.tap-sub { font-size: 13px; color: #b2aea5; max-width: 34ch; }

/* Always on screen, not on hover: the host screen is usually a TV or a tablet
 * that never sends a hover, and a control you cannot point at is a control
 * that is not there. It dims instead, and comes up to full on hover/focus. */
.fs-btn {
  position: absolute;
  right: 12px;
  bottom: 12px;
  z-index: 3;
  background: rgba(12, 11, 10, 0.62);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 10px;
  color: #f5f4ee;
  width: 38px;
  height: 38px;
  cursor: pointer;
  display: grid;
  place-items: center;
  opacity: 0.78;
  transition: opacity var(--mid) var(--ease), background var(--mid) var(--ease);
}
.stage:hover .fs-btn, .fs-btn:hover, .fs-btn:focus-visible {
  opacity: 1;
  background: rgba(12, 11, 10, 0.85);
}
.fs-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.stage:fullscreen { border-radius: 0; box-shadow: none; }
.stage:fullscreen .yt-mount { max-width: none; width: 100%; height: 100%; aspect-ratio: auto; }
.stage:-webkit-full-screen { border-radius: 0; box-shadow: none; }
.stage:-webkit-full-screen .yt-mount { max-width: none; width: 100%; height: 100%; aspect-ratio: auto; }

/* Corner stand-ins for the join code once fullscreen takes the header away.
 * `body.stage-fullscreen` is set from script, so these do not depend on a
 * single engine spelling `:fullscreen` the way this browser happens to. */
.fs-code, .fs-qr {
  display: none;
  position: absolute;
  top: 14px;
  z-index: 4;
}
body.stage-fullscreen .fs-code,
body.stage-fullscreen .fs-qr,
.stage:fullscreen .fs-code,
.stage:fullscreen .fs-qr { display: block; }
.fs-code {
  left: 14px;
  padding: 8px 14px;
  background: rgba(12, 11, 10, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 10px;
  font-family: var(--mono);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: #f5f4ee;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
/* No width/height here on purpose — QR.draw sizes the canvas to a whole number
 * of pixels per module, and a CSS resize would smear the modules into an
 * unscannable blur. It stays small; it just stays crisp. */
.fs-qr {
  right: 14px;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

body.stage-fullscreen .invite-rail { display: none !important; }

/* ─────────────── now playing ─────────────── */

.now { flex: none; }
.now-card {
  display: flex;
  gap: 14px;
  align-items: center;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 14px;
  box-shadow: var(--shadow-sm);
}
.now-thumb {
  width: 92px;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 10px;
  background: var(--bg-3);
  flex: none;
}
img.thumb-missing { background: var(--bg-3); content-visibility: hidden; }

.now-meta { min-width: 0; }
.now-title {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 18px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.now-artist { color: var(--ink-2); font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.now-by { color: var(--ink-3); font-size: 12px; }

.empty { color: var(--ink-3); text-align: center; padding: 26px 8px; margin: 0; font-size: 14px; }

/* ─────────────── transport ─────────────── */

.transport {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px 16px 14px;
  box-shadow: var(--shadow-sm);
  flex: none;
}
.seekrow { display: flex; align-items: center; gap: 12px; }
.t { font-variant-numeric: tabular-nums; color: var(--ink-3); font-size: 12px; min-width: 42px; font-family: var(--mono); }
.t:last-child { text-align: right; }
.buttons { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
#vol { flex: 1; min-width: 60px; }

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  flex: 1;
  height: 22px;
  background: transparent;
  cursor: pointer;
  min-width: 0;
}
input[type="range"]::-webkit-slider-runnable-track { height: 5px; border-radius: 999px; background: var(--bg-4); }
input[type="range"]::-moz-range-track { height: 5px; border-radius: 999px; background: var(--bg-4); }
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  margin-top: -4.5px;
  border-radius: 50%;
  background: var(--accent);
  border: 0;
  transition: transform var(--fast) var(--ease);
}
input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.2); }
input[type="range"]::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: var(--accent); border: 0; }
input[type="range"]:disabled { opacity: 0.4; cursor: default; }

/* ─────────────── tabs ─────────────── */

.tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 14px;
  flex: none;
}
.tab {
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  padding: 10px 14px;
  color: var(--ink-3);
  font-weight: 550;
  cursor: pointer;
  transition: color var(--fast) var(--ease), border-color var(--mid) var(--ease);
}
.tab:hover { color: var(--ink-2); }
.tab.on { color: var(--ink); border-bottom-color: var(--accent); }
.badge {
  background: var(--bg-3);
  border-radius: 999px;
  padding: 1px 8px;
  font-size: 12px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.tab.on .badge { background: var(--accent-soft); color: var(--accent); }

.panel { animation: panel-in var(--mid) var(--ease) both; }
.panel[hidden] { display: none; }
@keyframes panel-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* ─────────────── lists ─────────────── */

.list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 8px 10px;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.row:hover { border-color: var(--line-2); }
.row-num { color: var(--ink-3); font-size: 12px; min-width: 16px; text-align: right; font-variant-numeric: tabular-nums; }
.row-thumb { width: 62px; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 7px; background: var(--bg-3); flex: none; }
.row-meta { flex: 1; min-width: 0; }
.row-title { font-size: 14px; font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-sub { font-size: 12px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-time { font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.row-actions { display: flex; gap: 4px; flex: none; }
.add-btn {
  background: var(--accent);
  border: 1px solid transparent;
  color: var(--accent-ink);
  border-radius: 9px;
  height: 34px;
  padding: 0 14px;
  cursor: pointer;
  font-weight: 550;
  flex: none;
  transition: filter var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.add-btn:hover { filter: brightness(1.06); transform: translateY(-1px); }

/* The per-row action cluster is too dense for a phone. Buttons marked `.opt`
   have another route to the same thing, so they are the ones that go. */
@media (max-width: 560px) {
  .row-actions .opt { display: none; }
  .row-num { display: none; }
  .row-time { display: none; }
  .code { font-size: 17px; letter-spacing: 0.12em; }
}

.clear { margin-top: 14px; }

/* ─────────────── search ─────────────── */

.search-form { display: flex; gap: 8px; margin-bottom: 10px; }
#q {
  flex: 1;
  min-width: 0;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  height: var(--tap);
  padding: 0 14px;
  transition: border-color var(--fast) var(--ease);
}
#q:focus { border-color: var(--accent); }
.status { color: var(--ink-3); font-size: 13px; min-height: 20px; margin: 0 0 10px; }

/* ─────────────── invite panel ─────────────── */

.share { text-align: center; padding: 8px 0 24px; }
.qr { border-radius: 12px; background: #fff; padding: 8px; max-width: 100%; height: auto; box-shadow: var(--shadow-sm); }
.share-code { font-family: var(--mono); font-size: 28px; font-weight: 700; letter-spacing: 0.2em; margin: 16px 0 2px; }
.share-url { color: var(--ink-3); font-size: 13px; word-break: break-all; margin: 0 0 16px; }
.share-actions { display: flex; gap: 8px; justify-content: center; margin-bottom: 22px; }
.namefield { display: block; max-width: 300px; margin: 0 auto; text-align: left; font-size: 13px; color: var(--ink-2); }
#name-input {
  display: block;
  width: 100%;
  margin-top: 6px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  height: var(--tap);
  padding: 0 14px;
}
#name-input:focus { border-color: var(--accent); }

/* ─────────────── toasts ─────────────── */

.toasts {
  position: fixed;
  left: 50%;
  bottom: calc(18px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 50;
  width: min(420px, calc(100vw - 24px));
  pointer-events: none;
}
.toast {
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: 12px;
  padding: 11px 15px;
  font-size: 14px;
  box-shadow: var(--shadow-lg);
  animation: rise var(--mid) var(--ease);
}
.toast-warn { border-color: var(--warn); color: var(--warn); }
.toast.out { opacity: 0; transform: translateY(4px); transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease); }
@keyframes rise { from { transform: translateY(10px); opacity: 0; } }

/* ─────────────── modals ─────────────── */

.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  overflow-y: auto;
  animation: fade-in var(--mid) var(--ease) both;
}
.modal-backdrop[hidden] { display: none; }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

.modal {
  position: relative;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 28px 26px;
  max-width: 620px;
  width: 100%;
  max-height: 88dvh;
  overflow-y: auto;
  box-shadow: var(--shadow-lg);
  animation: modal-in var(--mid) var(--ease) both;
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(14px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}
.modal-sm { max-width: 400px; }
.modal h2 { margin: 0 0 6px; font-size: 22px; }
.modal h3 { margin: 22px 0 6px; font-size: 13px; color: var(--accent); letter-spacing: 0.06em; text-transform: uppercase; font-family: var(--sans); font-weight: 600; }
.modal p { margin: 0; color: var(--ink-2); font-size: 14px; }
.modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  background: transparent;
  border: 0;
  color: var(--ink-3);
  cursor: pointer;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}
.modal-close:hover { color: var(--ink); background: var(--bg-3); }

.linklike {
  background: none;
  border: 0;
  padding: 0;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  font: inherit;
  transition: color var(--fast) var(--ease);
}
.linklike:hover { color: var(--accent); }
.muted-inline { color: var(--ink-3); font-weight: 400; font-size: 13px; }
.room-fine { color: var(--ink-3); font-size: 12px; margin: 18px 0 0; }
.code-plain { letter-spacing: 0; font-size: 20px; font-family: var(--serif); }

/* ─────────────── library ─────────────── */

.library[hidden] { display: none; }
.lib-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 14px; }
.lib-tab {
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  padding: 9px 12px;
  color: var(--ink-3);
  font-weight: 550;
  cursor: pointer;
  font-size: 14px;
  transition: color var(--fast) var(--ease), border-color var(--mid) var(--ease);
}
.lib-tab.on { color: var(--ink); border-bottom-color: var(--accent); }
.lib-panel { animation: panel-in var(--mid) var(--ease) both; }
.lib-panel[hidden] { display: none; }

.pl {
  border: 1px solid var(--line);
  border-radius: 12px;
  margin-bottom: 8px;
  overflow: hidden;
  background: var(--bg-2);
  transition: border-color var(--fast) var(--ease);
}
.pl:hover { border-color: var(--line-2); }
.pl-head { display: flex; align-items: center; gap: 8px; padding: 8px 10px; }
.pl-toggle {
  background: none;
  border: 0;
  color: var(--ink);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  padding: 6px 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pl-count { color: var(--ink-3); font-size: 12px; flex: none; }
.pl-actions { display: flex; gap: 4px; flex: none; }
.pl-songs { padding: 0 10px 10px; }

.new-playlist { display: flex; gap: 8px; margin-top: 14px; }
.new-playlist input {
  flex: 1;
  min-width: 0;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  height: var(--tap);
  padding: 0 14px;
}
.new-playlist input:focus { border-color: var(--accent); }
.lib-foot { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line); }

.icon-btn.star.on { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 50%, transparent); background: var(--accent-soft); }

.picker-song { color: var(--ink-2); font-size: 13px; margin: 0 0 14px; }
.picker-list { list-style: none; margin: 0 0 6px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.picker-item {
  width: 100%;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--bg-3);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  cursor: pointer;
  font-weight: 550;
  transition: border-color var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.picker-item:hover:not(:disabled) { border-color: var(--accent); transform: translateX(2px); }
.picker-item:disabled { color: var(--ink-3); cursor: default; }

/* ─────────────── resume / install banners ─────────────── */

.resume, .install-bar {
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: var(--radius);
  padding: 16px 18px;
  margin: 0 0 22px;
  font-size: 14px;
  animation: chip-in var(--slow) var(--ease) both;
}
.resume[hidden], .install-bar[hidden] { display: none; }
.resume p { margin: 0 0 12px; }
.resume-actions { display: flex; gap: 8px; justify-content: center; }

.install-bar { display: flex; align-items: center; gap: 14px; text-align: left; }
.install-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.install-text strong { font-size: 15px; }
.install-text span { color: var(--ink-2); font-size: 13px; }
.install-actions { display: flex; align-items: center; gap: 8px; flex: none; }

@media (max-width: 560px) {
  .install-bar { flex-direction: column; align-items: stretch; }
  .install-actions { justify-content: space-between; }
  .install-actions .btn-primary { flex: 1; }
}

/* ─────────────── invite rail ─────────────── */

.invite-rail { display: none; }
.invite-rail[hidden] { display: none !important; }

/* ─────────────── room layout ─────────────── */

.room-body { display: flex; flex-direction: column; gap: 14px; }
.stage-col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.side-col { display: flex; flex-direction: column; min-width: 0; }
.panels { min-width: 0; }

/* ── host stage layout: one screen, nothing scrolls but the side list ──
   The host is a TV or a laptop someone glances at from across the room:
   video, what's playing, the controls and the queue all have to be visible
   at once. The page itself is locked to the viewport and only the side
   panel scrolls internally. Guests keep the ordinary flowing page. */
@media (min-width: 900px) and (min-height: 560px) {
  body.is-host { overflow: hidden; }
  body.is-host #view-room {
    max-width: 1560px;
    height: 100dvh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 0 24px calc(18px + env(safe-area-inset-bottom));
  }
  body.is-host .room-body {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr) clamp(340px, 28vw, 430px);
    gap: 20px;
    overflow: hidden;
  }
  body.is-host .stage-col { min-height: 0; }
  body.is-host .stage {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  body.is-host .yt-mount { height: 100%; width: auto; max-width: 100%; aspect-ratio: 16 / 9; }
  body.is-host .side-col { min-height: 0; overflow: hidden; }
  body.is-host .panels { flex: 1; min-height: 0; overflow-y: auto; padding-right: 4px; }
  body.is-host .panel[data-panel="queue"] { display: flex; flex-direction: column; }
  /* Same trade as the phone: the reorder arrows have "play next" as another
     route, so they are what gives way to the song title in a narrow column. */
  body.is-host .side-col .row-actions .opt,
  body.is-host .side-col .row-num,
  body.is-host .side-col .row-time { display: none; }
  body.is-host .share { padding-top: 0; }

  /* The join code lives permanently above the tabs — the single thing a new
     guest needs, never more than a glance away. */
  body.is-host .invite-rail {
    display: block;
    flex: none;
    background: var(--bg-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    margin-bottom: 14px;
    overflow: hidden;
    box-shadow: var(--shadow-sm);
  }
  .rail-body {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 14px;
    transition: opacity var(--mid) var(--ease);
  }
  .rail-body .qr { width: 96px; height: 96px; flex: none; padding: 6px; }
  .rail-meta { min-width: 0; }
  .rail-code { font-family: var(--mono); font-size: 24px; font-weight: 700; letter-spacing: 0.16em; margin: 0; }
  .rail-hint { color: var(--ink-3); font-size: 12px; margin: 4px 0 0; }
  .rail-toggle {
    width: 100%;
    background: transparent;
    border: 0;
    border-top: 1px solid var(--line);
    color: var(--ink-3);
    cursor: pointer;
    padding: 7px 0;
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    transition: color var(--fast) var(--ease), background var(--fast) var(--ease);
  }
  .rail-toggle:hover { color: var(--accent); background: var(--bg-3); }
  body.is-host .invite-rail.collapsed .rail-body { display: none; }
  body.is-host .invite-rail.collapsed .rail-toggle { border-top: 0; }
}

/* Big-screen / TV: everything scales up a notch. */
@media (min-width: 1600px) {
  html { font-size: 17px; }
  .code { font-size: 22px; }
}

/* ─────────────── phones ─────────────── */

@media (max-width: 720px) {
  .view { padding: 0 14px 28px; }
  .hero { padding: 24px 0 8px; }

  .room-head {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 6px 8px;
    padding: 10px 0;
  }
  .head-left { min-width: 0; }
  .head-left .label { display: none; }
  .head-right { justify-self: end; }

  .now-thumb { width: 76px; }
  .now-title { font-size: 16px; }

  .transport { padding: 10px 12px 12px; }
  .buttons { flex-wrap: wrap; row-gap: 10px; }
  .buttons #vol { order: 5; flex-basis: 100%; }

  .tabs { gap: 0; overflow-x: auto; scrollbar-width: none; }
  .tabs::-webkit-scrollbar { display: none; }
  .tab { padding: 10px 11px; font-size: 14px; white-space: nowrap; }

  .row { padding: 7px 8px; gap: 8px; }
  .row-thumb { width: 54px; }
  .row-title { font-size: 13px; }
  .add-btn { padding: 0 12px; }
  .row-actions { gap: 3px; }

  /* Stack the search field over its button — a 2-up row leaves neither usable. */
  .search-form { flex-wrap: wrap; }
  .search-form #q { flex: 1 1 100%; }
  .search-form .btn { flex: 1 1 100%; }

  .lib-foot .btn { flex: 1; }
  .modal { padding: 24px 20px; }
}

/* Installed, there is no browser chrome to scroll away — pad for the notch. */
@media (display-mode: standalone) {
  .room-head, .home-head { padding-top: max(12px, env(safe-area-inset-top)); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
