/* Peduli Sekayu · created by Ndikzz & GOS · © 2026 Ndikzz & GOS. Hak cipta dilindungi. */
/* Peduli Sekayu — Sistem Desain.

   Isi halaman memakai kerangka dokumen resmi: bidang putih, pemisah garis 1px, dan teks
   yang diberi ruang. Di situ tidak ada gradasi maupun bayangan dekoratif — keduanya
   tidak menyampaikan informasi apa pun dan hanya membuat halaman terasa ramai.

   DUA PENGECUALIAN YANG DISENGAJA, keduanya bidang identitas, bukan isi:
   1. Bilah atas — merah gelap bergradasi, menempel saat digulir.
   2. Hero beranda — merah penuh bergradasi dengan kartu aksi putih di atasnya.
   Di sanalah kanal ini menyatakan dirinya milik pemerintah, dan bidang putih polos
   tidak sanggup melakukannya: netral tidak sama dengan berwibawa. Begitu warga masuk ke
   halaman isi — daftar laporan, formulir, panel — warnanya kembali tenang supaya yang
   menonjol adalah datanya. */
:root {
  /* Merah — satu warna dominan, dipakai hemat */
  --merah:        #B81622;  /* aksi utama, status Diproses, aksen aktif */
  --merah-tua:    #7A0E14;  /* hover, badge Ditolak, badge Super Admin */
  --merah-samar:  #FDF2F2;  /* latar penekanan, panel identitas */

  /* Tinta */
  --tinta:        #14100E;  /* teks utama, bilah panel */
  --tinta-2:      #3A332E;  /* isi paragraf */
  --tinta-3:      #4A433D;  /* teks sekunder yang masih penting */
  /* LANTAI kontras untuk teks abu di atas putih — 4,74:1. Jangan pernah memakai abu
     yang lebih terang: nilai lama #9B938B hanya 3,03:1 dan gagal WCAG AA. */
  --tinta-redup:  #7A726A;

  /* Permukaan & garis — seluruhnya diturunkan dari crimson #B81622 (rona ~350°,
     kejenuhan 3–5%), bukan dari beige.
     ATURAN YANG BISA DIUJI: di setiap token blok ini, kanal Biru >= kanal Hijau.
     Begitu B < G, ronanya jatuh ke oranye dan nadanya masuk pita krem hangat yang kini
     jadi tanda tangan tampilan buatan generator. Nilai lama (#F5F1EF = 245/241/239)
     melanggarnya — cukup untuk lolos dari mata, tidak dari angkanya.
     Luminansinya sengaja hampir tak berubah (245 -> 244), jadi tak satu pun rasio
     kontras yang sudah diukur perlu dihitung ulang.
     Gunanya bukan hiasan: kartu dan tabel PUTIH baru punya kedalaman kalau berdiri di
     atas dasar yang lebih gelap. Halaman putih-di-atas-putih terasa lemah persis karena
     permukaannya tak pernah terpisah. */
  --putih:        #FFFFFF;
  --dasar:        #F4F0F1;  /* 244/240/241 */
  --dasar-tua:    #EBE4E6;  /* footer, menutup halaman */
  --permukaan:    #FAF7F8;  /* blok input & thead tabel di dalam kartu putih */
  --permukaan-2:  #EFE8EA;  /* pil hitung non-aktif, badge Diterima */
  --garis:        #E2DADC;  /* pemisah utama 1px */
  --garis-kuat:   #D6CCCF;  /* border tombol sekunder */
  --garis-input:  #C4B8BB;  /* border input */
  --titik-mati:   #C0B5B8;  /* titik timeline tahap yang belum terjadi */

  /* Peringatan non-merah (indikator tenggat "mendekati batas") */
  --kuning-tua:   #7A5C0C;
  /* Konfirmasi (toast sukses & banner tersimpan) */
  --hijau-tua:    #1F6B3A;
  --hijau-samar:  #E9F2EC;

  --r: 6px;

  /* Skala tipografi — dikunci sebagai token supaya ukuran tidak beranak sendiri di
     tiap halaman. 16,5px adalah LANTAI untuk teks isi; jangan pernah lebih kecil. */
  --t-xl: 38px; --t-l: 26px; --t-m: 20px; --t-s: 17px;
  --t-isi: 16.5px; --t-kecil: 14.5px; --t-label: 14px; --t-meta: 13px; --t-eyebrow: 11px;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
/* Kolom flex setinggi viewport: ini yang menjamin footer selalu sampai ke bawah layar,
   berapa pun pendeknya isi halaman. Sebelumnya tugas itu dititipkan ke `main { min-height:
   60vh }` — sebuah terkaan yang meleset begitu halaman lebih pendek dari layar, menyisakan
   pita latar halaman di bawah footer yang terbaca seperti bug.
   100dvh, bukan 100vh: di peramban HP, bilah alamat yang menyusut mengubah tinggi viewport,
   dan 100vh memakai tinggi TERBESAR sehingga menyisakan celah yang sama di layar kecil. */
body {
  margin: 0; background: var(--dasar); color: var(--tinta-2);
  min-height: 100dvh; display: flex; flex-direction: column;
  font-family: 'Instrument Sans', system-ui, sans-serif;
  font-size: var(--t-isi); line-height: 1.6;
}
/* Permukaan yang MEMBAWA ISI berdiri putih di atas dasar. Inilah yang memberi kedalaman
   tanpa satu pun bayangan: kartu, tabel, dan kotak aksi terpisah dari halaman karena
   nadanya berbeda, bukan karena diberi efek. */
.kartu, .tabel, .aksi-box, .chart-box, .kpi, .saring, .identitas, .akses-lipat,
.kotak-jelas, .zona-bahaya, .tabel-meta, .act-card { background: var(--putih); }

/* Judul memakai Bricolage Grotesque, tapi hanya sampai h2: di ukuran kecil huruf
   display justru terbaca sebagai gaya, bukan sebagai hierarki. h3 ke bawah memakai
   font teks dengan bobot tebal. */
h1, h2 { font-family: 'Bricolage Grotesque', 'Instrument Sans', sans-serif; font-weight: 800;
  letter-spacing: -.02em; line-height: 1.1; color: var(--tinta); margin: 0 0 12px; }
h3 { font-family: 'Instrument Sans', sans-serif; font-weight: 700; font-size: var(--t-s);
  line-height: 1.2; color: var(--tinta); margin: 0 0 8px; }
h1 { font-size: var(--t-xl); }
h2 { font-size: var(--t-m); }
a { color: var(--merah-tua); }
a:hover { color: var(--merah); }
.mono { font-family: 'IBM Plex Mono', monospace; font-weight: 600; font-variant-numeric: tabular-nums; }
/* Memuai mengisi sisa ruang — inilah yang mendorong footer ke bawah. Menggantikan
   `min-height: 60vh` yang lama. */
main { flex: 1; }
/* Penanda fokus kuning-hitam.
   Sebelumnya cincin fokus memakai merah identitas — dan merah di atas bilah merah atau
   hero merah praktis tidak terlihat sama sekali. Itu kegagalan WCAG 2.2 SC 1.4.11 yang
   nyata, bukan soal selera: pengguna keyboard kehilangan jejak posisinya persis di
   navigasi utama.
   Kuning ini SENGAJA bukan warna merek siapa pun dan memang harus bentrok dengan
   segalanya — itu sebabnya ia lolos di atas semua latar sistem ini: 4,94:1 terhadap
   crimson, dan tinta di atas kuning ~14,6:1. Jangan digeser ke oranye atau emas.
   Tiga detail yang mudah terlupa dan sengaja dipertahankan:
   - `outline: 3px solid transparent` menjaga penanda tetap ada di mode kontras tinggi
     Windows, tempat browser membuang box-shadow;
   - `text-decoration: none` karena garis bawah hitam 4px sudah menggantikannya;
   - shadow atas -2px menutup celah di atas huruf turun (g, y, p). */
/* CINCIN GANDA: putih di dalam, tinta di luar.
   Satu warna saja tidak sanggup melayani seluruh sistem ini — merah lenyap di atas bilah
   merah, tinta lenyap di atas bilah tinta, putih lenyap di atas kertas terang. Dua cincin
   bertumpuk menyelesaikannya tanpa memasukkan warna baru ke dalam palet: di bidang gelap
   yang terbaca cincin putihnya, di bidang terang yang terbaca cincin tintanya. Selalu ada
   satu yang kontras, di mana pun elemennya berdiri.
   Ini menggantikan kuning #FFDD00 milik GOV.UK. Kuning itu memang paling aman secara
   teknis, tapi ia warna asing yang berteriak di tengah sistem merah-tinta — dan penanda
   fokus tidak harus mencolok untuk menjadi jelas, ia hanya harus punya kontras. */
:focus-visible {
  outline: 2px solid var(--putih);
  outline-offset: 1px;
  box-shadow: 0 0 0 5px var(--tinta);
  border-radius: 3px;
}
/* Isian formulir: bordernya sendiri yang menebal jadi tinta, ditambah cincin di luar. */
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--putih); outline-offset: 1px;
  border-color: var(--tinta); box-shadow: 0 0 0 5px var(--tinta), inset 0 0 0 1px var(--tinta);
}

/* Setiap angka memakai lebar digit tetap. Tanpa ini kolom tabel bergoyang saat 9 -> 10
   dan hitung mundur OTP berdenyut tiap detik. */
td, th, .mono, .badge, .pil-hitung, .ind, .kode, .kartu-meta, .meta, time,
input[type="date"], .tiket-besar, .kode-besar, .capaian strong, .stats3 strong {
  font-variant-numeric: tabular-nums;
}

.wrap { max-width: 1024px; margin: 0 auto; padding: 24px 20px; }
.wrap-full { max-width: 1440px; margin: 0 auto; padding: 24px 30px; }
.sempit { max-width: 680px; }
.tengah { text-align: center; }
.eyebrow, .label-seksi {
  font-family: 'IBM Plex Mono', monospace; font-weight: 600; font-size: var(--t-eyebrow);
  letter-spacing: .15em; text-transform: uppercase; color: var(--merah);
}
.label-seksi { color: var(--tinta-3); margin: 28px 0 12px; display: block; }
.lead { font-size: var(--t-isi); color: var(--tinta-2); max-width: 62ch; }
/* Teks sekunder memakai --tinta-3, bukan --tinta-redup.
   --tinta-redup adalah lantai kontras di atas PUTIH MURNI (4,73:1). Begitu dasar halaman
   diberi nada hangat, nilainya turun ke 4,24:1 dan gagal WCAG AA — cukup untuk lolos
   dari mata, tidak cukup untuk lolos dari pengukuran. Token itu tetap ada dan tetap
   dipakai untuk placeholder di dalam kotak isian yang memang berlatar putih. */
