/* ── Primitif bersama semua halaman badminton ──

   TANGGA HURUF — satu peran satu token, jangan campur:
     judul baris / nama       --text-body-3b   (700 13)
     keterangan di bawahnya   --text-body-5r   (400 11)
     label bagian & status    --text-body-5b   (700 11, KAPITAL)
     aksi & penanda aksen     --text-body-4b   (700 12)
     angka di tabel           --text-body-4r   (400 12)
     angka menonjol           --text-body-2b   (700 14)
   Sebelumnya nama baris kadang 14 kadang 13, dan keterangan kadang 12 kadang
   11 — dua teks bersebelahan dengan tebal berbeda langsung terlihat acak.

   Tujuannya satu: setiap komponen yang muncul di lebih dari satu halaman hanya
   ditulis DI SINI. Sebelum file ini ada, .btn-primary punya tiga salinan di tiga
   halaman dan ketiganya sudah mulai berbeda paddingnya.

   Jarak memakai tangga token DS, bukan angka bebas:
     --gap-item-tight 2 · --gap-item-base 4 · --gap-item-loose 8
     --gap-section-tight 8 · --gap-section-base 12 · --gap-section-loose 16
     --gap-layout-tight 16 · --gap-layout-base 20
   Angka di luar tangga itu (7, 10, 11, 14) dipakai sebelumnya dan sudah
   dibereskan — jangan diperkenalkan lagi. */

/* ── Kerangka isi ── */

.step {
  padding: var(--gap-layout-tight);
  display: flex;
  flex-direction: column;
  gap: var(--gap-section-base);
}

/* Footer aksi. Aman dari home indicator iPhone lewat safe-area. */
.foot {
  flex: 0 0 auto;
  padding: var(--gap-section-base) var(--gap-layout-tight);
  padding-bottom: calc(var(--gap-section-base) + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--surface-border);
  background: var(--surface);
}

/* ── Kartu ── */

.card {
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-card);
  /* Sudut iframe dan gambar ikut terpotong radius kartunya; keduanya tidak bisa
     diberi radius dari luar. */
  overflow: hidden;
}

.card-pad { padding: var(--gap-section-base) var(--gap-section-loose); }

/* Kartu yang isinya padat (kartu match) pakai padding lebih rapat: isinya
   sudah punya jarak sendiri di dalam. */
.card-pad-tight { padding: var(--gap-item-loose) var(--gap-section-base); }

/* ── Label bagian ──
   Huruf kecil, kapital, redup. Dipakai sebagai judul kolom tabel maupun judul
   bagian di dalam kartu. */
.label,
.field-label,
.sched-label {
  font: var(--text-body-5b);
  color: var(--tertiary);
  text-transform: uppercase;
  letter-spacing: .04em;
}

.field-label { margin-bottom: var(--gap-item-loose); }

/* ── Pemilih yang membuka bottom sheet ──
   Dipakai halaman klub (pasangan head-to-head) dan halaman Profile (negara).
   Tinggal di sini, bukan di salah satu halaman: yang kedua menyalinnya berarti
   dua bentuk yang perlahan berbeda.

Dua pemilih. BUKAN pilih bebas, dan BUKAN <select> bawaan: isinya hanya
   pasangan yang memang pernah turun bareng, dan daftar lawannya hanya yang
   memang pernah dihadapi pasangan itu. Daftarnya dibuka sebagai bottom sheet
   supaya bentuknya sama dengan daftar lain di aplikasi ini, bukan menu sistem
   yang tampilannya lepas dari desain. */
.sel {
  display: flex;
  align-items: center;
  gap: var(--gap-item-loose);
  width: 100%;
  padding: var(--gap-section-base);
  font: var(--text-body-3b);
  color: var(--primary);
  text-align: left;
  /* Latar isian mengikuti wadahnya; yang mendefinisikan kotak ini garisnya. */
  background: transparent;
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-field);
  cursor: pointer;
}
.sel:hover { background: var(--surface-hover); }

/* Belum dipilih: teksnya ajakan, jadi warnanya warna teks bantu, bukan warna
   isi. Yang belum bisa dipilih dimatikan dengan atribut disabled bawaan —
   tidak bisa diklik, tidak kena tab keyboard, dan dibacakan sebagai nonaktif. */
