/* =========================================================================
   Sona — foglio di stile
   Palette dinamica: --accent / --accent-2 vengono riscritte da JS
   estraendo i colori dominanti dalla copertina del brano in riproduzione.
   ========================================================================= */

:root {
  --accent: #7c5cff;
  --accent-2: #ff4d9d;
  --ink: #ffffff;
  --ink-dim: rgba(255, 255, 255, .62);
  --ink-faint: rgba(255, 255, 255, .34);
  --base: #06060a;
  --panel-bg: rgba(14, 14, 20, .72);
  --stroke: rgba(255, 255, 255, .10);
  --radius: 18px;
  --ease: cubic-bezier(.22, 1, .36, 1);
  --font: "Segoe UI Variable Display", "Segoe UI", Inter, system-ui, -apple-system, "Helvetica Neue", sans-serif;
  --shadow-deep: 0 40px 120px rgba(0, 0, 0, .75), 0 8px 24px rgba(0, 0, 0, .5);
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}

body {
  background: var(--base);
  color: var(--ink);
  font-family: var(--font);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  cursor: default;
}

body.hide-cursor { cursor: none; }

/* L'attributo `hidden` non nasconde gli elementi SVG: la regola
   [hidden]{display:none} del browser sta in html.css e non copre il
   namespace SVG. Senza questa riga le icone play/pausa/caricamento
   verrebbero disegnate tutte insieme, impilate dentro al pulsante. */
[hidden] { display: none !important; }

svg { display: block; width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* ------------------------------------------------------------- sfondo --- */

#bg { position: fixed; inset: 0; z-index: 0; background: var(--base); overflow: hidden; }

.bg-layer {
  position: absolute;
  inset: -14%;
  background-size: cover;
  background-position: center;
  filter: blur(70px) saturate(1.7) brightness(.62);
  opacity: 0;
  transform: scale(1.18);
  transition: opacity 1.4s var(--ease);
  will-change: opacity, transform;
}
.bg-layer.on { opacity: 1; animation: drift 46s ease-in-out infinite alternate; }

@keyframes drift {
  from { transform: scale(1.16) translate3d(-2%, -1.5%, 0); }
  to   { transform: scale(1.30) translate3d(2.5%, 2%, 0); }
}

/* Velo colorato: lega lo sfondo all'accento estratto dalla copertina. */
.bg-tint {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 15% 10%, color-mix(in oklab, var(--accent) 42%, transparent), transparent 62%),
    radial-gradient(110% 85% at 85% 90%, color-mix(in oklab, var(--accent-2) 36%, transparent), transparent 60%);
  mix-blend-mode: screen;
  opacity: .55;
  transition: background 1.2s linear;
}

.bg-vignette {
  position: absolute; inset: 0;
  background:
    radial-gradient(130% 110% at 50% 45%, transparent 30%, rgba(0, 0, 0, .55) 72%, rgba(0, 0, 0, .88) 100%),
    linear-gradient(to top, rgba(0, 0, 0, .72) 0%, transparent 38%);
}

/* Grana pellicola: toglie il banding dai gradienti e rende l'immagine "filmica". */
.bg-grain {
  position: absolute; inset: -50%;
  opacity: .05;
  pointer-events: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
  animation: grain 1.1s steps(4) infinite;
}
@keyframes grain {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(-3%, 2%); }
  50%  { transform: translate(2%, -3%); }
  75%  { transform: translate(-2%, -2%); }
  100% { transform: translate(3%, 1%); }
}

/* ------------------------------------------------------ visualizzatore --- */

#viz { position: fixed; inset: 0; z-index: 1; width: 100%; height: 100%; display: block; pointer-events: none; }

/* -------------------------------------------------------------- palco --- */

#stage {
  position: relative; z-index: 2;
  height: 100%;
  display: grid;
  place-items: center;
  padding: clamp(24px, 5vw, 90px);
  padding-bottom: clamp(90px, 14vh, 190px);
  transition: transform .6s var(--ease), filter .5s var(--ease);
}

#np {
  position: relative;   /* aggancio per l'etichetta dello specchio */
  display: flex;
  align-items: center;
  gap: clamp(28px, 4.5vw, 76px);
  width: min(1500px, 100%);
}

/* --- copertina --- */

#artWrap { position: relative; flex: 0 0 auto; }

#artCard {
  --size: clamp(190px, min(38vh, 30vw), 460px);
  position: relative;
  width: var(--size); height: var(--size);
  border-radius: 22px;
  overflow: hidden;
  background: linear-gradient(145deg, #24243a, #101019);
  box-shadow: var(--shadow-deep), inset 0 0 0 1px rgba(255, 255, 255, .10);
  transform: perspective(1400px) rotateY(-7deg) rotateX(2deg) translateZ(0);
  transition: transform 1s var(--ease);
  will-change: transform;
}
body[data-state="playing"] #artCard { animation: breathe 7s ease-in-out infinite; }

@keyframes breathe {
  0%, 100% { transform: perspective(1400px) rotateY(-7deg) rotateX(2deg) translateY(0); }
  50%      { transform: perspective(1400px) rotateY(-4deg) rotateX(1deg) translateY(-10px); }
}

#art { width: 100%; height: 100%; object-fit: cover; display: block; opacity: 0; transition: opacity .7s var(--ease); }
#art.on { opacity: 1; }

#artFallback {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  color: rgba(255, 255, 255, .15);
  transition: opacity .5s var(--ease);
}
#artFallback svg { width: 32%; height: 32%; stroke-width: 1.5; }
#artFallback circle { fill: currentColor; stroke: none; }
#art.on ~ #artFallback { opacity: 0; }

/* Riflesso vetroso che scorre lentamente sulla copertina. */
#artSheen {
  position: absolute; inset: 0;
  background: linear-gradient(112deg, transparent 32%, rgba(255, 255, 255, .16) 47%, transparent 60%);
  transform: translateX(-120%);
  animation: sheen 9s ease-in-out infinite;
}
@keyframes sheen { 0%, 72% { transform: translateX(-120%); } 100% { transform: translateX(120%); } }

/* Alone colorato dietro la copertina; l'intensita' segue i bassi (--pulse). */
#artGlow {
  position: absolute; inset: -22%;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in oklab, var(--accent) 78%, transparent), transparent 68%);
  filter: blur(58px);
  opacity: calc(.34 + var(--pulse, 0) * .5);
  transform: scale(calc(1 + var(--pulse, 0) * .12));
  transition: opacity .09s linear, transform .09s linear;
}

/* Riflesso a pavimento. */
#artFloor {
  position: absolute;
  left: 6%; right: 6%; top: 100%;
  height: 34%;
  background: linear-gradient(to bottom, color-mix(in oklab, var(--accent) 30%, transparent), transparent 70%);
  filter: blur(22px);
  opacity: .5;
}

/* --- testi --- */

#meta { min-width: 0; flex: 1 1 auto; }

#eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: clamp(11px, 1.05vw, 15px);
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: clamp(10px, 1.4vh, 20px);
}
#eyebrow .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 14px var(--accent);
}
body[data-state="playing"] #eyebrow .dot { animation: pip 1.6s ease-in-out infinite; }
@keyframes pip { 50% { opacity: .28; transform: scale(.7); } }

