/*
 * Star Performance — satu-satunya sumber kebenaran gaya dan warna.
 *
 * Jangan menuliskan nilai warna langsung di dalam view. Seluruh warna hidup sebagai
 * custom property di blok :root di bawah, supaya perubahan palet cukup dilakukan
 * sekali di sini. Palet resminya tercatat di CLAUDE.md bagian "Palet warna".
 *
 * Porsi warna: putih dan krem dominan; oranye hanya untuk elemen penarik perhatian
 * (kepala aplikasi, tombol utama, penanda aktif).
 *
 * ---------------------------------------------------------------------------
 * TENTANG WARNA TURUNAN
 * ---------------------------------------------------------------------------
 * Palet tidak bertambah. Seluruh nada tambahan — latar lembut, garis, bayangan —
 * dibuat dengan color-mix() DARI token yang sudah disepakati, bukan dari nilai heksa
 * baru. Dengan begitu mengganti satu token palet ikut menggeser seluruh turunannya,
 * dan tidak ada warna liar yang lolos tanpa tercatat di sini.
 */

:root {
    /*
     * TEMA GELAP.
     *
     * Baseline semula menetapkan "putih dan krem dominan, oranye hanya untuk elemen
     * penarik perhatian". Keputusan itu DIUBAH atas permintaan pemilik sistem: layar
     * pemantauan dipakai berjam-jam di ruang latihan, dan tema gelap dengan aksen
     * menyala membuat angka lebih menonjol daripada latarnya.
     *
     * Yang TIDAK berubah: keluarga oranye tetap aksen tunggalnya. Yang dibalik hanya
     * peran terang dan gelap — oranye tidak diganti, tidak ditambah warna merek baru.
     *
     * Halaman cetak tetap terang; lihat blok @media print di bawah, yang menyetel ulang
     * seluruh token ini ke nilai terang. Mencetak latar hitam ke kertas menghabiskan
     * tinta dan membuat laporan tidak terbaca.
     */

    /* --- Aksen: keluarga oranye yang sudah disepakati, tidak berubah --- */
    --sp-aksen: #FF6B00;        /* aksen utama: tautan, sorotan, garis penegas */
    --sp-aksen-tua: #E65100;    /* tombol dan kepala aplikasi */

    /* --- Permukaan gelap. Latar halaman hitam pekat; kartu sedikit terangkat
           supaya batas panelnya tetap terbaca tanpa perlu garis tebal. --- */
    --sp-latar: #000000;        /* latar halaman */
    --sp-kartu: #0D0D0D;        /* kartu dan permukaan konten */
    /* Permukaan lencana dan kepala tabel dibiarkan sedikit hangat: di atas hitam
       pekat, oranye pada lencana akan tampak melayang bila alasnya abu murni. */
    --sp-krem: #1F160F;

    /* --- Teks dan netral pendukung --- */
    --sp-teks: #F6EFE7;
    --sp-teks-redup: #A29485;
    --sp-galat: #FF6B6B;
    --sp-sukses-latar: #0E2A20;
    --sp-sukses-garis: #1C6B4B;
    --sp-sukses-teks: #4ADE9B;
    --sp-nonaktif-latar: #241C17;

    /* Cahaya aksen: dipakai sangat hemat — hanya pada tombol utama, penanda aktif,
       dan batang grafik. Neon di mana-mana justru menghapus penekanannya. */
    --sp-cahaya: 0 0 12px color-mix(in srgb, var(--sp-aksen) 45%, transparent);

    /* --- Turunan: campuran token di atas, bukan warna baru --- */
    --sp-garis: color-mix(in srgb, var(--sp-teks) 14%, var(--sp-kartu));
    --sp-garis-samar: color-mix(in srgb, var(--sp-teks) 8%, var(--sp-kartu));

    /*
     * Warna PEMBANDING WAKTU pada laporan tahunan: tahun lalu dan tahun ini.
     *
     * Sengaja BUKAN dari keluarga oranye merek maupun dari hijau-merah keadaan. Yang
     * dibedakan di sini adalah waktu, bukan baik-buruk; memakai hijau-merah akan membuat
     * "tahun lalu" terbaca sebagai keadaan buruk pada indikator apa pun.
     *
     * Keduanya dipilih agar tetap berbeda gelap-terangnya ketika pencetak kantor
     * mengeluarkannya sebagai abu-abu.
     */
    --sp-tahun-lalu: #4C7FB8;
    --sp-tahun-kini: #E8791A;
    --sp-aksen-latar: color-mix(in srgb, var(--sp-aksen) 16%, var(--sp-kartu));
    --sp-galat-latar: color-mix(in srgb, var(--sp-galat) 14%, var(--sp-kartu));
    --sp-galat-garis: color-mix(in srgb, var(--sp-galat) 40%, var(--sp-kartu));
    --sp-sorot-baris: color-mix(in srgb, var(--sp-teks) 5%, var(--sp-kartu));
    /* Di tema gelap bayangan hitam tidak terlihat; kedalaman dibuat dari garis tipis. */
    --sp-bayang: 0 1px 0 color-mix(in srgb, var(--sp-teks) 6%, transparent);
    --sp-bayang-naik: 0 10px 28px color-mix(in srgb, #000000 55%, transparent);

    /*
     * Memberi tahu peramban bahwa halaman ini gelap.
     *
     * Bukan sekadar keterangan: widget yang digambar peramban sendiri — bilah gulir,
     * pemilih tanggal, panah select, sorotan autofill — tidak dapat diwarnai lewat CSS
     * biasa. Tanpa baris ini bilah gulir bilah samping keluar putih terang setinggi
     * layar di atas panel hitam, dan itu bagian paling mencolok di seluruh antarmuka.
     *
     * Blok @media print menyetelnya balik ke light; kertas selalu terang.
     */
    color-scheme: dark;

    /* --- Bentuk dan jarak --- */
    --sp-lengkung: .8rem;
    --sp-lengkung-kecil: .45rem;
    --sp-sela: 1.25rem;
    --sp-sela-besar: 2rem;
    --sp-sisi: 2rem;        /* padding kiri-kanan wilayah isi */
    --sp-lebar-sisi: 15rem; /* lebar bilah navigasi */
}

* { box-sizing: border-box; }

/* ===========================================================================
   BILAH GULIR
   ---------------------------------------------------------------------------
   color-scheme di atas sudah membuatnya gelap; di sini ia dirampingkan supaya
   tidak lagi merebut lebar dari isi panel yang digulirnya. Dua penulisan sebab
   dua mesin: `scrollbar-*` untuk Firefox, `::-webkit-scrollbar` untuk Chrome,
   Edge, dan Safari.

   Ibu jarinya dibuat dari token yang sudah ada, bukan abu-abu baru — dan ia
   sengaja TIDAK memakai warna aksen: bilah gulir adalah perkakas, bukan sesuatu
   yang perlu ditarik perhatiannya.
   =========================================================================== */

* {
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--sp-teks) 22%, transparent) transparent;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--sp-teks) 20%, transparent);
    border-radius: 999px;
    /* Batas bening menyisakan celah di kiri-kanan ibu jari; tanpa itu ia menempel
       rapat ke tepi panel dan terbaca sebagai garis pembatas, bukan bilah gulir. */
    border: 2px solid transparent;
    background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
    background: color-mix(in srgb, var(--sp-teks) 34%, transparent);
    background-clip: padding-box;
}

body {
    margin: 0;
    font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
    background: var(--sp-latar);
    color: var(--sp-teks);
    font-size: 15px;
    line-height: 1.5;
}

/* ===========================================================================
   KERANGKA: bilah samping + kepala + isi
   ---------------------------------------------------------------------------
   Navigasi dipindah ke bilah samping karena jumlah tautannya sudah belasan;
   berjajar di satu baris atas, tautan itu saling berdesakan dan kehilangan
   pengelompokan. Bilah samping berlatar putih supaya oranye tetap hanya menjadi
   satu bidang lebar — kepala aplikasi — sesuai porsi warna di CLAUDE.md.
   =========================================================================== */

.cangkang {
    min-height: 100vh;
    display: grid;
    grid-template-columns: var(--sp-lebar-sisi) minmax(0, 1fr);
}

.sisi {
    background: var(--sp-kartu);
    border-right: 1px solid var(--sp-garis);
    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: 0 0 1.5rem;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.sisi .merek {
    display: block;
    padding: 1.1rem var(--sp-sela) 1rem;
    font-size: 1rem;
    font-weight: 800;
    letter-spacing: .02em;
    color: var(--sp-aksen-tua);
    text-decoration: none;
    border-bottom: 1px solid var(--sp-garis);
    margin-bottom: .75rem;
}
.sisi .merek span { display: block; font-size: .7rem; font-weight: 600; color: var(--sp-teks-redup); letter-spacing: .08em; text-transform: uppercase; }

.sisi-kelompok {
    padding: .9rem var(--sp-sela) .25rem;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--sp-teks-redup);
}

.sisi a.tautan {
    display: block;
    padding: .45rem var(--sp-sela);
    margin: 0 .5rem;
    border-radius: var(--sp-lengkung-kecil);
    color: var(--sp-teks);
    text-decoration: none;
    font-size: .9rem;
    font-weight: 500;
    border-left: 3px solid transparent;
}
.sisi a.tautan:hover { background: var(--sp-latar); }
/* Penanda halaman aktif: satu-satunya oranye di bilah ini. */
.sisi a.tautan.aktif {
    background: var(--sp-aksen-latar);
    border-left-color: var(--sp-aksen);
    color: var(--sp-aksen);
    font-weight: 700;
    box-shadow: inset 3px 0 8px color-mix(in srgb, var(--sp-aksen) 22%, transparent);
}

/* ---------------------------------------------------------------------------
   TAUTAN BALIK KE PORTAL

   margin-top:auto mendorongnya ke DASAR bilah: .sisi adalah flex column, jadi
   tautan ini duduk di bawah berapa pun banyaknya menu yang dilihat perannya.
   Tanpa itu ia menempel di bawah tautan terakhir, dan pengelola sistem yang
   hanya punya satu menu akan melihatnya nyaris di puncak.

   Diredupkan dan tidak pernah beroranye: oranye di bilah ini sudah punya satu
   arti, yaitu halaman yang sedang dibuka. Tautan yang membawa KELUAR aplikasi
   tidak boleh terbaca seperti halaman aktif.
   --------------------------------------------------------------------------- */
.sisi a.tautan-portal {
    margin-top: auto;
    display: flex;
    align-items: center;
    gap: .5rem;
    /* Sasaran sentuh 44px: pelatih membukanya dari ponsel di pinggir lapangan. */
    min-height: 44px;
    padding: .55rem var(--sp-sela);
    margin-left: .5rem;
    margin-right: .5rem;
    border-top: 1px solid var(--sp-garis);
    border-radius: var(--sp-lengkung-kecil);
    color: var(--sp-teks-redup);
    text-decoration: none;
    font-size: .82rem;
    font-weight: 600;
}
.sisi a.tautan-portal:hover {
    background: var(--sp-latar);
    color: var(--sp-teks);
}
.sisi a.tautan-portal svg { width: 1rem; height: 1rem; flex: none; }

/* Layar masuk: cabang tamu tidak menggambar bilah samping sama sekali. */
.tautan-portal-tamu {
    text-align: center;
    margin: 1.25rem auto 0;
    font-size: .82rem;
}
.tautan-portal-tamu a {
    display: inline-block;
    min-height: 44px;
    line-height: 44px;
    padding: 0 .75rem;
    color: var(--sp-teks-redup);
    text-decoration: none;
    font-weight: 600;
}
.tautan-portal-tamu a:hover { color: var(--sp-aksen); text-decoration: underline; }

/* ---------------------------------------------------------------------------
   LACI NAVIGASI (hanya hidup di layar sempit)
   ---------------------------------------------------------------------------
   Pemicunya kotak centang, bukan JavaScript: laci yang digerakkan skrip akan
   tertutup rapat bila skripnya gagal dimuat, dan di ponsel itu berarti seluruh
   navigasi hilang. Kotak centang selalu bekerja dan menutup sendiri saat halaman
   berpindah.

   Kotak centangnya disembunyikan secara VISUAL, bukan dengan display:none atau
   atribut hidden — keduanya mengeluarkannya dari urutan tab, sehingga laci tidak
   lagi dapat dibuka lewat papan ketik.
   --------------------------------------------------------------------------- */

.pemicu-navigasi {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Di layar lebar bilah samping selalu terbuka, jadi keduanya tidak pernah tampil. */
.tombol-navigasi { display: none; }
.tirai { display: none; }

.utama { min-width: 0; display: flex; flex-direction: column; }

/* Kepala aplikasi — satu-satunya bidang beroranye penuh. */
.puncak {
    background: var(--sp-aksen-tua);
    color: var(--sp-kartu);
    padding: .6rem var(--sp-sisi);
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    position: sticky;
    top: 0;
    z-index: 20;
}
.puncak .label-halaman {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    opacity: .85;
}
.puncak .kanan { margin-left: auto; display: flex; align-items: center; gap: .75rem; font-size: .85rem; }
.puncak a { color: var(--sp-kartu); }

/* Chip konteks di kepala, sepadan dengan "18 Athletes · 4.261 Records" pada rujukan. */
.cip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .18rem .6rem;
    border-radius: 999px;
    font-size: .75rem;
    font-weight: 600;
    background: color-mix(in srgb, var(--sp-kartu) 22%, transparent);
    color: var(--sp-kartu);
    white-space: nowrap;
}

main { padding: var(--sp-sela-besar) var(--sp-sisi) 4rem; max-width: 82rem; width: 100%; }

/* ===========================================================================
   JUDUL
   =========================================================================== */

.judul-halaman { margin-bottom: var(--sp-sela-besar); }
.judul-halaman .aksi { margin-top: .75rem; }

h1 { font-size: 1.45rem; line-height: 1.25; margin: 0 0 .35rem; letter-spacing: -.01em; }
h1 + .redup { margin-top: 0; }

/* Judul bagian: huruf kecil berspasi lebar, dengan garis rambut di bawahnya.
   Bentuk ini yang membuat kartu terbaca sebagai panel, bukan sekadar kotak. */
h2 {
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--sp-teks-redup);
    margin: 0 0 .85rem;
    padding-bottom: .55rem;
    border-bottom: 1px solid var(--sp-garis-samar);
}
h3 { font-size: .95rem; margin: 1.1rem 0 .5rem; }
h4 { font-size: .8rem; margin: .9rem 0 .35rem; color: var(--sp-teks-redup); font-weight: 700; }

a { color: var(--sp-aksen-tua); text-underline-offset: .15em; }
a:hover { color: var(--sp-aksen); }

/* ===========================================================================
   KARTU DAN PAPAN ANGKA
   =========================================================================== */

.kartu {
    background: var(--sp-kartu);
    border: 1px solid var(--sp-garis);
    border-radius: var(--sp-lengkung);
    /* Dilonggarkan: isi kartu sebelumnya menempel ke tepinya dan terbaca sesak. */
    padding: 1.4rem 1.6rem 1.6rem;
    margin-bottom: var(--sp-sela);
    box-shadow: var(--sp-bayang);
}
.kartu > :last-child { margin-bottom: 0; }

/*
 * Kepala kelompok tahun pada daftar sesi.
 *
 * Tahunnya ditulis besar dan cacah sesinya menyusul redup di sebelahnya: yang dicari
 * mata saat menggulir adalah angka tahunnya, bukan keterangan di belakangnya. Garis
 * aksen tipis di bawahnya memisahkan kepala dari tabelnya tanpa menambah satu blok
 * berlatar lagi -- kartunya sendiri sudah menjadi pembatas antar tahun.
 */
.kepala-tahun {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    margin: 0 0 .75rem;
    padding-bottom: .4rem;
    border-bottom: 1px solid var(--sp-aksen);
    font-size: 1.05rem;
    letter-spacing: .04em;
}
.kepala-tahun .redup { font-size: .8rem; font-weight: 400; }

/* Papan kartu angka: menyesuaikan diri, tanpa perlu menyetel kolom di view. */
.papan {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: var(--sp-sela);
    margin-bottom: var(--sp-sela);
}

/*
 * Kartu angka bergaris aksen di sisi atas.
 *
 * Garis itu BUKAN hiasan: warnanya menyatakan keadaan — merah perlu perhatian,
 * oranye perlu dipantau, hijau aman — sehingga sebaris kartu dapat dibaca sekilas
 * tanpa membaca angkanya lebih dulu.
 */
.kartu-nilai {
    background: var(--sp-kartu);
    border: 1px solid var(--sp-garis);
    border-top: 3px solid var(--sp-teks-redup);
    border-radius: var(--sp-lengkung);
    padding: .9rem 1.1rem 1rem;
    box-shadow: var(--sp-bayang);
    display: flex;
    flex-direction: column;
    gap: .15rem;
    min-width: 0;
}
.kartu-nilai .label {
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--sp-teks-redup);
}
.kartu-nilai .angka { font-size: 1.75rem; font-weight: 800; line-height: 1.1; letter-spacing: -.02em; }
.kartu-nilai .satuan { font-size: .8rem; color: var(--sp-teks-redup); }

.kartu-nilai.aksen { border-top-color: var(--sp-aksen); }
.kartu-nilai.aksen .angka { color: var(--sp-aksen-tua); }
.kartu-nilai.sukses { border-top-color: var(--sp-sukses-teks); }
.kartu-nilai.sukses .angka { color: var(--sp-sukses-teks); }
.kartu-nilai.galat { border-top-color: var(--sp-galat); }
.kartu-nilai.galat .angka { color: var(--sp-galat); }
.kartu-nilai.krem { border-top-color: var(--sp-krem); }

/* ===========================================================================
   GOLONGAN DAFTAR (triase: perlu perhatian / pantau / aman)
   =========================================================================== */

