:root {
  --hitam: #141414; --hitam-2: #181818; --abu: #2f2f2f; --abu-2: #9a9a9a; --putih: #fff; --merah: #e50914; --merah-teks: #ec474f;
  --gutter: clamp(16px, 4vw, 60px);
  color-scheme: dark;
}
* { box-sizing: border-box; }
/* --merah-teks (#ec474f) = merah merek dicerahkan 20% dengan putih, DIPAKAI KHUSUS UNTUK TULISAN
   di latar gelap: #e50914 cuma 3,84:1, sedangkan ini 4,87:1. Fill/cincin/aksen tetap --merah asli
   (tak ada syarat kontras teks di situ), jadi warna mereknya tidak berubah. jhony 22 Sep 2026:
   "diperjelas juga seaghost creative" — WCAG sebetulnya mengecualikan logotype, dan itu keputusan
   dia untuk tidak memakai pengecualian itu. LOGO dikembalikan ke --merah asli (#e50914) atas
   permintaan jhony 23 Sep 2026 ("dikembalikan ke warna awal"); nama merek di kaki tetap --merah-teks.
   --abu-2 dinaikkan #808080 → #9a9a9a (22 Sep 2026). #808080 gagal ambang WCAG AA di SEMUA latar
   yang dipakai app ini: 4,66:1 di hitam, 4,32 di panel, 3,91 di gradien Now Playing, 3,63 di baris
   lagu aktif — ambangnya 4,5. #9a9a9a: 6,55 / 6,06 / 5,48 / 5,10, dan masih jelas lebih redup
   daripada judul. Diketahui penyapu scripts/periksa-kontras.sh, bukan oleh mata. */
html, body { margin: 0; background: var(--hitam); color: var(--putih); font: 15px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; }
img { max-width: 100%; display: block; }
button { font: inherit; cursor: pointer; }
a { color: inherit; text-decoration: none; }
[hidden] { display: none !important; }

.logo { font-weight: 900; letter-spacing: -0.5px; color: var(--merah); font-size: 22px; white-space: nowrap; }
.logo span { color: var(--putih); font-weight: 300; }
.logo-besar { font-size: 36px; }

/* Pembuka (index.html #pembuka) 4,2 dtk — jhony 1 Okt 2026: "barang yang berhamburan itu menyatu jadi tulisan
   LAYAR RUMAH, sesuaikan musiknya". Kepingan bercahaya (.keping = salinan tulisan dipotong clip-path petak bergerigi,
   dibuat skrip inline index.html) melayang dari segala arah & makin cepat, lalu MENGUNCI jadi huruf tepat di bunyi:
     1,5 dtk "ta"  (35,71%) kepingan LAYAR mengunci  → LAYAR utuh menyala + percikan
     1,9 dtk "DUM" (45,24%) kepingan RUMAH mengunci  → RUMAH utuh menyala + percikan
     1,9→3,6 dtk (→85,71%)  logo berpendar & mendekat sampai SELEBAR LAYAR, lalu memudar 3,6→4,0 dtk
     4,0 dtk kredit "by Seaghost Creative" (jhony 23 Okt 2026) muncul di denting, tahan, layar memudar 5,1→5,6 dtk
   Persen keyframe lama tetap relatif 4,2 dtk; HANYA .pembuka (pudar) & .kredit memakai 5,6 dtk.
   Bunyi: public/pembuka.mp3 dari scripts/buat-suara-pembuka-rakit.mjs (waktu yang sama).
   TAJAM: tulisan digambar 160px lalu DIPERKECIL (skala ≤ 1). MUAT: --maks = skala saat selebar layar − 16px tiap
   sisi (skrip inline). Merakit di skala .6 × maks (±60% lebar layar; .35 = kepingan cuma titik di HP). Kepingan ikut transform logo; jarak lontarnya dihitung skrip dalam px LAYAR dibagi skala.
   Selektor lewat #pembuka: aturan HP `.logo { font-size: 18px }` & TV `html.tv .logo` lebih bawah. */
.pembuka { --maks: .28; position: fixed; inset: 0; z-index: 9999; background: #000; display: flex; align-items: center; justify-content: center; overflow: hidden; pointer-events: none; animation: pembuka-pudar 5.6s ease-in forwards; }
#pembuka .logo-pembuka { position: relative; font-size: 160px; letter-spacing: -0.01em; transform: scale(calc(var(--maks) * .6)); animation: pembuka-logo 4.2s forwards, pembuka-logo-hilang 4.2s forwards; }
/* kredit: dua baris kecil di tengah, HANYA opacity + transform. Ukuran dipatok vw supaya muat di HP & TV. */
#pembuka .kredit { position: absolute; left: 0; right: 0; top: 50%; text-align: center; color: #c9c9c9; opacity: 0; will-change: transform, opacity;
  transform: translateY(-50%); animation: pembuka-kredit 5.6s forwards; font-size: clamp(17px, 4.4vw, 36px); line-height: 1.25; }
#pembuka .kredit small { display: block; font-size: .78em; font-style: italic; font-weight: 300; letter-spacing: .08em; color: #9a9a9a; margin-bottom: .25em; }
#pembuka .kredit b { font-weight: 700; letter-spacing: .32em; margin-right: -.32em; text-transform: uppercase; }
/* kilatan cahaya menyapu kredit 4,35→4,95 dtk (jhony 23 Okt 2026 "kilatan cahaya di tulisannya"). Tanpa background-clip
   beranimasi (= Paint tiap bingkai): salinan tulisan berpendar TETAP (.teks) dilihat lewat jendela miring bertepi lembut
   (.jendela, mask statis). Jendela bergeser ke kanan, .teks digeser BALIK sejauh sama → tulisan diam, cahayanya yang lewat.
   Dua-duanya transform saja. .kilat melebar .5em/1em supaya pendar tak terpotong; .teks diberi padding yang sama. */
#pembuka .kilat { position: absolute; inset: -.5em -1em; overflow: hidden; pointer-events: none; }
#pembuka .jendela { position: absolute; inset: 0; transform: translateX(-62%); will-change: transform; animation: pembuka-jendela 5.6s linear forwards;
  -webkit-mask-image: linear-gradient(105deg, transparent 22%, #000 50%, transparent 78%); mask-image: linear-gradient(105deg, transparent 22%, #000 50%, transparent 78%); }
#pembuka .kilat .teks { position: absolute; inset: 0; padding: .5em 1em; transform: translateX(62%); will-change: transform; animation: pembuka-teks-kilat 5.6s linear forwards;
  color: #fff; text-shadow: 0 0 6px #fff, 0 0 14px #fff, 0 0 30px rgba(255,170,170,1), 0 0 60px rgba(229,9,20,.9); }
#pembuka .kilat .teks small { color: #fff; }
/* MULUS (jhony 1 Okt 2026 "animasinya agak tersendat"): yang dianimasikan HANYA transform & opacity (compositor/GPU).
   Dulu pendar = text-shadow/color beranimasi → Paint TIAP bingkai di utas utama yang sedang memuat app (diukur
   scripts/ukur-pembuka.mjs: ±270 Paint / 4,5 dtk). Kini pendar = lapisan .cahaya bertext-shadow TETAP (digambar
   sekali) yang cuma diubah opacity-nya; kepingan & percikan dipaksa ke lapisan sendiri (will-change). */
#pembuka .utuh { display: block; }
#pembuka .utuh b, #pembuka .cahaya b { font-weight: inherit; }
#pembuka .utuh b { opacity: 0; text-shadow: 0 0 6px rgba(255,80,80,.5), 0 0 30px rgba(229,9,20,.5), 0 0 80px rgba(229,9,20,.4); animation: pembuka-muncul-a 4.2s step-end forwards; }
#pembuka .utuh span { opacity: 0; text-shadow: 0 0 6px rgba(255,255,255,.45), 0 0 24px rgba(255,255,255,.25), 0 0 80px rgba(229,9,20,.35); animation: pembuka-muncul-b 4.2s step-end forwards; }
#pembuka .cahaya { position: absolute; left: 0; top: 0; white-space: nowrap; pointer-events: none; }
#pembuka .cahaya b { color: #ff5050; opacity: 0; will-change: opacity; text-shadow: 0 0 10px rgba(255,225,225,1), 0 0 36px rgba(255,50,50,1), 0 0 100px rgba(229,9,20,.9); animation: pembuka-cahaya-a 4.2s linear forwards; }
#pembuka .cahaya span { opacity: 0; will-change: opacity; text-shadow: 0 0 10px #fff, 0 0 38px rgba(255,255,255,.85), 0 0 100px rgba(255,140,140,.7); animation: pembuka-cahaya-b 4.2s linear forwards; }
#pembuka .keping { position: absolute; left: 0; top: 0; white-space: nowrap; opacity: 0; will-change: transform, opacity;
  } /* TANPA filter: drop-shadow di 16 kepingan bergerak = ±62% kerja GPU (ukur-pembuka.mjs) → tersendat di HP */
#pembuka .keping.a { animation: pembuka-rakit-a 4.2s forwards; }
#pembuka .keping.b { animation: pembuka-rakit-b 4.2s forwards; }
/* pendar kepingan dilukis SEKALI ke dalam lapisan (text-shadow statis, terpotong clip-path di tepi keping — tak apa) */
#pembuka .keping .isi { clip-path: var(--klip); color: #ff4a4a; text-shadow: 0 0 8px rgba(255,170,170,1), 0 0 22px rgba(255,40,40,.95), 0 0 50px rgba(229,9,20,.8); }
#pembuka .keping .isi span { color: #fff; text-shadow: 0 0 8px #fff, 0 0 22px rgba(255,200,200,.9), 0 0 50px rgba(255,90,90,.7); }
#pembuka .percik { position: absolute; left: 50%; top: 50%; width: var(--u); height: var(--u); margin: calc(var(--u) / -2);
  border-radius: 50%; background: #fff; box-shadow: 0 0 6px 2px var(--c), 0 0 16px 4px var(--c); opacity: 0; will-change: transform, opacity; }
#pembuka .percik.a { animation: pembuka-percik-a 4.2s forwards; }
#pembuka .percik.b { animation: pembuka-percik-b 4.2s forwards; }
@keyframes pembuka-pudar { 0%, 91.07% { opacity: 1; } 100% { opacity: 0; visibility: hidden; } }
/* logo (4,2 dtk): utuh sampai 3,6 dtk (85,71%) lalu hilang di 4,0 dtk (95,24%) memberi tempat kredit */
@keyframes pembuka-logo-hilang { 0%, 85.71% { opacity: 1; } 95.24%, 100% { opacity: 0; } }
/* kredit (5,6 dtk): naik pelan & muncul 3,95→4,35 dtk (70,54%→77,68%), tetap sampai layar memudar */
/* sapuan 4,35→4,95 dtk dari 5,6 dtk = 77,68%→88,39%, rata (linear); ±62% = pita masuk dari kiri sampai keluar di kanan */
@keyframes pembuka-jendela { 0%, 77.68% { transform: translateX(-62%); } 88.39%, 100% { transform: translateX(62%); } }
@keyframes pembuka-teks-kilat { 0%, 77.68% { transform: translateX(62%); } 88.39%, 100% { transform: translateX(-62%); } }
@keyframes pembuka-kredit {
  0%, 70.54% { opacity: 0; transform: translateY(-50%) translateY(14px) scale(.96); animation-timing-function: cubic-bezier(.2,.7,.3,1); }
  77.68%, 100% { opacity: 1; transform: translateY(-50%); }
}
@keyframes pembuka-logo {
  0%, 45.24% { transform: scale(calc(var(--maks) * .6)); }
  47.5% { transform: scale(calc(var(--maks) * .65)); animation-timing-function: cubic-bezier(.45,0,.3,1); } /* hentak kecil di DUM */
  85.71%, 100% { transform: scale(var(--maks)); }
}
/* kepingan: muncul redup, melayang makin cepat (ease-in), MENGUNCI di bunyinya lalu digantikan tulisan utuh */
@keyframes pembuka-rakit-a {
  0% { opacity: 0; transform: translate(var(--tx), var(--ty)) rotate(var(--r)) scale(var(--s)); animation-timing-function: cubic-bezier(.5,0,.9,.6); }
  10% { opacity: .85; }
  35.70% { opacity: 1; transform: none; }
  35.71%, 100% { opacity: 0; transform: none; }
}
@keyframes pembuka-rakit-b {
  0%, 8% { opacity: 0; transform: translate(var(--tx), var(--ty)) rotate(var(--r)) scale(var(--s)); animation-timing-function: cubic-bezier(.5,0,.9,.6); }
  18% { opacity: .85; }
  45.23% { opacity: 1; transform: none; }
  45.24%, 100% { opacity: 0; transform: none; }
}
/* huruf utuh muncul tepat saat kepingannya mengunci; .cahaya (pendar kuat, putih-panas) berkilat di kunci, mereda,
   lalu menyala lagi selama logo mendekat — HANYA opacity */
@keyframes pembuka-muncul-a { 0% { opacity: 0; } 35.71%, 100% { opacity: 1; } }
@keyframes pembuka-muncul-b { 0% { opacity: 0; } 45.24%, 100% { opacity: 1; } }
@keyframes pembuka-cahaya-a {
  0%, 35.70% { opacity: 0; } 35.71% { opacity: 1; } 44% { opacity: .15; } 45.24% { opacity: .75; }
  60% { opacity: .1; } 85.71%, 100% { opacity: .9; }
}
@keyframes pembuka-cahaya-b {
  0%, 45.23% { opacity: 0; } 45.24% { opacity: 1; } 60% { opacity: .1; } 85.71%, 100% { opacity: .9; }
}
@keyframes pembuka-percik-a {
  0%, 35.70% { opacity: 0; transform: translate(var(--x0), var(--y0)); }
  35.71% { opacity: 1; transform: translate(var(--x0), var(--y0)); animation-timing-function: cubic-bezier(.1,.8,.3,1); }
  52%, 100% { opacity: 0; transform: translate(var(--x1), var(--y1)); }
}
@keyframes pembuka-percik-b {
  0%, 45.23% { opacity: 0; transform: translate(var(--x0), var(--y0)); }
  45.24% { opacity: 1; transform: translate(var(--x0), var(--y0)); animation-timing-function: cubic-bezier(.1,.8,.3,1); }
  64%, 100% { opacity: 0; transform: translate(var(--x1), var(--y1)); }
}
@media (prefers-reduced-motion: reduce) {
  .pembuka { animation-duration: .6s; }
  #pembuka .logo-pembuka, #pembuka .utuh b, #pembuka .utuh span { animation: none; opacity: 1; }
  #pembuka .keping, #pembuka .percik, #pembuka .cahaya, #pembuka .kredit { display: none; }
}