.sel.is-empty .sel-val { color: var(--tertiary); }
.sel:disabled { color: var(--disabled); background: var(--surface-disabled); cursor: not-allowed; }
.sel:disabled:hover { background: var(--surface-disabled); }
.sel:disabled .sel-val { color: inherit; }
.sel-val { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sel > svg { flex: 0 0 auto; color: var(--icon); }

/* Baris pilihan di dalam sheet. Kolom centang selebar tetap supaya teksnya
   tidak bergeser waktu pilihan berpindah. */
.opt {
  display: flex;
  align-items: center;
  gap: var(--gap-section-base);
  width: 100%;
  padding: var(--gap-section-base) 0;
  font: var(--text-body-3b);
  color: var(--primary);
  text-align: left;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--modal-border);
  cursor: pointer;
}
.opt:last-child { border-bottom: 0; }
.opt-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Jumlah match lebih kecil dari namanya: di daftar dua puluh baris dia
   berulang terus, dan dengan bobot yang sama dengan nama dia ikut bersaing
   dibaca. Angkanya tabular supaya "1 match" dan "12 matches" rata kanan. */
.opt-count {
  flex: 0 0 auto;
  font: var(--text-body-5r);
  color: var(--tertiary);
  font-variant-numeric: tabular-nums;
}
/* Centang duduk di kiri teks KANAN (keterangan/jumlah), bukan di ujung
   baris dan bukan di paling kiri. Kolomnya selalu ada walau kosong, jadi
   teks kanan di semua baris tetap rata di tepi yang sama. */
.opt-mark { flex: 0 0 auto; width: 18px; height: 18px; color: var(--brand); order: 1; }
.opt-count { order: 2; }

/* ── Bendera ──
   Bundar, dengan garis tipis di tepinya. Garisnya bukan hiasan: bendera yang
   sebagian putih (Indonesia, Jepang, Singapura) tanpa garis itu separuhnya
   hilang menyatu dengan latar putih. Pakai outline ke dalam, bukan bayangan,
   dan warnanya token pemisah supaya ikut tema gelap. */
.flag {
  flex: 0 0 auto;
  display: block;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  outline: 1px solid var(--divider);
  outline-offset: -1px;
}

/* ── Isian teks ──
   Latarnya TEMBUS PANDANG, ikut wadahnya; yang mendefinisikan kotaknya
   garisnya. Sama persis dengan .sel di halaman klub, supaya isian yang diketik
   dan isian yang dipilih tidak terlihat seperti dua jenis benda. */
.input {
  width: 100%;
  padding: var(--gap-section-base);
  font: var(--text-body-3b);
  color: var(--primary);
  background: transparent;
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-field);
  outline: none;
}
.input::placeholder { color: var(--tertiary); font: var(--text-body-3r); }
.input:focus { border-color: var(--brand); }
/* Input di dalam sheet (latar --modal) memakai garis wadahnya, --modal-border
   (31 Okt 2026). Dengan --surface-border, di dark mode garisnya hampir hilang
   (#303030 di atas #292929). Fokus tetap --brand. */
.sheet .input:not(:focus) { border-color: var(--modal-border); }

/* Yang tidak bisa diubah dibedakan dari yang kosong: bukan sekadar diabukan,
   tapi jelas tidak menerima ketikan. */
.input:disabled,
.input[readonly] {
  color: var(--disabled);
  background: var(--surface-disabled);
  cursor: not-allowed;
}
/* 8, bukan 2. Dengan 2 labelnya nempel ke isinya, sementara jarak ke blok
   berikutnya di dalam kartu yang sama 12 — bacanya jadi timpang: label seperti
   bagian dari baris di bawahnya, bukan judul yang menaungi kartunya. */
.sched-label { margin-bottom: var(--gap-item-loose); }

/* ── Baris daftar ──
   Avatar di kiri, dua baris teks di tengah, angka opsional di kanan. Dipakai
   daftar pemain, daftar peserta, dan daftar jadwal. */
.row {
  display: flex;
  align-items: center;
  gap: var(--gap-section-base);
  padding: var(--gap-section-base) 0;
  border-bottom: 1px solid var(--divider);
}

.row-body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--gap-item-tight);
}

.row-title { font: var(--text-body-3b); color: var(--primary); }
.row-meta { font: var(--text-body-5r); color: var(--secondary); }

/* ── Avatar ──
   Selalu kotak dengan radius kartu, tidak pernah lingkaran. --emphasis jadi
   alas selama gambarnya belum turun, jadi barisnya tidak berkedip kosong. */
.avatar {
  flex: 0 0 auto;
  background: var(--emphasis);
  border-radius: var(--radius-card);
  object-fit: cover;
}