.meta { font-size: var(--t-meta); color: var(--tinta-3); }
.hint { font-size: var(--t-kecil); color: var(--tinta-3); }
.kosong { color: var(--tinta-3); padding: 20px 0; }
/* --tinta-redup adalah lantai kontras di atas PUTIH (4,73:1). Di atas --permukaan yang
   sedikit lebih gelap nilainya turun ke 4,46:1 — lolos sekilas, gagal WCAG AA. Semua
   wadah berlatar permukaan karena itu menaikkan teks redupnya satu tingkat. Ditemukan
   dengan mengukur di browser, bukan dengan melihat. */
.footer .meta, .aksi-box .meta, .blok-lacak .meta, .kotak-eskalasi .meta, .saring .meta,
.footer .hint, .aksi-box .hint, .kotak-eskalasi .hint, .peta-gagal,
.tabel th, .kpi .kpi-label, .kpi .banding, .akses-lipat > summary {
  color: var(--tinta-3);
}
.deskripsi { color: var(--tinta-2); }

/* --- Bilah atas ---------------------------------------------------------- */
/* Bilah merah gelap, MENEMPEL saat halaman digulir. Merah pekat di sini yang membuat
   kanal ini terbaca sebagai milik pemerintah sejak pandangan pertama — bidang putih
   polos terasa netral, dan netral bukan yang dibutuhkan kantor kelurahan.
   Pita "kanal resmi" yang dulu berdiri sendiri tidak diperlukan lagi: bilah inilah
   penanda institusinya, dan pernyataannya pindah ke eyebrow di dalam hero.
   BOTTOM RADIUS SENGAJA TIDAK ADA. Versi produksi memakai `border-radius: 0 0 26px 26px`
   sementara hero mulai tepat di batas bawah bilah (celah 0 piksel). Sudut membulat
   memotong LATAR YANG DICAT, bukan kotak elemennya — sehingga di baji melengkung pojok
   kiri-bawah dan kanan-bawah, latar body ikut terlihat sebagai takik terang. Itulah
   "bolong di pojok" yang terlihat di produksi. Dengan bilah menempel, takik itu akan
   ikut berjalan saat digulir. Tanpa radius, bilah dan hero menjadi satu bidang utuh. */
.topbar {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 28px; flex-wrap: wrap; color: var(--putih);
  background:
    radial-gradient(120% 140% at 85% -20%, rgba(216, 35, 42, .5), transparent 55%),
    linear-gradient(180deg, #8E1119 0%, var(--merah-tua) 78%);
  box-shadow: 0 6px 18px rgba(122, 14, 20, .22);
}
/* Nama lembaga berdiri sendiri sebagai wordmark — tanpa kotak inisial di sebelahnya.
   Monogram "PS" tidak menambah pengenalan apa pun bagi warga yang belum mengenal
   layanannya, dan justru mengecilkan namanya sendiri. Yang dikenali warga adalah kata
   "Peduli Sekayu" dan keterangan wilayahnya. */
.topbar .brand { color: var(--putih); text-decoration: none; display: flex; align-items: center;
  font-family: 'Bricolage Grotesque', sans-serif; font-weight: 800; font-size: 23px; letter-spacing: -.03em; }
.brand-teks { display: flex; flex-direction: column; line-height: 1.1; }
.brand-sub { font-family: 'Instrument Sans', sans-serif; font-weight: 400; font-size: 12.5px;
  color: rgba(255, 255, 255, .85); letter-spacing: .01em; margin-top: 3px; }
.brand-sub-inline { font-family: 'Instrument Sans', sans-serif; font-weight: 400; font-size: 15px;
  color: rgba(255, 255, 255, .8); letter-spacing: 0; margin-left: 7px; }
.topbar nav { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }

/* Tidak ada lagi pola buka-tutup di navigasi utama. <details> yang dulu dipakai sebagai
   hamburger tampak bekerja tanpa JavaScript, padahal Chrome menyembunyikan isinya lewat
   slot internal ber-content-visibility yang tidak bisa dikalahkan `display` — seluruh
   tautan lenyap dari bilah di layar lebar. Dirender langsung jauh lebih tahan. */
/* Teks nav putih di atas bilah merah gelap — terukur 11,05:1 terhadap --merah-tua. */
.topbar nav > a:not(.btn) { position: relative; color: var(--putih); text-decoration: none; font-weight: 600;
  font-size: 15.5px; padding: 12px 14px; border-radius: var(--r); min-height: 46px;
  display: inline-flex; align-items: center; }
.topbar nav > a:not(.btn):hover { background: rgba(255, 255, 255, .14); color: var(--putih); }
/* Halaman yang sedang dibuka. Ditandai GARIS TEBAL di bawah tautannya, bukan sekadar
   warna atau bobot huruf: garis itu terbaca di sekali pandang bahkan pada layar yang
   pucat kena matahari, dan tetap ada bagi yang tidak membedakan warna. Pasangannya
   aria-current="page" dipasang app.js supaya pembaca layar ikut mengumumkannya —
   panduan USWDS menyebutnya "highlight the current section". */
.topbar nav > a:not(.btn).on { font-weight: 700; background: rgba(255, 255, 255, .1); }
.topbar nav > a:not(.btn).on::after {
  content: ''; position: absolute; left: 14px; right: 14px; bottom: 6px;
  height: 3px; background: var(--putih); border-radius: 2px;
}
/* Tombol utama di atas bilah merah: dibalik jadi putih supaya tetap menonjol —
   merah di atas merah kehilangan seluruh perbedaannya. */
.topbar nav > .btn-primary { background: var(--putih); color: var(--merah-tua); border-color: var(--putih); margin-left: 8px; }
.topbar nav > .btn-primary:hover { background: var(--merah-samar); color: var(--merah-tua); border-color: var(--merah-samar); }

/* Bilah panel: tinta solid, juga menempel. Item aktif ditandai garis bawah. */
.panelbar { background: var(--tinta); background-image: none; border-bottom: 0; box-shadow: 0 6px 18px rgba(0, 0, 0, .18); }
.panelbar .brand, .panelbar nav > a:not(.btn) { color: var(--putih); }
.panelbar .brand-mark { background: rgba(255, 255, 255, .14); border-color: rgba(255, 255, 255, .24); }
.panelbar nav > a:not(.btn):hover { background: rgba(255,255,255,.10); color: var(--putih); }
.panelbar nav > a.on { box-shadow: inset 0 -3px 0 var(--merah); }
.whoami { font-size: var(--t-meta); color: rgba(255,255,255,.75); }

/* --- Tombol -------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 1.5px solid transparent; border-radius: var(--r); padding: 11px 18px;
  min-height: 44px; font: 600 15.5px 'Instrument Sans', sans-serif;
  cursor: pointer; text-decoration: none; text-align: center;
}
.btn-primary { background: var(--merah); color: var(--putih); border-color: var(--merah); }
.btn-primary:hover { background: var(--merah-tua); border-color: var(--merah-tua); color: var(--putih); }
.btn-outline { background: var(--putih); color: var(--tinta); border-color: var(--garis-kuat); }
.btn-outline:hover { background: var(--permukaan-2); color: var(--tinta); }
/* Tombol outline di atas bilah panel yang gelap. Dulu masalahnya kontras: warna teks
   --aksen-teks hanya memberi 1,63:1 di atas tinta dan praktis tidak terbaca, ditambal
   dengan token --aksen-terang. Palet baru tidak lagi punya token itu — tombolnya kini
   memakai teks putih (15,9:1) dengan border abu terang yang tetap terlihat di atas
   tinta. Catatannya disimpan supaya bug kontrasnya tidak lahir kembali. */
.panelbar .btn-outline { background: transparent; color: var(--putih); border-color: #45403A; }
.panelbar .btn-outline:hover { background: rgba(255,255,255,.12); color: var(--putih); }
.btn-lg { padding: 16px 24px; font-size: var(--t-s); min-height: 54px; }
/* Tombol lihat kata sandi. Target sentuh tetap 44px sesuai sistem desain. */
.btn-lihat { align-self: flex-start; margin-top: .4rem; min-height: 44px; }

/* --- Formulir ------------------------------------------------------------ */
.lapor, .login-form, .login, .form-status { max-width: 680px; margin: 24px auto; padding: 0 20px; }
.field { display: flex; flex-direction: column; gap: 6px; margin: 16px 0; }
.field > span { font-weight: 700; font-size: var(--t-label); color: var(--tinta); }
input, select, textarea {
  font: 400 var(--t-isi) 'Instrument Sans', sans-serif; padding: 13px;
  border: 1.5px solid var(--garis-input); border-radius: var(--r);
  background: var(--putih); color: var(--tinta); width: 100%; min-height: 52px;
}
textarea { min-height: 120px; line-height: 1.55; }
/* Fokus isian ditangani aturan :focus-visible di atas (kuning + border tinta 2px).
   Aturan lama memakai merah tipis dan `outline: none`, yang menghapus penanda bawaan
   peramban tanpa menggantinya dengan sesuatu yang cukup terlihat. */
::placeholder { color: var(--tinta-redup); opacity: 1; }
.row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.step { border: 0; padding: 0; margin: 0; }
.hidden { display: none; }
.step-nav { display: flex; justify-content: space-between; gap: 10px; margin-top: 20px; }
.form-hapus, .form-reset, .form-wilayah { margin: 6px 0 0; }
/* Pembetulan kategori kegiatan: dropdown + tombol berdampingan di dalam sel tabel.
   Membungkus ke bawah pada layar sempit, bukan mendorong tabelnya melebar. */
.form-kategori { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0; }
.form-kategori select { width: auto; min-width: 150px; }

/* Input berkas: zona bergaris putus-putus, tanpa gradasi pada tombolnya. */
input[type="file"] {
  padding: 16px; border: 1.5px dashed var(--garis-input); border-radius: var(--r);
  background: var(--permukaan); cursor: pointer; color: var(--tinta-3); font-size: var(--t-kecil);
}
input[type="file"]:hover { border-color: var(--merah); background: var(--merah-samar); }
input[type="file"]::file-selector-button {
  font: 600 var(--t-label) 'Instrument Sans', sans-serif; color: var(--putih); background: var(--merah);
  border: 0; border-radius: var(--r); padding: 11px 16px; margin-right: 14px; cursor: pointer; min-height: 44px;
}
input[type="file"]::file-selector-button:hover { background: var(--merah-tua); }

/* Blok tanggal tinjau ulang — dijadikan satu panel supaya maksudnya jelas,
   bukan sekadar satu field yang muncul tiba-tiba saat status dipilih. */
.blok-tanggal { border: 1px solid var(--garis); border-left: 3px solid var(--merah);
  border-radius: 0 var(--r) var(--r) 0; padding: 16px 18px; background: var(--merah-samar); gap: 0; }
/* Field bersyarat wajib benar-benar tersembunyi saat atribut hidden dipasang.
   Tanpa aturan ini, `display: flex` dari .field mengalahkan [hidden] bawaan browser,
   sehingga kedua field syarat (foto bukti & tanggal tinjau ulang) selalu tampil
   sekaligus apa pun status yang dipilih petugas. */
.syarat[hidden] { display: none; }
.blok-tanggal-judul { margin: 0 0 6px; font-weight: 700; font-size: var(--t-s); color: var(--merah-tua); }
.blok-tanggal .hint { margin: 0 0 12px; }
.blok-tanggal .field { margin: 0; }
input[type="date"] { cursor: pointer; }
.input-tanggal { font-family: 'IBM Plex Mono', monospace; font-weight: 600; font-size: var(--t-s);
  letter-spacing: .02em; max-width: 260px; }
input[type="date"]::-webkit-calendar-picker-indicator { cursor: pointer; padding: 4px; border-radius: 4px; }

/* Pilihan kategori & mode kerahasiaan: baris bergaris, terpilih ditandai border merah
   DAN latar samar DAN bobot tebal — tidak pernah warna saja. */
.kat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 9px; margin: 12px 0; }
.kat-card { display: flex; align-items: center; gap: 10px; min-height: 58px;
  border: 1px solid var(--garis); border-radius: var(--r); padding: 13px 12px;
  cursor: pointer; background: var(--putih); color: var(--tinta); }
.kat-card input { display: none; }
.kat-card:has(input:checked) { border: 1.5px solid var(--merah); background: var(--merah-samar); font-weight: 700; }
/* Penanda kategori. Glyph ▲ ■ ● ◆ yang masih dirender views.js disembunyikan di sini
   sampai kategori ditulis ulang: bentuk-bentuk itu sudah bermakna sebagai indikator
   tenggat, dan memakainya lagi sebagai hiasan membuat maknanya luntur. */
.kat-ikon { flex: 0 0 8px; width: 8px; height: 8px; background: var(--merah);
  font-size: 0; color: transparent; overflow: hidden; }
.kat-nama { font-size: var(--t-kecil); font-weight: 500; line-height: 1.25; }
.rahasia-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 12px 0; }
.rahasia-card { border: 1px solid var(--garis); border-radius: var(--r); padding: 16px; cursor: pointer; background: var(--putih); }
.rahasia-card:has(input:checked) { border: 1.5px solid var(--merah); background: var(--merah-samar); }
.rahasia-card p { font-size: var(--t-kecil); color: var(--tinta-2); margin: 6px 0 0; }
.peta { height: 180px; border-radius: var(--r); border: 1px solid var(--garis); z-index: 0;
  margin-top: 10px; }
