/* Dua permukaan, satu keluarga.
 *
 * **Lapangan** (`masuk`, `tempel`, `ronde`, beranda pekerja) dipakai satu tangan,
 * di bawah matahari, sambil memegang durian. **Kantor** (`beranda` pengelola,
 * `tinjau`, `serah`, `pohon`, `pengaturan`, `cetak`) dibaca sambil duduk.
 *
 * Keduanya memakai tinta, hijau, dan bentuk kode yang sama. Yang berbeda cuma
 * jaraknya: lapangan meneriakkannya (garis 3px, target 56px, kertas putih),
 * kantor mengucapkannya dengan suara biasa (garis rambut, skala tipografi,
 * latar aluminium redup).
 *
 * Bahannya plat aluminium yang dipaku ke pohon — bukan dasbor. Kode `A-12`
 * diucapkan keras antar pekerja, jadi di layar ia distempel, bukan diketik.
 *
 * Empat aturan yang mengikat seluruh berkas ini:
 *
 * 1. Target sentuh minimal 44px — di lapangan dipakai 56px, karena 44px adalah
 *    batas bawah untuk jari bersih di ruangan, bukan untuk ibu jari yang basah
 *    sambil tangan satunya memegang durian.
 * 2. Kontras minimal 7:1 untuk SEMUA teks di KEDUA permukaan. Kantor tidak
 *    minta keringanan: pemilik membaca `/tinjau` dari kebun, di sinyal dan
 *    cahaya yang sama. Dijaga `tests/test_kontras.py`; warna teks baru yang
 *    tidak terdaftar di sana membuat tes merah.
 * 3. Aksi utama di BAWAH layar lapangan. Bagian atas layar HP tidak terjangkau
 *    ibu jari saat dipegang satu tangan.
 * 4. Hierarki dari skala, bobot, dan jarak — tidak pernah dari webfont. Pemilik
 *    membuka layar kantor dari kebun, di sinyal yang sama yang membuat kita
 *    membangun antrean lokal. Font yang harus diunduh dulu adalah layar yang
 *    belum bisa dibaca.
 */

:root {
  /* ── Identitas: malam dan daging ───────────────────────────────────────────
   * Buah durian jatuh malam, dan yang dicari orang di dalamnya kuning. Dua
   * warna itu yang memegang produk ini, dan pekerjaannya DIPISAH:
   *
   *   `--dalam`  adalah RANGKA — bilah, menu, cincin fokus, batas terpilih.
   *   `--daging` adalah AKSI  — satu tombol per layar, tidak pernah dua.
   *
   * Tidak pernah tertukar. Rangka yang berwarna aksi membuat seluruh layar
   * terbaca sebagai tombol, dan aksi yang berwarna rangka berhenti menjawab
   * "yang mana yang harus saya tekan".
   *
   * Nilai `--dalam`, `--daging`, dan `--di-daging` diambil apa adanya dari
   * papan alur (docs/flow.html) karena ketiganya lolos 7:1. Tiga nilai lain
   * dari papan itu TIDAK ikut utuh — lihat `--redup`, `--bahaya`, dan catatan
   * batas tombol di `.tombol-utama`. Papan itu dilihat di laptop; separuh
   * layar di sini dipakai di bawah matahari, dan alasan yang membenarkan
   * sebuah nilai di sana tidak otomatis ikut pindah ke sini. */
  --dalam: #2e2a4f;
  --dalam-tinta: #ffffff;
  /* Tint plum: keping rangka, halaman menu yang sedang dibuka, sinar fokus
   * isian kantor. */
  --dalam-tipis: #eeedf8;
  --daging: #ffc53d;
  --di-daging: #2a2000;

  --tinta: #1b1a26;
  /* Metadata dan keterangan.
   *
   * Papan alur memakai #5d6168 — 6,22:1 di atas kertas, di bawah lantai
   * lapangan. Hue-nya ikut pindah (abu berbias plum, bukan berbias hijau
   * seperti dulu); nilainya digelapkan sampai lolos: 8,47 di kertas, 7,59 di
   * kanvas. #5d6168 tidak dibuang — ia jadi `--redup-2`, yang hanya tampil di
   * kantor, tempat lantainya memang 4,5 dan alasannya memang berlaku. */
  --redup: #4a4c5c;
  --kertas: #ffffff;
  /* Latar layar kantor. Kanvas, bukan putih klinis — dan biasnya plum, bukan
   * hijau: netral yang membawa hue produknya terbaca sebagai dipilih. */
  --kertas-kantor: #f2f2f6;
  --garis: #1b1a26;
  /* Garis rambut kantor. BATAS, bukan teks — tidak masuk tabel kontras. */
  --garis-halus: #d7d7de;
  /* Hijau DIPERSEMPIT jadi satu arti: "ini tercatat".
   *
   * Dulu ia memegang tiga pekerjaan sekaligus — isian tombol utama, teks
   * pesan berhasil, keping pohon produktif. Begitu rangkanya jadi plum dan
   * aksinya jadi kuning, hijau bebas memegang satu arti, dan itu justru arti
   * yang paling tidak boleh kabur: kalimat di Aturan 9. "Catatan disimpan"
   * yang sewarna rangka berhenti terbaca sebagai jawaban atas sesuatu. */
  --utama: #0b5d1e;
  /* Hue dari papan alur (#c0341c) dipertahankan: ia lebih hangat dan lebih
   * mudah dibedakan dari kuning daripada #8c1007 yang lama. Nilainya tidak —
   * #c0341c hanya 5,60:1 dengan teks putih. Digelapkan sampai 8,40 / 7,52. */
  --bahaya: #93240f;
  --bahaya-tinta: #ffffff;
  /* Digelapkan dari #7a4a00 (7,48:1 — pasangan tersempit di produk) supaya
   * tetap ≥7:1 di atas latar kantor juga. Sekarang 8,82 dan 8,22. */
  --peringatan: #6b4100;
  --peringatan-tinta: #ffffff;
  --lembut: #eeedf4;

  /* Keluarga warna yang MEMBAWA INFORMASI, bukan hiasan: status pohon, grade,
   * dan tingkat kegentingan di layar tinjau. Tiap keluarga sepasang — tinta
   * pekat di atas tint pucat — dan tiap pasangan ≥7:1, diuji di
   * `tests/test_kontras.py`. Berwarna dan kontras tinggi tidak bertentangan;
   * yang bertentangan cuma berwarna dan pucat.
   *
   * Hijau, amber, dan merah SUDAH punya arti di produk ini (utama, peringatan,
   * bahaya) — keduanya dipakai ulang, tidak dibuatkan hijau kedua. Warna
   * semantik tidak boleh larut jadi dekorasi. */
  --hijau-tipis: #ebf5ee;
  --biru: #12496e;
  --biru-tipis: #e0ecf5;
  --ungu: #532a7d;
  --ungu-tipis: #ece2f6;
  --amber-tipis: #f5e9d4;
  /* Dicerahkan dari #f9e3e0 bersamaan dengan `--bahaya` yang baru: pasangan
   * keping merah jatuh ke 6,84 begitu tintanya digelapkan, dan keping yang
   * gagal justru pasangan yang membawa kata "mati". Sekarang 7,44. */
  --merah-tipis: #fdeeea;
  --abu-tipis: #e9ece9;

  /* Permukaan `depan` (spec 02 §12 revisi). Bukan hue baru: nada gelap dari
   * hijau merek yang sudah ada, supaya pita gelapnya terbaca sebagai produk
   * yang sama dan bukan sebagai halaman pemasaran yang ditempelkan.
   *
   * Ia punya barisnya sendiri di `tests/test_kontras.py` — permukaan baru yang
   * lahir tanpa penjaga adalah cara lapisan non-teks dulu hidup berbulan-bulan
   * tanpa ambang sama sekali. */
  --depan-gelap: #211e3a;
  --depan-gelap-2: #2e2a4f;
  /* Pita tenang halaman depan. Dulu `--hijau-tipis` — sisa identitas lama,
   * dan sejak hijau dipersempit jadi "ini tercatat" (27 Okt), pita hijau
   * selebar layar adalah warna semantik yang dipakai sebagai dekorasi, persis
   * yang dilarang di blok palet deret di atas.
   *
   * Krem, bukan abu: ia nada pucat dari `--daging`, jadi pergantian latar
   * halaman ini bergerak di dalam keluarga warnanya sendiri — malam, krem,
   * kertas — bukan meminjam hue keempat. */
  --depan-krem: #fdf4e0;
  /* Target sentuh. Lapangan 56px TIDAK BOLEH TURUN — dijaga
   * `test_token_desain.py`. Kantor 44px di semua lebar: menebak jenis penunjuk
   * dari lebar layar salah pada tablet dan laptop bersentuh, dan empat piksel
   * tidak sebanding dengan tebakan yang bisa salah. Kepadatan kantor datang
   * dari jarak dan tangga huruf, bukan dari mengecilkan benda yang disentuh. */
  --sentuh: 56px;
  --sentuh-kantor: 44px;

  /* ── Jarak: satu skala 4px, tidak ada angka di luar ini (spec 07 §2) ──
   * Jarak antar-elemen datang dari `gap` induknya, bukan margin anaknya. */
  --r1: 4px;
  --r2: 8px;
  --r3: 12px;
  --r4: 16px;
  --r5: 24px;
  --r6: 32px;
  --r7: 48px;
  --r8: 64px;

  /* ── Tangga huruf. Ukuran di luar tangga tidak boleh ada. ── */
  --t1: 12px;
  --t2: 14px;
  --t3: 16px;
  --t4: 18px;
  --t5: 24px;
  --t6: 32px;
  --t7: 44px;
  /* Dua tingkat di atas tangga kerja, untuk hero halaman depan saja (spec 02
   * §12 revisi). Ditambahkan DI ATAS, bukan disisipkan di antara: menyisipkan
   * ukuran di tengah tangga membuat setiap layar lain punya pilihan baru yang
   * tidak pernah diputuskan siapa pun. Layar kerja tidak boleh memakainya —
   * tidak ada judul di produk ini yang perlu 60px. */
  --t8: 60px;
  --t9: 84px;

  /* ── Sudut: TIGA nilai. Satu sudut untuk semua benda adalah salah satu sebab
   * semuanya terlihat seperti benda yang sama. ── */
  --sudut-0: 0;
  --sudut-1: 8px;
  --sudut-2: 12px;

  /* ── Ketinggian: menyatakan LAPISAN, bukan mempercantik. Panel yang isinya
   * sederajat tidak mendapat bayangan. ── */
  --tinggi-1: 0 0 0 1px var(--garis-lembut);
  --tinggi-2: 0 1px 2px rgba(27, 26, 38, 0.06), 0 1px 1px rgba(27, 26, 38, 0.04);
  --tinggi-3: 0 4px 14px rgba(27, 26, 38, 0.1);

  /* Permukaan bernuansa: kepala tabel dan baris berselang. Latar, bukan teks. */
  --permukaan-2: #ebebf2;
  /* Garis rambut yang lebih lembut daripada --garis-halus. Batas, bukan teks. */
  --garis-lembut: #e3e3ea;
  /* Tingkat teks ketiga, untuk kantor. Lantai kantor 4,5:1; ini 5,98 di atas
   * kertas dan 5,31 di atas permukaan bernuansa — sengaja tidak menempel di
   * lantainya. 4,5 adalah izin, bukan sasaran. */
  --redup-2: #5d6168;

  /* ── Palet deret: NON-TEKS ─────────────────────────────────────────────────
   * Isian grafik, tepi kartu, garis grade. **Bukan teks, dan tidak tunduk pada
   * ambang teks.**
   *
   * Versi pertama grafik memakai ulang tinta teks (`--utama`, `--bahaya`, …)
   * karena itu satu-satunya warna terdaftar. Ambang teks memaksa setiap warna
   * jadi gelap, dan lima warna gelap tidak bisa dibedakan sebagai lima
   * kategori — grade A/B/C keluar sebagai tiga batang hijau identik. Itu bukan
   * grafik; itu tabel yang digambar.
   *
   * WCAG menuntut **3:1** untuk non-teks yang membawa arti (1.4.11), bukan
   * 4,5:1. Kelima nada kuat di bawah lolos 3:1 terhadap kedua latar halaman DAN
   * terhadap tinta tipisnya sendiri, dijaga `tests/test_kontras.py`
   * (`PASANGAN_NONTEKS`). Teks di dalam dan di sekitar grafik tetap memakai
   * tinta teks pada ambang teksnya.
   *
   * Kategori yang berbeda mendapat HUE yang berbeda. Kecerahan yang mirip antar
   * hue itu wajar dan bukan cacat: yang membedakan hue-nya, dan tiap deret
   * selalu punya label teks di sampingnya. */
  --deret-hijau: #1a7f37;
  --deret-hijau-tipis: #d5f2de;
  --deret-biru: #1f6feb;
  --deret-biru-tipis: #dbeafe;
  --deret-ungu: #8250df;
  --deret-ungu-tipis: #ece1fb;
  --deret-amber: #a86a00;
  --deret-amber-tipis: #fdf2d6;
  --deret-merah: #cf222e;
  --deret-merah-tipis: #ffdfe1;

  /* ── Tanjakan tingkat: DERAJAT, bukan jenis ────────────────────────────────
   * Dipakai hanya untuk skala berurut — sekarang satu-satunya pemakainya adalah
   * pita umur buah, yang isinya tingkat kedekatan ke ambang.
   *
   * Palet `--deret-*` di atas menjawab pertanyaan lain: "kategori mana ini?".
   * Memakainya untuk derajat membuat biru terbaca sebagai jenis lain, bukan
   * sebagai satu langkah lebih dekat ke ambang — urutannya baru terbaca sesudah
   * legendanya dibaca, padahal urutan itulah isinya.
   *
   * Nilai 2–4 kebetulan sama dengan tiga hue deret hari ini, dan sengaja
   * ditulis sebagai literal, bukan alias: keduanya menjawab pertanyaan berbeda
   * dan harus bisa disetel sendiri-sendiri. Alias akan membuat penyetelan palet
   * kategori diam-diam mengubah arti tanjakan.
   *
   * Ambangnya sama dengan deret: non-teks 3:1, dijaga `PASANGAN_NONTEKS`. */
  /* Digelapkan dari #4a9e63: kanvas kantor yang baru satu persen lebih terang,
   * dan langkah terpucat tanjakan ini sudah menclok di 2,96 — tepat di bawah
   * lantai non-teks. Sekarang 3,38. Langkah 2–4 tidak ikut disetel: yang
   * membedakan langkah dari langkah di sini HUE (hijau → amber → merah), bukan
   * kecerahan, dan menyetel semuanya supaya berjarak dalam rasio kontras
   * adalah mengukur tanjakan dengan alat yang salah. */
  --tingkat-1: #44935b;
  --tingkat-2: #1a7f37;
  --tingkat-3: #a86a00;
  --tingkat-4: #cf222e;
  --ruang: 14px;
  --tepi: 3px;
  --lengkung: 10px;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--kertas);
  color: var(--tinta);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 18px;
  line-height: 1.4;
  /* Seluruh produk ini adalah kolom angka yang dibandingkan: selisih serah
   * terima, persen tanpa-kode, umur hari. Angka proporsional membuat kolomnya
   * bergoyang dan perbandingan jadi pekerjaan mata. */
  font-variant-numeric: tabular-nums;
}

