:root {
  --navy: #0B2545;
  --hijau: #1E8E5A;
  --oranye: #E08E00;
  --merah: #C62828;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at 20% 15%, #123563 0%, var(--navy) 45%, #061729 100%);
  font-family: -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  padding: 16px;
}

.kartu {
  position: relative;
  background: #fff;
  border-radius: 18px;
  padding: 40px 36px 32px;
  max-width: 480px;
  width: 100%;
  box-shadow: 0 24px 60px rgba(3, 15, 33, 0.4), 0 2px 8px rgba(3, 15, 33, 0.12);
  overflow: hidden;
}

.kartu::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 6px;
  background: linear-gradient(90deg, var(--navy) 0%, #1D4E8F 50%, var(--hijau) 100%);
}

.lencana-instansi {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #1D4E8F;
  background: #EAF1FB;
  padding: 5px 12px;
  border-radius: 999px;
  margin-bottom: 16px;
}

h1 {
  color: var(--navy);
  margin: 0 0 6px;
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: 0.02em;
}

.sub {
  color: #475467;
  font-size: 0.95rem;
  line-height: 1.55;
  margin: 0 0 22px;
}

.kartu-misi {
  background: #EAF1FB;
  border-left: 4px solid var(--navy);
  border-radius: 6px;
  padding: 14px 16px;
  margin-bottom: 28px;
}

.kartu-misi p {
  margin: 0;
  color: #1D3A5F;
  font-size: 0.92rem;
  line-height: 1.65;
  text-align: justify;
  text-justify: inter-word;
}

.status {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.95rem;
  margin-bottom: 8px;
  color: #222;
}

