/* Guilty Pleasures. Each song's cover art colours the whole screen and the music is a
   spinning mix CD. Lists and type do the work; the only fixed surface is the host's bar. */
:root {
  --base: #120d18;
  --text: #fbf8ff;
  --text-2: rgba(251, 248, 255, 0.74);
  --text-3: rgba(251, 248, 255, 0.5);
  --line: rgba(251, 248, 255, 0.14);
  --fill: rgba(251, 248, 255, 0.13);
  --fill-2: rgba(251, 248, 255, 0.22);
  --right: #8ff0c8;
  --right-ink: #0f2a20;
  --display: 'Gloock', Georgia, 'Times New Roman', serif;
  --body: 'Onest', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --iridescent: conic-gradient(from 20deg, #f4f6fb, #ffcdee, #c6efff, #fff4c2, #ded0ff, #f4f6fb, #ffcdee, #c6efff, #fff4c2, #ded0ff, #f4f6fb);
  color-scheme: dark;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; background: var(--base); }
/* Laptops and TVs: every size is in rem, so this one value scales the whole page for the sofa
   (about 16px on a laptop, 21px at 1920x1080, 42px at 3840x2160). */
@media (min-width: 1000px) and (min-height: 600px) { html { font-size: clamp(100%, calc(0.5vw + 1.05vh), 275%); } }
body { margin: 0; min-height: 100dvh; background: transparent; color: var(--text); font: 1rem/1.45 var(--body); -webkit-font-smoothing: antialiased; }
button, input, select { font: inherit; color: inherit; }
img { max-width: 100%; display: block; }
a { color: inherit; }
:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* ---- backdrop: the current cover, blurred into a colour field ---------------------- */
#backdrop { position: fixed; inset: 0; z-index: -1; overflow: hidden; background: var(--base); }
#backdrop .default {
  position: absolute; inset: 0; transition: opacity 0.8s ease;
  background:
    radial-gradient(70% 45% at 10% 4%, #5c2452 0%, rgba(92, 36, 82, 0) 70%),
    radial-gradient(60% 45% at 96% 26%, #1d5563 0%, rgba(29, 85, 99, 0) 70%),
    radial-gradient(85% 55% at 45% 106%, #7f3522 0%, rgba(127, 53, 34, 0) 70%);
}
#backdrop .layer { position: absolute; inset: -25%; background-position: center; background-size: cover; filter: blur(64px) saturate(1.6); opacity: 0; transition: opacity 0.8s ease; }
#backdrop .layer.on { opacity: 1; }
#backdrop .shade { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(18, 13, 24, 0.34) 0%, rgba(18, 13, 24, 0.5) 32%, rgba(18, 13, 24, 0.84) 66%, rgba(18, 13, 24, 0.95) 100%); }

/* ---- layout ------------------------------------------------------------------------ */
#app {
  max-width: 30rem; margin: 0 auto;
  padding-top: max(0.75rem, env(safe-area-inset-top));
  padding-bottom: 10.625rem;
  padding-left: max(1.25rem, env(safe-area-inset-left));
  padding-right: max(1.25rem, env(safe-area-inset-right));
}
.stack { display: flex; flex-direction: column; gap: 0.75rem; }
.section { margin-top: 1.875rem; }
.center { text-align: center; }
.play-grid { display: grid; gap: 0.25rem; }
/* Host screens on a laptop or TV spread out. Phones, portrait tablets and the players' screens
   keep one column, scaled by the root size above. Each screen's big layout sits in its section. */
@media (min-width: 800px) and (min-height: 500px) and (orientation: landscape) {
  #app.wide { max-width: min(94vw, 112rem); }
  #app.wide .play-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 3.5rem; align-items: start; }
  #app.wide .play-grid > :first-child { position: sticky; top: 1.5rem; }
  /* The host's laptop may be on the TV: make the disc and title read from the sofa. */
  #app.wide .disc-wrap:not(.small) { width: 22.5rem; }
  #app.wide .np .song { font-size: 2.9rem; }
  #app.wide .np .by { font-size: 1.15rem; }
}

/* ---- type -------------------------------------------------------------------------- */
h1, h2, h3 { font-family: var(--display); font-weight: 400; margin: 0; letter-spacing: -0.005em; text-wrap: balance; }
h1 { font-size: clamp(3rem, 15vw, 4.2rem); line-height: 0.95; }
h2 { font-size: 1.9rem; line-height: 1.08; }
h3 { font-size: 1.45rem; line-height: 1.15; }
p { margin: 0; }
.lede { font-size: 1.125rem; color: var(--text-2); max-width: 32ch; margin-top: 1.125rem; text-wrap: pretty; }
.muted { color: var(--text-2); }
.faint { color: var(--text-3); }
.small { font-size: 0.875rem; }
.num { font-variant-numeric: tabular-nums; }
.label { font-size: 0.875rem; color: var(--text-2); margin-bottom: 0.5rem; }

/* ---- status bar -------------------------------------------------------------------- */
.status { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 0.625rem; min-height: 2.75rem; font-size: 0.875rem; }
.status .code { font-weight: 600; letter-spacing: 0.16em; }
.status .mid { color: var(--text-2); text-align: center; }
.status .end { justify-self: end; display: flex; gap: 0.5rem; align-items: center; }
.icon-btn { width: 2.625rem; height: 2.625rem; border-radius: 50%; border: 0; padding: 0; background: var(--fill); display: grid; place-items: center; cursor: pointer; touch-action: manipulation; }
.icon-btn[aria-pressed="true"] { background: #fff; color: var(--base); }
.icon-btn svg { width: 1.25rem; height: 1.25rem; }
.textbtn { background: none; border: 0; padding: 0.625rem 0; color: var(--text-2); font-weight: 500; cursor: pointer; text-decoration: underline; text-underline-offset: 0.1875rem; }

/* ---- buttons and fields ------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  min-height: 3.375rem; padding: 0 1.5rem; border: 0; border-radius: 62.4375rem;
  background: #fff; color: var(--base); font-weight: 600; font-size: 1.0625rem;
  cursor: pointer; text-decoration: none; touch-action: manipulation; transition: transform 0.1s ease;
}
.btn:active:not(:disabled) { transform: scale(0.98); }
.btn:disabled { background: var(--fill); color: var(--text-3); cursor: default; }
.btn.block { width: 100%; }
.btn.soft { background: var(--fill); color: var(--text); }
.btn.small { min-height: 2.5rem; padding: 0 1rem; font-size: 0.9375rem; }
.row-btns { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.field { display: flex; flex-direction: column; gap: 0.5rem; }
.field > span { font-size: 0.875rem; color: var(--text-2); }
.input {
  width: 100%; min-height: 3.375rem; padding: 0 1.125rem; border-radius: 0.875rem;
  border: 1px solid var(--line); background: rgba(255, 255, 255, 0.07); color: var(--text); font-size: 1.0625rem;
}
.input::placeholder { color: var(--text-3); }
.input:focus { outline: none; border-color: rgba(255, 255, 255, 0.6); background: rgba(255, 255, 255, 0.1); }
.input.code { font-size: 1.8rem; font-weight: 600; letter-spacing: 0.34em; text-transform: uppercase; text-align: center; padding-left: 0.34em; }
.choices { display: flex; flex-direction: column; gap: 0.625rem; }
.choice { display: block; width: 100%; text-align: left; padding: 0.875rem 1rem; border-radius: 0.875rem; border: 1px solid var(--line); background: rgba(255, 255, 255, 0.05); cursor: pointer; }
.choice b { display: block; font-weight: 600; }
.choice small { display: block; color: var(--text-2); font-size: 0.875rem; margin-top: 0.1875rem; }
.choice[aria-pressed="true"] { border-color: #fff; background: rgba(255, 255, 255, 0.12); box-shadow: inset 0 0 0 1px #fff; }
.error-text { color: #ffb3b3; font-weight: 600; min-height: 1.45em; }
.select {
  appearance: none; border: 0; border-radius: 0.625rem; min-height: 2.5rem; padding: 0 2.125rem 0 0.75rem; max-width: 58%;
  background: var(--fill) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23fbf8ff' stroke-width='1.6'/%3E%3C/svg%3E") no-repeat right 0.75rem center / 0.75rem 0.5rem;
  color: var(--text); font-size: 0.9375rem;
}
.select option { background: #241a2b; color: var(--text); }
.select.full { width: 100%; max-width: none; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
@media (max-width: 420px) { .select.full { font-size: 0.875rem; } }
.switch { appearance: none; flex: none; width: 3rem; height: 1.75rem; border-radius: 62.4375rem; background: var(--fill-2); position: relative; cursor: pointer; transition: background 0.2s; margin: 0; }
.switch::before { content: ''; position: absolute; top: 0.1875rem; left: 0.1875rem; width: 1.375rem; height: 1.375rem; border-radius: 50%; background: #fff; transition: transform 0.2s; }
.switch:checked { background: var(--right); }
.switch:checked::before { transform: translateX(1.25rem); background: var(--right-ink); }

/* ---- lists ------------------------------------------------------------------------- */
.head { display: flex; justify-content: space-between; align-items: baseline; gap: 0.75rem; }
.head .aside { font-size: 0.875rem; color: var(--text-2); }
.list { list-style: none; margin: 0.625rem 0 0; padding: 0; }
.list > li { border-top: 1px solid var(--line); }
.row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 0.875rem; align-items: center;
  width: 100%; min-height: 3.625rem; padding: 0.625rem 0; text-align: left; background: none; border: 0;
}
.row.two { grid-template-columns: minmax(0, 1fr) auto; }
button.row { cursor: pointer; touch-action: manipulation; }
.thumb { width: 2.75rem; height: 2.75rem; border-radius: 0.5rem; object-fit: cover; background: var(--fill); flex: none; }
.t { font-weight: 600; line-height: 1.2; min-width: 0; }
.t .line, .t small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t small { font-weight: 400; font-size: 0.875rem; color: var(--text-2); margin-top: 0.125rem; }
.end-text { font-weight: 600; text-align: right; }
.end-text.dim { color: var(--text-3); font-weight: 400; font-style: italic; }
.tags { display: inline-flex; gap: 0.375rem; margin-left: 0.5rem; vertical-align: 0.0625rem; }
.tag { font-size: 0.75rem; font-weight: 600; padding: 0.125rem 0.5rem; border-radius: 62.4375rem; background: var(--fill); color: var(--text-2); }
.tag.good { background: var(--right); color: var(--right-ink); font-size: 0.9375rem; padding: 0.5rem 0.875rem; }
.kick { background: none; border: 0; color: var(--text-3); cursor: pointer; padding: 0.5rem; font-size: 1.1rem; line-height: 1; }

/* ---- chips (names) ----------------------------------------------------------------- */
.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.chip { min-height: 2.875rem; padding: 0 1.125rem; border-radius: 62.4375rem; border: 0; background: var(--fill); font-weight: 600; font-size: 1rem; cursor: pointer; touch-action: manipulation; }
.chip[aria-pressed="true"] { background: #fff; color: var(--base); }
.chip.small { min-height: 2.5rem; padding: 0 0.875rem; font-size: 0.9375rem; }
.row-chips { padding: 0 0 0.875rem 3.625rem; }

/* ---- the disc ---------------------------------------------------------------------- */
.disc-wrap { position: relative; width: min(66vw, 15.625rem); aspect-ratio: 1; margin: 1rem auto 0; }
.disc-wrap.small { width: min(46vw, 10.75rem); }
.disc-wrap .ring { position: absolute; inset: 0; transform: rotate(-90deg); }
.disc-wrap .ring circle { fill: none; stroke-width: 1.6; }
.disc-wrap .ring .track { stroke: rgba(255, 255, 255, 0.16); }
.disc-wrap .ring .bar { stroke: #fff; stroke-linecap: round; }
.disc {
  position: absolute; inset: 5%; border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0) 30%, rgba(255, 255, 255, 0.55) 31%, rgba(255, 255, 255, 0) 33%), var(--iridescent);
  box-shadow: 0 26px 50px -18px rgba(0, 0, 0, 0.65), inset 0 0 0 1px rgba(255, 255, 255, 0.45);
}
.disc .label { position: absolute; inset: 24%; border-radius: 50%; overflow: hidden; background: radial-gradient(circle at 40% 35%, #4a2a4f, #1d1424); }
.disc .label img { width: 100%; height: 100%; object-fit: cover; }
.disc .hub { position: absolute; left: 50%; top: 50%; width: 9%; aspect-ratio: 1; transform: translate(-50%, -50%); border-radius: 50%; background: var(--base); box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.4); }
.disc.spin { animation: spin 7s linear infinite; }
.disc.settle { animation: settle 2.6s cubic-bezier(0.12, 0.62, 0.3, 1) both; }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes settle { from { transform: rotate(0deg); } to { transform: rotate(600deg); } }

/* ---- home: one screen, no scrolling --------------------------------------------- */
#app.home { padding-bottom: max(1rem, env(safe-area-inset-bottom)); }
.home-screen {
  display: flex; flex-direction: column;
  min-height: calc(100dvh - max(0.75rem, env(safe-area-inset-top)) - max(1rem, env(safe-area-inset-bottom)));
}
.hero { position: relative; isolation: isolate; height: min(30vh, 15.625rem); flex: none; margin: 0 calc(-1 * max(1.25rem, env(safe-area-inset-right))) 0 0; overflow: hidden; display: flex; align-items: flex-end; }
.hero .disc-wrap { position: absolute; top: -1.125rem; right: -3.75rem; width: min(60vw, 15.625rem); margin: 0; }
/* The title inverts where it crosses the disc, so both stay readable. */
.hero h1 { position: relative; font-size: clamp(2.7rem, 13vw, 3.7rem); padding-bottom: 0.25rem; mix-blend-mode: difference; }
.home-screen .lede { margin-top: 0.75rem; font-size: 1.0625rem; }
.home-actions { margin-top: auto; padding-top: 1.375rem; display: flex; flex-direction: column; gap: 0.75rem; }
.join-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.625rem; }
.join-row .input.code { font-size: 1.5rem; letter-spacing: 0.3em; padding-left: 0.3em; }
.join-row .btn { padding: 0 1.75rem; }
.home-actions .faint { text-wrap: balance; }
.home-foot { display: flex; justify-content: space-between; align-items: center; gap: 0.75rem; margin-top: 1rem; }
details summary { cursor: pointer; list-style: none; }
details summary::-webkit-details-marker { display: none; }
.disclosure { display: flex; justify-content: space-between; align-items: center; gap: 0.75rem; padding: 0.875rem 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.disclosure::after { content: ''; width: 0.5625rem; height: 0.5625rem; border-right: 2px solid var(--text-2); border-bottom: 2px solid var(--text-2); transform: rotate(45deg); transition: transform 0.2s; margin-right: 0.25rem; }
details[open] > .disclosure::after { transform: rotate(-135deg); }

/* ---- panels that slide up: how to play, song search, game settings ------------------------ */
body.locked { overflow: hidden; }
.sheet {
  position: fixed; inset: 0; z-index: 50; overflow-y: auto; transform: translateY(100%); transition: transform 0.26s ease;
  background: radial-gradient(70% 45% at 10% 4%, #5c2452 0%, rgba(92, 36, 82, 0) 70%), radial-gradient(60% 45% at 96% 26%, #1d5563 0%, rgba(29, 85, 99, 0) 70%), var(--base);
}
.sheet.open { transform: none; }
.sheet-in {
  max-width: 30rem; min-height: 100%; margin: 0 auto; display: flex; flex-direction: column; gap: 1.5rem;
  padding: max(1rem, env(safe-area-inset-top)) max(1.25rem, env(safe-area-inset-right)) max(1.25rem, env(safe-area-inset-bottom)) max(1.25rem, env(safe-area-inset-left));
}
.sheet-head { display: flex; justify-content: space-between; align-items: center; gap: 0.75rem; padding-top: 0.5rem; }
.sheet-head h2 { font-size: 2.3rem; }
.howto-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1.25rem; }
.howto-steps li { display: grid; grid-template-columns: 2.25rem minmax(0, 1fr); gap: 0.875rem; align-items: start; }
.howto-steps .n { font-family: var(--display); font-size: 2rem; line-height: 1; color: var(--text-3); }
.howto-steps b { display: block; font-weight: 600; font-size: 1.0625rem; margin-bottom: 0.1875rem; }
.howto-steps .muted { display: block; }
.sheet-end { margin-top: auto; }

/* ---- lobby ------------------------------------------------------------------------- */
.lobby-first { margin-top: 1.125rem; }
/* The big screen's two columns. Elsewhere they add no boxes, so the lobby is one column as before. */
.lobby-grid, .lobby-join, .lobby-main { display: contents; }

/* One page: the players list takes whatever room is left and scrolls on its own, fading at
   its edges instead of sitting in a box. */
#app.fit { height: 100dvh; display: flex; flex-direction: column; overflow-y: auto; padding-bottom: max(1rem, env(safe-area-inset-bottom)); }
#app.fit > *, .lobby-join > *, .lobby-main > * { flex: none; }
#app.fit .players-section { flex: 1 1 auto; min-height: 9.375rem; display: flex; flex-direction: column; }
.players-scroll {
  flex: 1; min-height: 0; overflow-y: auto; margin-top: 0.625rem; padding-bottom: 0.875rem; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 8px, #000 calc(100% - 16px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 8px, #000 calc(100% - 16px), transparent 100%);
}
.players-scroll::-webkit-scrollbar { display: none; }
.players-scroll .list { margin-top: 0; }
.dock-space { height: 6.875rem; }
.search-open { margin-top: 0.75rem; text-align: left; color: var(--text-3); cursor: text; }
/* The host's question: in the lobby, and first in the song panel. */
.prompt { font-family: var(--display); font-size: 1.35rem; line-height: 1.2; color: var(--text); text-wrap: balance; }
.head + .prompt { margin-top: 0.375rem; }
.settings-open { width: 100%; margin-top: 1.125rem; background: none; border-left: 0; border-right: 0; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.disclosure.up::after { transform: rotate(-135deg); margin-top: 0.375rem; }
/* Short screens (iPhone SE and similar): tighter spacing so the host's lobby still fits. */
@media (max-height: 740px) {
  #app.fit .section { margin-top: 1.125rem; }
  #app.fit .players-section { min-height: 6.875rem; }
  #app.fit .status { min-height: 2.5rem; }
  #app.fit .invite { grid-template-columns: 5.25rem minmax(0, 1fr); gap: 0.875rem; }
  #app.fit .qr { width: 5.25rem; height: 5.25rem; padding: 0.375rem; border-radius: 0.75rem; }
  #app.fit .code-big { font-size: 1.75rem; }
  #app.fit .invite .link { margin: 0 0 0.5rem; }
  #app.fit .settings-open { margin-top: 0.5rem; padding: 0.625rem 0; }
  #app.fit .lobby-first { margin-top: 0.625rem; }
}
/* A host playing on a short phone has the invite as well as the question: tighter again. */
@media (max-height: 740px) and (max-width: 999px) {
  #app.wide.fit .section { margin-top: 0.875rem; }
  #app.wide.fit .prompt { font-size: 1.1rem; }
  #app.wide.fit .head + .prompt { margin-top: 0.25rem; }
  #app.wide.fit .search-open { min-height: 3rem; margin-top: 0.5rem; }
  #app.wide.fit .settings-open { padding: 0.5rem 0; }
  #app.wide.fit .dock-space { height: 6.25rem; }
}
.invite { display: grid; grid-template-columns: 7rem minmax(0, 1fr); gap: 1.125rem; align-items: center; }
.qr { width: 7rem; height: 7rem; border-radius: 0.875rem; background: #fff; padding: 0.5rem; }
.code-big { font-weight: 600; font-size: 2.2rem; line-height: 1.1; letter-spacing: 0.2em; }
.invite .link { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 0.8125rem; margin: 0.125rem 0 0.625rem; }
.results { margin-top: 0.625rem; }
.result { grid-template-columns: 2.75rem minmax(0, 1fr) 2.75rem; }
.result.picked { background: rgba(255, 255, 255, 0.06); }
.play-btn { width: 2.75rem; height: 2.75rem; border-radius: 50%; border: 0; background: var(--fill); display: grid; place-items: center; cursor: pointer; }
.play-btn svg { width: 1rem; height: 1rem; }
.confirm { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--line); }
.settings-body { padding: 0.25rem 0 0.5rem; }
.setting { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.75rem 0; border-bottom: 1px solid var(--line); }
.setting > span { min-width: 0; }
.setting b { display: block; font-weight: 600; }
.setting small { display: block; color: var(--text-3); font-size: 0.8125rem; margin-top: 0.125rem; }
/* The question row: label and hint above, then the choice and the host's own words at full width. */
.setting.stacked { flex-direction: column; align-items: stretch; gap: 0.625rem; }
#set-prompt-custom { min-height: 2.875rem; font-size: 1rem; }

/* Laptop or TV: the QR and code big on the left, to scan and read from the sofa; the question,
   players and settings on the right. Still one page with no scrolling: the QR takes the height
   the code, link and buttons under it leave (cqh is the height of the two columns). */
@media (min-width: 800px) and (min-height: 500px) and (orientation: landscape) {
  #app.wide > .lobby-grid {
    display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); column-gap: clamp(2.5rem, 5vw, 7rem);
    flex: 1 1 0; min-height: 0; margin-top: 1.125rem; container-type: size;
  }
  #app.wide .lobby-join, #app.wide .lobby-main { display: flex; flex-direction: column; min-height: 0; }
  #app.wide .lobby-join > .invite, #app.wide .lobby-main > :first-child { margin-top: 0; }
  #app.wide.fit .invite {
    --code: min(10vh, 6vw);
    --qr: max(7rem, min(58vh, 36vw, calc(100cqh - 7.6rem - 1.1 * var(--code))));
    grid-template-columns: var(--qr); gap: 1rem; align-items: start;
  }
  #app.wide.fit .qr { width: var(--qr); height: var(--qr); padding: calc(var(--qr) * 0.05); border-radius: 1.25rem; }
  #app.wide.fit .code-big { font-size: var(--code); line-height: 1.1; }
  #app.wide.fit .invite .small { font-size: 1rem; }
  #app.wide.fit .invite .link { margin: 0.125rem 0 0.75rem; }
  #app.wide .lobby-main .prompt { font-size: 1.75rem; line-height: 1.15; }
  #app.wide .lobby-main .prompt + .muted { font-size: 1.125rem; max-width: 46em; }
  #app.wide.fit .players-section { min-height: 6.875rem; }
}

/* ---- now playing ------------------------------------------------------------------- */
.np { text-align: center; margin-top: 1rem; }
.np .song { font-family: var(--display); font-size: 2rem; line-height: 1.05; text-wrap: balance; overflow-wrap: anywhere; }
.np .by { color: var(--text-2); margin-top: 0.375rem; }
.np .left { color: var(--text-3); font-size: 0.875rem; margin-top: 0.375rem; }
/* The shared screen's two sides. On a phone they stack with the same spacing as before. */
.play-grid.shared { gap: 0; }
.play-grid.shared .np + .section { margin-top: 2.125rem; }
@media (min-width: 800px) and (min-height: 500px) and (orientation: landscape) {
  /* A screen the whole room watches: the disc on the left, the song in big type beside it. */
  #app.wide .play-grid.shared {
    grid-template-columns: auto minmax(0, 1fr); align-items: center; align-content: center; gap: clamp(2.5rem, 5vw, 7rem);
    min-height: calc(100dvh - 14.25rem);
  }
  #app.wide .play-grid.shared > .disc-side { position: static; }
  #app.wide .play-grid.shared .disc-wrap { width: min(62vh, 40vw); margin: 0; }
  #app.wide .play-grid.shared .np { text-align: left; margin-top: 0; }
  #app.wide .play-grid.shared .np .song { font-size: clamp(2.9rem, 7vh, 9rem); line-height: 1; }
  #app.wide .play-grid.shared .np .by { font-size: 1.5rem; margin-top: 0.75rem; }
  #app.wide .play-grid.shared .np .left { font-size: 1.125rem; margin-top: 0.5rem; }
  #app.wide .play-grid.shared .np + .section { margin-top: 3rem; }
}