body {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* Permukaan kantor: latar aluminium, garis rambut, ruang lebih longgar. Ukuran
 * target sentuh TIDAK dikecilkan — mandor menerima serah terima di lapangan. */
body.kantor {
  background: var(--kertas-kantor);
  --ruang: 20px;
  --tepi: 1px;
  --lengkung: 8px;
}

/* Bilah hijau di kedua permukaan. Putih di atas --utama 8,08:1, jadi ini
 * menambah warna tanpa menyentuh keterbacaan — dan ia yang paling membuat
 * layar terbaca sebagai perangkat lunak, bukan sebagai formulir. */
.bilah {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 14px;
  background: var(--dalam);
  color: var(--dalam-tinta);
  border-bottom: 3px solid var(--dalam);
  font-weight: 700;
}

.kantor .bilah {
  border-bottom-width: 2px;
  letter-spacing: 0.01em;
}

.bilah a,
.bilah button {
  font-size: 16px;
}

/* Rangka: menu di kiri, isi di kanan. Di lapangan menunya tidak ada sama
 * sekali, jadi rangkanya cuma pembungkus yang tidak mengubah apa pun. */
.rangka {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

main {
  flex: 1;
  padding: var(--ruang);
  display: flex;
  flex-direction: column;
  gap: var(--ruang);
}

.kantor main {
  max-width: 60rem;
  width: 100%;
  margin: 0 auto;
}

h1 {
  font-size: 26px;
  margin: 0;
  line-height: 1.2;
}

h2 {
  font-size: 20px;
  margin: 0;
}

/* Judul bagian di kantor adalah label, bukan teriakan. Hierarkinya datang dari
 * huruf kecil ber-tracking di atas isi yang besar — bukan dari bobot yang sama
 * dengan segalanya, yang membuat sebelas bagian terbaca sama penting. */
.kantor h1 {
  font-size: 30px;
  letter-spacing: -0.015em;
}

.kantor h2 {
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--redup);
}

/* Keluaran layar tinjau adalah satu kalimat yang bisa diucapkan pemilik kepada
 * orang lain — "47 buah tidak pernah kembali". Ia bukan angka di antara angka,
 * jadi ia tidak memakai ukuran yang sama dengan angka lain. */
.kalimat-utama {
  font-size: 34px;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0;
}

/* Tombol: besar, berbatas tegas, tanpa bayangan halus yang hilang di matahari. */
.tombol {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--sentuh);
  padding: 14px 18px;
  font-size: 20px;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  color: var(--tinta);
  background: var(--kertas);
  border: 3px solid var(--garis);
  border-radius: 10px;
  cursor: pointer;
  touch-action: manipulation;
}

/* Satu aksi utama per layar, dan ia benda paling terang di layar itu.
 *
 * Batasnya SENGAJA gelap, bukan sewarna isiannya seperti tombol lain: kuning
 * #ffc53d cuma 1,58:1 di atas kertas putih, jadi tombol berbatas kuning adalah
 * tombol yang labelnya terbaca (10,20:1) tapi TEPINYA tidak — dan tepi itulah
 * yang dituju ibu jari. Papan alur memakai tepi bawah #e3a71a; ia 1,36:1 di
 * atas isiannya sendiri, yaitu tidak terlihat sama sekali di bawah matahari,
 * jadi ia tidak ikut pindah ke sini. */
.tombol-utama {
  background: var(--daging);
  border-color: var(--di-daging);
  color: var(--di-daging);
}

/* Menghapus pohon adalah satu-satunya aksi merusak di produk ini — ia sudah
 * dibatasi ke owner saja justru karena itu. Sampai sekarang tombolnya terlihat
 * identik dengan "Kembali": kelas ini sudah didaftarkan di tabel kontras sejak
 * awal, tapi tidak pernah dibuat. */
.tombol-bahaya {
  background: var(--bahaya);
  border-color: var(--bahaya);
  color: var(--bahaya-tinta);
}

.tombol-besar {
  min-height: 96px;
  font-size: 24px;
}

/* Tombol di dalam baris antrean kerja: masih ≥44px, tapi tidak lagi 56px kali
 * tiga kali 47 baris. Dipakai hanya di layar kantor. */
.tombol-rapat {
  min-height: 44px;
  padding: 8px 14px;
  font-size: 17px;
}

/* Beranda pekerja adalah dua tombol raksasa, dan memang harus begitu. Beranda
 * pengelola bukan: di sana tombol setinggi 96px membuat navigasi lebih besar
 * daripada tiga angka yang jadi alasan layar itu ada. Tetap ≥56px. */
.kantor .tombol-besar {
  min-height: 64px;
  font-size: 20px;
}

/* Tautan sekunder berjajar, bukan menumpuk selebar layar satu per satu. */
.kantor .navigasi {
  flex-direction: row;
  flex-wrap: wrap;
}

.kantor .navigasi > .tombol {
  flex: 1 1 14rem;
}

.tombol:disabled {
  opacity: 1;
  background: var(--lembut);
  /* Nilainya sama dengan `--redup` dan sengaja ditulis penuh: ini satu-satunya
   * kasus di `WARNA_LITERAL` test_kontras.py, dan tabel berparameter yang
   * kosong adalah tes yang tidak pernah berjalan. */
  color: #4a4c5c;
  border-color: #4a4c5c;
  cursor: not-allowed;
}

/* Isian ikut, bukan cuma tombol. Tanpa baris `input`/`select` di sini, kolom
 * isian lapangan memakai cincin fokus bawaan peramban — biru #005fcc, satu
 * warna yang tidak ada di palet mana pun produk ini, di layar yang seluruh
 * sisanya plum dan kuning. Layar kantor sudah punya aturannya sendiri sejak
 * awal; lapangan tidak pernah punya. */
.tombol:focus-visible,
.lapangan input:focus-visible,
.lapangan select:focus-visible,
.baris:focus-visible {
  /* Plum, bukan amber. Cincin fokus harus beda dari benda yang DIKELILINGINYA,
   * bukan cuma dari halamannya: amber di sekeliling tombol kuning terbaca
   * sebagai bagian tombolnya. Plum 8,53:1 terhadap kuning dan 13,46 terhadap
   * kertas. */
  outline: 4px solid var(--dalam);
  outline-offset: 2px;
}

/* Baris daftar — BUKAN tombol. Kode pohon rata kiri di kolom yang sama supaya
 * mata bisa memindainya; `.tombol` menengahkan isinya, sehingga tiap baris dari
 * 302 baris harus dibaca utuh untuk menemukan kodenya. Tinggi minimalnya tetap
 * satu target sentuh penuh. */
.baris {
  display: flex;
  align-items: center;
  gap: var(--r3);
  flex-wrap: wrap;
  min-height: var(--sentuh);
  padding: var(--r3) var(--r4);
  font-size: var(--t4);
  text-align: left;
  text-decoration: none;
  color: var(--tinta);
  background: var(--kertas);
  cursor: pointer;
  touch-action: manipulation;
}

/* Pemisah garis rambut ANTAR baris, bukan tepi per baris.
 *
 * Tepi membulat sendiri-sendiri membuat tujuh puluh baris kembali membaca
 * sebagai tumpukan kotak — persis cacat yang sedang diperbaiki, dalam bentuk
 * yang lebih kecil. Daftar adalah SATU benda dengan banyak baris di dalamnya,
 * bukan banyak benda yang kebetulan berurutan; pemisah menyatakan itu dan tepi
 * per baris menyangkalnya.
 *
 * Wadahnya yang membulat, sekali, di ujung-ujungnya. */
.daftar {
  display: flex;
  flex-direction: column;
  background: var(--kertas);
  border-radius: var(--sudut-2);
  overflow: hidden;
}

.kantor .daftar {
  box-shadow: var(--tinggi-1);
}

.daftar > .baris + .baris {
  border-top: 1px solid var(--garis-lembut);
}

.baris:hover {
  background: var(--permukaan-2);
}

/* Aksi di ujung baris. Membungkus ke barisnya sendiri di layar sempit, bukan
 * mendorong kunci barisnya keluar pandangan. */
.baris-aksi {
  display: flex;
  gap: var(--r2);
  flex-wrap: wrap;
  margin-left: auto;
}

/* Lampiran baris: isi yang MILIK satu baris tapi terlalu besar untuk muat di
 * dalamnya — usulan pencocokan di layar tinjau. Bertakuk dan berlatar nuansa
 * supaya jelas ia bagian dari baris di atasnya, bukan baris berikutnya. */
.baris-lampiran {
  display: flex;
  flex-direction: column;
  gap: var(--r2);
  padding: var(--r3) var(--r4) var(--r4) var(--r6);
  background: var(--permukaan-2);
  border-top: 1px solid var(--garis-lembut);
}

/* Kepala baris antrean tinjau: stempel pohon, stempel kode buah, lalu umur dan
 * penandanya di kanan — satu garis, bukan lima baris bertumpuk. Pekerjaan
 * pemilik di layar itu triase, dan triase butuh baris yang bisa dipindai. */