/* ── Tombol ──
   Isian penuh atau tanpa isian sama sekali. Tidak ada versi tint separuh
   (latar brand-low + teks brand): hierarkinya dari ada atau tidaknya isian. */

.btn-primary,
.btn-ghost {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-item-loose);
  width: 100%;
  padding: var(--gap-section-base) var(--gap-layout-tight);
  font: var(--text-body-3b);
  border-radius: var(--radius-field);
  text-decoration: none;
  cursor: pointer;
}

.btn-primary {
  /* --on-brand, bukan --white: di mode gelap ungunya terang dan teks putih di
     atasnya tidak terbaca. Lihat theme.css. */
  color: var(--on-brand);
  background: var(--brand);
  border: 0;
}

.btn-primary:disabled {
  background: var(--surface-disabled);
  color: var(--disabled);
  cursor: not-allowed;
}

.btn-ghost {
  color: var(--primary);
  background: transparent;
  border: 1px solid var(--surface-border);
}
.btn-ghost:hover { background: var(--surface-hover); }

/* Aksi yang tidak bisa dibatalkan. Tetap TANPA ISIAN: yang membedakan warnanya,
   bukan bobotnya. Tombol merah berisi penuh akan jadi benda paling menonjol di
   halaman, padahal ini justru yang paling jarang ditekan. */
.btn-danger { color: var(--negative); }
/* Latar hover-nya netral, bukan merah muda: DS tidak punya token merah lembut,
   dan bikin token tandingan di sini cuma menambah warna yang tidak dikenal
   siapa pun. */
.btn-danger:hover { background: var(--surface-hover); }

/* Tombol selebar isinya, dipakai waktu dia berdiri di tengah empty state:
   tombol selebar layar di tengah ruang kosong terlihat seperti panel, bukan
   ajakan menekan. */
.btn-inline { width: auto; margin-top: var(--gap-item-loose); }

/* ── Segmented kecil ──
   Dua-tiga pilihan yang menyatu dalam satu kotak, selebar isinya. Dipakai
   sebagai OPSI di atas tabel, bukan navigasi: kalau dibuat selebar layar dengan
   dua kotak terpisah, dia terbaca sebagai baris tab kedua.
   Yang terpilih diisi --emphasis (netral) dengan teks utama; bukan tint brand,
   sesuai aturan pilihan-tunggal. */
.seg-mini {
  display: inline-flex;
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-field);
  overflow: hidden;
}
.seg-mini button {
  padding: var(--gap-item-loose) var(--gap-section-base);
  font: var(--text-body-4b);
  color: var(--secondary);
  background: transparent;
  border: 0;
  cursor: pointer;
  white-space: nowrap;
}
.seg-mini button + button { border-left: 1px solid var(--surface-border); }
.seg-mini button:hover { background: var(--surface-hover); }
.seg-mini button[aria-pressed="true"] { background: var(--emphasis); color: var(--primary); }

/* ── Tab ── */

.tabs {
  flex: 0 0 auto;
  display: flex;
  border-bottom: 1px solid var(--surface-border);
}

.tab {
  flex: 1 1 0;
  padding: var(--gap-section-base) var(--gap-item-base);
  font: var(--text-body-4b);
  color: var(--secondary);
  background: transparent;
  border: 0;
  /* Garis bawah transparan dipasang di SEMUA tab, bukan cuma yang aktif. Kalau
     cuma yang aktif punya border, tinggi tab berubah 2px tiap pindah dan
     barisnya goyang. */
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  cursor: pointer;
  white-space: nowrap;
}
.tab:hover { background: var(--surface-hover); }
.tab[aria-selected="true"] { color: var(--primary); border-bottom-color: var(--brand); }

/* ── Pilihan tunggal: chip dan tile ──
   Yang terpilih ditandai GARIS brand, latarnya tetap sama dengan yang tidak
   terpilih. Bukan latar brand-low. */

.chip,
.seg-item {
  font: var(--text-body-4b);
  color: var(--secondary);
  background: transparent;
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-field);
  cursor: pointer;
  white-space: nowrap;
}

.chip { flex: 1 1 0; padding: var(--gap-item-loose) var(--gap-section-base); }

/* Angka di dalam chip (jumlah orang per tingkat). Lebih ringan dari labelnya:
   dia keterangan, bukan nama pilihannya. Angkanya tabular supaya chip yang
   berdampingan tidak bergeser lebarnya karena beda digit. */
.chip-count {
  margin-left: var(--gap-item-loose);
  font-weight: 400;
  color: var(--tertiary);
  font-variant-numeric: tabular-nums;
}
/* "Soon" duduk SEBARIS dengan labelnya, bukan di bawahnya: ditumpuk, tiap tile
   makan satu baris teks ekstra padahal isinya cuma satu kata. */