#title {
  margin: 0;
  font-size: clamp(30px, 4.6vw, 92px);
  /* Sotto 1.08 il fondo del riquadro passa sopra i tratti discendenti. */
  line-height: 1.08;
  font-weight: 800;
  letter-spacing: -.028em;
  text-wrap: balance;
  /* Alone come filtro e non come text-shadow: overflow:hidden rasa il
     text-shadow sul bordo del riquadro, mentre il filtro viene applicato
     dopo il ritaglio e l'ombra resta intera attorno alle lettere. */
  --rest-filter: drop-shadow(0 6px 44px rgba(0, 0, 0, .6));
  filter: var(--rest-filter);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* Il ritaglio cade a filo dell'ultima riga: senza questo margine le code
     di g, p, y e le parentesi restano tagliate. Il margine negativo lo
     riassorbe, cosi' la distanza dall'artista non cambia. */
  padding-bottom: .16em;
  margin-bottom: -.16em;
}

#artist {
  margin: clamp(8px, 1.4vh, 20px) 0 0;
  font-size: clamp(16px, 1.9vw, 34px);
  font-weight: 500;
  letter-spacing: -.01em;
  color: transparent;
  background: linear-gradient(96deg, var(--accent), var(--accent-2));
  -webkit-background-clip: text;
  background-clip: text;
  --rest-filter: brightness(1.35) saturate(1.15);
  filter: var(--rest-filter);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Micro-animazione d'ingresso a ogni cambio brano.
   La sfocatura si somma al filtro di riposo dell'elemento (--rest-filter):
   un semplice "filter: none" in coda, con animation-fill-mode both, lo
   spegnerebbe per sempre insieme all'alone del titolo. */
.enter { animation: enter .75s var(--ease) both; }
@keyframes enter {
  from { opacity: 0; transform: translateY(22px); filter: blur(9px) var(--rest-filter, ); }
  to   { opacity: 1; transform: none; filter: blur(0) var(--rest-filter, ); }
}

/* --- barra di avanzamento --- */

#seek { margin-top: clamp(20px, 3.2vh, 46px); max-width: 760px; outline: none; }
#seekTrack {
  position: relative;
  height: 6px;
  border-radius: 99px;
  background: rgba(255, 255, 255, .13);
  cursor: pointer;
  transition: height .2s var(--ease);
}
#seek:hover #seekTrack, #seek:focus-visible #seekTrack { height: 10px; }
#seekBuffer { position: absolute; inset: 0 auto 0 0; width: 0; border-radius: 99px; background: rgba(255, 255, 255, .16); }
#seekFill {
  position: absolute; inset: 0 auto 0 0; width: 0;
  border-radius: 99px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  box-shadow: 0 0 18px color-mix(in oklab, var(--accent) 60%, transparent);
}
#seekHead {
  position: absolute; right: 0; top: 50%;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: #fff;
  transform: translate(50%, -50%) scale(0);
  transition: transform .2s var(--ease);
  box-shadow: 0 2px 12px rgba(0, 0, 0, .6);
}
#seek:hover #seekHead, #seek:focus-visible #seekHead { transform: translate(50%, -50%) scale(1); }

#times {
  display: flex; justify-content: space-between;
  margin-top: 10px;
  font-size: clamp(11px, 1vw, 15px);
  font-variant-numeric: tabular-nums;
  color: var(--ink-dim);
  letter-spacing: .04em;
}

#upNext {
  margin-top: clamp(14px, 2vh, 26px);
  font-size: clamp(12px, 1.05vw, 16px);
  color: var(--ink-faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 760px;
}
#upNext .label {
  color: var(--accent);
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  margin-right: 12px;
  font-size: .85em;
}

/* ------------------------------------------------------------ comandi --- */

#controls {
  position: fixed; left: 0; right: 0; bottom: 0;
  z-index: 5;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 20px;
  padding: clamp(16px, 2.4vh, 34px) clamp(20px, 3.6vw, 56px);
  background: linear-gradient(to top, rgba(0, 0, 0, .74), transparent);
  transition: opacity .45s var(--ease), transform .45s var(--ease);
}
.ctl-left { display: flex; gap: 8px; }
.ctl-center { display: flex; align-items: center; gap: clamp(12px, 1.6vw, 26px); }
.ctl-right { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }

.ico {
  width: 42px; height: 42px;
  padding: 11px;
  border-radius: 12px;
  color: var(--ink-dim);
  transition: color .2s, background .2s, transform .2s var(--ease);
}
.ico:hover { color: #fff; background: rgba(255, 255, 255, .09); transform: translateY(-2px); }
.ico.lg { width: 50px; height: 50px; padding: 12px; color: rgba(255, 255, 255, .85); }
.ico[aria-pressed="true"] { color: var(--accent); background: color-mix(in oklab, var(--accent) 16%, transparent); }
.ico svg { stroke-width: 1.7; }
.ico.lg svg { fill: currentColor; stroke-width: 2; }

.play {
  width: clamp(58px, 5vw, 76px);
  height: clamp(58px, 5vw, 76px);
  padding: clamp(17px, 1.5vw, 23px);
  border-radius: 50%;
  color: #08080c;
  background: #fff;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .5), 0 0 0 0 color-mix(in oklab, var(--accent) 55%, transparent);
  transition: transform .22s var(--ease), box-shadow .3s;
}
.play:hover { transform: scale(1.07); box-shadow: 0 14px 46px rgba(0, 0, 0, .55), 0 0 0 12px color-mix(in oklab, var(--accent) 22%, transparent); }
.play:active { transform: scale(.96); }

/* Una sola icona alla volta, scelta da data-icon sul pulsante.
   Su elementi SVG non si puo' usare la proprieta' .hidden: non e'
   definita su SVGElement, quindi assegnarla non tocca il DOM. */
.play svg { display: none; fill: currentColor; stroke: none; }
.play[data-icon="play"] #iconPlay,
.play[data-icon="pause"] #iconPause,
.play[data-icon="load"] #iconLoad { display: block; }
.play svg.spin { fill: none; stroke: currentColor; stroke-width: 2.4; animation: spin .9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

#volWrap { display: flex; align-items: center; gap: 6px; }
#vol {
  width: 0; opacity: 0;
  transition: width .3s var(--ease), opacity .3s;
  -webkit-appearance: none; appearance: none;
  height: 4px; border-radius: 99px;
  background: rgba(255, 255, 255, .2);
  cursor: pointer;
}
#volWrap:hover #vol, #vol:focus-visible { width: clamp(70px, 8vw, 120px); opacity: 1; }
#vol::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 13px; height: 13px; border-radius: 50%;
  background: #fff; box-shadow: 0 0 10px rgba(0, 0, 0, .5);
}
#vol::-moz-range-thumb { width: 13px; height: 13px; border: 0; border-radius: 50%; background: #fff; }

/* Interfaccia che sparisce da sola: essenziale su TV e in streaming. */
body.idle #controls { opacity: 0; transform: translateY(22px); pointer-events: none; }
body.chrome-off #controls { opacity: 0 !important; pointer-events: none; }

/* ------------------------------------------------------ menu telefono --- */
/* Compare solo dove la barra in basso non regge tutte le icone: sta in un
   angolo che il pollice raggiunge e che nessun contenuto occupa. */

#btnMenu {
  position: fixed;
  top: max(12px, env(safe-area-inset-top));
  right: max(12px, env(safe-area-inset-right));
  z-index: 6;
  display: none;
  width: 46px; height: 46px;
  padding: 12px;
  border-radius: 15px;
  color: var(--ink);
  background: rgba(14, 14, 20, .55);
  backdrop-filter: blur(18px) saturate(1.4);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  border: 1px solid var(--stroke);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .45);
  transition: opacity .45s var(--ease), transform .45s var(--ease);
}
#btnMenu svg { stroke-width: 1.8; }
#btnMenu:active { transform: scale(.94); }

/* Sparisce con il resto dell'interfaccia, e mentre il pannello e' aperto:
   li' il pannello copre tutto lo schermo e ha gia' la sua X. */