/* ---- last chance -------------------------------------------------------------------- */
.countdown { font-family: var(--display); font-size: 2.4rem; line-height: 1; font-variant-numeric: tabular-nums; }
.timebar { height: 0.25rem; border-radius: 0.25rem; background: var(--fill); margin-top: 1rem; overflow: hidden; }
.timebar i { display: block; height: 100%; width: 100%; background: #fff; transition: width 0.25s linear; }
.review-row { display: grid; grid-template-columns: 2.75rem minmax(0, 1fr); gap: 0.875rem; align-items: center; }
.row:disabled { cursor: default; }
@media (min-width: 800px) and (min-height: 500px) and (orientation: landscape) {
  /* The clock big on the left, the songs on the right. */
  #app.wide .review-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: clamp(2.5rem, 5vw, 7rem); align-items: start; }
  #app.wide .review-head { position: sticky; top: 1.5rem; }
  #app.wide .review-head .head { flex-direction: column; align-items: flex-start; gap: 0.5rem; }
  #app.wide .review-head .muted { font-size: 1.125rem; }
  #app.wide .countdown { font-size: clamp(2.4rem, 13vh, 13rem); }
  #app.wide .review-list { margin-top: 1.125rem; }
}

/* ---- results ------------------------------------------------------------------------ */
.results-title { margin-top: 1.125rem; font-size: clamp(2.5rem, 12vw, 3.3rem); line-height: 1; }
.result-row.in { animation: fade 0.5s ease both; }
.owner { font-family: var(--display); font-size: 1.3rem; line-height: 1.1; text-align: right; }
.owner small { display: block; font-family: var(--body); font-size: 0.8125rem; color: var(--text-3); margin-top: 0.1875rem; }
.guesses { display: flex; flex-direction: column; gap: 0.375rem; padding: 0 0 0.875rem 3.625rem; font-size: 0.9375rem; color: var(--text-2); }
.guesses b { color: var(--text); font-weight: 600; }
.guesses .pts { color: var(--right); font-weight: 700; }
@keyframes rise { from { opacity: 0; transform: translateY(18px) scale(0.94); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
/* The replay: the song that's playing on the disc, then, after a beat, who picked it. */
.reel { margin-top: 0.5rem; text-align: center; }
.reel-text { margin-top: 1rem; }
.reel .song { font-family: var(--display); font-size: 1.75rem; line-height: 1.05; text-wrap: balance; overflow-wrap: anywhere; }
.reel .by { color: var(--text-2); margin-top: 0.375rem; }
.reveal { margin-top: 1.25rem; animation: rise 0.5s ease both; }
.reveal .label { margin-bottom: 0.125rem; }
.owner-name { font-family: var(--display); font-size: 2.6rem; line-height: 1; text-wrap: balance; overflow-wrap: anywhere; }
.reveal .got { color: var(--text-2); margin-top: 0.625rem; }
.reveal .mine { font-weight: 600; margin-top: 0.25rem; }
.reveal .why { color: var(--text-2); margin-top: 0.625rem; text-wrap: pretty; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.results-title.replaying { font-size: clamp(2rem, 8.5vw, 2.4rem); }
/* The host's two replay buttons share a row: Next song takes the room, Skip the replay its own width. */
.replay-btns { display: flex; gap: 0.5rem; }
.replay-btns > .btn { flex: 1 1 auto; white-space: nowrap; }
.replay-btns > .btn.soft { flex: none; padding: 0 1.125rem; }
/* Short phones: the small disc and less space, so the name shows without scrolling. */
@media (max-height: 740px) {
  .reel { margin-top: 0.25rem; }
  .reel .disc-wrap { width: min(46vw, 10.75rem); margin-top: 0.5rem; }
  .reel-text { margin-top: 0.625rem; }
  .reel .song { font-size: 1.5rem; }
  .reveal { margin-top: 0.75rem; }
}
@media (min-width: 800px) and (min-height: 500px) and (orientation: landscape) {
  /* The disc on the left, the name large beside it. The disc stays clear of the host's bar, and
     the songs already played wait for the full list, so nothing sits behind the bar. */
  #app.wide .reel {
    display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; align-content: start; gap: clamp(2.5rem, 5vw, 7rem);
    margin-top: 1.5rem; text-align: left;
  }
  #app.wide .reel .reel-disc .disc-wrap { width: min(56vh, 38vw, calc(100dvh - 22rem)); margin: 0; }
  #app.wide .reel-text { margin-top: 0; }
  #app.wide .reel:not([hidden]) ~ .results-list { display: none; }
  #app.wide .reel .song { font-size: clamp(2rem, 5.5vh, 6rem); }
  #app.wide .reel .by { font-size: 1.35rem; margin-top: 0.5rem; }
  #app.wide .reveal { margin-top: 2.25rem; }
  #app.wide .reveal .label { font-size: 1.125rem; }
  #app.wide .owner-name { font-size: clamp(3rem, 10vh, 11rem); line-height: 0.95; }
  #app.wide .reveal .got, #app.wide .reveal .mine, #app.wide .reveal .why { font-size: 1.35rem; }
  #app.wide .results-title.replaying { font-size: clamp(2.5rem, 12vw, 3.3rem); }
  /* After the replay the title, summary and list share one centred column. */
  #app.wide .results-list { max-width: 56rem; margin-inline: auto; }
  #app.wide .results-title ~ .lede { margin-left: max(0rem, (100% - 56rem) / 2); }
  #app.wide:has(> .reel[hidden]) .results-title { margin-left: max(0rem, (100% - 56rem) / 2); }
}

@media (min-width: 800px) and (min-height: 500px) and (max-height: 720px) and (orientation: landscape) {
  /* A laptop window with its browser bars: less space round the name, so it all clears the host's bar. */
  #app.wide .reel .song { font-size: clamp(1.75rem, 5vh, 6rem); }
  #app.wide .reveal { margin-top: 1.25rem; }
  #app.wide .owner-name { font-size: clamp(2.5rem, 9vh, 11rem); }
}

/* ---- final ------------------------------------------------------------------------- */
.podium { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: end; gap: 0.625rem; margin-top: 1.875rem; }
.step { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; text-align: center; min-width: 0; }
.step .nm { font-weight: 600; line-height: 1.15; overflow-wrap: anywhere; }
.step.first .nm { font-family: var(--display); font-weight: 400; font-size: 1.6rem; animation: fade 0.5s ease 1.5s both; }
.step .block { width: 100%; border-radius: 0.875rem 0.875rem 0 0; background: var(--fill); display: flex; flex-direction: column; align-items: center; padding-top: 0.75rem; transform-origin: bottom; animation: grow 0.7s cubic-bezier(0.2, 1.2, 0.4, 1) both; }
/* Gold, silver and bronze. */
.step.first .block { height: 10.5rem; background: linear-gradient(160deg, #fbe9a8 0%, #e3bb45 42%, #b98a26 100%); color: #2b1d04; animation-delay: 1s; }
.step.second .block { height: 7.625rem; background: linear-gradient(160deg, #f6f7fa 0%, #cdd0d8 45%, #9da2ad 100%); color: #1c1e25; animation-delay: 0.5s; }
.step.third .block { height: 5.5rem; background: linear-gradient(160deg, #f3c9a2 0%, #c8814b 45%, #8f532a 100%); color: #2b1407; animation-delay: 0s; }
.step .place { font-family: var(--display); font-size: 2.1rem; line-height: 1; }
.step .pts { font-size: 0.875rem; font-weight: 600; margin-top: 0.25rem; font-variant-numeric: tabular-nums; }
@keyframes grow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.award-title { font-family: var(--display); font-size: 1.2rem; }
.award-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 48%); gap: 0.875rem; align-items: center; padding: 0.75rem 0; }
.award-row > b { text-align: right; overflow-wrap: anywhere; }
@media (min-width: 800px) and (min-height: 500px) and (orientation: landscape) {
  /* One centred column: a podium to read from the sofa, then the standings and awards side by side. */
  #app.wide:has(> .podium) { max-width: min(94vw, 72rem); }
  #app.wide .podium { gap: 1rem; margin-top: 2.5rem; }
  #app.wide .step .nm { font-size: 1.5rem; }
  #app.wide .step.first .nm { font-size: 2.6rem; }
  #app.wide .step .block { padding-top: 1rem; }
  #app.wide .step.first .block { height: 30vh; }
  #app.wide .step.second .block { height: 22vh; }
  #app.wide .step.third .block { height: 16vh; }
  #app.wide .step .place { font-size: 3.4rem; }
  #app.wide .step .pts { font-size: 1.25rem; }
  #app.wide .final-grid { display: flex; gap: clamp(2.5rem, 5vw, 7rem); align-items: flex-start; margin-top: 2.5rem; }
  #app.wide .final-grid > * { flex: 1 1 0; min-width: 0; }
  #app.wide .final-awards { margin-top: 0; }
}

/* ---- fixed bars -------------------------------------------------------------------- */
.dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  padding: 1.625rem max(1.25rem, env(safe-area-inset-right)) calc(0.875rem + env(safe-area-inset-bottom)) max(1.25rem, env(safe-area-inset-left));
  background: linear-gradient(180deg, rgba(18, 13, 24, 0), rgba(18, 13, 24, 0.94) 34%);
}
.dock .in { max-width: 30rem; margin: 0 auto; display: flex; flex-direction: column; gap: 0.625rem; }
@media (min-width: 800px) and (min-height: 500px) and (orientation: landscape) { #app.wide .dock .in { max-width: 40rem; } }
.dock .note { text-align: center; font-size: 0.875rem; color: var(--text-2); }
.musicline { display: flex; align-items: center; justify-content: space-between; gap: 0.625rem; font-size: 0.875rem; color: var(--text-2); }
.musicline .row-btns { flex: none; }
.reacts { display: flex; justify-content: center; gap: 0.5rem; }
.reacts button { width: 2.875rem; height: 2.875rem; border-radius: 50%; border: 0; background: var(--fill); font-size: 1.4rem; line-height: 1; cursor: pointer; touch-action: manipulation; }
.reacts button:active { transform: scale(0.9); }
.floaters { position: fixed; inset: 0; pointer-events: none; overflow: hidden; z-index: 30; }
.floater { position: absolute; bottom: 5.625rem; font-size: 2.2rem; animation: float 2.6s ease-out forwards; text-align: center; }
.floater small { display: block; font-size: 0.7rem; font-weight: 600; background: rgba(0, 0, 0, 0.55); border-radius: 0.375rem; padding: 0.0625rem 0.375rem; }
@keyframes float { from { transform: translateY(0); opacity: 1; } to { transform: translateY(-60vh); opacity: 0; } }

/* ---- toasts, banners, misc ---------------------------------------------------------- */
.toast {
  position: fixed; left: 50%; bottom: calc(9.375rem + env(safe-area-inset-bottom)); transform: translateX(-50%); z-index: 60;
  max-width: calc(100% - 2rem); padding: 0.75rem 1.125rem; border-radius: 0.875rem; background: #fff; color: var(--base); font-weight: 600;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35);
}
.toast.err { background: #ffd1d1; color: #3a0d12; }
.offline-banner { position: sticky; top: 0; z-index: 35; text-align: center; padding: 0.5rem; background: #fff; color: var(--base); font-weight: 600; font-size: 0.875rem; }
.spinner { width: 1.375rem; height: 1.375rem; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite; display: inline-block; vertical-align: -0.3125rem; }
.stage-dock { max-width: 65rem; margin: 0.625rem auto 0; padding: 0 max(1.25rem, env(safe-area-inset-right)) 0 max(1.25rem, env(safe-area-inset-left)); }
.stage-dock iframe { border-radius: 0.75rem; display: block; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-delay: 0ms !important; transition-duration: 0.01ms !important; }
  .floater { display: none; }
}