/* Wadah segmented. Tadinya hidup di competition-new.html sendirian; begitu
   halaman Profil ikut memakainya, dia harus jadi milik bersama — kalau tidak,
   yang kedua diam-diam menumpuk ke bawah karena wadahnya tidak pernah ada. */
.seg { display: flex; gap: var(--gap-item-loose); }

.seg-item {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-item-loose);
  padding: var(--gap-section-base);
  font: var(--text-body-3b);
}

.chip:hover,
.seg-item:hover:not(:disabled) { background: var(--surface-hover); }

/* Pilihan yang belum jalan dimatikan pakai atribut disabled bawaan, bukan
   sekadar diwarnai abu: yang disabled tidak bisa diklik, tidak kena tab
   keyboard, dan dibacakan sebagai nonaktif. Tetap ditampilkan supaya arah
   fiturnya kelihatan. */
.chip:disabled,
.seg-item:disabled {
  color: var(--disabled);
  background: var(--surface-disabled);
  cursor: not-allowed;
}

.soon { font: var(--text-body-5r); color: var(--disabled); }

.chip[aria-pressed="true"],
.seg-item[aria-pressed="true"] {
  border-color: var(--brand);
  color: var(--primary);
}

/* ── Judul dua baris di header ──
   Baris pertama menerangkan JENIS halamannya, baris kedua menerangkan YANG
   MANA — nama klub atau tanggalnya. Tanpa baris kedua, dua kompetisi di klub
   yang sama terlihat identik. */
.hd-stack { display: flex; flex-direction: column; margin-right: auto; min-width: 0; }
.hd-stack .hd-title { margin-right: 0; }

.hd-sub {
  font: var(--text-body-5r);
  color: var(--secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Checkbox ──
   Kotak bawaan browser SELALU berlatar putih, jadi di mode gelap dia jadi
   bidang putih menyala di tengah baris gelap. accent-color tidak menolong:
   itu cuma mewarnai keadaan TERCENTANG.

   Jadi tampilannya diambil alih: kotak kosong bergaris saja, dan baru terisi
   brand waktu dicentang. Centangnya digambar dari dua sisi border sebuah kotak
   yang diputar 45°, bukan dari font atau gambar, supaya ikut warna teksnya dan
   tidak perlu file tambahan. */
input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin: 0;
  display: grid;
  place-content: center;
  background: transparent;
  border: 1.5px solid var(--surface-border);
  border-radius: var(--radius-field);
  cursor: pointer;
}

/* Di dalam modal atau sheet, garisnya ikut token wadahnya: --surface-border
   nyaris tak terlihat di atas latar modal. */
.modal-box input[type="checkbox"],
.sheet input[type="checkbox"] { border-color: var(--modal-border); }

input[type="checkbox"]:checked {
  background: var(--brand);
  border-color: var(--brand);
}

input[type="checkbox"]:checked::after {
  content: "";
  width: 5px;
  height: 9px;
  border: solid var(--on-brand);
  border-width: 0 2px 2px 0;
  transform: translateY(-1px) rotate(45deg);
}

input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* ── Kepala halaman ──
   Blok identitas yang sama dipakai halaman klub dan halaman kompetisi: avatar
   kotak, nama, lalu satu atau dua baris keterangan. Bentuknya sengaja sama
   dengan baris di daftar klub halaman depan, supaya yang diklik di daftar dan
   yang muncul sesudahnya terbaca sebagai benda yang sama. */
.page-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--gap-section-base);
  padding: var(--gap-item-loose) var(--gap-layout-tight) var(--gap-section-base);
}

/* Warna lencana klub DITENTUKAN JS, dari palet pastel bersama di club-data.js
   (ClubData.paintCrest). Yang di sini cuma bentuk dan nilai cadangan, dipakai
   sekejap sebelum JS jalan dan di halaman yang tidak memuat club-data.js. */
.page-head-avatar {
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  background: var(--emphasis);
  border-radius: var(--radius-card);
  font: var(--text-body-3b);
  color: var(--secondary);
  object-fit: cover;
}

.page-head-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
/* Kepala halaman game (31 Okt 2026): nama dan tanggal rata kiri, dua panah
   pindah game berdampingan di kanan. Dulu panah di kedua ujung, dan panah kiri
   tepat di bawah Back di header sehingga terbaca sebagai tombol kembali.
   Ujung riwayat: panahnya redup dan tidak bisa ditekan, tetap ada supaya
   pasangan panahnya tidak berubah bentuk. */