body.idle #btnMenu { opacity: 0; transform: translateY(-14px); pointer-events: none; }
body.chrome-off #btnMenu,
body.panel-open #btnMenu { opacity: 0; pointer-events: none; }

/* --------------------------------------------------- pannello laterale --- */

#panel {
  position: fixed; top: 0; right: 0; bottom: 0;
  z-index: 20;
  /* Le sei schede in fila ("Controlli" e' la piu' lunga da quando ha preso
     il posto di "Tasti") misurano circa 459px con i loro margini: 430px le
     faceva scorrere, con l'ultima tagliata a meta' invece che scrollabile
     per intero. 470px le fa stare tutte, con un margine per non ritrovarsi
     allo stesso punto alla prossima etichetta piu' lunga. */
  width: min(470px, 100vw);
  display: flex; flex-direction: column;
  background: var(--panel-bg);
  backdrop-filter: blur(34px) saturate(1.5);
  -webkit-backdrop-filter: blur(34px) saturate(1.5);
  border-left: 1px solid var(--stroke);
  box-shadow: -30px 0 80px rgba(0, 0, 0, .55);
  transform: translateX(102%);
  transition: transform .42s var(--ease);
}
body.panel-open #panel { transform: none; }

#scrim {
  position: fixed; inset: 0; z-index: 15;
  background: rgba(0, 0, 0, .42);
  opacity: 0; pointer-events: none;
  transition: opacity .35s;
}
body.panel-open #scrim { opacity: 1; pointer-events: auto; }

/* Testata, campo, schede e piede non si comprimono: sono i quattro
   elementi fissi del pannello, e l'unico a cedere dev'essere l'elenco in
   mezzo. Senza `flex: none` una coda lunga li schiaccia tutti, e i
   pulsanti delle schede — piu' alti della fila ormai ridotta — finiscono
   a coprire le righe che scorrono sotto. */
.panel-head,
#addForm,
.tabs,
.panel-foot { flex: 0 0 auto; }

.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 18px 12px;
}
.brand { display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 15.5px; letter-spacing: -.005em; }
.brand-mark {
  width: 18px; height: 21px; flex: 0 0 auto;
  color: var(--accent);
  filter: drop-shadow(0 0 10px color-mix(in oklab, var(--accent) 55%, transparent));
}
.brand-mark svg { stroke-width: 2.1; }
.brand-mark circle { fill: currentColor; stroke: none; }

#addForm { padding: 4px 18px 14px; }
.field {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 6px 6px 14px;
  border-radius: 14px;
  background: rgba(255, 255, 255, .07);
  border: 1px solid var(--stroke);
  transition: border-color .2s, background .2s;
}
.field:focus-within { border-color: color-mix(in oklab, var(--accent) 65%, transparent); background: rgba(255, 255, 255, .10); }
.field-ico { width: 18px; height: 18px; flex: 0 0 auto; color: var(--ink-faint); }
#urlInput {
  flex: 1 1 auto; min-width: 0;
  background: none; border: 0; outline: none;
  color: #fff; font: inherit; font-size: 14px;
  padding: 9px 0;
}
#urlInput::placeholder { color: var(--ink-faint); }
#btnAdd {
  padding: 9px 16px;
  border-radius: 10px;
  font-size: 13px; font-weight: 650;
  color: #0a0a10;
  background: linear-gradient(120deg, var(--accent), var(--accent-2));
  transition: filter .2s, transform .15s var(--ease);
}
#btnAdd:hover { filter: brightness(1.12); transform: translateY(-1px); }
#btnAdd:disabled { opacity: .5; cursor: progress; }
.hint { margin: 9px 2px 0; font-size: 11.5px; color: var(--ink-faint); }

/* Con sei schede la fila puo' non entrare su un portatile stretto: scorre
   invece di andare a capo, cosi' la riga resta una. */
.tabs {
  display: flex; gap: 4px; padding: 0 14px;
  border-bottom: 1px solid var(--stroke);
  overflow-x: auto; scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab { flex: 0 0 auto; white-space: nowrap; }
.tab {
  position: relative;
  padding: 11px 12px;
  font-size: 13px; font-weight: 600;
  color: var(--ink-faint);
  transition: color .2s;
}
.tab:hover { color: var(--ink-dim); }
.tab.is-on { color: #fff; }
.tab.is-on::after {
  content: ""; position: absolute; left: 12px; right: 12px; bottom: -1px;
  height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}
.tab span { opacity: .55; font-variant-numeric: tabular-nums; }

/* min-height: 0 perche' un elemento flex non scende sotto il proprio
   contenuto se non glielo si concede: e' quello che permette all'elenco
   di scorrere invece di allungare il pannello. */
.panel-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 8px 10px 16px; }
.panel-body::-webkit-scrollbar { width: 8px; }
.panel-body::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .14); border-radius: 99px; }

