/* Agrinas Hub — satu berkas gaya. Tanpa framework, tanpa JS. */
:root {
  /* Palet Agrinas */
  /* Hijau diselaraskan ke identitas Agrinas (#1a7f37) — lebih cerah & segar.
     hijau-600 (#1f8739) adalah latar tombol; putih di atasnya tetap 4.58:1 (LULUS WCAG AA). */
  --hijau-900: #12402a; --hijau-800: #175433; --hijau-700: #1a7f37;
  --hijau-600: #1f8739; --hijau-500: #37b45c; --hijau-300: #97dfae; --hijau-100: #ecf9f0;
  /* Netral */
  --tinta: #101d18; --tinta-2: #3d4d46; --pudar: #5f6f68;
  --garis: #dfe6e2; --garis-2: #eef3f1; --latar: #f2f6f4; --putih: #fff;
  --zebra: #f8fbf9;
  /* Keadaan — semua >= 4.5:1 di atas latarnya */
  --kuning: #7a4c00; --kuning-l: #fdf3e0; --kuning-g: #ecc78a;
  --merah: #a32218; --merah-l: #fdeeec; --merah-g: #f3c0ba;
  --biru: #14509e; --biru-l: #eaf2fd; --biru-g: #b6cdf0;
  --hijau-l: #e8f7ef; --hijau-g: #a9e0c2;
  /* Bentuk */
  --r: 12px; --r-kecil: 8px; --r-mini: 6px; --r-kapsul: 999px;
  --bayang: 0 1px 2px rgba(16, 29, 24, .05), 0 1px 3px rgba(16, 29, 24, .07);
  --bayang-2: 0 8px 24px -8px rgba(16, 29, 24, .18), 0 2px 6px rgba(16, 29, 24, .06);
  /* Isi tidak lagi dipaku 1100px: lebar kolom kanan = 100% sisa layar setelah
     sisi 264px, jadi halaman ikut melebar di monitor besar (dulu 66% di 1920). */
  --sisi-l: 264px;
  --ruang: 1.3rem;
  --sp: clamp(1rem, .6rem + 1.4vw, 2rem);      /* spasi tepi adaptif */
  --sisi-z: 30;
}

* , *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--latar); color: var(--tinta);
  font: 15px/1.55 "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased; }
h1, h2, h3 { letter-spacing: -.015em; }
h1 { font-size: clamp(1.3rem, 1.1rem + .8vw, 1.6rem); margin: 0 0 .25rem; font-weight: 700; }
h2 { font-size: .75rem; margin: 0 0 .9rem; text-transform: uppercase;
  letter-spacing: .08em; color: var(--pudar); font-weight: 700; }
h3 { font-size: .95rem; margin: 0 0 .5rem; }
a { color: var(--hijau-700); text-underline-offset: 2px; }
p { margin: 0 0 .6rem; }
p:last-child { margin-bottom: 0; }
code { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .8rem; background: var(--garis-2); padding: .1rem .34rem; border-radius: var(--r-mini); }
small { display: block; font-size: .8rem; line-height: 1.45; }
.pudar { color: var(--pudar); }
.ka { text-align: right; }
.kecil { font-size: .8rem; }
.tenang { margin: 0 0 .25rem; font-size: .875rem; color: var(--pudar); }
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--hijau-600); outline-offset: 2px; border-radius: 6px; }
.lompat { position: absolute; left: -999px; }
.lompat:focus { left: .6rem; top: .6rem; z-index: 99; background: var(--putih);
  padding: .5rem .8rem; border-radius: 8px; box-shadow: var(--bayang-2); }

/* ============================================================ rangka halaman */
.shell { display: grid; grid-template-columns: var(--sisi-l) minmax(0, 1fr); min-height: 100vh; }
.shell > * { min-width: 0; }
.sisi { background: linear-gradient(180deg, var(--hijau-900), #0f3a23 70%);
  color: #d8e5de; padding: 1.4rem 1.1rem; display: flex; flex-direction: column;
  gap: 1.4rem; position: sticky; top: 0; height: 100vh; z-index: var(--sisi-z); }
.isi { padding: var(--sp) var(--sp) 4rem;
  width: 100%; min-width: 0; }
.isi.polos { max-width: none; padding: 0; }

.merek { display: flex; align-items: center; gap: .7rem; min-width: 0;
  text-decoration: none; }
.merek img { display: block; height: 30px; width: auto; background: #fff;
  padding: .22rem .4rem; border-radius: 7px; flex: 0 0 auto; }
.merek .nama { min-width: 0; }
.merek b { display: block; color: #fff; font-size: 1rem; font-weight: 700; letter-spacing: -.01em; }
.merek small { display: inline; color: #a7c2b5; line-height: 1.35; }
/* :where() menurunkan kekhususan ke 0,0,1 supaya `nav` tetap bergaya tanpa
   menimpa kelas modifier. Sebelumnya selektor telanjang ini memaksa
   flex-direction:column pada SETIAP <nav> — termasuk .pub-nav (menu header
   menumpuk) dan .pub-halaman (paging menumpuk tegak di halaman artikel). */
:where(nav) { display: flex; gap: .18rem; }
:where(nav) a { color: #cfdfd8; text-decoration: none; padding: .58rem .8rem;
  border-radius: var(--r-kecil); font-size: .875rem; font-weight: 500; display: flex;
  align-items: center; gap: .6rem; border: 1px solid transparent; }
.ik { width: 18px; height: 18px; flex: 0 0 auto; fill: currentColor; opacity: .85; }
.ik.kecil { width: 15px; height: 15px; }
:where(nav) a:hover { background: rgba(255, 255, 255, .07); color: #fff; }
:where(nav) a.ini { background: var(--hijau-600); color: #fff; font-weight: 600;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .25); }
:where(nav) a.ini .ik { opacity: 1; }
/* Menu sisi dasbor satu-satunya yang memang tegak.
   Sisi dipatok setinggi layar (sticky, height:100vh), jadi isinya WAJIB muat —
   tanpa gulir di sini, kotak pengguna + tombol Keluar terdorong ke bawah layar
   dan tidak bisa dijangkau siapa pun. Terukur dengan 12 menu: butuh 815px saat
   layar 720px, dan label Keluar tampak menggantung di tepi bawah. Yang digulir
   menu-nya, bukan seluruh sisi (kalau .sisi yang digulir, merek ikut hilang). */
.nav-sisi { flex-direction: column; overflow-y: auto; overscroll-behavior: contain;
  min-height: 0; scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, .28) transparent; }
.nav-sisi::-webkit-scrollbar { width: 6px; }
.nav-sisi::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .25); border-radius: 3px; }
/* Lencana jumlah belum dibaca di butir menu sidebar (mis. "Message").
   `margin-left:auto` menempelkannya ke tepi kanan butir, jadi ia mengikuti
   panjang label tanpa satu pun koordinat yang perlu disesuaikan. */
.nav-sisi .menu-lencana { margin-left: auto; flex: 0 0 auto; min-width: 19px;
  padding: 0 6px; border-radius: 10px; background: var(--merah); color: #fff;
  font-size: .68rem; font-weight: 700; line-height: 18px; text-align: center; }
/* bilah bawah hanya untuk layar sempit */
.nav-bawah { display: none; }
.kaki { margin-top: auto; display: flex; flex-direction: column; gap: .7rem; }
.kotak-pengguna { background: rgba(255, 255, 255, .07); border-radius: var(--r-kecil);
  padding: .7rem .8rem; min-width: 0; }
.kotak-pengguna b { color: #fff; font-size: .88rem; display: block;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kotak-pengguna small { color: #a7c2b5; font-size: .74rem; word-break: break-all; }
.tanda { display: inline-block; margin-top: .4rem; font-size: .7rem; text-transform: uppercase;
  letter-spacing: .07em; color: var(--hijau-300); font-weight: 700; }

/* ============================================ indikator proses (spinner)
   Bilah tipis di paling atas layar + kunci layar. Dipakai setiap permintaan
   AJAX; di 30 ribu pengguna halaman tidak boleh diam tanpa tanda apa pun. */
#hub-proses { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 60;
  background: linear-gradient(90deg, transparent, var(--hijau-500), transparent);
  background-size: 45% 100%; background-repeat: no-repeat;
  animation: hub-geser 1s linear infinite; }
#hub-proses[hidden] { display: none; }
@keyframes hub-geser { from { background-position: -50% 0; } to { background-position: 150% 0; } }

.spinner { display: inline-block; width: 15px; height: 15px; flex: 0 0 auto;
  border: 2px solid rgba(255, 255, 255, .45); border-top-color: #fff;
  border-radius: 50%; animation: hub-putar .6s linear infinite; }
.spinner.gelap { border-color: rgba(16, 29, 24, .2); border-top-color: var(--hijau-700); }
@keyframes hub-putar { to { transform: rotate(360deg); } }

/* Tombol yang sedang mengirim: matikan klik ganda, tunjukkan ia bekerja. */
.tombol.sedang { opacity: .85; cursor: progress; }
.tombol.sedang > .spinner { margin-right: .15rem; }

/* Isi yang sedang dimuat ulang lewat AJAX diredupkan sedikit. */
.memuat { opacity: .55; transition: opacity .15s; pointer-events: none; }

/* Gelembung "sedang menulis" asisten. */
.aibalon .aiteks { white-space: pre-wrap; }
.aiteks-tunggu { display: flex; gap: .28rem; align-items: center; min-height: 1.2rem; }
.ai-titik { width: 7px; height: 7px; border-radius: 50%; background: var(--hijau-600);
  animation: hub-pantul 1.1s ease-in-out infinite; }
.ai-titik:nth-child(2) { animation-delay: .16s; }
.ai-titik:nth-child(3) { animation-delay: .32s; }
@keyframes hub-pantul { 0%, 80%, 100% { opacity: .3; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-4px); } }

/* Hormati preferensi pengguna: tanpa animasi, tetap ada tanda "sedang bekerja". */
@media (prefers-reduced-motion: reduce) {
  #hub-proses { animation: none; background: var(--hijau-500); }
  .spinner, .ai-titik { animation: none; }
  .aiteks-tunggu::after { content: "sedang menulis…"; font-size: .78rem; color: var(--pudar); }
}

/* ====================================== panel ubah sebaris dalam tabel */
.ubah { display: inline-block; text-align: left; position: relative; }
.ubah > summary.tombol { list-style: none; cursor: pointer; display: inline-flex;
  border: 1px solid var(--hijau-300); color: var(--hijau-700); background: var(--hijau-l);
  min-height: 32px; padding: .34rem .7rem; font-size: .8rem; border-radius: var(--r-kecil);
  font-weight: 600; align-items: center; justify-content: center; }
.ubah > summary.tombol:hover { background: var(--hijau-100); border-color: var(--hijau-500);
  color: var(--hijau-700); }
.ubah > summary.tombol:focus-visible { outline: 2px solid var(--hijau-600); outline-offset: 2px; }
.ubah > summary::-webkit-details-marker { display: none; }
.ubah[open] { display: block; }
.ubah[open] > summary { margin-bottom: .7rem; }
/* Panel ubah di dalam tabel: di layar lebar kolom aksi hanya selebar ~1%,
   jadi panel 420px yang mengalir normal meluber ke luar viewport (terukur
   tepi kanan = 1582px pada viewport 1280px). Di layar lebar panel ditambatkan
   ke tepi KANAN sel sehingga melebar ke kiri, dan dibatasi tinggi + gulir
   sendiri supaya tidak terpotong oleh .tabel-bungkus yang ber-overflow. */
.ubah form { width: 100%; box-sizing: border-box; background: var(--zebra);
  border: 1px solid var(--garis); border-radius: var(--r-kecil); padding: .9rem 1rem;
  box-shadow: var(--bayang-2); }
.ubah form label { font-size: .78rem; margin-bottom: .6rem; }
@media (min-width: 721px) {
  .ubah form { position: absolute; right: 0; z-index: 5; width: min(420px, 88vw);
    max-height: min(60vh, 400px); overflow-y: auto; }
}

/* ======================================================== bilah saring */
.saring { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center;
  background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r);
  padding: .7rem .8rem; margin-bottom: var(--ruang); box-shadow: var(--bayang); }
.saring input, .saring select { width: auto; flex: 1 1 220px; margin-top: 0; min-height: 42px;
  /* AKAR luber /keuangan @360px (isi 437px vs layar 360px): <select> native
     memakai lebar opsi terpanjang sebagai ukuran intrinsiknya ("KDMP Bina Usaha"
     -> 407px) dan menolak menyusut walau flex-basis kecil. Setiap item flex
     butuh min-width:0; kontrol form tidak terkecuali. */
  min-width: 0; max-width: 100%; }
.saring .tombol { flex: 0 0 auto; min-height: 42px; }
/* Jaring pengaman: kontrol <select> mana pun tidak boleh melampaui wadahnya.
   Tanpa ini, satu opsi ber-nama panjang cukup untuk membuat SELURUH halaman
   bergulir mendatar — dan bar bawah (position:fixed) ikut tampak "timbul
   tenggelam" karena tak lagi sejajar tepi dokumen. */
select { max-width: 100%; }
.sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ================================================================== kepala */
/* ================================================== pelatihan (materi LMS) */
.kolom-pilih { width: 1%; text-align: center; }
/* Bilah progres belajar: warna hijau Agrinas, tanpa pustaka. */
.jejak { height: 8px; border-radius: 999px; background: var(--zebra);
  border: 1px solid var(--garis); overflow: hidden; }
.jejak > span { display: block; height: 100%; background: var(--hijau-600, #1c7a4f); }
.jejak-baris { display: flex; align-items: center; gap: .6rem; }
.jejak-baris .jejak { flex: 1 1 auto; min-width: 80px; }
.jejak-baris b { font-variant-numeric: tabular-nums; font-size: .82rem; color: var(--pudar); }
/* Isi modul datang sebagai HTML dari LMS (gambar, paragraf, daftar). Batasi
   lebar baca supaya nyaman dan pastikan gambar tidak meluber keluar kartu. */
.materi-isi { max-width: 78ch; line-height: 1.7; }
.materi-isi img { max-width: 100%; height: auto; border-radius: var(--r-kecil); }
.materi-isi h1, .materi-isi h2, .materi-isi h3 { margin-top: 1.4rem; }
.materi-isi table { width: auto; max-width: 100%; }
.kepala { display: flex; justify-content: space-between; align-items: flex-start;
  gap: 1rem; margin-bottom: var(--ruang); padding-bottom: var(--ruang);
  border-bottom: 1px solid var(--garis); }
.kepala h1 { margin-bottom: .3rem; }
/* Deskripsi kepala dipotong SATU BARIS di semua lebar. Kalau ia membungkus,
   tinggi kepala ikut panjang teks dan jadi beda-beda antar halaman (terukur:
   920-1024px /distribusi & /vendor 109-110px vs 87-88px halaman lain; di
   ponsel dulu /distribusi 155px vs dasbor 133px). Teks utuh tetap di DOM
   (pembaca layar & salin-tempel tidak terpengaruh). */
.kepala > div { min-width: 0; }
.kepala .tenang { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.remah { font-size: .8rem; margin: 0 0 .7rem; }
.remah a { color: var(--pudar); text-decoration: none; }
.remah a:hover { color: var(--hijau-700); text-decoration: underline; }
.tombol-baris { display: flex; flex-wrap: wrap; gap: .5rem; }

/* ==================================================================== blok */
.blok { background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r);
  padding: 1.2rem 1.3rem 1.3rem; margin-bottom: var(--ruang); box-shadow: var(--bayang); }
.blok.sempit { max-width: 460px; }
.blok > h2:first-child { padding-bottom: .7rem; border-bottom: 1px solid var(--garis-2);
  margin-bottom: 1rem; }
.dua-kolom { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  gap: 1.1rem; align-items: start; }
.dua-kolom > div { min-width: 0; }

/* ============================================================= kartu angka */
.petak { display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: .85rem; margin-bottom: var(--ruang); }
.kartu { background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r);
  padding: .95rem 1.05rem; box-shadow: var(--bayang); min-width: 0; }
/* Deret kartu ringkasan yang bisa diklik (mis. status distribusi).
   AKAR: kelas ini dipakai view tapi aturannya tidak pernah ditulis, jadi kartu
   jatuh sebagai blok penuh yang bertumpuk dan tidak ada penanda pilihan aktif. */
.kartu-baris { display: grid; grid-template-columns: repeat(auto-fit, minmax(146px, 1fr));
  gap: .7rem; margin-bottom: var(--ruang); }
/* Sebagian deret kartu berupa <form> (tombol kirim) yang MEMBUNGKUS kartunya.
   Tanpa ini <form> meregang setinggi sel grid sementara tombolnya tidak, jadi
   kartu-kartu tampak bertingkat walau selnya sudah rata. Form jadi flex dan
   kartunya mengisi tinggi sel; isinya ditengahkan supaya tidak ada rongga
   menganggur di kartu yang teksnya pendek. */
.kartu-baris > form { display: flex; }
.kartu-baris > form > .kartu { flex: 1 1 auto; display: flex; flex-direction: column;
  justify-content: center; }
a.kartu { text-decoration: none; color: inherit; display: block;
  transition: border-color .12s, background .12s, box-shadow .12s; }
a.kartu:hover { border-color: var(--hijau-500); background: var(--hijau-100); }
a.kartu.ini { border-color: var(--hijau-600); background: var(--hijau-l);
  box-shadow: 0 0 0 1px var(--hijau-600), var(--bayang); }
.petak-judul { margin: 1.2rem 0 .4rem; font-size: .78rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em; color: var(--pudar); }
.kartu.angka { border-left: 3px solid var(--hijau-300); }
.kartu.angka small { text-transform: uppercase; letter-spacing: .07em; font-size: .7rem;
  line-height: 1.3;
  color: var(--pudar); font-weight: 700; }
.kartu.angka b { font-size: clamp(1.6rem, 1.3rem + 1.2vw, 2rem); line-height: 1.15;
  display: block; margin-top: .1rem; font-variant-numeric: tabular-nums;
  /* Nilai kartu bisa berupa email/URL panjang tanpa spasi. Tanpa ini kartu
     melebar melewati tepi layar dan SELURUH halaman bisa digeser ke samping
     (terukur /profil @360px: 60px luber, pelakunya `b` 367px di kotak 256px). */
  overflow-wrap: anywhere; }
/* Kartu isian panjang (email, nama koperasi) lebih kecil dari kartu angka
   dasbor — 1.6-2rem bukan ukuran yang enak untuk alamat email. */
.kartu.angka b.panjang { font-size: .95rem; line-height: 1.35; }
.aksi-kuning { border-left-color: var(--kuning-g); }
.aksi-merah { border-left-color: var(--merah-g); }
.aksi-hijau { border-left-color: var(--hijau-g); }
.aksi-biru { border-left-color: var(--biru-g); }
.t-kuning { color: var(--kuning); } .t-merah { color: var(--merah); }
.t-hijau { color: var(--hijau-600); } .t-biru { color: var(--biru); }

/* =================================================================== tabel */
.tabel-bungkus { overflow-x: auto; overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch; margin: 0 -.35rem; padding: 0 .35rem; }
table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: .875rem; }
th { text-align: left; font-size: .7rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--pudar); padding: .55rem .7rem; background: var(--zebra);
  border-bottom: 1px solid var(--garis); white-space: nowrap; font-weight: 700; }
th:first-child { border-top-left-radius: var(--r-kecil); }
th:last-child { border-top-right-radius: var(--r-kecil); }
td { padding: .7rem; border-bottom: 1px solid var(--garis-2); vertical-align: middle;
  overflow-wrap: anywhere; }