.game-head { padding-left: var(--gap-layout-tight); padding-right: var(--gap-layout-tight); gap: var(--gap-section-base); }
.game-head-body { align-items: flex-start; text-align: left; }
.ct-nav { flex: 0 0 auto; display: flex; gap: var(--gap-item-loose); }
.game-head .page-head-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.game-head .page-head-meta { max-width: 100%; }
.ct-progress b { font: var(--text-body-5b); color: var(--primary); }
/* Panahnya dikotaki garis (19 Sep 2026), supaya terbaca sebagai tombol
   pindah game, bukan hiasan di pinggir judul. Garis ikut token container
   (surface), sudut ikut chip. Kotaknya 32px, lebih ringan dari icbtn 40px. */
.ct-step {
  width: 32px;
  height: 32px;
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-field);
}
.ct-step.is-off { color: var(--disabled); pointer-events: none; }
.page-head-name { font: var(--text-title-3); color: var(--primary); }
.page-head-meta {
  font: var(--text-body-5r);
  color: var(--secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Angka kemajuan di ujung kanan kepala halaman. Sebagai kolom tersendiri, bukan
   baris ketiga di bawah nama: kepala halaman tetap dua baris. */
.page-head-stat {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
}

.page-head-stat-num { font: var(--text-body-2b); color: var(--primary); }
.page-head-stat-label {
  font: var(--text-body-5r);
  color: var(--tertiary);
  text-transform: uppercase;
  letter-spacing: .04em;
}

/* ── Empty state ──
   Satu bentuk untuk semua: ikon redup, satu kalimat, dan satu baris penjelas
   kalau perlu. Ditengahkan di ruang yang tersisa — bukan menempel di atas —
   supaya panel kosong tidak terbaca seperti halaman yang gagal memuat. */
.empty {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--gap-item-loose);
  padding: var(--gap-layout-base) var(--gap-layout-tight);
  text-align: center;
}

/* Ikonnya ditaruh di dalam kotak --emphasis, bukan mengambang sendirian:
   ikon garis tipis di tengah ruang kosong besar terlihat seperti sisa render. */
.empty-icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: var(--radius-card);
  background: var(--emphasis);
  color: var(--tertiary);
}

.empty-title { font: var(--text-body-3b); color: var(--secondary); }
.empty-sub { font: var(--text-body-5r); color: var(--tertiary); }

/* Versi kecil untuk di dalam kartu atau sheet: bentuknya sama, ikon lebih kecil,
   dan tidak memanjang mengisi layar. Dibuat lewat EmptyState({ small: true }). */
.empty-sm { flex: 0 0 auto; padding: var(--gap-section-base) 0; }
.empty-sm .empty-icon { width: 40px; height: 40px; }
/* Satu tombol opsional di bawah keterangan. */
.empty-act { margin-top: var(--gap-item-loose); width: auto; padding-left: var(--gap-layout-tight); padding-right: var(--gap-layout-tight); }
a.empty-act { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
/* .empty memakai display:flex, jadi atribut hidden perlu ditegaskan. */
.empty[hidden] { display: none; }

/* Panel yang isinya cuma empty state ikut memanjang, supaya "di tengah" berarti
   di tengah layar, bukan di tengah tumpukan teks setinggi 40px. */
.app-main { display: flex; flex-direction: column; }
.app-main > * { flex: 0 0 auto; }
.app-main > .is-fill { flex: 1 1 auto; display: flex; flex-direction: column; }

/* Empty state yang duduk langsung di .app-main (halaman yang ISINYA cuma empty
   state, seperti Kabar) ikut memanjang juga. Tanpa ini dia kena `flex: 0 0 auto`
   di atas dan menclok di bawah header.

   Tingginya TIDAK pernah dihitung pakai JavaScript. .app sudah 100dvh dan
   seluruh rantainya flex, jadi "sisa ruang" itu urusan tata letak, bukan angka
   yang perlu diukur — dan angka hasil ukuran pasti basi begitu bilah alamat
   Safari menyusut waktu discroll, layar diputar, atau papan ketik muncul. */
.app-main > .empty { flex: 1 1 auto; }

/* ── Rincian poin, dibuka sebagai bottom sheet ── */

/* Sheet menempel ke ARTBOARD, bukan ke viewport: di desktop halaman ini cuma
   393px di tengah layar, kalau fixed ke viewport sheet-nya melebar keluar
   bingkai. .app sudah overflow:hidden, jadi sheet ikut terpotong rapi. */
.app { position: relative; }

.sheet-backdrop {
  position: absolute;
  inset: 0;
  background: var(--overlay);
  z-index: 10;
}

.sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 11;
  max-height: 80%;
  display: flex;
  flex-direction: column;
  background: var(--modal);
  border-top-left-radius: var(--radius-modal);
  border-top-right-radius: var(--radius-modal);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

.sheet-grab {
  flex: 0 0 auto;
  width: 36px;
  height: 4px;
  margin: 8px auto 0;
  border-radius: var(--radius-pill);
  background: var(--modal-border);
}

/* Kepala sheet sedikit lebih besar (15 Sep 2026): judul setara judul kepala
   halaman (heading-1), keterangan 13px, avatar 40px. Berlaku untuk semua sheet. */
.sheet-hd {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--gap-section-base);
  padding: var(--gap-section-base) var(--gap-item-loose) var(--gap-section-base) var(--gap-layout-tight);
}

