:root{
  --acc:#ef4444;--acc2:#f97316;--r:18px;--font:Inter,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --bg:#0b0b10;--text:#f1f1f6;--mut:#9a9ab0;--line:rgba(255,255,255,.09);--ok:#22c55e;--bad:#ef4444;--warn:#eab308;
  --card:rgba(24,24,34,.62);--card-b:rgba(255,255,255,.09);--blur:18px;--bgblur:14px;--bgdim:.55;
  --safe-b:env(safe-area-inset-bottom,0px);--safe-t:env(safe-area-inset-top,0px);
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{min-height:100%}
body{font-family:var(--font);background:var(--bg);color:var(--text);font-size:14px;line-height:1.45;overflow-x:hidden}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;border:0;background:none}
img{max-width:100%;display:block}
.hide{display:none!important}
::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-thumb{background:rgba(255,255,255,.14);border-radius:8px}
svg.i{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0}
svg.i.f{fill:currentColor}

/* ---------- background ---------- */
#bg{position:fixed;inset:0;z-index:-1;overflow:hidden;background:var(--bg)}
#bg-img{position:absolute;inset:-60px;background-size:cover;background-position:center;filter:blur(var(--bgblur));transition:background-image .6s,opacity .6s;opacity:0}
#bg-dim{position:absolute;inset:0;background:rgba(6,6,10,var(--bgdim))}
#bg.aurora{background:radial-gradient(900px 560px at 85% -8%,color-mix(in srgb,var(--acc) 34%,transparent),transparent 60%),radial-gradient(800px 520px at -8% 105%,color-mix(in srgb,var(--acc2) 28%,transparent),transparent 60%),var(--bg)}
#bg.aurora #bg-dim,#bg.color #bg-dim{background:transparent}
#bg.has-img #bg-img{opacity:1}