.tinjau-kepala {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* Tiga resolusi dalam SATU baris. `.berjajar` memakai basis 45% yang memaksa
 * 2+1, dan satu baris tombol tambahan dikalikan 50 baris adalah satu layar
 * penuh gulungan yang tidak membawa informasi apa pun. */
.tinjau-aksi > .tombol {
  flex: 1 1 8rem;
}

/* Keterangan baris: nama varietas, status, jumlah. Didorong ke kanan supaya
 * kolom kode di kiri tetap satu garis lurus. */
.baris-sisa {
  margin-left: auto;
  font-size: 16px;
  color: var(--redup);
  text-align: right;
}

.tumpuk {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* `gap` sudah mengatur jaraknya; margin bawaan <p> menambahinya sekali lagi,
 * dan daftar sepuluh baris jadi terbaca seperti sepuluh bagian terpisah. */
.tumpuk > p {
  margin: 0;
}

.berjajar {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.berjajar > * {
  flex: 1 1 45%;
}

/* Aksi utama di bawah layar: jangkauan ibu jari, bukan bagian atas layar.
 *
 * **Didorong ke dasar dengan `margin-top: auto`, BUKAN `position: sticky`.**
 *
 * `sticky; bottom: 0` menggeser bilah ke ATAS isi sebelumnya begitu halaman
 * lebih tinggi daripada viewport — dan jarak geserannya persis setinggi
 * kelebihan itu, jadi tidak ada nilai `padding` yang bisa menampungnya. Latar
 * bilah yang pekat lalu menutupi apa pun yang ada di bawahnya.
 *
 * Yang tertutup ternyata **tombol kirim jalur ketik-kode** — jalan cadangan
 * yang dipakai justru ketika kamera gagal. Terukur: `elementFromPoint` di
 * tengah tombol itu mengembalikan bilahnya, bukan tombolnya. Pekerja mengetik
 * kodenya lalu buntu, dan Aturan 1 bocor lewat tata letak.
 *
 * Pertukarannya disebut apa adanya: dengan `margin-top: auto`, tombol "Selesai
 * blok" turun ke bawah lipatan saat halamannya panjang. **Tombol yang perlu
 * digulir masih bisa ditekan; tombol di bawah bilah pekat tidak bisa** — dan
 * Aturan 1 menang atas jangkauan ibu jari. Saat isinya muat satu layar, dan
 * itu keadaan biasanya, bilahnya tetap di dasar layar. */
.lapangan main > section {
  flex: 1 0 auto;
}

/* Pembungkus aksi ikut memanjang supaya `margin-top: auto` di dalamnya punya
 * ruang untuk mendorong. */
.aksi-pindai-isi {
  flex: 1 0 auto;
}

.aksi-bawah {
  margin-top: auto;
  background: var(--kertas);
  padding-top: 10px;
  border-top: 3px solid var(--garis);
}

label {
  display: block;
  font-weight: 700;
  margin-bottom: 6px;
}

.kantor label {
  font-size: 15px;
}

input,
select {
  width: 100%;
  min-height: var(--sentuh);
  padding: 12px;
  font-size: 22px;
  color: var(--tinta);
  background: var(--kertas);
  border: 3px solid var(--garis);
  border-radius: 10px;
  font-variant-numeric: tabular-nums;
}

/* Kolom isian kantor: garis tipis, bukan tepi 2px near-hitam.
 *
 * Tepi tebal di sebelah panel bergaris rambut membuat kolom isian jadi benda
 * paling berat di layar — padahal ia bukan yang paling penting. Itu bentuk
 * kecil dari cacat yang sedang diperbaiki: kalau semuanya berat, tidak ada yang
 * berat.
 *
 * `--redup-2` sebagai GARIS, bukan teks: 5,98:1 di atas kertas, jadi ia tetap
 * jelas terlihat sebagai kolom yang bisa diisi. Fokusnya justru dikuatkan —
 * yang perlu menonjol adalah kolom yang sedang diketik, bukan kedua belas
 * kolom sekaligus. */
.kantor input,
.kantor select {
  font-size: var(--t4);
  border-width: 1px;
  border-color: var(--redup-2);
  border-radius: var(--sudut-1);
  min-height: var(--sentuh-kantor);
}

.kantor input:focus,
.kantor select:focus {
  outline: none;
  border-color: var(--dalam);
  box-shadow: 0 0 0 3px var(--dalam-tipis);
}

.lapangan input[inputmode="numeric"] {
  letter-spacing: 0.15em;
}

/* Di kantor jarak itu dibuang: angkanya diketik sambil duduk, dan "11" yang
 * terbaca "1 1" pada kolom jumlah serah terima adalah salah baca yang mahal.
 * `tabular-nums` yang sekarang menjaga kelurusan kolomnya, bukan tracking. */
.kantor input[inputmode="numeric"] {
  letter-spacing: normal;
}

.kartu {
  border: var(--tepi) solid var(--garis);
  border-radius: var(--lengkung);
  padding: var(--ruang);
}

/* Kartu kantor: kertas putih di atas latar aluminium, dibatasi garis rambut.
 * Batas 3px pada sebelas kartu sekaligus membuat layar terbaca seperti kisi
 * kawat, bukan seperti dokumen. */
.kantor .kartu {
  background: var(--kertas);
  border-color: var(--garis-halus);
}

.kartu-terpilih {
  border-color: var(--dalam);
  border-width: 4px;
}

/* Kode pohon dan kode buah distempel, tidak diketik: plat aluminium dipaku ke
 * pohon adalah satu-satunya cara tahu buah di jaring berasal dari mana, dan
 * kodenya diucapkan keras antar pekerja. Monospace ber-tracking supaya `A-12`
 * dan `A-l2` tidak pernah tertukar saat dibaca ulang. */
.kode-plat,
.kode-besar {
  display: inline-block;
  /* Wadahnya sering `.tumpuk` (flex kolom), yang meregangkan anaknya selebar
   * kartu. Plat yang selebar layar bukan plat lagi — ia harus seukuran
   * kodenya, seperti aslinya yang dipaku ke pohon. */
  align-self: flex-start;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-weight: 700;
  letter-spacing: 0.1em;
  background: var(--lembut);
  /* Tintanya DINYATAKAN, tidak diwarisi.
   *
   * Komponen yang memasang latarnya sendiri tapi membiarkan tintanya datang
   * dari induk akan pecah di latar berwarna mana pun — dan ia pecah tanpa
   * suara, karena tabel kontras menghitung dari variabel CSS dan tidak pernah
   * melihat pasangan yang lahir dari pewarisan. Terbukti 27 Okt 2026: stempel
   * ini dipasang di pita plum yang tintanya putih, dan kode pohonnya jadi
   * putih di atas #eeedf4 — 1,07:1, di pita yang seluruh gunanya menyatakan
   * pohon mana. */
  color: var(--tinta);
  border: 2px solid var(--garis);
  border-radius: 5px;
}

.kode-plat {
  font-size: 17px;
  padding: 3px 8px 3px 10px;
}

.kode-besar {
  font-size: 30px;
  font-weight: 800;
  padding: 6px 12px 6px 15px;
  margin: 0;
}

/* Kalimat yang memuat angka, bukan angka itu sendiri. "81 buah — 47 di
 * antaranya perlu ditinjau" diset seukuran angka hero membuat angkanya berhenti
 * terbaca sebagai angka. Ia tetap SATU kalimat: memecahnya jadi dua baris
 * membuat "perlu ditinjau" terbaca sebagai himpunan terpisah dari "sisa", dan
 * yang terpisah akan dijumlahkan. */
.angka-kalimat {
  font-size: 26px;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin: 0;
}

/* Pohon yang sedang dipakai, dinyatakan di atas layar selama langkah 2.
 *
 * PLUM, bukan kuning — walaupun papan alur menggambarnya kuning. Kuning di
 * produk ini berarti "tekan ini", dan layar ini sudah punya satu tombol
 * kuning; pita kuning di atasnya membuat layar punya dua benda kuning dan
 * berhenti menjawab mana yang harus ditekan. Yang dibawa pita ini bukan aksi
 * melainkan KEADAAN TERKUNCI — dan keadaan terpilih di produk ini sudah plum
 * sejak `.tombol[aria-pressed="true"]`.
 *
 * Kenapa ia ada sama sekali: kode stiker sekali pakai selamanya (Aturan 4),
 * jadi stiker yang menempel ke pohon yang salah tidak pernah bisa dibetulkan.
 * Pohon yang sedang dipakai harus terbaca tanpa dicari, di setiap stiker. */
.pohon-terpasang {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* Token, bukan angka — walaupun aturan di sekelilingnya masih angka mentah
   * dan penjaga `test_komponen_memakai_token_bukan_angka_karangan` belum
   * sampai ke baris ini. Lingkup penjaga itu melebar setiap kali satu layar
   * dipindahkan dan tidak pernah menyempit; kode BARU yang menambah angka
   * mentah di bawah batasnya adalah utang yang dibuat sengaja. */
  gap: var(--r2);
  padding: var(--r4);
  border-radius: var(--sudut-2);
  background: var(--dalam);
  color: var(--dalam-tinta);
}

/* Pita tidak ikut memanjang.
 *
 * Pemilihnya WAJIB menyebut `.lapangan main >` juga. Ditulis sebagai
 * `.pohon-terpasang` saja (0,1,0) ia kalah dari `.lapangan main > section`
 * (0,1,2) yang memberi `flex: 1 0 auto` — aturannya tertulis, terbaca benar,
 * dan tidak pernah berlaku. Pita plum tetap setinggi separuh layar, dan saya
 * baru melihatnya saat memotret layarnya untuk halaman depan.
 *
 * Bentuk yang sama dengan `color: inherit` di pita gelap halaman depan yang
 * jatuh ke 1,63:1 pada 7 Sep: aturan CSS yang kalah spesifisitas tidak
 * memberi tanda apa pun bahwa ia tidak dipakai. */
.lapangan main > section.pohon-terpasang {
  flex: 0 0 auto;
}

.pohon-terpasang-label {
  margin: 0;
  font-size: var(--t2);
  font-weight: 700;
  /* `color: inherit` eksplisit, bukan diwarisi diam-diam: keterangan di pita
   * gelap halaman depan pernah jatuh ke 1,63:1 justru karena pewarisannya
   * kalah spesifisitas dari aturan `--redup` di tempat lain. */
  color: inherit;
}

/* Hanya jarak. Tintanya tidak diatur di sini: anak-anak pita mewarisi putih
 * dari `.pohon-terpasang`, dan stempel kode membawa tintanya sendiri (lihat
 * `.kode-besar`). Aturan `color: inherit` di sini akan terlihat benar dan
 * justru memaksa stempelnya ikut putih. */
.pohon-terpasang p {
  margin: 0;
}

/* Tombol hantu di atas plum: tepi dan teks putih, isian tembus. Tombol
 * berisian kertas di sini akan terbaca sebagai aksi utama layar, padahal
 * mengganti pohon adalah jalan keluar, bukan pekerjaan. */
.pohon-terpasang .tombol {
  background: transparent;
  border-color: var(--dalam-tinta);
  color: var(--dalam-tinta);
}

.angka-besar {
  font-size: 44px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  margin: 0;
}

.pesan {
  border: 3px solid var(--garis);
  border-radius: 10px;
  padding: 12px;
  font-weight: 700;
}

.kantor .pesan {
  border-width: 2px;
  font-size: 17px;
}

.pesan-galat {
  border-color: var(--bahaya);
  color: var(--bahaya);
}

.pesan-berhasil {
  border-color: var(--utama);
  color: var(--utama);
}

.pesan-peringatan {
  border-color: var(--peringatan);
  color: var(--peringatan);
}

/* Selisih adalah SATU-SATUNYA alasan layar serah terima ada: ronde bertemu titik
 * serah terima supaya selisih ketahuan, dan aturan 7 melarang menghapusnya.
 * Selisih setipis garis di atas tombol konfirmasi berwarna padat membuat mata
 * jatuh ke tombol yang melewatinya — itu menghapusnya dengan cara lain. Begitu
 * selisih ≠ 0 ia harus jadi benda paling keras di layar, lebih keras dari CTA.
 * Saat selisih = 0 ia tetap tenang; yang perlu diteriakkan cuma yang tidak cocok. */
/* `.pesan.selisih-keras`, bukan `.selisih-keras`: `.kantor .pesan` mengecilkan
 * teks pesan jadi 17px, dan satu kelas saja kalah spesifisitas — bloknya jadi
 * padat tapi kalimatnya tetap lirih, yang persis kebalikan dari maksudnya. */
.pesan.selisih-keras {
  background: var(--peringatan);
  border-color: var(--peringatan);
  color: var(--peringatan-tinta);
  font-size: 34px;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.015em;
  padding: 16px;
}

/* Antrean selalu terlihat, tidak pernah di dalam menu: pekerja harus bisa
 * melihat antreannya mandek tanpa mencari. */
.antrean {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  font-size: 16px;
  padding: 8px 14px;
  border-bottom: 3px solid var(--garis);
}

.antrean-menunggu {
  color: var(--peringatan);
}

.antrean-gagal {
  color: var(--bahaya);
}

video {
  width: 100%;
  max-height: 46dvh;
  background: #000;
  border: 3px solid var(--garis);
  border-radius: 10px;
}

.pilihan-grade {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.pilihan-grade .tombol {
  flex: 1 1 30%;
}

/* Berlaku untuk SEMUA tombol pilihan, bukan hanya grade: pilihan yang tidak
 * terlihat terpilih akan diisi ulang atau dilewati. "Jatuh matang" yang aktif
 * sejak awal harus terbaca aktif sejak awal. */
/* Pilihan yang sedang aktif adalah KEADAAN, bukan aksi — jadi ia plum, bukan
 * kuning. Kalau pilihan aktif dan tombol utama sama-sama kuning, layar punya
 * dua benda kuning dan berhenti menjawab mana yang harus ditekan. */
.tombol[aria-pressed="true"] {
  background: var(--dalam);
  border-color: var(--dalam);
  color: var(--dalam-tinta);
}

/* Keping berwarna yang membawa SATU fakta: status pohon, grade, umur yang
 * lewat ambang. Bentuknya sengaja berbeda dari stempel kode — stempel itu
 * identitas (plat aluminium), keping ini keadaan. */
.tanda {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  border: 2px solid currentColor;
  font-size: 15px;
  font-weight: 700;
  white-space: nowrap;
}

.tanda-hijau { background: var(--hijau-tipis); color: var(--utama); }
.tanda-biru { background: var(--biru-tipis); color: var(--biru); }
.tanda-ungu { background: var(--ungu-tipis); color: var(--ungu); }
.tanda-amber { background: var(--amber-tipis); color: var(--peringatan); }
.tanda-merah { background: var(--merah-tipis); color: var(--bahaya); }
.tanda-abu { background: var(--abu-tipis); color: var(--redup); }

/* Status pohon diwarnai dari nilainya sendiri, bukan dari peta di template:
 * status baru yang ditambahkan ke enum akan tampil netral dan terbaca, bukan
 * mewarisi warna status lain karena petanya lupa diperbarui. */
.tanda[data-status="belum_berbuah"] { background: var(--biru-tipis); color: var(--biru); }
.tanda[data-status="produktif"] { background: var(--hijau-tipis); color: var(--utama); }
.tanda[data-status="sakit"] { background: var(--amber-tipis); color: var(--peringatan); }
.tanda[data-status="mati"] { background: var(--merah-tipis); color: var(--bahaya); }

/* Grade adalah DATA milik kebun — namanya tidak diterjemahkan, dan jumlahnya
 * bisa berapa saja. Warnanya karena itu dari urutan, bukan dari kodenya:
 * kebun yang memakai "Super/Biasa" mendapat warna yang sama konsistennya
 * dengan kebun yang memakai A/B/C.
 *
 * Hanya tepi kiri. Keadaan terpilih (`aria-pressed`) tetap hijau penuh dan
 * tetap satu-satunya yang menandakan pilihan — warna grade tidak boleh bisa
 * dikira sebagai "sudah dipilih" di layar tempat salah pilih berarti satu
 * catatan panen yang tidak bisa diulang. */
.pilih-grade {
  border-left-width: 10px;
}

.grade-0 { border-left-color: var(--deret-hijau); }
.grade-1 { border-left-color: var(--deret-biru); }
.grade-2 { border-left-color: var(--deret-ungu); }
.grade-3 { border-left-color: var(--deret-amber); }

/* Buah yang paling lama tidak kembali adalah yang paling tidak mungkin kembali
 * (spec 02 §9). Keping umur karena itu memanas seiring jaraknya dari ambang —
 * dan yang paling parah jadi blok padat, bukan sekadar tint. */
.tanda-genting {
  background: var(--bahaya);
  border-color: var(--bahaya);
  color: var(--bahaya-tinta);
}

/* Kartu kantor mendapat tepi kiri berwarna sesuai isinya. Ini yang membuat
 * sebelas kartu putih berhenti terbaca sama penting, tanpa satu pun kata
 * tambahan di layar. */
/* Tepi kartu memakai palet DERET, bukan tinta teks: ia tanda non-teks, dan
 * memakai tinta teks di sini adalah kesalahan yang sama dengan yang melahirkan
 * grafik versi pertama — warna gelap yang tidak saling membedakan. */
.kantor .kartu-hijau { border-left: 6px solid var(--deret-hijau); }
.kantor .kartu-amber { border-left: 6px solid var(--deret-amber); }
.kantor .kartu-merah { border-left: 6px solid var(--deret-merah); }
.kantor .kartu-biru { border-left: 6px solid var(--deret-biru); }

/* Layar masuk. Kepala identitas, lalu SATU pintu berkartu.
 *
 * Dua pintu berdampingan dihapus 27 Okt 2026, dan aturan "jarak pemisah antar
 * pintu" ikut dihapus bersamanya — aturan yang tinggal tanpa benda yang
 * diaturnya adalah baris yang akan dipakai ulang oleh orang berikutnya untuk
 * sesuatu yang bukan maksudnya.
 *
 * Pintu kedua sekarang sebuah TAUTAN di bawah kartu, bukan kartu kedua. Ia
 * sengaja tenang: pekerja dan mandor sudah ada di layar yang benar begitu
 * aplikasi terbuka, dan yang perlu berpindah hanya pemilik — sekali, di
 * laptop. */
.masuk-kepala {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

/* Kartunya TIDAK memanjang di layar ini.
 *
 * `.lapangan main > section { flex: 1 0 auto }` ada supaya `.aksi-bawah` punya
 * ruang untuk didorong ke dasar layar. Layar masuk tidak punya `.aksi-bawah`,
 * jadi yang didapat cuma kartu yang melar: dulu dua kartu berbagi kelebihan
 * ruangnya dan tidak ada yang kelihatan, sekarang satu kartu menelannya
 * sendiri dan tombol Masuk mengambang di tengah kekosongan. */
.masuk main > section {
  flex: 0 0 auto;
}

.masuk-pintu-lain {
  margin: 0;
  text-align: center;
}

/* Tampilannya tenang, targetnya tidak. Mandor yang tersesat ke pintu email
 * harus bisa kembali dengan ibu jari, bukan dengan mengincar teks setinggi
 * 21px — dan 56px di sini sama wajibnya dengan di tombol mana pun. */
.masuk-pintu-lain a {
  display: inline-flex;
  align-items: center;
  min-height: var(--sentuh);
  padding: 0 var(--r4);
  color: var(--dalam);
  font-weight: 700;
}

/* ── Menu (kantor saja) ─────────────────────────────────────────────────── */

/* Di HP menu adalah SATU baris: strip yang bisa digeser, dengan Keluar
 * menempel di ujung kanan supaya ia tidak ikut tergeser keluar pandangan.
 * Menaruhnya di baris sendiri memakan satu baris penuh pada setiap layar
 * kantor, dan layar kantor di HP dibuka justru saat pemilik sedang berdiri
 * di kebun — ruang tegaknya yang paling mahal di sana. */
.menu {
  position: relative;
  display: flex;
  align-items: center;
  gap: 4px;
  border-bottom: 2px solid var(--garis-halus);
  background: var(--kertas);
}

.menu-daftar {
  flex: 1;
  min-width: 0;
  /* Geseran berhenti di batas item, bukan di tengah kata. */
  scroll-snap-type: x proximity;
}

.menu-daftar > li {
  scroll-snap-align: start;
}

.menu-daftar {
  display: flex;
  gap: 4px;
  list-style: none;
  margin: 0;
  /* Di HP menunya satu baris yang bisa digeser. Membungkus jadi tiga baris
   * memakan sepertiga layar pada SETIAP layar kantor; menyembunyikannya di
   * balik laci menambah satu ketukan pada setiap perpindahan — yang justru
   * alasan menu ini ada. Yang menggulir adalah wadahnya, bukan halamannya. */
  overflow-x: auto;
  padding: 8px;
  -webkit-overflow-scrolling: touch;
}

/* ── Ikon ───────────────────────────────────────────────────────────────────
 * Ukurannya ikut ukuran huruf di sekitarnya (`em`), bukan piksel tetap: ikon
 * yang tidak ikut mengecil saat tipenya turun tingkat akan terbaca sebagai
 * benda lain yang kebetulan berdekatan, bukan sebagai bagian dari barisnya.
 *
 * `flex: none` karena ikon di dalam tombol sempit akan dipipihkan oleh flex,
 * dan ikon yang gepeng lebih buruk daripada tidak ada ikon. */
.ikon {
  width: 1.25em;
  height: 1.25em;
  flex: none;
}

/* Ikon keadaan kosong: satu-satunya tempat ikon berdiri sendiri tanpa teks di
 * barisnya — karena di sana ia mengisi ruang yang memang kosong, dan judulnya
 * ada tepat di bawahnya. */
.ikon-besar {
  width: 2.5rem;
  height: 2.5rem;
  flex: none;
  color: var(--redup-2);
}

.menu-item {
  display: flex;
  align-items: center;
  gap: var(--r3);
  min-height: 44px;
  padding: 8px 14px;
  border-radius: 8px;
  font-size: 16px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  color: var(--tinta);
}

/* Halaman yang sedang dibuka. Ditandai `aria-current` di markup, dan warnanya
 * mengikuti atribut itu — bukan kelas terpisah yang bisa lepas darinya, dan
 * yang lepas berarti pembaca layar dan mata melihat dua hal berbeda. */
.menu-item[aria-current="page"] {
  background: var(--dalam-tipis);
  color: var(--dalam);
}

/* ── Dasbor: kisi, bukan tumpukan ───────────────────────────────────────────
 * Dua angka berdampingan terbaca sebagai sepasang; dua angka ditumpuk selebar
 * layar terbaca sebagai dua pengumuman berurutan. Yang kedua membuat layar ini
 * panjang tanpa menambah satu pun keputusan.
 *
 * Di bawah 48rem kembali satu kolom — di HP berdampingan berarti dua kolom
 * sempit, dan angka yang membungkus berhenti terbaca sebagai angka. */
.dasbor-kisi {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--r4);
}

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

/* Tindakan sebagai kartu, bukan tombol selebar layar. Ikon di kiri menamai
 * tujuannya, panah di kanan menyatakan ia membawa pergi — dua hal yang tombol
 * berisi kalimat panjang tidak pernah katakan. */
.aksi-kartu {
  display: flex;
  align-items: center;
  gap: var(--r3);
  min-height: 44px;
  padding: var(--r4);
  border: 1px solid var(--garis-halus);
  border-radius: var(--sudut-2);
  background: var(--kertas);
  color: var(--tinta);
  font-weight: 700;
  text-decoration: none;
}

.aksi-kartu span {
  flex: 1;
}

.aksi-kartu-utama {
  background: var(--daging);
  border-color: var(--di-daging);
  color: var(--di-daging);
}

.ikon-aksi {
  width: 1.75rem;
  height: 1.75rem;
  flex: none;
}

.kartu h2 {
  display: flex;
  align-items: center;
  gap: var(--r2);
}

.menu-keluar {
  flex: 0 0 auto;
  padding: 8px;
}

.menu-keluar .tombol {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--r2);
}

/* Tepi strip memudar tepat sebelum tombol Keluar.
 *
 * Tanpa ini item ketiga terpotong mendadak di belakang tombol dan terbaca
 * sebagai teks rusak, bukan sebagai "masih ada lagi ke kanan" — dan pemilik
 * yang baru pertama membuka tidak akan pernah tahu ada Pohon, Cetak, dan
 * Pengaturan di sana. Potongan yang menyatakan layarnya salah render adalah
 * potongan yang menyembunyikan separuh menu.
 *
 * `pointer-events: none` supaya ia tidak pernah menelan ketukan pada item
 * yang ada di bawahnya. */
.menu-keluar::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: 100%;
  width: 2.5rem;
  background: linear-gradient(to right, rgba(255, 255, 255, 0), var(--kertas));
  pointer-events: none;
}

.menu-keluar .tombol {
  min-height: 44px;
  font-size: 16px;
}

/* Kartu langkah berikutnya dan halaman panduan: kalimat yang dibaca, bukan
 * angka yang dipindai. Ukurannya di antara judul bagian dan badan teks. */
.langkah-apa,
.panduan-judul {
  font-size: 21px;
  font-weight: 800;
  letter-spacing: -0.01em;
  margin: 0;
}

/* Alasan dipisahkan dari langkahnya, bukan disambung jadi satu paragraf: yang
 * sedang buru-buru membaca langkahnya saja, dan yang bertanya "kenapa begini"
 * menemukan jawabannya tanpa harus membaca ulang instruksinya. */
.panduan-kenapa {
  border-left: 4px solid var(--garis-halus);
  padding-left: 14px;
}

.panduan-label {
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--redup);
  margin: 0 0 4px;
}

.tersembunyi {
  display: none !important;
}

.catatan {
  font-size: 16px;
  color: var(--redup);
  margin: 0;
}


/* ══════════════════════════════════════════════════════════════════════════
 * Responsif — empat kombinasi, bukan dua.
 *
 * Berkas ini sampai sekarang tidak punya satu pun `@media`. Akibatnya layar
 * kantor (lebar maks 60rem, kisi berdampingan) tidak pernah diuji di HP, dan
 * layar lapangan (target 56px, tipe besar) tidak pernah diuji di laptop —
 * padahal keduanya dipakai di kedua ukuran: pemilik membuka /tinjau dari HP
 * saat di kebun, dan mandor kadang mencatat dari laptop di rumah kebun.
 *
 * Yang TIDAK berubah di HP: target sentuh lapangan tetap 56px, dan aksi utama
 * tetap menempel di bawah layar. Keduanya lahir dari ibu jari, bukan dari
 * lebar viewport, jadi tidak ada breakpoint yang boleh mencabutnya.
 * ══════════════════════════════════════════════════════════════════════════ */

/* ── HP dan layar sempit ────────────────────────────────────────────────── */
@media (max-width: 40rem) {
  /* Menumpuk HANYA di kantor. Labelnya panjang ("Gugur tidak terpungut") dan
   * dibaca sambil duduk, jadi satu kolom penuh lebih terbaca.
   *
   * Lapangan TETAP berdampingan, dan itu diukur, bukan disukai: di 390px,
   * menumpuk membuat formulir buah 507px dan menaruh dasar tombol Simpan di
   * y=794px; berdampingan membuatnya 415px dan y=702px. 92px lebih dekat ke
   * ibu jari, dan target sentuhnya justru lebih TINGGI (80px, karena teksnya
   * membungkus dua baris) — bukan lebih kecil. Menggulir untuk mencapai
   * Simpan sambil satu tangan memegang durian adalah gulungan yang tidak
   * jadi dilakukan. */
  .kantor .berjajar > * {
    flex-basis: 100%;
  }

  /* Kecuali dua ini, yang basisnya sudah pas dan tidak boleh ikut melebar:
   * pilihan grade (A/B/C memang pendek), dan tiga resolusi di antrean tinjau
   * — memaksanya menumpuk menambah dua baris tombol pada tiap-tiap dari 50
   * baris, dan itu membatalkan perapatan yang baru saja dikerjakan. */
  .pilihan-grade .tombol {
    flex: 1 1 4.5rem;
  }

  .kantor .tinjau-aksi > .tombol {
    flex: 1 1 8rem;
  }

  .kantor {
    --ruang: 14px;
  }

  /* Keterangan baris berhenti didorong ke kanan: di satu kolom sempit ia
   * turun ke barisnya sendiri, dan rata kanan membuatnya terbaca terputus
   * dari kode di atasnya. */
  .baris-sisa {
    margin-left: 0;
    text-align: left;
  }

  .kalimat-utama {
    font-size: 27px;
  }

  .angka-besar {
    font-size: 36px;
  }

  .angka-kalimat {
    font-size: 22px;
  }

  .pesan.selisih-keras {
    font-size: 25px;
  }

  .kode-besar {
    font-size: 25px;
  }

  .kantor h1 {
    font-size: 24px;
  }
}

/* ── Laptop dan monitor ─────────────────────────────────────────────────── */
@media (min-width: 60rem) {
  /* Aturan "satu tangan di bawah matahari" tidak berlaku di sini, tapi ia juga
   * tidak boleh dibalik jadi kerusakan: tombol 56px yang direntangkan selebar
   * monitor 27 inci bukan tombol besar, ia garis. Yang dibatasi lebarnya,
   * BUKAN tinggi target sentuhnya — mandor yang sama membuka layar ini di HP
   * satu jam kemudian, dan mengecilkan targetnya di sini akan menggodanya
   * mengecilkan di sana juga. */
  .lapangan main {
    max-width: 34rem;
    width: 100%;
    margin: 0 auto;
  }

  /* Layar masuk pendek; menempel ke atas menyisakan setengah layar kosong di
   * bawahnya. Hanya di sini — layar lain punya isi yang tumbuh ke bawah, dan
   * menengahkannya akan membuat baris pertama melompat setiap kali isinya
   * bertambah. */
  .masuk main {
    justify-content: center;
  }

  /* Di layar lebar menu berdiri tetap di kiri: pekerjaan di layar kantor
   * berpindah-pindah — dari tinjau ke satu pohon lalu ke serah terima — dan
   * lewat beranda setiap kali menambah satu ketukan tanpa memberi apa pun. */
  .kantor .rangka {
    flex-direction: row;
    align-items: stretch;
  }

  .kantor .menu {
    flex: 0 0 14rem;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: space-between;
    border-bottom: none;
    border-right: 2px solid var(--garis-halus);
  }

  .kantor .menu-daftar {
    flex-direction: column;
    overflow-x: visible;
    gap: 2px;
    padding: 14px 10px;
  }

  .kantor .menu-item {
    font-size: 17px;
  }

  .kantor .menu-daftar {
    flex: 0 1 auto;
  }

  .kantor .menu-keluar {
    padding: 14px 10px;
  }

  /* Kolom tegak tidak menggeser apa pun; gradiennya justru akan menutupi item. */
  .kantor .menu-keluar::before {
    display: none;
  }

  /* Isi tetap berbatas 60rem, tapi ia sekarang berbagi lebar dengan menu —
   * `margin: 0 auto` di dalam sisa ruang, bukan di dalam layar penuh. */
  .kantor main {
    min-width: 0;
  }

  /* Bilah tetap selebar layar — ia bidang warna, bukan isi yang dibaca. */
  .lapangan .antrean {
    max-width: 34rem;
    width: 100%;
    margin: 0 auto;
  }

  /* Aksi bawah ikut menyempit bersama isinya, kalau tidak ia melayang sendiri
   * di tengah layar lebar dengan garis atas selebar monitor. */
  .lapangan .aksi-bawah {
    border-top: none;
    padding-top: 14px;
  }

  /* Kamera tidak perlu setengah layar laptop: 46dvh di monitor 27 inci adalah
   * kotak hitam raksasa yang mendorong sisanya keluar pandangan. */
  video {
    max-height: 32dvh;
  }
}

/* Tetikus punya arah pandang yang jari tidak punya. Sentuhan tidak pernah
 * "melayang", jadi keadaan ini hanya digambar di perangkat yang benar-benar
 * punya penunjuk halus — di HP ia tidak pernah menyala dan tidak pernah
 * tertinggal menyala sesudah diketuk. */
@media (hover: hover) and (pointer: fine) {
  /* HANYA tombol berlatar kertas. Tanpa penyaringan ini, `background` di sini
   * mengalahkan latar hijau tombol utama dan tombol terpilih — teksnya tetap
   * putih, dan hasilnya putih di atas --lembut: 1,14:1. Tertangkap penyapuan
   * DOM, tidak oleh tabel variabel, karena pasangan itu tidak pernah
   * dideklarasikan siapa pun; ia lahir dari dua aturan yang bertemu. */
  .tombol:hover:not(:disabled):not(.tombol-utama):not(.tombol-bahaya):not([aria-pressed="true"]) {
    background: var(--lembut);
  }

  .tombol-utama:hover:not(:disabled),
  .tombol-bahaya:hover:not(:disabled),
  .tombol[aria-pressed="true"]:hover {
    filter: brightness(1.15);
  }
}

/* ══════════════════════════════════════════════════════════════════════════
 * PERBENDAHARAAN KOMPONEN — spec 07 §3, daftar tertutup.
 *
 * Diagnosis yang melahirkan bagian ini: setiap layar adalah tumpukan persegi
 * panjang selebar layar. Kartu, tombol, kolom isian, dan baris daftar semuanya
 * berbentuk sama, selebar sama, disusun ke bawah. Lebar penuh adalah pernyataan
 * bahwa sesuatu penting — kalau semuanya lebar penuh, pernyataan itu kosong.
 *
 * Yang hilang bukan hiasan, melainkan perbendaharaan yang membedakan satu jenis
 * isi dari jenis lainnya. Menambah komponen di luar daftar ini menuntut alasan
 * tertulis di spec, bukan keputusan di dalam satu template.
 *
 * Semua nilai di bawah berasal dari token. Angka yang dikarang di sini adalah
 * cacat, bukan penyesuaian.
 * ══════════════════════════════════════════════════════════════════════════ */

/* ── Kepala halaman ─────────────────────────────────────────────────────────
 * Judul, konteks di bawahnya kalau ada, dan PALING BANYAK SATU aksi utama di
 * kanan. Sama bentuknya di sebelas layar — sekarang tiap layar mengarang
 * kepalanya sendiri, dan itu terlihat sebagai sebelas produk. */
.kepala {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--r4);
  flex-wrap: wrap;
}