.sheet-title { flex: 1 1 auto; min-width: 0; font: var(--text-heading-1); color: var(--primary); }
.sheet-sub { font: var(--text-body-4r); color: var(--secondary); }

/* Tanpa garis pemisah antara kepala sheet dan isinya: judul dan isi sudah
   terpisah oleh jarak, dan garis di situ cuma memotong panel jadi dua kotak. */
.sheet-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: var(--gap-item-base) var(--gap-layout-tight) var(--gap-layout-base);
  /* Ruang bawah dilebihkan: sheet berhenti tepat di tepi layar, dan di ponsel
     jempol menutupi baris terakhir kalau isinya mepet. */
  padding-bottom: calc(var(--gap-layout-base) + env(safe-area-inset-bottom, 0px));
}

/* Avatar di kepala sheet. Nama saja kurang: waktu berpindah-pindah pemain
   lewat panah di kaki, wajahnya yang paling cepat dikenali, bukan tulisannya. */
.sheet-face {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  background: var(--emphasis);
  border-radius: var(--radius-card);
}

/* ── Kaki sheet: geser ke sebelah ──
   Yang ditulis NAMA ORANGNYA, bukan "3 of 7". Nomor urut memberitahu posisi
   yang sudah kelihatan di tabel di belakangnya; nama memberitahu apa yang akan
   kamu dapat kalau ditekan, dan itu yang sebenarnya ditanyakan jempol.
   DI LUAR .sheet-body yang bisa di-scroll, supaya tombolnya tidak ikut hanyut
   ke bawah bersama isinya. */
.sheet-nav {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-item-loose);
  padding: var(--gap-section-tight) var(--gap-item-loose);
  padding-bottom: calc(var(--gap-section-tight) + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--modal-border);
}

/* Tombol berlabel, bukan ikon telanjang: panah + nama. */
.sheet-nav-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-item-base);
  min-width: 0;
  max-width: 45%;
  padding: var(--gap-item-loose) var(--gap-section-base);
  font: var(--text-body-4b);
  color: var(--primary);
  background: transparent;
  border: 0;
  border-radius: var(--radius-field);
  cursor: pointer;
}
.sheet-nav-btn:hover { background: var(--surface-hover); }

/* Nama panjang dipotong, panahnya tidak ikut menyusut. */
.sheet-nav-btn span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sheet-nav-btn svg { flex: 0 0 auto; color: var(--icon); }

/* Di ujung daftar tombolnya disembunyikan, bukan diputar balik ke awal:
   melompat dari juru kunci ke juara terasa seperti salah tekan.
   visibility, bukan display: tombol yang tersisa harus tetap di ujungnya
   sendiri, tidak melompat ke tengah. */
.sheet-nav-btn.is-off { visibility: hidden; }

/* ── Penanda menang/kalah ──
   Satu huruf di kotak kecil, cukup untuk dipindai dari atas ke bawah. Dipakai
   riwayat head-to-head dan rincian poin di sheet klasemen; dulu cuma ada di
   h2h.html dan rincian poin tidak punya penanda sama sekali, jadi menang atau
   kalah harus ditebak dari tanda plus-minusnya. */
.wl {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-field);
  font: var(--text-body-5b);
  color: var(--on-brand);
}
.wl.is-win  { background: var(--positive); }
.wl.is-loss { background: var(--negative); }

/* ── Banner keterangan (.hint) ──
   Satu kalimat di bawah pilihan (chip kategori H2H, mode klasemen) yang
   menjelaskan apa yang sedang ditampilkan. Aturan banner: ikon rata tengah
   vertikal walau teksnya dua baris, teks --primary, yang berwarna cuma ikon
   dan latar tint-nya. */