/* Di layar lebar 180px hanya menyisakan pita tipis yang sulit dipakai menandai titik
   dengan tepat. Di HP tingginya dipertahankan supaya peta tidak mendorong tombol
   "Lanjut" keluar layar. */
@media (min-width: 720px) { .peta { height: 320px; } }

/* Bilah langkah wizard: tiga titik lama diganti segmen. Nomor tetap dirender oleh
   views.js sebagai .dot, jadi selektornya dipertahankan. */
.langkah-bar { display: flex; gap: 4px; margin-bottom: 20px; }
.dot { flex: 1; height: 5px; border-radius: 2px; background: var(--permukaan-2);
  color: transparent; font-size: 0; overflow: hidden; }
.dot.on { background: var(--merah); }

/* --- Pesan & umpan balik ------------------------------------------------- */
.alert { background: var(--merah-samar); color: var(--tinta); padding: 13px 15px;
  border: 1px solid var(--merah); border-left: 3px solid var(--merah);
  border-radius: 0 var(--r) var(--r) 0; font-size: var(--t-kecil); }
/* Umpan balik berhasil. Dibedakan dari .alert (galat) lewat teks DAN warna,
   bukan warna saja — aturan yang sama dengan badge status. */
.alert.sukses { background: var(--hijau-samar); color: #14401F; border-color: var(--hijau-tua); border-left-color: var(--hijau-tua); }

/* --- Angka --------------------------------------------------------------- */
/* Pil hitung: satu-satunya bentuk untuk angka yang menempel pada label tab/filter/nav.
   Nol TIDAK dirender sebagai pil — ketiadaan lebih jelas daripada angka "0". */
.pil-hitung {
  display: inline-grid; place-items: center; min-width: 22px; height: 22px; padding: 0 6px;
  border-radius: 4px; line-height: 1; font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums; background: var(--permukaan-2); color: #554E48;
}
.tab.on .pil-hitung { background: var(--merah); color: var(--putih); }

/* --- Kartu laporan ------------------------------------------------------- */
.sec-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-bottom: 14px; }
/* Daftar laporan sebagai BARIS bertumpuk, bukan kisi kartu.
   Baris lebih cepat dipindai saat orang mencari satu hal tertentu, karena posisi tiap
   bagian tetap dan bisa ditebak mata. Kisi baru menang kalau tiap kartunya kaya isi —
   dan di sini isinya justru pendek. Baris juga memuat lebih banyak laporan per layar
   360px, dan tidak pernah meninggalkan lubang kosong seperti kartu yang meregang
   mengikuti tetangga tertingginya. */
/* TANPA `overflow: hidden`. Dulu ada untuk memotong sudut kartu mengikuti radius wadah —
   tetapi ia juga memotong pratinjau foto yang membesar saat hover, dan di daftar berisi
   satu kartu wadahnya setinggi kartu itu saja sehingga pembesarannya terpangkas habis
   dan tampak tidak terjadi apa-apa. Pembulatan sudut dipindah ke kartu pertama dan
   terakhir, yang mencapai hasil yang sama tanpa mengurung anaknya. */
.grid-kartu { display: flex; flex-direction: column; gap: 0;
  background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r);
  max-width: 46rem; }
.grid-kartu > .kartu:first-child { border-radius: var(--r) var(--r) 0 0; }
.grid-kartu > .kartu:last-child { border-radius: 0 0 var(--r) var(--r); }
.kartu { display: grid; grid-template-columns: 92px 1fr; gap: 14px; align-items: start;
  padding: 14px 16px; text-decoration: none; color: var(--tinta);
  border-left: 3px solid var(--st, var(--garis-kuat)); }
.kartu.tanpa-gambar { grid-template-columns: 1fr; }
.kartu + .kartu { border-top: 1px solid var(--garis); }
/* Tepi kiri sudah membawa warna status; saat disentuh seluruh barisnya yang menyala,
   bukan tepinya saja — umpan balik yang tidak menggeser apa pun. */
.kartu:hover { background: var(--merah-samar); }
.kartu-foto { width: 92px; height: 92px; object-fit: cover; border-radius: 4px;
  background: var(--permukaan-2); display: block; }
.kartu-teks { display: grid; gap: 5px; min-width: 0; }
.kartu-atas { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.kode { font-family: 'IBM Plex Mono', monospace; font-size: var(--t-meta); color: var(--tinta-3); }
/* Asal kegiatan menempel KANAN pada baris atas kartu.
   margin-left:auto, bukan sekadar justify-content:space-between pada .kartu-atas:
   .kartu-atas sudah flex-wrap:wrap, dan pada layar sempit judul panjang akan membungkus —
   dengan auto, asal tetap menempel kanan di barisnya sendiri, bukan melompat ke kiri. */
.kartu-judul { font-weight: 700; }
/* Pil kategori kegiatan: penanda jenis, dibaca lewat ikon + teks (bukan warna). Duduk tepat
   setelah judul; asal kegiatan tetap menempel kanan lewat margin-left:auto miliknya. */
.kartu-kategori { display: inline-flex; align-items: center; gap: 5px; flex: none;
  font-size: var(--t-meta); color: var(--tinta-2); background: var(--permukaan-2);
  border-radius: 999px; padding: 2px 9px 2px 8px; white-space: nowrap; }
.kk-ikon { font-size: .95em; line-height: 1; color: var(--tinta-3); }
/* Ndikzz & GOS 2026 */
/* Kartu KELOLA (/panel/kegiatan): wadah <div> dengan aksi di baris bawah. Judulnya sendiri
   yang jadi tautan; hanya judul yang menyala saat disentuh, bukan seluruh baris. */
.kartu-kelola:hover { background: transparent; }
a.kartu-judul { color: var(--tinta); text-decoration: none; }
a.kartu-judul:hover { text-decoration: underline; }
.kartu-aksi-baris { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 2px; font-size: var(--t-meta); }
.kartu-aksi-baris .form-hapus { margin: 0; display: inline; }
.detail-aksi { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 4px 0 14px; }
.detail-aksi .form-hapus { margin: 0; }
/* Pilih laporan untuk dicetak (hanya admin/super_admin di /laporan). Checkbox duduk di LUAR
   <a> kartu; form dibuat display:contents supaya tak memutus tata letak .grid-kartu. */
.cetak-form { display: contents; }
.cetak-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; margin: 4px 0 10px; padding: 10px 14px; background: var(--permukaan-2);
  border-radius: var(--r); }
.cetak-bar .hint { margin: 0; }
.pilih-item { display: flex; align-items: stretch; }
.pilih-item > .pilih-cek { flex: none; align-self: center; width: 18px; height: 18px;
  margin: 0 6px 0 14px; cursor: pointer; }
.pilih-item > .kartu { flex: 1 1 auto; min-width: 0; }
.grid-kartu > .pilih-item + .pilih-item { border-top: 1px solid var(--garis); }
.kartu-asal { margin-left: auto; display: flex; gap: 6px; align-items: center;
  font-size: var(--t-meta); color: var(--tinta-3); }
/* Teks polos "RT 02 RW 04": TIDAK boleh membungkus di tengah pasangan pada layar sempit
   (.kartu-asal sendiri tidak wrap, tapi teks di dalam span-nya bisa, dan hasilnya "RT 02"
   turun sendirian ke baris berikut). Pola yang sama dipakai .badge/.act-utama/.tab di
   berkas ini untuk alasan yang sama: label pendek yang harus tetap satu baris. */
.asal-wilayah { white-space: nowrap; }
.asal-lembaga { background: var(--permukaan-2); border-radius: 4px; padding: 2px 7px; }
/* Dipotong di batas BARIS, bukan di tengah kata. Pemotongan di server (slice) berhenti
   di huruf ke-140 apa pun yang ada di sana — sering di tengah kata. */