tbody tr:nth-child(even) { background: #fcfefd; }
tbody tr:hover { background: var(--hijau-100); }
tbody tr:last-child td { border-bottom: 0; }
.kolom-aksi { width: 1%; white-space: nowrap; text-align: right; }
td small { color: var(--pudar); margin-top: .15rem; }
.judul-sel { font-weight: 600; font-size: .95rem; line-height: 1.35; }
.kosong { text-align: center; color: var(--pudar); padding: 1.6rem .8rem; }

/* =========================================================== lencana status */
.lencana { display: inline-flex; align-items: center; gap: .35rem; padding: .25rem .6rem;
  border-radius: var(--r-kapsul); font-size: .7rem; font-weight: 700; letter-spacing: .02em;
  white-space: nowrap; border: 1px solid transparent; line-height: 1.35; }
/* Di ponsel tabel berubah jadi kartu; lencana panjang (mis. "Jawa Barat (luar
   Jabodetabek)") ikut meluber keluar kartu karena nowrap — biarkan membungkus. */
@media (max-width: 720px) { .tabel-bungkus .lencana { white-space: normal; } }
.lencana::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.s-BARU { background: var(--garis-2); color: var(--tinta-2); border-color: var(--garis); }
.s-DIKERJAKAN { background: var(--kuning-l); color: var(--kuning); border-color: var(--kuning-g); }
.s-DIAJUKAN { background: var(--biru-l); color: var(--biru); border-color: var(--biru-g); }
/* Pasokan: Disetujui = HIJAU (pasokan diterima), Ditolak = merah. */
.s-DISETUJUI { background: var(--hijau-l); color: var(--hijau-600); border-color: var(--hijau-g); }
.s-DIPROSES { background: var(--biru-l); color: var(--biru); border-color: var(--biru-g); }
.s-REVISI { background: var(--merah-l); color: var(--merah); border-color: var(--merah-g); }
.s-DITOLAK { background: var(--merah-l); color: var(--merah); border-color: var(--merah-g); }
.s-SELESAI { background: var(--hijau-l); color: var(--hijau-600); border-color: var(--hijau-g); }
/* Status distribusi: DIKIRIM = dalam perjalanan (biru), DITERIMA = hijau,
   DITOLAK = merah. DIAJUKAN memakai gaya .s-DIAJUKAN yang sudah ada. */
.s-DIKIRIM { background: var(--kuning-l); color: var(--kuning); border-color: var(--kuning-g); }
.s-DITERIMA { background: var(--hijau-l); color: var(--hijau-600); border-color: var(--hijau-g); }
.s-DITOLAK { background: var(--merah-l); color: var(--merah); border-color: var(--merah-g); }

/* ================================================================== tombol */
.tombol { display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .55rem 1rem; min-height: 40px; border: 1px solid transparent; cursor: pointer;
  border-radius: var(--r-kecil); font-size: .875rem; font-weight: 600; text-decoration: none;
  font-family: inherit; line-height: 1.2; transition: background .12s, border-color .12s, color .12s; }
.tombol.utama { background: var(--hijau-600); color: #fff; box-shadow: 0 1px 2px rgba(16, 29, 24, .18); }
.tombol.utama:hover { background: var(--hijau-700); }
.tombol.samar { background: var(--putih); border-color: var(--garis); color: var(--tinta-2); }
.tombol.samar:hover { border-color: var(--hijau-500); color: var(--hijau-700); background: var(--hijau-100); }
.tombol.mini { padding: .34rem .6rem; min-height: 32px; font-size: .8rem; }
/* Di ponsel .mini turun ke 32px dan tombolnya berdampingan di sel aksi tabel
   dengan jarak 8px — kurang dari separuh jarak jempol, jadi "Status" gampang
   meleset jadi "Hapus" (hapus tugas, tanpa undo). Kembalikan ke 40px serta
   pisahkan sedikit; hanya di ponsel, desktop tetap rapat. */
@media (max-width: 720px) {
  .tombol.mini { min-height: 40px; padding: .5rem .7rem; }
  .tabel-bungkus td.kolom-aksi .tombol.mini + .tombol.mini { margin-left: .3rem; }
}
/* Tombol berisi ikon SAJA: persegi, ikonnya sedikit lebih besar dari `.ik`
   bawaan (18px) karena di sini ikon adalah satu-satunya isi tombol. Ukuran
   tombolnya ditentukan di tempat pemakaian (mis. `.kat-aksi .tombol-ikon`). */
.tombol-ikon { padding: 0; }
.tombol-ikon .ik { width: 20px; height: 20px; opacity: 1; }
/* Tombol ber-ikon + label (mis. kepala halaman Koperasi). `inline-flex` supaya
   ikon & teksnya benar-benar sebaris dengan jarak tetap — sebagai inline-block
   biasa, ikon 16px dan teks duduk di baseline yang berbeda dan jaraknya jadi
   spasi teks yang ikut menyusut di layar sempit. Dipakai `<a>` maupun `<button>`
   (tombol formulir), jadi selektornya kelas, bukan elemen. */
.tombol.ikon-kiri { display: inline-flex; align-items: center; gap: .45rem; }
.tombol.ikon-kiri .ik { flex: 0 0 auto; width: 16px; height: 16px; opacity: .85; }
.tombol.ikon-kiri:hover .ik { opacity: 1; }
.tombol.peringatan { background: var(--merah-l); color: var(--merah); border-color: var(--merah-g); }
.tombol.peringatan:hover { background: #fbe0dd; }
.tombol.lebar { width: 100%; }
.sebaris { display: inline-block; margin: 0 0 .3rem .3rem; }
/* AKAR tombol menempel isian (terukur 0px di /pasokan, desktop & ponsel):
   `.sebaris` = inline-block TANPA flex, jadi `gap` tidak berlaku dan input
   duduk rapat dengan tombolnya. Di dalam sel tabel aksi jadikan flex supaya
   `gap` bekerja. Di luar tabel dibiarkan apa adanya (4 view lain tidak berubah). */
.tabel-bungkus td .sebaris { display: flex; align-items: center; gap: .5rem; margin: 0; }
/* Isian catatan di sel aksi ikut fleksibel TAPI punya lebar minimum: tanpa ini
   kolom aksi (width:1%) menekannya jadi 24px dan placeholder tak terbaca;
   sebelumnya ia 122px tetapi TERTIMPA tombol (-64px) — sama-sama rusak. */
.tabel-bungkus td .sebaris input:not([type="hidden"]) { flex: 1 1 auto; min-width: 7rem; }

/* =============================================================== formulir */
label { display: block; margin-bottom: .85rem; font-size: .82rem; font-weight: 600;
  color: var(--tinta-2); }
/* AKAR centang raksasa di /workspace/tugas: aturan di bawah menargetkan SEMUA
   <input>, termasuk type=checkbox/radio — kotaknya jadi selebar kolom + 42px
   tinggi, teks label terdorong ke baris berikutnya. Semua jenis di luar
   "kolom teks" dikecualikan di sini (satu tempat, semua formulir ikut sehat). */
input, select, textarea { width: 100%; margin-top: .35rem; padding: .6rem .7rem; font: inherit;
  font-size: .875rem; border: 1px solid #ccd7d1; border-radius: var(--r-kecil); background: var(--putih);
  color: var(--tinta); font-weight: 400; min-height: 42px; }
/* Atribut `hidden` HARUS menang. Bawaan peramban `[hidden]{display:none}`
   kalah oleh `display:flex/block` milik author, sehingga elemen ber-`hidden`
   tetap tampil — panel "+ Baru" pernah setinggi 709px dan menekan daftar
   percakapan sampai tinggal 13px (1 baris terlihat). */
[hidden] { display: none !important; }
/* Kotak centang/radio: ukuran asli, sejajar teks labelnya. */
/* 1.1em = "menyesuaikan tulisan": kotak tumbuh bersama ukuran huruf labelnya,
   jadi ia tak lagi 13px bawaan peramban yang lebih kecil dari teks 14px. */
input[type="checkbox"], input[type="radio"] { width: 1.1em; height: 1.1em; min-height: 0;
  margin: 0; padding: 0; accent-color: var(--hijau-600); flex: none; }
/* <label><input type=checkbox> Teks</label> -> satu baris: kotak di kiri,
   teks di kanan, keduanya rata tengah. */
label.centang { display: flex; flex-direction: row; align-items: center; gap: .5rem;
  font-weight: 400; margin-bottom: .3rem; }

/* AKAR luber di SEMUA formulir: <label>Teks<input></label> ditulis sebaris tanpa
   <br>. Karena input adalah inline-block, teks label dan kotak isian berbagi
   satu baris — dengan width:100% kotak isian mulai SETELAH teks label dan
   melebar 100% dari situ, jadi tepi kanannya keluar dari kartu (terukur 100px
   lebih lebar dari wadah, dan 58px keluar viewport di dalam panel ubah).
   display:block membuat setiap kotak isian mulai dari tepi kiri label. */
input, select, textarea { display: block; }
input::placeholder, textarea::placeholder { color: #67766f; }
input:hover, select:hover, textarea:hover { border-color: #b6c4bd; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--hijau-300);
  outline-offset: 1px; border-color: var(--hijau-500); }
textarea { resize: vertical; min-height: 96px; }
/* AKAR tombol menempel elemen sebelumnya (terukur 0px di 3 halaman):
   isian/label/paging tepat diikuti tombol tanpa jarak apa pun.
   asisten  : <textarea> lalu <div class="tombol-baris">
   pasokan  : <input type="text"> lalu <button class="tombol">
   stok     : <nav class="paging"> lalu <button class="tombol">
   Satu aturan di sini menutup semuanya — tanpa perlu menyisipkan pembungkus
   baru di tiap blade. */
label + .tombol, label + .tombol-baris,
input + .tombol, input + .tombol-baris,
select + .tombol, select + .tombol-baris,
textarea + .tombol, textarea + .tombol-baris,
.paging + .tombol, .paging + .tombol-baris,
p.bantuan + .tombol, p.bantuan + .tombol-baris { margin-top: .7rem; }
input[type="file"] { padding: .45rem .6rem; background: var(--zebra); font-size: .85rem; }
.grid-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 0 1.1rem; }
.lebar-penuh { grid-column: 1 / -1; }
.tumpuk { border-top: 1px solid var(--garis-2); padding-top: .9rem; margin-top: .9rem; }
.tumpuk:first-child { border-top: 0; padding-top: 0; margin-top: 0; }
.bantuan { font-size: .78rem; color: var(--pudar); font-weight: 400; margin: .35rem 0 0; }
/* Jarak antar formulir bertumpuk — KHUSUS formulir yang benar-benar menumpuk
   vertikal (mis. "Tambah Barang" di bawah daftar isian). Dulu selektornya
   `form + form`; di dalam .kartu-baris (grid) ia ikut menghukum formulir yang
   BERDAMPINGAN, sehingga tiap kartu setelah yang pertama terdorong 0.7rem ke
   bawah dan tingginya berkurang 0.7rem (terukur: kartu 1 = 92.8px, kartu 2-3 =
   81.7px, dasar kartu tidak sejajar). Grid sudah mengatur jarak lewat `gap`,
   jadi margin itu murni merusak — sekarang dikecualikan. */
form + form:not(.kartu-baris > *) { margin-top: .7rem; }

/* ================================================================== asisten */
/* Ruang percakapan di /asisten. Tiga hal yang DULU salah dan diperbaiki di sini:
   1. balon memakai `.pesan` (kotak peringatan: latar penuh + garis kiri 4px +
      margin 1rem) — percakapan jadi terlihat seperti tanggapan galat;
   2. #ai-balon selalu dirender walau kosong (height 0 tapi tetap memakan
      margin), dan #ai-mulai punya padding 0 sehingga judulnya menempel tepi;
   3. kotak tulis tidak punya bingkai sama sekali: label 13,6px di atas textarea,
      lalu tombol 0,7rem dari kenaikan aturan generik. */
#ai-balon { display: flex; flex-direction: column; gap: .6rem; }
#ai-balon[data-kosong] { display: none; }
/* Ruang percakapan dibatasi & digulir sendiri. AKAR: jawaban asisten bisa
   setinggi 974px (terukur di ponsel), sehingga kotak tulis terdorong 1,5 layar
   ke bawah — tidak terpakai. Batas HANYA berlaku saat ada isi: `max-height`
   tidak memaksa tinggi, jadi percakapan pendek tetap tanpa bilah gulir.
   `min(58vh, 520px)` = kurang dari satu layar, apa pun tinggi jendelanya. */
#ai-balon:not([data-kosong]) { margin-bottom: 1.1rem;
  max-height: min(58vh, 520px); overflow-y: auto; padding-right: .25rem; }
.aibalon { max-width: min(76ch, 92%); padding: .65rem .9rem; border-radius: var(--r);
  border: 1px solid var(--garis-2); background: var(--zebra); }
.aibalon > b { display: block; font-size: .7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--pudar); margin-bottom: .2rem; }
/* Pertanyaan pengguna: menjorok ke kanan, warna hijau muda. */
.aibalon.ingat { align-self: flex-end; background: var(--hijau-l); border-color: var(--hijau-g); }
.aibalon.ingat > b { color: var(--hijau-700); }
.aibalon.rusak { background: var(--merah-l); border-color: var(--merah-g); }
.aibalon.rusak > b { color: var(--merah); }
/* Isi jawaban = keluaran Markdown: paragraf, daftar, tabel, kutipan, judul,
   tautan. Semua disembunyikan dari `white-space: pre-wrap` lama — dengan HTML
   itu menghasilkan rongga raksasa antar elemen. */
.aibalon .aiteks { font-size: .9rem; line-height: 1.65; white-space: normal; }
.aiteks > :first-child { margin-top: 0; }
.aiteks > :last-child { margin-bottom: 0; }
.aiteks p { margin: 0 0 .6rem; }
.aiteks ul, .aiteks ol { margin: 0 0 .6rem; padding-left: 1.3rem; }
.aiteks li { margin-bottom: .2rem; }
.aiteks h1, .aiteks h2, .aiteks h3, .aiteks h4 { margin: 1rem 0 .4rem;
  font-size: .95rem; font-weight: 700; text-transform: none; letter-spacing: -.01em;
  color: var(--tinta); }
.aiteks h3, .aiteks h4 { font-size: .9rem; }
.aiteks strong { font-weight: 700; }
.aiteks table { width: auto; max-width: 100%; margin: 0 0 .7rem; border: 1px solid var(--garis);
  border-radius: var(--r-kecil); border-collapse: collapse; font-size: .82rem; }
.aiteks th { padding: .35rem .6rem; background: var(--zebra); }
.aiteks td { padding: .35rem .6rem; border-top: 1px solid var(--garis-2); }
.aiteks blockquote { margin: 0 0 .6rem; padding: .2rem 0 .2rem .8rem;
  border-left: 3px solid var(--hijau-300); color: var(--tinta-2); }
.aiteks code { font-size: .8rem; }
.aiteks pre { margin: 0 0 .6rem; padding: .6rem .7rem; background: var(--zebra);
  border: 1px solid var(--garis-2); border-radius: var(--r-kecil); overflow-x: auto; }
.aiteks pre code { background: none; padding: 0; }
.aiteks hr { border: 0; border-top: 1px solid var(--garis-2); margin: .8rem 0; }

#ai-mulai { padding: .2rem 0 .3rem; }
#ai-mulai h2 { margin-bottom: .35rem; }
#ai-mulai .bantuan { margin: 0 0 .8rem; }
/* Kartu saran ("Perintah cepat"). Dulu chevron-nya `float: right`, sehingga teks
   membungkus DI BAWAH panah dan di layar sempit (kartu ~156px) barisnya jadi
   berantakan. Sekarang kartunya flex: teks tumbuh, panah jadi butir tersendiri di
   kanan-atas dan tidak pernah ditabrak teks. */
.kartu-tanya { text-align: left; width: 100%; min-height: 76px; padding: .8rem .95rem;
  display: flex; align-items: flex-start; gap: .5rem;
  transition: border-color .12s, background .12s, box-shadow .12s; }
/* Chevron kecil: menandai kartu ini bisa ditekan, bukan sekadar kotak teks. */
.kartu-tanya::after { content: "\2192"; flex: 0 0 auto; margin-top: .1rem;
  color: var(--hijau-600); font-weight: 700; }
.kartu-tanya:hover { border-color: var(--hijau-500); background: var(--hijau-100);
  box-shadow: var(--bayang-2); }
.kartu-tanya b { font-size: .9rem; font-weight: 600; line-height: 1.45; }
/* Ponsel: kartu saran satu kolom. Dua kolom menyisakan ~156px dan memaksa teks
   membungkus 5-6 baris — tidak lagi terbaca sebagai "perintah cepat". */
@media (max-width: 620px) {
  #ai-contoh { grid-template-columns: 1fr; }
  #ai-contoh .kartu-tanya { min-height: 0; }
}

/* Kotak tulis: satu bingkai; bingkainya ikut menyala saat textarea difokus. */
.ai-tulis { border: 1px solid var(--garis); border-radius: var(--r); background: var(--putih);
  padding: .6rem .7rem .7rem; transition: border-color .12s, box-shadow .12s; }
.ai-tulis:focus-within { border-color: var(--hijau-500);
  box-shadow: 0 0 0 3px rgba(31, 135, 57, .13); }
.ai-tulis textarea { border: 0; padding: .25rem .3rem; min-height: 88px;
  outline: 0 !important; background: transparent; }
.ai-tulis textarea:focus { outline: 0; border: 0; }
.ai-tulis .tombol-baris { justify-content: flex-end; margin-top: .65rem; }
p.bantuan:last-child { margin-bottom: 0; }

/* =================================================================== pesan */
.pesan { padding: .75rem 1rem; border-radius: var(--r-kecil); margin-bottom: 1rem;
  font-size: .875rem; border: 1px solid transparent; border-left-width: 4px; }
.pesan a { font-weight: 600; }
.pesan.ok { background: var(--hijau-l); color: #14512f; border-color: var(--hijau-g); }
.pesan.rusak { background: var(--merah-l); color: var(--merah); border-color: var(--merah-g); }
.pesan.ingat { background: var(--kuning-l); color: var(--kuning); border-color: var(--kuning-g); }
.pesan.kunci { background: var(--biru-l); border-color: var(--biru-g); color: #0d3f7a; }
.pesan.kunci b { display: block; font-size: .7rem; text-transform: uppercase; letter-spacing: .07em; }
.pesan.kunci code { display: block; margin: .45rem 0; padding: .6rem .7rem; background: var(--putih);
  border: 1px dashed var(--biru-g); border-radius: var(--r-kecil); font-size: 1.05rem;
  font-weight: 700; user-select: all; word-break: break-all; }
.pesan.kunci small { font-size: .8rem; opacity: .85; }

/* Kepala panel asisten: avatar + identitas + lencana kesiapan. */
.ai-kepala { display: flex; align-items: center; gap: .75rem;
  padding-bottom: .9rem; margin-bottom: 1rem; border-bottom: 1px solid var(--garis-2); }
.ai-avatar { flex: none; width: 38px; height: 38px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--hijau-100); color: var(--hijau-700); border: 1px solid var(--hijau-g);
  font-size: .78rem; font-weight: 700; letter-spacing: .04em; }
.ai-kepala > div { min-width: 0; flex: 1 1 auto; }
.ai-kepala > div b { display: block; font-size: .95rem; }
.ai-kepala > div small { font-size: .78rem; }
.ai-kepala .lencana { flex: none; }

/* ================================================================ rincian */
.rincian { display: grid; grid-template-columns: minmax(120px, 34%) minmax(0, 1fr);
  gap: .45rem .9rem; margin: 0 0 1rem; font-size: .875rem; }
.rincian dt { color: var(--pudar); font-weight: 600; }
.rincian dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.kotak { background: var(--zebra); border: 1px solid var(--garis-2); border-radius: var(--r-kecil);
  padding: .8rem .9rem; font-size: .875rem; white-space: pre-wrap; overflow-wrap: anywhere; }
.kotak.catatan { background: var(--kuning-l); border-color: var(--kuning-g); margin-top: .8rem; }
.kotak.catatan b { display: block; font-size: .78rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--kuning); margin-bottom: .3rem; }

/* ======================================================= berkas & linimasa */
.berkas { display: flex; justify-content: space-between; gap: 1rem; align-items: center;
  border-bottom: 1px solid var(--garis-2); padding: .75rem 0; }
.berkas:last-child { border-bottom: 0; padding-bottom: 0; }
.berkas:first-child { padding-top: 0; }
.berkas a { font-weight: 600; text-decoration: none; overflow-wrap: anywhere; }
.berkas a:hover { text-decoration: underline; }
.obrolan { list-style: none; margin: 0 0 1rem; padding: 0; display: flex; flex-direction: column;
  gap: .6rem; max-height: 420px; overflow-y: auto; }
.obrolan li { background: var(--zebra); border: 1px solid var(--garis-2);
  border-radius: var(--r-kecil); padding: .6rem .8rem; max-width: 92%; }
.obrolan li.dia { background: var(--hijau-l); border-color: var(--hijau-g);
  align-self: flex-end; }
.obrolan b { font-size: .82rem; }
.obrolan small { display: inline; margin-left: .45rem; font-size: .72rem; }
.obrolan p { margin: .25rem 0 0; font-size: .875rem; white-space: pre-wrap;
  overflow-wrap: anywhere; }
.kosong-obrolan { background: none; border: 0; padding: 0; max-width: none; }
.linimasa { list-style: none; margin: 0; padding: 0; }
.linimasa li { position: relative; border-left: 2px solid var(--garis); padding: 0 0 .9rem 1rem;
  margin-left: .35rem; }
.linimasa li::before { content: ""; position: absolute; left: -6px; top: .35rem; width: 10px;
  height: 10px; border-radius: 50%; background: var(--putih); border: 2px solid var(--hijau-300); }
.linimasa li:last-child { padding-bottom: 0; }
.linimasa b { font-size: .86rem; }
.linimasa small { margin-top: .1rem; }
.linimasa p { margin: .3rem 0 0; font-size: .84rem; color: var(--tinta-2); }

/* Cegah meluap: kolom grid tidak boleh melebihi lebar induk (min-width:0). */
.pub-dua, .pub-binaan, .pub-kaki-grid, .pub-media, .pub-kartu-grid,
.pub-langkah, .pub-halaman, .panel-masuk { min-width: 0; }
.pub-dua > *, .pub-binaan > *, .pub-kepala-bagian, .pub-kartu, .pub-artikel,
.pub-orang, .pub-langkah > li { min-width: 0; }
.pub-media h3, .pub-artikel h3, .pub-kaki-grid p, .pub-kaki-grid li { overflow-wrap: anywhere; }

/* ========================================================= halaman masuk */
.latar-publik { background: radial-gradient(120% 100% at 12% 8%, #33a253, #175f38 55%, #12472c);
  min-height: 100vh; }
.masuk { min-height: 100vh; display: grid; place-items: center; padding: var(--sp); }
.panel-masuk { width: 100%; max-width: 940px; display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); background: var(--putih); border-radius: 18px;
  overflow: hidden; box-shadow: 0 30px 60px -20px rgba(0, 0, 0, .5); }
.panel-kiri { background: linear-gradient(165deg, var(--hijau-800), #14532d 75%); color: #d8e5de;
  padding: 2.4rem 2.2rem; display: flex; flex-direction: column; gap: 1.2rem; }
.panel-kiri h1 { color: #fff; font-size: 1.7rem; margin: 0; }
.panel-kiri p { color: #a7c2b5; font-size: .92rem; margin: 0; }
.panel-kiri .ciri { list-style: none; margin: auto 0 0; padding: 0; display: grid; gap: .6rem; }
.panel-kiri .ciri li { display: flex; gap: .6rem; align-items: flex-start;
  font-size: .85rem; color: #c7d8d0; }
.panel-kiri .ciri li::before { content: "✓"; color: var(--hijau-300); font-weight: 700; }
.panel-kanan { padding: 2.4rem 2.2rem; display: flex; flex-direction: column;
  justify-content: center; }
.panel-kanan h2 { font-size: 1.15rem; text-transform: none; letter-spacing: -.01em;
  color: var(--tinta); margin-bottom: .3rem; }
.merek.besar { flex-direction: column; align-items: center; text-align: center; gap: .5rem;
  margin-bottom: 1.5rem; }

/* ========================================================= kartu koperasi */
.publik { min-height: 100vh; display: grid; place-items: center; padding: var(--sp); }
.kartu-publik { background: var(--putih); border-radius: 16px; max-width: 520px; width: 100%;
  box-shadow: 0 30px 60px -20px rgba(0, 0, 0, .5); overflow: hidden; }
.kartu-publik .kepala-kartu { background: linear-gradient(160deg, var(--hijau-800), #14532d);
  color: #d8e5de; padding: 1.4rem 1.6rem; }
.kartu-publik .badan { padding: 1.6rem; }
.kartu-publik h1 { font-size: 1.35rem; margin: .2rem 0 .1rem; }
.kode-koperasi { font-family: ui-monospace, monospace; color: var(--hijau-600); font-weight: 700;
  margin: 0 0 1.1rem; letter-spacing: .05em; }
.sidik { background: var(--zebra); border: 1px dashed var(--garis); border-radius: var(--r-kecil);
  padding: .6rem .75rem; font-size: .82rem; margin: .8rem 0 0; overflow-wrap: anywhere; }

/* ======================================================== layar sempit ≤900 */
@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); }
  /* AKAR: di mobile kepala harus SATU baris. Sebelumnya .sisi tetap column,
     jadi merek dan identitas jatuh ke dua baris & tinggi kepala jadi ~104px. */
  /* align-self:start WAJIB: tanpa ini .shell (grid, min-height:100vh) meregangkan
     bar ini mengisi sisa layar -> tingginya = viewport - tinggi isi halaman
     (terukur 146px @845px, 346px @1200px; di layar pendek kebetulan 59px).
     Gejala: bar atas "sangat tinggi" hanya di HP berlayar tinggi / isi pendek. */
  .sisi { position: sticky; top: 0; height: auto; align-self: start; flex-direction: row;
    align-items: center; gap: .8rem; padding: .55rem var(--sp);
    border-bottom: 1px solid rgba(255, 255, 255, .1); }
  .sisi .merek small { display: none; }
  /* nav pindah ke bilah bawah; kepala hanya merek + identitas */
  .nav-sisi { display: none; }
  .sisi .merek { gap: .55rem; min-width: 0; }
  .sisi .merek svg { width: 26px; height: 26px; flex: 0 0 auto; }
  .sisi .merek b { font-size: .95rem; white-space: nowrap; overflow: hidden;
    text-overflow: ellipsis; }
  .kaki { margin-top: 0; margin-left: auto; flex-direction: row; flex-wrap: nowrap;
    align-items: center; gap: .5rem; min-width: 0; }
  .kotak-pengguna { background: none; padding: 0; text-align: right; min-width: 0;
    max-width: 34vw; }
  .kotak-pengguna b { font-size: .8rem; }
  .kotak-pengguna small, .kotak-pengguna .tanda { display: none; }
  /* tombol keluar jadi ikon saja supaya tidak mencuri ruang kepala */
  .kaki .tombol { flex: 0 0 auto; width: auto; min-height: 40px; padding: .3rem .65rem; }
  .kaki .tombol .label-keluar { display: none; }
  .kaki .tombol .ik.kecil { width: 18px; height: 18px; }
  /* AKAR: aturan `nav` di atas menetapkan flex-direction: column — bilah bawah
     harus eksplisit row, kalau tidak ketiga item menumpuk vertikal. */
  .nav-bawah { display: flex; flex-direction: row; flex-wrap: nowrap;
    position: fixed; inset: auto 0 0 0; z-index: 40;
    background: var(--putih); border-top: 1px solid var(--garis);
    box-shadow: 0 -2px 12px rgba(16, 29, 24, .07);
    padding: .35rem .3rem calc(.35rem + env(safe-area-inset-bottom));
    justify-content: center; gap: .15rem; align-items: stretch;
    /* Menu admin kini 8 item — di layar sempit bilah ini bergulir mendatar
       daripada memaksa setiap item jadi terlalu kecil untuk disentuh. */
    overflow-x: auto; overscroll-behavior-x: contain;
    scrollbar-width: none; }
  .nav-bawah::-webkit-scrollbar { display: none; }
  .nav-bawah a { flex: 1 1 auto; min-width: 76px; max-width: 118px;
    /* position:relative WAJIB: `.lencana-notif` memakai position:absolute dan
       tanpa ini ia mencari leluhur terdekat yang berposisi — yaitu bilahnya
       sendiri (position:fixed) — sehingga SEMUA lencana menumpuk di tepi kanan
       bilah, bukan menempel di ikonnya masing-masing. */
    position: relative;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: .15rem; padding: .35rem .2rem;
    border-radius: var(--r-kecil); color: var(--tinta-2); text-decoration: none;
    font-size: .68rem; font-weight: 600; letter-spacing: .01em; }
  .nav-bawah a span { max-width: 100%; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; }
  /* Lencana "belum dibaca" di bilah bawah: ditempelkan ke IKON, bukan ke pojok
     butir. `.lencana-notif` bawaannya `right:-3px` (menempel di pojok kanan
     elemen ber-posisi = butir menu) — untuk butir selebar 83px ikonnya di tengah,
     jadi lencana tampak mengambang di tepi butir dan 2px-nya melewati batas butir
     sampai menimpa butir sebelah. Di sini acuannya diganti ke tengah butir
     (ikon 21px terpusat → tepi kanannya di 50% + 10.5px), dengan rumus yang sama
     seperti menempelkan lencana ke ikon lonceng. */
  .nav-bawah .lencana-notif { top: .15rem; left: calc(50% + 4px); right: auto; }
  .ik-bawah { width: 21px; height: 21px; fill: currentColor; }
  .nav-bawah a:hover { background: var(--hijau-100); }
  .nav-bawah a.ini { color: var(--hijau-700); background: var(--hijau-l); }
  /* Tinggi bilah bawah, satu angka untuk seluruh halaman. Dulu dipaku 5.2rem
     di `.isi`; sekarang diturunkan dari tinggi bilahnya sendiri supaya tidak
     bisa berselisih saat bilah berubah. Di desktop tak terpakai (bilahnya
     display:none). */
  :root { --tb: calc(2.75rem + env(safe-area-inset-bottom));
    /* Tinggi NYATA bilah menu bawah (terukur 66px pada 360x780). Dipakai
       dialog untuk tahu berapa ruang yang harus disisakan di bawah, supaya
       pusatnya berada di ruang di ATAS bilah — bukan di tengah seluruh layar,
       yang membuat dialog tinggi menutupi menu. Angka tunggal: kalau bilahnya
       berubah tinggi, ubah di sini saja. */
    --tb-nav: calc(4.125rem + env(safe-area-inset-bottom)); }
  .dua-kolom { grid-template-columns: 1fr; }
  .isi { padding-bottom: calc(var(--tb) + .6rem); }
  .panel-masuk { grid-template-columns: 1fr; max-width: 480px; }
  .panel-kiri { padding: 1.6rem 1.6rem 1.4rem; gap: .8rem; }
  .panel-kiri .ciri { display: none; }
  .panel-kiri h1 { font-size: 1.4rem; }
  .panel-kanan { padding: 1.6rem; }
  .linimasa { max-height: 320px; overflow-y: auto; padding-right: .3rem; }
}

/* ======================================== mobile: tabel jadi daftar ≤720px */
@media (max-width: 720px) {
  .tabel-bungkus { overflow-x: visible; margin: 0; padding: 0; }
  .tabel-bungkus table, .tabel-bungkus tbody, .tabel-bungkus tr, .tabel-bungkus td { display: block; }
  .tabel-bungkus thead { display: none; }
  .tabel-bungkus tr { border: 1px solid var(--garis); border-radius: var(--r-kecil);
    background: var(--putih) !important; padding: .7rem .85rem; margin-bottom: .6rem;
    box-shadow: var(--bayang); }
  .tabel-bungkus tr:last-child { margin-bottom: 0; }
  .tabel-bungkus td { border: 0; padding: .3rem 0; display: grid;
    grid-template-columns: minmax(84px, 34%) minmax(0, 1fr); gap: .2rem .8rem;
    align-items: baseline; }
  .tabel-bungkus td::before { content: attr(data-l); font-size: .7rem; text-transform: uppercase;
    letter-spacing: .07em; color: var(--pudar); font-weight: 700; padding-top: .18rem; }
  /* AKAR "nilai menempel di kolom label" (terukur di /kerja /rapat /distribusi
     @320/360/390: seluruh sel bernilai >1 anak menaruh anak ke-2 di kolom 1).
     ::before memakai kolom 1 BARIS 1, jadi AUTO-PLACEMENT anak pertama sudah
     memakai kolom 2 baris 1 dan anak KEDUA tidak punya sisa sel di baris itu ->
     ia dibuang ke kolom 1 baris 2, yaitu tepat DI BAWAH LABEL, bukan di bawah
     nilai. Terlihat di /kerja: "Jumlah 5 SAK" + "diterima 0" (keterangan jatuh
     di bawah kata JUMLAH) dan "Tugas" + deskripsi di bawah kata TUGAS.
     Pisahkan lajur secara EKSPLISIT: label tetap kolom 1, dan SEMUA anak isi
     dikunci ke kolom 2 -> tiap anak dapat barisnya sendiri, rata dengan
     nilainya. Anak yang memang perlu selebar baris (panel/form terbuka,
     mis. `.lebar-penuh`) dikecualikan dan tetap 1 / -1. */
  .tabel-bungkus td > *:not(.lebar-penuh):not([class*="lebar-penuh"]) { grid-column: 2; }
  .tabel-bungkus td:not([data-l]) { display: block; padding-top: .5rem; }
  .tabel-bungkus td[data-l=""]:not(:has(*)) { display: none; }
  /* <th> sebagai label baris (tabel "pasangan label → nilai" seperti NPWP/NIK
     di /agri/hris/bpjs, yang <th>-nya ada di tbody, bukan thead). Tanpa aturan
     ini `th` tetap table-cell sementara `tr`/`td` sudah block, sehingga ia
     membentuk kotak anonim selebar isi judulnya dan tabelnya keluar layar —
     terukur: dokumen 438px di viewport 390px. Ketebalan: deskripsi di bawah
     label disembunyikan (labelnya sudah menyebut isinya); teks penuh tetap ada
     di berkas view. */
  .tabel-bungkus th { display: block; width: auto; padding: 0 0 .2rem;
    border: 0; font-size: .7rem; text-transform: uppercase; letter-spacing: .07em; }
  .tabel-bungkus th .pudar { display: none; }

  /* sel aksi tanpa label jadi blok penuh; yang ber-label tetap grid supaya
     label dan nilainya tidak menempel (mis. "TUGAS" + "5" -> "TUGAS5") */
  .tabel-bungkus td.kolom-aksi { text-align: left; padding-top: .7rem; width: auto; }
  /* Kolom pilih kena masalah yang sama dengan kolom aksi: `width: 1%` (trik
     "selebar isinya") di ponsel membuat sel jadi ~3px sehingga kotak centang
     tercekik tak bisa ditekan. Reset ke `auto` + ukuran sentuh yang layak. */
  .tabel-bungkus td.kolom-pilih { width: auto; text-align: left; padding-top: .7rem; }
  .tabel-bungkus td.kolom-pilih input[type="checkbox"] { width: 20px; height: 20px; }
  /* Di ponsel sel berubah jadi grid label+nilai. `text-align: right` untuk kolom
     angka adalah aturan desktop (menyejajarkan digit); di sini ia justru
     menempelkan angka ke tepi kanan sementara labelnya di kiri, jadi angka
     Rp terlihat menjauh dari labelnya. Kembalikan ke kiri — kerapian digit
     tetap dijaga `tabular-nums`. */
  .tabel-bungkus td.angka-kanan { text-align: left; }
  /* Tombol aksi disusun sebaris; margin bawaan .sebaris dinolkan karena di sini
     lebarnya sudah dibagi flex, sisa margin bikin sel meluber dari kartu. */
  /* Di PONSEL `display:flex` pada sel aksi aman dan memang dibutuhkan: tabelnya
     sudah `display:block` (lihat awal media query ini), jadi tidak ada algoritma
     tata letak tabel yang bisa dirusak, dan tombol-tombolnya tetap sebaris.
     🔴 Yang merusak di sini adalah `width:1%` — pada wadah flex di dalam elemen
     blok, 1% × 324px = ~3px sehingga sel kolaps. Karena itu aturan `width:1%`
     untuk kolom aksi dibatasi ke desktop (lihat #buku di bagian bawah). */
  .tabel-bungkus td.kolom-aksi:not([data-l]) { display: flex; flex-wrap: wrap; gap: .5rem;
    padding-top: .7rem; }
  /* Panel ubah saat terbuka harus mengambil satu baris penuh. Tanpa ini .ubah
     tetap selebar tombolnya (terukur 58px), dan formulir di dalamnya ikut
     tercekik jadi 56px sehingga semua isian tak terbaca. */
  .tabel-bungkus .ubah[open] { flex: 1 1 100%; width: 100%; }
  .tabel-bungkus .kolom-aksi .sebaris { margin: 0; display: flex; flex: 1 1 auto; }
  .tabel-bungkus .kolom-aksi .tombol { width: auto; flex: 1 1 auto; }
  .tabel-bungkus .kolom-aksi .sebaris .tombol { width: 100%; }
  /* AKAR kepala ponsel tidak seragam (dulu /distribusi 155 vs dasbor 133):
     1) `flex-direction:column` menaruh baris tombol DI BAWAH judul -> semua
        halaman ber-tombol (+52px) selalu lebih tinggi dari yang tanpa tombol;
     2) deskripsi panjang membungkus 1-3 baris, jadi tingginya ikut teks.
     Solusi: kepala tetap SATU BARIS (judul kiri, tombol kanan) dan deskripsi
     dipotong ellipsis 1 baris -> tinggi kepala seragam di semua halaman
     (81px), tidak lagi bergantung panjang teks atau ada/tidaknya tombol.
     Teks deskripsi utuh tetap di DOM (pembaca layar & salin-tempel utuh). */
  /* AKAR "tombol kepala terpotong": dulu baris tombol dipaksa nowrap +
     overflow-x:auto supaya tinggi kepala seragam. Hasilnya tombol yang tak muat
     BUKAN turun baris, melainkan tergeser ke luar layar dan tak bisa ditekan
     (mis. "Ajukan Barang" di /kerja manajer 360px). Sekarang baris boleh
     membungkus: tombolnya selalu utuh & terjangkau. Tinggi kepala memang tidak
     lagi identik antar halaman, jadi gate menguji hal yang benar-benar penting —
     setiap tombol ada utuh di dalam layar (lihat _ukur_isi.py). */
  .kepala { flex-direction: row; align-items: flex-start; flex-wrap: wrap; gap: .45rem .6rem; }
  /* Judul didahulukan: TIDAK ikut menyusut saat baris tombol panjang, dan
     dipotong 1 baris (dulu ia terhimpit jadi 3 baris -> kepala 113px di
     /kerja & /distribusi manajer yang punya 2 tombol). */
  .kepala > div:first-child { flex: 1 1 auto; min-width: 0; }
  .kepala h1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Deskripsi TIDAK dipotong di ponsel: butuh 1-3 baris (mis. /distribusi "0 surat
     jalan — alur: ..." = 508px teks di 358px layar, /admin/vendor 3 baris). Dulu
     dipaksa nowrap+ellipsis 1 baris demi tinggi seragam -> teksnya terpotong.
     Tinggi kepala kini mengikuti jumlah baris (tetap terbatas, lihat gate). */
  .kepala .tenang { white-space: normal; overflow: visible; text-overflow: clip; }
  /* Tombol tidak turun baris: yang menyusut adalah barisnya, bila tak muat
     barisnya bergulir mendatar (tinggi kepala tetap, tombol tetap terjangkau). */
  .kepala .tombol-baris { width: auto; flex: 1 1 auto; min-width: 0; flex-wrap: wrap;
    justify-content: flex-end; overflow: visible; }
  .kepala .tombol { width: auto; flex: 0 1 auto; white-space: nowrap;
    padding: .42rem .6rem; font-size: .86rem; }
  /* Tombol aksi kepala milik Agrinas disembunyikan di ponsel: baris tombol +
     judul tidak muat semeja, tombolnya terpotong tepi layar. Aksinya tetap
     terjangkau lewat bilah bawah & halaman Semua Fitur. */
  .kepala .hanya-desktop { display: none; }
  /* Kebalikannya: aksi kepala yang memang datang dari bilah bawah (mis. Ajukan
     Barang, sudah ada di Dasbor) disembunyikan di ponsel supaya baris tombol
     tidak menumpuk dua baris dan kepala tetap ringkas. */
  .kepala .hanya-ponsel { display: none; }
  .kartu.angka b { font-size: 1.7rem; }
  .blok { padding: 1rem; }
  .kaki .kotak-pengguna .tanda { display: none; }
}

/* Ponsel sempit: tombol kepala diperkecil supaya baris tombol (bisa 2 buah)
   muat semeja dengan judul -> kepala tetap 81px dan tombol tak terpotong. */
@media (max-width: 480px) {
  .kepala { gap: .45rem; }
  .kepala .tombol { padding: .34rem .42rem; font-size: .78rem; }
}

/* ======================================================= halaman beranda */
.beranda { max-width: 1000px; margin: 0 auto; padding: clamp(1.1rem, .6rem + 1.6vw, 2.2rem);
  display: flex; flex-direction: column; gap: clamp(1.4rem, 1rem + 1.6vw, 2.6rem); }
.beranda-kepala { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.beranda-kepala .merek { color: #fff; }
.beranda-kepala .merek .nama { text-align: left; }
.beranda-kepala .merek small { color: #a7c2b5; }
.beranda-hero { display: flex; flex-direction: column; gap: .9rem; padding-top: .4rem; }
.beranda-hero h1 { font-size: clamp(1.5rem, 1.1rem + 2.2vw, 2.5rem); color: #fff;
  max-width: 22ch; margin: 0; line-height: 1.15; }
.beranda-hero p { color: #bcd2c7; font-size: clamp(.9rem, .86rem + .3vw, 1.02rem);
  max-width: 62ch; margin: 0; }
.beranda-hero .tombol-baris { margin-top: .5rem; }
.beranda-hero .tombol.samar { background: rgba(255, 255, 255, .1); border-color: rgba(255, 255, 255, .28);
  color: #e6f6ee; }
.beranda-hero .tombol.samar:hover { background: rgba(255, 255, 255, .18); color: #fff; }
.beranda-ciri { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 1rem; }
.beranda-ciri article { background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r);
  padding: 1.15rem 1.25rem; box-shadow: var(--bayang); border-top: 3px solid var(--hijau-300); }
.beranda-ciri h2 { text-transform: none; letter-spacing: -.01em; font-size: .98rem;
  color: var(--tinta); margin: 0 0 .45rem; }
.beranda-ciri p { font-size: .875rem; color: var(--tinta-2); margin: 0; }
.beranda-judul { color: #fff; font-size: 1.05rem; text-transform: none; letter-spacing: -.01em;
  margin: 0 0 1rem; }
.beranda-alur ol { list-style: none; counter-reset: langkah; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 1rem; }
.beranda-alur li { counter-increment: langkah; background: rgba(255, 255, 255, .06);
  border: 1px solid rgba(255, 255, 255, .13); border-radius: var(--r); padding: 1.05rem 1.15rem;
  color: #c7d8d0; font-size: .85rem; }
.beranda-alur li::before { content: counter(langkah); display: flex; align-items: center;
  justify-content: center; width: 26px; height: 26px; border-radius: 50%; margin-bottom: .6rem;
  background: var(--hijau-300); color: var(--hijau-900); font-weight: 700; font-size: .8rem; }
.beranda-alur li b { display: block; color: #fff; font-size: .92rem; margin-bottom: .3rem; }
.beranda-kaki { display: flex; flex-wrap: wrap; gap: .3rem 1.4rem; justify-content: space-between;
  border-top: 1px solid rgba(255, 255, 255, .12); padding-top: 1.1rem;
  color: #8fa89c; font-size: .78rem; }
@media (max-width: 560px) {
  .beranda-kepala { gap: .7rem; }
  .beranda-kepala .merek small { display: none; }
  .beranda-kepala .tombol { min-height: 38px; padding: .4rem .8rem; }
  .beranda-hero h1 { max-width: none; }
  .beranda-hero .tombol { width: 100%; }
  .beranda-alur, .beranda-ciri { gap: .75rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* =========================================== paging dasbor (Prev 1 2 3 … N Next) */
.paging { display: flex; align-items: center; gap: .5rem; flex-wrap: nowrap;
  margin-top: 1.1rem; padding-top: 1rem; border-top: 1px solid var(--garis-2);
  justify-content: center; }
.paging-angka { list-style: none; display: flex; align-items: center; gap: .25rem;
  margin: 0; padding: 0; min-width: 0; }
.paging-angka a, .paging-angka span { display: grid; place-items: center;
  min-width: 36px; height: 36px; padding: 0 .55rem; border-radius: var(--r-kecil);
  font-size: .85rem; font-weight: 600; text-decoration: none; color: var(--tinta-2);
  font-variant-numeric: tabular-nums; }
.paging-angka a { border: 1px solid var(--garis); background: var(--putih); }
.paging-angka a:hover { border-color: var(--hijau-500); color: var(--hijau-700); background: var(--hijau-100); }
.paging-angka span[aria-current] { background: var(--hijau-600); color: #fff;
  border: 1px solid var(--hijau-600); }
.paging-angka .celah { min-width: 22px; padding: 0; color: var(--pudar); letter-spacing: .05em; }
.paging .tombol { min-height: 36px; padding: .34rem .8rem; }
/* Tombol tepi tetap dirender walau tidak berlaku supaya deret nomor tidak
   bergeser saat berpindah halaman. */
.paging .tanpa-isi { visibility: hidden; }
.paging .kata { display: inline; }
/* Mobile: kalimat diganti panah saja; 5 nomor + 2 tombol muat di 360px. */
@media (max-width: 620px) {
  .paging { gap: .3rem; }
  .paging .kata { display: none; }
  .paging .tombol { padding: .3rem .55rem; }
  .paging-angka a, .paging-angka span { min-width: 30px; height: 32px; padding: 0 .4rem;
    font-size: .8rem; }
  .paging-angka { gap: .18rem; }
}

/* ============================================== halaman "Semua Fitur" (/fitur)
   Kisi ikon: 3 kolom di ponsel, melebar otomatis di layar besar. */
/* auto-FIT, bukan auto-fill: auto-fill menyisakan track kosong selebar 80px,
   jadi enam kartu Ruang Kerja tampak sempit dan menyisakan ruang mati di
   kanan (terukur: kartu 80px di wadah 902px). auto-fit meruntuhkan track yang
   tak terpakai sehingga kartu mengisi lebar penuh; di ponsel hasilnya tetap
   4 kolom (~80px) seperti sebelumnya. */
.kisi-fitur { display: grid; grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
  gap: .7rem; margin-top: .4rem; }
.kartu-fitur { display: flex; flex-direction: column; align-items: center; gap: .5rem;
  padding: 1rem .5rem; text-align: center; text-decoration: none; color: var(--tinta-2);
  background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r);
  font-size: .8rem; font-weight: 600; min-height: 104px; justify-content: center;
  font-family: inherit; cursor: pointer;
  transition: border-color .12s, background .12s, color .12s; }
.kartu-fitur:hover { border-color: var(--hijau-500); background: var(--hijau-100); color: var(--hijau-700); }
.kartu-fitur.ini { border-color: var(--hijau-600); background: var(--hijau-l); color: var(--hijau-700); }
.kartu-fitur-ikon { display: grid; place-items: center; width: 44px; height: 44px;
  border-radius: 50%; background: var(--zebra); }
.kartu-fitur.ini .kartu-fitur-ikon { background: var(--hijau-100); }
.ik-fitur { width: 24px; height: 24px; fill: currentColor; }
.kartu-fitur-label { overflow-wrap: anywhere; }

/* Butir terkunci: fitur AgriConnect sebelum akunnya dihubungkan (lihat
   agri/_nav.blade.php). Label & ikon tetap terbaca — yang hilang hanya
   kemampuan membuka halaman, dan kliknya menjawab lewat notifikasi. */
.kartu-fitur.terkunci { background: var(--zebra); border-style: dashed; color: var(--pudar); }
.kartu-fitur.terkunci .kartu-fitur-ikon { background: transparent; }
.kartu-fitur.terkunci:hover { border-color: var(--garis); background: var(--zebra); color: var(--pudar); }

/* ========== RUANG KERJA — kisi kartu modul ==========
   Revisi Bos: di DESKTOP 4 kolom TETAP → 2 baris rapi. `auto-fit` bawaan TIDAK
   bisa dibiarkan: di wadah lebar ia mengisi sebanyak track yang muat sehingga
   semua kartu berbaris jadi SATU baris tipis.
   Penandanya kelas `kisi-rk` (dipasang di workspace.blade.php), BUKAN jumlah
   kartu: dulu `:has(> .kartu-fitur:nth-child(8)):not(…nth-child(9))` yang
   berarti "kisi berisi TEPAT 8 kartu", dan aturannya langsung mati begitu
   Messenger disembunyikan + Koperasi pindah ke Pintasan (kartu jadi 7).
   Kelas stabil: kisi lain yang memakai `.kisi-fitur` — Pintasan (3),
   Semua Fitur (22) — tidak ikut berubah.                                     */
/* ponytail: breakpoint 900px selaras dengan blok media lain di berkas ini */
@media (min-width: 900px) {
  .kisi-rk { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Menu modul AgriConnect — kisi berkelompok (lihat agri/_nav.blade.php).
   Empat kartu sebaris TETAP: 4 kolom @358px = kartu 81px, dan 81px masih
   memuat label 3 baris tanpa meluber (inilah sebabnya `auto-fit` tidak dipakai
   — di ponsel ia menghasilkan kolom 86px sehingga "Perjalanan Dinas" pecah
   tiga baris). */
/* label terbaca) alih-alih menyembunyikan tautan. `display: block` pada kisi
   ini WAJIB: `:where(nav)` (baris 76) membuat SETIAP <nav> flex demi menu
   sisi, jadi `nav.kisi-modul` di dalam <main> pun flex — tiap .kisi-baris
   jadi flex-item yang menyusut sampai grid 4 kolomnya tinggal 24px dan label
   terpecah satu huruf per baris (terukur 390px: kartu 12x300px, dokumen
   melebar 620px). */
.kisi-modul { display: block; margin-bottom: var(--ruang); }
.kisi-baris { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .6rem; }
/* Kartu shortcut ini harus RINGKAS: `.kartu-fitur` aslinya untuk 6 tujuan
   (padding 1rem + min-height 104px). Dengan label 1-2 kata, padding itu
   menyisakan rongga kosong dan empat barisnya jadi 556px di layar 360px —
   separuh layar pertama habis sebelum isi halaman terlihat. */
/* Kartu di sini MEMBENTANG (ikon kiri, label kanan), bukan tumpuk tengah:
   `.kartu-fitur` aslinya 6 kartu pendek @80px, dan pada kartu selebar 272px
   (desktop) susunan tumpuk meninggalkan rongga kanan setengah kartu. */
.kisi-modul .kartu-fitur { padding: .6rem .7rem; gap: .6rem; min-height: 0;
  font-size: .78rem; flex-direction: row; align-items: center; text-align: left;
  justify-content: flex-start; height: 100%; }
.kisi-modul .kartu-fitur-ikon { width: 34px; height: 34px; flex: 0 0 auto; }
.kisi-modul .ik-fitur { width: 19px; height: 19px; }

/* Kelompok menu — judul kecil, bukan pelipat. Tiap kelompok SELALU terbuka
   (lihat agri/_nav.blade.php soal kenapa bukan <details>). `.kartu-fitur-label`
   dipaksa 2 baris rata: dengan 3 kata seperti "Akun AgriConnect" ia melipat
   tiga baris dan membuat SATU kartu lebih tinggi dari sebarisnya (terukur:
   baris 80-99px), jadi tinggi kartu dipatok seragam dan label dipotong elipsis
   — teks penuh tetap ada di title/teks tombolnya. */
.kisi-seksi { margin-top: .9rem; }
.kisi-seksi-judul {
  display: flex; align-items: center; gap: .45rem; margin: 0;
  font-size: .72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--tinta-3);
}
.kisi-seksi-judul { flex: 1 1 auto; }
.kisi-seksi-jumlah {
  flex: 0 0 auto; font-size: .68rem; font-weight: 600; text-transform: none;
  letter-spacing: 0; color: var(--tinta-3); background: var(--zebra);
  border-radius: 999px; padding: .1rem .5rem;
}
.kisi-seksi .kisi-baris { margin-top: .5rem; align-items: stretch; }
.kisi-modul .kartu-fitur-label { display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden; }

@media (max-width: 720px) {
  /* Ponsel: 2 kolom, bukan 4 — 84px terlalu sempit untuk label HR seperti
     "Perjalanan Dinas" (terukur: 2 kolom = 171px, label utuh 1 baris). */
  .kisi-modul .kisi-baris { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem; }
  .kisi-modul .kartu-fitur { font-size: .82rem; padding: .55rem .6rem; gap: .5rem; }
  .kisi-modul .kartu-fitur-ikon { width: 30px; height: 30px; }
}

/* ======================================================================
   PRESENSI — foto & titik lokasi (gaya SIMKOPDES)
   ====================================================================== */
/* Foto bukti di riwayat: kotak POTRET 3:4. Perbandingan ini dipegang di sini
   (object-fit: cover) supaya baris dari mana pun — foto SIMKOPDES yang lanskap
   maupun potret hasil kamera Hub — tampil seragam tinggi tanpa perlu memotong
   berkasnya di server. */
.presensi-bukti { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .5rem; }
.foto-presensi { display: block; width: 60px; aspect-ratio: 3 / 4; object-fit: cover;
  border-radius: var(--r-kecil); border: 1px solid var(--garis); background: var(--zebra); }
a:hover > .foto-presensi { border-color: var(--hijau-500); }
.peta-tautan { font-size: .8rem; font-weight: 600; text-decoration: none;
  color: var(--hijau-700, #15402f); white-space: nowrap; }
.peta-tautan:hover { text-decoration: underline; }
/* Isian berkas bawaan peramban tampak seperti teks polos tanpa batas, jadi
   tingginya tidak sejajar dengan isian teks di sebelahnya. `.form-cepat` sudah
   mengunci tinggi isian teks 42px — yang ini disamakan. */
.form-cepat input[type="file"] { width: 100%; margin: .35rem 0 0; padding: .4rem .5rem;
  height: 42px; font-size: .8rem; border: 1px solid var(--garis);
  border-radius: var(--r-kecil); background: var(--putih); }
.form-cepat button[disabled] { opacity: .5; cursor: not-allowed; }

/* Bingkai kamera presensi: pratinjau dan potret menempati kotak yang SAMA, jadi
   tata letaknya tidak melompat saat beralih dari pratinjau ke hasil jepretan.
   aspect-ratio 3/4 POTRET: potretnya memang potret — bingkai lanskap membuat
   wajah tampil kecil, dan hasilnya harus dipotong lagi di kanvas. */
.kamera-bingkai { position: relative; aspect-ratio: 3 / 4; margin: .35rem 0 0;
  background: #000; border: 1px solid var(--garis); border-radius: var(--r-kecil);
  overflow: hidden; }
.kamera-bingkai video, .kamera-bingkai .potret { position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; }
.kamera-bingkai video.cermin { transform: scaleX(-1); }   /* pratinjau selfie dicerminkan */
.kamera-bingkai .potret { background: #000; }
.kamera-pesan { position: absolute; left: 0; right: 0; bottom: 0; margin: 0;
  padding: .45rem .6rem; color: #f2f2f2; background: rgba(0, 0, 0, .62);
  font-size: .76rem; }
.label-kamera { display: block; font-size: .82rem; font-weight: 600; }
.label-kamera + .kamera-bingkai { margin-top: .5rem; }
.form-cepat .kamera-bingkai + .sebaris { margin-top: .5rem; }
/* Bingkai pratinjau di DALAM modal: 4/3 = tinggi 310px pada lebar 414 → badan
   modal (88vh) harus menggulir di ponsel lanskap/low-end, dan itu memang
   disengaja — memampatkan gambar hanya membuat wajah tak terbaca. */
.modal .kamera-bingkai + .tombol-baris { margin-top: .55rem; }

/* ================================================== teks monospace & bantuan */
.teks-polos { margin: 0; padding: .9rem 1rem; background: var(--zebra);
  border: 1px solid var(--garis-2); border-radius: var(--r-kecil);
  font-family: "JetBrains Mono", ui-monospace, monospace; font-size: .8rem;
  line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; }
.teks-pesan { display: block; font-size: .82rem; color: var(--tinta-2);
  white-space: pre-wrap; max-width: 60ch; }
.samar-kecil { color: var(--pudar); font-size: .74rem; }
.bantuan { font-size: .8rem; color: var(--pudar); margin: .7rem 0 0; max-width: 78ch; }
textarea { width: 100%; font: inherit; padding: .6rem .7rem; border: 1px solid var(--garis);
  border-radius: var(--r-kecil); background: var(--putih); color: var(--tinta); resize: vertical; }
input[type="file"] { padding: .45rem .5rem; background: var(--putih); }

/* ================================================ konferensi video (iframe) */
.bingkai-video { position: relative; width: 100%; aspect-ratio: 16 / 9;
  background: #0d1f17; border-radius: var(--r); overflow: hidden; }
.bingkai-video iframe { position: absolute; inset: 0; width: 100%; height: 100%;
  border: 0; }
@media (max-width: 620px) {
  /* Layar sempit: ruang vertikal lebih berharga daripada lebar; video di atas,
     kontrol Jitsi tetap terjangkau tanpa menggulir. */
  .bingkai-video { aspect-ratio: 4 / 3; }
}

/* ==================================== rapat Cloudflare Realtime (dua arah) */
.sfu-panggung { display: grid; gap: .6rem; background: #0d1f17;
  border-radius: var(--r); padding: .6rem;
  /* min(210px, 100%) — BUKAN minmax(210px, 1fr): pada kolom yang lebih sempit
     dari 210px (ponsel + grid masih dua kolom), minmax MEMAKSA 210px sehingga
     video meluber keluar kotaknya. Ini penyebab utama tata letak "berantakan". */
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }
.sfu-kotak { position: relative; aspect-ratio: 16 / 9; background: #0a1710;
  border-radius: var(--r-kecil); overflow: hidden; }
.sfu-video { width: 100%; height: 100%; object-fit: cover; display: block; }
.sfu-nama { position: absolute; left: .4rem; bottom: .4rem; font-size: .72rem;
  padding: .1rem .45rem; border-radius: 999px; background: rgba(0, 0, 0, .55);
  color: #fff; }
/* Video orang lain yang sedang mematikan kamera: biar tidak terlihat "macet". */
.sfu-kotak.mati .sfu-video { visibility: hidden; }
.sfu-kotak.mati::after { content: "kamera mati"; position: absolute; inset: 0;
  display: grid; place-items: center; font-size: .78rem; color: var(--pudar); }

/* Tata letak rapat: panggung + sisi obrolan/peserta. */
.rapat-tata { display: grid; gap: .9rem; grid-template-columns: minmax(0, 1fr) clamp(260px, 24vw, 340px);
  align-items: start; }
.rapat-utama { min-width: 0; }
/* Panggung rapat: batas bawah dinaikkan dari 210px supaya di desktop tidak
   muncul 4 kotak kecil sebaris — 2 kotak per baris jauh lebih enak dilihat.
   min() menjaga kolom sempit tetap aman (lihat .sfu-panggung di atas). */
.sfu-panggung { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
#sfu-saya-kotak { max-width: 100%; }
.rapat-kendali { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .6rem; }
.rapat-kendali .tombol { padding: .4rem .7rem; font-size: .84rem; }
.sfu-kotak.besar { grid-column: 1 / -1; }
.sfu-lencana { position: absolute; right: .4rem; bottom: .4rem; font-size: .8rem; }

/* Sisi obrolan + daftar peserta. */
.rapat-sisi { display: flex; flex-direction: column; background: var(--putih);
  border: 1px solid var(--garis); border-radius: var(--r); overflow: hidden; }
.rapat-tab { display: flex; border-bottom: 1px solid var(--garis); }
.rapat-tab .tab { flex: 1; padding: .5rem; font: inherit; font-size: .85rem; cursor: pointer;
  background: none; border: 0; color: var(--pudar); border-bottom: 2px solid transparent; }
.rapat-tab .tab.aktif { color: var(--tinta); font-weight: 600; border-bottom-color: var(--hijau); }
.rapat-panel { display: flex; flex-direction: column; min-height: 320px; max-height: 60vh; }
.rapat-log { flex: 1; overflow-y: auto; padding: .6rem; font-size: .86rem; }
.rapat-pesan { margin-bottom: .5rem; line-height: 1.35; word-break: break-word; }
.rapat-pesan.rapat-sistem { color: var(--pudar); font-size: .8rem; }
.rapat-kirim { display: flex; gap: .35rem; padding: .5rem; border-top: 1px solid var(--garis); }
.rapat-kirim input { flex: 1; padding: .4rem .5rem; border: 1px solid var(--garis);
  border-radius: var(--r-kecil); font: inherit; font-size: .86rem; }
.rapat-reaksi { display: flex; gap: .25rem; padding: 0 .5rem .5rem; }
.rapat-reaksi button { font-size: 1rem; padding: .1rem .25rem; background: none;
  border: 1px solid var(--garis); border-radius: var(--r-kecil); cursor: pointer; }
.rapat-orang { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem;
  padding: .35rem 0; border-bottom: 1px solid var(--garis); }
.rapat-nama { font-weight: 600; font-size: .86rem; }
.rapat-orang .pudar { font-size: .76rem; }
.rapat-kendali-peserta { display: flex; flex-wrap: wrap; gap: .25rem; margin-left: auto; }
.rapat-kendali-peserta button { font-size: .72rem; padding: .1rem .35rem; }
/* Reaksi terbang (gaya Zoom). */
.rapat-terbang { position: fixed; bottom: 18vh; left: 50%; font-size: 2rem;
  pointer-events: none; animation: terbang 2.6s ease-out forwards; z-index: 40; }
@keyframes terbang { from { opacity: 1; transform: translate(-50%, 0) scale(.8); }
  to { opacity: 0; transform: translate(-50%, -40vh) scale(1.6); } }
.pesan.galat { background: #fdecec; border-color: #f3b7b7; color: #7a1f1f; }
/* Lobi ruang rapat (gaya Zoom): pratinjau diri + pilih perangkat SEBELUM masuk.
   Dua kolom di layar lebar, satu kolom di ponsel — sama seperti .rapat-tata. */
/* Lobi tidak punya kotak pratinjau: gambar Anda tampil di panggung. Satu kolom
   supaya panel pengaturan tidak melebar aneh di desktop. */
.rapat-lobi { background: var(--putih); border: 1px solid var(--garis);
  border-radius: var(--r); padding: .9rem; margin-bottom: .7rem; max-width: 520px; }
.rapat-lobi-isi { display: flex; flex-direction: column; gap: .55rem; min-width: 0; }
.rapat-lobi-isi label { font-size: .82rem; }
.rapat-lobi-isi select { width: 100%; padding: .35rem .45rem; border: 1px solid var(--garis);
  border-radius: var(--r-kecil); font: inherit; font-size: .84rem; background: var(--putih); }
.rapat-lobi-nama { font-weight: 600; margin: 0; }
.rapat-lobi-isi .pesan { margin: 0; }


/* ---- Ruang rapat di layar sempit (ponsel & tablet) ----
   WAJIB satu kolom: `.rapat-tata` bawaannya `1fr 300px`, dan di 390px kolom
   utama menyusut jadi ~45px sehingga video, tombol, dan kotak obrolan saling
   menindih — persis keluhan "sangat berantakan". Aturan ini pernah ada lalu
   ikut terhapus saat menyunting blok lobi; ia dikembalikan di sini. */
@media (max-width: 900px) {
  .rapat-tata { grid-template-columns: 1fr; }
  /* Bilah kendali menempel di bawah: di ponsel tombolnya jauh dari jempol kalau
     harus digulir dulu, padahal ini panggilan video — kendalinya harus selalu
     terjangkau. Latar ditulis supaya video yang lewat di belakangnya tidak
     membuat tombol tak terbaca. */
  .rapat-kendali { position: sticky; bottom: 0; z-index: 5; margin-top: .5rem;
    padding: .45rem 0; background: var(--kertas); border-top: 1px solid var(--garis); }
  .rapat-kendali .tombol { flex: 1 1 auto; justify-content: center; min-height: 42px;
    padding: .5rem .6rem; font-size: .86rem; }
  /* Obrolan tidak perlu setinggi 60vh di ponsel — panggungnya yang utama. */
  .rapat-panel { min-height: 240px; max-height: 52vh; }
  .rapat-sisi { border-radius: var(--r); }
  /* Kartu peserta: satu baris per orang, kendali pengelola pindah ke bawah
     (di 390px tombolnya berdesakan dengan namanya kalau tetap sebaris). */
  .rapat-orang { flex-wrap: wrap; }
  .rapat-kendali-peserta { width: 100%; margin-left: 0; }
  /* Tombol kendali pengelola tidak memakai `.tombol.mini` (hanya `mini`), jadi
     aturan 40px di atas tidak menjangkaunya: terukur cuma 19px — terlalu kecil
     untuk jempol. Samakan tinggi sentuhnya dengan tombol mini lain di ponsel. */
  .rapat-kendali-peserta button { min-height: 40px; padding: .4rem .55rem; font-size: .8rem; }
}


/* ============================ beranda publik (gaya situs perusahaan) */
/* Struktur mengikuti pola situs agrinaspalma.co.id: latar terang, hero foto
   penuh lebar, seksi bergantian terang/gelap, kartu putih, aksen hijau. */
.beranda-tubuh { background: #f4f5f0; color: #202725; }
.situs { display: flex; flex-direction: column; align-items: stretch; }
.situs h1, .situs h2, .situs h3 { text-transform: none; letter-spacing: -.015em; margin: 0; }
/* :where() membuat selektor ini tetap (0,1,0) tapi tidak menimpa kelas
   modifier seperti .pub-media-aksi / .pub-media-catatan (yang juga 0,1,0 dan
   ditulis belakangan). Tanpa :where(), seluruh margin kelas itu hilang. */
.situs :where(p) { margin: 0; }

/* --- bilah atas --- */
/* Arah flex ditulis eksplisit: CSS lama punya aturan global `nav` yang
   membocorkan flex-direction column ke .pub-nav (menu jadi menumpuk tegak). */
.pub-bar { position: sticky; top: 0; z-index: 20; display: flex; flex-direction: row;
  align-items: center; gap: 1rem; padding: .55rem clamp(.9rem, .4rem + 2vw, 2.4rem);
  background: rgba(255, 255, 255, .94); backdrop-filter: blur(8px);
  border-bottom: 1px solid #e2e7e2; }
/* Dua logo terpisah + garis pemisah, mengikuti pola agrinaspalma.co.id */
.pub-merek { display: flex; align-items: center; gap: .6rem; margin-right: auto;
  text-decoration: none; }
.pub-merek img { height: auto; width: auto; display: block; }
.pub-merek .merek-danantara { height: 27px; }
.pub-merek .merek-pemisah { display: block; width: 1px; height: 26px; background: #d9e2dc; }
.pub-merek .merek-agrinas { height: 31px; }
.pub-nav { display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center;
  gap: 1.5rem; font-size: .875rem; }
.pub-nav a { color: #3f4b45; text-decoration: none; font-weight: 500;
  white-space: nowrap; }
.pub-nav a:hover { color: var(--hijau-700); text-decoration: underline; }
.pub-bar .tombol { white-space: nowrap; }
/* Jarak antar-tautan nav 1.5rem; beri tombol setengah gap bilah lagi supaya
   iramanya sama, bukan menempel lebih rapat dari tautan di sebelahnya. */
.pub-bar .masuk-bar { margin-left: .5rem; }

/* --- hero --- */
/* Latar dalam hijau lebih terang: foto disaring hijau muda, bukan hampir hitam. */
.pub-hero { position: relative; min-height: clamp(420px, 62vh, 620px);
  background: #dff2e4; display: flex; align-items: center; overflow: hidden; }
.pub-hero-gambar { position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; }
.pub-hero::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(13, 76, 45, .89) 0%, rgba(17, 94, 55, .78) 42%,
    rgba(21, 110, 63, .42) 72%, rgba(24, 122, 70, .16) 100%); }
.pub-hero-isi { position: relative; z-index: 2; padding: clamp(1.6rem, .9rem + 3vw, 3.4rem)
  clamp(.9rem, .4rem + 2vw, 2.4rem); max-width: 1180px; margin: 0 auto; width: 100%;
  display: flex; flex-direction: column; gap: .8rem; }
.pub-hero-merek { color: var(--hijau-300); font-size: .78rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .12em; }
.pub-hero h1 { color: #fff; font-size: clamp(1.7rem, 1.1rem + 3.1vw, 3.2rem);
  line-height: 1.08; max-width: 19ch; }
.pub-hero-isi > p { color: #cfe0d7; max-width: 58ch;
  font-size: clamp(.9rem, .87rem + .28vw, 1.05rem); }
.pub-hero .tombol-baris { margin-top: .6rem; }
.pub-hero .tombol.samar { background: rgba(255, 255, 255, .12);
  border-color: rgba(255, 255, 255, .34); color: #eaf5ee; }
.pub-hero .tombol.samar:hover { background: rgba(255, 255, 255, .22); color: #fff; }

/* --- bagian umum --- */
.pub-latar-lembut { background: #eef4f0; }
/* Kolom seksi 1180px dibuat oleh PADDING, bukan margin-auto tiap anak.
   Sebelumnya tiap anak punya margin auto sendiri, jadi judul seksi (74ch)
   ter-center di x≈403 sementara grid mulai di x≈130 — tampak melayang dan
   itulah yang membuat tata letak desktop terlihat berantakan. */
.pub-bagian { padding: clamp(2.2rem, 1.2rem + 3.6vw, 4.4rem)
  max(clamp(.9rem, .4rem + 2vw, 2.4rem), calc((100% - 1180px) / 2)); }
.pub-bagian > * { max-width: 1180px; margin-left: auto; margin-right: auto; }
.pub-kepala-bagian { max-width: 74ch; margin-left: 0; margin-right: 0; }
.pub-media-catatan, .pub-media-aksi, .pub-halaman, .pub-kutipan { margin-left: 0; }
.pub-kepala-bagian { display: flex; flex-direction: column; gap: .65rem; margin-bottom: 1.8rem;
  max-width: 74ch; }
.pub-kepala-bagian h2 { font-size: clamp(1.35rem, 1.05rem + 1.5vw, 2.15rem); line-height: 1.16; }
.pub-kepala-bagian > p { color: #4d5a53; font-size: clamp(.9rem, .87rem + .25vw, 1.02rem); }
.pub-eyebrow { color: var(--hijau-600); font-size: .76rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .13em; }
.pub-dua { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(1.4rem, .9rem + 2.2vw, 3rem); align-items: start; }
.pub-dua h2 { font-size: clamp(1.3rem, 1.02rem + 1.4vw, 2rem); line-height: 1.16; margin-bottom: .7rem; }
.pub-dua p + p { margin-top: .7rem; }
/* Judul kolom kiri disejajarkan dengan kartu di kanan: kartu punya padding
   atas ~1.35rem + garis 1px, kolom teks tidak — tanpa ini judul kiri
   menggantung 23px lebih tinggi dan seksi terlihat tidak rapi. */
.pub-cerita { padding-top: calc(1.35rem + 1px); }
.pub-dua > div > p { color: #4d5a53; }

/* bagian gelap */
/* Dua hal yang membuat seksi ini tampak kotor di layar sempit:
   (1) h2 judul seksi memakai warna global --pudar (#5f6f68) dan paragraf
       kolom memakai #4d5a53 — keduanya nyaris hilang di atas hijau
       (1,7:1 dan 1,3:1). Semua teks di seksi gelap di-override di bawah.
   (2) Latar #155238 bertabrakan dengan hijau tombol/aksen di dekatnya;
       hijau-900 (#12402a) sudah ada di palet dan memberi kontras lebih rata. */
.pub-gelap { background: var(--hijau-900); color: #e6eee9; }
.pub-gelap .pub-kepala-bagian h2 { color: #fff; }
.pub-gelap .pub-kepala-bagian > p { color: #cfe0d7; }
.pub-gelap .pub-dua > div > p { color: #cfe0d7; }
.pub-gelap .pub-daftar li { color: #cfe0d7; }
.pub-gelap .pub-kutipan figcaption { color: #a3bcae; }
.pub-gelap h3 { color: #fff; }
.pub-gelap .pub-eyebrow { color: var(--hijau-300); }
.pub-gelap > div > h3, .pub-gelap .pub-dua h3 { margin-bottom: .8rem; font-size: 1.02rem; }

/* --- daftar --- */
.pub-daftar, .pub-tanpa-tanda { list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: .6rem; }
.pub-daftar li { position: relative; padding-left: 1.5rem; font-size: .9rem; color: #bfd2c7; }
.pub-daftar li::before { content: ""; position: absolute; left: .25rem; top: .52em;
  width: 7px; height: 7px; border-radius: 50%; background: var(--hijau-300); }
.pub-tanpa-tanda li { font-size: .85rem; color: inherit; }

/* --- linimasa --- */
.pub-lini { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column;
  gap: .9rem; border-left: 2px solid #d9e2da; padding-left: 1.15rem; }
.pub-lini li { position: relative; display: flex; flex-direction: column; gap: .15rem; }
.pub-lini li::before { content: ""; position: absolute; left: -1.62rem; top: .38em;
  width: 11px; height: 11px; border-radius: 50%; background: var(--hijau-600);
  border: 2px solid #f4f5f0; }
.pub-lini b { font-size: .82rem; color: var(--hijau-700); letter-spacing: .04em; }
.pub-lini span { font-size: .88rem; color: #4d5a53; }

/* --- kartu --- */
.pub-kartu { background: #fff; border: 1px solid #e3e8e3; border-radius: 12px;
  padding: 1.35rem 1.45rem; box-shadow: 0 1px 2px rgba(16, 29, 24, .05); }
.pub-identitas h3 { font-size: .95rem; margin-bottom: .9rem; }
.pub-identitas dl { margin: 0; display: grid; grid-template-columns: minmax(6rem, 8.6rem) minmax(0, 1fr);
  gap: .55rem .9rem; }
.pub-identitas dt { font-size: .78rem; color: #6a776f; text-transform: uppercase;
  letter-spacing: .05em; }
.pub-identitas dd { margin: 0; font-size: .87rem; }
/* auto-fill (bukan auto-fit): baris terakhir tetap selebar kartu lain,
   tidak diregangkan memenuhi sisa lebar halaman. */
/* Lebar kolom dipatok 3 kolom di desktop: kartu 4 kolom menyisakan 2 kartu
   di baris kedua (banyak ruang kosong). */
.pub-kartu-grid { display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(min(238px, 100%), 1fr)); }
@media (min-width: 900px) {
  .pub-kartu-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.pub-kartu-grid .pub-kartu { border-top: 3px solid var(--hijau-300); }
.pub-kartu h3 { font-size: .98rem; margin-bottom: .45rem; }
.pub-kartu p { font-size: .875rem; color: #4d5a53; }
.pub-kartu-grid { margin-bottom: 1.6rem; }

/* --- langkah --- */
/* 2x2 di desktop supaya kolomnya sejajar dengan 3 kolom kartu di atasnya
   (sebelumnya 4 kolom sempit yang tidak sejajar apa pun). */
.pub-langkah { list-style: none; counter-reset: l; margin: 0; padding: 0; display: grid;
  gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); }
@media (min-width: 900px) {
  .pub-langkah { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.pub-langkah li { counter-increment: l; background: #fff; border: 1px solid #e3e8e3;
  border-radius: 12px; padding: 1.1rem 1.2rem; font-size: .85rem; color: #4d5a53; }
.pub-langkah li::before { content: counter(l); display: flex; align-items: center;
  justify-content: center; width: 26px; height: 26px; border-radius: 50%;
  margin-bottom: .6rem; background: var(--hijau-600); color: #fff; font-weight: 700;
  font-size: .8rem; }
.pub-langkah li b { display: block; color: #202725; font-size: .92rem; margin-bottom: .3rem; }

/* --- kutipan --- */
.pub-kutipan { margin: clamp(1.8rem, 1.2rem + 2vw, 2.8rem) 0 0;
  border-left: 3px solid var(--hijau-300); padding-left: 1.5rem; max-width: 74ch; }
.pub-kutipan blockquote { margin: 0; color: #dfeae3;
  font-size: clamp(1rem, .94rem + .5vw, 1.3rem); line-height: 1.45; }
.pub-kutipan figcaption { margin-top: .7rem; color: #93ac9f; font-size: .8rem; }

/* --- gambar + keterangan --- */
.pub-gambar { margin: 0; }
.pub-gambar img { width: 100%; height: auto; border-radius: 12px; display: block; }
.pub-gambar figcaption { margin-top: .6rem; font-size: .8rem; color: #6a776f; }
.pub-binaan { align-items: center; }

/* --- kaki --- */
.pub-kaki { background: #134430; color: #c3d6c9; margin-top: auto; }
.pub-kaki-grid { max-width: 1180px; margin: 0 auto; padding: clamp(1.8rem, 1.2rem + 2vw, 2.8rem)
  clamp(.9rem, .4rem + 2vw, 2.4rem); display: grid; gap: 1.6rem;
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr)); }
.pub-kaki h3 { color: #fff; font-size: .82rem; text-transform: uppercase;
  letter-spacing: .08em; margin-bottom: .6rem; }
.pub-kaki p, .pub-kaki li { font-size: .83rem; line-height: 1.55; }
.pub-kaki ul { list-style: none; margin: 0; padding: 0; display: flex;
  flex-direction: column; gap: .4rem; }
.pub-kaki a { color: #b9c9c0; text-decoration: none; }
.pub-kaki a:hover { color: #fff; text-decoration: underline; }
.pub-kaki-logo { height: 42px; width: auto; display: block; margin-bottom: .7rem;
  background: #fff; padding: .35rem .5rem; border-radius: 6px; }
/* Kaki gelap: logo berwarna, jadi tiap logo berdiri di alas putih tipis
   supaya warna aslinya tidak hilang di latar hijau tua. */
.pub-kaki .lockup { height: 42px; width: auto; display: block; margin-bottom: .8rem; }
.pub-kaki .kaki-logo { display: inline-flex; align-items: center; gap: .55rem;
  background: #fff; border-radius: 8px; padding: .38rem .6rem; margin-bottom: .8rem; }
.pub-kaki .kaki-logo img { display: block; height: 30px; width: auto; }
.pub-kaki .kaki-logo .kaki-pemisah { width: 1px; height: 26px; background: #dbe4df; }
.pub-slogan { color: #8fa89c; font-size: .78rem; text-transform: uppercase;
  letter-spacing: .06em; }
.pub-kaki-bawah { border-top: 1px solid rgba(255, 255, 255, .1);
  max-width: 1180px; margin: 0 auto; padding: .9rem clamp(.9rem, .4rem + 2vw, 2.4rem);
  display: flex; flex-wrap: wrap; gap: .35rem 1.6rem; justify-content: space-between;
  font-size: .76rem; color: #7d9488; }

/* ===================== revisi: header, direksi, ruang media, login ===================== */

/* --- header: lockup Danantara | Agrinas Pangan --- */
/* Lockup sudah memuat kedua logo, jadi cukup satu gambar.
   Nama perusahaan tetap ada di teks aria-label + footer. */
.pub-nav { gap: 1.15rem; }

/* Menu layar sempit: <details> supaya navbar tetap ada tanpa JavaScript. */
.pub-menu { display: none; position: relative; }
.pub-menu summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center;
  gap: .4rem; padding: .5rem .7rem; border: 1px solid #dde4e0; border-radius: 8px;
  font-size: .85rem; font-weight: 600; color: #3f4b45; background: #fff; }
.pub-menu summary::-webkit-details-marker { display: none; }
.pub-menu[open] summary { border-color: var(--hijau-500); color: var(--hijau-700); }
.pub-menu nav { position: absolute; right: 0; top: calc(100% + .45rem); z-index: 30;
  flex-direction: column; gap: .1rem; min-width: 232px; background: #fff; padding: .5rem;
  border: 1px solid #e2e7e2; border-radius: 12px; box-shadow: var(--bayang-2); }
.pub-menu nav a { color: #3f4b45; text-decoration: none; font-weight: 500; font-size: .9rem;
  padding: .55rem .7rem; border-radius: 8px; white-space: nowrap; }
.pub-menu nav a:hover { background: var(--hijau-100); color: var(--hijau-700); }
.pub-menu nav a.masuk-menu { margin-top: .3rem; border-top: 1px solid var(--garis-2);
  border-radius: 0 0 8px 8px; color: var(--hijau-700); font-weight: 700; }

/* --- jajaran direksi --- */
/* Kartu profil mendatar: potret 4/5 di kiri, biodata di kanan. Kartu potret
   tegak menyisakan separuh lebar halaman kosong saat direksinya sedikit. */
.pub-direksi { display: grid; gap: 1.2rem;
  grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr)); }
.pub-orang { display: flex; align-items: stretch; background: #fff;
  border: 1px solid #e3e8e3; border-radius: 12px; overflow: hidden;
  box-shadow: 0 1px 2px rgba(16, 29, 24, .05); }
.pub-orang .foto { flex: 0 0 148px; background: #eef3f1; }
.pub-orang .foto img { width: 100%; height: 100%; object-fit: cover; object-position: top center;
  display: block; }
.pub-orang .foto.kosong { display: flex; align-items: center; justify-content: center;
  background: linear-gradient(160deg, var(--hijau-800), #14532d); }
.pub-orang .foto.kosong span { color: #fff; font-size: 2.6rem; font-weight: 700;
  letter-spacing: .04em; opacity: .92; }
.pub-orang .orang-isi { padding: 1.25rem 1.35rem; display: flex; flex-direction: column;
  justify-content: center; gap: .1rem; min-width: 0; }
.pub-orang .orang-jabatan { color: var(--hijau-600); font-size: .72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em; }
.pub-orang h3 { font-size: 1rem; margin: .3rem 0 .35rem; line-height: 1.3; }
.pub-orang p { font-size: .82rem; color: #4d5a53; }
.pub-orang .orang-sumber { font-size: .7rem; color: #7d8a83; margin-top: .55rem; }

/* --- pusat informasi / ruang media --- */
.pub-media { display: grid; gap: 1.2rem;
  grid-template-columns: repeat(auto-fill, minmax(min(310px, 100%), 1fr)); }
.pub-artikel { background: #fff; border: 1px solid #e3e8e3; border-radius: 12px; overflow: hidden;
  display: flex; flex-direction: column; text-decoration: none; color: inherit;
  box-shadow: 0 1px 2px rgba(16, 29, 24, .05); }
.pub-artikel:hover { border-color: var(--hijau-500); box-shadow: var(--bayang-2); }
.pub-artikel .gambar { position: relative; aspect-ratio: 16 / 9; background: #e9efeb; }
.pub-artikel .gambar img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* logo Agrinas + Danantara ditempel di sudut tiap gambar berita */
.pub-artikel .badge { position: absolute; left: .55rem; bottom: .55rem;
  background: rgba(255, 255, 255, .95); border-radius: 6px; padding: .22rem .42rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .18); }
.pub-artikel .badge img { height: 17px; width: auto; display: block; }
.pub-artikel .isi-artikel { padding: .95rem 1.05rem 1.15rem; display: flex;
  flex-direction: column; gap: .4rem; flex: 1; }
.pub-artikel .meta { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .55rem;
  font-size: .72rem; color: #6a776f; }
.pub-artikel .meta .media { color: var(--hijau-700); font-weight: 700;
  text-transform: uppercase; letter-spacing: .05em; }
.pub-artikel h3 { font-size: .97rem; line-height: 1.35; }
.pub-artikel p { font-size: .835rem; color: #4d5a53; }
.pub-artikel .baca { margin-top: auto; padding-top: .45rem; font-size: .8rem; font-weight: 600;
  color: var(--hijau-600); }
.pub-artikel:hover .baca { text-decoration: underline; }
.pub-artikel.tanpa-gambar .gambar { display: none; }
.pub-media-catatan { font-size: .76rem; color: #7d8a83; margin-top: 1.2rem; max-width: 74ch; }
.pub-media-aksi { margin: 2.4rem 0 0; text-align: center;
  display: flex; justify-content: center; }
.pub-media-aksi .tombol { min-height: 46px; padding: .7rem 1.6rem; }
/* Paging: dua tombol di ujung, nomor halaman di tengah. */
.pub-halaman { display: flex; align-items: center; gap: .6rem;
  margin: 2.4rem auto 0; padding-top: 1.6rem; border-top: 1px solid #dfe6e1;
  justify-content: center; }
.pub-halaman-angka { list-style: none; display: flex; align-items: center; gap: .3rem;
  margin: 0; padding: 0; }
.pub-halaman-angka a, .pub-halaman-angka span { display: grid; place-items: center;
  min-width: 40px; height: 40px; padding: 0 .5rem; border-radius: 8px; font-size: .85rem;
  font-weight: 600; text-decoration: none; color: #4d5a53; }
.pub-halaman-angka a { border: 1px solid #dfe6e1; background: #fff; }
.pub-halaman-angka a:hover { border-color: var(--hijau-500); color: var(--hijau-700);
  background: var(--hijau-100); }
.pub-halaman-angka span[aria-current] { background: var(--hijau-600); color: #fff;
  border: 1px solid var(--hijau-600); }
.pub-halaman .tombol { min-height: 40px; }
.pub-halaman .tanpa-isi { visibility: hidden; }
/* Mobile: tetap satu baris — 3 item (prev + nomor + next) muat di 390px;
   tombol selebar baris membuat paging jadi tiga tingkat. */
@media (max-width: 560px) {
  .pub-halaman { gap: .4rem; }
  .pub-halaman .tombol { padding: .5rem .7rem; font-size: .82rem; }
  .pub-halaman .tombol.tanpa-isi { display: none; }
}

/* --- halaman masuk: dua logo berwarna (Danantara | Agrinas), sama seperti kaki
   halaman. panel-kiri = flex column, jadi tanpa align-self: flex-start gambar
   diregangkan selebar panel dan rasionya jadi gepeng. */
.panel-kiri .merek-lockup { display: inline-flex; align-items: center; gap: .55rem;
  align-self: flex-start; background: #fff; border-radius: 8px; padding: .38rem .6rem; }
.panel-kiri .merek-lockup img { display: block; height: 30px; width: auto; }
.panel-kiri .merek-lockup .merek-pemisah { width: 1px; height: 26px; background: #d9e2dc; }

/* --- halaman masuk: rapatkan di layar PENDEK supaya form tetap utuh satu layar.
   Diletakkan di akhir berkas: blok .panel-kiri/.panel-kanan dasar dan aturan
   mobile (max-width:900px) ada di atas, spesifisitasnya sama, jadi urutan
   di sini yang menentukan. Jangan pindahkan ke atas. */
@media (max-height: 700px) {
  .masuk { padding: .75rem; }
  .panel-kiri, .panel-kanan { padding: 1.5rem 1.7rem; }
  .panel-kiri { gap: .85rem; }
  .panel-kiri h1 { font-size: 1.45rem; }
}
/* Kolom tunggal + pendek = paling boros tinggi (dua panel bertumpuk), padahal
   ruangnya paling sempit. Buang teks penjelas, sisakan logo, judul, dan form. */
@media (max-width: 900px) and (max-height: 700px) {
  .panel-kiri > p, .panel-kanan .bantuan { display: none; }
  .panel-kiri h1 { font-size: 1.3rem; }
}
/* Tingkat terakhir — HP kecil lawas (320x480, 4"). Semua dirapatkan; tidak ada
   yang disembunyikan lagi supaya form tetap lengkap. */
@media (max-width: 900px) and (max-height: 560px) {
  .masuk { padding: .5rem; }
  .panel-kiri, .panel-kanan { padding: .85rem 1rem; }
  .panel-kiri { gap: .5rem; }
  .panel-kiri h1 { font-size: 1.05rem; }
  .panel-kiri .merek-lockup img { height: 22px; }
  .panel-kanan h2 { font-size: 1rem; }
}

@media (max-width: 1060px) {
  .pub-nav { display: none; }
  .pub-menu { display: block; }
  /* Tombol Masuk di bilah hanya untuk desktop; di lebar ini tautannya sudah ada
     di dalam menu ☰ dan bilahnya harus tetap sesempit mungkin. */
  .pub-bar .masuk-bar { display: none; }
}
@media (max-width: 860px) {
  .pub-dua { grid-template-columns: 1fr; }
  .pub-binaan { grid-template-columns: 1fr; }
  .pub-identitas dl { grid-template-columns: 1fr; gap: .1rem; }
  .pub-identitas dd { margin-bottom: .5rem; }
}
@media (max-width: 560px) {
  .pub-merek { gap: .45rem; }
  .pub-merek .merek-danantara { height: 20px; }
  .pub-merek .merek-pemisah { height: 20px; }
  .pub-merek .merek-agrinas { height: 23px; }
  .pub-bar { gap: .4rem; padding: .5rem .9rem; }
  .pub-menu summary { padding: .45rem .55rem; font-size: .8rem; }
  /* Di mobile item ber-nomor (alur Agrinas Hub) diletakkan di tengah:
     nomor, judul, dan teksnya ikut center supaya tidak menggantung kiri. */
  .pub-langkah li { text-align: center; }
  .pub-langkah li::before { margin-left: auto; margin-right: auto; }
  .pub-kaki .lockup { height: 34px; }
  /* 400px terasa pendek di 390px-lebar: judul + paragraf + dua tombol
     selebar baris hampir memenuhi, sisa ruang atas-bawah tinggal tipis.
     448px (+12%) memberi napas tanpa mendorong seksi berikutnya terlalu jauh. */
  .pub-hero { min-height: 448px; }
  .pub-hero-isi { gap: .65rem; }
  .pub-hero h1 { max-width: none; }
  .pub-hero .tombol { width: 100%; }
  .pub-hero::after { background: linear-gradient(180deg, rgba(11, 68, 40, .89) 0%,
    rgba(15, 82, 48, .82) 55%, rgba(18, 96, 56, .72) 100%); }
  .pub-kaki-logo { height: 36px; }
}



/* ------------------------------------------------------------ Ruang Kerja
   Bilah modul, kalender bulanan, pohon wiki, dan pesan berterjemahan.
   Semua memakai warna & bentuk yang sudah ada di berkas ini. */
.modul-nav { display:flex; gap:.4rem; flex-wrap:wrap; margin:0 0 1.1rem; }
.modul-nav a { display:inline-flex; align-items:center; gap:.4rem; padding:.42rem .7rem;
  border:1px solid var(--garis, #d8ded9); border-radius:999px; font-size:.86rem;
  text-decoration:none; color:inherit; white-space:nowrap; }
.modul-nav a.ini { background:#15402f; border-color:#15402f; color:#fff; }
.modul-nav a:hover { background:#eef3ef; }
.modul-nav a.ini:hover { background:#1b5139; color:#fff; }

.obrolan { border:1px solid var(--garis, #e2e7e3); border-radius:.8rem;
  padding:.75rem .9rem; margin-bottom:.7rem; background:#fff; }
.obrolan-kepala { display:flex; justify-content:space-between; gap:.6rem; align-items:baseline; }
.obrolan-kepala > small { font-size:.74rem; }
.pesan-terjemah { margin-top:.55rem; padding:.5rem .7rem; border-left:3px solid #15402f;
  background:#f3f7f4; border-radius:.35rem; }
.pesan-terjemah > small { display:block; margin-bottom:.2rem; color:#15402f; }

/* Wadah editor. ONLYOFFICE MENGGANTI #editor-dokumen dengan iframe-nya sendiri,
   jadi iframe itu jadi SAUDARA wadah, bukan anak — karena itu tinggi dipasang di
   wadah pembungkus ini dan memakai `> *` (anak apa pun), bukan `> iframe`. */
.editor-bingkai { height:70vh; min-height:520px; border:1px solid var(--garis, #d8ded9);
  border-radius:.5rem; background:#fff; overflow:hidden; }
.editor-bingkai > * { display:block; width:100%; height:100%; border:0; }

.kal-grid { display:grid; grid-template-columns:repeat(7, 1fr); gap:3px; }
.kal-judul > div { text-align:center; font-size:.76rem; font-weight:600; padding:.3rem 0; color:#5b6b62; }
/* AKAR kalender meluber (terukur 407px dari layar 360px): kisi 7 kolom 1fr
   tidak boleh sempit dari MIN-CONTENT, dan min-content barisnya ditentukan
   isi. Tanpa `min-width:0` + `overflow:hidden`, satu judul acara yang panjang
   melebarkan kolomnya sendiri lalu mendorong SELURUH kisi keluar kartu. */
.kal-sel { min-height:88px; border:1px solid var(--garis, #e2e7e3); border-radius:.4rem;
  padding:.3rem; background:#fff; display:flex; flex-direction:column; gap:2px; min-width:0; overflow:hidden; }
.kal-luar { background:#f7f9f8; border-style:dashed; }
.kal-kini { outline:2px solid #15402f; }
.kal-tgl { font-size:.76rem; font-weight:600; color:#5b6b62; }
/* Wadah acara dalam satu sel. Desktop: bertumpuk, satu baris per acara
   (judul panjang dipotong) supaya kisi tetap rapi. */
.kal-acara-baris { display:flex; flex-direction:column; gap:2px; min-width:0; }
/* Di layar lebar judul panjang dipotong satu baris (kotak tetap rapi). Di
   ponsel `white-space:nowrap` DILEPAS: judul boleh membungkus 2 baris dan
   `overflow-wrap:anywhere` yang menjamin kata panjang pun tidak melebarkan
   kolom. Huruf dinaikkan ke .68rem agar tetap terbaca. */
.kal-acara { display:block; min-width:0; font-size:.7rem; line-height:1.25;
  padding:1px 3px; border-radius:.25rem; text-decoration:none; color:inherit;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; overflow-wrap:anywhere; }
.kal-rapat { background:#e3efe8; color:#15402f; }
.kal-rapat:hover { background:#cfe4d8; }
.kal-tenggat { background:#fdf1e3; color:#8a5a12; }

.wiki-pohon { list-style:none; margin:0; padding-left:1rem; }
.wiki-pohon > li { margin:.25rem 0; }
.wiki-pohon a { text-decoration:none; }
.wiki-pohon a:hover { text-decoration:underline; }
/* Ringkasan status persetujuan: tiga lencana sebaris, boleh melipat di ponsel. */
.setuju-ringkas { display:flex; flex-wrap:wrap; gap:.4rem; margin:0 0 .9rem; }
.daftar-langkah { list-style:none; margin:.4rem 0; padding-left:.8rem; font-size:.86rem; }
.baris-langkah { background:#fafcfb; }

@media (max-width: 720px) {
  /* 🔴 GRID KALENDER DI PONSEL: 7 kolom kisi TIDAK muat untuk menampilkan judul
     acara (tiap kolom ~40px). Pendekatan lama mengecilkannya jadi TITIK 7px
     `font-size:0` — informasinya hilang, hanya sisa "ada sesuatu hari itu".
     Sekarang: kisi tetap ada sebagai PETA BULAN (tanggal + jumlah acara), lalu
     daftar acara bulan itu ditampilkan sebagai AGENDA PER TANGGAL yang terbaca.
     Tidak ada yang disembunyikan, dan tidak perlu JS. */
  .kal-grid { gap:2px; }
  .kal-judul > div { font-size:.66rem; padding:.2rem 0; letter-spacing:.02em; }
  .kal-sel { min-height:0; padding:.3rem .2rem; border-radius:.35rem; }
  /* Sel di luar bulan ini TETAP ada sebagai kotak kosong: menyembunyikannya
     membuat sisa tanggal bergeser (terukur kolom 1-3 jadi 0px) dan nama hari
     tidak lagi sejajar dengan tanggalnya. */
  .kal-tgl { font-size:.8rem; justify-content:center; }
  .kal-titik { display:inline-flex; }
  /* Acara TIDAK lagi ditampilkan di dalam sel (tidak muat) — pindah ke daftar. */
  .kal-acara-baris { display:none; }
  .kal-sel.kal-pekan .kal-angka { color:#9aa5a0; }

  /* Daftar acara per tanggal (dirender oleh Blade setelah kisi). */
  .kal-daftar { display:grid; gap:.7rem; grid-template-columns:minmax(0, 1fr); }
  .kal-hari { border:1px solid var(--garis); border-radius:var(--r-kecil);
    background:var(--putih); padding:.55rem .7rem; }
  .kal-hari > h3 { margin:0 0 .35rem; font-size:.82rem; display:flex; gap:.45rem;
    align-items:center; flex-wrap:wrap; }
  .kal-hari > h3 .kal-angka { font-size:1rem; font-weight:700; }
  .kal-hari > h3 .kal-bulan { color:var(--pudar); font-weight:500; font-size:.76rem; }
  .kal-hari.kal-kini { border-color:var(--hijau-600); box-shadow:0 0 0 1px var(--hijau-600) inset; }
  .kal-hari .kal-acara { display:flex; gap:.5rem; align-items:flex-start; width:auto; height:auto;
    border-radius:var(--r-kecil); padding:.4rem .55rem; font-size:.85rem; margin-bottom:.3rem;
    position:static; /* 🔴 `white-space` bawaan .kal-acara = nowrap; tanpa normal di sini
       teks 539px tak bisa membungkus, kolom grid melebar jadi 621px, dan halaman
       meluber 264px di ponsel. */ white-space:normal; }
  .kal-hari .kal-acara:last-child { margin-bottom:0; }
  .kal-hari .kal-jam { flex:0 0 auto; font-weight:600; font-size:.78rem; opacity:.85; }
  .kal-hari .kal-nama { flex:1 1 auto; min-width:0; overflow-wrap:anywhere; }
  .kal-dua { grid-template-columns:1fr; }
  .kal-navigasi { width:100%; }
  .kal-navigasi .tombol { flex:1 1 auto; justify-content:center; }
}
/* Daftar acara per tanggal hanya untuk ponsel; di layar lebar acara ada DI DALAM
   sel kisi, jadi daftar ini disembunyikan agar tidak tampil dua kali. */
@media (min-width: 721px) { .kal-daftar { display:none; } }


/* ================================== surat jalan, jejak pantauan, baris turun */
.ttd-kisi { display: grid; grid-template-columns: 1fr 1fr; gap: 1.4rem; margin-top: 1.6rem; }
.ttd-kisi > div { border-top: 1px solid var(--garis); padding-top: .5rem; }
.ttd-kisi small { color: var(--pudar); }
.ttd-ruang { display: block; height: 58px; }
.ttd-kisi b { display: block; font-size: .86rem; border-top: 1px dotted var(--garis); padding-top: .25rem; }
@media (max-width: 620px) { .ttd-kisi { grid-template-columns: 1fr; gap: .8rem; } }

.jejak { margin: .5rem 0 0; padding: 0 0 0 .9rem; font-size: .78rem; color: var(--tinta-2); }
.jejak li { margin-bottom: .3rem; }
.baris-turun td { opacity: .55; }
.baris-turun .lencana.merah { opacity: 1; }
.ubah .jejak { list-style: disc; }

/* ======================================================================
   PERCAKAPAN (Messenger) — disusun seperti aplikasi pesan
   ----------------------------------------------------------------------
   Daftar ruang di kiri, percakapan di kanan. Nama kelas berawalan `wa-`
   supaya jelas ini satu sistem, bukan tumpukan kartu biasa.
   ====================================================================== */
/* ============================================= PERCAKAPAN — ukuran layar penuh

   Halaman percakapan mengisi SELURUH tinggi layar, bukan setinggi isinya.
   Sebelumnya .wa setinggi isi dan .wa-pesan dipaku height:min(62vh,560px),
   jadi di monitor besar percakapan menggantung di atas dan menyisakan ratusan
   piksel kosong di bawah — itu yang membuatnya terasa "nanggung".
   Rumus: 100dvh - kepala halaman - bilah nav bawah - tepi .isi. */

body.wa-penuh { display: flex; flex-direction: column; height: 100dvh; }
/* Shell mengisi SISA ruang setelah bilah bawah, bukan setinggi layar penuh.
   Sisa ini dihitung peramban sendiri — itulah sebabnya bilah bawah di halaman
   ini dipindah ke dalam aliran flex (lihat `body.wa-penuh .nav-bawah`), bukan
   lagi `position: fixed` yang menutupi dasar layar tanpa diketahui isi. */
body.wa-penuh .shell { flex: 1 1 auto; height: auto; min-height: 0; }
body.wa-penuh .isi { display: flex; flex-direction: column; min-height: 0;
  /* Bilah bawah sudah DI LUAR area ini (baris flex sendiri), jadi tidak ada
     yang perlu disisakan — cukup jarak tepi halaman seperti desktop. */
  padding-bottom: var(--sp); }
body.wa-penuh .wa { flex: 1 1 auto; min-height: 0;
  grid-template-rows: minmax(0, 1fr); align-items: stretch; }
/* Di ponsel, halaman obrolan TIDAK memakai bilah melayang: bilah bawah ikut
   aliran flex di dasar layar. Dua alasan:
     1. `.sisi` (kepala) di halaman ini `position: sticky` dan ikut menggulir,
         jadi bilah melayang justru menutupi kepala saat halaman digulir;
     2. bilah melayang menyembunyikan tinggi aslinya dari isi halaman, sehingga
         kolom tulis dan tombol Kirim berhenti di bawahnya (terukur 49px
         tertutup di 360/390/430px) — itu cacat yang tak bisa ditambal angka.
   Sebagai baris flex, sisa tinggi dibagi peramban sendiri: tidak ada angka
   ajaib, tidak ada yang tertutup. */
@media (max-width: 900px) {
  body.wa-penuh .nav-bawah { position: static; inset: auto; flex: 0 0 auto;
    box-shadow: none; }
}
.wa-sisi { display: flex; flex-direction: column; min-height: 0; }
.wa-atas { display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  padding: .5rem .6rem; border-bottom: 1px solid var(--garis); }
.wa-atas b { font-size: .8rem; letter-spacing: .04em; text-transform: uppercase; color: var(--pudar); }
.wa-baru { display: flex; flex-direction: column; gap: .45rem; padding: .6rem;
  border-bottom: 1px solid var(--garis); background: var(--zebra);
  /* Dibatasi + bisa digulir: tanpa ini panel melar setinggi isinya (~700px,
     daftar peserta 29 nama) dan menyisakan hampir nol ruang untuk daftar
     percakapan di bawahnya. */
  max-height: min(62vh, 430px); overflow-y: auto; }
.wa-baru label { font-size: .78rem; color: var(--tinta-2); display: flex; flex-direction: column; gap: .2rem; }
.pilih { border: 1px solid var(--garis); border-radius: var(--r-kecil); background: var(--putih); }
.pilih-kepala { display: flex; gap: .4rem; align-items: center; padding: .4rem; border-bottom: 1px solid var(--garis); }
.pilih-kepala input[type="search"] { margin: 0; min-height: 34px; padding: .3rem .5rem; }
/* ---------- Select2 (pencarian di <select> panjang) ----------
   Lingkup peserta & rekan kini SATU kolom ber-Select2: kotak cari dibawa oleh
   perkakasnya sendiri, bukan kotak terpisah di atas <select>. Sebelumnya ada
   DUA kolom yang tampak sama (terukur 17 Okt 2026: cari 337x46 & select 337x45,
   bg/border/radius/font identik, tanpa ikon) sehingga pengguna mengira tak ada
   pencarian. Gaya di bawah menyetel Select2 agar setinggi & sebentuk isian
   Hub lain (min-height 42px, radius --r-kecil, border --garis). */
.pilih2 + .select2-container { width: 100% !important; margin-top: .35rem; }
.select2-container--default .select2-selection--single {
  min-height: 42px; height: auto; padding: .35rem .5rem; display: flex; align-items: center;
  border: 1px solid #ccd7d1; border-radius: var(--r-kecil); background: var(--putih); }
.select2-container--default .select2-selection--single:hover { border-color: #b6c4bd; }
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--single {
  border-color: var(--hijau-600); outline: 2px solid var(--hijau-300); outline-offset: -1px; }
.select2-container--default .select2-selection--single .select2-selection__rendered {
  padding: 0; line-height: 1.35; color: var(--tinta); font-size: .875rem; }
.select2-container--default .select2-selection--single .select2-selection__placeholder { color: #67766f; }
.select2-container--default .select2-selection--single .select2-selection__arrow { height: 40px; right: .35rem; }
/* Kotak cari di dalam daftar turun: ikon kaca pembesar supaya jelas ia CARI,
   bukan isian biasa (perilaku ini yang dulu hilang). */
.select2-container--default .select2-search--dropdown .select2-search__field {
  min-height: 38px; padding: .4rem .6rem .4rem 2rem; border: 1px solid #ccd7d1;
  border-radius: var(--r-kecil); background: var(--zebra) no-repeat .55rem center;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235f6f68' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.5-3.5'/%3E%3C/svg%3E");
  background-size: 15px 15px; font-size: .875rem; }
.select2-dropdown { border: 1px solid var(--garis); border-radius: var(--r-kecil);
  box-shadow: 0 10px 26px rgba(0, 0, 0, .12); font-size: .875rem; overflow: hidden; }
.select2-container--default .select2-results__option[aria-selected="true"] {
  background: var(--hijau-600); color: #fff; }
.select2-container--default .select2-results__option--highlighted[aria-selected] {
  background: var(--zebra); color: var(--tinta); }
.select2-container--default .select2-results__group { color: var(--tinta-2); font-weight: 600; }
/* Keterangan "tak ada yang cocok" ikut berbahasa Indonesia? Select2 menaruh
   teks bawaannya di sini; bahasanya diatur lewat opsi JS halaman ini. */
.pilih-aksi { display: flex; gap: .3rem; flex: none; }
/* Daftar bergulir: cukup tinggi untuk beberapa baris, tapi tidak memanjangkan
   panel "+ Baru" yang dipakai bersama formulir lain. */
.pilih-daftar { list-style: none; margin: 0; padding: .2rem; max-height: 178px; overflow-y: auto; }
.pilih-daftar li { margin: 0; }
.pilih-daftar li[hidden] { display: none; }
/* CATATAN: harus `.wa-baru .pilih-baris`, bukan `.pilih-baris` saja. Aturan
   `.wa-baru label { flex-direction: column }` (satu kelas + satu elemen) lebih
   spesifik daripada `.pilih-baris` (satu kelas), jadi tanpa ini setiap baris
   tersusun VERTIKAL: kotak centang tidak sebaris dengan nama dan tinggi baris
   melonjak 15px -> 92px (terukur). */
.wa-baru .pilih-baris { display: flex; flex-direction: row; align-items: center; gap: .5rem;
  margin: 0; padding: .35rem .45rem; border-radius: var(--r-kecil); cursor: pointer;
  font-weight: 400; font-size: .82rem; color: var(--tinta); }
.pilih-baris:hover { background: var(--hijau-100); }
/* Baris terpilih ditandai centang + latar, jadi pilihan tetap terlihat walau
   namanya sedang tersaring keluar dari daftar. */
.pilih-baris.centang { background: var(--hijau-100); }
.pilih-baris.centang .pilih-nama { font-weight: 700; }
.pilih-baris.centang::after { content: "✓"; margin-left: auto; color: var(--hijau-600); font-weight: 800; }
.wa-baru .pilih-nama { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wa-baru .pilih-baris small { flex: none; max-width: 45%; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--pudar); font-size: .72rem; font-weight: 400; }
.pilih-ringkas { margin: .35rem .5rem 0; font-size: .76rem; color: var(--hijau-700, var(--hijau-600)); font-weight: 600; }
.pilih-kosong { margin: .4rem .5rem; font-size: .8rem; color: var(--pudar); }
.wa-daftar { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.wa-ruang { min-height: 0; }
.wa-pesan { flex: 1 1 auto; height: auto; min-height: 0; overflow-y: auto; }
.wa-kepala-teks { min-width: 0; flex: 1 1 auto; }
.wa-kepala-teks b, .wa-kepala-teks small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wa-info { position: relative; flex: none; }
.wa-info > summary { list-style: none; cursor: pointer; }
.wa-peserta { position: absolute; right: 0; top: calc(100% + .3rem); z-index: 5; margin: 0;
  padding: .5rem .8rem; list-style: none; min-width: 180px; max-height: 260px; overflow-y: auto;
  background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r-kecil);
  box-shadow: var(--bayang-2); font-size: .82rem; }
.wa-peserta li { padding: .18rem 0; }
/* Tombol kembali hanya berguna di ponsel (daftar jadi laci). */
.wa-kembali { display: none; flex: none; width: 36px; height: 36px; border: 0; background: none;
  font-size: 1.5rem; line-height: 1; color: var(--tinta-2); cursor: pointer; border-radius: 50%; }
.wa-kembali:hover { background: var(--hijau-100); }
.wa-ajak { display: grid; place-items: center; background: var(--zebra); }
.wa-ajak-dalam { max-width: 460px; padding: 1.5rem; }
.wa-cara { margin: .6rem 0; padding-left: 1.1rem; font-size: .88rem; color: var(--tinta-2); }
.wa-cara li { margin-bottom: .35rem; }

.wa { display: grid; grid-template-columns: minmax(0, 264px) minmax(0, 1fr); gap: .9rem; align-items: start; }
.wa-sisi { background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r); overflow: hidden; }
.wa-cari { padding: .55rem; border-bottom: 1px solid var(--garis); }
.wa-cari input { min-height: 36px; }
.wa-daftar { display: flex; flex-direction: column; max-height: 68vh; overflow-y: auto; }
/* Daftar versi halaman /workspace/pesan: selebar kartu, bukan kolom sempit. */
.wa-daftar.lebar { max-height: none; background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r); overflow: hidden; }
.wa-baris { display: flex; align-items: center; gap: .6rem; padding: .6rem .7rem; text-decoration: none; color: inherit; border-bottom: 1px solid var(--garis-2, #eef1ee); min-width: 0; }
.wa-baris:last-child { border-bottom: 0; }
.wa-baris:hover { background: var(--hijau-100); }
.wa-baris.ini { background: var(--hijau-l); }
.wa-avatar { flex: none; width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; background: var(--hijau-600, #15402f); color: #fff; font-weight: 700; font-size: .95rem; }
.wa-avatar.besar { width: 42px; height: 42px; }
.wa-baris-teks { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; }
.wa-baris-teks b, .wa-baris-teks small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wa-baris-teks b { font-size: .9rem; }
.wa-baris-teks small { color: var(--pudar); font-size: .78rem; }
.wa-baris-meta { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: .2rem; font-size: .72rem; color: var(--pudar); }

.wa-ruang { display: flex; flex-direction: column; min-width: 0; background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r); overflow: hidden; }
.wa-kepala { display: flex; align-items: center; gap: .65rem; padding: .6rem .8rem; border-bottom: 1px solid var(--garis); background: var(--zebra); }
.wa-kepala b { display: block; font-size: .95rem; }
.wa-kepala small { color: var(--pudar); font-size: .78rem; }
/* Papan pesan menggulir sendiri: kepala dan kotak tulis tetap di tempat. */
.wa-pesan { display: flex; flex-direction: column; gap: .35rem; padding: .85rem; background: #f3f5f2; overflow-y: auto; height: min(62vh, 560px); }
.wa-b { position: relative; max-width: 78%; align-self: flex-start; background: var(--putih); border: 1px solid var(--garis); border-radius: 14px 14px 14px 4px; padding: .45rem .8rem .3rem .65rem; box-shadow: 0 1px 1px rgba(16, 29, 24, .05); }
.wa-b.dia { align-self: flex-end; background: #dcf3dd; border-color: #c3e5c5; border-radius: 14px 14px 4px 14px; }
.wa-b.lanjut { margin-top: -.2rem; }
.wa-nama { display: block; font-size: .74rem; font-weight: 700; color: var(--hijau-700, #1b5139); margin-bottom: .1rem; }
.wa-teks { font-size: .9rem; overflow-wrap: anywhere; }
.wa-terjemah { margin-top: .3rem; padding-top: .25rem; border-top: 1px dashed var(--garis); font-size: .82rem; color: var(--tinta-2); }
.wa-jam { display: block; text-align: right; font-size: .66rem; color: var(--pudar); margin-top: .1rem; }
.wa-kirim-menunggu { opacity: .55; }
.wa-kosong { color: var(--pudar); font-size: .86rem; text-align: center; padding: 1rem; }
/* Alat per pesan (terjemahkan) disembunyikan di balik tombol titik-tiga. */
.wa-alat { position: absolute; top: .2rem; right: .3rem; }
.wa-alat > summary { list-style: none; cursor: pointer; color: var(--pudar); font-weight: 700; line-height: 1; padding: .1rem .3rem; border-radius: 4px; }
.wa-alat > summary::-webkit-details-marker { display: none; }
.wa-alat[open] { position: static; margin-top: .3rem; }
.wa-alat form { display: flex; gap: .35rem; align-items: center; flex-wrap: wrap; }
.wa-kirim { display: flex; gap: .5rem; align-items: flex-end; padding: .55rem .65rem; border-top: 1px solid var(--garis); }
.wa-kirim textarea { flex: 1 1 auto; min-height: 40px; max-height: 132px; resize: none; }
.wa-kirim .tombol { flex: none; width: auto; min-height: 40px; padding: .5rem 1rem; }

/* --------------------------------------------------------------- Messenger baru
   Tambahan dari cara kerja Lark (kategori, balas, reaksi, semat, sebut, sunting,
   tarik, terjadwal, lampiran) yang dirasakan seperti WhatsApp (lencana, centang
   dibaca, foto/berkas/suara).

   Catatan penyusunan: `.wa-baris` sekarang <div> berisi <a> + <form>, karena
   <form> di dalam <a> tidak sah dan tombol sematnya jadi tak bisa diklik. Karena
   itu susunan flex-nya pindah ke `.wa-baris-isi`. */
.wa-baris-isi { display: flex; align-items: center; gap: .6rem; flex: 1 1 auto; min-width: 0;
  text-decoration: none; color: inherit; }
.wa-baris { position: relative; }
/* Tombol semat percakapan: tampil saat disentuh/di-hover saja supaya daftar
   tidak penuh ikon, tapi tetap ada di layar sentuh (opacity, bukan display none). */
.wa-semat-form { flex: none; }
.wa-semat-form .tombol { padding: .15rem .3rem; min-height: 0; opacity: .35; }
.wa-baris:hover .wa-semat-form .tombol, .wa-semat-form .tombol:focus { opacity: 1; }

/* Penyaring kategori (Lark: belum dibaca/pribadi/grup/sebutan/tersemat).
   6 pil butuh ~476px sedangkan panelnya hanya 262px di desktop (356px di ponsel),
   jadi dengan `overflow-x:auto` dua pil terakhir TERPOTONG tanpa tanda apa pun —
   kategori "tersemat" praktis tak bisa ditemukan. Karena bilah ini hanya 1-2 baris
   dan pemilihnya sedikit, membungkus (`flex-wrap`) lebih baik daripada menggeser:
   semua pilihan terlihat sekaligus, tidak ada yang disembunyikan, dan tak perlu
   petunjuk "geser ke kanan" yang di layar sentuh sering tak terbaca. */
.wa-saring { display: flex; flex-wrap: wrap; gap: .3rem;
  padding: .45rem .55rem; border-bottom: 1px solid var(--garis); }
.wa-pil { flex: none; padding: .22rem .6rem; border-radius: 999px; font-size: .76rem;
  text-decoration: none; color: var(--tinta-2); background: var(--zebra);
  border: 1px solid var(--garis-2, #eef1ee); white-space: nowrap; }
.wa-pil:hover { background: var(--hijau-100); }
.wa-pil.ini { background: var(--hijau-600, #15402f); border-color: transparent; color: #fff; font-weight: 600; }

/* Lencana belum dibaca + sebutan (WhatsApp: angka hijau, Lark: @ penting). */
.wa-lencana { display: inline-grid; place-items: center; min-width: 20px; height: 20px;
  padding: 0 .35rem; border-radius: 999px; background: var(--hijau-600, #15402f); color: #fff;
  font-size: .7rem; font-weight: 700; }
.wa-lencana.sebut { background: #b91c1c; }
.wa-semat { font-size: .72rem; }
.wa-baris.belum .wa-baris-teks b { font-weight: 800; }

/* Balasan berkutip. */
.wa-kutip { display: block; margin-bottom: .28rem; padding: .2rem .45rem; border-left: 3px solid var(--hijau-600, #15402f);
  background: rgba(21, 64, 47, .07); border-radius: 4px; text-decoration: none; color: inherit; font-size: .78rem; }
.wa-kutip b { display: block; font-size: .72rem; color: var(--hijau-700, #1b5139); }
.wa-kutip span { color: var(--tinta-2); overflow-wrap: anywhere; }

/* Lampiran: foto, berkas, suara. */
.wa-foto { display: block; margin: -.1rem 0 .25rem; }
.wa-foto img { display: block; max-width: 100%; max-height: 260px; border-radius: 8px; cursor: zoom-in; }
.wa-berkas { display: flex; align-items: center; gap: .45rem; padding: .35rem .45rem; margin-bottom: .2rem;
  border: 1px solid var(--garis); border-radius: 8px; background: var(--putih); text-decoration: none; color: inherit; }
.wa-berkas-teks { display: flex; flex-direction: column; min-width: 0; }
.wa-berkas-teks b { font-size: .82rem; overflow-wrap: anywhere; }
.wa-berkas-teks small { color: var(--pudar); font-size: .7rem; }
.wa-suara audio { height: 34px; max-width: 230px; }

/* Reaksi emoji di bawah gelembung. */
.wa-reaksi { display: flex; flex-wrap: wrap; gap: .2rem; margin-top: .25rem; }
.wa-rx { display: inline-flex; align-items: center; gap: .15rem; padding: .05rem .35rem; font-size: .78rem;
  border: 1px solid var(--garis); border-radius: 999px; background: #fff; cursor: pointer; }
.wa-rx b { font-size: .68rem; color: var(--tinta-2); }
.wa-rx.saya { border-color: var(--hijau-600, #15402f); background: #e6f4e8; }
.wa-rx-baris { display: flex; flex-wrap: wrap; gap: .15rem; align-items: center; }

/* Baris bawah gelembung: sematan, "disunting", jam, centang dibaca. */
.wa-bawah { display: flex; align-items: center; justify-content: flex-end; gap: .3rem; margin-top: .1rem; }
.wa-bawah .wa-jam { margin: 0; }
.wa-suntingan { font-size: .66rem; color: var(--pudar); font-style: italic; }
.wa-tanda { font-size: .68rem; color: var(--pudar); letter-spacing: -.05em; }
.wa-tanda.dibaca { color: #1d7fd6; }
.wa-sebut { background: #fff2a8; color: inherit; border-radius: 3px; padding: 0 .12rem; }
.wa-b.sebut { box-shadow: 0 0 0 2px rgba(185, 28, 28, .35); }

/* Pita pesan yang disematkan + bilah balasan di atas kotak tulis. */
.wa-semat-pita { display: flex; align-items: center; gap: .4rem; padding: .35rem .7rem;
  background: #fff8e1; border-bottom: 1px solid var(--garis); font-size: .8rem; }
.wa-semat-isi { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--tinta-2); }
.wa-balas-bilah { display: flex; align-items: center; gap: .5rem; padding: .4rem .65rem;
  border-top: 1px solid var(--garis); background: var(--zebra); }
.wa-balas-teks { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.wa-balas-teks b { font-size: .74rem; color: var(--hijau-700, #1b5139); }
.wa-balas-teks small { color: var(--tinta-2); font-size: .76rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Alat per pesan versi baru: beberapa <form> bertumpuk dalam satu panel. */
.wa-alat-isi { display: flex; flex-direction: column; gap: .3rem; }
.wa-alat-isi .tombol { width: auto; }
.wa-jenis { display: flex; gap: .7rem; font-size: .78rem; }
.wa-jenis label { flex-direction: row; align-items: center; gap: .25rem; display: flex; }

/* Panel lampiran + rekam suara. */
.wa-lampir { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center;
  padding: .5rem .65rem; border-top: 1px solid var(--garis); background: var(--zebra); }
.wa-lampir .bantuan { flex: 1 1 100%; margin: 0; }
.wa-lampir-form { display: flex; gap: .4rem; align-items: center; }
.wa-suara-rekam { display: flex; gap: .4rem; align-items: center; }
.wa-kirim .wa-ikon { min-height: 40px; width: auto; padding: .4rem .7rem; font-size: 1.05rem; }
.wa-lebih { align-self: center; margin: 0 auto .35rem; }

/* Lihat foto besar (ala WhatsApp). */
.wa-lihat-foto { border: 0; padding: 0; background: transparent; max-width: 96vw; max-height: 96vh; }
.wa-lihat-foto img { display: block; max-width: 96vw; max-height: 86vh; border-radius: 8px; }

/* ======================================================================
   PROFIL — kartu identitas + daftar nilai, bukan tabel polos
   ====================================================================== */
.profil-hero { display: flex; align-items: center; gap: 1rem; padding: 1.05rem 1.15rem; background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r); box-shadow: var(--bayang); margin-bottom: var(--ruang); }
.profil-avatar { flex: none; width: 62px; height: 62px; border-radius: 50%; display: grid; place-items: center; background: linear-gradient(160deg, var(--hijau-800, #15402f), #1b5139); color: #fff; font-size: 1.35rem; font-weight: 700; }
.profil-hero > .identitas { min-width: 0; }
.profil-hero h2 { margin: 0 0 .15rem; font-size: 1.15rem; overflow-wrap: anywhere; }
.profil-hero p { color: var(--pudar); font-size: .86rem; overflow-wrap: anywhere; }
.profil-lencana { display: flex; flex-wrap: wrap; gap: .35rem; margin-top: .45rem; }
.identitas-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r); overflow: hidden; }
.identitas-grid > div { padding: .7rem .9rem; border-bottom: 1px solid var(--garis-2, #eef1ee); min-width: 0; }
.identitas-grid small { display: block; font-size: .68rem; text-transform: uppercase; letter-spacing: .07em; color: var(--pudar); font-weight: 700; margin-bottom: .12rem; }
.identitas-grid b { font-weight: 600; font-size: .9rem; overflow-wrap: anywhere; }
.rekening-kartu { display: flex; flex-direction: column; gap: .2rem; }
.rekening-kartu b { font-variant-numeric: tabular-nums; }

/* ======================================================================
   KATALOG BARANG — disusun seperti toko daring, plus saldo Agrinas
   ====================================================================== */
.saldo-kartu { display: flex; flex-wrap: wrap; gap: .55rem 1.2rem; align-items: center; justify-content: space-between; background: linear-gradient(160deg, var(--hijau-800, #15402f), #1b5139); color: #eef6f0; border-radius: var(--r); padding: .8rem 1rem; margin-bottom: var(--ruang); }
.saldo-kartu small { display: block; text-transform: uppercase; letter-spacing: .08em; font-size: .64rem; opacity: .88; font-weight: 700; }
.saldo-kartu b { display: block; font-size: clamp(1.3rem, 1rem + 1.2vw, 1.7rem); font-variant-numeric: tabular-nums; line-height: 1.2; }
.saldo-kartu p { color: #cfe0d7; font-size: .74rem; line-height: 1.4; margin: .15rem 0 0; }
.saldo-kartu .tombol { background: #eef6f0; color: #15402f; border-color: transparent; }
/* Tombol ikon keranjang di kepala: lencana jumlah menempel di sudutnya (pola
   toko daring). `.lencana-notif` memang sudah ada untuk lencana di atas lencana
   — di sini bingkainya putih, bukan hijau tua seperti di bilah sisi. */
.tombol-baris .posisi-lencana { position: relative; }
.tombol-baris .posisi-lencana .lencana-notif { border-color: var(--putih); background: var(--merah, #b91c1c); }
.katalog-baris { display: flex; flex-wrap: wrap; gap: .6rem; align-items: flex-end; margin-bottom: .9rem; }
.katalog-baris label { flex: 1 1 180px; }
/* Kisi produk. Lebar minimum kartu diturunkan dari 170px -> 150px: di layar 390px
   dan 1440px keduanya jadi satu kolom lebih banyak tanpa kartu terasa sempit
   (terukur 390px: 156px -> 2 kolom tetap; 1440px: 5 -> 6 kolom). */
.katalog-kisi { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr)); gap: .7rem; }
/* Kartu produk. Seluruh ukuran di bawah ini diukur, bukan ditebak: kartu lama
   setinggi 472px — 3/5 di antaranya hanya hiasan (kotak jenjang grosir 71px +
   isyarat berulang 16px + jarak dalam). Kartu toko daring memuat: gambar, nama,
   harga, jenjang, stok, aksi — tanpa bingkai berlebih. */
.kat-kartu { display: flex; flex-direction: column; background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r); overflow: hidden; box-shadow: var(--bayang); transition: box-shadow .12s; }
.kat-kartu:hover { box-shadow: 0 6px 18px -8px rgba(16, 29, 24, .28); }
.kat-gambar { position: relative; aspect-ratio: 1 / 1; background: var(--zebra); display: grid; place-items: center; overflow: hidden; }
.kat-gambar img { width: 100%; height: 100%; object-fit: cover; }
.kat-inisial { font-size: 2.2rem; font-weight: 800; color: var(--hijau-600, #15402f); opacity: .45; }
.kat-lencana { position: absolute; top: .4rem; left: .4rem; background: rgba(21, 64, 47, .86); color: #fff; font-size: .66rem; font-weight: 700; padding: .15rem .4rem; border-radius: 6px; }
.kat-lencana.habis { background: rgba(150, 30, 30, .88); }
.kat-badan { padding: .55rem .65rem .65rem; display: flex; flex-direction: column; gap: .2rem; flex: 1 1 auto; }
/* Nama barang: dipangkas 2 baris. Sebelumnya `min-height: 2.3em` membuat SETIAP
   kartu menanggung tinggi nama terpanjang di kisi, dan nama panjang tumbuh
   bebas (kartu ponsel 439-493px, tidak seragam) sehingga baris kisi terlihat
   bergerigi. `min-height` dihapus supaya kartu pendek tetap pendek. */
.kat-badan h3 { font-size: .84rem; line-height: 1.28; margin: 0; font-weight: 600;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.kat-harga { font-size: 1rem; font-weight: 800; color: var(--hijau-700, #15402f); font-variant-numeric: tabular-nums; line-height: 1.25; }
.kat-harga small { font-weight: 600; color: var(--pudar); font-size: .7rem; }
.kat-sisa { font-size: .72rem; color: var(--pudar); }
/* Lencana "Hemat" di pojok kanan atas gambar — hanya muncul bila ada jenjang
   grosir yang benar-benar lebih murah dari harga satuan. */
.kat-hemat { position: absolute; top: .4rem; right: .4rem; background: #c2410c; color: #fff;
  font-size: .66rem; font-weight: 800; padding: .15rem .4rem; border-radius: 6px; }
/* Kartu produk yang stoknya habis: gambar diredupkan, bukan disembunyikan —
   pembeli tetap bisa melihat barangnya. */
.kat-kartu.kosong .kat-gambar img { filter: grayscale(.55) opacity(.75); }
/* Daftar jenjang harga grosir di kartu: PIL-nya ringkas, disusun mendatar dan
   MEMBUNGKUS (bukan kotak oranye bertumpuk). Isi tiap pil = "5+" + harga, sama
   seperti penanda grosir di toko daring. Tinggi kartu turun ~50px dan lebarnya
   tidak lagi terpotong di kartu 156px. */
.kat-grosir { list-style: none; margin: .1rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: .2rem; }
.kat-grosir li { display: inline-flex; align-items: baseline; gap: .22rem;
  background: #fff7ed; border: 1px solid #fed7aa; border-radius: 999px;
  padding: .04rem .35rem; font-size: .68rem; color: #9a3412; font-variant-numeric: tabular-nums; }
.kat-grosir b { font-weight: 800; }
/* Baris aksi kartu katalog: kolom jumlah MELAR mengikuti lebar kartu, tombol
   keranjang tinggal ikon persegi. Sebelumnya input dipaku `width: 4.6rem`
   (terukur 74px di form 180px — sisa 100px kosong) dan tombolnya bertulisan
   "Keranjang" sehingga memakan hampir separuh lebar kartu.
   Tinggi disamakan (40px) supaya dasar keduanya rata. */
.kat-aksi { margin-top: auto; padding-top: .45rem; }
/* Satu variabel tinggi untuk kolom jumlah & tombol: tanpa ini keduanya berbeda
   (`stretch` ikut baris terbesar -> isian 51px, tombol 40px, dasar tidak rata).
   40px (bukan 42px): di kartu 150px, 42px membuat tombol keranjang tampak
   berat; 40px masih di atas ambang sasaran sentuh 36px dan menyisakan ruang. */
.kat-aksi form { --t: 40px; display: flex; gap: .45rem; align-items: center; }
.kat-aksi input[type="number"] { flex: 1 1 auto; width: auto; min-width: 0;
  height: var(--t); min-height: 0; margin: 0; }
.kat-aksi .tombol-ikon { flex: 0 0 auto; width: var(--t); height: var(--t);
  min-height: 0; padding: 0;
  /* Aturan global `input + .tombol { margin-top: .7rem }` menambah 11.2px di
     atas tombol ini (ia mengikuti isian jumlah di dalam formulirnya) sehingga
     dasar tombol meleset 5.6px dari dasar isian. Di baris flex, jarak diatur
     `gap` — margin itu murni merusak. */
  margin: 0; }

@media (max-width: 860px) {
  /* Ponsel: daftar ruang jadi pita mendatar supaya percakapan tetap lapang. */
  .wa { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); }
  /* Halaman DAFTAR: percakapan lama tak ditampilkan, daftarnya yang penuh. */
  .wa-sendiri .wa-ajak { display: none; }
  /* Halaman PERCAKAPAN: sisi kiri jadi LACI penuh yang dibuka tombol ‹,
     bukan pita mendatar (pita mendatar memakan ruang vertikal untuk daftar
     yang sedang tidak dipakai). */
  .wa-percakapan .wa-sisi { position: fixed; inset: 0; z-index: 60; border-radius: 0;
    width: 100%; transform: translateX(-102%); transition: transform .18s ease-out; }
  .wa-percakapan .wa-sisi.buka { transform: none; }
  .wa-laci.buka { position: fixed; inset: 0; background: rgba(16, 29, 24, .45); z-index: 55; }
  .wa-kembali { display: block; }
  .wa-b { max-width: 88%; }
  .katalog-kisi { grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr)); }
}

/* Gulir-tak-berujung katalog: penanda "muat lagi" + penutup akhir daftar. */
.katalog-lagi { display: flex; flex-direction: column; align-items: center; gap: .4rem;
  margin-top: 1rem; }
.katalog-lagi .tombol { min-width: 11rem; }
/* Saat gulir sedang mengambil halaman berikutnya: tombolnya berdenyut, supaya
   pengguna tahu gulirannya sedang bekerja dan tidak menggulir sia-sia. */
.katalog-lagi.memuat .tombol { opacity: .6; pointer-events: none; animation: katalog-denyut 1s ease-in-out infinite; }
@keyframes katalog-denyut { 0%, 100% { opacity: .45; } 50% { opacity: .9; } }
.katalog-habis { display: block; text-align: center; margin-top: 1rem; font-size: .82rem; }

/* Pilihan kanal pembayaran di checkout: kotak radio bawaan peramban tampak
   seperti daftar polos; ini menjadikannya kartu pilihan yang bisa ditekan. */
.pilihan-bayar { border: 0; padding: 0; margin: 0 0 .8rem; }
.pilihan-bayar legend { font-size: .74rem; text-transform: uppercase; letter-spacing: .07em; color: var(--pudar); font-weight: 700; margin-bottom: .35rem; }
.pilihan-bayar label.centang { align-items: flex-start; padding: .55rem .65rem; border: 1px solid var(--garis); border-radius: var(--r-kecil); margin-bottom: .4rem; cursor: pointer; }
.pilihan-bayar label.centang:hover { border-color: var(--hijau-500); background: var(--hijau-100); }
.pilihan-bayar label.centang input { margin-top: .25rem; }
.pilihan-bayar label.centang span { font-size: .86rem; line-height: 1.4; }
.pilihan-bayar label.centang small { display: block; font-size: .76rem; }

/* ======================================================================
   INVOICE — lembar yang bisa dicetak/disimpan PDF dari peramban
   ====================================================================== */
.invoice-lembar { background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r); padding: 1.4rem 1.5rem; max-width: 820px; }
.invoice-kepala { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; border-bottom: 2px solid var(--hijau-600, #15402f); padding-bottom: .8rem; margin-bottom: .9rem; }
.invoice-kepala h2 { margin: 0; font-size: 1.2rem; }
.invoice-nomor { text-align: right; font-variant-numeric: tabular-nums; }
.invoice-nomor b { display: block; font-size: 1.05rem; }
.invoice-pihak { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: .4rem 1.2rem; margin-bottom: .9rem; }
.invoice-pihak small { display: block; text-transform: uppercase; letter-spacing: .06em; font-size: .68rem; color: var(--pudar); font-weight: 700; }
.invoice-total { text-align: right; font-size: 1.05rem; font-weight: 800; padding-top: .5rem; }
.invoice-catatan { margin-top: .9rem; font-size: .8rem; color: var(--tinta-2); }
.invoice-lencana { display: inline-block; padding: .18rem .5rem; border-radius: 6px; font-size: .74rem; font-weight: 700; background: var(--zebra); border: 1px solid var(--garis); }

@media print {
  /* Cetak: hanya lembarnya, tanpa menu/hiasan halaman. */
  .sisi, .nav-bawah, .modul-nav, .kepala, .tombol, .tombol-baris, .pesan, #hub-proses { display: none !important; }
  .shell { display: block; }
  .isi { margin: 0; padding: 0; }
  .invoice-lembar { border: 0; max-width: none; padding: 0; }
  body { background: #fff; }
}

/* =================================================== keuangan: angka & arus kas
   Halaman keuangan adalah halaman UANG: angka harus lurus satu kolom supaya
   digitnya bisa dibandingkan dengan mata. Angka proporsional (default) membuat
   "1" lebih sempit dari "8", jadi baris Rp 111.111 dan Rp 888.888 tidak pernah
   sejajar — di tabel keuangan itu terbaca seperti salah ketik.
   `tabular-nums` menyamakan lebar digit; sumbangan ruangnya diambil dari
   padding sel, bukan dari ukuran huruf, supaya tidak ada nomor yang terpotong. */
.angka-kanan { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table td.angka-kanan { font-feature-settings: "tnum"; }
/* Nilai rupiah pada kolom angka sedikit lebih rapat daripada teks biasa. */
td.angka-kanan b { font-variant-numeric: tabular-nums; }
/* Uraian berisi beberapa baris pendek (masuk / keluar / rujukan); beri sedikit
   jarak antar baris supaya tidak terbaca sebagai satu kalimat panjang. */
.kwitansi { display: block; font-size: .82rem; color: var(--tinta-2); }
.kwitansi + .kwitansi { margin-top: .1rem; }

/* ---- batang arus kas: murni CSS, tanpa JavaScript ---- */
.arus { display: flex; align-items: flex-end; gap: 2px; height: 92px; margin: .2rem 0 .3rem;
  padding: .5rem .55rem 0; background: var(--zebra); border: 1px solid var(--garis);
  border-radius: var(--r-kecil); box-shadow: var(--bayang); }
/* Tiap batang adalah satu hari, dengan garis nol di TENGAH wadah. Batang `naik`
   tumbuh dari garis nol ke atas, `turun` ke bawah.
   PENTING: batang harus di-ABSOLUT-kan terhadap garis 50% (`bottom:50%` /
   `top:50%`), bukan disusun flex dengan `align-items`. Dengan flex, `height`
   diukur dari tepi wadah, jadi batang tumbuh dari ATAS wadah — tingginya benar
   tapi alasnya melayang dan grafiknya berbohong (terukur: alas bersebar 34,5px
   sebelum diperbaiki). */
.arus-batang { flex: 1 1 0; min-width: 2px; height: 100%; position: relative; }
.arus-batang::before { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 1px;
  background: var(--garis); }
.arus-batang i { position: absolute; left: 0; right: 0; display: block;
  border-radius: 2px; min-height: 2px; }
.arus-batang.naik i { bottom: 50%; }
.arus-batang.turun i { top: 50%; }
.arus-batang.naik i { background: var(--hijau-500); }
.arus-batang.turun i { background: var(--merah-g); }
.arus-batang:hover i { filter: brightness(.88); }
.arus-kaki { display: flex; justify-content: space-between; font-size: .72rem; color: var(--pudar); }

/* ============================================== sel tabel di layar sedang
   Tabel 5–6 kolom masih utuh di layar ≥721px, tapi wadahnya menyempit di
   721–1280px (sidebar 264px tetap + padding tepi) sehingga kolom tercekik:
   terukur @1024px sisa ruang di dalam sel Tugas tinggal 1,7px dan Surat Jalan
   20,1px — mata membacanya sebagai "kolom menempel". Padding sel dinaikkan
   HANYA di rentang itu: kolom yang benar-benar tercekik lalu membungkus isinya
   sendiri (baris jadi 2 baris seperti @1024px sekarang), dan jarak teks-ke-teks
   antar kolom ikut lega. Di ≥1281px tabel sudah lega (sisa 37–146px) jadi tidak
   diubah, dan di ≤720px tata letaknya milik media query ponsel. */
@media (min-width: 721px) and (max-width: 1280px) {
  th, td { padding-left: .85rem; padding-right: .85rem; }
}

/* ============================================== admin/akun: baris tabel & sel rapat
   Sel Aksi berisi <a> + <form class="sebaris"> + keterangan. Ketiganya anak
   INLINE, jadi selama ada di dalam satu baris teks (white-space berbeda pun
   tidak menolong di desktop, karena `.kolom-aksi` memakai `nowrap`), tingginya
   menumpuk: terukur 120px per baris di desktop dan 300–400px di ponsel untuk
   isi yang sebenarnya satu baris. Flex + wrap membuat keduanya sebaris dan
   tingginya wajar; ponsel sudah punya aturan flex-nya sendiri. */
.sebaris > .tombol { width: auto; }
.tabel-bungkus td.kolom-aksi { white-space: nowrap; }
.tabel-bungkus td.kolom-aksi > a.tombol,
.tabel-bungkus td.kolom-aksi > span.samar-kecil { vertical-align: middle; }
/* Tombol di dalam sel Aksi mewarisi margin-atas dari aturan formulir bertumpuk
   (.7rem). Margin itu benar untuk formulir yang BENAR-BENAR menumpuk, tetapi di
   sini tombolnya sebaris: margin 11,2px membuat sel setinggi 67px padahal
   tombolnya hanya 32px (terukur). Nolkan di dalam sel aksi. */
/* `:not(.ubah *)` WAJIB: panel `<details class="ubah">` juga berada di dalam sel
   aksi, dan isinya MENUMPUK vertikal. Tanpa pengecualian ini aturan di atas ikut
   menolkan margin tombol "Simpan" di /keuangan sehingga ia menempel kalimat
   bantuan di atasnya (terukur 0px). Yang dimaksud aturan ini hanya tombol
   SEBARIS sebagai anak langsung sel aksi. */
.tabel-bungkus td.kolom-aksi .tombol:not(.ubah *) { margin-top: 0; }
@media (min-width: 721px) {
  /* Isi sel aksi dibuat sebaris dengan `inline-flex` pada PEMBUNGKUSNYA, bukan
     dengan `display:flex` pada `<td>`-nya.
     🔴 `display:flex` pada `<td>` mengeluarkan sel dari algoritma tata letak
     tabel (elemen dengan display non-table-cell tidak lagi mengisi kolomnya),
     sehingga lebar kolom Aksi KOLAPS: terukur 22px di desktop dan 2,9px di
     ponsel — tombol 55px melimpah keluar sel dan tabel tampak "terpotong"
     walau tidak ada luber. Cukup satu aturan yang salah display. */
  .tabel-bungkus td.kolom-aksi > form.sebaris { display: inline-flex; margin: 0;
    vertical-align: middle; }
  .tabel-bungkus td.kolom-aksi > .tombol,
  .tabel-bungkus td.kolom-aksi > details.ubah { vertical-align: middle; }
  .tabel-bungkus td.kolom-aksi > * + * { margin-left: .5rem; }
  /* `line-height: 0` pada SEL, lalu dipulihkan pada anaknya. Tanpa ini kotak
     `inline-flex` (tombol) berada di dalam kotak baris dan menyisakan ruang
     descender ~11px, sehingga sel 66px untuk tombol 32px. Ruang itu milik garis
     dasar teks, bukan milik tombolnya. */
  .tabel-bungkus td.kolom-aksi { line-height: 0; }
  .tabel-bungkus td.kolom-aksi > * { line-height: 1.35; }
}

/* Lebar kolom tabel akun dipatok supaya tiap sel cukup untuk isinya dalam 1–2
   baris. Tanpa ini dua kolom identitas (nama & email) saling berebut lebar dan
   nama 32 karakter terpaksa jadi 4 baris — baris tabel 106px. Persentase di
   bawah berasal dari lebar TERUKUR isinya (tombol aksi 168px, lencana peran
   139px, cap waktu 112px), bukan angka karangan. */
.tabel-akun { table-layout: fixed; }
.tabel-akun th:nth-child(1) { width: 28%; }   /* Akun (nama + email) */
.tabel-akun th:nth-child(2) { width: 13%; }   /* Peran */
.tabel-akun th:nth-child(3) { width: 24%; }   /* Koperasi / Wilayah */
.tabel-akun th:nth-child(4) { width: 8%; }    /* Status */
.tabel-akun th:nth-child(5) { width: 11%; }   /* Masuk terakhir */
.tabel-akun th:nth-child(6) { width: 16%; }   /* Aksi */
/* Alamat surel panjang tanpa spasi melebarkan kolomnya sampai memaksa tabel
   menggulir mendatar. Biarkan membungkus di titik mana pun. */
.pecah { overflow-wrap: anywhere; word-break: break-word; }

/* Lebar kolom dasbor admin dipatok dari lebar TERUKUR isinya (bukan angka
   karangan). Tanpa patokan, kolom "Tugas" pada daftar tugas menelan 538px (48%
   tabel) untuk satu judul, sementara kode koperasi berdiri sendiri menghabiskan
   71px. Persentase di bawah = lebar isi terpanjang + padding. */
.tabel-tugas th:nth-child(1) { width: 44%; }   /* Tugas */
.tabel-tugas th:nth-child(2) { width: 22%; }   /* Koperasi */
.tabel-tugas th:nth-child(3) { width: 15%; }   /* Status */
.tabel-tugas th:nth-child(4) { width: 14%; }   /* Tenggat */
.tabel-tugas th:nth-child(5) { width: 5%; }    /* Aksi */
.tabel-koperasi th:nth-child(1) { width: 34%; } /* Koperasi (nama + kode) */
.tabel-koperasi th:nth-child(2) { width: 24%; } /* Wilayah */
.tabel-koperasi th:nth-child(3) { width: 24%; } /* Manajer */
.tabel-koperasi th:nth-child(4) { width: 9%; }  /* Status */
.tabel-koperasi th:nth-child(5) { width: 9%; }  /* Tugas */
@media (min-width: 721px) {
  .tabel-tugas, .tabel-koperasi { table-layout: fixed; }
}
/* Angka jumlah tugas disamakan lebarnya agar bisa dibandingkan antar baris. */
.tabel-koperasi td .angka { font-variant-numeric: tabular-nums; font-weight: 600; }

/* ---- Alat scan barcode (/distribusi/stok-koperasi) ----
   Kamera butuh area yang jelas: bingkai gelap + garis pemandu supaya pengguna tahu
   ke mana harus mengarahkan. Barcodenya sendiri tidak perlu presisi — pengenalan
   dilakukan peramban tiap 400 ms. */
.scan-bingkai { position: relative; border-radius: var(--r-kecil); overflow: hidden;
  background: #101914; aspect-ratio: 4 / 3; margin-bottom: .5rem; }
.scan-bingkai video { width: 100%; height: 100%; object-fit: cover; display: block; }
.scan-garis { position: absolute; left: 8%; right: 8%; top: 50%; height: 2px;
  background: var(--merah); box-shadow: 0 0 8px rgba(163, 34, 24, .8); }
#scan-modal .pilih-daftar { position: static; max-height: 220px; margin-top: .5rem; }
#scan-modal .kartu { margin-top: .5rem; }

/* ---- Pemilih KDMP yang bisa dicari (/keuangan) ----
   Kotak hasil MENGAMBANG di atas isi halaman (position:absolute) supaya
   membuka daftar tidak menggeser tabel, kartu, dan tombol di bawahnya —
   pada puluhan ribu koperasi daftar pernah dirender utuh dan mendorong
   seluruh halaman turun setiap kali dibuka. */
.cari-koperasi { align-items: flex-start; }
.cari-koperasi .cari-kop { position: relative; flex: 1 1 260px; min-width: 0; }
.cari-koperasi .cari-kop input[type="search"] { width: 100%; margin: 0; }
.cari-koperasi .pilih-daftar { position: absolute; inset-inline: 0; top: calc(100% + .25rem);
  z-index: 6; margin: 0; padding: .2rem; max-height: 260px; overflow-y: auto;
  background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r-kecil);
  box-shadow: 0 10px 24px rgba(0, 0, 0, .13); }
.cari-koperasi .pilih-daftar li[hidden] { display: none; }
/* Baris hasil = <a>, jadi ia perlu dilepas dari gaya tautan (garis bawah, warna
   biru) — kalau tidak, hasil pencarian terbaca seperti tautan keluar halaman. */
.cari-koperasi .pilih-baris { display: flex; flex-direction: row; align-items: center; gap: .5rem;
  padding: .4rem .45rem; border-radius: var(--r-kecil); text-decoration: none;
  color: var(--tinta); font-size: .85rem; }
.cari-koperasi .pilih-baris:hover { background: var(--hijau-100); }
.cari-koperasi .pilih-baris.centang { background: var(--hijau-100); }
.cari-koperasi .pilih-baris.centang .pilih-nama { font-weight: 700; }
.cari-koperasi .pilih-baris.centang::after { content: "✓"; margin-left: auto;
  color: var(--hijau-600); font-weight: 800; }
.cari-koperasi .pilih-nama { flex: 1 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.cari-koperasi .pilih-baris small { flex: 0 1 46%; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--pudar); font-size: .72rem; }
.cari-koperasi .pilih-kosong { margin: 0; padding: .5rem; font-size: .8rem; color: var(--pudar); }
#kop-terpilih { margin-top: .45rem; }

/* ---- Modal rincian Surat Jalan (/distribusi) ----
   <dialog> bawaan peramban: fokus terkunci, Esc menutup, latar inert. Yang
   ditambahkan hanya tampilannya. */
#rincian-modal { width: min(720px, calc(100vw - 1.6rem)); max-height: min(88vh, 860px);
  padding: 0; border: 0; border-radius: var(--r); box-shadow: var(--bayang-2);
  color: var(--tinta); overflow: hidden; }
#rincian-modal::backdrop { background: rgba(16, 29, 24, .48); }
#rincian-modal-isi { max-height: inherit; }
.rincian-modal-tutup { position: absolute; top: .55rem; right: .6rem; margin: 0; }
.rincian-modal-tutup .ikon-tutup { font-size: 1.15rem; line-height: 1; padding: .2rem .55rem; }
.sedang-muat { padding: 1.4rem 1.3rem; margin: 0; }

/* Panel: badan yang menggulir + kaki aksi yang selalu terlihat. Tanpa ini,
   tombol "Kirim Barang" tenggelam di dasar isi yang panjang dan pengguna
   menggulir dua kali untuk satu surat jalan. */
.rincian-panel { display: flex; flex-direction: column; max-height: min(88vh, 860px); }
.rincian-badan { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 1.2rem 1.3rem .4rem; }
.rincian-judul { display: flex; align-items: flex-start; justify-content: space-between;
  gap: .6rem; margin-bottom: .9rem; padding-right: 2.2rem; }
.rincian-judul b { display: block; font-size: 1rem; }
.rincian-judul small { display: block; color: var(--pudar); font-size: .8rem; }
.rincian-sub { font-size: .82rem; letter-spacing: .04em; text-transform: uppercase;
  color: var(--pudar); margin: 1.1rem 0 .4rem; }
.rincian-kaki { flex: none; display: flex; flex-wrap: wrap; gap: .5rem; justify-content: flex-end;
  align-items: center; padding: .8rem 1.3rem; border-top: 1px solid var(--garis);
  background: var(--zebra); }
/* Halaman penuh: panel tidak perlu memahat tinggi layar. */
.blok .rincian-panel { max-height: none; }
.blok .rincian-badan { overflow: visible; padding: 0 0 .4rem; }
.blok .rincian-kaki { background: none; padding: .8rem 0 0; }
@media (max-width: 560px) {
  /* Sama seperti .modal: `margin-bottom: 0` + `100vw` melemparkan dialog ke
     dasar layar dan menutupi bilah menu bawah. Dibiarkan terpusat. */
  #rincian-modal { width: min(720px, calc(100vw - 1.6rem)); inset: .8rem .8rem var(--tb-nav);
    max-height: calc(100dvh - .8rem - var(--tb-nav)); }
  .rincian-kaki { justify-content: stretch; }
  .rincian-kaki .tombol { flex: 1 1 auto; }
}

/* ---- Kepala blok: judul kiri, tombol aksi kanan atas ---- */
.kepala-blok { display: flex; align-items: flex-start; justify-content: space-between;
  gap: .8rem; flex-wrap: wrap; margin-bottom: .7rem; }
.kepala-blok h2 { margin: 0; }

/* ---- Modal bersama: .modal ----
   <dialog> bawaan peramban: fokus terkunci, Esc menutup, latar inert, dan
   `margin: auto` bawaannya yang menempatkannya di TENGAH layar (dialog
   non-modal menempel di atas). Yang ditambahkan hanya tampilannya. Dipakai
   /admin/barang (Tambah/Ubah) dan /pasokan (Update status). */
.modal { width: min(640px, calc(100vw - 1.6rem)); max-height: min(88vh, 780px);
  padding: 0; border: 0; border-radius: var(--r); box-shadow: var(--bayang-2);
  color: var(--tinta); overflow: hidden;
  /* Kolom flex di dialog itu sendiri, bukan hanya di `<form>`-nya.
     `.modal-badan` memakai `flex: 1 1 auto; min-height: 0` supaya isi panjang
     MENYUSUT dan bergulir. Itu hanya bekerja bila induknya flex container.
     Modal yang isinya dibungkus `<form>` sudah memenuhi syarat; modal TANPA form
     (mis. Rincian lahan di /admin/koperasi) tidak — `.modal-badan` tumbuh
     mengikuti isi (terukur 866px di dialog 646px), meluber ke luar, lalu
     dipotong `overflow: hidden` dialog tanpa bisa digulir: `scrollHeight`
     sama persis dengan `clientHeight`, jadi tidak ada yang bisa digulir. */
  /* `white-space: normal` WAJIB di sini, bukan hiasan.
     `<dialog>` kerap ditulis DI DALAM sel tabel, dan `.kolom-aksi` memakai
     `white-space: nowrap` (supaya tombol tidak terpecah dua baris). `white-space`
     diwariskan, jadi seluruh isi modal ikut nowrap: judul dialog melebar 731px
     dan paragraf bantuan 1108px di layar 390px — teksnya tidak membungkus sama
     sekali (terukur pada /admin/koperasi, dialog rincian lahan).
     Ditaruh di `.modal`, bukan di sel tiap halaman: satu aturan ini menutup
     SEMUA modal yang duduk di dalam sel tabel, di halaman mana pun. */
  white-space: normal; }
/* Hanya saat TERBUKA: `display:flex` polos mengalahkan `dialog:not([open])
   { display:none }` bawaan peramban, dan semua dialog di halaman ikut tampil. */
.modal[open] { display: flex; flex-direction: column; }
.modal::backdrop { background: rgba(16, 29, 24, .48); }
.modal form { display: flex; flex-direction: column; max-height: inherit; }
.modal-kepala { flex: none; display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; padding: .9rem 1.2rem; border-bottom: 1px solid var(--garis); background: var(--zebra); }
.modal-kepala h2 { margin: 0; font-size: 1.02rem; }
.modal-badan { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 1.1rem 1.2rem .3rem; }
.modal-kaki { flex: none; display: flex; gap: .5rem; justify-content: flex-end;
  padding: .8rem 1.2rem; border-top: 1px solid var(--garis); background: var(--zebra); }
.modal-kaki .tombol { min-width: 7.5rem; }
/* Status kesiapan di kaki modal: rata KIRI, mendorong tombolnya ke kanan.
   Tanpa ini ia ikut terdorong ke tepi kanan oleh `justify-content: flex-end`
   dan terbaca seperti label tombolnya. */
.modal-kaki [data-siap-status] { flex: 1 1 auto; margin: 0; text-align: left; }
.modal-badan .pesan { margin: 0 0 .9rem; }
@media (max-width: 560px) {
  /* Aturan ini benar-benar mengubah tata letak <dialog>; sisanya hanya boleh
     menyentuh TAMPILANNYA, kalau tidak dialog kembali menempel ke dasar layar.
     Dua kesalahan nyata yang diperbaiki (terukur pada 360x780):
       1. `margin-bottom: 0` — <dialog> bawaan peramban dipusatkan oleh
          `margin: auto`, jadi begitu margin-bawah jadi 0 sisa `margin-top:auto`
          melempar dialog ke DASAR layar. Seluruh dialog terukur bottom=780 dan
          menutupi bilah menu 66px.
       2. `width: 100vw` + sudut hanya-atas — dialog menempel tepi tanpa sela.
     Yang dipakai sekarang: kotak acuan dialog dipersempit lewat `inset` supaya
     tinggi menu bawah tak ikut dihitung, lalu peramban memusatkannya sendiri
     (`margin: auto` bawaan, TIDAK ditulis ulang). */
  .modal { width: min(640px, calc(100vw - 1.6rem)); inset: .8rem .8rem var(--tb-nav);
    /* `max-height: 100%` SALAH di sini: persentase diselesaikan terhadap tinggi
       viewport (terukur 780), bukan terhadap kotak `inset` di atas, sehingga
       dialog yang isinya panjang tumbuh melewati kotaknya dan menimpa menu
       (terukur top -27/bottom 753). Dihitung eksplisit dari sisa ruang. */
    max-height: calc(100dvh - .8rem - var(--tb-nav)); }
  .modal-kaki { justify-content: stretch; }
  .modal-kaki .tombol { flex: 1 1 auto; min-width: 0; }
}

/* ---- Bilah saring: satu baris yang benar-benar rata ----
   Diberlakukan untuk SEMUA `.saring` (bukan per halaman): dulu aturan ini
   ter-scope `#stok`, sehingga bilah di /pasokan kembali bergerigi — input 43px
   di sebelah select 42px. Satu aturan, semua halaman ikut sehat.
   Tiga sebab "kurang rapi" sebelumnya, semuanya terukur:
     1. label 63px (caption di atas isian) di sebelah isian 43px -> bergerigi;
     2. <input> 43px vs <select> 42px -> beda 1px karena border-nya beda;
     3. lebar acak (input 226px, select 148px) karena flex-basis 220px pada
        keduanya, sementara select mengambil lebar sesuai opsinya.
   Diperbaiki dengan mengunci TINGGI baris (--tb-saring) dan memberi setiap
   jenis kontrol BASIS yang berbeda: pencarian melar, pemilih kategori tetap.

   AKAR "pencarian nempel": baris ini dulu `padding: .6rem 0`, yang MENGHAPUS
   padding samping dari aturan `.saring` pertama di atas (`.7rem .8rem`) —
   properti yang sama, aturan yang lebih bawah menang. Bingkai bilah tetap
   tampak (background/border tak tersentuh) sementara ISINYA menempel 1px dari
   bingkainya sendiri (terukur /distribusi & /pasokan @390/1024/1440px;
   `padding: 9.6px 0px`, isian kiri = 1px). Dulu ditambal per-halaman untuk
   /pasokan (`#ps form.saring`) — itu gejala; akarnya di sini, jadi dibetulkan
   di sini supaya 34 halaman lain ikut sehat. `.lingkup-kop form.saring` yang
   memang bilah-tertanam (padding 0 disengaja) tetap menang karena lebih khusus. */
.saring { --tb-saring: 42px; display: flex; flex-wrap: wrap; align-items: center;
  gap: .55rem; padding: .6rem .8rem; }
/* `border: 0; padding: 0` WAJIB: label pembungkus ternyata mewarisi border 1px
   dari aturan lain, sehingga label 44px berdiri di sebelah isian 42px dan bilah
   tampak bergerigi. Tinggi baris HARUS ditentukan oleh ISIANNYA, bukan wadahnya. */
.saring label { display: flex; align-items: center; margin: 0; padding: 0;
  border: 0; flex: 0 1 auto; min-width: 0; }
/* Pencarian: satu-satunya yang melar — kolom yang paling sering dipakai. */
.saring label.cari { position: relative; flex: 1 1 300px; max-width: 460px; }
.saring label.pilih { flex: 0 1 220px; }
/* Tinggi & jarak dalam dikunci: `height` (bukan min-height) supaya <input> dan
   <select> mustahil berbeda walau border/bawaannya beda. */
.saring input, .saring select { width: 100%; height: var(--tb-saring);
  min-height: 0; margin: 0; padding: 0 .8rem; font-size: .875rem; line-height: var(--tb-saring); }
/* Ikon cari di dalam kotak: dekorasi, sehingga isian diberi ruang kiri. */
.saring .ikon-cari { position: absolute; left: .7rem; top: 50%; transform: translateY(-50%);
  width: 1.05rem; height: 1.05rem; pointer-events: none; fill: none; stroke: var(--pudar);
  stroke-width: 1.7; stroke-linecap: round; }
.saring label.cari input { padding-left: 2.3rem; }
/* Ikon bawaan kotak `search` disembunyikan: ada ikon sendiri, dan bawaan WebKit
   letaknya bertabrakan dengan padding kiri di atas. */
.saring input[type="search"]::-webkit-search-decoration,
.saring input[type="search"]::-webkit-search-cancel-button { display: none; }
/* `margin: 0` WAJIB: aturan global `label + .tombol { margin-top: .7rem }`
   (baris ~402) menambah 11,2px di atas tombol yang mengikuti label pencarian,
   sehingga dasar tombol meleset 5,6px dari dasar isiannya (terukur di
   /distribusi/stok-koperasi: isian y=412,9 vs tombol y=418,5). Di bilah yang
   flex, jarak sudah diatur `gap` — margin itu murni merusak. Tambalan yang sama
   sudah ada di `.kat-aksi .tombol-ikon`; di sini ditutup untuk SEMUA bilah. */
.saring .tombol { height: var(--tb-saring); min-height: 0; flex: 0 0 auto; margin: 0; }
/* Tombol IKON di bilah saring (mis. scan barcode di /distribusi/stok-koperasi):
   persegi seperti tingginya, bukan selebar teksnya. `.tombol-ikon` hanya
   menghapus padding, jadi tanpa aturan ini tombolnya jadi sliver selebar 20px
   dengan ikon meluber keluar bingkainya. */
.saring .tombol-ikon { width: var(--tb-saring); padding: 0; }
@media (max-width: 640px) {
  /* Ponsel: pencarian memakai lebar penuh, kategori & tombol berbagi barisnya. */
  .saring label.cari { flex: 1 1 100%; max-width: none; }
  .saring label.pilih { flex: 1 1 60%; }
  /* KECUALI bila persis di sebelahnya ada tombol IKON (mis. scan barcode di
     /distribusi/stok-koperasi): keduanya WAJIB tetap sebaris — "di sebelah kolom
     pencarian" adalah permintaan harfiah, bukan hanya di desktop. Karena
     pencarian tak lagi boleh 100%, ia mengambil sisa lebarnya (`flex-basis: 0`
     supaya tidak menuntut lebar isinya lalu membungkus tombolnya ke baris dua).
     Selektornya sempit (`:has` + anak langsung) supaya bilah lain di ponsel
     tidak ikut berubah. */
  .saring label.cari:has(+ .tombol-ikon) { flex: 1 1 0; min-width: 0; }
}

/* ---- Pemetaan lahan: dua sel pendek sebaris di ponsel ----
   Di ponsel `.tabel-bungkus` mengubah tiap sel jadi label+nilai bertumpuk, jadi
   tinggi baris = jumlah sel × tinggi sel. Empat sel → 348–367px per titik
   (terukur; sebelumnya enam sel 404–423px). Dua sel isinya pendek (luas+potensi,
   dan lencana status), jadi keduanya dibuat SEBARIS: label dan nilai berdampingan,
   bukan bertumpuk. Tidak ada informasi yang disembunyikan — hanya tata letaknya
   yang dipadatkan, sesuai aturan Bos (jangan hilangkan teks di ponsel). */
@media (max-width: 720px) {
  .tabel-pemetaan td[data-l="Lahan & Potensi"],
  .tabel-pemetaan td[data-l="Pembangunan"] { display: flex; align-items: baseline;
    gap: .55rem; padding-top: .15rem; padding-bottom: .15rem; }
  .tabel-pemetaan td[data-l="Lahan & Potensi"]::before,
  .tabel-pemetaan td[data-l="Pembangunan"]::before { flex: 0 0 auto; padding-top: 0; }
  /* Halaman Koperasi: sel Manajer & Status isinya pendek, jadi disejajarkan.
     Empat sel (dari tujuh) sudah memangkas baris 440–480px → ± 340px; dua sel
     ini yang tersisa dipadatkan lagi tanpa menyembunyikan teksnya. */
  .tabel-koperasi td[data-l="Manajer"],
  .tabel-koperasi td[data-l="Status"] { display: flex; align-items: baseline;
    gap: .55rem; padding-top: .15rem; padding-bottom: .15rem; flex-wrap: wrap; }
  .tabel-koperasi td[data-l="Manajer"]::before,
  .tabel-koperasi td[data-l="Status"]::before { flex: 0 0 auto; padding-top: 0; }
}

/* Tombol rincian yang menyerupai tautan: dipakai di dalam sel tabel agar tidak
   menambah satu sel tersendiri (tiap sel = +80px di ponsel). Tetap fokusabel
   dan menyasar-sentuh 44px, jadi bukan sekadar memperkecil tombol. */
.tautan-mini { background: none; border: 0; padding: .35rem 0; margin: 0;
  font: inherit; font-size: .85rem; font-weight: 600; color: var(--hijau-700);
  cursor: pointer; text-decoration: underline; min-height: 44px; }
.tautan-mini:hover { color: var(--hijau-600); }

/* ---- Lonceng notifikasi (DESKTOP) ----
   Tetap ada seperti sebelumnya: sebaris dengan logo & tulisan "Agrinas Hub",
   tepat di sebelahnya. Di PONSEL disembunyikan — tugasnya pindah ke butir
   "Notifikasi" di panel menu pojok kanan atas. */
.lonceng { position: relative; display: inline-flex; align-items: center;
  justify-content: center; flex: 0 0 auto;
  width: 42px; height: 42px; border-radius: 50%; color: #fff;
  background: rgba(255, 255, 255, .14); text-decoration: none; }
.lonceng:hover { background: rgba(255, 255, 255, .24); }
.lonceng .ik { width: 22px; height: 22px; fill: currentColor; }
/* Lencana angka: hiasan (angkanya sudah disebut di aria-label), jadi
   `aria-hidden` di markup supaya pembaca layar tidak membaca "3" sendirian. */
.lencana-notif { position: absolute; top: -3px; right: -3px; min-width: 19px;
  height: 19px; padding: 0 5px; border-radius: 10px; background: var(--merah);
  color: #fff; font-size: .68rem; font-weight: 700; line-height: 17px;
  text-align: center; border: 2px solid var(--hijau-900);
  box-sizing: content-box; pointer-events: none; }
@media (max-width: 900px) { .lonceng { display: none; } }

/* ---- Tombol menu di pojok kanan atas (PONSEL saja) ----
   Isinya: nama pengguna, Notifikasi, Keluar. Ikonnya tiga garis karena fungsinya
   menu — bukan lonceng. Tidak ada butir MENU di dalamnya (semua menu sudah di
   bilah bawah); "Notifikasi" bukan menu, ia pintu ke pengumuman. */
.menu-kanan { display: none; }
.menu-kanan-panel { display: none; }

/* Baris pertama kepala: merek kiri, tombol kanan. `.merek` flex:1 menyerap sisa
   lebar, jadi tombolnya terdorong ke ujung kanan tanpa menyentuh tata letak .sisi.
   `width: 100%` (bukan flex-grow): di ponsel `.sisi` itu baris flex, jadi tanpa
   ini kepalanya hanya selebar isinya (terukur 215px dari 390px) dan tombolnya
   berhenti di tengah, bukan di pojok. */
.sisi-kepala { display: flex; align-items: center; gap: .6rem;
  width: 100%; min-width: 0; }
.sisi-kepala .merek { flex: 1 1 auto; min-width: 0; }
/* "Koordinasi Manajer Koperasi" dibuang: memakan ruang kepala tanpa menambah
   informasi (teks itu juga muncul sebagai judul halaman). */
.sisi-kepala .nama small { display: none; }

@media (max-width: 900px) {
  /* Identitas pengguna + Keluar sudah pindah ke menu pojok, jadi `.kaki` tidak
     perlu tampil di kepala ponsel. Kalau dibiarkan ia memakan lebar di kanan —
     tombolnya berhenti di 320px dari 390px, tidak sampai pojok. */
  .sisi .kaki { display: none; }

  .menu-kanan { display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 auto; width: 44px; height: 44px; padding: 0; cursor: pointer;
    border: 0; border-radius: var(--r-kecil); color: #fff;
    background: rgba(255, 255, 255, .18); position: relative; }
  .menu-kanan:hover { background: rgba(255, 255, 255, .26); }
  .menu-kanan .ik { width: 24px; height: 24px; fill: currentColor; }
  /* Lencana di tombol: pakai `.lencana-notif` yang SAMA dengan lonceng desktop,
     jadi warnanya pasti merah dan angkanya tampil. Sebelumnya di sini hanya titik
     9px tanpa angka, dan latar tombolnya yang tembus pandang membuat lencananya
     tampak pucat. */
  .menu-kanan .lencana-notif { top: -4px; right: -4px; min-width: 20px;
    height: 20px; font-size: .7rem; line-height: 17px;
    border-color: var(--hijau-900); z-index: 2; }

  /* Panel: menempel dari kanan atas, di bawah kepala. */
  /* `bottom: auto; height: auto` WAJIB: gaya bawaan <dialog> memakai `inset: 0`,
     jadi tanpa ini kotaknya membentang sampai dasar layar dan menutupi seluruh
     halaman — tombolnya sendiri jadi tidak bisa diklik (terbukti di uji, bukan
     dugaan). `margin: 0` mematikan `margin: auto` bawaan yang memusatkan. */
  .menu-kanan-panel[open] { display: flex; flex-direction: column;
    position: fixed; top: calc(var(--sp) + 3.4rem); right: var(--sp);
    bottom: auto; left: auto; height: auto;
    width: min(16rem, calc(100vw - 2 * var(--sp))); margin: 0; padding: .3rem;
    border: 1px solid var(--garis-2); border-radius: var(--r-kecil);
    background: var(--putih); box-shadow: 0 12px 30px rgba(16, 29, 24, .22);
    gap: .1rem; z-index: 60; max-height: none; }
  .menu-pengguna { display: flex; flex-direction: column; gap: .1rem;
    padding: .5rem .6rem; border-bottom: 1px solid var(--garis-2); margin-bottom: .25rem; }
  .menu-pengguna b { font-size: .9rem; color: var(--tinta); }
  .menu-pengguna small { font-size: .74rem; color: var(--pudar);
    overflow: hidden; text-overflow: ellipsis; }
  .menu-pengguna .tanda { font-size: .72rem; color: var(--hijau-700); font-weight: 600; }
  /* Lencana angka di butir Notifikasi: penanda jumlah yang belum dibaca. */
  .menu-lencana { margin-left: auto; min-width: 20px; padding: 0 6px;
    border-radius: 10px; background: var(--merah); color: #fff;
    font-size: .7rem; font-weight: 700; line-height: 19px; text-align: center; }
  .menu-butir { display: flex; align-items: center; gap: .5rem;
    padding: .6rem .6rem; min-height: 44px; border-radius: var(--r-kecil);
    color: var(--tinta-2); text-decoration: none; font-size: .875rem; font-weight: 600; }
  .menu-butir:hover { background: var(--hijau-100); }
  .menu-butir.keluar { color: var(--merah); }
  .menu-butir.keluar:hover { background: var(--merah-l); }
}

/* ---- Pengumuman resmi: kop surat (dipakai halaman /pengumuman) ----
   Kop ini yang membuat pengumuman terbaca sebagai surat resmi perusahaan, bukan
   sekadar catatan. Latarnya putih supaya logo berwarna gelap tetap terbaca. */
.kop { display: flex; align-items: center; gap: .9rem;
  padding: .9rem 1rem; margin-bottom: .9rem;
  border: 1px solid var(--garis-2); border-bottom: 3px solid var(--hijau-700);
  border-radius: var(--r-kecil); background: #fff; }
.kop img { height: 46px; width: auto; flex: 0 0 auto; }
.kop div { min-width: 0; }
.kop b { display: block; font-size: 1rem; letter-spacing: .01em; }
.kop small { display: block; font-size: .78rem; color: var(--pudar); }
@media (max-width: 900px) {
  .kop img { height: 38px; }
  .kop b { font-size: .92rem; }
}

/* ---- Pengumuman & Aspirasi: daftar "kabar" ----
   Bukan tabel: isi pengumuman perlu lebar penuh untuk dibaca, dan di ponsel
   tabel akan memecahnya jadi label+nilai (tiap sel = tinggi baris). Satu kartu
   per kabar, judul + meta + isi. */
.kabar-daftar { display: flex; flex-direction: column; gap: .7rem; }
.kabar { border: 1px solid var(--garis-2); border-radius: var(--r-kecil);
  padding: .8rem .9rem; background: #fff; }
/* Belum dibaca: garis kiri hijau + latar tipis — penanda yang tetap terlihat
   tanpa bergantung warna lencana saja. */
.kabar-baru { border-left: 4px solid var(--hijau-600); background: var(--hijau-100); }
.kabar header { display: flex; flex-direction: column; gap: .15rem; margin-bottom: .35rem; }
.kabar h3 { margin: 0; font-size: .95rem; display: flex; flex-wrap: wrap;
  align-items: center; gap: .35rem; }
/* Daftar: judul jadi tautan ke halaman detail, ringkasan singkat di bawahnya.
   Seluruh kartu bisa diklik (tautan judul & "Baca lengkap" menuju halaman yang
   sama), jadi tidak ada lagi yang terasa "tidak bisa dibuka". */
.kabar-judul { color: inherit; text-decoration: none; }
.kabar-judul:hover, .kabar-judul:focus-visible { color: var(--hijau-700);
  text-decoration: underline; }
.kabar-ringkas { margin: .35rem 0 0; font-size: .875rem; line-height: 1.5;
  color: var(--tinta-2); overflow-wrap: anywhere; }
.kabar-buka { display: inline-block; margin-top: .45rem; font-size: .8rem;
  font-weight: 700; color: var(--hijau-700); text-decoration: none; }
.kabar-buka:hover { text-decoration: underline; }

/* Halaman detail pengumuman. Kelasnya SENDIRI-sendiri — sebelumnya bagian ini
   memakai `.jejak` (yang ternyata bilah progres, height 8px) sehingga tautan
   kembalinya tergencet jadi batang bergaris. */
.balik { margin: 0 0 .35rem; font-size: .82rem; font-weight: 600; }
.balik a { color: var(--hijau-700); text-decoration: none; }
.balik a:hover, .balik a:focus-visible { text-decoration: underline; }
.surat-meta { margin: 0 0 .7rem; padding-bottom: .55rem; font-size: .8rem;
  color: var(--pudar); border-bottom: 1px solid var(--garis-2); }
/* `pre-wrap` menjaga baris & paragraf yang ditulis pengirim; `overflow-wrap`
   menahan tautan panjang agar tidak meluber di ponsel. */
.surat-isi p { margin: 0; font-size: .95rem; line-height: 1.7;
  white-space: pre-wrap; overflow-wrap: anywhere; }
@media (max-width: 900px) {
  .surat-isi p { font-size: .9rem; line-height: 1.65; }
}
.kabar header small { font-size: .78rem; }
/* `overflow-wrap` wajib: manajer sering menempel tautan panjang di aspirasi. */
.kabar > p { margin: 0; font-size: .875rem; line-height: 1.5;
  white-space: pre-wrap; overflow-wrap: anywhere; }
.kabar .tanggapan { margin-top: .55rem; padding: .55rem .7rem; border-radius: var(--r-kecil);
  background: var(--hijau-l); border-left: 3px solid var(--hijau-600); }
.kabar .tanggapan p { margin: .2rem 0 0; font-size: .875rem; white-space: pre-wrap;
  overflow-wrap: anywhere; }
.kabar .tombol-baris { margin-top: .6rem; }

/* Formulir sederhana (pengumuman & aspirasi). Kolomnya menumpuk; `.lebar`
   menandai isian yang perlu baris penuh (perihal di desktop pun boleh lebar). */
.petak-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: .7rem; align-items: start; }
.petak-form label { display: flex; flex-direction: column; gap: .3rem; margin: 0; }
.petak-form label > span { font-size: .8rem; font-weight: 600; color: var(--pudar); }
.petak-form .lebar, .petak-form .tombol-baris { grid-column: 1 / -1; }
.petak-form textarea { min-height: 0; }

/* ---- Kartu status ringkas (/pasokan) ----
   Tingginya dipaku supaya deretan kartu rata walau labelnya satu/dua kata, dan
   angka dipisah sebagai baris tersendiri (labelnya kecil di atas). */
.kartu-status .kartu { display: flex; flex-direction: column; justify-content: center;
  gap: .15rem; min-height: 4.6rem; text-align: left; }
.kartu-status .kartu small { font-size: .74rem; letter-spacing: .02em; text-transform: uppercase;
  color: var(--pudar); font-weight: 600; }
.kartu-status .kartu b { font-size: 1.25rem; line-height: 1.1; }

/* ---- /pasokan: bilah saring & proporsi kolom ----
   Dua cacat terukur di halaman ini:

   1. "Pencarian terlalu nempel". Bingkai bilah `.saring` sudah x=33 pada
      viewport 390px (sudah sejajar tepi kartu tabel di bawahnya), tetapi
      ISIAN di dalamnya juga x=34 — hanya 1px dari garis bingkainya sendiri,
      karena `padding: .6rem 0` memang sengaja menghapus padding samping.
      Kini jaraknya 13px. Padding dinyatakan di sini, BUKAN di aturan `.saring`
      global: bilah saring dipakai 8 halaman lain yang sudah punya jarak sendiri
      (mis. #buku `.7rem 0`), dan mengubah spasi semua halaman itu bukan yang
      diminta — `.saring` global juga menahan bilah tanpa padding sama sekali.
   2. Kolom tabel: terukur 1073px terbagi Kode 440 (41%), UMKM & Komoditas 227,
      Jumlah & Nilai 125, Status & Pembayaran 192, Aksi 89. Kolom terlebar
      justru memuat informasi paling sedikit, sementara "Rp 7.000 / UNIT"
      terbelah dua baris di kolom 125px. Sebabnya nama koperasi yang panjang
      ("KOPERASI DESA MERAH PUTIH CIBEBER KECAMATAN SUKAGUMIWANG") ada di sel
      Kode, dan algoritma tabel otomatis melebarkan mengikuti isi terpanjang.
      Lebar di bawah dinyatakan per-kolom supaya kolom terlebar dipegang kolom
      yang paling banyak menjelaskan. Sengaja TETAP `table-layout: auto`:
      sel Aksi memakai `white-space: nowrap`, dan pada `fixed` isi yang tak
      muat LUBER keluar sel alih-alih melebarkan kolomnya — persentase di sini
      jadi arahan, bukan paku. */
#ps form.saring { padding: .7rem .8rem; }
@media (min-width: 721px) {
  /* Angka-angka ini hasil UKURAN, bukan selera. Percobaan pertama (18/31/16/23)
     membuat kolom Kode hanya 181px, sehingga nama koperasi panjang
     ("KOPERASI DESA MERAH PUTIH KENITEN KECAMATAN GEMUH…" — 56 karakter, data
     nyata) membungkus jadi TIGA baris dan barisnya jadi 143px sementara baris
     lain 91px. Dinaikkan ke 21% (228px) supaya nama sepanjang itu cukup DUA
     baris; ruangnya diambil dari kolom UMKM, yang tadinya paling lebar.
     Sesudahnya: 143px -> 91px, dan semua kolom sepadan dengan <th>-nya. */
  #ps th:nth-child(1) { width: 23%; }   /* Kode + tanggal + koperasi pembeli */
  #ps th:nth-child(2) { width: 23%; }   /* UMKM & Komoditas */
  #ps th:nth-child(3) { width: 16%; }   /* Jumlah & Nilai */
  #ps th:nth-child(4) { width: 20%; }   /* Status & Pembayaran */
  /* Aksi tidak diberi lebar: selebar isi tombolnya. */
}

/* ---- /pasokan (PONSEL): dua sel pendek disejajarkan ----
   Di ponsel tiap sel jadi label+nilai bertumpuk, jadi tinggi satu pasokan =
   jumlah sel x tinggi sel (terukur 477px untuk baris ber-nama-koperasi panjang,
   391px untuk sisanya). Kode dan Jumlah & Nilai isinya pendek, jadi label dan
   nilainya dibuat SEBARIS — tata letaknya dipadatkan, TIDAK ada teks yang
   disembunyikan. Pola sama dengan .tabel-koperasi td[data-l="Manajer"]. */
@media (max-width: 720px) {
  #ps .tabel-bungkus td[data-l="Kode"],
  #ps .tabel-bungkus td[data-l="Jumlah & Nilai"] { display: flex; align-items: baseline;
    gap: .55rem; padding-top: .15rem; padding-bottom: .15rem; flex-wrap: wrap; }
  #ps .tabel-bungkus td[data-l="Kode"]::before,
  #ps .tabel-bungkus td[data-l="Jumlah & Nilai"]::before { flex: 0 0 auto; padding-top: 0; }
}

/* ---- /pasokan: catatan penolakan memakai lebar penuh ----
   `.grid-form` merentangkan `<input>`/`<select>` jadi 100% kolomnya, termasuk
   yang berada DI DALAM modal. `<textarea>` tidak ikut: bawaannya ~20 kolom,
   jadi kotak "Keterangan / catatan penolakan" hanya ~60% lebar modal dan
   tampak menggantung. Dibuat penuh, karena itu isian paling panjang di modal. */
#bayar-ajukan textarea, #bayar-putus textarea, #pasokan-modal textarea { width: 100%; }

/* ---- Notifikasi melayang (toast) ----
   Melayang di atas, di tengah, di atas segalanya. `position: fixed` supaya tidak
   ikut tergulir; `max-width` supaya pesan panjang tetap terbaca di ponsel. */
#hub-toast { position: fixed; top: .9rem; left: 50%; transform: translateX(-50%);
  z-index: 90; display: flex; flex-direction: column; gap: .5rem; width: min(30rem, calc(100vw - 1.6rem));
  pointer-events: none; }
#hub-toast .toast { pointer-events: auto; padding: .7rem 1rem; border-radius: var(--r-kecil);
  border: 1px solid; box-shadow: var(--bayang-2); font-size: .875rem; font-weight: 600;
  animation: toast-masuk .22s ease-out; }
#hub-toast .toast.ok { background: var(--hijau-l); color: #14512f; border-color: var(--hijau-g); }
#hub-toast .toast.rusak { background: var(--merah-l); color: var(--merah); border-color: var(--merah-g); }
#hub-toast .toast.keluar { opacity: 0; transform: translateY(-.4rem); transition: all .35s ease-in; }
@keyframes toast-masuk { from { opacity: 0; transform: translateY(-.5rem); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  #hub-toast .toast { animation: none; }
  #hub-toast .toast.keluar { transition: none; }
}

/* ---- Form Tugas Cepat (/workspace) ----
   Bentuknya sengaja TIDAK memakai `.grid-form` generik. Terukur dengan
   `auto-fit minmax(230px,1fr)` pada form 1073px: grid menghasilkan EMPAT kolom
   sementara isiannya hanya dua (judul & tenggat, 255px masing-masing) — separuh
   kanan form menganggur dan isian tampak menggantung di kiri. Row-gap-nya juga 0
   (`.grid-form` hanya `gap: 0 1.1rem`), jadi barisnya rapat dan tidak terbaca
   sebagai kelompok.

   Di sini grid-nya eksplisit: dua kolom untuk judul & tenggat supaya keduanya
   memakai LEBAR PENUH form, dan satu baris untuk tombol yang rata kanan. */
.form-cepat { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 1.05rem 1.1rem; align-items: start; }
.form-cepat > .penuh { grid-column: 1 / -1; }
.form-cepat label { display: block; margin: 0; }
/* Tinggi kontrol dikunci dari SATU variabel. Tanpa ini <input> 43px berdiri di
   sebelah <input type=date> 45px — beda 2px dari bawaannya, dan itu yang paling
   kentara saat dikatakan "kurang rapih". */
.form-cepat input:not([type="hidden"]), .form-cepat select {
  width: 100%; height: 42px; min-height: 0; margin: .35rem 0 0; padding: 0 .8rem;
  font-size: .875rem; }
.form-cepat .cari-kop { margin-top: .35rem; }
.form-cepat .cari-kop input { margin-top: 0; }
/* Keterangan "Terpilih: …" menempel pada kotaknya, bukan melayang di bawah
   dengan jarak label — kalau tidak, blok Koperasi 20px lebih tinggi dari
   siblingnya dan barisnya tidak rata. */
.form-cepat .bantuan { margin-top: .4rem; }
.form-cepat .aksi { display: flex; justify-content: flex-end; align-items: center;
  gap: .6rem; padding-top: .3rem; }
.form-cepat .aksi .tombol { min-width: 9.5rem; }
@media (max-width: 720px) {
  .form-cepat { grid-template-columns: minmax(0, 1fr); }
  .form-cepat .aksi { justify-content: stretch; }
  .form-cepat .aksi .tombol { flex: 1 1 auto; }
}

/* ---- /keuangan: kotak lingkup (mode agregat) ----
   Sebelumnya baris "Sedang dilihat: …" hanya <p class="bantuan"> tanpa jarak
   bawah (terukur margin-bottom 0px, jarak ke kartu 0px) sehingga menempel ke
   kartu di bawahnya. Di mode agregat ia juga butuh wadah sendiri karena berisi
   pemilih koperasi — bukan sekadar keterangan. */
.lingkup-kop { display: flex; flex-wrap: wrap; gap: .8rem 1rem; align-items: center;
  justify-content: space-between; border: 1px solid var(--garis); border-radius: var(--r-kecil);
  background: var(--putih); padding: .8rem 1rem; margin: 0 0 1.1rem; }
.lingkup-kop b { font-size: .95rem; }
.lingkup-kop small { display: block; }
.lingkup-kop .cari-kop { margin-top: .3rem; min-width: 15rem; }
.lingkup-kop form.saring { margin: 0; padding: 0; }
/* Keterangan "Sedang dilihat" pada mode satu koperasi — jarak bawahnya dulu 0.
   Diberi cakupan #daftar (bukan #keuangan yang tidak ada) supaya SELECTOR-nya
   benar-benar cocok; selektor yang tidak cocok tidak memunculkan galat apa pun,
   hanya diam — persis jenis kesalahan yang paling lama dicari. */
#daftar .kop-terpilih { margin: .55rem 0 1.1rem; }

/* ---- /keuangan: tata letak Buku Kas ----
   Dua cacat terukur yang diperbaiki di sini:

   1. Tabel tidak memakai lebar yang tersedia — sel Aksi 22px dengan ~115px
      menganggur di kanan, dan kolom Uraian tercekik 95px walau isinya teks
      panjang. Sebabnya `th/td.kolom-aksi { width: 1% }` saja, sementara kolom
      teks tidak diberi arahan sama sekali sehingga semua kolom melebar rata.
      Di sini: kolom teks dibuat MELAR (Uraian), kolom angka & aksi tetap
      selebar isinya.
   2. `.dua-kolom` menaruh Rekap di kolom kanan yang sempit (407px dari 1117px),
      sehingga tabel kas berhenti di 648px dan sisa lebar kosong. Rekap dipindah
      ke bawah tabel; kelas `.dua-kolom` tidak dipakai lagi di halaman ini. */
#buku table { table-layout: auto; }
#buku th, #buku td { vertical-align: top; }
/* Uraian = satu-satunya kolom yang melar; sisanya selebar isinya. */
#buku th:nth-child(2), #buku td:nth-child(2) { width: auto; }
/* HANYA desktop. Aturan ini berada SETELAH media query ponsel dan memakai id
   (`#buku`), jadi spesifisitasnya mengalahkan `.tabel-bungkus td.kolom-aksi`
   milik ponsel — `width:1%` ikut terpakai di ponsel dan selnya kolaps jadi 3px
   lagi. Dibatasi ke min-width:721px supaya tata letak ponsel tetap milik
   media query-nya sendiri. */
@media (min-width: 721px) {
  #buku th.kolom-aksi, #buku td.kolom-aksi { width: 1%; white-space: nowrap; }
}
/* Isian panjang (nama koperasi pada mode agregat) jangan memaksa tabel melebar. */
#buku td.judul-sel, #buku .kwitansi { overflow-wrap: anywhere; }
@media (min-width: 721px) {
  /* Bilah saring Buku Kas: pencarian melar, dua pemilih tetap seukuran isinya. */
  #buku form.saring { display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 13rem) minmax(0, 11rem) auto auto;
    gap: .55rem; align-items: center; }
  #buku form.saring > * { min-width: 0; }
  #buku form.saring input, #buku form.saring select { width: 100%; }
}
/* Kotak pencarian koperasi pada kotak lingkup: satu bingkai (bukan .saring
   bersarang), dan kotak hasilnya mengambang dari tepi kiri kotak itu. */
.lingkup-kop form.cari-koperasi { position: relative; flex: 0 1 24rem; min-width: 0; }
.lingkup-kop form.cari-koperasi .cari-kop { margin: 0; }
.lingkup-kop form.cari-koperasi input[type="search"] { width: 100%; height: 42px;
  min-height: 0; margin: 0; padding: 0 .8rem; font-size: .875rem; }
/* Isian terkunci (baris otomatis) dibedakan tanpa menyembunyikan nilainya. */
.modal input.terkunci { background: var(--zebra); color: var(--pudar); cursor: not-allowed; }

/* ---- /workspace/dokumen: gaya halaman pengolah dokumen ----
   Kartu jenis berkas + ikon. Warnanya sengaja meniru konvensi yang sudah dikenal
   pengguna (Word biru, Excel hijau, PowerPoint oranye, PDF merah) supaya jenis
   berkas dikenali dari warna sebelum tulisannya dibaca. */
.kartu-jenis { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: .8rem; }
.kartu-jenis .dok-pilih { display: flex; flex-direction: column; align-items: center;
  gap: .35rem; padding: 1.1rem .8rem; text-align: center; cursor: pointer;
  background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r);
  font-family: inherit; font-size: .9rem; color: var(--tinta);
  transition: border-color .12s, box-shadow .12s, transform .12s; }
.kartu-jenis .dok-pilih:hover { border-color: var(--hijau-500); box-shadow: var(--bayang-2);
  transform: translateY(-1px); }
.kartu-jenis .dok-pilih:focus-visible { outline: 2px solid var(--hijau-600); outline-offset: 2px; }
.kartu-jenis .dok-pilih b { font-size: .95rem; }
.kartu-jenis .dok-pilih small { display: block; font-size: .74rem; line-height: 1.3; }

.dok-ikon { width: 34px; height: 34px; flex: 0 0 auto; display: inline-flex;
  align-items: center; justify-content: center; border-radius: .5rem; color: #fff; }
.dok-ikon svg { width: 20px; height: 20px; }
.dok-ikon.kecil { width: 24px; height: 24px; border-radius: .35rem; vertical-align: -6px; }
.dok-ikon.kecil svg { width: 15px; height: 15px; }
.dok-ikon.doc { background: #2b579a; }
.dok-ikon.xls { background: #217346; }
.dok-ikon.ppt { background: #c43e1c; }
.dok-ikon.pdf { background: #b3202c; }

/* Tab kelompok dokumen — sebaris, aktif ditandai garis bawah. */
.dok-tab { display: flex; flex-wrap: wrap; gap: .2rem; margin: 0 0 .9rem;
  border-bottom: 1px solid var(--garis); }
.dok-tab a { display: inline-flex; align-items: center; gap: .4rem; padding: .5rem .85rem;
  font-size: .85rem; font-weight: 600; color: var(--tinta-2); text-decoration: none;
  border-bottom: 2px solid transparent; margin-bottom: -1px; }
.dok-tab a:hover { color: var(--tinta); }
.dok-tab a.ini { color: var(--hijau-700); border-bottom-color: var(--hijau-600); }
.dok-tab .jml { background: var(--zebra); border-radius: 999px; padding: .05rem .45rem;
  font-size: .72rem; color: var(--pudar); }
.dok-tab a.ini .jml { background: var(--hijau-100); color: var(--hijau-700); }

/* Pilihan akses di dialog: radio + keterangan, satu baris per pilihan. */
.dok-pilih-akses { border: 0; padding: 0; margin: 0 0 .9rem; }
.dok-pilih-akses legend { font-size: .82rem; font-weight: 600; color: var(--tinta-2);
  padding: 0; margin-bottom: .4rem; }
.dok-pilih-akses .pilihan { display: flex; align-items: flex-start; gap: .55rem;
  border: 1px solid var(--garis); border-radius: var(--r-kecil); padding: .55rem .7rem;
  margin-bottom: .4rem; cursor: pointer; font-weight: 400; }
.dok-pilih-akses .pilihan:hover { border-color: var(--hijau-500); }
/* `:has()` memilih kartu yang radionya tercentang — tanpa JS sama sekali. */
.dok-pilih-akses .pilihan:has(input:checked) { border-color: var(--hijau-600);
  background: var(--hijau-l); }
.dok-pilih-akses .pilihan input { width: auto; height: auto; margin: .2rem 0 0; flex: 0 0 auto; }
.dok-pilih-akses .pilihan b { display: block; font-size: .87rem; }
.dok-pilih-akses .pilihan small { display: block; font-size: .76rem; color: var(--pudar); }

/* PDF: panel ringkas, bukan editor kosong. */
.dok-pdf { display: flex; gap: .9rem; align-items: flex-start; padding: .9rem;
  background: var(--zebra); border: 1px solid var(--garis); border-radius: var(--r-kecil); }
.dok-pdf .dok-ikon { width: 44px; height: 44px; }
.dok-pdf .dok-ikon svg { width: 26px; height: 26px; }
.dok-pdf b { font-size: .95rem; }
.dok-pdf p { margin: .2rem 0 0; font-size: .82rem; }

/* ---- /workspace/catatan-harian: catatan pribadi ----
   Kartu, bukan tabel: catatan itu tulisan bebas (bisa panjang, berbaris-baris),
   dan tabel memaksa isinya jadi satu baris terpotong. */
.cat-kepala { display: flex; flex-wrap: wrap; gap: .6rem 1rem; align-items: center;
  justify-content: space-between; margin-bottom: .9rem; }
.cat-kepala h2 { margin: 0; }
.cat-tanggal { display: flex; gap: .5rem; align-items: center; }
.cat-tanggal input[type="date"] { width: auto; margin: 0; height: 42px; }

.cat-kartu { display: flex; gap: .9rem; align-items: flex-start;
  background: var(--putih); border: 1px solid var(--garis); border-radius: var(--r-kecil);
  border-left: 3px solid var(--pudar); padding: .8rem .9rem; margin-bottom: .6rem; }
.cat-kartu.kecil { padding: .7rem .8rem; margin-bottom: 0; }
.cat-kartu .cat-isi { flex: 1 1 auto; min-width: 0; }
.cat-kartu h3 { margin: 0 0 .2rem; font-size: .98rem; line-height: 1.35; }
.cat-kartu.kecil h3 { font-size: .92rem; }
.cat-meta { margin: 0 0 .35rem; font-size: .74rem; color: var(--pudar);
  display: flex; flex-wrap: wrap; gap: .35rem; align-items: center; }
.cat-teks { font-size: .87rem; line-height: 1.5; color: var(--tinta-2);
  overflow-wrap: anywhere; }
/* Batasi tinggi pratinjau di arsip: satu catatan panjang tidak boleh mengubur
   puluhan catatan lain di bawahnya. */
.cat-kartu.kecil .cat-teks { display: -webkit-box; -webkit-line-clamp: 3;
  -webkit-box-orient: vertical; overflow: hidden; }
.cat-kendala { margin-top: .45rem; padding: .45rem .6rem; font-size: .82rem;
  background: var(--zebra); border-radius: var(--r-kecil); color: var(--tinta-2);
  overflow-wrap: anywhere; }
.cat-kendala b { display: block; font-size: .72rem; text-transform: uppercase;
  letter-spacing: .05em; color: var(--pudar); margin-bottom: .15rem; }
.cat-aksi { flex: 0 0 auto; display: flex; flex-wrap: wrap; gap: .35rem; align-items: flex-start; }
.cat-aksi form { margin: 0; }

/* Warna tepi kiri per jenis — dibaca sekilas sebelum teksnya dibaca. */
.cat-kegiatan { border-left-color: #2b579a; }
.cat-kendala  { border-left-color: #b3261e; }
.cat-rencana  { border-left-color: #0e5a66; }
.cat-ide      { border-left-color: #8a6d00; }
.cat-penting  { border-left-color: #7a3ea8; }

.cat-arsip-baris { display: grid; gap: .55rem; }
.cat-kosong { text-align: center; padding: 1.6rem 1rem; border: 1px dashed var(--garis);
  border-radius: var(--r-kecil); background: var(--zebra); }
.cat-kosong p { margin: 0 0 .35rem; }
.cat-kosong .tombol { margin-top: .5rem; }

/* Dua kolom di dalam dialog (jenis + tanggal) — berdampingan saat lapang. */
.cat-dua { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; }
.cat-saran { display: flex; flex-wrap: wrap; gap: .35rem; align-items: center; }
.cat-saran .pil { font: inherit; font-size: .76rem; padding: .18rem .55rem; cursor: pointer;
  border: 1px solid var(--garis); border-radius: 999px; background: var(--putih);
  color: var(--tinta-2); }
.cat-saran .pil:hover { border-color: var(--hijau-500); color: var(--hijau-700); }

/* 🔴 Tinggi tombol disamakan lewat SEL-nya. Sebelum ini tombol 32px dan form
   jadi 43px: `align-items: flex-start` menjadikan tiap anak flex-item, sehingga
   FORM ikut jadi flex container dengan tinggi barisnya sendiri — dan Hapus
   tampak lebih tinggi daripada Ubah. `line-height: 0` pada wadah + dipulihkan
   pada form menghapus ruang descender tanpa mengubah ukuran tombol. */
.cat-aksi { align-items: center; }
.cat-aksi form { line-height: 0; display: flex; }
/* `margin: 0` WAJIB: ada aturan global yang memberi tombol di dalam form
   `margin-top: .7rem` (11,2px), sehingga wadah tombol jadi 43px sementara
   tombolnya sendiri tetap 32px — itulah "tombol berantakan" yang terlihat. */
.cat-aksi .tombol { line-height: 1.35; margin: 0; }

/* Dialog Detail (baca-saja). */
.cat-detail { font-size: .9rem; line-height: 1.55; color: var(--tinta-2);
  white-space: pre-wrap; overflow-wrap: anywhere; max-height: 46vh; overflow-y: auto;
  padding: .1rem 0; }
 #cat-lihat .cat-kendala { white-space: pre-wrap; }

/* Ponsel: aksi turun ke bawah isi (kartu satu kolom), tombol memenuhi lebar
   supaya mudah ditekan — bukan dua tombol kecil berdempetan. */
@media (max-width: 640px) {
  .cat-kartu { flex-direction: column; gap: .6rem; }
  .cat-aksi { width: 100%; }
  .cat-aksi .tombol, .cat-aksi form { flex: 1 1 auto; }
  .cat-aksi .tombol { width: 100%; justify-content: center; }
  .cat-dua { grid-template-columns: 1fr; }
  .cat-tanggal { width: 100%; }
  .cat-tanggal input[type="date"] { flex: 1 1 auto; min-width: 0; }
}

/* ---- /workspace/kalender: bagian desktop ----
   Peta bulan tetap kisi 7 kolom; acara tampil DI DALAM sel (lihat aturan .kal-*
   di atas). Daftar per tanggal hanya untuk ponsel. */
.kal-kepala { display: flex; flex-wrap: wrap; gap: .6rem 1rem; align-items: center;
  justify-content: space-between; margin-bottom: .9rem; }
.kal-kepala h2 { margin: 0; }
.kal-navigasi { display: flex; flex-wrap: wrap; gap: .35rem; }
.kal-tgl { display: flex; align-items: center; gap: .3rem; }
.kal-angka { font-variant-numeric: tabular-nums; }
.kal-titik { display: none; background: var(--hijau-100, #e3efe8); color: #15402f;
  border-radius: 999px; font-size: .66rem; font-weight: 700; padding: .02rem .34rem; }
.kal-jam { flex: 0 0 auto; }
.kal-nama { min-width: 0; }
.kal-dua { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; }
.kal-pekan .kal-angka { color: #9aa5a0; }

/* ---- /workspace/tugas: kartu ringkasan, status berwarna, progres ---- */
.tg-kartu { display: grid; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); gap: .5rem;
  /* `grid-auto-rows: 1fr` menyamakan tinggi SELURUH baris kartu. Tanpa ini,
     label yang membungkus ("Perlu Revisi") membuat barisnya lebih tinggi daripada
     baris lain, dan deretan kartu tampak bergerigi. */
  grid-auto-rows: 1fr; }
.tg-kartu .kartu { text-align: center; padding: .6rem .5rem; text-decoration: none; }
.tg-kartu .kartu b { display: block; font-size: 1.25rem; line-height: 1.2; }
.tg-kartu .kartu small { font-size: .72rem; }
.tg-kartu .kartu.ini { outline: 2px solid var(--hijau-600); outline-offset: -2px; }
.pil-status { font-weight: 600; }
.pil-status.biru { color: #1d4ed8; } .pil-status.kuning { color: #92600a; }
.pil-status.ungu { color: #6b21a8; } .pil-status.oranye { color: #b45309; }
.pil-status.merah { color: #b3261e; } .pil-status.hijau { color: #1a7f4b; }
.prio-rendah { background: #eef2f0; color: #4b5b54; } .prio-normal { background: #e3efe8; color: #15402f; }
.prio-tinggi { background: #fdeceb; color: #b3261e; }
.tg-telat { color: #b3261e; font-weight: 600; }
.tg-desk, .tg-catatan { display: block; }
.tg-catatan { margin-top: .2rem; padding: .3rem .45rem; background: var(--zebra);
  border-radius: var(--r-kecil); font-size: .78rem; }
.tg-riwayat { margin: .4rem 0 0; padding-left: 1.1rem; font-size: .82rem; }
.tg-riwayat li { margin-bottom: .45rem; }
.tg-riwayat li div { overflow-wrap: anywhere; }
.tg-dua { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; }

/* ---- /workspace/jobdesc: daftar uraian tugas dari Lampiran PKWT ---- */
.jd-daftar { display: grid; gap: .55rem; grid-template-columns: minmax(0, 1fr); }
.jd-kartu { border: 1px solid var(--garis); border-left: 3px solid var(--pudar);
  border-radius: var(--r-kecil); background: var(--putih); padding: .6rem .75rem; }
.jd-kartu.jd-wajib { border-left-color: #2b579a; }
.jd-kepala { display: flex; gap: .5rem; align-items: flex-start; flex-wrap: wrap; }
.jd-kepala h3 { margin: 0; font-size: .92rem; flex: 1 1 auto; min-width: 0; }
.jd-no { flex: 0 0 auto; width: 22px; height: 22px; border-radius: 999px; background: var(--zebra);
  color: var(--tinta-2); font-size: .72rem; font-weight: 700; display: inline-flex;
  align-items: center; justify-content: center; }
.jd-wajib .jd-no { background: #2b579a; color: #fff; }
.jd-menit { flex: 0 0 auto; }
.jd-desk { margin: .35rem 0 0 30px; font-size: .82rem; line-height: 1.5; color: var(--tinta-2);
  overflow-wrap: anywhere; }
.jd-poin { margin: 1rem 0 .4rem; font-size: .86rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--hijau-700); }

@media (max-width: 640px) {
  .tg-kartu { grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); }
  .tg-dua { grid-template-columns: 1fr; }
  .jd-desk { margin-left: 0; }
}

/* Kepala satu bagian: judul di kiri, tombol di kanan (dipakai dasbor & halaman
   modul). Flex-wrap supaya di ponsel tombol turun sendiri, bukan menekan judul. */
.kepala-bagian { display: flex; flex-wrap: wrap; gap: .5rem 1rem; align-items: center;
  justify-content: space-between; margin-bottom: .8rem; }
.kepala-bagian h2 { margin: 0; }
.kepala-bagian .tombol-baris { display: flex; flex-wrap: wrap; gap: .35rem; }

/* ============================================== AgriConnect (modul mandiri)
   Hanya tiga hal yang benar-benar baru: daftar alasan, daftar ringkas di kartu,
   dan isi pelajaran. Selebihnya memakai kelas bersama (.kartu, .blok, .lencana,
   .tabel-bungkus, .modal) — tidak ada gaya baru untuk hal yang sudah ada. */
.daftar-alasan { margin: .6rem 0 0; padding-left: 1.1rem; font-size: .86rem; line-height: 1.65; }
.daftar-alasan li { margin-bottom: .3rem; }
.daftar-ringkas { margin: .5rem 0 .7rem; padding-left: 1.1rem; font-size: .84rem; line-height: 1.5; }
.daftar-ringkas li { margin-bottom: .25rem; }
/* Isi pelajaran: teks apa adanya, tetapi baris barunya dipertahankan dan
   dibatasi lebarnya supaya enak dibaca di layar lebar. */
.materi-isi { white-space: pre-wrap; max-width: 68ch; line-height: 1.7; font-size: .93rem; }
.pilihan-sebaris { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }

/* Daftar langkah E-Learning: tombol centang di kiri, teks langkah di kanan.
   Baris yang sudah tuntas ditandai centang, bukan disembunyikan. */
.daftar-langkah { list-style: none; margin: .5rem 0 .7rem; padding: 0; font-size: .88rem; }
.daftar-langkah li { display: flex; align-items: center; gap: .5rem; padding: .3rem 0;
  border-bottom: 1px solid var(--garis, #e6e8ee); }
.daftar-langkah li form { margin: 0; }
.daftar-langkah li.sudah { color: var(--pudar, #6b7280); }

/* ---- /admin/materi: unggah berprogres + daftar materi ----
   Kotak seret-lepas di kiri, isian di kanan; satu kolom di layar sempit.

   Kotak IKUT TINGGI baris (`stretch`) dan isinya dipusatkan tegak. Dengan
   `align-items: start` kotak setinggi 186px menggantung di atas sementara isian
   kanan setinggi 330px, sehingga kotak terbaca "melayang terlalu ke atas".
   Meregangkannya membuat tepi atas & bawahnya sejajar dengan kolom isian. */
.grid-form-mm { display: grid; grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  gap: 1.05rem 1.2rem; align-items: stretch; }
.lebar-penuh-mm { grid-column: 1 / -1; }
.mm-aksi { grid-column: 1 / -1; display: flex; align-items: center; justify-content: flex-end;
  gap: .8rem; flex-wrap: wrap; border-top: 1px solid var(--garis-2); padding-top: .9rem; }
/* Status kesiapan rata KIRI, mendorong tombolnya ke kanan — tanpa ini ia ikut
   terdorong dan terbaca seperti label tombolnya. */
.mm-aksi .bantuan { flex: 1 1 auto; margin: 0; text-align: left; }

/* Kotak seret-lepas. <input type=file> aslinya disembunyikan lewat clip-path,
   BUKAN display:none — supaya ia tetap fokusable dan label `for`-nya tetap
   terbuka oleh klik maupun Enter saat JavaScript mati.
   `flex-direction: column` menumpuk kartu berkas/bilah kemajuan tegak (bawaan
   flex adalah BARIS, yang membuat keduanya berdampingan). `min-height` menjaga
   kotak tidak mengempis di ponsel saat ajakan diganti kartu berkas — di sana
   grid satu kolom, jadi kotak tidak lagi mewarisi tinggi kolom isian. */
.mm-jatuh { position: relative; display: flex; flex-direction: column; justify-content: center;
  min-height: 172px;
  border: 1.5px dashed #c8d6cf;
  border-radius: var(--r); background: var(--zebra); transition: border-color .12s, background .12s; }
.mm-berkas { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); border: 0; }
/* `flex: 1 1 auto` membuat ajakan ini memenuhi tinggi kotak; `min-height`
   adalah LANTAI saat kolom kanan kebetulan lebih pendek (mis. sesudah berkas
   terpilih, tinggi kotak tidak lagi ikut baris). Isi dipusatkan tegak. */
.mm-jatuh-isi { display: flex; flex-direction: column; align-items: center; justify-content: center;
  flex: 1 1 auto; gap: .3rem; text-align: center; padding: 1.4rem 1rem; margin: 0; cursor: pointer;
  color: var(--tinta-2); font-weight: 500; min-height: 172px; }
.mm-jatuh-isi:hover { color: var(--hijau-700); }
.mm-jatuh-isi b { font-size: .95rem; }
.mm-jatuh-isi span { font-size: .85rem; color: var(--pudar); }
.mm-jatuh-isi u { text-decoration-color: var(--hijau-500); }
.mm-jatuh-isi small.bantuan { margin-top: .35rem; max-width: 32ch; }
.mm-jatuh-ikon { width: 34px; height: 34px; fill: none; stroke: var(--hijau-600);
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; margin-bottom: .2rem; }
.mm-jatuh.mm-seret { border-color: var(--hijau-500); background: var(--hijau-100); }
.mm-jatuh.mm-seret .mm-jatuh-isi { color: var(--hijau-700); }
/* Berkas terpilih: kotak isi diganti kartu berkas, jadi tidak ada dua ajakan
   yang saling menimpa dan bingkai putus-putusnya tidak lagi relevan. */
.mm-jatuh.ada-berkas { border-style: solid; border-color: var(--hijau-g); background: var(--putih); }
.mm-terpilih { display: flex; align-items: center; gap: .65rem; padding: 1rem; }
.mm-terpilih-ikon { width: 26px; height: 26px; flex: 0 0 auto; fill: none; stroke: var(--hijau-600);
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.mm-terpilih-teks { min-width: 0; flex: 1 1 auto; }
.mm-terpilih-teks b { display: block; font-size: .9rem; overflow-wrap: anywhere; }
.mm-terpilih-teks small { color: var(--pudar); }

/* Bilah kemajuan unggah — memakai .jejak yang sudah ada, bukan komponen baru. */
.mm-jalur { padding: .1rem 1rem 1rem; }
.mm-jalur .jejak { height: 10px; }
.mm-jalur .jejak > span { background: var(--hijau-600); transition: width .15s linear; }
.mm-jalur small { margin-top: .4rem; color: var(--pudar); }

.mm-isian label { display: block; }

/* Nama berkas bisa sangat panjang: boleh putus, dan dibatasi lebarnya supaya
   kolom lain tidak tercekik. */
.berkas-nama { display: block; max-width: 32ch; overflow-wrap: anywhere; }

/* Ponsel: isian minimal 16px.
   Safari iOS MEMPERBESAR halaman saat isian difokuskan bila ukuran hurufnya di
   bawah 16px — halaman melompat dan tata letaknya rusak di tengah pengisian.
   Basis huruf halaman 15px, jadi selisih 1px itu cukup untuk memicu zoom.
   Dipasang di SATU tempat untuk semua isian, bukan per halaman: satu aturan
   menutup seluruh formulir (profil, toko, stok, …) sekaligus. */
@media (max-width: 720px) {
  input, select, textarea { font-size: 16px; }
}

@media (max-width: 720px) {
  .grid-form-mm { grid-template-columns: minmax(0, 1fr); }
  .mm-aksi { justify-content: stretch; }
  .mm-aksi .bantuan { flex: 1 1 100%; }
  .mm-aksi .tombol { flex: 1 1 auto; }
}

/* ============================================ tab meja SDM (/admin/hr)
   Empat tab meja kepegawaian. Sama seperti .rapat-tab: satu baris, boleh
   digulir mendatar di ponsel supaya label tidak terpotong (bukan mengecilkan
   huruf), dan tab aktif ditandai garis bawah — bukan hanya warna. */
.pil-baris { display: flex; gap: .35rem; overflow-x: auto; overscroll-behavior-x: contain;
  border-bottom: 1px solid var(--garis); margin: 0 0 1rem; padding-bottom: 0; }
.pil-baris .pil { flex: none; padding: .45rem .8rem; font: inherit; font-size: .88rem;
  text-decoration: none; color: var(--pudar); border-bottom: 2px solid transparent;
  white-space: nowrap; }
.pil-baris .pil:hover { color: var(--tinta-2); }
.pil-baris .pil.ini { color: var(--tinta); font-weight: 600; border-bottom-color: var(--hijau); }

@media (max-width: 720px) {
  /* Ponsel: empat label panjang ("Rekrutmen & Onboarding") tidak muat sebaris.
     MEMBUNGKUS, bukan menggulir: gulir mendatar menyembunyikan tab terakhir —
     dan Bos melarang menyembunyikan informasi di ponsel (terukur 2 pil keluar
     layar di 320px saat mode gulir). */
  .pil-baris { flex-wrap: wrap; overflow-x: visible; margin-bottom: .8rem; row-gap: .1rem; }
  .pil-baris .pil { font-size: .84rem; padding: .4rem .6rem; }
}

/* ================================================== panel analisa lintas modul
   Dipakai partials/analisa.blade.php (Jurnal Audit & Struktur & Tim). Semua
   grafiknya CSS murni — tanpa pustaka grafik, tanpa JavaScript — mengikuti pola
   grafik arus kas modul Keuangan.

   SATU batang per hari, tumbuh dari garis dasar (`align-items: flex-end`),
   BUKAN batang dua arah seperti arus kas: arus kas punya nol di tengah karena
   nilainya bisa negatif, sedangkan jumlah aktivitas tidak pernah negatif dan
   nol-di-tengah hanya membuat batangnya tampak menggantung. `height: 100%`
   pada kolom WAJIB ada di atas `align-items: flex-end` — tanpa itu persentase
   tinggi batang diukur dari tinggi intrinsik kolom dan grafiknya tidak tumbuh. */
.tren { display: flex; align-items: flex-end; gap: 2px; height: 96px; margin: .2rem 0 .3rem;
  padding: .5rem .55rem 0; background: var(--zebra); border: 1px solid var(--garis);
  border-radius: var(--r-kecil); box-shadow: var(--bayang); }
.tren-kolom { flex: 1 1 0; min-width: 2px; height: 100%; display: flex;
  align-items: flex-end; border-radius: 2px 2px 0 0; }
.tren-kolom i { display: block; width: 100%; min-height: 2px; border-radius: 2px;
  background: var(--hijau-500); }
/* Hari tanpa aktivitas tetap tampil (batang pendek) supaya hari sepi tidak
   menghilang dan trennya tidak terbaca lebih ramai daripada kenyataannya. */
.tren-kolom.kosong i { background: var(--garis); opacity: .55; }
.tren-kolom:hover i { filter: brightness(.88); }

/* Baris pita: label — batang — angka. Dipakai cakupan kerja, sebaran, aksi,
   dan kesiapan supaya semuanya terbaca dengan satu bahasa visual. */
.petak-kotak { display: grid; gap: .55rem; margin-top: .7rem; }
.petak-kotak .jejak-baris { display: grid; grid-template-columns: minmax(88px, 1.5fr) minmax(70px, 3fr) auto;
  align-items: center; gap: .7rem; }
.petak-kotak .jejak-baris .nama { min-width: 0; overflow-wrap: anywhere; font-size: .84rem; }
.petak-kotak .jejak-baris b { font-variant-numeric: tabular-nums; font-size: .84rem; color: var(--tinta); text-align: right; }
.petak-kotak .jejak-baris small { grid-column: 2 / -1; margin-top: -.2rem; }
/* Ember sebaran: hijau makin tua seiring aktivitas. Yang "belum ada" memakai
   abu-abu, BUKAN merah — ia keadaan awal, bukan kesalahan. */
.petak-kotak .jejak > span.e-nol { background: var(--garis); }
.petak-kotak .jejak > span.e-rendah { background: var(--merah-g); }
.petak-kotak .jejak > span.e-sedang { background: var(--kuning-g); }
.petak-kotak .jejak > span.e-tinggi { background: var(--hijau-500); }
.petak-kotak .jejak > span.peringatan { background: var(--merah-g); }
/* Deretan lencana nama koperasi dorman: wadah terpisah supaya tidak menempel
   satu baris teks panjang yang menyulitkan pemindaian.
   `white-space: normal` WAJIB di sini: `.lencana` memakai `nowrap`, dan nama
   koperasi bisa 56 karakter ("KOPERASI DESA MERAH PUTIH CIBEBER KECAMATAN
   SUKAGUMIWANG" terukur 441px) sehingga halaman meluber mendatar di ponsel
   (478px di layar 390px). Ia lencana nama, bukan penanda status — membungkus
   dua baris tidak apa-apa. */
.lencana.samar { background: var(--zebra); color: var(--tinta-2); font-size: .74rem;
  padding: .18rem .5rem; margin: 0 .25rem .3rem 0; white-space: normal;
  max-width: 100%; overflow-wrap: anywhere; }
.lencana.samar::before { display: none; }

/* Varian warna lencana untuk pengumuman & aspirasi (jenis + status).
   Rumah ini sudah punya polanya lewat `.s-<STATUS>`; varian nama-panjang ini
   dipakai di tempat yang statusnya bukan salah satu konstanta alur tugas. */
.lencana.hijau { background: var(--hijau-l); color: var(--hijau-600); border-color: var(--hijau-g); }
.lencana.kuning { background: var(--kuning-l); color: var(--kuning); border-color: var(--kuning-g); }
.lencana.biru { background: var(--biru-l); color: var(--biru); border-color: var(--biru-g); }
.lencana.merah { background: var(--merah-l); color: var(--merah); border-color: var(--merah-g); }

/* Forum di halaman indeks Messenger: daftar topik diskusi.
   Gaya `pilih-baris` di blok lain hanya berlaku DI DALAM `.wa-baru`, jadi
   baris forum (yang tinggal di panel ajakan) perlu bentuknya sendiri —
   kalau tidak, tautannya tampil sebagai teks polos tanpa sasaran ketuk. */
.wa-forum { margin: 1rem 0 0; text-align: left; }
.wa-forum > b { display: block; font-size: .82rem; color: var(--tinta-2); margin-bottom: .35rem; }
.wa-forum .pilih-daftar { max-height: none; padding: 0; }
.wa-forum .pilih-baris { display: block; padding: .5rem .55rem; border-radius: var(--r-kecil);
  text-decoration: none; color: inherit; }
.wa-forum .pilih-baris:hover { background: var(--hijau-100); }
.wa-forum .pilih-nama { display: block; font-weight: 600; }
.wa-forum .pilih-baris small { display: block; color: var(--pudar); font-size: .8rem; }

/* Pesan yang ditarik tampil sebagai keterangan (riwayat tidak berlubang). */
.wa-b .wa-ditarik { color: var(--pudar); }

/* Topik forum di dalam ruangnya: pembuka diskusi, bukan pesan. */
.wa-topik-bilah { display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap;
  padding: .55rem .8rem; border-bottom: 1px solid var(--garis); background: var(--zebra); }
.wa-topik-bilah b { flex: none; font-size: .74rem; letter-spacing: .04em; text-transform: uppercase;
  color: var(--pudar); }
.wa-topik-bilah span { font-size: .9rem; color: var(--tinta); }

/* ============================================ KOPERASI — halaman /kop (/kop/*)
   Semua kelas di blok ini berawalan `kop-` dan HANYA dipakai modul Koperasi.
   Sengaja tidak menumpang kelas bersama (`.kartu`, `.blok`): modul ini butuh
   tampilan yang lebih padat & berwibawa daripada daftar biasa, dan menaikkan
   gaya kelas bersama akan mengubah 40+ halaman lain yang memakainya.

   CATATAN: kepala halaman TIDAK punya gaya sendiri lagi. Versi gelap
   (`.kop-hero`) dibuang 2026-10-18 atas permintaan Bos — modul Koperasi harus
   memakai pola kepala Hub yang sama (`.kepala`), jadi tidak ada dua bahasa
   visual di satu aplikasi.
   ------------------------------------------------------------------------ */

/* Petak angka: ikon dalam kotak bersudut + angka besar. Kartu ringkasan biasa
   hanya punya label & angka, sehingga enam kotak berturut-turut tampak rata. */
.kop-stat { display: flex; gap: .7rem; align-items: flex-start; background: var(--putih);
  border: 1px solid var(--garis); border-radius: var(--r);
  padding: .85rem .95rem; box-shadow: var(--bayang); min-width: 0; }
.kop-stat-ikon { flex: 0 0 auto; width: 36px; height: 36px; border-radius: 10px;
  display: grid; place-items: center; background: var(--hijau-100); color: var(--hijau-700); }
.kop-stat-ikon .ik { width: 19px; height: 19px; }
.kop-stat-teks { min-width: 0; }
.kop-stat-teks small { display: block; font-size: .68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em; color: var(--pudar); }
.kop-stat-teks b { display: block; margin-top: .12rem; line-height: 1.15;
  font-size: clamp(1.25rem, 1.05rem + 1vw, 1.65rem);
  font-variant-numeric: tabular-nums; color: var(--tinta); }
.kop-stat-teks b.panjang { font-size: 1rem; font-weight: 700; }
.kop-stat-teks i { display: block; font-style: normal; font-size: .72rem; color: var(--pudar); }

/* Judul blok ber-ikon — dipakai <h2> di dalam `.blok`. */
.kop-judul { display: inline-flex; align-items: center; gap: .45rem; }
.kop-judul .ik { width: 18px; height: 18px; flex: 0 0 auto; color: var(--hijau-600); }

/* Bilah progres tipis: satu angka persen lebih baik terbaca sebagai panjang. */
.kop-progres { height: 8px; border-radius: var(--r-kapsul); background: var(--garis-2);
  overflow: hidden; margin-top: .5rem; }
.kop-progres > span { display: block; height: 100%; border-radius: var(--r-kapsul);
  background: linear-gradient(90deg, var(--hijau-500), var(--hijau-700)); }

/* Panel "Padanan Pemetaan Lahan": baris kunci–nilai yang rapat. */
.kop-peta { display: grid; gap: .1rem; margin: 0 0 .6rem; }
.kop-peta-baris { display: flex; flex-wrap: wrap; gap: .3rem .6rem; align-items: baseline;
  padding: .5rem 0; border-bottom: 1px solid var(--garis-2); font-size: .85rem; }
.kop-peta-baris:last-child { border-bottom: 0; }
.kop-peta-baris > span:first-child { flex: 0 0 auto; min-width: 9rem;
  font-size: .74rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--pudar); }
.kop-peta-baris > b { font-variant-numeric: tabular-nums; }

@media (max-width: 720px) {
  .kop-hero { padding: 1rem 1.05rem; }
  .kop-hero-isi { gap: .85rem; }
  .kop-hero h1 { max-width: none; }
  .kop-hero-status { display: inline-flex; width: auto; }
  /* Tombol melebar penuh: di ponsel tiga tombol berdampingan menyisakan ~90px
     per tombol dan labelnya ("Keuangan Koperasi") terpotong. */
  .kop-hero .tombol-baris { width: 100%; }
  .kop-hero .tombol-baris > .tombol,
  .kop-hero .tombol-baris > form { flex: 1 1 100%; }
  .kop-hero .tombol-baris > form > .tombol { width: 100%; }
  .kop-peta-baris > span:first-child { min-width: 100%; }
}

/* ---------------------------------------------- Koperasi: POS di PONSEL
   Terukur di 390px: tabel barang berubah jadi kartu per baris (aturan global
   `.tabel-bungkus` di atas) — lima sel bertumpuk = 205px per barang. Katalog
   300 barang berarti gulir 61.500px, dan tombol "+ Keranjang" baru terlihat
   SETELAH menggulir satu kartu penuh: kasir praktis tidak bisa memakainya.
   Yang dipadatkan: sel pendek (Harga, Stok) dibuat SEBARIS dengan labelnya,
   dan blok identitas → tombol disusun bertingkat. Tidak ada teks yang
   disembunyikan — hanya tata letaknya yang dirapatkan, sesuai aturan Bos.
   ---------------------------------------------------------------------- */
@media (max-width: 720px) {
  /* `tr` jadi GRID dua kolom: sel pendek berpasangan sebaris, sisanya melebar
     penuh. Terukur: 5 sel bertumpuk = kartu 205px; setelah dipadatkan begini
     turun ke ±130px, dan tombol "+ Keranjang" langsung terlihat tanpa menggulir
     satu kartu penuh. Tidak ada teks yang disembunyikan. */
  .tabel-pos tr { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: .7rem; padding: .55rem .7rem; margin-bottom: .45rem; }
  /* Barang = identitas: satu blok penuh, label atasannya dilepas karena nama
     barang sudah jelas, dan baris "BARANG" cuma menghabiskan tinggi kartu. */
  .tabel-pos td[data-l="Barang"] { grid-column: 1 / -1; display: block; padding: 0 0 .15rem; }
  .tabel-pos td[data-l="Barang"]::before { display: none; }
  /* Harga & Stok berdampingan: isinya pendek (satu baris), jadi dua sel satu
     baris lebih baik daripada dua baris terpisah. */
  .tabel-pos td[data-l="Harga"],
  .tabel-pos td[data-l="Stok"] { display: flex; align-items: baseline;
    gap: .4rem; padding: .1rem 0; flex-wrap: wrap; }
  .tabel-pos td[data-l="Harga"] { grid-column: 1; }
  .tabel-pos td[data-l="Stok"] { grid-column: 2; }
  .tabel-pos td[data-l="Harga"]::before,
  .tabel-pos td[data-l="Stok"]::before { flex: 0 0 auto; padding-top: 0; }
  /* Tombol keranjang jadi lebar penuh: sasaran sentuh besar, tidak meleset. */
  .tabel-pos td.kolom-aksi { grid-column: 1 / -1; padding-top: .5rem; }
  .tabel-pos td.kolom-aksi .tombol { width: 100%; min-height: 42px; }

  /* Riwayat nota: 7 sel = kartu 297px per nota. Nomor+Tanggal dan Total+Bayar
     dipasangkan sebaris; teks panjang (pembeli, status, aksi) melebar penuh. */
  .tabel-nota tr { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: .7rem; padding: .6rem .75rem; }
  .tabel-nota td[data-l="Nomor"],
  .tabel-nota td[data-l="Tanggal"],
  .tabel-nota td[data-l="Total"],
  .tabel-nota td[data-l="Bayar"] { display: flex; align-items: baseline;
    gap: .45rem; padding: .12rem 0; flex-wrap: wrap; }
  .tabel-nota td[data-l="Nomor"] { grid-column: 1; }
  .tabel-nota td[data-l="Tanggal"] { grid-column: 2; }
  .tabel-nota td[data-l="Total"] { grid-column: 1; }
  .tabel-nota td[data-l="Bayar"] { grid-column: 2; }
  .tabel-nota td[data-l="Pembeli"],
  .tabel-nota td[data-l="Status"],
  .tabel-nota td.kolom-aksi { grid-column: 1 / -1; }
  .tabel-nota td[data-l="Nomor"]::before,
  .tabel-nota td[data-l="Tanggal"]::before,
  .tabel-nota td[data-l="Total"]::before,
  .tabel-nota td[data-l="Bayar"]::before { flex: 0 0 auto; padding-top: 0; }
  .tabel-nota td.kolom-aksi { padding-top: .45rem; }

  /* Form kasir: pasangan isian pendek dijadikan DUA KOLOM supaya tidak menuntut
     gulir panjang sebelum tombol Simpan. `grid-form` global sudah satu kolom;
     hanya di POS isiannya pendek-pendek. */
  .kop-form-2 { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem .7rem; }
  .kop-form-2 > label { min-width: 0; }
  .kop-form-2 > label.lebar-penuh { grid-column: 1 / -1; }
  /* Tombol Simpan melebar penuh: di ponsel ia target utama, dan berdampingan
     dengan "Kosongkan Keranjang" membuat keduanya sempit. */
  .pos-aksi > .tombol { flex: 1 1 100%; min-height: 46px; }

  /* Kepala Koperasi: TIGA tombol berlabel panjang ("Tarik dari SIMKOPDES" 18
     karakter). Dibiarkan mengalir sebaris mereka mengecil sampai labelnya
     terpotong — dan di sini tombolnya bukan hiasan, itu aksi utama pengelola.
     Dipakai GRID, bukan flex: dengan `flex: 1 1 calc(50%-...)` pembulatan
     subpiksel kadang membuat dua tombol tidak muat semeja lalu masing-masing
     membungkus ke barisnya sendiri dan melebar penuh (terukur: 358px per
     tombol alih-alih ±175px). Grid menentukan kolomnya, bukan menebak. */
  .kepala-kop .tombol-baris { display: grid; grid-template-columns: 1fr 1fr;
    width: 100%; gap: .45rem; }
  /* "Tarik dari SIMKOPDES" selalu melebar penuh: labelnya paling panjang, dan
     ia satu-satunya yang berupa formulir (POST). */
  .kepala-kop .tombol-baris > form { grid-column: 1 / -1; }
  .kepala-kop .tombol { width: 100%; min-height: 42px; justify-content: center;
    font-size: .84rem; padding: .42rem .55rem; }
  .kepala-kop .tombol .ik { width: 15px; height: 15px; }
  /* Bila hanya ada SATU tombol langsung (mis. tak ada form Tarik), biarkan
     melebar penuh — dua kolom dengan satu isi menyisakan rongga aneh. */
  .kepala-kop .tombol-baris > .tombol:only-child { grid-column: 1 / -1; }
}

/* ---- Gerbang WhatsApp di formulir Siaran ----
   Duduk sebagai sel grid .grid-form, jadi tombolnya sebaris dengan kolom
   Sasaran di desktop. `align-self: end` + margin bawah yang sama dengan
   `label` menyejajarkannya dengan <select>, bukan dengan teks labelnya. */
.wa-gabung { display: flex; align-items: center; gap: .45rem; flex-wrap: nowrap;
  align-self: end; margin-bottom: .85rem; }
.wa-gabung .bantuan { margin: 0; flex: 1 1 auto; }
@media (max-width: 720px) { .wa-gabung { grid-column: 1 / -1; flex-wrap: wrap; } }
/* QR di dalam dialog: latar putih wajib — kode QR transparan tidak terbaca
   pemindai saat modal berlatar gelap, dan padding menjaga zona sunyi. */
.wa-qr-bingkai { margin: .3rem 0; text-align: center; }
.wa-qr-bingkai img { background: #fff; padding: 10px; border-radius: 12px;
  width: min(280px, 100%); height: auto; }

/* ================================================== /keuangan: rekap kategori
   "Ke mana uangnya pergi" — dua kolom berdampingan (pemasukan | pengeluaran),
   satu baris per kategori dengan batang persentase. Batangnya <i> di dalam
   <span>, bukan <progress>: <progress> tidak bisa diwarnai beda per sisi
   (masuk hijau, keluar merah) tanpa trik vendor, sedangkan elemen biasa cukup
   `width`.
   Di ponsel kolomnya menumpuk: dua kolom berisi nama kategori + rupiah +
   persen + batang menyisakan ~130px per kolom dan semuanya membungkus. */
.kategori-kas { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: .8rem 1.4rem; margin: .1rem 0 .9rem; }
.kategori-sisi { border: 1px solid var(--garis); border-radius: var(--r-kecil);
  padding: .7rem .85rem; background: var(--putih); }
.kategori-sisi > b { display: block; font-size: .82rem; margin-bottom: .55rem;
  padding-bottom: .45rem; border-bottom: 1px solid var(--garis-2); }
.kategori-baris { display: grid; grid-template-columns: minmax(0, 1fr) auto auto;
  gap: .1rem .55rem; align-items: baseline; margin-bottom: .5rem; }
.kategori-baris:last-child { margin-bottom: 0; }
.kategori-nama { font-size: .82rem; overflow-wrap: anywhere; }
.kategori-angka { font-size: .82rem; font-weight: 600; font-variant-numeric: tabular-nums;
  white-space: nowrap; }
.kategori-persen { font-size: .75rem; font-variant-numeric: tabular-nums;
  white-space: nowrap; min-width: 3.2em; text-align: right; }
/* Batang menempati baris KEDUA, selebar seluruh kolom: ia membandingkan
   kategori satu sama lain, jadi skalanya harus sama panjang. */
.kategori-batang { grid-column: 1 / -1; display: block; height: 5px;
  background: var(--garis-2); border-radius: 3px; overflow: hidden; }
.kategori-batang > i { display: block; height: 100%; border-radius: 3px;
  background: var(--hijau-500); }
.kategori-sisi:last-child .kategori-batang > i { background: var(--merah-g); }
@media (max-width: 720px) {
  .kategori-kas { grid-template-columns: 1fr; }
}


/* ---- Navigasi halaman FITUR AgriConnect (/agri/hris/*) -------------------
   Pengganti kisi 21 kartu di atas isi halaman: satu jalur pulang + butir
   antarfitura. Di ponsel butirnya MENGALIR MENYAMPING (bukan disembunyikan dan
   bukan membungkus jadi tiga baris) supaya isi halaman tetap dekat. */
.agri-subnav { display: flex; align-items: center; gap: .55rem; flex-wrap: wrap;
  margin: .1rem 0 1rem; padding: .5rem .6rem; background: var(--putih);
  border: 1px solid var(--garis); border-radius: var(--r); }
.agri-subnav-pulang { color: var(--hijau-700); font-weight: 600; text-decoration: none;
  white-space: nowrap; }
.agri-subnav-butir { display: flex; gap: .35rem; flex: 1 1 240px; min-width: 0;
  overflow-x: auto; padding-bottom: 2px; scrollbar-width: thin; }
.agri-subnav-butir a { padding: .3rem .6rem; border: 1px solid var(--garis);
  border-radius: 999px; color: var(--tinta-2); font-size: .82rem; text-decoration: none;
  white-space: nowrap; }
.agri-subnav-butir a:hover { border-color: var(--hijau-500); color: var(--hijau-700); }
.agri-subnav-butir a.ini { background: var(--hijau-l); border-color: var(--hijau-600);
  color: var(--hijau-700); font-weight: 600; }
.agri-subnav-status { padding: .25rem .55rem; border: 1px solid var(--hijau-g);
  border-radius: 999px; background: var(--hijau-l); color: #14512f;
  font-size: .78rem; font-weight: 600; white-space: nowrap; }
.agri-subnav-sambung { padding: .3rem .7rem; border: 1px solid var(--hijau-600);
  border-radius: 999px; background: var(--hijau-600); color: #fff;
  font-family: inherit; font-size: .82rem; font-weight: 600; cursor: pointer;
  white-space: nowrap; }
.agri-subnav-sambung:hover { background: var(--hijau-700); border-color: var(--hijau-700); }
/* Di ponsel butir antarfitura turun ke barisnya sendiri: satu baris tombol
   (pulang + Hubungkan/Tersambung), satu baris pil yang mengalir menyamping.
   Tanpa ini tombol Hubungkan terlempar ke baris ketiga. */
@media (max-width: 720px) {
  .agri-subnav { gap: .45rem .55rem; }
  .agri-subnav-pulang { order: 0; }
  .agri-subnav-status, .agri-subnav-sambung { order: 1; margin-left: auto; }
  .agri-subnav-butir { order: 2; flex: 1 1 100%; }
}

/* ==========================================================================
   AgriConnect — penyeragaman & polesan (2026-10-21)
   Satu blok untuk seluruh halaman /agri*: judul blok dengan penghitung baris,
   bar saring tabel, dan kartu Absen AgriConnect. Ditaruh di sini (bukan di
   dalam <style> per halaman) karena keluhan aslinya justru "tiap halaman beda".
   ========================================================================== */

/* ---- Judul blok + penghitung --------------------------------------------- */
.blok-kepala { display: flex; align-items: baseline; justify-content: space-between;
  gap: .6rem; flex-wrap: wrap; }
.blok-kepala h2 { margin-bottom: .35rem; }
.blok-kepala > :last-child { font-size: .8rem; font-variant-numeric: tabular-nums; }

/* ---- Bar saring yang dibuat hub-saring-tabel.js --------------------------- */
.saring-tabel { margin: 0 0 .6rem; }
.saring-tabel .saring-hitung { flex: 0 0 auto; font-size: .8rem;
  font-variant-numeric: tabular-nums; margin-left: auto; }
.saring-pager { display: flex; align-items: center; justify-content: flex-end;
  gap: .6rem; margin: .7rem 0 .1rem; font-size: .82rem; }
.saring-pager .tombol { min-height: 36px; padding: .25rem .7rem; }
.saring-pager .tombol[disabled] { opacity: .45; cursor: default; }
.saring-pager[hidden] { display: none; }
@media (max-width: 720px) {
  /* Di ponsel penghitung turun ke barisnya sendiri: kolom cari + select sudah
     memakai seluruh lebar, dan angka yang menempel di kanan akan terpotong. */
  .saring-tabel .saring-hitung { flex: 1 1 100%; margin-left: 0; }
  .saring-pager { justify-content: space-between; }
  .saring-pager .tombol { flex: 0 0 auto; }
}

/* ---- Kartu Absen AgriConnect -------------------------------------------- */
.agri-absen { border-left: 3px solid var(--hijau-600); }
.agri-absen-kepala { display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; flex-wrap: wrap; margin-bottom: .5rem; }
.agri-absen-kepala h2 { margin: 0; }
.agri-absen-form { display: grid; grid-template-columns: minmax(220px, 280px) 1fr;
  gap: .9rem 1.1rem; align-items: start; margin-top: .6rem; }
.agri-berkas, .agri-ket { display: flex; flex-direction: column; gap: .3rem;
  font-size: .85rem; font-weight: 600; color: var(--tinta-2); }
.agri-berkas input[type="file"] { font-weight: 400; font-size: .82rem;
  padding: .7rem .8rem; background: var(--hijau-100);
  border: 1px dashed var(--hijau-300); border-radius: var(--r); cursor: pointer;
  width: 100%; }
.agri-berkas input[type="file"]:hover { border-color: var(--hijau-600); }
.agri-berkas input[type="file"]::file-selector-button { margin-right: .7rem;
  padding: .4rem .8rem; border: 0; border-radius: 8px; background: var(--hijau-600);
  color: #fff; font: inherit; font-weight: 600; cursor: pointer; }
.agri-ket input[type="text"] { font-weight: 400; }
.agri-absen-kaki { grid-column: 1 / -1; display: flex; align-items: center;
  gap: .8rem; flex-wrap: wrap; padding-top: .2rem; }
.agri-absen-kaki .tombol { min-height: 44px; padding-inline: 1.4rem; }
.agri-absen-kaki .bantuan { flex: 1 1 320px; margin: 0; font-weight: 400; }
.agri-absen-form .pesan { margin: .1rem 0 0; font-weight: 400; }
@media (max-width: 720px) {
  /* Satu kolom: berkas di atas, keterangan di bawah, tombol selebar kartu —
     ibu jari tidak perlu membidik tombol kecil di pojok. */
  .agri-absen-form { grid-template-columns: 1fr; gap: .7rem; }
  .agri-absen-kaki { flex-direction: column; align-items: stretch; gap: .45rem; }
  /* `flex: 1 1 320px` di atas jadi flex-BASIS sumbu tegak saat kolom →
     tinggi paksa 320px. Di ponsel kembalikan ke tinggi isinya. */
  .agri-absen-kaki .bantuan { flex: 0 0 auto; }
  .agri-absen-kaki .tombol { width: 100%; }
}

/* ---- Polesan kecil yang berlaku di semua halaman AgriConnect ------------- */
.petak .kartu.angka { transition: border-color .15s ease, box-shadow .15s ease; }
.petak .kartu.angka:hover { border-color: var(--hijau-300);
  box-shadow: 0 2px 10px rgba(16, 29, 24, .05); }
.blok .tabel-bungkus table tbody tr:hover { background: var(--zebra); }

/* Dua lencana keadaan Absen Masuk/Pulang berdampingan; di ponsel turun baris
   sendiri supaya judul kartu tidak terhimpit. */
.lencana-baris { display: flex; gap: .4rem; flex-wrap: wrap; }
@media (max-width: 720px) { .lencana-baris { width: 100%; } }


/* ===== Absen Agrinashub (dipindah dari blade 2026-10-21) =====
   Sebelumnya CSS ini ditulis inline di setiap render halaman absen:
   +9,6 KB di SETIAP muat halaman dan tidak pernah bisa di-cache.
   Di sini ia ikut hub.css yang di-cache lama, jadi byte-nya dibayar
   sekali saja. Semua selektornya ber-scope kelas halaman absen. */
.kepala-blok { display: flex; align-items: center; justify-content: space-between; gap: .8rem;
    flex-wrap: wrap; margin-bottom: .9rem; }
  .kepala-blok h2 { margin: 0; }
  .notis { padding: .6rem .8rem; border-radius: var(--r-kecil); font-size: .88rem; margin-bottom: .8rem; }
  .notis-ok { background: var(--hijau-l); border: 1px solid var(--hijau-g); color: var(--hijau-800); }
  .notis-galat { background: var(--merah-l); border: 1px solid var(--merah-g); color: var(--merah); }

  .pilih-aksi { display: grid; gap: .6rem; margin-bottom: 1rem;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
  .pilih-aksi-butir { display: flex; gap: .6rem; align-items: flex-start; padding: .75rem .85rem;
    border: 1px solid var(--garis); border-radius: var(--r-kecil); background: var(--putih);
    cursor: pointer; transition: border-color .15s, background .15s; }
  .pilih-aksi-butir:hover { border-color: var(--hijau-500); background: var(--hijau-100); }
  .pilih-aksi-butir input { margin-top: .2rem; accent-color: var(--hijau-600); }
  .pilih-aksi-butir input:checked + span strong { color: var(--hijau-700); }
  .pilih-aksi-butir span { display: block; }
  .pilih-aksi-butir strong { display: block; font-size: .9rem; }
  .pilih-aksi-butir small { color: var(--pudar); font-size: .78rem; }

  .bukti-baris { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    margin: 1rem 0; }
  .bukti-kotak { display: flex; flex-direction: column; gap: .55rem; }
  /* Tombol kamera & lokasi di tengah: keduanya aksi tunggal di kolom sempit,
     dan rata kiri membuatnya terlihat seperti potongan formulir yang terlepas. */
  .tombol-tengah { justify-content: center; }
  /* Tombol tetap BISA ditekan walau belum lengkap; hanya terlihat lebih redup
     supaya jelas ada yang kurang. Bukan `disabled`: tombol mati tidak bisa
     memberi alasan saat ditekan. */
  .tombol.utama.belum { opacity: .62; }
  .tombol-tengah > .tombol { min-width: 9.5rem; }
  .lokasi-kotak { border: 1px dashed var(--garis); border-radius: var(--r-kecil);
    padding: .8rem; background: var(--zebra); min-height: 96px; }
  .lokasi-rinci { margin: .5rem 0 0; display: grid; gap: .3rem; }
  .lokasi-rinci div { display: flex; justify-content: space-between; gap: .6rem; font-size: .8rem; }
  .lokasi-rinci dt { color: var(--pudar); margin: 0; }
  .lokasi-rinci dd { margin: 0; font-variant-numeric: tabular-nums; font-weight: 600; }

  .linimasa { list-style: none; margin: 0; padding: 0; }
  .linimasa-butir { display: flex; gap: .75rem; padding: .55rem 0;
    border-bottom: 1px solid var(--garis-2); }
  .linimasa-butir:last-child { border-bottom: 0; }
  .linimasa-jam { font-variant-numeric: tabular-nums; font-weight: 700; font-size: .88rem;
    color: var(--hijau-700); flex: 0 0 3rem; }
  .linimasa-isi { min-width: 0; }
  .linimasa-isi strong { display: block; font-size: .88rem; }
  .linimasa-isi small { color: var(--pudar); font-size: .76rem; }
  .linimasa-keluar .linimasa-jam { color: var(--merah); }
  .linimasa-istirahat_mulai .linimasa-jam,
  .linimasa-istirahat_selesai .linimasa-jam { color: var(--kuning); }

  .daftar-ringkas { margin: 0; padding-left: 1.1rem; font-size: .85rem; line-height: 1.6; }
  .daftar-ringkas li { margin-bottom: .5rem; }
  .daftar-ringkas li:last-child { margin-bottom: 0; }

  /* ---------- Riwayat: filter & tabel yang jadi kartu di ponsel ---------- */
  /* Bentuk yang diminta Bos: label DI ATAS kotak pilih, tombol "Lihat" DI BAWAH.
     Dipakai GRID dua kolom, bukan flex: dengan flex, tombol bisa dipaksa turun
     lewat `flex-basis: 100%` tetapi lalu IKUT MELAR selebar layar. Di grid, tombol
     cukup ditugaskan ke baris kedua (`grid-column: 1 / -1`) dan lebarnya
     dikembalikan ke selebar teksnya lewat `justify-self: start`.
     Ponsel: tombol memang selebar layar (jempol lebih mudah). */
  .saring-riwayat { display: grid; grid-template-columns: auto auto;
    justify-content: start; align-items: end;
    gap: .55rem .7rem; margin-bottom: 1rem; }
  .saring-riwayat label { display: flex; flex-direction: column; align-items: stretch;
    gap: .3rem; min-width: 0; margin: 0; padding: 0; }
  .saring-label { font-size: .7rem; text-transform: uppercase;
    letter-spacing: .07em; color: var(--pudar); font-weight: 700; line-height: 1.2;
    white-space: nowrap; }
  /* Tinggi DIKUNCI 42px dan `flex: 0 0 auto`: aturan global
     `.saring select { flex: 1 1 220px }` dulu membuat select setinggi 220px di
     sini (flex-basis berlaku vertikal). Selektor (0,2,1) menang atas
     `.saring select` (0,1,1) tanpa bergantung urutan berkas. */
  .saring-riwayat select { flex: 0 0 auto; width: 9.5rem; max-width: 100%;
    height: 42px; min-height: 42px; margin-top: 0; padding: 0 .6rem; line-height: normal;
    border: 1px solid var(--garis); border-radius: var(--r-kecil);
    background: var(--putih); font: inherit; font-size: .875rem; color: var(--tinta); }
  .saring-riwayat select:focus-visible { outline: 2px solid var(--hijau-500); outline-offset: 1px; }
  .saring-riwayat .tombol { grid-column: 1 / -1; justify-self: start;
    height: 42px; min-height: 42px; margin: 0; }
  @media (max-width: 560px) {
    .saring-riwayat { grid-template-columns: 1fr 1fr; }
    .saring-riwayat select { width: 100%; }
    .saring-riwayat .tombol { justify-self: stretch; width: 100%; }
  }

  .riwayat-isi[aria-busy="true"] { opacity: .55; transition: opacity .12s; }
  .riwayat-kosong { padding: .6rem 0; }

  .riwayat-tabel table { width: 100%; border-collapse: collapse; }
  .riwayat-tabel th { text-align: left; font-size: .7rem; text-transform: uppercase;
    letter-spacing: .07em; color: var(--pudar); font-weight: 700;
    padding: .5rem .55rem; border-bottom: 1px solid var(--garis); white-space: nowrap; }
  .riwayat-tabel td { padding: .6rem .55rem; border-bottom: 1px solid var(--garis-2);
    font-size: .875rem; vertical-align: middle; }
  .riwayat-tabel tbody tr:hover { background: var(--zebra); }
  .riwayat-tanggal { font-weight: 400; text-align: left; text-transform: none;
    letter-spacing: 0; font-size: .875rem; color: var(--tinta); }
  .riwayat-tanggal b { display: block; font-weight: 700; }
  .riwayat-tanggal small { color: var(--pudar); font-size: .76rem; }
  .riwayat-angka { font-variant-numeric: tabular-nums; }
  .riwayat-angka small { display: inline; color: var(--pudar); font-size: .74rem; }

  .riwayat-kaki { display: flex; align-items: center; justify-content: space-between;
    gap: .8rem; flex-wrap: wrap; margin-top: .9rem; }
  .riwayat-kaki .bantuan { margin: 0; }

  @media (max-width: 720px) {
    .dua-kolom { grid-template-columns: 1fr; }

    /* Kepala tabel disembunyikan secara visual (bukan display:none) supaya
       pembaca layar tetap mendapat hubungan kolom -> nilai. */
    .riwayat-tabel thead { position: absolute; width: 1px; height: 1px; overflow: hidden;
      clip-path: inset(50%); white-space: nowrap; }
    .riwayat-tabel table, .riwayat-tabel tbody { display: block; }
    .riwayat-tabel tr { display: block; border: 1px solid var(--garis);
      border-radius: var(--r-kecil); background: var(--putih);
      box-shadow: var(--bayang); margin-bottom: .6rem; padding: .55rem .75rem; }
    .riwayat-tabel tr:hover { background: var(--putih); }
    .riwayat-tabel td { display: flex; align-items: baseline; justify-content: space-between;
      gap: .75rem; padding: .3rem 0; border-bottom: 0; font-size: .85rem; }
    .riwayat-tabel td::before { content: attr(data-label); flex: 0 0 44%;
      font-size: .7rem; text-transform: uppercase; letter-spacing: .05em;
      color: var(--pudar); font-weight: 700; }
    .riwayat-tabel th[scope="row"] { display: block; padding: 0 0 .45rem;
      margin-bottom: .35rem; border-bottom: 1px solid var(--garis-2); }
    .riwayat-tabel th[scope="row"]::before { content: none; }
    .riwayat-tanggal b { font-size: .95rem; }
    .riwayat-kaki { flex-direction: column; align-items: flex-start; }
    .riwayat-kaki .paging { width: 100%; justify-content: space-between; }
  }

  @media (max-width: 720px) {
    .dua-kolom { grid-template-columns: 1fr; }
  }


/* ===== Modal bukti foto absen: dua foto berdampingan =====
   Dua kolom di layar lebar supaya masuk & pulang bisa DIBANDINGKAN sejajar
   (itu gunanya); satu kolom di ponsel karena dua potret 3:4 berdampingan di
   layar 360px hanya menyisakan ~150px per wajah — terlalu kecil untuk dilihat. */
.foto-pasangan { display: grid; grid-template-columns: 1fr 1fr; gap: .9rem; }
.foto-kotak { margin: 0; display: flex; flex-direction: column; gap: .4rem; min-width: 0; }
.foto-kotak figcaption { display: flex; align-items: baseline; gap: .4rem; flex-wrap: wrap; }
.foto-kotak figcaption strong { font-size: .8rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--pudar); }
.foto-kotak figcaption span { font-size: .8rem; color: var(--tinta-2);
  font-variant-numeric: tabular-nums; }
.foto-bingkai { position: relative; aspect-ratio: 3 / 4; border-radius: var(--r-kecil);
  overflow: hidden; background: var(--zebra); border: 1px solid var(--garis); }
.foto-bingkai img { width: 100%; height: 100%; object-fit: cover; display: block; }
.foto-kosong { margin: 0; position: absolute; inset: 0; display: grid; place-items: center;
  font-size: .8rem; color: var(--pudar); text-align: center; padding: .8rem; }
.tombol-x { font-size: 1.1rem; line-height: 1; padding: .2rem .55rem; min-width: 34px; }
@media (max-width: 560px) {
  .foto-pasangan { grid-template-columns: 1fr; gap: .8rem; }
  .foto-bingkai { aspect-ratio: 4 / 3; }
}


/* ===== Perpindahan halaman tanpa muat ulang (AJAX nav di hub.js) =====
   Isi <main id="isi"> diganti di tempat, jadi tanpa animasi layar berubah
   seketika dan terasa seperti kedip. Naik 6px + pudar 0.22s cukup memberi
   kesan "halaman datang", tanpa menunda apa pun: pengguna yang membaca cepat
   tetap melihat konten segera.

   Bilah #hub-proses yang sudah ada tetap dipakai sebagai penanda permintaan
   berjalan; animasi ini hanya untuk isi yang SUDAH tiba. */
.isi.masuk-nav { animation: hub-masuk-nav .22s ease-out; }
@keyframes hub-masuk-nav {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .isi.masuk-nav { animation: none; }
}


/* ===== Penanda jumlah barang di butir "Keranjang" (modul-nav Toko) =====
   Memakai gaya `.lencana-notif` yang sudah dipakai lonceng & bilah bawah, tapi
   duduk INLINE di dalam tautan (bukan menempel di pojok ikon), jadi posisinya
   dikembalikan ke static dan warnanya disamakan dengan butir yang aktif.
   `margin-left:auto` mendorongnya ke ujung kanan butir — sejajar di semua
   bahasa/lebar label, tanpa perlu mengukur teks. */
.modul-nav .lencana-nav {
  position: static; margin-left: auto; min-width: 19px; height: 19px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0 .28rem; border-radius: 999px; font-size: .7rem; font-weight: 700;
  line-height: 1; color: #fff; background: var(--merah, #b91c1c);
  border: 1px solid var(--putih);
}
.modul-nav a.ini .lencana-nav { border-color: transparent; }

/* Teks untuk pembaca layar saja — tidak memakan ruang, tidak terlihat. */
.hanya-pembaca {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}


/* ===== Lencana JENIS produk di kartu katalog =====
   Tiga warna, tiga arti: subsidi (hijau = bantuan pemerintah), lokal (oranye
   = dari koperasi lain), non-subsidi (abu = komersial biasa). Tanpa beda warna,
   lencana hanya teks panjang yang sulit dipindai sementara berbelanja. */
.kat-lencana.j-subsidi { background: rgba(21, 100, 60, .92); }
.kat-lencana.j-lokal { background: rgba(154, 52, 18, .92); }
.kat-lencana.j-nonsubsidi { background: rgba(60, 72, 66, .82); }

/* Checkbox subsidi di formulir Kelola Katalog: kotak centang + dua baris teks.
   `.centang` global memakai flex-row sehingga keterangan panjang meluber;
   di sini teksnya dibungkus dan checkbox-nya tidak menyusut. */
.centang-subsidi { display: flex; align-items: flex-start; gap: .5rem; }
.centang-subsidi input[type="checkbox"] { flex: 0 0 auto; width: 1.05rem;
  height: 1.05rem; margin-top: .15rem; }
.centang-subsidi span { font-size: .85rem; line-height: 1.35; }
.centang-subsidi .bantuan { display: block; font-size: .76rem; }

/* ===== Katalog di PONSEL =====
   Tiga hal yang membuat halaman terasa berantakan di layar sempit:
   1) bilah saring membungkus jadi 3 baris (cari 1 baris, jenis 1 baris,
      tombol 1 baris) — total ~150px hanya untuk penyaring;
   2) kartu 140px memaksa nama produk terpotong jadi 2 kata;
   3) sisa ruang di kanan kisi karena `auto-fill` menyisakan kolom kosong.

   Perbaikannya: penyaring dipadatkan jadi DUA baris (cari, lalu jenis+tombol
   sebaris), dan kisi memakai `auto-fit` dengan minimum 46% supaya SELALU
   dua kolom rapi — tidak pernah menyisakan kolom setengah kosong. */
@media (max-width: 640px) {
  .saring-katalog { padding: .5rem .6rem; gap: .4rem; }
  .saring-katalog label.cari { flex: 1 1 100%; max-width: none; }
  /* Jenis + tombol berbagi satu baris; `min-width: 0` wajib supaya <select>
     yang opsinya panjang ("Produk Lokal & UMKM") tidak mendorong tombol keluar. */
  .saring-katalog label.pilih { flex: 1 1 auto; min-width: 0; }
  .saring-katalog .bersih-saring { flex: 0 0 auto; }
  .saring-katalog .bersih-saring[hidden] { display: none; }
}

@media (max-width: 560px) {
  /* Dua kolom pasti: 46% + gap, bukan `auto-fill` yang bergantung lebar sisa. */
  .katalog-kisi { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .55rem; }
  .kat-badan { padding: .45rem .5rem .55rem; }
  .kat-badan h3 { font-size: .8rem; }
  .kat-harga { font-size: .92rem; }
  /* Baris aksi: kolom jumlah menyusut, tombol tetap 38px agar bisa disentuh. */
  .kat-aksi form { --t: 38px; gap: .3rem; }
  .kat-aksi input[type="number"] { padding-left: .4rem; padding-right: .2rem; }
}