.hint {
  display: flex;
  align-items: center;
  gap: var(--gap-item-loose);
  padding: var(--gap-item-loose) var(--gap-section-base);
  background: var(--surface-info);
  border-radius: var(--radius-card);
  /* body-4, bukan body-5: ini kalimat yang dibaca, bukan keterangan kecil di
     pojok. 11px di atas latar tint terlalu berat dibaca. */
  font: var(--text-body-4r);
  color: var(--primary);
}
.hint svg { flex: 0 0 auto; color: var(--info); }
.hint[hidden] { display: none; }

/* ── Baris kesimpulan di dalam sheet ──
   Diberi latar --emphasis supaya berhenti terbaca sebagai baris data biasa.
   Ini angka yang dicari orang waktu membuka sheet-nya; kalau tampil sama
   dengan baris di atasnya, dia tenggelam di antara daftar. */
.sheet-total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-section-base);
  margin-top: var(--gap-section-loose);
  padding: var(--gap-section-base) var(--gap-section-loose);
  background: var(--emphasis);
  border-radius: var(--radius-card);
}

.sheet-total-label { font: var(--text-body-4b); color: var(--secondary); }
.sheet-total-val { font: var(--text-title-3); color: var(--primary); }

/* Dua ringkasan berdampingan, sama lebar: Average dan W-L, urutannya sama
   dengan segmented di atas tabelnya. Di kotak setengah lebar, label ditumpuk
   di atas angka; sejajar kiri-kanan tidak muat. */
/* ── Share result (share-card.js) ──
   Pratinjau kartu 4:5 selebar sheet, pilihan warna kartu di bawahnya, lalu
   tombol Share. Sheet ini lebih tinggi dari sheet lain karena gambarnya. */
.share-sheet { max-height: 92%; }
.share-sheet .sheet-body { display: flex; flex-direction: column; gap: var(--gap-section-base); }
.share-preview {
  aspect-ratio: 4 / 5;
  max-width: 100%;
  max-height: 52vh;
  margin: 0 auto;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--emphasis);
}
.share-preview img { display: block; width: 100%; height: 100%; object-fit: contain; }
.share-opts { display: flex; justify-content: center; }

/* ── Crop foto profil (photo-crop.js) ──
   Kotak persegi dengan sudut sama seperti avatar di seluruh app. touch-action
   none: geser dan cubit di kotak ini milik alat crop, bukan milik halaman. */
.pc-sheet .sheet-body { display: flex; flex-direction: column; gap: var(--gap-section-base); }
.pc-stage {
  width: 100%;
  max-width: 320px;
  aspect-ratio: 1 / 1;
  margin: 0 auto;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--emphasis);
  touch-action: none;
  cursor: grab;
}
.pc-img { display: block; width: 100%; height: 100%; }
.pc-zoom { width: 100%; max-width: 320px; margin: 0 auto; accent-color: var(--brand); }
.pc-acts { display: flex; gap: var(--gap-item-loose); }
.pc-acts > * { flex: 1 1 0; }
.share-sheet .seg-mini { border-color: var(--modal-border); }
.share-sheet .seg-mini button + button { border-left-color: var(--modal-border); }

.sheet-totals { display: flex; gap: var(--gap-item-loose); margin-top: var(--gap-section-loose); }
.sheet-totals .sheet-total {
  flex: 1 1 0;
  min-width: 0;
  margin-top: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--gap-item-tight);
}

/* ── Pemilih gedung (venue-picker.js) ── */
.vp-body { display: flex; flex-direction: column; gap: var(--gap-section-base); padding-bottom: var(--gap-section-base); }
.vp-results { display: flex; flex-direction: column; min-height: 48px; }
.vp-note { font: var(--text-body-5r); color: var(--tertiary); padding: var(--gap-item-loose) 0; }
.vp-acts { display: flex; gap: var(--gap-item-loose); }
.vp-acts > * { flex: 1 1 0; }

/* Daftar home base milik klub: nama, kota, dan tombol lepas. */
.hb-list { list-style: none; margin: 0; padding: 0; }
.hb-item { display: flex; align-items: center; gap: var(--gap-section-base); padding: var(--gap-item-loose) 0; border-bottom: 1px solid var(--divider); }
.hb-list li:last-child .hb-item { border-bottom: 0; }
.hb-item-body { flex: 1 1 auto; min-width: 0; }
.hb-item-name { display: block; font: var(--text-body-3b); color: var(--primary); }
.hb-item-city { display: block; font: var(--text-body-5r); color: var(--secondary); }
.hb-remove { flex: 0 0 auto; font: var(--text-body-5b); color: var(--negative); background: transparent; border: 0; padding: 0; cursor: pointer; }