.list { list-style: none; margin: 0; padding: 0; }
.row {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 10px;
  border-radius: 12px;
  cursor: pointer;
  transition: background .18s;
}
.row:hover { background: rgba(255, 255, 255, .07); }
.row.is-current { background: color-mix(in oklab, var(--accent) 18%, transparent); }
.row-art {
  width: 46px; height: 46px; flex: 0 0 auto;
  border-radius: 9px; object-fit: cover;
  background: rgba(255, 255, 255, .07);
}
.row-txt { min-width: 0; flex: 1 1 auto; }
.row-title { font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row-sub { font-size: 12px; color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }
.row-time { font-size: 11.5px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.row-del, .row-add {
  width: 26px; height: 26px; flex: 0 0 auto;
  padding: 5px; border-radius: 7px;
  color: var(--ink-faint);
  opacity: 0; transition: opacity .18s, color .18s, background .18s;
}
.row:hover .row-del, .row:hover .row-add,
.row-del:focus-visible, .row-add:focus-visible { opacity: 1; }
.row-del:hover { color: #ff6b81; background: rgba(255, 107, 129, .13); }
.row-add:hover { color: var(--accent); background: color-mix(in oklab, var(--accent) 20%, transparent); }
.empty { padding: 34px 16px; text-align: center; font-size: 13px; color: var(--ink-faint); line-height: 1.6; }

/* --- riordino della coda --- */

.row.is-sortable { gap: 9px; padding-left: 4px; }
.row-grip {
  flex: 0 0 auto; align-self: stretch;
  width: 20px; min-height: 34px; margin: -8px 0;
  display: grid; place-items: center;
  border-radius: 7px; color: var(--ink-faint);
  cursor: grab; touch-action: none;
  opacity: 0; transition: opacity .18s, color .18s, background .18s;
}
.row-grip svg { width: 15px; height: 22px; }
.row-grip:hover { color: var(--ink); background: rgba(255, 255, 255, .09); }
.row-grip:active { cursor: grabbing; }

.row-move { display: flex; flex-direction: column; gap: 1px; flex: 0 0 auto; opacity: 0; transition: opacity .18s; }
.row-arrow {
  width: 26px; height: 21px; padding: 3px 6px;
  border-radius: 6px; color: var(--ink-faint);
  transition: color .18s, background .18s;
}
.row-arrow:hover:not(:disabled) { color: #fff; background: rgba(255, 255, 255, .1); }
.row-arrow:disabled { opacity: .22; cursor: default; }

.row:hover .row-grip, .row:hover .row-move,
.row-grip:focus-visible, .row-move:focus-within { opacity: 1; }

/* Mentre si trascina: la riga presa resta incollata al puntatore, le
   altre si scansano con calma per far vedere dove finira'. */
.list.is-sorting .row { transition: transform .16s var(--ease), background .18s; }
.list.is-sorting .row-grip, .list.is-sorting .row-move { opacity: 1; }
.row.is-dragging {
  position: relative; z-index: 3;
  transition: none;
  background: rgba(255, 255, 255, .12);
  box-shadow: 0 16px 34px rgba(0, 0, 0, .5);
}
.row.is-dragging .row-grip { cursor: grabbing; color: var(--ink); }
body.is-sorting { user-select: none; -webkit-user-select: none; }

/* ------------------------------------------------------ impostazioni --- */

/* Tutta la riga e' il comando: sulla TV, da lontano, mirare a un
   interruttore da 40 px non e' realistico. */
.settings { padding: 6px 10px; }
.setting {
  display: flex; align-items: center; gap: 14px;
  width: 100%; padding: 14px;
  text-align: left;
  border-radius: 12px;
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--stroke);
  transition: background .2s, border-color .2s;
}
.setting:hover { background: rgba(255, 255, 255, .08); }
.setting[aria-checked="true"] { border-color: color-mix(in oklab, var(--accent) 45%, transparent); }
.setting-txt { display: block; min-width: 0; flex: 1 1 auto; }
.setting-txt strong { display: block; font-size: 13.5px; font-weight: 650; }
.setting-txt span { display: block; margin-top: 4px; font-size: 12px; line-height: 1.55; color: var(--ink-dim); }

.switch {
  position: relative; flex: 0 0 auto;
  width: 44px; height: 26px; border-radius: 99px;
  background: rgba(255, 255, 255, .14);
  border: 1px solid var(--stroke);
  transition: background .22s var(--ease);
}
.switch i {
  position: absolute; top: 3px; left: 3px;
  width: 18px; height: 18px; border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .5);
  transition: transform .22s var(--ease);
}
.setting[aria-checked="true"] .switch {
  background: linear-gradient(120deg, var(--accent), var(--accent-2));
  border-color: transparent;
}
.setting[aria-checked="true"] .switch i { transform: translateX(18px); }

.settings .hint { margin: 10px 4px 18px; }

.help { padding: 6px 10px; display: flex; flex-direction: column; gap: 14px; }
/* Il distacco dal resto lo da' gia' il flex del contenitore: un margine qui
   si sommerebbe e raddoppierebbe lo spazio prima della prima card. */
.help dl { display: grid; grid-template-columns: auto 1fr; gap: 9px 18px; margin: 0; font-size: 13px; }
.help dt {
  justify-self: start;
  padding: 3px 9px; border-radius: 7px;
  background: rgba(255, 255, 255, .08);
  border: 1px solid var(--stroke);
  font-size: 11.5px; font-weight: 600;
}
.help dd { margin: 0; color: var(--ink-dim); align-self: center; }
.help-note { padding: 14px; border-radius: 12px; background: rgba(255, 255, 255, .05); border: 1px solid var(--stroke); font-size: 12.5px; line-height: 1.65; }
.help-note strong { display: block; margin-bottom: 6px; color: var(--accent); letter-spacing: .1em; text-transform: uppercase; font-size: 11px; }
.help-note p { margin: 0; color: var(--ink-dim); }
.help-note p.muted { margin-top: 7px; color: var(--ink-faint); font-size: 11.5px; }
.help-note code { display: block; margin: 7px 0; padding: 7px 9px; border-radius: 7px; background: rgba(0, 0, 0, .4); font-size: 11.5px; word-break: break-all; user-select: all; }
/* Un indirizzo da copiare vuole la sua riga; un parametro citato dentro a una
   frase no: a blocco spezzerebbe il discorso in una scaletta di una parola. */
.help-note code.inline {
  display: inline; margin: 0; padding: 1px 6px;
  background: rgba(0, 0, 0, .35);
  word-break: normal; white-space: nowrap;
}
/* --- costruttore dell'indirizzo della sovrimpressione --- */

/* Chiuso di suo: i campi non stanno li' a farsi vedere finche' nessuno li
   chiede. `summary` sostituisce il posto della vecchia intestazione fissa,
   quindi eredita il suo disegno (maiuscoletto, colore d'accento). */
#ovDetails summary {
  display: flex; align-items: center; gap: 7px;
  margin-top: 10px;
  color: var(--accent);
  font-size: 11px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  cursor: pointer;
  list-style: none;         /* il triangolo di sistema lo ridisegniamo sotto */
}
#ovDetails summary::-webkit-details-marker { display: none; }
#ovDetails summary::before {
  content: '';
  width: 7px; height: 7px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(-45deg);
  transition: transform .18s var(--ease);
  flex: 0 0 auto;
}
#ovDetails[open] summary::before { transform: rotate(45deg); }
#ovDetails summary:hover { color: color-mix(in oklab, var(--accent) 80%, white); }
/* Il contenuto e' gia' nascosto da [hidden]-like default di <details>;
   qui resta solo lo spazio verso il triangolo appena si apre. */
#ovDetails[open] summary { margin-bottom: 12px; }

.ov-build {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 8px;
  margin: 10px 0 9px;
}
.ov-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ov-field > span {
  font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 650;
}
/* L'unita' di misura non e' un'altra etichetta: e' una nota a margine. */
.ov-field > span i { font-style: normal; opacity: .62; letter-spacing: 0; text-transform: none; }

.ov-field select,
.ov-field input {
  width: 100%; min-width: 0;
  padding: 6px 8px;
  border-radius: 8px;
  border: 1px solid var(--stroke);
  background: rgba(0, 0, 0, .34);
  color: var(--ink);
  font: inherit; font-size: 12px;
}
.ov-field select:focus, .ov-field input:focus {
  outline: none;
  border-color: color-mix(in oklab, var(--accent) 62%, transparent);
}
/* Il menu a tendina si apre col disegno del sistema, che e' chiaro: senza
   questo le voci sarebbero bianche su bianco. */
.ov-field option { background: #14141c; color: var(--ink); }

.ov-toggles {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  margin-bottom: 10px;
}
.ov-toggles label {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--ink-dim); cursor: pointer;
}
.ov-toggles input[type="checkbox"] { accent-color: var(--accent); cursor: pointer; }
.ov-color input[type="color"] {
  width: 30px; height: 20px; padding: 0;
  border: 1px solid var(--stroke); border-radius: 6px;
  background: none; cursor: pointer;
}
.ov-color input[type="color"]:disabled { opacity: .35; cursor: default; }

.ov-actions { display: flex; align-items: center; gap: 12px; margin-top: 9px; }
/* `.cta` nasce per riempire la riga in cui sta; qui e' un pulsante fra due,
   e deve stare largo quanto la sua scritta. */
.ov-actions .cta { flex: 0 0 auto; padding: 7px 13px; font-size: 12px; }

.help-note code span { display: block; }
.help-note code span.alt { color: var(--ink-faint); margin-top: 3px; }