.golongan { margin-bottom: var(--sp-sela); }
.golongan > .kepala {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .5rem .9rem;
    border-radius: var(--sp-lengkung) var(--sp-lengkung) 0 0;
    border: 1px solid var(--sp-garis);
    border-bottom: 0;
    border-left: 4px solid var(--sp-teks-redup);
    background: var(--sp-sorot-baris);
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--sp-teks-redup);
}
.golongan > .kepala .jumlah {
    margin-left: auto;
    background: var(--sp-kartu);
    border: 1px solid var(--sp-garis);
    border-radius: 999px;
    padding: 0 .5rem;
    font-size: .75rem;
}
.golongan > .isi {
    border: 1px solid var(--sp-garis);
    border-radius: 0 0 var(--sp-lengkung) var(--sp-lengkung);
    background: var(--sp-kartu);
    box-shadow: var(--sp-bayang);
    overflow: hidden;
}

.golongan.galat > .kepala { border-left-color: var(--sp-galat); color: var(--sp-galat); background: var(--sp-galat-latar); }
.golongan.aksen > .kepala { border-left-color: var(--sp-aksen); color: var(--sp-aksen-tua); background: var(--sp-aksen-latar); }
.golongan.sukses > .kepala { border-left-color: var(--sp-sukses-teks); color: var(--sp-sukses-teks); background: var(--sp-sukses-latar); }

/* Satu baris daftar: nama, lencana, lalu keterangan pendukung. */
.baris-ringkas {
    display: flex;
    align-items: baseline;
    gap: .55rem;
    flex-wrap: wrap;
    padding: .7rem .9rem;
    border-bottom: 1px solid var(--sp-garis-samar);
}
.baris-ringkas:last-child { border-bottom: 0; }
.baris-ringkas:hover { background: var(--sp-sorot-baris); }
.baris-ringkas .nama { font-weight: 700; }
.baris-ringkas .keterangan { flex-basis: 100%; font-size: .85rem; color: var(--sp-teks-redup); }
.baris-ringkas .kanan { margin-left: auto; font-size: .85rem; color: var(--sp-teks-redup); }

/* ===========================================================================
   TABEL
   =========================================================================== */

table { width: 100%; border-collapse: collapse; font-size: .9rem; }
th, td { text-align: left; padding: .5rem .6rem; border-bottom: 1px solid var(--sp-garis-samar); }
th {
    color: var(--sp-teks-redup);
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .09em;
    border-bottom: 1px solid var(--sp-garis);
    white-space: nowrap;
}
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--sp-sorot-baris); }
/* Tabel keterangan dua kolom (kepala di kiri) tidak perlu sorotan baris. */
tbody th { width: 12rem; text-transform: none; letter-spacing: 0; font-size: .8rem; }

/* Pembungkus untuk tabel lebar; menggulir sendiri alih-alih melebarkan halaman. */
.gulir { overflow-x: auto; }

/* ===========================================================================
   LENCANA, CHIP DELTA, DAN SOROTAN
   =========================================================================== */

.lencana {
    display: inline-block;
    padding: .1rem .5rem;
    border-radius: 999px;
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .02em;
    background: var(--sp-krem);
    color: var(--sp-aksen-tua);
    white-space: nowrap;
}
.lencana.nonaktif { background: var(--sp-nonaktif-latar); color: var(--sp-teks-redup); }
.lencana.sukses { background: var(--sp-sukses-latar); color: var(--sp-sukses-teks); }
.lencana.galat { background: var(--sp-galat-latar); color: var(--sp-galat); }

/*
 * Chip perubahan. Arah panah dan warnanya dibaca bersama, tidak sendiri-sendiri:
 * warna saja tidak cukup bagi yang sulit membedakan warna.
 */
.delta {
    display: inline-block;
    padding: .05rem .45rem;
    border-radius: var(--sp-lengkung-kecil);
    font-size: .72rem;
    font-weight: 700;
    background: var(--sp-nonaktif-latar);
    color: var(--sp-teks-redup);
    white-space: nowrap;
}
.delta-ket { font-weight: 400; opacity: .75; }
.kartu-nilai .delta { margin-left: .25rem; }
.delta.naik { background: var(--sp-sukses-latar); color: var(--sp-sukses-teks); }
.delta.turun { background: var(--sp-galat-latar); color: var(--sp-galat); }

.redup { color: var(--sp-teks-redup); font-size: .875rem; }
.sorot { font-size: 1.6rem; font-weight: 800; color: var(--sp-aksen-tua); letter-spacing: -.02em; margin: .2rem 0; }

/* Keadaan kosong: bukan baris tabel yang menyamar, melainkan pesan yang jelas. */
.kosong { color: var(--sp-teks-redup); font-size: .9rem; padding: .9rem 0; }

/* ===========================================================================
   FORMULIR DAN TOMBOL
   =========================================================================== */

label { display: block; margin: .75rem 0 .25rem; font-weight: 600; font-size: .82rem; }

/*
 * Daftarnya menyebut month, search, email, dan tel juga.
 *
 * Tanpa ketiganya peramban menggambar isian itu dengan gaya bawaannya: lebarnya
 * mengikuti isi, bukan kolomnya, dan latarnya terang di atas kartu gelap. Pada kartu
 * "Laporan cetak" akibatnya paling terlihat — pemilih bulan menyusut jadi sepertiga
 * lebar tombol di bawahnya, dan barisnya terbaca seperti tata letak yang belum jadi.
 */
input[type=text], input[type=password], input[type=date], input[type=number],
input[type=month], input[type=search], input[type=email], input[type=tel],
input[type=file], select, textarea {
    width: 100%;
    padding: .6rem .75rem;
    border: 1px solid var(--sp-garis);
    border-radius: var(--sp-lengkung-kecil);
    /* Sedikit lebih gelap daripada kartunya supaya isian terbaca sebagai isian,
       bukan sebagai bidang kosong. */
    background: var(--sp-latar);
    color: var(--sp-teks);
    font: inherit;
    font-size: .9rem;
}
/*
 * Ikon pemilih tanggal dan panah select TIDAK lagi ditambal di sini.
 *
 * Sebelumnya ikon kalender dibalik warnanya (filter: invert) dan select diberi
 * color-scheme sendiri, sebab halaman belum menyatakan dirinya gelap. Sekarang
 * `color-scheme: dark` di :root sudah membuat peramban menggambar keduanya terang
 * dengan sendirinya — mempertahankan pembalikan itu justru mengembalikannya
 * menjadi hitam di atas latar hitam.
 */
textarea { min-height: 3.5rem; }
/*
 * PEMILIH JAMAK pada ubin laporan.
 *
 * <select multiple> mewarisi padding pemilih tunggal, dan padding setebal itu di atas
 * daftar bergulir menyisakan ruang kosong di kedua sisi tiap barisnya. Yang dibutuhkan di
 * sini justru sebaliknya: barisnya rapat supaya beberapa sesi terlihat sekaligus.
 *
 * Tingginya dibiarkan mengikuti atribut `size` pada markahnya. Memaksanya lewat CSS
 * berarti tinggi yang sama untuk daftar berisi dua sesi dan daftar berisi dua puluh.
 */
select[multiple] {
    padding: .3rem;
    line-height: 1.6;
}
select[multiple] option { padding: .15rem .35rem; }

/* Aturan prioritas jendela, ditulis kecil tepat di bawah pemilihnya. */
.petunjuk-jendela { font-size: .72rem; margin: .35rem 0 0; }

input:focus, select:focus, textarea:focus {
    outline: 2px solid var(--sp-aksen);
    outline-offset: 1px;
    border-color: var(--sp-aksen);
}

button, .tombol {
    background: var(--sp-aksen-tua);
    color: #FFFFFF;
    border: 1px solid var(--sp-aksen);
    cursor: pointer;
    padding: .5rem 1rem;
    border-radius: var(--sp-lengkung-kecil);
    font-weight: 700;
    font-size: .85rem;
    text-decoration: none;
    display: inline-block;
    line-height: 1.4;
}
/* Cahaya aksen hanya di sini dan pada penanda aktif — neon di mana-mana justru
   menghapus penekanannya. */
button:hover, .tombol:hover {
    background: var(--sp-aksen);
    border-color: var(--sp-aksen);
    color: #FFFFFF;
    box-shadow: var(--sp-cahaya);
}
button:disabled { opacity: .5; cursor: not-allowed; }

button.sekunder {
    background: var(--sp-kartu);
    color: var(--sp-aksen-tua);
    border-color: var(--sp-aksen);
}
button.sekunder:hover { background: var(--sp-krem); color: var(--sp-aksen-tua); }

/* ===========================================================================
   PESAN
   =========================================================================== */

.galat { color: var(--sp-galat); margin: .35rem 0; font-size: .875rem; }

.sukses, .peringatan {
    padding: .65rem .9rem;
    border-radius: var(--sp-lengkung-kecil);
    margin-bottom: var(--sp-sela);
    font-size: .9rem;
    border-left-width: 4px;
    border-left-style: solid;
}
.sukses {
    background: var(--sp-sukses-latar);
    border: 1px solid var(--sp-sukses-garis);
    border-left: 4px solid var(--sp-sukses-teks);
    color: var(--sp-sukses-teks);
}
.peringatan {
    background: var(--sp-krem);
    border: 1px solid var(--sp-krem);
    border-left: 4px solid var(--sp-aksen);
    color: var(--sp-teks);
}

/* ===========================================================================
   GRID INPUT HASIL BANYAK ATLET
   Kolom nama menempel di kiri saat digulir mendatar dan kepala tabel menempel di
   atas, supaya pelatih tidak kehilangan konteks saat mengisi belasan item untuk
   puluhan atlet.
   =========================================================================== */

.gulir-grid {
    overflow: auto;
    max-height: 70vh;
    border: 1px solid var(--sp-garis);
    border-radius: var(--sp-lengkung-kecil);
}
.grid { border-collapse: separate; border-spacing: 0; }
.grid th, .grid td { white-space: nowrap; background: var(--sp-kartu); }
.grid thead th { position: sticky; top: 0; z-index: 2; background: var(--sp-krem); }
.grid .lengket-kiri {
    position: sticky;
    left: 0;
    z-index: 1;
    border-right: 1px solid var(--sp-garis);
}
/* Perpotongan kepala dan kolom nama harus menang atas keduanya. */
.grid thead .lengket-kiri { z-index: 3; }
.grid td input { width: 6.5rem; }

/*
 * KOLOM ITEM TURUNAN: RAST, 1RM, Bleep Test.
 *
 * Angkanya dihitung dari bahan mentah di layar kalkulatornya, jadi selnya sengaja tidak
 * berkotak isian. Garis putus menyatakan itu tanpa satu kata pun: kolom yang tampak sama
 * dengan tetangganya tetapi tidak dapat diketik terbaca sebagai kolom yang rusak.
 */
.grid th.kepala-turunan,
.grid td.sel-turunan {
    border-left: 1px dashed var(--sp-aksen);
    border-right: 1px dashed var(--sp-aksen);
}
.grid td.sel-turunan { text-align: right; }
.grid .nilai-turunan {
    display: block;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
}

/* Baris item turunan pada layar per atlet: bacaan, bukan isian. Latarnya sedikit
   terangkat supaya terbaca sebagai baris berjenis lain, bukan baris yang kotak
   isiannya kebetulan hilang. */
tr.baris-turunan > td { background: var(--sp-krem); }
tr.baris-turunan .nilai-turunan { font-variant-numeric: tabular-nums; font-weight: 700; }
.grid .capaian { display: block; font-size: .72rem; color: var(--sp-teks-redup); }

/* ===========================================================================
   TABEL LEBAR PADA LAPORAN CETAK
   ---------------------------------------------------------------------------
   BUKAN .gulir-grid. Pembungkus itu milik layar input hasil, dan ia membatasi
   tinggi (max-height: 70vh) supaya kepala tabel tetap terlihat saat pelatih
   mengisi puluhan baris. Batas tinggi itu masuk akal untuk sebuah LAYAR.

   Untuk sebuah DOKUMEN ia bencana: kertas tidak dapat digulir, jadi baris yang
   berada di luar kotak 70vh tidak "tersembunyi" melainkan HILANG dari cetakan.
   Laporan resmi yang keluar terpotong diam-diam adalah kegagalan yang paling
   mahal — tidak ada yang tampak salah pada layarnya.

   Karena itu pembungkus laporan hanya menggulir MENDATAR, dan di blok @media
   print ia melepaskan isinya sama sekali.
   =========================================================================== */

.gulir-laporan {
    overflow-x: auto;
    border: 1px solid var(--sp-garis);
    border-radius: var(--sp-lengkung-kecil);
}
.tabel-rekap { border-collapse: separate; border-spacing: 0; }
.tabel-rekap th, .tabel-rekap td { white-space: nowrap; background: var(--sp-kartu); }
.tabel-rekap thead th { background: var(--sp-krem); }
.tabel-rekap tfoot th, .tabel-rekap tfoot td {
    background: var(--sp-krem);
    font-weight: 700;
    border-top: 1px solid var(--sp-garis);
}
/*
 * Kepala kolom bertingkat: baris atas menyebut sesinya, baris bawah menyebut isi tiap
 * kolom. Garis pemisah di kiri tiap kelompok membuat pasangan "skor total + peringkat"
 * terbaca sebagai satu sesi, bukan sebagai dua kolom yang kebetulan bersebelahan.
 */
.tabel-rekap .kepala-sesi {
    text-align: center;
    border-left: 2px solid var(--sp-garis);
}
.tabel-rekap .kepala-sesi:first-of-type { border-left: 0; }
.tabel-rekap .kepala-sesi span { display: block; font-weight: 400; text-transform: none; letter-spacing: 0; }

/* Angka disejajarkan kanan dan berlebar digit tetap, supaya kolom skor dapat
   dibandingkan sekilas dari atas ke bawah tanpa membaca tiap barisnya. */
.tabel-rekap td.angka { text-align: right; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   BLOK HASIL TES SATU ATLET
   ---------------------------------------------------------------------------
   Item sebagai BARIS, bukan kolom. Baris dapat berpindah halaman, kolom tidak:
   itulah sebabnya bentuk ini tidak pernah terpotong di kertas berapa pun
   banyaknya item tes, sedangkan matriks lebar yang digantikannya selalu.

   Tabelnya sengaja TIDAK dibungkus .gulir-laporan: enam kolom memang muat, dan
   pembungkus yang menggulir hanya akan menyembunyikan kekeliruan lebar bila
   suatu hari ada kolom ditambahkan. */

.tabel-atlet { width: 100%; }
.tabel-atlet th, .tabel-atlet td { white-space: normal; }
.tabel-atlet td:first-child { width: 40%; }

.kepala-atlet {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    flex-wrap: wrap;
    margin: 0 0 .5rem;
    padding-bottom: .4rem;
    border-bottom: 2px solid var(--sp-aksen);
}
.kepala-atlet .kanan { margin-left: auto; display: flex; gap: .35rem; flex-wrap: wrap; }

.deret-biomotor {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    margin-bottom: .6rem;
}
/* Kepala kelompok biomotor di dalam tabel item lintas sesi. */
.tabel-rekap .kelompok-baris th {
    text-align: left;
    background: var(--sp-krem);
    font-size: .66rem;
    letter-spacing: .1em;
    color: var(--sp-aksen-tua);
}
/* Capaian ditulis di bawah hasil mentah; warnanya penanda cepat, bukan penilaian resmi. */
.tabel-rekap .capaian { display: block; font-size: .68rem; color: var(--sp-teks-redup); }
.tabel-rekap .capaian.baik { color: var(--sp-sukses-teks); }
.tabel-rekap .capaian.kurang { color: var(--sp-galat); }
/*
 * KEPALA KOLOM SEJAJAR DENGAN ISINYA, bukan menurut urutan barisnya.
 *
 * Aturan lama meratakan KANAN seluruh kepala pada baris terakhir `thead`. Itu benar untuk
 * tabel berkepala dua baris, yang baris keduanya memang berisi sub-kolom angka — dan
 * keliru untuk tabel berkepala SATU baris: di sana baris terakhir adalah satu-satunya
 * baris, sehingga "Nama" dan "Regu" ikut rata kanan sementara isinya rata kiri. Hasilnya
 * kepala yang tampak melenceng dari kolomnya sendiri.
 *
 * Sekarang perataannya ditentukan kolomnya: kepala bertanda `.angka` rata kanan, sisanya
 * rata kiri — sama dengan aturan selnya.
 */
.tabel-rekap thead th { text-align: left; }
.tabel-rekap thead th.angka { text-align: right; }
.tabel-rekap thead th.kepala-sesi { text-align: center; }

/*
 * KELOMPOK KOLOM BERSELANG WARNA: DIBUANG bersama matriks yang memakainya.
 *
 * Aturan ini menandai batas kelompok kolom pada matriks hasil tes — sebelas item, tiga
 * kolom masing-masing. Matriks itu sendiri sudah diganti bentuk per atlet (item sebagai
 * BARIS), sebab tiga puluh tiga kolom tidak pernah muat di kertas dan yang tercetak
 * hanya beberapa item pertama.
 *
 * Maksudnya tidak hilang, hanya berpindah bentuk: pada tabel menurun, batas kelompok
 * dijawab kepala baris `.kelompok-baris` yang MENYEBUT nama biomotornya, dan itu lebih
 * langsung daripada selang warna yang hanya menandai batas tanpa menamainya.
 */

/* Kolom nama tetap terlihat saat digulir mendatar — di layar saja. */
.tabel-rekap .lengket-kiri {
    position: sticky;
    left: 0;
    z-index: 1;
    border-right: 1px solid var(--sp-garis);
}

/* ===========================================================================
   KISI UBIN KEADAAN
   ---------------------------------------------------------------------------
   Satu ubin per orang untuk pemantauan harian. Mata menyapu mencari warna yang
   menyimpang, bukan membaca baris demi baris — bentuk yang jauh lebih cepat
   daripada tabel ketika yang dicari hanya "siapa yang bermasalah hari ini".

   Warna tidak pernah menjadi satu-satunya penanda: tiap ubin menuliskan
   kategorinya. Laporan yang seluruh maknanya bersandar pada merah dan hijau
   kehilangan maknanya bagi pembaca yang tidak membedakan keduanya.
   =========================================================================== */

.ubin-kisi {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
    gap: .5rem;
    margin-top: .75rem;
}
.ubin {
    display: block;
    padding: .55rem .7rem .6rem;
    border: 1px solid var(--sp-garis);
    border-left: 4px solid var(--sp-teks-redup);
    border-radius: var(--sp-lengkung-kecil);
    background: var(--sp-latar);
    text-decoration: none;
    color: var(--sp-teks);
}
.ubin:hover { border-color: var(--sp-aksen); background: var(--sp-aksen-latar); color: var(--sp-teks); }
.ubin-angka {
    display: block;
    font-size: 1.35rem;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}
.ubin-status {
    display: block;
    font-size: .58rem;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--sp-teks-redup);
}
.ubin-nama {
    display: block;
    font-size: .78rem;
    font-weight: 700;
    margin-top: .25rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ubin-ket { display: block; font-size: .66rem; color: var(--sp-teks-redup); }

.ubin.sukses { border-left-color: var(--sp-sukses-teks); }
.ubin.sukses .ubin-angka, .ubin.sukses .ubin-status { color: var(--sp-sukses-teks); }
.ubin.aksen { border-left-color: var(--sp-aksen); }
.ubin.aksen .ubin-angka, .ubin.aksen .ubin-status { color: var(--sp-aksen-tua); }
.ubin.galat { border-left-color: var(--sp-galat); background: var(--sp-galat-latar); }
.ubin.galat .ubin-angka, .ubin.galat .ubin-status { color: var(--sp-galat); }
/* Belum mengisi: sengaja pucat, bukan merah — belum ada datanya bukan keadaan buruk. */
.ubin.kosong { border-left-color: var(--sp-garis); background: var(--sp-kartu); }
.ubin.kosong .ubin-angka { color: var(--sp-teks-redup); }

/* ===========================================================================
   DERET DONAT KECIL
   ---------------------------------------------------------------------------
   Satu donat per biomotor, berjajar. Ukurannya sengaja kecil: yang dibaca dari
   sebuah donat hanyalah PORSI, dan porsi terbaca pada diameter 5rem sama
   jelasnya dengan pada 9rem — sisanya cuma memakan halaman.
   =========================================================================== */

.donat-deret {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr));
    gap: .5rem;
    margin: .5rem 0 .25rem;
}
.donat-satu { text-align: center; }
.donat-satu .donat { width: 5rem; height: 5rem; margin: 0 auto; }
/* Legenda tiap donat dimatikan: label komponennya sudah tertulis di bawahnya, dan
   dua puluh baris legenda "Hasil / Kekurangan" yang berulang hanya jadi bising. */