.kartu-isi { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; font-size: var(--t-kecil); line-height: 1.45; color: var(--tinta-2); }
.kartu-meta { font-size: var(--t-meta); color: var(--tinta-3); }

/* --- Badge status -------------------------------------------------------- */
/* Warnanya datang inline dari lib.STATUS. Label teksnya WAJIB ikut: status tidak
   pernah boleh dibedakan hanya lewat warna. */
.badge { display: inline-block; font-weight: 700; font-size: 11.5px; letter-spacing: .04em;
  text-transform: uppercase; padding: 4px 9px; border-radius: 4px; white-space: nowrap; }

/* --- Indikator tenggat --------------------------------------------------- */
/* Bentuknya diberi lebar tetap supaya tiga baris berturut-turut rata kiri; tanpa ini
   kotak/segitiga/lingkaran punya lebar berbeda dan kolomnya bergerigi. */
.ind { display: inline-flex; align-items: center; gap: 8px; font-size: var(--t-meta);
  font-variant-numeric: tabular-nums; }
.ind > .bentuk { flex: 0 0 14px; display: grid; place-items: center; }
.ind.aman { color: #554E48; }
.ind.dekat { color: var(--kuning-tua); font-weight: 700; }
.ind.terlambat { color: var(--merah); font-weight: 700; }

/* Nama langkah wizard. Bilah segmen di atasnya hanya bentuk — bentuk saja tidak
   memberi tahu warga sedang berada di langkah mana. */
.judul-wizard { font-size: var(--t-l); margin: 0 0 14px; }
.nama-langkah { margin: 0 0 20px; font-size: var(--t-kecil); color: var(--tinta-3); }
.nama-langkah strong { color: var(--merah); font-variant-numeric: tabular-nums; }
/* Wajib/tidak wajib ditandai DI LABEL, bukan lewat tanda bintang yang harus ditebak. */
.field .wajib, .field .opsional { font-style: normal; font-weight: 500; font-size: var(--t-meta); }
.field .wajib { color: var(--merah); }
.field .opsional { color: var(--tinta-3); }
.rahasia-card strong { display: flex; align-items: center; gap: 8px; font-size: var(--t-s); color: var(--tinta); }
/* Kalimat-hasil: perbedaan antara dua mode harus terbaca sebagai AKIBAT, bukan sebagai
   dua nama yang kebetulan bersinonim. */
.hasil-pilihan { display: block; margin: 8px 0 6px; font-weight: 700; font-size: var(--t-isi); color: var(--tinta); }
.rahasia-card ul { margin: 0; padding-left: 18px; }
.rahasia-card li { font-size: var(--t-kecil); color: var(--tinta-2); margin-bottom: 4px; }
.badge-saran { font-size: var(--t-eyebrow); font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  background: var(--merah-samar); color: var(--merah-tua); border: 1px solid var(--merah); padding: 3px 7px; border-radius: 4px; }
.landasan { border-top: 1px solid var(--garis); padding-top: 12px; margin-top: 18px; }

/* Kotak kode OTP. Tetap SATU input bernama `kode` — enam kotak terpisah tidak bisa
   menyatu jadi satu nilai tanpa JavaScript, dan mematikan autofill kode sekali-pakai
   dari email/SMS. Kesan "enam kotak" dibuat dari jarak antar huruf, bukan enam field. */
.kotak-kode { font-size: 26px; letter-spacing: .5em; text-align: center; padding-left: .5em; min-height: 60px; }
.jalan-keluar { border-top: 1px solid var(--garis); padding-top: 14px; margin-top: 18px; }

/* --- Terkirim ------------------------------------------------------------ */
/* Kepala berwarna berbeda per mode: konsekuensi memilih Anonim Penuh harus terasa
   sejak detik pertama, bukan setelah membaca paragraf. */
.kepala-terkirim { padding: 20px; border-radius: var(--r); margin-bottom: 18px; }
.kepala-terkirim .eyebrow { color: inherit; opacity: .85; }
.kepala-terkirim h1 { color: inherit; margin: 6px 0 0; }
.kepala-terkirim.rahasia { background: var(--merah); color: var(--putih); }
.kepala-terkirim.anonim { background: var(--tinta); color: var(--putih); }
.tiket-besar { font-family: 'IBM Plex Mono', monospace; font-weight: 600; font-size: 32px;
  letter-spacing: .05em; background: var(--putih); border: 1.5px dashed var(--garis-input);
  border-radius: var(--r); padding: 20px 24px; margin: 16px auto; display: inline-block; color: var(--tinta); }

/* --- Detail & timeline --------------------------------------------------- */
.kembali, .tautan-kembali { display: inline-flex; align-items: center; min-height: 44px; margin-bottom: 8px; text-decoration: none; font-weight: 600; }
.detail-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding-bottom: 14px; border-bottom: 1px solid var(--garis); }
.kode-besar { font-family: 'IBM Plex Mono', monospace; font-weight: 600; font-size: 19px; letter-spacing: .04em; }
.detail-isi { font-size: var(--t-isi); color: var(--tinta-2); max-width: 66ch; }
.timeline { list-style: none; padding: 0; margin: 18px 0; border-left: 2px solid var(--garis); }
.tl-item { display: flex; gap: 12px; padding: 0 0 20px 18px; margin-left: 7px; }
.tl-nomor { flex: 0 0 auto; width: 14px; height: 14px; border-radius: 50%; background: var(--merah);
  color: transparent; font-size: 0; display: grid; place-items: center; margin-left: -26px; margin-top: 5px; }