.kepala-teks {
  display: flex;
  flex-direction: column;
  gap: var(--r1);
  min-width: 0;
}

.kepala h1 {
  margin: 0;
}

.kepala-konteks {
  font-size: var(--t3);
  color: var(--redup);
  margin: 0;
}

.kepala-aksi {
  flex: 0 0 auto;
}

/* ── Panel ──────────────────────────────────────────────────────────────────
 * TIDAK SEMUA HAL ADALAH PANEL. Panel menyatakan "ini satu kesatuan yang
 * terpisah"; daftar sepuluh baris bukan sepuluh panel. Itu kesalahan yang
 * sedang diperbaiki di /pohon, /serah, dan /tinjau. */
.panel {
  background: var(--kertas);
  border-radius: var(--sudut-2);
  padding: var(--r5);
  display: flex;
  flex-direction: column;
  gap: var(--r4);
}

.kantor .panel {
  box-shadow: var(--tinggi-1);
}

.lapangan .panel {
  border: 3px solid var(--garis);
}

/* Panel yang isinya sederajat tidak mendapat bayangan; yang mengambang di atas
 * isi lain mendapatnya. Ketinggian menyatakan lapisan, bukan kepentingan. */
.panel-angkat {
  box-shadow: var(--tinggi-3);
}

.panel-kepala {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--r3);
}