.panel-foot {
  display: flex; align-items: center; gap: 9px;
  padding: 12px 18px;
  border-top: 1px solid var(--stroke);
  font-size: 12px; color: var(--ink-faint);
}
.status { width: 8px; height: 8px; border-radius: 50%; background: #7a7a86; flex: 0 0 auto; }
.status.ok { background: #35d07f; box-shadow: 0 0 10px #35d07f; }
.status.bad { background: #ff5c72; box-shadow: 0 0 10px #ff5c72; }
#statusText { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.link { color: var(--ink-faint); font-size: 12px; text-decoration: underline; text-underline-offset: 3px; }
.link:hover { color: #ff6b81; }

/* ---------------------------------------------------------- libreria --- */

.lib-actions { display: flex; gap: 8px; padding: 6px 10px 0; }
.cta {
  flex: 1 1 auto;
  padding: 11px 14px;
  border-radius: 12px;
  font-size: 13px; font-weight: 650;
  color: #0a0a10;
  background: linear-gradient(120deg, var(--accent), var(--accent-2));
  transition: filter .2s, transform .15s var(--ease);
}
.cta:hover { filter: brightness(1.12); transform: translateY(-1px); }
.cta.ghost {
  color: var(--ink);
  background: rgba(255, 255, 255, .08);
  border: 1px solid var(--stroke);
}
.cta.ghost:hover { background: rgba(255, 255, 255, .13); filter: none; }

.lib-sep {
  display: flex; align-items: center; gap: 9px;
  margin: 18px 10px 8px;
  padding-top: 14px;
  border-top: 1px solid var(--stroke);
  font-size: 11px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-faint);
}
.badge {
  padding: 3px 8px; border-radius: 99px;
  background: color-mix(in oklab, var(--accent) 22%, transparent);
  color: var(--accent);
  letter-spacing: .1em; font-size: 9.5px;
}

/* ----------------------------------------------------------- playlist --- */

/* Una playlist non e' un brano: non ha copertina ne' durata da mostrare in
   riga, ma ha diversi modi di finire in coda. Quindi niente riga stretta,
   ma un blocco con il nome sopra e i comandi sotto. */
.plist { padding: 4px 0; }
.plist-row {
  padding: 11px 12px 10px;
  border-radius: 13px;
  border: 1px solid var(--stroke);
  background: rgba(255, 255, 255, .04);
  margin: 0 2px 8px;
}
.plist-row:hover { background: rgba(255, 255, 255, .07); }
.plist-row.is-open { background: rgba(255, 255, 255, .07); border-color: rgba(255, 255, 255, .16); }

/* Il nome apre e chiude il contenuto: e' un pulsante a tutta riga, cosi'
   il bersaglio e' largo quanto la playlist. */
.plist-open { display: flex; align-items: center; gap: 10px; width: 100%; padding: 0; text-align: left; }
.plist-txt { min-width: 0; flex: 1 1 auto; }
.plist-chev {
  width: 17px; height: 17px; flex: 0 0 auto;
  color: var(--ink-faint);
  transition: transform .22s var(--ease), color .2s;
}
.plist-row.is-open .plist-chev { transform: rotate(180deg); color: var(--ink); }

.plist-tracks {
  margin-top: 10px;
  padding-top: 6px;
  border-top: 1px solid var(--stroke);
  max-height: 44vh;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.plist-tracks::-webkit-scrollbar { width: 7px; }
.plist-tracks::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .14); border-radius: 99px; }
/* Dentro una playlist la riga non porta da nessuna parte: niente cursore
   che promette un clic che non c'e'. */
.plist-tracks .row { padding: 6px; cursor: default; }
.plist-tracks .empty { padding: 18px 10px; }

.plist-name { font-size: 13.5px; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plist-meta { margin-top: 2px; font-size: 11.5px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.plist-acts { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 10px; }

.pl-btn {
  padding: 6px 11px;
  border-radius: 9px;
  border: 1px solid var(--stroke);
  background: rgba(255, 255, 255, .06);
  font-size: 12px; font-weight: 600; color: var(--ink-dim);
  transition: color .18s, background .18s, border-color .18s;
}
.pl-btn:hover { color: #fff; background: rgba(255, 255, 255, .12); }
.pl-btn.is-primary {
  color: #0a0a10; font-weight: 700; border-color: transparent;
  background: linear-gradient(120deg, var(--accent), var(--accent-2));
}
.pl-btn.is-primary:hover { filter: brightness(1.12); }
.pl-btn.ghost { background: none; color: var(--ink-faint); }
.pl-btn.ghost:hover { color: var(--ink); background: rgba(255, 255, 255, .08); }
.pl-btn.is-danger:hover { color: #ff8e9c; background: rgba(255, 107, 129, .13); border-color: rgba(255, 107, 129, .3); }

/* ------------------------------------------------------ accoppiamento --- */

#pair {
  position: fixed; inset: 0; z-index: 50;
  display: grid; place-items: center;
  padding: clamp(20px, 4vw, 60px);
  background: rgba(4, 4, 8, .9);
  backdrop-filter: blur(28px);
  animation: fade .3s var(--ease);
}
@keyframes fade { from { opacity: 0; } }

.pair-card {
  display: flex; align-items: center;
  gap: clamp(28px, 4vw, 64px);
  padding: clamp(26px, 3.4vw, 52px);
  border-radius: 26px;
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--stroke);
  box-shadow: var(--shadow-deep);
  animation: enter .5s var(--ease) both;
}

/* Il QR deve restare leggibile inquadrato da lontano, quindi e' grande
   e sempre su fondo bianco: gli scanner soffrono i contrasti invertiti. */
.pair-qr {
  width: clamp(200px, 26vmin, 340px);
  height: clamp(200px, 26vmin, 340px);
  flex: 0 0 auto;
  padding: 4px;                 /* la zona di silenzio e' gia' dentro l'SVG */
  border-radius: 18px;
  background: #fff;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .5);
  /* Il lato dell'SVG lo decide snapQrToWholeModules(), che lo porta a un
     multiplo esatto dei moduli: quel che avanza diventa bianco attorno, e
     il codice va tenuto al centro. */
  display: grid;
  place-items: center;
}
/* Un QR non e' un'icona: la regola `svg { fill: none; stroke: currentColor }`
   piu' sopra lo ridurrebbe a un quadrato bianco. I colori arrivano gia'
   come stili inline dal generatore, questa riga e' solo una rete. */
.pair-qr svg, .pair-inline-qr svg { fill: initial; stroke: none; }

.pair-qr svg { display: block; max-width: 100%; max-height: 100%; }

.pair-side { min-width: 0; }
.pair-eyebrow {
  font-size: clamp(11px, 1vw, 14px); font-weight: 600;
  letter-spacing: .24em; text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: 10px;
}
.pair-code {
  font-size: clamp(44px, 7vw, 108px);
  font-weight: 800;
  letter-spacing: .1em;
  line-height: 1;
  background: linear-gradient(120deg, var(--accent), var(--accent-2));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: brightness(1.3);
}
.pair-text {
  margin: 18px 0 26px;
  font-size: clamp(13px, 1.15vw, 17px);
  line-height: 1.65;
  color: var(--ink-dim);
}
.pair-text code {
  display: inline-block; margin-top: 4px;
  padding: 4px 9px; border-radius: 7px;
  background: rgba(0, 0, 0, .45);
  color: var(--ink);
  font-size: .92em; user-select: all;
}
.pair-close {
  padding: 12px 30px; border-radius: 99px;
  font-size: 14px; font-weight: 650;
  color: #08080c; background: #fff;
  transition: transform .2s var(--ease);
}
.pair-close:hover { transform: translateY(-2px) scale(1.03); }

/* Versione ridotta dentro al pannello. */
.pair-inline { display: flex; gap: 14px; align-items: center; margin: 10px 0 12px; }
.pair-inline-qr {
  width: 124px; height: 124px; flex: 0 0 auto;
  padding: 3px; border-radius: 10px; background: #fff;
  display: grid;
  place-items: center;          /* vedi .pair-qr: il lato lo fissa il JS */
}
.pair-inline-qr svg { display: block; max-width: 100%; max-height: 100%; }
.pair-inline-code {
  font-size: 26px; font-weight: 800; letter-spacing: .12em;
  color: var(--accent);
  margin: 2px 0 6px;
}
.help-note kbd {
  padding: 1px 6px; border-radius: 5px;
  background: rgba(255, 255, 255, .1);
  border: 1px solid var(--stroke);
  font-size: .9em;
}

/* --- lucchetti della stanza --- */

.lock-row {
  display: flex; align-items: center; gap: 9px;
  margin-top: 8px; color: var(--ink-dim);
  cursor: pointer; user-select: none;
}
.lock-row input { accent-color: var(--accent); width: 15px; height: 15px; flex: none; cursor: pointer; }

/* --- specchio ---
   Una finestra che rispecchia mostra la stessa cosa ma non comanda niente:
   i tasti che non farebbero nulla si spengono invece di restare li' a
   invitare. Restano visibili — servono a leggere lo stato — ma dicono da
   soli che non sono da premere. */

body[data-role="viewer"] .ctl-center button,
body[data-role="viewer"] .ctl-left button,
body[data-role="viewer"] #volWrap,
body[data-role="viewer"] #seekTrack,
body[data-role="viewer"] #addForm {
  opacity: .45;
  pointer-events: none;
}
/* Il visualizzatore no: e' proprio la cosa che ogni schermo sceglie per se'. */

/* Dentro OBS non c'e' nessuno a cui dirlo, e un'etichetta finirebbe dritta
   nello stream. */
body[data-role="viewer"]:not([data-ui]) #np::after {
  content: 'specchio';
  position: absolute; top: 0; right: 0;
  padding: 2px 8px; border-radius: 999px;
  background: rgba(255, 255, 255, .08);
  border: 1px solid var(--stroke);
  color: var(--ink-faint);
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
}

@media (max-aspect-ratio: 1/1) {
  .pair-card { flex-direction: column; text-align: center; }
}

/* -------------------------------------------------------------- toast --- */

#toast {
  position: fixed; left: 50%; bottom: clamp(96px, 15vh, 160px);
  z-index: 30;
  transform: translate(-50%, 16px);
  padding: 12px 22px;
  border-radius: 99px;
  background: rgba(12, 12, 18, .9);
  backdrop-filter: blur(20px);
  border: 1px solid var(--stroke);
  font-size: 13.5px;
  box-shadow: 0 16px 44px rgba(0, 0, 0, .55);
  opacity: 0; pointer-events: none;
  transition: opacity .3s, transform .3s var(--ease);
  max-width: min(560px, 88vw);
  text-align: center;
}
#toast.on { opacity: 1; transform: translate(-50%, 0); }

/* --------------------------------------------------------- gate avvio --- */

#gate {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  background: radial-gradient(90% 80% at 50% 40%, #16121f, #05050a 70%);
  transition: opacity .6s var(--ease), visibility .6s;
}
body.started #gate { opacity: 0; visibility: hidden; }
.gate-inner { text-align: center; animation: enter .8s var(--ease) both; }
.gate-mark {
  width: 66px; height: 76px;
  margin: 0 auto 20px;
  color: var(--accent);
  filter: drop-shadow(0 0 30px color-mix(in oklab, var(--accent) 60%, transparent));
}
.gate-mark svg { stroke-width: 2; }
.gate-mark circle { fill: currentColor; stroke: none; }
.gate-inner h1 { margin: 0; font-size: clamp(38px, 6vw, 72px); font-weight: 800; letter-spacing: -.03em; }
.gate-inner p { margin: 12px 0 34px; color: var(--ink-dim); font-size: clamp(14px, 1.4vw, 18px); }
.gate-actions {
  display: flex; flex-wrap: wrap;
  justify-content: center; align-items: center;
  gap: 14px;
}
#btnGate,
#btnGateRemote {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 15px 34px;
  border: 1px solid transparent;
  border-radius: 99px;
  font-size: 16px; font-weight: 650;
  text-decoration: none;
  cursor: pointer;
  transition: transform .2s var(--ease), box-shadow .3s, background .2s, border-color .2s;
}
#btnGate svg,
#btnGateRemote svg {
  width: 20px; height: 20px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