.tl-item.berjalan .tl-nomor { background: var(--putih); box-shadow: 0 0 0 4px var(--merah); }
.tl-status { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* --- Foto ---------------------------------------------------------------- */
.galeri { display: flex; gap: 10px; flex-wrap: wrap; margin: 14px 0; }
.galeri-item { margin: 0; display: flex; flex-direction: column; align-items: stretch; }
.galeri a { display: block; line-height: 0; border-radius: var(--r); overflow: hidden; border: 1px solid var(--garis); }
.galeri img { width: 160px; height: 120px; object-fit: cover; display: block; }
.sel-foto { width: 68px; }
.foto-mini { width: 56px; height: 56px; object-fit: cover; border-radius: 4px; display: block;
  border: 1px solid var(--garis); background: var(--permukaan-2); }
.tanpa-foto { display: inline-block; width: 56px; text-align: center; color: var(--tinta-3); }

/* Keadaan gagal saat sumber dari CDN tidak bisa dimuat */
.peta-gagal { display: flex; align-items: center; justify-content: center; text-align: center;
  padding: 20px; border: 1px dashed var(--garis-input); border-radius: var(--r);
  /* Teks yang memuat INSTRUKSI ("cukup tulis patokan lokasinya") tidak boleh mengecil —
     ukuran kecil hanya untuk meta murni seperti tanggal dan hitungan. */
  background: var(--permukaan); color: var(--tinta-3); font-size: var(--t-isi); line-height: 1.5; }
.peta-gagal p { margin: 0; }
.tabel-cadangan td { padding: 10px 12px; }

/* --- Cek tiket & filter -------------------------------------------------- */
.cek, .filter { display: flex; gap: 12px; flex-wrap: wrap; margin: 16px 0; align-items: flex-end; }
.cek .field, .filter .field { margin: 0; flex: 1 1 200px; }
.filter select { width: 100%; }
.hasil-cek { margin-top: 20px; display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
input.galat, input.galat:focus { border-color: var(--merah); box-shadow: inset 0 0 0 1px var(--merah); }

/* Saringan tampil TERBUKA, bukan di balik tombol yang harus diklik dulu.
   Penyaring yang disembunyikan sama saja dengan penyaring yang tidak ada: warga tidak
   tahu ia bisa menyaring, jadi ia menggulir seluruh daftar atau menyerah. Tiga pilihan
   ini juga sekaligus memberi tahu APA yang bisa disaring — kategori, wilayah, status —
   yang tak akan pernah terbaca kalau tertutup. */
.saring { border: 1px solid var(--garis); border-radius: var(--r); margin: 16px 0; padding: 16px; }
.saring > .filter { margin: 0; }
.chip-baris { margin: 18px 0 14px;  display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0; }
/* Seluruh chip adalah tombol pelepasnya, bukan hanya glyph × yang mungil. */
.chip { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 14px;
  background: var(--tinta); color: var(--putih); border-radius: var(--r); text-decoration: none;
  font-size: var(--t-label); font-weight: 600; }
.chip:hover { background: var(--merah); color: var(--putih); }
.chip-bersih { background: var(--putih); color: var(--tinta); border: 1px solid var(--garis-kuat); }
.chip-bersih:hover { background: var(--permukaan-2); color: var(--tinta); }
/* Baris hitung adalah JUDUL bagi daftar di bawahnya, bukan blok berdiri sendiri:
   jaraknya dirapatkan ke daftarnya dan dilebarkan dari saringan di atasnya, supaya
   terbaca "hasil dari saringan tadi" dan bukan sebagai kalimat yang mengambang. */
.baris-hitung { margin: 18px 0 8px; color: var(--tinta-2); }
.baris-hitung strong { font-variant-numeric: tabular-nums; }
/* Blok ini dirender DI DALAM `.grid-kartu`, yang punya bingkai dan sudut membulat.
   Tanpa padding mendatar teksnya menempel persis ke garis bingkainya — dan padding
   mendatarnya disamakan dengan `.kartu` supaya keadaan kosong berdiri di garis tepi yang
   sama dengan keadaan berisi. */
.kosong-blok { padding: 28px 16px; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.kosong-blok p { margin: 0; color: var(--tinta-2); }

/* --- Beranda: kotak kepercayaan, blok lacak, blok angka ------------------ */
/* Janji kerahasiaan tepat di bawah kartu aksi — tempat keraguan warga muncul, persis
   sesudah ia melihat tombol kirim. Di atas hero merah, dasarnya putih transparan. */
.kotak-percaya { margin: 18px auto 0; padding: 12px 16px; max-width: 54ch;
  background: rgba(255, 255, 255, .13); border: 1px solid rgba(255, 255, 255, .26);
  border-radius: var(--r); font-size: var(--t-kecil); color: var(--putih); }
.kotak-percaya strong { color: var(--putih); }
/* Blok yang sama bila muncul di halaman berlatar putih. */
.wrap .kotak-percaya { background: var(--merah-samar); border: 0; border-left: 3px solid var(--merah);
  border-radius: 0 var(--r) var(--r) 0; color: var(--tinta-2); }
.wrap .kotak-percaya strong { color: var(--tinta); }

/* --- Detail publik ------------------------------------------------------- */
.tahap { margin-left: auto; }
.tabel-meta { width: 100%; border-collapse: collapse; margin: 18px 0; border: 1px solid var(--garis); }
.tabel-meta th, .tabel-meta td { text-align: left; padding: 11px 13px; border-bottom: 1px solid var(--garis);
  font-size: var(--t-kecil); vertical-align: top; }
.tabel-meta tr:last-child th, .tabel-meta tr:last-child td { border-bottom: 0; }
.tabel-meta th { width: 38%; font-weight: 600; color: var(--tinta-3); }
/* Baris identitas diberi latar sendiri: frasa "sengaja disamarkan" itu yang mencegah
   warga mengira datanya hilang atau sistemnya gagal menyimpan. */
.baris-samar td { background: var(--permukaan); }
.kotak-jelas { border: 1px solid var(--garis); border-left: 3px solid var(--merah);
  border-radius: 0 var(--r) var(--r) 0; padding: 16px 18px; margin: 18px 0; background: var(--putih); }
.kotak-jelas h3 { margin: 0 0 6px; }
.kotak-jelas p { margin: 0 0 8px; font-size: var(--t-kecil); color: var(--tinta-2); }
.kotak-jelas p:last-child { margin-bottom: 0; }
.target-waktu { margin: 12px 0 0; }
.kotak-eskalasi { margin: 18px 0; padding: 16px 18px; background: var(--permukaan);
  border: 1px solid var(--garis); border-radius: var(--r); }
.kotak-eskalasi p { margin: 0; font-size: var(--t-kecil); color: var(--tinta-2); }

/* --- Statistik ----------------------------------------------------------- */
.chart-grid, .rekap-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.chart-box { background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r); padding: 18px; }

/* --- Grafik bar (HTML/CSS, bukan library) -------------------------------- */
/* Angka SELALU ditulis di samping batang: panjang batang memberi kesan besaran, tapi
   tidak bisa dibaca persis — dan angka persislah yang dicari petugas. */
.bar-daftar { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.bar-daftar li { display: grid; grid-template-columns: minmax(90px, 30%) 1fr auto; align-items: center; gap: 10px; }
.bar-label { font-size: var(--t-kecil); color: var(--tinta-2); }
.bar-jalur { height: 12px; background: var(--permukaan-2); border-radius: 2px; overflow: hidden; }
.bar-isi { display: block; height: 100%; background: var(--merah); border-radius: 2px; min-width: 2px; }
.bar-nilai { font-weight: 700; font-variant-numeric: tabular-nums; color: var(--tinta); }

/* Tren enam bulan: batang vertikal, bulan berjalan ditandai merah. */
.tren { list-style: none; margin: 0 0 24px; padding: 0; display: grid;
  grid-template-columns: repeat(6, 1fr); gap: 10px; align-items: end; height: 170px; }
.tren li { display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  gap: 6px; height: 100%; }
.tren-batang { width: 100%; max-width: 54px; background: var(--garis); border-radius: 2px 2px 0 0; min-height: 3px; order: 2; }
.tren-batang.berjalan { background: var(--merah); }
.tren-nilai { order: 1; font-weight: 700; font-size: var(--t-meta); font-variant-numeric: tabular-nums; color: var(--tinta); }
.tren-label { order: 3; font-size: var(--t-meta); color: var(--tinta-3); }

/* --- KPI rekap ----------------------------------------------------------- */
.kpi-baris { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; margin: 20px 0 10px; }
.kpi { border: 1px solid var(--garis); border-radius: var(--r); padding: 18px; background: var(--putih);
  display: flex; flex-direction: column; gap: 4px; }
/* Satu angka yang dicari Lurah lebih dulu, jadi ia yang diberi bidang merah. */
.kpi-utama { background: var(--merah-samar); border-color: var(--merah); }
.kpi-label { font-size: var(--t-meta); color: var(--tinta-3); }
.kpi-angka { font-family: 'Bricolage Grotesque', sans-serif; font-weight: 800; font-size: 38px;
  line-height: 1; letter-spacing: -.03em; color: var(--tinta); font-variant-numeric: tabular-nums; }
.kpi-utama .kpi-angka { color: var(--merah-tua); }
/* Penyebutnya wajib ikut: "78%" tanpa "14 dari 18" tidak bisa dipertanggungjawabkan
   saat Lurah bertanya balik dari mana angkanya. */
.kpi-sebut { font-size: var(--t-meta); color: var(--tinta-2); }
.banding { font-size: var(--t-meta); color: var(--tinta-3); }
.aksi-ekspor { margin: 24px 0; }

/* --- Panel: tab & tabel -------------------------------------------------- */
.tabs { display: flex; gap: 4px; margin: 16px 0; flex-wrap: wrap; }
.tab { display: flex; align-items: center; gap: 8px; padding: 11px 14px; min-height: 44px;
  text-decoration: none; background: var(--putih); color: var(--tinta-3); font-weight: 600;
  font-size: var(--t-kecil); border: 1px solid var(--garis); border-radius: var(--r); }
.tab:hover { background: var(--permukaan); color: var(--tinta); }
.tab.on { background: var(--tinta); color: var(--putih); border-color: var(--tinta); }
.tabel { width: 100%; border-collapse: collapse; background: var(--putih); border: 1px solid var(--garis); }
.tabel th, .tabel td { text-align: left; padding: 12px; border-bottom: 1px solid var(--garis); font-size: var(--t-kecil); }
.tabel th { font-family: 'IBM Plex Mono', monospace; font-weight: 600; font-size: var(--t-eyebrow);
  letter-spacing: .12em; text-transform: uppercase; background: var(--permukaan); color: var(--tinta-3); }
.tabel tbody tr { cursor: pointer; }
.tabel tbody tr:hover { background: var(--permukaan); }

/* --- Panel: kotak masuk -------------------------------------------------- */
.cari-panel { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; margin: 16px 0; }
.cari-panel .field { margin: 0; }
.cari-panel .field:first-of-type { flex: 2 1 260px; }
.cari-panel .field { flex: 1 1 150px; }
.sel-kode, .sel-laporan { display: table-cell; }
.sel-kode a, .sel-kode .meta { display: block; }
.tautan-baris { font-weight: 600; text-decoration: none; }
.isi-ringkas { display: block; color: var(--tinta-2); }
.sel-laporan .meta { display: block; margin-top: 3px; }

/* --- Panel: identitas & kotak aksi --------------------------------------- */
.identitas { background: var(--merah-samar); border: 1px solid var(--merah); border-radius: var(--r);
  margin: 16px 0; overflow: hidden; }
/* Kepala merah solid: membuka blok ini adalah tindakan yang tercatat, dan petugas
   berhak tahu itu SEBELUM membacanya — bukan cuma tercatat diam-diam. */
.identitas-kepala { background: var(--merah); color: var(--putih); padding: 10px 16px;
  display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline; }
.identitas > :not(.identitas-kepala) { margin: 10px 16px; }
.identitas .btn { margin: 12px 16px 14px; }
.label-terbatas { display: block; font-weight: 700; font-size: var(--t-eyebrow); letter-spacing: .1em;
  text-transform: uppercase; color: var(--putih); margin: 0; }
.identitas-catat { font-size: var(--t-meta); color: rgba(255,255,255,.85); }
.identitas-nama { font-size: var(--t-s); }

/* Riwayat: waktu di kolom kiri berlebar tetap supaya mata bisa memindainya menurun. */
.tabel-riwayat td { vertical-align: top; }
.waktu-riwayat { width: 150px; white-space: nowrap; color: var(--tinta-3); }
.catatan-riwayat { margin: 6px 0 0; padding-left: 12px; border-left: 2px solid var(--garis);
  color: var(--tinta-2); font-size: var(--t-kecil); }
.akses-lipat { margin: 12px 0; border: 1px solid var(--garis); border-radius: var(--r); }
.akses-lipat > summary { padding: 12px 14px; min-height: 44px; display: flex; align-items: center;
  cursor: pointer; font-size: var(--t-kecil); color: var(--tinta-3); }
.akses-lipat .tabel { border: 0; border-top: 1px solid var(--garis); }
.aksi-box { background: var(--permukaan); border: 1px solid var(--garis); border-radius: var(--r);
  padding: 18px; margin: 16px 0; }
.form-status { margin: 0; padding: 0; max-width: none; }
.form-status > * { margin-top: 12px; }
.riwayat { padding-left: 18px; }
.riwayat li { margin-bottom: 10px; font-size: var(--t-kecil); }
/* Tombol aksi di baris tabel dibuat seragam tingginya supaya barisnya tidak bergerigi. */
.sel-aksi { display: flex; gap: 8px; align-items: flex-start; flex-wrap: wrap; }
.sel-aksi .btn, .sel-aksi .btn-hapus, .aksi-lipat > summary { min-height: 38px; padding: 8px 12px; font-size: var(--t-label); }
.form-aksi { margin: 0; }
.aksi-lipat { border: 1px solid var(--garis-kuat); border-radius: var(--r); }
.aksi-lipat > summary { display: flex; align-items: center; cursor: pointer; font-weight: 600;
  font-size: var(--t-label); white-space: nowrap; }
.aksi-lipat[open] { border-color: var(--merah); }
.aksi-lipat .form-reset, .aksi-lipat .form-wilayah {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 0 12px 12px; margin: 0; max-width: 340px;
}
.aksi-lipat input, .aksi-lipat select { width: auto; min-width: 130px; min-height: 38px; padding: 8px 10px; }
.aksi-lipat .form-wilayah input { min-width: 90px; }
.aksi-lipat .hint { flex: 1 1 100%; margin: 0; }

/* --- Hapus & pulihkan ---------------------------------------------------- */
.tumpuk-hapus { display: flex; flex-direction: column; gap: 10px; margin: 18px 0 6px; }
.kartu-hapus { display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 16px 18px; border: 1px solid var(--merah); border-left: 3px solid var(--merah);
  border-radius: 0 var(--r) var(--r) 0; background: var(--merah-samar); }
.kartu-hapus-judul { margin: 0; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  font-size: var(--t-eyebrow); color: var(--merah-tua); }
.kartu-hapus-objek { margin: 4px 0 2px; font-weight: 600; font-size: var(--t-s); color: var(--tinta); }
.kartu-hapus .meta { margin: 0; }
.kartu-hapus-aksi { display: flex; gap: 10px; }
.kartu-hapus-aksi form { margin: 0; }
.btn-hapus { background: var(--putih); color: var(--merah-tua); border: 1px solid var(--merah);
  padding: 10px 14px; min-height: 44px; font: 600 var(--t-label) 'Instrument Sans', sans-serif;
  border-radius: var(--r); cursor: pointer; }
.btn-hapus:hover { background: var(--merah-tua); color: var(--putih); border-color: var(--merah-tua); }
.zona-bahaya { margin-top: 32px; padding: 18px; border: 1px solid var(--merah); border-radius: var(--r); background: var(--putih); }
.zona-bahaya .label-seksi { margin-top: 0; color: var(--merah-tua); }

/* --- Navigasi bawah (layar kecil) ---------------------------------------- */
/* Ikon digambar dengan border CSS — tanpa pustaka ikon, tanpa emoji. Setiap item tetap
   membawa label teks: bentuk geometris saja tidak cukup untuk dikenali, apalagi oleh
   warga yang jarang memakai aplikasi. */
.nav-bawah { display: none; }
.nb-ikon { position: relative; display: block; width: 21px; height: 21px; }
.nb-beranda::before { content: ''; position: absolute; left: 50%; top: 1px; transform: translateX(-50%);
  border-left: 9px solid transparent; border-right: 9px solid transparent; border-bottom: 8px solid currentColor; }
.nb-beranda::after { content: ''; position: absolute; left: 3px; right: 3px; top: 9px; bottom: 2px;
  border: 2.5px solid currentColor; border-top: 0; }
.nb-lapor::before { content: ''; position: absolute; left: 50%; top: 2px; bottom: 2px; width: 2.5px;
  transform: translateX(-50%); background: currentColor; }
.nb-lapor::after { content: ''; position: absolute; top: 50%; left: 2px; right: 2px; height: 2.5px;
  transform: translateY(-50%); background: currentColor; }
.nb-telusuri::before { content: ''; position: absolute; left: 1px; top: 1px; width: 13px; height: 13px;
  border: 2.5px solid currentColor; border-radius: 50%; }
.nb-telusuri::after { content: ''; position: absolute; right: 2px; bottom: 2px; width: 8px; height: 2.5px;
  background: currentColor; transform: rotate(45deg); transform-origin: right center; }
.nb-berita::before { content: ''; position: absolute; left: 2px; right: 2px; top: 1px; bottom: 1px;
  border: 2.5px solid currentColor; }
.nb-berita::after { content: ''; position: absolute; left: 6px; right: 6px; top: 6px; height: 2.5px;
  background: currentColor; box-shadow: 0 5px 0 currentColor; }
.nb-saya::before { content: ''; position: absolute; left: 50%; top: 1px; transform: translateX(-50%);
  width: 9px; height: 9px; border: 2.5px solid currentColor; border-radius: 50%; }
.nb-saya::after { content: ''; position: absolute; left: 2px; right: 2px; bottom: 2px; height: 8px;
  border: 2.5px solid currentColor; border-bottom: 0; border-radius: 9px 9px 0 0; }

/* --- Banner tanpa sambungan ---------------------------------------------- */
/* Menempel di atas layar supaya terbaca kapan pun sinyal putus, termasuk saat warga
   sedang mengisi wizard di tengah halaman. */
.banner-offline { position: fixed; top: 0; left: 0; right: 0; z-index: 40;
  background: var(--kuning-tua); color: var(--putih); padding: 11px 16px;
  font-size: var(--t-kecil); line-height: 1.45; }
.banner-offline[hidden] { display: none; }

/* --- Footer -------------------------------------------------------------- */
/* Footer sedikit lebih gelap dari dasar halaman — bukan garis tipis, melainkan bidang
   yang benar-benar MENUTUP halaman. Di layanan publik, footer adalah tempat warga
   mencari alamat dan nomor telepon saat aplikasinya gagal menolong; ia harus terlihat
   sebagai bagian yang berdiri sendiri, bukan sisa halaman. */
.footer { background: var(--dasar-tua); color: var(--tinta-2); border-top: 1px solid var(--garis-kuat);
  padding: 28px 20px; display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap;
  font-size: var(--t-kecil); margin-top: 48px; }
.footer a { color: var(--merah-tua); }
.footer-utama, .footer-note { display: flex; flex-direction: column; gap: 3px; }
.footer-utama strong { font-size: var(--t-isi); color: var(--tinta); }
.footer-resmi { color: var(--tinta-2); }
/* --tinta-redup adalah lantai kontras di atas PUTIH (4,73:1). Footer berlatar
   --permukaan yang sedikit lebih gelap, dan di sana nilainya turun ke 4,46:1 — lolos
   sekilas, gagal WCAG AA. Teks di atas permukaan bertinta memakai --tinta-3. */
.footer-note { color: var(--tinta-3); text-align: right; align-items: flex-end; max-width: 46ch; }

/* --- Beranda (bentuk lama) ------------------------------------------------
   Blok-blok di bawah masih dirender views.js sampai beranda() ditulis ulang di fase
   berikutnya. Gayanya diratakan ke sistem baru — bukan dihapus — supaya tidak ada
   halaman yang kehilangan tata letaknya di antara dua commit. */
/* Hero merah. Ini wajah kanal — bidang berwarna penuh yang langsung menyatakan
   "layanan resmi", dan satu-satunya tempat gradasi dibiarkan hidup di seluruh sistem.
   Sudut bawahnya membulat DAN latar di belakangnya putih, jadi tidak ada takik seperti
   pada bilah atas: bidang merahnya berakhir di lengkungan itu sendiri. */
.beranda-hero {
  position: relative; overflow: hidden; color: var(--putih); text-align: center;
  padding: clamp(30px, 6vw, 62px) clamp(16px, 4vw, 40px) clamp(34px, 6vw, 58px);
  border-radius: 0 0 clamp(20px, 4vw, 36px) clamp(20px, 4vw, 36px);
  background:
    radial-gradient(120% 120% at 12% 0%, rgba(216, 35, 42, .62), transparent 55%),
    radial-gradient(120% 120% at 100% 100%, rgba(90, 10, 16, .92), transparent 60%),
    linear-gradient(160deg, #C81A28 0%, var(--merah) 48%, #6E0C12 100%);
}
/* Dua lingkaran tipis — satu-satunya hiasan yang dipertahankan. Ia memberi kedalaman
   pada bidang merah yang lebar tanpa menambah satu pun elemen yang harus dibaca. */
.beranda-hero::before, .beranda-hero::after {
  content: ''; position: absolute; border-radius: 50%; pointer-events: none;
}
.beranda-hero::before { width: 320px; height: 320px; top: -140px; right: -80px;
  border: 2px solid rgba(255, 255, 255, .12); }
.beranda-hero::after { width: 220px; height: 220px; bottom: -120px; left: -60px;
  background: rgba(255, 255, 255, .06); }
.hero-inner { position: relative; max-width: 820px; margin: 0 auto; }
.hero-eyebrow { display: inline-flex; align-items: center; gap: 9px;
  font-family: 'IBM Plex Mono', monospace; font-weight: 600; font-size: var(--t-eyebrow);
  letter-spacing: .15em; text-transform: uppercase; color: var(--putih);
  background: rgba(255, 255, 255, .15); border: 1px solid rgba(255, 255, 255, .3);
  padding: 7px 15px; border-radius: 999px; }
/* Titik penanda: statis, bukan berdenyut. Denyut menarik mata terus-menerus tanpa
   menyampaikan apa pun, dan mengganggu pembaca yang peka gerak. */
.pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--putih); flex: 0 0 8px; }
@media (prefers-reduced-motion: reduce) { .pulse { animation: none; } }
.beranda-hero h1 { font-size: clamp(2rem, 6.5vw, 3.1rem); line-height: 1.04; letter-spacing: -.035em;
  margin: 18px auto 12px; max-width: 17ch; color: var(--putih); text-wrap: balance; }
/* Sorotan pada kata kunci. Latar putih transparan di atas merah — bukan warna teks,
   supaya tetap terbaca saat gradasi di belakangnya berubah gelap. */
.hi-sorot { background: rgba(255, 255, 255, .2); padding: 0 .3em; border-radius: 8px;
  box-decoration-break: clone; -webkit-box-decoration-break: clone; }
.hero-lead { font-size: clamp(1rem, 2.6vw, 1.15rem); color: rgba(255, 255, 255, .95);
  max-width: 46ch; margin: 0 auto; text-wrap: pretty; }
.hero { max-width: 1024px; margin: 0 auto; padding: 32px 20px 8px; }
.hero h1 { margin: 8px 0 12px; max-width: 18ch; }
.hero-cta { display: flex; gap: 12px; flex-wrap: wrap; margin: 20px 0; }
/* Kartu aksi putih di atas hero merah: dua jalan utama warga — membuat laporan baru,
   atau melacak yang sudah dikirim — diangkat jadi satu bidang terang yang tak mungkin
   terlewat. Bayangannya fungsional, bukan hiasan: ia yang memisahkan kartu dari merah
   di belakangnya. */
.act-card { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-end; text-align: left;
  background: var(--putih); border-radius: 12px; padding: 16px;
  margin: clamp(22px, 4vw, 30px) auto 0; max-width: 640px;
  box-shadow: 0 16px 36px rgba(80, 8, 14, .3); }
.act-utama { white-space: nowrap; flex: 0 0 auto; }
/* Pertanyaan dipindah ke label di atas input. Sebelumnya ikut jadi placeholder
   ("Sudah pernah lapor? Masukkan kode tiket") dan terpotong di layar 390px,
   sehingga justru tidak terbaca. Placeholder kini mengajarkan formatnya. */
.act-cek { display: flex; flex-direction: column; gap: 6px; flex: 1 1 260px; min-width: 220px; }
.act-cek-label { font-size: var(--t-label); font-weight: 700; color: var(--tinta); }
.act-cek-baris { display: flex; gap: 8px; }
.act-cek input { width: 100%; font-family: 'IBM Plex Mono', monospace; font-weight: 600; letter-spacing: .05em; }
/* Statistik: angka display selalu DI ATAS labelnya. Di dalam hero merah, pemisahnya
   garis putih transparan — bukan garis abu yang tak akan terlihat di atas merah. */
.stats3, .capaian { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  margin-top: clamp(24px, 4vw, 34px); }
.stats3 div, .capaian div { display: flex; flex-direction: column; padding: 4px 14px;
  border-right: 1px solid rgba(255, 255, 255, .22); }
.stats3 div:last-child, .capaian div:last-child { border-right: 0; }
.stats3 strong, .capaian strong { font-family: 'Bricolage Grotesque', sans-serif; font-weight: 800;
  font-size: clamp(1.8rem, 5vw, 2.4rem); line-height: 1; letter-spacing: -.03em; color: var(--putih); }
/* .92 putih di atas merah tergelap hero masih 5,9:1 — di atas ambang AA. */
.stats3 span, .capaian span { font-size: var(--t-meta); color: rgba(255, 255, 255, .92); margin-top: 8px; }
.hero-periode { margin: 18px 0 0; font-size: var(--t-meta); color: rgba(255, 255, 255, .88); }
.hero-periode a { color: var(--putih); text-decoration: underline; }
/* Di luar hero (halaman statistik) blok yang sama kembali memakai tinta di atas putih. */
.wrap .stats3 div, .wrap .capaian div { border-right-color: var(--garis); }
.wrap .stats3 strong, .wrap .capaian strong { color: var(--tinta); }
.wrap .stats3 span, .wrap .capaian span { color: var(--tinta-3); }
.kat-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 9px; }
.tile { display: flex; align-items: center; gap: 10px; min-height: 56px; text-decoration: none; color: var(--tinta);
  background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r); padding: 13px 12px; }
