/*
 * HUD bergaya game kasual: panel bulat gelap tembus pandang, huruf tebal
 * bergaris tepi, warna pekat. Sengaja meniru tata letak game olahraga di
 * CrazyGames — informasi penting di sudut, tengah layar dibiarkan bersih.
 *
 * Tidak ada huruf dari luar. Huruf web dari CDN berarti satu permintaan
 * jaringan lagi sebelum layar pertama muncul, dan kalau gagal dimuat, HUD-nya
 * berubah bentuk di depan mata pemain.
 */

* { box-sizing: border-box; margin: 0; padding: 0; }

/* ---- huruf bulat, DIBUNDEL BUKAN DIUNDUH DARI CDN (§43.12) --------------
   Larangan lama di berkas ini berbunyi "huruf dari CDN dilarang", dan aturan itu
   TIDAK dilanggar di sini — justru dipenuhi lebih baik. Yang ditolak dari CDN
   adalah permintaan ke peladen luar saat halaman dibuka: ia menambah tempat yang
   bisa gagal, dan waktu ia gagal tiap perangkat jatuh ke huruf bawaannya
   masing-masing. Berkas ini duduk di dalam proyek, seperti three.module.js dan
   ketiga belas PNG tombol sentuh.

   Justru tumpukan huruf sistem-lah yang selama ini melanggar semangat aturan
   itu: `ui-rounded` cuma bulat di Apple. Di Windows ia jatuh ke Segoe UI dan di
   Android ke Roboto — keduanya TIDAK bulat sama sekali. Jadi bentuk hurufnya
   memang sudah berbeda di tiap perangkat, persis hal yang dihindari waktu emoji
   ditolak (§30.7). Satu berkas 29 KB menghapus perbedaan itu.

   Cuma subset LATIN yang diambil (U+0000–00FF dan tanda baca umum). Subset
   Ibrani dan Latin-diperluas tidak dipakai satu huruf pun oleh menu berbahasa
   Indonesia ini.

   `font-weight: 300 700` bukan salah tulis: Fredoka huruf VARIABEL, dan 700
   adalah setebal-tebalnya. `font-weight: 900` yang dipakai di seluruh menu
   dijepit ke 700 oleh peramban tanpa penebalan tiruan — deklarasi rentang di
   sinilah yang mencegahnya. Lisensinya SIL OFL, disimpan di font/OFL.txt. */
@font-face {
  font-family: 'Fredoka';
  font-style: normal;
  font-weight: 300 700;
  /* `swap`: teks menu tampil seketika dengan huruf bawaan lalu berganti begitu
     berkasnya siap. `block` akan menyembunyikan seluruh tulisan menu selama
     berkasnya dimuat — layar pembuka kosong untuk menghemat satu kedipan. */
  font-display: swap;
  src: url('../font/fredoka.woff2') format('woff2');
}

/* Kendali formulir TIDAK mewarisi huruf halaman menurut bawaan peramban — ia
   memaksakan hurufnya sendiri (di Chrome: Arial 13,33 px). Tanpa baris ini,
   setiap `<button>` di menu yang tidak menulis `font-family`-nya sendiri
   digambar dengan Arial, sementara tulisan di sekitarnya memakai tumpukan
   bulat yang dipilih di bawah — dua huruf berbeda dalam satu tombol yang sama
   (nama mode Arial, judul layar bukan). Terukur: `.mode-teks b` mengembalikan
   "Arial" sebelum aturan ini ada. */
button, input, select, textarea { font-family: inherit; }

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #cdeeff;
  /* Fredoka di depan (lihat `@font-face` di atas) — huruf acuan game rujukan
     memang keluarga ini. Sisa tumpukannya DIPERTAHANKAN sebagai jaring pengaman
     untuk detik pertama sebelum berkasnya siap, dan untuk keadaan langka waktu
     berkasnya gagal dimuat sama sekali: `ui-rounded` memetakan ke SF Pro Rounded
     di Apple, lalu Segoe UI/Roboto yang sama-sama punya face Black sungguhan
     sehingga `font-weight: 900` tidak jatuh ke penebalan tiruan yang bertepi
     kotor. */
  font-family: 'Fredoka', ui-rounded, "Segoe UI", "Trebuchet MS", Roboto, system-ui, sans-serif;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

#scene {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;   /* seret di kanvas memutar kamera, bukan menggulir halaman */
}

/* ---------------------------------------------------------------- kerangka -- */

#hud {
  position: fixed;
  inset: 0;
  pointer-events: none;   /* klik tembus ke kanvas; hanya penyetel yang menangkapnya */
  color: #fff;
  font-size: 13px;
  transition: opacity 0.2s;
  /* DI ATAS #menu (20), dan itu aman justru karena selama menu terbuka seluruh
     isi #hud dipadamkan kecuali #putar (lihat aturan `body:not(.bertanding)`
     di bagian menu). Angkanya harus ada di SINI, bukan di #putar: `position:
     fixed` membentuk stacking context tersendiri, jadi z-index sebesar apa pun
     yang dipasang pada anak #hud tetap terkurung di dalamnya — #putar sempat
     diberi z-index 30 dan tetap tertimbun menu, karena yang dibandingkan
     dengan menu adalah #hud (waktu itu `auto`), bukan anaknya. */
  z-index: 25;
}
/* Menyamarkan HUD (tombol H / lembar setelan) sengaja MELEWATI lapisan penuh
   layar. Kalau seluruh #hud diredupkan sekaligus, dialog konfirmasi dan layar
   hasil ikut jadi 12% — dan pemain HP yang menyamarkan HUD lalu ingin
   mengembalikannya harus menebak-nebak letak tombol yang hampir tak terlihat. */
#hud.samar > *:not(.tirai):not(#putar) { opacity: 0.12; }

/*
 * Gaya panel dan tombol mengikuti bahasa visual game kasual CrazyGames bergaya
 * "Free Kicks": GARIS TEPI GELAP TEBAL, bayangan bawah PEJAL (bukan kabur), dan
 * huruf gemuk. Ini bukan tempelan selera — dunia 3D-nya sendiri digambar
 * dengan garis tepi hitam (lambung terbalik, lihat js/toon.js), jadi HUD
 * bergaris tipis putih justru terbaca seperti berasal dari game lain. Warna
 * pekat + garis tebal juga yang membuat tombol tetap terbaca di atas rumput
 * terang maupun tanah benteng yang gelap.
 *
 * Huruf bulatnya sendiri (Baloo/Fredoka di game acuan) TIDAK bisa ditiru
 * persis: huruf dari CDN dilarang di proyek ini (lihat catatan di atas), jadi
 * yang dipakai tebal 800 + jarak huruf dari huruf sistem — mendekati, bukan
 * sama.
 */
:root {
  --garis: #10141c;
  /* PERMUKAAN KARTU. Dulu `#fff` telanjang di tiga tempat (`.kotak`,
     `.kartu`, `.tur-kartu`). Putih murni adalah satu-satunya warna di seluruh
     palet ini yang tidak pernah dipilih — ia cuma nilai bawaan — dan di
     sebelah keping `#eef1f6` yang bergaris hitam tebal ia terbaca menyilaukan,
     bukan bersih. Abu kebiruan tipis: rona yang sama condongnya dengan
     `--biru`, jadi ia senada dengan palet alih-alih jadi kelabu netral yang
     berdiri sendiri.

     Kepingnya SENGAJA tidak ikut diabukan. Sesudah kartunya turun ke
     `--kartu`, `#eef1f6` jadi LEBIH TERANG daripada bidang di belakangnya —
     dan itu justru menegakkan tingkatan yang dulu rata: kartu adalah
     permukaan, keping adalah benda yang berdiri di atasnya. Keping putih yang
     memang bermakna ("belum jadi milikmu", §43.9) tetap putih murni, karena
     sekarang barulah ia benar-benar terbaca sebagai warna yang dipilih. */
  --kartu: #e7ebf3;
  --kuning: #ffd23f;
  --kuning-bawah: #a97c14;
  --merah: #ff5d4d;
  --merah-bawah: #93291d;
  --biru: #4b90e2;
  --biru-bawah: #1f4f8a;
  --hijau: #2fc86b;
  --hijau-bawah: #17803f;

  /* Ruang di bawah kartu komidi tempat patokan berdiri (§47.1).
     Dipakai DUA tempat: `.komidi` menyediakannya sebagai `padding-bottom`, dan
     `.menu-kaki.rapat` mengangkat dirinya setinggi itu supaya dasar tombolnya
     jatuh di garis yang sama dengan dasar KARTU komidi — bukan dasar strip
     beserta ruang patokannya. Ditulis dua kali, keduanya menyimpang pada
     penyuntingan berikutnya dan tombolnya meleset beberapa piksel dari kartu di
     sebelahnya — meleset yang tidak menghasilkan galat apa pun. */
  --ruang-patokan: calc(clamp(9px, 1.6vh, 13px) + clamp(4px, 0.9vh, 8px));

  /* ---- warna tombol komando (§40.7) -------------------------------------
     Keluhannya: "warna tombol SERBU itu abu-abu, kontras dan tidak senada
     dibanding tombol lain yang cenderung biru, merah, dan kuning." Sesudah
     diperiksa ternyata bukan satu tombol melainkan TIGA — SERBU, TAHAN, dan
     MUNDUR berbagi abu-abu yang sama (#2c3445 di HP, #39435a di desktop),
     sementara TEBAS merah dan SALVO biru.

     Aturan yang dipakai: SATU WARNA PER ARTI, DAN JANGAN PAKAI ULANG WARNA
     YANG SUDAH PUNYA ARTI LAIN.

       merah   = menyerang     → TEBAS (aksi pribadi) dan SERBU (perintah regu)
       hijau   = bertahan      → TAHAN
       biru    = melempar/surut→ SALVO (terang) dan MUNDUR (tua)
       kuning  = SEDANG BERJALAN, dan hanya itu

     Kuning sengaja TIDAK diberikan ke tombol mana pun sebagai warna dasar.
     Ia satu-satunya bahasa "sikap ini yang sedang dituruti regumu", dipakai
     `.aktif` di kedua tata letak; begitu ada tombol yang kuning sejak diam,
     bacaan itu hilang dan pemain kehilangan satu-satunya cara mengetahui
     perintah mana yang berlaku tanpa membaca panel statistik.

     TEBAS dan SERBU sama-sama merah, dan itu disengaja: keduanya memang
     "menyerang", cuma beda skala. Keduanya tidak pernah tertukar karena
     ukurannya jauh berbeda (TEBAS `--serang`, SERBU `--orbit`) dan isinya
     berbeda (pedang vs. ikon serbu). MUNDUR memakai biru TUA, sekeluarga
     dengan SALVO tapi jelas lebih gelap — dua-duanya tidak pernah dibaca
     bersamaan karena SALVO selalu membawa angka hitung mundur di wajahnya.

     MAJU (hanya ada di baris desktop; di HP ia keadaan netral tanpa tombol,
     §26) memakai MERAH TUA — sekeluarga dengan SERBU dan bukan warna kelima,
     karena keduanya memang perintah yang sama arahnya: maju itu serbu yang
     ditahan. Sepasang MUNDUR/SALVO mengerjakan hal yang sama di keluarga biru.
     Tiga keluarga warna untuk lima sikap terbaca jauh lebih cepat daripada
     lima warna lepas, dan tidak ada satu pun yang abu-abu.

     `--kmd-abu` tinggal dipakai keadaan MATI/isi ulang, bukan sikap. */
  --kmd-serbu: #e04a3a;
  --kmd-maju: #9c3b30;
  --kmd-tahan: #279a56;
  --kmd-mundur: #2b6099;
  /* FORMASI memakai hijau TUA — sekeluarga dengan TAHAN, karena bentuk barisan
     memang cuma berarti waktu regunya sedang menahan.

     GANTI biru-kehijauan: ia BUKAN perintah sama sekali (menekannya tidak
     mengubah apa pun di medan, cuma memutar bentuk mana yang tertera di tombol
     FORMASI), jadi ia sengaja tidak ikut salah satu keluarga warna perintah.
     Diminta bukan abu-abu, dan memang tidak boleh: satu-satunya abu-abu yang
     tersisa sekarang adalah TEBAS, dan dua tombol abu-abu berdampingan akan
     terbaca sebagai sepasang padahal keduanya tidak berhubungan.

     TEBAS justru DIMINTA jadi abu-abu (§40.9). Merahnya dulu dipilih sebagai
     "warna menyerang", tapi sesudah SERBU ikut merah, dua merah bersebelahan
     di gugus yang sama saling meredam. Abu-abu batu di sini bekerja lebih baik
     daripada kedengarannya: TEBAS satu-satunya tombol yang tidak pernah
     berganti keadaan — ia tidak punya "aktif", tidak punya isi ulang, tidak
     punya batal — jadi ia justru tombol yang paling tidak butuh warna. */
  --kmd-fm: #1d6b3d;
  --kmd-ganti: #2a8f9e;
  --kmd-tebas: #566076;
  --kmd-abu: #39435a;

  /* ---- tangga huruf menu ------------------------------------------------
     Sebelumnya tiap elemen menu menulis `clamp()`-nya sendiri, dan hasilnya
     sebelas ukuran berbeda yang tidak berhubungan satu sama lain (12/13/14 px
     dipakai untuk tiga hal yang beda kepentingannya) serta tujuh nilai
     `letter-spacing` acak antara 0,2 dan 1,2 px. Gaya huruf game kasual justru
     bergantung pada jenjang yang sedikit dan berjarak lebar — judul jauh lebih
     besar dari tombol, tombol jauh lebih besar dari label. Empat anak tangga
     ini yang dipakai seluruh menu; tidak ada ukuran lain yang boleh muncul.

     Semuanya dipatok ke TINGGI layar (vh), bukan lebar: yang menyempit pada HP
     mendatar adalah tingginya, dan huruf yang mengikuti lebar akan tetap besar
     justru waktu ruangnya paling sedikit. */
  /* Dinaikkan dari clamp(20px, 5.2vh, 34px) (§43.11). Terukur di 892×412, judul
     lama 21,4 px berdiri di atas tombol setinggi 55,6 px — perbandingan 0,38,
     sementara di menu rujukan judulnya kira-kira 0,65 × tinggi tombol. Judul
     yang lebih kecil dari benda di bawahnya berhenti terbaca sebagai judul. */
  --fs-judul: clamp(25px, 7vh, 44px);
  --fs-tombol: clamp(13px, 3.2vh, 19px);
  /* Khusus nama mode di beranda (§42.2). Sengaja SATU TINGKAT DI ATAS
     `--fs-tombol`, bukan memakainya: sesudah anak judul dihapus, nama mode jadi
     satu-satunya tulisan di tombol itu, dan ia harus mengisi tinggi yang
     ditinggalkan anak judulnya. Percobaan pertama memakai `--fs-label` dan
     hasilnya justru MENGECIL 13,2 → 11 px — tangga hurufnya menurun
     (judul > tombol > label > kecil), jadi "naik satu tingkat" berarti naik ke
     angka yang lebih besar, bukan ke nama yang terdengar lebih penting. */
  --fs-mode: clamp(16px, 4.4vh, 25px);
  --fs-label: clamp(11px, 2.4vh, 15px);
  --fs-kecil: clamp(9.5px, 1.9vh, 12.5px);

  /* Huruf kapital gemuk perlu diregangkan supaya tidak terbaca sebagai satu
     gumpalan; huruf kecil justru tidak. Karena itu cuma dua nilai, bukan
     tujuh: satu untuk semua tulisan KAPITAL, satu untuk sisanya. */
  --lc-kapital: 1.1px;
  --lc-biasa: 0.2px;
}

.panel {
  position: absolute;
  background: rgba(18, 22, 32, 0.82);
  border: 3px solid var(--garis);
  border-radius: 14px;
  padding: 9px 13px;
  backdrop-filter: blur(3px);
  /* Bayangan lembut, bukan tepi timbul pejal: panelnya perlu terpisah dari
     medan 3D di belakangnya, tapi tidak boleh ikut terlihat seperti tombol. */
}

kbd {
  display: inline-block;
  min-width: 17px;
  padding: 1px 5px;
  border-radius: 5px;
  background: #f2f4f8;
  color: #1b2030;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.5;
  text-align: center;
}

.kecil { margin-top: 5px; font-size: 11px; opacity: 0.66; }

/* ------------------------------------------------------------------ panel --- */

.panel-judul { top: 12px; left: 12px; }
.panel-judul strong {
  display: block;
  font-size: 17px;
  letter-spacing: 1.2px;
  color: #ffd75e;
  text-shadow: 0 2px 0 #7a4a12;
}
.panel-judul span { font-size: 11px; opacity: 0.6; }

/* ---- sudut kanan-atas: baris ringkas + tombol STATS (§57.41.4/.5) -------
   Papan skor delapan baris yang dulu berdiri di sini sudah pindah ke lembar
   tengah layar. Yang tersisa satu baris — dan satu baris tidak bisa menindih
   tombol apa pun, yang persis jadi keluhan panel lama di 892×412. */
.skor-atas {
  top: 12px;
  right: 12px;
  display: flex;
  align-items: stretch;
  gap: 7px;
  padding: 0;
  border: 0;
  background: none;
  pointer-events: auto;
}
/* Latarnya SAMA dengan lembar statistik yang dibuka tombol di sebelahnya —
   permintaan langsung, dan alasannya masuk akal sendiri: baris ini memang
   potongan pertama dari tabel itu, cuma berisi barisnya sendiri. */
.skor-ringkas {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border: 3px solid var(--garis);
  border-radius: 12px;
  background: rgba(24, 30, 44, 0.86);
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
}
/* Panjinya sendiri, bukan titik warna — dan MEMANJANG MENDATAR (§57.42.4).
   Rasionya tidak lagi 3:4 seperti kanvas `teksturPanji()`, jadi `object-fit:
   cover` di sini benar-benar bekerja: ia MEMOTONG pita atas dan bawah panji
   alih-alih menggencetnya. Yang dipotong justru bagian yang tidak membawa
   kabar — lambang bangsa duduk di tengah kanvas panji, dan bidang warna di
   sekelilingnya sama saja dipotong atau tidak.

   Tingginya sengaja disamakan dengan tinggi keping angka di sebelahnya supaya
   seluruh baris ini duduk pada satu garis dasar yang sama. */
.ku-panji {
  display: block;
  width: 26px;
  height: 17px;
  border: 2px solid rgba(0, 0, 0, 0.5);
  border-radius: 3px;
  object-fit: cover;
  flex-shrink: 0;
}
/* Dipotong dengan elipsis, bukan dibiarkan mendorong keping di kanannya:
   "Tiongkok" dua kali lebar "Aztek", dan baris yang lebarnya berubah tiap kali
   pemain berganti bangsa membuat tombol STATS di sebelahnya ikut bergeser. */
.ku-nama {
  max-width: 8.5em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 800;
}
.ku-bd, .ku-jm {
  min-width: 2.2em;
  padding: 3px 5px;
  border-radius: 5px;
  text-align: center;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}
/* Satu keping berwarna per baris, aturan yang sama dengan papan hasil
   (§57.40): bendera yang memutus pertandingan waktu jam habis — itulah yang
   berhak berwarna. Jumlah orang cukup keping gelap. */
.ku-bd { background: var(--kuning); color: #221800; }
.ku-jm { background: rgba(255, 255, 255, 0.12); color: #fff; }
/* SIKAP REGU, pengganti batang moral (§57.42.4). Sengaja BUKAN keping berlatar
   seperti dua angka di kirinya: kedua angka itu HASIL yang dikumpulkan, sikap
   adalah PERINTAH yang sedang berjalan — dua jenis kabar yang berbeda tidak
   boleh memakai bentuk yang sama. Yang membedakannya di sini garis tepi tanpa
   isian, bentuk yang sama dengan tombol sikap di sudut berseberangan.

   Lebar tetap, dan itu bukan kerapian belaka: tanpanya baris ini melebar dan
   menyempit tiap kali pemain berganti sikap ("HOLD" lawan "RETREAT"), dan
   tombol STATS di sebelah kanannya ikut melompat. */
.ku-sikap {
  flex-shrink: 0;
  min-width: 4.6em;
  padding: 2px 6px;
  border: 2px solid rgba(255, 255, 255, 0.34);
  border-radius: 5px;
  text-align: center;
  font-size: 0.85em;
  font-weight: 900;
  letter-spacing: 0.6px;
  color: #cfd8ea;
}
/* Satu-satunya sikap yang diberi warna, karena ia satu-satunya yang
   MENGHABISKAN sesuatu: selama SERBU menyala, barisan pecah mengejar dan
   pemimpinnya ikut berlari (§57.41.7). Tiga sikap lain adalah keadaan tenang
   yang tidak perlu menarik mata. */
.ku-sikap.serbu { border-color: var(--merah); color: #ffb0a6; }
/* Pemimpin tumbang: satu-satunya keadaan yang mengubah rupa baris ini, karena
   ia satu-satunya kabar yang mengubah apa yang harus pemain lakukan. */
.skor-ringkas.bospergi { border-color: var(--merah); }

/* Tombol STATS: PERSEGI, seperti yang diminta — dan itu membedakannya dari
   setiap tombol lain di HUD, yang semuanya bulat atau berkotak lebar. */
.stats-tbl {
  width: 58px;
  border: 3px solid var(--garis);
  border-radius: 12px;
  background: #39435a;
  color: #fff;
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.8px;
  line-height: 1;
  cursor: pointer;
  transition: filter 0.12s, transform 0.07s;
}
.stats-tbl:hover { filter: brightness(1.18); }
.stats-tbl:active { transform: scale(0.94); }

.bar {
  height: 10px;
  border: 2px solid var(--garis);
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.5);
  overflow: hidden;
}
.bar > div {
  height: 100%;
  width: 100%;
  background: #5fbf5a;
  transition: width 0.3s, background 0.3s;
}

/* Komando: baris tombol besar di bawah tengah — posisi yang sama dipakai
   nanti untuk tombol sentuh di HP. */
.panel-komando {
  bottom: 14px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 7px;
  padding: 7px;
  /* `left: 50%` tanpa `right` membuat lebar tersedianya cuma SEPARUH layar, dan
     begitu tombol keenam (FORMASI, §40.8) masuk, keenamnya diperas sampai
     labelnya patah dua baris — "1" di atas, "TAHAN" di bawah. `max-content`
     membuat barisnya selebar isinya lalu tetap dipusatkan oleh transform. */
  width: max-content;
  max-width: 96vw;
}
.panel-komando .cmd { white-space: nowrap; }
/* Aturan di bawah sengaja DILINGKUPI `.panel-komando`, bukan `.cmd` telanjang.
   Tombol komando versi HP memakai kelas `.cmd` yang sama supaya satu fungsi
   `setKomando()` bisa menyalakan keduanya sekaligus — tapi bentuknya bundar,
   bukan persegi panjang berlabel angka. Tanpa pelingkupan ini, padding dan
   radius baris desktop ikut terbawa ke tombol bundarnya. */
.panel-komando .cmd {
  padding: 9px 15px;
  border: 2px solid var(--garis);
  border-radius: 10px;
  background: var(--kmd-abu);
  font-weight: 800;
  font-size: 12px;
  letter-spacing: 0.6px;
  transition: all 0.12s;
}
.panel-komando .cmd kbd { margin-right: 5px; }

/* WARNA SIKAP REGU (§40.7): satu warna per arti, tanpa abu-abu.
   Lihat catatan lengkap di dekat `--kmd-serbu` di blok :root. */
.panel-komando [data-k="serbu"] { background: var(--kmd-serbu); }
.panel-komando [data-k="tahan"] { background: var(--kmd-tahan); }
.panel-komando [data-k="mundur"] { background: var(--kmd-mundur); }
.panel-komando [data-k="maju"] { background: var(--kmd-maju); }

/* ---- FORMASI dan GANTI (§40.8) -------------------------------------------
   Ikon denahnya menggambar bentuk yang sedang dipegang tombol — titik kuning
   di tiap ikon adalah PEMIMPIN, dan itu yang membuat "melingkar" langsung
   terbaca: yang dikelilingi adalah pemain sendiri. */
.panel-komando .cmd.fm,
.panel-komando .cmd.ganti { display: flex; align-items: center; gap: 7px; }
.panel-komando .cmd.fm { background: var(--kmd-fm); }
.panel-komando .cmd.ganti { background: var(--kmd-ganti); }
.panel-komando .cmd.fm img,
.panel-komando .cmd.ganti img { width: 20px; height: 20px; object-fit: contain; display: block; }
#fm-nama { font-size: 11px; letter-spacing: 0.4px; }
.panel-komando .cmd.aktif { background: var(--kuning); color: #221800; }
.panel-komando .cmd.aktif kbd { background: #2a1c00; color: #ffd75e; }

/* SALVO berbeda dari keempat tombol di sebelahnya: ia perintah SEKALI PAKAI,
   bukan sikap yang bertahan. Karena itu ia tidak pernah menyala sebagai
   "aktif" — ia berkedip sebentar waktu ditekan, lalu meredup selama isi ulang.
   Kalau bentuknya sama persis dengan yang lain, pemain akan mengira menekannya
   membatalkan komando yang sedang berjalan. */
.panel-komando .cmd.sekali { background: var(--biru); }
.panel-komando .cmd.sekali.nyala { background: #8fdcff; color: #06222f; }
/* Latar yang diredupkan, bukan `opacity` pada tombolnya — alasannya sama
   dengan catatan di #gugus: angka hitung mundur (::after di bawah) ikut
   pudar kalau tombolnya sendiri yang ditransparankan. */
.panel-komando .cmd.sekali.isi-ulang { background: #2b4757; color: rgba(255, 255, 255, 0.4); }
/* Ditekan tapi tidak ada yang bisa dilempar. Warnanya sengaja BEDA dari yang
   berhasil (merah, bukan biru): dua hasil yang berbeda harus terlihat berbeda,
   kalau tidak pemain tidak pernah tahu perintahnya sampai atau tidak. */
.panel-komando .cmd.sekali.gagal {
  background: rgba(224, 90, 74, 0.5);
  color: #fff;
  opacity: 1;
}
/* SEDANG DIBIDIK (§39.4): tombolnya ditahan, pemandu bidik terbuka di medan.
   Ditandai CINCIN, bukan warna latar — warna latar sudah dipakai tiga keadaan
   lain (siap, berhasil, isi ulang), dan keadaan keempat yang memakai bahasa
   yang sama akan tertukar dengan salah satunya. Cincin itu bahasa baru, dan
   artinya mudah ditebak: sesuatu sedang terbuka dan menunggu dilepas. */
/* Cincinnya digambar `outline`, BUKAN `box-shadow`: seluruh proyek ini sudah
   membuang bayangan (§57.40 mencatat sensusnya nol), dan cincin ini pernah
   ikut terbawa — aturannya tertinggal KOSONG, jadi keadaan “sedang membidik”
   tidak punya tanda apa pun selama beberapa putaran meski komentarnya di atas
   menjanjikan cincin. `outline` tidak memakan ruang tata letak, jadi tombolnya
   tidak bergeser waktu cincinnya menyala. */
.cmd.sekali.membidik,
#gugus .sekali.membidik {
  outline: 3px solid #8fdcff;
  outline-offset: 2px;
}

/* Keterangan bidik SALVO: jarak dan berapa orang yang akan melempar.
   Di tengah, TIDAK menempel di tombolnya — di HP tombol SALVO sedang ditutupi
   ibu jari yang menyeretnya, jadi angka yang ditaruh di dekatnya adalah angka
   yang tidak pernah terbaca.

   Di desktop ia duduk di BAWAH, tepat di atas #pesan: tengah-atas sudah dipakai
   panel penyetel tampilan, dan angka yang tertimbun di belakang panel sama saja
   dengan tidak ada. Di HP panel itu tidak ada, jadi di sana ia naik ke atas —
   lihat body.hp di bawah. */
#bidik-info {
  position: absolute;
  left: 50%;
  bottom: 164px;
  transform: translateX(-50%);
  padding: 6px 15px;
  border: 3px solid var(--garis);
  border-radius: 999px;
  background: rgba(10, 18, 26, 0.88);
  color: #eaf4ff;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.2px;
  white-space: nowrap;
  pointer-events: none;
}
#bidik-info b { color: #ffe08a; font-size: 15px; }
#bidik-info.gagal { border-color: #e05a4a; }
#bidik-info.gagal b { color: #ffb1a6; }

/* Pesan sekilas. Ditaruh di atas baris komando, di tengah — satu-satunya
   tempat yang pasti dilihat pemain tanpa ia harus mengalihkan pandangan dari
   pertempuran. */
#pesan {
  position: absolute;
  left: 50%;
  bottom: 122px;
  transform: translate(-50%, 8px);
  padding: 8px 17px;
  border: 3px solid var(--garis);
  border-radius: 999px;
  background: rgba(10, 18, 26, 0.9);
  color: #eaf4ff;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.2px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.18s ease;
}
#pesan.tampil { opacity: 1; transform: translate(-50%, 0); }

/* Tombol aksi pemimpin. Ditaruh di kanan-bawah, jauh dari baris komando di
   tengah, supaya ibu jari kanan di HP tidak pernah menyenggol komando waktu
   menebas — dua kelompok tombol dengan akibat yang sangat berbeda tidak boleh
   bertetangga. */
.panel-aksi {
  bottom: 96px;
  right: 12px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 7px;
  pointer-events: auto;
}
.aksi {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 124px;
  padding: 12px 14px;
  border: 3px solid var(--garis);
  border-radius: 12px;
  /* TEBAS abu-abu batu, sama seperti versi HP-nya (§40.9). */
  background: var(--kmd-tebas);
  color: #f2f5fb;
  font-size: 12px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0.8px;
  cursor: pointer;
  transition: transform 0.07s, filter 0.12s;
}
.aksi span { margin-left: auto; }
.aksi:hover { filter: brightness(1.08); }
.aksi:active { transform: scale(0.97); }
.aksi.lempar { background: var(--kuning); color: #221800; }

.panel-bantuan { bottom: 14px; left: 12px; max-width: 300px; line-height: 1.9; }

/* 84px, bukan 12: sudut atas-tengah sekarang milik teks waktu pertandingan
   (#waktu-hud). Angka 34px + label 11px dengan jarak §27 lebih tinggi dari
   lencana kecil semula (dulu cukup 66px), jadi turun lagi supaya tidak
   bersenggolan. */
.panel-setel { top: 84px; left: 50%; transform: translateX(-50%); pointer-events: auto; }
.setel-judul {
  font-size: 10px;
  letter-spacing: 1px;
  opacity: 0.55;
  margin-bottom: 5px;
  text-transform: uppercase;
}
.baris {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 2px 0;
  font-size: 11px;
}
.baris label { width: 84px; opacity: 0.75; }
.baris input[type="range"] { width: 122px; accent-color: #ffd75e; }
.baris output { width: 58px; text-align: right; opacity: 0.75; font-variant-numeric: tabular-nums; }

/* Angka fps/gambar/segitiga disembunyikan dari pemain — itu bacaan dev,
   bukan sesuatu yang berguna di tengah pertandingan, dan pemain melaporkan
   ia justru mengganggu di sudut layar. Tetap dihitung dan ditulis ke
   elemennya (lihat `bingkai()` di main.js) supaya masih bisa dipanggil balik
   dengan cepat lewat `?fps=1` waktu menyetel performa. */
.panel-stat { display: none; }
body.tampilkan-stat .panel-stat {
  display: block;
  bottom: 14px;
  right: 12px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
body.hp.tampilkan-stat .panel-stat {
  top: calc(70px + env(safe-area-inset-top));
  left: calc(10px + env(safe-area-inset-left));
  right: auto;
  bottom: auto;
  padding: 4px 8px;
  font-size: 10px;
  opacity: 0.5;
}
.panel-mode { bottom: 52px; right: 12px; font-size: 11px; }

/* --------------------------------------------------------- tombol sudut ---- */

/* Waktu pertandingan: TEKS TELANJANG di tengah-atas, sengaja TANPA `.panel`
   pembungkus (nol latar, nol garis tepi kotak, nol padding). Permintaan
   "hilangkan kotak" sempat dibaca sebagai "hilangkan semuanya" (§24) — angka
   dan tulisannya sendiri ternyata tetap diinginkan, cuma bungkusnya yang
   tidak. Keterbacaan di atas dunia 3D yang berwarna-warni dijaga lewat garis
   tepi hitam pada hurufnya sendiri (pola yang sama dipakai `.panel-judul
   strong` dan `.hasil-judul`), bukan lewat kotak gelap di belakangnya. */
#waktu-hud {
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  pointer-events: none;
}
/* §57.54: `#waktu`, BUKAN `#waktu-hud b`.
   Aturan ini menggambarkan ANGKA JAM, dan angka jam cuma satu elemen —
   tapi selektor lamanya mengenai SETIAP `<b>` di dalam `#waktu-hud`,
   termasuk kata bercetak tebal di dalam kartu tutorial yang kebetulan
   berdiri di dalamnya. Akibatnya "CHANGE" dan "FORM UP" terukur 26 px
   `display: block` di tengah kalimat 12 px.

   Diperbaiki di SUMBERNYA, bukan dengan menimpanya dari kartu: percobaan
   menimpa gagal dua kali berturut-turut karena perlombaan kekhususan
   (`.ajar-teks b` 0-1-1 kalah dari `#waktu-hud b` 1-0-1; lalu
   `#ajar .ajar-teks b` 1-0-1 kalah dari `body.hp #waktu-hud b` 1-1-1),
   dan menaikkan angkanya lagi cuma memindahkan perlombaan yang sama satu
   tingkat ke atas. Selektor yang menyebut benda yang dimaksudnya tidak
   punya perlombaan sama sekali. */
#waktu {
  display: block;
  font-size: 34px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 1px;
  line-height: 1;
  color: #fff;
  text-shadow:
    -2px -2px 0 var(--garis), 2px -2px 0 var(--garis),
    -2px 2px 0 var(--garis), 2px 2px 0 var(--garis),
    0 4px 0 rgba(13, 16, 23, 0.35);
}
/* 6px, bukan 1: rapat seperti dulu bikin "3:00" dan "BATTLE TIME" terbaca
   seperti satu kata yang kepotong, bukan angka besar dengan label kecil di
   bawahnya. */
#waktu-hud span {
  display: block;
  margin-top: 6px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--kuning);
  text-shadow:
    -1px -1px 0 var(--garis), 1px -1px 0 var(--garis),
    -1px 1px 0 var(--garis), 1px 1px 0 var(--garis);
}
/* Menit terakhir: cuma angkanya berubah warna, sesuai keputusan §23.2 —
   seluruh teks berubah rupa (dulu sempat jadi kotak merah tua) terasa
   terlalu mencolok di tengah pertandingan. */
#waktu-hud.mepet b { color: #ff8b7c; }

body.hp #waktu-hud { top: calc(8px + env(safe-area-inset-top)); }
body.hp #waktu { font-size: 26px; }
body.hp #waktu-hud span { margin-top: 4px; font-size: 10px; }

/* Sudut kiri-atas: PETA KECIL lalu tombol setelan (§57.41.8).
   `align-items: flex-start` supaya tombol setelan tetap menempel di tepi ATAS
   waktu petanya dibesarkan — kalau ia ikut turun ke tengah peta setinggi 3/4
   layar, tombol yang paling sering dicari pemain berpindah tempat tiap kali
   peta diperbesar. */
.panel-sudut {
  top: 88px;
  left: 12px;
  display: flex;
  align-items: flex-start;
  gap: 7px;
  padding: 6px;
  border: 0;
  background: none;
  pointer-events: auto;
  /* DI ATAS zona stik (§57.41.8). Terukur di 892×412: `#stik-zona` mengambil
     44% lebar × 72% tinggi dari sudut kiri-BAWAH — 340×297 px — dan peta
     kecil selebar 1/3 layar turun sampai y=197. Keduanya bertumpuk, dan
     karena `#sentuh` berdiri lebih belakang di DOM, zona stik menang: kaca
     pembesarnya tidak bisa ditekan sama sekali. Terbukti waktu diuji —
     ketukannya kehabisan waktu 30 detik. */
  z-index: 3;
}
.ikon {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border: 3px solid var(--garis);
  border-radius: 11px;
  background: #39435a;
  color: #fff;
  font-size: 15px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  transition: filter 0.12s, transform 0.07s;
}
.ikon:hover { filter: brightness(1.15); }
.ikon:active { transform: scale(0.92); }
.ikon img { width: 66%; height: 66%; object-fit: contain; display: block; }

/* ---- peta kecil (§57.41.8) ---------------------------------------------
   Lebarnya PECAHAN LEBAR LAYAR seperti yang diminta — 1/3 bawaan, 3/4 waktu
   dibesarkan — tapi ikut dijepit tinggi jendela. Peta persegi selebar 3/4
   layar mendatar 892×412 akan setinggi 669 px pada layar setinggi 412: yang
   dilihat pemain cuma sepertiga atasnya, dan kaca pembesarnya sendiri berada
   di luar layar. Yang dijepit tingginya, bukan permintaannya. */
/* DUA PERTIGA ukuran lama (§57.42.3): 1/3 lebar layar → 2/9, dan jepitan
   tingginya ikut dua pertiga supaya perbandingan keduanya tidak berubah —
   kalau cuma lebarnya yang dikecilkan, pada layar mendatar pendek jepitan
   tinggilah yang menang dan petanya sama sekali tidak menyusut.

   Yang dibayar pengecilan ini kerapatan, bukan keterbacaan: seluruh benda di
   dalamnya digambar dari `S` (sisi kanvas) lewat `Math.max(...)`, jadi markas,
   bendera, dan titik prajurit berhenti menyusut di ukuran terkecil yang masih
   terlihat alih-alih ikut mengecil sampai hilang. */
.peta-mini {
  position: relative;
  width: min(22.222vw, 30.667vh);
  height: min(22.222vw, 30.667vh);
  border: 3px solid var(--garis);
  border-radius: 12px;
  background: rgba(16, 21, 32, 0.82);
  overflow: hidden;
  transition: width 0.18s ease, height 0.18s ease;
}
.peta-mini.besar {
  width: min(75vw, 82vh);
  height: min(75vw, 82vh);
}
/* BADAN PETANYA TEMBUS SENTUHAN, kaca pembesarnya tidak.

   Pasangan aturan ini yang membuat `z-index: 3` di atas tidak merampas zona
   stik: yang naik ke atas cuma satu tombol 26 px, bukan seluruh persegi
   selebar sepertiga layar. Jempol yang mendarat di atas peta tetap sampai ke
   stik di belakangnya — dan itu memang yang benar, karena peta ini bacaan,
   bukan kendali. */
.peta-mini { pointer-events: none; }
.peta-mini canvas { display: block; width: 100%; height: 100%; }
/* Kaca pembesar di POJOK KANAN BAWAH petanya — permintaan langsung, dan sudut
   itu memang satu-satunya yang tidak pernah berisi markas (pusat arena selalu
   di tengah peta). */
.peta-zum {
  position: absolute;
  right: 4px;
  bottom: 4px;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border: 2.5px solid var(--garis);
  border-radius: 8px;
  background: #39435a;
  color: #fff;
  cursor: pointer;
  pointer-events: auto;
  transition: filter 0.12s, transform 0.07s;
}
.peta-zum:hover { filter: brightness(1.18); }
.peta-zum:active { transform: scale(0.9); }
.peta-zum svg { display: block; width: 72%; height: 72%; }
/* Batang tegak tanda TAMBAH dicabut waktu petanya sudah besar — yang tersisa
   tanda kurang, dan itulah yang akan dilakukan ketukan berikutnya. Satu tombol
   yang berganti arti wajib memperlihatkan arti barunya. */
.peta-zum.kecilkan .zum-tegak { display: none; }

/* ---- lembar statistik: TABEL (§57.41.4) ---------------------------------
   Kolomnya dipahat SEKALI di sini dan dipakai kepala maupun barisnya lewat
   `subgrid`, pola yang sama dengan papan hasil (`.hasil-kepala` /
   `.hasil-baris`). Itulah yang membuat angka di bawah kepala kolom benar-benar
   lurus di bawahnya — bukan dua daftar lebar yang kebetulan mirip. */
.kotak.lebar.stat-kotak { width: min(566px, 95vw); gap: clamp(6px, 1.4vh, 10px); text-align: left; }
.stat-tabel {
  display: grid;
  width: 100%;
  grid-template-columns:
    22px minmax(78px, 1fr) 44px 36px 44px 48px minmax(52px, 82px) 62px;
  border: 3px solid var(--garis);
  border-radius: clamp(9px, 1.8vh, 13px);
  background: #eef1f6;
  overflow: hidden;
}
.stat-kepala, .stat-baris {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
  gap: 9px;
  padding: 6px 11px;
}
.stat-kepala {
  border-bottom: 3px solid var(--garis);
  background: #dbe1ee;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.6px;
  color: #6b7590;
  text-transform: uppercase;
}
.stat-baris {
  border-top: 1px solid #ccd4e6;
  font-size: 12px;
  font-weight: 700;
  color: #1b2030;
}
.stat-kepala + .stat-baris { border-top: 0; }
/* Baris pemain ditandai WARNA NAMANYA, bukan kata di belakangnya — aturan
   yang sama dengan papan hasil (§57.40): kolom USER-nya sudah menulis "You". */
.stat-baris.kamu { background: #e5edfb; }
.stat-baris.kamu .wb span { color: #2f6fd0; }
.stat-baris.habis { opacity: 0.42; }
.stat-baris.habis .wb span { text-decoration: line-through; }
.stat-kepala span, .stat-baris > * { min-width: 0; }
.stat-baris .no { color: #6b7590; font-weight: 900; font-variant-numeric: tabular-nums; }
/* Kolom WARBAND: panji + nama bangsanya, satu benda. Panjinya yang sama persis
   dengan yang berkibar di bentengnya (`gambarPanji`, dari `teksturPanji()`) —
   dua gambar terpisah untuk benda yang sama pasti menyimpang suatu hari. */
.stat-baris .wb { display: flex; align-items: center; gap: 7px; min-width: 0; }
.stat-baris .wb img {
  display: block;
  width: 15px;
  height: 20px;
  border: 2px solid rgba(0, 0, 0, 0.35);
  border-radius: 3px;
  object-fit: cover;
  flex-shrink: 0;
}
.stat-baris .wb span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 800;
}
.stat-baris .us { color: #6b7590; font-weight: 800; font-size: 11px; }
/* Mahkota pemimpin. Selama menyala, regu itu TIDAK BISA dibuat kabur — jadi
   ini bukan hiasan melainkan bacaan taktis: yang mahkotanya sudah padam adalah
   regu yang tinggal didorong sedikit lagi. */
.stat-baris .ld { display: grid; place-items: center; color: #d99a1a; }
.stat-baris .ld svg { display: block; width: 15px; height: 15px; }
.stat-baris .ld.tumbang { color: #b9c1d2; }
.stat-baris .bd, .stat-baris .jm {
  padding: 2px 0;
  border-radius: 5px;
  text-align: center;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}
.stat-baris .bd { background: #ffcf3f; color: var(--garis); }
.stat-baris .jm { background: #dbe1ee; color: #1b2030; }
/* Yang kabur ditulis MENEMPEL pada jumlah selamat, bukan di kolomnya sendiri:
   ia bagian dari jawaban "berapa yang masih di lapangan", dan satu kolom lagi
   yang isinya nol di hampir tiap baris bukan kabar melainkan lebar. */
.stat-baris .kbr { margin-left: 3px; color: #c0533f; font-size: 10px; font-style: normal; }
.stat-baris .mr .bar { display: block; width: 100%; height: 9px; border-width: 2px; background: #cfd6e5; }
.stat-baris .mr .bar > span { display: block; height: 100%; }
/* Keping sikap DIWARNAI menurut sikapnya, warna yang sama persis dengan tombol
   busur sentuh (`#gugus [data-k=...]`) dan baris komando desktop (§40.7).
   Delapan keping kelabu identik yang cuma berbeda tulisannya adalah kolom yang
   harus DIBACA satu per satu; delapan keping berwarna terbaca sekaligus. */
.stat-baris .sikap {
  padding: 3px 5px;
  border-radius: 4px;
  background: var(--kmd-abu);
  color: #fff;
  font-size: 9.5px;
  font-weight: 900;
  letter-spacing: 0.4px;
  text-align: center;
}
.stat-baris .sikap[data-k="serbu"] { background: var(--kmd-serbu); }
.stat-baris .sikap[data-k="maju"] { background: var(--kmd-maju); }
.stat-baris .sikap[data-k="tahan"] { background: var(--kmd-tahan); }
.stat-baris .sikap[data-k="mundur"] { background: var(--kmd-mundur); }

/* ---- silang penutup di pojok kotak (§57.41.9) --------------------------
   `.berpalang` menyediakan lorong kanan-atas untuk silangnya, supaya judul
   yang panjang tidak berjalan lurus ke bawah tombolnya. */
.kotak.berpalang { position: relative; }
.kotak.berpalang .kotak-judul { padding-right: 30px; }
.kotak-silang {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border: 2.5px solid var(--garis);
  border-radius: 8px;
  background: #eef1f6;
  color: var(--garis);
  cursor: pointer;
  transition: background 0.12s, transform 0.07s;
}
.kotak-silang:hover { background: #dbe1ee; }
.kotak-silang:active { transform: scale(0.9); }
.kotak-silang svg { display: block; width: 62%; height: 62%; }

/* ------------------------------------------------- kendali sentuh (HP) ------ */

/* Keduanya baru dipasang oleh `body.hp`. Di desktop tidak ada satu pun piksel
   dari blok ini yang tergambar. */
#sentuh, #gugus { display: none; }

/*
 * SEMUA UKURAN KENDALI DIIKATKAN KE TINGGI LAYAR, bukan piksel tetap.
 *
 * Ini pelajaran dari Mobile Legends / Free Fire: di sana joystick memakan
 * sekitar 30% tinggi layar dan tombol serang sekitar 22%, sehingga jempol
 * menempuh sudut yang sama di HP 5 inci maupun tablet 11 inci. Angka piksel
 * tetap melakukan sebaliknya — joystick 124 px yang pas di HP kecil menyusut
 * jadi kancing di tablet, dan tombol yang tadinya nyaman jadi terlalu jauh
 * dari pangkal jempol.
 *
 * `dvh` dipakai, bukan `vh`: bilah alamat peramban HP yang menyembul dan
 * bersembunyi mengubah tinggi tampak, dan `vh` tidak ikut berubah — tombolnya
 * akan tertutup bilah alamat tepat pada saat dipencet. Baris `vh` di atasnya
 * jadi cadangan untuk peramban yang belum mengenal `dvh`.
 */
body.hp {
  --serang: clamp(78px, 21vh, 132px);
  --serang: clamp(78px, 21dvh, 132px);
  --orbit: clamp(54px, 14.5vh, 92px);
  --orbit: clamp(54px, 14.5dvh, 92px);
  --stik: clamp(112px, 30vh, 188px);
  --stik: clamp(112px, 30dvh, 188px);

  /* Pusat tombol TEBAS, diukur dari pojok kanan-bawah. Semua tombol busur
     diletakkan relatif terhadap titik ini, jadi menggeser satu angka di sini
     memindahkan seluruh gugus sekaligus. */
  --tepi-x: calc(18px + env(safe-area-inset-right));
  --tepi-y: calc(12px + env(safe-area-inset-bottom));
  --cx: calc(var(--tepi-x) + var(--serang) / 2);
  --cy: calc(var(--tepi-y) + var(--serang) / 2);

  /* Jari-jari busur. Sisipan 18 px itu yang membuat ketiga tombol regu punya
     jarak: pada busur 45° antar-tombol, tali busurnya jadi ±67 px sedangkan
     tombolnya 57 px — tersisa 10 px sela di antara mereka, dan 18 px sela ke
     tombol TEBAS di tengah. Dengan sisipan yang lebih kecil (9 px) ketiganya
     nyaris bersinggungan dan gugusnya terbaca sebagai satu gumpalan. */
  --r: calc(var(--serang) / 2 + var(--orbit) / 2 + 18px);
  --sela: 12px;
  /* Sela kelompok FORMASI/GANTI terhadap busur perintah — sengaja jauh lebih
     lebar dari `--sela` supaya keduanya terbaca sebagai kelompok tersendiri
     (§40.9). */
  --sela-fm: 26px;
  --mundur: calc(var(--orbit) * 0.82);
}

#stik-zona {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 44%;
  max-width: 340px;
  height: 72%;
  pointer-events: auto;
  touch-action: none;
}
#stik-alas {
  position: absolute;
  left: calc(18px + env(safe-area-inset-left));
  bottom: calc(14px + env(safe-area-inset-bottom));
  width: var(--stik);
  height: var(--stik);
  border-radius: 50%;
  /* Cukup terang untuk terbaca di atas tanah benteng yang cokelat gelap —
     alas joystick yang cuma bisa dilihat di atas rumput terang bukan alas
     joystick, melainkan tebakan. */
  border: 3px solid rgba(16, 20, 28, 0.75);
  background: rgba(12, 16, 24, 0.3);
  opacity: 0.8;
  transition: opacity 0.15s;
}
#stik-alas.pegang { opacity: 1; }
#stik-knop {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--stik) * 0.42);
  height: calc(var(--stik) * 0.42);
  margin-left: calc(var(--stik) * -0.21);
  margin-top: calc(var(--stik) * -0.21);
  border-radius: 50%;
  background: rgba(240, 245, 255, 0.8);
  border: 3px solid var(--garis);
}

/* Tombol bundar: bentuk dasar semua tombol sentuh. RATA, tanpa bayangan dan
   tanpa tepi timbul — cuma bidang warna pekat bergaris tepi gelap, sama
   seperti dunia 3D-nya yang juga bidang warna rata bergaris tepi.
   PEMBEDA VISUAL (GDD §13.5): aksi PRIBADI pemimpin berwarna merah pekat,
   perintah REGU berwarna gelap netral, dan SALVO biru karena ia sekali-pakai.
   Jadi cakupan tiap tombol terbaca dari warnanya tanpa menghafal nama. */
.bulat {
  position: absolute;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 3px solid var(--garis);
  background: #2c3445;
  color: #fff;
  cursor: pointer;
  pointer-events: auto;
  touch-action: none;
  transition: transform 0.07s, background 0.12s, filter 0.12s;
}
/* Umpan balik tekan tanpa bayangan: tombolnya mengecil sedikit. Cukup untuk
   terasa hidup, tidak memunculkan kembali kesan tombol timbul. */
.bulat:active { transform: scale(0.92); filter: brightness(1.15); }

/* Ikon mengisi 64% garis tengah tombol (dulu 46% — terlalu kecil, tandanya
   terlihat mengambang sebagai noktah di tengah lingkaran kosong).
   Angka ini bekerja sama dengan pengolahan berkasnya: tiap PNG dipangkas ke
   bingkai alfa yang rapat dengan margin cuma ~2%, jadi 64% di sini benar-benar
   berarti tanda setinggi ~62% garis tengah tombol. Kalau margin di berkasnya
   longgar (versi pertama pakai 9%), angka CSS sebesar apa pun tidak menolong —
   yang mengembang cuma ruang kosongnya. */
.bulat img { width: 64%; height: 64%; display: block; object-fit: contain; pointer-events: none; }
/* TEBAS tombolnya paling besar, jadi persentase yang sama akan membuat
   pedangnya terasa jauh lebih berat dari tetangganya. */
#gugus .tebas img { width: 58%; height: 58%; }

/*
 * Susunan gugus: TEBAS di pojok, SERBU/TAHAN/SALVO mengorbitnya pada busur
 * 180°–135°–90° dengan jarak yang persis sama satu sama lain, dan MUNDUR
 * tepat di atas SALVO.
 *
 * SERBU dan TAHAN ditukar dari susunan awal (dulu TAHAN di 180°, SERBU di
 * 135°) atas permintaan langsung — keduanya tetap bertetangga sebagai
 * pasangan yang paling sering ditukar, cuma urutannya dibalik.
 *
 * Ketiga tombol regu di busur (SERBU/TAHAN/SALVO) tetap seukuran satu sama
 * lain. MUNDUR sengaja dibuat sedikit LEBIH KECIL (atas permintaan langsung)
 * supaya posisinya di puncak gugus, yang paling jauh dari pangkal jempol dan
 * paling jarang dipakai, terasa proporsional — bukan tombol yang menuntut
 * perhatian sebesar TEBAS di sebelahnya.
 */
#gugus { position: absolute; inset: 0; pointer-events: none; }
#gugus .tebas {
  right: var(--tepi-x);
  bottom: var(--tepi-y);
  width: var(--serang);
  height: var(--serang);
  background: var(--kmd-tebas);
}

#gugus .cmd { width: var(--orbit); height: var(--orbit); }
/* Warna sikap regu, sama artinya dengan baris desktop (§40.7). */
#gugus [data-k="serbu"] { background: var(--kmd-serbu); }
#gugus [data-k="tahan"] { background: var(--kmd-tahan); }
#gugus [data-k="mundur"] { background: var(--kmd-mundur); }
#gugus [data-k="serbu"] {
  right: calc(var(--cx) + var(--r) - var(--orbit) / 2);
  bottom: calc(var(--cy) - var(--orbit) / 2);
}
#gugus [data-k="tahan"] {
  right: calc(var(--cx) + var(--r) * 0.7071 - var(--orbit) / 2);
  bottom: calc(var(--cy) + var(--r) * 0.7071 - var(--orbit) / 2);
}
#gugus [data-k="salvo"] {
  right: calc(var(--cx) - var(--orbit) / 2);
  bottom: calc(var(--cy) + var(--r) - var(--orbit) / 2);
}
/* Diposisikan lewat titik tengahnya (`--cx`/`--mundur`/2), bukan lewat sisi
   `--orbit` seperti tetangganya — supaya tetap terpusat tepat di atas SALVO
   dan berjarak `--sela` yang sama walau ukurannya sendiri lebih kecil. */
#gugus [data-k="mundur"] {
  right: calc(var(--cx) - var(--mundur) / 2);
  bottom: calc(var(--cy) + var(--r) + var(--orbit) / 2 + var(--sela));
  width: var(--mundur);
  height: var(--mundur);
}

/* FORMASI dan GANTI melanjutkan busur MENDATAR ke kiri dari SERBU (§40.9).
   Ukurannya sama persis dengan SERBU, dan selanya `--sela-fm` yang lebih lebar
   dari `--sela` busur — jarak itulah yang memberi tahu jempol bahwa dua tombol
   ini kelompok lain: yang di busur memerintahkan regu, yang di sini mengatur
   bentuk barisannya. */
#gugus .fm,
#gugus .ganti {
  bottom: calc(var(--cy) - var(--orbit) / 2);
  width: var(--orbit);
  height: var(--orbit);
}
#gugus .fm {
  right: calc(var(--cx) + var(--r) + var(--orbit) / 2 + var(--sela-fm));
  background: var(--kmd-fm);
}
#gugus .ganti {
  right: calc(var(--cx) + var(--r) + var(--orbit) * 1.5 + var(--sela-fm) * 2);
  background: var(--kmd-ganti);
}
/* FORMASI dan GANTI dulu meminta angka sendiri (74% untuk denah barisan) karena
   berkasnya memang cacat, bukan karena tandanya butuh ruang lain. Terukur pada
   PNG lamanya: isi `ganti.png` cuma 64,8% dari bingkainya dan pusatnya meleset
   +7,8% ke kanan, `f-blok.png` 91% dengan pusat +4,5% — jadi pada 64% tanda
   GANTI sebenarnya cuma setinggi 41,5% garis tengah tombol (itulah kenapa ia
   terlihat kecil dan mengambang ke kanan), dan denah barisan dipaksa 74% cuma
   untuk mengejar ketinggalan yang sama.

   Keempat berkasnya (ganti + tiga denah barisan) sudah dipangkas ulang ke
   bingkai alfanya dan ditengahkan, jadi sekarang isinya 95-96% dengan pusat
   meleset paling jauh 0,6% — sama seperti ikon lain yang sudah melewati
   pengolahan itu (lihat catatan `.bulat img` di atas). Akibatnya FORMASI ikut
   aturan 64% yang sama dengan tetangganya: tandanya jadi LEBIH KECIL dari
   sebelumnya (61,3% dari 67,3%) sekaligus seukuran SERBU di sebelahnya.

   GANTI tetap dapat angka sendiri, dan cuma itu satu-satunya yang tersisa:
   tandanya dua panah bergaris tipis, bukan bidang pejal seperti ikon lain, jadi
   pada persentase yang sama ia terbaca lebih ringan. */
#gugus .ganti img { width: 70%; height: 70%; }

#gugus .cmd.aktif { background: var(--kuning); color: #221800; }
/* FORMASI menyala dan bisa dibatalkan persis seperti sikap regu, walau ia
   bukan `.cmd` — lencana batalnya dipasang aturan `.bulat .batal` di bawah. */
#gugus .fm.aktif { background: var(--kuning); }
#gugus .fm.aktif .batal { display: grid; }

/* Lencana batal pada sikap yang sedang menyala. Sengaja lencana kecil di
   pojok, BUKAN mengganti ikon utamanya jadi tanda silang: kalau ikon utamanya
   yang diganti, satu-satunya cara membaca sikap regu yang sedang berjalan
   ikut hilang tepat pada saat sikap itu aktif.
   Warnanya MERAH — warna cancel/stop yang dikenal universal (dan sudah
   dipakai TEBAS untuk aksi pribadi), sehingga lencananya langsung terbaca
   sebagai "ketuk untuk batal". Isinya sekarang ikon cancel.png yang sama
   dipakai tombol Keluar, bukan huruf ✕ font — konsisten satu bentuk tanda
   silang di seluruh HUD. */
.bulat .batal {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 21px;
  height: 21px;
  display: none;
  place-items: center;
  border-radius: 50%;
  border: 2px solid var(--garis);
  background: var(--merah);
}
.bulat .batal img { width: 62%; height: 62%; object-fit: contain; }
#gugus .cmd.aktif .batal { display: grid; }

#gugus .sekali { background: var(--biru); }
#gugus .sekali.nyala { background: #8fdcff; color: #06222f; }
#gugus .sekali.gagal { background: var(--merah); }
/* Meredupkan IKONNYA saja, bukan seluruh tombol (dulu `opacity: 0.45` di
   tombolnya). `opacity` pada tombol ikut memudarkan pseudo-element angka
   hitung mundur di bawah ini — padahal angka itulah yang justru harus
   terbaca paling jelas selama isi ulang. Latarnya diredupkan terpisah
   supaya tombolnya tetap terbaca "belum siap". */
#gugus .sekali.isi-ulang { background: #2b4757; }
#gugus .sekali.isi-ulang img { opacity: 0.3; }

/* Hitung mundur isi ulang SALVO (§26.6).
   Ditulis di atas ikonnya, bukan di sampingnya: tombol bulat tidak punya
   ruang sisa, dan angka yang menempel di tepi akan tertimpa tombol
   tetangganya di busur. Ikonnya sendiri sudah diredupkan `isi-ulang`, jadi
   angka putih bergaris hitam di atasnya tetap terbaca. Isinya datang dari
   atribut `data-sisa` yang cuma disentuh waktu detiknya berganti — bukan
   tiap bingkai. */
#gugus .sekali.isi-ulang::after,
.panel-komando .cmd.sekali.isi-ulang::after {
  content: attr(data-sisa);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 20px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: #fff;
  text-shadow:
    -2px -2px 0 var(--garis), 2px -2px 0 var(--garis),
    -2px 2px 0 var(--garis), 2px 2px 0 var(--garis);
  pointer-events: none;
}
/* Di baris komando desktop tombolnya jauh lebih kecil dan berisi tulisan,
   jadi angkanya ikut mengecil supaya tidak menutupi kata "SALVO". */
.panel-komando .cmd.sekali { position: relative; }
.panel-komando .cmd.sekali.isi-ulang::after { font-size: 13px; }

/* -------------------------------------------------- lapisan penuh layar ----- */

.tirai {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(6, 10, 16, 0.72);
  backdrop-filter: blur(3px);
  pointer-events: auto;
  z-index: 5;
  padding: 16px;
}
.tirai[hidden] { display: none; }

/* ---- dialog pembelian (§57.41.12) --------------------------------------
   Lebarnya DIPATOK, tidak lagi menyusut ke lebar kalimat terpanjangnya:
   "Buka Yamato?" dan "Buka arena Padang Salju?" menghasilkan dua dialog yang
   lebarnya berbeda jauh untuk keputusan yang sama persis, dan dialog yang
   berganti ukuran tiap kali dibuka terbaca sebagai dua dialog berbeda. */
.beli-kotak { width: min(320px, 90vw); }
.beli-harga {
  display: grid;
  gap: 5px;
  padding: clamp(7px, 1.5vh, 11px) clamp(10px, 2vw, 14px);
  border-radius: clamp(8px, 1.6vh, 12px);
  background: #eef1f6;
}
.beli-baris {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: var(--fs-kecil);
  font-weight: 800;
  letter-spacing: var(--lc-biasa);
  color: #6b7590;
  /* Title Case, bukan ALL CAPS — label baris (Price, Balance After), bukan
     heading/tombol. */
  text-transform: capitalize;
}
.beli-baris b {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: #1b2030;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.beli-baris svg { display: block; width: 1em; height: 1em; }
/* Baris HARGA lebih besar dari baris sisa saldo: yang satu keputusan, yang
   satu akibatnya. */
.beli-baris.utama b { font-size: calc(var(--fs-label) * 1.35); }
/* Sisa saldo yang MINUS tidak pernah bisa terjadi (tombolnya mati waktu intan
   kurang), tapi kalau suatu hari bisa, ia harus terbaca sebagai peringatan
   dan bukan sebagai angka biasa. */
.beli-baris .kurang { color: var(--merah-bawah); }

/* Kartu putih bergaris tebal dengan bayangan bawah pejal — bentuk yang sama
   dipakai game kasual CrazyGames untuk semua dialognya. Di sinilah gaya itu
   paling pas: lapisan penuh layar memang sedang MENGHENTIKAN permainan, jadi
   ia boleh (dan sebaiknya) terlihat sebagai benda yang berbeda dari HUD
   tembus pandang di baliknya. */
.kotak {
  width: min(330px, 92vw);
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px;
  border-radius: 20px;
  border: 4px solid var(--garis);
  background: var(--kartu);
  color: #1b2030;
  text-align: center;
  /* HP mendatar cuma setinggi ±390 px; kartu hasil berisi judul, empat baris
     peringkat, dan tombol nyaris melampauinya. Dibatasi tinggi layar dan
     dibolehkan digulir supaya baris terakhir tidak pernah terpotong di luar
     jangkauan. */
  max-height: calc(100vh - 24px);
  max-height: calc(100dvh - 24px);
  overflow-y: auto;
}
.kotak.lebar { width: min(430px, 94vw); }
/* Judul kartu dialog: TINTA, bukan biru.
   Birunya (#3b5bfd) tidak ada di mana pun lagi dalam game ini — palet arenanya
   kuning/merah/hijau/biru-baja di atas garis tepi hitam tebal, dan biru terang
   itu satu-satunya warna yang datang dari tempat lain. Yang paling terasa di
   dialog konfirmasi, tempat kalimatnya justru harus terbaca sebagai pertanyaan
   yang serius, bukan sebagai pranala. */
.kotak-judul {
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.3px;
  line-height: 1.35;
  color: var(--garis);
  margin-bottom: 2px;
}
/* Lencana tanya. Dialog ini SELALU menanyakan sesuatu yang tidak bisa
   dibatalkan (menyerah, keluar), dan tanda kuning bergaris tebal memakai bahasa
   yang sama dengan tombol-tombol di baliknya — bukan gaya dialog dari game
   lain. */
#tanya-teks { display: flex; flex-direction: column; align-items: center; gap: 9px; }
#tanya-teks::before {
  content: '!';
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border: 3px solid var(--garis);
  border-radius: 50%;
  background: var(--kuning);
  color: #221800;
  font-size: 20px;
  line-height: 1;
}
#tanya .kotak { gap: 13px; padding: 20px 18px 18px; }
/* Di bawah garis ini bukan setelan lagi, melainkan jalan keluar. */
.setel-pisah { height: 2px; margin: 5px 2px 3px; border-radius: 2px; background: #ccd5e5; }

/* §57.68 — DUA JALAN KELUAR SEBARIS, diminta langsung.

   Dibungkus `<div>` sendiri, bukan diberi `flex-direction: row` pada kartunya:
   kartu setelan berisi TIGA baris setelan di atas garis pemisah yang harus
   tetap bertumpuk ke bawah. Membalik arah kartunya akan menyeret ketiganya
   ikut sebaris.

   `flex: 1 1 0` menyamakan lebar keduanya — dua jalan keluar yang berdiri
   berdampingan dengan lebar berbeda membuat yang lebih lebar terbaca sebagai
   pilihan utama, padahal SURRENDER justru yang paling menghukum. */
.setel-keluar {
  display: flex;
  gap: clamp(6px, 1.4vw, 10px);
}
.setel-keluar .tbl {
  flex: 1 1 0;
  min-width: 0;
  white-space: nowrap;
  /* §57.68: TINGGINYA DISAMAKAN. Terukur tanpa baris ini: 53 px lawan 45 px.
     Sebabnya BUKAN sisipan dan bukan bibir `--bawah` (dua tebakan pertama,
     keduanya salah) — keduanya terukur identik: sisipan 13/13 px, garis 3 px,
     tinggi teks 16 px. Yang berbeda KOTAK ISINYA: 21 px lawan 13 px.

     Artinya salah satu tombol dipepatkan ke `line-height`-nya sementara yang
     lain memakai tinggi baris alami huruf Fredoka. Menyamakan sisipan tidak
     akan pernah menyelesaikannya, karena sisipannya memang sudah sama.

     `min-height` SEMPAT DICOBA dan gagal: ia menaikkan KEDUANYA 8 px (53->61
     dan 45->53) sehingga selisihnya utuh — bukti bahwa selisih itu bukan soal
     lantai melainkan isi yang memang berbeda tinggi.

     `height` pasti + flex pemusat yang menyelesaikannya: tingginya berhenti
     bergantung pada isi sama sekali, dan labelnya dipusatkan di dalam kotak
     yang tingginya sudah ditentukan. Aman karena kedua label satu baris
     (`white-space: nowrap` di atas) — tidak ada yang bisa tumbuh melewatinya. */
  height: 53px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
/* KELUAR PERTANDINGAN diberi jarak di KEDUA sisinya, bukan cuma di atas.
   Terukur, tetangga bawahnya (TUTUP) cuma berjarak 7 px — jarak yang sama
   dengan jarak antarbaris setelan yang tidak berakibat apa-apa, padahal salah
   satunya membuang pertandingan yang sedang berjalan dan satunya lagi cuma
   menutup lembar. Warna merah membedakan keduanya; jarak yang sama justru
   mengatakan keduanya sederajat. */
#s-keluar { margin-bottom: 8px; }
.kotak-baris { display: flex; gap: 10px; }
.kotak-baris .tbl { flex: 1; }
.kotak .kecil { color: #5b667e; opacity: 0.85; }

/* Bayangan tebalnya lahir dari SATU peubah, `--bawah`, dan bukan dari sepasang
   aturan per warna tombol. Tiap ragam tombol cuma mengganti nilainya; aturan
   `box-shadow` dan aturan `:active`-nya ditulis sekali di sini. Kalau tiap ragam
   menulis bayangannya sendiri, tiap ragam juga harus ingat menulis ulang
   bayangan-ditekannya — dan yang lupa akan tetap terlihat benar sampai ada yang
   menekannya, persis jenis meleset yang tidak menghasilkan galat apa pun.

   Bentuknya (bayangan pejal 4 px tanpa kabur, ditekan = turun 3 px + bayangan
   menyusut jadi 1 px) bukan gaya baru: `.pintu-kembali` dan `.mode` di berkas
   ini sudah memakainya. Yang berubah cuma tombol dialog akhirnya ikut, jadi
   tidak ada lagi dua bahasa tombol dalam satu game. Menggantikan `scale(0.97)`,
   yang mengecilkan tombol dari keempat sisinya — gerak yang terbaca seperti
   benda menjauh, bukan seperti tombol yang tertekan ke bawah. */
.tbl {
  --bawah: #b6c0d4;
  padding: 13px 14px;
  border: 3px solid var(--garis);
  border-radius: 13px;
  background: #eef1f6;
  color: #1b2030;
  font-size: 13px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0.7px;
  cursor: pointer;
  transition: filter 0.12s, transform 0.07s;
}
.tbl:hover { filter: brightness(1.06); }
.tbl:active { transform: translateY(3px); }
/* Baris PILIHAN dan tombol sekunder: netral, bukan biru pejal.
   Dulu ketiga baris setelan memakai biru jenuh (#7c9bff, hue 226) sementara di
   kartu yang sama berdiri hijau (hue 145) dan merah (hue 6) — tiga hue yang
   hampir berjarak sama di roda warna, resep yang dipakai kalau tujuannya
   warna-warna itu saling berlomba diperhatikan. Padahal "Sudut pandang" dan
   "Musik" bukan ajakan bertindak; keduanya cuma daftar. Dengan warna netral di
   sini, yang tersisa berwarna tinggal dua tombol yang memang punya akibat —
   dan kontras yang tersisa jadi berarti, bukan bising. */
.tbl.datar { background: #dee5f3; color: #2a3450; --bawah: #a8b5cf; }
/* Baris setelan yang punya NILAI: label di kiri, keadaan sekarang di kanan
   sebagai keping gelap. Tanpa nilai yang terpampang, tombol "Sudut pandang"
   tidak memberi tahu pemain ia sedang di mana — ia harus menekannya dulu untuk
   tahu, dan itu berarti mengubah sesuatu cuma untuk membacanya. */
.setel-baris { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.setel-baris b {
  padding: 3px 10px;
  border: 2px solid var(--garis);
  border-radius: 999px;
  background: rgba(11, 22, 51, 0.22);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.3px;
  white-space: nowrap;
}
.tbl.utama { background: var(--hijau); color: #06240f; --bawah: var(--hijau-bawah); }
/* Merahnya diturunkan dari `--merah` (#ff5d4d, lightness 65%) ke 57% supaya
   sekelas dengan hijau `.tbl.utama` (48%). Sebelumnya tombol BAHAYA justru
   yang paling terang di kartu — lebih menonjol dari tombol yang disarankan,
   padahal ia yang seharusnya tidak ditekan tanpa sengaja. Hue-nya tetap merah:
   yang diseragamkan terang dan jenuhnya, bukan warnanya. */
.tbl.bahaya { background: #e8503f; color: #2b0a06; --bawah: var(--merah-bawah); }
/* Ragam BAHAYA yang lebih ringan, untuk waktu DUA jalan keluar berdiri
   bersebelahan (§57.41.9 memindahkan MENYERAH dan KELUAR ke lembar setelan
   yang sama). Dua tombol merah pejal bertumpuk terbaca sebagai satu dinding
   merah: pemain harus MEMBACA keduanya untuk tahu mana yang lebih berat,
   padahal bedanya justru yang paling perlu terlihat — MENYERAH tercatat kalah,
   KELUAR tidak. Yang pejal dipakai untuk akibat yang lebih besar; yang ini
   bergaris tepi merah dengan isi terang untuk yang lebih ringan. */
.tbl.bahaya.tipis {
  background: #fbe4e0;
  border-color: var(--merah-bawah);
  color: var(--merah-bawah);
  --bawah: #e3b4ab;
}
/* Pilihan KETIGA: ada dan bisa ditekan, tapi sengaja tidak berlomba dengan dua
   tombol pejal di atasnya. "Kembali ke menu" adalah jalan keluar, bukan langkah
   berikutnya yang disarankan — dan tiga tombol pejal sederajat di satu kartu
   membuat pemain harus membaca ketiganya sebelum bisa memilih. */
/* Tiga tombol jalan di kartu hasil, DIURUT MENURUT KEJENUHAN WARNA.
 *
 * Dulu KEMBALI hampir putih (`.samar`, latar #f3f6fb) — bekas susunan lama
 * waktu ia tombol keempat yang bertumpuk di bawah dan memang harus mundur.
 * Dalam satu baris bertiga, satu tombol nyaris tanpa warna di sebelah dua
 * tombol berwarna tidak terbaca sebagai "pilihan yang lebih tenang", ia terbaca
 * sebagai lubang.
 *
 *   KEMBALI    #8b98b5  biru-batu, jenuh 17%   mundur
 *   MAIN LAGI  --biru   #4b90e2, jenuh 72%     ulangi yang sama
 *   LANJUT     --hijau  #2fc86b, jenuh 62%     maju satu tingkat
 *
 * Ketiganya duduk di busur biru->hijau roda warna, jadi tidak ada yang saling
 * berlomba seperti tiga hue berjarak sama (lihat catatan `.tbl.datar` di atas).
 * Yang membedakan derajatnya KEJENUHAN, bukan hue: makin ke kanan makin
 * berwarna, dan urutan itu sama persis dengan urutan "seberapa maju langkah
 * ini". Hurufnya semua gelap, mengikuti bahasa tombol game ini (hijau #06240f,
 * kuning #221800) — bukan putih, yang akan membuat ketiganya terbaca sebagai
 * tombol dari game lain.
 *
 * Waktu LANJUT tidak ada, MAIN LAGI naik jadi `.utama` (hijau): yang bergaris
 * tebal selalu langkah paling maju yang tersedia, bukan tombol yang itu-itu
 * juga. Lihat `usai()` di js/main.js. */
.tbl.kembali { background: #8b98b5; color: #141b2b; --bawah: #5a678a; }
.tbl.ulang { background: var(--biru); color: #06203f; --bawah: var(--biru-bawah); }

/* Judul hasil: huruf gemuk bergaris tepi hitam, ditiru dari judul game acuan.
   Garis tepinya dibuat dari empat bayangan teks, bukan `-webkit-text-stroke`
   yang menggerus bagian dalam huruf sampai kurus di ukuran besar. */
.hasil-judul {
  font-size: clamp(30px, 8vh, 46px);
  font-weight: 800;
  letter-spacing: 2px;
  text-shadow:
    -2px -2px 0 var(--garis), 2px -2px 0 var(--garis),
    -2px 2px 0 var(--garis), 2px 2px 0 var(--garis);
}
.hasil-judul.menang { color: var(--kuning); }
.hasil-judul.kalah { color: var(--merah); }
.hasil-judul.seri, .hasil-judul.keluar, .hasil-judul.menyerah { color: #9aa7bd; }
/* Satu baris keterangan di bawah pernyataan. Warnanya kelabu dan hurufnya jauh
   lebih kecil dari judul dengan sengaja: ia menjawab "kenapa/lalu apa", bukan
   "apa" — dan begitu ia mulai berlomba dengan judul, kartunya punya dua judul.
   `text-wrap: balance` supaya kalau ia terpaksa jadi dua baris di kartu paling
   sempit, keduanya sama panjang, bukan satu baris penuh + satu kata. */
.hasil-sebab {
  /* Dinaikkan dari 12 px (§57.42.7). Ia memang harus kalah jauh dari judulnya
     — itulah gunanya — tapi pada 12 px ia sudah lebih kecil daripada kepala
     kolom papan di bawahnya, jadi satu-satunya kalimat di kartu ini ditulis
     dengan huruf terkecil di kartu ini. */
  font-size: 13.5px;
  line-height: 1.35;
  color: #5b667e;
  font-weight: 600;
  /* Title Case, bukan ALL CAPS: ini kalimat pendek ("Round 3 comes next"),
     bukan heading/tombol — revisi prinsip kapital (lihat blok konsolidasi
     di ujung berkas). Ditulis sebagai `text-transform`, bukan huruf besar
     di sumbernya, supaya sumbernya sendiri tetap terbaca sebagai kalimat
     waktu disunting. */
  text-transform: capitalize;
  letter-spacing: 0.5px;
  text-wrap: balance;
}
.hasil-sebab[hidden] { display: none; }
.hasil-cerita { display: flex; flex-direction: column; gap: 4px; }
.hasil-papan { display: flex; flex-direction: column; gap: 5px; }
/* `[hidden]` HARUS dituliskan ulang di sini. Aturan `display` mana pun dari
   lembar penulis mengalahkan `display: none` bawaan peramban, jadi tanpa baris
   ini `hasil-papan.hidden = true` di JS tidak menyembunyikan apa pun.
   Tidak ada lagi jalur yang menyembunyikannya sejak §57.39.8 (hadiahnya
   tinggal DI DALAM papan), tapi barisnya ditahan: perangkap yang sama sudah
   dua kali menggigit di berkas ini, dan yang memasang `hidden` berikutnya
   tidak akan mencari sebabnya di lembar gaya. */
.hasil-papan[hidden] { display: none; }
/* Papan peringkat mengalir per LAJUR, bukan per baris: dengan `--lajur: 2`, sel
   ke-1..--baris mengisi lajur kiri dari atas ke bawah, sisanya lajur kanan.
   Itulah yang membuat "1..4 di kiri, 5..8 di kanan" jadi sifat susunannya dan
   bukan sesuatu yang perlu dihitung ulang tiap kali jumlah bangsanya berubah.
   Kedua peubahnya disetel `gambarPapan()` di js/main.js — termasuk waktu cuma
   ada satu lajur, jadi tidak ada cabang khusus untuk kasus yang sekarang. */
/* SATU KOTAK untuk seluruh papan, bukan satu kotak per baris (§57.40).
   Sampai putaran ini tiap baris menggambar `border: 3px` + `border-radius`
   sendiri, jadi papan empat baris berarti DELAPAN garis tebal mendatar
   bertumpuk berjarak nyaris sama — mata tidak melihat satu tabel, ia melihat
   empat benda terpisah yang kebetulan sejajar. Di panel juara tiap baris
   bahkan memuat tiga bingkai bersarang (baris, pil bendera, pil hadiah) dalam
   tinggi 24 px.

   Garis tebalnya sekarang cuma DUA — tepi luar papan — dan barisnya dipisah
   garis rambut. Ciri "kotak hitam tebal" permainan ini tidak hilang, ia
   dipindahkan ke tingkat yang benar: papan adalah bendanya, baris adalah
   isinya.

   `row-gap: 0` wajib: dengan celah, garis rambut pemisahnya akan mengambang
   di tengah pita kosong alih-alih menempel jadi batas antar-baris. Jarak
   antar-baris sekarang lahir dari `--baris-y`, satu tempat, bukan dua.

   `column-gap` DIPERTAHANKAN untuk papan dua lajur: yang tampak di celah itu
   sekarang latar papannya sendiri (bukan latar kartu, karena `overflow:
   hidden` + latar di sini), jadi ia terbaca sebagai kanal pemisah di dalam
   satu papan, bukan sebagai dua papan yang berdampingan. */
/* `.hasil-tabel` sekarang cuma WADAH; yang jadi kotak bergaris adalah tiap
   `.hasil-kolom` di dalamnya (§57.41.17).

   Versi sebelumnya menaruh kedua lajur di dalam SATU kotak dengan
   `column-gap: 12px` di tengahnya. Celah itu memperlihatkan latar kotaknya
   sendiri, jadi ia terbaca sebagai saluran di dalam satu papan — bagus selama
   itu memang yang dimaksud, tapi akibatnya garis rambut pemisah baris lajur
   KIRI berhenti di tengah papan dan tidak pernah bertemu tepi mana pun. Itulah
   "garis tepi tabel yang putus". Dua kotak yang masing-masing menutup dirinya
   sendiri tidak punya kasus itu sama sekali. */
.hasil-tabel {
  display: flex;
  align-items: flex-start;
  gap: clamp(8px, 1.6vw, 13px);
}
.hasil-kolom {
  flex: 1 1 0;
  min-width: 0;
  border: 3px solid var(--garis);
  border-radius: clamp(9px, 1.8vh, 13px);
  background: #eef1f6;
  overflow: hidden;
}

/* Kepala kolom dan baris peringkat memakai GRID yang sama, dituliskan sekali.
   Dulu barisnya `flex` dengan `min-width` di angkanya — cukup untuk terlihat
   rapi, tidak cukup untuk menjamin bahwa kepala kolom benar-benar berdiri di
   atas kolom yang dimaksudnya. Grid dengan lebar kolom yang sama persis
   membuat "sejajar" jadi sifat susunannya, bukan hasil yang perlu diperiksa
   ulang tiap kali angkanya bertambah satu digit. */
.hasil-baris,
.hasil-kepala {
  display: grid;
  /* Lebar kolom angkanya dalam PIKSEL, bukan `em`. Terukur: dengan `3.6em`
     kepala kolom meleset 10 px di 892x412 dan 15,4 px di 1366x768 — kepala
     kolom sengaja berhuruf lebih kecil daripada barisnya, jadi `em` yang sama
     di kedua tempat berarti lebar yang berbeda. Satuan yang ikut ukuran huruf
     tidak bisa dipakai untuk menyejajarkan dua elemen yang ukuran hurufnya
     memang beda. */
  /* ENAM kolom: NO, WARBAND (panji + nama bangsa), USER, FLAGS, ALIVE, REWARD
     (§57.41.16). Titik warna 11 px yang dulu berdiri sendiri sebagai kolom
     kedua sudah masuk KE DALAM kolom WARBAND sebagai panji — satu kolom untuk
     satu benda, bukan gambar di satu kolom dan namanya di kolom sebelahnya. */
  grid-template-columns: 18px minmax(0, 1fr) 40px 38px 34px 54px;
  align-items: center;
  gap: 8px;
}
/* Kolom WARBAND: panji lalu nama bangsanya. Panjinya gambar yang SAMA PERSIS
   dengan yang berkibar di bentengnya (`gambarPanji`, dari `teksturPanji()`) —
   dua gambar terpisah untuk benda yang sama pasti menyimpang suatu hari.
   Rasio 3:4 mengikuti kanvas panjinya supaya lambangnya tidak gepeng. */
.hasil-baris .wb { display: flex; align-items: center; gap: 7px; min-width: 0; }
.hasil-baris .wb img {
  display: block;
  width: 15px;
  height: 20px;
  border: 2px solid rgba(0, 0, 0, 0.35);
  border-radius: 3px;
  object-fit: cover;
  flex-shrink: 0;
}
/* Kolom USER lebih redam daripada WARBAND: yang menjawab "siapa ini" nama
   orangnya, tapi yang dicari mata pertama kali di papan peringkat tetap
   benderanya. */
.hasil-baris .us {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: center;
  font-size: 11px;
  font-weight: 800;
  color: #6b7590;
}
.hasil-baris.kamu .us { color: #2f6fd0; }
.hasil-baris .us small {
  margin-left: 3px;
  font-size: 8.5px;
  font-weight: 900;
  color: #c0533f;
}
/* Kepala kolom sekarang BARIS PERTAMA di dalam papan, bukan tulisan kelabu
   yang mengambang di atasnya. Dulu jaraknya ke baris pertama sama persis
   dengan jarak antar-baris (`row-gap`), jadi ia terbaca sebagai baris kelima
   yang kebetulan kelabu. Latar sedikit lebih tua + garis tebal di bawahnya
   yang membuatnya jadi kepala.

   Sisipan mendatarnya SAMA PERSIS dengan barisnya sekarang (dulu `+3px`,
   mengganti tebal garis tepi tiap baris yang sudah tidak ada) — satu peubah,
   satu nilai, jadi kolomnya mustahil menyimpang. */
.hasil-kepala {
  padding: clamp(3px, 0.8vh, 6px) var(--baris-x, 11px);
  border-bottom: 3px solid var(--garis);
  background: #dbe1ee;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.6px;
  color: #6b7590;
}
/* Nomor peringkat. Tanpa nama kolom di atasnya — angka 1..8 berderet menurun di
   tepi kiri daftar terurut tidak perlu diberi tahu bahwa ia peringkat. */
.hasil-baris .rank { color: #8792a8; font-size: 11px; text-align: right; }
.hasil-kepala span:not(.wb) { text-align: center; }
/* NO rata KANAN di kepala maupun di barisnya — angka rata kanan di bawah
   kepala rata tengah adalah persis ketidaklurusan yang diminta hilang. */
.hasil-kepala span:first-child { text-align: right; }
.hasil-kepala .wb { text-align: left; }
.hasil-baris {
  padding: var(--baris-y, 7px) var(--baris-x, 11px);
  /* Garis RAMBUT di ATAS, bukan di bawah. Di papan dua lajur, `:last-child`
     cuma mengenai baris terakhir lajur KANAN — dengan garis bawah, lajur kiri
     meninggalkan satu garis menggantung di tepi dalam papan. Garis atas tidak
     punya kasus itu sama sekali; yang perlu dikecualikan cuma baris pertama
     sesudah kepala kolom, dan kepala kolom sudah punya garis tebalnya
     sendiri. */
  border-top: 1px solid #ccd4e6;
  font-size: 13px;
  font-weight: 700;
}
.hasil-kepala + .hasil-baris { border-top: 0; }
/* DUA tanda yang berdiri sendiri-sendiri, karena keduanya menjawab pertanyaan
   yang berbeda: "siapa yang menang" (isi hijau) dan "yang mana aku" (lingkar
   biru). Dulu cuma juara yang ditandai — jadi di panel KALAH, baris pemain
   tenggelam di antara tiga baris lain yang bentuknya persis sama, dan di panel
   MENANG kedua tanda itu jatuh pada baris yang sama sehingga tidak ada yang
   bisa tahu hijau itu berarti apa. Lingkar dipakai untuk "kamu", bukan warna
   isi, supaya ia tetap terbaca di atas baris juara yang sudah hijau. */
.hasil-baris.juara { background: #cdf3dd; }
/* Nama regu pemain diberi warna, bukan tanda "(kamu)" di belakangnya:
   panel ini sudah berbahasa Inggris dan "You (you)" menyebut hal yang sama
   dua kali (alasan yang sama mencabutnya dari baris peserta lobi). */
.hasil-baris.kamu .nm { color: #2f6fd0; }
/* Baris pemain sendiri TANPA lingkar/bayangan di sekelilingnya (§57.39.8).
   Lingkar itu meluber ke luar tepi baris dan memakan celah antar baris,
   sehingga tetangga atas-bawahnya ikut terdorong dan deretnya berhenti terlihat
   rata — persis alasan yang sama membuat papan turnamen membuangnya lebih dulu
   (§57.22.3). Penandanya sekarang teks "(kamu)" tebal berwarna di dalam nama
   bangsanya, yang tetap terbaca di atas latar hijau baris juara karena ia teks,
   bukan warna latar. */
/* HADIAH tanpa keping sama sekali. Pil biru-muda bergaris tepi yang dulu
   berdiri di sini adalah bingkai KETIGA dalam satu baris (baris, pil bendera,
   pil hadiah) — dan begitu barisnya sendiri kehilangan bingkainya, satu-
   satunya alasan pil ini ada ikut gugur: yang memisahkan kolom sekarang
   kolomnya, dan yang menamainya kepala kolom REWARD di atasnya. Yang tersisa
   lambang intan + angkanya, dan itu memang sudah menyebut seluruhnya. */
.hasil-baris .hdh {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: #1b2030;
}
.hasil-baris .hdh svg { width: 11px; height: 11px; flex-shrink: 0; }
/* Yang tidak menerima apa-apa: tanda pisah, tanpa pil. Kotak berwarna berisi
   "—" akan terbaca seperti hadiah bernilai nol yang tetap diberikan; yang benar
   adalah tidak ada penerima sama sekali. */
.hasil-baris .hdh.nihil { border: none; background: none; color: #a8b0c2; }
.hasil-baris .nm { text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hasil-baris b { text-align: center; font-variant-numeric: tabular-nums; font-weight: 800; }
/* SATU-SATUNYA keping berwarna yang tersisa di baris, dan itu memang
   maksudnya: bendera adalah angka yang memutus pertandingan waktu jam habis,
   jadi ia yang pantas jadi satu-satunya yang menonjol. Garis tepi hitamnya
   dicabut (tinggal isian kuning lembut berbentuk kotak, seukuran radius papan
   yang mengurungnya) — garis tebal di dalam papan yang sudah bergaris tebal
   adalah bingkai di dalam bingkai, persis cacat yang baru saja dibereskan. */
.hasil-baris .bd {
  padding: 2px 0;
  border-radius: 5px;
  background: #ffcf3f;
  color: var(--garis);
  font-weight: 900;
}

/* Kaki panel dijauhkan SATU TINGKAT dari papannya. `.kotak` cuma punya satu
   `gap`, jadi tanpa baris ini jarak judul→papan, papan→tombol, dan jarak di
   dalam papan semuanya sama — dan panel tanpa tingkatan jarak terbaca sebagai
   tumpukan, bukan sebagai tiga bagian. Ditulis `margin-top` pada kakinya,
   bukan `gap` yang diperbesar: `gap` berlaku pada semua celah sekaligus. */
.hasil-aksi { display: flex; flex-direction: column; gap: 9px; margin-top: clamp(2px, 0.9vh, 7px); }
.hasil-aksi .tbl { text-align: center; }
/* JARAK KHUSUS DI DUA SAMBUNGAN kartu hasil (§57.42.7) — aturan yang sama
   dengan `.tur-hasil-kotak` di css/turnamen.css, dan alasannya sama: yang
   diminta terlihat adalah pemisahan judul / papan / kaki, bukan kartu yang
   seluruh isinya renggang. Menaikkan `gap` kartunya sendiri akan ikut
   merenggangkan baris-baris DI DALAM papan. */
.hasil-kotak .hasil-cerita { margin-bottom: clamp(4px, 1.2vh, 10px); }
.hasil-kotak .hasil-papan { margin-bottom: clamp(3px, 1vh, 8px); }
/* Tombol kaki kartu hasil dinaikkan sedikit supaya sepadan dengan judul
   30-46 px di atasnya — sisipan tegak dan ukuran huruf, bukan lebarnya. */
.hasil-nav .tbl { padding: 15px 13px; font-size: 14px; }

/* Tiga tombol jalan, SATU baris, lebar sama.
   `flex: 1 1 0` — bukan `1 1 auto`: lebar dasar yang berbeda-beda membuat tiga
   tombol berakhir dengan lebar berbeda-beda semata-mata karena labelnya berbeda
   panjang, dan deret tombol yang lebarnya acak terbaca seperti tata letak yang
   lepas, bukan seperti pilihan.

   Pasangan `max-width` + `space-between` yang membuat susunan yang diminta lahir
   sendiri, tanpa satu pun cabang khusus:
   - kartu sempit (papan satu lajur, ±394 px isi): sepertiga = 126 px, jauh di
     bawah batas, jadi ketiganya melar mengisi baris dan saling bersentuhan;
   - kartu lebar (papan dua lajur, ±724 px isi): sepertiga = 241 px terpotong
     jadi 210 px, sisa ruangnya dibagi `space-between` — KEMBALI mepet tepi
     kiri, LANJUT mepet tepi kanan, dan MAIN LAGI jatuh PERSIS di tengah karena
     kedua tetangganya selebar sama. Ketengahannya sifat susunan, bukan angka
     yang dihitung. */
.hasil-nav {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 10px;
}
/* §57.63 — TULISAN TOMBOL TETAP SEBARIS, tombolnya boleh memanjang. Diminta
   langsung, dan yang diperbaiki cacat terukur: `flex: 1 1 0` memaksa ketiga
   tombol sama lebar (123 px di 1280x720), dan "SAVE STREAK" — label
   terpanjang — pecah jadi DUA BARIS di dalam tombolnya sendiri sementara
   BACK dan PLAY AGAIN di kanan-kirinya tetap sebaris.

   `flex-basis: auto` menggantikan `0`: lebar dasar tiap tombol jadi lebar
   LABELNYA, lalu `flex-grow: 1` membagi sisa ruang secara merata di atas
   dasar itu. Yang berlabel panjang berakhir sedikit lebih lebar daripada
   tetangganya — persis "bisa diperpanjang jika kurang ruang" yang diminta —
   dan tidak ada satu pun yang lebih sempit daripada labelnya sendiri.

   `white-space: nowrap` menutup sisanya: di layar yang benar-benar sempit,
   `flex-shrink` masih boleh memangkas tombol di bawah lebar labelnya, dan
   tanpa baris ini pemangkasan itu kembali memecah labelnya jadi dua baris. */
/* §57.68 — KETIGANYA SAMA LEBAR LAGI, diminta langsung ("semua tombol dipanel
   (3 tombol) itu tolong samakan panjangnya dengan tombol paling panjang").

   Ini MEMBALIK `flex-basis: auto` §57.63 di atas, dan yang membuat pembalikan
   itu aman adalah sebab lamanya sudah hilang. §57.63 memakai `auto` karena
   `flex: 1 1 0` memberi ketiganya 123 px sementara "SAVE STREAK" menuntut
   lebih, sehingga labelnya pecah dua baris. Sekarang labelnya berubah:
   tombol kiri jadi "BACK TO MENU" (§57.68), yang JUSTRU lebih panjang
   daripada "SAVE STREAK" — jadi lebar bersama yang ditentukan label
   terpanjang sudah cukup untuk ketiganya.

   `flex-basis: 0` + `flex-grow: 1` membagi ruang RATA sehingga ketiganya
   persis sama lebar; `min-width: max-content` menaikkan lantainya ke label
   terpanjang, jadi tidak ada yang bisa dipangkas sampai labelnya pecah.
   Keduanya harus berpasangan: `basis: 0` sendirian mengulang cacat §57.63,
   `max-content` sendirian membuat lebarnya kembali tidak sama.

   `max-width` DIBUANG: batas 210 px per tombol akan menahan pertumbuhan
   sebelum ketiganya sempat sama lebar di kartu yang lebar. */
.hasil-nav .tbl {
  flex: 1 1 0;
  min-width: max-content;
  white-space: nowrap;
}
/* §57.68: aturan `:has(#b-iklan[hidden]) { max-width: none }` DIBUANG bersama
   `max-width` yang jadi alasannya. Sejak ketiga tombol memakai `flex: 1 1 0`,
   sisa ruang selalu habis dibagi rata di antara tombol yang TAMPIL — dua
   maupun tiga — jadi lubang 300 px yang dulu diperbaiki aturan ini tidak
   mungkin lagi terbentuk, dan tidak ada lagi batas yang perlu dilepas. */

/* TOMBOL IKLAN kartu hasil (57.39.9): keping ikon "putar" berwarna sorot, lalu
   apa yang didapat di sebelahnya.

   Badannya KELABU, bukan kuning maupun hijau. Kuning dulu dipakai supaya ia
   tidak terlihat sederajat dengan langkah utama — alasan yang masih berlaku —
   tapi sejak ia berdiri SEBARIS dengan dua tombol jalan, kuning justru jadi
   warna paling terang di baris itu dan menang atas MAIN LAGI yang hijau. Yang
   membedakannya sekarang bukan warna badannya melainkan KEPING IKONNYA: satu-
   satunya benda bersorot di seluruh baris, cukup menarik mata tanpa pernah
   tertukar dengan tombol jalan di kiri-kanannya.

   `display: flex` di sini mengulang perangkap yang sudah pernah kena `.tbl.dua`
   dan `.hasil-papan`: `display` apa pun dari lembar penulis mengalahkan
   `display: none` bawaan peramban untuk `[hidden]`, jadi tombol yang JS
   sembunyikan akan tetap terbit. `.tbl[hidden]` di bawah yang mencegahnya. */
.tbl.iklan {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 8px 12px;
  background: #dee5f3;
  color: #2a3450;
  --bawah: #a8b5cf;
}
.tbl[hidden] { display: none; }
.tbl.iklan b {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.4px;
}
.tbl.iklan b svg { width: 12px; height: 12px; flex-shrink: 0; }
/* Keping ikonnya: kuning bergaris tepi penuh, ukuran tetap. Kuning di sini
   tidak berbenturan dengan "kuning = intan" — ikon di dalamnya memang lambang
   iklan berhadiah, dan tombol iklan di pojok menu pun kuning seluruhnya. */
.iklan-tanda {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border: 2.5px solid var(--garis);
  border-radius: 7px;
  background: var(--kuning);
  color: var(--garis);
}
.iklan-tanda svg { display: block; width: 74%; height: 74%; }
/* Sudah ditonton: bukan "mati", melainkan "lunas". Karena itu ia berubah jadi
   hijau muda yang sama dengan baris juara, bukan diredupkan seperti tombol
   yang tidak bisa ditekan. */
.tbl.iklan.siap { background: #cdf3dd; color: #06240f; --bawah: #8fc9a8; }
.tbl.iklan.siap .iklan-tanda { background: #8fd8ac; }

/* Kartu MELEBAR begitu papannya pecah jadi dua lajur, di tinggi layar apa pun.
   Ditulis di luar @media dengan sengaja: terukur, tanpa baris ini kartu di
   1366x768 tetap selebar 430 px sementara papannya sudah dua lajur — dua lajur
   selebar 190 px, dan kedelapan nama bangsanya terpotong. Yang memaksa lebar
   adalah jumlah lajurnya, bukan tinggi layarnya. */
.kotak.lebar.hasil-kotak.banyak { width: min(760px, 94vw); }
.tbl:disabled { cursor: default; }
.tbl:disabled:hover { filter: none; }
.tbl:disabled:active { transform: none; }

/* Iklan contoh `?iklan=uji` (js/iklan.js) — hanya ada selama SDK belum
   terpasang, dan tidak pernah muncul tanpa argumen itu. */
.iklan-contoh .iklan-hitung {
  font-size: 40px;
  font-weight: 800;
  color: #3b5bfd;
  font-variant-numeric: tabular-nums;
}

/* Layar PENDEK — HP mendatar, tempat game ini sebenarnya dimainkan. Pada
   892x412 tirai cuma menyisakan ±388 px tinggi.

   Susunannya TIDAK berubah di sini, cuma kepadatannya. Versi sebelumnya
   memindahkan tombol ke samping judul supaya kartunya lebih pendek; itu memang
   menghemat ±90 px, tapi ongkosnya judul yang tidak lagi berdiri sendiri —
   satu-satunya bagian kartu yang benar-benar dibaca pada detik pertama, dan
   yang mestinya paling terakhir dikorbankan. Yang dipangkas di sini
   gantinya: sisi kartu, ukuran judul, dan padding baris peringkat. */
@media (max-height: 560px) {
  /* `.kotak.lebar` ikut ditulis di pemilih ini semata-mata karena kekhususan:
     lebar 430 px di sana punya dua kelas, dan `.hasil-kotak` sendirian kalah
     darinya — terukur sebagai kartu yang mengabaikan seluruh blok ini. */
  .kotak.lebar.hasil-kotak { padding: 12px 16px; gap: 7px; }
  /* Judulnya ikut TINGGI layar, bukan lebarnya: yang langka di sini tinggi. */
  .hasil-judul { font-size: clamp(22px, 7vh, 34px); }
  /* 4 px, bukan 5: dengan baris keterangan terpasang, kartu MENANG empat bangsa
     di 892x412 tersisa 2,8 px dari batas tirai — cukup untuk lulus, tidak cukup
     untuk kalimat keterangan yang lebih panjang dari yang kebetulan diuji. */
  .hasil-papan { --baris-x: 10px; --baris-y: 4px; }
  .hasil-baris { font-size: 12px; }
  .hasil-aksi { gap: 7px; }
  .hasil-nav .tbl { padding: 11px 12px; }
  .tbl.iklan { gap: 5px; padding: 7px 9px; }
  .tbl.iklan b { font-size: 11px; }
  .iklan-tanda { width: 19px; height: 19px; border-radius: 6px; }

  /* Papan DUA LAJUR (lima bangsa ke atas) memakai tinggi yang sama dengan empat
     bangsa satu lajur — itulah gunanya. Tapi delapan bangsa di 640x360 tetap
     paling mepet dari semua gabungan yang ada, jadi barisnya dirapatkan sedikit
     lagi, dan hanya waktu papannya memang sedang panjang. */
  .banyak .hasil-papan { --baris-x: 9px; --baris-y: 4px; }
  /* Judulnya mengalah begitu papannya melebar: kartu dua lajur adalah kartu
     yang isinya paling banyak, dan judul 34 px di atasnya tinggi yang dibayar
     tepat waktu tingginya paling mahal. */
  .banyak .hasil-judul { font-size: clamp(20px, 6vh, 30px); }

  /* MANAGE THE COMPETITION di layar pendek (§57.42.11). Terukur di 892×412:
     kartunya — tiga tombol ukuran BERTUMPUK ditambah empat baris hasil —
     mendorong tombol ENTER 40 px keluar dari tepi bawah layar.

     Yang dipangkas KEPADATANNYA, bukan susunannya. Mengembalikan ketiga tombol
     jadi satu baris memang menghemat dua baris sekaligus, tapi pada lebar
     kartu 440 px tiap tombol cuma dapat ±142 px sementara "Medium (1 vs 3)"
     sendiri meminta lebih — jadi yang dihemat tinggi dibayar dengan tiga label
     yang patah dua baris masing-masing, dan tingginya kembali persis seperti
     semula.

     Dipotong dari empat tempat sekaligus supaya tidak ada satu bagian pun yang
     dipangkas sampai jelek: sisipan kartu, jarak antar-isinya, sisipan tombol
     ukuran, dan sisipan keempat baris hasilnya. */
  #kartu-tur { padding: 9px 12px; gap: 5px; }
  #tur-pilih-jenis { gap: 5px; }
  /* §57.49: label ukuran turnamen berubah dari "(1vs3)" jadi "(4 Groups)" —
     "Medium (4 Groups)" empat huruf lebih panjang dari yang dulu paling
     panjang. Terukur MELUBER 7 px di dalam tombolnya sendiri pada 640x360
     (tombol cuma dapat 98 px di sana), yaitu tulisannya terpotong, bukan
     patah baris.

     Yang dikecilkan HURUFNYA, bukan labelnya: kata "Groups" yang membuatnya
     panjang justru satu-satunya bagian yang memberi tahu apa yang dihitung,
     jadi memendekkannya ("4 Grp") mengembalikan persis kebingungan yang
     penggantian ini dimaksudkan untuk hilangkan. Sisipan mendatar ikut
     dirapatkan jadi 3 px karena pada lebar 98 px, tiap px sisipan langsung
     dibayar oleh tulisannya.

     Ukurannya angka MATI, bukan `clamp(…, 2.4vw, …)`: blok ini dipicu oleh
     TINGGI layar, bukan lebar, jadi klausa `vw` tidak pernah menggigit — di
     640x360 ia menghasilkan 15,4 px dan langsung terkunci di batas atas,
     yang persis nilai yang sedang diperbaiki. Terukur: pada 12 px tulisannya
     meminta 101,9 px sementara ruang isi tombol cuma 86 px. */
  #tur-pilih-jenis .tab { padding: 7px 3px; font-size: 10px; letter-spacing: 0; }
  #kartu-tur .baris-info { margin-top: 2px; padding: 5px 10px; }
}

/* Tingkat kepadatan KETIGA, untuk layar setinggi 400 px ke bawah — HP kecil
   mendatar (360 px logis), bukan HP mendatar pada umumnya.
   Ambangnya lahir dari satu ukuran: dengan tombol iklan berhadiah terpasang,
   kartu MENANG empat bangsa memakai 369 px di 640x360 sementara tirai cuma
   menyisakan 336 — meluber 33 px. Di 892x412, layar yang sebenarnya jadi
   sasaran, kartu yang sama memakai 365 px dari 388 dan tidak perlu dipadatkan
   sama sekali. Jadi yang dipadatkan cuma yang memang tidak muat, dan tidak ada
   satu pun peranti biasa yang membayar kerapatan ini tanpa sebab.

   Diukur sebagai kekurangan 33 px, ditutup dari empat tempat sekaligus supaya
   tidak ada satu bagian pun yang dipangkas sampai jelek: baris peringkat (-4 px
   x 4 baris), jarak antarbaris (-1 x 3), tombol jalan (-4), dan tombol iklan
   yang dua barisnya dijadikan satu (-14). */
@media (max-height: 400px) {
  .hasil-judul { font-size: clamp(19px, 6vh, 26px); }
  /* Baris keterangan ikut mengecil, dan cuma di sini. Ia paling akhir dipangkas
     karena 12 px sudah huruf terkecil di kartu ini. */
  .hasil-sebab { font-size: 11px; }
  .hasil-cerita { gap: 3px; }
  .kotak.lebar.hasil-kotak { gap: 6px; }
  .hasil-aksi { gap: 6px; }
  .hasil-papan { --baris-x: 9px; --baris-y: 3px; }
  .banyak .hasil-papan { --baris-y: 3px; }
  /* Keping bendera yang menentukan tinggi baris, bukan hurufnya: dengan padding
     2 px + garis 2 px ia 22,4 px sementara sel lain cuma 14,4 px. Jadi satu
     piksel di sini berharga dua piksel per baris. */
  .hasil-baris .bd { padding: 1px 0; }
  .hasil-nav .tbl { padding: 8px 10px; }
  .tbl.iklan { gap: 4px; padding: 6px 8px; }
  .tbl.iklan b { font-size: 10.5px; letter-spacing: 0.2px; }
  .iklan-tanda { width: 17px; height: 17px; border-radius: 5px; }
}

.tengah { text-align: center; }

#putar {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 14px;
  background: #12161f;
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.5px;
  pointer-events: auto;
  /* Paling atas DI DALAM #hud. Yang menentukan letaknya terhadap menu adalah
     z-index #hud sendiri, bukan angka ini — lihat catatan di sana. */
  z-index: 9;
}
#putar[hidden] { display: none; }
.putar-ikon {
  width: 88px;
  height: 54px;
  border: 5px solid var(--kuning);
  border-radius: 10px;
  color: transparent;
  animation: miring 1.6s ease-in-out infinite;
}
@keyframes miring {
  0%, 100% { transform: rotate(90deg); }
  50% { transform: rotate(0deg); }
}

/* ------------------------------------------------------------------- HP ----- */

/* Dipasang oleh JS (`body.hp`), bukan lewat @media murni: yang menentukan
   bukan cuma lebar layar tapi juga jenis penunjuknya — jendela desktop yang
   dikecilkan tidak butuh joystick, sedangkan tablet lebar tetap butuh. Lihat
   `tataLetak()` di main.js. */
body.hp #sentuh, body.hp #gugus { display: block; }
body.hp .panel-komando,
body.hp .panel-aksi,
body.hp .panel-bantuan,
body.hp .panel-setel,
body.hp .panel-judul,
body.hp .panel-mode { display: none; }

body.hp .panel-sudut {
  top: calc(10px + env(safe-area-inset-top));
  left: calc(10px + env(safe-area-inset-left));
}

/* Sudut kanan-atas di HP (§57.41.5). Sekarang cuma SATU baris ringkas plus
   tombol STATS, jadi seluruh penyetelan kepadatan papan delapan baris yang
   dulu berdiri di sini — pengecilan huruf `.banyak`, susunan dua kolom waktu
   dilebarkan, pagar `max-height` yang diturunkan dari peubah gugus sentuh —
   ikut dicabut bersama papannya. Semuanya menjawab masalah yang sudah tidak
   ada: tinggi panel yang tumbuh mengikuti jumlah bangsa. Baris tunggal tidak
   pernah tumbuh. */
body.hp .skor-atas {
  top: calc(8px + env(safe-area-inset-top));
  right: calc(10px + env(safe-area-inset-right));
  gap: 6px;
}
body.hp .skor-ringkas {
  gap: 6px;
  padding: 5px 8px;
  font-size: clamp(9.5px, 2.6vh, 12px);
  font-size: clamp(9.5px, 2.6dvh, 12px);
}
/* Nama bangsa TETAP TAMPIL di HP sejak §57.42.4 — permintaan langsung, dan
   ongkosnya sudah dibayar di aturan `.ku-nama` di atas: lebarnya dijepit
   `max-width` lalu dipotong elipsis, jadi ia tidak bisa lagi mendorong keping
   apa pun ke luar layar seperti waktu ia dicabut dulu. Di HP jepitannya
   dipersempit lagi karena di sini lebar yang langka, bukan tinggi. */
body.hp .ku-nama { max-width: 5.4em; }
body.hp .ku-panji { width: 22px; height: 15px; }
body.hp .ku-sikap { min-width: 4em; padding: 2px 4px; }
body.hp .stats-tbl {
  width: auto;
  padding: 0 9px;
  font-size: clamp(9px, 2.4vh, 11px);
  font-size: clamp(9px, 2.4dvh, 11px);
}

/* Peta kecil di HP: sudut kiri-atas yang sama, cuma jaraknya mengikuti takik
   layar. Batas tingginya sudah dipahat di `.peta-mini` sendiri. */
body.hp .panel-sudut {
  top: calc(8px + env(safe-area-inset-top));
  left: calc(8px + env(safe-area-inset-left));
  gap: 6px;
  padding: 0;
}

/* Lembar statistik di HP: kolom LEAD dan USER dicabut, dan itu bukan
   penghematan sembarangan — keduanya kolom yang isinya paling sering sama di
   seluruh tabel (“CPU” tujuh kali, mahkota menyala delapan kali). Yang tersisa
   justru kolom yang benar-benar berbeda tiap baris. */
body.hp .stat-tabel {
  grid-template-columns: 20px minmax(56px, 1fr) 36px 40px minmax(38px, 60px) 54px;
}
body.hp .stat-baris .us, body.hp .stat-kepala span:nth-child(3) { display: none; }
body.hp .stat-baris .ld, body.hp .stat-kepala span:nth-child(4) { display: none; }
body.hp .stat-kepala, body.hp .stat-baris { gap: 6px; padding: 5px 8px; }
body.hp .stat-baris { font-size: 11px; }

/* Pesan sekilas di HP TURUN KE BAWAH LAYAR (§40.5).
   Dulu `bottom: 34%` — melayang di tengah medan, tepat menutupi pertempuran
   yang sedang diperingatkannya. Sekarang ia duduk di pita bawah, di antara
   stik kiri dan gugus tombol kanan: keduanya berlabuh di sudutnya
   masing-masing, jadi tengah-bawah adalah satu-satunya bagian layar yang
   dijamin kosong dari jempol maupun tombol.

   `max-width` dan pemotongan katanya perlu karena pita itu memang sempit di
   layar kecil — pesan sepanjang "Barisanmu tertinggal jauh — mereka berangkat
   menyusul" tanpa batas lebar akan menyeberang ke bawah stik. */
body.hp #pesan {
  bottom: calc(16px + env(safe-area-inset-bottom));
  /* Dipusatkan di CELAH, bukan di layar (§40.9): sesudah FORMASI dan GANTI
     memanjang ke kiri dari SERBU, pita bawah tidak lagi kosong di tengah, dan
     pesan yang dipusatkan ke layar akan tertimbun tombol GANTI. Batas kanannya
     dihitung dari rumus letak GANTI itu sendiri, jadi ia ikut bergeser sendiri
     kalau ukuran gugusnya berubah. */
  left: calc(var(--stik) + 28px + env(safe-area-inset-left));
  right: calc(var(--cx) + var(--r) + var(--orbit) * 2.5 + var(--sela-fm) * 2 + 12px);
  transform: none;
  width: max-content;
  max-width: 100%;
  margin: 0 auto;
  font-size: 12px;
  padding: 6px 13px;
  white-space: normal;
  text-align: center;
  line-height: 1.35;
}
body.hp #pesan.tampil { transform: none; }
/* Di HP jam pertandingan duduk di tengah atas, jadi keterangan bidik turun ke
   bawahnya. Ditaruh cukup tinggi supaya tetap jauh dari ibu jari yang sedang
   menyeret tombol SALVO di sudut bawah. */
body.hp #bidik-info { top: 66px; bottom: auto; font-size: 12px; padding: 5px 12px; }
body.hp #bidik-info b { font-size: 14px; }

/* Kartu lapisan penuh dipadatkan di HP mendatar yang pendek. */
body.hp .kotak { padding: 14px; gap: 7px; }
/* `body.hp .hasil-judul` DIHAPUS, bukan disetel ulang — perangkap yang sama
   persis dengan `body.hp .hasil-baris` yang dibuang di §48. `body.hp` ditentukan
   LEBAR layar, sementara yang menentukan besar judul kartu hasil tinggi layar,
   jadi keduanya tidak pernah bisa sepakat. Lebih buruk lagi kekhususannya
   (0,0,2,1) mengalahkan `.banyak .hasil-judul` (0,0,2,0), sehingga judul yang
   sengaja dikecilkan untuk kartu dua lajur diam-diam tidak pernah berlaku di
   layar selebar 760 px ke bawah. Ukuran judul sekarang cuma diputuskan di
   `@media (max-height: 560px)`. */
/* Kepadatan baris peringkat DIPINDAH ke `@media (max-height: 560px)` di atas.
   Yang menentukan muat atau tidaknya papan itu tinggi layar, bukan lebarnya:
   `body.hp` juga berlaku di HP TEGAK setinggi 844 px, tempat barisnya justru
   punya ruang berlimpah — dan aturan di sini merapatkannya tanpa sebab. Lebih
   penting lagi, ia berlaku SESUDAH aturan @media itu, jadi selama ia ada,
   papan dua lajur yang lebih rapat tidak pernah bisa lebih rapat. */
body.hp .tbl { padding: 11px 12px; }

/* ==================================================== menu pembuka ========= *
 *
 * Bahasa visualnya meneruskan acuan yang sama seperti HUD (game kasual
 * CrazyGames bergaya "Free Kicks"): kartu putih bergaris hitam tebal berbayang
 * PEJAL, tombol warna pekat yang benar-benar turun waktu ditekan, judul gemuk
 * gradasi kuning bergaris hitam. Yang berubah dari versi pertama bukan bahasa
 * itu, melainkan TATA LETAK dan LATARNYA.
 *
 * ---------------------------------------------------------------------------
 * 1. MENDATAR DUA KOLOM, DAN TIDAK PERNAH DIGULIR
 *
 * Versi pertama ditulis "mobile dulu" dalam arti HP TEGAK: satu kolom selebar
 * 420 px, ukuran dasarnya ukuran layar tegak, dengan satu tambalan
 * `max-height: 560px` untuk mendatar. Itu salah sasaran — game ini MEMAKSA
 * layar mendatar (lihat #putar), jadi HP tegak justru satu-satunya bentuk yang
 * tidak pernah dipakai bermain. Akibatnya terukur: layar Quick Match meluber
 * 217 px di 640×360 dan 168 px di 892×412.
 *
 * Gulungan di game peramban mendatar bukan ketidaknyamanan kecil, melainkan
 * kehilangan isi: tidak ada isyarat apa pun bahwa masih ada tombol di bawah
 * lipatan, dan di dalam iframe portal, roda tetikus sering diambil halaman
 * induknya. Karena itu `#menu` sekarang `overflow: hidden` MUTLAK pada layar
 * mendatar, dan seluruh isi diukur dalam `vh` supaya memadat sendiri alih-alih
 * meluber. Gulungan cuma diizinkan pada layar tegak — keadaan yang memang
 * sudah ditutup lapisan "putar HP-mu".
 *
 * 2. UKURANNYA vh, BUKAN px BERTAMBALAN MEDIA QUERY
 *
 * `clamp(kecil, Nvh, besar)` di tiap penyantap ruang tegak. Satu media query
 * yang memadatkan semuanya sekaligus hanya benar pada satu tinggi layar dan
 * melompat kasar di sekitarnya; `vh` benar di seluruh rentang 320–900 px
 * tanpa satu pun ambang.
 *
 * 3. LATARNYA ARENA SUNGGUHAN
 *
 * `#menu` tidak lagi biru pejal. Di belakangnya berjalan panggung 3D milik
 * js/menu3d.js, dan lapisan ini cuma tirai gelap tipis supaya teks tetap
 * terbaca. Tirainya digelapkan di atas dan di bawah, dibiarkan bening di
 * tengah — persis tempat kamera latar menaruh cakrawala.
 *
 * Versi sebelumnya menambal keredupan potret dengan `backdrop-filter:
 * brightness(1.45)` pada kotak potret — sebuah lubang persegi di tirai. Itu
 * ikut hilang bersama kotaknya, dan tidak diganti dengan tambalan lain:
 * persegi yang dicerahkan tanpa garis tepi cuma menghasilkan sambungan
 * mendadak di tengah pemandangan. Gantinya dikerjakan di dua tempat yang lebih
 * benar — tirainya sendiri diringankan di pita tengah (di bawah), dan pemimpin
 * potret diberi lampu kunci sendiri di js/menu3d.js (`KUNCI_POTRET`).
 */
/* HUD pertandingan DIPADAMKAN selama menu masih terbuka.
   Dulu ini tidak perlu: menu berlatar biru pejal, jadi apa pun di belakangnya
   tertutup rapat. Begitu latarnya jadi arena tembus pandang, jam "3:00 BATTLE
   TIME", panel judul, dan seluruh gugus tombol sentuh langsung terbaca
   menembus tirai — pertandingan yang belum ada terlihat sudah berjalan.

   `#putar` sengaja dikecualikan: lapisan "putar HP-mu ke posisi mendatar"
   justru paling dibutuhkan SEBELUM pertandingan dimulai. */
body:not(.bertanding) #hud > *:not(#putar) { display: none !important; }

/* ---- lapisan pemuat penuh layar (§57.41.2) ----------------------------
   Berdiri DI ATAS #menu (z 20) dan di atas seluruh HUD, karena tugasnya
   menutupi persis peralihan di antara keduanya: menu yang sedang ditinggalkan
   dan arena yang belum selesai dibangun. Warnanya sama dengan `#menu::after`
   supaya perpindahan dari lapisan pemuat menu ke lapisan ini tidak terlihat
   sebagai kedipan warna. */
#muat {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-content: center;
  gap: 14px;
  justify-items: center;
  background: #182031;
  transition: opacity 0.35s ease;
}
#muat[hidden] { display: none; }
#muat.pudar { opacity: 0; pointer-events: none; }
/* Cincin berputar, digambar CSS — bukan GIF dan bukan glif: proyek ini tidak
   mengunduh aset, dan glif pemuat mana pun digambar sistem operasi. */
.muat-tanda {
  width: 34px;
  height: 34px;
  border: 4px solid rgba(255, 255, 255, 0.18);
  border-top-color: var(--kuning);
  border-radius: 50%;
  animation: muat-putar 0.9s linear infinite;
}
@keyframes muat-putar { to { transform: rotate(360deg); } }
.muat-teks {
  color: #9fb0cc;
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 1.4px;
}
@media (prefers-reduced-motion: reduce) {
  .muat-tanda { animation-duration: 3s; }
}

#menu {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  overflow: hidden;
  overscroll-behavior: contain;
  color: #fff;
  /* Tirai: pekat di kepala dan kaki (tempat judul dan tombol duduk), nyaris
     bening di pita tengah supaya arenanya benar-benar terlihat.

     Pita tengahnya DIRINGANKAN dari 0,34/0,50 ke 0,20/0,32 waktu kotak potret
     dibuang. Kotak itu dulu memasang `backdrop-filter: brightness(1.45)` yang
     mencerahkan kembali pemimpin di dalamnya; tanpa lubang itu, tirai lama
     akan meredam modelnya persis seperti ia meredam arena. Yang tetap gelap
     cuma kepala dan kaki layar — di sanalah judul dan tombol duduk, dan cuma
     di sanalah tirai benar-benar bekerja untuk keterbacaan. */
  background:
    linear-gradient(180deg,
      rgba(9, 13, 24, 0.88) 0%,
      rgba(9, 13, 24, 0.2) 42%,
      rgba(9, 13, 24, 0.32) 70%,
      rgba(9, 13, 24, 0.9) 100%),
    rgba(12, 17, 30, 0.22);
}
#menu[hidden] { display: none; }

/* Lapisan biru pejal yang menutupi kanvas SEBELUM panggung latar selesai
   dibangun. Dunia latar butuh ratusan milidetik untuk digabung, dan
   membangunnya sebelum menu digambar berarti halaman terlihat macet tepat di
   detik pertama. Jadi menu tampil dulu di atas lapisan ini, latarnya menyusul,
   lalu lapisan ini memudar (kelas `.hidup` dipasang js/main.js). */
#menu::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #182031;
  pointer-events: none;
  transition: opacity 0.9s ease;
}
#menu.hidup::after { opacity: 0; }

/* ---- satu layar -------------------------------------------------------
   Sisipan luarnya sengaja lebih longgar dari versi sebelumnya. Yang lama
   memakai `clamp(8px, 2.4vh, 20px)`, dan pada layar setinggi 517 px itu cuma
   12,4 px — judul bergaris tepi 7 px praktis menyentuh tepi atas, sementara
   tombol paling bawah menempel ke tepi bawah karena bayangan pejal 6 px-nya
   ikut memakan jarak yang tersisa. Sisipan bawah karena itu dibuat LEBIH TEBAL
   dari yang atas: ia harus menampung tinggi tombol DITAMBAH bayangannya. */
.layar {
  position: relative;
  z-index: 1;                       /* di atas lapisan pemuat di atas */
  /* `flex: 1` DITAHAN pertumbuhannya oleh `max-width`, bukan oleh `width`.
     Versi sebelumnya menulis `flex: 1` + `width: min(1020px, 100%)` dan batas
     itu TIDAK PERNAH SEKALI PUN BERLAKU: `flex: 1` adalah singkatan dari
     `flex: 1 1 0%`, dan flex-basis selain `auto` MENGGANTIKAN `width` sebagai
     ukuran dasar — jadi layar tumbuh mengisi seluruh lebar jendela dan satu-
     satunya jarak ke tepi yang tersisa cuma padding-nya sendiri.

     Terukur sebelum diperbaiki: pada jendela 1109 px, `#layar-cepat` selebar
     1109 px penuh dan isinya mulai di x = 32. Itulah sebab sesungguhnya
     keluhan "isi terlalu mepet tepi kanan dan kiri" — bukan padding yang
     kurang, melainkan pembatas lebar yang diam-diam mati. `max-width` bekerja
     SESUDAH flex-grow membagi ruang, jadi ia benar-benar memotong; sisa
     ruangnya diserap `margin: 0 auto`, yang di dalam flex memang menyerap
     ruang bebas. */
  flex: 1;
  min-width: 0;
  max-width: 980px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 2.6vh, 20px);
  /* Sisipan samping DILIPATGANDAKAN dari clamp(16px, 3.4vw, 32px). Bersama
     `max-width` di atas, tepi isi pada jendela 1109 px pindah dari x = 32 ke
     x ≈ 105 — jarak yang benar-benar terbaca sebagai bingkai, bukan sekadar
     padding tombol. */
  padding: clamp(14px, 4vh, 30px) clamp(18px, 4vw, 40px);
  /* Atas dan bawah sengaja BERBEDA, dan keduanya jauh lebih tebal dari versi
     sebelumnya (20,7 px dan 24,8 px pada layar 517 px — terukur, dan keduanya
     dikeluhkan). Bawah tetap yang paling tebal karena bayangan pejal tombol
     ikut memakan jarak yang tersisa di sana. */
  padding-top: calc(clamp(18px, 6.8vh, 50px) + env(safe-area-inset-top));
  padding-bottom: calc(clamp(20px, 7.6vh, 60px) + env(safe-area-inset-bottom));
}
.layar[hidden] { display: none; }

/* ---- kepala layar: judul + satu baris keterangan ----------------------
   Rata KIRI di layar dua kolom: judul yang dipusatkan di atas isi dua kolom
   membuat seluruh layar terbaca simetris seperti formulir; digeser ke kiri, ia
   jadi kepala halaman dan kolom di bawahnya boleh berbeda berat tanpa terlihat
   miring. Beranda memakai `.tengah` karena isinya memang satu kolom di tengah,
   dan judul rata kiri di atas kolom yang dipusatkan terbaca seperti salah
   satunya lupa disejajarkan. */
.layar-kepala { flex-shrink: 0; }
.layar-kepala.tengah { position: relative; text-align: center; }

/* Kepala dengan PINTU KELUAR di kirinya (Quick Match).
   `align-items: center` menyejajarkan pintu ke tengah tinggi judul, bukan ke
   garis dasarnya: judul ini punya garis tepi tebal dan bayangan jatuh, jadi
   kotak hurufnya jauh lebih tinggi dari huruf yang terlihat, dan pintu yang
   disejajarkan ke atas akan tampak melayang di atas tulisannya. */
.layar-kepala.berpintu {
  display: flex;
  align-items: center;
  gap: clamp(8px, 1.8vw, 16px);
}
.pintu-kembali {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  /* Dipatok ke `--fs-judul`, bukan ke vh: pintu ini pasangan judul di
     sebelahnya, jadi ia harus mengecil dan membesar bersamanya. Angka 1,15
     membuat kotaknya sedikit lebih tinggi dari huruf judulnya — cukup untuk
     terbaca sebagai tombol, tidak cukup untuk menyaingi judul. */
  width: calc(var(--fs-judul) * 1.15);
  height: calc(var(--fs-judul) * 1.15);
  padding: calc(var(--fs-judul) * 0.2);
  border: 3px solid var(--garis);
  border-radius: clamp(10px, 1.8vh, 15px);
  background: var(--merah);
  /* Warna GARIS ikon, bukan warna teks: svg-nya `stroke="currentColor"` dan
     `fill="none"` (§43.4), jadi satu-satunya yang mewarnainya properti ini. */
  color: #2b0a06;
  cursor: pointer;
  transition: transform 0.08s;
}
.pintu-kembali svg { display: block; width: 100%; height: 100%; }
.pintu-kembali:active { transform: translateY(2px); }

/* ---- lambang di belakang judul ----------------------------------------
   Ukurannya dipatok ke UKURAN HURUF JUDUL (`--fs-judul`), bukan ke vh atau px
   tetap: itulah arti "proporsional dengan tulisannya" — judul mengecil di layar
   pendek, lambangnya ikut mengecil dengan perbandingan yang sama, jadi
   hubungan keduanya tidak pernah berubah di ukuran layar mana pun.

   `z-index: -2` menaruhnya di belakang lapisan garis tepi judul (`::before`,
   z-index -1) sekaligus di belakang isian kuningnya. Keduanya lolos ke konteks
   penumpukan milik `.layar` (satu-satunya leluhur ber-z-index di sini), jadi
   urutannya benar tanpa perlu konteks penumpukan tambahan — dan itu penting:
   membuat `.layar-kepala` jadi konteks penumpukan sendiri akan mengurung
   `::before` judul di dalamnya dan memunculkan kembali bug garis-menutupi-isian
   yang sudah dicatat di atas.

   Kelegapan dinaikkan 0,15 → 0,34 (§43.11). 0,15 dipilih waktu lambang ini
   berdiri di pita paling gelap tirai `#menu` (kelegapan 0,88 di tepi atas), dan
   di sana ia memang terlihat. Sesudah judul turun ke tengah layar (§43.3),
   latarnya jadi pita tirai yang paling BENING — arena hijau terang di baliknya
   menelan kuning setipis itu sampai lambangnya praktis hilang. Yang berubah
   bukan seleranya, melainkan apa yang ada di belakangnya.

   Hurufnya tetap tidak terancam: judul digambar dua lapis, dan lapisan
   garisnya setebal 4–7 px hitam pekat berdiri di antara lambang dan isian
   kuningnya. */
/* DIGESER KE ATAS, lalu DIPERKECIL LAGI. Lambangnya dipusatkan tepat di tengah
   judul waktu ia masih SVG setipis garis; sesudah jadi gambar perisai
   bersilang pedang yang pejal, pusat massanya justru di perisai — bagian
   bawah — jadi pedangnya terpotong di atas sementara pita kosong menganga di
   antara lambang dan tepi atas layar. Pergeseran ke atas menjawab itu.

   Pembesaran 3,6 → 5,4 yang menyertainya ternyata terlalu jauh: TERUKUR di
   1280x720 ujung pedangnya berhenti 50 px dari tepi atas layar — sebaris
   dengan keping intan/bahasa/iklan di pojok — sementara tepi bawah perisainya
   cuma 10 px di atas petak mode, jadi ia menyundul dua benda sekaligus.
   Sekarang 4,2 dengan geser -60%: terukur 92 px dari tepi atas dan 22 px di
   atas petak mode. Kedua angka itu HASIL PENGUKURAN, bukan taksiran — lambang
   ini melayang `position: absolute`, jadi tidak satu pun jarak di sekelilingnya
   lahir dari `gap` yang bisa dipercaya begitu saja. */
.judul-lambang {
  position: absolute;
  z-index: -2;
  left: 50%;
  top: 50%;
  /* -60% → -56%: diminta turun sedikit, dan "sedikit" di sini dibatasi dari
     BAWAH, bukan dari selera. Terukur di 1280x720: pada -60% tepi bawah
     perisai berhenti 22 px di atas petak mode; tiap 1% pergeseran memindahkan
     lambang ±1,9 px, jadi -52% yang sempat dicoba menyisakan cuma 7 px — ia
     praktis menyentuh petak mode. -56% memberi 15 px: lambangnya benar-benar
     turun (8 px dari sebelumnya) tanpa mengubah jarak itu jadi sundutan. */
  transform: translate(-50%, -56%);
  width: calc(var(--fs-judul) * 4.2);
  color: #ffd98a;
  /* PEJAL, tanpa kelegapan sama sekali (§57.42.8). Ia dulu diredam 0,34 supaya
     tidak berlomba dengan huruf judul di depannya — tapi yang membuatnya tidak
     berlomba sebenarnya `z-index: -2`: lambang ini berdiri DI BELAKANG judul,
     dan hurufnya sendiri berlatar gradasi kuning-jingga bergaris tepi tebal
     yang tetap terbaca penuh di atas apa pun. Yang hilang karena kelegapan itu
     justru bentuk lambangnya — pada 0,34 di atas arena hijau, perisai dan
     pedangnya tidak lagi punya tepi yang bisa dikenali. */
  pointer-events: none;
}
.judul-lambang img { display: block; width: 100%; height: auto; }

.judul-besar {
  position: relative;
  margin: 0;
  /* Dipatok ke TINGGI layar, bukan lebar. Yang membuat judul lama tersundut
     tepi bukan lebarnya — melainkan layar mendatar yang pendek, di mana judul
     sebesar 7,2vw memakan seperempat tinggi yang tersedia. */
  font-size: var(--fs-judul);
  font-weight: 900;
  letter-spacing: var(--lc-kapital);
  line-height: 1.04;
  background: linear-gradient(180deg, #ffe27a 0%, #ffc32e 52%, #f08a1d 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* SENGAJA tanpa `filter` pada induknya. `filter` membuat induk jadi stacking
   context tersendiri, dan begitu itu terjadi, anak ber-`z-index: -1` tidak lagi
   jatuh DI BELAKANG latar induknya — ia justru digambar sesudahnya, sehingga
   huruf hitam bergaris tebal ini menutupi gradasi kuning yang seharusnya jadi
   isian. Bayangannya dipindah ke lapisan garis ini saja. */
.judul-besar::before {
  content: attr(data-teks);
  position: absolute;
  inset: 0;
  z-index: -1;
  -webkit-text-stroke: clamp(4px, 1.1vh, 7px) var(--garis);
  color: var(--garis);
}
.judul-sub {
  margin: clamp(3px, 0.9vh, 7px) 0 0;
  font-size: var(--fs-kecil);
  font-weight: 700;
  letter-spacing: var(--lc-biasa);
  color: rgba(255, 255, 255, 0.72);
  /* Teks tipis di atas arena bergerak butuh garis gelapnya sendiri; tirai saja
     tidak cukup waktu kamera kebetulan melewati tembok benteng yang terang. */
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.85);
}

/* ---- badan layar: dua kolom ------------------------------------------
   Kiri lebih sempit dari kanan: kiri berisi pemimpin 3D (satu benda tegak,
   tidak butuh lebar), kanan berisi kartu pilihan dan tombol. */
.layar-isi {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(14px, 3vw, 26px);
  align-items: stretch;
}
/* Beranda: satu kolom, dipusatkan. */
.layar-isi.tunggal {
  display: flex;
  justify-content: center;
  align-items: center;
}
/* JUDUL TURUN MENDEKATI TOMBOL (§43.3). Sebelumnya `.layar-isi` memakai
   `flex: 1` — ia melahap seluruh sisa tinggi lalu memusatkan tombol di
   dalamnya, sementara judul tertinggal menempel di tepi atas. Akibatnya jarak
   judul→tombol adalah SISA RUANG layar, bukan angka yang dipilih: makin tinggi
   layarnya makin jauh keduanya terpisah.

   Sekarang isinya berhenti setinggi dirinya sendiri (`flex: 0 1 auto`) dan
   seluruh kelompok judul+tombol yang dipusatkan tegak oleh `.layar`. Yang
   memisahkan judul dari tombol tinggal `gap` milik `.layar` — 10 px di layar
   pendek, 20 px di layar tinggi — dan `padding-top`-nya (18–50 px + poni) tetap
   menjamin judul tidak pernah menyentuh tepi atas. Mendatarnya tidak disentuh:
   `.layar-kepala.tengah` sudah memusatkannya, dan lambang di belakang judul
   ikut turun bersamanya karena ia memang anak judul itu.

   Efek sampingnya menyenangkan: sundutan 1,14 px lambang di tepi atas layar
   640×360 (dicatat §42.10 sebagai cacat lama yang sengaja dibiarkan) hilang
   sendiri — bukan karena lambangnya diperbaiki, melainkan karena tidak ada lagi
   yang berdiri sedekat itu ke tepi. */
#layar-beranda { justify-content: center; }
#layar-beranda .layar-isi.tunggal { flex: 0 1 auto; }
/* Kepala beranda setinggi LAMBANGNYA, bukan setinggi hurufnya. Lambang itu
   `position: absolute` — ia tidak menyumbang tinggi apa pun ke induknya — dan
   selebar `--fs-judul × 3,6` (§32.8) ia menjulur ±1,28 × tinggi huruf ke atas
   DAN ke bawah. Selama judul berdiri sendirian di tepi atas layar, julurannya
   jatuh ke ruang kosong dan tidak ada yang menyadarinya.

   Begitu judul diturunkan mendekati tombol (§43.3), juluran bawah itu masuk ke
   belakang tombol yang PEJAL, dan terukur 17 px lambang tertutup di 892×412 —
   yang terlihat cuma separuh atasnya, terbaca seperti ikon terpotong yang
   melayang di atas judul, bukan lambang di belakangnya.

   Yang diminta "dekat dengan tombol" adalah JUDUL BESERTA LAMBANGNYA, jadi yang
   pantas berjarak sedikit dari tombol adalah tepi bawah lambang — bukan tepi
   bawah huruf. `min-height` di sini memberi lambang ruangnya kembali; jarak ke
   tombol tetap `gap` milik `.layar`. */
#layar-beranda .layar-kepala.tengah {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(var(--fs-judul) * 3.6);
}
/* CARA MAIN + PRIVASI dijauhkan dari petak mode (§43.11). `gap` milik `.kolom`
   cuma 8–16 px, dan itu jarak yang sama dengan jarak antar-baris di dalam petak
   mode sendiri — akibatnya kedua pil terbaca sebagai BARIS KETIGA petak itu,
   bukan sebagai tingkat yang berbeda. Di menu rujukan jaraknya kira-kira
   0,7 × tinggi tombol mode; di sini terukur cuma 0,16 ×.

   Ditulis sebagai `margin-top` pada pilnya, bukan `gap` yang diperbesar: `gap`
   berlaku pada SEMUA celah di kolom itu, jadi memperbesarnya akan ikut
   merenggangkan jarak yang justru sudah benar. */
#layar-beranda .menu-kaki { margin-top: clamp(6px, 3vh, 26px); }
.kolom {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(9px, 2vh, 16px);
  min-width: 0;
  min-height: 0;
}
/* Layar dua kolom (Quick Match) DITEMPELKAN KE ATAS, tidak dipusatkan tegak.
   Dipusatkan, tinggi kolom yang tersisa dibagi rata atas-bawah, jadi kartu
   pengaturan berhenti di ketinggian yang sama persis berapa pun ruang yang
   ditambahkan di bawahnya — menambah sisipan bawah tidak pernah menaikkannya
   satu piksel pun. Ditempelkan ke atas, seluruh isi naik dan ruang sisanya
   berkumpul jadi satu pita kosong di bawah, tempat yang memang tidak ditempati
   apa-apa. Layar teks (`.teks`) sudah punya aturannya sendiri di bawah. */
.layar-isi:not(.teks):not(.tunggal) .kolom { justify-content: flex-start; }
/* Lebar kolom tengah beranda. Sejarahnya panjang: melar bebas ia terukur 588×58
   (10,1 : 1, terbaca sebagai bilah menu aplikasi); dibatasi 460 px jadi 7,4 : 1;
   dipatok 390 px dan §31.13 mencatatnya "tertahan di 6,3 : 1".

   Catatan 6,3 : 1 itu ternyata cuma berlaku di layar TINGGI. Diukur ulang di HP
   mendatar 892×412 — tempat game ini sebenarnya dimainkan — tombolnya 390×52,6,
   yaitu 7,41 : 1; di 720×360 bahkan 7,54 : 1. Sebabnya lebar dipatok angka tetap
   sementara tinggi ikut mengecil bersama tinggi layar, jadi di layar pendek
   rasionya justru melar. Itulah keluhan "masih kepanjangan" yang dilaporkan:
   bukan selera, angkanya memang tidak pernah sampai ke sasaran lama.

   Sekarang lebarnya TIDAK dipatok lagi melainkan diambil dari isinya
   (`max-content`), sesudah `flex: 1` pada `.mode-teks` dibuang (§42.2). Yang
   menentukan jadi tombol terpanjang — "QUICK MATCH" — dan ketiganya ikut selebar
   itu lewat `width: 100%`, jadi tepi kanannya tetap rata satu garis. Batas atas
   390 px ditinggalkan sebagai jaring pengaman kalau suatu saat ada nama mode
   yang jauh lebih panjang.

   Batas atasnya dinaikkan 390 → 720 px waktu deret mode jadi DUA LAJUR (§43.1).
   390 px adalah anggaran untuk satu tombol; dua tombol bersebelahan beserta
   celahnya butuh kira-kira dua kali itu. Cara mengukurnya tidak berubah — yang
   menentukan tetap `max-content`, jadi di layar sempit kolomnya tetap menyusut
   sendiri dan batas ini cuma berlaku waktu ruangnya memang berlimpah. */
.kolom-tengah {
  width: max-content;
  max-width: min(720px, 100%);
  justify-content: center;
}
/* Layar yang isinya cuma tulisan (cara main, privasi). Kedua kartunya
   ditempelkan ke TEPI ATAS, bukan dipusatkan sendiri-sendiri: dipusatkan,
   kartu pendek dan kartu panjang berhenti di ketinggian berbeda dan sepasang
   kotak putih itu terbaca seperti dua benda yang kebetulan berdekatan, bukan
   dua kolom dari satu halaman. */
.layar-isi.teks { align-items: start; }
.layar-isi.teks .kolom { justify-content: flex-start; }

/* ---- pemimpin 3D, TANPA bingkai ---------------------------------------
   Yang terlihat di sini bukan gambar HTML: pemimpin 3D digambar langsung ke
   kanvas di belakang menu, tepat di dalam persegi ini (lihat `bingkai()` di
   js/menu3d.js). Dulu persegi ini punya garis tepi 4 px, sudut membulat,
   bayangan pejal, dan vignette dalam `inset 0 0 60px 12px rgba(4,8,16,.72)`.
   Semuanya dibuang, dan bukan cuma karena selera:

     · Vignette itu penyebab terbesar keluhan "pemimpinnya terlalu gelap" —
       ia menggelapkan kaki dan bahu modelnya sendiri, bukan cuma tepinya.
     · Kotak bergaris tepi memotong pemandangan jadi dua bidang terpisah,
       sehingga modelnya terbaca sebagai foto yang DITEMPEL di atas arena.
       Tanpa kotak, ia berdiri DI arena.

   Yang tersisa cuma persegi tembus pandang: penentu letak scissor, penangkap
   seretan jari, dan tidak lebih. */
.potret {
  position: relative;
  /* `max-height` DIPERLUKAN, dan bukan soal ukuran modelnya. Tanpa batas atas,
     `flex: 1` membuat persegi ini menelan seluruh tinggi kolom yang tersisa
     (terukur 417×313 px pada layar 517 px) dan MENDORONG keping nama serta
     baris panji ke dasar kolom — 24,8 px dari tepi bawah layar. Itu sebab
     sesungguhnya keluhan "nama bangsa dan tombol bendera terlalu ke bawah":
     bukan keduanya yang jatuh, melainkan persegi di atasnya yang mengembang
     tanpa henti.

     Dibatasi, sisa tinggi kolom berhenti dibagikan ke sini dan berkumpul jadi
     ruang kosong di bawah baris panji. Bingkai model 3D-nya sendiri tidak ikut
     berubah: `kamPotret` memakai FOV TEGAK, jadi tinggi persegi cuma mengubah
     ukuran gambarnya dalam piksel, bukan seberapa besar model mengisi
     bingkainya. */
  /* BATAS ATASNYA DIBUANG (§47.1), dan itu memutar balik keputusan §31 dengan
     sadar. Dulu `max-height: clamp(140px, 46vh, 300px)` dipasang karena tanpa
     batas, persegi ini menelan seluruh tinggi kolom dan MENDORONG keping nama
     serta baris panji ke dasar kolom — keluhan "nama bangsa dan tombol bendera
     terlalu ke bawah".

     Yang berubah: dasar baris panji sekarang GARIS ACUAN seluruh layar. Kaki
     kolom kanan menaikkan dirinya supaya dasar tombolnya jatuh di garis yang
     sama (§47.1), jadi baris panji memang HARUS berdiri di dasar kolomnya —
     bukan menggantung di tengah dengan pita kosong di bawahnya.

     Dengan batas itu tetap ada, sisa ruang kolom kiri (terukur 110 px di
     1366×768) berkumpul di antara keping nama dan baris panji: pita kosong di
     tempat yang justru paling terlihat. Tanpa batas, sisa itu diserap modelnya
     sendiri — benda yang memang jadi alasan layar ini ada. Batas bawahnya tetap
     dan tetap yang menjaga layar pendek. */
  flex: 1 1 auto;
  min-height: clamp(80px, 20vh, 190px);
  overflow: hidden;
  cursor: grab;
  /* Seretan jari memutar model, jadi peramban tidak boleh menafsirkannya
     sebagai gulungan atau cubitan lebih dulu. */
  touch-action: none;
  user-select: none;
}
.potret:active { cursor: grabbing; }

/* Persegi pratinjau arena di layar pilih peta. Batas tingginya disalin persis
   dari `.potret` di atas, tapi tinggi JADI-nya tetap berbeda sedikit — dan itu
   bukan kelalaian, melainkan akibat `flex: 1 1 auto`: yang menentukan tinggi
   akhirnya sisa ruang kolom, dan sisa ruang kolom peta lebih kecil karena kartu
   arenanya membawa keping SEGERA yang tidak dipunyai kartu bangsa. Terukur
   156,2 lawan 142,2 px di 640×360 dan 249,8 lawan 178,4 di layar tegak.

   Dibiarkan, karena yang dijaga sebenarnya bukan kesamaan angka melainkan
   kesamaan ATURAN: kedua kolom memakai batas yang sama dan membagi sisa ruang
   dengan cara yang sama, jadi keduanya bereaksi seragam terhadap layar apa pun.
   Memaksa keduanya setinggi persis sama menuntut tinggi tetap di salah satunya,
   dan tinggi tetap itulah yang dibuang §31 dari seluruh menu ini.

   Yang TIDAK ikut disalin: `cursor: grab`, `touch-action: none`, dan penangan
   seretannya. Belum ada model arena yang bisa diputar, dan kursor yang
   menjanjikan seretan pada persegi yang tidak menanggapi apa pun adalah
   kebohongan yang paling cepat ketahuan. Ketiganya menyusul bersama modelnya. */
.pratinjau {
  position: relative;
  flex: 1 1 auto;
  min-height: clamp(80px, 20vh, 190px);
  overflow: hidden;
  /* Bingkai supaya arena terbaca sebagai PETA — benda yang dibingkai dan
     dilihat dari luar — bukan seperti `.potret` di sebelah kolomnya yang
     sengaja dibiarkan tanpa bingkai (§43.3) supaya pemimpinnya terbaca
     berdiri DI arena. Radiusnya sama dengan `.kartu` di kolom kanan supaya
     kedua kotak di layar ini terasa satu keluarga bentuk. */
  border: 4px solid var(--garis);
  border-radius: clamp(12px, 2.4vh, 20px);
  /* Isinya (pesan "belum digambar") dipusatkan di persegi yang sama yang jadi
     kotak scissor arena — jadi pesan dan model menempati tempat yang sama
     persis, dan tidak pernah bisa terlihat berdua. */
  display: grid;
  place-items: center;
}
/* Cuma untuk arena yang BELUM ada modelnya. Dipadamkan js/main.js begitu
   arenanya siap (kelas `.siap` dari `setPeta`), bukan disembunyikan dari HTML:
   yang menentukan siap atau tidak adalah `PETA[p].siap` di js/peta.js, dan satu-
   satunya berkas yang boleh membacanya yang menggambar layar ini.

   Warnanya putih redup dengan garis gelapnya sendiri, sama seperti keterangan
   lain yang berdiri di atas arena hidup (lihat `#waktu-hud`): tirai `#menu` saja
   tidak cukup waktu kamera latar kebetulan melewati tembok benteng yang terang. */
.pratinjau-pesan {
  padding: 0 clamp(8px, 2vw, 16px);
  color: rgba(255, 255, 255, 0.72);
  font-size: var(--fs-kecil);
  font-weight: 800;
  letter-spacing: var(--lc-biasa);
  text-align: center;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.85);
}
.pratinjau.siap .pratinjau-pesan { display: none; }
/* Tulisan "seret untuk memutar" DIBUANG seluruhnya (aturannya dulu ada persis
   di sini). Alasannya bukan kerapian: memutar pemimpin tidak mengubah apa pun
   dalam permainan dan tidak perlu dilakukan untuk melanjutkan, jadi ia satu-
   satunya tulisan di layar ini yang menyuruh pemain melakukan sesuatu yang
   boleh dilewatkan — dan ia berdiri di pita paling terang layar, tempat mata
   jatuh pertama kali. Seretannya sendiri tetap hidup di js/main.js; yang hilang
   cuma pengumumannya. */

/* Nama bangsa: elemen ALIRAN BIASA, bukan keping melayang.
   Versi lama memasangnya `position: absolute; bottom: 8px` di dalam kotak
   potret. Begitu kotaknya dibuang ia kehilangan acuannya dan jatuh menimpa
   kaki model serta baris panji di bawahnya — persis tabrakan yang dikeluhkan.
   Sebagai elemen aliran, jaraknya diatur `gap` kolomnya dan mustahil menimpa
   apa pun. */
.potret-nama {
  align-self: center;
  flex-shrink: 0;
  padding: clamp(4px, 1vh, 8px) clamp(12px, 2.2vw, 20px);
  border: 3px solid var(--garis);
  border-radius: 999px;
  background: var(--kuning);
  color: #2b1f00;
  font-size: var(--fs-label);
  font-weight: 900;
  letter-spacing: var(--lc-kapital);
  white-space: nowrap;
}

/* Sejak §57.39.1 ia `<button>`, bukan `<span>`: menekannya membeli atau
   memilih apa yang sedang berdiri di tengah komidi. Yang perlu disetel cuma
   dua sifat bawaan tombol yang tidak diinginkan (garis tepi peramban sudah
   ditimpa `.potret-nama` sendiri): kursornya, dan tekanan kecil waktu ditekan
   supaya ia terasa sebagai tombol, bukan sebagai keping yang kebetulan bisa
   diklik. */
.potret-nama { cursor: pointer; }
.potret-nama:active { transform: translateY(1px); }

/* TIGA keadaan, dan hanya dua yang berpakaian lain. `.potret-nama` dasarnya
   kuning, dan kuning di seluruh permainan ini berarti satu hal: "ini
   pilihanmu" — jadi ia dipakai apa adanya untuk DIPILIH.

   TERSEDIA (sudah dibeli, belum dipegang) putih bergaris tepi: ia tawaran,
   bukan keadaan. Harga berlambang intan juga putih — bentuk yang sama dengan
   label lobi turnamen (`#tur-nama-bangsa.status-kunci` di css/turnamen.css),
   supaya "putih = belum jadi milikmu / belum jadi pilihanmu" satu arti di
   kedua layar. SEGERA kelabu: satu-satunya dari ketiganya yang tidak bisa
   diapa-apakan pemain. */
.potret-nama.status-ada { background: #fff; color: var(--garis); }
.potret-nama.status-segera { background: #d7dded; color: #4a5570; cursor: default; }
.potret-nama.status-segera:active { transform: none; }
.potret-nama.status-kunci {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: #fff;
  color: var(--garis);
}
.potret-nama.status-kunci svg {
  width: clamp(11px, 2vh, 14px);
  height: clamp(11px, 2vh, 14px);
}

/* ---- keping kuning ---------------------------------------------------- */
.keping {
  flex-shrink: 0;
  padding: clamp(3px, 0.9vh, 6px) clamp(8px, 1.5vw, 12px);
  border: 3px solid var(--garis);
  border-radius: 999px;
  background: var(--kuning);
  color: #2b1f00;
  font-size: var(--fs-kecil);
  font-weight: 900;
  letter-spacing: var(--lc-kapital);
}

/* ---- deret mode -------------------------------------------------------- */
/* EMPAT tombol dalam DUA LAJUR (§43.1), bukan tumpukan tegak. LATIHAN masuk
   sebagai mode keempat, dan empat baris tegak tidak muat di HP mendatar 360 px
   bersama judul dan kaki. Dua lajur menukar tinggi dengan lebar: dua baris saja,
   dan tiap tombol tinggal separuh lebar kolom.

   `minmax(0, 1fr)`, bukan `1fr` — pelajaran §42.6 yang sama: `1fr` sebenarnya
   `minmax(auto, 1fr)`, dan `auto` menolak menyusut di bawah lebar isinya, jadi
   lajur berisi nama terpanjang diam-diam jadi lebih lebar dari tetangganya. */
.deret-mode {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(7px, 2vh, 14px) clamp(7px, 1.5vw, 13px);
}
.mode {
  display: flex;
  align-items: center;
  gap: clamp(9px, 1.8vw, 15px);
  width: 100%;
  padding: clamp(8px, 2vh, 16px) clamp(11px, 1.9vw, 17px);
  border: 4px solid var(--garis);
  border-radius: clamp(11px, 2vh, 16px);
  color: #10141c;
  text-align: left;
  cursor: pointer;
  transition: transform 0.08s;
}
/* TANPA PEMBATAS APA PUN (§43.4): tidak ada garis tepi, tidak ada sudut
   membulat, tidak ada bidang putih di belakangnya. Yang membatasi ikon cuma
   tombolnya sendiri. Kotak putih 3 px yang dulu ada di sini membuat tiap tombol
   terbaca sebagai "kotak kecil DI DALAM kotak besar" — dua bingkai bersarang
   untuk satu benda.

   `color` diwariskan ke `currentColor` milik SVG di dalamnya, jadi garis ikonnya
   memakai hitam `--garis` yang sama dengan garis tepi tombol dan hurufnya —
   satu warna garis untuk seluruh menu, bukan hitam versi ikon sendiri. */
.mode-ikon {
  flex-shrink: 0;
  width: clamp(26px, 6.4vh, 44px);
  height: clamp(26px, 6.4vh, 44px);
  display: grid;
  place-items: center;
  color: var(--garis);
}
.mode-ikon svg { display: block; width: 100%; height: 100%; }
/* `flex: 1` DIBUANG (§42.2). Itulah sebab sesungguhnya ruang menganga di tengah
   tombol: blok tulisan menyerap SELURUH sisa lebar kolom lalu mendorong keping
   SEGERA ke tepi kanan, sehingga jarak label→keping terukur 147–195 px di
   892×412 — bukan karena tombolnya kurang pendek, melainkan karena ada yang
   sengaja disuruh melar. Dengan `flex: 0 1 auto`, tulisannya selebar dirinya
   sendiri dan yang memisahkannya dari keping tinggal `gap` barisnya. */
.mode-teks { flex: 0 1 auto; min-width: 0; }
/* Naik ke `--fs-mode` (lihat catatannya di `:root`): terukur 13,2 → 16,5 px di
   892×412. Anak judul yang dihapus membawa pergi ±14 px tinggi tombol, dan tanpa
   penggantinya barisnya jadi pipih — rasio lebar:tinggi justru memburuk walau
   lebarnya sudah dipangkas. Huruf yang lebih besar mengembalikan tinggi itu pada
   bagian yang memang ingin dibaca. */
.mode-teks b {
  display: block;
  font-size: var(--fs-mode);
  font-weight: 900;
  letter-spacing: var(--lc-kapital);
  line-height: 1.1;
  white-space: nowrap;
}
/* Anak judul, hidup lagi sesudah §42.1 membuangnya (§43.2). SENGAJA TIDAK
   `nowrap` seperti nama modenya di atas: nama mode adalah label yang patah dua
   baris akan terlihat rusak, sedangkan keterangan ini boleh melipat kalau
   layarnya benar-benar sempit — dan lebih baik ia melipat daripada memaksa
   kolomnya melar dan menghidupkan kembali ruang kosong yang jadi keluhan §42.

   `font-style: normal` pada `<i>`: unsurnya dipilih karena maknanya
   ("keterangan sampingan"), bukan karena miringnya. Huruf miring pada teks
   sekecil ini justru mengurangi keterbacaan di layar HP. */
.mode-teks i {
  display: block;
  margin-top: clamp(1px, 0.5vh, 4px);
  /* `--fs-label`, bukan `--fs-kecil` (§43.11). `--fs-kecil` adalah anak tangga
     paling bawah — tempat keterangan pinggiran seperti "kabur: 0" — dan pada
     892×412 ia cuma 9,5 px. Keterangan mode bukan pinggiran: ia satu-satunya
     kalimat yang menjelaskan apa isi tombolnya. Tetap memakai anak tangga yang
     SUDAH ADA, bukan angka keenam sendiri (§32 melarang itu). */
  font-size: var(--fs-label);
  font-style: normal;
  font-weight: 700;
  letter-spacing: var(--lc-biasa);
  line-height: 1.15;
  color: rgba(16, 20, 28, 0.74);
}
/* Keping SEGERA didorong ke kanan oleh MARGIN, bukan oleh tulisan yang melar.
   Bedanya nyata: `margin-left: auto` cuma menyerap sisa ruang yang MEMANG ada,
   sedangkan `flex: 1` pada tulisan MENCIPTAKAN ruang itu lebih dulu. Di kolom
   yang sudah dipersempit (§42.2) sisanya tinggal beberapa piksel, jadi kepingnya
   berdiri tepat di sebelah tulisan seperti yang diminta. */
.mode > .keping,
.mode > .mode-panah { margin-left: auto; }
/* Bayangan pejal DIRAMPINGKAN dari 6 px ke 4 px (dan tombol pil dari 4 ke 3).
   Bayangan tebal ala balok mainan itu memang tanda khas gaya rujukannya, tapi
   ia juga yang membuat tombol menempel ke tepi bawah layar — tinggi yang
   terlihat selalu tinggi tombol DITAMBAH bayangannya. Diperkecil, bukan
   dihapus: pemendekan bayangan waktu ditekan (`:active` di bawah) adalah
   satu-satunya umpan balik sentuh yang dimiliki tombol ini, dan tanpa bayangan
   sama sekali tidak ada lagi yang bisa dipendekkan. */
.mode.merah { background: var(--merah); }
.mode.biru { background: #6b8cff; }
.mode.hijau { background: var(--hijau); }
.mode.kuning { background: var(--kuning); }
.mode:not(.kunci):active { transform: translateY(3px); }

/* Panah penutup baris. Digambar dari DUA GARIS TEPI sebuah kotak kosong yang
   diputar 45°, bukan dari huruf "›": glif panah diambil dari huruf sistem, jadi
   bentuk dan tebalnya berbeda di tiap perangkat — masalah yang sama persis
   dengan emoji, yang sudah ditolak proyek ini waktu memilih PNG untuk ikon
   tombol sentuh. Kotak berputar ini tebalnya ditentukan CSS, jadi ia sama di
   mana pun.

   Cuma dipasang pada mode yang BISA ditekan. Panah berarti "ada lanjutannya";
   memasangnya pada tombol terkunci akan menjanjikan layar yang belum ada. */
.mode-panah {
  flex-shrink: 0;
  width: clamp(8px, 1.5vh, 12px);
  height: clamp(8px, 1.5vh, 12px);
  margin-right: clamp(2px, 0.6vw, 5px);
  border-right: 3px solid var(--garis);
  border-bottom: 3px solid var(--garis);
  transform: rotate(-45deg);
  opacity: 0.8;
}

/* Mode terkunci: WARNANYA UTUH, cuma diberi keping "SEGERA" dan tidak bisa
   ditekan. Dua percobaan sebelumnya sama-sama meleset — `grayscale(0.85)` +
   `opacity: 0.45` menghasilkan dua baris kelabu yang lenyap ke latar, dan
   `grayscale(0.5)` + `opacity: 0.62` cuma memperlemah gejalanya. Yang keliru
   asumsinya: barisan mode adalah tempat pemain membaca ke mana permainan ini
   tumbuh, jadi meredamnya justru menghapus satu-satunya gunanya. Yang perlu
   dikomunikasikan "belum bisa disentuh", dan untuk itu keping SEGERA plus
   kursor biasa sudah cukup — bayangannya diratakan supaya barisnya tidak
   terlihat menonjol siap ditekan. */
.mode.kunci {
  cursor: default;
}
.kunci-keping { background: #fff; }

/* ---- kartu putih isi pilihan ------------------------------------------ */
.kartu {
  display: flex;
  flex-direction: column;
  gap: clamp(5px, 1.2vh, 10px);
  padding: clamp(11px, 2.3vh, 20px) clamp(11px, 2vw, 20px);
  border: 4px solid var(--garis);
  border-radius: clamp(12px, 2.4vh, 20px);
  background: var(--kartu);
  color: #1b2030;
}
.kartu-kepala {
  /* NOL, bukan `clamp(2px, 0.9vh, 8px)` seperti dulu (§57.64). Kartunya sudah
     `display:flex` dengan `gap`-nya sendiri, jadi margin ini BERTUMPUK di
     atas gap — dan hasil tumpukan itu (13,7 px terukur) tidak berlaku untuk
     judul yang duduk di dalam pembungkus per-mode, yang tidak menerima gap
     kartu sama sekali (5 px). Dinolkan, `gap` jadi satu-satunya penentu jarak
     dan kedua tempat jatuh di angka yang sama. */
  margin-top: 0;
  font-size: var(--fs-label);
  font-weight: 900;
  letter-spacing: var(--lc-biasa);
  /* HITAM, bukan biru terang (§57.41.10). Biru `#3d5afe` di sini bertabrakan
     dengan satu-satunya benda lain di kartu yang berwarna biru — bilah
     terisi penggeser tepat di bawahnya — jadi judul baris terbaca seperti
     bagian dari kontrol yang diaturnya, bukan sebagai namanya. Warna ini yang
     sama dengan seluruh tulisan gelap lain di kartu (`.kartu-teks b`,
     `.baris-info b`). */
  color: #1b2030;
  /* Title Case lewat CSS, bukan lewat teks yang ditulis besar di
     index.html (kalimatnya kadang panjang — "Number of Members in Each
     Warbands" — dan menulisnya kapital di HTML membuat sumbernya sendiri
     susah dibaca waktu disunting). BUKAN ALL CAPS: judul SUB-BAGIAN di
     dalam kartu (Weather, Round, Difficulty Level, Obstacles), bukan
     heading layar (H1) atau tombol. */
  text-transform: capitalize;
}
.kartu-kepala:first-child { margin-top: 0; }
/* §57.64 — JARAK KE KONTROL DI BAWAHNYA, ditulis sebagai `margin-bottom` di
   judulnya sendiri dan bukan diserahkan pada `gap` kartu.

   Terukur sebelum diperbaiki: "Weather" berjarak 8,6 px ke deret tombolnya
   (itu `gap` kartu bekerja) sementara "Round" berjarak 0 px — menempel.
   Bedanya bukan gaya melainkan kedudukan: Round dibungkus `<div>` penyekat
   supaya bisa ditoggle `hidden` per mode, dan `gap` milik kartu berhenti di
   tepi pembungkus itu — anak-anak di DALAMNYA tidak pernah menerimanya.

   Menambal dengan memberi pembungkusnya `display:flex` akan memperbaiki yang
   ini dan meninggalkan perangkap yang sama untuk pembungkus berikutnya. Jarak
   ini milik judulnya, jadi ia yang membawanya — di dalam pembungkus maupun
   tidak.

   NILAINYA SAMA DENGAN `gap` KARTU, bukan angka yang dikira-kira. Terukur
   sesudah tambalan pertama: judul yang jadi anak langsung kartu berjarak
   13,7 px (gap kartu + margin-top judulnya) sementara yang di dalam pembungkus
   cuma 5 px — dua jarak berbeda untuk baris yang sama bentuknya, persis
   ketimpangan yang sedang diperbaiki, cuma bergeser satu langkah.

   Jadi jarak ini DIBERIKAN CUMA DI DALAM PEMBUNGKUS, tempat `gap` kartu tidak
   sampai. Di luar pembungkus, `gap` sudah mengerjakannya dan menambahkan
   margin di sini berarti menumpuk dua jarak — cacat yang sama, arah
   sebaliknya. Nilainya disamakan dengan `gap` kartu supaya keduanya jatuh di
   angka yang sama, dan `margin-top` bawaan judul dinolkan (lihat
   `.kartu-kepala` di atas) supaya tidak ada suku ketiga yang ikut menumpuk. */
.peta-blok > .kartu-kepala + .pilih-tab,
.peta-blok > .kartu-kepala + .pilih-centang { margin-top: clamp(5px, 1.2vh, 10px); }
/* Pembungkus per-mode: jarak yang sama, supaya baris pertama di dalamnya
   berdiri sejauh dari kontrol di atasnya seperti baris mana pun yang menjadi
   anak langsung kartu. */
.peta-blok { margin-top: clamp(5px, 1.2vh, 10px); }
/* §57.63 — judul bagian KEDUA di dalam satu kartu ("Competition Details" di
   bawah ketiga tombol ukuran). Jaraknya sedikit lebih lebar daripada judul
   pertama: yang di atasnya bukan tepi kartu melainkan sebaris tombol, dan
   jarak antar-baris biasa membuatnya menempel pada tombol terakhir — persis
   bacaan yang judul ini ada untuk mencegahnya.

   §57.64: nilainya diturunkan dari 14 ke 8 karena yang dijumlahkan sekarang
   cuma `gap` kartu (margin bawaan judul sudah nol), bukan gap + margin
   bawaan. Jarak tampaknya tetap kira-kira sama dengan sebelumnya. */
.kartu-kepala.kedua { margin-top: clamp(4px, 1vh, 8px); }
.kartu-kepala.baris-nilai { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.kartu-kepala.baris-nilai b {
  min-width: 3.4em;
  padding: clamp(1px, 0.4vh, 4px) clamp(7px, 1.2vw, 11px);
  border: 3px solid var(--garis);
  border-radius: 999px;
  background: var(--kuning);
  color: #2b1f00;
  font-size: var(--fs-label);
  font-weight: 900;
  letter-spacing: var(--lc-biasa);
  text-align: center;
  font-variant-numeric: tabular-nums;
  /* Title Case, bukan ALL CAPS — biasanya angka murni, tapi bisa berisi
     status ('Solo' untuk 0 anggota). */
  text-transform: capitalize;
}
.kartu-teks { font-size: var(--fs-label); font-weight: 600; line-height: 1.6; color: #46506b; }
.kartu-teks b { color: #1b2030; font-weight: 800; }
.kartu-kecil { font-size: var(--fs-kecil); font-weight: 600; line-height: 1.5; color: #7b869d; }

/* ---- baris HASIL, bukan baris pilihan ---------------------------------
   Durasi tidak pernah dipilih pemain — ia jatuh dari jumlah tim lewat
   `durasiUntuk()` di js/main.js. Karena itu bentuknya sengaja DIBEDAKAN dari
   baris pilihan di atasnya: tanpa garis tepi gelap tebal, berlatar kelabu
   muda. Baris hasil yang berpakaian seperti kontrol akan terus disentuh pemain
   dan tidak pernah membalas. */
.baris-info {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: clamp(3px, 1vh, 9px);
  padding: clamp(6px, 1.4vh, 11px) clamp(9px, 1.7vw, 14px);
  border-radius: clamp(8px, 1.6vh, 12px);
  background: #eef1f6;
  font-size: var(--fs-kecil);
  font-weight: 800;
  letter-spacing: var(--lc-biasa);
  color: #6b7590;
  /* Title Case, bukan ALL CAPS — label baris hasil (Map, Round, Reward),
     bukan heading/tombol. Ditimpa lagi eksplisit di blok konsolidasi ujung
     berkas (`.baris-info span`/`.baris-info b`) — dua deklarasi sama
     sengaja, supaya tidak ada satu sumber kebenaran yang lupa disamakan. */
  text-transform: capitalize;
}
/* Aturan `.tangga-baris`/`.tangga-titik`/`.tangga-maks` DICABUT bersama baris
   "AI Skill" (§57.42.1) — tidak ada lagi elemen yang memakainya. */

.baris-info b {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: #1b2030;
  font-size: var(--fs-label);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Baris REWARD dan ENTRANCE FEE membawa lambang intan sebaris (§57.42.11).
   Sama seperti di tombol berharga: SVG sebaris tanpa ukuran mengembang sampai
   setinggi barisnya, jadi ia dijepit ke ukuran hurufnya di sini. */
.baris-info b svg { width: 0.95em; height: 0.95em; flex-shrink: 0; }

/* ---- pilih bangsa: panji sungguhan, bukan kotak warna.
   Gambarnya diambil dari tekstur panji prosedural yang dipakai bendera di dalam
   permainan (`teksturPanji()`), jadi bendera di menu PERSIS bendera yang nanti
   berkibar di bentengnya — nol aset baru, dan mustahil keduanya menyimpang
   karena tidak ada salinan kedua yang harus ikut disetel. */
/* ---- komidi geser pilih bangsa: YANG DI TENGAH ITULAH YANG TERPILIH ----
   Jendelanya tetap tiga kartu (§42.4) — hari bangsa kedelapan selesai digambar,
   tidak ada satu pun angka di berkas ini yang perlu diubah, dan kartunya tidak
   menyusut jadi keping selebar jempol.

   Yang berubah: sepasang panah kiri/kanan dibuang, dan yang menggantikannya
   gerakan, bukan tombol lain. Strip ini digulir jempol lalu berhenti sendiri di
   kartu terdekat.

   Penghentiannya diserahkan ke `scroll-snap-type`, BUKAN dihitung sendiri di
   JS. Bukan karena lebih pendek — karena gulir bermomentum di HP punya kurva
   perlambatan milik sistem operasi, dan animasi buatan sendiri yang berjalan di
   atasnya selalu terasa setengah detik lebih lambat dari jari yang melepasnya.
   JS di sini cuma MEMBACA kartu mana yang akhirnya berhenti di tengah. */
.komidi {
  position: relative;
  flex-shrink: 0;
  /* Strip ini DIDORONG KE DASAR kolom kirinya (§47.1). Selama potretnya masih
     melar mengisi sisa ruang, `auto` di sini bernilai nol dan tidak mengubah
     apa pun; ia baru bekerja kalau suatu saat ada yang membatasi tinggi potret
     lagi. Gunanya menjamin satu hal yang dipakai kolom kanan sebagai acuan:
     dasar kartu komidi selalu jatuh di garis yang sama dengan dasar kolomnya
     dikurangi ruang patokan. */
  margin-top: auto;
  /* Ruang untuk patokan di bawah kartu tengah. Kalau tidak disediakan, patokan
     yang `position: absolute` tidak menyumbang tinggi apa pun ke induknya dan
     ia akan tertimpa apa pun yang berdiri di bawah strip ini — cacat yang sama
     persis dengan lambang judul di §43.3. */
  padding-bottom: var(--ruang-patokan);
}
.komidi-jalur {
  /* Dua peubah ini SATU-SATUNYA sumber lebar kartu, dan ruang kosong di kedua
     ujung memakai angka yang sama. Ditulis dua kali, keduanya akan menyimpang
     pada penyuntingan berikutnya dan bangsa pertama berhenti setengah kartu di
     luar tengah — meleset yang tidak menghasilkan galat apa pun, cuma pilihan
     yang salah. */
  --celah-pihak: clamp(5px, 1vw, 10px);
  --lebar-pihak: calc((100% - 2 * var(--celah-pihak)) / 3);

  display: flex;
  gap: var(--celah-pihak);
  overflow-x: auto;
  /* Menyeret strip ini dengan tetikus TIDAK boleh ikut menyorot nama bangsa di
     dalam kartunya. Tanpa ini, setiap geseran meninggalkan blok sorotan biru di
     bawah panji — dan sorotan itu bertahan sesudah jari dilepas. */
  user-select: none;
  -webkit-user-select: none;
  /* Guliran yang sampai di ujung tidak boleh diteruskan ke halaman di
     belakangnya — di HP itu yang membuat seluruh menu ikut bergoyang waktu
     pemain menggeser melewati bangsa terakhir. */
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* Batangnya disembunyikan, bukan disisakan: ia menambah tinggi hanya di
     desktop, jadi strip ini akan berbeda tinggi di dua perangkat tanpa alasan
     yang bisa dilihat pemain. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.komidi-jalur::-webkit-scrollbar { display: none; }
/* RUANG KOSONG DI KEDUA UJUNG SUDAH DIBUANG (§46.1), dan aturannya sengaja
   ditinggalkan sebagai catatan supaya tidak dihidupkan lagi.

   Dulu sepasang `::before`/`::after` selebar satu kartu berdiri di sini, dan
   gunanya benar: tanpa keduanya kartu pertama dan terakhir mentok di tepi dan
   tidak pernah sampai ke tengah, sehingga "yang di tengah itulah yang terpilih"
   jadi janji yang justru gugur di dua tempat paling sering dikunjungi.

   Tapi harganya ikut terlihat begitu dipakai: waktu Romawi di tengah, petak
   kirinya KOSONG; waktu Viking di tengah, petak kanannya kosong. Dua dari empat
   bangsa — dan satu dari tiga arena — tampil dengan jendela yang bolong
   separuh, dan yang bolong itu justru sisi yang seharusnya mengundang digeser.

   Daftarnya sekarang MELINGKAR: js/main.js menggambar beberapa salinan penuh
   berjajar lalu memindahkan guliran tanpa animasi kembali ke salinan tengah
   tiap kali strip berhenti. Karena isi tiap salinan sama persis, pemindahan itu
   tidak terlihat sama sekali — yang tersisa cuma daftar yang tidak punya ujung.
   Ganjalan ujung karena itu bukan cuma tidak dibutuhkan lagi: ia akan menyisipkan
   lubang selebar satu kartu di tengah lingkaran. */
.komidi-kartu {
  /* `flex: 0 0 <lebar>` — bukan `flex: 1`. Di wadah yang boleh digulir, `1`
     membuat keempat kartu berbagi lebar yang terlihat dan gulirannya jadi tidak
     punya apa-apa untuk digulir. */
  flex: 0 0 var(--lebar-pihak);
  scroll-snap-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(3px, 0.8vh, 7px);
  padding: clamp(5px, 1.2vh, 10px) 3px;
  border: 3px solid var(--garis);
  border-radius: clamp(8px, 1.6vh, 13px);
  background: #eef1f6;
  color: #1b2030;
  cursor: pointer;
  transition: transform 0.14s, background 0.14s, opacity 0.14s;
}
/* Yang TIDAK di tengah diredam sedikit. Bukan hiasan: ia yang membuat "tengah =
   terpilih" terbaca sebelum pemain menggeser sekali pun, tanpa menambah satu
   pun tulisan penjelas ke layar. Diredam ringan saja — kartu tetangga yang
   nyaris tidak terlihat berhenti jadi undangan untuk digeser. */
.komidi-kartu:not(.aktif) { opacity: 0.68; transform: scale(0.92); }
/* ---- patokan: penunjuk kartu mana yang sedang terpilih.
   DIAM di tengah strip, bukan ikut bergerak bersama kartunya. Yang bergerak di
   sini kartunya, dan patokan yang ikut bergeser cuma akan jadi benda kedua yang
   harus diikuti mata. Digambar dari dua garis tepi kotak kosong yang diputar,
   bukan dari glif "▲" — sama seperti `.mode-panah`: glif diambil dari huruf
   sistem, jadi bentuk dan tebalnya berbeda di tiap perangkat. */
.komidi-patokan {
  position: absolute;
  left: 50%;
  bottom: clamp(2px, 0.5vh, 5px);
  width: clamp(9px, 1.6vh, 13px);
  height: clamp(9px, 1.6vh, 13px);
  border-top: 3px solid var(--kuning);
  border-left: 3px solid var(--kuning);
  transform: translateX(-50%) rotate(45deg);
  /* Kuning di atas arena hijau yang terang butuh garis gelapnya sendiri; tirai
     `#menu` saja tidak cukup waktu kamera kebetulan melewati tembok benteng. */
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.9));
}
.komidi-kartu img {
  width: 100%;
  max-width: clamp(26px, 6.2vh, 46px);
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border: 2px solid var(--garis);
  border-radius: 5px;
  image-rendering: pixelated;
}
.komidi-kartu span {
  font-size: var(--fs-kecil);
  font-weight: 800;
  letter-spacing: var(--lc-biasa);
}
.komidi-kartu.aktif { background: var(--kuning); }

/* Kartu arena memakai IKON GARIS, bukan gambar panji seperti kartu bangsa.
   Bukan sekadar karena arenanya belum digambar: panji itu benda yang memang ada
   di dalam permainan dan diambil dari tekstur yang sama (`teksturPanji()`),
   sementara gambar kecil arena tidak punya sumber semacam itu — ia harus
   digambar tangan, dan gambar tangan yang menirukan arena adalah salinan kedua
   yang bisa menyimpang dari arena aslinya. Ikon garis tidak berpura-pura jadi
   potret: ia lambang, dan lambang tidak bisa keliru soal rupa.

   Ukurannya disamakan dengan `img` di atas supaya kedua komidi setinggi sama —
   lihat catatan di `.pratinjau`. */
.komidi-kartu svg {
  display: block;
  width: 100%;
  max-width: clamp(20px, 4.6vh, 34px);
  height: auto;
  aspect-ratio: 1;
  color: var(--garis);
}
/* Arena yang BELUM DIGAMBAR. Diredam sedikit dan diberi keping SEGERA, tapi
   TETAP berwarna utuh dan tetap bisa dibawa ke tengah — §32.6 dua kali menolak
   mengelabukan tombol terkunci karena itu menghapus satu-satunya gunanya:
   memberi tahu pemain ke mana permainan ini tumbuh. Yang dicegah cuma
   berangkatnya, dan itu diurus tombol MULAI BERTEMPUR, bukan kartu ini. */
.komidi-kartu .keping {
  padding: 1px clamp(4px, 1vw, 7px);
  border-width: 2px;
  font-size: clamp(7px, 1.35vh, 9px);
  letter-spacing: 0;
}
/* Kartu terkunci yang sedang DI TENGAH tetap tersorot penuh: sorotan itu
   menjawab "yang mana yang sedang saya lihat", bukan "yang mana yang bisa
   dimainkan". Pertanyaan kedua dijawab tombol berangkat yang mati. */
.komidi-kartu.kunci:not(.aktif) svg { opacity: 0.75; }
/* KEPING HARGA, dan ia sengaja berbeda rupa dari keping SEGERA di sebelahnya.
   Keduanya menempel di kartu yang sama-sama terkunci, tapi artinya berlawanan
   arah: SEGERA berarti "belum ada, tidak ada yang bisa kamu lakukan", HARGA
   berarti "sudah ada, dan ini ongkosnya". Keping yang serupa untuk dua kabar
   yang berlawanan adalah cara tercepat membuat pemain berhenti membaca
   keduanya. Karena itu harga berlambang intan dan berlatar putih bergaris,
   bukan kuning pejal. */
.komidi-kartu .keping.harga {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  background: #fff;
  color: var(--garis);
}
.komidi-kartu .keping.harga svg {
  height: clamp(7px, 1.35vh, 9px);
  width: auto;
  opacity: 1;
}
/* Kartu bangsa yang terkunci tidak dikelabukan (§32.6), tapi panjinya diredam
   sedikit supaya keping harganya menang di mata. */
.komidi-kartu.kunci:not(.aktif) img { opacity: 0.72; }

/* ---- kotak centang jenis rintangan (§47.3) -----------------------------
   Satu baris chip di bawah tab AKTIF/NONAKTIF, satu chip per jenis rintangan
   yang dikenal arena terpilih.

   BUKAN `<input type="checkbox">`, dengan alasan yang sama yang membuat
   penggeser di kartu ini memakai `appearance: none` (lihat `.geser`): kotak
   centang bawaan peramban digambar sistem operasi, jadi ia berbeda bentuk di
   tiap perangkat dan tidak satu pun bentuknya berasal dari game ini. Yang
   dipakai tombol biasa dengan `aria-pressed`, dan centangnya SVG sebaris
   seperti seluruh ikon menu (§43.4).

   `wrap`, dan itu bukan kehati-hatian berlebihan: hutan sudah punya tiga jenis
   hari ini, dan di kolom kanan 640×360 tiga chip beserta labelnya sudah dekat
   dengan lebar yang tersedia. Arena yang suatu saat punya empat akan melipat
   sendiri alih-alih meluber. */
.pilih-centang {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(4px, 0.9vw, 8px);
}
.centang {
  display: flex;
  align-items: center;
  gap: clamp(4px, 0.8vw, 7px);
  padding: clamp(5px, 1.1vh, 9px) clamp(8px, 1.4vw, 13px);
  border: 3px solid var(--garis);
  border-radius: clamp(8px, 1.6vh, 12px);
  background: #eef1f6;
  color: #1b2030;
  font-size: var(--fs-kecil);
  font-weight: 800;
  line-height: 1;
  letter-spacing: var(--lc-biasa);
  cursor: pointer;
  transition: background 0.1s;
  /* Title Case, bukan huruf kecil apa adanya — chip Obstacle Detail
     (Tree/Rock/River), status singkat, bukan heading/tombol. Sumbernya
     (`RINTANG[k].nama` di js/peta.js) sengaja huruf kecil karena juga
     dipakai id ikon berkas gambar; casing tampilannya diurus di sini. */
  text-transform: capitalize;
}
/* Kotaknya PERSEGI walau chip-nya bulat, dan itu disengaja: bentuk persegi
   dengan centang di dalamnya adalah satu-satunya bentuk yang sudah dikenal
   semua orang sebagai "boleh lebih dari satu". Chip bulat tanpa kotak akan
   terbaca sebagai tab — dan tab berarti pilih salah satu. */
.centang-kotak {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: clamp(13px, 2.2vh, 18px);
  height: clamp(13px, 2.2vh, 18px);
  border: 2.5px solid var(--garis);
  border-radius: 4px;
  background: #fff;
  color: transparent;          /* centangnya baru berwarna waktu tercentang */
}
.centang-kotak svg { display: block; width: 82%; height: 82%; }
/* Tercentang = HIJAU, warna yang sama dengan tab AKTIF dan tombol MULAI
   BERTEMPUR (§57.39.6). Dulu kuning, dan kuning di layar ini sudah punya arti
   sendiri: "ini pilihanmu" (kartu komidi aktif, keping intan, label DIPILIH).
   Centang rintangan bukan pilihan tunggal melainkan saklar nyala/padam, dan
   nyala/padam sudah punya warnanya sendiri satu baris di atasnya. */
.centang.aktif { background: var(--hijau); color: #06301a; }
.centang.aktif .centang-kotak { background: var(--hijau); color: #06301a; }
.centang:not(:disabled):active { transform: translateY(1px); }

/* ---- tab tersegmen (kesulitan) ---------------------------------------- */
.pilih-tab { display: flex; gap: clamp(5px, 1vw, 9px); }
.pilih-tab .tab {
  flex: 1;
  padding: clamp(7px, 1.7vh, 13px) 4px;
  border: 3px solid var(--garis);
  border-radius: clamp(8px, 1.6vh, 12px);
  background: #eef1f6;
  color: #1b2030;
  /* Ditulis panjang, BUKAN `font: 900 var(--fs-kecil)/1 inherit`. Bentuk
     ringkas itu tampak benar dan diam-diam salah: `inherit` di dalam shorthand
     `font` membuat peramban memperlakukan SELURUH deklarasi sebagai
     `font: inherit`, sehingga tebal dan ukurannya dibuang tanpa peringatan.
     Terukur sebelum diperbaiki — tab ini, `.pil`, dan `.tbl-besar` semuanya
     mengembalikan 16 px / tebal 400 (nilai warisan dari body), bukan ukuran
     dan tebal yang tertulis di sebelahnya. Itu sebabnya tombol menu terlihat
     tipis dan seragam besarnya. */
  font-size: var(--fs-label);
  font-weight: 900;
  line-height: 1;
  letter-spacing: var(--lc-kapital);
  cursor: pointer;
  transition: transform 0.08s, background 0.14s;
}
.pilih-tab .tab:active { transform: scale(0.96); }
.pilih-tab .tab.aktif { background: var(--hijau); }
/* Tab yang TIDAK BERLAKU di arena terpilih (mis. HUJAN di gurun): diredam dan
   dimatikan, TETAP DIGAMBAR. Menyembunyikannya akan memendekkan kartu ini tiap
   kali komidi arena berhenti di arena yang cuacanya lebih sedikit, dan seluruh
   isi di bawahnya melompat naik tepat waktu mata pemain masih di komidi.
   Diredam, kartunya diam dan yang berubah cuma yang bisa ditekan — sekaligus
   memberi tahu bahwa cuaca itu ada, cuma tidak di sini. Prinsip yang sama
   dengan §32.6 menolak menyembunyikan mode yang belum jadi.

   `:disabled` sudah menghentikan ketukan dan `click` sendiri, jadi tidak ada
   penjaga kedua yang perlu ditulis di js/main.js. */
.pilih-tab .tab:disabled {
  opacity: 0.34;
  cursor: default;
  transform: none;
}
/* SATU KOLOM, bukan sebaris (§57.42.11 — tombol ukuran turnamen). Labelnya di
   sana bukan satu kata melainkan dua bagian ("Medium" beserta "(1 vs 3)"), dan
   tiga label sepanjang itu berdampingan di kartu selebar ±420 px berakhir
   patah dua baris masing-masing — tiga tombol setinggi dua baris yang isinya
   terpotong. Ditumpuk, tiap tombol dapat lebar penuh kartu dan labelnya utuh
   dalam satu baris, dan tinggi memang yang berlimpah di kartu ini sesudah
   Weather/Obstacles/Obstacle Detail tidak ada di sini. */
.pilih-tab.tegak { flex-direction: column; }

/* ---- penggeser --------------------------------------------------------
   Digambar sendiri, bukan `accent-color` bawaan. Penggeser bawaan peramban
   bergaris tipis dan berknop rata — di antara tombol bergaris tepi 3-4 px ia
   satu-satunya benda yang terlihat berasal dari formulir, bukan dari game.

   Bagian yang sudah terlewati diisi warna lewat peubah `--isi` yang ditulis
   js/main.js tiap kali nilainya berubah. `accent-color` tidak bisa dipakai
   untuk itu karena ia mati begitu `appearance: none` dipasang. */
/* KNOPNYA KOTAK DAN LEBIH BESAR (§57.41.10), bukan lagi bulatan kuning kecil.
   Knop bulat berdiameter 15-22 px adalah satu-satunya bentuk bulat di seluruh
   kartu pengaturan — semua tetangganya (tab kesulitan, kotak centang, keping
   nilai) persegi bersudut tumpul — jadi ia terbaca seperti benda dari
   formulir peramban yang lupa disetel. Yang persegi juga jauh lebih mudah
   ditangkap jempol: sisi datar 30 px lawan lengkung 22 px.

   Tinggi knop dibuat SAMA PERSIS dengan tinggi input, karena `appearance:
   none` tanpa aturan `::-webkit-slider-runnable-track` membuat webkit
   meratakan knop ke TEPI ATAS jalurnya alih-alih memusatkannya. Satu peubah
   `--gsr` yang memegang keduanya, jadi keduanya tidak bisa berselisih. */
.geser {
  --gsr: clamp(19px, 3.4vh, 26px);
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: var(--gsr);
  margin: clamp(1px, 0.4vh, 4px) 0;
  border: 3px solid var(--garis);
  border-radius: 7px;
  background: linear-gradient(90deg, #3d5afe 0 var(--isi, 50%), #dfe4ee var(--isi, 50%) 100%);
  cursor: pointer;
}
.geser::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: calc(var(--gsr) * 1.35);
  height: var(--gsr);
  border: 3px solid var(--garis);
  border-radius: 5px;
  background: var(--kuning);
}
.geser::-moz-range-thumb {
  width: calc(var(--gsr) * 1.35);
  height: var(--gsr);
  border: 3px solid var(--garis);
  border-radius: 5px;
  background: var(--kuning);
}

/* ---- tombol besar & pil kaki ------------------------------------------ */
/* MULAI BERTEMPUR SENGAJA TIDAK `flex: 1` LAGI.
   Dibiarkan melebar mengisi sisa baris, ia terukur 450×48 (9,4 : 1) waktu
   barisnya selebar kartu, lalu 298×48 (6,2 : 1) sesudah barisnya dibatasi 430
   px — dan pada ukuran itu pun masih dilaporkan memanjang. Sebabnya bukan
   lebarnya saja melainkan PERBANDINGANNYA: tombol setinggi 48 px tidak akan
   pernah terlihat gempal seberapa pun lebarnya dipangkas, karena lebar
   minimumnya sudah ditentukan panjang tulisannya sendiri (±225 px untuk "MULAI
   BERTEMPUR" pada ukuran huruf tombol).

   Jadi yang dikerjakan dua-duanya: lebarnya dikunci di sekitar batas bawah yang
   masih memuat tulisannya, DAN tingginya dinaikkan lewat padding tegak. 240×57
   memberi 4,2 : 1 — perbandingan yang sama dengan tombol besar di game acuan,
   dan tombol yang lebih tinggi juga lebih mudah ditekan jempol. */
.tbl-besar {
  /* Batas atasnya 268 px, bukan 250. Terukur waktu memeriksa kaki bertiga
     (§42.3): di 1280×720 dan 1366×768, "MULAI BERTEMPUR" satu baris meminta
     255,1 px sementara clamp ini menahannya di 250 — jadi labelnya patah dua
     baris DI DALAM tombolnya sendiri, kurang 5,1 px. Cacat lama, bukan akibat
     BARAK: diuji dengan BARAK dicabut dari barisnya, patahnya tetap terjadi.
     Batas ini gunanya menahan tombol supaya tidak melar di layar lebar, dan
     batas yang lebih sempit dari label yang harus dimuatnya bukan penahan,
     melainkan pemotong. */
  flex: 0 1 clamp(190px, 23vw, 268px);
  padding: clamp(12px, 3vh, 24px) clamp(12px, 2vw, 22px);
  border: 4px solid var(--garis);
  border-radius: clamp(11px, 2vh, 16px);
  font-size: var(--fs-tombol);      /* longhand — lihat catatan di `.pilih-tab .tab` */
  font-weight: 900;
  line-height: 1;
  letter-spacing: var(--lc-kapital);
  cursor: pointer;
  transition: transform 0.08s;

  /* Warna dan bayangan diambil dari TIGA peubah yang diisi kelas warnanya
     (§47.2). Sebelumnya `background` dan `box-shadow` ditulis di `.tbl-besar.hijau`
     sementara bayangan tekannya ditulis di `.tbl-besar:active` dengan
     `var(--hijau-bawah)` yang dipahat — jadi tombol warna KEDUA akan mewarisi
     bayangan tekan hijau, dan cacatnya cuma terlihat selama 80 milidetik saat
     tombolnya ditekan. */
  background: var(--tbl-atas);
  color: var(--tbl-teks);
}
.tbl-besar.hijau { --tbl-atas: var(--hijau); --tbl-bawah: var(--hijau-bawah); --tbl-teks: #06240f; }
/* Biru untuk tindakan yang BERPINDAH, hijau untuk yang MENGAKHIRI persiapan.
   Warnanya sudah punya arti itu di HUD (§40.7: biru = melempar/surut, dipakai
   SALVO dan MUNDUR), dan yang dipinjam di sini bukan artinya melainkan
   kedudukannya: biru adalah warna yang bukan "jalan terakhir". Tulisannya gelap
   seperti seluruh tombol menu ini — putih di atas #4b90e2 cuma 3,2 : 1. */
.tbl-besar.biru { --tbl-atas: var(--biru); --tbl-bawah: var(--biru-bawah); --tbl-teks: #071f3a; }
/* KUNING = "belanja". Ia sengaja BUKAN hijau: hijau di baris kaki selalu berarti
   "berangkat sekarang", dan tombol yang memotong intan lalu tetap meninggalkan
   pemain di layar yang sama tidak boleh memakai warna yang menjanjikan
   perpindahan. Kuning juga warna keping intan dan warna tombol iklan di pojok,
   jadi ketiganya terbaca sebagai satu keluarga: yang berhubungan dengan intan
   berwarna kuning, di mana pun ia berdiri. */
.tbl-besar.kuning { --tbl-atas: var(--kuning); --tbl-bawah: var(--kuning-bawah); --tbl-teks: #2b1f00; }
/* BUKA (Unlock) membawa ikon intan sebaris di depan angkanya, bukan lagi kata
   "INTAN" yang dieja — jadi tombolnya perlu jadi baris flex supaya ikon dan
   dua potong teksnya (UNLOCK, lalu ikon+angka) sejajar rapi di tengah. */
/* `:not([hidden])` — TANPA itu, `display` di sini mengalahkan `display: none`
   bawaan `[hidden]` (keduanya spesifisitas 0-1-0, dan aturan penulis SELALU
   menang atas lembar gaya UA berapa pun spesifisitasnya), jadi tombol BUKA
   yang sedang disembunyikan (bangsa/peta sudah terbuka) akan tetap muncul
   sebagai kotak kuning kosong. */
/* `.harga` ikut aturan yang sama dan bukan sebagai kelas kembar yang
   kebetulan mirip: keduanya tombol yang MENULISKAN HARGA di badannya sendiri
   (UNLOCK ⟡300, ENTER ⟡50), dan lambang intan sebaris tanpa ukuran akan
   mengembang memenuhi tombolnya di mana pun ia dipasang. Satu aturan untuk
   satu bentuk, jadi tombol berharga ketiga tidak perlu menemukan cacat yang
   sama lagi dari nol. */
.tbl-besar.buka:not([hidden]),
.tbl-besar.harga:not([hidden]) { display: inline-flex; align-items: center; justify-content: center; gap: clamp(4px, 1vw, 8px); }
.tbl-besar.buka svg,
.tbl-besar.harga svg { width: 0.8em; height: 0.8em; flex-shrink: 0; }
.tbl-besar:not(:disabled):active { transform: translateY(3px); }
/* Tombol SEKUNDER di baris kaki: selebar labelnya saja, bukan selebar anggaran
   tombol besar. Dua tombol berlebar penuh meminta ±385 px sementara kolom kanan
   di 640×360 cuma ±355 px — keduanya menyusut rata dan "MULAI BERTEMPUR" patah
   dua baris di dalam tombolnya sendiri. `nowrap` bukan hiasan yang menemani:
   tanpanya ia menyusut dengan memotong labelnya, bukan dengan berhenti
   menyusut, jadi barisnya terlihat "muat" sambil tetap salah. */
.tbl-besar.sisi { flex: 0 1 auto; white-space: nowrap; }
/* Berangkat ke arena yang BELUM DIGAMBAR. Ini satu-satunya tempat di seluruh
   menu yang benar-benar boleh mengelabukan tombol, dan alasannya berbeda dari
   yang ditolak §32.6: di sana redaman dipakai untuk mengumumkan "belum ada" —
   pekerjaan yang sudah dikerjakan keping SEGERA dengan lebih jelas. Di sini
   redaman mengumumkan "tidak bisa DITEKAN SEKARANG", dan itu memang persis apa
   yang terjadi. Kepingnya sendiri sudah ada di kartu arenanya, jadi keterangan
   "belum digambar" tidak diulang dua kali di layar yang sama. */
.tbl-besar:disabled {
  cursor: default;
  filter: grayscale(0.72);
  opacity: 0.6;
}

.menu-kaki {
  flex-shrink: 0;
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: clamp(8px, 1.6vw, 14px);
}
/* Baris KEMBALI + MULAI di layar Quick Match: keduanya sejajar, MULAI melebar
   mengisi sisa. Menumpuknya jadi dua baris memakan tinggi yang persis
   dibutuhkan kartu pengaturan di atasnya pada HP mendatar 360 px. */
/* Barisnya sendiri tidak lagi butuh `max-width`: sesudah MULAI BERTEMPUR
   berhenti melebar (lihat catatan di `.tbl-besar`), lebar baris ini jatuh dari
   jumlah kedua tombolnya — sekitar 118 + 12 + 240 = 370 px — dan `auto` di
   kiri-kanan memusatkannya di bawah kartu. Membatasi lebarnya lagi cuma akan
   jadi angka kedua yang harus ikut disetel tiap kali salah satu tombol berubah.

   `align-items: stretch` warisan `.menu-kaki` yang membuat KEMBALI ikut
   setinggi MULAI: sepasang tombol yang tingginya berbeda terbaca sebagai dua
   benda yang kebetulan bersebelahan, bukan satu baris keputusan. */
/* Kaki Quick Match / pilih peta.
   `margin` kiri-kanannya 0 dan barisnya RATA KANAN, bukan `auto` yang
   memusatkan. Baris yang dipusatkan berhenti di tempat yang tidak dirujuk apa
   pun di layar; disejajarkan ke kanan, tepi kanannya jatuh persis di tepi kanan
   kartu pengaturan di atasnya — keduanya anak `.kolom-kanan` yang
   `align-items: stretch`, jadi keduanya berakhir di garis yang sama tanpa satu
   angka pun ditulis di sini. Itu yang membuat jaraknya ke tepi layar sama:
   bukan angka yang disamakan, melainkan tepi yang sama.

   `margin-top: auto` (§46.3) — dan inilah yang menyamakan tinggi MULAI BERTEMPUR
   di kedua layar. Kartu pengaturan bangsa punya lima baris isi, kartu arena cuma
   tiga; ditempelkan mengikuti kartunya masing-masing, tombol yang SAMA berdiri
   49–77 px lebih tinggi di layar peta daripada di layar bangsa, dan berpindah
   layar membuatnya melompat. Yang disamakan bukan tinggi kartunya (itu menuntut
   angka tetap di salah satunya — persis yang dibuang §31 dari seluruh menu ini)
   melainkan TEPI yang dirujuk: keduanya sekarang menggantung di dasar kolom
   kanan, dan kedua kolom kanan itu tinggi barisnya sama karena `.layar-isi`
   milik keduanya sama-sama `flex: 1` di bawah kepala layar yang sama tinggi.

   Sisa ruang di antara kartu dan tombol karena itu berkumpul di TENGAH kolom,
   bukan di bawah tombol. Di layar yang isinya justru tidak muat (640×360 pada
   layar bangsa) sisa ruangnya negatif, `auto` jadi nol dengan sendirinya, dan
   tombolnya kembali menempel di kartunya seperti semula — tidak ada cabang
   khusus yang perlu ditulis untuk itu.

   `margin-bottom: var(--ruang-patokan)` (§47.1) — dan inilah yang menaikkan
   barisnya sampai DASAR TOMBOLNYA sejajar dengan DASAR KARTU komidi di kolom
   kiri, bukan dengan dasar strip beserta ruang patokannya. Tanpa itu tombolnya
   berhenti 13–23 px lebih rendah dari kartu di sebelahnya: kedua kolom memang
   berakhir di garis yang sama, tapi yang terlihat mata di kolom kiri bukan tepi
   kolomnya melainkan tepi bawah kartu — dan patokan yang berdiri di bawahnya
   ruang kosong, bukan benda. */
.menu-kaki.rapat {
  margin: 0;
  margin-top: auto;
  margin-bottom: var(--ruang-patokan);
  padding-top: clamp(5px, 1.6vh, 14px);
  justify-content: flex-end;
  gap: clamp(5px, 1vw, 12px);
}
/* Yang TIDAK boleh menyusut yang utama; yang sekunder sudah mengurus lebarnya
   sendiri lewat `.tbl-besar.sisi` di atas. */
.menu-kaki.rapat .tbl-besar:not(.sisi) { flex-shrink: 0; }
.pil {
  padding: clamp(8px, 1.8vh, 14px) clamp(14px, 2.6vw, 24px);
  border: 3px solid var(--garis);
  border-radius: 999px;
  background: #eef1f6;
  color: #1b2030;
  font-size: var(--fs-label);       /* longhand — lihat catatan di `.pilih-tab .tab` */
  font-weight: 900;
  line-height: 1;
  letter-spacing: var(--lc-kapital);
  cursor: pointer;
  transition: transform 0.08s;
}
.pil:not(:disabled):active { transform: translateY(2px); }
/* Pil yang belum bisa ditekan (GAME LAINNYA, §46.5). Perlakuannya sama persis
   dengan tombol pojok: WARNA UTUH, yang diratakan bayangannya. Tanpa aturan ini
   ia tampil identik dengan CARA MAIN di sebelahnya dan satu-satunya tanda bahwa
   ia mati adalah ketukan yang tidak menghasilkan apa-apa — umpan balik yang
   datang sesudah pemain sudah terlanjur menekan.

   TIDAK dikelabukan (§32.6): yang perlu dikatakan tombol yang belum aktif adalah
   "belum bisa disentuh", bukan "jangan lihat aku" — dan di sini justru penting ia
   tetap terlihat, karena keberadaannya sendiri yang mengumumkan permainan ini
   punya saudara. */
.pil:disabled { cursor: default; }
.pil.kembali { background: var(--merah); color: #2b0a06; }

/* BARAK sudah TIDAK ADA di kaki Quick Match. §42.3 memindahkannya ke sana dari
   deret mode beranda, dan seluruh aturannya — petak tegak selebar 46 px, huruf
   8-10,5 px tanpa jarak antarhuruf, keping SEGERA yang dilepas — lahir dari satu
   sebab: kaki bertiga yang tidak punya sisa lebar. Kakinya sekarang berisi satu
   tombol, jadi sebabnya hilang dan aturannya ikut dihapus, bukan disimpan
   menunggu. Waktu BARAK benar-benar dibangun, ia akan lahir di layar yang punya
   ruangnya sendiri dan tidak akan mewarisi satu pun angka sempit itu.

*/

/* ---- gugus pojok kanan atas layar: BAHASA + IKLAN (§43.6, §46.6) --------
   Diukur dari tepi JENDELA, bukan dari kolom menu: induknya `#menu` yang
   `position: fixed; inset: 0`. Lihat catatan di index.html soal kenapa ia bukan
   anak `#layar-beranda`.

   YANG DIPASANG DI POJOK BARISNYA, bukan tombolnya. Sesudah tombol bahasa lahir
   di sebelah kiri iklan, dua elemen `absolute` berdampingan berarti yang kiri
   harus menghitung `right`-nya dari lebar yang kanan ditambah celahnya — lebar
   tombol iklan tertulis di dua tempat, dan yang kedua pasti terlupakan pada hari
   ukurannya disetel. Sebagai satu baris, tombol bahasa tidak tahu apa pun soal
   tetangganya.

   `env(safe-area-inset-*)` dipakai di dua sisi sekaligus. Pojok layar adalah
   satu-satunya tempat lengkungan layar dan poni benar-benar berbahaya — di
   tengah layar keduanya tidak pernah menyentuh apa pun — dan halaman ini memang
   sudah digambar sampai ke tepi lewat `viewport-fit=cover`. */
#sudut-atas {
  position: absolute;
  z-index: 3;
  top: calc(clamp(10px, 2.4vh, 18px) + env(safe-area-inset-top));
  right: calc(clamp(10px, 2vw, 20px) + env(safe-area-inset-right));
  display: flex;
  align-items: stretch;
  gap: clamp(6px, 1.2vw, 11px);
}
#sudut-atas[hidden] { display: none; }

/* ---- kotak profil pojok KIRI-ATAS (§57.42.13) --------------------------
   Sepasang dengan `#sudut-atas` di seberangnya, sampai ke angka: `top` yang
   sama persis, sisipan tepi yang sama, lapisan yang sama. Yang berbeda cuma
   sisinya — dan itu memang satu-satunya yang boleh berbeda, karena dua sudut
   atas yang tidak sejajar terbaca sebagai dua benda yang kebetulan ada di
   dekat tepi, bukan sebagai dua ujung dari satu bilah.

   `--lencana` diisi js/profil.js dari lencana pemain (perunggu/perak/emas),
   dan DUA benda memakainya: garis tepi kotak dan isi bar runtun. Satu peubah,
   bukan dua penulisan warna — kalau tidak, keduanya pasti menyimpang pada hari
   ambang lencananya disetel. */
#profil-sudut {
  --lencana: #c87f3a;
  position: absolute;
  z-index: 3;
  top: calc(clamp(10px, 2.4vh, 18px) + env(safe-area-inset-top));
  left: calc(clamp(10px, 2vw, 20px) + env(safe-area-inset-left));
  display: flex;
  align-items: center;
  gap: clamp(7px, 1.4vw, 11px);
  padding: clamp(5px, 1vh, 8px) clamp(10px, 1.8vw, 15px) clamp(5px, 1vh, 8px) clamp(5px, 1vh, 8px);
  border: 3px solid var(--lencana);
  border-radius: clamp(10px, 2vh, 15px);
  background: rgba(20, 26, 40, 0.82);
  color: #fff;
  cursor: pointer;
  transition: transform 0.08s, filter 0.12s;
}
#profil-sudut[hidden] { display: none; }
#profil-sudut:hover { filter: brightness(1.12); }
#profil-sudut:active { transform: translateY(2px); }
/* Foto kepala pemimpin. Persegi bersudut tumpul, BUKAN lingkaran: setiap
   bingkai di permainan ini persegi bersudut tumpul, dan satu lingkaran di
   pojok layar pembuka akan jadi satu-satunya bentuk yang berasal dari bahasa
   antarmuka lain. */
.profil-foto {
  flex-shrink: 0;
  width: clamp(34px, 6.4vh, 48px);
  height: clamp(34px, 6.4vh, 48px);
  border-radius: clamp(7px, 1.4vh, 11px);
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
}
.profil-foto img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Panji cadangan (render gagal) dipasang `contain`, bukan `cover`: bendera
   yang dipotong penuh kehilangan lambangnya, dan lambang itulah satu-satunya
   yang membedakan sepuluh bendera satu sama lain. */
.profil-foto .panji-besar,
.profil-foto img[src$=".svg"] { object-fit: contain; }
.profil-teks {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  min-width: 0;
}
.profil-nama {
  max-width: clamp(78px, 14vw, 130px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: clamp(11px, 2.1vh, 14px);
  font-weight: 900;
  letter-spacing: var(--lc-biasa);
}
.profil-runtun { display: flex; align-items: center; gap: 6px; }
.profil-bar {
  display: block;
  width: clamp(56px, 10vw, 88px);
  height: clamp(6px, 1.1vh, 9px);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
  overflow: hidden;
}
.profil-bar i { display: block; height: 100%; background: var(--lencana); }
.profil-runtun b {
  font-size: clamp(9.5px, 1.7vh, 12px);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  color: #cfd8ea;
}
/* Kedua tombol memakai kerangka yang SAMA — tinggi, garis tepi, radius, warna
   — supaya keduanya terbaca sebagai sepasang, bukan sebagai satu tombol dan
   satu tempelan. Keduanya sekarang membawa ikon+teks (AD, ID) jadi lebarnya
   sama-sama mengikuti isinya, bukan dipatok persegi.

   Warnanya UTUH walau `disabled`, mengikuti §32.6: yang perlu dikatakan sebuah
   tombol belum aktif adalah "belum bisa disentuh", bukan "jangan lihat aku".
   Bayangannya yang diratakan — itulah tanda ia tidak sedang menunggu ditekan. */
#sudut-atas > button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(3px, 0.8vw, 6px);
  height: clamp(38px, 7.6vh, 54px);
  padding: clamp(5px, 1.2vh, 9px);
  border: 3px solid var(--garis);
  border-radius: clamp(10px, 1.8vh, 15px);
  background: var(--kuning);
  color: var(--garis);
  cursor: pointer;
  transition: transform 0.08s;
}
#sudut-atas > button:disabled { cursor: default; }
#sudut-atas > button:not(:disabled):active { transform: translateY(2px); }
/* Ikon mengambil tingginya dari tombol, bukan lebarnya: tombol bahasa lebih
   lebar dari tinggi, dan `width: 100%` yang dipakai versi lama akan meregangkan
   bola buminya jadi lonjong. */
#sudut-atas svg { display: block; height: 100%; width: auto; aspect-ratio: 1; }

/* KEPING INTAN. Kerangkanya sengaja SAMA PERSIS dengan kedua tombol di
   sebelahnya — tinggi, garis tepi, radius, warna — supaya ketiganya terbaca
   sebagai satu gugus. Yang membedakannya bahwa ia TIDAK punya bayangan tekan
   dan tidak punya `:active`: bayangan itulah satu-satunya yang mengatakan
   "benda ini bisa ditekan", dan keping ini memang tidak bisa. */
#intan-sudut {
  display: flex;
  align-items: center;
  gap: clamp(3px, 0.8vw, 6px);
  height: clamp(38px, 7.6vh, 54px);
  padding: clamp(5px, 1.2vh, 9px) clamp(9px, 1.6vw, 13px);
  border: 3px solid var(--garis);
  border-radius: clamp(10px, 1.8vh, 15px);
  background: var(--kuning);
  color: var(--garis);
}
#intan-sudut svg { display: block; height: 68%; width: auto; aspect-ratio: 1; }
#intan-nilai {
  font-size: var(--fs-kecil);
  font-weight: 900;
  line-height: 1;
  letter-spacing: var(--lc-kapital);
  /* Angka bertabular supaya kepingnya tidak berdenyut lebar tiap kali digitnya
     berubah — dari 99 ke 100 lebarnya melompat, dan yang melompat duduk di
     pojok layar tempat mata memakainya sebagai patokan diam. */
  font-variant-numeric: tabular-nums;
  min-width: 2.4ch;
  text-align: right;
}
/* Sesaat sesudah bertambah. Satu denyut, bukan animasi berulang: yang perlu
   diberitahukan cuma "ini yang barusan berubah". */
#intan-sudut.naik { animation: intan-naik 0.5s ease-out; }
@keyframes intan-naik {
  0% { transform: scale(1); }
  35% { transform: scale(1.18); }
  100% { transform: scale(1); }
}
#bahasa-sudut span, #musik-sudut span, #ads-sudut span {
  font-size: var(--fs-kecil);
  font-weight: 900;
  line-height: 1;
  letter-spacing: var(--lc-kapital);
  /* Title Case, bukan ALL CAPS — status pendek (En/On/Off/Ad), bukan
     heading/tombol utama. */
  text-transform: capitalize;
}

/* ---- gerakan masuk elemen 2D (butir tertunda §30.11) -------------------
   Perpindahan antar layar dulu berupa GANTI SEKETIKA: `keLayar()` cuma
   memindahkan atribut `hidden`. Itu tidak mengganggu waktu semua layar
   berbentuk sama, tapi sesudah beranda jadi satu kolom di tengah dan Quick
   Match jadi dua kolom kiri-kanan, ketukannya melompat dari susunan yang satu
   ke susunan yang sama sekali lain dalam satu bingkai.

   Tidak ada JS yang perlu ditambahkan untuk memicunya: elemen yang berpindah
   dari `display: none` ke terlihat MEMULAI ULANG animasinya sendiri, dan
   `hidden` persis melakukan itu. Jadi pemicunya sudah ada sejak dulu.

   `backwards`, BUKAN `both`. Keduanya sama-sama mengisi tahap sebelum animasi
   berjalan, tapi `both` juga mempertahankan bingkai terakhir SESUDAH selesai —
   dan nilai dari animasi mengalahkan deklarasi biasa, sehingga
   `transform: translateY(3px)` pada `:active` tombol tidak akan pernah berlaku
   lagi. `backwards` melepaskan propertinya begitu animasi habis, jadi umpan
   balik tekan tombol tetap hidup. */
@keyframes menu-masuk {
  from { opacity: 0; transform: translateY(11px); }
  to { opacity: 1; transform: none; }
}
.layar > *,
.deret-mode > *,
.menu-kaki > * {
  animation: menu-masuk 0.3s cubic-bezier(0.22, 0.9, 0.3, 1) backwards;
}
/* Bertingkat, tidak serentak: judul lebih dulu, lalu isinya, lalu kakinya.
   Jedanya sengaja pendek (0,05 s) — cukup untuk terbaca sebagai satu gerakan
   yang mengalir, terlalu pendek untuk terasa sebagai menunggu. */
.layar > *:nth-child(2) { animation-delay: 0.05s; }
.layar > *:nth-child(3) { animation-delay: 0.1s; }
.deret-mode > *:nth-child(1) { animation-delay: 0.06s; }
.deret-mode > *:nth-child(2) { animation-delay: 0.11s; }
.deret-mode > *:nth-child(3) { animation-delay: 0.16s; }
.deret-mode > *:nth-child(4) { animation-delay: 0.21s; }

/* Dihormati, bukan diabaikan: gerakan masuk murni hiasan, jadi ia hal pertama
   yang harus mati waktu pemain minta gerakan dikurangi. */
@media (prefers-reduced-motion: reduce) {
  .layar > *,
  .deret-mode > *,
  .menu-kaki > * { animation: none; }
}

/* ---- layar TEGAK -------------------------------------------------------
   Satu-satunya keadaan yang boleh digulir, dan itu aman: HP tegak sudah
   ditutupi lapisan "putar HP-mu ke posisi mendatar", jadi ini cuma bentuk
   sementara sebelum pemain memutar perangkatnya — bukan bentuk yang dipakai
   bermain. Dua kolom dilipat jadi satu, dan potret dipendekkan supaya isi di
   bawahnya tetap kelihatan. */
@media (max-aspect-ratio: 1/1) {
  #menu { overflow-y: auto; }
  /* `max-width`, bukan `width` — alasannya sama dengan di aturan dasar:
     flex-basis dari `flex: 1` menelan `width`. */
  /* `safe center`, bukan `center`. Keduanya sama persis selama isinya muat.
     Begitu isinya LEBIH TINGGI dari layar — dan di layar tegak itu keadaan
     biasa, bukan kecelakaan — `center` mendorong kelebihannya keluar di KEDUA
     ujung, dan ujung atas tidak bisa dicapai guliran sama sekali: `scrollTop`
     sudah 0 dan judulnya tetap terpotong. Terukur begitu: isi 922 px di layar
     892 px, `#menu.scrollTop` = 0, dan 15 px teratas hilang. `safe` menyuruh
     pemusatan itu mengalah jadi rata-atas tepat pada saat ia mulai merugikan. */
  .layar { max-width: 460px; justify-content: safe center; }
  .layar-kepala { position: relative; text-align: center; }
  .layar-isi {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: 12px;
  }
  .kolom { justify-content: flex-start; }
  /* KOLOM KIRI MENIMPA KARTU PENGATURAN. Cacat lama, terlihat di 412×892:
     petak bangsa tergambar tepat di atas tulisan "Kesulitan".

     Sebabnya bukan tinggi salah satu kolom, melainkan tinggi BARISNYA. Di sini
     `.layar-isi` masih `flex: 1`, jadi ia punya tinggi pasti (722,2 px), dan
     grid yang tingginya pasti membagi ruang itu rata ke kedua barisnya —
     terukur `grid-template-rows: 355,094px 355,109px`. Isi kolom kiri 432,4 px,
     jadi ia meluber 77 px keluar barisnya sendiri dan mendarat di isi baris
     kedua. `align-items: start` di atas justru yang membuatnya terlihat: ia
     menyuruh tiap kolom setinggi ISINYA, bukan setinggi barisnya, sehingga
     tidak ada lagi yang memotong luberan itu.

     Yang dibetulkan sumbernya: barisnya diminta setinggi isi (`min-content`),
     dan `.layar-isi` berhenti melar (`flex: 0 0 auto`) supaya tingginya
     ditentukan isinya, bukan sisa layar. Hasilnya memang lebih tinggi dari
     layar — dan itu memang boleh di sini: `#menu` sudah `overflow-y: auto` di
     baris pertama media query ini. `.tunggal` (beranda) dikecualikan, ia flex
     satu kolom dan sudah punya aturannya sendiri di §43.3. */
  .layar-isi:not(.tunggal) { flex: 0 0 auto; grid-auto-rows: min-content; }
  .potret { min-height: 28vh; max-height: 34vh; }
  /* Tangga hurufnya dipatok ke LEBAR di sini, bukan tinggi: pada HP tegak
     tinggi justru berlimpah dan lebar yang langka, kebalikan persis dari
     keadaan mendatar yang jadi dasar nilai di `:root`. */
  :root {
    /* `--fs-judul`, bukan `.judul-besar { font-size }` langsung seperti dulu:
       lambang di belakang judul mengambil ukurannya dari peubah ini, jadi
       menyetel judulnya saja akan membuat lambang tetap berukuran mendatar di
       layar tegak. Peubah tetap satu-satunya sumber ukuran. */
    --fs-judul: clamp(28px, 8.4vw, 44px);
    --fs-tombol: clamp(13px, 4.4vw, 18px);
    /* Ikut dipatok ke lebar seperti tetangganya — kalau tidak, nama mode tetap
       memakai `4vh` dari `:root` dan di HP tegak yang tinggi berlimpah ia
       melar sendirian di antara huruf-huruf yang justru mengecil. */
    --fs-mode: clamp(16px, 5.4vw, 22px);
    --fs-label: clamp(11px, 3.4vw, 14px);
    --fs-kecil: clamp(10px, 3vw, 12px);
  }
  /* `text-align: center` di baris `.layar-kepala` atas TIDAK memusatkan kepala
     berpintu — ia flex, dan yang memusatkan anak flex `justify-content`. Tanpa
     baris ini pintu+judul menggantung di kiri sementara semua yang lain di layar
     tegak dipusatkan. */
  .layar-kepala.berpintu { justify-content: center; }
  /* RUANG UNTUK GUGUS POJOK. Sejak §55 keping intan dan tombol iklan berdiri
     juga di layar bangsa dan layar peta, bukan cuma di beranda — dan di layar
     tegak selebar 412 px, gugus itu (200 px) menutupi separuh kanan baris
     judul yang baru saja dipusatkan oleh aturan di atas. Terukur: kotak gugus
     bertumpang tindih dengan kotak `.judul-besar` di 412x780, dan tidak di
     640x360 maupun di atasnya.

     Yang mengalah JUDULNYA, bukan gugusnya, dan itu bukan pilihan sembarangan:
     judul "QUICK MATCH" sudah diketahui pemain sebelum ia sampai di sana —
     ialah yang baru saja ditekannya — sementara jumlah intan adalah angka yang
     tidak ada di tempat lain mana pun di layar ini.

     Yang diberikan RUANG TEGAK, bukan ruang mendatar, dan itu perbaikan dari
     percobaan pertama: `padding-right` selebar gugusnya memang memindahkan
     judul ke kiri, tapi di 412 px ia harus 214 px — lebih dari separuh layar —
     dan yang tersisa untuk "QUICK MATCH" tinggal 120 px. Judulnya selamat dari
     tumpang tindih dengan cara dipatahkan dua baris.

     Diturunkan 30 px, judulnya tetap selebar aslinya dan gugus pojok lewat di
     ATASNYA. Ongkosnya 30 px ruang tegak di satu-satunya bentuk layar yang
     memang boleh digulir (lihat catatan #putar di atas).

     Beranda dikecualikan: judulnya `.tengah`, bukan `.berpintu`, dan gugus di
     sana sudah berdiri di atas ruang kosong sejak §43.6. */
  .layar-kepala.berpintu { margin-top: 30px; }
  /* Kaki dilebarkan penuh: di layar selebar 412 px, tombol yang berhenti di
     190 px lalu didorong ke kanan meninggalkan pita kosong selebar dirinya
     sendiri di kiri.

     `flex: 1 1 auto`, BUKAN `width: 100%` seperti versi satu-tombol. Sesudah
     PILIH PETA berdiri di sebelahnya (§46.2), lebar 100% berarti tombol hijaunya
     sendiri sudah selebar barisnya dan pil di sebelahnya terdorong keluar. Yang
     melar sisa ruangnya, jadi barisnya tetap penuh baik berisi satu tombol
     maupun dua. */
  .menu-kaki.rapat .tbl-besar { flex: 1 1 auto; width: auto; }
  /* Sisa ruang tegak di layar tegak dipakai gulungan, bukan dibagikan: baris
     kaki yang menggantung di dasar kolom (§46.3) di sini akan terlempar ke dasar
     halaman yang tingginya sudah melebihi layar. */
  .menu-kaki.rapat { margin-top: 0; }
  .judul-lambang { width: calc(var(--fs-judul) * 3.7); }
  /* Ikut 3,2 seperti lambangnya sendiri di baris atas — kalau tidak, kepala
     layar menyediakan ruang untuk lambang mendatar yang lebih besar dan judul
     tegak jadi menggantung di tengah pita kosong. */
  #layar-beranda .layar-kepala.tengah { min-height: calc(var(--fs-judul) * 3.2); }
  /* SATU LAJUR lagi di layar tegak. Dua lajur adalah tukar-tambah tinggi
     dengan lebar (§43.1), dan di sini yang langka justru lebarnya: pada 412 px
     tegak tiap tombol tinggal ±188 px, sementara "QUICK MATCH" sendiri sudah
     meminta ±148 px pada `--fs-mode` versi tegak. Tingginya memang berlimpah di
     sini, jadi empat baris tidak menyakiti siapa pun. */
  .deret-mode { grid-template-columns: minmax(0, 1fr); }
}

/* §57.68: DUA BLOK PALET PRATINJAU ("Palet Perang" dan "Monokrom") DICABUT.
   Keduanya cuma bisa dinyalakan lewat tombol Palet di `#prat-bilah`, dan
   bilah itu sudah dibuang atas permintaan langsung — jadi ±210 baris token
   warna ini menjadi kode yang tidak mungkin dijalankan siapa pun.

   Palet ASLI tidak tersentuh sama sekali: kedua blok ini bekerja dengan
   MENIMPA token di bawah `body.palet-perang`/`body.palet-mono`, dan tanpa
   kelas itu menempel mereka memang tidak pernah berlaku. */
/* ============================================================================
   BASE PLAYER (§57.42.13)

   Halaman "siapa aku" — satu-satunya layar yang tidak menyiapkan apa pun untuk
   pertandingan berikutnya. Susunannya karena itu juga berbeda dari setiap
   layar lain: bukan dua kolom yang membagi lebar, melainkan PEMANDANGAN di
   tengah dengan dua kolom yang MELAYANG di atasnya.

   Bedanya bukan selera. Di grid dua kolom, pemimpin 3D-nya akan dijepit jadi
   pita di antara kolom kiri dan kolom kanan; melayang, kedua kolom cuma
   memakan tepi dan seluruh sisa layar tetap jadi arena yang terlihat penuh —
   dan arena itulah alasan halaman ini punya latar hidup, bukan gambar.
   ============================================================================ */

.base-isi {
  position: relative;
  flex: 1;
  min-height: 0;
}
/* Persegi tempat `bingkaiMenu()` menggambar pemimpin (lihat `.potret`). Ia
   dipusatkan dan dibatasi lebarnya, bukan dibiarkan selebar layar: kamera
   potret memakai FOV TEGAK, jadi persegi yang terlalu lebar tidak membesarkan
   modelnya sama sekali — ia cuma memperlebar ruang kosong di kiri-kanannya,
   dan ruang kosong itu jatuh tepat di bawah kedua kolom melayang. */
/* §57.60: DILEBARKAN (min(46vh, 52%) -> min(76vh, 62%)), memperbaiki model
   yang terpotong di kiri dan kanan.

   Kamera potret memakai FOV TEGAK, dan itu memotong dua arah sekaligus di
   kotak yang terlalu sempit mendatar: cakupan mendatarnya = cakupan tegak x
   ASPEK, jadi makin jangkung kotaknya makin sedikit dunia yang terlihat ke
   samping. Terukur di 1280x720 sebelum perubahan ini: kotak 331x547 (aspek
   0,61) mencakup 1,82 m mendatar, yaitu 0,91 m dari poros — sementara
   perisai bundar Viking terjulur ±1,0 m dari poros. Kurang 0,09 m, dan itu
   terlihat sebagai pedang serta perisai yang terpotong rata oleh tepi yang
   tidak ada gambarnya ("dibingkai tak terlihat").

   Catatan di bawah — bahwa persegi terlalu lebar cuma menambah ruang kosong —
   benar untuk kotak yang aspeknya SUDAH sehat, dan keliru dipakai sejauh ini:
   ia dipakai membenarkan kotak yang justru lebih sempit daripada aspek yang
   dirancang kameranya. `.potret` di layar lain beraspek 0,93 dan modelnya utuh
   di sana; angka baru ini menyamakan base ke aspek itu (500x547 = 0,91 pada
   1280x720), yang mencakup 1,37 m dari poros — margin 0,37 m untuk perisai.

   Ruangnya memang ada: kolom kiri ±62 px dan kolom kanan ±250 px menyisakan
   968 px bebas di antara keduanya, jadi 500 px tidak mendesak apa pun. */
.base-potret {
  position: absolute;
  inset: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(76vh, 62%);
  max-height: none;
}
.base-kiri,
.base-kanan {
  position: absolute;
  top: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.base-kiri {
  left: 0;
  justify-content: center;
  gap: clamp(9px, 2vh, 16px);
}
/* KANAN: kartu di atas, hadiah harian di tengah, QUICK GAME di dasar. Yang
   memisahkan ketiganya `margin-top: auto` pada yang tengah, bukan
   `space-between` — di layar pendek `space-between` membuat ketiganya saling
   menempel rata sementara yang harus tetap di pojok cuma yang terakhir. */
.base-kanan {
  right: 0;
  align-items: flex-end;
  gap: clamp(8px, 1.8vh, 14px);
}
.base-hadiah { margin-top: auto; }

/* Tiga pintu koleksi. Persegi berikon, seukuran tombol sentuh yang nyaman,
   dan bergaris tepi tebal yang sama dengan setiap tombol menu lain. */
.base-ikon {
  width: clamp(46px, 8.6vh, 64px);
  height: clamp(46px, 8.6vh, 64px);
  display: grid;
  place-items: center;
  border: 3px solid var(--garis);
  border-radius: clamp(10px, 2vh, 15px);
  background: rgba(20, 26, 40, 0.82);
  color: #ffd98a;
  cursor: pointer;
  transition: transform 0.08s, filter 0.12s;
}
.base-ikon:hover { filter: brightness(1.15); }
.base-ikon:active { transform: translateY(2px); }
.base-ikon svg { width: 58%; height: 58%; }

.base-kartu {
  width: clamp(178px, 26vw, 250px);
  display: flex;
  flex-direction: column;
  gap: clamp(4px, 1vh, 8px);
  padding: clamp(9px, 1.9vh, 15px) clamp(10px, 1.7vw, 15px);
  border: 3px solid var(--garis);
  border-radius: clamp(10px, 2vh, 15px);
  background: rgba(20, 26, 40, 0.86);
  color: #fff;
}
.base-nama { display: flex; flex-direction: column; gap: 4px; }
.base-nama > span,
.base-runtun > span:first-child {
  font-size: clamp(8px, 1.4vh, 10px);
  font-weight: 900;
  letter-spacing: 1px;
  color: #8e9ab4;
}
/* Kolom isian yang tidak terlihat seperti formulir peramban: latar gelap yang
   sama dengan kartunya, garis tepi tipis yang cuma menyala waktu difokuskan.
   Aturan yang sama yang membuat penggeser di layar Quick Match digambar
   sendiri alih-alih memakai `accent-color`. */
.base-nama input {
  width: 100%;
  padding: 5px 8px;
  border: 2px solid rgba(255, 255, 255, 0.22);
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.07);
  color: #fff;
  font: inherit;
  font-size: clamp(11px, 2vh, 14px);
  font-weight: 800;
}
.base-nama input:focus { outline: none; border-color: var(--kuning); }
.base-runtun { display: flex; align-items: center; gap: 7px; }
.base-runtun .profil-bar.besar { flex: 1; width: auto; }
.base-runtun b {
  font-size: clamp(10px, 1.9vh, 13px);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
}
.base-stat {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: clamp(10px, 1.8vh, 12.5px);
  font-weight: 800;
  color: #a8b3c8;
}
.base-stat b { color: #fff; font-weight: 900; font-variant-numeric: tabular-nums; }
/* LENCANA: keping berwarna lencana, lalu satu baris kecil yang menyebut berapa
   bendera lagi menuju lencana berikutnya. Kepingnya diberi garis tepi berwarna
   dan tulisan sewarna itu, bukan isian pejal — pejal, ia jadi benda paling
   terang di kartu dan menang atas angka-angka di atasnya. */
.base-lencana {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: clamp(2px, 0.8vh, 6px);
  padding-top: clamp(5px, 1.1vh, 9px);
  border-top: 2px solid rgba(255, 255, 255, 0.14);
}
.lencana-keping {
  flex-shrink: 0;
  padding: 3px 9px;
  border: 2px solid var(--lencana);
  border-radius: 999px;
  color: var(--lencana);
  font-size: clamp(9px, 1.6vh, 11px);
  font-weight: 900;
  letter-spacing: 0.8px;
}
.base-lencana i {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-style: normal;
  font-size: clamp(8.5px, 1.5vh, 10.5px);
  font-weight: 800;
  color: #8e9ab4;
}

/* HADIAH HARIAN: tombol persegi berikon, sekeluarga dengan tiga pintu koleksi
   di seberangnya — bentuk yang sama untuk "ini membuka sesuatu". Yang
   membedakan cuma warnanya waktu SIAP: kuning, warna yang di seluruh permainan
   ini berarti intan. */
.base-hadiah {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: clamp(7px, 1.5vh, 12px) clamp(9px, 1.6vw, 14px);
  border: 3px solid var(--garis);
  border-radius: clamp(10px, 2vh, 15px);
  background: rgba(20, 26, 40, 0.82);
  color: #8e9ab4;
  cursor: pointer;
  transition: transform 0.08s, filter 0.12s;
}
.base-hadiah svg { width: clamp(22px, 4vh, 30px); height: clamp(22px, 4vh, 30px); }
.base-hadiah b { font-size: clamp(8.5px, 1.5vh, 10.5px); font-weight: 900; letter-spacing: 0.9px; }
.base-hadiah:active { transform: translateY(2px); }
/* Sudah diambil hari ini: DIREDAM, bukan disembunyikan — pemain harus bisa
   melihat bahwa hadiahnya ada dan sudah ia ambil, bukan menemukan tempat
   kosong lalu bertanya-tanya. */
.base-hadiah.siap { background: var(--kuning); border-color: var(--garis); color: #2b1f00; }
/* §57.64 — TOMBOL CASUAL: satu-satunya tombol BERANGKAT di halaman Base
   Player, diminta dibuat lebih menarik.

   Yang ditambahkan TIGA lapis, dan ketiganya sengaja tidak mengubah bentuk
   dasarnya — ia harus tetap terbaca sebagai `.tbl-besar.hijau` yang sama
   dengan tombol berangkat di layar lain, karena itulah yang membuat pemain
   tahu fungsinya sebelum membacanya:

     1. GRADASI, bukan hijau rata. Memberi tombolnya bentuk padat alih-alih
        bidang datar, bahasa yang sama dengan kotak hadiah harian sebelum
        §57.64 mencabutnya.
     2. BAYANGAN JATUH berwarna hijau redup. Bukan bayangan netral: bayangan
        yang mewarisi warna tombolnya terbaca sebagai cahaya yang dipancarkan
        benda itu sendiri, dan itu tepat untuk satu-satunya ajakan di layar.
     3. KILAU yang menyapu sekali tiap beberapa detik (`::after`), meminjam
        bahasa yang sudah dipakai keping intan dan kotak hadiah. Jedanya
        panjang (5,5 dtk) dan sapuannya cepat — kilau yang terlalu sering
        berhenti menjadi ajakan dan mulai menjadi gangguan di halaman yang
        pemain memang berlama-lama di dalamnya.

   `overflow: hidden` mengurung kilaunya di dalam sudut membulat tombol, dan
   `position: relative` memberi `::after` patokan. `prefers-reduced-motion`
   mematikan sapuannya — sisa dua lapis lain tidak bergerak sama sekali, jadi
   tombolnya tetap menonjol tanpa satu pun animasi. */
.base-main {
  flex: 0 0 auto;
  position: relative;
  overflow: hidden;
  background: linear-gradient(180deg, #57df84 0%, var(--hijau) 55%, #21b45c 100%);
  /* §57.65 — lapis cahaya hijau (`0 10px 22px rgba(46,204,113,.34)`) dicabut:
     kabut yang mengambang di sekeliling tombol dan melunturkan tepinya.

     §57.68 — BIBIR 3D-nya IKUT DICABUT, diminta langsung dengan tangkapan
     layar tombolnya ("hilangkan shadow (efek 3D) di tombol casual").

     §57.65 sempat mempertahankan `0 6px 0` dengan alasan ia bukan bayangan
     melainkan bibir yang memberi ketebalan — dan alasan itu keliru membaca
     yang diminta: yang terlihat di layar sebagai "efek 3D" memang lapis itu,
     terlepas dari peran strukturalnya. Permintaannya diulang sambil menunjuk
     tombolnya, jadi bibirnya yang mengalah.

     `:active` sekarang memakai `translateY` alih-alih memendekkan bibir yang
     sudah tidak ada. Tanpa penggantinya, tombol utama halaman ini jadi
     satu-satunya tombol yang tidak memberi tanda apa pun waktu ditekan. */
  box-shadow: none;
}
.base-main:active { transform: translateY(2px); }
.base-main::after {
  content: '';
  position: absolute;
  top: -30%;
  bottom: -30%;
  width: 38%;
  left: -55%;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.55) 50%, rgba(255, 255, 255, 0) 100%);
  transform: rotate(18deg);
  animation: base-main-kilau 5.5s 1.2s ease-in-out infinite;
  pointer-events: none;
}
@keyframes base-main-kilau {
  0%   { left: -55%; }
  /* Sapuannya habis di 14% dari daur — sisanya tombol berdiri diam. */
  14%  { left: 125%; }
  100% { left: 125%; }
}
@media (prefers-reduced-motion: reduce) {
  .base-main::after { animation: none; opacity: 0; }
}

/* ---- panel koleksi ------------------------------------------------------ */
.koleksi-tirai { position: fixed; z-index: 50; }
/* §57.64 — TINGGI SERAGAM untuk KEEMPAT panel Base Player, diminta langsung
   dengan panel Warlord's Base sebagai acuan.

   Terukur sebelum diseragamkan: Warlord's Base 334 px, Custom Player 367 px,
   Warlords 415 px, Map Arenas 475 px — empat tinggi berbeda untuk empat pintu
   yang berdiri berdampingan di kolom yang sama. Membukanya bergantian membuat
   kotaknya melompat-lompat naik-turun di tengah layar.

   Sebabnya isinya: tiap panel setinggi apa yang kebetulan dimuatnya, dan Map
   Arenas memuat tiga paragraf keterangan arena sementara Warlord's Base cuma
   petak bangsa. Jadi yang disamakan TINGGI KOTAKNYA, dan isi yang tidak muat
   menggulir di dalamnya — `.koleksi-ket` sudah `overflow-y: auto` sejak awal,
   jadi keterangan panjang sudah tahu cara menggulir tanpa satu baris pun
   ditambahkan.

   `--panel-h` dipakai bersama `.rupa-kotak` di bawah supaya keempatnya tidak
   bisa menyimpang pada hari salah satunya disetel. */
/* §57.68 — DITINGGIKAN 334 -> 380 px di batas atas, diminta langsung
   ("pertinggi sedikit panel custom player, warlords, warlords base dan map
   arenas dengan patokan tinggi yang sama").

   Batas bawah dan `vh` ikut naik sebanding (280 -> 310 px, 46 -> 52vh) supaya
   kenaikannya terasa juga di layar yang lebih pendek — kalau cuma batas
   atasnya yang naik, satu-satunya layar yang berubah adalah yang paling
   tinggi.

   380 px dipilih pemilik proyek dari tiga usul. Di 720 px ia menyisakan
   ±170 px ruang napas atas-bawah untuk tirainya; 420 px yang sempat diusulkan
   membuat panel hampir memenuhi layar pendek. */
:root { --panel-h: clamp(310px, 52vh, 380px); }
.kotak.lebar.koleksi-kotak {
  width: min(660px, 94vw);
  height: var(--panel-h);
  text-align: left;
}
.koleksi-isi {
  display: grid;
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  gap: clamp(9px, 1.8vw, 16px);
  min-height: 0;
  /* §57.64: MENGISI sisa tinggi kotak yang kini dipatok, dan tidak lebih.
     Tanpa `1 1 0`, kisi ini setinggi isinya dan meluber keluar kotak
     berketinggian tetap — yang terlihat sebagai isi terpotong di tepi bawah,
     bukan sebagai isi yang menggulir. */
  flex: 1 1 0;
  /* Baris kisi DIJEPIT ke tinggi kisinya, tidak boleh melar mengikuti isi.
     Terukur tanpa ini: `.koleksi-kiri` berdiri 403 px di dalam kisi 255 px —
     `1fr` bawaan grid adalah `minmax(auto, 1fr)`, dan bagian `auto`-nya
     menolak mengecil di bawah tinggi isi. `minmax(0, 1fr)` mencabut lantai
     itu, dan barulah `height: 100%` pada kolomnya punya angka untuk dipatuhi. */
  grid-template-rows: minmax(0, 1fr);
}
.koleksi-kiri {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(5px, 1.1vh, 9px);
  min-width: 0;
  /* Ikut dibatasi tinggi kisinya, supaya `min-height: 0` pada gambar di bawah
     benar-benar punya batas untuk dipatuhi. `height: 100%` bukan sekadar
     penegasan: `max-height: calc(100%...)` pada gambar di dalamnya menghitung
     persentase terhadap tinggi kolom INI, dan persentase terhadap tinggi yang
     tidak definit diabaikan peramban tanpa satu pun peringatan. */
  min-height: 0;
  height: 100%;
}
/* Persegi gambar berukuran TETAP nisbi (rasio 1:1), bukan tinggi yang mengikuti
   isinya: ketiga koleksi mengisinya dengan gambar berukuran berbeda (foto badan
   256², foto markas 320², ilustrasi arena 160×120), dan kotak yang tingginya
   ikut isinya membuat seluruh panel melompat tiap kali koleksinya berganti. */
.koleksi-gambar {
  width: 100%;
  aspect-ratio: 1 / 1;
  /* §57.64 — BOLEH MENGECIL dari bujur sangkarnya waktu kolomnya kehabisan
     tinggi. Sejak panel dipatok `--panel-h`, `aspect-ratio` sendirian menjadi
     cacat: tingginya dihitung dari LEBAR kolom dan sama sekali tidak tahu
     berapa tinggi yang tersisa, jadi di panel 331 px gambar bujur sangkar
     memakan hampir seluruhnya dan mendorong tombol "Selected" di bawahnya
     keluar tepi panel — terlihat terpotong separuh di tangkapan layar Map
     Arenas, dan kolom kiri ini TIDAK menggulir (cuma keterangan di kanan yang
     bisa), jadi yang terdorong keluar benar-benar hilang.

     `min-height: 0` SAJA TIDAK CUKUP, dan itu terukur: `aspect-ratio`
     memberi tinggi DEFINIT (= lebar kolom), dan tinggi definit menang atas
     penyusutan flex — tombolnya tetap terpotong sesudah `min-height: 0`
     ditambahkan.

     Percobaan kedua (`max-height` dihitung dari `--panel-h`) juga meleset,
     dan terukur kenapa: `--panel-h` tinggi KOTAK, sementara yang membatasi
     gambar tinggi `.koleksi-isi` di dalamnya — beda 76 px (331 vs 255) yang
     dimakan judul panel, sisipan kotak, dan celahnya. Terukur waktu itu:
     kolom kiri 403 px di dalam kisi 255 px, meluber 148 px.

     Yang dipakai sekarang `100%` — tinggi `.koleksi-kiri` yang sudah dijepit
     kisinya — dikurangi jatah nama dan tombol di bawahnya beserta dua celah.
     Angkanya diturunkan dari elemen yang benar-benar ada di sana (nama 17 px,
     tombol 42 px, gap 7,2 px x2), bukan dikira-kira, dan disebut sebagai
     `clamp` supaya ikut mengecil di layar pendek bersama keduanya. */
  min-height: 0;
  max-height: calc(100% - clamp(62px, 11vh, 82px));
  display: grid;
  place-items: center;
  border: 3px solid var(--garis);
  border-radius: clamp(9px, 1.8vh, 13px);
  background: #d7dceb;
  overflow: hidden;
  /* §57.65 — JALUR BARIS DIPATOK, dan INI yang benar-benar menghentikan
     gambar terpotong sepinggang. `max-height: 100%` pada gambarnya (lihat
     aturan di bawah) TIDAK CUKUP, dan alasannya melingkar:

     kotak ini `display: grid`, jadi persentase pada anaknya diukur terhadap
     JALUR BARIS, bukan terhadap tinggi kotak. Jalur baris bawaannya `auto`,
     yang berarti "setinggi isinya" — yaitu setinggi gambar itu sendiri. Maka
     `max-height: 100%` berbunyi "gambar tidak boleh lebih tinggi daripada
     gambar", yang selalu benar dan karena itu tidak membatasi apa pun.
     Terukur: kotak 175,7 px, jalur 228 px, gambar 228 px, 52 px dipotong
     `overflow: hidden` di atas.

     `minmax(0, 1fr)` memutus lingkaran itu: `1fr` mengikat jalur ke tinggi
     kotak yang sudah dibatasi `max-height`, dan `minmax(0, ...)` mencabut
     lantai `auto` yang kalau tidak akan menolak menyusut di bawah tinggi
     isinya — persis pasangan yang sudah dipakai `.koleksi-isi` (§57.64) untuk
     cacat yang sama satu tingkat di atas. */
  grid-template-rows: minmax(0, 1fr);
}
/* §57.64 — `contain`, BUKAN `cover`. Dilaporkan langsung: kaki tokoh Viking
   terpotong di tepi bawah kotak.

   `cover` benar selama kotaknya bujur sangkar — foto tokoh dan foto markas
   memang dipotret 1:1, jadi tidak ada yang hilang. Begitu kotaknya dibatasi
   `max-height` supaya tombol di bawahnya tidak terdorong keluar panel
   (lihat `.koleksi-gambar`), nisbahnya tidak lagi 1:1 — dan `cover` menjawab
   itu dengan MEMOTONG sisi panjang alih-alih mengecilkan isinya. Yang
   dipotong bagian bawah: persis kaki tokohnya.

   `contain` memuat seluruh gambar apa pun nisbah kotaknya, dengan ongkos
   sedikit ruang kosong di sisi yang lebih panjang — dan ruang kosong berlatar
   `#d7dceb` yang sama dengan kotaknya tidak terlihat sebagai apa pun,
   sementara kaki yang hilang langsung terlihat. Panji sudah memakai `contain`
   sejak awal karena alasan yang sama; sekarang seluruh isi kotak ini
   seragam. */
/* §57.65 — `max-width`/`max-height` DITAMBAHKAN, dan itulah yang benar-benar
   memperbaiki "gambar karakter terpotong setengah badan".

   `contain` yang dipasang §57.64 TIDAK PERNAH BERLAKU, dan angkanya yang
   menunjukkannya: kotaknya terukur 234x175,7 px sementara gambar di dalamnya
   228x228 px — 52 px menggantung di bawah tepi kotak dan dipotong
   `overflow: hidden` milik `.koleksi-gambar`. Itu persis potongan sepinggang
   yang dilaporkan.

   Sebabnya `height: 100%` pada anak dari induk yang tingginya sendiri
   ditentukan `max-height: calc(...)`: persentase tinggi mengacu ke tinggi
   induk yang BELUM definit pada saat anaknya ditata, jadi peramban
   mengabaikannya — diam-diam, tanpa peringatan, persis seperti yang sudah
   dicatat di `.koleksi-kiri` beberapa aturan di atas. Gambar lalu memakai
   ukuran alaminya (256 px dikecilkan ke lebar kolom) dan `object-fit` tidak
   punya apa pun untuk dikerjakan: ia cuma menata isi DI DALAM kotak yang
   sudah punya ukuran, dan kotak yang ukurannya salah tetap salah.

   `max-height` bekerja di tempat `height` gagal karena ia dievaluasi
   terhadap tinggi induk yang sudah terhitung, bukan dipakai untuk
   menghitungnya. Pasangan `max-width` menjaga sisi yang satunya waktu
   kolomnya yang lebih sempit. Keduanya bersama `contain` berarti: kecilkan
   sampai muat pada sisi mana pun yang lebih ketat, jangan potong. */
.koleksi-gambar img,
.koleksi-gambar svg {
  display: block;
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
.koleksi-gambar .panji-besar { padding: 14%; }
.koleksi-seni { display: block; width: 100%; height: 100%; }
.koleksi-pesan {
  padding: 0 12px;
  text-align: center;
  font-size: clamp(9px, 1.6vh, 11px);
  font-weight: 800;
  color: #6b7590;
}
.koleksi-nama {
  font-size: clamp(11px, 2vh, 14px);
  font-weight: 900;
  letter-spacing: var(--lc-kapital);
  color: var(--garis);
  /* Title Case, bukan ALL CAPS — nama bangsa/arena, bukan heading/tombol. */
  text-transform: capitalize;
}
.koleksi-kanan {
  display: flex;
  flex-direction: column;
  gap: clamp(7px, 1.4vh, 12px);
  min-width: 0;
  /* §57.64 — DIJEPIT ke tinggi kisinya, alasan yang sama dengan
     `.koleksi-kiri`. Yang boleh menggulir di kolom ini CUMA `.koleksi-ket`
     (keterangan), dan itu bergantung pada kolomnya sendiri berhenti melar:
     terlihat di tangkapan layar sesudah kolom kiri diperbaiki — petak
     Forest/Desert/Snow ikut tergulir ke luar tepi atas panel, padahal ia
     kontrol utama layar ini dan keterangan di bawahnya cuma penjelasnya.
     Yang tergulir keluar tidak bisa ditekan sama sekali. */
  min-height: 0;
  height: 100%;
  overflow: hidden;
}
/* Deret petak pilihan TIDAK IKUT MENGECIL waktu kolomnya sempit — ia yang
   dipakai, bukan yang dibaca. Yang menyerah keterangan di bawahnya, yang
   memang sudah tahu cara menggulir (`.koleksi-ket { overflow-y: auto }`). */
.koleksi-kanan > .koleksi-petak,
.koleksi-kanan > .rupa-tab { flex: 0 0 auto; }

/* DUA SUSUNAN dari satu kelas. `baris` digulir mendatar (bangsa: sepuluh dan
   akan bertambah; arena: tiga), `kisi` mengisi ke bawah (markas). Yang
   menentukan bukan jumlahnya melainkan apa yang berdiri DI BAWAHNYA: panel
   yang punya keterangan harus menyisakan ruang tegak untuk keterangan itu,
   panel yang tidak punya boleh memakainya sendiri. */
.koleksi-petak { display: flex; gap: clamp(5px, 1vw, 9px); min-width: 0; }
.koleksi-petak.baris {
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.koleksi-petak.baris::-webkit-scrollbar { display: none; }
.koleksi-petak.kisi {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  overflow-y: auto;
  max-height: min(46vh, 300px);
}
.koleksi-sel {
  flex: 0 0 clamp(74px, 12vw, 96px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: clamp(5px, 1.1vh, 9px) 4px;
  border: 3px solid var(--garis);
  border-radius: clamp(8px, 1.6vh, 12px);
  background: #eef1f6;
  color: #1b2030;
  cursor: pointer;
  transition: transform 0.08s, background 0.14s;
}
.koleksi-petak.kisi .koleksi-sel { flex: 1 1 auto; }
.koleksi-sel:active { transform: scale(0.96); }
.koleksi-sel.terpilih { background: var(--kuning); }
/* TERKUNCI tetap digambar penuh dan tetap bisa ditekan — halaman koleksi
   seluruh gunanya memperlihatkan apa yang ADA, termasuk yang belum jadi milik
   pemain (§32.6). Yang membedakan cuma kelegapannya. */
.koleksi-sel.terkunci { opacity: 0.46; }
.koleksi-sel img {
  display: block;
  width: clamp(26px, 4.4vh, 34px);
  height: clamp(20px, 3.4vh, 26px);
  border: 2px solid rgba(0, 0, 0, 0.42);
  border-radius: 3px;
  object-fit: cover;
}
.koleksi-sel svg { width: clamp(21px, 3.6vh, 28px); height: clamp(21px, 3.6vh, 28px); }
.koleksi-sel span {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* §57.64: 10,5 px -> 13 px di batas atas, diminta langsung. Satu aturan ini
     melayani EMPAT panel sekaligus — label tab Face/Skin di Custom Player dan
     nama bangsa/markas/arena di ketiga panel koleksi — jadi menaikkannya di
     sini memperbaiki keempatnya tanpa empat aturan terpisah yang pasti
     menyimpang satu sama lain kelak.
     `text-overflow: ellipsis` di atas yang menjaga nama terpanjang ("Frankish")
     tetap aman di petak tersempit: yang memanjang dipotong, bukan meluber. */
  font-size: clamp(9px, 1.9vh, 13px);
  font-weight: 900;
  letter-spacing: 0.4px;
}

.koleksi-ket {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: clamp(8px, 1.5vh, 13px) clamp(9px, 1.6vw, 14px);
  border-radius: clamp(8px, 1.6vh, 12px);
  background: #d7dceb;
  color: #1b2030;
}
.koleksi-ket[hidden] { display: none; }
.koleksi-ket > b {
  display: block;
  font-size: clamp(12px, 2.2vh, 15px);
  font-weight: 900;
  letter-spacing: var(--lc-kapital);
  /* Title Case, bukan ALL CAPS — nama entitas, bukan heading/tombol. */
  text-transform: capitalize;
}
.koleksi-sub {
  display: block;
  margin-top: 2px;
  font-size: clamp(9px, 1.6vh, 11px);
  font-weight: 800;
  color: #6b7590;
}
.koleksi-ket p {
  margin: clamp(5px, 1.1vh, 9px) 0 0;
  font-size: clamp(9.5px, 1.7vh, 12px);
  font-weight: 600;
  line-height: 1.45;
  color: #414c66;
}
.koleksi-baris {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: clamp(5px, 1.1vh, 9px);
  font-size: clamp(9px, 1.6vh, 11px);
  font-weight: 800;
  letter-spacing: var(--lc-biasa);
  color: #6b7590;
  /* Title Case, bukan ALL CAPS — label baris, bukan heading/tombol. */
  text-transform: capitalize;
}

/* ---- panel hadiah harian ------------------------------------------------ */
/* §57.60: "DAY 1" berdiri sebagai KEPING, bukan sebaris tulisan kelabu.
   Terukur sebelumnya: 12,5 px, tulisan TERKECIL di panel yang isinya cuma
   tiga baris — padahal ia satu-satunya yang menyebut runtun, yaitu alasan
   pemain kembali besok. Sebagai keping berlatar ia mendapat berat tanpa
   harus ikut membesar dan bersaing dengan angka hadiahnya. */
.harian-hari {
  align-self: center;
  padding: clamp(3px, 0.7vh, 5px) clamp(10px, 1.9vw, 14px);
  border-radius: 999px;
  background: #e2e7f2;
  text-align: center;
  font-size: clamp(10px, 1.8vh, 12px);
  font-weight: 900;
  letter-spacing: 1.4px;
  color: #55607d;
}
/* Angka hadiahnya BESAR dan berlambang: ia satu-satunya hal yang benar-benar
   ditanyakan pemain waktu membuka panel ini. */
/* §57.60 memberi hadiahnya PANGGUNG SENDIRI — kotak kuning bergaris tepi —
   supaya ia terbaca sebagai satu benda alih-alih baris ketiga sebuah daftar.
   §57.64 MENCABUT kotak itu lagi, diminta langsung, dan alasannya bertahan:
   sejak tombol CLAIM di bawahnya juga kotak bergaris tepi selebar panel,
   kotak kuning ini berdiri tepat di atas kotak kedua yang bentuknya nyaris
   sama — dua persegi panjang bertumpuk yang cuma berbeda warna, dan yang
   ATAS bukan tombol sementara yang BAWAH tombol. Kemiripan bentuk itu
   mengundang ketukan pada benda yang tidak bisa diketuk.

   Yang menggantikannya bukan ketiadaan melainkan UKURAN: angkanya sendiri
   sudah 32-38 px, jauh lebih besar daripada apa pun di panel ini, dan itu
   sudah cukup menjadikannya pusat tanpa latar apa pun. Kini ia benar-benar
   "ikon + angka di tengah panel", yang memang bentuk paling sederhana untuk
   mengatakan satu hal.

   `justify-content: center` DIPERTAHANKAN dan sekarang barulah ia terlihat
   bekerja: selama ada kotak selebar panel, pemusatan terjadi di dalam kotak
   itu dan yang terlihat mata justru tepi kotaknya, bukan pusat isinya. */
.harian-upah {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(6px, 1.2vw, 10px);
  padding: clamp(4px, 0.9vh, 8px) 0;
  color: #1b2030;
}
.harian-upah svg { width: clamp(26px, 4.6vh, 34px); height: clamp(26px, 4.6vh, 34px); }
.harian-upah b {
  font-size: clamp(26px, 5vh, 38px);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* ---- EFEK SURPRISE HADIAH HARIAN (§57.63) ---------------------------------
   Diminta langsung: kotak hadiah harian harus terasa seperti dibuka, bukan
   seperti angka yang sudah tertulis di sana sejak awal.

   Yang dianimasikan KOTAK HADIAHNYA (`.harian-upah`), bukan seluruh panel:
   panel yang melompat-lompat memindahkan tombol CLAIM di bawahnya, dan
   tombol yang bergerak pada saat pemain hendak menekannya adalah cacat, bukan
   kejutan. Kotak hadiah berdiri di tengah dan tidak ada yang harus ditekan di
   dalamnya, jadi ia bebas bergerak.

   TIGA LAPIS, dan ketiganya menyala dari satu kelas `.kejut` yang dipasang
   js/profil.js lalu dilepas sendiri saat animasinya habis:
     1. kotaknya MEMBESAR dari 0,7 dengan sedikit lewatan (`cubic-bezier`
        berpantul) — gerakan "meletus keluar", bukan memudar masuk.
     2. kilau putih menyapu melintasinya sekali (`::after`), meminjam bahasa
        yang sama dengan kilau pada keping intan.
     3. cincin cahaya melebar keluar lalu memudar (`::before`) — sisa ledakan.
   Angkanya sendiri ikut terbawa karena ia anak kotak itu. */
/* §57.64: `overflow: hidden` DICABUT bersama kotak kuningnya. Ia ada untuk
   mengurung kilau dan cincin di dalam tepi kotak — dan begitu tepinya tidak
   ada lagi, yang dikerjakannya cuma memotong cincin ledakan yang sengaja
   dilahirkan lebih besar (`inset: -40%`) tepat pada garis yang tak terlihat.
   Tanpa kurungan, ledakannya menyapu keluar seperti yang dimaksud sejak
   awal. */
.harian-upah { position: relative; }
.harian-upah.kejut { animation: harian-letus 0.52s cubic-bezier(0.34, 1.56, 0.64, 1) both; }
/* Cincin ledakan. `inset: -40%` supaya lingkarannya lahir lebih besar dari
   kotaknya dan yang terlihat cuma busur yang menyapu keluar. */
.harian-upah.kejut::before {
  content: '';
  position: absolute;
  inset: -40%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 246, 199, 0.95) 0%, rgba(255, 226, 122, 0) 65%);
  animation: harian-cincin 0.62s ease-out both;
  pointer-events: none;
}
/* Sapuan kilau. Miring 20 derajat, sama dengan kilau tombol di berkas ini. */
.harian-upah.kejut::after {
  content: '';
  position: absolute;
  top: -30%;
  bottom: -30%;
  width: 45%;
  left: -60%;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.85) 50%, rgba(255, 255, 255, 0) 100%);
  transform: rotate(20deg);
  animation: harian-kilau 0.6s 0.1s ease-out both;
  pointer-events: none;
}
@keyframes harian-letus {
  0% { transform: scale(0.7); opacity: 0; }
  60% { transform: scale(1.06); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes harian-cincin {
  0% { transform: scale(0.35); opacity: 0.9; }
  100% { transform: scale(1.35); opacity: 0; }
}
@keyframes harian-kilau {
  0% { left: -60%; }
  100% { left: 115%; }
}
/* Gerakan dimatikan, KEJUTANNYA TIDAK. Yang tersisa kilatan latar sekejap —
   perubahan keadaan tetap terbaca tanpa satu pun benda yang bergerak. */
@media (prefers-reduced-motion: reduce) {
  .harian-upah.kejut { animation: harian-kilat 0.4s ease-out both; }
  .harian-upah.kejut::before,
  .harian-upah.kejut::after { animation: none; content: none; }
  @keyframes harian-kilat {
    0% { background: linear-gradient(180deg, #fffdf4 0%, #fff6d8 100%); }
    100% { background: linear-gradient(180deg, #fff8de 0%, #ffeeb4 100%); }
  }
}

/* ============================================================================
   §57.43 — IKON BERKAS, LAYAR PEMUAT, DAN SELURUH PEROMBAKAN BASE PLAYER
   ============================================================================ */

/* ---- lambang gambar bersama ------------------------------------------------
   `.ik-intan` dipakai di mana pun lambang intan tertulis: keping pojok layar,
   keping harga komidi, baris Reward/Entrance Fee, tombol ENTER, kolom HADIAH.
   Ukurannya `em`, bukan piksel — satu-satunya cara sebuah lambang sebaris
   tetap sepadan dengan huruf di sebelahnya di seluruh tempat yang ukuran
   hurufnya berbeda-beda. */
.ik-intan {
  display: inline-block;
  width: 1.15em;
  height: 1.15em;
  vertical-align: -0.24em;
  object-fit: contain;
  flex-shrink: 0;
}
/* Di dalam tombol besar yang sudah `inline-flex` (`.tbl-besar.harga`,
   `.tbl-besar.buka`), `vertical-align` tidak berlaku sama sekali — flex yang
   memusatkannya. Yang perlu dimatikan cuma sisa geseran itu. */
.tbl-besar .ik-intan,
.tbl .ik-intan,
.baris-info .ik-intan { vertical-align: 0; }

#intan-sudut .ik-intan { width: 1.35em; height: 1.35em; }
#ads-sudut img { display: block; width: 1.5em; height: 1.5em; object-fit: contain; }

/* ---- LAYAR PEMUAT (§57.43.5) ----------------------------------------------
   Cincin berputar diganti judul permainan + bilah kemajuan berpersen. Lihat
   catatan panjang di index.html kenapa. */
.muat-judul {
  position: relative;
  display: grid;
  place-items: center;
  /* Lambang di belakang judul memakai `--fs-judul` yang sama dengan beranda,
     jadi keduanya berukuran sepadan — dan perpindahan beranda→pemuat tidak
     terbaca sebagai pindah aplikasi. */
  padding: calc(var(--fs-judul) * 0.55) 0;
}
.muat-judul .judul-besar { font-size: var(--fs-judul); text-align: center; }
.muat-bilah {
  width: min(52vw, 340px);
  height: clamp(9px, 1.7vh, 14px);
  border: 3px solid var(--garis);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  overflow: hidden;
}
.muat-bilah i {
  display: block;
  width: 0;
  height: 100%;
  background: linear-gradient(180deg, #ffe27a 0%, #ffc32e 55%, #f08a1d 100%);
  /* Transisi PENDEK, dan itu disengaja: bilah ini melompat tiap 90 ms selama
     `rambatMuat()` berjalan, dan transisi yang lebih panjang dari selang
     antar-lompatan tidak pernah sempat selesai — yang terlihat justru bilah
     yang selalu tertinggal di belakang angkanya sendiri. */
  transition: width 0.12s linear;
}
#muat .muat-teks {
  color: #cfd8ea;
  font-size: clamp(11px, 2vh, 14px);
  font-weight: 900;
  letter-spacing: 1.4px;
  font-variant-numeric: tabular-nums;
}

/* ---- KOTAK PROFIL POJOK BERANDA (§57.43.1) --------------------------------
   Garis tepi HITAM, bukan warna lencana. Sebabnya lambang lencana yang
   sekarang berdiri di sebelah nama: dua benda yang menyebut tingkatan yang
   sama, satu di antaranya mewarnai seluruh tepi kotak, berarti kotak ini
   berteriak soal lencana dua kali sebelum menyebut namanya sekali. Hitam
   mengembalikannya jadi bingkai, dan lambangnya yang bicara.

   `--lencana` TETAP diisi js/profil.js: isian bar runtun masih memakainya. */
#profil-sudut { border-color: #0e131f; }
/* Kolom teks tidak lagi `align-items: flex-start`: baris atas (nama+lencana)
   yang menentukan lebar kolom, dan bar di bawahnya melar mengisi lebar itu.
   Dengan `flex-start`, bar berlebar 100% mengukur diri terhadap kontennya
   sendiri dan menyusut jadi selebar angka di ujungnya. */
.profil-teks { align-items: stretch; }
.profil-baris {
  display: flex;
  align-items: center;
  gap: clamp(5px, 1vw, 8px);
  min-width: 0;
}
/* Nama MELAR mengisi sisa baris; lencana yang mematok tepi kanan. Batas
   lebarnya sekarang jauh lebih longgar daripada dulu (`clamp(78px,14vw,130px)`)
   karena namanya sendiri sudah dibatasi 10 huruf di js/ekonomi.js — dua batas
   untuk hal yang sama berarti yang lebih ketat diam-diam mengalahkan yang
   lain, dan elipsis muncul pada nama yang sebenarnya sah. */
.profil-nama { flex: 1 1 auto; max-width: none; min-width: 0; }
.profil-lencana {
  flex-shrink: 0;
  display: block;
  width: clamp(17px, 3.1vh, 23px);
  height: clamp(17px, 3.1vh, 23px);
}
.profil-lencana img { display: block; width: 100%; height: 100%; object-fit: contain; }
/* BAR TIDAK MELEBIHI BATAS LENCANA: lebarnya 100% dari kolom, dan kolomnya
   selebar baris nama+lencana di atasnya. Ujung kanan keduanya karena itu
   selalu sejajar, berapa pun panjang namanya — yang diminta §57.43.1. */
.profil-bar { width: 100%; }
.profil-runtun { width: 100%; }
.profil-runtun b { flex-shrink: 0; }

/* ---- WAKTU + KETERANGAN (§57.43.7) ----------------------------------------
   `#pesan` sekarang anak `#waktu-hud`, bukan elemen melayang sendiri. Aturan
   letaknya yang lama (posisi tetap di layar) dicabut di bawah; yang tersisa
   cuma rupanya. */
#waktu-hud { text-align: center; }
/* "battle time" dinaikkan sedikit — permintaan langsung. Angkanya sendiri
   sudah besar; yang tertinggal justru labelnya, dan label yang terlalu kecil
   membuat angka di atasnya terbaca sebagai angka tanpa satuan. */
#waktu-hud > span { font-size: clamp(10px, 1.9vh, 13px); letter-spacing: 1.6px; }
/* Ditulis `body #pesan` dan `body.hp #pesan`, bukan `#pesan` saja: aturan
   lamanya berdiri di DUA tempat, dan yang di `body.hp` berspesifisitas lebih
   tinggi (satu id + satu kelas + satu elemen). Ditimpa di sini alih-alih
   dihapus di tempatnya karena yang lama juga menyetel `left`/`right` dari
   rumus letak gugus tombol — dan mencabut rumus itu sebagian berarti satu
   sisa yang terlewat menarik kalimat ini kembali ke pojok layar pada satu
   ukuran layar saja. */
body #pesan,
body.hp #pesan {
  position: static;
  left: auto;
  right: auto;
  bottom: auto;
  transform: none;
  width: max-content;
  max-width: min(92vw, 460px);
  margin: clamp(5px, 1.1vh, 9px) auto 0;
  text-align: center;
  white-space: normal;
}
body #pesan.tampil,
body.hp #pesan.tampil { transform: none; }

/* ---- BARIS STATISTIK HUD (§57.43.6) ---------------------------------------
   STATS masuk KE DALAM kotaknya. Yang tinggal di `.skor-atas` cuma tugas
   meletakkan; seluruh rupa kotaknya pindah ke `.skor-ringkas`. */
.skor-atas {
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
}
.skor-ringkas {
  /* Tingginya DIPATOK ke tombol pengaturan di seberang layar — `.ikon` di
     css/style.css, 38 px termasuk garis tepi 3 px. Angkanya ditulis ulang di
     sini dan bukan dibaca dari peubah karena `.ikon` memang tidak punya satu;
     kalau tingginya nanti disetel, keduanya harus disetel bersama, dan
     catatan ini yang mengingatkannya. Dua benda sederajat di baris paling atas
     layar yang tingginya berbeda adalah satu-satunya hal yang membuat baris
     atas terlihat miring. */
  height: 38px;
  box-sizing: border-box;
  padding: 0 0 0 clamp(7px, 1.2vw, 11px);
  border: 3px solid var(--garis);
  border-radius: clamp(9px, 1.8vh, 13px);
  background: rgba(20, 26, 40, 0.86);
  overflow: hidden;
}
.ku-bd {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.ku-bd svg { width: 1.05em; height: 1.05em; flex-shrink: 0; }
/* STATS jadi keping TERAKHIR di dalam baris, dipisah garis tegak seperti
   pemisah keping lainnya — bukan tombol kedua di sebelah kotak. Sudutnya ikut
   sudut kotak induknya di sisi kanan saja, jadi ia terbaca sebagai bagian yang
   dipotong dari baris itu. */
.skor-ringkas .stats-tbl {
  align-self: stretch;
  margin-left: clamp(6px, 1.1vw, 10px);
  border: 0;
  border-left: 3px solid var(--garis);
  border-radius: 0;
  padding: 0 clamp(9px, 1.6vw, 14px);
}

/* ---- MANAGE THE COMPETITION (§57.43.2) ------------------------------------ */

/* TIGA TOMBOL SEBARIS, masing-masing dua tingkat. */
/* §57.63 — EMPAT tombol sebaris (jumlah anggota regu: 5/10/15/20 Mem).
   Mewarisi seluruh bentuk `.tiga` di bawah; yang berbeda cuma jumlah
   anggotanya, dan karena tiap tombol `flex: 1 1 0` pembagian lebarnya
   mengurus dirinya sendiri. Ukuran hurufnya sedikit di bawah `.tiga` karena
   labelnya lebih panjang ("20 MEM" enam huruf lawan "LARGE" lima) di dalam
   kotak yang seperempat lebih sempit. */
.pilih-tab.empat { display: flex; flex-direction: row; gap: clamp(4px, 0.8vw, 7px); }
.pilih-tab.empat .tab {
  flex: 1 1 0;
  min-width: 0;
  padding: clamp(9px, 2.1vh, 16px) 2px;
  font-size: clamp(11px, 2.1vh, 15px);
  white-space: nowrap;
}
.pilih-tab.tiga { display: flex; flex-direction: row; }
/* Ukuran huruf & sisipan tombol ini ditetapkan di §57.63 dekat ujung berkas,
   di tempat yang sama dengan dua penyetelan sebelumnya — cari
   `.pilih-tab.tiga .tab` di sana. Ditulis di satu tempat supaya tidak ada
   empat aturan yang saling menimpa untuk satu tombol. */
.pilih-tab.tiga .tab {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  line-height: 1.1;
}
.pilih-tab.tiga .tab b {
  font-size: inherit;
  font-weight: 900;
  letter-spacing: 0.4px;
}
/* Angka lawan lebih kecil dan lebih redam: ia KETERANGAN nama di atasnya,
   bukan nama kedua. Warnanya diwarisi supaya tab yang menyala hijau tetap
   membawa keduanya. */
.pilih-tab.tiga .tab i {
  font-style: normal;
  font-size: clamp(8px, 1.5vh, 10.5px);
  font-weight: 800;
  opacity: 0.72;
  font-variant-numeric: tabular-nums;
}

/* TOMBOL PUTIH — bentuk keempat `.tbl-besar`, sederajat dengan hijau/biru/
   kuning dan memakai peubah yang sama persis. Dipakai tombol yang menuliskan
   HARGA di badannya: warna terang adalah warna intan di seluruh permainan
   ini, dan hijau ("berangkat") berbohong tentang apa yang terjadi sesudah
   ENTER ditekan — pemain membayar lalu menunggu, bukan berangkat. */
.tbl-besar.putih { --tbl-atas: #f4f7fd; --tbl-bawah: #c3cddf; --tbl-teks: #1b2438; }
body.palet-perang .tbl-besar.putih { --tbl-atas: #efe6d4; --tbl-bawah: #bfae90; }
body.palet-mono .tbl-besar.putih { --tbl-atas: #f2f2f2; --tbl-bawah: #bdbdbd; }

/* KAKI SEJAJAR DASAR KOMIDI (§57.43.2). Kolom kanan diregangkan penuh dan
   kakinya didorong ke dasar dengan `margin-top: auto`; kolom kiri berakhir di
   dasar komidi peta. Keduanya anak `.layar-isi` yang tingginya sama, jadi
   "dasar" keduanya memang satu garis — tanpa satu angka pun dihitung. */
#layar-tur-atur .kolom-kanan { justify-content: flex-start; }
#layar-tur-atur .kolom-kanan .menu-kaki { margin-top: auto; }

/* ---- PAPAN HASIL: WARBAND + USER JADI SATU BLOK (§57.43.8) ----------------
   Lima kolom, bukan enam. Yang hilang kolom USER berlebar tetap 40 px — dan
   40 px itulah sebabnya: username sepuluh huruf meluber melewatinya lalu
   menabrak kolom bendera di sebelahnya. Sekarang nama bangsa dan nama orang
   bertumpuk di dalam satu sel `1fr` yang boleh menyusut, jadi nama panjang
   memotong DIRINYA SENDIRI dengan elipsis alih-alih mendorong tetangganya. */
.hasil-baris,
.hasil-kepala { grid-template-columns: 18px minmax(0, 1fr) 38px 34px 54px; }
.hasil-baris .siapa {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 1px;
  min-width: 0;
  overflow: hidden;
}
.hasil-baris .siapa .nm,
.hasil-baris .siapa .us {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Nama ORANG lebih kecil dan lebih redam daripada nama BANGSA di atasnya: yang
   dicari mata pertama kali di papan peringkat tetap benderanya, dan username
   adalah keterangan siapa yang memegangnya. */
.hasil-baris .siapa .us {
  font-size: 10.5px;
  font-weight: 700;
  color: #7c869c;
  letter-spacing: 0.2px;
}
.hasil-baris.kamu .siapa .us { color: #2f6fd0; }
/* Panji tidak lagi dipusatkan terhadap satu baris teks melainkan terhadap dua,
   jadi ia boleh sedikit lebih tinggi — dan tinggi itulah yang membuat sepuluh
   panji bisa dibedakan sekilas. */
.hasil-baris .wb img { width: 17px; height: 23px; }
/* Keping AFK di kolom REWARD (§57.43.8), menggantikan tanda pisah. Merah
   redam, bukan merah penuh: ia menjelaskan ketiadaan, bukan mengumumkan
   bahaya. */
.hasil-baris .hdh.nihil {
  border: none;
  background: none;
  color: #b9707a;
  font-size: 10px;
  letter-spacing: 0.6px;
}

/* ---- KAKI PANEL HASIL: DI TENGAH, SAMA LEBAR, RAPAT (§57.43.9) ------------
   `space-between` diganti `center`. Yang lama memaku tombol terluar ke tepi
   kartu, jadi lebar baris tombol diputuskan lebar KARTU — dan begitu papannya
   pecah dua lajur, kartunya melebar 300 px dan yang bertambah cuma lubang di
   tengah baris.

   `flex: 0 1 var(--nav-lebar)` — dasar yang SAMA untuk semua, jadi lebarnya
   dipatok satu angka alih-alih oleh panjang label masing-masing. Angkanya
   dipilih dari label terpanjang yang benar-benar ada di baris ini
   ("PLAY AGAIN ♦80" di panel juara turnamen). */
.hasil-nav,
.tur-nav {
  --nav-lebar: clamp(104px, 22vw, 168px);
  justify-content: center;
  gap: clamp(5px, 1vw, 9px);
}
/* §57.63 — LEBAR PASTI DIGANTI LEBAR MINIMUM, supaya label panjang tidak
   pecah dua baris. Diminta langsung ("tulisan didalam tombol tetap sebaris,
   bisa diperpanjang jika kurang ruang").

   `width: var(--nav-lebar)` memaku ketiga tombol pada satu angka, dan terukur
   di 1280x720 angka itu 123 px — cukup untuk "BACK" dan "PLAY AGAIN", TIDAK
   cukup untuk "SAVE STREAK", yang karena itu pecah jadi dua baris sendirian
   di tengah baris tombol.

   `min-width` menggantikannya: angka yang sama tetap jadi lebar SERAGAM untuk
   label pendek — jadi maksud aslinya (lebar dipatok satu angka, bukan oleh
   panjang label masing-masing) tetap berlaku di kasus yang biasa — sementara
   label yang tidak muat boleh mendorong tombolnya melebar secukupnya.
   `white-space: nowrap` yang memastikan pelebaran itu benar-benar terjadi
   alih-alih labelnya patah. */
/* §57.63 — LEBAR PASTI DIGANTI LEBAR YANG MENGIKUTI LABEL, supaya label
   panjang tidak pecah dua baris. Diminta langsung ("tulisan didalam tombol
   tetap sebaris, bisa diperpanjang jika kurang ruang").

   `width: var(--nav-lebar)` memaku ketiga tombol pada satu angka, dan terukur
   di 1280x720 angka itu 123 px — cukup untuk "BACK" dan "PLAY AGAIN", TIDAK
   cukup untuk "SAVE STREAK", yang karena itu pecah jadi dua baris sendirian
   di tengah baris tombol.

   `min-width` SEBAGAI PENGGANTI dicoba lebih dulu dan SALAH secara terukur:
   ketiganya lalu melebar ke 168 px dan gugusnya meluber keluar tepi kanan
   panel — "PLAY AGAIN" terpotong. Yang benar `width: auto` + `max-width`,
   tanpa lantai lebar sama sekali: tiap tombol selebar labelnya, gugusnya
   dipusatkan `justify-content: center` seperti sebelumnya, dan tidak ada
   satu pun yang bisa mendorong yang lain keluar panel.

   `white-space: nowrap` yang menjaga janji "tetap sebaris" waktu `flex-
   shrink` memangkas mereka di layar sempit. */
.hasil-nav .tbl,
.tur-nav .tbl {
  flex: 0 1 auto;
  width: auto;
  max-width: var(--nav-lebar);
  padding: 13px 10px;
  font-size: 13.5px;
  text-align: center;
  white-space: nowrap;
}
/* Aturan lama yang melepas batas lebar waktu tombol iklan tersembunyi tidak
   berlaku lagi — lebarnya sekarang memang dipatok, dan dua tombol di tengah
   adalah susunan yang benar. */
.hasil-nav:has(#b-iklan[hidden]) .tbl { max-width: none; }

/* TOMBOL IKLAN tanpa keping (§57.43.9): ikonnya berdiri telanjang di samping
   tulisannya, sama seperti lambang intan di tombol harga. Keping kuning di
   dalam tombol membuatnya terbaca sebagai tombol-berisi-tombol — satu-satunya
   di baris yang bentuknya begitu — dan tingginya ikut naik demi keping itu. */
.iklan-tanda {
  display: block;
  flex-shrink: 0;
  width: 1.55em;
  height: 1.55em;
  border: 0;
  border-radius: 0;
  background: none;
  object-fit: contain;
}
.tbl.iklan { gap: 6px; padding: 13px 6px; }
.tbl.iklan.siap .iklan-tanda { background: none; }

/* ---- BASE PLAYER, tata letak (§57.43.10) ----------------------------------
   Latar tetap arena 3D hidup — bukan gambar yang ditempel di atasnya. Yang
   dipadamkan ORBITNYA (`panggung.setDiam()` di js/menu3d.js), jadi yang
   terlihat memang "gambar hutan dari game asli yang tidak memutar", tanpa
   satu piksel pun aset baru dan tanpa masalah urutan lapis: model 3D pemimpin
   digambar ke kanvas yang SAMA, dan gambar latar apa pun yang ditempel di
   antaranya pasti menutupinya.

   TANPA SCRIM PENGGELAP, dan itu keputusan yang diambil dari pengukuran.
   Percobaan pertama memasang `.base-latar` — gradasi gelap di kedua tepi,
   bening di tengah — supaya kedua kolom melayang tetap terbaca di atas kanopi
   hutan yang terang. Hasilnya justru sebuah PERSEGI GELAP yang batasnya
   terlihat jelas (terukur di 1280x720: tepi tajam di x=190 dan x=1090,
   tepat pada batas `.base-isi`), karena landaian 26% pada kotak selebar
   900 px berarti kegelapannya masih 0,3 di titik 300 px dari tepi.

   Yang menggantikannya: tidak ada. Kartu statistik sudah punya latar gelap
   sendiri (`rgba(20,26,40,0.86)`) dan keempat tombol ikon juga — jadi yang
   perlu terbaca memang sudah berdiri di atas dasarnya sendiri, dan yang
   tersisa di antara keduanya cuma pemandangan yang memang harus terlihat
   penuh. */
.base-kiri,
.base-kanan { z-index: 1; }

/* MODEL DIGESER KE KIRI (§57.43.10) supaya selisih jaraknya ke kolom kiri dan
   ke kolom kanan SAMA. Ia tidak lagi dipusatkan ke layar: kolom kanan (kartu
   statistik, ±250 px) jauh lebih lebar daripada kolom kiri (deret ikon,
   ±64 px), jadi model yang berdiri di tengah layar duduk jauh lebih dekat ke
   kanan. Pusatnya digeser separuh selisih kedua kolom itu. */
.base-potret {
  left: calc(50% - (var(--base-kanan, 250px) - var(--base-kiri, 64px)) / 2);
  z-index: 0;
}
.base-kiri { --base-kiri: clamp(46px, 8.6vh, 64px); width: var(--base-kiri); }
.base-kanan { --base-kanan: clamp(178px, 26vw, 250px); }
/* Peubahnya harus terbaca oleh `.base-potret` yang bukan anak keduanya, jadi
   nilainya diulang di induk bersama. Dua penulisan untuk satu angka memang
   rawan menyimpang — dijaga dengan menuliskan RUMUS yang sama persis dan
   menaruh ketiganya berdampingan di sini. */
.base-isi {
  --base-kiri: clamp(46px, 8.6vh, 64px);
  --base-kanan: clamp(178px, 26vw, 250px);
}
.base-ikon img { display: block; width: 74%; height: 74%; object-fit: contain; }

/* KARTU STATISTIK (§57.43.11) ------------------------------------------------ */
.base-baris.nama {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}
.base-baris.nama > span {
  flex-shrink: 0;
  font-size: clamp(7.5px, 1.3vh, 9.5px);
  font-weight: 900;
  letter-spacing: 1.1px;
  color: #8b97ae;
}
.base-nama-teks {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: right;
  font-size: clamp(11px, 2vh, 14px);
  font-weight: 900;
}
.base-baris.nama input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 3px 7px;
  border: 2px solid var(--garis);
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  font: inherit;
  font-size: clamp(11px, 2vh, 14px);
  font-weight: 900;
  text-align: right;
}
.base-baris.nama input[hidden],
.base-nama-teks[hidden] { display: none; }
/* Tombol pensil. Sengaja SEKECIL mungkin yang masih bisa ditekan jempol: ia
   satu-satunya kontrol di kartu yang isinya empat baris bacaan, dan kontrol
   yang lebih menonjol daripada isinya membuat kartu terbaca sebagai formulir. */
.base-edit {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border: 2px solid var(--garis);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.12);
  color: #ffd98a;
  cursor: pointer;
}
.base-edit:hover { filter: brightness(1.2); }
.base-edit:active { transform: scale(0.92); }
.base-edit svg { width: 68%; height: 68%; }

/* RUNTUN dalam kotaknya sendiri — satu-satunya baris di kartu ini yang punya
   BATAS, dan karena itu satu-satunya yang bisa digambarkan sebagai bar. */
.base-runtun {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: clamp(4px, 0.9vh, 7px) clamp(6px, 1.1vw, 9px);
  border: 2px solid rgba(255, 255, 255, 0.16);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.06);
}

/* Garis pemisah sebelum lencana: di atasnya angka MENTAH, di bawahnya
   KESIMPULAN dari angka pertama. Tanpa pemisah, lencana terbaca sebagai baris
   statistik keempat. */
.base-pisah {
  height: 2px;
  margin: clamp(2px, 0.5vh, 4px) 0;
  background: rgba(255, 255, 255, 0.16);
  border-radius: 2px;
}
.base-lencana {
  display: flex;
  align-items: center;
  gap: clamp(6px, 1.1vw, 10px);
  min-width: 0;
}
.lencana-gbr {
  flex-shrink: 0;
  display: block;
  width: clamp(26px, 4.6vh, 36px);
  height: clamp(26px, 4.6vh, 36px);
  object-fit: contain;
}
.lencana-teks { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.lencana-teks b {
  font-size: clamp(10px, 1.8vh, 13px);
  font-weight: 900;
  letter-spacing: 0.7px;
  color: var(--lencana, #c87f3a);
}
/* Ambang berikutnya: kabar yang menyebut JALAN, bukan keadaan — lihat catatan
   di js/profil.js. Boleh membungkus dua baris, karena "375 flags to Gold" di
   kartu 178 px memang tidak muat sebaris. */
.lencana-teks i {
  font-style: normal;
  font-size: clamp(8px, 1.4vh, 10px);
  font-weight: 800;
  line-height: 1.25;
  color: #93a0b8;
}

/* ---- §57.63: baris lencana jadi PINTU ke panel daftar ---------------------
   Ia tetap terlihat persis sama seperti sebelumnya waktu diam — yang
   ditambahkan cuma tanda bahwa ia bisa ditekan, dan hanya pada saat jari
   atau tetikus benar-benar di atasnya. Baris ini duduk di dalam kartu
   ringkasan; memberinya latar tetap akan menjadikannya tombol keempat di
   kartu yang isinya bacaan. */
.base-lencana {
  cursor: pointer;
  padding: clamp(3px, 0.6vh, 5px);
  margin: calc(-1 * clamp(3px, 0.6vh, 5px));
  border-radius: clamp(7px, 1.3vh, 10px);
  transition: background 0.12s;
}
.base-lencana:hover { background: rgba(255, 255, 255, 0.09); }
.base-lencana:active { background: rgba(255, 255, 255, 0.14); }

/* ---- §57.63: PANEL DAFTAR LENCANA ----------------------------------------
   Satu tangga bertiga: lambang, nama + ambangnya, lalu penanda keadaan.
   Yang SEDANG dipakai diberi garis tepi berwarna lencananya sendiri; yang
   BELUM dicapai diredam. Tidak ada tombol apa pun di dalamnya — lihat
   catatan di index.html. */
.lencana-kotak { width: min(360px, 92vw); gap: clamp(9px, 1.8vh, 14px); padding: clamp(15px, 3vh, 22px); }
.lencana-daftar { display: flex; flex-direction: column; gap: clamp(7px, 1.4vh, 11px); }
.lencana-baris {
  display: flex;
  align-items: center;
  gap: clamp(8px, 1.6vw, 13px);
  padding: clamp(8px, 1.6vh, 12px) clamp(10px, 2vw, 14px);
  border: 3px solid var(--garis);
  border-radius: clamp(9px, 1.8vh, 13px);
  background: #e8edf7;
}
.lencana-baris.kini {
  /* Warna lencananya sendiri, bukan warna sorot bersama: yang membedakan
     baris ini dari dua lainnya justru IDENTITASNYA, dan lencana perak yang
     disorot kuning menyebut dua warna untuk satu benda. */
  border-color: var(--lencana);
  background: linear-gradient(180deg, #fffdf6 0%, #fff4dc 100%);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lencana) 35%, transparent);
}
.lencana-baris.belum { opacity: 0.55; }
.lencana-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.lencana-info b {
  font-size: clamp(12px, 2.2vh, 15px);
  font-weight: 900;
  letter-spacing: 0.5px;
  color: #1b2030;
}
.lencana-info i {
  font-style: normal;
  font-size: clamp(9px, 1.6vh, 11px);
  font-weight: 800;
  color: #6b7794;
}
.lencana-tanda {
  flex-shrink: 0;
  padding: clamp(3px, 0.6vh, 5px) clamp(7px, 1.4vw, 10px);
  border-radius: 999px;
  background: #ccd5e6;
  font-size: clamp(8px, 1.4vh, 10px);
  font-weight: 900;
  letter-spacing: 0.9px;
  color: #55607d;
  /* Title Case, bukan ALL CAPS — status singkat (Current/Done/Locked),
     bukan heading/tombol. */
  text-transform: capitalize;
}
.lencana-baris.kini .lencana-tanda { background: var(--lencana); color: #2b1f00; }

/* ---- §57.63: PANEL SELAMAT NAIK LENCANA ----------------------------------
   Lambangnya BESAR dan di tengah — panel ini ada untuk satu benda saja, dan
   benda itu sebuah gambar. Ia masuk dengan gerakan yang sama dengan kotak
   hadiah harian (`harian-letus`), karena keduanya kejutan yang sejenis. */
.naik-kotak { width: min(340px, 92vw); gap: clamp(8px, 1.6vh, 12px); padding: clamp(15px, 3vh, 22px); text-align: center; }
.naik-gbr { display: flex; justify-content: center; }
.naik-gbr img {
  width: clamp(72px, 15vh, 110px);
  height: clamp(72px, 15vh, 110px);
  object-fit: contain;
  animation: harian-letus 0.55s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
/* WARNA LENCANA SEBAGAI LATAR, BUKAN SEBAGAI WARNA HURUF. Terukur: perak
   (#b9c2cf) sebagai warna huruf di atas panel #eef1f8 memberi rasio kontras
   1,5:1 — namanya praktis lenyap, dan justru nama itulah yang panel ini ada
   untuk mengumumkannya. Emas (#f2c14a) tidak jauh lebih baik. Sebagai keping
   berlatar warna lencana dengan tulisan tinta gelap, ketiga lencana terbaca
   sama jelasnya dan warnanya tetap menyebut lencana yang mana. */
.naik-nama {
  align-self: center;
  padding: clamp(4px, 0.9vh, 7px) clamp(12px, 2.4vw, 18px);
  border: 3px solid var(--garis);
  border-radius: 999px;
  background: var(--lencana, #c87f3a);
  font-size: clamp(15px, 2.8vh, 19px);
  font-weight: 900;
  letter-spacing: 0.6px;
  color: #241a05;
}
.naik-teks {
  margin: 0;
  font-size: clamp(11px, 2vh, 13px);
  font-weight: 700;
  line-height: 1.5;
  color: #55607d;
  text-wrap: balance;
}
@media (prefers-reduced-motion: reduce) {
  .naik-gbr img { animation: none; }
}

/* KAKI: hadiah harian DI SAMPING KIRI Quick Game, keduanya setinggi sama
   (§57.43.10). Bertumpuk, keduanya memakan dua tinggi baris di kolom yang
   tingginya sudah habis dipakai kartu di atasnya. */
.base-kaki {
  margin-top: auto;
  display: flex;
  align-items: stretch;
  gap: clamp(7px, 1.3vw, 11px);
}
.base-hadiah {
  margin-top: 0;
  /* Lebar tetap, bukan `1fr`: yang harus besar QUICK GAME — ia jalan keluar
     dari halaman ini — dan hadiah harian tombol sampingan yang dibuka sekali
     sehari. Dua tombol sama lebar akan menyatakan keduanya sederajat. */
  flex: 0 0 auto;
  width: clamp(54px, 9.6vh, 74px);
}
.base-hadiah img { display: block; width: clamp(24px, 4.4vh, 34px); height: clamp(24px, 4.4vh, 34px); object-fit: contain; }
/* QUICK GAME DIBESARKAN sampai setinggi tombol hadiah harian — permintaan
   langsung. Sebelumnya ia `.tbl-besar` biasa, jauh lebih pendek, dan tombol
   utama halaman yang lebih pendek daripada tombol sampingannya di sebelah
   membalik derajat keduanya. */
.base-main {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  /* HURUFNYA IKUT DIBESARKAN menyesuaikan tombolnya (§57.63) — permintaan
     langsung. `.tbl-besar` memberinya `--fs-tombol` (19 px terukur di
     1280x720) di dalam kotak setinggi 74 px, jadi hurufnya cuma memakai
     seperempat tinggi tombol dan tombol utama halaman ini terbaca lebih
     lemah daripada ukurannya.

     Dipatok ke TINGGI TOMBOL (`vh`), bukan ke lebar: tombol ini tumbuh
     mengikuti tinggi tombol hadiah harian di sebelahnya (`align-items:
     stretch` di `.base-kaki`), jadi tinggi itulah yang menentukan berapa
     ruang yang sebenarnya ada untuk hurufnya. Batas atas 30 px menahannya
     supaya tidak melar melewati lebar 193 px yang tersedia — "CASUAL" pada
     30 px meminta ±150 px, masih di dalam tombol dengan sisipan utuh. */
  font-size: clamp(19px, 4vh, 30px);
  /* Sisipan mendatar `.tbl-besar` (22 px) dihitung untuk huruf 19 px. Pada
     30 px ia menyisakan terlalu sedikit ruang bernapas di kiri-kanan, jadi
     dikecilkan — yang menahan lebar tombol tetap `flex`, bukan sisipan ini. */
  padding-left: clamp(8px, 1.2vw, 14px);
  padding-right: clamp(8px, 1.2vw, 14px);
}

/* ---- PANEL KOLEKSI (§57.43.12, §57.43.15, §57.43.16) ---------------------- */

/* Judul di TENGAH. `.berpalang` memasang sisipan kanan 30 px untuk memberi
   ruang tombol silang, dan sisipan itu menggeser pusat judul 15 px ke kiri —
   jadi ia harus dilawan dengan sisipan kiri yang sama, bukan dicabut (tanpa
   sisipan kanan, judul panjang menyelinap ke bawah tombol silangnya). */
.kotak.berpalang .kotak-judul.tengah { text-align: center; padding-left: 30px; }

/* SILANG MERAH. Panel-panel ini terbit di atas halaman berlatar hutan yang
   terang, dan silang putih bergaris tipis di atas kanopi hijau muda praktis
   tidak terlihat. Merah juga menyatakan arti yang benar: satu-satunya tombol
   di panel yang MEMBATALKAN, di antara belasan petak yang semuanya memilih. */
.kotak-silang.merah {
  background: var(--merah, #e0483a);
  border-color: var(--garis);
  color: #fff;
}
.kotak-silang.merah:hover { background: #f05a4b; filter: none; }

/* TIGA PETAK SEKALIGUS, tetap bisa digulir (§57.43.15). `flex-basis` dihitung
   dari lebar wadahnya dikurangi dua celah lalu dibagi tiga — jadi petak
   KEEMPAT jatuh tepat di tepi kanan dan terlihat separuh, dan separuh itulah
   yang memberi tahu pemain masih ada lagi di sebelah kanan. Tanpanya, deret
   yang pas tiga terbaca sebagai deret yang isinya memang cuma tiga. */
.koleksi-petak.baris.tiga { --celah: clamp(5px, 1vw, 9px); }
.koleksi-petak.baris.tiga .koleksi-sel {
  flex: 0 0 calc((100% - var(--celah) * 2) / 3);
  min-width: 0;
}
.koleksi-sel { position: relative; }
/* GEMBOK di pojok kanan-atas petak (§57.43.17), menggantikan "redup saja".
   Redup menyatakan "tidak bisa ditekan" — dan sejak petak terkunci justru
   MEMBUKA dialog beli, itu kebalikan dari yang benar. Gemboknya menyatakan
   "belum jadi milikmu", yang memang bisa diubah. */
.koleksi-sel.terkunci { opacity: 0.78; }
.sel-gembok {
  position: absolute;
  top: 3px;
  right: 3px;
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  border-radius: 5px;
  background: rgba(12, 16, 26, 0.86);
  color: #ffd98a;
}
.sel-gembok svg { display: block; width: 72%; height: 72%; }
/* Ikon arena di petak sekarang berkas gambar, bukan SVG garis — aturannya
   disamakan dengan panji bangsa di petak sebelahnya supaya keduanya sebesar
   sama di dalam petak yang sama. */
.koleksi-sel img { object-fit: contain; }

/* KOTAK KETERANGAN: nama di tengah, garis, paragraf rata kanan-kiri
   (§57.43.15/§57.43.16). */
/* Kotak keterangan ini berlatar TERANG (`.koleksi-ket { background: #d7dceb }`),
   jadi warnanya diambil dari keluarga gelap — bukan `#ffd98a` kuning madu yang
   dipakai judul di panel berlatar gelap. Terukur waktu diuji: kuning madu di
   atas #d7dceb praktis tidak terbaca. */
.ket-kepala {
  text-align: center;
  font-size: clamp(12px, 2.2vh, 16px);
  font-weight: 900;
  letter-spacing: var(--lc-kapital);
  /* Title Case, bukan ALL CAPS — nama entitas, bukan heading/tombol.
     Ditimpa lagi eksplisit di blok konsolidasi ujung berkas. */
  text-transform: capitalize;
  color: #1b2030;
}
.ket-garis {
  height: 2px;
  margin: clamp(5px, 1vh, 8px) 0;
  background: rgba(27, 32, 48, 0.22);
  border-radius: 2px;
}
/* RATA KANAN-KIRI, permintaan langsung. `hyphens: auto` ikut karena tanpanya
   perataan penuh pada kolom sesempit ini membuka celah antar-kata selebar
   beberapa huruf — "sungai kata" yang justru lebih sulit dibaca daripada rata
   kiri biasa. */
/* `.koleksi-ket .ket-isi`, bukan `.ket-isi` saja: aturan `.koleksi-ket p` di
   atas berspesifisitas lebih tinggi (satu kelas + satu elemen) dan akan
   mengembalikan `margin-top` yang justru harus nol di sini — garis pemisah di
   atasnya sudah menyediakan jaraknya sendiri. */
.koleksi-ket .ket-isi {
  margin: 0;
  text-align: justify;
  hyphens: auto;
  font-size: clamp(9.5px, 1.7vh, 12px);
  font-weight: 600;
  line-height: 1.5;
  color: #414c66;
}

/* ---- PANEL CUSTOM PLAYER (§57.43.13) -------------------------------------- */
/* Gambar besar panel Custom Player. Memakai kerangka `.koleksi-gambar` yang
   sama dengan ketiga panel koleksi — satu bentuk untuk satu benda — dan cuma
   menambah tinggi minimum supaya kotaknya tidak menciut waktu gambarnya belum
   selesai dirender. */
.rupa-gambar { min-height: clamp(120px, 24vh, 210px); }
/* Baris kategori: dua petak sama lebar, bentuknya sama dengan petak koleksi —
   keduanya "pilih satu dari beberapa", dan bahasa bentuk yang sama berarti
   pemain tidak perlu belajar dua kali. */
.rupa-tab { display: flex; gap: clamp(5px, 1vw, 9px); }
.rupa-tab .koleksi-sel { flex: 1 1 0; min-width: 0; }
.rupa-tab .koleksi-sel img,
.rupa-tab .rupa-warna { width: clamp(20px, 3.4vh, 26px); height: clamp(20px, 3.4vh, 26px); }
/* §57.64 — TINGGI SERAGAM, sama dengan ketiga panel koleksi (lihat
   `--panel-h` dan catatan panjangnya di `.kotak.lebar.koleksi-kotak`).
   Panel ini keempat pintu yang sama di kolom Base Player, jadi ia ikut aturan
   yang sama. `.rupa-wadah` di bawah sudah `overflow-y: auto`, jadi kisi gaya
   wajah yang tidak muat menggulir sendiri. */
/* §57.65 — LEBARNYA ikut disamakan dengan ketiga panel koleksi, bukan cuma
   tingginya. §57.64 menyamakan tinggi keempat pintu Base Player dan berhenti
   di situ, jadi Custom Player tetap ±420 px sementara Warlords/Map Arenas/
   Warlord's Base 660 px — empat pintu berdampingan yang melompat LEBARNYA
   waktu dibuka bergantian, cacat yang sama persis dengan yang §57.64
   perbaiki pada sumbu tegak.

   Ini juga yang membuat pembesaran huruf dan wajah §57.65 bisa berdiri:
   pada 420 px, kisi gaya wajah cuma memuat DUA petak sebaris dan delapan
   gaya jadi empat baris gulir di panel yang tingginya cuma memuat satu
   setengah. Pada 660 px ia kembali memuat tiga-empat sebaris pada ukuran
   huruf yang baru — jadi keterbacaan yang diminta tidak dibayar dengan
   panel yang harus digulir untuk melihat apa pun. */
.kotak.lebar.rupa-kotak { width: min(660px, 94vw); height: var(--panel-h); }

/* §57.64 — DIBESARKAN dari `clamp(7.5px, 1.3vh, 10px)`, diminta langsung
   ("pastikan tulisan di tombol/kotaknya jelas terlihat karena yang sekarang
   terlalu kecil").

   Catatan lama di bawah tetap berlaku dan justru itu yang membuat kenaikan ini
   aman: nama gaya BOLEH mengecil sampai batas bawahnya waktu petaknya sempit.
   Yang dinaikkan batas ATAS dan tengahnya — di layar lebar, tempat petaknya
   memang lega, "Common" tidak lagi ditulis 10 px sementara seluruh panel lain
   di halaman yang sama berhuruf 15 px. Batas bawah 9 px (dari 7,5) masih
   memuat "Common" utuh pada petak tersempit di HP mendatar. */
.rupa-sel span { font-size: clamp(9px, 1.9vh, 13px); letter-spacing: 0.2px; }
/* Wadah isi kategori: KISI yang mengisi ke bawah dan digulir tegak. Baris
   mendatar yang panjang menyembunyikan isinya di luar tepi kanan tanpa satu
   tanda pun bahwa masih ada lagi — dan jenis wajah maupun warna kulit
   keduanya akan bertambah. */
.rupa-wadah {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(5px, 1vw, 9px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 2px;
}
.rupa-sel { position: relative; }
/* Petak warna kulit: cakram warna pejal bergaris tepi, bukan gambar. Ia
   satu-satunya benda di panel ini yang seluruh isinya memang warna, dan
   merendernya sebagai foto kepala akan menyembunyikan justru apa yang
   dipilih di balik helm dan bayangan. */
.rupa-warna {
  display: block;
  /* §57.65 — ikut membesar bersama foto wajah di petak sebelahnya (36 -> 52 px).
     Keduanya berdiri di KISI YANG SAMA dan berganti lewat tab yang sama, jadi
     membesarkan salah satunya saja membuat tinggi petak melompat pada detik
     pemain berpindah dari Face ke Skin. Angkanya sengaja sedikit di bawah foto
     (52 lawan 62 px): cakram penuh warna terbaca lebih besar daripada foto
     kepala berlatar tembus pandang pada ukuran yang sama persis. */
  width: clamp(34px, 6vh, 52px);
  height: clamp(34px, 6vh, 52px);
  border: 2.5px solid var(--garis);
  border-radius: 50%;
  background: var(--w, #f0c8a0);
}
/* §57.65 — WAJAHNYA DIPERBESAR (44 -> 62 px di batas atas), diminta langsung:
   "wajah dan tulisan bisa terlihat jelas, yang ada saat ini terlihat sangat
   kecil".

   Yang membuat keluhannya benar bukan angka 44 px itu sendiri melainkan
   perbandingannya dengan petak yang memuatnya: kisi empat kolom di panel
   selebar ini memberi tiap petak ±96 px, jadi foto 44 px cuma mengisi
   sekitar seperempat luas petaknya dan sisanya ruang kosong bergaris tepi.
   Petak yang sebagian besar isinya kosong terbaca sebagai petak kosong.

   Kenapa `contain` dipertahankan meski kotaknya membesar: sumbernya foto
   kepala berlatar tembus pandang dengan perbandingan yang tidak persis
   persegi, dan `cover` akan memangkas justru bagian atas kepala — helm dan
   rambut, yaitu satu-satunya hal yang MEMBEDAKAN kedelapan gaya wajah ini
   satu sama lain. Cacat yang sama sudah terjadi sekali di `.koleksi-gambar`
   (§57.64) dan diperbaiki dengan jawaban yang sama. */
.rupa-sel img {
  width: clamp(38px, 7.2vh, 62px);
  height: clamp(38px, 7.2vh, 62px);
  object-fit: contain;
}

/* ---- HP mendatar: kepadatan panel baru ------------------------------------
   Diukur di 892x412 — tempat game ini sebenarnya dimainkan. Yang paling cepat
   kehabisan tinggi kartu statistik Base Player (tujuh baris) dan wadah kisi
   Custom Player. */
@media (max-height: 560px) {
  .base-kartu { gap: 3px; padding: 7px 9px; }
  .base-runtun { padding: 3px 6px; }
  .base-pisah { margin: 1px 0; }
  .lencana-gbr { width: 24px; height: 24px; }
  .base-ikon { width: 42px; height: 42px; }
  .base-isi,
  .base-kiri { --base-kiri: 42px; }
  .base-hadiah { width: 52px; }
  .base-hadiah img { width: 22px; height: 22px; }
  .rupa-wadah { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .rupa-sel img { width: 28px; height: 28px; }
  .rupa-warna { width: 24px; height: 24px; }
  .muat-bilah { width: min(58vw, 300px); }
}

/* ======================================================================
   §57.44 — putaran rapi-rapi besar: pojok atas, panel hasil, Base Player,
   panel beli, tutorial. Ditulis di ujung berkas dengan alasan yang sama
   dengan §57.43: aturan berkekhususan sama yang datang belakangan menang,
   jadi seluruh penyetelan satu putaran duduk di satu tempat yang bisa
   dibaca sebagai satu cerita, bukan tersebar di sepuluh sisipan.
   ====================================================================== */

/* ---- 57.44.1  GUGUS POJOK KANAN-ATAS jadi sepasang dengan kotak profil --
   Sebelumnya ketiganya KUNING dengan tulisan gelap, berhadapan dengan kotak
   profil yang gelap bertulisan putih. Dua sudut atas dari satu bilah yang
   sama tidak boleh berasal dari dua bahasa warna yang berbeda — yang kuning
   terbaca sebagai tombol ajakan (seperti QUICK GAME di tengah layar),
   padahal tidak satu pun dari ketiganya menjanjikan hadiah.

   Angka-angkanya diambil dari `#profil-sudut` apa adanya supaya keduanya
   tidak bisa menyimpang: latar `rgba(20,26,40,0.82)`, tepi `#0e131f`,
   radius dan tinggi yang sama. */
#intan-sudut,
#sudut-atas > button {
  background: rgba(20, 26, 40, 0.82);
  border-color: #0e131f;
  color: #fff;
}
/* Tulisannya PUTIH, ketiganya. Sebelumnya ia `var(--garis)` — warna yang
   memang benar di atas kuning dan tidak terbaca sama sekali di atas gelap. */
#intan-nilai,
#bahasa-sudut span,
#musik-sudut span,
#ads-sudut span { color: #fff; }

/* SATU TINGGI IKON untuk ketiganya (§57.44.1). Terukur sebelum disetel:
   intan 21,6 px, bola bumi 30,8 px, iklan 20,0 px — tiga ikon sebaris yang
   tidak satu pun setinggi tetangganya. Dipatok lewat TINGGI dan `width:auto`,
   bukan lewat sisi persegi: ikon iklan yang baru berbanding 16:9, dan
   memaksanya persegi berarti memampatkannya. */
#sudut-atas {
  --pojok-ikon: clamp(20px, 3.5vh, 26px);
}
#intan-sudut .ik-intan,
#ads-sudut img,
#sudut-atas svg {
  display: block;
  height: var(--pojok-ikon);
  width: auto;
  aspect-ratio: auto;
  object-fit: contain;
}
#intan-sudut .ik-intan { aspect-ratio: 1; }
#sudut-atas svg { aspect-ratio: 1; }

/* BAHASA, MUSIK, dan IKLAN SELEBAR SATU SAMA LAIN. Terukur: 73,4 px dan
   68,5 px — selisih lima piksel, cukup untuk terbaca sebagai dua tombol yang
   tidak sengaja berbeda. Dipatok `min-width` bersama, bukan lebar tetap:
   kalau nanti isinya lebih panjang dari patokan, keduanya masih boleh
   tumbuh. MUSIK (§57.62) ikut patokan yang sama — "ON"/"OFF" sama pendeknya
   dengan "EN"/"AD", jadi ketiganya tetap terbaca sebagai satu gugus. */
#bahasa-sudut,
#musik-sudut,
#ads-sudut {
  min-width: clamp(66px, 12vw, 92px);
  padding-left: clamp(6px, 1.1vw, 10px);
  padding-right: clamp(6px, 1.1vw, 10px);
}

/* KEPING INTAN dirapatkan. Terukur: 16,0 px sela kiri dan 16,0 px sela kanan
   pada keping selebar 87 px — sela yang lebih lebar dari ikonnya sendiri
   membuat angka dan lambang terlihat mengambang, bukan sepasang. `min-width`
   pada angkanya tetap dipertahankan (ia yang mencegah keping berdenyut lebar
   waktu digitnya bertambah), cuma diperkecil. */
#intan-sudut {
  padding-left: clamp(7px, 1.2vw, 10px);
  padding-right: clamp(7px, 1.2vw, 10px);
  gap: clamp(3px, 0.6vw, 5px);
}
#intan-nilai { min-width: 1.8ch; }

/* ---- 57.44.2  LENCANA TEPAT DI ATAS ANGKA RUNTUN ----------------------
   Terukur sebelum disetel: pusat lencana di x=159,5 dan pusat angka di
   x=168,4 — sembilan piksel meleset, cukup untuk terbaca sebagai dua benda
   yang kebetulan berdekatan. Sebabnya keduanya cuma sama-sama RATA KANAN,
   dan dua benda berbeda lebar yang rata kanan tidak pernah sepusat.

   Diperbaiki dengan mengubah kolom teks jadi KISI dua lajur: nama | lencana
   di baris atas, bar | angka di baris bawah. Lajur kanan lebarnya ditentukan
   yang terlebar dari keduanya, dan isinya dipusatkan — jadi lencana berdiri
   tepat di atas angkanya berapa pun panjang keduanya.

   `display: contents` pada kedua pembungkusnya supaya HTML-nya tidak perlu
   dibongkar: keempat anaknya naik jadi anak langsung kisi. */
.profil-teks {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  column-gap: clamp(5px, 1vw, 8px);
  row-gap: 4px;
}
.profil-baris,
.profil-runtun { display: contents; }
.profil-lencana,
.profil-runtun b { justify-self: center; }
/* Bar berhenti di batas lajur kirinya sendiri, jadi ia MUSTAHIL melewati
   tepi lencana — yang dulu dijaga `width: 100%` sekarang dijaga kisinya. */
.profil-bar { width: 100%; }

/* ---- 57.44.3  IKON ARENA di kartu komidi ------------------------------
   `img` polos di dalam `.komidi-kartu` sudah punya aturannya sendiri jauh di
   atas: garis tepi 2 px, `aspect-ratio: 3/2`, `object-fit: cover`,
   `image-rendering: pixelated`. Semua itu BENAR untuk panji bangsa — selembar
   kain persegi panjang berbingkai — dan semuanya salah untuk ikon lepas: yang
   dihasilkan adalah ikon di dalam kotaknya sendiri di dalam kotak kartunya,
   persis "kotak di dalam kotak" yang diminta hilang. Kelas sendiri, bukan
   pengecualian di dalam aturan panji, supaya keduanya tidak saling menawar. */
.komidi-kartu .a-ikon {
  display: block;
  width: 100%;
  max-width: clamp(26px, 6.2vh, 46px);
  height: auto;
  aspect-ratio: 1;
  border: 0;
  border-radius: 0;
  object-fit: contain;
  image-rendering: auto;
}
.komidi-kartu.kunci:not(.aktif) .a-ikon { opacity: 0.72; }

/* ---- 57.44.3b  SATU TINGGI untuk seluruh tombol kartu Manage The Map ----
   Terukur sebelum disetel: baris cuaca dan baris AKTIF/NONAKTIF sama-sama
   `.pilih-tab .tab`, sedangkan baris rintangan `.centang` — sisipan tegaknya
   lebih kecil DAN ukuran hurufnya satu tingkat lebih kecil, jadi baris ketiga
   berdiri lebih pendek dari dua baris di atasnya di kartu yang sama.

   Disamakan lewat SUMBERNYA, bukan lewat `min-height` yang ditebak: `.centang`
   diberi sisipan tegak dan ukuran huruf yang SAMA PERSIS dengan `.pilih-tab
   .tab`, lalu kotak centangnya dipatok `1em` supaya kotak itu tidak lebih
   tinggi daripada baris hurufnya sendiri. Dengan begitu tinggi keduanya
   dihitung dari angka yang sama dan mustahil menyimpang berapa pun `vh`-nya. */
.centang {
  padding-block: clamp(7px, 1.7vh, 13px);
  font-size: var(--fs-label);
  font-weight: 900;
}
.centang-kotak { width: 1em; height: 1em; border-radius: 3px; }

/* ---- 57.44.3c  KNOP PENGGESER memanjang tegak -------------------------
   Diminta: kotak kuningnya menjulur ke atas dan ke bawah melewati jalurnya.
   Bukan hiasan — knop yang persis setinggi jalurnya adalah knop yang tepinya
   berimpit dengan tepi jalur di kedua sisi, dan yang terlihat cuma "bagian
   jalur yang berwarna lain". Menjulur, ia jadi benda tersendiri di atas
   jalur, dan itulah yang mengatakan ia bisa diseret.

   `margin-top` negatif WAJIB di webkit: `appearance: none` tanpa aturan
   `::-webkit-slider-runnable-track` membuat knop diratakan ke TEPI ATAS
   jalur, jadi tinggi tambahan seluruhnya jatuh ke bawah. Firefox memusatkan
   knopnya sendiri, jadi `::-moz-range-thumb` justru TIDAK boleh diberi
   margin — itu sebabnya keduanya tidak bisa digabung jadi satu aturan. */
.geser { --gsr-julur: clamp(3px, 0.7vh, 6px); }
.geser::-webkit-slider-thumb {
  width: calc(var(--gsr) * 1.02);
  height: calc(var(--gsr) + var(--gsr-julur) * 2);
  margin-top: calc(var(--gsr-julur) * -1);
  border-radius: 6px;
}
.geser::-moz-range-thumb {
  width: calc(var(--gsr) * 1.02);
  height: calc(var(--gsr) + var(--gsr-julur) * 2);
  border-radius: 6px;
}

/* ---- 57.44.4  PAPAN HASIL: enam kolom, huruf sebesar tombol -----------
   Tiga perubahan yang saling bergantung, jadi ditulis sebagai satu blok.

   (a) WARBAND dan USER kembali jadi DUA KOLOM, membalik §57.43.8. Yang dulu
       memaksa keduanya bertumpuk adalah lebar TETAP 40 px pada kolom USER;
       sekarang keduanya `minmax(0, 1fr)` — masing-masing boleh menyusut dan
       memotong dirinya sendiri dengan elipsis, jadi sebab aslinya lenyap.

   (b) Karena tidak bertumpuk lagi, keduanya tidak perlu berbagi satu tinggi
       baris — dan berbagi tinggi itulah yang memaksa keduanya ditulis 10,5 px
       dan 13 px, jauh lebih kecil daripada tulisan tombol di kakinya. Seluruh
       isi tabel sekarang mengambil `--tabel-fs`, satu peubah, yang dipatok
       SAMA dengan ukuran huruf tombol di bawahnya.

   (c) TEBAL dan HITAM, semuanya. Kelabu #6b7590 / #7c869c yang dipakai kolom
       USER, ROUND, dan ALIVE adalah warna untuk keterangan sampingan; di
       papan hasil tidak ada satu pun kolom yang sampingan — pemain datang ke
       panel ini justru untuk membaca angka-angka itu. */
.hasil-kotak { --tabel-fs: clamp(12px, 2.4vh, 15px); }
.hasil-baris,
.hasil-kepala { grid-template-columns: 18px minmax(0, 1fr) minmax(0, 1fr) 38px 34px 54px; }
/* Kisi papan TURNAMEN ditulis di css/turnamen.css, bukan di sini: berkas itu
   dimuat BELAKANGAN dan sudah memegang aturan berkekhususan sama, jadi apa pun
   yang ditulis di sini untuk `.tur-tabel` kalah tanpa suara. Terukur: kepala
   kolom menerima enam nama sementara kisinya masih lima lajur, dan nama
   keenam turun ke baris kedua. */
.hasil-baris {
  font-size: var(--tabel-fs);
  font-weight: 900;
  color: #10141c;
}
/* Setiap sel mengambil ukuran dan warna dari barisnya. Ditulis sebagai daftar
   kelas, bukan `*`: keping bendera/TOTAL dan keping hadiah punya warnanya
   sendiri yang memang harus menang, dan `*` akan menimpanya juga. */
.hasil-baris .rank,
.hasil-baris .nm,
.hasil-baris .us,
.hasil-baris .bbk,
.hasil-baris .slmt,
.tur-tabel .bbk,
.tur-tabel .slmt,
.hasil-baris b {
  font-size: var(--tabel-fs);
  font-weight: 900;
  color: #10141c;
}
/* NO dan ALIVE DI TENGAH KOLOMNYA, begitu pula WARBAND dan USER. Yang lama
   memaku NO rata kanan di baris DAN di kepala kolomnya; rata kanan itu benar
   waktu kolomnya selebar angkanya, dan salah begitu kolomnya 18 px berisi satu
   digit. */
.hasil-baris .rank,
.hasil-kepala span:first-child { text-align: center; }
.hasil-baris .wb { justify-content: center; }
.hasil-kepala .wb { text-align: center; }
.hasil-baris .nm,
.hasil-baris .us {
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
/* Baris pemain: SATU-SATUNYA baris berwarna di seluruh papan (§57.44.4).
   Biru muda, bukan hijau — hijau sudah berarti "menang" di seluruh permainan
   ini, dan baris ini harus terbaca sama saja di panel menang maupun kalah. */
.hasil-baris.kamu { background: #cfe0fb; }
.hasil-baris.kamu .nm,
.hasil-baris.kamu .us { color: #123a72; }
/* Warna juara/logam sudah tidak pernah ditulis JS lagi. Dinetralkan di sini,
   bukan cuma dihapus dari sumbernya, supaya baris `kamu` yang kebetulan juga
   juara tidak bisa dimenangkan aturan lama yang berkekhususan sama. */
.hasil-baris.juara { background: transparent; }
.hasil-baris.kamu.juara { background: #cfe0fb; }
/* Kepala kolom tetap lebih kecil dari isinya — ia nama kolom, bukan isi — tapi
   ikut naik bersama `--tabel-fs` alih-alih dipatok 9,5 px. */
.hasil-kepala {
  font-size: calc(var(--tabel-fs) * 0.78);
  font-weight: 900;
  color: #3d4658;
}
/* Kalimat di bawah judul: HITAM, bukan kelabu #5b667e. Ia satu-satunya kalimat
   di panel dan ia menerangkan apa yang baru saja terjadi. Panel turnamen
   berlatar GELAP, jadi di sana "yang paling terbaca" justru yang paling
   terang — aturan yang sama diterapkan ke dua ground yang berbeda. */
.hasil-sebab { color: #10141c; font-weight: 800; }
.hasil-kotak .hasil-sebab { font-size: clamp(12px, 2.4vh, 15px); }
/* §57.63 — JUDUL DIKECILKAN, diminta langsung ("tulisan di headingsnya
   terlalu besar"). Terukur di 1280x720 sebelum diperbaiki: "BATTLE COMPLETE"
   pada 52 px memakan kotak 386x126 px di dalam panel setinggi 336 px — 37%
   seluruh panel dihabiskan judul, sementara papan peringkat yang memuat
   seluruh hasil pertandingan berbagi sisanya dengan tiga tombol.

   Angka barunya tetap membuat judul jelas yang terbesar di panel (kalimat di
   bawahnya 15 px, tabelnya ±13 px), cuma berhenti mendominasi. Batas
   bawahnya ikut turun supaya layar pendek tidak justru mengecilkannya lebih
   sedikit daripada layar tinggi. */
.hasil-judul { font-size: clamp(24px, 6vh, 36px); }
/* SATU ukuran huruf untuk seluruh tombol di kaki kedua panel, dan ukuran itu
   sama dengan ukuran huruf tabelnya. Sebelumnya `.tbl` 13 px sementara panel
   turnamen menyetelnya lagi di tempat lain — dua tombol bersebelahan dengan
   huruf berbeda besar terbaca sebagai dua tingkat kepentingan yang tidak
   pernah dimaksudkan ada. */
.hasil-nav .tbl,
.tur-nav .tbl {
  font-size: var(--tabel-fs);
  font-weight: 900;
}
.hasil-nav .tbl b,
.tur-nav .tbl b { font-size: inherit; font-weight: inherit; }

/* ---- 57.44.5  TOMBOL UKURAN TURNAMEN sebaris, satu ukuran huruf -------- */
.pilih-tab.tiga .tab {
  flex-direction: row;
  gap: 0;
  white-space: nowrap;
  font-size: clamp(8.5px, 1.6vh, 11.5px);
  font-weight: 900;
  letter-spacing: 0.2px;
  font-variant-numeric: tabular-nums;
  padding-inline: 2px;
}

/* ---- 57.44.6  LAMBANG HARGA DI DALAM KURUNG --------------------------
   Tombol berharga (`.tbl-besar.harga`, `.tbl-besar.buka`, tombol status panel
   koleksi) semuanya `inline-flex` dengan `gap`. Tanpa pembungkus, "UNLOCK (",
   lambang intan, dan "300)" adalah TIGA anak flex — dan gap-nya menyisipkan
   8 px di antara tanda kurung dan isinya, jadi yang terbaca "UNLOCK ( 300 )".
   Persis kebalikan dari apa yang dikerjakan kurung. */
.hrg {
  display: inline-flex;
  align-items: center;
  gap: 0.14em;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ---- 57.44.7  DIALOG DI ATAS PANEL, bukan di bawahnya ------------------
   CACAT SUNGGUHAN, ditemukan lewat pengukuran dan bukan lewat pembacaan.

   `#buka` (dialog beli) adalah `.tirai` biasa: `z-index: 5`. Panel Warlords /
   Map Arenas / Custom Player memakai `.koleksi-tirai`: `z-index: 50`. Jadi
   setiap dialog beli yang dibuka DARI salah satu panel itu terbit DI
   BELAKANGNYA — tombol CANCEL dan UNLOCK-nya tidak bisa disentuh sama sekali.

   Terukur: klik tetikus sungguhan pada titik tengah tombol CANCEL tidak
   mengubah apa pun (`#buka` tetap terbuka); yang menerima ketukan itu
   `#koleksi` yang menutupinya. Satu-satunya jalan keluar pemain adalah tombol
   silang panelnya — dan begitu panel itu hilang, dialog yang sejak tadi
   bersembunyi di belakangnya muncul. Itulah "panel konfirmasi muncul setelah
   klik tombol silang": ia tidak muncul, ia TERUNGKAP.

   Dialog keputusan karena itu diberi lapisan sendiri di atas segalanya di
   dalam `#menu`. Ditulis sebagai satu daftar, bukan angka yang ditaburkan
   satu per satu, supaya urutan lapisannya bisa dibaca sebagai urutan. */
#buka,
#harian { z-index: 56; }

/* ---- 57.44.7b  DIALOG KEPUTUSAN: satu bentuk untuk ketiganya ----------
   `#buka` (beli), `#tanya` (menyerah/keluar), dan `#harian` (hadiah harian)
   dulu bertiga punya lebar, ukuran judul, dan ukuran tombol yang berbeda-beda
   — tiga dialog yang menghentikan permainan untuk satu keputusan, dengan tiga
   perawakan. Sekarang ketiganya mengambil angka dari satu tempat. */
.beli-kotak,
.harian-kotak,
#tanya .kotak {
  width: min(340px, 92vw);
  gap: clamp(9px, 1.8vh, 14px);
  padding: clamp(15px, 3vh, 22px);
}
.beli-kotak .kotak-judul,
.harian-kotak .kotak-judul,
#tanya .kotak-judul {
  font-size: clamp(15px, 2.9vh, 19px);
  font-weight: 900;
  letter-spacing: 0.4px;
  text-align: center;
}
/* Baris tombol: DUA tombol yang SELALU sama lebar dan sama tinggi. Sebelumnya
   keduanya selebar labelnya masing-masing, jadi "CANCEL" berdiri jauh lebih
   sempit daripada "UNLOCK" dan pasangan yang seharusnya setara terbaca sebagai
   satu tombol utama plus satu tempelan. */
.beli-kotak .kotak-baris,
.harian-kotak .kotak-baris,
#tanya .kotak-baris {
  display: flex;
  gap: clamp(7px, 1.4vw, 11px);
}
.beli-kotak .kotak-baris .tbl,
.harian-kotak .kotak-baris .tbl,
#tanya .kotak-baris .tbl {
  flex: 1 1 0;
  min-width: 0;
  padding: clamp(10px, 2vh, 14px) 10px;
  font-size: clamp(12px, 2.2vh, 14px);
  font-weight: 900;
  letter-spacing: 0.8px;
}
/* Kotak harga: baris label kelabu di kiri, angka tinta di kanan, dengan garis
   rambut di antaranya. Garis itu yang menyatakan bahwa baris kedua adalah
   AKIBAT dari baris pertama, bukan angka kedua yang sederajat. */
.beli-harga { gap: 0; }
.beli-baris { padding: clamp(5px, 1vh, 8px) 0; }
.beli-baris + .beli-baris { border-top: 2px solid #d6dcea; }
.beli-baris span {
  font-size: clamp(9px, 1.7vh, 11px);
  font-weight: 900;
  letter-spacing: 1px;
}
.beli-baris b { font-size: clamp(13px, 2.4vh, 16px); }
.beli-baris.utama b { font-size: clamp(18px, 3.4vh, 24px); }

/* Hadiah harian: tiga tingkat yang jelas — judul, keterangan hari, lalu angka
   besar. Ukurannya diturunkan dari 26-38 px ke 24-32 px supaya ia tidak lebih
   besar daripada judul panelnya sendiri, dan tulisan hari dinaikkan supaya ia
   tidak jadi tulisan terkecil di panel yang isinya cuma tiga baris. */
.harian-hari { font-size: clamp(10px, 1.8vh, 12px); letter-spacing: 1.4px; }
.harian-upah { gap: clamp(6px, 1.2vw, 10px); }
.harian-upah b { font-size: clamp(24px, 4.6vh, 32px); }
.harian-upah .ik-intan { width: 1.05em; height: 1.05em; }

/* §57.60: JUDULNYA DIKAPITALKAN dan diberi jarak huruf, menyamakannya
   dengan judul layar dan tombol di seluruh permainan ini — "Daily Reward"
   berhuruf kecil adalah satu-satunya judul berkapitalisasi kalimat di
   antara dialog-dialog yang semuanya berkapital. Ukurannya ikut naik
   sedikit supaya jarak ke tombol CLAIM (14 px) terbaca sebagai tingkatan,
   bukan sebagai dua tulisan yang kebetulan beda 5 px. */
.harian-kotak .kotak-judul {
  font-size: clamp(16px, 3.1vh, 21px);
  letter-spacing: 1.6px;
  text-transform: uppercase;
}

/* §57.60: sisipan panel dirapatkan sedikit dan jaraknya dibuat TIDAK SAMA
   RATA. Ketiga isi panel dulu berjarak seragam, jadi tidak ada yang
   terbaca sebagai kelompok; sekarang keping hari menempel ke blok hadiah
   di bawahnya (keduanya menjawab "dapat apa hari ini") sementara tombol
   berdiri terpisah sebagai tindakan. */
.harian-kotak { gap: clamp(7px, 1.4vh, 11px); }
.harian-kotak .harian-hari { margin-bottom: clamp(-3px, -0.5vh, -1px); }
.harian-kotak .kotak-baris { margin-top: clamp(2px, 0.6vh, 5px); }

/* ---- 57.44.8  TOMBOL STATUS panel koleksi ----------------------------
   Tiga keadaan, tiga warna, satu bentuk. Warnanya sengaja dipinjam dari
   tempat yang sudah memakainya: kuning = "ini pilihanmu" (kartu komidi
   aktif, keping intan), putih bergaris = "bisa dipakai", hijau = ajakan
   bertindak (tombol berangkat, tombol CLAIM). */
.koleksi-aksi {
  width: 100%;
  padding: clamp(7px, 1.5vh, 11px) clamp(8px, 1.6vw, 13px);
  border: 3px solid var(--garis);
  border-radius: clamp(8px, 1.6vh, 12px);
  /* §57.64: 12 px -> 14 px di batas atas, diminta langsung. Tombol ini memuat
     satu-satunya angka di panel yang menentukan keputusan (harga UNLOCK), dan
     pada 12 px ia tulisan terkecil di kotak — di bawah nama gaya di petak
     tepat di atasnya. Sisipan tegaknya sengaja TIDAK ikut naik: tingginya
     sudah pas terhadap petak di atasnya, dan menaikkan keduanya sekaligus
     akan mendorong baris ketiga kisi keluar dari panel yang tingginya baru
     saja dipatok `--panel-h`. */
  font-size: clamp(10.5px, 1.95vh, 14px);
  font-weight: 900;
  letter-spacing: 0.8px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35em;
  cursor: pointer;
  transition: transform 0.08s, filter 0.12s;
}
.koleksi-aksi[hidden] { display: none; }
.koleksi-aksi.pilih { background: var(--kuning); color: var(--garis); cursor: default; }
.koleksi-aksi.ada { background: #eef1f6; color: #1b2030; }
.koleksi-aksi.kunci { background: var(--hijau); color: #06301a; }
.koleksi-aksi.segera { background: #c3cbdb; color: #4a5468; cursor: default; }
.koleksi-aksi:not(:disabled):hover { filter: brightness(1.07); }
.koleksi-aksi:not(:disabled):active { transform: translateY(2px); }
.koleksi-kiri { gap: clamp(5px, 1vh, 9px); }

/* EMPAT petak sebaris (§57.44.8), bukan tiga. */
.koleksi-petak.baris.empat { --celah: clamp(4px, 0.8vw, 8px); gap: var(--celah); }
.koleksi-petak.baris.empat .koleksi-sel {
  flex: 0 0 calc((100% - var(--celah) * 3) / 4);
  min-width: 0;
}

/* ---- 57.44.9  PETAK CUSTOM PLAYER: gambar + tombol status -------------
   Petaknya sekarang PEMBUNGKUS berisi dua tombol, bukan satu tombol. Yang di
   atas cuma memperlihatkan, yang di bawah memutuskan — pemisahan yang sama
   dengan panel koleksi, dan dengan sebab yang sama: satu ketukan yang
   sekaligus membuka dialog pembayaran tidak pernah memberi pemain kesempatan
   melihat apa yang sedang ia pertimbangkan. */
.rupa-petak {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.rupa-petak .rupa-sel { flex: 1 1 auto; width: 100%; }
.rupa-petak.terpilih .rupa-sel { background: var(--kuning); }
.rupa-petak.terkunci .rupa-sel { opacity: 0.5; }
.rupa-petak.disorot .rupa-sel { box-shadow: 0 0 0 3px #ffd98a inset; }
.rupa-aksi {
  width: 100%;
  padding: clamp(4px, 0.9vh, 7px) 3px;
  border: 2.5px solid var(--garis);
  border-radius: clamp(6px, 1.2vh, 9px);
  /* §57.65 — angka di sini SENGAJA dibiarkan pada nilai lamanya, dan itu
     bukan kelalaian: aturan `.rupa-aksi` KEDUA (§57.44.22, jauh di bawah)
     berkekhususan sama dan ditulis belakangan, jadi ia yang menang untuk
     `font-size`. Kenaikan yang diminta §57.65 dipasang DI SANA.

     Ditulis di sini supaya pembaca berikutnya tidak mengulang percobaan yang
     sudah gagal sekali: menaikkan angka di blok ini tidak mengubah satu
     piksel pun di layar — terukur, tetap 7,6 px sesudah blok ini sempat
     dinaikkan ke 13 px. */
  font-size: clamp(7.5px, 1.35vh, 10px);
  font-weight: 900;
  letter-spacing: 0.4px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.3em;
  white-space: nowrap;
  cursor: pointer;
}
.rupa-aksi.pilih { background: var(--kuning); color: var(--garis); cursor: default; }
.rupa-aksi.ada { background: #eef1f6; color: #1b2030; }
.rupa-aksi.kunci { background: var(--hijau); color: #06301a; }
.rupa-aksi:not(:disabled):active { transform: translateY(1px); }
.rupa-aksi .ik-intan { width: 1.1em; height: 1.1em; }

/* ---- 57.44.12  BASE PLAYER: dua kolom didorong ke tepi ----------------
   `.layar` dibatasi 980 px lalu dipusatkan, jadi "tepi kiri" bagi kedua kolom
   ini sebenarnya tepi KOLOM — terukur di 1280x720: x=190 dan x=1090, sembilan
   puluh piksel di dalam tepi jendela pada tiap sisi. Diminta agar keduanya
   digeser keluar.

   Angka geserannya DIHITUNG, bukan dipatok: ia persis sisa ruang yang memang
   ada di luar kolom 980 px, dijepit maksimum 90 px. Di layar yang lebih
   sempit dari 980 px sisa itu negatif dan `clamp` mengembalikannya ke nol —
   jadi aturan ini mustahil mendorong kolom keluar dari jendela. */
#layar-base .base-isi { --base-lepas: clamp(0px, calc((100vw - 980px) / 2), 90px); }
#layar-base .base-kiri { left: calc(-1 * var(--base-lepas)); }
#layar-base .base-kanan { right: calc(-1 * var(--base-lepas)); }
/* Model tetap di TENGAH di antara keduanya: rumusnya cuma bergantung pada
   selisih lebar kedua kolom, dan geseran di atas menambah jarak yang SAMA di
   kedua sisi. */

/* QUICK GAME memanjang mengisi sisa baris kaki, tulisannya tetap di tengah.
   `flex: 0 0 auto` yang lama membuatnya selebar labelnya sendiri, jadi ia
   berhenti jauh sebelum tepi kartu di atasnya dan barisnya terlihat separuh
   kosong. */
.base-kaki .base-main {
  flex: 1 1 auto;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  white-space: nowrap;
}

/* KARTU STATISTIK, susunan §57.44.12 */
.base-baris.nama { gap: clamp(5px, 1vw, 9px); }
/* Nama rata KIRI sekarang, dan pensilnya didorong ke tepi kanan oleh
   `margin-left: auto` — bukan oleh kolom ketiga yang lebarnya harus ditebak. */
.base-baris.nama .base-nama-teks,
.base-baris.nama input { text-align: left; }
.base-baris.nama .base-nama-teks { font-size: clamp(12px, 2.2vh, 15.5px); }
.base-baris.nama .base-edit { margin-left: auto; }
/* Baris lencana: lambang, bar, angka. Bar-nya bentuk yang SAMA PERSIS dengan
   bar runtun di atasnya (`.profil-bar`) — dua ukuran kemajuan di satu kartu
   yang digambar dengan dua bentuk berbeda memaksa pemain membaca keduanya
   dua kali. */
.lencana-bar {
  flex: 1 1 auto;
  min-width: 0;
  height: clamp(7px, 1.3vh, 10px);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
  overflow: hidden;
}
.lencana-bar i { display: block; height: 100%; background: var(--lencana, #c87f3a); }
.lencana-angka {
  flex-shrink: 0;
  font-size: clamp(9.5px, 1.7vh, 12px);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  color: #cfd8ea;
}

/* ---- 57.44.14  BILAH PEMUAT lebih tebal -------------------------------
   Terukur 10 px pada layar 720 px — segaris tipis di bawah judul setinggi
   40-an px, dan pada HP mendatar ia turun ke 8 px. Dinaikkan ke 16-24 px dan
   dilebarkan, dengan isian yang punya kilau sendiri: bilah pemuat adalah satu-
   satunya benda yang bergerak di layar itu, jadi ia harus cukup besar untuk
   terlihat bergerak. */
.muat-bilah {
  width: min(72vw, 420px);
  height: clamp(16px, 3vh, 24px);
  border-width: 3px;
  border-radius: 999px;
}
#muat-isi { border-radius: 999px; }
#muat .muat-teks { font-size: clamp(12px, 2.2vh, 16px); font-weight: 900; }

/* ---- 57.44.19  BARIS RINGKAS di kiri tombol STATS ---------------------
   Diminta dirapikan, dan yang perlu dirapikan bisa disebut satu per satu:
   panji setinggi 17 px, keping angka setinggi ±16 px yang ditentukan sisipan
   3 px-nya sendiri, dan keping sikap setinggi ±14 px berhuruf 0,85em. Empat
   benda berjajar di dalam kotak setinggi 38 px, tidak satu pun setinggi
   tetangganya, masing-masing duduk pada garis dasar yang berbeda.

   Disamakan lewat SATU tinggi (`--keping`) yang dipegang keempatnya, dan
   ukuran huruf yang sama untuk ketiga keping teks. Sikap tetap dibedakan —
   bergaris tepi tanpa isian, sesuai §57.42.4 — cuma tidak lagi lewat ukuran. */
.skor-ringkas { --keping: 22px; gap: clamp(6px, 1.1vw, 9px); }
.skor-ringkas .ku-panji { width: 30px; height: var(--keping); }
.skor-ringkas .ku-bd,
.skor-ringkas .ku-jm,
.skor-ringkas .ku-sikap {
  height: var(--keping);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 7px;
  font-size: 12px;
  line-height: 1;
}
/* "FALL BACK" adalah label terpanjang di antara empat sikap; lebarnya dipatok
   ke sana supaya baris ini tidak melebar-menyempit tiap kali sikapnya berganti
   dan menyeret tombol STATS ikut melompat. */
.skor-ringkas .ku-sikap { min-width: 6.1em; font-size: 11px; }
.skor-ringkas .ku-nama { font-size: 12.5px; }

/* ---- 57.44.20  LAYAR TUTORIAL ----------------------------------------
   Satu kartu melayang di tepi bawah-tengah, di atas HUD pertandingan yang
   sedang berjalan. BUKAN `.tirai`: tirai membekukan permainan, dan seluruh
   gagasan tutorial ini adalah pemain benar-benar menekan tombolnya sendiri
   sambil membaca. */
#ajar {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(clamp(74px, 15vh, 122px) + env(safe-area-inset-bottom));
  z-index: 6;
  width: min(460px, 88vw);
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 1.2vh, 10px);
  padding: clamp(10px, 2vh, 16px) clamp(12px, 2.4vw, 18px);
  border: 3px solid var(--garis);
  border-radius: clamp(12px, 2.2vh, 17px);
  background: rgba(20, 26, 40, 0.93);
  color: #fff;
  pointer-events: auto;
  text-align: center;
}
#ajar[hidden] { display: none; }
.ajar-kepala {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(6px, 1.2vw, 10px);
}
.ajar-langkah {
  flex-shrink: 0;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--kuning);
  color: #221800;
  font-size: clamp(9px, 1.6vh, 11px);
  font-weight: 900;
  letter-spacing: 0.8px;
  font-variant-numeric: tabular-nums;
}
.ajar-judul {
  font-size: clamp(13px, 2.5vh, 17px);
  font-weight: 900;
  letter-spacing: 0.8px;
  color: var(--kuning);
}
.ajar-teks {
  font-size: clamp(11px, 2vh, 14px);
  font-weight: 700;
  line-height: 1.45;
  color: #dbe3f2;
  text-wrap: balance;
}
.ajar-teks b { color: #fff; }
.ajar-teks kbd {
  display: inline-block;
  padding: 1px 5px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.1);
  font: inherit;
  font-size: 0.9em;
  font-weight: 900;
}
/* §57.53: gaya `.ajar-kaki`, `.ajar-bar`, dan `.ajar-tbl` DICABUT bersama
   markahnya. Kartunya sekarang cuma dua baris bacaan — kepala dan teks.

   Ini sekaligus mencabut satu bug yang sedang diperbaiki waktu
   permintaannya datang: `#stik-zona` (daerah tangkap jari selebar 44%
   layar, tak terlihat, `pointer-events: auto`) menimbun tombol SKIP di
   mode sentuh — terukur lewat `elementFromPoint`, yang mengembalikan
   `#stik-zona` alih-alih tombolnya. Kartu tanpa tombol tidak bisa punya
   tombol yang tertimbun, dan ia justru TIDAK BOLEH menangkap jari: ia
   berdiri di bagian atas layar tempat kamera diseret. */
/* Langkah yang SUDAH tuntas: kartunya berkedip hijau sekali, lalu langkah
   berikutnya menggantikannya. Satu kedipan, bukan animasi berulang — yang
   perlu dikatakan cuma "yang barusan itu benar". */
#ajar.lulus { border-color: var(--hijau); }

/* Sorotan pada tombol yang sedang diajarkan. Cincin berdenyut di LUAR tombol,
   bukan warna latar di dalamnya: tombol perintah sudah memakai warna latarnya
   sendiri untuk menyatakan aktif/tidak, dan menimpanya berarti tutorial
   berbohong tentang keadaan tombol yang sedang ia tunjuk. */
/* `border-radius: inherit` DICABUT di sini, bukan ditimpa di §57.45.4 — lihat
   catatan lengkapnya di sana. Ia satu-satunya sebab tombol bulat berubah jadi
   persegi selama disorot, dan menimpanya dari bawah cuma memindahkan
   pertanyaannya ("ditimpa dengan apa?") tanpa menjawabnya. */
.ajar-sorot {
  animation: ajar-denyut 1.15s ease-in-out infinite;
}
@keyframes ajar-denyut {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 210, 63, 0.85); }
  50% { box-shadow: 0 0 0 7px rgba(255, 210, 63, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .ajar-sorot { animation: none; box-shadow: 0 0 0 4px rgba(255, 210, 63, 0.85); }
}
/* §57.51: STIK dikelilingi LINGKARAN BERCAHAYA, bukan penanda kotak.
   Diminta langsung.

   Dua hal harus benar sekaligus, dan yang pertama ada di js/ajar.js: yang
   disorot `#stik-alas` (alas bulat stiknya) bukan `#stik-zona`, yang cuma
   daerah tangkap jari selebar 44% layar. Yang kedua di sini — `box-shadow`
   mengikuti `border-radius` elemennya, dan alas stik memang sudah bulat,
   jadi cincinnya bulat dengan sendirinya. Yang ditambahkan cuma CAHAYAnya:
   `box-shadow` kedua tanpa sebaran nol yang meleleh keluar cincin, supaya
   ia benar-benar terbaca menyala dan bukan sekadar bergaris tebal. */
#stik-alas.ajar-sorot {
  animation: ajar-pijar 1.15s ease-in-out infinite;
}
@keyframes ajar-pijar {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(255, 210, 63, 0.9), 0 0 14px 4px rgba(255, 210, 63, 0.55);
  }
  50% {
    box-shadow: 0 0 0 10px rgba(255, 210, 63, 0), 0 0 26px 10px rgba(255, 210, 63, 0.28);
  }
}
@media (prefers-reduced-motion: reduce) {
  #stik-alas.ajar-sorot {
    animation: none;
    box-shadow: 0 0 0 4px rgba(255, 210, 63, 0.85), 0 0 18px 6px rgba(255, 210, 63, 0.45);
  }
}

/* ---- 57.44.21  BARIS KOMANDO DESKTOP benar-benar bisa DITEKAN -----------
   Cacat lama, ditemukan waktu menguji tutorial. `#hud` seluruhnya
   `pointer-events: none` supaya seretan kamera tembus ke kanvas, dan tiap
   panel yang memang harus menangkap jari menyalakannya kembali sendiri —
   `.panel-aksi` (TEBAS/LEMPAR), `.panel-setel`, `.skor-atas`, `.bulat`.
   `.panel-komando` TIDAK, padahal keenam tombolnya masing-masing punya
   penangan `pointerdown` yang dipasang js/main.js dan `cursor: pointer` di
   wajahnya.

   Akibatnya di desktop: enam tombol yang terlihat seperti tombol, berperilaku
   seperti tombol waktu disorot, dan tidak melakukan apa-apa waktu ditekan.
   Satu-satunya jalan memerintah barisan di desktop adalah angka 1-7 di papan
   ketik — yang memang tertulis di tiap tombol, tapi tidak seorang pun membaca
   `<kbd>` sebelum mencoba menekan benda di sebelahnya lebih dulu. */
.panel-komando { pointer-events: auto; }

/* ---- 57.44.22  TOMBOL STATUS PETAK KECIL muat di petaknya ---------------
   Terukur: "UNLOCK (\u2666 90)" pada 10 px meminta ±86 px sementara petaknya 77 px,
   jadi enam dari enam tombol memotong labelnya jadi "NLOCK ( 90". Diperkecil
   sampai muat, dan lambang intannya ikut mengecil bersamanya — bukan dipatok
   piksel, supaya keduanya tetap sepadan berapa pun `vh`-nya. */
/* §57.65 — DINAIKKAN LAGI (7,6 -> 12 px), diminta langsung: tulisan di tombol
   dan kotak panel Custom Player "terlalu kecil".

   Aturan INI yang harus diubah, bukan `.rupa-aksi` di §57.44.9 jauh di atas:
   keduanya berkekhususan sama persis (0,1,0) dan yang ini ditulis BELAKANGAN,
   jadi ia yang menang. Menaikkan angka di atas saja tidak mengubah satu piksel
   pun — terukur: tetap 7,6 px sesudah aturan atas dinaikkan ke 13 px.
   Perangkap yang sama dengan `body.hp .tbl` dan `.kustom-kaki .tur-status`,
   dengan satu beda: di sini yang menentukan URUTAN, bukan kekhususan.

   Angka 7,6 px punya alasan yang sah waktu ditulis (§57.44.22): "UNLOCK ◇90"
   pada 10 px menuntut ±86 px sementara petaknya cuma 77 px. Yang membuatnya
   bisa dicabut sekarang bukan pengabaian alasan itu melainkan PENGHAPUSAN
   sebabnya — petaknya DILEBARKAN lebih dulu (lihat `.rupa-wadah` di bawah),
   jadi label terpanjang muat pada huruf yang jauh lebih besar. Kedua
   perubahan itu satu paket; melepas salah satunya mengembalikan label yang
   terpotong jadi "NLOCK ( 90".

   Angka 12 px, bukan 13 px seperti nama gaya di atasnya: labelnya SATU KATA
   lebih panjang ("UNLOCK ◇90" lawan "Common") dan membawa lambang intan
   selebar 1em. Terukur pada petak barunya, bukan dikira-kira. */
.rupa-aksi {
  font-size: clamp(7.5px, 1.65vh, 12px);
  letter-spacing: 0;
  padding-inline: 2px;
}
.rupa-aksi .ik-intan { width: 1em; height: 1em; }

/* §57.65 — DUA KOLOM di panel selebar ini, bukan tiga. Pasangan wajib dari
   kenaikan huruf di atas.

   Yang menyesatkan waktu ini dilacak: kisinya SUDAH tiga kolom di aturan
   dasar (§57.43.13), jadi "turunkan jumlah kolom" terdengar seperti sudah
   dikerjakan. Yang menentukan lebar petak ternyata bukan jumlah kolomnya
   melainkan lebar KOLOM KANAN yang memuat kisi itu — terukur 68,6 px per
   petak, dan "UNLOCK ◇90" pada 12 px menuntut 84 px (luber +15,4 px, diukur
   langsung terhadap label terpanjang, bukan terhadap "Selected" yang
   kebetulan pendek).

   `auto-fill` dengan lantai 92 px, bukan angka kolom tetap: panel ini berdiri
   pada lebar yang berbeda-beda (tirai 660 px di desktop, jauh lebih sempit di
   HP mendatar), dan lantai lebar petak menyatakan syarat yang sebenarnya —
   "petak tidak boleh lebih sempit dari labelnya" — sementara angka kolom
   tetap cuma kebetulan menghasilkan itu pada satu lebar layar. Jumlah
   kolomnya lalu mengikuti sendiri: tiga di panel lebar, dua waktu sempit. */
.rupa-wadah { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }

/* ---- 57.44.23  PAPAN DUA LAJUR: nama bangsa harus muat ------------------
   Terukur di 1280x720 dengan lima peserta: lajur WARBAND jadi 69,75 px, dan
   pada 15 px tebal "Frankish" memerlukan ±70 px SEBELUM panji dan celahnya —
   jadi "Fran…", "Rom…", "Yam…". Nama bangsa yang terpotong di papan hasil
   membuang satu-satunya kabar yang tidak bisa dibaca dari kolom mana pun lain.

   Dibereskan di dua sisi sekaligus, karena satu sisi saja tidak cukup: kartunya
   dilebarkan 100 px (ruang itu MEMANG ada — kartu dua lajur berdiri di layar
   yang sudah dipastikan >= 560 px oleh `PAPAN_LEBAR_MIN`), dan huruf tabelnya
   diturunkan satu tingkat KHUSUS di susunan dua lajur. Satu lajur tidak
   tersentuh: di sana ruangnya berlimpah dan hurufnya memang harus sebesar
   tulisan tombol. */
.kotak.lebar.hasil-kotak.banyak { width: min(860px, 96vw); }
.hasil-kotak.banyak { --tabel-fs: clamp(11px, 2.1vh, 13.5px); }
.hasil-kotak.banyak .hasil-baris .wb img { width: 15px; height: 20px; }
.hasil-kotak.banyak .hasil-baris .wb { gap: 5px; }

/* ---- 57.44.24  JARAK ANTAR-PARAGRAF di kotak keterangan -----------------
   Paragraf arena dan sejarah bangsa sekarang lebih dari satu (§57.44.10,
   §57.44.11), dan `* { margin: 0 }` di kepala berkas ini berarti keduanya
   menempel tanpa satu piksel pun di antaranya — yang terbaca satu blok teks
   panjang yang kebetulan berganti baris, bukan dua paragraf. */
.ket-isi + .ket-isi { margin-top: 0.55em; }

/* ======================================================================== */
/* 57.45  PUTARAN RAPI-RAPI KEDUA                                           */
/* ======================================================================== */

/* ---- 57.45.1  KEPING BAHASA DAN IKLAN DIPENDEKKAN ----------------------
   Terukur sebelum disetel: keduanya 92,0 px, yaitu batas atas
   `clamp(66px, 12vw, 92px)` yang dipasang §57.44.1. Angka itu dipilih dulu
   untuk MENYAMAKAN lebar keduanya, dan ia berhasil — tapi ia menyamakannya
   pada lebar yang lebih besar daripada isi mana pun di dalamnya, sehingga
   dua tombol yang isinya cuma ikon dan dua huruf berakhir selebar keping
   intan berangka empat digit di sebelahnya.

   Patokannya diturunkan sampai menempel pada isinya sendiri, BUKAN dilepas.
   Melepas `min-width` memang memendekkan keduanya, tapi ia juga membuat
   lebarnya kembali ditentukan lebar tulisan masing-masing — dan "EN" lebih
   sempit daripada "AD" pada huruf yang sama, jadi keduanya akan berbeda lagi
   persis seperti sebelum §57.44.1.

   IKONNYA IKUT DIKECILKAN, dan itu syarat bukan hiasan. Percobaan pertama cuma
   menurunkan `min-width` jadi 76 px, dan hasilnya terukur: keping bahasa
   menurut jadi 76 px sementara keping iklan berhenti di 85,8 px. Sebabnya ikon
   iklan berbanding 16:9 — pada tinggi 26 px ia selebar 38,5 px, jadi isi keping
   iklan sendiri sudah lebih lebar daripada patokan barunya dan patokan itu
   berhenti berlaku untuknya. Dua keping yang §57.44.1 susah payah samakan
   berpisah lagi.

   `--pojok-ikon` karena itu diturunkan dari 20-26 px jadi 16-20 px. Ketiga
   ikon tetap SETINGGI SATU SAMA LAIN — itu yang diminta §57.44.1 dan itu tidak
   dibatalkan — cuma ketiganya sama-sama lebih pendek, dan ikon iklan yang ikut
   menyusut membawa isi kepingnya turun jadi 79 px.

   Patokan bersamanya lalu dipatok TEPAT di angka itu, bukan di bawahnya:
   keping iklan adalah yang isinya paling lebar dari keduanya, jadi patokan
   yang lebih rendah darinya cuma berlaku untuk keping bahasa dan keduanya
   berpisah lagi. Terukur sesudah disetel: 79,0 px dan 79,0 px, selisih nol,
   turun dari 92 px. */
#sudut-atas { --pojok-ikon: clamp(16px, 2.8vh, 20px); }
#bahasa-sudut,
#musik-sudut,
#ads-sudut {
  min-width: clamp(58px, 7.4vw, 79px);
  padding-left: clamp(5px, 0.8vw, 8px);
  padding-right: clamp(5px, 0.8vw, 8px);
}

/* ---- 57.45.2  TOMBOL STATS BUKAN LEMPENGAN BERSUDUT TAJAM --------------
   Terukur: `border-radius: 0px` pada tombol setinggi 32 px yang `align-self:
   stretch` di dalam baris setinggi 32 px. Artinya keempat sudutnya menempel
   pada tepi dalam kotak induknya — dan walau `overflow: hidden` induknya
   membulatkan dua sudut KANAN, dua sudut KIRI-nya tetap siku betulan di
   tengah baris.

   §57.43.6 memilih bentuk itu dengan sengaja ("keping terakhir yang dipotong
   dari baris"), dan gagasannya masih benar — yang keliru pelaksanaannya:
   sebuah lempengan yang tingginya persis setinggi baris tidak terbaca sebagai
   keping, ia terbaca sebagai baris yang ujungnya dicat lain. Ketiga keping
   tetangganya (bendera, jumlah, sikap) semuanya setinggi `--keping` dengan
   sudut membulat, jadi yang dikerjakan di sini cuma memasukkan STATS ke
   keluarga yang sudah ada di baris itu.

   Garis tegak pemisahnya DIBUANG bersama lempengannya. Ia dulu satu-satunya
   yang memisahkan tombol dari keping di sebelahnya; sekarang isian pejatnya
   sendiri yang mengerjakan itu, sama seperti keping sikap dibedakan oleh
   garis tepinya sendiri. */
.skor-ringkas .stats-tbl {
  align-self: center;
  height: calc(var(--keping) + 4px);
  margin-left: clamp(4px, 0.8vw, 7px);
  margin-right: clamp(6px, 1.1vw, 10px);
  border: 0;
  border-radius: 8px;
  padding: 0 clamp(8px, 1.5vw, 12px);
}

/* ---- 57.45.3  KARTU TUTORIAL PINDAH KE BAWAH "BATTLE TIME" -------------
   Letaknya sekarang ditentukan induknya (`#waktu-hud`, lihat index.html), jadi
   seluruh aturan melayang yang lama dicabut di sini: `position`, `left`,
   `bottom`, dan `transform`.

   `margin-inline: auto` dengan lebar tetap — bukan `align-items` pada
   induknya: `#waktu-hud` juga menampung angka jam dan label yang keduanya
   `display: block` dan sudah dipusatkan `text-align: center`, dan mengubah
   induknya jadi flex akan mengubah cara keduanya berdiri. */
#ajar {
  position: static;
  left: auto;
  bottom: auto;
  transform: none;
  margin: clamp(8px, 1.6vh, 14px) auto 0;
  /* 52vw, bukan 88vw. Di HP mendatar 892 px, 88vw berarti kartu selebar
     785 px yang membentang dari bawah peta kecil sampai bawah baris skor —
     dua panel yang justru harus tetap terbaca selama tutorial berjalan. */
  width: min(440px, 52vw);
  text-align: center;
}
/* §57.54: di layar SEMPIT kartunya menyusut supaya tidak menyentuh peta
   kecil dan tombol setelan di kiri-atas. Terukur di 640x360 dengan lebar
   52vw: tepi kiri kartu 153,6 px sementara tepi kanan tombol setelan
   162,4 px — bertumpuk 8,8 px, dan sekarang keduanya sebaris jadi
   tumpukannya benar-benar terlihat. Sebelum kartunya naik sejajar, ini
   tidak pernah muncul karena kartunya berdiri jauh di bawah keduanya. */
@media (max-width: 760px) and (orientation: landscape) {
  body.mengajar #ajar { width: min(360px, 44vw); }
}
/* TEGAK: lebarnya justru harus MELAR, bukan menyusut. Aturan `44vw` di atas
   ditulis untuk layar mendatar sempit, tempat peta kecil dan tombol setelan
   berdiri di kiri kartu; di layar tegak keduanya berada di ATAS kartu, jadi
   tidak ada yang perlu dihindari ke samping. Terukur di 412x892 tanpa
   pembatas orientasi: kartu menyusut jadi 181,3 px dan kalimat langkah
   pertama pecah jadi LIMA baris. */
@media (orientation: portrait) {
  body.mengajar #ajar { width: min(440px, 88vw); }
}
/* §57.54: PUNCAK KARTU SEJAJAR DENGAN PUNCAK TOMBOL PENGATURAN.
   Diminta langsung, dan itu lebih tepat daripada "di bagian atas layar":
   dua benda yang berdiri di pita atas layar tapi tidak sebaris terbaca
   sebagai dua lapisan yang tidak saling kenal.

   `position: absolute` dengan `top` yang DISALIN dari `.panel-sudut`,
   bukan margin negatif yang ditebak. Percobaan sebelumnya menarik kartu
   naik dengan margin negatif seukuran jam + labelnya — angka yang benar
   cuma selama ukuran jam tidak berubah, dan dua `clamp()` yang harus
   dijumlahkan tangan tiap kali salah satunya disetel.

   Sekarang tempatnya tidak lagi diturunkan dari tinggi benda di atasnya
   sama sekali: ia dipatok ke tepi layar, di angka yang sama persis dengan
   tombol yang harus ia sejajari. `left: 50%` + `translateX(-50%)` menjaga
   ia tetap di tengah mendatar.

   Yang dipindahkan INDUKNYA (`#waktu-hud`), bukan kartunya sendiri, dan
   itu perbaikan atas percobaan yang gagal: `position: fixed` pada kartu
   menghasilkan selisih tetap 8 px terhadap tombol setelan, karena induknya
   memakai `transform: translateX(-50%)` — dan elemen ber-`transform`
   menjadi containing block bagi keturunan `fixed`-nya, jadi `top` yang
   ditulis di kartu DITUMPUK di atas `top` induknya alih-alih menggantikan.

   Induknya sudah berada di tengah mendatar dan sudah dipatok ke tepi atas;
   yang perlu cuma menyamakan angka `top`-nya dengan `.panel-sudut`. Kartu
   sendiri kembali ke aliran biasa (`margin: 0`), dan karena jam serta
   labelnya `display: none` selama tutorial (lihat di bawah), ia jadi isi
   pertama induknya. */
body.mengajar #waktu-hud { top: 88px; }
body.mengajar.hp #waktu-hud { top: calc(8px + env(safe-area-inset-top)); }
body.mengajar #ajar { margin: 0; }
/* Jam dan labelnya `display: none` — BUKAN `visibility: hidden` seperti
   §57.51. Selama kartunya digantung di bawah keduanya, `visibility` memang
   pilihan yang benar (tempatnya tersisa, kartunya tidak melompat). Sekarang
   yang menentukan letak kartu adalah `top` induknya, dan tempat kosong dua
   baris tak terlihat justru mendorongnya turun 60 px dari tombol yang harus
   ia sejajari. */
body.mengajar #waktu,
body.mengajar #waktu-hud > span { display: none; }
/* §57.53: `pointer-events: none` — KEBALIKAN dari sebelumnya, dan itu
   berubah karena kartunya berubah. Dulu ia menyalakan penangkapan jari
   untuk dirinya sendiri supaya tombol SKIP di dalamnya bisa ditekan.
   Sesudah semua tombol dicabut, tidak ada lagi yang perlu ditekan di sini
   — dan kartu yang menangkap jari di BAGIAN ATAS LAYAR justru memakan
   seretan kamera, yaitu satu-satunya hal yang memang dilakukan orang di
   daerah itu.

   Sekarang ia benar-benar cuma bacaan: terlihat, tembus jari, dan tidak
   menghalangi apa pun di bawahnya. */
#ajar { pointer-events: none; }
/* Garis tepi hitam yang dipakai jam dan labelnya TIDAK boleh menetes ke dalam
   kartu — `text-shadow` diwariskan, dan huruf berbayang di atas kartu gelap
   pejal terbaca sebagai huruf yang kotor. */
#ajar, #ajar * { text-shadow: none; }

/* UKURAN DAN WARNA (§57.45.3). Sebelumnya judul 17 px kuning, teks 14 px
   #dbe3f2, nomor langkah 11 px — tiga tingkat yang selisihnya terlalu rapat
   untuk kartu selebar ini, dan warna teks yang cuma satu langkah dari putih
   sehingga bagian <b> yang seharusnya menonjol nyaris tidak terlihat
   bedanya. Dinaikkan sekaligus dijauhkan: judul lebih besar, badan teks
   lebih terang, dan yang <b> benar-benar putih. */
.ajar-judul { font-size: clamp(15px, 2.9vh, 20px); letter-spacing: 1px; }
.ajar-langkah { font-size: clamp(10px, 1.8vh, 12px); padding: 3px 9px; }
.ajar-teks {
  font-size: clamp(12px, 2.2vh, 15px);
  line-height: 1.5;
  color: #c9d4e8;
}
/* §57.54: UKURAN DAN BENTUKNYA DIKEMBALIKAN, bukan cuma warnanya.
   Kata bercetak tebal di dalam kartu terukur 26 px `display: block`
   sementara kalimat di sekelilingnya 12 px — "CHANGE" dan "FORM UP"
   berdiri sebagai judul raksasa di baris sendiri dan mendorong kartu jadi
   ENAM baris.

   Sebabnya pewarisan, bukan aturan yang salah tulis: `#ajar` adalah ANAK
   `#waktu-hud`, dan `#waktu-hud b` (angka jam pertandingan) memang
   `display: block; font-size: 26px`. Selektor itu jauh lebih khusus
   daripada `.ajar-teks b`, jadi ia menang tanpa pernah bermaksud menyentuh
   kartu ini.

   Diperbaiki di kartunya — dikembalikan ke sebaris dengan kalimatnya dan
   seukuran huruf induknya. `font-size: inherit`, bukan angka: ukuran
   `.ajar-teks` sendiri sudah `clamp()` yang mengikuti tinggi layar, dan
   angka tetap di sini akan lepas darinya di layar pendek.

   Aturan jamnya sendiri sudah dipersempit jadi `#waktu` (lihat catatannya
   di atas), jadi yang tertulis di sini tidak lagi melawan apa pun — ia
   cuma menyatakan bentuk yang memang diinginkan. */
.ajar-teks b {
  display: inline;
  font-size: inherit;
  line-height: inherit;
  color: #ffd23f;
}

/* ---- 57.45.4  SOROTAN TIDAK LAGI MEMPERSEGI TOMBOL BULAT ---------------
   Cacat, dan sebabnya satu kata: `border-radius: inherit`.

   `inherit` mengambil radius INDUK, bukan radius elemen itu sendiri. Enam
   tombol perintah sentuh adalah `.bulat` (`border-radius: 50%`), dan induknya
   `#gugus` tidak punya radius sama sekali — jadi begitu `.ajar-sorot`
   menempel, radius tombolnya sendiri DITIMPA jadi 0 dan lingkaran itu berubah
   jadi persegi selama disorot. Persis yang dikeluhkan.

   Diperbaiki dengan MENCABUT barisnya di tempatnya sendiri, bukan menimpanya
   dari sini. `revert` sempat dicoba dan salah dengan cara yang sama: ia
   mengembalikan nilai ke lembar gaya PERAMBAN, dan lembar gaya peramban
   menetapkan `border-radius: 0` untuk `<button>` — jadi tombol bulatnya tetap
   jadi persegi, cuma lewat jalan yang lebih panjang.

   Yang benar tidak menyebut `border-radius` sama sekali: `box-shadow` selalu
   mengikuti radius elemen yang ditempelinya, jadi cincinnya bulat pada tombol
   bulat dan membulat pada tombol persegi-lengkung tanpa satu baris pun yang
   menyebut bentuk.

   Sekaligus yang diminta: yang menyala GARIS TEPINYA. Cincin denyut lama
   berdiri di luar tombol tanpa menyentuh tepinya sendiri; sekarang tepinya
   ikut berpendar lewat lapisan `box-shadow` kedua yang tidak melebar
   (`0 0 0 3px`), jadi bentuk tombolnya tergaris kuning DAN berdenyut. */
.ajar-sorot {
  animation: ajar-denyut 1.15s ease-in-out infinite;
}
@keyframes ajar-denyut {
  0%, 100% {
    box-shadow: 0 0 0 3px rgba(255, 210, 63, 1), 0 0 0 3px rgba(255, 210, 63, 0.85);
  }
  50% {
    box-shadow: 0 0 0 3px rgba(255, 210, 63, 1), 0 0 0 11px rgba(255, 210, 63, 0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .ajar-sorot {
    animation: none;
    box-shadow: 0 0 0 3px rgba(255, 210, 63, 1), 0 0 0 6px rgba(255, 210, 63, 0.45);
  }
}

/* ---- 57.45.5  PANEL PENGEMBANG PADAM SELAMA TUTORIAL -------------------
   `Render tuning`, penunjuk kamera, dan baris statistik pemuatan adalah alat
   pengembang yang kebetulan tidak pernah disembunyikan di desktop. Selama
   tutorial berjalan ketiganya padam, dan yang pertama memang harus: terukur di
   1280x720, panelnya berdiri di 428-852 x 88-160 px sementara kartu tutorial
   yang baru terbit di 420-860 x 109-275 px. Kepala kartu — nomor langkah dan
   judulnya — tertutup seluruhnya. */
body.mengajar .panel-setel,
body.mengajar .panel-mode,
body.mengajar .panel-stat { display: none; }

/* ---- 57.51  JAM, "BATTLE TIME", DAN BARIS STATISTIK PADAM SAAT TUTORIAL --
   Diminta langsung. Ketiganya dibuang dari bagian atas layar selama tutorial
   berjalan; KOTAK TOMBOL STATS tetap berdiri, dan itu bukan pengecualian
   sembarangan — ada satu langkah tutorial yang mengajarkan tombol itu
   (`kunci: 'stat'` di js/ajar.js), jadi menyembunyikannya akan membuat
   langkah itu mustahil dituntaskan.

   Jamnya padam karena selama tutorial ia BOHONG: `tenang: true` menghentikan
   hitungannya sama sekali (lihat kepala js/ajar.js), jadi yang terbaca pemain
   adalah "3:00" yang tidak pernah bergerak. Angka beku di sudut layar
   mengajak dibaca sebagai tenggat, dan tenggat itu tidak ada.

   `visibility`, bukan `display`, untuk jam dan labelnya: kartu tutorial
   adalah ANAK `#waktu-hud` dan berdiri di bawah keduanya. `display: none`
   akan menarik kartunya naik ke tempat jam — yaitu ke bawah peta kecil dan
   baris skor — sementara `visibility: hidden` mengosongkan tulisannya tanpa
   memindahkan apa pun. Yang diminta "dihapus dari layar", dan tulisan yang
   tak terlihat sudah hilang dari layar.

   `#pesan` ikut padam: isinya kalimat tenggat ("Leave your fort in 5s...")
   yang dihitung dari jam yang sedang tidak berjalan. */
/* §57.54: `display: none`, sama seperti jam dan labelnya. Selama tutorial
   `#pesan` selalu kosong (kalimat tenggat dihitung dari jam yang tidak
   berjalan), tapi kotak kosong itu TETAP MEMAKAN TEMPAT — terukur
   mendorong kartu 23 px di bawah tombol setelan yang harus ia sejajari,
   sesudah jam dan labelnya sendiri sudah dicabut. */
body.mengajar #pesan { display: none; }

/* §57.52: MENYERAH padam selama tutorial, KELUAR tetap.
   Bagian dari keluhan "tombol pengaturan di tutorial tidak berguna".

   Lembar setelannya sendiri BEKERJA — kamera, musik, dan layar penuh
   semuanya berlaku, dan diuji begitu. Yang tidak berguna dua tombol di
   bawah pemisah: MENYERAH berarti "pertandingan ini tercatat KALAH", dan
   tutorial tidak punya catatan untuk dikalahi. Ia menawarkan akibat yang
   tidak ada.

   KELUAR dibiarkan berdiri, dan itu justru harus: sejak §57.52 tutorial
   tidak lagi berakhir sendiri, jadi ia satu-satunya jalan keluar sebelum
   langkah terakhir tuntas. Menyembunyikan keduanya akan mengurung pemain
   di dalam pertandingan yang tidak bisa dimenangkan maupun dikalahkan.

   Pemisah di atasnya ikut padam — pemisah yang memisahkan satu benda dari
   ketiadaan cuma garis yang menggantung. */
body.mengajar #s-menyerah,
body.mengajar #lembar-setelan .setel-pisah { display: none; }

/* §57.52: KARTU TUTORIAL DI ATAS ZONA TANGKAP STIK.
   Bug nyata di mode sentuh: tombol SKIP tidak bisa ditekan sama sekali.

   `#stik-zona` adalah daerah tangkap jari selebar 44% layar dan setinggi
   72% — tidak terlihat, tapi `pointer-events: auto`. Terukur di 892x412:
   titik tengah tombol SKIP (277,5 , 180) mengembalikan `#stik-zona` dari
   `elementFromPoint`, bukan tombolnya. Kartu tutorial memang punya
   `z-index: 6`, tapi angka itu tidak pernah dibandingkan dengan stik:
   `#waktu-hud` (induk kartu) TIDAK punya z-index, jadi kartu dan stik
   berada di stacking context yang sama dan yang menang urutan sumber —
   `#stik-zona` ditulis belakangan.

   Diperbaiki di INDUKNYA, bukan dengan menaikkan angka di kartunya:
   selama induknya tidak bernomor, angka berapa pun di kartu tidak
   berpengaruh. Ini persis jebakan yang sudah dicatat di kepala berkas ini
   ("z-index sebesar apa pun tidak menolong kalau yang dibandingkan bukan
   elemennya").

   Digantung pada KARTUNYA yang terlihat (`#waktu-hud:has(#ajar:not([hidden]))`),
   bukan pada `body.mengajar`. Percobaan pertama memakai `body.mengajar` dan
   meninggalkan satu celah yang terukur: `selesaikan()` MENCABUT kelas itu,
   sementara kartunya masih berdiri di layar membawa tombol BACK TO MENU —
   jadi tombol terakhir tutorial tertimbun lagi oleh `#stik-zona` tepat
   sesudah langkah terakhir tuntas. Yang menentukan memang keberadaan
   kartunya, bukan sedang-tidaknya tutorial berjalan.

   Di luar itu `#waktu-hud` isinya jam yang `pointer-events: none`, dan
   menaikkannya tanpa sebab berarti mengubah susunan lapisan seluruh HUD
   demi sesuatu yang tidak ada. */
#waktu-hud:has(#ajar:not([hidden])) { z-index: 7; }
/* Baris statistik pemain (bendera, jumlah, sikap) padam; tombol STATS di
   ujung kanannya TETAP. `.skor-atas` sendiri dibiarkan berdiri supaya
   tombolnya tidak ikut hilang bersama kotaknya. */
body.mengajar .skor-ringkas > :not(.stats-tbl) { display: none; }

/* ---- 57.45.6  PAPAN HASIL: BENDERA SEJAJAR, ALIVE DI TENGAH ------------
   (a) BENDERA SEJAJAR KE BAWAH. Terukur di kartu Quick Match: panji baris
       Viking di x=290,3, Slavia 291,0, Yamato 286,4 — meleset sampai 4,6 px;
       di papan babak turnamen 488,1 / 485,7 / 489,8 / 484,5, meleset 5,3 px.
       Sebabnya `justify-content: center` pada sel WARBAND: yang dipusatkan
       adalah PASANGAN bendera+nama sebagai satu benda, jadi tiap huruf yang
       ditambahkan nama mendorong benderanya ke kiri.

       Diperbaiki dengan mengubah sel itu jadi KISI dua lajur — `auto` untuk
       benderanya (dan lebar bendera memang tetap, 17x23 px untuk semua bangsa)
       lalu sisanya untuk nama. Lajur pertama karena itu selebar itu di setiap
       baris, jadi benderanya berdiri di titik yang sama persis. Namanya sendiri
       tetap DIPUSATKAN di dalam lajur keduanya, jadi permintaan §57.44.4
       ("warband di tengah kolom") tidak dibatalkan — yang berubah cuma apa yang
       dipusatkan: dulu pasangannya, sekarang namanya. */
.hasil-baris .wb {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 7px;
  justify-content: initial;
}
.hasil-baris .wb .nm { text-align: center; }

/* (b) ALIVE DI TENGAH KOLOMNYA. Sel ALIVE papan turnamen sebuah `<i>`
      (`.slmt`), dan ia satu-satunya sel di seluruh papan yang tidak pernah
      diberi perataan — `.hasil-baris b { text-align: center }` cuma menjangkau
      sel `<b>`. Jadi ia mewarisi rata-kiri dari barisnya sementara kepala
      kolomnya sendiri di tengah. */
.hasil-baris .slmt,
.tur-tabel .slmt {
  display: block;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* (c) PANEL SEDIKIT LEBIH TINGGI DAN LEBIH LAPANG. Terukur: kartu Quick Match
      860x363 px dan papan babak 460x381 px di layar setinggi 720 px — masing-
      masing cuma memakai separuh tinggi layar, dengan baris tabel setinggi
      35 px yang berdesakan di bawah judul setinggi 52 px. Yang ditambah TINGGI
      BARIS dan sela di dalam kartunya, bukan `min-height` pada kartunya:
      kartu yang dipaksa tinggi sementara isinya tetap akan menumbuhkan ruang
      kosong di bawah tombol, bukan melapangkan isinya. */
.hasil-baris { padding-block: clamp(3px, 0.7vh, 6px); }
.hasil-kepala { padding-block: clamp(2px, 0.5vh, 5px); }
.kotak.lebar.hasil-kotak { gap: clamp(9px, 1.9vh, 15px); }

/* ---- 57.45.8  TOMBOL UKURAN KOMPETISI SEUKURAN TULISAN DI BAWAHNYA -----
   Terukur di layar Manage The Competition: ketiga tombol ukuran berhuruf
   11,5 px, sementara nama baris di bawahnya ("Map", "Round") 12,5 px dan
   nilainya ("Forest", "4") 15 px. Jadi tiga TOMBOL — benda yang ditekan, dan
   satu-satunya keputusan di panel itu — bertuliskan huruf terkecil di seluruh
   panel, lebih kecil daripada keterangan yang cuma dibaca.

   Ukurannya dipatok ke `.baris-info b`, angka yang sama persis: keduanya
   sekarang membaca satu skala. Lebarnya tidak berubah (149,9 px per tombol)
   dan label terpanjang "Medium (1vs3)" pada 15 px berukuran ±103 px, jadi
   satu barisnya tetap muat tanpa dipotong.

   §57.63 — DIBESARKAN LAGI, 15 px → 18 px, dan sisipan tegaknya ikut naik.
   Diminta langsung ("tulisannya diperbesar dan tombolnya disesuaikan"), dan
   ruangnya memang baru tersedia: sejak "(N Groups)" dicabut, label terpanjang
   tinggal "MEDIUM" — enam huruf, ±72 px pada 18 px kapital — di dalam tombol
   selebar 149,9 px. Ukuran ini disamakan dengan `--fs-label` judul kartu di
   atasnya, jadi tombol tidak lagi bertuliskan huruf terkecil di panelnya.

   §57.72 — DIPATOK ke 11 px TETAP (bukan `clamp`), diminta langsung ("tulisan
   di panel competition size... 11 px"). Angka tunggal, bukan rentang: yang
   diminta ukuran pasti, bukan batas atas baru untuk skala responsif yang
   sudah ada. `padding` dipertahankan dari §57.63 (tinggi tombol tidak diminta
   berubah, hanya hurufnya).

   DITULIS DI SINI, bukan sebagai aturan keempat di ujung berkas: dua aturan
   `.pilih-tab.tiga .tab` sebelumnya (§57.44.5 dan yang ini) sudah saling
   menimpa berurutan, dan aturan ketiga yang menimpa keduanya lagi cuma
   memindahkan pertanyaan "yang mana yang berlaku?" satu langkah lebih jauh. */
.pilih-tab.tiga .tab {
  font-size: 11px;
  padding: clamp(9px, 2.1vh, 16px) 4px;
}

/* ---- 57.45.9  KAKI BASE PLAYER: DUA TOMBOL LEBIH PANJANG --------------
   Terukur: baris kaki 255,8 px berisi tombol harian 69,1 px dan QUICK GAME
   yang mengisi sisanya. Diminta keduanya sedikit memanjang, dan tulisan
   harian ("DAY 2", "DAY 100") tidak boleh pernah patah jadi dua baris.

   Barisnya sendiri yang dilebarkan, bukan tombolnya satu per satu: kedua
   tombol dijatah `flex`, jadi melebarkan salah satunya cuma memindahkan lebar
   dari yang lain. Melebarnya ke KIRI — ke arah pemandangan — karena kolom
   kanan sudah menempel di tepi layar, dan menariknya ke kanan berarti
   memotongnya di layar sempit. */
.base-kaki {
  width: calc(100% + clamp(14px, 2.6vw, 34px));
  margin-left: calc(clamp(14px, 2.6vw, 34px) * -1);
}
.base-hadiah { width: clamp(62px, 11vh, 86px); }
/* "DAY 100" pada 10,5 px berhuruf renggang 0,9 px berukuran ±52 px; tombol
   selebar 86 px menampungnya, tapi `nowrap` yang menjaminnya — tanpa itu,
   satu bahasa berhuruf lebih lebar sudah cukup untuk memecahnya jadi dua
   baris dan menaikkan tinggi seluruh baris kaki. */
.base-hadiah b { white-space: nowrap; }

/* ---- 57.45.12  PETAK CUSTOM PLAYER TANPA KOTAK WAJAH ------------------
   `.rupa-sel img` mewarisi `border: 2px solid rgba(0,0,0,0.42)` beserta
   radiusnya dari `.koleksi-sel img`. Garis itu benar di panel koleksi — di
   sana isinya PANJI dan GAMBAR ARENA, dua gambar berlatar penuh yang tanpa
   bingkai akan luntur ke latar petaknya. Foto kepala di panel ini justru
   kebalikannya: latarnya sudah tembus pandang dan siluetnya sendiri yang
   membentuk gambar, jadi garis persegi di sekelilingnya menambahkan kotak
   yang tidak ada isinya — kotak di dalam kotak, persis yang dikeluhkan. */
.rupa-sel img { border: 0; border-radius: 0; }

/* Nama di bawah model besar waktu yang berdiri di sana cuma PRATINJAU. Warna
   dan huruf miringnya sengaja berbeda dari nama bangsa yang biasa berdiri di
   sana: dua kabar berbeda tidak boleh memakai rupa yang sama. */
.potret-nama.pratinjau-rupa,
#rupa-nama.pratinjau-rupa {
  color: #5f6b85;
  font-style: italic;
  letter-spacing: 0.6px;
}

/* ---- 57.45.13  PANJI MENDATAR DI PETAK WARLORDS DAN WARLORD'S BASE -----
   Petak koleksi menggambar panji pada 34x26 px dengan `object-fit: cover`,
   dan sumbernya kain TEGAK 3:4 — jadi sepertiga tinggi kain terpotong, dan
   yang terpotong justru ujung atas dan bawah lambangnya. Sumbernya sekarang
   panji 5:3 (`panjiLebarURL()` di js/dunia.js), jadi petaknya diberi
   perbandingan yang sama supaya tidak ada lagi yang dipotong sama sekali. */
.koleksi-sel img.panji-lebar {
  width: clamp(34px, 5.8vh, 46px);
  height: auto;
  aspect-ratio: 5 / 3;
  object-fit: fill;
}

/* ---- 57.45.16  IKON INTAN SEJAJAR DENGAN TULISAN TOMBOLNYA -------------
   Terukur pada tombol UNLOCK (150) berhuruf 12 px: kotak ikon berpusat di
   y=492,93 dan kotak simpul teks di y=492,42 — praktis sama, dan justru itulah
   sebabnya ia terlihat melorot.

   Kotak sebuah simpul teks setinggi SELURUH baris, termasuk ruang turunan di
   bawah garis dasar yang tidak dipakai satu pun angka. Yang benar-benar
   terlihat mata cuma pita dari tinggi huruf besar sampai garis dasar, dan pita
   itu berpusat sekitar 1,2 px LEBIH TINGGI daripada pusat kotaknya. Ikon yang
   dipusatkan pada kotak karena itu selalu duduk lebih rendah daripada angka di
   sebelahnya, dan `align-items: center` tidak bisa memperbaikinya — ia
   memusatkan dengan benar pada kotak yang salah.

   Dua penyetelan, dan keduanya perlu:
     1. Digeser naik 0,1em, yaitu selisih terukur itu dinyatakan sebagai
        pecahan ukuran huruf supaya benar pada semua ukuran tombol.
     2. Dikecilkan dari 1,15em jadi 1,05em. Pada 12 px, ikon 1,15em setinggi
        13,8 px berdiri di sebelah angka setinggi ±8,6 px — separuh lebih
        besar, dan benda yang jauh lebih besar terbaca tidak sebaris walau
        pusatnya tepat.

   `transform` dipakai, bukan `position: relative` + `top`: ikon ini berdiri di
   dalam wadah `inline-flex` (`.hrg`), dan `top` pada anak flex tidak menggeser
   apa pun sampai `position` ikut disetel. */
/* §57.63 — GESERANNYA DIKECILKAN 0,1em → 0,045em, dan ini memperbaiki
   KELEBIHAN KOREKSI dari penyetelan di atas, bukan membatalkannya.

   Angka 0,1em di atas diturunkan dari satu pengukuran pada tombol berhuruf
   12 px, tempat selisih terlihatnya ±1,2 px. Yang tidak ikut terperiksa waktu
   itu: selisih tersebut TIDAK tumbuh sebanding dengan ukuran huruf — ia lahir
   dari ruang turunan di bawah garis dasar, yang pada muka huruf ini tetap
   tipis walau hurufnya membesar. Dinyatakan sebagai `em`, koreksi yang pas di
   12 px jadi hampir dua kali lipat terlalu besar di 19 px (tombol ENTER) dan
   lebih parah lagi di tombol yang lebih besar.

   Terukur di tombol ENTER berhuruf 19 px: pusat ikon 1,9 px DI ATAS pusat
   kotak angka, dan pada tangkapan layar yang dibesarkan ke 54 px intannya
   jelas melayang di atas garis "ENTER (…50)". Nilai baru menyisakan koreksi
   secukupnya untuk melawan ruang turunan tanpa mengangkat ikonnya keluar
   dari barisnya sendiri. */
.hrg .ik-intan,
.tbl .ik-intan,
.tbl-besar .ik-intan,
.koleksi-aksi .ik-intan,
.rupa-aksi .ik-intan,
.hasil-baris .hdh .ik-intan,
.tur-tabel .hdh .ik-intan {
  width: 1.05em;
  height: 1.05em;
  transform: translateY(-0.045em);
}

/* ---- 57.45.17  HALAMAN PRIVASI PUNYA KERANGKANYA SENDIRI ---------------
   Kerangka `.layar-isi` bawaan adalah kisi DUA KOLOM TIDAK SIMETRIS milik
   layar Quick Match — kolom kiri sempit untuk model 3D, kolom kanan lebar
   untuk panel pengaturan. Halaman teks yang menumpanginya mendapat dua kartu
   selebar 358 px dan 516 px, dan itulah seluruh sebab "tidak proporsional".

   Di sini ia diganti kisi yang tiap lajurnya sama lebar. `align-items:
   stretch` (bawaan kisi) memberi tiap kartu tinggi baris penuh, jadi dua
   kartu bersebelahan berakhir sama tinggi berapa pun panjang kalimatnya. */
.layar-isi.privasi-isi {
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1.8vh, 16px);
}
/* `.privasi-buka` DICABUT: kalimat pembuka "The short version is..." dibuang
   karena keempat kartu di bawahnya sudah menyatakan hal yang sama, dan
   kalimat yang cuma mengumumkan bahwa penjelasan akan menyusul menunda
   penjelasan itu sendiri. Aturannya ikut dihapus supaya tidak jadi gaya
   yatim yang menunggu penanda yang tidak akan datang lagi. */
.privasi-kisi {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(8px, 1.6vw, 16px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 2px;
}
.kartu.privasi-kartu {
  width: auto;
  height: 100%;
  margin: 0;
  gap: clamp(4px, 1vh, 8px);
  text-align: left;
}
.privasi-kartu .kartu-teks { text-align: left; }
/* Satu lajur begitu lebarnya tidak lagi cukup untuk dua kartu teks yang
   masing-masing masih menyisakan panjang baris yang enak dibaca. Ambangnya
   diukur dari panjang barisnya, bukan dari nama perangkat. */
@media (max-width: 720px) {
  .privasi-kisi { grid-template-columns: minmax(0, 1fr); }
}

/* ---- 57.45.18  JUDUL BESAR YANG HURUF I-NYA TERTELAN -------------------
   "PRIVACY" terbaca "PRNACY". Bukan salah ketik dan bukan salah huruf — I dan
   V berdempetan sampai isian kuningnya menyatu jadi satu bentuk yang persis
   menyerupai N.

   Sebabnya perbandingan dua angka. Garis tepi judul `-webkit-text-stroke`
   setebal 7 px (clamp 4-7 px), dan garis tepi digambar di TENGAH kontur, jadi
   tiap huruf melebar 3,5 px ke kiri dan 3,5 px ke kanan. Renggang hurufnya
   `--lc-kapital`, yaitu 1,1 px. Tujuh piksel pelebaran melawan satu piksel
   renggang berarti tepi hitam semua huruf memang menyatu — dan penyatuan itu
   DIINGINKAN, ia yang membuat judul terbaca sebagai satu stiker utuh. Yang
   tidak diinginkan adalah huruf yang batangnya sendiri cuma selebar garis
   tepinya. Di antara enam huruf gemuk, I hilang.

   Dinyatakan dalam `em`, bukan piksel: judulnya sendiri `clamp()` terhadap
   tinggi layar, dan renggang tetap yang benar pada 44 px terlalu longgar pada
   22 px. `max()` menjaga judul yang huruf besarnya sudah cukup renggang tidak
   ikut merenggang lagi.

   0,085em, dan angkanya dicari bukan ditebak: pada 0,05em isian kuning I dan V
   masih bersentuhan di ujung atasnya, pada 0,085em keduanya terpisah sementara
   tepi hitamnya tetap menyatu. Judulnya tetap satu stiker utuh, dan hurufnya
   kembali tujuh. */
.judul-besar { letter-spacing: max(var(--lc-kapital), 0.085em); }

/* ============================================================================
   §57.63 — KAPITALISASI TEKS UI (direvisi dua kali sesudahnya)
   ============================================================================

   Keputusan pemilik proyek berjalan tiga tahap:
     1. §57.63 asli: SEMUA tulisan antarmuka jadi huruf besar, kecuali
        paragraf panjang.
     2. Revisi: kapital cuma untuk label BERKATA SEDIKIT (<=3 kata); label
        panjang jadi Title Case.
     3. Revisi kedua, YANG BERLAKU SEKARANG: bukan lagi soal panjang kata
        sama sekali — ALL CAPS cuma untuk heading/judul layar-panel dan
        tombol/header kolom tabel. Semua yang lain, betapapun pendeknya
        (Weather, Round, Soon, You), jadi Title Case. Sebabnya diukur
        langsung di layar: aturan tahap 2 masih menyisakan "Weather"/
        "Difficulty Level" ALL CAPS berdampingan dengan "Number Of
        Warbands Group" Title Case di kartu yang sama — tidak konsisten
        walau tiap aturannya sendiri "benar" menurut kategorinya.

   DIKERJAKAN LEWAT `text-transform`, BUKAN dengan menulis ulang tiap teks jadi
   huruf besar di index.html dan di berkas js. Tiga sebabnya, dan ketiganya
   sudah pernah dipakai di berkas ini (lihat catatan `.kartu-kepala`):

     1. SUMBERNYA TETAP TERBACA. "Number of Members in Each Warbands" masih
        bisa disunting sebagai kalimat; ditulis kapital di sumber, ia jadi
        pita huruf yang harus dieja waktu diperiksa.
     2. TEKS YANG LAHIR DARI KODE IKUT TERBAWA. Nama bangsa, nama arena, label
        status, dan seluruh teks yang disusun js/*.js tidak perlu satu pun
        `.toUpperCase()` yang bisa terlupa di jalur kedua.
     3. SATU TEMPAT UNTUK DIBATALKAN. Kalau suatu hari sebagian harus kembali
        huruf biasa, yang disunting aturan di sini — bukan berburu ratusan
        string di dua puluh berkas.

   Dipasang di UJUNG berkas supaya menang atas aturan sebelumnya tanpa perlu
   satu pun `!important`. */

/* ---- ALL CAPS — CUMA heading/judul dan tombol --------------------------
   Prinsip direvisi (kedua kalinya): kapital penuh dulu berlaku untuk "yang
   dipindai mata" (label, judul, tombol, nama, angka satuan) — terlalu
   luas, dan hasilnya di layar terasa tidak konsisten (nama bangsa di kartu
   komidi ALL CAPS, tapi baris label lain sudah Title Case di kartu yang
   sama). Yang tersisa di sini cuma DUA kategori: heading/judul panel-layar,
   dan sesuatu yang berperan sebagai tombol atau header kolom tabel — dua
   hal yang secara konvensi UI memang boleh menonjol lebih dari isinya. */
.pilih-tab .tab,              /* tombol ukuran/kesulitan/cuaca */
.tbl,                         /* semua tombol biasa */
.tbl-besar,                   /* tombol besar (START, ENTER, UNLOCK) */
.pil,                         /* pil kaki beranda */
.kotak-judul,                 /* judul semua dialog/panel */
.setel-baris span,            /* TOMBOL setelan (Camera, Music, Fullscreen) */
.setel-baris b,               /* nilainya di dalam tombol yang sama */
.tur-kumpul,                  /* judul panel lobi turnamen/custom */
.hasil-kepala,                /* header kolom tabel hasil (NO/WARBAND/USER) */
.panel-bantuan {               /* legenda kontrol keyboard di HUD gameplay —
                                  tombol yang dijelaskannya (STRIKE, THROW)
                                  sudah kapital; keterangannya harus konsisten */
  text-transform: uppercase;
}

/* ---- yang TETAP huruf biasa --------------------------------------------
   Dinyatakan TERPISAH dan SESUDAH daftar di atas, bukan dengan menghindari
   pemilihnya: beberapa di antaranya (mis. `.kartu-teks` yang memuat `<b>`)
   bersarang di dalam elemen yang memang ikut kapital, jadi satu-satunya cara
   yang benar-benar bekerja adalah membatalkannya kembali di sini. */
.kartu-teks,                  /* paragraf kartu (privacy, keterangan) */
.kartu-teks b,                /* termasuk penekanan DI DALAM paragraf */
.ket-isi,                     /* paragraf keterangan koleksi */
.naik-teks,                   /* kalimat panel naik lencana */
.privasi-kartu .kartu-teks,   /* paragraf privacy policy */
.ajar-teks,                   /* kalimat tutorial */
#base-nama {                  /* kolom isian nama: yang diketik pemain */
  text-transform: none;
}

/* ---- TITLE CASE — semua yang BUKAN heading/judul/tombol ----------------
   Revisi kedua: bukan lagi soal "panjang vs pendek" (aturan sebelumnya),
   melainkan "heading/tombol vs bukan". Status, nama entitas, label baris,
   isi tabel data — tidak satu pun dari ini heading atau tombol, jadi tidak
   lagi ALL CAPS, betapapun pendeknya (SOON, SELECTED, DAY 1 termasuk).

   `capitalize`, bukan menulis ulang huruf di sumbernya: sumbernya sendiri
   campuran (subjudul mode Sentence case, label baris kontrol sudah Title
   Case, sebagian string literal ALL CAPS langsung di JS seperti 'SELECTED'/
   'SOON') dan `capitalize` menyamakan tampilannya tanpa perlu menyentuh
   satu pun string sumber — huruf pertama tiap kata naik, sisanya apa
   adanya. Kelas `.judul-panjang` dipasang manual di index.html pada elemen
   yang memang panjang; `.mode-teks i` sudah selektor sendiri. */
.keping,                      /* keping SOON / status fitur */
.komidi-kartu span,           /* nama bangsa/arena di kartu komidi */
.baris-info span,             /* label baris info (Map, Round, Reward) */
.baris-info b,                /* nilainya (Forest, 4, ...) */
.base-stat span,              /* label statistik Base Player */
.base-nama-teks,              /* nama pemain */
.lencana-info b,              /* nama lencana di panel daftar */
.lencana-info i,              /* ambangnya (150 flags) */
.naik-nama,                   /* nama lencana di panel selamat */
.harian-hari,                 /* Day 1 / Already Claimed */
#base-hadiah-teks,            /* Daily / Day 1 / Claimed di kotak hadiah harian */
.potret-nama,                 /* label Selected/Available di bawah model */
.koleksi-aksi,                /* tombol status koleksi (Selected/Available/Soon) */
.ket-kepala,                  /* judul kotak keterangan koleksi (nama entitas) */
.hasil-baris,                 /* baris tabel hasil pertandingan — DATA, bukan header */
.tur-tabel,                   /* isi tabel turnamen — DATA, bukan header */
.mode-teks i,                 /* subjudul tombol mode beranda */
span.judul-panjang,           /* label baris kontrol yang panjang — `span`
                                  disertakan supaya spesifisitasnya menyamai
                                  `.baris-info span`/`.kartu-kepala` di atas,
                                  kalah tidak jadi soal apa yang menang */
.judul-panjang {
  text-transform: capitalize;
}

/* Pesan pratinjau ("Arena model not drawn yet") ikut Title Case — bukan
   heading/tombol, murni status yang dipindai sekilas. */
.pratinjau-pesan { text-transform: capitalize; }