.panel-judul {
  font-size: var(--t1);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--redup);
  margin: 0;
}

/* ── Bilah alat ─────────────────────────────────────────────────────────────
 * Saringan dan pencarian di atas daftar. Bentuk tetap di /pohon dan daftar mana
 * pun berikutnya. */
.bilah-alat {
  display: flex;
  align-items: center;
  gap: var(--r3);
  flex-wrap: wrap;
}

.bilah-alat > .kolom {
  flex: 1 1 16rem;
  min-width: 0;
}

.bilah-alat-hitung {
  flex: 0 0 auto;
  font-size: var(--t2);
  color: var(--redup);
  font-variant-numeric: tabular-nums;
}

/* ── Kolom isian ────────────────────────────────────────────────────────────
 * Label, isian, keterangan bantu, keterangan galat, penanda wajib — susunan
 * tetap, jarak tetap. */
.kolom {
  display: flex;
  flex-direction: column;
  gap: var(--r1);
}

.kolom-label {
  font-size: var(--t2);
  font-weight: 700;
  margin: 0;
}

.kolom-wajib {
  color: var(--bahaya);
}

.kolom-bantu {
  font-size: var(--t2);
  color: var(--redup-2);
  margin: 0;
}

/* Galat TIDAK PERNAH hanya warna: teksnya wajib ada, dan `role=alert` supaya
 * pembaca layar mendapatkannya juga. Warna yang berdiri sendiri tidak sampai ke
 * orang yang tidak membedakannya, dan tidak sampai ke siapa pun yang mendengar
 * layarnya dibacakan. */
.kolom-galat {
  font-size: var(--t2);
  font-weight: 700;
  color: var(--bahaya);
  margin: 0;
}

.kolom input[aria-invalid="true"],
.kolom select[aria-invalid="true"] {
  border-color: var(--bahaya);
}

/* Dua kolom pendek yang menjawab SATU pertanyaan berdampingan: "Dari nomor" dan
 * "Sampai nomor" adalah satu rentang, bukan dua isian yang kebetulan berdekatan. */
.kolom-pasangan {
  display: flex;
  gap: var(--r3);
  flex-wrap: wrap;
}

.kolom-pasangan > .kolom {
  flex: 1 1 8rem;
}

/* ── Tabel ──────────────────────────────────────────────────────────────────
 * Untuk isi yang memang tabular. Di layar sempit ia BERUBAH JADI BARIS DAFTAR,
 * tidak meluap ke samping — lihat blok @media di bawah. */
.tbl {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.tbl th,
.tbl td {
  text-align: left;
  padding: var(--r3) var(--r3);
  border-bottom: 1px solid var(--garis-lembut);
}

.tbl thead th {
  position: sticky;
  top: 0;
  background: var(--permukaan-2);
  font-size: var(--t1);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--redup);
  border-bottom: 2px solid var(--garis-halus);
}

.tbl .angka {
  text-align: right;
}

.tbl tbody tr:hover {
  background: var(--permukaan-2);
}

/* ── Keadaan kosong ─────────────────────────────────────────────────────────
 * Satu kalimat yang menjelaskan KENAPA kosong, dan satu aksi kalau ada yang
 * bisa dikerjakan. Bukan "Tidak ada data" — layar kosong adalah layar yang
 * paling sering dilihat pemilik baru, dan sampai sekarang ia yang paling tidak
 * dirancang. */
.kosong {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--r2);
  padding: var(--r6) var(--r5);
  border: 1px dashed var(--garis-halus);
  border-radius: var(--sudut-2);
  background: var(--permukaan-2);
}

.kosong-judul {
  font-size: var(--t4);
  font-weight: 800;
  margin: 0;
}

.kosong-sebab {
  color: var(--redup);
  margin: 0;
  max-width: 46ch;
}

/* ── Tombol: peran, bukan warna ─────────────────────────────────────────────
 * `.tombol-samar` melengkapi utama/sekunder/bahaya yang sudah ada. Peran tetap
 * peran walaupun warnanya berubah: tombol bahaya tetap bahaya. */
.tombol-samar {
  background: transparent;
  border-color: transparent;
  color: var(--tinta);
  text-decoration: underline;
}

/* Ukuran kantor. Lapangan memakai --sentuh dan tidak diturunkan oleh apa pun. */
.kantor .tombol-kantor {
  min-height: var(--sentuh-kantor);
  padding: var(--r2) var(--r4);
  font-size: var(--t3);
}

/* Sedang mengirim: tombol tetap terbaca dan tetap mengatakan apa yang terjadi.
 * Tombol yang cuma meredup tanpa kata dibaca sebagai tombol rusak. */
.tombol[aria-busy="true"] {
  cursor: progress;
}

/* ── Chip: berbeda BENTUK dari tombol ───────────────────────────────────────
 * `.tanda` sudah bulat penuh dan bertepi tipis; tombol bersudut 8px dan bertepi
 * tebal. Perbedaan bentuk itu yang membuat chip tidak pernah dikira bisa
 * ditekan — warna saja tidak cukup, karena tombol pun berwarna. */
.tanda {
  font-size: var(--t2);
}

@media (max-width: 40rem) {
  /* Tabel berubah jadi baris daftar, tidak meluap ke samping. Kepala kolom
   * pindah ke tiap sel lewat `data-kepala`, jadi satu baris tetap terbaca
   * sebagai pasangan nama-nilai.
   *
   * **Berlaku dari tiga kolom ke atas.** Tabel dua kolom yang salah satunya
   * sudah kunci — `B — 25 buah` — justru dirugikan: labelnya digandakan dan
   * tingginya jadi tiga kali lipat untuk menyampaikan satu angka. Ia menolak
   * transformasinya dengan `.tbl-dua`.
   *
   * Transformasi tetap jadi BAWAAN, dan opt-out-nya yang eksplisit: tabel lebar
   * yang lupa dikecualikan cuma jadi tinggi — jelek, tapi terbaca. Kalau
   * bawaannya dibalik, tabel lebar yang lupa menyatakan diri akan MELUAP ke
   * samping, dan luapan adalah kegagalan, bukan kejelekan. Bawaan yang salah
   * harus yang paling tidak berbahaya. */
  .tbl:not(.tbl-dua) thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  .tbl:not(.tbl-dua),
  .tbl:not(.tbl-dua) tbody,
  .tbl:not(.tbl-dua) tr,
  .tbl:not(.tbl-dua) td {
    display: block;
    width: 100%;
  }

  .tbl:not(.tbl-dua) tr {
    border: 1px solid var(--garis-lembut);
    border-radius: var(--sudut-1);
    padding: var(--r2);
    margin-bottom: var(--r2);
  }

  .tbl:not(.tbl-dua) td {
    border-bottom: none;
    padding: var(--r1) var(--r2);
    display: flex;
    justify-content: space-between;
    gap: var(--r3);
  }

  .tbl:not(.tbl-dua) td::before {
    content: attr(data-kepala);
    font-size: var(--t1);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--redup);
    font-weight: 700;
  }

  .tbl .angka {
    text-align: right;
  }

  /* Tabel dua kolom tetap tabel: padatkan saja jaraknya. */
  .tbl-dua th,
  .tbl-dua td {
    padding: var(--r2);
  }

  .panel {
    padding: var(--r4);
  }

  .kosong {
    padding: var(--r5) var(--r4);
  }
}

/* ── Contoh token di /desain. Bagian ini hanya dipakai halaman contoh; ia ikut
 * aturan token yang sama supaya halaman yang membuktikan sistem itu tidak jadi
 * pengecualian pertama darinya. ── */
.contoh-token {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--r1);
}

.contoh-jarak {
  height: var(--r5);
  background: var(--dalam);
  border-radius: var(--sudut-0);
}

.contoh-tinggi {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--r8);
  height: var(--r8);
  background: var(--kertas);
  border-radius: var(--sudut-2);
  font-weight: 700;
}

/* Tombol lapangan tetap 56px walaupun dipamerkan di halaman kantor: yang
 * ditunjukkan adalah ukuran sungguhannya, bukan versi yang dirapatkan. */
.contoh-lapangan .tombol {
  min-height: var(--sentuh);
}

/* ── Grafik dasbor (spec 02 §2a, mutu grafik) ────────────────────────────────
 * Kantor saja. Layar lapangan tidak mendapat grafik apa pun.
 *
 * Isian dan goresan memakai palet DERET pada ambang non-teks 3:1; teks di dalam
 * dan di sekitar grafik tetap memakai tinta teks pada ambang teksnya. Versi
 * pertama mencampur keduanya dan keluar sebagai lima batang gelap yang tidak
 * saling membedakan. */
/* `overflow: hidden`, bukan `visible`.
 *
 * Dengan `visible`, isi yang keluar kotaknya tetap terlukis ke ruang kosong di
 * sekitarnya dan tampak baik-baik saja — label sumbu puncak sempat 17px di luar
 * dan tidak ada yang menyadarinya sampai kotaknya diukur. Kesalahan posisi yang
 * disembunyikan oleh ruang kosong akan muncul begitu ada yang mengisi ruang itu.
 *
 * Dengan `hidden`, salah posisi jadi terlihat sebagai terpotong. Cacat yang
 * kelihatan lebih murah daripada cacat yang menunggu. */
.grafik-svg {
  width: 100%;
  display: block;
  overflow: hidden;
}

/* Tiga puluh titik plus sumbu tidak muat di 120px — datanya jadi pita. */
.grafik-tinggi {
  height: 180px;
}

@media (max-width: 40rem) {
  .grafik-tinggi {
    height: 140px;
  }
}

.grafik-kisi {
  stroke: var(--garis-lembut);
  stroke-width: 1;
}

.grafik-sumbu {
  stroke: var(--garis-halus);
  stroke-width: 1.5;
}

/* Digambar di atas data, jadi ia butuh kontrasnya sendiri terhadap apa pun yang
 * ada di bawahnya — termasuk kolom pucat "tidak diperiksa". `paint-order`
 * menaruh goresan putih di belakang isian huruf, bukan di depannya. */
.grafik-sumbu-label {
  fill: var(--redup);
  font-size: var(--t1);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  paint-order: stroke fill;
  stroke: var(--kertas);
  stroke-width: 3;
  stroke-linejoin: round;
}

.grafik-batang {
  fill: var(--deret-hijau);
}

.grafik-batang-akhir {
  fill: var(--deret-hijau);
  stroke: var(--tinta);
  stroke-width: 1.5;
}

/* Bentuknya BATANG, bukan area bergradien — dari dua pilihan spec §2a butir 4.
 *
 * Bukan selera: garis area menginterpolasi melintasi hari yang tidak diperiksa,
 * yaitu menggambar nilai untuk hari yang tidak pernah diukur. Itu melanggar
 * aturan kejujuran 5, dan aturan itu menang atas bentuk yang lebih halus.
 * Batang berdiri sendiri-sendiri, jadi lubang tetap terbaca sebagai lubang. */
/* Ronde tercatat dengan nol buah: pengukuran yang hasilnya nol, bukan
 * ketiadaan. Ia meninggalkan jejak. */
.grafik-nol {
  fill: var(--redup);
}

/* Hari yang tidak diperiksa: lubang dalam liputan. Tetap pucat dengan sengaja —
 * yang berubah warna adalah datanya, bukan lubangnya. */
.grafik-tak-diperiksa {
  fill: var(--permukaan-2);
}

/* Donat sebaran grade. Tiap potongan hue berbeda, dan legendanya membawa nama,
 * jumlah, dan persen — nilai terbaca tanpa menunjuk, karena di HP tidak ada
 * hover. */
.grafik-donat {
  fill: none;
  stroke-width: 22;
}

.grafik-donat-lubang {
  fill: var(--kertas);
}