.tile:hover { background: var(--permukaan); border-color: var(--garis-kuat); }
/* Glyph dekoratif dibuang: bentuk ▲ ■ ● sudah bermakna sebagai indikator tenggat,
   memakainya lagi sebagai hiasan kategori merusak maknanya. Diganti penanda kotak. */
.tile-ikon { flex: 0 0 8px; width: 8px; height: 8px; background: var(--merah);
  font-size: 0; color: transparent; border-radius: 0; }
.tile-nama { font-weight: 500; font-size: var(--t-kecil); line-height: 1.25; }
.langkah-wrap h2.tengah { margin-bottom: 18px; }
.langkah3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
.step-card { background: var(--putih); padding: 20px; border: 1px solid var(--garis); border-radius: var(--r); }
/* Nomor langkah memang berurutan — di sini penomoran mengangkut informasi (urutan yang
   harus dilalui warga), bukan sekadar hiasan struktur. */
.step-no { display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%;
  font-weight: 700; font-size: 15px; color: var(--putih); background: var(--merah); margin-bottom: 12px;
  font-variant-numeric: tabular-nums; }
.step-card p { color: var(--tinta-2); font-size: var(--t-kecil); }

/* --- Berita ------------------------------------------------------------ */
.berita-daftar { display: grid; gap: 16px; }
.berita-kartu { display: grid; grid-template-columns: 320px 1fr; gap: 16px; align-items: start;
  padding: 14px; background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r);
  text-decoration: none; color: inherit; }