.donat-satu .legenda { display: none; }
.donat-judul {
    display: block;
    font-size: .68rem;
    font-weight: 700;
    line-height: 1.2;
    margin-top: .15rem;
    color: var(--sp-teks-redup);
}

/* ===========================================================================
   BAR MENDATAR BERLABEL
   ---------------------------------------------------------------------------
   Untuk membandingkan komponen BERNAMA — biomotor, aspek readiness. Grid tiga
   kolom: nama, bilah, angka. Angka disejajarkan kanan dengan lebar digit tetap
   supaya kolomnya dapat dibaca menurun sebagai daftar, bukan hanya sebagai
   pelengkap bilah.
   =========================================================================== */

.bar-daftar { display: flex; flex-direction: column; gap: .3rem; margin: .5rem 0; }
.bar-baris {
    display: grid;
    grid-template-columns: minmax(6rem, 11rem) minmax(0, 1fr) 3.2rem;
    align-items: center;
    gap: .6rem;
}
.bar-label {
    font-size: .8rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.bar-jalur {
    display: block;
    height: .55rem;
    border-radius: 999px;
    background: var(--sp-nonaktif-latar);
    overflow: hidden;
}
.bar-isian {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--sp-aksen);
}
/* Warna semantik terpisah dari aksen: keadaan, bukan merek. */
.bar-isian.sukses { background: var(--sp-sukses-teks); }
.bar-isian.galat { background: var(--sp-galat); }
.bar-isian.redup { background: var(--sp-teks-redup); }

/* --- Bar ganda: hasil dan kekurangan berbagi satu jalur ---
   Ruas kekurangan digaris miring, bukan sekadar dibiarkan kosong. Jalur kosong terbaca
   sebagai "belum digambar"; garis miring terbaca sebagai "ini jaraknya" — dan jarak
   itulah yang dipakai pelatih menyusun program. Radiusnya dimatikan pada kedua ruas
   supaya sambungannya rapat: dua ruas berujung bulat menyisakan celah yang tampak
   seperti kekeliruan hitung. */
.bar-jalur.ganda { display: flex; }
.bar-jalur.ganda .bar-isian { border-radius: 0; }
.bar-jalur.ganda .bar-isian:first-child { border-radius: 999px 0 0 999px; }
.bar-jalur.ganda .bar-isian:last-child { border-radius: 0 999px 999px 0; }
.bar-isian.kurang {
    background: repeating-linear-gradient(
        135deg,
        color-mix(in srgb, var(--sp-teks-redup) 55%, transparent) 0 3px,
        transparent 3px 7px
    );
}
.bar-nilai {
    font-size: .8rem;
    font-weight: 800;
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.bar-ket { font-size: .7rem; color: var(--sp-teks-redup); margin: -.15rem 0 .2rem 0; }

/* --- Grafik garis banyak deret ---
   Deret dibedakan oleh BENTUK penanda dan pola garis putus, bukan hanya warna. Grafik ini
   dirancang untuk ikut tercetak, dan pencetak laser kantor mengeluarkan seluruh warna
   sebagai abu-abu yang nyaris sama — dua deret yang hanya berbeda warna menjadi dua garis
   identik di atas kertas. Warna di sini hanya penegas, bukan satu-satunya pembeda. */
.grafik.multigaris { min-width: 22rem; }
/* Sparkline dalam sel tabel: hanya bentuk deretnya, angkanya sudah ada di kolom sebelah. */
.grafik.multigaris.mini { min-width: 0; width: 5.5rem; height: 1.6rem; }
.sparkline { display: inline-block; line-height: 0; }
.grafik-kisi { stroke: var(--sp-garis-samar); stroke-width: 1; }
.grafik-label.sumbu { font-size: 8px; fill: var(--sp-teks-redup); }
.multigaris-jalur { fill: none; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; }
.multigaris-titik { stroke-width: 1; }
.multigaris-angka { font-size: 13px; font-weight: 800; fill: var(--sp-teks); }
.multigaris-jalur.deret-0, .multigaris-titik.deret-0 { stroke: var(--sp-aksen); fill: var(--sp-aksen); }
.multigaris-jalur.deret-1, .multigaris-titik.deret-1 { stroke: var(--sp-teks); fill: var(--sp-teks); }
.multigaris-jalur.deret-2, .multigaris-titik.deret-2 { stroke: var(--sp-teks-redup); fill: var(--sp-teks-redup); }
.multigaris-jalur.deret-3, .multigaris-titik.deret-3 { stroke: var(--sp-sukses-teks); fill: var(--sp-sukses-teks); }
.multigaris-jalur { fill: none; }
.multigaris-legenda {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem 1.1rem;
    margin: .4rem 0 .2rem;
    font-size: .78rem;
}
.multigaris-legenda .baris { display: inline-flex; align-items: center; gap: .4rem; }
.multigaris-legenda .contoh { width: 2.2rem; height: .8rem; flex: none; }

/* --- Grafik batang SVG sebaris (tanpa pustaka pihak ketiga) --- */
.grafik { width: 100%; min-width: 20rem; height: auto; display: block; }
.grafik-sumbu { stroke: var(--sp-garis); stroke-width: 1; }
.grafik-batang { fill: var(--sp-aksen); }
/* Batang bergaris putus: angkanya belum dibekukan dan masih dapat berubah. */
.grafik-batang.sementara {
    fill: var(--sp-krem);
    stroke: var(--sp-aksen);
    stroke-width: 1.5;
    stroke-dasharray: 4 3;
}
/* --- Grafik garis: untuk deret panjang, arahnya yang dibaca bukan tinggi tiap titik --- */
.grafik-kisi { stroke: var(--sp-garis-samar); stroke-width: 1; }
.grafik-sumbu-teks { font-size: 8px; fill: var(--sp-teks-redup); text-anchor: end; }
.grafik-garis-jalur { fill: none; stroke: var(--sp-aksen); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.grafik-titik { fill: var(--sp-aksen); stroke: var(--sp-kartu); stroke-width: 1; }
/* Ambang: garis putus, sengaja tidak beraksen supaya tidak bersaing dengan datanya. */
.grafik-ambang { stroke: var(--sp-galat); stroke-width: 1.5; stroke-dasharray: 5 3; opacity: .7; }

/* Hari tanpa data: garis tipis di dasar, bukan batang setinggi nol. */
.grafik-kosong { stroke: var(--sp-teks-redup); stroke-width: 2; stroke-dasharray: 2 2; opacity: .55; }
/* Bidang grafik batang 640x260; ukuran huruf dalam satuan viewBox, jadi ia ikut
   membesar-mengecil bersama grafiknya dan tetap sebanding pada lebar layar mana pun. */
.grafik-angka { font-size: 15px; font-weight: 800; fill: var(--sp-teks); text-anchor: middle; }
.grafik-label { font-size: 13px; fill: var(--sp-teks-redup); text-anchor: middle; }

/* ===========================================================================
   POLA TAMPILAN DASBOR
   Bentuknya mengikuti rujukan Star Jasmani; paletnya tetap palet kesepakatan.
   Tanpa Chart.js dan tanpa Font Awesome: keduanya CDN, sehingga aplikasi akan
   bergantung pada internet dan grafiknya hilang saat laporan dicetak.
   =========================================================================== */

/* Label kecil berspasi lebar di atas judul halaman. */
.label-atas {
    display: block;
    font-size: .68rem;
    font-weight: 800;
    letter-spacing: .3em;
    text-transform: uppercase;
    color: var(--sp-aksen-tua);
    margin-bottom: .35rem;
}

.judul-besar {
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 800;
    letter-spacing: -.03em;
    line-height: 1.1;
    margin: 0 0 .3rem;
}
.judul-besar em { font-style: normal; color: var(--sp-aksen-tua); }

/* Lencana ikon: kotak membulat berlatar lembut. */
.lencana-ikon {
    width: 2.1rem;
    height: 2.1rem;
    border-radius: .6rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--sp-krem);
    color: var(--sp-aksen-tua);
    flex-shrink: 0;
}
.lencana-ikon svg { width: 1rem; height: 1rem; }
.lencana-ikon.sukses { background: var(--sp-sukses-latar); color: var(--sp-sukses-teks); }
.lencana-ikon.galat { background: var(--sp-galat-latar); color: var(--sp-galat); }
.lencana-ikon.redup { background: var(--sp-nonaktif-latar); color: var(--sp-teks-redup); }

/* Kartu angka: baris atas berisi label dan ikon, bar tipis di kakinya. */
.kartu-nilai .atas { display: flex; align-items: flex-start; justify-content: space-between; gap: .5rem; }
.kartu-nilai .atas .label { margin: 0; }

/* display:block wajib: sebagai <span> inline, tinggi dan overflow tidak berlaku
   sehingga sebagian bar tidak tergambar sama sekali. */
.bar-tipis {
    display: block;
    height: 6px;
    border-radius: 3px;
    background: var(--sp-nonaktif-latar);
    overflow: hidden;
    margin-top: .35rem;
}
/* min-width menjaga nilai kecil tetap terlihat sebagai garis, bukan lenyap. */
.bar-isi { display: block; height: 100%; min-width: 3px; border-radius: 3px; background: var(--sp-aksen); }
.bar-isi.sukses { background: var(--sp-sukses-teks); }
.bar-isi.galat { background: var(--sp-galat); }
.bar-isi.redup { background: var(--sp-teks-redup); }

/* Daftar bar mendatar: nama, angka, lalu bar di bawahnya. */
.daftar-bar { display: flex; flex-direction: column; gap: .7rem; }
.daftar-bar .baris .kepala {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    margin-bottom: .25rem;
    font-size: .82rem;
}
.daftar-bar .baris .kepala .nilai { font-weight: 800; }

/* Peringkat bermedali. Emas, perak, dan perunggu diambil dari palet yang ada —
   tidak ada warna baru yang diselundupkan lewat pintu hiasan. */
.medali {
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: .75rem;
    font-weight: 800;
    flex-shrink: 0;
    background: var(--sp-nonaktif-latar);
    color: var(--sp-teks-redup);
}
.medali.satu { background: var(--sp-aksen); color: var(--sp-kartu); }
.medali.dua { background: var(--sp-krem); color: var(--sp-aksen-tua); }
.medali.tiga { background: color-mix(in srgb, var(--sp-aksen-tua) 35%, var(--sp-krem)); color: var(--sp-kartu); }

/* Bulatan inisial nama. */
.avatar {
    width: 1.9rem;
    height: 1.9rem;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--sp-aksen-tua);
    color: var(--sp-kartu);
    font-size: .75rem;
    font-weight: 800;
    flex-shrink: 0;
}
.avatar.putri { background: color-mix(in srgb, var(--sp-aksen) 55%, var(--sp-teks-redup)); }

/* Kartu aksi: ikon, judul, keterangan singkat. */
.deret-aksi {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: .75rem;
    margin-bottom: var(--sp-sela);
}
.kartu-aksi {
    display: flex;
    align-items: center;
    gap: .7rem;
    padding: .8rem .9rem;
    border: 1px solid var(--sp-garis);
    border-radius: var(--sp-lengkung);
    background: var(--sp-kartu);
    text-decoration: none;
    color: var(--sp-teks);
    box-shadow: var(--sp-bayang);
}
.kartu-aksi:hover { border-color: var(--sp-aksen); color: var(--sp-teks); }
.kartu-aksi .judul { display: block; font-size: .78rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }
.kartu-aksi .ket { display: block; font-size: .72rem; color: var(--sp-teks-redup); }
.kartu-aksi.utama { background: var(--sp-aksen-tua); border-color: var(--sp-aksen-tua); color: var(--sp-kartu); }
.kartu-aksi.utama .ket { color: color-mix(in srgb, var(--sp-kartu) 75%, transparent); }
.kartu-aksi.utama .lencana-ikon { background: color-mix(in srgb, var(--sp-kartu) 22%, transparent); color: var(--sp-kartu); }

/* ===========================================================================
   TOMBOL AKSI BARIS
   ---------------------------------------------------------------------------
   Kolom aksi tabel sebelumnya berisi tautan telanjang yang berdempetan:
   "lihat peringkat cetak rekap" terbaca sebagai satu kalimat, bukan dua
   tindakan — batas antar keduanya hanya spasi, dan sasaran sentuhnya setipis
   tinggi huruf.

   Yang dipakai di sini bukan emoji melainkan ikon SVG dari komponen yang sudah
   ada. Alasannya sama dengan alasan komponen itu dibuat: emoji digambar
   berbeda-beda oleh tiap sistem, ukurannya tidak dapat disamakan dengan tinggi
   huruf di sebelahnya, dan sebagiannya berwarna sendiri sehingga menembus palet.

   Ikonnya diam berwarna redup dan baru menyala saat disorot. Sebaris tiga
   tombol yang seluruhnya beraksen akan saling berebut perhatian, dan tidak ada
   satu pun yang akhirnya menonjol.
   =========================================================================== */

.aksi-baris {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem;
}
/*
 * Formulir satu tombol (misalnya "keluarkan") ikut sebaris, bukan turun sendiri.
 *
 * align-items: center wajib. Tanpa itu tombol di dalam formulir yang juga memuat
 * kotak isian — seperti "hentikan" yang bersebelahan dengan pemilih tanggal —
 * ikut merenggang setinggi kotak itu, dan sebaris kapsul jadi beda-beda tinggi.
 */
.aksi-baris form { margin: 0; display: inline-flex; align-items: center; gap: .35rem; }

.aksi-mini {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .3rem .6rem;
    border: 1px solid var(--sp-garis);
    border-radius: 999px;
    /* Sedikit lebih gelap daripada kartunya, supaya terbaca sebagai bidang yang
       dapat ditekan — bukan tulisan yang kebetulan berwarna. */
    background: var(--sp-latar);
    color: var(--sp-teks);
    font-size: .76rem;
    font-weight: 600;
    line-height: 1.25;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    /* Tidak boleh diciutkan oleh induk fleksnya. Tanpa ini, sebuah kapsul yang
       kesempitan memang tidak memotong tulisannya (nowrap) tetapi tetap
       kehilangan lebar, dan tingginya membengkak jadi dua baris — sebaris kapsul
       lalu tampak beda-beda tinggi tanpa sebab yang terlihat. */
    flex: none;
}
.aksi-mini svg {
    width: .82rem;
    height: .82rem;
    flex: none;
    color: var(--sp-teks-redup);
}
.aksi-mini:hover {
    border-color: var(--sp-aksen);
    background: var(--sp-aksen-latar);
    color: var(--sp-aksen);
}
.aksi-mini:hover svg { color: var(--sp-aksen); }
.aksi-mini:focus-visible { outline: 2px solid var(--sp-aksen); outline-offset: 2px; }

/*
 * Tindakan utama sebuah baris — satu saja per baris, kalau tidak penekanannya hilang.
 *
 * Modifiernya bernama .tegas, BUKAN .utama. Nama .utama sudah dipakai kerangka
 * halaman (`<div class="utama">`, kolom isi di samping bilah navigasi) dengan
 * `display: flex; flex-direction: column` — dan aturan itu menang atas display
 * kapsul ini, sehingga ikon menumpuk di ATAS labelnya dan tingginya jadi dua kali
 * lipat. Bentroknya tidak terlihat di berkas gaya; hanya terlihat setelah dibuka.
 */