.tombol { border: 0; border-radius: 999px; padding: 10px 24px; font-weight: 700; font-size: 16px; display: inline-flex; align-items: center; gap: 6px; }
.tombol-putih { background: var(--putih); color: #000; }
.tombol-putih:hover { background: #e6e6e6; }
.tombol-abu { background: rgba(109,109,110,.7); color: var(--putih); }
.tombol-abu:hover { background: rgba(109,109,110,.5); }
/* Semua tombol LONJONG, bukan kotak (jhony 23 Sep 2026: "jangan kotak ... cek semua bentuk kotak").
   .tombol-teks dulu kotak bergaris + HURUF KAPITAL; kini pil berlatar lembut tanpa garis, senada
   dengan .mutu / .musik-unduh yang memang sudah bulat. Border 1px TRANSPARAN tetap dipasang supaya
   varian yang mewarnai garisnya (.terunduh hijau) tak menggeser ukuran. */
.tombol-teks { background: rgba(255,255,255,.09); border: 1px solid transparent; color: #d6d6d6; padding: 6px 16px; border-radius: 999px; font-size: 13px; font-weight: 600; }
.tombol-teks:hover { color: var(--putih); background: rgba(255,255,255,.16); }
/* Dua tingkat tindakan merusak, sengaja berbeda berat: yang BERGARIS untuk pilihan yang masih
   bisa dibatalkan (menu Kelola), yang PEKAT untuk pemastian terakhir. Kalau keduanya sama
   pekat, tombol merah jadi biasa dan berhenti memperingatkan apa pun. */
.tombol-bahaya { background: var(--merah); color: #fff; border: 0; }
.tombol-bahaya:hover { filter: brightness(1.1); }
.tombol-bahaya-garis { background: rgba(229,9,20,.1); color: #ff6b6b; border: 1px solid #a3181f; border-radius: 999px; }
.tombol-bahaya-garis:hover { background: rgba(229,9,20,.12); color: #fff; }
/* Sudah terunduh = HIJAU, dan tekan lagi berarti HAPUS unduhan. Satu tanda untuk
   semua tombol unduh: playlist (.terunduh-pl), episode (.tombol-teks.kecil), dan
   film di halaman detail (.tombol.tombol-abu). */
.tombol-teks.terunduh-pl, .tombol-teks.terunduh { color: #46d369; border-color: #46d369; background: rgba(70,211,105,.08); }
.tombol-teks.terunduh-pl:hover, .tombol-teks.terunduh:hover { color: #fff; border-color: #46d369; background: rgba(70,211,105,.15); }
.tombol.terunduh { background: rgba(70,211,105,.18); color: #46d369; box-shadow: inset 0 0 0 1px #46d369; }
.tombol.terunduh:hover { background: rgba(70,211,105,.3); color: #fff; }
.tombol-ikon { background: none; border: 0; color: var(--putih); font-size: 28px; line-height: 1; padding: 8px 12px; }

/* ---------- Profil ---------- */
/* penanda ujung baris geser yang diisi bertahap (musik.js isiBertahap): tak terlihat, cukup lebar untuk diamati */
.muat-lagi { flex: 0 0 24px; min-width: 24px; }
/* Ruang atas dipesan untuk tombol Kembali/Keluar (absolut di pojok): kalau daftar profil lebih
   tinggi dari layar (5 profil di HP), isi yang "ditengahkan" mulai dari padding atas — tanpa ruang
   ini judul "Siapa yang menonton?" tertimpa tombol (jhony, 21 Sep 2026, tangkapan layar). */
.layar-profil { height: 100dvh; box-sizing: border-box; overflow: hidden; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 28px; padding: calc(env(safe-area-inset-top,0px) + 64px) var(--gutter) 24px; text-align: center; }
.layar-profil h1 { font-weight: 400; font-size: clamp(24px, 4vw, 44px); margin: 0; }
/* Daftar profil = KOTAK yang digulir VERTIKAL (jhony 21 Sep 2026: "gesernya vertikal"): berapa pun
   profilnya, logo, judul, Kelola Profil/Undang, dan Keluar tetap di layar; yang bergulir cuma kisi
   profil di dalam kotaknya. Layar profil dipatok setinggi layar (bukan min-height) supaya kotak
   ini boleh menyusut (min-height: 0) dan mengambil sisa ruangnya. */
.daftar-profil { display: flex; flex-wrap: wrap; justify-content: center; align-content: flex-start; gap: 24px; width: 100%; flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 8px 4px; scrollbar-width: thin; -webkit-overflow-scrolling: touch; }
.profil { background: none; border: 0; color: var(--abu-2); display: flex; flex-direction: column; align-items: center; gap: 10px; width: 120px; flex: 0 0 auto; }
.profil .avatar { width: 100px; height: 100px; border-radius: 6px; display: grid; place-items: center; font-size: 44px; font-weight: 700; color: #fff; border: 3px solid transparent; position: relative; }
.profil:hover .avatar, .profil:focus-visible .avatar { border-color: var(--putih); }
.profil:hover { color: var(--putih); }
.profil.tambah .avatar { background: none; border: 2px dashed var(--abu-2); color: var(--abu-2); font-size: 56px; font-weight: 300; }
.profil.hapus .avatar::after { content: "✕"; position: absolute; inset: 0; display: grid; place-items: center; background: rgba(0,0,0,.65); color: var(--merah); font-size: 40px; border-radius: 4px; }
.form-profil { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.form-profil input { background: #333; border: 0; border-radius: 4px; color: var(--putih); padding: 10px 14px; font-size: 16px; width: 220px; }

/* ---------- Nav ---------- */
.nav { position: fixed; top: 0; left: 0; right: 0; z-index: 20; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 12px var(--gutter); padding-top: calc(12px + env(safe-area-inset-top, 0px)); background: var(--hitam); transition: background .3s; }
.nav.padat { background: var(--hitam); }
.nav-kiri { order: 1; display: flex; align-items: center; gap: 24px; min-width: 0; flex: 1 1 auto; }
.nav-menu { display: flex; gap: 18px; font-size: 14px; }
.nav-menu a { color: #e5e5e5; opacity: .8; white-space: nowrap; }
.nav-menu a.aktif { font-weight: 700; opacity: 1; }
.cari { order: 2; display: flex; align-items: center; gap: 8px; background: rgba(0,0,0,.5); border: 1px solid #555; border-radius: 6px; padding: 0 10px; }
.cari svg { flex: 0 0 auto; color: #bbb; }
.cari input { background: none; border: 0; color: var(--putih); padding: 8px 0; width: 210px; font-size: 14px; outline: none; }
.cari input::placeholder { color: #9a9a9a; }
#tombolProfil { order: 3; }
#unggahHp { display: none; }  /* Unggah baris-2 khusus HP */
.avatar-kecil { width: 32px; height: 32px; border-radius: 4px; border: 0; color: #fff; font-weight: 700; font-size: 16px; flex: 0 0 auto; }
.nav-kanan { order: 4; display: flex; align-items: center; gap: 12px; }
@media (max-width: 700px) {
  .nav { padding-left: 16px; padding-right: 16px; gap: 8px; }
  /* nav-kiri "lenyap" (display:contents) → logo & menu jadi anak langsung .nav,
     jadi menu bisa turun ke barisnya sendiri sementara logo tetap tampak. */
  .nav-kiri { display: contents; }
  .logo { order: 1; display: inline; font-size: 18px; flex: 0 0 auto; }
  .cari { order: 2; flex: 1 1 0; min-width: 0; }           /* baris-1: logo · cari · avatar */
  .cari input { width: 100%; flex: 1; min-width: 0; }
  #tombolProfil { order: 3; flex: 0 0 auto; }
  /* baris-2: menu sepenuh lebar, semua item muat; geser mendatar hanya jika perlu */
  .nav-menu { order: 4; flex: 1 1 100%; width: 100%; gap: 17px; font-size: 14px; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .nav-menu::-webkit-scrollbar { display: none; }
  #unggahHp { display: none; }                             /* "Unggah" cukup di dalam menu */
  .grid { padding-top: calc(var(--nav-h, 86px) + 44px); }  /* nav 2 baris di HP: 86+44 = 130px seperti sebelumnya */
}

/* ---------- Hero ---------- */
.hero { position: relative; isolation: isolate; margin-top: var(--nav-h, 60px); min-height: 62vw; max-height: 85dvh; display: flex; align-items: flex-end; padding: 0 var(--gutter) clamp(24px, 6vw, 72px); overflow: hidden; }
.hero-gambar { position: absolute; inset: 0; z-index: -1; }
.hero-gambar img { width: 100%; height: 100%; object-fit: cover; }
.hero-gambar::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, var(--hitam) 0%, rgba(20,20,20,.4) 45%, rgba(20,20,20,.1) 100%), linear-gradient(to right, rgba(20,20,20,.7), transparent 60%); }
.hero-isi { max-width: 620px; padding-top: 28vw; }
.hero-isi h2 { font-size: clamp(28px, 5vw, 60px); margin: 0 0 10px; line-height: 1.05; text-shadow: 0 2px 12px rgba(0,0,0,.6); }
.hero-ket { color: #ddd; margin: 0 0 18px; font-size: clamp(13px, 1.4vw, 17px); text-shadow: 0 1px 6px rgba(0,0,0,.8); }
.hero-tombol { display: flex; gap: 10px; }
@media (min-width: 900px) { .hero { min-height: 56.25vw; } .hero-isi { padding-top: 0; } }
/* HP: hero lebih tinggi & judul di bawah supaya backdrop tampil lebih utuh (tak tertutup nav) */
@media (max-width: 700px) {
  .hero { min-height: 78vw; align-items: flex-end; padding-bottom: 22px; }
  .hero-isi { padding-top: 0; }
}

/* ---------- Baris kartu ---------- */
.baris-semua { display: flex; flex-direction: column; gap: 28px; padding: 16px 0 40px; margin-top: -4vw; position: relative; z-index: 1; }
/* Ruang untuk .nav (position:fixed) datang dari .hero{margin-top:var(--nav-h)}. Kalau hero
   DISEMBUNYIKAN (tab Musik), tak ada lagi yang menyediakannya, sementara .baris-semua masih
   menarik dirinya -4vw ke atas → judul baris PERTAMA tertelan nav (label "Playlist" hilang,
   kartunya tetap tampak). Kembalikan ruangnya. */
#hero[hidden] + .baris-semua { margin-top: calc(var(--nav-h, 60px) + 8px); }
/* Halaman DETAIL (album/artis/playlist) memakai wadah .grid-detail, bukan .baris-semua — dan
   ruang untuk nav tetap itu tadinya cuma disediakan aturan di atas. Akibatnya kepala halaman
   playlist mulai di y=56 sementara nav berakhir di y=86: lambang di pojok kiri-atas sampul
   tertutup nav. Persis kelas cacat yang sama seperti label "Playlist" dulu. */
#hero[hidden] + .grid-detail,
#hero[hidden] + .aktivitas { margin-top: calc(var(--nav-h, 60px) + 8px); } /* wadah ketiga (19 Sep): kelas cacat yang sama, aturan yang sama */
.baris h3 { margin: 0 0 8px var(--gutter); font-size: clamp(16px, 1.6vw, 22px); font-weight: 600; }
.geser { display: flex; gap: 8px; overflow-x: auto; padding: 6px var(--gutter) 10px; scroll-snap-type: x proximity; scroll-padding-inline: var(--gutter); scrollbar-width: none; }
.geser::-webkit-scrollbar { display: none; }
/* Tombol geser ‹ › (hanya laptop/pointer; muncul saat hover) — HP tetap pakai sentuh */
.geser-wrap { position: relative; }
.geser-panah { position: absolute; top: 0; bottom: 12px; width: 52px; z-index: 4; border: 0; cursor: pointer; color: #fff; font-size: 32px; line-height: 1; display: grid; place-items: center; opacity: 0; transition: opacity .2s; }
.geser-panah.kiri { left: 0; background: linear-gradient(90deg, rgba(0,0,0,.72), transparent); border-radius: 0 6px 6px 0; }
.geser-panah.kanan { right: 0; background: linear-gradient(270deg, rgba(0,0,0,.72), transparent); border-radius: 6px 0 0 6px; }
.geser-wrap:hover .geser-panah { opacity: .92; }
.geser-panah:hover { opacity: 1 !important; }
.geser-panah.sembunyi { opacity: 0 !important; pointer-events: none; }
.kartu { flex: 0 0 auto; width: clamp(110px, 15vw, 200px); background: none; border: 0; padding: 0; color: var(--putih); text-align: left; scroll-snap-align: start; transition: transform .2s; border-radius: 4px; position: relative; }
.kartu.lebar { width: clamp(200px, 26vw, 340px); }
.kartu:hover, .kartu:focus-visible { transform: scale(1.06); z-index: 2; }
.kartu img, .kartu .tanpa-gambar { width: 100%; aspect-ratio: 2/3; object-fit: cover; border-radius: 4px; background: var(--abu); }
.kartu.lebar img, .kartu.lebar .tanpa-gambar { aspect-ratio: 16/9; }
.kartu .tanpa-gambar { display: grid; place-items: center; text-align: center; padding: 8px; color: #bbb; font-size: 13px; }
.kartu .kartu-judul { font-size: 13px; margin-top: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: #ddd; }
.kartu .kartu-sub { font-size: 12px; color: var(--abu-2); }
.kartu .lencana { position: absolute; top: 6px; left: 6px; background: var(--merah); color: #fff; font-size: 10px; font-weight: 700; padding: 2px 6px; border-radius: 2px; }
.kartu .lencana-hapus { background: #f5c518; color: #141414; }
/* 4K / HDR (1 Okt 2026): pojok kanan atas, tak bertabrakan dengan lencana BARU di kiri */
.kartu .lencana-mutu { position: absolute; top: 6px; right: 6px; background: rgba(0,0,0,.72); color: #fff; font-size: 10px; font-weight: 700; padding: 2px 6px; border-radius: 2px; border: 1px solid rgba(255,255,255,.55); letter-spacing: .3px; }
.kotak-hdr { border-color: #f5c518 !important; color: #f5c518 !important; }
.detail-meta .kotak-hapus { background: #f5c518; color: #141414; font-weight: 700; font-size: 13px; padding: 1px 8px; border-radius: 3px; }
.progres { height: 3px; background: rgba(255,255,255,.3); border-radius: 2px; overflow: hidden; margin-top: 4px; }
.progres > div { height: 100%; background: var(--merah); width: 0; }
/* Ruang untuk .nav (position:fixed) HARUS ikut tinggi navnya, bukan angka tetap: navnya
   flex-wrap, jadi tingginya 58px (satu baris), 97px (dua baris, 701–1023px), atau 132px (mode TV).
   Dengan 90px tetap, pucuk kartu baris pertama masuk ke balik bar di seluruh pita 701–1023px —
   wadah keempat dengan cacat yang sama setelah .hero, .baris-semua, dan .aktivitas.
   Angka +32 dipilih supaya jaraknya di lebar yang selama ini diuji TIDAK berubah (58+32 = 90). */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(clamp(110px, 15vw, 200px), 1fr)); gap: 16px 10px; padding: calc(var(--nav-h, 60px) + 32px) var(--gutter) 40px; }
.grid .kartu { width: auto; }
.kosong { padding: 120px var(--gutter); text-align: center; color: var(--abu-2); font-size: 18px; }
.kosong code { color: #ddd; background: var(--abu); padding: 2px 6px; border-radius: 3px; }
.kaki { padding: 24px var(--gutter) 48px; color: var(--abu-2); font-size: 12px; display: flex; flex-direction: column; gap: 10px; }
.kaki-aksi { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.kaki-kredit { color: var(--abu-2); letter-spacing: .3px; }
.kaki-kredit strong { color: var(--merah-teks); font-weight: 700; letter-spacing: 0; }
.kaki-kredit a { color: inherit; text-decoration: none; }
.kaki-kredit a:hover strong, .kaki-kredit a:focus-visible strong { text-decoration: underline; }

/* ---------- Detail ---------- */
.detail { position: fixed; inset: 0; z-index: 30; background: rgba(0,0,0,.7); overflow-y: auto; padding: 0; }
.detail-kotak { background: var(--hitam-2); max-width: 860px; margin: 0 auto; min-height: 100dvh; position: relative; border-radius: 0; }
@media (min-width: 900px) { .detail { padding: 32px 16px; } .detail-kotak { min-height: 0; border-radius: 8px; overflow: hidden; } }
.tutup { position: absolute; top: 12px; right: 12px; z-index: 2; width: 36px; height: 36px; border-radius: 50%; border: 0; background: var(--hitam-2); color: var(--putih); font-size: 24px; line-height: 1; }
.detail-gambar { position: relative; aspect-ratio: 16/9; background: var(--abu); }
.detail-gambar img { width: 100%; height: 100%; object-fit: cover; }
.detail-gambar::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, var(--hitam-2), transparent 50%); }
.detail-isi { padding: 0 clamp(16px, 4vw, 48px) 32px; margin-top: -48px; position: relative; }
.detail-isi h2 { font-size: clamp(24px, 4vw, 40px); margin: 0 0 8px; line-height: 1.1; }
.detail-meta { display: flex; flex-wrap: wrap; gap: 8px 14px; color: #ccc; font-size: 14px; align-items: center; margin-bottom: 16px; }
.detail-meta .kotak { border: 1px solid var(--abu-2); border-radius: 3px; padding: 0 5px; font-size: 11px; color: #ddd; }
.detail-meta .hijau { color: #46d369; font-weight: 700; }
.detail-tombol { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.detail-berkas { color: var(--abu-2); font-size: 12px; word-break: break-all; margin: 12px 0 0; }
.pilih-season { margin: 24px 0 10px; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.unduh-season { font-size: 15px; }
.pilih-season select, .pilih-subtitle { background: #242424; color: var(--putih); border: 1px solid #555; border-radius: 4px; padding: 6px 10px; font-size: 15px; }
.daftar-episode { list-style: none; margin: 0; padding: 0; }
.episode { display: grid; grid-template-columns: 28px 140px 1fr; gap: 14px; align-items: center; padding: 12px 8px; border-bottom: 1px solid #333; border-radius: 6px; cursor: pointer; }
.episode:hover, .episode.aktif { background: #333; }
.episode .nomor { color: #bbb; font-size: 20px; text-align: center; }
.episode img, .episode .tanpa-gambar { aspect-ratio: 16/9; object-fit: cover; border-radius: 4px; background: var(--abu); width: 100%; }
.episode .judul { font-weight: 600; }
.episode .durasi { color: var(--abu-2); font-size: 13px; }
@media (max-width: 520px) { .episode { grid-template-columns: 22px 100px 1fr; gap: 10px; } }
/* Baris episode di daftar UNDUHAN punya tombol Hapus di ujung → butuh satu kolom tambahan.
   WAJIB berada SESUDAH aturan .episode di atas (termasuk media query-nya): kespesifikan sama,
   jadi yang belakangan menang. Pernah ditaruh sebelum media query 520px dan akibatnya di HP
   tombolnya terlempar ke baris di bawah gambar. */
.episode-unduhan { grid-template-columns: 28px 140px 1fr auto; }
@media (max-width: 520px) { .episode-unduhan { grid-template-columns: 22px 100px 1fr auto; } }

/* ---------- Pemutar ---------- */
.pemutar { position: fixed; inset: 0; z-index: 40; background: #000; }
.pemutar video { width: 100%; height: 100%; object-fit: contain; background: #000; }
/* POTRET (HP tegak): kotak <video> setinggi layar membuat subtitle (::cue, selalu di dasar KOTAK elemen) jatuh
   ke dasar layar, jauh di bawah pita gambar di tengah (jhony 28 Sep). Tinggi kotak ikut proporsi gambar &
   diletakkan di tengah → subtitle tepat di bawah gambar, seperti YouTube tegak. Lanskap/TV tak berubah. */
@media (orientation: portrait) {
  .pemutar { display: flex; align-items: center; justify-content: center; }
  .pemutar video { height: auto; max-height: 100%; }
}
.pemutar-atas { position: absolute; top: 0; left: 0; right: 0; display: flex; align-items: center; gap: 8px; padding: 8px 12px; padding-top: calc(8px + env(safe-area-inset-top, 0px)); background: linear-gradient(to bottom, rgba(0,0,0,.8), transparent); transition: opacity .3s; }
.pemutar.sembunyi .pemutar-atas { opacity: 0; pointer-events: none; }
.pemutar-judul { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.pemutar-judul strong { font-size: 17px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pemutar-judul span { color: #bbb; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pemutar-muat { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; color: #ddd; pointer-events: none; background: rgba(0,0,0,.35); }
.putaran { width: 48px; height: 48px; border: 4px solid rgba(255,255,255,.25); border-top-color: var(--merah); border-radius: 50%; animation: putar 0.9s linear infinite; }
@keyframes putar { to { transform: rotate(360deg); } }
.episode-berikut { position: absolute; right: 24px; bottom: 90px; box-shadow: 0 4px 20px rgba(0,0,0,.6); }
/* Lewati Intro (25 Sep 2026): tetap tampil walau kontrol pemutar menyembunyikan diri (seperti Netflix) */
.lewati-intro { position: absolute; right: 24px; bottom: 90px; z-index: 5; background: rgba(20,20,20,.7); color: var(--putih); border: 2px solid rgba(255,255,255,.85); box-shadow: 0 4px 20px rgba(0,0,0,.6); }
@media (hover: hover) { .lewati-intro:hover { background: rgba(60,60,60,.85); } }
html.tv .lewati-intro { font-size: 24px; padding: 14px 32px; right: 48px; bottom: 120px; }
video::cue { background: rgba(0,0,0,.6); font-size: clamp(16px, 2.6vw, 30px); }

.profil .avatar .gembok { position: absolute; bottom: 4px; right: 4px; font-size: 16px; }

.detail-sinopsis { color: #ddd; font-size: 15px; line-height: 1.5; margin: 0 0 16px; max-width: 640px; }
/* Admin: terjemahkan sinopsis Inggris (12 Okt 2026). Kotak suntingnya selebar sinopsis supaya yang diketik = yang tampil.
   Huruf 16px: di bawah itu Safari/Chrome HP memperbesar halaman saat kotaknya disentuh. */
.detail-terjemah { margin: -6px 0 16px; max-width: 640px; }
.detail-terjemah-teks { display: block; width: 100%; box-sizing: border-box; background: #000; color: var(--putih); border: 1px solid #555;
  border-radius: 6px; padding: 10px 12px; font: inherit; font-size: 16px; line-height: 1.5; resize: vertical; min-height: 150px; }
.detail-terjemah-teks:focus { outline: none; border-color: var(--warna-profil, var(--merah)); }
.detail-terjemah-pesan { color: #bdbdbd; font-size: 13px; line-height: 1.4; margin: 8px 0 10px; }
.detail-terjemah-aksi { display: flex; gap: 10px; flex-wrap: wrap; }
/* TV: mengetik sinopsis dengan remote tak masuk akal, dan tombol tambahan di sini menggeser jalur panah remote. */
html.tv .detail-terjemah { display: none !important; }
.detail-meta .bintang { color: #f5c518; font-weight: 700; }
.detail-meta .bintang-sumber { margin-left: .3em; font-size: .72em; font-weight: 600; color: var(--abu-2); letter-spacing: .02em; }

.berkas .persen { grid-column: 1 / -1; font-weight: 800; font-size: 22px; letter-spacing: -0.5px; margin-top: 2px; }
.berkas .status.selesai ~ .persen, .berkas.selesai .persen { color: #46d369; }
/* baris unggah musik: nama kiri, status + tombol Ulangi kanan */
.berkas-musik { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid #222; }
.berkas-musik .nama { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.berkas-musik .status { color: #bbb; font-size: 13px; white-space: nowrap; }
.berkas-musik .status.selesai { color: #46d369; }
.berkas-musik .status.galat { color: #ff6b6b; }
.berkas-musik .ulang { background: var(--merah); color: #fff; border: none; border-radius: 6px; padding: 5px 11px; font-weight: 700; cursor: pointer; white-space: nowrap; }
.berkas-musik .ulang[hidden] { display: none; }

.form-profil #pinProfil, .form-profil #pinProfil2 { width: 150px; }

body:not(.admin) .admin-only { display: none !important; }
body.admin .bukan-admin { display: none !important; } /* menu Request: penonton saja (jhony 28 Sep) */
.request-form { max-width: 520px; box-sizing: border-box; display: flex; flex-direction: column; gap: 14px; padding: 8px var(--gutter) 40px; }
.request-form button[type=submit] { justify-content: center; padding: 13px 24px; }
.request-form h2 { margin: 0; font-size: 24px; }
.request-form .ket { color: var(--abu-2); margin: -6px 0 0; font-size: 14px; }
.request-form label.isian { display: flex; flex-direction: column; gap: 6px; font-size: 14px; color: #ccc; }
.request-form input[type=text], .request-form input[type=number] { background: #242424; color: var(--putih); border: 1px solid #555; border-radius: 6px; padding: 11px 12px; font-size: 16px; font-family: inherit; }
.request-form .jenis { display: flex; gap: 8px; }
.request-form .isian[hidden] { display: none; }
.request-form .jenis label { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 6px; padding: 11px 6px; border: 1px solid #555; border-radius: 6px; cursor: pointer; }
.request-form .jenis label:has(input:checked) { border-color: var(--putih); background: #2a2a2a; }
.request-form .pesan { min-height: 20px; font-size: 14px; }
.request-form .pesan.ok { color: #46d369; }
.request-form .pesan.salah { color: #ff6b6b; }

.pemutar-toast { position: absolute; top: calc(16px + env(safe-area-inset-top, 0px)); left: 50%; transform: translateX(-50%); max-width: min(92%, 540px); background: rgba(20,20,20,.94); border: 1px solid #4a4a4a; color: #fff; padding: 10px 16px; border-radius: 8px; font-size: 14px; line-height: 1.35; text-align: center; z-index: 6; box-shadow: 0 6px 24px rgba(0,0,0,.6); }

/* pemutar: kolom kualitas & subtitle jangan melebar di HP */
.pemutar-atas .pilih-subtitle { flex: 0 1 auto; min-width: 0; max-width: 40vw; text-overflow: ellipsis; }
@media (max-width: 600px) {
  .pemutar-atas { gap: 6px; padding: 8px 10px; }
  .pemutar-atas .pilih-subtitle { font-size: 12px; padding: 5px 6px; max-width: 34vw; }
  .pemutar-judul strong { font-size: 15px; }
  .pemutar-judul span { font-size: 12px; }
}

/* ---------- Unduhan offline ---------- */
.unduh-status { margin-top: 10px; font-size: 13px; color: #ccc; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.unduh-status .progres { flex: 1; min-width: 120px; height: 6px; }
.unduh-status .galat { color: #ff6b6b; }
.unduh-status .tombol-teks { padding: 5px 12px; }
#detailUnduh { border: 1px solid #666; }
.ep-unduh { margin-top: 6px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ep-unduh .tombol-teks.kecil { padding: 3px 10px; font-size: 11px; }
.ep-unduh-status { font-size: 12px; color: #bbb; display: flex; align-items: center; gap: 8px; flex: 1 1 100%; min-width: 0; flex-wrap: wrap; }
/* Pemilih kualitas unduhan (Penuh / Hemat) — pil ringkas yang membungkus rapi di HP */
.mutu { background: rgba(255,255,255,.08); border: 1px solid #6a6a6a; color: #eee; padding: 7px 16px; border-radius: 18px; font-size: 13px; white-space: nowrap; cursor: pointer; }
.mutu:hover, .mutu:focus-visible { border-color: var(--putih); color: var(--putih); background: rgba(255,255,255,.14); }
.ep-unduh-status .progres { flex: 1; min-width: 80px; height: 5px; }
.kartu { position: relative; }
.kartu-hapus { position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; border-radius: 50%; border: 0; background: rgba(0,0,0,.7); color: #fff; font-size: 13px; line-height: 1; display: none; }
.kartu:hover .kartu-hapus, .kartu:focus-within .kartu-hapus { display: block; }
@media (hover: none) { .kartu-hapus { display: block; } }
.unduhan-pakai { grid-column: 1 / -1; color: var(--abu-2); font-size: 12px; padding: 12px var(--gutter) 0; }

/* ---------- Ajakan pasang PWA & pita "Versi baru siap" ---------- */
.ajak-pasang, .pita-versi {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(16px + env(safe-area-inset-bottom, 0px)); z-index: 90;
  width: min(440px, calc(100vw - 24px));
  display: flex; align-items: center; gap: 12px;
  background: var(--hitam-2); border: 1px solid var(--abu); border-radius: 12px;
  padding: 12px 14px; box-shadow: 0 12px 40px rgba(0,0,0,.55);
  animation: ajakNaik .28s ease;
}
@keyframes ajakNaik { from { opacity: 0; transform: translate(-50%, 16px); } to { opacity: 1; transform: translate(-50%, 0); } }
.ajak-ikon { width: 44px; height: 44px; border-radius: 10px; flex: 0 0 auto; }
.ajak-teks { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.ajak-teks strong { font-size: 14px; }
.ajak-teks span { font-size: 12px; color: var(--abu-2); line-height: 1.35; }
.ajak-aksi { display: flex; flex-direction: column; gap: 6px; flex: 0 0 auto; }
.ajak-aksi .tombol { padding: 7px 16px; font-size: 13px; }
.ajak-aksi .tombol-teks { padding: 4px 8px; border: 0; background: none; letter-spacing: .5px; }
@media (max-width: 460px) {
  .ajak-pasang, .pita-versi { flex-wrap: wrap; }
  .ajak-aksi { flex-direction: row; width: 100%; justify-content: flex-end; }
}
/* Mini-player duduk di dasar layar (tinggi ~61px) — pita harus DI ATASNYA, bukan menutupi
   tombol putar orang yang sedang mendengarkan musik. */
body.ada-musik .ajak-pasang, body.ada-musik .pita-versi { bottom: calc(76px + env(safe-area-inset-bottom, 0px)); }

/* ---------- Musik ---------- */
.musik-baris-judul { display: flex; align-items: baseline; gap: 12px; }
/* "Lihat semua" = tautan teks + panah, BUKAN kotak bergaris (jhony 23 Sep 2026: "lebih estetik
   jangan kotak"). Padding memberi sasaran ketuk tanpa tampak sebagai kotak; margin negatif
   mengembalikan letak teksnya sejajar judul. Panahnya bergeser saat disorot. */
.lihat-semua { background: none; border: 0; color: var(--abu-2); font-size: 13px; font-weight: 600; letter-spacing: .2px;
  padding: 8px 6px; margin: -8px 0; display: inline-flex; align-items: center; gap: 2px; border-radius: 6px; white-space: nowrap; }
.lihat-semua::after { content: '›'; font-size: 19px; line-height: 0; font-weight: 400; transition: transform .15s ease; }
@media (hover: hover) {
  .lihat-semua:hover { color: var(--putih); }
  .lihat-semua:hover::after { transform: translateX(3px); }
}
.lihat-semua:focus-visible { color: var(--putih); outline: 2px solid var(--putih); outline-offset: 0; }
.lihat-semua:focus-visible::after { transform: translateX(3px); }
.kartu-artis img.bulat, .kartu-artis .tanpa-gambar.bulat { border-radius: 50%; aspect-ratio: 1; object-fit: cover; }
.playlist-cover { display: grid; place-items: center; font-size: 40px; background: linear-gradient(135deg, #333, #555); color: #fff; aspect-ratio: 1; }
/* Mozaik 2×2 sampul album untuk cover playlist */
.playlist-mozaik { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 0; width: 100%; aspect-ratio: 2/3; border-radius: 4px; overflow: hidden; background: var(--abu); }
.playlist-mozaik img, .playlist-mozaik .tanpa-gambar { width: 100%; height: 100%; object-fit: cover; }
.playlist-mozaik.kepala-cover { width: 160px; height: 160px; aspect-ratio: 1; border-radius: 8px; box-shadow: 0 8px 30px rgba(0,0,0,.5); }
.grid-detail { display: block; padding: 0 var(--gutter); }
.kembali-musik, .detail-judul-musik { margin: 8px 0; }
.detail-judul-musik { font-size: 24px; }
.kepala-detail-musik { display: flex; gap: 18px; align-items: flex-end; margin: 10px 0 18px; flex-wrap: wrap; }
.kepala-cover { width: 160px; height: 160px; border-radius: 8px; object-fit: cover; box-shadow: 0 8px 30px rgba(0,0,0,.5); }
.kepala-cover.tanpa-gambar { display: grid; place-items: center; font-size: 60px; }
.kepala-info { display: flex; flex-direction: column; gap: 8px; }
.daftar-lagu { list-style: none; margin: 0; padding: 0; }
.baris-lagu { display: flex; align-items: center; gap: 12px; padding: 10px 8px; border-radius: 6px; cursor: pointer; }
.baris-lagu:hover { background: var(--hitam-2); }
.lagu-no { color: var(--abu-2); width: 24px; text-align: right; font-variant-numeric: tabular-nums; }
.lagu-info { flex: 1; min-width: 0; }
.lagu-judul { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lagu-sub { color: var(--abu-2); font-size: 13px; }
.lagu-durasi { color: var(--abu-2); font-size: 13px; font-variant-numeric: tabular-nums; }
.lagu-menu { background: none; border: 0; color: var(--abu-2); font-size: 18px; padding: 0 6px; cursor: pointer; }
.lagu-menu:hover { color: var(--putih); }
/* indikator unduh per lagu (ala Spotify): kosong / spinner / ⤓ hijau */
.lagu-unduh { width: 16px; height: 16px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; }
.lagu-unduh.terunduh::before { content: '⤓'; color: #46d369; font-weight: 900; font-size: 15px; line-height: 1; }
.lagu-unduh.mengunduh { border: 2px solid rgba(255,255,255,.22); border-top-color: var(--merah); border-radius: 50%; animation: putar .9s linear infinite; }
.kosong-inline { color: var(--abu-2); padding: 20px var(--gutter); }
body.ada-musik #isiUtama { padding-bottom: 78px; }

/* Mini-player */
.mini-player { position: fixed; left: 0; right: 0; bottom: env(safe-area-inset-bottom, 0px); z-index: 60;
  display: flex; align-items: center; gap: 12px; padding: 8px 12px; background: #1c1c1cfa; backdrop-filter: blur(8px);
  border-top: 1px solid #333; cursor: pointer; }
.mini-cover { width: 44px; height: 44px; border-radius: 5px; object-fit: cover; background: #333; flex: 0 0 auto; }
.mini-info { flex: 1; min-width: 0; }
.mini-info strong { display: block; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mini-info span { color: var(--abu-2); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
.mini-tombol { background: none; border: 0; color: var(--putih); font-size: 20px; padding: 6px 8px; cursor: pointer; flex: 0 0 auto; border-radius: 50%; transition: background .15s, transform .08s; -webkit-tap-highlight-color: transparent; }
.mini-tombol:active { transform: scale(.82); background: rgba(255,255,255,.16); }
.mini-tutup { color: var(--abu-2); font-size: 16px; }
.mini-tutup:active { color: var(--putih); }

/* Now Playing */
/* Latar mengambil warna dominan SAMPUL (--hero, diisi musik.js). Dipisah ke ::before dengan
   background-color solid + mask memudar, bukan gradien langsung: background-color bisa
   di-transisi halus antarlagu, gradien tidak. */
.layar-musik::before { content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-color: var(--hero, #2a2a2a); transition: background-color 600ms ease;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.6) 42%, rgba(0,0,0,.3) 72%, rgba(0,0,0,.12) 100%);
  mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.6) 42%, rgba(0,0,0,.3) 72%, rgba(0,0,0,.12) 100%); }
.layar-musik > * { position: relative; z-index: 1; }
.layar-musik { position: fixed; inset: 0; z-index: 80; background: var(--hitam);
  display: flex; flex-direction: column; align-items: center; gap: 10px; padding: calc(env(safe-area-inset-top,0px) + 12px) var(--gutter) calc(env(safe-area-inset-bottom,0px) + 20px); }
/* Tombol tutup duduk DI ATAS sampul yang kini selebar layar — tanpa latar sendiri ia
   lenyap ke dalam gambar. Bulatan gelap + blur membuatnya terbaca di sampul apa pun. */
.musik-tutup { position: absolute; z-index: 2; top: calc(env(safe-area-inset-top,0px) + 10px); left: 14px;
  width: 36px; height: 36px; display: grid; place-items: center; border: 0; border-radius: 50%;
  background: rgba(0,0,0,.5); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  color: var(--putih); font-size: 22px; line-height: 1; cursor: pointer; }
.musik-tutup:active { background: rgba(0,0,0,.72); }
/* Rapat: margin 28->8 & jarak 12->8. Tiap piksel di sini langsung jadi ruang lirik. */
.musik-atas { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-top: 8px; width: 100%; max-width: 480px; }
/* Sampul memenuhi LEBAR layar; dibatasi tinggi layar supaya lirik/daftar tak habis di layar pendek */
.musik-cover { width: min(100%, 52vh); aspect-ratio: 1; border-radius: 10px; object-fit: cover; background: #333; box-shadow: 0 14px 50px rgba(0,0,0,.6); }
.musik-judul { text-align: center; width: 100%; max-width: 480px; }
.musik-judul strong { display: block; font-size: 18px; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.musik-judul span { display: block; color: var(--abu-2); font-size: 13px; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Nama artis di Now Playing = tautan ke halaman artis (ala Spotify). Tampil seperti teks; warnanya
   sedikit lebih terang dari sumber di sebelahnya supaya terbaca "bisa diketuk". Hover hanya di perangkat bertetikus. */
.musik-artis-tautan { background: none; border: 0; padding: 0; font: inherit; color: #d6d6d6; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.musik-artis-tautan:active { text-decoration: underline; }
@media (hover: hover) { .musik-artis-tautan:hover { color: var(--putih); text-decoration: underline; } }
html.tv .musik-artis-tautan:focus { outline: 3px solid var(--putih); outline-offset: 3px; border-radius: 4px; }
/* Panel bawah: Lirik & Daftar lagu berbagi ruang yang SAMA (ditukar lewat tab),
   jadi menambah daftar lagu tak memakan tinggi layar sedikit pun. */
.musik-panel { flex: 1; min-height: 0; width: 100%; max-width: 480px; display: flex; flex-direction: column; gap: 4px; }
.musik-tab { display: flex; gap: 6px; justify-content: center; flex: 0 0 auto; }
.musik-tab-btn { background: none; border: 0; color: var(--abu-2); font-size: 13px; padding: 4px 12px; border-radius: 14px; cursor: pointer; }
.musik-tab-btn.aktif { color: var(--putih); background: rgba(255,255,255,.12); }
.musik-daftar { flex: 1; min-height: 0; overflow-y: auto; width: 100%; margin: 0; padding: 0; list-style: none; }
.musik-daftar li { display: flex; gap: 10px; align-items: baseline; padding: 9px 10px; border-radius: 6px; cursor: pointer; text-align: left; }
.musik-daftar li:hover { background: rgba(255,255,255,.07); }
/* Baris yang SEDANG diputar ditandai pita merah di tepi kiri + isi merah tipis — bukan dengan
   mewarnai tulisannya merah. Terukur dari tangkapan layar HP jhony (22 Sep 2026): judul merah
   #e50914 di atas baris aktif cuma 2,9:1, ambang teks kecil 4,5:1. Putih di situ 13,9:1. */
.musik-daftar li.kini { background: rgba(229,9,20,.18); box-shadow: inset 3px 0 0 var(--merah); }
/* Nomor & artis memakai --abu-2, yang dinaikkan ke #9a9a9a justru karena baris ini: di latar
   merah tipis, #808080 cuma 3,6:1. Sekarang 5,1:1. */
.musik-daftar .no { color: var(--abu-2); font-size: 12px; min-width: 20px; text-align: right; flex: 0 0 auto; }
.musik-daftar .jdl { font-size: 14px; color: #f2f2f2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.musik-daftar li.kini .jdl { color: var(--putih); font-weight: 600; }
.musik-daftar .art { color: var(--abu-2); font-size: 12px; margin-left: auto; flex: 0 0 auto; }
.musik-lirik { flex: 1; min-height: 0; overflow-y: auto; width: 100%; max-width: 480px; text-align: center; padding: 10px 0; -webkit-mask-image: linear-gradient(transparent, #000 12%, #000 88%, transparent); mask-image: linear-gradient(transparent, #000 12%, #000 88%, transparent); }
/* Batang gulir di layar musik (keluhan laptop jhony 23 Sep: "ada 2 slider di kanan"):
   (1) baris aktif diperbesar scale(1.04) melebar keluar panel → overflow-y:auto ikut
   memunculkan gulir MENDATAR; (2) batang tegak lirik tak perlu — lirik menggulir sendiri
   mengikuti lagu, roda tetikus tetap jalan; (3) halaman di BELAKANG lapisan fixed ikut
   menampilkan batang gulirnya di tepi kanan jendela. */
.musik-lirik { overflow-x: hidden; scrollbar-width: none; -ms-overflow-style: none; }
.musik-lirik::-webkit-scrollbar { width: 0; height: 0; display: none; }
.musik-daftar { overflow-x: hidden; scrollbar-width: thin; }
html:has(#layarMusik:not([hidden])), body:has(#layarMusik:not([hidden])) { overflow: hidden; }
.lirik-baris { margin: 10px 0; color: #f2f2f2; font-size: 16px; line-height: 1.4; }
.musik-lirik.sinkron .lirik-baris { color: #8a8a8a; font-size: 19px; font-weight: 600; cursor: pointer; transition: color .2s, transform .2s; }
.musik-lirik.sinkron .lirik-baris.aktif { color: var(--putih); transform: scale(1.04); }
.lirik-kosong { color: var(--abu-2); margin-top: 30px; }
/* HP: SAMPUL BESAR ↔ PANEL (jhony 26 Sep 2026). Lagu diputar = sampul besar saja; ketuk Lirik/Daftar lagu →
   sampul mengecil ke pojok kiri atas (di samping tombol ▾) dan panel memenuhi ruang. Laptop/TV tak tersentuh:
   aturan ini hanya < 820px dan bukan mode TV (JS memasang kelasnya, CSS yang memutuskan berlaku atau tidak). */
@media (max-width: 819px) and (orientation: portrait), (max-width: 819px) and (min-height: 501px) {
  html:not(.tv) .layar-musik.np-sampul .musik-lirik,
  html:not(.tv) .layar-musik.np-sampul .musik-daftar { display: none; }
  /* Sampul+judul+tombol aksi DIRAPATKAN ke tombol Lirik/Daftar lagu (jhony 26 Sep 2026: "tombol lirik agak
     dikeatasin, barisan tombol download agak ke bawah" — terukur 114px kosong di antara keduanya). */
  /* lalu "sampul tarik ke atas, mepet dengan tombol back" (sampul 10px di bawah ▾), lalu "masih tll banyak ruang
     kosong" (lr-v229: ±140px menganga di antara judul & baris aksi). Menggeser saja cuma memindah lubangnya —
     tinggi layar tetap — jadi ruangnya DIISI: judul, tombol aksi & tombol Lirik/Daftar diperbesar, sisa ruang
     DIBAGI RATA (space-between: sampul di atas, baris aksi di bawah, judul di antaranya). */
  html:not(.tv) .layar-musik.np-sampul .musik-atas { flex: 1 1 auto; min-height: 0; justify-content: space-between; gap: 16px; padding-top: 36px; padding-bottom: 26px; }
  html:not(.tv) .layar-musik.np-sampul .musik-judul strong { font-size: 23px; }
  html:not(.tv) .layar-musik.np-sampul .musik-judul span { font-size: 15px; margin-top: 2px; }
  html:not(.tv) .layar-musik.np-sampul .musik-aksi { gap: 16px; }
  html:not(.tv) .layar-musik.np-sampul .musik-unduh, html:not(.tv) .layar-musik.np-sampul .musik-vol { width: 50px; height: 50px; font-size: 13px; }
  html:not(.tv) .layar-musik.np-sampul .musik-unduh .ikon, html:not(.tv) .layar-musik.np-sampul .musik-vol .ikon { width: 24px; height: 24px; }
  /* "tombol lirik dan daftar lagu dikebawahin dikit" (jhony 26 Sep 2026): 14px lebih dekat ke bar waktu, baris aksi tetap */
  html:not(.tv) .layar-musik.np-sampul .musik-panel { flex: 0 0 auto; margin-bottom: 8px; }
  /* di mode sampul keduanya TOMBOL pembuka (bukan tab terpilih) → pil berlatar supaya terbaca bisa diketuk */
  html:not(.tv) .layar-musik.np-sampul .musik-tab-btn { background: rgba(255,255,255,.18); color: var(--putih); font-weight: 600; padding: 11px 18px; font-size: 15px; min-width: 140px; }
  html:not(.tv) .layar-musik .musik-cover { transition: width .25s ease, border-radius .25s ease; }
  html:not(.tv) .layar-musik.np-panel .musik-atas {
    display: grid; grid-template-columns: 96px minmax(0, 1fr); grid-template-areas: "sampul judul" "aksi aksi";
    column-gap: 12px; row-gap: 8px; align-items: center; margin-top: 0; }
  /* Mode panel: tombol ▾ DISEMBUNYIKAN (jhony 26 Sep 2026) — sampul kecil yang menempati pojok kiri atas.
     Jalan pulang: ketuk tab aktif / sampul kecil (→ sampul besar, ▾ kembali), atau tombol back HP. */
  html:not(.tv) .layar-musik.np-panel .musik-tutup { display: none; }
  /* Lirik & Daftar lagu SAMA LEBAR: kalau tidak, pasangan yang teksnya beda panjang tampak miring dari
     tengah — yang aktif berlatar pil, yang lain tidak, jadi mata membaca pusatnya di tempat yang salah. */
  html:not(.tv) .layar-musik .musik-tab-btn { min-width: 116px; text-align: center; border: 1px solid rgba(255,255,255,.34); color: #e6e6e6; }
  /* "highlight agak dikontraskan" (jhony 26 Sep 2026): yang AKTIF = pil putih tulisan hitam (dulu isi putih 12% —
     di atas latar berwarna sampul nyaris tak terbedakan dari yang tidak aktif). */
  html:not(.tv) .layar-musik .musik-tab-btn.aktif { background: var(--putih); color: #111; border-color: var(--putih); font-weight: 700; }
  html:not(.tv) .layar-musik.np-panel .musik-cover { grid-area: sampul; width: 96px; border-radius: 8px; box-shadow: 0 4px 14px rgba(0,0,0,.5); cursor: pointer; }
  html:not(.tv) .layar-musik.np-panel .musik-judul { grid-area: judul; text-align: left; }
  html:not(.tv) .layar-musik.np-panel .musik-aksi { grid-area: aksi; justify-self: center; }
}
/* Layar lebar (laptop): dua kolom — cover+kontrol di kiri, LIRIK penuh di kanan (biar tak terjepit) */
@media (min-width: 820px) {
  .layar-musik {
    display: grid;
    grid-template-columns: minmax(280px, 360px) minmax(0, 640px);
    grid-template-rows: 1fr auto auto auto;
    grid-template-areas: "atas lirik" "seek lirik" "waktu lirik" "kontrol lirik";
    align-content: center; justify-content: center; gap: 10px 56px; padding: 40px 6vw;
  }
  .layar-musik .musik-atas { grid-area: atas; align-self: center; margin-top: 0; max-width: 360px; }
  .layar-musik .musik-panel { grid-area: lirik; align-self: stretch; max-width: 640px; }
  .layar-musik .musik-lirik { max-width: 640px; padding: 0; }
  .layar-musik .musik-seek { grid-area: seek; max-width: none; }
  .layar-musik .musik-waktu { grid-area: waktu; max-width: none; }
  .layar-musik .musik-kontrol { grid-area: kontrol; margin-top: 6px; }
}
/* HP DIMIRINGKAN (jhony 15 Okt 2026, tangkapan 2000×895: semua menumpuk). Lebar ±760px tapi tinggi cuma ±340px —
   susunan potret (sampul di atas, kontrol di bawah) tak muat, jadi elemennya saling timpa. Di sini DUA KOLOM:
   sampul + tombol aksi di kiri, judul · lirik/daftar · bar · kontrol di kanan. Lirik selalu tampil (seperti laptop;
   JS tak memasang np-sampul/np-panel karena mqLebar ikut kueri ini). Blok potret di atas DIKECUALIKAN dari kueri ini. */
@media (orientation: landscape) and (max-height: 500px) {
  html:not(.tv) .layar-musik {
    display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto auto auto;
    grid-template-areas: "sampul judul" "sampul lirik" "sampul seek" "aksi waktu" "aksi kontrol";
    align-content: stretch; justify-content: stretch; align-items: center; gap: 2px 28px;
    padding: calc(env(safe-area-inset-top,0px) + 10px) calc(env(safe-area-inset-right,0px) + 24px) calc(env(safe-area-inset-bottom,0px) + 8px) calc(env(safe-area-inset-left,0px) + 64px); }
  html:not(.tv) .layar-musik .musik-atas { display: contents; }
  /* display:contents melepas anak-anaknya dari `.layar-musik > *` (z-index 1) → lapisan warna ::before menimpa judul & sampul */
  html:not(.tv) .layar-musik .musik-atas > * { position: relative; z-index: 1; }
  html:not(.tv) .layar-musik .musik-cover, html:not(.tv) .layar-musik .musik-video-bingkai { grid-area: sampul; width: min(38vw, calc(100dvh - 120px)); align-self: center; justify-self: center; }
  html:not(.tv) .layar-musik .musik-judul { grid-area: judul; text-align: left; max-width: none; }
  html:not(.tv) .layar-musik .musik-judul strong { font-size: 18px; }
  html:not(.tv) .layar-musik:has(#musikMode:not([hidden])) .musik-judul { padding-right: 170px; }
  html:not(.tv) .layar-musik .musik-mode { left: auto; right: calc(env(safe-area-inset-right,0px) + 20px); transform: none; }
  html:not(.tv) .layar-musik .musik-aksi { grid-area: aksi; justify-self: center; align-self: center; flex-wrap: nowrap; }
  html:not(.tv) .layar-musik .musik-panel { grid-area: lirik; align-self: stretch; max-width: none; }
  html:not(.tv) .layar-musik .musik-tab { justify-content: flex-start; }
  html:not(.tv) .layar-musik .musik-lirik { max-width: none; padding: 4px 0; }
  html:not(.tv) .layar-musik .musik-seek { grid-area: seek; max-width: none; margin: 6px 0 0; }
  html:not(.tv) .layar-musik .musik-waktu { grid-area: waktu; max-width: none; }
  html:not(.tv) .layar-musik .musik-kontrol { grid-area: kontrol; margin-top: 0; gap: 16px; }
  html:not(.tv) .musik-kbtn { width: 44px; height: 44px; }
  html:not(.tv) .musik-kbtn .ikon { width: 24px; height: 24px; }
  html:not(.tv) .musik-kbtn.besar { width: 54px; height: 54px; }
  html:not(.tv) .musik-kbtn.besar .ikon { width: 28px; height: 28px; }
}
/* Bar durasi: TIPIS (3px) dan turun merapat ke tombol putar, menjauh dari lirik.
   Menggayai track sendiri mematikan isian bawaan `accent-color`, jadi isiannya digambar
   lewat gradien dengan --isi yang diperbarui bersama nilai slider (musik.js). */
.musik-seek { -webkit-appearance: none; appearance: none; width: 100%; max-width: 480px; height: 3px; margin: 10px 0 0; padding: 0; border-radius: 2px; background: linear-gradient(to right, var(--merah) var(--isi, 0%), rgba(255,255,255,.22) var(--isi, 0%)); cursor: pointer; }
.musik-seek::-webkit-slider-thumb { -webkit-appearance: none; width: 11px; height: 11px; border-radius: 50%; background: var(--putih); border: 0; }
.musik-seek::-moz-range-thumb { width: 11px; height: 11px; border-radius: 50%; background: var(--putih); border: 0; }
.musik-seek::-moz-range-track { height: 3px; background: transparent; }
.musik-waktu { width: 100%; max-width: 480px; display: flex; justify-content: space-between; color: var(--abu-2); font-size: 12px; font-variant-numeric: tabular-nums; margin-top: 2px; }
/* Mutu berkas yang diputar (mis. "MP3 · 320 kbps") DITITIPKAN di baris waktu, bukan baris baru di
   bawah judul: baris baru di sana memakan tinggi panel lirik — uji HP "ruang lirik >= 230px"
   langsung merah (245 → 228px). Di sini ia tak menambah tinggi apa pun. */
.musik-waktu .musik-kualitas { opacity: .75; letter-spacing: .2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 0 8px; }
.musik-kontrol { margin-top: -6px; }
/* Kontrol dikecilkan: tiap piksel di sini langsung jadi ruang lirik/daftar lagu.
   Sasaran sentuh tetap >=40px (pedoman minimum jempol), jadi masih enak ditekan. */
.musik-kontrol { display: flex; align-items: center; justify-content: center; gap: 18px; }
.musik-kbtn { position: relative; background: none; border: 0; color: var(--putih); font-size: 21px; cursor: pointer; opacity: .9; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; transition: background .15s, transform .08s; -webkit-tap-highlight-color: transparent; }
.musik-kbtn .ikon { width: 20px; height: 20px; fill: currentColor; display: block; }
.musik-kbtn:active { transform: scale(.82); background: rgba(255,255,255,.16); }   /* umpan balik saat ditekan */
.musik-kbtn.besar { background: var(--putih); color: #000; width: 48px; height: 48px; font-size: 20px; }
.musik-kbtn.besar:active { transform: scale(.9); background: #ddd; }
/* aktif (acak/ulang menyala) — emoji abaikan `color`, jadi pakai lingkaran + titik penanda */
/* NYALA (acak / ulang): ikon PUTIH di atas lingkaran merah + cincin merah — bukan ikon merah di
   atas isi merah. Terukur 22 Sep 2026: ikon #e50914 di lingkaran nyala cuma 2,78:1, sedangkan
   ambang WCAG untuk objek grafis (1.4.11) 3:1. Putih di situ 13,3:1. Cincinnya membuat keadaan
   "nyala" tetap terbaca tanpa bergantung pada warna saja. */
.musik-kbtn.nyala { color: var(--putih); opacity: 1; background: rgba(229,9,20,.28); box-shadow: inset 0 0 0 1.5px var(--merah); }
.musik-kbtn.nyala::after { content: ''; position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%); width: 5px; height: 5px; border-radius: 50%; background: var(--putih); }
/* HP: PEMUTAR DIBESARKAN (jhony 26 Sep 2026: "mgkin player nya gak dibesarkan" — ruang kosong di Now Playing
   diisi kontrol yang berguna, bukan celah). Dulu sengaja dikecilkan (play 48px) demi ruang lirik; sejak lirik
   punya mode panel sendiri (sampul mengecil) ruang itu tak lagi dibutuhkan di sini. Laptop/TV tak tersentuh. */
@media (max-width: 819px) and (orientation: portrait), (max-width: 819px) and (min-height: 501px) {
  html:not(.tv) .musik-kontrol { gap: 20px; margin-top: 2px; }
  html:not(.tv) .musik-kbtn { width: 52px; height: 52px; }
  html:not(.tv) .musik-kbtn .ikon { width: 28px; height: 28px; }
  html:not(.tv) .musik-kbtn.besar { width: 70px; height: 70px; }
  html:not(.tv) .musik-kbtn.besar .ikon { width: 34px; height: 34px; }
  html:not(.tv) .musik-kbtn.nyala::after { bottom: 5px; width: 6px; height: 6px; }
  html:not(.tv) .musik-seek { height: 4px; margin-top: 14px; }
  html:not(.tv) .musik-seek::-webkit-slider-thumb { width: 15px; height: 15px; }
  html:not(.tv) .musik-seek::-moz-range-thumb { width: 15px; height: 15px; }
  html:not(.tv) .musik-waktu { font-size: 13px; margin-top: 4px; }
}
/* Unduh · Volume · Layar = TIGA TOMBOL IKON BULAT sebaris, senada tombol bulat di halaman playlist
   (jhony 26 Sep 2026: tombol berteks "melebar ke bawah" — "Volume disamakan: longgar" tak muat di
   samping "Unduh offline", Layar turun ke baris kedua). Keadaan dibaca dari ikon + cincin warna;
   namanya di aria-label/title dan disebut lewat toast tiap diketuk. */
.musik-unduh, .musik-vol { position: relative; background: none; border: 1.5px solid rgba(255,255,255,.45); color: var(--putih); padding: 0; width: 40px; height: 40px; border-radius: 50%; display: inline-grid; place-items: center; cursor: pointer; font-size: 10px; font-weight: 700; flex-shrink: 0; -webkit-tap-highlight-color: transparent; }
.musik-unduh .ikon, .musik-vol .ikon { width: 20px; height: 20px; fill: currentColor; display: block; }
.musik-unduh:active, .musik-vol:active { transform: scale(.9); }
.musik-unduh.terunduh { border-color: #46d369; color: #46d369; }
/* NYALA: ikon PUTIH di atas isi merah tipis + cincin merah (merah di latar gelap cuma 3,2:1). */
.musik-vol.nyala { border-color: var(--merah); background: rgba(229, 9, 20, .22); color: var(--putih); }
/* Longgar vs ketat: ketat diberi titik penanda seperti .musik-kbtn.nyala */
.musik-vol.ketat::after { content: ''; position: absolute; bottom: 4px; left: 50%; transform: translateX(-50%); width: 4px; height: 4px; border-radius: 50%; background: var(--putih); }
/* Timer tidur aktif: sisa menit (mis. 15') DI DALAM lingkaran — cukup besar untuk dibaca sekilas. */
.musik-timer { font-size: 12px; }
html.tv .musik-timer { font-size: 16px; }
/* "Samakan volume": mati = redup, nyala = aksen merah (pola sama dg .musik-kbtn.nyala) */
/* Saklar geser on/off: abu saat mati, hijau saat nyala, bulatannya bergeser */
.saklar { display: inline-flex; align-items: center; gap: 8px; background: none; border: 0; padding: 4px 0; cursor: pointer; color: var(--abu-2); font-size: 13px; }
.saklar-jalur { position: relative; flex: 0 0 auto; width: 38px; height: 22px; border-radius: 11px; background: #555; transition: background .2s; }
.saklar-bulat { position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: transform .2s; }
/* Aksen "sedang aktif" = MERAH (identitas app). HIJAU disisakan KHUSUS untuk
   "tersimpan di perangkat ini" (tombol Terunduh, ikon di daftar lagu) supaya maknanya tak luntur. */
.saklar.nyala { color: var(--merah); }
.saklar.nyala .saklar-jalur { background: var(--merah); }
.saklar.nyala .saklar-bulat { transform: translateX(16px); }
/* Unduh + Samakan volume BERDAMPINGAN: menumpuk ke bawah memakan ruang lirik */
.musik-aksi { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }

/* Peringatan "jangan tutup halaman" saat mengunggah. Unggah jalan di JS HALAMAN
   (Background Fetch untuk upload DIMATIKAN — lihat public/unggah.js), jadi menutup
   halaman benar-benar menghentikannya. Dibuat menempel di atas supaya tak terlewat. */
.peringatan-unggah { position: sticky; top: 0; z-index: 30; display: block;
  background: #7a4b00; color: #ffe9c7; border-bottom: 1px solid #a86b00;
  padding: 10px var(--gutter); font-size: 13px; line-height: 1.45; }
.peringatan-unggah strong { display: block; color: #fff; font-size: 14px; }
.peringatan-unggah span { display: block; opacity: .9; margin-top: 2px; }

/* Tombol kembali di layar profil — hanya tampil kalau MASIH ada profil aktif untuk dituju. */
.profil-kembali { position: absolute; top: calc(env(safe-area-inset-top,0px) + 14px); left: 16px;
  background: none; border: 1px solid var(--abu-2); color: var(--abu-2); border-radius: 20px;
  padding: 7px 16px; font-size: 13px; cursor: pointer; }
.profil-kembali:hover { color: var(--putih); border-color: var(--putih); }
.profil-undangan { color: var(--putih); max-width: 420px; line-height: 1.5; }
.profil-undangan a { color: var(--merah); font-weight: 700; }
.profil-undangan a.tombol { display: inline-flex; margin-top: 10px; color: #000; text-decoration: none; }
.profil-bawah { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }
/* Akun email (22 Sep 2026): form masuk akun di layar profil + baris "akun@… · Keluar akun" */
.form-akun { flex-direction: column; align-items: center; }
.form-akun #akunAjakan { margin: 0 0 4px; }
.form-akun input { width: min(320px, calc(100vw - 32px)); }
.profil .profil-email { display: block; color: var(--abu-2); font-size: 11px; margin-top: -6px; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.akun-galat { color: #ffb84d; }
/* merah-teks, bukan --merah: tulisan kecil di latar gelap (--merah cuma 3,84:1) */
.profil-undangan a.akun-kontak { color: var(--merah-teks); text-decoration: underline; overflow-wrap: anywhere; }
.sambung-tv { display: flex; flex-direction: column; align-items: center; gap: 12px; margin: 8px 16px 0; max-width: 760px; }
.sambung-tv[hidden] { display: none; }
.sambung-tv-judul { font-size: 22px; font-weight: 700; margin: 0; text-align: center; }
.sambung-tv-isi { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; justify-content: center; }
.sambung-tv-qr { background: #fff; padding: 10px; border-radius: 8px; line-height: 0; min-width: 180px; min-height: 180px; }
.sambung-tv-qr svg { width: 200px; height: 200px; display: block; }
.sambung-tv-langkah { max-width: 380px; color: var(--abu-2); font-size: 16px; }
.sambung-tv-langkah p { margin: 0 0 8px; }
.sambung-tv-langkah strong { color: var(--putih); }
.sambung-tv-kode { font: 700 44px/1.1 ui-monospace, Menlo, Consolas, monospace; letter-spacing: 6px; color: var(--putih); margin: 6px 0 10px; }
.sambung-tv-ket { font-size: 13px; }
.akun-info { color: var(--abu-2); font-size: 13px; display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: center; }
.akun-info #akunEmail { color: var(--putih); }
.keluar-profil { position: absolute; top: calc(env(safe-area-inset-top,0px) + 14px); right: 16px; }

/* Pemeran: baris wajah yang digulir mendatar (di HP jempol menggeser, di layar besar tetap satu baris).
   Gulir MENDATAR butuh lebar anak yang dipatok (flex: 0 0 <lebar>) — tanpa itu anaknya
   menyusut memenuhi wadah dan barisnya tak pernah bisa digulir. */
.detail-pemeran { margin: 22px 0 0; max-width: 100%; }
.detail-pemeran h3 { font-size: 15px; color: #bbb; font-weight: 600; margin: 0 0 10px; text-transform: uppercase; letter-spacing: 0.6px; }
.detail-pemeran ul { list-style: none; margin: 0; padding: 0 0 6px; display: flex; gap: 14px; overflow-x: auto; scrollbar-width: thin; -webkit-overflow-scrolling: touch; }
.detail-pemeran li { flex: 0 0 92px; text-align: center; }
.detail-pemeran img, .detail-pemeran .tanpa-wajah { width: 76px; height: 76px; border-radius: 50%; object-fit: cover; object-position: center top; background: var(--abu); display: block; margin: 0 auto 7px; }
.detail-pemeran .tanpa-wajah { display: grid; place-items: center; color: var(--abu-2); font-size: 24px; font-weight: 700; }
.detail-pemeran .nama { font-size: 13px; font-weight: 600; line-height: 1.25; }
.detail-pemeran .peran { font-size: 12px; color: var(--abu-2); line-height: 1.25; margin-top: 2px; }
@media (max-width: 520px) {
  .detail-pemeran li { flex: 0 0 78px; }
  .detail-pemeran img, .detail-pemeran .tanpa-wajah { width: 64px; height: 64px; }
}

/* Tombol Putar melayang di tengah gambar episode. Tembus pandang, tapi WAJIB tetap
   terbaca di atas bingkai terang maupun gelap (uji: Episode 5 Neagley nyaris hitam,
   Episode 4 nyaris putih) — karena itu lingkaran gelap + tepi & panah putih sekaligus,
   bukan salah satunya saja. */
.episode .bingkai { position: relative; display: block; }
.episode .putar-ep {
  position: absolute; inset: 0; margin: auto;
  width: 40px; height: 40px; padding: 0; border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,.9); background: rgba(0,0,0,.45);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  color: #fff; display: grid; place-items: center; cursor: pointer;
  box-shadow: 0 1px 6px rgba(0,0,0,.5);
  transition: background .15s, transform .15s;
}
.episode .putar-ep svg { width: 18px; height: 18px; fill: currentColor; margin-left: 2px; /* panah terlihat di tengah */ }
.episode .putar-ep:hover, .episode .putar-ep:focus-visible { background: rgba(0,0,0,.72); transform: scale(1.08); }
.episode .putar-ep:active { transform: scale(.94); }
@media (max-width: 520px) {
  .episode .putar-ep { width: 36px; height: 36px; }
  .episode .putar-ep svg { width: 16px; height: 16px; }
}

/* ---------- Tombol Acak di kepala detail (playlist/album/artis) ---------- */
/* Empat tombol (Putar, Acak, unduh, titik tiga) WAJIB muat satu baris di 390px. Di kepala radio
   ruangnya paling sempit (padding 18px kiri-kanan), dan dengan jarak 10px + tombol bulat 44px
   barisnya melipat — titik tiganya turun sendirian ke baris kedua. Angka di bawah dipilih dari
   pengukuran, bukan kira-kira. */
.kepala-aksi { display: flex; gap: 8px; align-items: center; margin-top: 10px; flex-wrap: wrap; }
.kepala-aksi .kbtn-bulat { width: 40px; height: 40px; flex: 0 0 40px; }

/* ---------- Kepala playlist RADIO ----------
   Tiga sampul bundar (besar di tengah, dua kecil mengapit) di atas latar berona. Ronanya
   diturunkan dari NAMA playlist (--rona), jadi tiap radio punya warna sendiri yang tetap sama
   tiap dibuka, tanpa perlu disimpan di mana pun. */
.kepala-radio { margin: 6px 0 18px; border-radius: 12px; overflow: hidden;
  background: linear-gradient(180deg, hsl(var(--rona, 20) 62% 62%) 0%, hsl(var(--rona, 20) 45% 38%) 46%, var(--hitam-2) 100%); }
.radio-lingkar { display: flex; align-items: center; justify-content: center; gap: 0; padding: 26px 16px 14px; }
.radio-bulat { border-radius: 50%; object-fit: cover; background: var(--abu); box-shadow: 0 6px 24px rgba(0,0,0,.45); }
.radio-bulat.tengah { width: 148px; height: 148px; z-index: 2; }
.radio-bulat.kiri, .radio-bulat.kanan { width: 104px; height: 104px; }
.radio-bulat.kiri { margin-right: -26px; }
.radio-bulat.kanan { margin-left: -26px; }
.radio-bulat.tanpa-gambar { display: grid; place-items: center; font-size: 46px; color: #ddd; }
.radio-isi { padding: 4px 18px 20px; }
.radio-judul { font-size: clamp(28px, 7vw, 44px); line-height: 1.05; margin: 0 0 10px; font-weight: 800; letter-spacing: -0.5px; }
.radio-merek { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: 14px; margin-bottom: 4px; }
.lr-lambang { width: 22px; height: 22px; flex: 0 0 22px; }
@media (max-width: 520px) {
  .radio-bulat.tengah { width: 118px; height: 118px; }
  .radio-bulat.kiri, .radio-bulat.kanan { width: 82px; height: 82px; }
  .radio-bulat.kiri { margin-right: -20px; }
  .radio-bulat.kanan { margin-left: -20px; }
}
.radio-dengan { color: rgba(255,255,255,.88); font-size: 14px; margin-bottom: 8px; }

/* ---------- Tombol bulat berikon (unduh, menu titik tiga) ----------
   Teks tombol unduh dipindah ke title/aria-label; kemajuan unduhan punya elemennya sendiri
   (.unduh-maju) supaya indikator "Mengunduh 12/50" tidak terhapus saat ikonnya digambar ulang. */
.kbtn-bulat { width: 40px; height: 40px; flex: 0 0 40px; display: grid; place-items: center;
  background: transparent; color: #cfcfcf; border: 1px solid #5a5a5a; border-radius: 50%; cursor: pointer; padding: 0; }
.kbtn-bulat .ikon { width: 22px; height: 22px; fill: currentColor; }
/* Sorotan HOVER hanya untuk perangkat yang benar-benar punya penunjuk. Di Android, `:hover`
   MENEMPEL pada elemen terakhir yang diketuk sampai orangnya mengetuk tempat lain — jadi tombol
   yang baru saja ditekan tetap tampil "tersorot" dan warnanya menimpa keadaan sebenarnya.
   Dilaporkan jhony 20 Sep 2026 untuk tombol + Koleksi Kamu: "logonya gak berwarna merah, tetap
   warna putih". Fokus TIDAK ikut dibatasi: remote TV & keyboard memang perlu melihat sorotannya. */
@media (hover: hover) {
  .kbtn-bulat:hover:not(:disabled) { color: var(--putih); border-color: var(--putih); background: rgba(255,255,255,.08); }
}
.kbtn-bulat:focus-visible { color: var(--putih); border-color: var(--putih); background: rgba(255,255,255,.08); }
.kbtn-bulat:disabled { opacity: .55; cursor: default; }
.kbtn-bulat.terunduh-pl { color: #46d369; border-color: #46d369; }
/* Putar & Acak di KEPALA halaman: bundar, tanpa teks (seperti Spotify).
   Teks "Putar"/"Acak" dibuang 22 Sep 2026 karena barisnya tak cukup untuk lima tombol di layar
   HP — menu titik tiga jatuh sendirian ke baris kedua (potret jhony). Putar sengaja lebih besar
   & TERISI: di satu baris ikon serupa, yang utama harus menang tanpa perlu dibaca. */
.putar-bulat { width: 48px; height: 48px; flex: 0 0 48px; background: var(--putih); color: #000; border-color: var(--putih); }
.putar-bulat .ikon { width: 26px; height: 26px; }
.kepala-aksi .putar-bulat { width: 48px; height: 48px; flex: 0 0 48px; }
@media (hover: hover) {
  .putar-bulat:hover:not(:disabled) { background: #fff; color: #000; border-color: #fff; }
}
.putar-bulat:focus-visible { background: #fff; color: #000; border-color: #fff; }
html.tv .putar-bulat { width: 64px; height: 64px; flex: 0 0 64px; }
html.tv .putar-bulat .ikon { width: 34px; height: 34px; }
html.tv .kepala-aksi .kbtn-bulat { width: 56px; height: 56px; flex: 0 0 56px; }
html.tv .kepala-aksi .putar-bulat { width: 64px; height: 64px; flex: 0 0 64px; }
.unduh-maju { color: #bbb; font-size: 13px; align-self: center; }

/* ---------- Menu titik tiga ---------- */
.menu-kecil { position: absolute; z-index: 60; min-width: 190px; padding: 6px; border-radius: 10px;
  background: #282828; border: 1px solid #3d3d3d; box-shadow: 0 10px 34px rgba(0,0,0,.6); }
.menu-kecil-item { display: block; width: 100%; text-align: left; background: transparent; border: 0;
  color: var(--putih); font-size: 15px; padding: 10px 12px; border-radius: 6px; cursor: pointer; }
.menu-kecil-item:hover, .menu-kecil-item:focus-visible { background: #3d3d3d; }
.menu-kecil-item.bahaya { color: #ff6b6b; }

/* Sampul KARTU untuk playlist radio — senada dengan kepala halaman dalamnya.
   Ukuran lingkaran dalam PERSEN lebar kartu, supaya ikut mengecil di HP tanpa aturan tambahan.
   `.kartu img` memaksa width:100% + aspect-ratio 2/3, jadi di sini ditimpa dengan sengaja. */
.radio-cover { position: relative; width: 100%; aspect-ratio: 2/3; border-radius: 4px; overflow: hidden;
  display: grid; place-items: center;
  background: linear-gradient(180deg, hsl(var(--rona, 20) 62% 60%) 0%, hsl(var(--rona, 20) 45% 30%) 100%); }
.radio-cover-lingkar { display: flex; align-items: center; justify-content: center; width: 100%; }
.kartu .radio-cover img.radio-cover-bulat, .radio-cover-bulat {
  width: 38%; aspect-ratio: 1; height: auto; border-radius: 50%; object-fit: cover;
  background: var(--abu); box-shadow: 0 3px 12px rgba(0,0,0,.45); }
.kartu .radio-cover img.radio-cover-bulat.tengah, .radio-cover-bulat.tengah { width: 54%; z-index: 2; }
.radio-cover-bulat.kiri { margin-right: -9%; }
.radio-cover-bulat.kanan { margin-left: -9%; }
.radio-cover-bulat.tanpa-gambar { display: grid; place-items: center; font-size: 22px; color: #eee; }
/* Judul radio ikut ditempel di sampulnya (22 Sep 2026) — lapisan gelap di bawah WAJIB, gradien
   sampul yang terang (hijau/ungu) menelan tulisan putih tanpa itu. */
.radio-cover::after { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(0,0,0,0) 45%, rgba(0,0,0,.66) 100%); }

/* ---------- Sampul playlist BIASA: gambar + nama + lambang ----------
   Nama playlist DITEMPEL di sampulnya (seperti sampul editorial), jadi kartu tetap dikenali
   walau judul di bawahnya terpotong. Lapisan gelap di bawah wajib: tanpa itu judul putih hilang
   di atas sampul yang terang. */
.pl-sampul { position: relative; width: 100%; aspect-ratio: 2/3; border-radius: 4px; overflow: hidden; background: var(--abu); }
.pl-sampul.besar { width: min(280px, 72vw); aspect-ratio: 1; border-radius: 8px; box-shadow: 0 10px 34px rgba(0,0,0,.55); }
.kartu .pl-sampul img.pl-sampul-gambar, .pl-sampul-gambar { width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; display: block; border-radius: 0; }
.pl-sampul.tanpa-sampul .pl-sampul-gambar { display: grid; place-items: center; font-size: 34px; color: #eee;
  background: linear-gradient(160deg, hsl(var(--rona, 20) 55% 52%), hsl(var(--rona, 20) 45% 26%)); }
.pl-sampul::after { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(0,0,0,.42) 0%, rgba(0,0,0,0) 34%, rgba(0,0,0,.72) 100%); }
.pl-sampul-lambang { position: absolute; top: 7px; left: 7px; z-index: 2; line-height: 0; }
.pl-sampul-lambang .lr-lambang { width: 20px; height: 20px; filter: drop-shadow(0 1px 3px rgba(0,0,0,.8)); }
.pl-sampul.besar .pl-sampul-lambang .lr-lambang { width: 28px; height: 28px; }
.pl-sampul-judul { position: absolute; left: 9px; right: 9px; bottom: 8px; z-index: 2; color: #fff; font-weight: 800;
  font-size: clamp(13px, 1.35vw, 17px); line-height: 1.12; letter-spacing: -0.2px; text-shadow: 0 2px 8px rgba(0,0,0,.75);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.pl-sampul.besar .pl-sampul-judul { left: 16px; right: 16px; bottom: 14px; font-size: clamp(22px, 5.2vw, 34px); }

/* Kepala playlist biasa: sampul di tengah, keterangan di bawahnya (seperti contoh Spotify). */
.kepala-plist { display: flex; flex-direction: column; align-items: center; gap: 14px; margin: 8px 0 18px; }
.kepala-plist-isi { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }
.kepala-plist-isi .kepala-aksi { justify-content: center; }

/* ---------- Layar PIN ----------
   Menggantikan prompt() bawaan peramban: kotak putih sistem yang menyebut nama domain
   ("layarrumah.stream menyatakan…") dan mematahkan suasana app. Layar ini memakai token yang
   sudah ada, supaya satu bahasa dengan layar "Siapa yang menonton?".

   Yang KHAS di sini: layar mengenakan WARNA PROFILnya sendiri (`--warna-profil`, dipasang dari
   JS) — kotak yang sedang diisi bergaris warna avatar orang itu. Di app banyak profil, itu
   menjawab pertanyaan nyata "ini PIN siapa yang sedang saya ketik". */
.layar-pin { position: fixed; inset: 0; z-index: 50; background: var(--hitam);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 24px var(--gutter); text-align: center; }
/* Layar PILIHAN & TEKS (public/dialog.js) di atas SEMUA lapisan, termasuk Now Playing (80) & mini-player (90).
   Di z-index 50 bawaan .layar-pin, timer tidur yang dibuka dari Now Playing terbuka DI BELAKANGNYA — jhony
   26 Sep 2026: "tombol timernya gak berfungsi" (ternyata berfungsi, tapi tak terlihat). Toast ikut naik (101). */
.layar-pilih, .layar-teks { z-index: 100; }
.layar-pin .pin-avatar { width: 64px; height: 64px; border-radius: 6px; display: grid; place-items: center;
  font-size: 30px; font-weight: 700; color: #fff; }
.layar-pin h2 { font-weight: 400; font-size: clamp(20px, 5vw, 30px); margin: 6px 0 0; }
.pin-sub { color: var(--abu-2); margin: 0; font-size: 15px; }
.pin-angka-wadah { position: relative; margin-top: 10px; }
.pin-angka { display: flex; gap: 12px; }
.pin-digit { width: 48px; height: 60px; border-radius: 6px; background: #000; border: 1px solid #333;
  border-bottom: 2px solid #333; display: grid; place-items: center; font-size: 26px; color: var(--putih); }
.pin-digit.terisi { border-bottom-color: var(--warna-profil, var(--putih)); }
.pin-digit.kini { border-color: var(--warna-profil, var(--putih)); box-shadow: 0 0 0 3px rgba(255,255,255,.08); }
/* Kursor berkedip di kotak yang sedang ditunggu: tanpa ini kotak kosong tak memberi isyarat
   bahwa papan ketik sudah siap — orang menunggu sesuatu terjadi. */
.pin-digit.kini::after { content: ""; width: 2px; height: 26px; background: var(--warna-profil, var(--putih)); animation: pin-kedip 1.1s steps(1) infinite; }
@keyframes pin-kedip { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }
/* Masukan asli menumpang DI ATAS kotak: mengetuk kotak berarti mengetuk kotak masukan, jadi papan
   ketik HP muncul tanpa perlu tipuan fokus. 16px supaya iOS tidak memperbesar halaman. */
.pin-masukan { position: absolute; inset: 0; width: 100%; opacity: 0; font-size: 16px;
  border: 0; background: transparent; color: transparent; }
.pin-galat { min-height: 20px; margin: 4px 0 0; color: #ff6b6b; font-size: 14px; } /* ruangnya dipesan: tak ada lompatan saat galat muncul */
.pin-aksi { display: flex; flex-direction: column; align-items: center; gap: 10px; margin-top: 4px; }
.layar-pin.salah .pin-angka { animation: pin-goyang .4s; }
@keyframes pin-goyang { 0%,100% { transform: translateX(0); } 20% { transform: translateX(-8px); } 40% { transform: translateX(8px); } 60% { transform: translateX(-5px); } 80% { transform: translateX(5px); } }
@media (prefers-reduced-motion: reduce) { .layar-pin.salah .pin-angka { animation: none; } .pin-digit.kini::after { animation: none; } }
@media (max-width: 360px) { .pin-digit { width: 42px; height: 54px; } .pin-angka { gap: 9px; } }
/* Daftar tombol bisa PANJANG (memilih di antara 22 playlist): dibatasi tinggi layar & digulir,
   bukan mendorong tombol Batal keluar layar. */
.pilih-tombol { display: flex; flex-direction: column; gap: 10px; width: min(300px, 100%); margin-top: 10px; max-height: 60vh; overflow-y: auto; padding: 2px; }
.pilih-tombol .tombol { flex: 0 0 auto; }
/* baris daftar (email terdaftar): dua baris — email + profilnya; email panjang dipotong di huruf mana pun */
.pilih-tombol .tombol-daftar { display: block; border-radius: 12px; text-align: left; font-weight: 400; font-size: 14px; line-height: 1.35; white-space: pre-line; overflow-wrap: anywhere; padding: 8px 12px; }
.pilih-tombol .tombol-daftar::first-line { font-weight: 700; }
.teks-masukan { width: min(320px, 100%); margin-top: 10px; background: #000; color: var(--putih); border: 1px solid #555;
  border-bottom: 2px solid var(--warna-profil, var(--merah)); border-radius: 6px; padding: 12px 14px; font-size: 18px; }
.teks-masukan:focus { outline: none; border-color: var(--warna-profil, var(--merah)); }
.toast-kecil { position: fixed; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%);
  z-index: 101; background: rgba(20,20,20,.96); border: 1px solid #4a4a4a; color: #fff; padding: 10px 16px; border-radius: 8px;
  font-size: 14px; max-width: min(92%, 420px); text-align: center; box-shadow: 0 6px 24px rgba(0,0,0,.6); }
.pilih-tombol .tombol { justify-content: center; width: 100%; }
/* Keterangan di pemilih profil saat tanpa sinyal. Dulu layarnya berhenti kosong — "Siapa yang
   menonton?" tanpa satu pun profil — dan terbaca seperti semua profil hilang. */
.profil-luring { color: var(--abu-2); font-size: 14px; margin: 0; max-width: 330px; line-height: 1.5; }
.profil-coba-lagi { margin-top: 12px; }

/* ---------- Aktivitas (khusus admin, public/aktivitas.js) ---------- */
.aktivitas { padding: 24px var(--gutter) 60px; display: grid; gap: 14px; max-width: 760px; }
.aktivitas-atas { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.aktivitas-judul { font-size: 22px; margin: 0; }
.aktivitas-kartu { background: #1c1c1c; border-radius: 8px; padding: 14px 16px; border-left: 3px solid transparent; }
.aktivitas-kartu.aktif { border-left-color: var(--merah); }
.aktivitas-pilih { display: block; width: 100%; text-align: left; color: inherit; font: inherit; border: 0; border-left: 3px solid transparent; cursor: pointer; position: relative; padding-right: 40px; }
.aktivitas-pilih.aktif { border-left-color: var(--merah); }
.aktivitas-pilih:hover, .aktivitas-pilih:focus-visible { background: #262626; outline: none; }
.aktivitas-pilih .aktivitas-sekarang { font-size: 14px; margin: 10px 0 0; }
.aktivitas-panah { position: absolute; right: 16px; top: 50%; transform: translateY(-50%); font-size: 26px; color: var(--abu-2); }
.aktivitas-segar { justify-self: start; }
.aktivitas-kepala { display: flex; align-items: center; gap: 12px; }
.aktivitas-kepala .avatar { width: 36px; height: 36px; border-radius: 4px; font-size: 16px; display: grid; place-items: center; flex: none; }
.aktivitas-nama { display: flex; flex-direction: column; min-width: 0; }
.aktivitas-nama strong { font-size: 16px; }
.aktivitas-lalu { font-size: 12px; color: var(--abu-2); }
.aktivitas-kartu.aktif .aktivitas-lalu { color: #46d369; }
.aktivitas-sekarang { margin: 12px 0 4px; font-size: 15px; font-weight: 600; }
.aktivitas-daftar { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 6px; }
.aktivitas-baris { display: grid; grid-template-columns: 18px 6.4em 1fr; gap: 8px; font-size: 13px; color: #d0d0d0; align-items: baseline; }
.aktivitas-ikon { color: var(--abu-2); text-align: center; }
.aktivitas-jam { color: var(--abu-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.aktivitas-teks { min-width: 0; overflow-wrap: anywhere; }
.aktivitas-kosong { color: var(--abu-2); font-size: 14px; margin: 4px 0; }
/* perangkat pemakai (App Android / PWA / Peramban) — kartu profil & tiap baris riwayat */
.aktivitas-perangkat { margin: 8px 0 0; font-size: 13px; color: #d0d0d0; }
.aktivitas-perangkat strong { color: var(--putih); font-weight: 600; }
.aktivitas-perangkat-lain { color: var(--abu-2); }
.aktivitas-klien { display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 4px; background: #2a2a2a; color: #b8b8b8; font-size: 11px; line-height: 17px; white-space: nowrap; vertical-align: 1px; }
.aktivitas-mutu.hemat { background: #3a2a10; color: #ffcf7a; } /* Hemat menonjol: admin perlu tahu siapa yang koneksinya tersendat */
.aktivitas-proses.berat { background: #3a1216; color: #ff9aa2; } /* encode video = minipc bekerja keras */
.aktivitas-jejak { margin-top: 12px; padding-top: 12px; border-top: 1px solid #2a2a2a; }
.aktivitas-jejak h3 { margin: 0; font-size: 15px; }
.aktivitas-jejak .aktivitas-baris { grid-template-columns: 18px 6.4em 1fr; }
@media (max-width: 749px) { .aktivitas-baris { grid-template-columns: 16px 6.2em 1fr; } .aktivitas-jam { font-size: 12px; } } /* kolom jam muat "29 Sep 20:55" (77px di 13px, diukur 6 Okt); dulu 44px = tanggal menimpa judul */

/* TV: tanpa pointer melayang, panah geser ‹ › yang hanya muncul saat :hover tak akan pernah
   terlihat — di sana ia dibuat tetap tampak. Fokus juga harus KELIHATAN dari jarak 3 meter:
   :focus-visible saja tak selalu menyala untuk fokus yang dipindahkan dari kode. */
.geser-wrap.tetap .geser-panah { opacity: .8; }
.geser-wrap.tetap .geser-panah.sembunyi { opacity: 0 !important; }
/* Bingkai fokus HANYA di TV (fokus dari remote/kode) & fokus papan ketik. Dulu `.kartu:focus` polos → di HP
   kartu yang diketuk menerima fokus, fokus dikembalikan ke sana saat detail ditutup, dan bingkai putih
   menempel di baris (laporan jhony 28 Sep, kartu Cosmos di Baru Ditambahkan). */
html.tv .kartu:focus, .kartu:focus-visible { outline: 3px solid var(--putih); outline-offset: 3px; transform: scale(1.06); z-index: 2; }
.geser-panah:focus { opacity: 1 !important; outline: 3px solid var(--putih); outline-offset: -5px; }

/* ---------------- Mode TV ----------------
   Dinyalakan oleh public/app.js (kelas `tv` di <html>) saat layar besar + tak bisa disentuh +
   tak punya pointer melayang; bisa dipaksa dengan ?tv=1 / ?tv=0. Dua hal yang membedakan TV dari
   layar lain: orang duduk ~3 meter jauhnya (semua harus lebih besar), dan sebagian TV memotong
   tepi gambar (overscan) — karena itu jarak tepi dilebarkan, bukan sekadar diperbesar. */
html.tv { --gutter: 3.5vw; }
html.tv body { font-size: 19px; }
/* Bar atas di TV. Angka pertama (menu 21px, logo 30px, cari 19px) masih ukuran laptop: di
   layar 1920 yang ditonton dari ~3 meter, tautan setinggi 29px terbaca sebesar teks 8px di
   depan hidung — jhony melihatnya langsung ("menu di halaman utama masih kecil"). Dipakai
   clamp, bukan angka mati, karena mode TV juga menyala di 1280px: di sana nilai bawahnya yang
   berlaku supaya tujuh tautan + kotak cari tetap muat satu baris (kalau tidak, .nav yang
   flex-wrap akan melipatnya diam-diam). */
html.tv .nav { padding-top: 2.4vh; padding-bottom: 2.4vh; gap: 10px clamp(14px, 1.2vw, 24px); }
html.tv .nav-kiri { gap: clamp(22px, 2.3vw, 44px); }
html.tv .nav-menu { gap: clamp(20px, 2.3vw, 44px); font-size: clamp(23px, 1.6vw, 31px); }
html.tv .logo { font-size: clamp(30px, 2.2vw, 42px); }
html.tv .cari { padding: 0 clamp(12px, 0.9vw, 18px); border-radius: 8px; }
html.tv .cari svg { width: clamp(18px, 1.3vw, 25px); height: clamp(18px, 1.3vw, 25px); }
html.tv .cari input { font-size: clamp(19px, 1.3vw, 25px); width: clamp(190px, 15vw, 300px); padding: clamp(9px, 0.8vh, 14px) 0; }
html.tv .avatar-kecil { width: clamp(38px, 2.6vw, 50px); height: clamp(38px, 2.6vw, 50px); font-size: clamp(19px, 1.3vw, 25px); border-radius: 6px; }
html.tv .baris h3, html.tv .baris-semua h3 { font-size: 26px; margin-bottom: 0; } /* jarak ke kartu = ruang atas .geser (36px) */
html.tv .lihat-semua { font-size: 19px; padding: 8px 10px; }
html.tv .lihat-semua:focus { color: var(--putih); outline: 3px solid var(--putih); outline-offset: 0; }
html.tv .kartu { width: clamp(220px, 16vw, 330px); }
html.tv .kartu.lebar { width: clamp(360px, 30vw, 560px); }
html.tv .kartu .kartu-judul { font-size: 18px; }
html.tv .kartu .kartu-sub { font-size: 16px; }
/* Ruang atas-bawah = kartu tersorot (skala 1,09 + garis 4px + jarak 4px) tak terpotong oleh .geser yang
   overflow-nya ikut memotong tegak (foto TV 27 Sep: garis atas & bawah kartu hilang). Snap dimatikan di TV:
   baris digeser lewat kode (kartu menempel kiri) dan snap `proximity` ikut menarik saat animasi halus. */
html.tv .geser { gap: 16px; padding-top: 36px; padding-bottom: 36px; scroll-snap-type: none; }
/* Hero di TV dipatok ke LAYAR, bukan ke lebar. `min-height: 62vw` berarti 1190px di layar
   1920 — lebih tinggi dari layarnya sendiri, jadi tombol Putar/Info jatuh di bawah lipatan
   (terukur 20 Sep: tombol 1063-1119px di layar 1080, terpotong). Di TV tak ada gulir jari
   untuk menemukannya kembali; itu tombol pertama yang ditekan orang. Sisa 96px disengaja:
   pucuk baris kartu pertama ikut terlihat, itulah yang memberi tahu "masih ada di bawah". */
html.tv .hero { min-height: 0; max-height: none; height: calc(100vh - var(--nav-h, 60px) - 96px); }
html.tv .hero-isi { padding-top: 0; }
html.tv .hero-isi h2 { font-size: clamp(34px, 4vw, 64px); }
html.tv .hero-ket { font-size: 22px; }
html.tv .tombol { font-size: 20px; padding: 14px 30px; }
html.tv .kaki { font-size: 16px; }
/* Fokus di TV harus terbaca dari sofa: tebal, terang, dan kartunya ikut membesar. */
html.tv .kartu:focus { outline: 4px solid var(--putih); outline-offset: 4px; transform: scale(1.09); }
html.tv a:focus, html.tv button:focus, html.tv .nav-menu a:focus { outline: 3px solid var(--putih); outline-offset: 4px; opacity: 1; }
html.tv .geser-panah { width: 74px; font-size: 42px; }

/* Layar musik di TV: tombol 40px yang pas untuk ibu jari di HP menjadi titik kecil dari sofa.
   Foto layar TV jhony (19 Sep) menunjukkan kontrol seukuran HP mengambang di ruang kosong. */
html.tv .musik-kbtn { width: 64px; height: 64px; font-size: 30px; }
html.tv .musik-kbtn .ikon { width: 30px; height: 30px; }
html.tv .musik-kbtn.besar { width: 86px; height: 86px; font-size: 32px; }
html.tv .musik-kontrol { gap: 30px; }
html.tv .musik-judul strong { font-size: 27px; }
html.tv .musik-judul span { font-size: 19px; }
html.tv .musik-seek { height: 7px; }
html.tv .musik-seek::-webkit-slider-thumb { width: 20px; height: 20px; }
html.tv .musik-seek::-moz-range-thumb { width: 20px; height: 20px; }
html.tv .musik-waktu { font-size: 18px; }
html.tv .musik-tab-btn { font-size: 19px; padding: 10px 18px; }
html.tv .musik-lirik.sinkron .lirik-baris { font-size: 25px; }
html.tv .musik-daftar { font-size: 19px; }
html.tv .saklar-label { font-size: 18px; }
html.tv .musik-unduh, html.tv .musik-vol { width: 56px; height: 56px; font-size: 13px; }
html.tv .musik-unduh .ikon, html.tv .musik-vol .ikon { width: 28px; height: 28px; }
html.tv .musik-tutup { width: 56px; height: 56px; font-size: 30px; }
/* Fokus remote di layar musik: tombolnya bulat, jadi penandanya ikut bulat. */
html.tv .musik-kbtn:focus, html.tv .musik-tab-btn:focus, html.tv .musik-unduh:focus, html.tv .musik-vol:focus, html.tv .musik-tutup:focus, html.tv .saklar:focus {
  outline: 4px solid var(--putih); outline-offset: 4px; opacity: 1;
}
/* Kolom kiri layar musik dipatok maksimal 360px (dibuat untuk laptop). Di TV, tombol yang sudah
   diperbesar TIDAK muat di sana lalu MENYUSUT diam-diam oleh flex-shrink — terukur 59px padahal
   CSS meminta 86px. Jadi kolomnya dilebarkan DAN tombolnya dilarang menyusut. */
html.tv .layar-musik { grid-template-columns: minmax(420px, 560px) minmax(0, 900px); gap: 14px 64px; }
html.tv .musik-kbtn { flex: 0 0 auto; }

/* Now Playing di TV: tata letaknya dibuat untuk laptop — sampul dipatok 360px, panel lirik 640px.
   Di layar 1920 itu menyisakan ~458px kosong di kanan dan celah tegak di kolom kiri (diukur
   19 Sep 2026, cocok dengan foto layar TV jhony). Di TV pematok itu dilepas dan panel dibiarkan
   mengisi sisa layar. */
html.tv .layar-musik { grid-template-columns: minmax(480px, 620px) minmax(0, 1fr); padding: 3.5vh 4vw; }
html.tv .layar-musik .musik-atas { max-width: none; }
html.tv .musik-cover { width: min(100%, 52vh); }
html.tv .musik-judul { max-width: none; }
html.tv .layar-musik .musik-panel { max-width: none; }
html.tv .layar-musik .musik-lirik { max-width: none; }
html.tv .musik-daftar { max-width: none; }

/* Setelan TV putaran kedua, dari foto layar TV jhony (19 Sep): sampul kalah besar dari lirik,
   kolom kiri terbelah celah 71px, lirik menempel ke atas panel, dan judul lagu nyaris seukuran
   baris lirik sehingga tak terbaca sebagai judul. */
/* 62vh membuat seluruh isi kolom kiri meluber ~25px keluar dari jarak aman tepi — di TV itu
   justru bagian yang bisa terpotong overscan. 56vh: sampul tetap besar, isi tetap di dalam. */
html.tv .musik-cover { width: min(100%, 56vh); }
html.tv .musik-judul strong { font-size: 40px; line-height: 1.15; }
html.tv .musik-judul span { font-size: 22px; }
/* Baris atas tak lagi 1fr: kolom kiri jadi SATU blok rapat, lalu seluruh grid dipusatkan. */
html.tv .layar-musik { grid-template-rows: auto auto auto auto; }
html.tv .layar-musik .musik-atas { align-self: end; }
html.tv .layar-musik .musik-kontrol { margin-top: 14px; }
/* Lirik tersinkron: baris aktif ditahan di TENGAH panel (musik-putar.js sudah scrollIntoView
   block:'center'), tapi baris pertama & terakhir tak bisa sampai ke tengah tanpa ruang napas
   di atas dan di bawahnya. */
html.tv .musik-lirik.sinkron { padding-block: 32vh; }

/* Putaran ketiga dari foto TV jhony: teks lirik & daftar lagu masih kecil dari sofa, dan batang
   gulir panel tergambar sebagai garis terang yang mengganggu. Tombol putar besar memakai ikon
   SVG gelap di atas lingkaran putih. */
html.tv .musik-lirik.sinkron .lirik-baris { font-size: 32px; margin: 14px 0; }
html.tv .lirik-baris { font-size: 26px; margin: 14px 0; }
html.tv .musik-daftar .jdl { font-size: 24px; }
html.tv .musik-daftar .no { font-size: 18px; min-width: 32px; }
html.tv .musik-daftar .art { font-size: 18px; }
html.tv .musik-daftar li { padding: 12px 14px; }
html.tv .musik-tab-btn { font-size: 21px; }
html.tv .musik-lirik, html.tv .musik-daftar { scrollbar-width: none; -ms-overflow-style: none; }
html.tv .musik-lirik::-webkit-scrollbar, html.tv .musik-daftar::-webkit-scrollbar { width: 0; height: 0; display: none; }
html.tv .musik-kbtn.besar .ikon { width: 36px; height: 36px; }
/* Ikon SVG di dalam tombol teks & mini-player (menggantikan karakter ▶ ⏭ yang dirender TV
   sebagai emoji kuning). Tombol .tombol sudah inline-flex dengan gap, jadi tak perlu spasi. */
.tombol .ikon { width: 17px; height: 17px; fill: currentColor; flex: 0 0 auto; }
.mini-tombol .ikon { width: 19px; height: 19px; fill: currentColor; }
html.tv .tombol .ikon { width: 22px; height: 22px; }

/* ---------------- Halaman detail (film/serial) di TV ----------------
   Dibuat 19 Sep 2026 sesudah jhony melihatnya di TV: "daftar episode masih tampilan hp".
   Diukur di 1920×1080 mode TV — kotaknya 860px (45% layar), gambar episode 140×79, judul
   episode 19px, durasi 13px. Itu angka yang dipilih untuk layar HP genggam, bukan untuk
   orang yang duduk 3 meter dari layar. Di TV kotaknya dibuat selebar layar, gambar episode
   ikut besar, dan tiap baris jadi target fokus yang kelihatan dari sofa. */
html.tv .detail { padding: 0; }
html.tv .detail-kotak { max-width: none; border-radius: 0; min-height: 100dvh; }
/* Backdrop di TV: dua kemauan yang saling tarik. Kalau tingginya dipatok ke bagian layar dan
   gambarnya di-`cover` (percobaan pertama, 20 Sep), yang tampak cuma 31% tinggi gambar — jhony
   melihatnya langsung: "backdrop/poster di atas jadi kepotong". Kalau rasionya dibiarkan 16/9
   selebar 1920, tingginya 1080px: satu gambar menghabiskan seluruh layar TV dan daftar episode
   tak kebagian tempat.
   Jalan keluarnya cara pemutar media di TV: gambar UTUH (`contain`) di tengah, dan sisa ruang
   kiri-kanan diisi salinan gambar yang sama dalam keadaan kabur — jadi layar tetap penuh tanpa
   satu piksel pun dipotong. Backdrop nyata di pustaka ini 1,78–2,35 rasio, keduanya muat.
   `padding-bottom` menyediakan pita kabur di bawah gambar, tempat judul & tombol menumpang
   (.detail-isi punya margin-top negatif) tanpa menutupi gambarnya. */
/* `isolation: isolate` WAJIB: tanpa konteks tumpukan sendiri, `z-index` pada ::after ikut
   dihitung di konteks induk dan gradiennya menimpa judul & tombol di bawahnya (terlihat di
   potret 20 Sep: "Uji Serial" nyaris tak terbaca). */
html.tv .detail-gambar { aspect-ratio: auto; height: 46vh; box-sizing: border-box; padding-bottom: 76px; overflow: hidden; isolation: isolate; background-size: cover; background-position: center; background-repeat: no-repeat; }
html.tv .detail-gambar::before { content: ""; position: absolute; inset: 0; background-image: inherit; background-size: cover; background-position: center; filter: blur(34px) brightness(.45); transform: scale(1.12); }
html.tv .detail-gambar img { object-fit: contain; position: relative; z-index: 1; }
/* Gradien penyatu harus tetap paling depan — gambar tajam kini punya z-index sendiri. */
html.tv .detail-gambar::after { z-index: 2; background: linear-gradient(to top, var(--hitam-2) 6%, transparent 46%); }
/* Sinopsis panjang (TMDB kadang 6-7 baris) mendorong daftar episode keluar layar. Di TV ia
   dipotong 3 baris: yang dicari orang di halaman ini daftar episodenya, bukan ringkasannya. */
html.tv .detail-sinopsis { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
html.tv .detail-isi { padding: 0 5vw 6vh; margin-top: -72px; }
html.tv .detail-isi h2 { font-size: clamp(40px, 3.6vw, 64px); margin-bottom: 12px; }
html.tv .detail-meta { font-size: 20px; gap: 10px 20px; margin-bottom: 22px; }
html.tv .detail-meta .kotak { font-size: 15px; padding: 1px 8px; }
html.tv .detail-meta .kotak-hapus { font-size: 17px; padding: 2px 10px; }
html.tv .detail-sinopsis { font-size: 21px; max-width: 62ch; margin-bottom: 22px; }
html.tv .detail-berkas { font-size: 15px; }
html.tv .detail-tombol { gap: 16px; }
html.tv .tutup { width: 56px; height: 56px; font-size: 34px; top: 24px; right: 24px; }
html.tv .pilih-season { margin: 26px 0 12px; font-size: 22px; }
html.tv .pilih-season select { font-size: 21px; padding: 10px 18px; }
/* Lebar gambar dipatok, bukan dibiarkan ikut layar: di 1920 sebuah kolom 20vw membuat tiap baris
   setinggi 253px — hanya SATU baris muat di bawah backdrop, dan daftarnya tak lagi terlihat
   sebagai daftar. 300px (169px tinggi) menyisakan dua baris terlihat + potongan baris ketiga,
   yang adalah cara daftar memberi tahu "masih ada di bawah". */
html.tv .daftar-episode { max-width: 1500px; }
html.tv .episode { grid-template-columns: 56px clamp(220px, 15vw, 300px) 1fr; gap: 24px; padding: 14px 18px; border-radius: 10px; }
html.tv .episode .nomor { font-size: 30px; }
html.tv .episode .judul { font-size: 26px; }
html.tv .episode .durasi { font-size: 19px; margin-top: 6px; }
html.tv .episode .putar-ep { width: 64px; height: 64px; }
html.tv .episode .putar-ep svg { width: 26px; height: 26px; }
html.tv .ep-unduh { margin-top: 12px; gap: 14px; }
html.tv .ep-unduh .tombol-teks.kecil { font-size: 16px; padding: 7px 16px; }
html.tv .ep-unduh-status { font-size: 17px; }
html.tv .detail-pemeran h3 { font-size: 19px; }
html.tv .detail-pemeran li { flex: 0 0 128px; }
html.tv .detail-pemeran img, html.tv .detail-pemeran .tanpa-wajah { width: 108px; height: 108px; font-size: 34px; }
html.tv .detail-pemeran .nama { font-size: 18px; }
html.tv .detail-pemeran .peran { font-size: 16px; }
/* Jebakan yang sama seperti media query 520px di atas: `.episode-unduhan` (0,1,0) kalah dari
   `html.tv .episode` (0,2,1), jadi kolom "Hapus"-nya HARUS dituliskan ulang untuk TV. */
html.tv .episode-unduhan { grid-template-columns: 56px clamp(220px, 15vw, 300px) 1fr auto; }
/* Barisnya sendiri kini bisa difokus remote (tabindex dipasang app.js) — penandanya harus
   sekuat kartu beranda, karena inilah satu-satunya petunjuk "di mana saya" di TV. */
.episode:focus-visible { outline: 2px solid var(--putih); outline-offset: -2px; }
html.tv .episode:focus { outline: 4px solid var(--putih); outline-offset: -2px; background: #3a3a3a; }
/* Baris yang mendarat PERSIS di tepi bawah layar (scrollIntoView 'nearest' berhenti begitu ia
   muat) rawan terpotong overscan TV — terukur bottom 937 dari layar 937. scroll-margin memberi
   jarak aman tanpa mengubah tata letaknya. */
html.tv .episode, html.tv .detail-tombol button, html.tv .pilih-season select { scroll-margin: 90px; }
/* Batang gulir peramban TV lebar dan selalu terlihat; di sini ia cuma hiasan — yang menggulir
   halaman ini tombol arah remote, bukan tetikus. (Sama seperti panel lirik di layar musik.) */
html.tv .detail { scrollbar-width: none; -ms-overflow-style: none; }
html.tv .detail::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* ---------- Rentang warna video di TV ----------
   20 Sep 2026: jhony melaporkan video di TV "terlalu cerah". Diukur: berkasnya bt709 rentang
   terbatas (hitam disimpan sebagai 16, bukan 0) dan keluaran server menandainya dengan benar
   di kedua jalur encode — tapi TV-nya TIDAK meregangkan 16-235 ke 0-255, jadi hitam tampil
   abu. Dibuktikan lewat /uji-warna.html: dari tiga video berisi pola yang sama, yang terlihat
   benar di TV-nya justru yang pikselnya sudah teregang.
   Peregangan dilakukan di sini, bukan dengan meng-encode ulang: encode ulang memaksa transcode
   untuk SEMUA berkas yang sebenarnya bisa diputar langsung. */
#pilihWarna { display: none; }
html.tv #pilihWarna { display: inline-block; }
.pemutar video.rentang-penuh { filter: url(#lrRentangPenuh); }

/* ---------------- Halaman musik (playlist/album/artis) di TV ----------------
   20 Sep 2026, keluhan ketiga dengan sebab yang sama: "kalau kita klik playlist, halamannya
   masih tampilan hp". Halaman ini memang tak pernah punya aturan TV — sampul 160px, judul
   24px, baris lagu 13-16px. Dan seperti daftar episode, <li> baris lagunya tak bisa difokus,
   jadi remote tak punya jalan ke lagu yang tak kebetulan terlihat. */
html.tv .grid-detail { padding: 0 var(--gutter) 6vh; }
html.tv .kembali-musik { font-size: 19px; padding: 10px 22px; }
html.tv .detail-judul-musik { font-size: clamp(34px, 3vw, 54px); margin: 14px 0; }
html.tv .kepala-detail-musik { gap: 36px; margin: 18px 0 28px; }
html.tv .kepala-cover, html.tv .playlist-mozaik.kepala-cover { width: clamp(180px, 17vw, 300px); height: clamp(180px, 17vw, 300px); }
html.tv .kepala-info { gap: 14px; }
html.tv .kepala-info .kartu-sub { font-size: 21px; }
html.tv .daftar-lagu { max-width: 1500px; }
html.tv .baris-lagu { padding: 15px 18px; gap: 22px; border-radius: 10px; }
html.tv .lagu-no { font-size: 22px; width: 46px; }
html.tv .lagu-judul { font-size: 25px; }
html.tv .lagu-sub { font-size: 18px; margin-top: 4px; }
html.tv .lagu-durasi { font-size: 19px; }
html.tv .lagu-menu { font-size: 28px; padding: 0 14px; }
html.tv .lagu-unduh { width: 22px; height: 22px; }
html.tv .lagu-unduh.terunduh::before { font-size: 21px; }
/* Penanda fokus sekuat kartu beranda — di TV inilah satu-satunya petunjuk "di mana saya". */
.baris-lagu:focus-visible { outline: 2px solid var(--putih); outline-offset: -2px; }
html.tv .baris-lagu:focus { outline: 4px solid var(--putih); outline-offset: -2px; background: #3a3a3a; }
html.tv .baris-lagu, html.tv .kepala-aksi button, html.tv .kembali-musik { scroll-margin: 90px; }

/* ---------- Koleksi Kamu ---------- */
/* Tombol + melayang di pojok kartu. Kartunya sendiri <button>, jadi tombol ini SAUDARA-nya di
   dalam pembungkus — bukan anaknya (tombol di dalam tombol tak sah, dan di TV fokus remote jadi
   kacau). Pembungkusnya mewarisi lebar kartu supaya baris geser tak berubah tata letaknya. */
.kartu-bungkus { position: relative; flex: 0 0 auto; width: clamp(110px, 15vw, 200px); scroll-snap-align: start; }
.kartu-bungkus > .kartu { width: 100%; }
.kbtn-koleksi.kbtn-kartu { position: absolute; top: 6px; right: 6px; width: 32px; height: 32px; flex: 0 0 32px;
  background: rgba(0,0,0,.62); backdrop-filter: blur(2px); border-color: rgba(255,255,255,.55); }
.kbtn-koleksi.kbtn-kartu .ikon { width: 18px; height: 18px; }
.kbtn-koleksi.tersimpan { color: var(--merah); border-color: var(--merah); }
/* Keadaan "tersimpan" tak boleh disembunyikan sorotan: hover/fokus cuma menambah latar, warnanya
   tetap merah. Tanpa aturan ini, `.kbtn-bulat:hover` (kespesifikan lebih tinggi) menang dan tanda
   tersimpannya lenyap justru di detik orang menekannya. */
.kbtn-koleksi.tersimpan:hover:not(:disabled), .kbtn-koleksi.tersimpan:focus-visible {
  color: var(--merah); border-color: var(--merah); background: rgba(229,9,20,.14); }
.kbtn-koleksi.kbtn-lagu { width: 32px; height: 32px; flex: 0 0 32px; border: 0; color: #9a9a9a; }
.kbtn-koleksi.kbtn-lagu .ikon { width: 20px; height: 20px; }
.kbtn-koleksi.kbtn-lagu.tersimpan, .kbtn-koleksi.kbtn-lagu.tersimpan:hover:not(:disabled),
.kbtn-koleksi.kbtn-lagu.tersimpan:focus-visible { color: var(--merah); }
/* Di dalam grid (halaman Koleksi Kamu) kartu mengisi kolomnya, jadi pembungkusnya ikut melebar. */
.grid > .kartu-bungkus { width: auto; }
/* TV: + pada KARTU disembunyikan. Remote bergerak antar kartu (kiri/kanan) dan antar baris
   (atas/bawah) — tak ada arah tersisa untuk menjangkau tombol di pojok kartu, dan tombol yang
   terlihat tapi tak bisa dicapai lebih buruk daripada yang tak ditampilkan. Di TV, menyimpan
   dilakukan dari halaman album/artis/playlist-nya, yang tombolnya memang terjangkau. */
html.tv .kbtn-koleksi.kbtn-kartu { display: none; }
html.tv .kbtn-koleksi.kbtn-lagu { width: 46px; height: 46px; flex: 0 0 46px; }
/* Halaman playlist/album di TV (jhony 27 Sep 2026: "cek juga di halaman playlist, apakah masih kurang besar").
   Diukur di TV LG 1920: label merek 14px, sub-judul lagu 18px, durasi/info/Kembali 19px, ikon 20-22px,
   sampul 280px (Now Playing 525px). Dibaca dari sofa → semua dinaikkan; kelasnya dipakai album & artis juga. */
html.tv .pl-sampul.besar { width: 400px; }
html.tv .pl-sampul.besar .pl-sampul-judul { font-size: 44px; left: 22px; right: 22px; bottom: 20px; }
html.tv .pl-sampul.besar .pl-sampul-lambang .lr-lambang { width: 38px; height: 38px; }
html.tv .radio-merek { font-size: 21px; gap: 10px; }
html.tv .radio-merek svg { width: 30px; height: 30px; }
html.tv .kepala-plist-isi .kartu-sub { font-size: 24px; }
html.tv .kepala-aksi { gap: 16px; }
html.tv .kepala-aksi .kbtn-bulat { width: 72px; height: 72px; flex: 0 0 72px; }
html.tv .kepala-aksi .putar-bulat { width: 84px; height: 84px; flex: 0 0 84px; }
html.tv .kepala-aksi .kbtn-bulat .ikon { width: 30px; height: 30px; }
html.tv .kepala-aksi .putar-bulat .ikon { width: 40px; height: 40px; }
html.tv .kembali-musik { font-size: 23px; padding: 12px 26px; }
html.tv .lagu-no { font-size: 24px; }
html.tv .lagu-judul { font-size: 28px; }
html.tv .lagu-sub { font-size: 22px; }
html.tv .lagu-durasi { font-size: 22px; }
html.tv .lagu-menu { font-size: 44px; font-weight: 700; }
html.tv .kbtn-koleksi.kbtn-lagu { width: 54px; height: 54px; flex: 0 0 54px; }
html.tv .kbtn-koleksi.kbtn-lagu .ikon { width: 28px; height: 28px; }
html.tv .kartu-bungkus { width: clamp(220px, 16vw, 330px); }

/* Pita pendaftar (admin, 23 Sep 2026): di bawah nav; pita versi/APK ada di bawah layar, jadi tak bertabrakan */
.pita-pendaftar { position: fixed; top: calc(var(--nav-h, 60px) + 8px); left: 50%; transform: translateX(-50%); z-index: 30;
  width: min(560px, calc(100vw - 32px)); display: flex; align-items: center; gap: 10px; padding: 10px 12px 10px 16px;
  background: #1f1f1f; border: 1px solid var(--merah); border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,.6); color: var(--putih); font-size: 14px; }
.pita-pendaftar > span { flex: 1; }
.pita-pendaftar .tombol { padding: 8px 16px; font-size: 14px; }
.pita-pendaftar[hidden] { display: none; }
#pendaftarAkun.ada-pendaftar, #menuAkun.ada-pendaftar { color: var(--merah-teks); font-weight: 700; }

/* ---- Rekomendasi ala Netflix (25 Sep 2026) ---- */
/* Top 10: angka besar berbingkai di KIRI poster (tak menutupi gambar) */
.kartu.kartu-top { width: calc(clamp(110px, 15vw, 200px) + clamp(40px, 5vw, 70px)); padding-left: clamp(40px, 5vw, 70px); }
.kartu .angka-top { position: absolute; left: 0; bottom: 34px; font-size: clamp(64px, 9vw, 128px); font-weight: 900; line-height: .78; letter-spacing: -4px;
  color: var(--hitam, #141414); -webkit-text-stroke: 2px #e5e5e5; paint-order: stroke; pointer-events: none; }
.detail-mirip { margin: 26px 0 0; }
.detail-mirip h3 { font-size: 15px; color: #bbb; font-weight: 600; margin: 0 0 10px; text-transform: uppercase; letter-spacing: 0.6px; }
.detail-mirip .grid { padding: 0; grid-template-columns: repeat(auto-fill, minmax(clamp(100px, 13vw, 150px), 1fr)); }
/* html.tv .kartu memaksa 220–330px (baris geser TV); di grid ini kartu harus ikut lebar KOLOM, atau di TV
   kartu 307px dijejalkan ke kolom 150px dan saling menimpa / melebarkan halaman detail. */
.detail-mirip .grid .kartu { width: auto; }
.trailer { position: fixed; inset: 0; z-index: 40; background: rgba(0,0,0,.92); display: grid; place-items: center; padding: 56px 12px 12px; }
.trailer[hidden] { display: none; }
.trailer-bingkai { width: min(100%, calc((100dvh - 80px) * 16 / 9)); aspect-ratio: 16/9; background: #000; }
.trailer-bingkai iframe { width: 100%; height: 100%; border: 0; display: block; }

/* Jempol suka / bukan buat saya (25 Sep 2026): tombol bulat ikon saja; menyala = putih penuh */
.tombol-jempol { padding: 10px; width: 44px; height: 44px; justify-content: center; }
.tombol-jempol .ikon { width: 20px; height: 20px; }
.tombol-jempol[aria-pressed="true"] { background: var(--putih); color: #111; }
html.tv .tombol-jempol { width: 64px; height: 64px; }
html.tv .tombol-jempol .ikon { width: 28px; height: 28px; }
.kelompok-jempol { display: inline-flex; gap: inherit; }
.kelompok-jempol:not(:has(button:not([hidden]))) { display: none; }

/* Pratinjau otomatis di hero (25 Sep 2026): iframe YouTube menutupi hero seperti object-fit: cover.
   Ukuran dari unit kontainer; perambat tanpa cq (TV lama) jatuh ke 100%/100% = berbingkai, tetap aman.
   Gambar hero tetap di depan sampai .tampak (YouTube sempat mulai). Gradasi ::after tetap di atas. */
.hero-gambar { container-type: size; }
.hero-pratinjau { position: absolute; top: 50%; left: 50%; width: 100%; height: 100%; width: max(100cqw, 177.78cqh); height: max(100cqh, 56.25cqw);
  transform: translate(-50%, -50%) scale(1.3); border: 0; pointer-events: none; opacity: 0; transition: opacity .8s; } /* 1.3: potong pita hitam trailer layar lebar (2,39:1 di bingkai 16:9) + teks YouTube di tepi bawah */
.hero-pratinjau.tampak { opacity: 1; }
.hero-gambar img { transition: opacity .8s; }
.hero-gambar:has(.hero-pratinjau.tampak) img { opacity: 0; }
.hero-suara { position: absolute; right: var(--gutter); bottom: clamp(24px, 6vw, 72px); width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,.7); background: rgba(20,20,20,.45); color: var(--putih); display: flex; align-items: center; justify-content: center; padding: 0; z-index: 1; }
.hero-suara .ikon { width: 22px; height: 22px; fill: currentColor; }
.hero-suara[hidden] { display: none; }
@media (hover: hover) { .hero-suara:hover { background: rgba(60,60,60,.7); } }
html.tv .hero-suara { width: 64px; height: 64px; }
html.tv .hero-suara .ikon { width: 32px; height: 32px; }

/* Pengaturan tontonan (25 Sep 2026): panel kecepatan + gaya subtitle. Gaya subtitle = kelas di #layarPutar
   (::cue tak bisa membaca variabel CSS di semua perambat). Tersimpan per perangkat (localStorage gayaSub). */
.atur-putar svg { width: 22px; height: 22px; fill: currentColor; }
#dengarPutar[hidden] { display: none; }
/* ⏮ ⏭ di tengah video (6 Okt 2026): kiri & kanan, ruang tengah dibiarkan untuk tombol putar bawaan peramban */
.urutan-putar { position: absolute; inset: 0; pointer-events: none; transition: opacity .3s; }
.tombol-urutan { position: absolute; top: 50%; transform: translateY(-50%); width: 56px; height: 56px; border: 0; border-radius: 50%; background: rgba(0,0,0,.45); color: #fff; display: grid; place-items: center; cursor: pointer; pointer-events: auto; }
.tombol-urutan:hover, .tombol-urutan:focus-visible { background: rgba(0,0,0,.7); outline: 2px solid rgba(255,255,255,.6); outline-offset: 2px; }
.tombol-urutan svg { width: 30px; height: 30px; fill: currentColor; }
#sebelumPutar { left: 12%; } #berikutPutar { right: 12%; }
.tombol-urutan[hidden] { display: none; }
.pemutar.sembunyi .urutan-putar { opacity: 0; }
.pemutar.sembunyi .tombol-urutan { pointer-events: none; }
.panel-putar { position: absolute; top: calc(56px + env(safe-area-inset-top, 0px)); right: 12px; z-index: 6; display: grid; gap: 10px; min-width: 220px;
  background: rgba(20,20,20,.95); border: 1px solid #4a4a4a; border-radius: 8px; padding: 14px 16px; box-shadow: 0 6px 24px rgba(0,0,0,.6); }
.panel-putar[hidden] { display: none; }
.panel-putar label { display: grid; gap: 4px; font-size: 13px; color: #ccc; }
.panel-putar select { font-size: 15px; padding: 8px; background: #222; color: var(--putih); border: 1px solid #555; border-radius: 4px; }
.pemutar.sembunyi .panel-putar { display: none; }
html.tv .panel-putar { min-width: 340px; top: 96px; }
html.tv .panel-putar label { font-size: 20px; }
html.tv .panel-putar select { font-size: 22px; padding: 10px; }
#layarPutar.sub-kecil video::cue { font-size: clamp(13px, 2vw, 22px); }
#layarPutar.sub-besar video::cue { font-size: clamp(20px, 3.6vw, 42px); }
#layarPutar.sub-raksasa video::cue { font-size: clamp(24px, 4.8vw, 56px); }
/* TV (jhony 27 Sep 2026: "subtitle di tv kurang besar"): batas px di atas dibuat untuk laptop — di 1920×1080
   "Sedang" mentok 30px = 2,8% tinggi layar, dibaca dari sofa. Di TV ukurannya ikut TINGGI layar. */
html.tv #layarPutar video::cue { font-size: 4.8vh; }
html.tv #layarPutar.sub-kecil video::cue { font-size: 3.8vh; }
html.tv #layarPutar.sub-besar video::cue { font-size: 6vh; }
html.tv #layarPutar.sub-raksasa video::cue { font-size: 7.6vh; }
#layarPutar.sub-pekat video::cue { background: rgba(0,0,0,.92); }
#layarPutar.sub-tanpa video::cue { background: transparent; text-shadow: 0 0 3px #000, 0 0 3px #000, 1px 1px 2px #000, -1px -1px 2px #000; }

/* YouTube langsung (app.js gambarKartuYouTube, 2 Okt 2026): tautan YouTube di kotak cari → satu kartu putar */
.yt-kartu { display: flex; gap: 18px; align-items: flex-start; padding: 6px var(--gutter) 14px; max-width: calc(900px + 2 * var(--gutter)); }
.yt-gambar { position: relative; flex: 0 0 auto; width: min(420px, 46%); aspect-ratio: 16 / 9; border-radius: 6px; overflow: hidden; background: var(--abu); cursor: pointer; }
.yt-gambar img { width: 100%; height: 100%; object-fit: cover; }
.yt-durasi { position: absolute; right: 6px; bottom: 6px; background: rgba(0,0,0,.8); padding: 1px 6px; border-radius: 4px; font-size: 13px; font-weight: 600; }
.yt-teks { display: flex; flex-direction: column; gap: 6px; min-width: 0; align-items: flex-start; }
.yt-judul { font-size: 18px; font-weight: 700; overflow-wrap: anywhere; }
.yt-kanal { color: var(--abu-2); font-size: 14px; margin-bottom: 8px; }
.yt-memuat { color: var(--abu-2); padding: 18px 0; }
@media (max-width: 620px) {
  .yt-kartu { flex-direction: column; gap: 10px; }
  .yt-gambar { width: 100%; }
}

/* Video Musik (app.js gambarVideoMusik, 2 Okt 2026): kotak cari/tempel tautan di atas, kartu 16:9 per playlist */
.vm-atas { padding: 16px var(--gutter) 6px; /* ruang nav datang dari #hero[hidden] + .baris-semua */ display: flex; flex-direction: column; gap: 10px; max-width: calc(820px + 2 * var(--gutter)); }
.vm-baris-cari { display: flex; gap: 10px; align-items: center; }
.vm-cari { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px; background: var(--hitam-2); border: 1px solid #555; border-radius: 999px; padding: 0 14px; color: var(--abu-2); }
.vm-cari:focus-within { border-color: var(--putih); color: var(--putih); }
.vm-cari input { flex: 1 1 auto; min-width: 0; background: transparent; border: 0; outline: 0; color: var(--putih); font: inherit; font-size: 16px; padding: 11px 0; }
.vm-tambah { flex: 0 0 auto; padding: 9px 18px; }
.vm-pesan { color: #d6d6d6; font-size: 14px; }
.vm-pesan.galat { color: #ff8a8a; }
.vm-kosong { color: var(--abu-2); padding: 12px var(--gutter); }
.vm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(clamp(150px, 22vw, 300px), 1fr)); gap: 18px 12px; padding: 4px var(--gutter) 18px; }
.vm-kartu { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.vm-gambar { position: relative; width: 100%; aspect-ratio: 16 / 9; border: 0; padding: 0; border-radius: 6px; overflow: hidden; background: var(--abu); }
.vm-gambar img { width: 100%; height: 100%; object-fit: cover; }
.vm-durasi { position: absolute; right: 5px; bottom: 6px; background: rgba(0,0,0,.8); color: var(--putih); padding: 1px 6px; border-radius: 4px; font-size: 12px; font-weight: 600; }
.vm-progres { position: absolute; left: 0; right: 0; bottom: 0; margin: 0; border-radius: 0; }
.vm-judul { font-size: 14px; font-weight: 600; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.vm-kanal { color: var(--abu-2); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vm-aksi { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.vm-status { font-size: 12px; color: #d6d6d6; display: flex; flex-direction: column; gap: 4px; }
.vm-status .progres { margin: 0; }
@media (max-width: 620px) {
  .vm-atas { padding-top: 8px; }
  .vm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 10px; }
}
.vm-aksi .tombol-teks, .vm-kepala .tombol-teks { padding: 4px 12px; font-size: 12px; }

/* Sakelar Lagu | Video di atas tab Musik (ala YouTube Music) */
.sakelar-musik { display: flex; gap: 8px; padding: 12px var(--gutter) 2px; }
.sakelar-musik .chip { border: 1px solid #555; background: rgba(255,255,255,.08); color: var(--putih); border-radius: 8px; padding: 7px 16px; font-size: 14px; font-weight: 600; }
.sakelar-musik .chip.aktif { background: var(--putih); color: #000; border-color: var(--putih); }
.sakelar-musik + .vm-atas { padding-top: 10px; }
html.tv .sakelar-musik .chip { font-size: 22px; padding: 10px 26px; }
.vm-aksi .tombol-teks, .vm-kepala .tombol-teks { display: inline-flex; align-items: center; gap: 4px; }
.vm-aksi .ikon, .vm-kepala .ikon { width: 14px; height: 14px; fill: currentColor; flex: 0 0 auto; }
.vm-tambah .ikon, .yt-kartu .ikon { width: 18px; height: 18px; fill: currentColor; }
html.tv .vm-aksi .ikon, html.tv .vm-kepala .ikon { width: 20px; height: 20px; }
@media (max-width: 620px) { /* HP: nama playlist utuh di barisnya sendiri, tombol di bawahnya */
}

/* Now Playing: Lagu | Video untuk suara Video Musik (musik-putar.js #musikKeVideo) */
.musik-mode { position: absolute; z-index: 2; top: calc(env(safe-area-inset-top,0px) + 12px); left: 50%; transform: translateX(-50%); padding: 0; }
.musik-mode .chip { background: rgba(0,0,0,.45); padding: 6px 16px; } /* duduk SEBARIS tombol tutup: tak menambah tinggi tata letak HP */
.musik-mode .chip.aktif { background: var(--putih); }

/* kartu playlist Video Musik (satu kartu per playlist, seperti halaman Musik) */
.vm-kembali { margin: 4px var(--gutter) 6px; }

/* Video di bingkai sampul Now Playing (musik-putar.js aturVideoNp) — ukuran = sampul */
.musik-video-bingkai { position: relative; width: min(100%, 52vh); aspect-ratio: 1; border-radius: 10px; overflow: hidden; background: #000; box-shadow: 0 14px 50px rgba(0,0,0,.6); }
.musik-video-bingkai video { width: 100%; height: 100%; object-fit: contain; display: block; }
.musik-cover.diganti-video { display: none; }
.musik-video-penuh { position: absolute; right: 8px; bottom: 8px; width: 40px; height: 40px; border: 0; border-radius: 50%; background: rgba(0,0,0,.6); color: var(--putih); display: grid; place-items: center; cursor: pointer; }
.musik-video-penuh .ikon { width: 22px; height: 22px; fill: currentColor; }
html:not(.tv) .layar-musik.np-panel .musik-video-bingkai { grid-area: sampul; width: 96px; border-radius: 8px; box-shadow: 0 4px 14px rgba(0,0,0,.5); }
html:not(.tv) .layar-musik.np-panel .musik-video-penuh { display: none; }
html:not(.tv) .layar-musik.np-panel .musik-mode { display: none; } /* mode daftar/lirik: sakelar menimpa judul; ganti di tampilan besar */
html:not(.tv) .layar-musik.np-panel .musik-video-bingkai { cursor: pointer; }
/* baris Video (video tanpa playlist) di halaman Video Musik: kartu 16:9 geser, seperti baris di halaman Musik */
.vm-kartu-geser { width: clamp(200px, 30vw, 320px); }
.vm-kartu-geser .vm-gambar img { aspect-ratio: auto; height: 100%; border-radius: 0; }
.vm-kartu-geser .kartu-judul { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; white-space: normal; }

/* kepala playlist Video Musik: judul, lalu SATU baris tombol (jhony: "susun tombolnya yang rapi") */
.vm-kepala { display: block; padding: 0 var(--gutter); }
.vm-kepala h3 { margin: 0 0 10px; white-space: normal; }
.vm-tombol { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; margin-bottom: 12px; }
.vm-tombol .tombol { padding: 8px 16px; font-size: 14px; gap: 6px; white-space: nowrap; }
.vm-tombol .tombol .ikon, .vm-ikon .ikon { width: 18px; height: 18px; fill: currentColor; }
/* ikon saja (jhony 16 Okt 2026 "pakai logo aja … biar gak melebar"): bulat, sama besar */
.vm-tombol .tombol.ikon-saja { width: 44px; height: 44px; padding: 0; border-radius: 50%; justify-content: center; gap: 0; flex: 0 0 auto; }
.vm-tombol .tombol.ikon-saja .ikon { width: 20px; height: 20px; }
.vm-tombol .vm-unduh-semua.terunduh { color: #46d369; }
.vm-tombol .vm-unduh-semua.berjalan:disabled { opacity: 1; }
.vm-ikon { flex: 0 0 auto; width: 36px; height: 36px; display: grid; place-items: center; border: 0; border-radius: 50%; background: rgba(255,255,255,.09); color: #d6d6d6; cursor: pointer; }
.vm-ikon:hover { background: rgba(255,255,255,.16); color: var(--putih); }
.vm-hapus-pl { margin-left: auto; }
.vm-aksi { flex-wrap: nowrap; align-items: center; }
.vm-aksi .vm-unduh { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Tombol unduh per kartu = IKON SAJA (jhony 16 Okt: "biar gak melebarkan"): ⤓ / ✓ hijau / lingkaran merah berputar
   seperti .lagu-unduh di daftar lagu. Teks dari kelolaUnduh tetap ada (font-size 0) untuk pembaca layar; keadaan dibaca
   dari kelas .terunduh dan :disabled (kelolaUnduh mematikan tombol selama mengunduh/memproses). */
.vm-aksi .vm-unduh { flex: 0 0 auto; width: 36px; height: 36px; padding: 0; border: 0; border-radius: 50%; display: grid; place-items: center;
  background: rgba(255,255,255,.09); color: #d6d6d6; font-size: 0; line-height: 0; gap: 0; display: inline-flex; align-items: center; justify-content: center; }
.vm-aksi .vm-unduh::before { content: ''; width: 20px; height: 20px; background: currentColor;
  -webkit-mask: var(--ikon-unduh) center / contain no-repeat; mask: var(--ikon-unduh) center / contain no-repeat; }
.vm-aksi .vm-unduh { --ikon-unduh: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M11 4h2v8.2l3.3-3.3 1.4 1.4L12 16l-5.7-5.7 1.4-1.4 3.3 3.3zM5 18h14v2H5z'/%3E%3C/svg%3E"); }
.vm-aksi .vm-unduh.terunduh { color: #46d369; background: rgba(70,211,105,.14); border: 0;
  --ikon-unduh: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9.5 16.2 5.3 12l-1.4 1.4 5.6 5.6L20.1 8.4 18.7 7z'/%3E%3C/svg%3E"); }
.vm-aksi .vm-unduh:disabled:not(.terunduh) { opacity: 1; cursor: default; }
.vm-aksi .vm-unduh:disabled:not(.terunduh)::before { width: 18px; height: 18px; box-sizing: border-box; background: none; -webkit-mask: none; mask: none;
  border: 2px solid rgba(255,255,255,.22); border-top-color: var(--merah); border-radius: 50%; animation: putar .9s linear infinite; }
html.tv .vm-aksi .vm-unduh { width: 52px; height: 52px; }
html.tv .vm-aksi .vm-unduh::before { width: 28px; height: 28px; }
html.tv .vm-aksi .vm-unduh:disabled:not(.terunduh)::before { width: 26px; height: 26px; border-width: 3px; }
.vm-aksi .vm-hapus { margin-left: auto; }
html.tv .vm-ikon { width: 52px; height: 52px; }
html.tv .vm-tombol .tombol { font-size: 20px; padding: 10px 22px; }
html.tv .vm-tombol .tombol.ikon-saja { width: 60px; height: 60px; padding: 0; }
html.tv .vm-tombol .tombol.ikon-saja .ikon { width: 28px; height: 28px; }
/* HP DIMIRINGKAN — halaman lain (sapuan `bash scripts/sapu-datar.sh`, jhony 15 Okt 2026). Tinggi ±340px:
   (1) detail film/serial: gambar 16:9 selebar layar = 427px → judul & tombol Putar tenggelam di bawah lipatan;
   (2) pilih profil: logo + judul + jarak 28px menyisakan kotak profil yang terpotong separuh. */
@media (orientation: landscape) and (max-height: 500px) {
  html:not(.tv) .detail-gambar { aspect-ratio: auto; height: 52dvh; }
  html:not(.tv) .layar-profil { gap: 10px; padding-top: calc(env(safe-area-inset-top,0px) + 48px); padding-bottom: 12px; }
  html:not(.tv) .layar-profil .logo-besar { font-size: 26px; }
  html:not(.tv) .layar-profil h1 { font-size: 20px; }
  html:not(.tv) .daftar-profil { gap: 16px; padding: 4px; }
  html:not(.tv) .profil { width: 96px; gap: 6px; }
  html:not(.tv) .profil .avatar { width: 72px; height: 72px; font-size: 32px; }
  html:not(.tv) .profil.tambah .avatar { font-size: 40px; }
}
/* Video Musik LURING dari tab Unduhan (bukaUnduhanVm): suara "Dengar" dialirkan server → tak berguna tanpa sinyal */
.vm-luring .vm-dengar { display: none; }