.berita-kartu:hover { border-color: var(--merah); }
.berita-kartu.tanpa-gambar { grid-template-columns: 1fr; }
.berita-gambar { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--r); background: var(--dasar); }
.berita-judul { margin: 0 0 6px; font-size: 20px; line-height: 1.25; }
.berita-teaser { margin: 0 0 8px; color: var(--tinta-redup); }
.berita-meta { margin: 0; font-size: 14px; color: var(--tinta-redup); }
.berita-lengkap { max-width: 720px; }
.berita-utama { width: 100%; height: auto; border-radius: var(--r); margin: 16px 0; }
.berita-teks p { margin: 0 0 14px; line-height: 1.7; }
.berita-galeri { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.berita-galeri img { width: 100%; height: auto; border-radius: var(--r); }
.paginasi { display: flex; align-items: center; justify-content: center; gap: 12px; margin-top: 20px; }
.paginasi-posisi { color: var(--tinta-redup); font-size: 14px; }
/* Wadah beberapa foto pada formulir sunting berita, satu .foto-kelola per foto. */
.foto-grid { display: flex; flex-wrap: wrap; gap: 12px; }
.foto-kelola { display: grid; gap: 6px; justify-items: start; }

@media (max-width: 720px) {
  :root { --t-xl: 32px; --t-l: 24px; }
  /* Bilah jadi dua baris: identitas di atas, navigasi menggulir mendatar di bawahnya.
     Menggulir, bukan membungkus — tautan yang membungkus menumpuk setinggi tiga
     baris pada bilah yang MENEMPEL, dan memakan layar yang dibutuhkan isinya. Lima
     tujuan tersering tetap punya jalan pintas di navigasi bawah. */
  /* flex-wrap: nowrap WAJIB di sini. Aturan dasar .topbar memakai `wrap`, dan pada arah
     column `wrap` membuat wadahnya jadi banyak kolom — lebarnya lalu tumbuh mengikuti
     item terlebar (nav yang tidak membungkus), sehingga SELURUH halaman menggeser ke
     samping alih-alih navnya yang menggulir di dalam. */
  .topbar { padding: 10px 0 0; flex-direction: column; flex-wrap: nowrap;
    align-items: stretch; gap: 8px; }
  .topbar .brand { padding: 0 16px; }
  /* min-width: 0 WAJIB. Flex item bawaannya `min-width: auto` — ia menolak menyusut di
     bawah lebar isinya, sehingga `overflow-x: auto` tak pernah menyala: nav justru
     memaksa bilah melebar dan SELURUH halaman ikut menggeser ke samping. */
  .topbar nav { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    min-width: 0; padding: 0 16px 8px; gap: 4px; scrollbar-width: none; }
  .topbar nav::-webkit-scrollbar { display: none; }
  .topbar nav > a:not(.btn) { white-space: nowrap; padding: 9px 10px; min-height: 40px; font-size: 14.5px; }
  .topbar nav > .btn-primary { white-space: nowrap; margin-left: 4px; min-height: 40px; padding: 9px 14px; }
  .footer-note { text-align: left; align-items: flex-start; }

  /* Navigasi bawah menempel di tepi layar. Halaman diberi ruang di bawah supaya isinya
     tidak pernah tertutup bilah ini. */
  .nav-bawah { display: grid; grid-template-columns: repeat(5, 1fr); position: sticky; bottom: 0; z-index: 30;
    background: var(--putih); border-top: 1px solid var(--garis); }
  .nav-bawah a { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
    min-height: 56px; padding: 8px 4px; text-decoration: none; color: var(--tinta-3); }
  .nav-bawah a.on { color: var(--merah); box-shadow: inset 0 3px 0 var(--merah); }
  .nav-bawah a.on .nb-label { font-weight: 700; }
  .nb-label { font-size: 11.5px; line-height: 1; }
  body { padding-bottom: 0; }
  .footer { margin-bottom: 0; }
  .row, .rahasia-cards, .chart-grid, .rekap-grid, .kat-grid { grid-template-columns: 1fr; }
  .footer, .footer-note { text-align: left; }
  .act-cek { flex: 1 1 100%; }
  .wrap, .wrap-full { padding: 20px 16px; }
  .galeri img { width: 130px; height: 98px; }
  /* Tabel panel lebih lebar dari layar HP (tujuh kolom). Yang menggulir harus TABELNYA,
     bukan seluruh halaman — halaman yang bergeser ke samping membuat tombol dan teks
     ikut lari dari layar. Kotak masuk akan berubah jadi daftar kartu di fase panel;
     sampai itu, ini yang menahan agar badan halaman tidak pernah menggulir horizontal. */
  .tabel { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tabs { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 4px; }
  .tab { white-space: nowrap; }
  .berita-kartu { grid-template-columns: 1fr; }
}

/* --- Batang bersegmen: aduan vs kegiatan --------------------------------- */
/* Dua segmen berdampingan dalam satu jalur. Segmen kegiatan diberi garis miring SELAIN
   warna — sebagian orang tidak membedakan merah dari abu-abu, dan invariant proyek
   melarang warna jadi satu-satunya pembeda. Angka dan labelnya tetap ada sebagai teks. */
/* Batang bersegmen memakai baris DUA TINGKAT, bukan grid tiga kolom seperti batang
   tunggal. Alasannya terukur: `.bar-daftar li` adalah grid `minmax(90px,30%) | 1fr | auto`,
   dan nilai di sini berupa kalimat ("2 aduan · 0 kegiatan"), bukan satu angka. Kalimat itu
   merebut kolom `auto`, label terjepit ke 90px lalu membungkus dua baris, dan jalurnya
   tersisa sempit. Label dan angka karena itu berbagi satu baris penuh, batangnya sendiri
   di baris bawah selebar kotak. */
.bar-tumpuk { gap: 18px; }
.bar-tumpuk li { display: block; }
.bar-kepala { display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 6px; }
.bar-tumpuk .bar-label { color: var(--tinta); font-weight: 600; }

/* Angka disetel sebagai LAJUR ANGKA: mono bertabular figures, angkanya tebal dan satuannya
   kecil-tenang. Dibaca menurun, kolom kanan terbaca seperti neraca — dan itu memang
   bentuk yang dicari orang di halaman transparansi kelurahan. */
.bar-tumpuk .bar-nilai { display: flex; gap: 8px; font-weight: 400;
  font-family: 'IBM Plex Mono', monospace; font-size: var(--t-meta);
  color: var(--tinta-3); white-space: nowrap; }
.bar-tumpuk .bar-nilai b { font-weight: 600; color: var(--tinta); font-variant-numeric: tabular-nums; }
.bar-tumpuk .bar-nilai .nol b { color: var(--tinta-3); font-weight: 400; }
.hitung-kosong { font-style: italic; color: var(--tinta-3); }
.hitung-pisah { color: var(--garis-input, var(--tinta-3)); }

.bar-tumpuk .bar-jalur { display: flex; height: 10px; }
/* Merah = aduan (warna status "Diproses"), hijau = kegiatan (warna status "Selesai").
   Keduanya token yang SUDAH dipakai badge status di seluruh aplikasi, bukan warna baru —
   dan pasangannya bermakna: aduan adalah masalah, kegiatan adalah sesuatu yang sudah
   dikerjakan.

   Tidak ada arsiran. Versi sebelumnya memakai abu bergaris miring sebagai pembeda
   non-warna, tetapi hasilnya terbaca seperti area kosong yang rusak, bukan data.
   Invariant "warna bukan satu-satunya pembeda" tetap dipenuhi lewat jalur yang sama
   dengan badge status di aplikasi ini: setiap segmen membawa angka dan namanya sebagai
   teks ("2 aduan · 0 kegiatan"), dan keterangannya bertulisan. */
.seg-aduan { background: var(--merah); }
.seg-kegiatan { background: var(--hijau-tua); }
/* Celah putih memisahkan kedua segmen. Ini BUKAN hiasan, melainkan satu-satunya pembeda
   di dalam batang yang tidak bergantung warna — dan ia memikul beban itu karena diukur:
   luminansi #B81622 dan #1F6B3A nyaris sama persis (rasio 1,01), jadi bagi penyandang
   buta warna merah-hijau kedua segmen menyatu menjadi satu batang abu tanpa batas.
   Lebarnya 3px, bukan 1px: pada batang setinggi 10px, satu piksel terlalu halus untuk
   dilihat sebagai batas. */
.seg-kegiatan:not(.seg-kosong) { box-shadow: inset 3px 0 0 var(--putih); }

.bar-legenda { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: var(--t-meta); color: var(--tinta-2); margin: 0 0 16px; }
.bar-legenda .kunci { width: 14px; height: 14px; border-radius: 3px; display: inline-block;
  flex: 0 0 auto; }

/* Delapan baris dua tingkat butuh lebar; Per Status hanya lima batang pendek. */
.chart-lebar { grid-column: 1 / -1; }
@media (max-width: 720px) {
  .chart-grid, .rekap-grid { grid-template-columns: 1fr; }
  .bar-kepala { flex-wrap: wrap; gap: 2px; }
}

.bar-tumpuk .seg-kosong { min-width: 0; }

/* --- Pratinjau foto per kategori di statistik ---------------------------- */
/* Angka memberi tahu BERAPA; foto memberi tahu SEPERTI APA. Menyapu satu baris kategori
   memunculkan beberapa foto nyata dari kategori itu, sehingga "12 aduan Kebersihan"
   berubah dari statistik jadi sesuatu yang dikenali warga sebagai gang dekat rumahnya.

   `display: none` di luar kurungan hover: perangkat sentuh tidak pernah merender strip
   ini sama sekali, jadi gambarnya pun tidak diunduh. Baris statistik hanya 39px — strip
   yang selalu tampil akan membuat delapan kategori menjadi ~800px dan halaman ini justru
   lebih buruk di HP.

   Murni CSS: nol JavaScript, tidak bisa gagal dimuat. */
/* Seluruh baris kategori adalah tautan ke daftar laporan kategori itu. Ditulis sebagai
   <a> sungguhan, bukan penangan klik JavaScript: ia bisa dibuka di tab baru, disalin
   alamatnya, dijangkau tombol Tab, dan tetap bekerja saat skrip gagal dimuat. */
/* ANGKA-nya yang jadi tautan, bukan seluruh baris: yang diklik persis yang ditunjuk.
   Ditulis sebagai <a> sungguhan supaya bisa dibuka di tab baru dan dijangkau Tab. */
a.hitung { text-decoration: none; color: inherit; border-radius: 4px; padding: 2px 4px;
  margin: -2px -4px; }
a.hitung:hover { background: var(--merah-samar); text-decoration: underline;
  text-underline-offset: 3px; }

.bar-foto { display: none; }

@media (hover: hover) and (pointer: fine) {
  .bar-tumpuk li { position: relative; }
  .bar-foto {
    display: flex; gap: 6px; position: absolute; left: 0; top: calc(100% + 6px); z-index: 6;
    padding: 6px; background: var(--putih); border: 1px solid var(--garis);
    border-radius: var(--r); box-shadow: 0 10px 30px rgba(0, 0, 0, .18);
    opacity: 0; visibility: hidden; transform: translateY(-4px);
    transition: opacity .15s ease, transform .15s ease, visibility .15s;
  }
  .bar-tumpuk li:hover .bar-foto,
  .bar-tumpuk li:focus-within .bar-foto { opacity: 1; visibility: visible; transform: none; }
  .bar-foto-kotak { margin: 0; display: flex; flex-direction: column; gap: 4px; align-items: center;
    border-top: 3px solid var(--garis); padding-top: 5px; text-decoration: none; color: inherit; }
  .bar-foto-kotak:hover .bar-foto-item { border-color: var(--tinta-3); }
  .bar-foto-kotak:hover .bar-foto-label { text-decoration: underline; text-underline-offset: 2px; }
  /* Tepi berwarna MENGIKUTI segmen grafiknya, jadi mata langsung menghubungkan foto ini
     dengan batang yang mana. Labelnya tetap teks — warna sendirian tidak cukup. */
  .seg-tepi-aduan { border-top-color: var(--merah); }
  .seg-tepi-kegiatan { border-top-color: var(--hijau-tua); }
  .bar-foto-label { font-size: var(--t-eyebrow); letter-spacing: .06em;
    text-transform: uppercase; color: var(--tinta-3); font-weight: 600; }
  .bar-foto-item { width: 84px; height: 84px; object-fit: cover; border-radius: 4px;
    border: 1px solid var(--garis); display: block; }
  /* Kotak grafik tidak boleh memotong pratinjau yang menggantung di bawah barisnya. */
  .chart-box { overflow: visible; }
}

@media (prefers-reduced-motion: reduce) {
  .bar-foto { transition: none; }
}

/* --- Identitas di bilah publik ------------------------------------------- */
/* Menjawab satu pertanyaan yang dulu tak terjawab di halaman publik: "saya ini sedang
   siapa?". Sebelumnya bilah ini selalu menawarkan "Masuk", bahkan kepada orang yang
   sedang masuk — dan seorang Ketua RT yang membuka Halaman Publik dari navigasinya
   sendiri tampak baru saja dikeluarkan, tanpa jalan kembali.

   Perannya ditulis KECIL DI BAWAH nama, bukan disingkat jadi warna atau ikon: "Warga"
   dan "Ketua RT" membuka pintu yang berbeda, dan menebaknya salah berarti mengeklik
   ke tempat yang keliru. */
.whoami-tautan { display: inline-flex; flex-direction: column; line-height: 1.15;
  gap: 1px; white-space: nowrap; }
.whoami-peran { font-size: var(--t-eyebrow); letter-spacing: .08em; text-transform: uppercase;
  opacity: .72; font-weight: 600; }

/* `.whoami` sebuah <span> polos di antara tautan yang punya padding sendiri, sedangkan
   `.topbar nav` hanya ber-gap 2px — akibatnya ia menempel ke tombol Keluar di sebelahnya.
   Diberi ruang napasnya sendiri, bukan dengan melebarkan gap seluruh bilah. */
.whoami { padding: 0 10px 0 6px; }
  /* "+N lagi" berdiri sebagai kartu terakhir dengan tinggi yang sama, jadi barisnya tetap
     rata alih-alih ada teks kecil menggantung di ujungnya. */
  .bar-foto-sisa { width: 56px; height: 84px; display: flex; flex-direction: column;
    align-items: center; justify-content: center; text-align: center; align-self: flex-end;
    border: 1px dashed var(--garis-input); border-radius: 4px; font-size: var(--t-meta);
    color: var(--tinta-3); font-weight: 600; line-height: 1.2; }
/* Nama kategori sebagai tautan: target besar yang mengembalikan kemampuan "klik kategori,
   masuk ke daftarnya" — hilang saat tautan dipindah ke angkanya saja, dan angka adalah
   sasaran kecil yang mudah meleset. */
.bar-label-tautan { text-decoration: none; color: inherit; }
.bar-label-tautan:hover { text-decoration: underline; text-underline-offset: 3px; }
/* Segmen batang juga dapat diklik. Kursornya berubah supaya keterklikannya terbaca,
   dan sedikit menggelap saat disapu agar umpan baliknya jelas. */
a.bar-isi { cursor: pointer; }
a.seg-aduan:hover { background: var(--merah-tua); }
a.seg-kegiatan:hover { filter: brightness(.85); }

/* --- Rekap kegiatan per bulan (halaman /kegiatan) ------------------------- */
.rekap-kegiatan { border: 1px solid var(--garis); border-radius: var(--r);
  background: #fff; padding: 16px; margin: 0 0 20px; }
.rk-kepala { display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.rk-judul { margin: 0; font-size: 1.15rem; }
.rk-tahun { display: inline-block; min-width: 3.6ch; text-align: center; color: #fff;
  background: var(--merah); border-radius: var(--r); padding: 0 .5rem; transition: background .2s; }
.rk-tahun-form { display: flex; align-items: center; gap: 8px; }
.rk-tahun-form input[type=range] { accent-color: var(--merah); width: clamp(120px, 30vw, 220px); }
.rk-nav { display: inline-flex; align-items: center; justify-content: center; width: 34px;
  height: 34px; border: 1px solid var(--garis-kuat); border-radius: 50%; color: var(--merah);
  text-decoration: none; font-size: 1.3rem; line-height: 1; background: #fff; }
.rk-nav:hover { background: var(--merah-samar); }
.rk-nav[hidden] { visibility: hidden; }
.rk-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.rk-tabel { border-collapse: separate; border-spacing: 0; width: 100%; font-size: .92rem; }
.rk-tabel th, .rk-tabel td { padding: 8px 6px; text-align: center;
  border-bottom: 1px solid var(--garis); white-space: nowrap; }
.rk-tabel thead th { position: sticky; top: 0; background: var(--dasar); z-index: 2; font-weight: 600; }
.rk-tabel th.rk-asal { position: sticky; left: 0; z-index: 3; background: var(--dasar);
  text-align: left; min-width: 128px; }
.rk-tabel tbody th.rk-asal { z-index: 1; background: #fff; font-weight: 600; }
.rk-tabel tbody tr:hover th.rk-asal, .rk-tabel tbody tr:hover td { background: var(--dasar-tua); }
.rk-bln.kini, .rk-sel.kini { background: var(--merah-samar); }
.rk-sel.ada { color: var(--hijau-tua); font-weight: 700; letter-spacing: -1px; }
.rk-sel.ada .rk-tanda { display: inline-block; animation: rk-pop .35s ease both;
  animation-delay: calc(var(--i) * .03s); }
.rk-sel.nol { color: var(--tinta-redup); }
.rk-sel.nol::after { content: '·'; color: var(--garis-kuat); }
.rk-total { font-weight: 700; color: var(--tinta); background: var(--dasar); }
.rk-tabel tbody tr[data-total="0"] th.rk-asal { color: var(--tinta-redup); }
.rk-legenda { font-size: .82rem; color: var(--tinta-3); margin: 8px 0 0; }
.rk-tanda-legenda { color: var(--hijau-tua); font-weight: 700; }
@keyframes rk-pop { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .rk-sel.ada .rk-tanda { animation: none; } }

/* --- Logo merek di bilah atas (Home & panel) ------------------------------ */
/* Lingkaran putih di belakang logo: base logo berwarna merah, jadi tanpa alas
   putih ia tenggelam di bilah panel yang gelap. */
.topbar .brand { display: inline-flex; align-items: center; gap: 10px; }
.brand-logo { flex: none; width: 40px; height: 40px; border-radius: 50%;
  background: #fff; padding: 4px; object-fit: contain; box-shadow: 0 1px 4px rgba(20,24,29,.22); }
.panelbar .brand-logo { width: 34px; height: 34px; padding: 3px; }