/* ---------- cards ---------- */
.card{background:var(--card);border:1px solid var(--card-b);border-radius:var(--r);backdrop-filter:blur(var(--blur));-webkit-backdrop-filter:blur(var(--blur));padding:18px}
body[data-card=solid] .card{background:#15151e;backdrop-filter:none;border-color:#23232f}
body[data-card=outline] .card{background:transparent;backdrop-filter:none;border:1.5px solid color-mix(in srgb,var(--acc) 55%,transparent)}
body[data-card=neon] .card{background:rgba(10,10,16,.72);border:1px solid var(--acc);box-shadow:0 0 0 1px color-mix(in srgb,var(--acc) 30%,transparent),0 0 28px color-mix(in srgb,var(--acc) 30%,transparent)}
.card h3{font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--mut);margin-bottom:12px;font-weight:600}
.row{display:flex;align-items:center;gap:10px}.wrap{flex-wrap:wrap}.grow{flex:1;min-width:0}.gap{gap:16px}
.col{display:flex;flex-direction:column;gap:12px}
.mut{color:var(--mut)}.small{font-size:12px}.ell{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.badge{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:99px;font-size:11px;font-weight:700;background:rgba(255,255,255,.08);border:1px solid var(--line)}
.badge.acc{background:color-mix(in srgb,var(--acc) 22%,transparent);border-color:color-mix(in srgb,var(--acc) 50%,transparent)}
.badge.ok{background:rgba(34,197,94,.16);border-color:rgba(34,197,94,.4);color:#86efac}
.badge.sp{background:rgba(30,215,96,.15);border-color:rgba(30,215,96,.4);color:#4ade80}

/* ---------- buttons / inputs ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:9px 16px;border-radius:12px;font-weight:600;background:rgba(255,255,255,.08);border:1px solid var(--line);transition:.15s}
.btn:hover{background:rgba(255,255,255,.14)}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn.pri{background:linear-gradient(135deg,var(--acc),var(--acc2));border:0;color:#fff;box-shadow:0 8px 24px color-mix(in srgb,var(--acc) 35%,transparent)}
.btn.pri:hover{filter:brightness(1.08)}
.btn.bad{background:rgba(239,68,68,.15);border-color:rgba(239,68,68,.4);color:#fca5a5}
.btn.sp{background:#1db954;border:0;color:#04130a}
.btn.sm{padding:6px 10px;font-size:12px;border-radius:9px}
.btn.ic{padding:9px;border-radius:50%;width:38px;height:38px}
.btn.on{background:color-mix(in srgb,var(--acc) 28%,transparent);border-color:var(--acc);color:#fff}
input[type=text],input[type=search],input[type=url],select,textarea{width:100%;padding:10px 12px;border-radius:12px;background:rgba(0,0,0,.28);border:1px solid var(--line);outline:0;transition:.15s}
input:focus,select:focus,textarea:focus{border-color:var(--acc);box-shadow:0 0 0 3px color-mix(in srgb,var(--acc) 22%,transparent)}
select option{background:#15151e}
input[type=color]{width:44px;height:38px;padding:2px;border-radius:10px;border:1px solid var(--line);background:rgba(0,0,0,.28)}
input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:6px;border-radius:9px;background:rgba(255,255,255,.14);outline:0;accent-color:var(--acc)}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:15px;height:15px;border-radius:50%;background:#fff;box-shadow:0 0 0 3px color-mix(in srgb,var(--acc) 60%,transparent)}
.field{display:flex;flex-direction:column;gap:6px}.field>label{font-size:12px;color:var(--mut);font-weight:600}
.seg{display:flex;background:rgba(0,0,0,.28);border:1px solid var(--line);border-radius:12px;padding:3px;gap:3px}
.seg button{flex:1;padding:7px 8px;border-radius:9px;font-size:12px;font-weight:600;color:var(--mut)}
.seg button.on{background:linear-gradient(135deg,var(--acc),var(--acc2));color:#fff}
.sw{position:relative;width:42px;height:24px;border-radius:99px;background:rgba(255,255,255,.16);flex-shrink:0;transition:.2s}
.sw::after{content:"";position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#fff;transition:.2s}
.sw.on{background:var(--acc)}.sw.on::after{left:21px}

/* ---------- layout ---------- */
#app{display:flex;min-height:100vh}
#side{width:248px;flex-shrink:0;position:sticky;top:0;height:100vh;padding:18px 14px;display:flex;flex-direction:column;gap:6px;background:rgba(10,10,15,.72);backdrop-filter:blur(18px);border-right:1px solid var(--line);overflow-y:auto}
.brand{display:flex;align-items:center;gap:11px;padding:4px 8px 16px}
.brand img{width:40px;height:40px;border-radius:50%;box-shadow:0 0 0 2px var(--acc),0 0 22px color-mix(in srgb,var(--acc) 45%,transparent)}
.brand b{font-size:16px}.brand small{display:block;color:var(--mut);font-size:11px}
.nav a{display:flex;align-items:center;gap:11px;padding:10px 12px;border-radius:12px;color:var(--mut);font-weight:600;transition:.15s}
.nav a:hover{background:rgba(255,255,255,.07);color:var(--text)}
.nav a.on{background:color-mix(in srgb,var(--acc) 20%,transparent);color:#fff}
.side-h{font-size:11px;letter-spacing:.08em;color:var(--mut);text-transform:uppercase;font-weight:700;padding:14px 12px 4px}
.srv{display:flex;align-items:center;gap:10px;padding:7px 10px;border-radius:12px;color:var(--mut);font-weight:600}
.srv:hover{background:rgba(255,255,255,.07);color:var(--text)}.srv.on{background:color-mix(in srgb,var(--acc) 20%,transparent);color:#fff}
.srv img,.srv .ph{width:28px;height:28px;border-radius:9px;background:#23232f;display:grid;place-items:center;font-size:11px;font-weight:800;flex-shrink:0;object-fit:cover}
.eq{display:inline-flex;gap:2px;align-items:flex-end;height:12px;margin-left:auto}.eq i{width:3px;background:var(--acc);border-radius:2px;animation:eq 1s infinite ease-in-out}.eq i:nth-child(2){animation-delay:.2s}.eq i:nth-child(3){animation-delay:.4s}
@keyframes eq{0%,100%{height:3px}50%{height:12px}}
.me{margin-top:auto;display:flex;align-items:center;gap:10px;padding:10px;border-radius:14px;background:rgba(255,255,255,.05);border:1px solid var(--line)}
.me img{width:34px;height:34px;border-radius:50%}
#main{flex:1;min-width:0;padding:26px clamp(14px,3vw,38px) 60px;max-width:1280px;margin:0 auto;width:100%}
.page-h{display:flex;align-items:center;gap:14px;margin-bottom:20px;flex-wrap:wrap}
.page-h h1{font-size:24px;font-weight:800}.page-h img.gi{width:46px;height:46px;border-radius:14px}
.tabs{display:flex;gap:6px;margin-bottom:18px;overflow-x:auto;padding-bottom:2px}
.tabs a{padding:8px 15px;border-radius:99px;font-weight:700;color:var(--mut);background:rgba(255,255,255,.05);border:1px solid var(--line);white-space:nowrap}
.tabs a.on{background:linear-gradient(135deg,var(--acc),var(--acc2));color:#fff;border:0}
.grid{display:grid;gap:16px}.g2{grid-template-columns:1fr 1fr}.g3{grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}
.stat{display:flex;flex-direction:column;gap:2px}.stat b{font-size:26px;font-weight:800}.stat span{color:var(--mut);font-size:12px;font-weight:600}

/* ---------- login ---------- */
.login{min-height:100vh;display:grid;place-items:center;padding:20px}
.lbox{max-width:420px;width:100%;text-align:center;padding:38px 30px}
.lbox img{width:84px;height:84px;border-radius:50%;margin:0 auto 16px;box-shadow:0 0 0 3px var(--acc),0 0 40px color-mix(in srgb,var(--acc) 50%,transparent)}
.lbox h1{font-size:26px;margin-bottom:6px}.lbox p{color:var(--mut);margin-bottom:22px}
.feat{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:0 0 24px;text-align:left}.feat span{font-size:12px;color:var(--mut);display:flex;gap:7px;align-items:center}

/* ---------- player ---------- */
.player{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,1fr);gap:16px;align-items:start}
.np{display:flex;gap:22px;align-items:center}
.cover{width:230px;height:230px;border-radius:calc(var(--r) - 2px);background:linear-gradient(135deg,color-mix(in srgb,var(--acc) 40%,#111),color-mix(in srgb,var(--acc2) 40%,#111));overflow:hidden;flex-shrink:0;box-shadow:0 22px 50px rgba(0,0,0,.5);position:relative}
.cover img{width:100%;height:100%;object-fit:cover}
.cover .ph{position:absolute;inset:0;display:grid;place-items:center;opacity:.55}.cover .ph svg{width:64px;height:64px}
body[data-layout=vinyl] .cover{border-radius:50%;box-shadow:0 0 0 10px rgba(0,0,0,.55),0 22px 50px rgba(0,0,0,.5)}
body[data-layout=vinyl] .cover.spin{animation:rot 14s linear infinite}
body[data-layout=vinyl] .cover::after{content:"";position:absolute;left:50%;top:50%;width:34px;height:34px;margin:-17px;border-radius:50%;background:var(--bg);box-shadow:0 0 0 4px rgba(255,255,255,.12)}
@keyframes rot{to{transform:rotate(360deg)}}
body[data-layout=minimal] .cover{display:none}
.meta h2{font-size:24px;font-weight:800;line-height:1.2;margin-bottom:4px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.meta .by{color:var(--mut);font-size:15px;margin-bottom:12px}
.bar{height:8px;border-radius:9px;background:rgba(255,255,255,.14);cursor:pointer;position:relative;margin:14px 0 6px}
.bar i{position:absolute;left:0;top:0;bottom:0;border-radius:9px;background:linear-gradient(90deg,var(--acc),var(--acc2));width:0}
.bar b{position:absolute;top:50%;width:14px;height:14px;margin:-7px 0 0 -7px;border-radius:50%;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,.5);left:0}
.times{display:flex;justify-content:space-between;color:var(--mut);font-size:12px;font-variant-numeric:tabular-nums}
.ctl{display:flex;align-items:center;justify-content:center;gap:10px;margin:12px 0}
.ctl .big{width:56px;height:56px;border-radius:50%;background:linear-gradient(135deg,var(--acc),var(--acc2));color:#fff;display:grid;place-items:center;box-shadow:0 10px 28px color-mix(in srgb,var(--acc) 45%,transparent)}
.ctl .big svg{width:24px;height:24px}

.avs{display:flex}.avs img{width:26px;height:26px;border-radius:50%;border:2px solid var(--bg);margin-left:-8px}.avs img:first-child{margin-left:0}
.q-item{display:flex;align-items:center;gap:11px;padding:8px;border-radius:12px;transition:.12s}
.q-item:hover{background:rgba(255,255,255,.06)}
.q-item img,.q-item .th{width:44px;height:44px;border-radius:9px;object-fit:cover;background:#23232f;flex-shrink:0}
.q-item .n{width:20px;text-align:center;color:var(--mut);font-size:12px;font-variant-numeric:tabular-nums}
.q-act{display:flex;gap:2px;opacity:0;transition:.12s}.q-item:hover .q-act{opacity:1}
@media(hover:none){.q-act{opacity:1}}
.q-list{max-height:520px;overflow-y:auto;margin:0 -6px;padding:0 6px}
.chips{display:flex;flex-wrap:wrap;gap:7px}.chip{padding:6px 11px;border-radius:99px;font-size:12px;font-weight:600;background:rgba(255,255,255,.07);border:1px solid var(--line)}.chip.on{background:color-mix(in srgb,var(--acc) 30%,transparent);border-color:var(--acc)}
.banner{display:flex;align-items:center;gap:12px;padding:14px 16px;border-radius:var(--r);background:color-mix(in srgb,var(--acc) 18%,rgba(0,0,0,.4));border:1px solid color-mix(in srgb,var(--acc) 55%,transparent);margin-bottom:16px;animation:pop .25s}
@keyframes pop{from{transform:translateY(-6px);opacity:0}}
.empty{text-align:center;color:var(--mut);padding:26px 10px}
.empty svg{display:block;width:36px;height:36px;opacity:.5;margin:0 auto 8px}

/* ---------- settings ---------- */
.set{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:16px;align-items:start}
.preview{position:sticky;top:18px}
.pv{border-radius:var(--r);overflow:hidden;position:relative;min-height:250px;padding:18px;border:1px solid var(--line)}
.pv .bgl{position:absolute;inset:-30px;background-size:cover;background-position:center}
.pv .dim{position:absolute;inset:0}
.pv .in{position:relative}
.up{display:flex;align-items:center;justify-content:center;gap:10px;padding:22px;border:2px dashed var(--line);border-radius:14px;color:var(--mut);cursor:pointer;text-align:center}
.up:hover{border-color:var(--acc);color:var(--text)}
.save{position:sticky;bottom:calc(14px + var(--safe-b));display:flex;justify-content:flex-end;gap:10px;padding:12px;border-radius:16px;background:rgba(14,14,20,.88);backdrop-filter:blur(14px);border:1px solid var(--line);margin-top:16px;z-index:20}
.sec-t{font-weight:700;margin:4px 0 10px;display:flex;align-items:center;gap:8px}
.hr{height:1px;background:var(--line);margin:14px 0}

/* ---------- lists ---------- */
.pl{display:flex;align-items:center;gap:12px;padding:10px;border-radius:14px;cursor:pointer;border:1px solid transparent}
.pl:hover{background:rgba(255,255,255,.06)}.pl.on{background:color-mix(in srgb,var(--acc) 16%,transparent);border-color:color-mix(in srgb,var(--acc) 45%,transparent)}
.pl .pic{width:48px;height:48px;border-radius:11px;background:linear-gradient(135deg,color-mix(in srgb,var(--acc) 50%,#111),color-mix(in srgb,var(--acc2) 50%,#111));display:grid;place-items:center;overflow:hidden;flex-shrink:0}
.pl .pic img{width:100%;height:100%;object-fit:cover}
.cols2{display:grid;grid-template-columns:320px minmax(0,1fr);gap:16px;align-items:start}
.hint{padding:12px 14px;border-radius:12px;background:rgba(234,179,8,.1);border:1px solid rgba(234,179,8,.35);color:#fde68a;font-size:12.5px}
.tbl{width:100%;border-collapse:collapse}.tbl td,.tbl th{padding:9px 8px;text-align:left;border-bottom:1px solid var(--line);font-size:13px}.tbl th{color:var(--mut);font-size:11px;text-transform:uppercase;letter-spacing:.06em}

/* ---------- misc ---------- */
.boot{min-height:100vh;display:grid;place-items:center}.spin{width:34px;height:34px;border-radius:50%;border:3px solid rgba(255,255,255,.15);border-top-color:var(--acc);animation:rot .8s linear infinite}
#toasts{position:fixed;right:16px;bottom:calc(16px + var(--safe-b));display:flex;flex-direction:column;gap:8px;z-index:99;pointer-events:none}
.toast{padding:11px 15px;border-radius:12px;background:#1b1b26;border:1px solid var(--line);box-shadow:0 12px 30px rgba(0,0,0,.5);max-width:340px;animation:pop .2s;pointer-events:auto}
.toast.err{border-color:rgba(239,68,68,.6)}.toast.ok{border-color:rgba(34,197,94,.55)}
.modal{position:fixed;inset:0;background:rgba(0,0,0,.6);backdrop-filter:blur(4px);display:grid;place-items:center;z-index:80;padding:16px}
.modal .card{width:100%;max-width:440px;background:#15151e}
#mnav{display:none}

@media(max-width:1000px){
  .player,.set,.cols2,.g2{grid-template-columns:1fr}
  .preview{position:static}
}
@media(max-width:860px){
  #side{display:none}
  #main{padding:16px 12px calc(86px + var(--safe-b))}
  #mnav{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:50;padding:8px 6px calc(8px + var(--safe-b));background:rgba(10,10,15,.92);backdrop-filter:blur(18px);border-top:1px solid var(--line);justify-content:space-around}
  #mnav a{display:flex;flex-direction:column;align-items:center;gap:3px;font-size:10px;font-weight:700;color:var(--mut);padding:4px 10px;border-radius:12px}
  #mnav a.on{color:#fff}#mnav a.on svg{color:var(--acc)}
  .np{flex-direction:column;text-align:center}.cover{width:min(70vw,260px);height:min(70vw,260px)}
  .page-h h1{font-size:20px}
}

/* ---------- AI assistant ---------- */
.ai-log{display:flex;flex-direction:column;gap:12px;height:min(52vh,460px);overflow-y:auto;padding:4px 2px;scroll-behavior:smooth}
.ai-msg{display:flex;flex-direction:column;gap:8px;max-width:88%}
.ai-msg.user{align-self:flex-end;align-items:flex-end}
.ai-b{padding:10px 14px;border-radius:16px;background:rgba(255,255,255,.07);border:1px solid var(--line);white-space:pre-wrap;word-break:break-word}
.ai-msg.user .ai-b{background:linear-gradient(135deg,var(--acc),var(--acc2));border:0;color:#fff;border-bottom-right-radius:5px}
.ai-msg.assistant .ai-b{border-bottom-left-radius:5px}
.ai-songs{display:flex;flex-direction:column;gap:6px;width:min(560px,100%)}
.ai-log .empty{margin:auto}

/* ---------- admin console ---------- */
.console{height:min(60vh,520px);overflow-y:auto;background:rgba(0,0,0,.4);border:1px solid var(--line);border-radius:12px;padding:10px;font:12px/1.5 ui-monospace,Menlo,Consolas,monospace}
.console .ln{white-space:pre-wrap;word-break:break-word;color:#cfcfe0}
.console .ln.warn{color:#fde047}.console .ln.error{color:#fca5a5}
@media(max-width:860px){#mnav a{padding:4px 6px}.ai-msg{max-width:96%}}

/* ---------- lyrics ---------- */
.tabs2{flex:0 0 auto}.tabs2 button{white-space:nowrap;padding:7px 14px}
.lyrics{position:relative;max-height:520px;min-height:260px;overflow-y:auto;padding:90px 6px;text-align:center;scrollbar-width:thin;
  -webkit-mask-image:linear-gradient(transparent,#000 14%,#000 86%,transparent);mask-image:linear-gradient(transparent,#000 14%,#000 86%,transparent)}
.ly{font-size:20px;font-weight:800;line-height:1.35;padding:7px 8px;color:rgba(255,255,255,.34);cursor:pointer;transition:color .25s,transform .25s;transform-origin:center}
.ly:hover{color:rgba(255,255,255,.65)}
.ly.on{color:#fff;transform:scale(1.06);text-shadow:0 0 28px color-mix(in srgb,var(--acc) 60%,transparent)}
.ly-plain{white-space:pre-wrap;font-size:15px;line-height:1.75;color:rgba(255,255,255,.82);padding:0 6px}
.lyrics:has(.ly-plain){padding:14px 6px;text-align:left;-webkit-mask-image:none;mask-image:none}

/* ---------- suggestion cards (Spotify style) ---------- */
.sc-row{display:flex;gap:14px;overflow-x:auto;padding:2px 2px 10px;scroll-snap-type:x proximity;scrollbar-width:thin}
.sc{flex:0 0 150px;text-align:left;padding:10px;border-radius:14px;background:rgba(255,255,255,.04);border:1px solid transparent;scroll-snap-align:start;transition:.18s}
.sc:hover{background:rgba(255,255,255,.09);border-color:var(--line);transform:translateY(-3px)}
.sc-i{position:relative;width:100%;aspect-ratio:1;border-radius:11px;overflow:hidden;background:linear-gradient(135deg,color-mix(in srgb,var(--acc) 35%,#111),color-mix(in srgb,var(--acc2) 35%,#111));margin-bottom:10px;box-shadow:0 10px 24px rgba(0,0,0,.4)}
.sc-i img{width:100%;height:100%;object-fit:cover;transition:transform .35s}
.sc:hover .sc-i img{transform:scale(1.06)}
.sc-i .ph{position:absolute;inset:0;display:grid;place-items:center;opacity:.5}
.sc-p{position:absolute;right:8px;bottom:8px;width:40px;height:40px;border-radius:50%;display:grid;place-items:center;background:linear-gradient(135deg,var(--acc),var(--acc2));color:#fff;box-shadow:0 8px 20px rgba(0,0,0,.45);opacity:0;transform:translateY(8px);transition:.2s}
.sc-p svg{width:18px;height:18px}
.sc:hover .sc-p,.sc:focus-visible .sc-p{opacity:1;transform:none}
@media(hover:none){.sc-p{opacity:1;transform:none}.sc{flex-basis:130px}}
.sc-t{font-weight:700;font-size:13px;margin-bottom:2px}

/* ---------- general polish ---------- */
.card{box-shadow:0 12px 34px rgba(0,0,0,.22);transition:border-color .2s,transform .2s,box-shadow .2s}
a.card:hover{transform:translateY(-2px);border-color:color-mix(in srgb,var(--acc) 45%,transparent);box-shadow:0 18px 40px rgba(0,0,0,.3)}
.page-h h1{font-size:28px;font-weight:800;letter-spacing:-.02em}
.btn:hover{filter:brightness(1.18)}.btn:active{transform:scale(.97)}.btn:focus-visible,.chip:focus-visible,.sc:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.btn.pri:hover{filter:brightness(1.1);box-shadow:0 10px 30px color-mix(in srgb,var(--acc) 50%,transparent)}
.chip{transition:.15s;cursor:pointer}.chip:hover{background:rgba(255,255,255,.14)}
.cover{width:260px;height:260px}
.meta h2{font-size:28px;letter-spacing:-.02em}
.bar{height:6px;transition:height .15s}.bar:hover{height:9px}
.bar b{opacity:0;transition:opacity .15s}.bar:hover b{opacity:1}
.ctl .big{transition:transform .15s}.ctl .big:hover{transform:scale(1.08)}
.nav a.on,.srv.on{box-shadow:inset 3px 0 0 var(--acc)}
.fade-in{animation:pop .3s}
#main>*{animation:pop .28s ease both}
::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-thumb{background:rgba(255,255,255,.16);border-radius:9px}::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.28)}
@media(max-width:860px){.cover{width:150px;height:150px}.meta h2{font-size:21px}.ly{font-size:18px}.lyrics{padding:60px 4px}.player{grid-template-columns:1fr}}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* ======================================================================
   v4: tighter layout, every screen size, seek bar, new panes
   ====================================================================== */
body{font-size:13.5px}
html,body{min-height:100dvh}
.card{padding:14px}
.card h3{margin-bottom:10px}
#app{min-height:100dvh}
#side{height:100dvh;width:226px;padding:14px 10px}
#main{padding:18px clamp(12px,2.4vw,30px) 48px;max-width:1440px}
.page-h{margin-bottom:14px;gap:10px}
.page-h h1{font-size:clamp(20px,2.4vw,26px)}
.page-h img.gi{width:40px;height:40px;border-radius:12px}
.tabs{margin-bottom:12px}.tabs a{padding:6px 13px}
.tabs.sub{margin-bottom:14px}
.grid{gap:12px}.g3{grid-template-columns:repeat(auto-fill,minmax(min(100%,210px),1fr))}
.g2{grid-template-columns:repeat(auto-fit,minmax(min(100%,340px),1fr))}
.stat b{font-size:22px}
.login{min-height:100dvh}
.boot{min-height:100dvh}

/* player fits the screen: cover scales with the window, lists scroll inside their card */
.player{gap:12px;grid-template-columns:minmax(0,1.2fr) minmax(0,1fr)}
.cover,.cover{width:clamp(130px,17vw,230px);height:clamp(130px,17vw,230px)}
.np{gap:18px}
.meta h2{font-size:clamp(19px,2.2vw,26px)}
.meta .by{font-size:14px;margin-bottom:8px}
.q-list{max-height:clamp(260px,calc(100dvh - 330px),560px)}
.ctl{gap:8px;flex-wrap:wrap;margin:10px 0}
.ctl .big{width:52px;height:52px}
.q-item{padding:6px 8px;gap:10px}
.q-item img,.q-item .th{width:40px;height:40px}
.sc-row{gap:10px}.sc{flex-basis:140px}

/* seek bar: big invisible hit area, works with finger and mouse */
.bar{height:6px;touch-action:none;user-select:none;margin:14px 0 6px;outline:0}
.bar::before{content:"";position:absolute;left:0;right:0;top:-14px;bottom:-14px}
.bar.drag,.bar:focus-visible{height:10px}
.bar.drag b,.bar:focus-visible b{opacity:1}
.bar .tip{position:absolute;bottom:18px;transform:translateX(-50%);padding:2px 7px;border-radius:7px;background:#000d;font-size:11px;font-weight:700;opacity:0;pointer-events:none;white-space:nowrap;transition:opacity .1s}
.bar .tip.on{opacity:1}
@media(hover:none){.bar b{opacity:1}.bar{height:8px}}

/* tables scroll sideways instead of breaking the page */
.tbl-wrap{overflow-x:auto;margin:0 -4px;padding:0 4px}
.tbl{min-width:420px}
.card.inner{background:rgba(255,255,255,.04);border-radius:14px;padding:12px;box-shadow:none;backdrop-filter:none}
.perm-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,230px),1fr));gap:6px;margin-top:8px}
.perm{display:flex;gap:8px;align-items:flex-start;padding:7px 9px;border-radius:10px;background:rgba(0,0,0,.2);border:1px solid var(--line);cursor:pointer;font-size:12.5px}
.perm input{margin-top:2px;accent-color:var(--acc)}
.ai-act{display:flex;gap:10px;align-items:center;padding:8px 10px;border-radius:12px;background:rgba(255,255,255,.05);border:1px solid var(--line)}
.ai-act .dot{width:24px;height:24px;border-radius:50%;display:grid;place-items:center;font-weight:800;background:rgba(255,255,255,.1);flex-shrink:0}
.ai-act.done{border-color:rgba(34,197,94,.5)}.ai-act.done .dot{background:var(--ok);color:#04130a}
.ai-act.failed{border-color:rgba(239,68,68,.5)}.ai-act.failed .dot{background:var(--bad)}
.ai-act.pending{border-color:rgba(234,179,8,.55)}.ai-act.pending .dot{background:var(--warn);color:#201a00}
.ai-log{height:min(50dvh,460px)}
textarea{width:100%;padding:10px 12px;border-radius:12px;background:rgba(0,0,0,.28);border:1px solid var(--line);outline:0;resize:vertical}
input[type=checkbox]{width:16px;height:16px}

/* tablet: sidebar shrinks to an icon rail */
@media(max-width:1180px){
  #side{width:68px;padding:12px 8px;align-items:center}
  #side .brand div,#side .side-h,#side .nav a span,#side .srv span.ell,#side .me .grow{display:none}
  #side .nav a,#side .srv{justify-content:center;padding:10px}
  #side .nav a{font-size:0;gap:0}#side .nav a svg{width:20px;height:20px}
  #side .brand{padding:4px 0 10px}
  #side .me{padding:6px;flex-direction:column}
  #install-slot .btn{font-size:0;padding:9px}
}
@media(max-width:1000px){.player,.set,.cols2{grid-template-columns:1fr}.q-list{max-height:380px}}
/* phone: bottom bar scrolls if there are many items, content tight */
@media(max-width:860px){
  #side{display:none}
  #main{padding:12px 10px calc(76px + var(--safe-b))}
  #mnav{justify-content:flex-start;overflow-x:auto;gap:2px;padding:6px 4px calc(6px + var(--safe-b));scrollbar-width:none}
  #mnav::-webkit-scrollbar{display:none}
  #mnav a{flex:1 0 62px;padding:4px 6px}
  .np{flex-direction:column;text-align:center;gap:10px}
  .cover{width:min(56vw,230px);height:min(56vw,230px)}
  .card{padding:12px}
  .ctl .btn.ic{width:36px;height:36px}
  .toast{max-width:calc(100vw - 32px)}
  #toasts{right:12px;left:12px;align-items:flex-end}
  .save{bottom:calc(70px + var(--safe-b))}
}
@media(max-width:380px){.ctl{gap:5px}.ctl .big{width:46px;height:46px}.page-h h1{font-size:19px}}
/* installed app: respect the notch */
@media(display-mode:standalone){body{overscroll-behavior-y:contain}#main{padding-top:calc(18px + var(--safe-t))}}

/* ================= confirm dialog ================= */
.modal .card.confirm{max-width:380px;text-align:center;padding:26px 22px;animation:cfin .16s ease-out}
@keyframes cfin{from{opacity:0;transform:translateY(8px) scale(.97)}to{opacity:1;transform:none}}
.cf-ic{width:52px;height:52px;border-radius:50%;display:grid;place-items:center;margin:0 auto 12px;background:color-mix(in srgb,var(--acc) 22%,transparent);color:#fff}
.cf-ic.bad{background:rgba(239,68,68,.18);color:#fca5a5}
.cf-ic svg.i{width:24px;height:24px}
.cf-t{display:block;font-size:17px}.cf-p{margin-top:6px;font-size:13px}.cf-b{margin-top:18px;gap:10px}
.cf-b .btn{padding:11px 14px}

/* ================= admin extras ================= */
.number,input[type=number]{width:100%}
.badge.warn{background:rgba(234,179,8,.15);border-color:rgba(234,179,8,.4);color:#fde047}
.badge.bad{background:rgba(239,68,68,.16);border-color:rgba(239,68,68,.45);color:#fca5a5}
.hd{width:10px;height:10px;border-radius:50%;margin-top:5px;flex-shrink:0;background:#777}
.hd.ok{background:var(--ok);box-shadow:0 0 10px rgba(34,197,94,.6)}.hd.warn{background:var(--warn)}.hd.fail{background:var(--bad);box-shadow:0 0 10px rgba(239,68,68,.6)}
.pf-bn{height:110px;border-radius:14px;background:linear-gradient(135deg,var(--acc),var(--acc2)) center/cover;border:1px solid var(--line)}
.pf-av{width:76px;height:76px;border-radius:50%;object-fit:cover;border:3px solid var(--acc);flex-shrink:0}
.term-in{font:13px/1.5 ui-monospace,Menlo,Consolas,monospace;background:rgba(0,0,0,.45)}
.term-out{background:rgba(0,0,0,.5);border:1px solid var(--line);border-radius:12px;padding:12px;font:12px/1.55 ui-monospace,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-word;max-height:55vh;overflow:auto;color:#d4d4e4}
.term-out.ok{border-color:rgba(34,197,94,.4)}.term-out.err{border-color:rgba(239,68,68,.5);color:#fca5a5}

/* ================= landing page ================= */
.lp{max-width:1180px;margin:0 auto;padding:0 20px calc(40px + var(--safe-b))}
.lp h1,.lp h2,.lp h3{letter-spacing:-.02em}
.lp-nav{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:18px;padding:calc(12px + var(--safe-t)) 0 12px;margin-bottom:8px;backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
.lp-brand{display:flex;align-items:center;gap:10px;font-size:18px}.lp-brand img{width:34px;height:34px;border-radius:50%}
.lp-links{display:flex;gap:4px;margin-left:12px;flex:1}.lp-links a{padding:8px 12px;border-radius:10px;color:var(--mut);font-weight:600}.lp-links a:hover{color:#fff;background:rgba(255,255,255,.07)}
.btn.lg{padding:14px 24px;font-size:15px;border-radius:14px}
.lp-hero{display:grid;grid-template-columns:1.1fr .9fr;gap:40px;align-items:center;padding:56px 0 70px}
.lp-hero h1{font-size:clamp(34px,5.4vw,60px);line-height:1.04;margin:16px 0}
.lp-hero h1 em{font-style:normal;background:linear-gradient(135deg,var(--acc),var(--acc2));-webkit-background-clip:text;background-clip:text;color:transparent}
.lp-hero p{font-size:17px;color:var(--mut);max-width:560px;margin-bottom:26px}
.lp-stats{display:flex;gap:30px;margin-top:34px;flex-wrap:wrap}
.lp-stat b{display:block;font-size:30px;font-weight:800}.lp-stat span{color:var(--mut);font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.07em}
.lp-mock{background:rgba(18,18,27,.8);border:1px solid var(--card-b);border-radius:22px;box-shadow:0 30px 80px rgba(0,0,0,.5),0 0 80px color-mix(in srgb,var(--acc) 22%,transparent);overflow:hidden;transform:perspective(1200px) rotateY(-6deg) rotateX(2deg)}
.lp-mock-top{display:flex;align-items:center;gap:6px;padding:12px 14px;border-bottom:1px solid var(--line)}.lp-mock-top i{width:10px;height:10px;border-radius:50%;background:rgba(255,255,255,.18)}.lp-mock-top span{margin-left:8px;font-size:12px;color:var(--mut)}
.lp-mock-body{display:flex;gap:16px;padding:18px;align-items:center}
.lp-art{width:112px;height:112px;border-radius:16px;display:grid;place-items:center;flex-shrink:0;background:linear-gradient(135deg,var(--acc),var(--acc2));box-shadow:0 12px 30px color-mix(in srgb,var(--acc) 40%,transparent)}.lp-art svg.i{width:44px;height:44px}
.lp-eq{display:flex;gap:3px;align-items:flex-end;height:16px;margin-bottom:6px}.lp-eq i{width:4px;background:var(--acc);border-radius:2px;animation:lpeq 1s ease-in-out infinite}
.lp-eq i:nth-child(2){animation-delay:.15s}.lp-eq i:nth-child(3){animation-delay:.3s}.lp-eq i:nth-child(4){animation-delay:.45s}.lp-eq i:nth-child(5){animation-delay:.6s}
@keyframes lpeq{0%,100%{height:4px}50%{height:16px}}
.lp-bar{height:5px;border-radius:9px;background:rgba(255,255,255,.14);margin:12px 0}.lp-bar i{display:block;height:100%;width:42%;border-radius:9px;background:linear-gradient(90deg,var(--acc),var(--acc2))}
.lp-ctl{display:flex;align-items:center;gap:16px;color:var(--mut)}.lp-play{width:38px;height:38px;border-radius:50%;background:#fff;color:#111;display:grid;place-items:center}
.lp-mock-q{padding:6px 18px 18px;display:flex;flex-direction:column;gap:2px}.lp-mock-q div{display:flex;gap:12px;padding:9px 10px;border-radius:10px;font-size:13px}.lp-mock-q div:first-child{background:rgba(255,255,255,.05)}
.lp-sec{padding:60px 0;scroll-margin-top:70px}
.lp-h{text-align:center;max-width:640px;margin:0 auto 34px}.lp-h h2{font-size:clamp(26px,3.6vw,38px);margin:12px 0 8px}.lp-h p{color:var(--mut);font-size:16px}
.lp-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:16px}
.lp-feat{background:var(--card);border:1px solid var(--card-b);border-radius:18px;padding:22px;backdrop-filter:blur(12px);transition:transform .2s,border-color .2s}
.lp-feat:hover{transform:translateY(-4px);border-color:color-mix(in srgb,var(--acc) 55%,transparent)}
.lp-fi{width:44px;height:44px;border-radius:13px;display:grid;place-items:center;margin-bottom:14px;background:linear-gradient(135deg,var(--acc),var(--acc2));color:#fff}
.lp-feat h3{font-size:16px;margin-bottom:6px;text-transform:none;letter-spacing:0;color:var(--text);font-weight:700}.lp-feat p{color:var(--mut);font-size:13.5px}
.lp-steps{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
.lp-step{background:var(--card);border:1px solid var(--card-b);border-radius:18px;padding:24px;position:relative}
.lp-n{width:38px;height:38px;border-radius:50%;display:grid;place-items:center;font-weight:800;margin-bottom:12px;background:color-mix(in srgb,var(--acc) 25%,transparent);border:1px solid var(--acc)}
.lp-step h3{text-transform:none;letter-spacing:0;color:var(--text);font-size:17px;margin-bottom:6px}.lp-step p{color:var(--mut)}
.lp-about{display:flex;gap:32px;align-items:center;padding:32px}.lp-about h2{font-size:30px;margin:12px 0}.lp-about p{color:var(--mut);margin-bottom:10px;font-size:15px}.lp-about-b{min-width:230px}.lp-about-b .btn{width:100%;padding:13px}
.lp-faq{max-width:760px;margin:0 auto;display:flex;flex-direction:column;gap:10px}
.lp-q{background:var(--card);border:1px solid var(--card-b);border-radius:14px;padding:0 18px}
.lp-q summary{cursor:pointer;padding:16px 0;font-weight:700;list-style:none;display:flex;justify-content:space-between;gap:12px}
.lp-q summary::-webkit-details-marker{display:none}.lp-q summary::after{content:"+";font-size:20px;color:var(--mut);line-height:1}.lp-q[open] summary::after{content:"–"}
.lp-q p{color:var(--mut);padding-bottom:16px}
.lp-cta{text-align:center;padding:48px 20px;margin:30px 0;background:linear-gradient(135deg,color-mix(in srgb,var(--acc) 22%,transparent),color-mix(in srgb,var(--acc2) 14%,transparent))}
.lp-cta h2{font-size:clamp(24px,3.4vw,34px);margin-bottom:6px}.lp-cta .row{margin-top:20px}
.lp-foot{text-align:center;padding:30px 0 10px;border-top:1px solid var(--line);margin-top:30px}.lp-foot a{color:var(--mut);font-weight:600}.lp-foot a:hover{color:#fff}
@media(max-width:900px){
  .lp-hero{grid-template-columns:1fr;padding:30px 0 50px;gap:34px}.lp-mock{transform:none}
  .lp-links{display:none}.lp-nav{justify-content:space-between}.lp-steps{grid-template-columns:1fr}
  .lp-about{flex-direction:column;align-items:stretch}.lp-hide-s{display:none}.lp-sec{padding:40px 0}
}

/* ---- loading shimmer, logo fallback, discover ---- */
@keyframes shim{0%{background-position:100% 50%}100%{background-position:0 50%}}
.sk,img.sk{background:linear-gradient(90deg,rgba(255,255,255,.05) 25%,rgba(255,255,255,.13) 37%,rgba(255,255,255,.05) 63%);background-size:400% 100%;animation:shim 1.3s ease infinite}
.sl{height:11px;border-radius:6px;margin:5px 0;width:70%}.sl.s{width:40%}
img.fb{object-fit:contain!important;padding:12%;background:#14141c}
.sc{display:flex;flex-direction:column;justify-content:flex-start;align-self:flex-start;--w:150px;flex:0 0 var(--w);width:var(--w);min-width:0}
.sc-i{flex:none}
@media(hover:none){.sc{--w:130px}}
@media(max-width:700px){.sc{--w:140px}}
.inf-gap{display:flex;justify-content:center}.inf-gap:empty{display:none}
.inf-tail{min-height:2px}

/* unsaved-changes bar: only there when something changed */
.save{align-items:center;animation:pop .22s}
.save.hide{display:none}

/* discover: card grid */
.tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px}
.tile{display:flex;flex-direction:column;gap:3px;padding:8px;border-radius:14px;background:rgba(255,255,255,.04);border:1px solid var(--line);transition:transform .15s,background .15s}
.tile:hover{background:rgba(255,255,255,.09);transform:translateY(-2px)}
.tcover{position:relative;aspect-ratio:1;border-radius:10px;overflow:hidden;background:#23232f;cursor:pointer;margin-bottom:6px}
.tcover img{width:100%;height:100%;object-fit:cover;display:block}
.tplay{position:absolute;right:8px;bottom:8px;width:38px;height:38px;border-radius:50%;display:grid;place-items:center;color:#fff;background:linear-gradient(135deg,var(--acc),var(--acc2));box-shadow:0 6px 18px rgba(0,0,0,.45);opacity:0;transform:translateY(6px);transition:.18s}
.tplay svg{width:16px;height:16px}
.tile:hover .tplay,.tcover:focus-within .tplay{opacity:1;transform:none}
@media(hover:none){.tplay{opacity:1;transform:none}}
.tdur{position:absolute;left:6px;bottom:6px;padding:1px 6px;border-radius:6px;font-size:11px;font-weight:700;background:#000b}
.tt{font-weight:700;font-size:13px}.ts{font-size:12px;color:var(--mut)}
.tact{display:flex;gap:6px;margin-top:6px}.tact .btn{flex:1;justify-content:center}
.tile .sl{height:12px;border-radius:6px;margin:4px 0}.tile .sl.s{width:60%}

/* lyrics timing */

/* volume: icon | slider | value, with equal side columns so the slider sits in the true middle */
.vol{display:grid;grid-template-columns:44px minmax(0,1fr) 44px;align-items:center;column-gap:10px;width:100%;max-width:340px;margin:6px auto 0}
.vol-i{display:grid;place-items:center;color:var(--mut)}.vol-i svg{width:20px;height:20px}
.vol-v{text-align:center;font-size:12px;font-weight:600;color:var(--mut);font-variant-numeric:tabular-nums}
.vol input[type=range]{height:6px;background:linear-gradient(90deg,var(--acc),var(--acc2)) 0/var(--p,50%) 100% no-repeat,rgba(255,255,255,.14);cursor:pointer;touch-action:pan-y}
.vol input[type=range]::-webkit-slider-thumb{width:16px;height:16px;box-shadow:0 1px 6px rgba(0,0,0,.5)}
.vol input[type=range]::-moz-range-thumb{width:16px;height:16px;border:0;border-radius:50%;background:#fff;box-shadow:0 1px 6px rgba(0,0,0,.5)}
.vol input[type=range]:disabled{opacity:.45;cursor:not-allowed}

/* save queue: a clean accent pill instead of a plain grey box */
.q-head{flex-wrap:nowrap;gap:8px}
.btn.saveq{padding:7px 14px;gap:7px;border-radius:99px;font-weight:700;white-space:nowrap;background:color-mix(in srgb,var(--acc) 16%,transparent);border:1px solid color-mix(in srgb,var(--acc) 50%,transparent);color:#fff}
.btn.saveq svg{width:15px;height:15px}
.btn.saveq:hover:not(:disabled){background:linear-gradient(135deg,var(--acc),var(--acc2));border-color:transparent;transform:translateY(-1px);box-shadow:0 6px 18px color-mix(in srgb,var(--acc) 35%,transparent)}
.btn.saveq:active:not(:disabled){transform:none}

/* =====================================================================
   MOTION + STYLE SYSTEM  (every piece is switched by a data-* on <body>,
   which the owner changes in Manage server -> Look)
   ===================================================================== */
:root{--speed:1;--glow-p:35%;--glow-px:59px;--ease:cubic-bezier(.22,1,.36,1)}

/* ---------- animated backgrounds ---------- */
#bg-fx{position:absolute;inset:0;overflow:hidden;pointer-events:none}
body[data-fx=none] #bg-fx{display:none}
.flowfx{position:absolute;inset:-30%;will-change:transform;filter:blur(30px);
  background:radial-gradient(38% 38% at 28% 30%,color-mix(in srgb,var(--acc) 42%,transparent),transparent 70%),radial-gradient(34% 34% at 72% 62%,color-mix(in srgb,var(--acc2) 36%,transparent),transparent 70%);
  animation:flow calc(22s / var(--speed)) ease-in-out infinite alternate}
.flowfx.b{background:radial-gradient(30% 30% at 70% 25%,color-mix(in srgb,var(--acc2) 30%,transparent),transparent 70%),radial-gradient(36% 36% at 25% 75%,color-mix(in srgb,var(--acc) 30%,transparent),transparent 70%);animation-duration:calc(30s / var(--speed));animation-direction:alternate-reverse}
@keyframes flow{from{transform:translate3d(-7%,-5%,0) rotate(0) scale(1)}to{transform:translate3d(7%,6%,0) rotate(28deg) scale(1.18)}}
.orb{position:absolute;border-radius:50%;filter:blur(64px);opacity:.5;will-change:transform;animation:orb calc(19s / var(--speed)) ease-in-out infinite alternate}
.orb.o0{width:46vmax;height:46vmax;left:-12%;top:-14%;background:var(--acc)}
.orb.o1{width:38vmax;height:38vmax;right:-10%;top:8%;background:var(--acc2);animation-delay:-4s}
.orb.o2{width:34vmax;height:34vmax;left:22%;bottom:-18%;background:color-mix(in srgb,var(--acc) 60%,var(--acc2));animation-delay:-8s}
.orb.o3{width:22vmax;height:22vmax;right:18%;bottom:6%;background:var(--acc);opacity:.3;animation-delay:-12s}
.orb.o4{width:18vmax;height:18vmax;left:46%;top:30%;background:var(--acc2);opacity:.25;animation-delay:-2s}
@keyframes orb{from{transform:translate3d(0,0,0) scale(1)}to{transform:translate3d(9vmax,-7vmax,0) scale(1.25)}}
.star{position:absolute;width:var(--sz);height:var(--sz);border-radius:50%;background:#fff;opacity:.12;animation:twinkle calc(var(--d) / var(--speed)) ease-in-out var(--dl) infinite}
@keyframes twinkle{50%{opacity:.95;transform:scale(1.5)}}
.gridfx{position:absolute;inset:0;background-image:linear-gradient(color-mix(in srgb,var(--acc) 26%,transparent) 1px,transparent 1px),linear-gradient(90deg,color-mix(in srgb,var(--acc) 26%,transparent) 1px,transparent 1px);background-size:48px 48px;
  -webkit-mask-image:radial-gradient(75% 65% at 50% 35%,#000,transparent);mask-image:radial-gradient(75% 65% at 50% 35%,#000,transparent);animation:gridmove calc(7s / var(--speed)) linear infinite}
@keyframes gridmove{to{background-position:0 48px,48px 0}}
body[data-anim=off] #bg-fx *{animation:none!important}
@media(max-width:860px){.flowfx{filter:blur(18px)}.orb{filter:blur(40px)}}

/* ---------- pages and cards rise in, one after another ---------- */
@keyframes rise{from{opacity:0;transform:translateY(16px) scale(.985)}to{opacity:1;transform:none}}
@keyframes rise-l{from{opacity:0;transform:translateY(30px) scale(.95)}55%{opacity:1;transform:translateY(-4px) scale(1.01)}to{transform:none}}
@keyframes fade{from{opacity:0}to{opacity:1}}
body[data-anim=subtle] #main.enter .card,body[data-anim=subtle] #main.enter .page-h{animation:fade .4s both;animation-delay:calc(var(--i,0) * 40ms)}
body[data-anim=smooth] #main.enter .card,body[data-anim=smooth] #main.enter .page-h{animation:rise calc(.6s / var(--speed)) var(--ease) both;animation-delay:calc(var(--i,0) * 60ms)}
body[data-anim=lively] #main.enter .card,body[data-anim=lively] #main.enter .page-h{animation:rise-l calc(.8s / var(--speed)) var(--ease) both;animation-delay:calc(var(--i,0) * 85ms)}
body:not([data-anim=off]) .modal{animation:pop .3s var(--ease)}
body:not([data-anim=off]) .toast{animation:toast-in .45s var(--ease)}
@keyframes toast-in{from{opacity:0;transform:translateY(18px) scale(.94)}to{opacity:1;transform:none}}

/* ---------- micro interactions ---------- */
.btn,.chip,.sc,.pl,.q-item,.seg button,.tabs a,.ctl .big{transition:transform .28s var(--ease),background .2s,box-shadow .28s,border-color .2s,color .2s,filter .2s,opacity .2s}
.btn,.chip,.seg button,.tabs a,.ctl .big{position:relative;overflow:hidden;isolation:isolate}
.rip{position:absolute;border-radius:50%;background:radial-gradient(circle,rgba(255,255,255,.55),rgba(255,255,255,0) 65%);transform:scale(0);opacity:.9;pointer-events:none;animation:rip .65s ease-out forwards;z-index:-1}
@keyframes rip{to{transform:scale(1);opacity:0}}
body:not([data-anim=off]) .btn:active:not(:disabled),body:not([data-anim=off]) .ctl .big:active,body:not([data-anim=off]) .chip:active{transform:scale(.94)}
body:not([data-anim=off]) .btn.ic:hover:not(:disabled){transform:translateY(-2px)}
body:not([data-anim=off]) .ctl .big:hover{transform:scale(1.08)}
body[data-hover=lift] .sc:hover,body[data-hover=lift] .pl:hover{transform:translateY(-4px)}
body[data-hover=lift] .q-item:hover{transform:translateX(3px)}
body[data-hover=glow] .card:hover,body[data-hover=glow] .sc:hover,body[data-hover=glow] .pl:hover{box-shadow:0 0 0 1px color-mix(in srgb,var(--acc) 55%,transparent),0 12px 44px color-mix(in srgb,var(--acc) 26%,transparent)}
body[data-hover=pop] .sc:hover,body[data-hover=pop] .pl:hover,body[data-hover=pop] .q-item:hover{transform:scale(1.035)}
body[data-anim=off] *{transition-duration:0s!important}
.ctl .big{animation:none}
body[data-anim=lively] .ctl .big.on,body[data-anim=lively] .cover.spin~*{will-change:transform}

/* ---------- cover effects (while a song plays) ---------- */
body[data-cover=glow] .cover.spin,body[data-cover=float] .cover.spin,body[data-cover=pulse] .cover.spin{filter:drop-shadow(0 0 var(--glow-px) color-mix(in srgb,var(--acc) var(--glow-p),transparent))}
body[data-cover=float]:not([data-layout=vinyl]) .cover.spin{animation:float calc(5s / var(--speed)) ease-in-out infinite}
body[data-cover=pulse]:not([data-layout=vinyl]) .cover.spin{animation:beat calc(1.7s / var(--speed)) ease-in-out infinite}
@keyframes float{50%{transform:translateY(-10px) rotate(.6deg)}}
@keyframes beat{0%,100%{transform:scale(1)}18%{transform:scale(1.035)}36%{transform:scale(1)}}
body[data-anim=off] .cover.spin{animation:none!important}

/* ---------- sound bars ---------- */
.viz{display:flex;align-items:flex-end;gap:3px;height:20px;margin:6px 0 2px;opacity:.55;transition:opacity .4s}
.viz i{width:4px;height:100%;border-radius:3px;background:linear-gradient(to top,var(--acc),var(--acc2));transform:scaleY(.14);transform-origin:bottom}
.viz.on{opacity:1}.viz.on i{animation:viz .8s ease-in-out infinite alternate}
@keyframes viz{from{transform:scaleY(.14)}to{transform:scaleY(1)}}
body[data-viz=off] .meta>.viz{display:none}
body[data-anim=off] .viz i{animation:none!important;transform:scaleY(.3)}
@media(max-width:860px){.np .viz{justify-content:center}}

/* ---------- song title ---------- */
body[data-title=gradient] .meta h2,body[data-title=shimmer] .meta h2{-webkit-background-clip:text;background-clip:text;color:transparent}
body[data-title=gradient] .meta h2{background-image:linear-gradient(90deg,#fff,color-mix(in srgb,var(--acc2) 65%,#fff))}
body[data-title=shimmer] .meta h2{background-image:linear-gradient(100deg,#fff 30%,var(--acc2) 44%,var(--acc) 56%,#fff 70%);background-size:260% 100%;animation:shim calc(5s / var(--speed)) linear infinite}
@keyframes shim{to{background-position:-260% 0}}

/* ---------- progress bar ---------- */
body[data-bar=thick] .bar{height:12px!important}
body[data-bar=thick] .bar b{width:20px;height:20px;margin:-10px 0 0 -10px}
body[data-bar=glow] .bar i{box-shadow:0 0 14px color-mix(in srgb,var(--acc) 75%,transparent)}
body[data-bar=glow] .bar b{box-shadow:0 0 0 4px color-mix(in srgb,var(--acc) 35%,transparent),0 0 18px var(--acc)}
.bar i,.bar b{transition:width .25s linear,left .25s linear}
.bar.drag i,.bar.drag b{transition:none}

/* ---------- buttons ---------- */
body[data-btn=solid] .btn.pri,body[data-btn=solid] .ctl .big{background:var(--acc);box-shadow:0 6px 18px color-mix(in srgb,var(--acc) 32%,transparent)}
body[data-btn=glass] .btn.pri,body[data-btn=glass] .ctl .big{background:color-mix(in srgb,var(--acc) 26%,rgba(255,255,255,.06));border:1px solid color-mix(in srgb,var(--acc) 60%,transparent);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);box-shadow:inset 0 1px 0 rgba(255,255,255,.18)}
body[data-btn=outline] .btn.pri,body[data-btn=outline] .ctl .big{background:transparent;border:1.5px solid var(--acc);box-shadow:0 0 18px color-mix(in srgb,var(--acc) 28%,transparent)}
body[data-btn=outline] .btn.pri:hover,body[data-btn=outline] .ctl .big:hover{background:color-mix(in srgb,var(--acc) 22%,transparent)}

/* ---------- lyrics ---------- */
.ly{transition:color .3s,transform .35s var(--ease),filter .3s,opacity .3s,text-shadow .3s}
body[data-lyfx=glow] .ly.on{transform:none;text-shadow:0 0 var(--glow-px) var(--acc),0 0 10px color-mix(in srgb,var(--acc) 70%,transparent)}
body[data-lyfx=blur] .ly{filter:blur(1.6px);opacity:.75}
body[data-lyfx=blur] .ly.on{filter:none;opacity:1;transform:scale(1.04)}
body[data-lyfx=blur] .ly:hover{filter:none}

/* ---------- one-tap looks + custom css box ---------- */
.presets{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:10px}
.preset{display:flex;flex-direction:column;align-items:center;gap:7px;padding:10px 6px;border-radius:14px;background:rgba(255,255,255,.05);border:1px solid var(--line);font-size:12px;font-weight:700;color:var(--text);transition:transform .25s var(--ease),border-color .2s,background .2s}
.preset:hover{transform:translateY(-3px);border-color:var(--acc);background:rgba(255,255,255,.09)}
.preset:active{transform:scale(.95)}
.pv-sw{width:100%;height:38px;border-radius:10px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.18),0 6px 16px rgba(0,0,0,.3)}
textarea.code{min-height:130px;font-family:"JetBrains Mono",ui-monospace,Menlo,Consolas,monospace;font-size:12px;line-height:1.5;resize:vertical}

/* ---------- owner announcement ---------- */
#announce:empty{display:none}
#announce{position:sticky;top:0;z-index:60}
.ann{display:flex;align-items:center;gap:10px;padding:10px 16px;padding-top:calc(10px + var(--safe-t));font-size:13px;font-weight:600;border-bottom:1px solid;-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);animation:slide-down .55s var(--ease)}
.ann svg{width:18px;height:18px;flex-shrink:0}
.ann.info{background:color-mix(in srgb,var(--acc) 26%,rgba(10,10,15,.92));border-color:color-mix(in srgb,var(--acc) 55%,transparent)}
.ann.success{background:rgba(22,101,52,.55);border-color:rgba(34,197,94,.5);color:#bbf7d0}
.ann.warn{background:rgba(113,63,18,.6);border-color:rgba(234,179,8,.55);color:#fde68a}
.ann .x{width:28px;height:28px;border-radius:50%;display:grid;place-items:center;background:rgba(255,255,255,.1);flex-shrink:0}
.ann .x:hover{background:rgba(255,255,255,.2)}.ann .x svg{width:14px;height:14px}
@keyframes slide-down{from{transform:translateY(-100%);opacity:0}to{transform:none;opacity:1}}


/* ======================================================================
   v5: smooth + fits the screen
   (seek bar on the compositor, tidy tabs, panels that never outgrow the
   window, lighter backgrounds, lyrics sync, terms link)
   ====================================================================== */

/* ---------- seek bar: moves with a CSS variable, no layout work per tick ---------- */
.bar{--p:0;touch-action:none;-webkit-user-select:none;user-select:none;cursor:pointer}
.bar i{width:100%!important;transform:scaleX(var(--p));transform-origin:left center;will-change:transform;transition:none!important}
.bar b{left:calc(var(--p) * 100%)!important;transition:none!important}
.bar:focus-visible{outline:2px solid var(--acc);outline-offset:6px}
.np .meta{min-width:0}
@media(max-width:860px){
  .np .meta{width:100%;align-self:stretch}
  .np .meta .bar{margin-top:12px}
  .bar{height:8px}
  .bar::before{top:-18px;bottom:-18px}
}

/* ---------- lyrics sync row ---------- */
.ly-sync{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:10px;padding-top:10px;border-top:1px solid var(--line);flex-wrap:wrap}
.ly-sync.hide{display:none}
.ly-sync-v{min-width:64px;text-align:center;font-size:12px;font-weight:700;color:var(--mut);font-variant-numeric:tabular-nums}

/* ---------- tabs: one tidy segmented bar (admin, staff, server, settings) ---------- */
.tabs{position:relative;display:flex;gap:4px;padding:4px;margin-bottom:14px;border-radius:16px;background:rgba(10,10,16,.45);border:1px solid var(--line);
  overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;scroll-snap-type:x proximity;width:fit-content;max-width:100%}
.tabs::-webkit-scrollbar{display:none}
.tabs a{display:inline-flex;align-items:center;gap:7px;padding:8px 14px;border-radius:12px;font-weight:700;font-size:13px;color:var(--mut);background:transparent;border:0;white-space:nowrap;scroll-snap-align:center;transition:background .2s,color .2s,box-shadow .2s}
.tabs a svg.i{width:15px;height:15px;opacity:.85}
.tabs a:hover{color:var(--text);background:rgba(255,255,255,.07)}
.tabs a.on{color:#fff;background:linear-gradient(135deg,var(--acc),var(--acc2));box-shadow:0 6px 18px color-mix(in srgb,var(--acc) 38%,transparent)}
.tabs a.on svg.i{opacity:1}
/* the admin area has a lot of tabs: on a wide screen they wrap into tidy rows, on a phone they scroll with a soft edge */
.tabs.many{display:grid;grid-template-columns:repeat(auto-fit,minmax(122px,1fr));overflow:visible;width:100%}
.tabs.many a{justify-content:center}
@media(max-width:860px){
  .tabs.many{display:flex;flex-wrap:nowrap;overflow-x:auto;width:100%;
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 14px,#000 calc(100% - 22px),transparent 100%);mask-image:linear-gradient(90deg,transparent 0,#000 14px,#000 calc(100% - 22px),transparent 100%)}
  .tabs.many a{flex:0 0 auto}
}
.tabs.sub{background:rgba(10,10,16,.35)}

/* ---------- pages that must fit the window: playlists + AI ----------
   The page itself never grows past the screen; the lists inside the cards scroll instead. */
:root{--head-h:92px}
.fit{display:flex;flex-direction:column;height:calc(100dvh - 72px - var(--safe-t));min-height:420px}
.fit>.page-h{flex:0 0 auto}
.fit-body{flex:1 1 auto;min-height:0}
.fit .cols2{height:100%;grid-template-rows:minmax(0,1fr)}
.fit .cols2>*{min-height:0}
.fit .pl-side{display:flex;flex-direction:column;gap:12px;min-height:0;height:100%}
.fit .pl-side .grow-card{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.fit .pl-side .grow-card .pl-list{flex:1 1 auto;min-height:0;overflow-y:auto;margin:0 -6px;padding:0 6px}
.fit .pl-detail{display:flex;flex-direction:column;min-height:0;height:100%}
.fit .pl-detail .pl-tracks{flex:1 1 auto;min-height:0;overflow-y:auto;margin:0 -6px;padding:0 6px}
.fit .pl-detail .q-list{max-height:none!important}
.fit-card{display:flex;flex-direction:column;min-height:0;height:100%}
.fit-card .ai-log{flex:1 1 auto;min-height:0;height:auto}
@media(max-width:1000px){
  /* stacked on small screens: the list gets a fixed share of the screen, the open playlist gets the rest */
  .fit{height:calc(100dvh - 24px - var(--safe-b) - 64px)}
  .fit .cols2{grid-template-columns:1fr;grid-template-rows:minmax(150px,34%) minmax(0,1fr)}
}
.ai-log{height:auto}
.ai-in{flex:0 0 auto}
.ai-chips{flex:0 0 auto;max-height:84px;overflow-y:auto;margin:10px 0 !important}

/* ---------- lyrics / queue panels follow the window height ---------- */
.side-card .q-list,.side-card .lyrics{max-height:clamp(280px,calc(100dvh - 300px),620px)}
.lyrics{min-height:240px}
@media(max-width:1000px){.side-card .q-list,.side-card .lyrics{max-height:min(60dvh,460px)}}

/* ---------- queue thumbnails stay small ---------- */
.q-item img,.q-item .th{width:40px!important;height:40px!important;max-width:40px;border-radius:9px;object-fit:cover}
.q-item img.fb{object-fit:contain}

/* ---------- LIGHTER BACKGROUNDS, SAME LOOK ----------
   The old animated layers were soft gradients that were then blurred again by the browser, which is very
   heavy on phones. The gradients are already soft, so the extra blur is gone. */
.flowfx{filter:none!important}
.orb{filter:none!important;opacity:.38;background:radial-gradient(closest-side,var(--c,var(--acc)),transparent)!important}
.orb.o0{--c:var(--acc)}.orb.o1{--c:var(--acc2)}.orb.o2{--c:color-mix(in srgb,var(--acc) 60%,var(--acc2))}.orb.o3{--c:var(--acc);opacity:.26}.orb.o4{--c:var(--acc2);opacity:.2}
.flowfx,.orb,.star,.gridfx{backface-visibility:hidden;contain:strict}
#bg{contain:strict}
#bg-img{will-change:opacity}
.card{will-change:auto}
/* long lists only paint what is on screen */
.q-item,.pl,.tile{content-visibility:auto;contain-intrinsic-size:auto 56px}
.tile{contain-intrinsic-size:auto 220px}
/* the cover glow is a filter on a moving element: use a plain shadow instead, same colour */
body[data-cover=glow] .cover.spin,body[data-cover=float] .cover.spin,body[data-cover=pulse] .cover.spin{filter:none;box-shadow:0 0 var(--glow-px) color-mix(in srgb,var(--acc) var(--glow-p),transparent),0 22px 50px rgba(0,0,0,.5)}
body[data-layout=vinyl][data-cover] .cover.spin{box-shadow:0 0 0 10px rgba(0,0,0,.55),0 0 var(--glow-px) color-mix(in srgb,var(--acc) var(--glow-p),transparent)}

/* phones and older computers: measured while the page loads (see the frame check in app.js) and only then
   the heaviest effects are swapped for cheaper ones. Fast devices keep everything. */
body[data-perf=lite] .card{-webkit-backdrop-filter:none;backdrop-filter:none;background:rgba(22,22,32,.9)}
body[data-perf=lite] #side,body[data-perf=lite] #mnav,body[data-perf=lite] .lp-nav,body[data-perf=lite] .save,body[data-perf=lite] .modal{-webkit-backdrop-filter:none;backdrop-filter:none}
body[data-perf=lite] #bg-fx *{animation-duration:calc(60s / var(--speed))!important}
body[data-perf=lite] .viz.on i{animation-duration:1.4s}
body[data-perf=lite] #bg-img{filter:none}
body[data-perf=lite][data-layout=vinyl] .cover.spin{animation-duration:30s}

/* ---------- footer links (terms) ---------- */
.legal{display:flex;gap:6px 14px;flex-wrap:wrap;justify-content:center;font-size:12px;color:var(--mut);padding:10px 0 0}
.legal a{color:var(--mut);font-weight:600;text-decoration:underline;text-underline-offset:3px;text-decoration-color:rgba(255,255,255,.25)}
.legal a:hover{color:var(--text)}
#side .legal{justify-content:flex-start;padding:6px 10px 0}
@media(max-width:1180px){#side .legal{display:none}}

/* ======================================================================
   Listen on: Bot · Both · This device
   ====================================================================== */
.osw{--i:0;position:relative;display:grid;grid-template-columns:repeat(3,1fr);padding:4px;border-radius:14px;background:rgba(10,10,16,.55);border:1px solid var(--line);isolation:isolate;min-width:0}
.osw-thumb{position:absolute;z-index:-1;top:4px;bottom:4px;left:4px;width:calc((100% - 8px) / 3);border-radius:10px;background:linear-gradient(135deg,var(--acc),var(--acc2));
  box-shadow:0 6px 16px color-mix(in srgb,var(--acc) 40%,transparent);transform:translateX(calc(var(--i) * 100%));transition:transform .38s var(--ease)}
.osw button{display:flex;align-items:center;justify-content:center;gap:6px;padding:8px 6px;border:0;background:transparent;color:var(--mut);font:inherit;font-weight:700;font-size:12.5px;border-radius:10px;cursor:pointer;white-space:nowrap;min-width:0;transition:color .25s}
.osw button svg.i{width:15px;height:15px;flex:none}
.osw button span{overflow:hidden;text-overflow:ellipsis}
.osw button[aria-checked=true]{color:#fff}
.osw button:not([aria-checked=true]):hover{color:var(--text)}
.osw.wide{max-width:430px}
.osw.sm{max-width:290px}.osw.sm button{padding:6px 4px;font-size:11.5px}.osw.sm button svg.i{display:none}
.osw.side{width:100%}.osw.side button{padding:7px 2px;font-size:11.5px;gap:0}.osw.side button svg.i{display:none}
.osw.hdr{flex:none;align-self:flex-start;width:min(330px,100%)}
.side-out{padding:0 4px 6px}
.page-h{flex-wrap:wrap}
@media(max-width:700px){.osw.hdr{width:100%;order:9}.osw.hdr button span{font-size:12px}}
body[data-out=device] .srv-only{display:none}

/* ---------- mini player (this device) ---------- */
#lp{position:fixed;z-index:60;left:50%;bottom:calc(14px + var(--safe-b));width:min(560px,calc(100vw - 24px));transform:translate(-50%,24px);opacity:0;pointer-events:none;
  background:rgba(20,20,30,.92);border:1px solid var(--line);border-radius:20px;padding:10px 12px 10px;box-shadow:0 18px 50px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.03) inset;
  -webkit-backdrop-filter:blur(16px) saturate(1.2);backdrop-filter:blur(16px) saturate(1.2);transition:transform .45s var(--ease),opacity .3s}
#lp.on{transform:translate(-50%,0);opacity:1;pointer-events:auto}
@media(min-width:861px){#lp{left:calc(50% + 120px)}}
@media(max-width:860px){#lp{bottom:calc(70px + var(--safe-b))}}
body.has-lp #main{padding-bottom:150px}
.lp-main{display:flex;align-items:center;gap:10px}
.lp-cover{width:44px;height:44px;flex:none;border-radius:12px;overflow:hidden;background:#15151f;box-shadow:0 6px 16px rgba(0,0,0,.4)}
.lp-cover img{width:100%;height:100%;object-fit:cover;display:block}
.lp-info{flex:1;min-width:0}
.lp-t{font-weight:800;font-size:14px}
.lp-s{font-size:12px;color:var(--mut)}
.lp-ctl{display:flex;align-items:center;gap:6px}
.lp-ctl .pri{width:42px;height:42px;border-radius:50%}
#lp.mirror .lp-ctl{display:none}
.lp-seek{display:flex;align-items:center;gap:10px;margin-top:8px;font-size:11px;color:var(--mut);font-variant-numeric:tabular-nums}
.lp-seek .bar{flex:1;margin:0;height:5px}
.lp-seek .bar::before{top:-12px;bottom:-12px}
#lp.mirror .lp-bar{pointer-events:none;opacity:.8}
.lp-foot{display:flex;align-items:center;gap:10px;margin-top:8px}
.lp-foot svg.i{width:16px;height:16px;color:var(--mut);flex:none}
.lp-vol{width:90px;accent-color:var(--acc);height:4px}
.lp-mode{font-size:11px;font-weight:700;color:var(--mut);padding:4px 9px;border-radius:999px;border:1px solid var(--line);white-space:nowrap}
.lp-mode.sync{color:#fff;border-color:transparent;background:linear-gradient(135deg,var(--acc),var(--acc2))}
@media(max-width:480px){.lp-vol{width:64px}.lp-mode{display:none}}
/* the real YouTube player lives off-screen (it is the sound source) */
#lp-host{position:fixed;left:-400px;bottom:0;width:200px;height:200px;overflow:hidden;pointer-events:none;opacity:.01}

/* compact mini player: on a phone the "Both" mode only needs the title, the switch and the volume */
#lp.mirror .lp-seek{display:none}
@media(max-width:560px){
  .osw.sm button span{display:none}.osw.sm button svg.i{display:block}
  .osw.sm{max-width:150px}
  .lp-foot{gap:8px}
}
@media(max-width:560px){
  #lp.mirror .lp-foot{display:none}
  #lp.mirror{padding:8px 10px}
  body.has-lp #main{padding-bottom:130px}
}

/* ======================================================================
   Big "Listen on" switch (Bot · Both · This device): icon + name + hint, easy to tap
   ====================================================================== */
.osw-h{display:none;font-size:10.5px;font-weight:600;opacity:.75;line-height:1.1;white-space:nowrap}
.osw.lg{width:100%;max-width:none;padding:5px;border-radius:16px}
.osw.lg .osw-thumb{top:5px;bottom:5px;left:5px;width:calc((100% - 10px) / 3);border-radius:12px}
.osw.lg button{flex-direction:column;gap:3px;padding:10px 4px;min-height:62px;font-size:13px}
.osw.lg button svg.i{display:block;width:20px;height:20px}
.osw.lg button span{font-size:13px}
.osw.lg .osw-h{display:block}
@media(max-width:700px){
  .osw.hdr{width:100%;padding:5px;border-radius:16px}
  .osw.hdr .osw-thumb{top:5px;bottom:5px;left:5px;width:calc((100% - 10px) / 3);border-radius:12px}
  .osw.hdr button{flex-direction:column;gap:3px;padding:10px 4px;min-height:60px}
  .osw.hdr button svg.i{width:20px;height:20px}
  .osw.hdr .osw-h{display:block}
}

/* ======================================================================
   Now playing: bar (phones) + full player with queue (phone = full screen, tablet / desktop = side panel)
   ====================================================================== */
#dock{display:none}
.np-cover,.fp-cover{overflow:hidden;background:#15151f;display:grid;place-items:center}
.np-cover img,.fp-cover img{width:100%;height:100%;object-fit:cover;display:block}
@media(max-width:860px){
  #dock{display:block;position:fixed;z-index:55;left:8px;right:8px;bottom:calc(64px + var(--safe-b));border-radius:18px;background:rgba(24,24,34,.95);border:1px solid var(--line);
    box-shadow:0 14px 38px rgba(0,0,0,.55);overflow:hidden;transform:translateY(24px);opacity:0;pointer-events:none;cursor:pointer;
    -webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);transition:transform .4s var(--ease),opacity .25s}
  #dock.on{transform:none;opacity:1;pointer-events:auto}
  .dk-main{display:flex;align-items:center;gap:10px;padding:8px 10px}
  .np-cover{width:46px;height:46px;border-radius:11px;flex:none}
  .dk-info{flex:1;min-width:0}
  .np-t{font-weight:800;font-size:14px}
  .np-s{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--mut);min-width:0}
  .np-m svg.i{width:12px;height:12px;display:block}
  .np-btn{width:42px;height:42px;border-radius:50%;display:grid;place-items:center;color:#fff;flex:none;border:0;background:transparent}
  .np-btn.main{background:linear-gradient(135deg,var(--acc),var(--acc2));box-shadow:0 6px 16px color-mix(in srgb,var(--acc) 40%,transparent)}
  .np-btn svg.i{width:20px;height:20px}
  .dk-prog{height:3px;background:rgba(255,255,255,.12)}
  .dk-prog i{display:block;height:100%;width:100%;transform:scaleX(var(--p,0));transform-origin:left center;background:linear-gradient(90deg,var(--acc),var(--acc2))}
  #lp{display:none!important}
  body.has-dock #main{padding-bottom:calc(150px + var(--safe-b))}
  body.has-dock .save{bottom:calc(132px + var(--safe-b))}
  body.has-dock #toasts{bottom:calc(132px + var(--safe-b))}
}
body.fp-open{overflow:hidden}
#fp{position:fixed;inset:0;z-index:90;display:flex;justify-content:flex-end;background:rgba(0,0,0,0);visibility:hidden;pointer-events:none;transition:background .3s,visibility 0s .4s}
#fp.on{background:rgba(0,0,0,.55);visibility:visible;pointer-events:auto;transition:background .3s}
.fp-panel{position:relative;width:min(480px,100%);height:100%;display:flex;flex-direction:column;gap:12px;padding:calc(10px + var(--safe-t)) 18px calc(16px + var(--safe-b));
  background:#0b0b10;overflow:hidden;isolation:isolate;transform:translateX(100%);transition:transform .42s var(--ease);border-left:1px solid var(--line)}
.fp-panel::before{content:"";position:absolute;inset:-40px;z-index:-1;background:var(--fp-img,none) center/cover;filter:blur(46px) saturate(1.3);opacity:.42;transform:scale(1.2)}
.fp-panel::after{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(180deg,rgba(11,11,16,.15),rgba(11,11,16,.78) 55%,#0b0b10)}
#fp.on .fp-panel{transform:none}
@media(max-width:860px){.fp-panel{width:100%;border-left:0;transform:translateY(100%)}}
.fp-top{display:flex;align-items:center;gap:10px}
.fp-x{width:42px;height:42px;border-radius:50%;display:grid;place-items:center;background:rgba(255,255,255,.1);color:#fff;border:0;flex:none}
.fp-x svg.i{width:22px;height:22px}
.fp-sp{width:42px;flex:none}
.fp-where{flex:1;min-width:0;text-align:center;line-height:1.25}
.fp-where small{display:block;font-size:10px;letter-spacing:.12em;color:var(--mut);font-weight:700}
.fp-where b{display:block;font-size:13px}
.fp-tabs{flex:none}.fp-tabs button{padding:9px 8px;font-size:13px}
.fp-now{flex:1 1 auto;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:14px;padding:4px 2px 4px;scrollbar-width:none}
.fp-now::-webkit-scrollbar{display:none}
.fp-cover{width:min(100%,max(180px,42dvh));aspect-ratio:1;border-radius:22px;margin:4px auto 0;box-shadow:0 24px 60px rgba(0,0,0,.55),0 0 70px color-mix(in srgb,var(--acc) 22%,transparent);flex:none}
.fp-meta{min-width:0}
.fp-title{font-size:23px;font-weight:800;line-height:1.2;letter-spacing:-.01em;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.fp-by{color:var(--mut);font-size:15px;margin-top:3px}
.fp-seek{margin-top:2px}
.fp-bar{height:7px;margin:10px 0 4px;touch-action:none}
.fp-bar::before{content:"";position:absolute;left:0;right:0;top:-16px;bottom:-16px}
.fp-bar b{opacity:1}
.fp-times{display:flex;justify-content:space-between;font-size:12px;color:var(--mut);font-variant-numeric:tabular-nums}
.fp-ctl{display:flex;align-items:center;justify-content:space-between;padding:0 2px}
.fp-b{width:50px;height:50px;border-radius:50%;display:grid;place-items:center;color:#fff;background:transparent;border:0;flex:none;transition:transform .15s,background .2s,color .2s}
.fp-b:active:not(:disabled){transform:scale(.92)}
.fp-b:disabled{opacity:.4}
.fp-b svg.i{width:24px;height:24px}
.fp-b.big{width:72px;height:72px;background:linear-gradient(135deg,var(--acc),var(--acc2));box-shadow:0 12px 30px color-mix(in srgb,var(--acc) 45%,transparent)}
.fp-b.big svg.i{width:30px;height:30px}
.fp-b.sm{width:42px;height:42px}.fp-b.sm svg.i{width:22px;height:22px}
.fp-b.on{color:var(--acc)}
.fp-b[data-r="1"]::after{content:"1";position:absolute;font-size:9px;font-weight:800;margin:-14px -22px 0 0}
.fp-ctl2{display:flex;align-items:center;gap:8px}
.fp-volw{flex:1;display:flex;align-items:center;gap:10px;min-width:0}
.fp-volw svg.i{width:18px;height:18px;color:var(--mut);flex:none}
.fp-vol{flex:1;min-width:0;height:5px;accent-color:var(--acc)}
.fp-note{display:flex;align-items:center;gap:8px;padding:9px 12px;border-radius:12px;font-size:12px;color:var(--mut);background:rgba(255,255,255,.06);border:1px solid var(--line)}
.fp-note svg.i{width:16px;height:16px;flex:none}
.fp-out .side-h{padding:2px 4px 6px}
.fp-queue{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.fp-queue.hide,.fp-now.hide{display:none}
.fp-ql{flex:1 1 auto;min-height:0;max-height:none!important;overflow-y:auto;margin:0 -6px;padding:0 6px}
.fp-ql .q-item.cur{background:color-mix(in srgb,var(--acc) 18%,transparent);border-radius:12px}
.fp-ql .q-item .n svg.i{width:14px;height:14px;color:var(--acc)}
.fp-ql .q-act{opacity:1}
@media(max-height:640px){.fp-cover{width:min(100%,150px)}.fp-b.big{width:62px;height:62px}}

/* ======================================================================
   Playlists: on a phone you see the list, tap one and it opens as its own screen (with a back button)
   ====================================================================== */
.pl-go{display:none}
.pl-back{display:none}
.pl-hero{display:flex;align-items:center;gap:14px}
.pl-cover{width:76px;height:76px;border-radius:16px;overflow:hidden;flex:none;display:grid;place-items:center;
  background:linear-gradient(135deg,color-mix(in srgb,var(--acc) 50%,#111),color-mix(in srgb,var(--acc2) 50%,#111));box-shadow:0 10px 26px rgba(0,0,0,.4)}
.pl-cover img{width:100%;height:100%;object-fit:cover}
.pl-cover svg.i{width:30px;height:30px;opacity:.85}
.pl-name{font-size:21px;font-weight:800;letter-spacing:-.01em}
.pl-acts{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.pl-skel{display:flex;flex-direction:column;gap:12px;padding:4px 0}
.pl-skel .sk{border-radius:12px;background-color:rgba(255,255,255,.06)}
.pl-skel .sk-h{height:76px;border-radius:16px}.pl-skel .sk-r{height:52px}
.pl-back svg{transform:rotate(90deg)}
.pl-go svg{transform:rotate(-90deg);width:18px;height:18px;opacity:.5}
@media(max-width:860px){
  .pl-go{display:grid;place-items:center}
  .pl-back{display:inline-flex;flex:none;width:42px;height:42px}
  .fit{height:auto;min-height:0}
  .fit .cols2{display:block;height:auto}
  .fit .cols2>*{min-height:0}
  .fit .pl-side{height:auto;gap:12px}
  .fit .pl-side .grow-card .pl-list{overflow:visible;max-height:none;margin:0;padding:0}
  .fit .pl-detail{height:auto;padding:14px}
  .fit .pl-detail .pl-tracks{overflow:visible;margin:0;padding:0}
  .cols2.pl-open .pl-side{display:none}
  .cols2:not(.pl-open) .pl-detail{display:none}
  .pl{padding:10px 8px;gap:12px}
  .pl .pic{width:56px;height:56px;border-radius:13px}
  .pl-hero{position:sticky;top:0;z-index:5;margin:-14px -14px 0;padding:calc(12px + var(--safe-t) * 0) 14px 12px;background:rgba(14,14,20,.92);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border-radius:var(--r) var(--r) 0 0}
  .pl-cover{width:58px;height:58px;border-radius:13px}.pl-name{font-size:18px}
  .pl-acts .btn{flex:1 1 0;min-height:44px}
  .pl-acts .btn.bad{flex:0 0 48px}
  .pl-tracks .q-item{padding:8px 4px}
  .pl-tracks .q-act{opacity:1;gap:0}
  .pl-tracks .q-act .btn{width:32px;height:32px;padding:0}
  .pl-tracks .q-item .n{display:none}
  .page-h h1{font-size:22px}
}

/* covers that are missing must not blow up (the fallback logo has a % padding) */
.q-item img.fb,.lp-cover img.fb,.np-cover img.fb{padding:6px!important}
/* the way into the full player from the server page (phones only) */
.fp-open-row{display:none}
@media(max-width:860px){
  .fp-open-row{display:block;margin-bottom:12px}
  .fp-open-btn{width:100%;min-height:46px;font-size:14px;border-radius:14px;background:color-mix(in srgb,var(--acc) 22%,rgba(255,255,255,.06));border:1px solid color-mix(in srgb,var(--acc) 55%,transparent)}
  .np .cover{cursor:pointer}
}
.fp-cover img.fb{padding:18%!important}