.titik {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.titik.ok { background: var(--hijau); }
.titik.warn { background: var(--oranye); }

.footer {
  margin-top: 20px;
  font-size: 0.8rem;
  color: #999;
}

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

.landing-tombol {
  flex: 1 1 auto;
  text-align: center;
  padding: 12px 22px;
  border-radius: 8px;
  font-weight: 700;
  font-size: 0.95rem;
  text-decoration: none;
  transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
}

.landing-tombol-utama {
  background: var(--navy);
  color: #fff;
  box-shadow: 0 6px 16px rgba(11, 37, 69, 0.35);
}
.landing-tombol-utama:hover { background: #123563; transform: translateY(-1px); box-shadow: 0 8px 20px rgba(11, 37, 69, 0.42); }

.landing-tombol-sekunder {
  background: #fff;
  color: var(--navy);
  border: 1.5px solid #D0D5DD;
}
.landing-tombol-sekunder:hover { border-color: var(--navy); background: #F7F9FB; transform: translateY(-1px); }

/* ---------- Layout halaman umum (dashboard, unggah data, dst) ---------- */

body.halaman {
  display: block;
  background: #F2F4F7;
  padding: 0;
}

.topbar {
  background: var(--navy);
  color: #fff;
  padding: 14px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  position: sticky;
  top: 0;
  z-index: 50;
}

.brand-wrap {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
}

.topbar .brand {
  color: #fff;
  font-weight: 700;
  font-size: 1.3rem;
  text-decoration: none;
  flex-shrink: 0;
}

.topbar .tagline {
  color: #B7C4D6;
  font-size: 0.9rem;
  line-height: 1.3;
  max-width: 640px;
}

.topbar .nav {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
}

/* Tiap item nav (link & dropdown summary) diberi bantalan (padding) +
   sudut membulat + latar transparan yang muncul saat hover/fokus --
   sebelumnya cuma teks polos bermargin, area sentuhnya kecil (setinggi
   teks saja) dan tidak ada penanda visual "ini bisa ditekan". Spasi
   antaritem sekarang murni dari `gap` di .topbar .nav (bukan lagi
   margin-left tiap anak satu-satu) supaya jaraknya konsisten & tidak
   dobel dengan bantalan baru ini. */
.topbar .nav a {
  color: #DCE6F0;
  text-decoration: none;
  font-size: 0.92rem;
  padding: 9px 13px;
  border-radius: 8px;
  transition: background-color .15s ease, color .15s ease;
}

.topbar .nav a:hover, .topbar .nav a:focus-visible { color: #fff; background: rgba(255,255,255,0.1); }

/* Dropdown menu (Manajemen Data, Kelola User) -- pakai <details>/<summary>
   bawaan browser, bukan JS, supaya berfungsi tanpa skrip tambahan dan tetap
   mudah dipakai di layar sentuh (klik untuk buka/tutup). */
.nav-drop {
  position: relative;
  display: inline-block;
}

.nav-drop summary {
  color: #DCE6F0;
  font-size: 0.92rem;
  cursor: pointer;
  list-style: none;
  padding: 9px 13px;
  border-radius: 8px;
  transition: background-color .15s ease, color .15s ease;
}
.nav-drop summary::-webkit-details-marker { display: none; }
.nav-drop summary:hover { color: #fff; background: rgba(255,255,255,0.1); }
.nav-drop[open] summary { color: #fff; background: rgba(255,255,255,0.14); }
.nav-drop summary::after { content: " \25BE"; font-size: 0.7em; }

.nav-drop-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  padding: 6px;
  min-width: 190px;
  z-index: 20;
}
/* Dropdown "Dashboard" SENGAJA jadi item nav-drop paling kiri (dekat tepi
   layar) -- kalau menunya tetap rata kanan (right:0) seperti Manajemen
   Data/Kelola User, menunya akan terpotong keluar layar di sisi kiri.
   Rata kiri di sini supaya menunya melebar ke kanan, masih di dalam layar. */
.nav-drop-kiri .nav-drop-menu { right: auto; left: 0; }

.nav-drop-menu a {
  display: block;
  color: var(--navy) !important;
  margin-left: 0 !important;
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 0.88rem !important;
}
.nav-drop-menu a:hover { background: #F2F4F7; color: var(--navy) !important; }

/* Badge status + Logout dibungkus SATU unit flex (.nav-akun) supaya
   keduanya selalu ikut membungkus (wrap ke baris baru) BERSAMA-SAMA
   kalau baris nav-nya kehabisan tempat -- sebelumnya keduanya item
   terpisah, jadi kadang badge-nya masih muat di baris pertama tapi
   Logout sendirian "terlempar" ke baris kedua, terlihat berantakan &
   tidak simetris. */
.nav-akun {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-left: 12px;
}

/* Status user (nama + peran) di navbar -- badge/pill yang tetap mencolok &
   "gagah" supaya jelas beda dari link menu (tidak bisa diklik) dan gampang
   dikenali siapa yang sedang login -- garis pinggir pill-nya sendiri
   (border penuh di semua sisi) sudah cukup menandai badge ini SATU
   KELOMPOK dengan Logout di sebelahnya, terpisah dari link navigasi.
   Tahap 118 -- SEBELUMNYA gradasi kuning terang (#FFD873/#E0A72E) yang
   kontrasnya berlebihan & bikin teks susah dibaca; diganti gradasi biru
   kehijauan (teal) senada warna identitas --navy (#0B2545) supaya tetap
   menonjol tapi terlihat profesional & padu dengan warna navbar. */
.status-user {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 14px;
  border-radius: 999px;
  background: linear-gradient(135deg, #2E6E8E, #123C5C);
  border: 1px solid rgba(255,255,255,0.25);
  color: #F4F8FB;
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.2px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.25);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}
.status-user:hover, .status-user:focus-visible { opacity: 0.85; color: #F4F8FB; }

/* Logout -- merah eye-catching, sengaja beda dari link nav lain supaya
   gampang ditemukan user, tetap diberi bantalan yang sama dengan link
   nav lain supaya area sentuhnya nyaman. */
.nav-logout {
  color: #FF6B6B !important;
  font-weight: 700 !important;
}
.nav-logout:hover, .nav-logout:focus-visible { color: #fff !important; background: rgba(255,107,107,0.18); }

/* Lonceng Notifikasi Keamanan (Tahap 106) -- reuse struktur .nav-drop
   (details/summary) supaya otomatis ikut perilaku "tutup dropdown lain
   saat salah satu dibuka"/"tutup saat klik luar" yang sudah ada (lihat
   skrip di bawah <script> base.html). Tanda seru merah HANYA muncul kalau
   ada notifikasi belum dibaca (di-toggle lewat JS, bukan CSS). */
.lonceng-summary {
  position: relative;
  font-size: 1.15rem;
  padding: 8px 14px !important;
}
.lonceng-summary::after { content: ""; }
.lonceng-badge {
  position: absolute;
  top: 2px;
  right: 4px;
  background: var(--merah);
  color: #fff;
  font-size: 0.6rem;
  font-weight: 800;
  line-height: 1;
  min-width: 15px;
  height: 15px;
  border-radius: 999px;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
  box-shadow: 0 0 0 2px var(--navy);
  animation: lonceng-berdenyut 1.6s ease-in-out infinite;
}
@keyframes lonceng-berdenyut {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.2); }
}
.notif-dropdown-menu { width: 340px; max-width: 88vw; padding: 0; overflow: hidden; }
.notif-dropdown-header {
  padding: 10px 14px;
  font-weight: 700;
  color: var(--navy);
  border-bottom: 1px solid #EEF1F4;
  font-size: 0.9rem;
}
#notif-dropdown-daftar { max-height: 360px; overflow-y: auto; }
.notif-dropdown-item {
  padding: 9px 14px;
  border-bottom: 1px solid #F2F4F7;
  font-size: 0.8rem;
}
.notif-dropdown-item-baris1 { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 3px; }
.notif-dropdown-waktu { color: #98A2B3; font-size: 0.74rem; white-space: nowrap; }
.notif-dropdown-item-baris2 { color: #475467; }
.notif-dropdown-kosong { padding: 16px 14px; color: #98A2B3; font-size: 0.85rem; text-align: center; }
.notif-dropdown-footer {
  display: block;
  text-align: center;
  padding: 9px;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--navy) !important;
  background: #F7F9FB;
  border-radius: 0 !important;
  margin-left: 0 !important;
}
.notif-dropdown-footer:hover { background: #EEF1F4; }

.breadcrumb {
  font-size: 0.85rem;
  color: #667085;
  margin-bottom: 6px;
}
.breadcrumb a { color: var(--navy); text-decoration: none; }
.breadcrumb a:hover { text-decoration: underline; }
.breadcrumb span { margin: 0 6px; }
.breadcrumb strong { color: var(--navy); }

.konten {
  max-width: 2200px;
  margin: 0 auto;
  padding: 20px 28px 60px;
}

/* Footer atribusi -- baris kecil & tidak mencolok di paling bawah SETIAP
   halaman berlogin (base.html), sengaja netral/kalem (bukan warna brand)
   supaya tidak mengalihkan perhatian dari konten utama. Rentang tahunnya
   otomatis (lihat app/templates_util.py::rentang_tahun_footer) -- "2026"
   saja selama masih tahun peluncuran, otomatis jadi "2026-2027",
   "2026-2028", dst begitu tahun berjalan lewat, tanpa perlu diubah manual. */
.app-footer {
  text-align: center;
  color: #98A2B3;
  font-size: 0.78rem;
  padding: 18px 20px 22px;
}

.panel {
  background: #fff;
  border-radius: 10px;
  padding: 20px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.06);
  margin-bottom: 20px;
}

.panel h1, .panel h2 { color: var(--navy); margin-top: 0; }

/* Rata kiri-kanan (justify) untuk paragraf keterangan yang cukup panjang
   -- baris tunggal/pendek TIDAK terlihat berbeda sama sekali (justify
   cuma meregangkan spasi pada baris yang benar-benar membungkus ke baris
   berikutnya), jadi aman diterapkan luas tanpa merapikan tiap halaman
   satu per satu. */
.panel p, .info, .peringatan, .dashboard-kartu-tautan span:not(.dashboard-kartu-ikon) {
  text-align: justify;
  text-align-last: left;
}

table.tabel {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

table.tabel th, table.tabel td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid #E5E9EF;
  white-space: nowrap;
}

table.tabel th {
  background: #F7F9FB;
  color: var(--navy);
}

/* Header tabel yang bisa diklik untuk sortir (lihat macro sortir_tabel_js()
   & th_urut() di _macros.html) -- panah ganda pudar kalau belum aktif,
   berubah jadi panah tunggal solid searah urutan begitu kolom itu yang
   sedang dipakai mengurutkan. */
table.tabel th.th-urut {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
table.tabel th.th-urut:hover { background: #E9EDF3; }

/* Baris tabel yang bisa diklik untuk membuka detail (Tahap 66, mis. Laporan
   Sudah Ditindaklanjuti) -- highlight halus supaya jelas interaktif. */
table.tabel tr.baris-klik:hover { background: #F7F9FB; }
table.tabel th.th-urut::after { content: " \21C5"; color: #98A2B3; font-size: 0.8em; }
table.tabel th.th-urut-asc::after { content: " \2191"; color: var(--navy); font-weight: 700; }
table.tabel th.th-urut-desc::after { content: " \2193"; color: var(--navy); font-weight: 700; }

/* Tahap 132.9 -- highlight baris saat kursor di atasnya, di SEMUA tabel
   .tabel (bukan cuma baris-klik yang eksplisit ditandai interaktif di
   atas) -- membantu mata menyusuri baris lebar tanpa salah baca kolom,
   terutama tabel dengan banyak kolom (Database Kendaraan, dst). */
table.tabel tbody tr:hover { background: #F7F9FB; }

/* Kolom aksi (tombol Edit/Reset/Hapus/dst, biasanya kolom PALING KANAN)
   tetap terlihat begitu tabel lebar digeser horizontal -- ditambahkan ke
   <table> yang kolom terakhirnya memang berisi tombol aksi lewat class
   "tabel-aksi-sticky" (Database Kendaraan, Data Anomali, Koreksi Golongan,
   Kirim Pesan WhatsApp, Riwayat Impor, Manajemen Hak Akses, Kunjungan,
   Database Alamat, Database Kendaraan Non-Aktif). SCOPED ke desktop
   (>880px, breakpoint kartu-mobile .tabel-kartu-mobile) karena versi
   mobile sudah stacking penuh per baris & tidak butuh sticky sama sekali
   -- menerapkannya juga di mobile cuma akan memotong kartu tanpa manfaat. */
@media (min-width: 881px) {
  table.tabel.tabel-aksi-sticky td:last-child {
    position: sticky;
    right: 0;
    background: #fff;
    box-shadow: -4px 0 6px -4px rgba(0,0,0,0.08);
  }
  table.tabel.tabel-aksi-sticky th:last-child {
    position: sticky;
    right: 0;
    background: #F7F9FB;
    box-shadow: -4px 0 6px -4px rgba(0,0,0,0.08);
  }
  /* Baris opacity:0.55 (kendaraan nonaktif) & hover butuh warna latar
     kolom sticky ikut menyesuaikan, bukan tetap putih polos -- kalau
     tidak, kolom sticky-nya akan terlihat "salah warna" dibanding sisa
     barisnya sendiri saat digeser/hover. */
  table.tabel.tabel-aksi-sticky tbody tr:hover td:last-child { background: #F7F9FB; }
}

/* Tabel ringkasan wilayah (Kabupaten/Kota, Kecamatan, Kelurahan/Desa, RT,
   Jenis Kendaraan -- lihat ringkasan_wilayah() di _macros.html, dipakai
   berulang di banyak halaman drill-down Dashboard) -- header kolomnya
   (mis. "Jumlah Tunggakan", "Sudah Ditindaklanjuti", "Perlu Tindak
   Lanjut") sebelumnya satu baris nowrap panjang yang memaksa tabelnya
   melebar jauh & selalu perlu digeser horizontal walau datanya cuma
   beberapa baris pendek. Header dibuat boleh membungkus 2 baris supaya
   lebar kolom bisa jauh lebih ringkas -- pola yang sama seperti
   .tabel-hasil-tindak-lanjut. table-layout:fixed + lebar eksplisit per
   kolom WAJIB (max-width saja tidak cukup di table-layout:auto bawaan
   .tabel -- lihat catatan di atas .tabel-hasil-tindak-lanjut). */
/* min-width WAJIB di samping table-layout:fixed -- tanpanya, di HP yang
   benar-benar sempit (mis. 412px) kolomnya dipaksa menyusut sampai jauh
   di bawah kebutuhan minimalnya (rupiah, persentase, dst jadi saling
   bertumpuk/terpotong -- lebih parah daripada sebelum perubahan ini)
   alih-alih tabelnya melebar & digeser horizontal seperti seharusnya.
   Nilai ini dihitung dari kebutuhan lebar minimum tiap kolom (batang
   nama wilayah, rupiah terpanjang, dst) -- lebih ringkas daripada
   sebelum header dibungkus 2 baris, tapi tetap perlu digeser di HP
   sempit (scrollbar-nya sudah dihaluskan, lihat .tabel-scroll). */
/* Tahap 84 -- min-width dinaikkan dari 680px ke 900px: 4 kolom rupiah
   (SWDKLLJ/PKB/Opsen PKB/Total) sebelumnya hanya diberi ~9-11% dari
   680px (~65px), jauh di bawah kebutuhan angka seperti "Rp 232.320.000"
   (~95-100px pada font tebal) -- angka yang tidak muat itu, karena TIDAK
   punya spasi/tanda hubung untuk membungkus (cuma titik ribuan), meluber
   ke kolom sebelahnya dan bertumpuk dengan isinya (mis. "232.320.000Rp
   0" tanpa jarak) -- laporan pengguna "tulisan bertumpuk". overflow-wrap
   di bawah tetap dipertahankan sbg jaring pengaman untuk angka yang
   masih lebih panjang dari itu (mis. total gabungan wilayah besar). */
table.tabel.tabel-wilayah { table-layout: fixed; min-width: 900px; }
table.tabel.tabel-wilayah th {
  white-space: normal;
  line-height: 1.25;
  vertical-align: bottom;
}
table.tabel.tabel-wilayah td {
  white-space: normal;
  overflow-wrap: anywhere;
}
/* Lebar tiap kolom SEKARANG diatur lewat <colgroup> di _macros.html
   (Tahap 67, header 2 baris: grup "Nominal Tunggakan" membawahi 4
   sub-kolom) -- colgroup dipilih daripada nth-child per <th> karena
   header-nya 2 baris (indeks kolom fisik beda dari indeks <th> per baris,
   colgroup satu-satunya cara jelas menargetkan kolom fisik). Aturan di
   sini cuma perilaku non-lebar (bungkus teks) yang tetap perlu CSS. */
table.tabel.tabel-wilayah td:nth-child(1) { white-space: nowrap; }
/* Nama wilayah (batang peringkat) & badge persentase sudah punya
   penanganan overflow sendiri (ellipsis/nowrap di dalam elemennya
   masing-masing) -- white-space:normal di <td> pembungkusnya tidak
   memengaruhi keduanya, cuma berlaku untuk sel angka polos (jumlah unit,
   rupiah, dst) supaya bisa membungkus kalau kolomnya sempit. */

/* Scrollbar bawaan Android Chrome untuk elemen overflow-x:auto tampil
   sebagai batang abu-abu tebal yang cukup mengganggu secara visual --
   dibuat jauh lebih tipis & halus di sini (tanpa menghilangkan
   kemampuan geser itu sendiri, yang tetap diperlukan untuk tabel lebar
   di layar sempit). scrollbar-gutter:auto (bawaan) supaya tidak
   menambah lebar tetap kalau kontennya sebenarnya sudah pas & tidak
   perlu digeser sama sekali. */
.tabel-scroll {
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: #D0D5DD transparent;
}
.tabel-scroll::-webkit-scrollbar { height: 5px; }
.tabel-scroll::-webkit-scrollbar-track { background: transparent; }
.tabel-scroll::-webkit-scrollbar-thumb { background: #D0D5DD; border-radius: 4px; }

/* Tabel "Wilayah Terbanyak Melakukan Tindak Lanjut" (Dashboard/Peringkat)
   -- nama kategori hasil kunjungan cukup panjang (mis. "Kendaraan Rusak
   Hilang atau Dicuri"), kalau dipaksa satu baris (nowrap bawaan .tabel)
   tabelnya melebar jauh ke kanan. Header kolom ini SENGAJA boleh membungkus
   jadi ~2 baris dengan lebar kolom dibatasi, supaya tabel tetap ringkas. */
/* max-width SAJA tidak berpengaruh di table-layout:auto (bawaan .tabel) --
   kolom tetap mencoba selebar teksnya lalu bertumpuk dengan kolom
   sebelahnya. table-layout:fixed + lebar eksplisit di baris header
   PERTAMA wajib supaya browser benar-benar membungkus & membatasi lebar
   tiap kolom kategori. Selector di sini SENGAJA diberi awalan
   "table.tabel" (bukan cuma ".tabel-hasil-tindak-lanjut") supaya
   spesifisitasnya menang melawan aturan white-space:nowrap bawaan di
   "table.tabel th, table.tabel td" -- kalau tidak, nowrap-nya tetap
   menang walau class ini ditambahkan belakangan. */
/* min-width supaya di layar sempit (HP) tabel ini melebar & di-scroll
   horizontal lewat .tabel-scroll pembungkusnya -- BUKAN dipaksa menyusut
   sampai kolom persentasenya (24%/11%/dst) jadi cuma puluhan piksel,
   yang sebelumnya bikin header & badge di dalamnya bertumpuk tidak
   terbaca. Di layar lebar (desktop) tidak berpengaruh karena lebar wajar
   tabel ini sudah jauh di atas nilai min-width ini. */
table.tabel.tabel-hasil-tindak-lanjut { table-layout: fixed; min-width: 900px; }
table.tabel.tabel-hasil-tindak-lanjut th, table.tabel.tabel-hasil-tindak-lanjut td {
  white-space: normal;
  line-height: 1.25;
  /* Beberapa label kategori hasil kunjungan tidak punya spasi sama sekali
     di tengahnya (mis. "Rusak/Hilang/Dicuri", cuma dipisah garis miring)
     -- tanpa ini, "kata" sepanjang itu tidak pernah membungkus ke baris
     baru, malah meluber keluar batas kolom (table-layout:fixed tidak
     memaksa overflow:hidden) dan tertumpuk visual dengan teks kolom di
     sebelahnya, persis laporan pengguna "tulisan bertumpuk". */
  overflow-wrap: anywhere;
}
table.tabel.tabel-hasil-tindak-lanjut th { vertical-align: bottom; }
table.tabel.tabel-hasil-tindak-lanjut th:nth-child(1), table.tabel.tabel-hasil-tindak-lanjut td:nth-child(1) { white-space: nowrap; width: 42px; }
table.tabel.tabel-hasil-tindak-lanjut th:nth-child(2) { width: 20%; }
table.tabel.tabel-hasil-tindak-lanjut th:nth-child(3) { width: 10%; }
/* Sisa kolom (kategori hasil kunjungan, jumlahnya tetap 6 -- lihat
   HASIL_KUNJUNGAN di app/models/kunjungan.py) dibagi rata secara eksplisit
   -- tanpa ini, table-layout:fixed di sebagian browser mobile menyusutkan
   kolom-kolom ini jauh lebih sempit daripada perkiraan "bagi rata" pada
   umumnya, memperparah masalah peluberan di atas. */
table.tabel.tabel-hasil-tindak-lanjut th:nth-child(n+4) { width: 11.66%; }

/* Tabel profil kendaraan (2 kolom label/nilai) -- teks nilai yang panjang
   (mis. alamat gabungan, data mentah) sebaiknya membungkus ke baris baru,
   bukan memaksa tabel melebar seperti tabel data tabular biasa. table-layout
   fixed dipakai supaya lebar kolom mengikuti definisi (kolom label 180px),
   bukan dihitung ulang dari konten terpanjang -- itu penyebab tabel ini bisa
   melebar sampai keluar layar HP walau white-space sudah diizinkan membungkus. */
.tabel-kv { table-layout: fixed; width: 100%; }
table.tabel.tabel-kv td { white-space: normal; word-break: break-word; }

/* Grafik batang rangking wilayah (Dashboard, level Kecamatan & Kelurahan/
   Desa) -- nama wilayah SENGAJA digabung ke dalam batangnya sendiri (bukan
   kolom terpisah) supaya hemat tempat & langsung terbaca wilayah mana yang
   batangnya itu. Batang mengkodekan besaran metrik yang sedang dipilih di
   "Urutkan berdasarkan" (Jumlah Unit/Tunggakan SWDKLLJ/PKB/Opsen/Total/
   Alamat Lengkap/Perlu Tindak Lanjut) -- panjang DAN warnanya ikut berubah
   bersamaan (lihat ringkasan_wilayah() di _macros.html), supaya metrik yang
   sedang dilihat langsung terlihat jelas tanpa perlu baca angka satu-satu.
   Label diberi lebar penuh (bukan mengikuti lebar isian) supaya tetap
   terbaca walau batangnya pendek -- warna teks gelap dipilih supaya
   kontrasnya tetap aman baik di atas warna isian maupun trek kosongnya. */
.peringkat-bar {
  position: relative;
  display: block;
  height: 34px;
  min-width: 140px;
  border-radius: 8px;
  background: #EAF0FE;
  overflow: hidden;
  text-decoration: none;
}
.peringkat-bar-isi {
  position: absolute;
  inset: 0;
  width: 0;
  background: linear-gradient(90deg, #A8C2FA, #6E93F0);
  transition: width 0.2s ease;
}
/* .peringkat-bar-label sendiri display:flex (supaya teksnya center-vertikal
   di dalam batang) -- tapi text-overflow:ellipsis TIDAK berlaku pada
   container flex (spesifikasi CSS Overflow cuma menerapkannya ke container
   block/inline-block). Tanpa pembungkus terpisah ini, teks nama wilayah
   panjang di HP (kolom sempit, lihat catatan min-width di .tabel-wilayah)
   dulu terpotong PAKSA tanpa "...", dan anonymous flex item-nya
   (min-width:auto bawaan) menolak menyusut di bawah lebar teks aslinya --
   membuat batangnya melebar keluar sel tabel & bertumpuk dengan kolom
   sebelahnya. Teks dibungkus span block terpisah supaya ellipsis benar2
   berlaku, dan min-width:0 di keduanya supaya sama2 boleh menyusut. */
.peringkat-bar-label {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  height: 100%;
  min-width: 0;
  padding: 0 12px;
}
.peringkat-bar-label-teks {
  display: block;
  min-width: 0;
  width: 100%;
  color: var(--navy);
  font-weight: 600;
  font-size: 0.88rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.peringkat-bar:hover .peringkat-bar-label { text-decoration: underline; }
.peringkat-bar:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
/* Varian hijau -- tabel "Wilayah Terbanyak Melakukan Tindak Lanjut" di
   bawah Tabel Peringkat, batangnya proporsional terhadap wilayah dengan
   jumlah tindak lanjut TERBANYAK (baris pertama = 100%), bukan terhadap
   total kendaraan wilayah itu sendiri -- supaya langsung terlihat wilayah
   mana yang paling menonjol di tabel ini. */
.peringkat-bar-hijau .peringkat-bar-isi { background: linear-gradient(90deg, #8FDCB3, #1E8E5A); }

/* Tahap 100 -- palet warna batang per metrik "Urutkan berdasarkan" di
   .tabel-wilayah (ringkasan_wilayah() di _macros.html). Kelas metrik-* ini
   ditoggle di elemen <table> lewat JS (perbaruiBar()) tiap kali dropdown
   berubah -- .peringkat-bar-isi default (biru, di atas) tetap dipakai untuk
   metrik Jumlah Unit, jadi tidak perlu aturan metrik-jumlah terpisah.
   Nominal tunggakan (SWDKLLJ/PKB/Opsen/Total) sengaja satu keluarga warna
   merah/oranye -- uang yang belum dibayar -- dengan tingkat saturasi
   berbeda per kolom supaya tetap bisa dibedakan; Alamat Lengkap hijau
   (progres baik); Perlu Tindak Lanjut kuning keemasan (perlu aksi). */
.tabel-wilayah.metrik-swdkllj .peringkat-bar-isi { background: linear-gradient(90deg, #F7C9A0, #E07A2E); }
.tabel-wilayah.metrik-pkb .peringkat-bar-isi { background: linear-gradient(90deg, #F3AFAF, #D4453D); }
.tabel-wilayah.metrik-opsen .peringkat-bar-isi { background: linear-gradient(90deg, #E6BEDD, #A63D95); }
.tabel-wilayah.metrik-total .peringkat-bar-isi { background: linear-gradient(90deg, #F6B99A, #C62828); }
.tabel-wilayah.metrik-lengkap .peringkat-bar-isi { background: linear-gradient(90deg, #8FDCB3, #1E8E5A); }
.tabel-wilayah.metrik-tindaklanjut .peringkat-bar-isi { background: linear-gradient(90deg, #FBD08B, #C1670C); }

/* Pie chart pembobotan wilayah (Dashboard) -- lihat
   app/routers/dashboard.py: _tambah_potongan_pie(). Nama wilayah, persentase,
   dan jumlah unit ditampilkan sekali saja lewat label garis penunjuk & tooltip
   (<title> per potongan) -- tidak diulang lagi di luar chart. */
.pie-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 14px 0 22px;
}
.pie-svg { width: 100%; max-width: 480px; height: auto; flex-shrink: 0; overflow: visible; }
.pie-svg .pie-potongan { stroke: #fff; stroke-width: 1.5; transition: opacity 0.15s ease; }
a:has(> .pie-potongan) { cursor: pointer; }
a:has(> .pie-potongan):hover .pie-potongan { opacity: 0.8; }
.pie-total-angka { font-size: 26px; font-weight: 700; fill: var(--navy); font-family: inherit; }
.pie-total-label { font-size: 11px; fill: #667085; font-family: inherit; }
/* Garis penunjuk (leader line) dari potongan pie ke label nama+persentase+jumlah --
   lihat _tambah_label_pie() di app/routers/dashboard.py. Hanya potongan yang
   cukup besar yang diberi garis ini; sisanya tetap terbaca lewat tooltip. */
.pie-leader { fill: none; stroke: #B7C4D6; stroke-width: 1; }
.pie-label-tautan { cursor: pointer; }
.pie-label-nama { font-size: 11px; font-weight: 700; fill: var(--navy); font-family: inherit; }
.pie-label-pct { font-size: 10px; fill: #667085; font-family: inherit; }
.pie-label-tautan:hover .pie-label-nama { text-decoration: underline; }

/* Peta interaktif choropleth (Dashboard) -- lihat app/services/peta.py.
   Batas <path> per kabupaten/kota diberi kursor pointer & efek hover
   supaya jelas bisa diklik, sama seperti nama wilayah di tabel ranking.
   Legenda SENGAJA ditaruh di ATAS peta (langsung di bawah dropdown "Warna
   berdasarkan"), sebagai strip horizontal ringkas -- bukan di samping/bawah
   peta seperti sebelumnya, supaya tidak bergantung pada sisa ruang kosong
   di sekitar SVG peta. Peta sendiri dibungkus kartu lembut (gradasi +
   border) supaya ruang kosong di sekitar bentuk peta (viewBox punya
   padding di semua sisi buat label hover, lihat PADDING di peta.py) tetap
   terlihat sengaja/rapi, bukan cuma latar putih kosong. */
.peta-legenda {
  font-size: 0.82rem;
  margin: 10px 0 4px;
  background: #F7F9FC;
  border: 1px solid #E9ECF2;
  border-radius: 10px;
  padding: 10px 14px;
}
.peta-legenda strong { display: block; margin-bottom: 6px; color: var(--navy); }
.peta-legenda-baris { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.peta-legenda-item { display: inline-flex; align-items: center; gap: 6px; color: #475467; }
.peta-swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 3px;
  flex-shrink: 0;
}
/* Tahap 108, poin 5 -- pembungkus 3-kolom: kartu wawasan kiri, peta di
   tengah, kartu sorotan wilayah kanan. Peta SENGAJA tetap dibatasi
   max-width (lihat .peta-svg) supaya proporsinya tidak melar aneh di
   layar sangat lebar -- ruang kosong yang DULU cuma jadi padding
   kiri-kanan kosong sekarang terisi 2 kartu (bukan peta yang dipaksa
   melebar, yang justru bikin bentuk provinsinya distorsi). */
.peta-wrap-luas {
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: 16px;
  margin-bottom: 22px;
}
.peta-wrap-luas-tanpa-tips { display: block; }
.peta-panel-tips {
  /* Tahap 112, poin 5 -- kotak diperlebar (260/340 -> 300/400px) supaya
     teks yang fontnya diperbesar di bawah tetap punya cukup ruang napas
     per baris, bukan malah jadi lebih sesak dari sebelumnya. */
  flex: 1 1 300px;
  min-width: 260px;
  max-width: 400px;
  background: linear-gradient(165deg, #0B2545, #1B3D6D);
  color: #fff;
  border-radius: 14px;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: 0 4px 14px rgba(11, 37, 69, 0.14);
}
.peta-panel-kanan { background: linear-gradient(165deg, #14663f, #1E8E5A); }
/* Tahap 109, poin 2 -- judul + tombol navigasi manual (next/prev) dalam
   satu baris, supaya user bisa membaca ulang wawasan yang mungkin
   terlewat sebelum sempat terbaca (sebelumnya HANYA berganti otomatis
   tiap 7 detik / mengikuti hover, tanpa kendali manual sama sekali). */
.peta-panel-judul-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.peta-panel-judul { font-size: 1rem; font-weight: 700; opacity: 0.97; }
.peta-panel-nav { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.peta-panel-nav-btn {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.4);
  background: rgba(255,255,255,0.12);
  color: #fff;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s ease;
}
.peta-panel-nav-btn:hover, .peta-panel-nav-btn:focus-visible { background: rgba(255,255,255,0.28); }
.peta-panel-nav-btn:disabled { opacity: 0.35; cursor: default; }
.peta-panel-nav-hitung { font-size: 0.78rem; opacity: 0.85; min-width: 28px; text-align: center; }
/* Tahap 109, poin 2 -- teks diperbesar & dirapikan justify (rata
   kiri-kanan) supaya kalimat panjang tetap enak dibaca dalam kartu
   sesempit ini; angka/nama wilayah penting ditandai <strong> di server
   (lihat _susun_wawasan_peta di dashboard.py) supaya langsung menonjol
   sekilas pandang tanpa harus membaca seluruh kalimat. */
.peta-panel-isi {
  /* Tahap 112, poin 5 -- diperbesar (1rem -> 1.12rem) & line-height sedikit
     dilonggarkan supaya kalimat wawasan lebih gampang dibaca sekilas
     pandang, konsisten dengan permintaan pengguna "besarkan tulisan". */
  font-size: 1.12rem;
  line-height: 1.7;
  opacity: 0.97;
  text-align: justify;
  text-align-last: left;
  transition: opacity 0.22s ease;
  min-height: 3.4em;
}
.peta-panel-isi strong { color: #FFD98C; font-weight: 700; }
.peta-panel-kanan .peta-panel-isi strong { color: #C8F7DC; }
@media (max-width: 1100px) {
  .peta-wrap-luas { flex-direction: column; }
  .peta-panel-tips { max-width: none; }
}

.peta-wrap {
  position: relative;
  display: flex;
  justify-content: center;
  margin-top: 4px;
  flex: 1 1 auto;
  min-width: 0;
  /* margin-bottom SENGAJA ditambah -- sebelumnya heading section
     berikutnya (mis. "Podium Tiga Besar Tindak Lanjut Terbaik") langsung
     menempel di bawah garis kotak peta ini, terkesan mepet/sesak. */
  background: linear-gradient(180deg, #F7FAFF 0%, #fff 100%);
  border: 1px solid #E9ECF2;
  border-radius: 14px;
  padding: 18px;
}
.peta-svg { width: 100%; max-width: 640px; height: auto; flex-shrink: 0; overflow: visible; }

/* Tahap 112, poin 6 -- peta lokator kecil (siluet Pulau Sumatera) di pojok
   kiri-atas kartu peta utama, murni konteks visual (tidak bisa diklik). */
.peta-lokator {
  position: absolute;
  top: 10px;
  left: 10px;
  width: 108px;
  background: rgba(255, 255, 255, 0.94);
  border: 1px solid #E2E7F0;
  border-radius: 10px;
  padding: 6px 6px 5px;
  box-shadow: 0 2px 8px rgba(11, 37, 69, 0.14);
  z-index: 2;
}
.peta-lokator-svg { width: 100%; height: auto; display: block; }
.peta-lokator-path { fill: #D3DAE6; stroke: #fff; stroke-width: 1; }
.peta-lokator-aktif { fill: var(--navy); }
.peta-lokator-label {
  display: block;
  font-size: 0.62rem;
  line-height: 1.25;
  color: #667085;
  text-align: center;
  margin-top: 4px;
}
@media (max-width: 480px) { .peta-lokator { width: 82px; padding: 4px 4px 3px; } .peta-lokator-label { font-size: 0.56rem; } }

/* Tahap 112, poin 6 -- "garis imajiner" batas kab/kota se-provinsi yang
   ditumpangkan di BELAKANG peta Kecamatan yang di-zoom (lihat
   muat_peta_kecamatan_dengan_konteks() di app/services/peta.py) -- murni
   latar/konteks, bukan elemen interaktif (tidak ada fill, tidak ada
   pointer-events).
   Tahap 113, poin 4 -- garis dipertegas (lebih tebal, warna lebih gelap,
   opacity dinaikkan) dari versi awal yang terlalu samar/nyaris tak
   terlihat, + nama tiap wilayah tetangga dituliskan di tengah areanya
   supaya batas ini benar-benar informatif, bukan cuma dekorasi.
   Tahap 114, poin 1 -- ternyata versi Tahap 113 terlalu TEBAL & labelnya
   berebut ruang dengan kecamatan yang di-zoom (garis solid utama), jadi
   diturunkan lagi ke garis tipis semi-transparan yang tetap terlihat
   jelas sebagai "batas administratif" tapi tidak mendominasi peta --
   penumpukan nama wilayah sendiri sudah ditangani di sisi data lewat
   _saring_label_tumpang_tindih() (app/services/peta.py), bukan lewat CSS. */
.peta-konteks-kabkota path {
  fill: none;
  stroke: #8B98B0;
  stroke-width: 1;
  stroke-dasharray: 4 3;
  opacity: 0.65;
  pointer-events: none;
}
.peta-konteks-label {
  fill: #667085;
  font-size: 10px;
  font-weight: 600;
  font-family: inherit;
  opacity: 0.85;
  pointer-events: none;
  paint-order: stroke;
  stroke: #fff;
  stroke-width: 2.5px;
  stroke-linejoin: round;
}
.peta-wilayah { stroke: #fff; stroke-width: 1.5; transition: opacity 0.15s ease, filter 0.15s ease; }
a:has(> .peta-wilayah) { cursor: pointer; }
a:has(> .peta-wilayah):hover .peta-wilayah { opacity: 0.75; }
.peta-wilayah-kosong { cursor: default; }
/* Wilayah yang sedang disorot kursor (lihat script di _macros.html:
   peta_svg) -- diberi garis batas tebal & sedikit terang supaya kelihatan
   "terangkat" dari wilayah lain, yang warnanya sengaja dibiarkan statis. */
.peta-wilayah-aktif { stroke: var(--navy); stroke-width: 2.5; filter: brightness(1.08); }
.peta-sorot { pointer-events: none; }
.peta-sorot-garis { stroke-width: 1.75; stroke-dasharray: 3 3; }
/* Kotak latar putih di belakang label -- supaya tulisannya tetap kontras
   & mudah dibaca di atas warna wilayah apa pun (sebelumnya teks memakai
   warna wilayah langsung tanpa latar, sulit dibaca di atas warna terang). */
.peta-sorot-kotak { fill: #fff; fill-opacity: 0.97; stroke: #D0D5DD; stroke-width: 1; filter: drop-shadow(0 2px 5px rgba(11,37,69,0.18)); }
.peta-sorot-nama { font-size: 13px; font-weight: 700; font-family: inherit; fill: var(--navy); }
.peta-sorot-jumlah, .peta-sorot-tunggakan, .peta-sorot-tindaklanjut { font-size: 11px; font-weight: 600; font-family: inherit; fill: #344054; }

.badge {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
}
.badge.ok { background: #E4F6EC; color: var(--hijau); }
.badge.warn { background: #FDF1DD; color: var(--oranye); }
.badge.merah { background: #FBE6E5; color: var(--merah); }
.badge.netral { background: #EDEFF2; color: #555; }

/* Linimasa (timeline) -- dipakai bareng oleh User Log (Tahap 91) & Timeline
   Tindak Lanjut (Tahap 92): garis vertikal + titik warna per kategori,
   kartu putih per baris. Kelas warna titik (login/logout/login_gagal/aksi
   untuk User Log; ok/warn/netral/merah untuk hasil kunjungan) dipasang
   lewat atribut `class` pada .linimasa-titik dari template masing-masing. */
.linimasa { position: relative; margin: 18px 0 6px; padding-left: 28px; }
.linimasa::before {
  content: ""; position: absolute; left: 9px; top: 6px; bottom: 6px; width: 2px; background: #E4E7EC;
}
.linimasa-item { position: relative; margin-bottom: 18px; }
.linimasa-titik {
  position: absolute; left: -28px; top: 6px; width: 15px; height: 15px; border-radius: 50%;
  background: #98A2B3; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #D0D5DD;
}
.linimasa-titik.login, .linimasa-titik.ok { background: var(--hijau); box-shadow: 0 0 0 3px #fff, 0 0 0 4px var(--hijau); }
.linimasa-titik.logout, .linimasa-titik.netral { background: #667085; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #667085; }
.linimasa-titik.login_gagal, .linimasa-titik.merah { background: var(--merah); box-shadow: 0 0 0 3px #fff, 0 0 0 4px var(--merah); }
.linimasa-titik.aksi, .linimasa-titik.warn { background: var(--oranye); box-shadow: 0 0 0 3px #fff, 0 0 0 4px var(--oranye); }
.linimasa-kartu {
  background: #fff; border: 1px solid #E4E7EC; border-radius: 10px; padding: 16px 20px;
  box-shadow: 0 1px 2px rgba(16,24,40,0.05); transition: border-color 0.15s, box-shadow 0.15s;
}
.linimasa-kartu:hover { border-color: #C7CDD6; box-shadow: 0 2px 8px rgba(16,24,40,0.08); }
/* Header kartu: judul/badge rata kiri, tanggal & jam rata kanan --
   `align-items: flex-start` (bukan center) supaya blok tanggal/jam yang
   dua baris (lihat .linimasa-tanggal/.linimasa-jam) tetap sejajar rapi
   dengan baris pertama judul, bukan ikut ke tengah. */
.linimasa-kartu-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 6px; }
.linimasa-judul { font-weight: 700; color: var(--navy); font-size: 1.05rem; line-height: 1.4; }
/* Tanggal & jam diperbesar dan ditonjolkan (Tahap 92 revisi) supaya jadi
   penanda "kapan" yang cepat ditangkap mata tanpa perlu membaca detail
   kartu -- tanggal jadi baris utama (tebal, warna navy senada judul),
   jam jadi baris kedua yang lebih kecil, keduanya rata kanan supaya
   sejajar rapi dari kartu ke kartu di sepanjang linimasa. Dipakai bareng
   oleh User Log (teks polos, tanpa dipecah tanggal/jam -- tetap ikut
   ukuran dasar yang sudah diperbesar di sini) & Riwayat Tindak Lanjut
   (dipecah eksplisit lewat .linimasa-tanggal/.linimasa-jam, lihat
   kunjungan/timeline.html). */
.linimasa-waktu {
  display: flex; flex-direction: column; align-items: flex-end; line-height: 1.35;
  font-size: 0.95rem; font-weight: 700; color: var(--navy); white-space: nowrap; flex-shrink: 0;
}
.linimasa-tanggal { font-size: 1.08rem; font-weight: 700; color: var(--navy); }
.linimasa-jam { font-size: 0.88rem; font-weight: 600; color: #475467; }
/* Rata kiri-kanan (justify) untuk teks deskriptif yang bisa lebih dari
   satu baris (alamat, catatan petugas) -- pola sama seperti paragraf di
   `.panel p`/`.info` (lihat Tahap 67.2): `text-align-last: left`
   memastikan baris terakhir/baris tunggal TIDAK ikut meregang aneh,
   cuma baris yang benar-benar membungkus yang dirapikan. */
.linimasa-sub { font-size: 0.92rem; color: #475467; margin-top: 6px; line-height: 1.6; text-align: justify; text-align-last: left; }
.linimasa-meta { font-size: 0.82rem; color: #667085; margin-top: 10px; display: flex; gap: 16px; flex-wrap: wrap; align-items: center; }

/* Penanda asal data per nomor polisi (GASPOL Jasa Raharja / BAPENDA
   Pemprov Jambi) -- logo di /static/img, lihat _macros.html: badge_sumber. */
.lencana-sumber {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  border: 1px solid #D0D5DD;
  margin-right: 4px;
  cursor: default;
  overflow: hidden;
  vertical-align: middle;
}
.lencana-sumber img { width: 16px; height: 16px; object-fit: contain; }

/* Tahap 118 -- Lembar Kerja (kunjungan/daftar.html) dipakai petugas di
   lapangan lewat HP untuk mencatat kunjungan, jadi tabelnya (17 kolom)
   diubah jadi tumpukan KARTU per kendaraan di layar sempit -- tidak perlu
   lagi menggeser tab ke kanan/kiri untuk sampai ke tombol "Catat
   Kunjungan". Kolom sekunder (alamat rinci, breakdown tunggakan, dst)
   disembunyikan default & bisa dibuka lewat <details> ringkas per kartu;
   kolom utama (Nomor Polisi+lencana sumber, Nama Pemilik, Total
   Tunggakan, Status) & tombol aksi tetap selalu terlihat. Di layar lebar
   (desktop/tablet) tabelnya TETAP tabel biasa seperti sebelumnya --
   transformasi ini HANYA aktif di bawah breakpoint mobile. */
.tabel-kartu-mobile .kol-ringkas-mobile { display: none; }

/* Tahap 130 -- nomor urut ganda di kolom "Nomor Polisi" pada tabel kartu
   mobile (mis. Lembar Kerja/kunjungan/daftar.html): prefix "1. " ditulis
   di kolom utama SUPAYA nomor urut tetap kelihatan di HP (kolom "No."
   termasuk kol-sekunder & thead ikut disembunyikan total di breakpoint
   mobile, lihat blok di bawah). Di layar lebar kolom "No." sudah tampil
   sendiri, jadi prefix ini disembunyikan supaya tidak dobel. (Manajemen
   Nomor HP/kendaraan/kontak.html sejak Tahap 130 TIDAK lagi pakai kelas
   tabel-kartu-mobile sama sekali -- pengguna lebih suka tampilan tabel
   asli yang bisa digeser horizontal, bukan tumpukan kartu, jadi masalah
   dobel ini otomatis tidak berlaku untuk halaman itu.) */
.nomor-urut-mobile { display: none; }

@media (max-width: 880px) {
  .tabel-kartu-mobile thead { display: none; }
  .tabel-kartu-mobile, .tabel-kartu-mobile tbody, .tabel-kartu-mobile tr, .tabel-kartu-mobile td {
    display: block; width: 100%;
  }
  .tabel-kartu-mobile tr {
    margin-bottom: 12px;
    border: 1px solid #E4E7EC;
    border-radius: 10px;
    padding: 12px 14px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.05);
  }
  .tabel-kartu-mobile td { border: none; padding: 3px 0; }
  .tabel-kartu-mobile .kol-sekunder { display: none; }
  .tabel-kartu-mobile .kol-ringkas-mobile { display: block; margin: 8px 0; }
  .tabel-kartu-mobile .nomor-urut-mobile { display: inline; }
  .tabel-kartu-mobile .kol-utama[data-label]::before {
    content: attr(data-label) ": ";
    display: block;
    font-weight: 600;
    color: #667085;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.3px;
  }
  .tabel-kartu-mobile .kol-ringkas-mobile summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--navy);
    font-size: 0.85rem;
  }
  .tabel-kartu-mobile .ringkas-mobile-isi p {
    margin: 6px 0 0;
    font-size: 0.85rem;
    color: #475467;
    line-height: 1.5;
  }
  .tabel-kartu-mobile .kol-aksi {
    display: flex;
    gap: 8px;
    margin-top: 10px;
  }
  .tabel-kartu-mobile .kol-aksi a { flex: 1; text-align: center; }
}

/* Tahap 130 -- editor pesan WhatsApp (kendaraan/kontak.html) diminta
   tampil berdampingan dengan mockup layar chat WhatsApp (bukan cuma
   gelembung hijau lepas) supaya petugas langsung dapat gambaran tampilan
   pesan yang diterima pemilik kendaraan. Murni ilustrasi CSS -- BUKAN
   tangkapan layar sungguhan/bukti pengiriman, sejalan dengan disclaimer
   "Status WA" di halaman yang sama (aplikasi tidak punya tanda terima
   dari WhatsApp). #preview-bubble di dalamnya diisi/diperbarui lewat JS
   yang sama seperti sebelumnya (sinkronPesanEditor()). */
.wa-mockup-hp {
  border: 1px solid #D0D5DD;
  border-radius: 10px;
  overflow: hidden;
  background: #E7DFD5;
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
}
.wa-mockup-header {
  display: flex;
  align-items: center;
  gap: 10px;
  background: #075E54;
  color: #fff;
  padding: 10px 12px;
}
.wa-mockup-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: #128C7E;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.wa-mockup-nama { font-weight: 600; font-size: 0.86rem; line-height: 1.2; }
.wa-mockup-status { font-size: 0.7rem; color: #CFEDE8; }
.wa-mockup-chat {
  min-height: 160px;
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}
.wa-mockup-bubble {
  max-width: 92%;
  background: #DCF8C6;
  border-radius: 8px 2px 8px 8px;
  padding: 7px 9px;
  font-size: 0.86rem;
  line-height: 1.4;
  white-space: pre-wrap;
  word-break: break-word;
  box-shadow: 0 1px 1px rgba(0,0,0,0.08);
}

.form-baris { margin-bottom: 14px; }
.form-baris label { display: block; font-weight: 600; color: var(--navy); margin-bottom: 4px; font-size: 0.9rem; }
.form-baris select, .form-baris input[type=file] {
  width: 100%;
  padding: 8px;
  border: 1px solid #D0D5DD;
  border-radius: 6px;
  font-size: 0.92rem;
}

/* Grid multi-kolom untuk form yang punya banyak baris sejenis (mis. daftar
   pemetaan kolom impor, pengaturan impor) -- supaya layar lebar (lihat
   .konten max-width 2200px) dipakai secara nyata, bukan satu kolom panjang
   ke bawah yang terasa sempit walau panelnya sendiri sudah lebar. */
.form-grid-lebar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 4px 24px;
}
@media (max-width: 640px) {
  .form-grid-lebar { grid-template-columns: 1fr; }
}

.kotak-setelan {
  background: #F7F9FB;
  border: 1px solid #E5E9EF;
  border-radius: 10px;
  padding: 16px 18px;
  margin-bottom: 18px;
}
.kotak-setelan h3 { margin: 0 0 10px; color: var(--navy); font-size: 1rem; }
.baris-checkbox { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 10px; }
.baris-checkbox input[type=checkbox] { margin-top: 3px; flex-shrink: 0; }
.baris-checkbox label { font-size: 0.9rem; color: #344054; }

.tombol {
  display: inline-block;
  background: var(--navy);
  color: #fff;
  border: none;
  padding: 10px 20px;
  border-radius: 6px;
  font-size: 0.95rem;
  cursor: pointer;
  text-decoration: none;
}
.tombol:hover { opacity: 0.9; }

/* Tombol aksi UTAMA (mis. "Selesai -- Lanjut ke Dashboard" di halaman
   Proses Impor) -- dibedakan warna & ukuran dari .tombol biasa supaya
   jelas mana langkah lanjutan yang disarankan, bukan cuma salah satu
   dari beberapa tautan yang setara. */
.tombol-utama {
  display: inline-block;
  background: var(--hijau);
  color: #fff;
  border: none;
  padding: 12px 24px;
  border-radius: 6px;
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
}
.tombol-utama:hover { opacity: 0.9; }

/* Ukuran tombol terstandarisasi (Tahap 67) -- menggantikan puluhan variasi
   padding/font-size inline yang tumbuh organik per halaman (6px 14px vs
   7px 14px vs 8px 16px, dst) sehingga tombol yang secara fungsi setara
   (mis. "Cetak"/"Unduh Excel" di berbagai tabel) selalu tampil dengan
   ukuran yang SAMA persis di seluruh aplikasi. `.tombol-sm` = tombol aksi
   di atas panel/tabel (Cetak, Unduh Excel, Terapkan, Simpan, Setujui/
   Tolak, dst). `.tombol-xs` = tombol kecil di dalam baris tabel (Edit,
   Reset, per-baris). */
.tombol-sm, .tombol-utama.tombol-sm { padding: 8px 16px; font-size: 0.85rem; }
.tombol-xs, .tombol-utama.tombol-xs { padding: 4px 10px; font-size: 0.78rem; }

/* Penanda "proses masih hidup" di halaman Proses Impor -- lingkaran kecil
   yang berdenyut terus-menerus SELAMA proses berjalan, supaya pengguna
   tetap yakin halamannya tidak macet walau progres baris belum berubah
   (mis. baru mulai, checkpoint pertama belum lewat). */
@keyframes denyut-hidup {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.4; transform: scale(0.7); }
}
.penanda-hidup {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--hijau);
  margin-right: 6px;
  animation: denyut-hidup 1.1s ease-in-out infinite;
}

/* Bar progres TAK TENTU (indeterminate) -- dipakai SEBELUM checkpoint
   progres pertama (baris_diproses masih 0), saat lebar bar berbasis
   persentase tidak ada gunanya sama sekali (0% = tidak terlihat sama
   sekali, terkesan macet). Garis terang bergerak bolak-balik menandakan
   proses aktif walau angkanya belum bergerak. */
@keyframes geser-tak-tentu {
  0% { left: -35%; }
  100% { left: 100%; }
}
.bar-tak-tentu {
  position: absolute;
  top: 0; bottom: 0;
  width: 35%;
  background: var(--hijau);
  border-radius: 999px;
  animation: geser-tak-tentu 1.2s ease-in-out infinite;
}

/* Kumpulan tombol aksi (mis. Lihat Mode Demo/Cetak Laporan/Unduh Excel di
   Dashboard, Aktifkan/Hapus Data Contoh di Mode Demo) -- SENGAJA flexbox
   dengan gap, bukan tombol inline + margin-left seperti sebelumnya, supaya
   saat tombolnya membungkus ke baris baru di layar sempit (HP) tetap ada
   jarak vertikal antar barisnya. Tombol inline+margin-left cuma punya
   jarak HORIZONTAL; begitu membungkus, baris keduanya langsung menempel
   rapat ke baris pertama (bahkan bisa terkesan bertumpuk). */
.tombol-grup {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 16px;
}

.peringatan {
  background: #FDF1DD;
  border-left: 4px solid var(--oranye);
  padding: 10px 14px;
  border-radius: 4px;
  margin-bottom: 14px;
  font-size: 0.88rem;
}

.info {
  background: #EAF1FB;
  border-left: 4px solid var(--navy);
  padding: 10px 14px;
  border-radius: 4px;
  margin-bottom: 14px;
  font-size: 0.88rem;
}

/* Tahap 158 -- disclaimer estimasi rupiah (disclaimer_rupiah() di
   _macros.html), sebelumnya (Tahap 157) tombol pil + modal overlay,
   sekarang jadi accordion <details>/<summary> di tempat -- tidak ada
   overlay/backdrop lagi, isinya muncul langsung di bawah barnya. */
.disclaimer-inline { margin-bottom: 14px; }

.disclaimer-bar {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 8px;
  background: #FDF1DD;
  border-left: 4px solid var(--oranye);
  padding: 10px 14px;
  border-radius: 8px;
  font-size: 0.95rem;
}
.disclaimer-bar::-webkit-details-marker { display: none; }
.disclaimer-bar::before {
  content: "\25B8";
  color: var(--oranye);
  transition: transform .15s ease;
}
.disclaimer-inline[open] > .disclaimer-bar::before { transform: rotate(90deg); }
.disclaimer-isi {
  margin-top: 2px;
  padding: 12px 16px;
  background: #FFFBF2;
  border-left: 4px solid var(--oranye);
  border-radius: 0 0 8px 8px;
  font-size: 0.95rem;
  line-height: 1.6;
  color: #1B2430;
  text-align: justify;
  text-align-last: left;
}
.disclaimer-isi ul { margin: 6px 0 0; padding-left: 20px; }

/* Tahap 134.1 -- judul "DISCLAIMER ON !!!" berkedip lembut ("bernafas",
   bukan blink kasar) antara navy gelap & oranye identitas aplikasi supaya
   tetap menarik perhatian setiap kali halaman dibuka TANPA terasa norak/
   mengganggu -- dua warna yang sudah dipakai di tempat lain aplikasi ini
   (navy = warna utama, oranye = border kotak disclaimer sendiri), jadi
   tetap terasa satu identitas, bukan warna asing baru. Siklus 2.6 detik
   naik-turun halus (ease-in-out) meniru ritme napas tenang, bukan
   berkedip cepat yang melelahkan mata. Dihormati prefers-reduced-motion
   -- berhenti jadi warna oranye statis untuk pengguna yang sensitif
   terhadap animasi. */
.disclaimer-judul-berkedip {
  color: var(--navy);
  text-shadow: 0 0 0 rgba(224, 142, 0, 0);
  animation: nafas-disclaimer 2.6s ease-in-out infinite;
}
@keyframes nafas-disclaimer {
  0%, 100% { color: var(--navy); text-shadow: 0 0 0 rgba(224, 142, 0, 0); }
  50% { color: var(--oranye); text-shadow: 0 0 8px rgba(224, 142, 0, 0.55); }
}
@media (prefers-reduced-motion: reduce) {
  .disclaimer-judul-berkedip { animation: none; color: var(--oranye); }
}

/* Tahap 158 -- pie chart pembobotan wilayah (pembobotan_wilayah_ringkas()
   di _macros.html), sebelumnya (Tahap 157) kartu sticky dua kolom di
   kanan tabel, sekarang jadi accordion <details>/<summary> satu kolom
   lurus di atas tabel -- diciutkan default jadi satu baris ringkasan
   ("Pembobotan Wilayah: ... +N wilayah lainnya"), diklik untuk melihat
   donut lengkap di tempat. ".panel" (style.css atas) sudah memberi
   kartu putih+shadow; di sini cuma atur summary-nya. */
.ringkas-pembobotan { margin-bottom: 14px; }
.ringkas-strip {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.92rem;
  color: #475467;
}
.ringkas-strip::-webkit-details-marker { display: none; }
.ringkas-strip::before {
  content: "\25B8";
  color: var(--navy);
  flex-shrink: 0;
  transition: transform .15s ease;
}
.ringkas-pembobotan[open] > .ringkas-strip::before { transform: rotate(90deg); }
.ringkas-isi { margin-top: 14px; }

/* Ringkasan cepat berwarna di puncak Dashboard -- sengaja pakai gradasi
   warna berbeda per kartu (bukan satu warna polos) supaya langsung
   menarik perhatian & masing-masing angka terasa punya "identitas"
   sendiri, konsisten dengan warna status yang sudah dipakai di badge
   (--hijau = baik, --oranye = perlu perhatian, --navy = identitas brand). */
.stat-tile-row {
  display: grid;
  /* Tahap 108, poin 2 -- lebar kartu diperbesar (220-300px -> 260-420px)
     & padding/font ikut naik supaya di layar lebar (panel maks. 2200px,
     lihat .konten) kartunya benar-benar mengisi ruang, bukan menyisakan
     kolom kosong lebar di kiri-kanan seperti sebelumnya. auto-fit + batas
     atas + justify-content:center tetap dipertahankan supaya baris kartu
     tetap seimbang di tengah pada layar berapa pun lebarnya, sama seperti
     pola yang dipakai .dashboard-tautan-lanjut & .rekap-hasil-row di
     bawah. */
  grid-template-columns: repeat(auto-fit, minmax(260px, 420px));
  justify-content: center;
  gap: 18px;
  margin-bottom: 14px;
}
.stat-tile {
  display: block;
  border-radius: 14px;
  padding: 22px 24px;
  color: #fff;
  text-decoration: none;
  box-shadow: 0 4px 14px rgba(11, 37, 69, 0.12);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  cursor: pointer;
}
/* Keempat kartu ini SENGAJA diklik-kan ke /dashboard/ranking -- halaman
   itulah yang punya rincian lengkap tiap angka ringkasan di sini (pie
   chart jumlah unit, tabel yang bisa diurutkan jumlah tunggakan, dan
   tabel wilayah terbanyak tindak lanjut). */
.stat-tile:hover, .stat-tile:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 10px 24px rgba(11, 37, 69, 0.26);
}
.stat-tile-angka {
  font-size: clamp(1.5rem, 2.8vw, 2.1rem);
  font-weight: 700;
  line-height: 1.15;
}
.stat-tile-label {
  font-size: 0.92rem;
  opacity: 0.94;
  margin-top: 6px;
}
/* Tahap 108, poin 2 -- affordance klik EKSPLISIT (teks "Lihat rincian ->"),
   bukan cuma mengandalkan efek hover/shadow yang baru terlihat setelah
   kursor sudah di atasnya -- supaya dari sekilas pandang pun sudah jelas
   kartu ini bisa diklik, bukan sekadar tampilan angka statis. */
.stat-tile-lihat {
  font-size: 0.78rem;
  font-weight: 600;
  opacity: 0.85;
  margin-top: 12px;
  letter-spacing: 0.02em;
}
.stat-navy { background: linear-gradient(135deg, #0B2545, #1B3D6D); }
.stat-hijau { background: linear-gradient(135deg, #14663f, #1E8E5A); }
.stat-oranye { background: linear-gradient(135deg, #B36E00, #E08E00); }
.stat-biru { background: linear-gradient(135deg, #1D4E8F, #4A7FD1); }
@media (max-width: 900px) { .stat-tile-row { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .stat-tile-row { grid-template-columns: 1fr; } }

/* Tahap 112, poin 1 -- catatan kecil di bawah kartu "Kabupaten/Kota
   Teridentifikasi" saat ada kendaraan yang alamat kab/kota-nya belum
   teridentifikasi, supaya tetap transparan tanpa ikut dihitung sebagai
   wilayah administratif ke-12 di kartunya sendiri. */
.catatan-belum-teridentifikasi {
  font-size: 0.85rem;
  color: #667085;
  background: #F7F9FC;
  border: 1px solid #E9ECF2;
  border-radius: 8px;
  padding: 8px 14px;
  margin: -6px 0 14px;
}
.catatan-belum-teridentifikasi strong { color: var(--navy); }

/* Tahap 109, poin 1 -- bungkus "Total Tunggakan" jadi SATU kartu besar
   berdiri sendiri (bukan lagi judul teks polos menempel ke konten lain di
   atasnya) supaya terlihat sebagai satu unit informasi yang jelas &
   profesional -- identitas warna oranye konsisten dengan kartu Total
   Tunggakan versi lama yang sekarang digabung ke sini.
   Tahap 113, poin 3 -- diubah dari gradasi PUCAT (nyaris tak beda dari
   .jelajah-section di bawahnya) jadi latar gradasi PEKAT solid warna
   amber/oranye tua dengan teks putih -- supaya kotak paling penting di
   Dashboard ini (satu-satunya angka finansial) langsung menonjol tegas
   sekilas pandang, jelas beda "kelas" dari kartu tautan navigasi biasa.
   Tahap 114, poin 2 -- amber/oranye pekat itu dirasa terlalu "panas"/tidak
   nyaman dipandang setelah section ini dipindah jadi blok PALING ATAS
   Dashboard (lihat dashboard/index.html) -- diganti gradasi navy->teal
   yang senada dengan warna identitas utama aplikasi (--navy: #0B2545),
   jauh lebih "adem" & profesional tapi tetap solid/pekat (BUKAN kembali ke
   gradasi pucat lama) supaya masih menonjol tegas dari kartu navigasi
   biasa di bawahnya. */
.tunggakan-section {
  background: linear-gradient(135deg, #0B2545 0%, #123A5E 55%, #1B6E8C 100%);
  border: none;
  border-radius: 16px;
  padding: 20px 22px 22px;
  margin-bottom: 22px;
  box-shadow: 0 8px 22px rgba(11, 37, 69, 0.28);
}
.tunggakan-section-judul {
  color: #fff;
  font-size: 1.1rem;
  font-weight: 700;
  margin: 0 0 4px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
}
.tunggakan-section-sub {
  color: rgba(255, 255, 255, 0.88);
  font-size: 0.92rem;
  line-height: 1.5;
  margin: 0 0 16px;
}
/* Tahap 109, poin 1 -- CSS Grid (BUKAN flex+wrap seperti sebelumnya) dengan
   kolom eksplisit: kartu-tanda-kartu-tanda-kartu-tanda-kartu. Ini menjamin
   keempat kartu SELALU sejajar rapi dalam satu baris pada layar yang cukup
   lebar (lebar tiap kartu dipaksa sama oleh `1fr`, bukan mengikuti panjang
   kontennya sendiri seperti flex dulu yang bikin baris terlihat berantakan
   saat salah satu angka jauh lebih panjang dari yang lain). Kartu Total
   sedikit lebih lebar (1.15fr) supaya menonjol sebagai hasil akhir. */
.rincian-tunggakan-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr auto 1.15fr;
  align-items: stretch;
  gap: 10px;
}
/* Tahap 113, poin 3 -- kartu komponen (SWDKLLJ/PKB/Opsen) sekarang "kaca
   buram" tembus pandang di atas latar gradasi pekat .tunggakan-section
   (bukan kartu putih polos seperti sebelumnya, yang di atas latar pucat
   dulu nyaris tak beda dari kartu .jelajah-section) -- kartu Total tetap
   dibedakan lewat latar SOLID PUTIH supaya jadi satu-satunya titik paling
   terang & langsung menarik mata sebagai hasil akhir penjumlahan. */
.rincian-tunggakan-kartu {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 10px;
  padding: 14px 16px;
  min-width: 0;
  text-decoration: none;
  transition: box-shadow 0.15s ease, transform 0.15s ease, background 0.15s ease;
}
.rincian-tunggakan-kartu:hover, .rincian-tunggakan-kartu:focus-visible {
  background: rgba(255, 255, 255, 0.22);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.18);
  transform: translateY(-2px);
}
.rincian-tunggakan-label { font-size: 0.85rem; color: rgba(255, 255, 255, 0.85); font-weight: 600; }
.rincian-tunggakan-angka { font-size: 1.2rem; color: #fff; font-weight: 700; word-break: break-word; }
/* Tahap 115, poin 2 -- SWDKLLJ/PKB/Opsen PKB sebelumnya bertiga memakai
   gaya "kaca buram" yang identik, jadi sekilas pandang sulit dibedakan
   komponen mana yang mana kecuali membaca labelnya. Tiap kartu diberi
   aksen warna berbeda (garis kiri + warna label) yang LEMBUT & selaras
   dengan gradasi navy-teal latar belakangnya (bukan warna mencolok/panas
   seperti amber Tahap 113 yang sudah diganti) supaya tetap terasa satu
   keluarga & profesional, sekadar cukup beda untuk dikenali cepat. */
.rincian-tunggakan-swdkllj { border-left: 3px solid #5EEAD4; }
.rincian-tunggakan-swdkllj .rincian-tunggakan-label { color: #99F6E4; }
.rincian-tunggakan-pkb { border-left: 3px solid #FDE68A; }
.rincian-tunggakan-pkb .rincian-tunggakan-label { color: #FDE68A; }
.rincian-tunggakan-opsen { border-left: 3px solid #C4B5FD; }
.rincian-tunggakan-opsen .rincian-tunggakan-label { color: #DDD6FE; }
.rincian-tunggakan-total {
  background: #fff;
  border-color: #fff;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
}
.rincian-tunggakan-total:hover, .rincian-tunggakan-total:focus-visible {
  background: #fff;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.28);
}
.rincian-tunggakan-total .rincian-tunggakan-label { color: #145E7A; }
.rincian-tunggakan-total .rincian-tunggakan-angka { color: #0B2545; }
.rincian-tunggakan-lihat { font-size: 0.76rem; font-weight: 600; color: rgba(255, 255, 255, 0.8); margin-top: 2px; }
.rincian-tunggakan-total .rincian-tunggakan-lihat { color: #1B6E8C; }
.rincian-tunggakan-plus {
  display: flex;
  align-items: center;
  color: rgba(255, 255, 255, 0.75);
  font-size: 1.4rem;
  font-weight: 700;
}
/* Layar sedang -- 7 kolom sudah terlalu sempit untuk tetap nyaman dibaca,
   turun jadi grid 2 kolom (tanda +/= disembunyikan, urutan tetap terbaca
   sebagai daftar 4 kartu). */
@media (max-width: 1000px) {
  .rincian-tunggakan-row { grid-template-columns: 1fr 1fr; }
  .rincian-tunggakan-plus { display: none; }
}
@media (max-width: 560px) {
  .rincian-tunggakan-row { grid-template-columns: 1fr; }
}

/* Rekapitulasi hasil kunjungan RT per kategori (Sudah Dibayar, Janji
   Bayar, dst) -- tombol-tombol berwarna di atas Peta Interaktif Dashboard,
   pola visual sama seperti .stat-tile (kartu gradasi warna, bisa diklik)
   tapi warnanya SATU PER KATEGORI (bukan makna status baik/perlu
   perhatian) supaya tiap kategori gampang dibedakan sekilas pandang. */
/* Tahap 112, poin 4 -- SELALU tepat 3 kolom (bukan auto-fit yang bisa jatuh
   ke 4+2 atau kombinasi ganjil lain tergantung lebar layar persis) supaya
   keenam kategori HASIL_KUNJUNGAN konsisten tersusun rapi 3 di atas + 3 di
   bawah pada layar lebar, turun ke 2 kolom lalu 1 kolom di layar sempit
   (breakpoint sama seperti sebelumnya). */
.rekap-hasil-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 26px;
}
/* Tata letak HORIZONTAL (ikon di kiri dalam lencana bulat, teks mengisi
   sisa lebar di kanan) -- BUKAN ditumpuk vertikal seperti percobaan
   pertama, yang di HP (kartu jadi 1 kolom selebar layar penuh) membuat
   konten menggerombol di kiri & menyisakan ruang kosong besar di kanan.
   Pola ini meniru .podium-tempat yang sudah terbukti proporsional di
   segala lebar layar. */
.rekap-hasil-tombol {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 16px;
  border-radius: 14px;
  padding: 16px 20px;
  color: #fff;
  text-decoration: none;
  box-shadow: 0 4px 14px rgba(11, 37, 69, 0.12);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  cursor: pointer;
}
.rekap-hasil-tombol:hover, .rekap-hasil-tombol:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(11, 37, 69, 0.22);
}
.rekap-hasil-ikon {
  flex-shrink: 0;
  width: 54px;
  height: 54px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.7rem;
  line-height: 1;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
  box-shadow: inset 0 1px 3px rgba(255, 255, 255, 0.3);
}
.rekap-hasil-info { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.rekap-hasil-label { font-size: 0.92rem; font-weight: 700; opacity: 0.95; line-height: 1.35; }
.rekap-hasil-angka { font-size: 1.22rem; font-weight: 700; margin-top: 7px; }
.rekap-hasil-pct { font-size: 0.85rem; opacity: 0.85; margin-top: 2px; }
.rekap-hijau { background: linear-gradient(135deg, #14663f, #1E8E5A); }
.rekap-emas { background: linear-gradient(135deg, #8A5A00, #E0A72E); }
.rekap-biru { background: linear-gradient(135deg, #1D4E8F, #4A7FD1); }
.rekap-ungu { background: linear-gradient(135deg, #5B2A86, #8B5CC7); }
.rekap-merah { background: linear-gradient(135deg, #8A1F1F, #C0392B); }
.rekap-abu { background: linear-gradient(135deg, #40495A, #667085); }
@media (max-width: 700px) { .rekap-hasil-row { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 420px) { .rekap-hasil-row { grid-template-columns: 1fr; } }

/* Kartu tautan ke sub-halaman Dashboard (Ranking Kabupaten/Kota, Peringkat
   RT, Ranking Jenis Kendaraan) -- dipisah dari halaman utama supaya tidak
   menumpuk semua tabel/grafik sekaligus, lihat app/routers/dashboard.py. */
.dashboard-tautan-lanjut {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 400px));
  justify-content: center;
  gap: 16px;
  margin-bottom: 26px;
}
.dashboard-kartu-tautan {
  display: block;
  position: relative;
  background: #fff;
  border: 1px solid #E2E7F0;
  border-left: 5px solid var(--aksen, var(--navy));
  border-radius: 12px;
  padding: 18px 20px 18px 54px;
  text-decoration: none;
  transition: box-shadow 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.dashboard-kartu-tautan:hover { box-shadow: 0 8px 20px rgba(11, 37, 69, 0.18); transform: translateY(-3px); }
.dashboard-kartu-tautan strong { display: block; color: var(--navy); font-size: 1.04rem; margin-bottom: 5px; }
.dashboard-kartu-tautan span:not(.dashboard-kartu-ikon) { display: block; color: #667085; font-size: 0.9rem; line-height: 1.5; }
.dashboard-kartu-ikon {
  position: absolute;
  left: 14px;
  top: 16px;
  font-size: 1.15rem;
  line-height: 1;
}
.kartu-navy { --aksen: var(--navy); }
.kartu-hijau { --aksen: var(--hijau); }
.kartu-oranye { --aksen: var(--oranye); }
.kartu-biru { --aksen: #1D4E8F; }
.kartu-ungu { --aksen: #6D3FA8; }

/* Tahap 112, poin 3 -- bungkus kartu-kartu tautan Peringkat di atas jadi
   SATU kotak section berdiri sendiri (pola sama seperti .tunggakan-section,
   tapi aksen biru muda -- BUKAN oranye -- supaya kedua blok jelas beda
   "zona" sekilas pandang, tidak menyatu tanpa batas seperti sebelumnya). */
.jelajah-section {
  background: linear-gradient(180deg, #F3F7FF 0%, #fff 65%);
  border: 1px solid #D7E3FA;
  border-radius: 16px;
  padding: 20px 22px 22px;
  margin-bottom: 26px;
  box-shadow: 0 4px 14px rgba(11, 37, 69, 0.06);
}
.jelajah-section-judul { color: var(--navy); font-size: 1.05rem; font-weight: 700; margin: 0 0 4px; }
.jelajah-section-sub { color: #667085; font-size: 0.92rem; line-height: 1.5; margin: 0 0 16px; }
.jelajah-section .dashboard-tautan-lanjut { margin-bottom: 0; }

/* Menu Laporan (Tahap 94) -- kartu per jenis laporan yang bisa dicetak/
   diunduh, dipakai bersama variabel warna --aksen dari .kartu-* di atas. */
.laporan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
  margin-top: 18px;
}
.laporan-kartu {
  background: #fff;
  border: 1px solid #E2E7F0;
  border-top: 4px solid var(--aksen, var(--navy));
  border-radius: 12px;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
}
.laporan-kartu h3 { margin: 0 0 8px; color: var(--navy); font-size: 1.05rem; }
.laporan-kartu p { margin: 0 0 14px; color: #667085; font-size: 0.88rem; line-height: 1.55; flex-grow: 1; }
.laporan-kartu .tombol-grup { margin-bottom: 0; }

/* Judul Dashboard (kiri) + kotak "Info Database" (kanan, pojok kanan atas
   panel utama) sebaris -- bukan panel terpisah lebar-penuh seperti
   sebelumnya, supaya tidak boros ruang. */
.dashboard-atas {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  flex-wrap: wrap;
  /* Tahap 115, poin 3 -- tanpa jarak bawah di sini, kotak Info Database
     langsung menempel ke kotak berikutnya (disclaimer rupiah / kotak
     "Belum ada data") begitu saja, karena keduanya sama-sama kotak
     berlatar/berbingkai yang tidak punya margin-atas sendiri. */
  margin-bottom: 18px;
}
.dashboard-atas-judul { flex: 1 1 320px; min-width: 0; }

.info-db-mini {
  flex: 0 0 auto;
  background: #F7F9FB;
  border: 1px solid #E5E9EF;
  border-radius: 10px;
  padding: 10px 14px;
  min-width: 200px;
}
.info-db-mini h2 {
  margin: 0 0 6px;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #667085;
}
.info-db-mini p { margin: 3px 0; font-size: 0.9rem; color: #333; white-space: nowrap; }
.info-db-mini p strong { color: var(--navy); }
@media (max-width: 700px) {
  .info-db-mini { flex-basis: 100%; }
  .info-db-mini p { white-space: normal; }
}

.peringkat-rt-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}
/* min-width:0 SENGAJA -- tanpa ini, tabel lebar di dalam grid item
   memaksa kolom grid melebar mengikuti lebar mentah tabelnya (bukan
   1fr yang seharusnya), mendorong seluruh halaman scroll ke samping.
   Dengan ini, .tabel-scroll di dalamnya yang menangani lebarnya sendiri. */
.peringkat-rt-grid > div { min-width: 0; }
@media (max-width: 900px) {
  .peringkat-rt-grid { grid-template-columns: 1fr; }
}

/* Podium 3 besar untuk papan "RT Terbaik" & podium Dashboard -- kartu
   ringkas dengan aksen garis atas emas/perak/perunggu. Tata letak
   HORIZONTAL (medali di kiri, nama+detail di tengah/kanan) -- BUKAN
   ditumpuk vertikal seperti sebelumnya -- supaya medalinya bisa
   diperbesar tanpa kartu jadi terlalu tinggi, dan urutan kartunya dari
   KIRI KE KANAN Juara 1/2/3 (bukan urutan podium sungguhan 2-1-3) --
   lihat urutan <a> di podium_tiga_besar()/papan_peringkat_rt() di
   _macros.html, CSS di sini cuma mengikuti urutan DOM apa adanya. */
.podium-rt {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  align-items: stretch;
  gap: 10px;
  margin-bottom: 18px;
}
.podium-tempat {
  display: flex;
  flex-direction: row;
  align-items: center;
  text-align: left;
  gap: 10px;
  text-decoration: none;
  color: inherit;
  background: #fff;
  /* min-width:0 WAJIB -- item grid/flex secara bawaan tidak mau menyusut
     lebih kecil dari lebar minimum kontennya sendiri (nama wilayah yang
     tidak dibungkus paksa), akibatnya di lebar layar tanggung kartu ini
     bisa "bocor"/tumpang tindih ke kartu sebelahnya alih-alih membungkus
     teksnya. Ini jaring pengaman terakhir supaya itu TIDAK PERNAH terjadi
     lagi di lebar berapa pun, di luar perbaikan titik ambang di bawah. */
  min-width: 0;
  border: 2px solid #E9ECF2;
  border-radius: 12px;
  padding: 12px 12px;
  transition: box-shadow .15s ease, transform .15s ease;
}
.podium-medali-wrap { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; gap: 5px; }
/* Medali dibuat jadi lencana bulat (gradasi radial + bayangan) -- bukan
   cuma emoji polos -- supaya lebih menonjol & "menarik" sesuai
   permintaan pengguna. Ukuran lingkaran tetap dijaga proporsional
   dengan tinggi kartu (jangan sampai kartu jadi tinggi sekali). */
.podium-medali {
  font-size: 1.9rem;
  line-height: 1;
  width: 50px;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  box-shadow: 0 2px 6px rgba(11, 37, 69, 0.18), inset 0 1px 3px rgba(255, 255, 255, 0.6);
}
/* Label "Juara N" diberi latar pil berwarna solid (bukan teks abu-abu
   kecil) supaya kontras & terbaca jelas pada sekilas pandang. */
.podium-label-juara {
  font-size: 0.68rem;
  font-weight: 800;
  color: #fff;
  padding: 2px 10px;
  border-radius: 20px;
  white-space: nowrap;
  letter-spacing: .01em;
}
.podium-info { min-width: 0; }
.podium-nama { font-weight: 700; color: var(--navy); font-size: 0.86rem; }
.podium-sub { color: #8A93A6; font-size: 0.7rem; margin-top: 1px; }
.podium-pct { font-weight: 700; font-size: 0.88rem; margin-top: 5px; }
/* Bobot proporsi -- dipakai di podium_tiga_besar() (Dashboard), digabung
   SATU BARIS dengan .podium-pct (bukan baris terpisah) supaya kartunya
   tidak makin tinggi/penuh; TIDAK dipakai di papan_peringkat_rt() lama
   (podium-pct sudah cukup di sana). */
.podium-bobot { font-weight: 400; color: #97A1B3; font-size: 0.68rem; }
.podium-emas { border-color: #E8AC1E; background: linear-gradient(180deg, #FFFAEE 0%, #fff 65%); }
.podium-emas .podium-nama { font-size: 0.9rem; }
.podium-emas .podium-pct { color: #A87400; }
.podium-emas .podium-medali { background: radial-gradient(circle at 35% 28%, #FFEFC2, #E8AC1E 72%); }
.podium-emas .podium-label-juara { background: #E8AC1E; }
.podium-perak { border-color: #9AA4B5; }
.podium-perak .podium-pct { color: #5B6472; }
.podium-perak .podium-medali { background: radial-gradient(circle at 35% 28%, #F3F5F8, #9AA4B5 72%); }
.podium-perak .podium-label-juara { background: #8A93A6; }
.podium-perunggu { border-color: #C07C41; background: linear-gradient(180deg, #FDF5EE 0%, #fff 65%); }
.podium-perunggu .podium-pct { color: #8A5321; }
.podium-perunggu .podium-medali { background: radial-gradient(circle at 35% 28%, #F5D6B4, #C07C41 72%); }
.podium-perunggu .podium-label-juara { background: #C07C41; }
.podium-tempat:hover { box-shadow: 0 4px 14px rgba(11, 37, 69, 0.1); transform: translateY(-2px); }
/* Kartu horizontal (medali + teks berdampingan) butuh lebih banyak lebar
   daripada versi tumpuk-vertikal lama -- di HP, 3 kartu sejajar jadi
   terlalu sempit, jadi ditumpuk 1 kolom supaya tetap proporsional &
   tidak ada teks yang terpotong/bertumpuk. Titik ambang ini SENGAJA
   dipakai berdiri sendiri dari titik ambang .podium-dua-periode di bawah
   (yang jauh lebih besar) -- begitu 2 periode berdampingan aktif, lebar
   yang tersisa untuk tiap periode cuma separuh layar, jadi 3 kartu di
   dalamnya tetap perlu ditumpuk sampai lebar yang JAUH lebih besar
   daripada saat cuma 1 periode yang tampil. */
@media (max-width: 600px) {
  .podium-rt { grid-template-columns: 1fr; }
}

/* Bungkus tiap tingkat wilayah (Kabupaten/Kota, Kecamatan, dst) dalam
   panel lembut sendiri-sendiri -- supaya keempatnya (x2 periode = 8 blok
   podium) tidak melebur jadi satu tumpukan panjang tanpa jeda di atas
   latar putih polos, yang sebelumnya terkesan ramai/padat. */
.podium-level {
  background: #FAFBFD;
  border: 1px solid #EEF1F5;
  border-radius: 14px;
  padding: 16px 18px 18px;
  margin-bottom: 14px;
}
.podium-level h3 { margin-top: 0; }
.podium-level-terakhir { margin-bottom: 0; }
@media (max-width: 640px) {
  .podium-level { padding: 14px 12px 16px; }
}

/* Podium dibagi 2 periode berdampingan (Bulan Ini | Tahun Berjalan). Tahap
   100 -- garis tipis 1px sebelumnya (border-left#E5E9EF) dilaporkan
   pengguna KURANG TEGAS, gampang terlewat sekilas mata sehingga kedua
   periode terkesan melebur jadi satu tabel besar. Diganti jadi KOTAK
   terpisah sendiri-sendiri per periode (border tebal + latar putih
   kontras dari latar .podium-level di belakangnya) -- pemisahnya sekarang
   bukan cuma garis tipis di tengah, tapi bentuk kotak utuh yang jelas
   batasnya di keempat sisi, tetap konsisten dipakai di layout
   berdampingan (desktop) maupun ditumpuk (HP), tidak perlu aturan
   terpisah lagi untuk breakpoint sempit. */
.podium-dua-periode {
  display: flex;
  align-items: stretch;
  gap: 18px;
  margin-bottom: 6px;
}
.podium-periode-kolom {
  flex: 1 1 0;
  min-width: 0;
  padding: 14px 16px 16px;
  background: #fff;
  border: 2px solid #CBD3DE;
  border-radius: 12px;
}
.podium-periode-kolom h4 { margin: 0 0 10px; font-size: 0.9rem; color: var(--navy); }
/* Titik ambang ini SENGAJA jauh lebih besar daripada breakpoint umum lain
   di file ini (mis. 800px) -- 2 periode berdampingan artinya 2 SET kartu
   podium 3-kolom sekaligus (6 kartu total) harus muat berdampingan, itu
   butuh jauh lebih banyak lebar daripada sekadar 2 kolom teks/tabel
   biasa. Titik ambang lama (800px) TERLALU RENDAH -- terbukti dari
   laporan pengguna: di lebar sedang (~800-1100px, umum terjadi di HP
   dengan pengaturan "Ukuran tampilan/Screen zoom" diperkecil), 2 periode
   sudah berdampingan padahal tiap kartu di dalamnya jadi cuma ~120px,
   jauh di bawah kebutuhan minimalnya -- teks & lencana medali jadi
   tumpang tindih/melewati batas kartu. */
@media (max-width: 1200px) {
  .podium-dua-periode { flex-direction: column; gap: 14px; }
}

.rt-bar-list { display: flex; flex-direction: column; gap: 6px; }
.rt-bar-baris {
  display: flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: inherit;
}
.rt-bar-rank {
  flex: 0 0 20px;
  text-align: center;
  font-weight: 700;
  font-size: 0.8rem;
  color: #667085;
}
.rt-bar-track {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  height: 30px;
  border-radius: 7px;
  background: #EDEFF2;
  overflow: hidden;
}
.rt-bar-isi { position: absolute; inset: 0; width: 0; transition: width 0.2s ease; }
.rt-bar-list-terbaik .rt-bar-isi { background: linear-gradient(90deg, #8FDCB3, #1E8E5A); }
.rt-bar-list-perhatian .rt-bar-isi { background: linear-gradient(90deg, #F6B99A, #C62828); }
.rt-bar-label {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  height: 100%;
  padding: 0 10px;
  font-weight: 600;
  font-size: 0.82rem;
  color: var(--navy);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rt-bar-angka { flex: 0 0 auto; font-size: 0.76rem; color: #667085; white-space: nowrap; }
.rt-bar-baris:hover .rt-bar-label { text-decoration: underline; }
@media (max-width: 480px) {
  .rt-bar-angka { display: none; }
}


/* ---------- Menu (hamburger) & sentuhan lebih nyaman di layar HP ----------
   Pakai checkbox tersembunyi + <label> (bukan JS) supaya tetap berfungsi
   tanpa skrip tambahan, sejalan dengan pola <details>/<summary> nav-drop
   di atas. */
.nav-toggle-cb { display: none; }
.nav-toggle-lbl { display: none; }

@media (max-width: 800px) {
  .nav-toggle-lbl {
    display: block;
    color: #fff;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    padding: 4px 8px;
  }
  .topbar .nav {
    display: none;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    flex-basis: 100%;
    gap: 2px;
    margin-top: 6px;
    border-top: 1px solid rgba(255,255,255,0.15);
    padding-top: 8px;
  }
  .nav-toggle-cb:checked ~ .nav { display: flex; }
  .topbar .nav a, .topbar .nav > span {
    margin-left: 0;
    padding: 10px 4px;
  }
  .topbar .nav > .nav-akun {
    margin: 6px 0 0;
    padding: 0;
    align-self: flex-start;
    gap: 14px;
  }
  .topbar .nav .status-user {
    padding: 6px 14px;
  }
  .nav-drop { margin-left: 0; width: 100%; }
  .nav-drop summary { padding: 10px 4px; }
  .nav-drop-menu {
    position: static;
    box-shadow: none;
    padding: 0 0 0 14px;
    min-width: 0;
  }
}

/* Daftar Pengguna (Tahap 48) -- diganti dari satu tabel lebar (perlu
   digeser horizontal) jadi grup <details> berlapis mengikuti hierarki
   wilayah (Kab/Kota -> Kecamatan -> Kelurahan/Desa -> RT), tertutup
   sampai diklik, dan tiap akun jadi baris flex ringkas (bukan kolom
   tabel kaku) -- otomatis membungkus di layar sempit tanpa perlu
   scrollbar horizontal sama sekali. */
/* Tahap 131 -- kotak "ringkas" untuk sub-seksi di dalam panel utama (mis.
   toolbar Kirim Massal & accordion Tulis/Uji Pesan WhatsApp di halaman
   Kirim Pesan WhatsApp/kendaraan/kontak.html) -- padding lebih kecil dari
   .panel biasa, dan untuk sub-seksi yang tidak dipakai tiap kunjungan
   halaman (menulis ulang template pesan, uji kirim) dibungkus <details>
   tertutup by default (pola sama .pengguna-peran/.pengguna-cabang di
   bawah) supaya tabel utama langsung terlihat tanpa scroll panjang, baik
   di HP maupun PC, tanpa menghilangkan fitur apa pun -- cuma disembunyikan
   sampai diklik. */
.panel-ringkas {
  background: #F7F9FB;
  border: 1px solid #E5E9EF;
  border-radius: 10px;
  padding: 12px 16px;
  margin-bottom: 12px;
}
details.panel-ringkas { padding: 0; }
details.panel-ringkas > summary {
  cursor: pointer;
  list-style: none;
  padding: 12px 16px;
  color: var(--navy);
  font-weight: 600;
  font-size: 0.92rem;
}
details.panel-ringkas > summary::-webkit-details-marker { display: none; }
details.panel-ringkas > summary::before { content: "\25B8 "; color: #98A2B3; }
details.panel-ringkas[open] > summary::before { content: "\25BE "; }
details.panel-ringkas > summary + div { padding: 0 16px 14px; }

.pengguna-peran, .pengguna-cabang {
  border: 1px solid #E5E9EF;
  border-radius: 8px;
  margin-bottom: 8px;
  overflow: hidden;
}
.pengguna-peran > summary, .pengguna-cabang > summary {
  cursor: pointer;
  list-style: none;
  padding: 10px 14px;
  background: #F7F9FB;
  color: var(--navy);
  font-size: 0.92rem;
}
.pengguna-cabang > summary { background: #FAFBFD; font-size: 0.88rem; }
.pengguna-peran > summary::-webkit-details-marker, .pengguna-cabang > summary::-webkit-details-marker { display: none; }
.pengguna-peran > summary::before, .pengguna-cabang > summary::before { content: "\25B8 "; color: #98A2B3; }
.pengguna-peran[open] > summary::before, .pengguna-cabang[open] > summary::before { content: "\25BE "; }
.pengguna-jumlah { font-weight: 400; color: #667085; font-size: 0.85em; }

/* Ringkasan status (Tahap 49) -- rincian aktif/nonaktif & online/offline
   di baris judul tiap kelompok/cabang, supaya bisa dilihat tanpa perlu
   membuka grupnya dulu. Simbol titik & warnanya SENGAJA sama persis
   dengan badge status per akun (.pengguna-status di baris_pengguna())
   supaya konsisten satu bahasa visual. Badge yang count-nya 0 tidak
   dirender (lihat macro ringkasan_status()), jadi tidak berjejalan. */
.pengguna-ringkasan { display: inline-flex; flex-wrap: wrap; gap: 4px 10px; margin-left: 4px; font-size: 0.78rem; font-weight: 600; vertical-align: middle; }
.titik-status { white-space: nowrap; }
.titik-online { color: var(--hijau); }
.titik-offline { color: #667085; }
.titik-nonaktif { color: var(--merah); }

/* Subjudul kelompok gabungan (Tahap 49, mis. "Tim Pembina SAMSAT
   Daerah" yang sekarang mencakup Jasa Raharja + Walikota/Bupati/BPPRD
   -- lihat _SUBJUDUL_KELOMPOK_GABUNGAN di pengguna.py) -- menjelaskan
   kenapa kelompok itu berisi akun-akun dari beberapa institusi. */
.pengguna-subjudul { color: #667085; font-size: 0.82rem; margin: 0 0 8px; }

.pengguna-peran-isi { padding: 4px 14px 8px; }
.pengguna-cabang-isi { padding: 2px 6px 6px 18px; }
.pengguna-daftar { display: flex; flex-direction: column; }
.pengguna-baris {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 16px;
  padding: 9px 6px;
  border-bottom: 1px solid #EEF1F5;
}
.pengguna-baris:last-child { border-bottom: none; }
.pengguna-identitas { display: flex; align-items: center; gap: 8px; flex: 1 1 220px; min-width: 0; }
.pengguna-username { font-weight: 700; color: var(--navy); font-size: 0.9rem; }
.pengguna-nama { color: #475467; font-size: 0.85rem; }
.pengguna-kontak { color: #667085; font-size: 0.8rem; flex: 1 1 200px; min-width: 0; }
.pengguna-status { flex: 0 0 auto; }
.pengguna-aksi { flex: 0 0 auto; display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }

/* Bilah konfirmasi batch (Tahap 48) -- dipakai di Daftar Pengguna &
   Manajemen Hak Akses. Mengambang di bawah, muncul HANYA kalau ada
   perubahan yang belum diterapkan -- perubahan sungguhan baru dikirim ke
   server begitu "Terapkan/Confirm Semua" ditekan, bukan tiap klik. */
.batch-bar {
  position: fixed;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--navy);
  color: #fff;
  padding: 10px 16px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  gap: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.28);
  z-index: 40;
  max-width: calc(100vw - 24px);
  flex-wrap: wrap;
  justify-content: center;
}
.tombol-toggle-pending { background: var(--oranye) !important; }

/* Baris tabel Manajemen Hak Akses yang sedang ditandai berubah (belum
   dikirim ke server) -- lihat skrip di hak_akses_daftar.html. */
tr.hakakses-baris-berubah { background: #FFFBEA; }
tr.hakakses-baris-reset .hakakses-cek { opacity: 0.55; }

@media (max-width: 640px) {
  .konten { padding: 10px 8px 40px; }
  .panel { padding: 14px; }

  /* Input/select minimal 16px supaya Safari iOS tidak otomatis zoom saat
     fokus, dan tombol dibuat lebih lega untuk jari (bukan kursor mouse). */
  .form-baris select, .form-baris input, .form-baris textarea {
    font-size: 16px;
    padding: 10px;
  }
  .tombol { padding: 10px 18px; }
  table.tabel { font-size: 0.82rem; }
  table.tabel th, table.tabel td { padding: 7px 8px; }
  .tabel-kv td:first-child { width: 120px !important; }
}

/* Tahap 141 -- komponen bersama untuk halaman referensi/manajemen data yang
   perlu terasa "profesional & representatif" untuk dipakai memonitor &
   mengelola (Database Alamat, Manajemen Akun), BUKAN gradasi warna mencolok
   ala kartu Dashboard (.stat-tile) yang cocok untuk ringkasan
   "marketing/insight" -- di sini datanya dipakai kerja sehari-hari, jadi
   nadanya sengaja lebih adem/netral (kartu putih, aksen warna tipis di
   kiri), konsisten dengan nada ".info"/".tabel-desa-rt" yang sudah ada. */
.ringkasan-mini-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin: 14px 0 22px;
}
.ringkasan-mini-kartu {
  background: #fff;
  border: 1px solid #E5E9EF;
  border-left: 4px solid var(--navy);
  border-radius: 10px;
  padding: 14px 16px;
  text-decoration: none;
  color: inherit;
  display: block;
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}
a.ringkasan-mini-kartu:hover, a.ringkasan-mini-kartu:focus-visible {
  box-shadow: 0 6px 16px rgba(11, 37, 69, 0.1);
  transform: translateY(-2px);
}
.ringkasan-mini-kartu.aksen-hijau { border-left-color: var(--hijau); }
.ringkasan-mini-kartu.aksen-oranye { border-left-color: var(--oranye); }
.ringkasan-mini-kartu.aksen-merah { border-left-color: var(--merah); }
.ringkasan-mini-angka {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--navy);
  line-height: 1.15;
}
.ringkasan-mini-label {
  font-size: 0.8rem;
  color: #667085;
  margin-top: 4px;
}
.ringkasan-mini-kartu.aksen-hijau .ringkasan-mini-angka { color: var(--hijau); }
.ringkasan-mini-kartu.aksen-oranye .ringkasan-mini-angka { color: var(--oranye); }
.ringkasan-mini-kartu.aksen-merah .ringkasan-mini-angka { color: var(--merah); }

/* Pil kecil untuk jumlah (mis. "11 kecamatan"), pengganti teks abu-abu
   polos -- lebih jelas dipisahkan dari nama wilayah/entitas di sebelahnya. */
.pil-hitung {
  display: inline-block;
  background: #EDEFF2;
  color: #555;
  font-weight: 600;
  font-size: 0.76rem;
  padding: 2px 9px;
  border-radius: 999px;
  margin-left: 6px;
}

/* Toolbar aksi admin (Koreksi Ejaan / Tambah Wilayah Baru, dst) -- baris
   tombol rapi berdampingan, menggantikan tumpukan <details> polos yang
   terasa berantakan saat beberapa aksi ada sekaligus di satu tempat. */
.toolbar-aksi {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.toolbar-aksi > details {
  border: 1px solid #E5E9EF;
  border-radius: 8px;
  background: #FAFBFC;
}
.toolbar-aksi > details > summary {
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 7px 12px;
  color: var(--navy);
  list-style: none;
  user-select: none;
}
.toolbar-aksi > details > summary::-webkit-details-marker { display: none; }
.toolbar-aksi > details[open] { background: #F5F8FC; }
.toolbar-aksi > details > summary::before { content: "\25B8\0020"; font-size: 0.7rem; }
.toolbar-aksi > details[open] > summary::before { content: "\25BE\0020"; }
.toolbar-aksi-form {
  padding: 0 12px 12px;
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

/* Kotak pencarian cepat wilayah (client-side, lihat JS di daftar.html) --
   dipakai memfilter hierarki 1.500+ baris tanpa perlu scroll manual. */
.pencarian-wilayah {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.pencarian-wilayah input[type="search"] {
  flex: 1 1 320px;
  padding: 9px 14px;
  border: 1px solid #D0D5DD;
  border-radius: 8px;
  font-size: 0.92rem;
}
.pencarian-wilayah input[type="search"]:focus { border-color: var(--navy); outline: none; }
.pencarian-wilayah-info { font-size: 0.82rem; color: #667085; }
mark.tanda-cocok { background: #FFF3B0; color: inherit; padding: 0 1px; border-radius: 2px; }
details.wilayah-tersembunyi { display: none !important; }