#btnGate { color: #08080c; background: #fff; }
#btnGate svg { fill: currentColor; stroke: none; }
#btnGate:hover { transform: translateY(-2px) scale(1.03); box-shadow: 0 16px 44px rgba(0, 0, 0, .5), 0 0 0 12px rgba(255, 255, 255, .08); }

#btnGateRemote {
  color: var(--ink);
  background: rgba(255, 255, 255, .07);
  border-color: rgba(255, 255, 255, .18);
}
#btnGateRemote:hover {
  transform: translateY(-2px) scale(1.03);
  background: rgba(255, 255, 255, .13);
  border-color: rgba(255, 255, 255, .3);
  box-shadow: 0 16px 44px rgba(0, 0, 0, .45);
}
.gate-inner .gate-note {
  margin: 26px auto 0;
  max-width: 46ch;
  color: var(--ink-dim);
  font-size: clamp(12px, 1.1vw, 14px);
  opacity: .8;
}

/* ------------------------------------------------------- credito 109tech --- */

.credit-link {
  display: inline-block;
  margin-top: 10px;
  font-size: 13px;
  color: var(--ink-faint);
  text-decoration: none;
  opacity: .8;
  transition: opacity .2s, color .2s;
}
.credit-link:hover { opacity: 1; color: var(--accent); }
.gate-inner .credit-link { margin-top: 14px; }
.panel-foot .credit-link { flex: 0 0 auto; margin-top: 0; }

/* -------------------------------------------- modalita' OBS / Twitch --- */
/* ?ui=obs : niente comandi, niente gate, sfondo trasparente opzionale.     */

body[data-ui="obs"] #controls,
body[data-ui="obs"] #btnMenu,
body[data-ui="obs"] #panel,
body[data-ui="obs"] #scrim,
body[data-ui="obs"] #gate { display: none !important; }

body[data-ui="obs"] #stage { padding-bottom: clamp(24px, 5vw, 90px); }

body[data-transparent="1"],
body[data-transparent="1"] #bg,
body[data-transparent="1"] .bg-layer,
body[data-transparent="1"] .bg-tint,
body[data-transparent="1"] .bg-vignette,
body[data-transparent="1"] .bg-grain { background: transparent !important; }
body[data-transparent="1"] .bg-layer { display: none; }

/* ------------------------------------------ modalita' sovrimpressione --- */
/* ?ui=overlay : niente sfondo e niente visualizzatore, solo il dettaglio del
   brano in un angolo, da appoggiare in OBS sopra a una grafica gia' pronta.
   Le misure derivano tutte da --ov-scale, cosi' una manopola sola nell'URL
   ingrandisce il riquadro senza scomporlo.                                */

body[data-ui="overlay"] {
  --ov-scale: 1;
  --ov-pad: calc(40px * var(--ov-scale));
  --ov-bleed: calc(30px * var(--ov-scale));
  --ov-viz-opacity: .8;
  background: transparent;
}

body[data-ui="overlay"] #bg,
body[data-ui="overlay"] #controls,
body[data-ui="overlay"] #btnMenu,
body[data-ui="overlay"] #panel,
body[data-ui="overlay"] #scrim,
body[data-ui="overlay"] #gate,
body[data-ui="overlay"] #pair,
body[data-ui="overlay"] #toast,
/* Alone, riflesso a pavimento e sheen sono fatti per staccare la copertina
   da uno sfondo scuro: qui sotto c'e' la grafica di qualcun altro, e una
   macchia di colore sfocata le finirebbe sopra. */
body[data-ui="overlay"] #artGlow,
body[data-ui="overlay"] #artFloor,
body[data-ui="overlay"] #artSheen { display: none !important; }