/* Baris pilihan yang berupa tautan (misalnya di lembar notifikasi) tidak
   boleh bergaris bawah: bentuknya harus sama dengan baris tombol. */
a.opt { text-decoration: none; }

/* Baris alamat di sheet Share: alamatnya ditulis penuh dan boleh patah, supaya
   yang menyalin tahu persis apa yang disalin. */
.sh-link {
  padding: var(--gap-section-base);
  margin-bottom: var(--gap-section-base);
  border: 1px solid var(--modal-border);
  border-radius: var(--radius-card);
  font: var(--text-body-4r);
  color: var(--secondary);
  overflow-wrap: anywhere;
}
.sh-wa { margin-top: var(--gap-item-loose); display: flex; align-items: center; justify-content: center; text-decoration: none; }

/* ── Toast ──
   Kabar singkat yang TIDAK memblokir layar, pengganti window.alert untuk
   kegagalan dan peringatan aturan. Ditaruh di dalam .app (seperti sheet), jadi
   di desktop dia ikut bingkai artboard, bukan melebar ke seluruh layar.
   Di atas sheet (z-index 11) supaya kabar dari dalam sheet tetap terbaca. */
.toast {
  position: absolute;
  left: var(--gap-layout-tight);
  right: var(--gap-layout-tight);
  bottom: calc(var(--gap-layout-tight) + env(safe-area-inset-bottom, 0px));
  z-index: 12;
  display: flex;
  align-items: flex-start;
  gap: var(--gap-section-base);
  padding: var(--gap-section-base) var(--gap-layout-tight);
  border-radius: var(--radius-card);
  background: var(--primary);
  color: var(--surface);
  font: var(--text-body-3r);
}
/* Halaman bermenu bawah: toast duduk DI ATAS menu, bukan menutupinya. */
.app:has(> .nav) .toast { bottom: calc(64px + var(--gap-item-loose) + env(safe-area-inset-bottom, 0px)); }
.toast.is-bad { background: var(--negative); color: var(--white); }
.toast-text { flex: 1 1 auto; min-width: 0; }
.toast-x {
  flex: 0 0 auto;
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: var(--text-body-3b);
  cursor: pointer;
  opacity: .8;
}


/* ── Tab bergeser (dipakai club.html, index.html, profile.html) ──
   Kelima panel berjajar dalam satu jalur; scroll-snap membuatnya berhenti pas
   di tepi, jadi tidak ada panel yang berhenti separuh. Tiap panel punya gulir
   vertikalnya SENDIRI: posisi baca di Ranking tidak ikut terbawa waktu pindah
   ke Members, dan kepala daftar yang menempel tetap menempel di panelnya. */
.app-main:has(> .tab-track) { overflow-y: hidden; }
.tab-track {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  /* Geseran tidak merembet ke halaman di belakangnya (di iOS: swipe back). */
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.tab-track::-webkit-scrollbar { display: none; }
/* Tab biasa (SwipeTabs swipe:false): panel yang aktif saja yang ada di jalur,
   jadi jalurnya tidak perlu bisa digulir ke samping sama sekali. */
.tab-track.is-static {
  overflow-x: hidden;
  scroll-snap-type: none;
}
.tab-slide {
  flex: 0 0 100%;
  min-width: 0;
  overflow-y: auto;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  display: flex;
  flex-direction: column;
}
.tab-slide > * { flex: 0 0 auto; }
/* .app-main > .is-fill tidak lagi kena (panel sekarang anak jalur), jadi
   aturan yang sama dipasang ulang di sini. */
.tab-slide.is-fill,
.tab-slide > .is-fill { flex: 1 1 auto; display: flex; flex-direction: column; }
.tab-slide > .empty { flex: 1 1 auto; }

/* ── Confirm (shell.js) ── konfirmasi di bottom sheet: keterangan lalu dua
   tombol sejajar, Batal bergaris dan aksi utama block. */
.cf-sheet .sheet-body { display: flex; flex-direction: column; gap: var(--gap-section-base); }
.cf-sub { font: var(--text-body-3r); color: var(--primary); }
.cf-acts { display: flex; gap: var(--gap-item-loose); }
.cf-acts > * { flex: 1 1 0; }