.grafik-donat-total {
  fill: var(--tinta);
  font-size: var(--t5);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.grafik-donat-satuan {
  fill: var(--redup-2);
  font-size: var(--t1);
}

/* Garis ambang pada grafik umur: satu-satunya grafik yang punya nilai batas,
 * dan batas yang tidak digambar adalah informasi yang dibuang. */
.grafik-ambang {
  stroke: var(--deret-merah);
  stroke-width: 2;
  stroke-dasharray: 5 4;
}

.grafik-ambang-label {
  fill: var(--bahaya);
  font-size: var(--t1);
  font-weight: 700;
}

.grafik-nilai {
  fill: var(--tinta);
  font-size: var(--t1);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.grafik-waktu {
  display: flex;
  justify-content: space-between;
  font-size: var(--t1);
  color: var(--redup-2);
  font-variant-numeric: tabular-nums;
}

.grafik-ringkas {
  font-size: var(--t5);
  font-weight: 800;
  letter-spacing: -0.015em;
  margin: 0;
  font-variant-numeric: tabular-nums;
}

/* Legenda: warna, nama, jumlah, persen. Warna tidak pernah sendirian membawa
 * arti — teksnya ada di sebelahnya, selalu. */
/* Lebarnya dibatasi supaya nama dan angkanya tetap satu pasang. `margin-left:
 * auto` pada angkanya benar — ia merapikan kolom — tapi di panel selebar 1.400px
 * ia memisahkan keduanya dengan gurun kosong, dan mata berhenti
 * menghubungkannya. */
.grafik-legenda {
  display: flex;
  flex-direction: column;
  max-width: 21rem;
  gap: var(--r2);
  list-style: none;
  margin: 0;
  padding: 0;
  font-variant-numeric: tabular-nums;
}

.grafik-legenda li {
  display: flex;
  align-items: center;
  gap: var(--r2);
  font-size: var(--t3);
}

.grafik-kunci {
  width: var(--r3);
  height: var(--r3);
  border-radius: 3px;
  flex: 0 0 auto;
}

.grafik-legenda-nama {
  font-weight: 700;
}

.grafik-legenda-angka {
  margin-left: auto;
  color: var(--redup);
  font-size: var(--t2);
}

.tombol-rapat[aria-current="page"] {
  background: var(--dalam);
  border-color: var(--dalam);
  color: var(--dalam-tinta);
}

/* ── Diagram Panduan ────────────────────────────────────────────────────────
 * Gambar yang menemani teks, bukan yang menggantikannya: tiap diagram berdiri
 * di sebelah kalimat yang mengatakan hal yang sama. Warna tidak pernah jadi
 * satu-satunya pembawa arti — di sini ia bahkan bukan pembawa arti sama
 * sekali, hanya bentuknya. */
.diagram {
  width: 100%;
  max-width: 14rem;
  height: auto;
  flex: 0 0 auto;
}

/* Goresan diagram memakai warna RANGKA, bukan hijau.
 *
 * Hijau sekarang berarti "ini tercatat" dan tidak boleh dipinjam untuk
 * menggambar kulit durian — warna semantik yang dipakai sebagai gambar
 * berhenti berarti apa-apa di tempat ia sungguh membawa arti. */
.diagram .d-isi {
  fill: var(--dalam-tipis);
  stroke: var(--dalam);
  stroke-width: 2;
}

.diagram .d-tengah {
  fill: none;
  stroke: var(--dalam);
  stroke-width: 1.5;
  stroke-dasharray: 3 3;
}

.diagram .d-garis {
  fill: var(--dalam);
}

.diagram .d-duri {
  stroke: var(--dalam);
  stroke-width: 2;
  stroke-linecap: round;
}

.diagram .d-plat,
.diagram .d-kotak {
  fill: var(--kertas);
  stroke: var(--tinta);
  stroke-width: 2;
}

.diagram .d-layar {
  fill: var(--permukaan-2);
}

.diagram .d-tombol {
  fill: var(--permukaan-2);
  stroke: var(--redup-2);
  stroke-width: 1;
}

.diagram .d-tipis,
.diagram .d-panah {
  stroke: var(--redup);
  stroke-width: 2;
  stroke-linecap: round;
}

.diagram .d-sinar {
  stroke: var(--biru);
  stroke-width: 2;
  stroke-dasharray: 4 4;
  stroke-linecap: round;
}

/* Buah yang sedang jatuh: samar, karena ia keadaan sebelumnya — bukan dua buah. */
.diagram .d-samar {
  fill: none;
  stroke: var(--garis-halus);
  stroke-width: 2;
}

.diagram .d-lintasan {
  fill: none;
  stroke: var(--redup-2);
  stroke-width: 1.5;
  stroke-dasharray: 4 4;
}

.diagram .d-jaring {
  stroke: var(--tinta);
  stroke-width: 2;
}

.diagram .d-jaring-tali {
  stroke: var(--redup-2);
  stroke-width: 1;
}

.diagram .d-selisih {
  fill: var(--peringatan);
  font-size: var(--t5);
  font-weight: 800;
}

/* Diagram di samping teks di layar lebar, di atasnya di layar sempit — teks
 * yang menyempit sampai empat kata per baris lebih buruk daripada gambar yang
 * pindah ke atas. */
.panduan-langkah {
  display: flex;
  gap: var(--r5);
  align-items: flex-start;
  flex-wrap: wrap;
}

.panduan-isi {
  flex: 1 1 22rem;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--r3);
}

/* ═══ Permukaan `depan` — halaman depan publik (spec 02 §12 revisi) ═══════
 *
 * Permukaan KETIGA, dan alasannya bukan selera. `kantor` dibangun untuk tabel,
 * formulir, dan daftar yang dioperasikan berulang oleh orang yang sudah tahu
 * apa yang dia cari. Halaman ini dibaca sekali, oleh orang yang belum tahu
 * apa-apa, dan tugasnya meyakinkan. Memakai `kantor` di sini adalah aturan yang
 * dipindahkan tanpa alasannya ikut pindah (Aturan 12) — dan hasilnya ditolak
 * pemilik produk: "terlihat seperti tahun 1990".
 *
 * Yang IKUT dari sistem desain, dan tidak boleh tidak: token jarak, tangga
 * huruf (boleh menambah tingkat DI ATAS t7, tidak boleh mengarang di
 * antaranya), palet yang sudah terdaftar, dan ambang kontras teks 4,5:1 yang
 * diukur alat yang sama. Permukaan ini punya barisnya sendiri di
 * `tests/test_kontras.py`.
 *
 * Yang TIDAK ikut: perbendaharaan komponen kantor, kepadatannya, dan aturan
 * target sentuh — tidak ada yang dioperasikan di sini kecuali satu tautan. */
body.depan {
  background: var(--kertas);
  --ruang: 20px;
  --tepi: 1px;
  --lengkung: 12px;
}

/* Bilah menyatu dengan hero: warnanya sama, garisnya hilang. Bilah yang
 * berdiri sendiri di atas hero membaginya jadi dua benda, dan yang di atas
 * terbaca sebagai perkakas. */
.depan .bilah {
  background: var(--depan-gelap);
  border-bottom: 0;
  padding: var(--r3) var(--r5);
}

/* `main` di sini TIDAK punya lebar maksimum dan tidak punya padding: yang
 * mengatur lebar adalah tiap pita, supaya latarnya bisa membentang penuh
 * sementara isinya tetap terkendali. */
.depan main {
  padding: 0;
  gap: 0;
  max-width: none;
}

.pita {
  padding: var(--r8) var(--r5);
}

.pita-dalam {
  max-width: 68rem;
  margin: 0 auto;
  width: 100%;
}

/* Lebar baca untuk teks berjalan. Bagian yang isinya paragraf memakai ini;
 * bagian yang isinya kisi tidak — itu temuan putaran sebelumnya yang tetap
 * berlaku: panjang barisnya benar, yang salah adalah menganggap SEMUA bagian
 * harus jadi teks berjalan. */
.sempit {
  max-width: 40rem;
  /* Jaraknya datang dari `gap` induk, bukan dari margin anaknya (spec 07 §2) —
   * dan bagian ini tidak punya satu pun sampai paragrafnya menempel ke
   * judulnya. */
  display: flex;
  flex-direction: column;
  gap: var(--r4);
}

/* ── Huruf display, dan HANYA di sini ──────────────────────────────────────
 *
 * Aturan nomor 4 di kepala berkas ini berbunyi: hierarki dari skala, bobot,
 * dan jarak — tidak pernah dari webfont. Alasannya tertulis di sana, dan
 * alasannya tentang LAYAR KERJA: pemilik membuka `/tinjau` dari kebun, di
 * sinyal yang sama yang membuat kita membangun antrean lokal, dan huruf yang
 * harus diunduh dulu adalah layar yang belum bisa dibaca.
 *
 * Alasan itu tidak ikut ke halaman depan, dan memindahkannya tanpa memeriksa
 * adalah persis kesalahan yang berulang di proyek ini. Di sini tidak ada yang
 * sedang bekerja: orang membaca sekali, memutuskan peduli atau tidak, lalu
 * pergi. Yang tidak boleh adalah halaman yang KOSONG sampai hurufnya tiba —
 * dan itu dicegah `font-display: swap` plus cadangan system-ui, bukan dengan
 * tidak punya huruf sama sekali.
 *
 * Badan teks tetap system-ui. Yang diunduh hanya judul, dan hanya di halaman
 * yang tidak dipakai bekerja. Tautannya ada di `depan.html`, bukan di
 * `dasar.html`, supaya layar lapangan tidak bisa ikut memintanya tanpa
 * sengaja. */
.depan h1,
.depan h2,
.depan h3,
.depan .faq-tanya,
.depan .langkah-judul {
  font-family: "Archivo", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Sumbu lebar dipakai justru di ukuran besar: Archivo melebar tanpa jadi
   * gemuk, dan judul yang melebar terbaca sebagai papan, bukan sebagai
   * paragraf yang kebetulan besar. Peramban tanpa dukungan `font-variation-
   * settings` mengabaikannya dan tetap dapat judul yang benar. */
  font-variation-settings: "wdth" 112;
  font-weight: 800;
}

/* ── Pita gelap: hero dan satu bagian yang harus berhenti dibaca sekilas ── */
.pita-hero,
.pita-gelap {
  background: var(--depan-gelap);
  color: var(--dalam-tinta);
}

.pita-hero {
  padding-top: var(--r7);
  padding-bottom: var(--r8);
  position: relative;
  overflow: hidden;
}

/* Jaring di dasar pita hero.
 *
 * Bukan tekstur dekoratif yang bisa dipakai di halaman mana pun: ia benda yang
 * disebut kalimat tepat di atasnya — buah jatuh sendiri KE JARING di bawah
 * pohon — dan ia menutup pita itu di tempat buahnya mendarat.
 *
 * 10% putih di atas #211e3a menaikkan latarnya ke sekitar #36334a; teks putih
 * di sana masih ~11:1, jauh di atas lantai permukaan ini. Ia juga `aria-hidden`
 * dengan sendirinya karena ia `::after` tanpa isi. */
.pita-hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--r8);
  background:
    repeating-linear-gradient(
      45deg,
      rgb(255 255 255 / 10%) 0 2px,
      transparent 2px 14px
    ),
    repeating-linear-gradient(
      -45deg,
      rgb(255 255 255 / 10%) 0 2px,
      transparent 2px 14px
    );
  pointer-events: none;
}

/* Isinya di atas jaring, bukan di bawahnya. */
.pita-hero > .pita-dalam {
  position: relative;
  z-index: 1;
}

/* Pita gambar ikut diangkat, dan ini bukan kerapian.
 *
 * Bingkai tangkapan layar ditarik NAIK ke dalam pita hero dengan margin
 * negatif. Begitu hero punya `::after`, lapisan jaring itu — yang berposisi —
 * melukis di atas pita gambar yang tidak berposisi, dan yang tertutup persis
 * bilah "Contoh — nama dan angkanya karangan": keterangan yang menyatakan
 * angka di gambar itu karangan. Dekorasi yang menutupi pengakuan adalah
 * cacat, bukan soal tumpukan. */
.pita-gambar {
  position: relative;
  z-index: 2;
}

.pita-tenang {
  background: var(--depan-krem);
}

/* Pita tangkapan layar ikut krem: bingkainya putih, dan kartu putih di atas
 * latar putih kehilangan tepinya — yang hilang justru batas antara "ini
 * halaman" dan "ini perangkat lunaknya". */
.pita-gambar {
  background: var(--depan-krem);
}

/* Penutup gelap dan lapang. Dua bagian terakhir — "Yang sengaja tidak
 * dibangun" dan "Keadaan sekarang" — mengisi tempat yang di halaman pemasaran
 * lain ditempati testimoni dan deretan logo. Kita tidak punya satu pun dari
 * itu, dan meniru bentuknya akan membuat lubang persis di tempat sinyal
 * kepercayaan seharusnya ada.
 *
 * Yang dipakai sebagai gantinya bukan pengganti: **tidak ada pesaing yang
 * berani menulis bagian ini**, dan pembaca yang skeptis mengenali kejujuran
 * lebih cepat daripada mengenali klaim. Karena itu keduanya dapat ruang dan
 * tipografi setara bagian testimoni, bukan diperlakukan sebagai catatan kaki. */
.pita-tutup {
  padding-top: var(--r8);
  padding-bottom: var(--r8);
}

.pita-tutup .depan-isi,
.pita-tutup .depan-arti {
  font-size: var(--t5);
  line-height: 1.45;
}

.depan-masuk-tutup {
  margin-top: var(--r6);
}

/* Bagian batas: ruangnya dilonggarkan, bukan isinya ditambah. */
.pita-tenang {
  padding-top: var(--r8);
  padding-bottom: var(--r8);
}

/* ── Hero ────────────────────────────────────────────────────────────────
 * Satu pernyataan besar, dan gambar sebesar pernyataannya. */
/* Judul di lebar penuh pita, gambar turun ke baris berikutnya. Dijepit di
 * samping gambar, judul dua-kalimat ini pecah jadi TIGA baris dengan patahan
 * di tengah kedua kalimatnya — dan pada ukuran hero, patahan itu yang paling
 * terlihat di seluruh halaman. Lebar kolomnya yang mengatur, bukan algoritma
 * pembungkus yang menebak. */
.hero {
  display: flex;
  flex-direction: column;
  gap: var(--r6);
}

.hero-bawah {
  display: flex;
  gap: var(--r7);
  align-items: center;
  flex-wrap: wrap;
}

.hero-teks {
  flex: 1 1 24rem;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--r5);
}

.hero-gambar {
  flex: 1 1 18rem;
  min-width: 0;
  display: flex;
  justify-content: center;
}

.depan h1 {
  font-size: var(--t8);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
}

/* Tiap kalimat judul satu baris sendiri. Patahannya datang dari sini, bukan
 * dari lebar kolom yang diukur — lihat catatan panjang di `depan.html`.
 * `max-width` yang dulu berdiri di sini dihapus bersamaan: membiarkannya
 * berarti dua aturan mengatur hal yang sama, dan yang satu diam-diam membatasi
 * yang lain pada lebar layar tertentu. */
.hero-kalimat {
  display: block;
  text-wrap: balance;
}

.hero-isi {
  font-size: var(--t4);
  line-height: 1.6;
  margin: 0;
  max-width: 32rem;
}

/* Kalimat inti produk. Ia yang harus terbawa pulang kalau pembaca berhenti di
 * layar pertama, jadi ia lebih besar dari isi dan diberi garis tepi — bukan
 * warna lain, yang di produk ini selalu berarti sesuatu. */
.hero-arti {
  font-size: var(--t5);
  line-height: 1.35;
  font-weight: 700;
  margin: 0;
  max-width: 32rem;
  /* PUTIH, bukan kuning. Hero sekarang punya satu benda kuning — stikernya —
   * dan garis kuning di sebelahnya membuat hero punya dua. Pita malam lain
   * tetap bergaris kuning karena di sana tidak ada benda kuning lain. */
  border-left: 6px solid var(--dalam-tinta);
  padding-left: var(--r5);
}

/* ── Dua benda di hero: plat pohon dan stiker buah ────────────────────────
 *
 * Bukan ikon dan bukan diagram — bendanya sendiri, seukuran benda. Plat
 * aluminium yang dipaku di batang dan stiker di plastik pembungkus adalah
 * seluruh dasar produk ini, dan sampai sekarang keduanya cuma sebesar biji di
 * dalam tangkapan layar.
 *
 * Stiker KUNING, plat pucat. Itu bukan selera: kuning adalah warna aksi produk
 * ini, dan stiker adalah satu-satunya benda di sini yang dipasang orang. Satu
 * benda kuning per layar tetap berlaku — pil Masuk di bilah dan garis kalimat
 * inti keduanya putih justru supaya ini yang jadi satu-satunya. */
.hero-gambar {
  flex-direction: column;
  align-items: center;
  gap: 0;
}

.objek {
  display: grid;
  justify-items: center;
  gap: var(--r2);
  padding: var(--r4) var(--r5);
  border-radius: var(--sudut-2);
  position: relative;
}

.objek-plat {
  background: var(--lembut);
  color: var(--tinta);
  border: 3px solid var(--tinta);
}

/* Dua paku di sudut atas: benda ini dipaku, bukan ditempel, dan itu yang
 * membedakannya dari stiker di bawahnya. */
.objek-paku {
  position: absolute;
  top: var(--r2);
  width: var(--r2);
  height: var(--r2);
  border-radius: 50%;
  background: var(--redup);
}

.objek-paku:first-child { left: var(--r2); }
.objek-paku:nth-child(2) { right: var(--r2); }

.objek-stiker {
  background: var(--daging);
  color: var(--di-daging);
  border: 3px solid var(--di-daging);
}

/* Petak QR: kotak bertepi, bukan gambar QR sungguhan. QR yang bisa dipindai di
 * halaman jualan akan dipindai orang, dan yang ia temukan kode karangan. */
/* Petak berpola, bukan QR sungguhan. QR yang benar-benar bisa dipindai di
 * halaman jualan akan dipindai orang — dan yang ia temukan kode karangan yang
 * tidak ada di kebun mana pun. Polanya cukup untuk terbaca "ini kode", dan
 * tidak cukup untuk berpura-pura jadi kode. */