/* Il palco diventa una griglia di ancoraggio: `pos` sceglie solo l'angolo. */
body[data-ui="overlay"] #stage {
  height: 100%;
  padding: var(--ov-pad);
  place-items: center;
  pointer-events: none;
  transition: opacity .45s var(--ease);
}
body[data-ui="overlay"][data-pos^="top"] #stage { align-items: start; }
body[data-ui="overlay"][data-pos^="bottom"] #stage { align-items: end; }
body[data-ui="overlay"][data-pos$="left"] #stage { justify-items: start; }
body[data-ui="overlay"][data-pos$="right"] #stage { justify-items: end; }

/* A coda vuota non c'e' niente da dire: meglio il vuoto che "Sona — incolla
   un link" rimasto in sovrimpressione sullo stream. */
body[data-ui="overlay"][data-state="idle"] #stage { opacity: 0; }

body[data-ui="overlay"] #np {
  position: relative;
  width: auto;
  max-width: min(100%, calc(760px * var(--ov-scale)));
  gap: calc(22px * var(--ov-scale));
  align-items: center;
}
body[data-ui="overlay"] #meta { flex: 0 1 auto; }

/* Il visualizzatore sta dietro alla scheda e finisce dove finisce lei: gli
   stili sono scritti sulle misure del canvas, quindi si rimpiccioliscono da
   soli. `bleed` gli lascia sfumare un po' anche attorno, cosi' il riquadro
   non ha un bordo netto in cui la scena si taglia di colpo. */
/* Misure esplicite e non `inset` con `width:auto`: il canvas e' un elemento
   rimpiazzato, quindi da `auto` prende la dimensione del proprio bitmap —
   che e' proprio quella che qui viene calcolata a partire dal riquadro. */
body[data-ui="overlay"] #viz {
  position: absolute;
  left: calc(var(--ov-bleed) * -1);
  top: calc(var(--ov-bleed) * -1);
  width: calc(100% + var(--ov-bleed) * 2);
  height: calc(100% + var(--ov-bleed) * 2);
  z-index: 0;
  opacity: var(--ov-viz-opacity);
  /* Le due estremita' sfumano: senza, la scena finisce con un taglio netto
     a mezz'aria e si legge come un rettangolo appoggiato sulla grafica
     invece che come lo sfondo del brano. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 86%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 86%, transparent 100%);
}
/* Ancorata a un bordo, la scheda ci sta attaccata: sfumare dal lato del
   bordo toglierebbe proprio la parte che si vede meglio. */
body[data-ui="overlay"][data-pos$="left"] #viz {
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 86%, transparent 100%);
  mask-image: linear-gradient(90deg, #000 0, #000 86%, transparent 100%);
}
body[data-ui="overlay"][data-pos$="right"] #viz {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 14%, #000 100%);
}
/* Il canvas e' il primo figlio di #np: senza questo i testi e la copertina
   finirebbero sotto al disegno. */
body[data-ui="overlay"] #artWrap,
body[data-ui="overlay"] #meta { position: relative; z-index: 1; }

/* Ancorato a destra il riquadro si specchia, altrimenti la copertina
   guarderebbe fuori dallo schermo e i testi partirebbero dal vuoto. */
body[data-ui="overlay"][data-pos$="right"] #np { flex-direction: row-reverse; text-align: right; }

/* Un velo dietro alle scritte: serve solo sulle grafiche chiare, dove il
   contorno del testo da solo non basta. */
body[data-ui="overlay"][data-plate="1"] #np {
  padding: calc(18px * var(--ov-scale)) calc(24px * var(--ov-scale));
  border-radius: calc(18px * var(--ov-scale));
  background: rgba(8, 8, 14, .58);
  border: 1px solid rgba(255, 255, 255, .09);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .45);
  /* Con il velo il visualizzatore diventa lo sfondo della scheda: il bordo
     del velo e' un bordo vero, e la scena si ferma li'. Il canvas resta
     comunque piu' grande, cosi' il disegno non viene compresso ma tagliato. */
  overflow: hidden;
}
/* L'anello gira attorno alla copertina invece di riempire il riquadro, e la
   copertina sta su un fianco della scheda: gli serve piu' spazio di quanto
   ne serva agli altri, e sfumare i lati gli taglierebbe proprio la corona. */
body[data-ui="overlay"][data-viz="ring"] {
  --ov-bleed: calc(100px * var(--ov-scale));
  /* E, di conseguenza, va staccato di piu' anche dal bordo della sorgente:
     con i 40px degli altri la corona finirebbe fuori dall'inquadratura.
     `&pad=` continua a comandare, per chi la vuole a filo lo stesso. */
  --ov-pad: calc(100px * var(--ov-scale));
}
body[data-ui="overlay"][data-viz="ring"] #viz,
body[data-ui="overlay"][data-viz="ring"][data-pos$="left"] #viz,
body[data-ui="overlay"][data-viz="ring"][data-pos$="right"] #viz {
  -webkit-mask-image: none;
  mask-image: none;
}

/* Ritagliato dal velo, sfumare i lati toglierebbe la scena prima del bordo. */
body[data-ui="overlay"][data-plate="1"] #viz,
body[data-ui="overlay"][data-plate="1"][data-pos$="left"] #viz,
body[data-ui="overlay"][data-plate="1"][data-pos$="right"] #viz {
  -webkit-mask-image: none;
  mask-image: none;
}

/* --- copertina --- */

body[data-ui="overlay"] #artCard {
  --size: calc(120px * var(--ov-scale));
  border-radius: calc(12px * var(--ov-scale));
  /* Niente prospettiva ne' respiro: a questa taglia il tre quarti si legge
     come una copertina storta, e il movimento distrae da quello che sta
     succedendo nella scena. */
  transform: none;
  animation: none !important;
  box-shadow: 0 calc(10px * var(--ov-scale)) calc(30px * var(--ov-scale)) rgba(0, 0, 0, .5),
              inset 0 0 0 1px rgba(255, 255, 255, .10);
}
body[data-ui="overlay"][data-art="0"] #artWrap { display: none; }

/* --- testi --- */

body[data-ui="overlay"] #eyebrow {
  font-size: calc(11px * var(--ov-scale));
  margin-bottom: calc(8px * var(--ov-scale));
  gap: calc(7px * var(--ov-scale));
}
body[data-ui="overlay"] #eyebrow .dot {
  width: calc(7px * var(--ov-scale)); height: calc(7px * var(--ov-scale));
}
body[data-ui="overlay"][data-label="0"] #eyebrow { display: none; }

/* Il contorno scuro sostituisce lo sfondo: sotto puo' esserci qualsiasi
   cosa, e senza un'ombra stretta il titolo sparisce sulle zone chiare.
   Passa da --rest-filter perche' l'animazione d'ingresso ci si somma. */
body[data-ui="overlay"] #title {
  font-size: calc(30px * var(--ov-scale));
  line-height: 1.14;
  -webkit-line-clamp: 2;
  --rest-filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .95)) drop-shadow(0 calc(3px * var(--ov-scale)) calc(14px * var(--ov-scale)) rgba(0, 0, 0, .75));
}
body[data-ui="overlay"] #artist {
  font-size: calc(17px * var(--ov-scale));
  margin-top: calc(5px * var(--ov-scale));
  --rest-filter: brightness(1.3) saturate(1.1) drop-shadow(0 1px 2px rgba(0, 0, 0, .9));
}

/* --- avanzamento --- */