.aksi-mini.tegas {
    border-color: var(--sp-aksen);
    color: var(--sp-aksen);
    background: var(--sp-aksen-latar);
}
.aksi-mini.tegas svg { color: var(--sp-aksen); }
.aksi-mini.tegas:hover { background: var(--sp-aksen); border-color: var(--sp-aksen); color: #FFFFFF; }
.aksi-mini.tegas:hover svg { color: #FFFFFF; }

/* Tindakan yang membatalkan sesuatu. Merahnya baru muncul saat disorot: sebuah
   baris yang memuat tombol merah permanen terbaca sebagai baris bermasalah. */
.aksi-mini.bahaya:hover {
    border-color: var(--sp-galat);
    background: var(--sp-galat-latar);
    color: var(--sp-galat);
}
.aksi-mini.bahaya:hover svg { color: var(--sp-galat); }

/* Keadaan kosong berukuran penuh, dengan ikon besar dan ajakan bertindak. */
.kosong-besar { text-align: center; padding: 2.5rem 1rem; }
.kosong-besar svg { width: 2.2rem; height: 2.2rem; color: var(--sp-nonaktif-latar); }
.kosong-besar .judul { display: block; font-weight: 800; margin: .6rem 0 .2rem; }
.kosong-besar .ket { color: var(--sp-teks-redup); font-size: .875rem; }

/* Donat distribusi. Lingkaran SVG dengan stroke-dasharray — tanpa pustaka grafik. */
.donat { width: 9rem; height: 9rem; display: block; margin: 0 auto; }
.donat circle { fill: none; stroke-width: 14; }
.donat .alas { stroke: var(--sp-nonaktif-latar); }
.donat-tengah { text-anchor: middle; }
.donat-tengah .angka { font-size: 15px; font-weight: 800; fill: var(--sp-teks); }
.donat-tengah .ket { font-size: 6px; fill: var(--sp-teks-redup); letter-spacing: .1em; text-transform: uppercase; }

.legenda { display: flex; flex-direction: column; gap: .45rem; margin-top: .9rem; }
.legenda .baris { display: flex; align-items: center; justify-content: space-between; gap: .5rem; font-size: .8rem; }
.legenda .titik { width: .7rem; height: .7rem; border-radius: .2rem; display: inline-block; flex-shrink: 0; }

/* ===========================================================================
   GRAFIK SVG SEBARIS
   Tanpa pustaka grafik: SVG sebaris tetap terbaca saat halaman dicetak, dan
   justru di situ grafik paling sering dibutuhkan.
   =========================================================================== */

.grafik { width: 100%; min-width: 20rem; height: auto; display: block; }
.grafik-sumbu { stroke: var(--sp-garis); stroke-width: 1; }
.grafik-batang { fill: var(--sp-aksen); }
/* Batang bergaris menandai angka yang belum dibekukan snapshot. */
.grafik-batang.sementara { fill: var(--sp-krem); stroke: var(--sp-aksen); stroke-width: 1.5; stroke-dasharray: 4 3; }
.grafik-angka { font-size: 14px; font-weight: 800; fill: var(--sp-teks); text-anchor: middle; }
.grafik-label { font-size: 12px; fill: var(--sp-teks-redup); text-anchor: middle; }

/* Batang mendatar untuk papan peringkat: nama di kiri, panjang batang = skor. */
.batang-peringkat {
    display: grid;
    grid-template-columns: 1.6rem minmax(6rem, 12rem) 1fr 3rem;
    gap: .5rem;
    align-items: center;
    padding: .3rem .1rem;
    border-bottom: 1px solid var(--sp-garis-samar);
    font-size: .85rem;
}
.batang-peringkat:last-child { border-bottom: 0; }
.batang-peringkat .nomor { color: var(--sp-teks-redup); font-weight: 700; text-align: right; }

/*
 * Kolom nama menahan avatar dan teks pada SATU baris.
 *
 * Menimpa .deret yang dipakai markahnya: .deret membungkus isinya bila sempit, dan di
 * sini pembungkusan itu melempar avatar ke baris sendiri lalu merusak tinggi seluruh
 * baris. min-width:0 wajib — tanpa itu butir grid menolak menyusut dan angka skor di
 * ujung kanan terdorong keluar.
 */
.batang-peringkat .nama {
    display: flex;
    align-items: center;
    gap: .45rem;
    flex-wrap: nowrap;
    min-width: 0;
    overflow: hidden;
}
.batang-peringkat .nama > span:last-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.batang-peringkat .rel {
    background: var(--sp-nonaktif-latar);
    border-radius: 999px;
    height: .6rem;
    overflow: hidden;
}
.batang-peringkat .rel span { display: block; height: 100%; min-width: 4px; background: var(--sp-aksen); border-radius: 999px; }
/*
 * Angka yang belum dibekukan digambar bergaris miring, bukan sekadar dipucatkan.
 * Krem di atas latar krem nyaris tak terbaca, dan bar yang tampak kosong akan
 * disangka nol — persis salah tafsir yang paling mahal di papan peringkat.
 */
.batang-peringkat .rel span.sementara {
    background: repeating-linear-gradient(
        45deg,
        var(--sp-aksen) 0 5px,
        color-mix(in srgb, var(--sp-aksen) 40%, var(--sp-kartu)) 5px 10px
    );
}
.batang-peringkat .angka { font-weight: 700; text-align: right; white-space: nowrap; }

/* --- Grafik tren sederhana (berat badan antar tanggal) --- */
.tren {
    display: flex;
    align-items: flex-end;
    gap: .25rem;
    height: 7rem;
    padding: .5rem;
    background: var(--sp-latar);
    border: 1px solid var(--sp-garis);
    border-radius: var(--sp-lengkung-kecil);
}
.tren-batang {
    flex: 1 1 auto;
    min-width: .4rem;
    background: var(--sp-aksen);
    border-radius: .2rem .2rem 0 0;
}

/* ===========================================================================
   PINTU LAPORAN CETAK
   ===========================================================================

   Empat laporan yang dibuka dari dasbor cabor, masing-masing dengan pemilih
   periodenya sendiri.

   Sebelumnya keempatnya ditumpuk langsung di dalam satu kartu: dua formulir tanpa
   pembatas apa pun, lalu satu tautan berikon, lalu dua paragraf keterangan yang
   sudah kehilangan hubungannya dengan tombol mana pun. Tombolnya juga tiga rupa
   berbeda — tombol utama, tombol sekunder, dan kapsul berikon — untuk tiga hal yang
   sebenarnya setara, sehingga matanya membaca perbedaan yang tidak ada artinya.

   Sekarang tiap laporan berdiri sebagai ubinnya sendiri: judul, satu kalimat
   keterangan, pemilih periodenya, dan SATU bentuk tombol yang sama untuk semuanya.
   Tombolnya dijajarkan ke dasar ubin supaya barisnya tetap rata walau keterangannya
   berbeda panjang. */

.pintu-laporan {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: var(--sp-sela);
    margin-top: .75rem;
}

.pintu-laporan .ubin {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    padding: .9rem 1rem 1rem;
    background: var(--sp-latar);
    border: 1px solid var(--sp-garis);
    border-left: 3px solid var(--sp-aksen);
    border-radius: var(--sp-lengkung-kecil);
}

.pintu-laporan .ubin h3 { margin: 0 0 .15rem; }

.pintu-laporan .ubin .redup { margin: 0 0 .35rem; font-size: .8rem; }
.pintu-laporan .ubin label { margin: .25rem 0 .2rem; }

/* Tombol menempel ke dasar ubin: baris ubin dengan keterangan berbeda panjang tetap
   memperlihatkan tombolnya sejajar, dan mata tidak perlu mencarinya ubin per ubin. */
.pintu-laporan .ubin .aksi { margin-top: auto; padding-top: .6rem; }
.pintu-laporan .ubin .aksi button,
.pintu-laporan .ubin .aksi .tombol { width: 100%; text-align: center; }

/* ===========================================================================
   DIAGRAM SEBAR
   ---------------------------------------------------------------------------
   Titiknya diberi isian penuh beraksen dan garis tepi selatar kartu, supaya dua
   titik yang berdekatan tetap terbaca sebagai dua, bukan satu bercak. Nomornya
   digambar di atas titik: dua puluh enam nama pada satu bidang saling menimpa
   sampai tidak satu pun terbaca. */

.sebar-titik {
    fill: var(--sp-aksen);
    stroke: var(--sp-kartu);
    stroke-width: 1.5;
}
.sebar-nomor {
    font-size: 12px;
    font-weight: 700;
    fill: var(--sp-teks);
    text-anchor: middle;
}

/* ===========================================================================
   PETA PANAS CAPAIAN 1RM
   ---------------------------------------------------------------------------
   Baris atlet, kolom gerakan, warna dari capaiannya. Bentuk ini yang membuat pola
   KOLEKTIF terbaca sekali pandang: satu kolom yang merah seluruhnya berarti
   gerakan itu masalah regu, bukan masalah beberapa orang, dan itu kesimpulan yang
   berbeda penanganannya.

   Warnanya lahir dari angkanya, bukan dari pewarnaan manual per sel seperti di
   Excel: begitu angkanya berubah, warnanya ikut tanpa disentuh.

   `print-color-adjust: exact` wajib. Alur cetaknya "Simpan sebagai PDF" pada
   peramban, dan tanpa properti itu seluruh selnya keluar putih polos — peta panas
   tanpa warna tidak menyisakan apa pun yang dapat dibaca. */

/*
 * DIPADATKAN AGAR MUAT LEBAR A4.
 *
 * Enam gerakan ditambah nama, regu, dan rerata menghasilkan sembilan kolom. Pada ukuran
 * tabel biasa lebarnya 1082px di halaman selebar 784px — dan kolom yang jatuh di luar
 * lebar halaman tidak "tersembunyi" melainkan HILANG dari cetakan, persis kekeliruan yang
 * dulu memotong matriks hasil tes pada dasbor keseluruhan.
 *
 * Kepala kolomnya membungkus, bukan memaksa satu baris: yang penting muat, bukan tetap
 * satu baris.
 */
.peta-panas { font-size: .74rem; }
.peta-panas th, .peta-panas td { padding: .3rem .35rem; white-space: normal; }
.peta-panas thead th { word-break: break-word; }

.peta-panas td.panas {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
}
.peta-panas td.panas-sangat-baik { background: var(--sp-sukses-latar); color: var(--sp-sukses-teks); }
.peta-panas td.panas-baik { background: color-mix(in srgb, var(--sp-aksen) 22%, var(--sp-kartu)); }
.peta-panas td.panas-cukup { background: var(--sp-krem); }
.peta-panas td.panas-perlu-perhatian { background: var(--sp-galat-latar); color: var(--sp-galat); }
.peta-panas td.panas-kosong { background: var(--sp-kartu); color: var(--sp-teks-redup); font-weight: 400; }

.legenda-panas {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    margin-top: .6rem;
}
.legenda-panas .panas {
    padding: .2rem .5rem;
    border-radius: var(--sp-lengkung-kecil);
    font-size: .75rem;
    font-weight: 700;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
}
.legenda-panas .panas-sangat-baik { background: var(--sp-sukses-latar); color: var(--sp-sukses-teks); }
.legenda-panas .panas-baik { background: color-mix(in srgb, var(--sp-aksen) 22%, var(--sp-kartu)); }
.legenda-panas .panas-cukup { background: var(--sp-krem); }
.legenda-panas .panas-perlu-perhatian { background: var(--sp-galat-latar); color: var(--sp-galat); }
.legenda-panas .panas-kosong { background: var(--sp-kartu); color: var(--sp-teks-redup); font-weight: 400; }

/* --- Kop dan tanda tangan laporan resmi --- */

.logo-laporan {
    height: 2.2rem;
    width: auto;
    max-width: 8rem;
    object-fit: contain;
    display: block;
    margin-bottom: .25rem;
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
}

/* Dua penanda tangan berdampingan. Ditumpuk ke bawah akan memakan tinggi halaman yang
   justru paling sempit tempatnya, yaitu kaki halaman terakhir. */
.ttd-kelompok { display: flex; gap: 2rem; align-items: flex-start; }
.ttd .tempat { display: block; font-size: .72rem; margin-bottom: .2rem; }

/* --- Utilitas tata letak kecil, supaya view tidak perlu menulis style inline --- */
.kartu-sempit { max-width: 26rem; margin: 3rem auto; }
.aksi { margin-top: 1rem; display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.sebaris { display: inline; }
.pilihan { font-weight: 400; display: flex; align-items: center; gap: .45rem; margin: .3rem 0; }
.pilihan input { width: auto; }

/*
 * DAFTAR SESI pada ubin laporan cetak.
 *
 * Menggantikan `<select multiple>`, yang punya keadaan tersembunyi: klik biasa MENGGANTI
 * pilihan alih-alih menambah, sehingga memilih dua sesi menuntut Ctrl+klik. Tanpa itu
 * yang terkirim hanya sesi terakhir yang disentuh, laporannya tetap terbit, dan tidak ada
 * satu pun tanda bahwa cakupannya bukan yang diminta.
 *
 * Tingginya dibatasi dan digulir di dalam dirinya sendiri: cabor yang sudah berjalan
 * bertahun-tahun punya belasan sesi, dan ubin setinggi belasan baris centang akan
 * memanjang melewati ubin di sebelahnya.
 */
.daftar-sesi {
    max-height: 9.5rem;
    overflow-y: auto;
    border: 1px solid var(--sp-garis);
    border-radius: var(--sp-lengkung-kecil);
    background: var(--sp-latar);
    padding: .35rem .6rem;
    margin-bottom: .75rem;
}
.daftar-sesi .pilihan { margin: 0; }
.daftar-sesi .pilihan + .pilihan { border-top: 1px solid var(--sp-garis-samar); }
.daftar-sesi .pilihan .redup { font-size: .78rem; margin-left: .35rem; }

/* Label untuk kelompok isian yang bukan satu <input>, jadi tidak dapat memakai <label>. */
/*
 * Penomoran halaman. Dipusatkan dan diberi jarak longgar: ketiga bagiannya ditekan dari
 * ponsel, dan tautan yang berdempetan berarti meleset ke halaman yang salah.
 */
/* ===========================================================================
   LAPORAN TAHUNAN TIM — dasbor visual
   ---------------------------------------------------------------------------
   Rata, tanpa gradasi maupun bayangan berlebih: halaman ini dibaca di layar DAN
   dicetak ke kertas, dan efek yang bagus di layar hampir selalu hilang atau
   menghitam di kertas. Yang membedakan bagian di sini adalah garis dan jarak,
   bukan kedalaman.

   DUA KELUARGA WARNA, dua sumbu makna, dan tidak pernah dicampur:
     biru / oranye  = WAKTU        (tahun lalu / tahun ini)
     hijau / merah  = BAIK-BURUK   (membaik / memburuk)
   =========================================================================== */

.papan-metrik { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }

.kartu-metrik .satuan { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.keterangan-metrik { margin: -.35rem 0 1rem; font-size: .78rem; }

/* Baris pemilih tahun dan cabor. */
.baris-pemilih {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: .75rem 1.25rem;
}
.baris-pemilih > span { flex: 1 1 12rem; }
.baris-pemilih .aksi { flex: 0 0 auto; margin: 0; }
.baris-pemilih select { margin-bottom: 0; }

/* Legenda warna, digambar ULANG sebagai kotak — bukan mengandalkan pembaca
   mengingat warna mana milik tahun mana. */
.legenda-warna {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem 1.2rem;
    margin-bottom: .85rem;
    font-size: .8rem;
}
.legenda-warna span { display: inline-flex; align-items: center; gap: .4rem; }
.legenda-warna .kotak {
    width: .85rem;
    height: .85rem;
    border-radius: 2px;
    display: inline-block;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}
.legenda-warna .kotak.lalu { background: var(--sp-tahun-lalu); }
.legenda-warna .kotak.kini { background: var(--sp-tahun-kini); }

/* Petak bagan dua tahun: satu bagan per indikator, masing-masing bersumbu sendiri. */
.petak-batang-tahun {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 1rem;
}
.batang-tahun {
    border: 1px solid var(--sp-garis);
    border-radius: var(--sp-lengkung-kecil);
    padding: .7rem .6rem .5rem;
    text-align: center;
}
.batang-tahun-judul {
    display: block;
    font-size: .78rem;
    font-weight: 700;
    margin-bottom: .6rem;
}
.batang-tahun-bidang {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: .9rem;
    height: 7.5rem;
}
.batang-tahun-kolom {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    height: 100%;
    flex: 0 1 3rem;
}
.batang-tahun-angka {
    font-size: .78rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    margin-bottom: .25rem;
}
.batang-tahun-batang {
    width: 100%;
    min-height: 2px;
    border-radius: 2px 2px 0 0;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}
.batang-tahun-batang.lalu { background: var(--sp-tahun-lalu); }
.batang-tahun-batang.kini { background: var(--sp-tahun-kini); }
/* Tahun tanpa data digambar bergaris putus, BUKAN batang setinggi nol: batang nol
   terbaca sebagai "nilainya nol", sedangkan yang dimaksud "belum ada data". */
.batang-tahun-batang.kosong {
    background: none;
    border: 1px dashed var(--sp-garis);
    height: 100% !important;
}
.batang-tahun-tahun {
    font-size: .72rem;
    color: var(--sp-teks-redup);
    margin-top: .3rem;
}

/*
 * Penomoran halaman. Dipusatkan dan diberi jarak longgar: ketiga bagiannya ditekan
 * dari ponsel, dan tautan yang berdempetan berarti meleset ke halaman yang salah.
 */
.paginasi {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: .5rem .9rem;
    margin-top: 1rem;
}
.paginasi .posisi-halaman { font-size: .82rem; }
.paginasi .aksi-mini.nonaktif { opacity: .4; cursor: not-allowed; }

.label-pemilih {
    display: block;
    font-weight: 700;
    font-size: .82rem;
    margin-bottom: .35rem;
}

/*
 * Pemicu "Pilih semua" pada daftar centang.
 *
 * Diberi garis pemisah di bawahnya, bukan sekadar dicetak tebal: ia BUKAN salah satu
 * pilihan pada daftar itu melainkan pengendali daftarnya, dan tanpa pemisah ia terbaca
 * sebagai calon pertama yang kebetulan bernama "Pilih semua".
 *
 * Cacahnya didorong ke kanan supaya jumlah terpilih terbaca tanpa menghitung sendiri.
 */
.pilihan-semua {
    margin: 0 0 .5rem;
    padding-bottom: .5rem;
    border-bottom: 1px solid var(--sp-garis);
}
.pilihan-semua .redup { margin-left: auto; font-size: .8rem; }
.deret { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }

/* ===========================================================================
   HALAMAN CETAK LAPORAN (paket 4.9)
   Tanpa bilah samping dan tanpa kepala aplikasi: yang tercetak hanya isi laporan.
   =========================================================================== */

.halaman-cetak { background: var(--sp-kartu); }
.halaman-cetak .isi-cetak,
.halaman-cetak .kop,
.halaman-cetak > .aksi {
    max-width: 58rem;
    margin-left: auto;
    margin-right: auto;
    padding-left: 1.25rem;
    padding-right: 1.25rem;
}

/* Kop laporan berlatar putih — bukan bidang oranye. Garis aksen di bawahnya sudah
   cukup menegaskan, dan tinta oranye selebar kop hanya memboroskan toner. */
.kop {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1.5rem;
    flex-wrap: wrap;
    background: var(--sp-kartu);
    color: var(--sp-teks);
    padding-top: 1.5rem;
    padding-bottom: .75rem;
    border-bottom: 3px solid var(--sp-aksen);
}
.kop h1 { margin: .25rem 0; }
.kop-instansi {
    margin: 0;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--sp-aksen-tua);
}
/*
 * Salinan pribadi atlet. Sengaja TIDAK beraksen oranye seperti kop instansi: warna
 * aksen menyatakan dokumen resmi, dan salinan pribadi justru harus terbaca sebagai
 * bukan itu — kalau keduanya tampak sama, salinan pribadi dapat beredar seolah-olah
 * laporan bertandatangan pelatih.
 */
.kop-pribadi {
    color: var(--sp-teks-redup);
    letter-spacing: .06em;
    border: 1px dashed var(--sp-teks-redup);
    border-radius: var(--sp-lengkung-kecil);
    padding: .15rem .5rem;
    display: inline-block;
}

.kop-kanan { text-align: right; }
.kop-kanan p { margin: .15rem 0; }

.isi-cetak { padding-bottom: 3rem; }
.isi-cetak h3 { font-size: 1rem; margin: 1rem 0 .5rem; }
.isi-cetak h4 { font-size: .85rem; margin: .9rem 0 .35rem; }

/* ===========================================================================
   DUA KOLOM PADA HALAMAN CETAK
   ---------------------------------------------------------------------------
   Bidang A4 cukup lebar untuk dua kolom, dan sebagian besar kartu laporan —
   grafik, tabel ringkas — tidak butuh selebar halaman. Susunan satu kartu per
   lebar membuat dokumen memakai dua halaman untuk isi yang muat di satu, dan
   tiap pergantian halaman memaksa pembacanya kehilangan konteks.

   Menyempit sendiri menjadi satu kolom di layar sempit; yang menentukan bukan
   media cetak melainkan lebar yang tersedia.
   =========================================================================== */

.dua-kolom {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
    gap: var(--sp-sela);
    align-items: start;
}
/* Kartu di dalamnya tidak boleh terpotong di tengah saat berganti halaman. */
.dua-kolom > .kartu { break-inside: avoid; margin-bottom: 0; }

/* Varian rapat: dua kolom bahkan pada lebar sedang, untuk daftar berbaris pendek. */
.dua-kolom.rapat { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: .9rem; }

/* Tabel daftar berbaris pendek: dirapatkan supaya dua kolomnya benar-benar hemat. */
.ringkas { font-size: .82rem; }
.ringkas th, .ringkas td { padding: .3rem .45rem; }
.ringkas td.angka { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ringkas .lencana { font-size: .62rem; padding: 0 .35rem; }

/* ===========================================================================
   PITA KATEGORI BERSKALA
   ---------------------------------------------------------------------------
   Menaruh sebuah angka di dalam rentangnya sendiri. Lebar tiap ruas SEBANDING
   dengan lebar rentangnya, bukan dibagi rata — pita yang ruasnya sama lebar
   padahal rentangnya berbeda jauh akan membuat pembaca salah menaksir jarak
   nilainya ke ambang berikutnya, dan itu justru satu-satunya hal yang ingin
   dibacanya dari gambar ini.
   =========================================================================== */

.pita { margin: .75rem 0 1.75rem; }
.pita-batang {
    position: relative;
    display: flex;
    border-radius: var(--sp-lengkung-kecil);
    overflow: hidden;
    border: 1px solid var(--sp-garis);
}
.pita-ruas {
    min-width: 0;
    padding: .5rem .4rem .45rem;
    text-align: center;
    background: var(--sp-nonaktif-latar);
    border-right: 1px solid var(--sp-kartu);
    overflow: hidden;
}
.pita-ruas:last-child { border-right: 0; }
/* Ruas tempat nilainya berada — satu-satunya yang beraksen. */
.pita-ruas.aktif { background: var(--sp-aksen-latar); }
.pita-nama {
    display: block;
    font-size: .64rem;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--sp-teks-redup);
    white-space: nowrap;
}
.pita-ruas.aktif .pita-nama { color: var(--sp-aksen-tua); }
.pita-rentang { display: block; font-size: .66rem; color: var(--sp-teks-redup); white-space: nowrap; }

.pita-penanda {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 0;
    border-left: 2px solid var(--sp-aksen);
}
.pita-nilai {
    position: absolute;
    top: -1.35rem;
    left: 0;
    transform: translateX(-50%);
    font-size: .72rem;
    font-weight: 800;
    color: var(--sp-aksen-tua);
    white-space: nowrap;
}
.pita-tanda {
    position: absolute;
    bottom: -1.2rem;
    left: 0;
    transform: translateX(-50%);
    font-size: .58rem;
    font-weight: 800;
    letter-spacing: .1em;
    color: var(--sp-aksen);
    white-space: nowrap;
}

/* Penanda dokumen campuran: pembaca harus tahu bagian mana yang tidak akan berubah. */
.penanda-beku, .penanda-hidup {
    margin-top: 1.75rem;
    padding: .45rem .8rem;
    border-radius: var(--sp-lengkung-kecil);
    font-size: .8rem;
    border-bottom: 0;
}
.penanda-beku { background: var(--sp-krem); border-left: 4px solid var(--sp-aksen-tua); color: var(--sp-teks); }
.penanda-hidup { background: var(--sp-latar); border-left: 4px dashed var(--sp-teks-redup); color: var(--sp-teks-redup); }

/* ===========================================================================
   GAYA LAPORAN BERPITA
   ---------------------------------------------------------------------------
   Mengikuti bentuk lembar Star Jasmani milik pelatih: kop berpita warna, bilah
   judul gelap tiap bagian, tabel berkepala gelap, dan kaki bertanda tangan.

   TENTANG LATAR BERWARNA DI KERTAS.

   CLAUDE.md memperingatkan bahwa pencetak fisik kerap membuang latar berwarna,
   sehingga teks putih di atasnya lenyap. Peringatan itu tetap benar — tetapi
   alur kerja laporan ini bukan pencetak fisik melainkan "Cetak → Simpan sebagai
   PDF" pada peramban, dan di sana latar dipertahankan selama print-color-adjust
   disetel exact. Karena itu tiap bidang berlatar gelap di sini WAJIB membawa
   properti tersebut; tanpa itu, satu setelan peramban saja sudah cukup membuat
   seluruh judul bagian menghilang dari dokumen resmi.
   =========================================================================== */

.pita-warna,
.pita-bagian,
.tabel-laporan thead th,
.kaki-laporan {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}

/* ---------------------------------------------------------------------------
   KOP BERPITA — tiga kolom: merek, judul, keterangan cetak.

   Proporsinya mengikuti lembar Star Jasmani: 28% / 44% / 28%, merek tebal
   berspasi lebar di kiri, judul terbesar di tengah, tiga baris keterangan
   berukuran kecil di kanan. Yang membuat bentuk itu bekerja bukan warnanya
   melainkan HIERARKI ukurannya — 16px, 15px, 7,5px — dan jarak antar ketiganya.
   --------------------------------------------------------------------------- */

.kop-pita {
    display: grid;
    grid-template-columns: 28% minmax(0, 1fr) 28%;
    align-items: center;
    background: var(--sp-aksen-tua);
    color: #FFFFFF;
    border-radius: 6px;
    padding: 10px 16px;
    margin-bottom: 8px;
}
.kop-pita .merek-laporan {
    font-size: 16px;
    font-weight: 900;
    letter-spacing: 2px;
    text-transform: uppercase;
    line-height: 1.1;
}
/* Kata kedua merek diberi warna muda — penanda merek, bukan hiasan. */
.kop-pita .merek-laporan em { font-style: normal; color: #FFD2AE; }
.kop-pita .merek-laporan span {
    display: block;
    font-size: 7px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: #FFD2AE;
    margin-top: 2px;
}
.kop-pita .judul-tengah { text-align: center; }
.kop-pita .judul-tengah h1 {
    margin: 0;
    font-size: 15px;
    font-weight: 900;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: #FFFFFF;
    border: 0;
    padding: 0;
}
.kop-pita .judul-tengah .anak-judul {
    display: block;
    font-size: 8px;
    color: #FFD2AE;
    margin-top: 3px;
    letter-spacing: .02em;
}
.kop-pita .kanan-laporan {
    text-align: right;
    font-size: 7.5px;
    line-height: 1.8;
    color: #FFD2AE;
}

/* Salinan pribadi: pita netral. Dokumen yang bukan dokumen resmi tidak boleh
   tampak seresmi yang bertanda tangan. */
.kop-pita.pribadi { background: var(--sp-teks-redup); }
.kop-pita.pribadi .merek-laporan em,
.kop-pita.pribadi .merek-laporan span,
.kop-pita.pribadi .judul-tengah .anak-judul,
.kop-pita.pribadi .kanan-laporan { color: #F0EBE4; }

/* --- Bilah judul bagian: pengganti <h3> polos --- */
.pita-bagian {
    background: var(--sp-teks);
    color: var(--sp-latar);
    font-size: 7.5px;
    font-weight: 700;
    letter-spacing: .5px;
    text-transform: uppercase;
    padding: 5px 7px;
    border-radius: 3px 3px 0 0;
    margin: 0 0 4px;
    border: 0;
}
.pita-bagian.aksen { background: var(--sp-aksen-tua); color: #FFFFFF; }

/* --- Tabel laporan: kepala gelap, baris berselang --- */
/* Tabel dibungkus kotak bersudut supaya kepala hitamnya berhenti rapi di tepi. */
.tbl-bungkus { border: 1px solid var(--sp-garis); border-radius: 6px; overflow: hidden; }

.tabel-laporan { width: 100%; border-collapse: collapse; font-size: 8.5px; }
.tabel-laporan thead th {
    background: var(--sp-teks);
    color: var(--sp-latar);
    font-size: 7.5px;
    font-weight: 700;
    letter-spacing: .5px;
    text-transform: uppercase;
    padding: 5px 7px;
    border: 0;
    white-space: nowrap;
    text-align: center;
}
.tabel-laporan thead th:first-child { text-align: left; }
.tabel-laporan tbody td { padding: 4px 7px; border-bottom: 1px solid var(--sp-garis-samar); text-align: center; }
.tabel-laporan tbody td:first-child { text-align: left; }
.tabel-laporan tbody tr:last-child td { border-bottom: 0; }
/* Baris berselang: mata tidak kehilangan barisnya pada tabel selebar halaman. */
.tabel-laporan tbody tr:nth-child(even) { background: var(--sp-sorot-baris); }
.tabel-laporan tbody tr:hover { background: var(--sp-aksen-latar); }
.tabel-laporan td.angka, .tabel-laporan th.angka {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.tabel-laporan tfoot td, .tabel-laporan tfoot th {
    background: var(--sp-krem);
    font-weight: 800;
    padding: .3rem .5rem;
    border-top: 2px solid var(--sp-aksen);
}

/* --- Bilah kemajuan di dalam sel tabel --- */
.sel-bar {
    display: block;
    height: .45rem;
    border-radius: 999px;
    background: var(--sp-nonaktif-latar);
    min-width: 3rem;
    /* Isian tidak boleh menyembul keluar jalurnya, berapa pun persennya. */
    overflow: hidden;
}
.sel-bar > span { display: block; height: 100%; max-width: 100%; border-radius: 999px; background: var(--sp-aksen); }
.sel-bar > span.sukses { background: var(--sp-sukses-teks); }
.sel-bar > span.galat { background: var(--sp-galat); }

/*
 * KELAS KEADAAN PADA BILAH BUKAN KOTAK PESAN.
 *
 * `.sukses` dan `.galat` juga dipakai sebagai kotak pesan di seluruh sistem, dan keduanya
 * membawa padding, border, margin, serta ukuran huruf. Dipasang pada ISIAN BILAH, warisan
 * itu menggelembungkan bilahnya sampai melewati jalurnya sendiri — bilah hijau yang
 * menyembul keluar garis, persis yang terlihat pada laporan readiness.
 *
 * Warisan itu dimatikan di sini, bukan dengan mengganti nama kelasnya: nama `sukses` dan
 * `galat` sudah dipakai belasan tempat sebagai penanda keadaan, dan mengganti sebagiannya
 * saja akan meninggalkan dua kosakata untuk satu maksud.
 */
.sel-bar > span,
.bar-isi,
.bar-isian,
.bar-tipis > span {
    padding: 0;
    border: 0;
    margin: 0;
    font-size: 0;
    line-height: 0;
}

/* --- Lencana bulat bergaya grade --- */
/* ---------------------------------------------------------------------------
   STRIP ANGKA — deret sel berbingkai, label kecil di atas angka besar.

   Angka 22px di atas label 7px: perbandingan ukuran itulah yang membuat strip
   terbaca sebagai kesimpulan, bukan sebagai baris tabel biasa.
   --------------------------------------------------------------------------- */

.strip-angka {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    border: 2px solid var(--sp-aksen-tua);
    border-radius: 4px;
    margin-bottom: 8px;
    overflow: hidden;
}
.strip-angka .sel {
    padding: 8px 6px;
    text-align: center;
    border-right: 1px solid var(--sp-garis-samar);
}
.strip-angka .sel:last-child { border-right: 0; }
.strip-angka .label {
    display: block;
    font-size: 7px;
    color: var(--sp-teks-redup);
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 700;
    margin-bottom: 3px;
}
.strip-angka .nilai { display: block; font-size: 22px; font-weight: 900; line-height: 1; color: var(--sp-aksen-tua); }
.strip-angka .nilai.gelap { color: var(--sp-teks); }
.strip-angka .nilai.hijau { color: var(--sp-sukses-teks); }
.strip-angka .nilai.merah { color: var(--sp-galat); }
.strip-angka .ket { display: block; font-size: 7px; color: var(--sp-teks-redup); margin-top: 2px; }
/* Sel bertanda: latar sangat tipis, cukup untuk memisahkan tanpa berisik. */
.strip-angka .sel.sorot { background: var(--sp-aksen-latar); }
.strip-angka .sel.baik { background: var(--sp-sukses-latar); }
.strip-angka .sel.buruk { background: var(--sp-galat-latar); }

.grade {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.5rem;
    height: 1.5rem;
    padding: 0 .35rem;
    border-radius: 999px;
    font-size: .62rem;
    font-weight: 800;
    letter-spacing: .04em;
    background: var(--sp-nonaktif-latar);
    color: var(--sp-teks-redup);
}
.grade.sukses { background: var(--sp-sukses-latar); color: var(--sp-sukses-teks); }
.grade.aksen { background: var(--sp-aksen-latar); color: var(--sp-aksen-tua); }
.grade.galat { background: var(--sp-galat-latar); color: var(--sp-galat); }

/* --- Kaki laporan bertanda tangan --- */
.kaki-laporan {
    display: grid;
    grid-template-columns: 60% 40%;
    align-items: end;
    margin-top: 10px;
    padding-top: 8px;
    border-top: 2px solid var(--sp-aksen-tua);
    font-size: 7.5px;
    line-height: 1.8;
    color: var(--sp-teks-samar, var(--sp-teks-redup));
}
.kaki-laporan .merek-kaki { color: var(--sp-aksen-tua); font-size: 10px; font-weight: 900; }
.kaki-laporan .ttd { text-align: center; }
.kaki-laporan .ttd .garis {
    display: block;
    width: 100px;
    border-bottom: 1px solid var(--sp-teks);
    margin: 28px auto 4px;
}
.kaki-laporan .ttd strong { display: block; font-size: 8px; font-weight: 700; color: var(--sp-teks); }
.kaki-laporan .ttd .peran { display: block; font-size: 7px; color: var(--sp-teks-redup); }

/* ===========================================================================
   LEMBAR PROFIL KONDISI FISIK
   ---------------------------------------------------------------------------
   Lembar satu halaman bergaya berkas Excel pelatih: kop kuning, pita nama,
   tabel berkepala oranye, dan radar per komponen.

   TENTANG PALET.

   CLAUDE.md menetapkan keluarga oranye sebagai aksen TUNGGAL, tanpa warna merek
   baru. Lembar ini menambahkan kuning dan hijau — dan itu keputusan pemilik
   sistem, bukan kelalaian: kedua warna sudah dipakai pada berkas yang selama ini
   diserahkan ke instansi, dan menyeragamkannya ke oranye akan membuat dokumen
   ini tidak lagi dikenali sebagai lembar yang sama.

   Batasnya tetap: kuning dan hijau hanya hidup DI DALAM lembar ini. Layar
   aplikasi tidak menyentuhnya sama sekali.

   LEBARNYA TETAP 210mm, bukan mengikuti lebar viewport. Tata letak yang
   bergantung lebar peramban akan tampil berbeda antara layar dan hasil cetak,
   dan perbedaan itu baru ketahuan setelah PDF-nya terlanjur dikirim.
   =========================================================================== */

.lembar-profil {
    --lp-kuning: #FFC72C;
    --lp-kuning-muda: #FFE082;
    --lp-oranye: #F5A623;
    --lp-hijau: #8BC34A;
    --lp-hijau-muda: #E8F5E0;
    --lp-tinta: #14110C;
    --lp-garis: #C9C4BA;
    --lp-gelap: #23201B;

    width: 210mm;
    max-width: 100%;
    margin: 0 auto;
    background: #FFFFFF;
    color: var(--lp-tinta);
    padding: 0 0 6mm;
    font-size: 8.6pt;
    line-height: 1.35;
}

.lembar-profil,
.lembar-profil .lp-kop,
.lembar-profil .lp-pita,
.lembar-profil th,
.lembar-profil .lp-panel-gelap {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}

/* --- Kop kuning: logo kiri, judul besar, logo kanan --- */
.lp-kop {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 4mm;
    background: linear-gradient(90deg, var(--lp-oranye), var(--lp-kuning));
    padding: 2.5mm 4mm;
    border-bottom: 2px solid var(--lp-tinta);
}
.lp-kop h1 {
    margin: 0;
    text-align: center;
    font-size: 15pt;
    font-weight: 900;
    letter-spacing: .04em;
    color: var(--lp-tinta);
    text-transform: uppercase;
}
.lp-logo { display: flex; gap: 2mm; align-items: center; }
.lp-logo img, .lp-logo .lp-logo-kosong {
    width: 9mm;
    height: 9mm;
    object-fit: contain;
    border-radius: 2px;
}
/* Slot logo yang belum diisi: kotak bergaris putus, bukan gambar rusak. */
.lp-logo .lp-logo-kosong {
    border: 1px dashed color-mix(in srgb, var(--lp-tinta) 45%, transparent);
    display: block;
}

/* --- Pita nama atlet --- */
.lp-pita {
    background: var(--lp-kuning);
    border: 1px solid var(--lp-tinta);
    border-top: 0;
    padding: 1.4mm 4mm;
    font-weight: 900;
    font-size: 11pt;
    letter-spacing: .02em;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 3mm;
}
.lp-pita .lp-kelas { font-size: 8pt; font-weight: 700; letter-spacing: .1em; }

/* --- Kerangka isi --- */
.lp-isi { padding: 3mm 4mm 0; display: flex; flex-direction: column; gap: 2.5mm; }
.lp-baris { display: grid; gap: 2.5mm; align-items: start; }
.lp-baris.bio { grid-template-columns: 26mm minmax(0, 1fr) minmax(0, 1.25fr); }
.lp-baris.dua { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }

/* Tiap blok utama tidak boleh terpotong di tengah halaman. */
.lp-blok { break-inside: avoid; page-break-inside: avoid; }

.lp-judul {
    background: var(--lp-oranye);
    border: 1px solid var(--lp-tinta);
    color: var(--lp-tinta);
    font-size: 7pt;
    font-weight: 900;
    letter-spacing: .1em;
    text-transform: uppercase;
    padding: .9mm 2mm;
    margin: 0 0 1mm;
    text-align: center;
}
.lp-judul.kuning { background: var(--lp-kuning); }
/* Judul kedua di dalam satu kolom: diberi jarak atas supaya tidak menempel pada
   panel di atasnya, tanpa memakai blok pemisah yang menambah tinggi lagi. */
.lp-judul-rapat { margin-top: 2mm; }

/* --- Foto atlet --- */
.lp-foto {
    width: 26mm;
    height: 34mm;
    object-fit: cover;
    border: 1px solid var(--lp-tinta);
    display: block;
    background: #EFEDE8;
}
.lp-foto-kosong {
    width: 26mm;
    height: 34mm;
    border: 1px dashed var(--lp-garis);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    font-size: 6.5pt;
    color: #8A8578;
    padding: 2mm;
}

/* --- Tabel lembar --- */
.lp-tabel { width: 100%; border-collapse: collapse; font-size: 7.6pt; }
.lp-tabel th {
    background: var(--lp-kuning);
    border: 1px solid var(--lp-garis);
    padding: .8mm 1.4mm;
    font-size: 6.6pt;
    font-weight: 900;
    letter-spacing: .04em;
    text-transform: uppercase;
    text-align: center;
    color: var(--lp-tinta);
}
.lp-tabel td { border: 1px solid var(--lp-garis); padding: .7mm 1.4mm; }
.lp-tabel td.nama { font-weight: 700; text-align: left; }
.lp-tabel td.angka { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lp-tabel tbody tr:nth-child(4n+3),
.lp-tabel tbody tr:nth-child(4n+4) { background: #FAF9F6; }
/* Baris persen di bawah nilai mentah: lebih kecil dan redup. */
.lp-tabel tr.lp-persen td { font-size: 6.8pt; color: #6B6558; border-top: 0; }
/* Kolom tes acuan disorot hijau muda, seperti pada berkas aslinya. */
.lp-tabel .acuan { background: var(--lp-hijau-muda); }
.lp-tabel tr.lp-persen td.acuan { background: var(--lp-hijau-muda); }
.lp-tabel .baik { color: #3C7A12; font-weight: 700; }
.lp-tabel .kurang { color: #B3261E; font-weight: 700; }

/* --- Panel gelap untuk grafik --- */
.lp-panel-gelap {
    background: radial-gradient(circle at 50% 35%, #3A362F 0%, var(--lp-gelap) 70%);
    border: 1px solid var(--lp-tinta);
    padding: 1.5mm;
    text-align: center;
}
.lp-panel-gelap .lp-panel-judul {
    font-size: 6.4pt;
    font-weight: 900;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--lp-kuning);
    margin-bottom: .8mm;
}

/* --- Tes turunan pada lembar: RAST, Bleep, dan 1RM ---

   PANELNYA TERANG, bukan gelap seperti panel radar di atasnya, dan itu bukan selera.
   Grafik garis mewarnai jalur serta angkanya dari token --sp-*, dan blok @media print
   menyetel ulang seluruh token itu ke nilai TERANG supaya laporan biasa tidak keluar
   sebagai teks putih di atas latar yang dibuang pencetak. Di atas panel gelap, akibatnya
   tinta gelap di atas latar gelap: grafiknya utuh di layar dan kosong di kertas, dan
   perbedaan itu baru ketahuan sesudah PDF-nya terlanjur dikirim.

   Warnanya juga diikat ke --lp-* di dalam ruang lingkup lembar. Lembar ini SELALU putih,
   di layar maupun di kertas, jadi ia tidak boleh ikut berganti bersama tema aplikasi. */
.lp-turunan .lp-sub {
    font-size: 6.6pt;
    font-weight: 900;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #6B6558;
    margin: 0 0 1mm;
}
.lp-turunan .lp-baris.dua { margin-bottom: 2mm; align-items: start; }
.lp-turunan .lp-kosong {
    border: 1px dashed var(--lp-garis);
    padding: 3mm 2mm;
    text-align: center;
    font-size: 7pt;
    color: #8A8578;
    margin: 0;
}
.lp-panel-terang {
    background: #FFFDF6;
    border: 1px solid var(--lp-garis);
    padding: 1.5mm 1mm .5mm;
    text-align: center;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}

.lembar-profil .grafik-kisi { stroke: color-mix(in srgb, var(--lp-tinta) 14%, transparent); }
.lembar-profil .grafik-label,
.lembar-profil .grafik-label.sumbu { fill: #6B6558; }
.lembar-profil .grafik-sumbu { stroke: color-mix(in srgb, var(--lp-tinta) 45%, transparent); }
.lembar-profil .multigaris-angka { fill: var(--lp-tinta); font-size: 11px; }
.lembar-profil .multigaris-legenda { font-size: 6.4pt; color: #6B6558; }

/* Empat deret, dibedakan WARNA dan POLA sekaligus. Polanya datang dari komponennya
   sendiri; yang disetel di sini hanya warnanya, dan keempatnya dipilih agar tetap
   berbeda gelap-terangnya ketika pencetak kantor mengeluarkannya sebagai abu-abu. */
.lembar-profil .multigaris-jalur.deret-0,
.lembar-profil .multigaris-titik.deret-0 { stroke: #C77800; fill: #C77800; }
.lembar-profil .multigaris-jalur.deret-1,
.lembar-profil .multigaris-titik.deret-1 { stroke: var(--lp-tinta); fill: var(--lp-tinta); }
.lembar-profil .multigaris-jalur.deret-2,
.lembar-profil .multigaris-titik.deret-2 { stroke: #6B6558; fill: #6B6558; }
.lembar-profil .multigaris-jalur.deret-3,
.lembar-profil .multigaris-titik.deret-3 { stroke: #5A8F2A; fill: #5A8F2A; }

/* Batas kategori VO2max, dicetak sebagai deret kecil di bawah tabelnya. */
.lp-ambang {
    display: flex;
    flex-wrap: wrap;
    gap: .8mm 2mm;
    margin: 1mm 0 0;
    font-size: 6.4pt;
    color: #6B6558;
}
.lp-ambang span { white-space: nowrap; }

.lp-tabel-rm td.hijau { color: #4B7A1F; font-weight: 700; }

/* --- Radar ---
   Aturan BAWAAN memakai token --sp-*, bukan --lp-*. Radar semula hanya hidup di lembar
   profil A4, sehingga warnanya diambil dari custom property lembar itu; begitu ia dipakai
   di dasbor dan laporan lain, property tersebut tidak ada di sana dan garisnya kehilangan
   warna tanpa satu pun galat yang terlihat. Nilai lembar dikembalikan di bawah, di dalam
   ruang lingkupnya sendiri.

   Lebarnya juga dibatasi dalam rem, bukan mm. Batas 46mm masuk akal di atas kertas dan
   terlalu kecil di layar — label sumbunya menyusut sampai tidak terbaca, dan radar yang
   tidak terbaca angkanya berhenti menjadi grafik. */
.radar { width: 100%; height: auto; max-width: 26rem; display: block; margin: 0 auto; }
.radar-jaring { fill: none; stroke: color-mix(in srgb, var(--sp-teks) 18%, transparent); stroke-width: 1; }
.radar-jaring.luar { stroke: color-mix(in srgb, var(--sp-teks) 38%, transparent); }
.radar-jari { stroke: color-mix(in srgb, var(--sp-teks) 16%, transparent); stroke-width: 1; }
.radar-isi {
    fill: color-mix(in srgb, var(--sp-aksen) 30%, transparent);
    stroke: var(--sp-aksen);
    stroke-width: 1.6;
}
.radar-titik { fill: var(--sp-aksen); }
.radar-label { font-size: 9px; fill: var(--sp-teks); }
.radar-angka { font-size: 9px; font-weight: 800; fill: var(--sp-aksen); }
.radar-skala { font-size: 8px; fill: var(--sp-teks-redup); }
/* Deret pembanding: poligon bergaris putus tanpa isian, supaya tetap terbedakan pada
   cetakan hitam putih dan poligon atlet tetap yang terbaca lebih dulu. */
.radar-banding { fill: none; stroke: var(--sp-teks); stroke-width: 1.4; stroke-dasharray: 5 3; }
.radar-contoh-utama { stroke: var(--sp-aksen); stroke-width: 2.4; }
.radar-contoh-banding { stroke: var(--sp-teks); stroke-width: 2; stroke-dasharray: 5 3; }
/* Garis acuan pada grafik batang — rata-rata regu dan sejenisnya. */
/* --- Bilah laporan: satu baris header, bukan tumpukan formulir ---
   Bilah ini tidak pernah ikut tercetak (.tanpa-cetak). Susunannya mendatar supaya tombol
   yang paling sering ditekan — cetak — tidak tenggelam di antara kotak isian yang jarang
   dipakai. Menyempit sendiri menjadi dua baris di layar kecil. */
.bilah-laporan {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .6rem 1rem;
    padding: .7rem 1.25rem;
    margin-bottom: 1rem;
    border-bottom: 1px solid var(--sp-garis);
    background: var(--sp-kartu);
    position: sticky;
    top: 0;
    z-index: 5;
}
.bilah-laporan .sisi-kiri,
.bilah-laporan .sisi-kanan { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.bilah-laporan .ruas-bilah { display: flex; align-items: center; gap: .4rem; margin: 0; }
.bilah-laporan .ruas-bilah input[type="text"] {
    width: min(18rem, 46vw);
    margin: 0;
    padding: .3rem .6rem;
    font-size: .78rem;
}
.bilah-laporan button[disabled] { opacity: .45; cursor: not-allowed; }

/*
 * Bilah lembar A4. Memakai kerangka .bilah-laporan, dengan dua perbedaan.
 *
 * Keterangan "Background graphics" dibatasi lebarnya dan dikecilkan: ia dibaca sekali
 * saat pertama mencetak, lalu tidak pernah lagi, sedangkan tombol di sebelahnya ditekan
 * tiap kali. Tanpa batas lebar ia meregang mengisi seluruh sisa baris dan menjadi
 * bagian paling menonjol pada bilah yang bukan miliknya.
 *
 * Lembarnya sendiri berlebar TETAP 210mm dan dipusatkan, jadi bilahnya ikut dipusatkan
 * pada lebar yang sama. Bilah selebar viewport di atas lembar selebar 210mm membuat
 * tombolnya terlempar jauh dari halaman yang dikendalikannya.
 */
.bilah-lembar {
    width: min(210mm, 100%);
    margin-left: auto;
    margin-right: auto;
    border: 1px solid var(--sp-garis);
    border-radius: .5rem;
}
.bilah-lembar .catatan-cetak {
    margin: 0;
    max-width: 26rem;
    font-size: .74rem;
    line-height: 1.4;
}
.bilah-pesan { padding: 0 1.25rem; margin-bottom: .75rem; }

@media (max-width: 40rem) {
    .bilah-laporan { position: static; padding: .6rem .9rem; }
    .bilah-laporan .ruas-bilah input[type="text"] { width: 100%; }
    .bilah-laporan .sisi-kanan { width: 100%; }
    .bilah-laporan .ruas-bilah { width: 100%; }
}

/* --- Kartu Parameter RAST: kurva di kiri, hasil hitungan di kanan ---
   Susunan ini meniru lembar pelatih: grafik memakan ruang, empat angka hasilnya berdiri
   sebagai kolom sempit di sampingnya. Menumpuknya ke bawah membuat tiap parameter memakan
   satu halaman sendiri, dan lembar berisi empat parameter menjadi empat halaman. */
.parameter-rast {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(9rem, 13rem);
    gap: 1rem;
    align-items: start;
}
.parameter-rast .kurva { min-width: 0; }
.parameter-rast .panel-hasil th { white-space: nowrap; }
.parameter-rast .panel-hasil td { text-align: right; font-weight: 800; font-variant-numeric: tabular-nums; }

@media (max-width: 48rem) {
    .parameter-rast { grid-template-columns: 1fr; }
}

/* --- Kepala identitas MENDATAR ---
   Tabel kunci-nilai menurun memakan sepertiga halaman pertama untuk enam baris yang
   seluruhnya pendek, dan mendorong grafik — pokok lembarnya — turun ke bawah lipatan.
   Dijajarkan mendatar, keenamnya muat dalam dua baris dan grafik naik ke atas. */
/*
 * TIAP MEDAN IDENTITAS BERDIRI SEBAGAI KARTUNYA SENDIRI.
 *
 * Semula keenamnya berbagi satu panel: satu kotak berlatar, isinya enam pasang label dan
 * nilai yang hanya dipisahkan jarak. Pada lebar penuh, "Kelas tanding" dan nilai
 * sebelahnya duduk berdekatan tanpa batas apa pun, dan matanya harus menebak pasangan
 * mana milik siapa. Diberi latar masing-masing, tiap medan menjadi satuan yang jelas —
 * dan barisnya tetap rapi ketika salah satu nilainya jauh lebih panjang daripada yang lain.
 *
 * Pembungkusnya kini tanpa latar dan tanpa garis: yang berlatar adalah medannya, bukan
 * kotak yang menampung mereka.
 */
.kop-identitas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: .6rem;
    margin-bottom: var(--sp-sela);
}
.kop-identitas .medan {
    display: flex;
    flex-direction: column;
    gap: .2rem;
    min-width: 0;
    padding: .6rem .8rem;
    border: 1px solid var(--sp-garis);
    border-radius: var(--sp-lengkung-kecil);
    background: var(--sp-kartu);
    /* Garis aksen tipis di kiri: penanda yang sama dengan kartu nilai di seluruh sistem,
       supaya medan identitas terbaca sebagai keluarga yang sama. */
    border-left: 3px solid var(--sp-aksen);
}
.kop-identitas .label {
    font-size: .62rem;
    font-weight: 800;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--sp-teks-redup);
}
.kop-identitas .nilai { font-size: .95rem; font-weight: 700; line-height: 1.3; }
.kop-identitas .nilai .redup { font-weight: 400; font-size: .8rem; }

/* --- Medan UTAMA: nama atlet dicetak besar ---
   Pada lembar per atlet, nama orangnya adalah satu-satunya keterangan yang dicari
   pembaca lebih dulu; sisanya (gender, kelas, periode) baru dibaca sesudah ia yakin
   memegang berkas orang yang benar. Sebelumnya nama itu hanya muncul sebagai anak
   judul pada kop -- seukuran keterangan periode di sebelahnya, sehingga berkas dua
   atlet berbeda terbaca nyaris sama sekilas pandang, dan yang tertukar baru ketahuan
   sesudah dokumennya terlanjur diserahkan.

   Yang dibesarkan NILAINYA, bukan labelnya: label "Atlet" tetap sekecil label medan
   lain supaya keluarga medannya tidak pecah. Medannya mengambil dua kolom sebab nama
   lengkap Indonesia kerap tiga kata atau lebih, dan satu kolom memaksanya patah di
   tempat yang tidak dipilih siapa pun. */
.kop-identitas .medan.utama { grid-column: span 2; border-left-width: 5px; }
.kop-identitas .medan.utama .nilai { font-size: 1.55rem; line-height: 1.15; }

@media (max-width: 40rem) {
    .kop-identitas { grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); gap: .45rem; }
    .kop-identitas .medan { padding: .45rem .6rem; }
    /* Dua kolom tidak muat di layar sempit; medan utama mengambil seluruh baris
       supaya namanya tetap utuh alih-alih patah di tengah kata. */
    .kop-identitas .medan.utama { grid-column: 1 / -1; }
    .kop-identitas .medan.utama .nilai { font-size: 1.3rem; }
}

/* --- Garis acuan pada grafik batang ---
   Tiga gaya yang dapat dibedakan TANPA warna: titik-titik untuk target baku, padat untuk
   rerata regu, putus untuk rerata kelompok. Bentuk referensi memakai warna emas untuk
   rerata regu; di sini warnanya mengikuti aksen sistem, tetapi pembedanya tetap polanya —
   cetakan hitam putih adalah tempat garis acuan paling sering dibaca. */
.grafik-acuan { stroke: var(--sp-teks-redup); stroke-width: 1.6; fill: none; }
.grafik-acuan.gaya-titik { stroke-dasharray: 2 4; }
.grafik-acuan.gaya-padat { stroke: var(--sp-aksen); stroke-dasharray: none; }
.grafik-acuan.gaya-putus { stroke-dasharray: 8 4; }
.grafik-label.acuan { font-size: 12px; fill: var(--sp-teks-redup); }

/* Di dalam lembar A4 radar kembali memakai palet dan satuan lembar itu. */
.lembar-profil .radar { max-width: 46mm; }
.lembar-profil .radar-isi { fill: rgba(245, 166, 35, .35); stroke: var(--lp-oranye); }
.lembar-profil .radar-titik { fill: var(--lp-oranye); }
.lembar-profil .radar-label { font-size: 6px; fill: #E8E4DA; }
.lembar-profil .radar-angka { font-size: 6px; fill: var(--lp-kuning); }
.lembar-profil .radar-skala { font-size: 5px; }
.lembar-profil .radar-jaring { stroke: rgba(232, 228, 218, .22); }
.lembar-profil .radar-jaring.luar { stroke: rgba(232, 228, 218, .45); }
.lembar-profil .radar-jari { stroke: rgba(232, 228, 218, .2); }
.lembar-profil .radar-banding { stroke: var(--lp-hijau); }

/* --- Radar besar: satu radar berisi seluruh item --- */
.lp-radar-besar { padding: 2mm 1mm 1mm; }
.lembar-profil .lp-radar-besar .radar { max-width: 62mm; }

/* --- Panel capaian per komponen biomotor --- */
.lp-komponen-deret {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(28mm, 1fr));
    gap: 1.2mm;
    margin-top: 1.5mm;
}
.lp-komponen {
    border: 1px solid var(--lp-garis);
    border-left: 2.5px solid var(--lp-oranye);
    padding: 1mm 1.4mm 1.2mm;
}
.lp-komponen.baik { border-left-color: var(--lp-hijau); }
.lp-komponen.kurang { border-left-color: #B3261E; }
.lp-komponen-nama {
    display: block;
    font-size: 5.8pt;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #6B6558;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.lp-komponen-nilai { display: block; font-size: 10.5pt; font-weight: 900; line-height: 1.15; }
.lp-komponen.baik .lp-komponen-nilai { color: #3C7A12; }
.lp-komponen.kurang .lp-komponen-nilai { color: #B3261E; }
.lp-komponen-bar { display: block; height: .9mm; background: #E7E4DC; border-radius: 999px; margin-top: .5mm; }
.lp-komponen-bar > span { display: block; height: 100%; border-radius: 999px; background: var(--lp-oranye); }
.lp-komponen.baik .lp-komponen-bar > span { background: var(--lp-hijau); }
.lp-komponen.kurang .lp-komponen-bar > span { background: #B3261E; }

/* --- Grafik berat per bulan --- */
.lp-bulan { display: flex; align-items: flex-end; gap: 1mm; height: 22mm; padding: 0 1mm; }
.lp-bulan .kolom { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; height: 100%; }
.lp-bulan .batang { width: 100%; background: var(--lp-hijau); border-radius: 1px 1px 0 0; min-height: 1px; }
.lp-bulan .batang.kosong { background: rgba(255, 255, 255, .12); }
.lp-bulan .angka { font-size: 5.6pt; font-weight: 700; color: #F2EFE6; margin-bottom: .4mm; }
.lp-bulan .bulan { font-size: 5.6pt; color: #B9B4A8; margin-top: .5mm; }

/* --- Kartu angka ringkas --- */
.lp-angka-deret { display: grid; grid-template-columns: repeat(auto-fit, minmax(22mm, 1fr)); gap: 1.5mm; }
.lp-angka {
    border: 1px solid var(--lp-garis);
    border-top: 2px solid var(--lp-oranye);
    padding: 1.2mm 1.6mm;
    text-align: center;
}
.lp-angka .lp-label { display: block; font-size: 5.8pt; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: #6B6558; }
.lp-angka .lp-nilai { display: block; font-size: 12pt; font-weight: 900; line-height: 1.1; }
.lp-angka .lp-ket { display: block; font-size: 6pt; color: #6B6558; }
.lp-angka.hijau { border-top-color: var(--lp-hijau); }
.lp-angka.hijau .lp-nilai { color: #3C7A12; }
.lp-angka.merah { border-top-color: #B3261E; }
.lp-angka.merah .lp-nilai { color: #B3261E; }

/*
 * ANGKA PAHLAWAN pada ringkasan.
 *
 * Kelima angka ringkasan sebelumnya berukuran sama persis dan berjajar rata, sehingga
 * tidak satu pun menonjol dan pembacanya membaca kelimanya berturut-turut untuk
 * menemukan yang dicarinya. Yang pertama ditanyakan pembaca lembar ini selalu satu:
 * seberapa jauh atlet ini dari targetnya secara keseluruhan.
 *
 * Latarnya diberi warna, jadi ia WAJIB membawa print-color-adjust: exact. Alur cetaknya
 * "Simpan sebagai PDF", dan tanpa properti itu bloknya keluar putih polos -- justru
 * bagian yang paling dimaksudkan untuk terlihat.
 */
.lp-sorot { margin-bottom: 1.5mm; }
.lp-sorot-angka {
    background: linear-gradient(90deg, var(--lp-kuning) 0%, var(--lp-kuning-muda) 100%);
    border: 1px solid var(--lp-tinta);
    border-left: 3mm solid var(--lp-oranye);
    padding: 1.8mm 3mm;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}
.lp-sorot-angka .lp-label {
    display: block;
    font-size: 6pt;
    font-weight: 900;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: #6B5A18;
}
.lp-sorot-angka .lp-besar {
    display: block;
    font-size: 22pt;
    font-weight: 900;
    line-height: 1;
    color: var(--lp-tinta);
    font-variant-numeric: tabular-nums;
}
.lp-sorot-angka .lp-ket { display: block; font-size: 6.2pt; color: #6B5A18; margin-top: .4mm; }

/* Bilah capaian: angka yang sama, digambar sebagai JARAK menuju 100. */
.lp-sorot-bar {
    display: block;
    height: 1.6mm;
    margin-top: 1.2mm;
    background: rgba(20, 17, 12, .18);
    overflow: hidden;
}
.lp-sorot-bar > span {
    display: block;
    height: 100%;
    background: var(--lp-tinta);
}
.lp-sorot-angka.baik .lp-sorot-bar > span { background: #3C7A12; }
.lp-sorot-angka.kurang .lp-sorot-bar > span { background: #B3261E; }

/*
 * KEPALA KELOMPOK BIOMOTOR di dalam tabel item.
 *
 * Sebelumnya sebelas parameter mengalir sebagai satu daftar tanpa satu pun batas, dan
 * pembacanya harus tahu sendiri mana yang termasuk Power dan mana yang Speed. Berkas
 * Excel pelatih memisahkannya dengan baris berwarna; ini bentuk yang sama.
 */
.lp-tabel tr.lp-kelompok th {
    background: var(--lp-oranye);
    color: var(--lp-tinta);
    text-align: left;
    font-size: 6.4pt;
    font-weight: 900;
    letter-spacing: .1em;
    text-transform: uppercase;
    padding: .9mm 1.4mm;
    border: 1px solid var(--lp-tinta);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}
.lp-tabel tr.lp-kelompok th > span { display: inline-block; }
.lp-tabel tr.lp-kelompok .lp-kelompok-nilai {
    float: right;
    font-variant-numeric: tabular-nums;
}

/* Lencana kategori: satu kata yang menentukan pembacaan seluruh panelnya. */
.lp-lencana {
    display: inline-block;
    background: var(--lp-hijau-muda);
    border: 1px solid var(--lp-hijau);
    color: #3C7A12;
    font-size: 6pt;
    font-weight: 900;
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: .3mm 1.2mm;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}

/* --- Kaki lembar --- */
.lp-kaki {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: 4mm;
    margin: 3mm 4mm 0;
    padding-top: 1.5mm;
    border-top: 2px solid var(--lp-oranye);
    font-size: 6.4pt;
    color: #6B6558;
}
.lp-kaki .ttd { text-align: center; min-width: 42mm; }
.lp-kaki .ttd .garis { display: block; border-bottom: 1px solid var(--lp-tinta); height: 8mm; margin-bottom: .6mm; }
.lp-kaki .ttd strong { color: var(--lp-tinta); font-size: 7.2pt; }

/* ---------------------------------------------------------------------------
   Layar sempit: lebar tetap 210mm akan menggeser halaman, jadi ia diperkecil
   secara proporsional — BUKAN diubah tata letaknya. Yang dilihat di layar harus
   sama persis dengan yang keluar di kertas.
   --------------------------------------------------------------------------- */
@media (max-width: 220mm) {
    .lembar-profil {
        width: 210mm;
        transform-origin: top left;
        transform: scale(calc(100vw / 230mm));
    }
    .pembungkus-lembar { overflow: hidden; }
}



@media print {
    /*
     * KERTAS SELALU TERANG.
     *
     * Seluruh token disetel ulang ke nilai terang di sini. Layar boleh gelap, kertas
     * tidak: mencetak latar hitam menghabiskan tinta, dan sebagian besar pencetak
     * membuang latar berwarna sehingga teks putih di atasnya hilang sama sekali —
     * laporan resmi yang keluar kosong adalah kegagalan yang paling mahal.
     */
    :root {
        --sp-latar: #FFFFFF;
        --sp-kartu: #FFFFFF;
        --sp-krem: #FBE7C6;
        --sp-teks: #1F1B16;
        --sp-teks-redup: #6B6055;
        --sp-galat: #B3261E;
        --sp-sukses-latar: #ECFDF5;
        --sp-sukses-garis: #A7F3D0;
        --sp-sukses-teks: #065F46;
        --sp-nonaktif-latar: #ECE6DF;
        --sp-garis: #D9CDBC;
        --sp-garis-samar: #EBE2D6;
        --sp-cahaya: none;
        --sp-bayang: none;
        --sp-bayang-naik: none;
    }

    /* Kertas selalu terang, termasuk widget bawaan peramban. */
    :root { color-scheme: light; }

    body { background: #FFFFFF; color: #1F1B16; }

    /*
     * KERTAS TIDAK DAPAT DIGULIR.
     *
     * Setiap pembungkus yang menggulir di layar WAJIB melepaskan isinya di sini.
     * Kalau tidak, bagian yang berada di luar kotaknya tidak sekadar tersembunyi
     * — ia hilang dari cetakan, tanpa satu pun tanda bahwa ada yang hilang.
     *
     * Ditulis menyapu seluruh kelas pembungkus, bukan satu per satu sesuai yang
     * kebetulan sedang dipakai laporan: kelas gulir berikutnya yang ditambahkan
     * ke sebuah view laporan tidak akan mengulang kekeliruan yang sama.
     */
    .gulir, .gulir-grid, .gulir-laporan, .kartu, .tren {
        overflow: visible !important;
        max-height: none !important;
    }

    /* Kolom dan kepala yang menempel hanya bermakna pada bidang yang bergulir. */
    .lengket-kiri, .grid thead th, .tabel-rekap .lengket-kiri {
        position: static !important;
    }

    /* Di kertas, sel boleh membungkus: yang penting muat, bukan tetap satu baris. */
    .grid th, .grid td, .tabel-rekap th, .tabel-rekap td { white-space: normal; }

    /* Tabel rekap periode dapat berkolom banyak; dikecilkan supaya tetap masuk. */
    .tabel-rekap { font-size: .78rem; }
    .gulir-laporan { border: 0; }

    /*
     * BLOK HASIL TES SATU ATLET tidak dibelah halaman bila memang muat.
     *
     * Blok yang terbelah membuat kepala "nama atlet" tertinggal di halaman
     * sebelumnya, dan pembaca yang membalik halaman menemukan tabel angka tanpa
     * tahu itu milik siapa. `avoid` hanya berlaku bila bloknya cukup pendek;
     * blok yang lebih tinggi daripada satu halaman tetap dibelah, dan untuk itu
     * kepala tabelnya diulang lewat thead.
     */
    .blok-atlet { break-inside: avoid; page-break-inside: avoid; }
    .kepala-atlet { break-after: avoid; page-break-after: avoid; }
    .tabel-atlet thead { display: table-header-group; }

    /*
     * KEPALA BAGIAN TIDAK PERNAH TERTINGGAL SENDIRIAN di kaki halaman.
     *
     * Judul yang terpisah dari isinya lebih buruk daripada tidak berjudul: pembacanya
     * mencari isi bagian itu di halaman yang sama, tidak menemukannya, lalu menyimpulkan
     * bagiannya kosong. Berlaku untuk seluruh laporan, bukan hanya blok atlet.
     */
    .pita-bagian, .penanda-beku, .penanda-hidup { break-after: avoid; page-break-after: avoid; }
    .tabel-atlet tr { break-inside: avoid; page-break-inside: avoid; }

    /*
     * PEMADATAN KERTAS.
     *
     * Ukuran yang lapang di layar memboroskan halaman di kertas: satu halaman A4
     * bermargin 1,6cm hanya menyisakan tinggi isi sekitar 24,7cm, dan tiap
     * pergantian halaman memaksa pembacanya kehilangan konteks. Yang dikecilkan
     * hanya JARAK dan UKURAN — tidak satu pun isi yang dibuang di sini; yang
     * memang tidak perlu dicetak sudah bertanda .tanpa-cetak di viewnya.
     */
    body { font-size: 12px; line-height: 1.4; }

    .papan { gap: .4rem; margin-bottom: .4rem; }
    .kartu-nilai { padding: .3rem .55rem .35rem; border-top-width: 2px; }
    .kartu-nilai .angka { font-size: 1rem; line-height: 1.15; }
    .kartu-nilai .label { font-size: .58rem; }
    .kartu-nilai .satuan { font-size: .62rem; }

    .peringatan { padding: .3rem .55rem; margin-bottom: .35rem; font-size: .72rem; }

    h2 { margin-bottom: .4rem; padding-bottom: .25rem; }
    h3 { margin: .5rem 0 .3rem; font-size: .92rem; }
    p { margin: .25rem 0; }

    table { font-size: .78rem; }
    th, td { padding: .22rem .4rem; }

    .dua-kolom { gap: .75rem; }
    /*
     * TINGGI GRAFIK DIPATOK HANYA DI LEMBAR A4 YANG PADAT.
     *
     * Aturan ini semula berlaku untuk SELURUH grafik di kertas: `.grafik { max-height:
     * 5.25rem }`. Itu masuk akal ketika satu-satunya grafik cetak adalah pelengkap kecil
     * pada lembar profil A4, dan menjadi keliru begitu ada laporan yang grafiknya justru
     * POKOK halaman. Pada 5,25rem — kira-kira 84 piksel — grafik berbidang 640×260
     * menyusut menjadi selebar 207 piksel di tengah halaman selebar 900: angkanya tidak
     * terbaca, dan pembacanya menyimpulkan grafiknya rusak.
     *
     * Sekarang pembatasnya diberi RUANG LINGKUP. Di dalam `.lembar-profil` grafik tetap
     * pelengkap dan tetap dipatok; di laporan lain ia dibiarkan setinggi rasionya, dengan
     * batas atas yang longgar supaya satu grafik tidak menghabiskan satu halaman penuh.
     */
    .lembar-profil .grafik { max-height: 5.25rem; }
    /*
     * PENGECUALIAN dari patokan di atas. Pada tiga panel tes turunan, grafiknya bukan
     * pelengkap melainkan ISI panelnya: kurva enam sprint dan deret VO2max lintas sesi
     * tidak menyampaikan apa pun pada 84 piksel, dan panel yang menyisakan tabel angka
     * saja lebih baik tidak bergrafik sama sekali daripada bergrafik yang tidak terbaca.
     * Batasnya tetap ada supaya satu panel tidak menghabiskan setengah halaman.
     */
    .lembar-profil .lp-grafik-pokok .grafik { max-height: 34mm; }
    .lembar-profil .grafik-garis { max-height: none; height: 6.4rem; width: 100%; }

    /*
     * Grafik pada laporan biasa: setinggi rasionya, dibatasi seperempat halaman A4.
     * Yang dibaca dari grafik cetak adalah bentuk deret DAN angkanya — dan angka itulah
     * yang pertama hilang ketika gambarnya diperkecil.
     */
    .grafik { max-height: 62mm; }
    .grafik.multigaris { max-height: 68mm; }
    .grafik.multigaris.mini { max-height: 1.6rem; }

    /* Pita kop dan judul bagian dirapatkan, tetapi tidak dihilangkan warnanya. */
    /* Kop dan tabel sudah berukuran piksel kecil di layar; di kertas hanya
       jaraknya yang dirapatkan, ukurannya tidak diubah lagi. */
    .kop-pita { padding: 7px 12px; margin-bottom: 6px; }
    .pita-bagian { padding: 4px 6px; margin-bottom: 3px; }
    .tabel-laporan thead th, .tabel-laporan tbody td { padding: 3px 5px; }
    .strip-angka { margin-bottom: 6px; }
    .strip-angka .sel { padding: 5px 4px; }
    .strip-angka .nilai { font-size: 17px; }
    .kaki-laporan { margin-top: 7px; padding-top: 5px; }
    .kaki-laporan .ttd .garis { margin-top: 16px; }

    .donat-deret { grid-template-columns: repeat(auto-fit, minmax(5rem, 1fr)); gap: .35rem; }
    .donat-satu .donat { width: 3.9rem; height: 3.9rem; }
    .donat-judul { font-size: .6rem; }

    /* Bar mendatar: lebih rapat, tetapi bilahnya tetap terlihat. */
    .bar-daftar { gap: .18rem; margin: .3rem 0; }
    .bar-baris { grid-template-columns: minmax(5rem, 9rem) minmax(0, 1fr) 2.8rem; gap: .45rem; }
    .bar-label, .bar-nilai { font-size: .72rem; }
    .bar-jalur { height: .45rem; }

    /* Daftar berbaris pendek dirapatkan sekali lagi khusus di kertas. */
    .ringkas { font-size: .72rem; }
    .ringkas th, .ringkas td { padding: .16rem .35rem; }

    .kop { padding-top: .75rem; padding-bottom: .5rem; }
    .kop h1 { font-size: 1.2rem; }
    .isi-cetak { padding-bottom: 0; }
    .penanda-beku, .penanda-hidup { margin-top: .6rem; padding: .3rem .6rem; }

    /* Tombol cetak dan tautan navigasi tidak ikut ke atas kertas. */
    .tanpa-cetak { display: none !important; }

    /* Tombol aksi baris kehilangan kapsulnya di kertas: yang dicetak adalah
       dokumen, dan bidang yang tampak dapat ditekan di atas kertas hanya
       membingungkan pembacanya. */
    .aksi-mini { border: 0; background: none; padding: 0; color: #1F1B16; }
    .aksi-mini svg { display: none; }

    /* Begitu pula kerangka aplikasi: bilah samping, kepala, dan pemicu lacinya. */
    .sisi, .puncak, .tirai, .tombol-navigasi, .pemicu-navigasi { display: none !important; }
    .cangkang { display: block; }
    main { padding: 0; max-width: none; }

    .halaman-cetak { background: #FFFFFF; }
    .halaman-cetak .isi-cetak, .halaman-cetak .kop { max-width: none; padding: 0; }

    .kartu {
        border: 0;
        padding: 0;
        margin-bottom: .6rem;
        box-shadow: none;
        /* Satu tabel tidak dipotong di tengah bila masih muat di halaman berikutnya. */
        break-inside: avoid;
    }
    .peringatan, .penanda-beku, .penanda-hidup { break-inside: avoid; }
    thead { display: table-header-group; }

    /*
     * TABEL YANG TERBELAH HALAMAN HARUS TERBACA SEBAGAI SATU TABEL.
     *
     * `thead` yang diulang saja belum cukup: potongan kedua tetap tampak seperti tabel
     * BARU yang kebetulan berkepala sama, sebab tidak ada yang menyatakan ia lanjutan.
     * Pemilik sistem melaporkannya persis begitu -- "satu tabel tapi hasilnya ada dua".
     *
     * Garis atas tebal pada potongan lanjutan menjawabnya: ia menandai batas sambungan,
     * bukan batas tabel baru. Bawaannya `border-top` tipis seperti baris biasa.
     */
    .tabel-rekap thead { display: table-header-group; }
    .tabel-rekap tfoot { display: table-footer-group; }

    /*
     * KARTU LAPORAN TIDAK DIPAKSA UTUH.
     *
     * `break-inside: avoid` pada kartu setinggi satu halaman melempar seluruh kartunya ke
     * halaman berikutnya dan meninggalkan kertas kosong sebesar sisa halaman berjalan --
     * itulah ruang kosong besar sebelum "Perkembangan Putra" yang dilaporkan pemilik
     * sistem. Yang dijaga utuh cukup BARISNYA dan kepala bagiannya; isi kartunya sendiri
     * boleh mengalir ke halaman berikutnya.
     */
    .halaman-cetak .kartu { break-inside: auto; page-break-inside: auto; }
    .dua-kolom > .kartu { break-inside: auto; page-break-inside: auto; }

    /*
     * Blok yang memang harus utuh menyatakannya sendiri lewat `.blok-cetak`, bukan
     * mewarisinya dari `.kartu`. Dipakai kartu bagan pada laporan tahunan: bagan yang
     * terbelah dua halaman tidak dapat dibaca sebagai bagan.
     */
    .blok-cetak { break-inside: avoid; page-break-inside: avoid; }
    tr { break-inside: avoid; }
    tbody tr:hover { background: transparent; }

    /*
     * Margin 1,2cm, bukan 1,6cm.
     *
     * Selisihnya 0,8cm tinggi — sekitar 30px pada 96dpi — dan itulah yang memisahkan
     * laporan readiness muat satu halaman dari tumpah ke halaman kedua. Memangkas isi
     * lebih jauh demi selisih sekecil itu berarti mengorbankan keterbacaan untuk
     * persoalan yang sebenarnya persoalan tepi kertas, bukan persoalan isi.
     *
     * 1,2cm masih margin dokumen yang wajar dan aman dari batas cetak pencetak mana pun.
     */
    @page { size: A4; margin: 12mm; }

    /* ---------------------------------------------------------------------
       Lembar profil kondisi fisik.

       Aturannya dipindahkan ke SINI, bukan berdiri sebagai blok @media print
       kedua. Dua blok cetak dalam satu berkas gaya tidak salah menurut CSS —
       peramban menggabungkannya — tetapi setiap perkakas yang membaca "blok
       cetak" akan menemukan yang pertama saja dan mengira itu seluruhnya.
       Satu blok, satu tempat mencari.
       --------------------------------------------------------------------- */
    /*
         * TIDAK ada @page di sini.
         *
         * @page bersifat dokumen, bukan elemen — mendeklarasikannya lagi akan menimpa
         * setelan halaman seluruh laporan lain yang memakai berkas gaya yang sama.
         * Ukuran dan marginnya diatur satu kali di blok cetak utama.
         */
        .lembar-profil {
            width: auto;
            transform: none;
            padding-bottom: 0;
            box-shadow: none;
        }

        /*
         * KERAPATAN CETAK: mencegah halaman kosong sebesar hampir satu halaman penuh.
         *
         * Blok "Item test fisik" membawa `break-inside: avoid`, dan itu benar: tabel yang
         * terpotong di tengah kehilangan kepala kolomnya, sehingga angka pada halaman
         * berikutnya tidak dapat ditelusuri ke item mana pun.
         *
         * Tetapi `avoid` punya keadaan patologis, dan justru itu yang terjadi di sini:
         * blok yang MUAT dalam satu halaman tetapi TIDAK muat pada sisa halaman berjalan
         * dilempar utuh ke halaman berikutnya. Terukur pada regu ini: bloknya berakhir
         * pada 1073px sedangkan bidang cetak berakhir pada 1032px -- lebih 41px, dan
         * ongkosnya 800px kertas kosong.
         *
         * Yang dikerjakan di sini merapatkan tabelnya SECUKUPNYA supaya bloknya muat,
         * bukan mencabut `avoid`. Mencabutnya menukar satu masalah dengan masalah yang
         * lebih sulit dilihat: blok ini grid dua kolom, dan grid berbaris tunggal tidak
         * dapat difragmentasi rapi -- yang keluar bukan potongan yang bersih melainkan
         * isi yang meluber melewati batas halaman.
         *
         * HANYA DI KERTAS. Kerapatan layar tidak disentuh sama sekali; di sana tidak ada
         * batas halaman yang perlu dihormati.
         */
        .lembar-profil .lp-isi { gap: 2mm; }
        .lembar-profil .lp-tabel td { padding: .45mm 1.2mm; }
        .lembar-profil .lp-tabel th { padding: .5mm 1.2mm; }
        /*
         * Baris persen dirapatkan lebih jauh daripada baris nilainya: ia sudah tidak
         * bergaris atas (menyatu dengan baris di atasnya sebagai satu item), berhuruf
         * lebih kecil, dan berwarna redup. Merapatkannya tidak mengurangi keterbacaan
         * apa pun, sementara tujuh belas item berarti tujuh belas baris seperti ini.
         */
        .lembar-profil .lp-tabel tr.lp-persen td { font-size: 6.4pt; padding: .3mm 1.2mm; }

        /*
         * Kepala bagian tidak pernah tertinggal sendirian di kaki halaman. Judul yang
         * terpisah dari tabelnya lebih buruk daripada tidak berjudul: pembacanya mencari
         * isinya di halaman yang sama dan menyimpulkan bagian itu kosong.
         */
        .lembar-profil .lp-judul,
        .lembar-profil .lp-sub { break-after: avoid; page-break-after: avoid; }
}

/* ===========================================================================
   LAYAR SEMPIT — PONSEL DAN TABLET
   ---------------------------------------------------------------------------
   Prinsipnya: TIDAK ADA YANG DIKURANGI. Pelatih membuka sistem ini dari ponsel di
   pinggir lapangan, dan fitur yang "tidak muat" bukan berarti tidak dibutuhkan —
   justru di lapanganlah grid hasil dan papan peringkat paling sering dilihat.
   Karena itu tidak satu pun tautan, kolom, atau tombol disembunyikan di layar
   sempit; yang berubah hanya cara menampungnya:

     - navigasi menjadi laci yang menggeser masuk, bukan deretan yang tergulir
       sampai tautan terakhirnya tidak pernah ditemukan;
     - tabel lebar menggulir di dalam kartunya sendiri, kolom nama tetap menempel;
     - sasaran sentuh dibesarkan ke 44px, ukuran yang dapat ditekan jempol;
     - kotak isian memakai font 16px, sebab iOS memperbesar seluruh halaman ketika
       memfokus isian yang fontnya lebih kecil dari itu — dan halaman yang tiba-tiba
       melar saat mulai mengetik terasa rusak.
   =========================================================================== */

/* --- Tablet dan ponsel: bilah samping menjadi laci --- */
@media (max-width: 60rem) {
    :root { --sp-sisi: 1rem; --sp-sela: 1rem; --sp-sela-besar: 1.25rem; }

    .cangkang { grid-template-columns: minmax(0, 1fr); }

    /*
     * Laci. 100dvh, bukan 100vh: di peramban ponsel bilah alamat menciut saat
     * digulir, dan 100vh membuat bagian bawah laci tertutup bilah itu sehingga
     * tautan terakhir tidak pernah dapat ditekan.
     */
    .sisi {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        width: min(17.5rem, 84vw);
        height: 100dvh;
        z-index: 60;
        border-right: 1px solid var(--sp-garis);
        box-shadow: var(--sp-bayang-naik);
        transform: translateX(-100%);
        transition: transform .22s ease;
        padding-bottom: calc(1.5rem + env(safe-area-inset-bottom));
        overscroll-behavior: contain;
    }

    #buka-navigasi:checked ~ .cangkang .sisi { transform: translateX(0); }

    /* Tirai: menekan di luar laci menutupnya, sebab tirainya label yang sama. */
    #buka-navigasi:checked ~ .cangkang .tirai {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 55;
        background: color-mix(in srgb, #000000 62%, transparent);
        cursor: pointer;
    }

    /* Tombol laci: tiga garis, digambar dari elemen — tanpa berkas ikon. */
    .tombol-navigasi {
        display: inline-flex;
        flex-direction: column;
        justify-content: center;
        gap: 4px;
        width: 2.75rem;
        height: 2.75rem;
        margin-left: -.5rem;
        padding: .7rem;
        border-radius: var(--sp-lengkung-kecil);
        cursor: pointer;
        flex: none;
    }
    .tombol-navigasi span {
        display: block;
        height: 2px;
        border-radius: 2px;
        background: var(--sp-kartu);
        transition: transform .22s ease, opacity .15s ease;
    }
    .tombol-navigasi:active { background: color-mix(in srgb, #000000 18%, transparent); }

    /* Laci terbuka: garis tengah lenyap, dua sisanya menyilang menjadi tanda tutup. */
    #buka-navigasi:checked ~ .cangkang .tombol-navigasi span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
    #buka-navigasi:checked ~ .cangkang .tombol-navigasi span:nth-child(2) { opacity: 0; }
    #buka-navigasi:checked ~ .cangkang .tombol-navigasi span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

    /* Papan ketik: fokus pada kotak centang harus terlihat di tombolnya. */
    #buka-navigasi:focus-visible ~ .cangkang .tombol-navigasi {
        outline: 2px solid var(--sp-kartu);
        outline-offset: 2px;
    }

    /*
     * Kepala aplikasi tetap menempel di atas, tetapi label halaman dipendekkan
     * dengan elipsis alih-alih mendorong chip nama ke baris berikutnya.
     */
    .puncak {
        gap: .5rem;
        flex-wrap: nowrap;
        padding: .4rem .75rem;
        padding-right: calc(.75rem + env(safe-area-inset-right));
        padding-left: calc(.75rem + env(safe-area-inset-left));
    }
    .puncak .label-halaman {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .puncak .kanan { gap: .4rem; flex: none; }
    /*
     * Chip nama dipersempit, TIDAK dihilangkan: pada perangkat yang dipakai
     * bergantian, mengetahui sedang masuk sebagai siapa justru lebih penting di
     * ponsel daripada di laptop.
     */
    .puncak .cip { max-width: 8.5rem; overflow: hidden; text-overflow: ellipsis; }
    .puncak button { padding: .4rem .7rem; }

    main {
        padding: var(--sp-sela-besar) var(--sp-sisi) 3.5rem;
        padding-left: calc(var(--sp-sisi) + env(safe-area-inset-left));
        padding-right: calc(var(--sp-sisi) + env(safe-area-inset-right));
    }

    .papan { grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); gap: .75rem; }
    .kartu-nilai .angka { font-size: 1.45rem; }
    .kartu { padding: 1.1rem 1.1rem 1.2rem; }
    tbody th { width: auto; }

    /*
     * Tabel lebar menggulir DI DALAM kartunya, bukan melebarkan halaman.
     *
     * Diterapkan pada kartu, bukan dituntut dari tiap view: sebuah tabel yang lupa
     * dibungkus akan membuat seluruh halaman bergeser mendatar, dan kesalahan itu
     * baru terlihat setelah dibuka di ponsel. Menaruhnya di sini membuat lupa itu
     * tidak lagi mungkin.
     */
    .kartu { overflow-x: auto; -webkit-overflow-scrolling: touch; }

    /* Grid hasil: lebih pendek supaya kepala tabel tetap terlihat di layar pendek. */
    .gulir-grid { max-height: 65vh; }
    .grid td input { width: 5rem; }
}

/* --- Ponsel --- */
@media (max-width: 40rem) {
    h1 { font-size: 1.25rem; }
    .judul-besar { font-size: 1.5rem; }
    .sorot { font-size: 1.35rem; }

    .papan { grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); }

    /*
     * SASARAN SENTUH.
     *
     * 44px adalah ukuran terkecil yang masih dapat ditekan jempol dengan andal.
     * Tombol setinggi 30px memang muat di layar, tetapi setiap kali meleset pelatih
     * harus mengulang — dan di pinggir lapangan itu berarti berhenti mengetik.
     */
    button, .tombol {
        min-height: 2.75rem;
        padding: .6rem 1rem;
    }
    /* Tombol aksi baris ikut dibesarkan, tetapi tidak sampai 44px: sebaris tiga
       di dalam sel tabel akan membuat tiap baris setinggi setengah layar. */
    .aksi-mini { min-height: 2.25rem; padding: .4rem .75rem; font-size: .8rem; }
    .aksi-baris { gap: .4rem; }
    .sisi a.tautan { padding: .7rem var(--sp-sela); }

    /*
     * BARIS CENTANG ikut aturan 44px yang sama.
     *
     * Sebelumnya baris `.pilihan` setinggi 20px dengan kotak centang 13px — di bawah
     * separuh ambang. Pada daftar "Tambah peserta" berisi dua puluh enam nama yang
     * ditekan sambil berdiri di pinggir lapangan, meleset satu baris berarti atlet yang
     * salah masuk sesi, dan kekeliruan itu tidak menimbulkan galat apa pun: ia hanya
     * tersimpan.
     *
     * Yang dibesarkan barisnya, bukan hanya kotaknya. Label membungkus kotak centangnya,
     * jadi seluruh lebar baris ikut dapat ditekan — sasaran 44px setinggi baris dan
     * selebar kartu, bukan kotak 13px yang harus dibidik.
     */
    .pilihan {
        min-height: 2.75rem;
        margin: 0;
        gap: .65rem;
    }
    .pilihan input[type=checkbox], .pilihan input[type=radio] {
        width: 1.35rem;
        height: 1.35rem;
        flex: none;
    }

    /*
     * Font 16px pada kotak isian. iOS memperbesar seluruh halaman saat memfokus
     * isian yang fontnya di bawah 16px, dan halaman yang tiba-tiba melar begitu
     * mulai mengetik terasa seperti kerusakan. Ukurannya dipulihkan dengan
     * memperbesar sasaran sentuh, BUKAN dengan mematikan cubit-perbesar —
     * mematikannya menutup satu-satunya jalan pembaca berpenglihatan terbatas
     * membaca tabel padat.
     */
    input[type=text], input[type=password], input[type=date], input[type=number],
    input[type=month], input[type=search], input[type=email], input[type=tel],
    input[type=file], select, textarea {
        font-size: 16px;
        min-height: 2.75rem;
    }
    textarea { min-height: 4.5rem; }
    .grid td input { min-height: 2.5rem; }

    /* Formulir sebaris di dalam sel menumpuk, bukan berdesakan mendatar. */
    td form.sebaris { display: block; margin-top: .35rem; }

    /* Deret aksi dasbor: satu kolom, tetap lengkap. */
    .deret-aksi { grid-template-columns: minmax(0, 1fr); }

    /* Kop laporan: menumpuk, supaya nama instansi tidak terpotong. */
    .kop { flex-direction: column; gap: .5rem; }
    .kop-kanan { text-align: left; }
}

/*
 * Yang menyatakan tidak ingin ada gerakan tidak mendapat geseran laci: lacinya
 * langsung ada atau langsung tidak ada. Fungsinya tetap utuh.
 */
@media (prefers-reduced-motion: reduce) {
    .sisi, .tombol-navigasi span { transition: none; }
}