.objek-qr {
  width: var(--r7);
  height: var(--r7);
  border: 3px solid currentColor;
  border-radius: 3px;
  background-image: repeating-conic-gradient(
    currentColor 0 25%,
    transparent 0 50%
  );
  background-size: 33.34% 33.34%;
}

.objek-kode {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--t6);
  font-weight: 700;
  letter-spacing: 0.08em;
}

.objek-nama {
  font-size: var(--t2);
  font-weight: 700;
  opacity: 0.75;
}

/* Tali putus-putus antara keduanya: satu-satunya hubungan yang ada antara
 * pohon dan buah, dan ia dipasang orang — bukan ditemukan sistem. */
.objek-tali {
  display: block;
  width: 3px;
  height: var(--r7);
  background: repeating-linear-gradient(
    var(--dalam-tinta) 0 6px,
    transparent 6px 12px
  );
}

/* Diagram di pita gelap: goresan putih. Tanpa ini ia hijau di atas hijau
 * gelap dan hilang sama sekali. */
/* Diagram di pita gelap: seluruh goresan jadi putih, seluruh isian jadi
 * kosong. Ditulis dengan pemilih atribut, BUKAN dengan mendaftar tiap kelas:
 * daftar kelas yang ketinggalan satu tidak memerah di mana pun — ia cuma
 * membuat sebagian gambar hilang di atas latar gelap, dan tidak ada tes yang
 * melihat gambar. `d-jaring-tali` sudah ketinggalan sekali dengan cara itu.
 *
 * Isian putih akan menutupi goresannya sendiri pada bentuk bertumpuk, jadi
 * gambarnya jadi garis saja — dan garis putih di atas hijau gelap adalah
 * bentuk yang paling terbaca di sini. */
.pita-hero .diagram [class^="d-"],
.pita-gelap .diagram [class^="d-"] {
  fill: none;
  stroke: var(--dalam-tinta);
}

/* JARING kuning, dan hanya jaring.
 *
 * Satu benda di gambar ini yang bukan buah dan bukan pohon: jaring yang
 * menangkapnya. Ia juga satu-satunya benda di halaman ini yang bisa diberi
 * warna tanpa meminjam arti — buah kuning akan terbaca sebagai matang, pohon
 * kuning tidak berarti apa-apa. `--daging` 10,15:1 di atas malam, jauh di
 * atas lantai non-teks 3:1.
 *
 * Aturannya tetap: satu benda kuning per layar. Di hero itu jaring ini; pil
 * Masuk di bilah sengaja putih supaya tidak ada yang kedua. */
.pita-hero .diagram .d-jaring,
.pita-hero .diagram .d-jaring-tali {
  stroke: var(--daging);
}

/* Tanda ± adalah TEKS, bukan goresan: memberinya stroke akan menguraikan
 * hurufnya alih-alih mewarnainya. */
.pita-hero .diagram .d-selisih,
.pita-gelap .diagram .d-selisih {
  fill: var(--dalam-tinta);
  stroke: none;
}

.hero-gambar .diagram {
  max-width: 30rem;
}

/* ── Bagian dua kolom: teks dan gambar berdampingan ─────────────────────── */
.duo {
  display: flex;
  gap: var(--r7);
  align-items: center;
  flex-wrap: wrap;
}

.duo-teks {
  flex: 1 1 26rem;
  min-width: 0;
  max-width: 40rem;
  display: flex;
  flex-direction: column;
  gap: var(--r4);
}

.duo-gambar {
  flex: 1 1 16rem;
  min-width: 0;
  display: flex;
  justify-content: center;
}

.duo-gambar .diagram {
  max-width: 22rem;
}

/* ── Judul bagian ────────────────────────────────────────────────────────
 * `.kantor h2` adalah LABEL panel — kapital semua, ber-tracking, redup. Ia
 * menjawab "bagaimana menamai satu panel", dan benar untuk pertanyaan itu.
 * Judul di sini KALIMAT, dan kapital semua membuatnya dua baris teriakan. */
/* t7, bukan t6. Dengan hero 84px dan badan 18px, judul bagian di 32px terbaca
 * setara teks tebal biasa — delapan bagian jadi sama penting dan halamannya
 * kehilangan tingkat keduanya. t7 (44px) sudah ada di tangga; tidak ada yang
 * perlu dikarang. */
.depan h2 {
  font-size: var(--t7);
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin: 0;
  text-transform: none;
  color: inherit;
  font-weight: 700;
  text-wrap: balance;
}

.depan h2.tengah {
  text-align: center;
  margin: 0 auto var(--r7);
  max-width: 46rem;
}

.depan-isi {
  font-size: var(--t4);
  line-height: 1.65;
  margin: 0;
}

/* Kalimat "jadi apa artinya" di tiap bagian: kesimpulan, bukan kutipan dan
 * bukan peringatan. Penandanya garis tepi dan bobot.
 *
 * Di pita malam garisnya KUNING, dan itu bukan pelanggaran aturan di atas:
 * `--daging` bukan warna semantik yang dipinjam, ia warna aksi produk ini —
 * dan kalimat ini adalah satu-satunya kalimat tiap bagian yang meminta
 * pembacanya menyimpulkan sesuatu. Di pita terang ia plum, karena kuning
 * 1,58:1 di atas kertas dan garis yang tidak terlihat bukan garis. */
.depan-arti {
  font-size: var(--t4);
  line-height: 1.55;
  font-weight: 700;
  margin: 0;
  border-left: 4px solid currentColor;
  padding-left: var(--r4);
}

.pita:not(.pita-gelap):not(.pita-hero) .depan-arti {
  border-left-color: var(--dalam);
}

.pita-gelap .depan-arti,
.pita-hero .depan-arti {
  border-left-color: var(--daging);
  border-left-width: 6px;
}

/* ── Daftar "yang sengaja tidak dibangun" ────────────────────────────────
 *
 * Empat keping dicoret, satu keping tidak. Coretan dipakai karena ia satu-
 * satunya tanda yang artinya tidak perlu dijelaskan — dan yang membedakannya
 * bukan cuma warna: keping yang dibangun punya tinta dan tepi yang berbeda,
 * jadi pembaca yang tidak membedakan warna tetap melihat mana yang mana. */
.batas-daftar {
  list-style: none;
  margin: var(--r5) 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--r3);
}

.batas-daftar li {
  font-size: var(--t3);
  font-weight: 700;
  padding: var(--r2) var(--r4);
  border-radius: var(--sudut-2);
  border: 2px solid var(--garis-halus);
}

.batas-tidak {
  color: var(--redup);
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}

.batas-ya {
  color: var(--dalam-tinta);
  background: var(--dalam);
  border-color: var(--dalam);
}

/* ── Selisih yang punya NAMA ──────────────────────────────────────────────
 *
 * Satu gambar yang menggantikan tiga paragraf. Yang dijual produk ini bukan
 * pencatatan melainkan selisih yang bisa ditanyakan: "−3 buah" tidak bisa
 * ditanyakan ke siapa pun, `DM-8K1D2P tidak sampai` bisa.
 *
 * Titik yang hilang digambar BERONGGA, bukan dihilangkan. Yang hilang harus
 * tetap menempati tempatnya — deret yang memendek cuma terbaca sebagai angka
 * yang lebih kecil, dan itu persis cara kebocoran hari ini tidak terlihat. */
/* Lebarnya dibatasi walau pitanya penuh: 14 titik dalam satu baris butuh
 * ruang, tapi bingkai selebar 1200px membuat isinya menggumpal di kiri dan
 * dua pertiga gambar jadi kosong. */
.selisih {
  margin: var(--r6) 0;
  max-width: 44rem;
}

.selisih-isi {
  padding: var(--r5);
  display: flex;
  flex-direction: column;
  gap: var(--r4);
}

.selisih-baris {
  margin: 0;
  font-size: var(--t3);
  color: var(--redup);
}

.selisih-baris b {
  font-size: var(--t6);
  line-height: 1;
  color: var(--tinta);
  margin-right: var(--r2);
}

/* Seluruh barisnya merah, bukan cuma angkanya: ia duduk di atas tint merah,
 * dan `--redup` di atas `--merah-tipis` adalah pasangan yang tidak pernah
 * didaftarkan di tabel kontras — yaitu pasangan yang tidak pernah diukur. */
.selisih-merah,
.selisih-merah b {
  color: var(--bahaya);
}

.selisih-titik {
  display: flex;
  flex-wrap: wrap;
  gap: var(--r2);
}

.selisih-titik span {
  width: var(--r5);
  height: var(--r5);
  border-radius: 50%;
}

.titik-sampai { background: var(--dalam); }

.titik-hilang {
  border: 3px solid var(--bahaya);
  background: transparent;
}

.selisih-dua {
  display: flex;
  flex-wrap: wrap;
  gap: var(--r6);
  align-items: flex-start;
}

/* Berlatar tint merah supaya ia yang ditemukan mata lebih dulu. Di sinilah
 * seluruh isi halaman ini bermuara: tiga kode yang bisa ditanyakan ke orang. */
.selisih-hilang {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--r2);
  padding: var(--r4);
  border-radius: var(--sudut-2);
  background: var(--merah-tipis);
}

.kode-hilang {
  background: var(--merah-tipis);
  color: var(--bahaya);
  border-color: var(--bahaya);
}

/* ── Empat langkah sebagai kisi kartu ────────────────────────────────────
 * Bukan daftar bernomor vertikal, yang bentuk dokumen. Empat langkah adalah
 * empat KATEGORI, dan `--deret-*` adalah palet yang menjawab persis pertanyaan
 * itu — dipakai untuk pertanyaannya sendiri, bukan dipinjam sebagai hiasan. */
/* Empat kolom di layar lebar, bukan dua kali dua: empat langkah berurutan
 * yang dipatahkan jadi dua baris terbaca sebagai dua pasang. */
.langkah-kisi {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--r5);
  /* `align-items: start` dibuang bersama diagram di kartu 3: alasannya adalah
   * kartu itu — ia dua kali tinggi tetangganya, dan meregangkan yang lain
   * sebaris akan memberi mereka ruang kosong yang muncul karena tetangganya,
   * bukan karena isinya. Tanpa diagramnya, keempat kartu seimbang, dan yang
   * benar sekarang justru sebaliknya: empat langkah setara harus bertepi
   * bawah yang sama. */
}

.langkah-kartu {
  background: var(--kertas);
  border: 1px solid var(--garis-halus);
  border-top: 4px solid var(--deret-hijau);
  border-radius: var(--lengkung);
  padding: var(--r5);
  display: flex;
  flex-direction: column;
  gap: var(--r3);
}

.langkah-1 { border-top-color: var(--deret-hijau); }
.langkah-2 { border-top-color: var(--deret-biru); }
.langkah-3 { border-top-color: var(--deret-ungu); }
.langkah-4 { border-top-color: var(--deret-amber); }

/* Latar keping nomor memakai nada TEKS (`--utama`, `--biru`, `--ungu`,
 * `--peringatan`), bukan nada `--deret-*` yang dipakai garis atas kartunya.
 *
 * Bukan inkonsistensi — dua ambang yang berbeda untuk dua pertanyaan yang
 * berbeda. Garis atas kartu tidak membawa teks: ia non-teks, ambangnya 3:1.
 * Keping ini membawa angka: ambangnya 4,5:1. Versi pertama memakai
 * `--deret-*` untuk keduanya, dan `putih di atas --deret-amber` keluar
 * **4,44:1** — di bawah ambang, ditangkap `test_setiap_warna_teks_ada_di_tabel`
 * karena `--kertas` dipakai sebagai warna teks tanpa pernah didaftarkan.
 *
 * Ini bentuk yang sama dengan memakai ambang teks untuk isian grafik, dibalik:
 * memakai palet non-teks untuk sesuatu yang membawa teks. */
.langkah-nomor {
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--t4);
  font-weight: 800;
  color: var(--dalam-tinta);
  background: var(--dalam);
}

/* Keping nomornya SATU warna untuk keempatnya.
 *
 * Dulu empat warna — plum, biru, ungu, cokelat — dan berdampingan dalam satu
 * baris keduanya yang gelap-keunguan saling meniru. Warnanya juga tidak
 * membawa apa-apa: nomornya sudah menyebut langkah keberapa ini. Yang tetap
 * berbeda per kartu garis atasnya, dan itu memang palet KATEGORI. */

.langkah-judul {
  font-size: var(--t5);
  line-height: 1.25;
  font-weight: 700;
  margin: 0;
  text-wrap: balance;
}

.langkah-isi {
  font-size: var(--t3);
  line-height: 1.6;
  margin: 0;
}

/* Di DALAM kartunya. Gambar dua-orang-dan-± yang berdiri di antara langkah 3
 * dan 4 terbaca sebagai gambar untuk "Perlu ditinjau" — justru langkah yang
 * tidak melibatkan orang kedua. */
.langkah-gambar {
  margin-top: auto;
  padding-top: var(--r4);
  display: flex;
  justify-content: center;
}

.langkah-gambar .diagram {
  max-width: 11rem;
}

/* ── Pengakuan atas apa yang TIDAK dihalangi produk ini ─────────────────── */
.depan-jujur {
  background: var(--amber-tipis);
  border-left: 4px solid var(--peringatan);
  border-radius: var(--lengkung);
  padding: var(--r5);
  font-size: var(--t3);
  line-height: 1.6;
  margin: 0;
}

/* ── Tautan Masuk: satu-satunya yang dioperasikan di halaman ini ────────── */
/* Di pita gelap, keterangan ini mewarisi putih pita — bukan `--redup`, yang di
 * atas `--depan-gelap` keluar 1,63:1 dan praktis tidak terbaca.
 *
 * Versi pertama menaruhnya di `.depan-masuk-tutup`, kelas tunggal yang KALAH
 * spesifisitas dari `.depan-masuk-catatan` di bawah — jadi aturannya tertulis,
 * terbaca benar, dan tidak berlaku. Ditangkap sapuan DOM, yang mengukur warna
 * yang BENAR-BENAR dirender; tabel pasangan statis tidak bisa melihatnya,
 * karena ia hanya tahu pasangan yang didaftarkan orang. */
.pita-gelap .depan-masuk-catatan {
  color: inherit;
}

.depan-masuk-catatan {
  display: flex;
  align-items: center;
  gap: var(--r4);
  flex-wrap: wrap;
  margin: var(--r5) 0 0;
  color: var(--redup);
  font-size: var(--t3);
}