body[data-ui="overlay"] #seek {
  margin-top: calc(13px * var(--ov-scale));
  max-width: none;
  pointer-events: none;
}
body[data-ui="overlay"] #seekTrack {
  height: calc(4px * var(--ov-scale));
  background: rgba(255, 255, 255, .22);
  cursor: default;
}
/* La pallina segue il puntatore, e qui di puntatore non ce n'e' nessuno. */
body[data-ui="overlay"] #seekHead { display: none; }
body[data-ui="overlay"] #times {
  margin-top: calc(6px * var(--ov-scale));
  font-size: calc(11px * var(--ov-scale));
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .9));
}
body[data-ui="overlay"][data-bar="0"] #seek { display: none; }

/* "A seguire" parte spento: in sovrimpressione e' quasi sempre una riga di
   troppo. `&next=1` lo riaccende. */
body[data-ui="overlay"] #upNext { display: none; }
body[data-ui="overlay"][data-next="1"] #upNext {
  display: block;
  max-width: none;
  margin-top: calc(10px * var(--ov-scale));
  font-size: calc(12px * var(--ov-scale));
  color: var(--ink-dim);
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .9));
}

/* --------------------------------------------------------- responsive --- */

/* Verticale / schermi stretti: impilato e centrato. */
@media (max-aspect-ratio: 4/5), (max-width: 760px) {
  #np { flex-direction: column; text-align: center; gap: clamp(22px, 4vh, 44px); }
  #meta { width: 100%; }
  #artCard { --size: clamp(180px, 46vw, 340px); }
  #eyebrow, #seek, #upNext { margin-left: auto; margin-right: auto; }
  #times { max-width: none; }
  /* Le cinque icone a destra non entrano: in una griglia a tre colonne
     finivano oltre il bordo destro dello schermo, menu compreso. Qui la
     barra torna una fila sola con i comandi che sul telefono servono
     davvero: il volume lo fanno i tasti fisici, il codice del telecomando
     e' nel pannello (Tasti), e il menu e' salito in alto a destra. */
  #controls {
    display: flex;
    justify-content: center;
    gap: clamp(10px, 4vw, 22px);
    padding: 14px max(14px, env(safe-area-inset-left)) max(18px, env(safe-area-inset-bottom)) max(14px, env(safe-area-inset-right));
  }
  .ctl-left,
  #volWrap,
  #btnPair,
  #btnQueue { display: none; }
  .ctl-right { gap: 6px; }

  #btnMenu { display: block; }

  /* Il pannello occupa tutto lo schermo: la barra di stato del telefono
     puo' finire sopra la testata, e con essa sulle schede. */
  .panel-head { padding: max(16px, env(safe-area-inset-top)) 16px 10px; }
  .panel-foot { padding-bottom: max(10px, env(safe-area-inset-bottom)); }

  /* Il suggerimento sui tasti parla di Invio e Shift: sul telefono ruba
     solo una riga alle schede. */
  #addForm { padding: 4px 16px 12px; }
  #addHint { display: none; }

  /* Sei schede in 375px chiedevano 433px: l'ultima ("Tasti") restava
     fuori dallo schermo, senza niente che facesse capire che la fila
     scorre. Strette abbastanza, ci stanno tutte. */
  .tabs { gap: 2px; padding: 0 8px; justify-content: space-between; }
  .tab { padding: 11px 6px; font-size: 12.5px; }
  .tab.is-on::after { left: 6px; right: 6px; }
}

/* Telefoni piccoli: le sei schede sforano di una decina di pixel, e
   l'ultima tagliata a meta' sembra un errore piu' che un invito a
   scorrere. Un filo piu' strette entrano anche qui. */
@media (max-width: 340px) {
  .tabs { padding: 0 6px; }
  .tab { padding: 11px 4px; font-size: 12px; }
  .tab.is-on::after { left: 4px; right: 4px; }
}

/* Schermi molto larghi (TV 4K): piu' respiro, testi piu' grandi. */
@media (min-width: 2200px) {
  #np { gap: 100px; }
  #title { font-size: clamp(72px, 4.2vw, 130px); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .12s !important; }
  .bg-grain { display: none; }
}

/* --------------------------------------------------------- una domanda ---
   Il prompt() del browser esce dal tema, e in una sorgente OBS non compare
   nemmeno: la richiesta di un nome se la disegna Sona. */

.ask {
  position: fixed; inset: 0; z-index: 70;
  display: grid; place-items: center;
  padding: 24px;
  background: rgba(4, 4, 8, .66);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  animation: askIn .18s var(--ease);
}
.ask-card {
  width: min(420px, 100%);
  padding: 22px;
  border-radius: 18px;
  background: rgba(18, 18, 26, .96);
  border: 1px solid var(--stroke);
  box-shadow: var(--shadow-deep);
}
.ask-title { margin: 0; font-size: 16px; font-weight: 700; letter-spacing: -.01em; }
.ask-hint { margin: 7px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--ink-dim); }
.ask-input {
  width: 100%; margin-top: 16px;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .06);
  border: 1px solid var(--stroke);
  color: var(--ink); font: inherit; font-size: 14px;
}
.ask-input:focus { outline: none; border-color: color-mix(in oklab, var(--accent) 60%, transparent); }
.ask-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
.ask-btn {
  padding: 10px 16px;
  border-radius: 11px;
  border: 1px solid var(--stroke);
  background: rgba(255, 255, 255, .06);
  font-size: 13px; font-weight: 650; color: var(--ink-dim);
  transition: color .18s, background .18s, filter .18s;
}
.ask-btn:hover { color: #fff; background: rgba(255, 255, 255, .12); }
.ask-btn.is-primary {
  color: #0a0a10; border-color: transparent;
  background: linear-gradient(120deg, var(--accent), var(--accent-2));
}
.ask-btn.is-primary:hover { filter: brightness(1.12); background: linear-gradient(120deg, var(--accent), var(--accent-2)); }
.ask-btn.is-danger { color: #ff8e9c; background: rgba(255, 92, 114, .12); border-color: rgba(255, 92, 114, .28); }
.ask-btn.is-danger:hover { color: #fff; background: rgba(255, 92, 114, .26); }

@keyframes askIn { from { opacity: 0; } to { opacity: 1; } }

/* Scelta fra piu' voci (per esempio: in quale playlist finisce il brano). */
.ask-list { margin-top: 14px; max-height: 46vh; overflow-y: auto; overscroll-behavior: contain; }
.ask-list::-webkit-scrollbar { width: 7px; }
.ask-list::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .14); border-radius: 99px; }

.ask-group {
  margin: 14px 2px 6px;
  font-size: 10.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-faint);
}
.ask-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 11px 12px; border-radius: 11px;
  font-size: 13.5px; color: var(--ink-dim); text-align: left;
  transition: color .16s, background .16s, border-color .16s;
}
.ask-item:hover { color: #fff; background: rgba(255, 255, 255, .09); }
.ask-item-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ask-item-meta { flex: 0 0 auto; font-size: 11.5px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.ask-item.is-action { margin-bottom: 4px; color: var(--ink); font-weight: 650; border: 1px dashed var(--stroke); }
.ask-item.is-action:hover { border-color: color-mix(in oklab, var(--accent) 55%, transparent); }
.ask-empty { margin: 18px 4px 6px; font-size: 12.5px; color: var(--ink-faint); text-align: center; }

/* Riquadro diagnostico di "?debug=1". Sta sopra a tutto, anche in modalita'
   OBS, dove serve proprio perche' la console non e' raggiungibile. */
#debugBox {
  position: fixed; top: 12px; left: 12px; z-index: 999;
  margin: 0; padding: 10px 13px;
  border: 1px solid rgba(255, 255, 255, .18); border-radius: 10px;
  background: rgba(6, 6, 12, .82);
  font: 12px/1.55 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: #d8e2ff; white-space: pre;
  pointer-events: none; user-select: none;
}