/* Satu-satunya tombol penuh di halaman ini, dan ia di penutup — bukan di
 * hero. Halaman ini memang tidak punya pendaftaran sendiri; tombol besar di
 * hero akan menjanjikan jalan masuk yang tidak ada.
 *
 * SATU aturan, bukan aturan dasar plus penimpa di `.pita-gelap`. Penimpa itu
 * sempat ada, ditulis LEBIH DULU di berkas ini, dengan spesifisitas yang sama
 * (0,2,0) — jadi aturan dasar di bawahnya menang dan tombolnya tetap hijau.
 * Ia terbaca benar dan tidak pernah berlaku. Bentuk yang sama dengan
 * `.pohon-terpasang` dan `.pita-label.tengah` di berkas ini; ketiganya hanya
 * ketahuan dengan membaca `getComputedStyle`, bukan dengan membaca CSS-nya.
 *
 * Isian kuning bertepi GELAP, aturan yang sama dengan `.tombol-utama` di
 * aplikasi: kuning 1,58:1 di atas kertas, jadi tepinya tidak boleh kuning —
 * dan tombol yang sama tidak boleh berubah bentuk antara halaman depan dan
 * layar kerja. */
.depan .tombol-depan {
  min-height: var(--sentuh-kantor);
  padding: var(--r3) var(--r5);
  font-size: var(--t3);
  background: var(--daging);
  color: var(--di-daging);
  border: 3px solid var(--di-daging);
  border-radius: var(--sudut-2);
}

/* Pil bergaris putih, BUKAN kuning — walaupun ia tombol.
 *
 * Kuning di halaman ini menandai satu aksi, dan aksi itu ada di penutup.
 * Dua benda kuning di layar pertama membuat keduanya berhenti menjawab mana
 * yang dimaksud; putih di atas malam 16,01:1 dan tidak kalah terlihat. */
.depan-masuk {
  color: var(--dalam-tinta);
  font-weight: 700;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  min-height: var(--sentuh-kantor);
  padding: 0 var(--r4);
  border: 2px solid var(--dalam-tinta);
  /* `--sudut-2`, bukan pil. Pil menuntut nilai keempat di skala sudut, dan
   * spec 07 §2 menetapkan tiga — alasannya tertulis di sana: skala yang bocor
   * sekali berhenti jadi skala. Satu tombol tidak cukup alasan untuk
   * melebarkannya; kalau nanti seluruh bahasa visualnya memang berbentuk pil,
   * itu perubahan spec dengan alasannya sendiri, bukan satu baris di sini. */
  border-radius: var(--sudut-2);
}

/* ── Layar sempit ────────────────────────────────────────────────────────
 * Kisi jadi satu kolom dan hero mengecil satu tingkat tangga huruf — bukan
 * ukuran karangan di antara tingkat. */
@media (max-width: 720px) {
  .pita {
    padding: var(--r7) var(--r4);
  }

  /* t6, bukan t7. Diukur pada 390px: patahan jatuh tepat di titik hanya untuk
   * ukuran ≤28px, dan 28px bukan tingkat tangga — mengarangnya melanggar satu
   * batasan untuk memperbaiki hal lain.
   *
   * Dari yang ADA di tangga, t6 yang paling sedikit merusak: dua baris dengan
   * kalimat KEDUA utuh ("Buah durian tidak" / "dipetik. Ia jatuh sendiri.").
   * t7 memberi tiga baris dengan kalimat kedua terbelah dan "sendiri." sendirian
   * di baris ketiga. Kalimat pertama yang terbelah langsung diselesaikan
   * pembaca; kalimat kedua yang terbelah kehilangan seluruh isinya. */
  .depan h1 {
    font-size: var(--t6);
  }

  .depan h2 {
    font-size: var(--t5);
  }

  .hero-arti {
    font-size: var(--t4);
  }

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

  .hero-gambar .diagram,
  .duo-gambar .diagram {
    max-width: 100%;
  }
}

/* Layar besar: hero naik satu tingkat lagi. Tidak ada layar kerja yang boleh
 * memakai ini — 84px adalah ukuran untuk satu kalimat yang dibaca sekali. */
@media (min-width: 1200px) {
  .depan h1 {
    font-size: var(--t9);
  }
}

/* ── Bingkai tangkapan layar produk ──────────────────────────────────────
 *
 * Keterangan "data contoh" hidup DI BILAH BINGKAI, bukan di bawah gambar.
 * Keberatan aslinya (spec 02 §12) adalah urutan baca: keterangan di bawah
 * gambar dibaca sesudah gambarnya, dan gambar sudah bekerja lebih dulu.
 * Bingkai membuat keduanya dibaca bersamaan — dan ia ikut terbawa kalau ada
 * yang memotret bagian ini lalu mengirimkannya ke orang lain.
 *
 * Bilahnya sengaja BUKAN hijau aplikasi dan bukan tipografi bilah produk.
 * Kalau ia duduk di posisi bilah judul dengan gaya yang sama, "Contoh" akan
 * terbaca sebagai nama kebun — syarat yang dibawa kata-katanya sendiri. */
.pita-gambar {
  padding-top: 0;
  margin-top: calc(var(--r8) * -1);
}

.bingkai {
  margin: 0;
  border-radius: var(--lengkung);
  overflow: hidden;
  border: 1px solid var(--garis-halus);
  box-shadow: 0 24px 60px rgb(33 30 58 / 20%);
  background: var(--kertas);
}

.bingkai-bilah {
  display: flex;
  align-items: center;
  gap: var(--r3);
  padding: var(--r3) var(--r4);
  background: var(--tinta);
  color: var(--kertas);
  font-size: var(--t2);
  letter-spacing: 0.02em;
}

.bingkai-titik {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--deret-amber);
  flex: 0 0 auto;
}

.bingkai-isi {
  display: block;
  width: 100%;
  height: auto;
}

/* Di HP gambarnya berbentuk HP: tinggi dan sempit. Dibiarkan penuh lebar ia
 * jadi kolom sangat panjang, jadi tingginya dibatasi dan ia dipusatkan. */
@media (max-width: 720px) {
  .bingkai-isi {
    max-height: 70vh;
    width: auto;
    max-width: 100%;
    margin: 0 auto;
  }
}

/* ── Label kecil di atas judul bagian ────────────────────────────────────
 * Ini konstruksi LABEL, bukan kalimat — jadi kapital dan tracking di sini
 * benar, berbeda dengan `h2` yang isinya kalimat. Ia juga mengisi jarak antara
 * hero 84px dan judul 44px dari arah lain: mata mendapat tingkat ketiga.
 *
 * "Keadaan sekarang" sengaja TANPA label: ia penutup, dan label di atasnya
 * membuatnya terbaca sebagai bagian keenam dari daftar, bukan sebagai akhir.
 * "Yang sengaja tidak dibangun" juga tanpa label — judulnya sudah berbunyi
 * seperti label jenis, dan menambahkannya mengatakan hal yang sama dua kali
 * dengan ukuran huruf berbeda. */
/* Label bagian. Dulu hijau — dan sejak hijau berarti "ini tercatat", label
 * dekoratif berwarna hijau adalah warna semantik yang dipakai sebagai hiasan.
 *
 * Kapital semua juga dilepas: ia tanda paling umum halaman yang dirakit dari
 * cetakan, dan label di sini pendek ("Taruhannya", "Kenapa sulit") sehingga
 * bobot dan garis sudah cukup memisahkannya dari judul. */
.pita-label {
  margin: 0 0 var(--r3);
  font-size: var(--t2);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--dalam);
  display: flex;
  align-items: center;
  gap: var(--r2);
}

.pita-label::before {
  content: "";
  width: var(--r5);
  height: 3px;
  background: currentColor;
  flex: 0 0 auto;
}

/* Di pita malam label jadi KUNING. #ffc53d 10,15:1 di atas #211e3a — ia
 * terbaca di sana dan tidak terbaca di atas kertas (1,58:1), jadi kuning di
 * halaman ini hidup di pita gelap dan di tombol, tidak di mana-mana lagi. */
.pita-gelap .pita-label,
.pita-hero .pita-label {
  color: var(--daging);
}

/* `text-align` tidak mengatur apa pun di wadah flex — sejak label ini punya
 * garis `::before`, yang menengahkannya `justify-content`. Aturan lama tetap
 * terbaca benar dan diam-diam tidak berlaku. */
.pita-label.tengah {
  justify-content: center;
}

/* ── Kisi fitur: tiga kartu yang dibangun MENGELILINGI gambar UI ─────────
 * Bukan teks dengan gambar di sampingnya. Tiga, bukan empat: angka empat
 * adalah argumen di bagian "Empat langkah" di atasnya. */
/* `align-items: start` membuat tiap kartu setinggi isinya sendiri, dan
 * `margin-top: auto` di bingkainya jadi tidak punya ruang untuk mendorong —
 * aturan yang tertulis benar dan tidak pernah berlaku. Akibatnya tiga gambar
 * mulai di tiga ketinggian berbeda, dan tiga benda sejenis yang tidak sebaris
 * berhenti terbaca sebagai satu kelompok. */
.kisi-fitur {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--r5);
}

.fitur-kartu {
  display: flex;
  flex-direction: column;
  gap: var(--r3);
}

.fitur-judul {
  font-size: var(--t5);
  line-height: 1.25;
  font-weight: 700;
  margin: 0;
  text-wrap: balance;
}

/* Paragraflah yang menyerap selisih panjang naskah, bukan gambarnya. Dengan
 * ini ketiga bingkai mulai di garis yang sama walau naskahnya beda panjang. */
.fitur-isi {
  font-size: var(--t3);
  line-height: 1.6;
  margin: 0 0 var(--r2);
  flex: 1 1 auto;
}

.fitur-kartu .bingkai {
  box-shadow: 0 12px 32px rgb(33 30 58 / 14%);
}

/* ── Gambar HP di bagian lapangan ────────────────────────────────────────
 * Dibatasi lebarnya: gambar berbentuk HP yang dibiarkan penuh lebar jadi
 * kolom sangat panjang yang mendorong seluruh bagian berikutnya ke bawah. */
.lapangan-gambar {
  display: flex;
  justify-content: center;
  margin-top: var(--r6);
}

.bingkai-hp {
  max-width: 20rem;
}

@media (max-width: 900px) {
  .kisi-fitur {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── FAQ ─────────────────────────────────────────────────────────────────
 * Dua kolom di layar lebar, satu di sempit. `<details>` sengaja tidak dipakai:
 * jawaban di balik ketukan tidak terbaca oleh yang memindai halaman, dan tiga
 * dari tujuh jawaban ini mengakui batas produk — bagian yang paling perlu
 * terbaca tanpa dicari. Halaman yang menyembunyikan pengakuannya di balik
 * akordeon menyembunyikan hal yang paling membuatnya dipercaya. */
.faq {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--r6) var(--r7);
}

.faq-butir {
  display: flex;
  flex-direction: column;
  gap: var(--r2);
}

.faq-tanya {
  font-size: var(--t4);
  font-weight: 700;
  line-height: 1.35;
  text-wrap: balance;
}

.faq-jawab {
  margin: 0;
  font-size: var(--t3);
  line-height: 1.65;
}

@media (max-width: 900px) {
  .faq {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── Halaman asal-usul (`/b/<kode>`, `/p/<kode>`) ───────────────────────────
 * Dibuka kamera HP, hampir selalu di luar ruangan, oleh orang yang memegang
 * durian dengan tangan satunya. Satu kolom, satu pusat perhatian, dan tidak
 * ada yang bisa diketuk selain satu tautan di bawah.
 *
 * Permukaannya `depan` (lihat `asal.html`), jadi ia mewarisi token jarak dan
 * tangga huruf dari sana. Yang TIDAK ikut dari `depan` adalah lebar penuh
 * pita: halaman ini bukan halaman pemasaran, isinya cuma beberapa baris. */
.depan main > .asal {
  max-width: 34rem;
  margin: 0 auto;
  padding: var(--r7) var(--r5) var(--r8);
}

.asal-sampul {
  margin: 0 0 var(--r2);
  color: var(--redup);
  font-size: var(--t2);
}

/* Kode pohon adalah satu-satunya hal yang dicari orang di halaman ini. */
.asal-pohon {
  margin: 0;
  font-size: clamp(2.5rem, 12vw, 3.5rem);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

.asal-varietas {
  margin: var(--r1) 0 0;
  font-size: var(--t4);
  color: var(--depan-gelap);
  font-weight: 700;
}

.asal-rinci {
  margin: var(--r6) 0 0;
  display: grid;
  gap: 0;
}

.asal-rinci > div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--r4);
  padding: var(--r3) 0;
  border-bottom: 1px solid var(--garis-halus);
}

/* Baris terakhir tidak bergaris: di bawahnya sudah ada garis `.asal-tentang`,
 * dan dua garis berjarak beberapa piksel terbaca sebagai cacat, bukan sebagai
 * pemisah. */
.asal-rinci > div:last-child {
  border-bottom: 0;
}

.asal-rinci dt {
  color: var(--redup);
}

.asal-rinci dd {
  margin: 0;
  font-weight: 700;
  text-align: right;
}

.asal-redup {
  color: var(--redup);
  font-weight: 400;
}

.asal-catatan {
  margin: var(--r5) 0 0;
  padding: var(--r4);
  border-left: 3px solid var(--garis);
  background: var(--permukaan-2);
  color: var(--redup);
}

/* Kalimat yang menyebut apa yang TIDAK ditampilkan. Ia bukan hiasan: ia yang
 * menjawab kecurigaan pertama pemilik kebun yang melihat halaman ini di
 * presentasi — "jadi hasil panen saya bisa dibaca orang lewat?". */
.asal-tentang {
  margin: var(--r7) 0 0;
  padding-top: var(--r5);
  border-top: 1px solid var(--garis-halus);
  color: var(--redup);
  font-size: var(--t1);
  max-width: 46ch;
}

.asal-tautan {
  margin: var(--r3) 0 0;
}

/* Tanpa ini tautannya biru bawaan peramban — satu-satunya warna di halaman
 * yang tidak ada di palet, di halaman yang justru paling sering dilihat orang
 * luar. */
.asal-tautan a {
  color: var(--depan-gelap);
  font-weight: 700;
}

/* Kalimat yang mengoreksi angka di atasnya — bukan peringatan bahaya, tapi
 * juga tidak boleh selemah catatan biasa: ia mengubah arti angkanya. */
.catatan-awas {
  margin: var(--r1) 0 0;
  /* --peringatan (#6b4100), BUKAN --peringatan-tinta (#ffffff). Yang kedua
   * adalah warna teks DI ATAS latar peringatan; di kartu putih ia hilang
   * sama sekali. Token yang benar di tempat yang salah. */
  color: var(--peringatan);
  font-size: var(--t1);
  font-weight: 600;
}

/* ── Baris daftar di titik kumpul ───────────────────────────────────────────
 * Kode · pohon · keadaan, dalam SATU baris di lebar HP.
 *
 * `.berjajar` tidak dipakai di sini walau terlihat cocok: ia membungkus pada
 * 45%, karena ia dibuat untuk dua isian berdampingan. Tiga kolom di dalamnya
 * pecah jadi dua baris setengah jadi. Aturan yang benar di tempat yang salah
 * — bentuk kesalahan yang sudah berulang di proyek ini. */
.baris-timbang {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--r3);
  padding: var(--r3) var(--r4);
  border-bottom: 1px solid var(--garis-halus);
}
.baris-timbang:last-child { border-bottom: 0; }
.baris-timbang > span:nth-child(2) { color: var(--redup); }
