/* ==========================================================================
   SIRKAT UIS — Gaya antarmuka
   Tema: Hijau Sage. Merek memegang seluruh kerangka (bilah sisi, kepala
   tabel, judul), aksen memegang tindakan (menu aktif, tombol utama, sorotan).
   Karena keduanya sekeluarga warna, tindakan dibedakan lewat terang-gelap:
   paling pekat di atas halaman terang, paling terang di atas bilah gelap.
   ========================================================================== */

:root {
  /* ==================================================================
     PALET MEREK — hijau tua, emas & krem, dari colorhunt.co/palette/
     123f36-2a6b5c-c49a45-e8dcc4

     Palet sumber memberi dua hijau (#123f36, #2a6b5c), satu emas
     (#c49a45), dan satu krem (#e8dcc4):

       --merek-*  hijau, kerangka: bilah sisi, kepala tabel, judul
       --aksen-*  tindakan: tombol utama, menu aktif, sorotan
       --emas-*   emas, peringatan dan penanda AT COST

     Krem menjadi keadaan aktif di atas bilah yang gelap; hijau paling
     tua menjadi tombol utama di atas halaman terang. Satu nilai tidak
     cukup untuk keduanya: yang terbaca di atas putih akan hilang di atas
     hijau tua, dan sebaliknya.

     EMAS PALET SEKALIGUS MENJADI AMBER SEMANTIK, dan itu disengaja.
     Emas #c49a45 hanya terpaut 5,2 derajat corak dari amber peringatan
     yang dipakai sistem ini sejak awal (#c9821f). Dua emas yang nyaris
     sama pada satu layar tidak menambah apa pun: lencana hitungan dan
     penanda AT COST justru saling meniadakan karena mata membacanya
     sebagai warna yang sama tetapi tidak persis. Karena itu keduanya
     memakai satu nilai, diambil dari palet.

     Langkah 900, 700, 500, 300, 100, dan 50 TIDAK ada pada palet sumber
     dan diturunkan pada corak yang sama agar tetap satu keluarga.
     ================================================================== */
  --merek-900: #0b2922;   /* diturunkan — dasar bilah sisi, 15,5:1    */
  --merek-800: #123f36;   /* palet sumber — bilah sisi, 11,7:1        */
  --merek-700: #1c5649;   /* diturunkan — kepala tabel & judul, 8,5:1 */
  --merek-600: #2a6b5c;   /* palet sumber — keadaan hover, 6,3:1      */
  --merek-500: #4f9281;   /* diturunkan — cincin fokus & garis tepi   */
  --merek-300: #8cbcae;   /* diturunkan — hijau muda                  */
  --merek-100: #d6e5de;   /* diturunkan — rona & baris total          */
  --merek-50:  #f1f7f4;   /* diturunkan — latar sorotan               */

  --aksen:        #1c5649; /* tombol utama di atas halaman terang     */
  --aksen-600:    #16463b; /* keadaan hover, 10,6:1                   */
  --aksen-700:    #0f332b; /* paling pekat — teks putih aman, 13,7:1  */
  --aksen-50:     #f1f7f4; /* rona hijau pucat                        */
  --aksen-terang: #e8dcc4; /* palet sumber — menu aktif DI ATAS bilah gelap, 11,4:1 */
  --aksen-terang-600: #f1e9d8; /* hover menu aktif                    */

  /* ==================================================================
     EMAS SEMANTIK — bukan alias warna merek, tetapi KINI diambil dari
     palet yang sama.

     --emas dipakai kuning peringatan pada .notif-warn, .lc-kuning,
     .meter.sedang, .skor-2, serta .isi-manual (kuning = AT COST), dan
     juga lencana hitungan pada bilah sisi. Ia tetap berdiri sendiri dari
     --aksen: begitu merek berganti warna, alias akan ikut mengubah
     peringatan dan menghapus artinya.

     Nilainya diselaraskan ke emas palet #c49a45. Nilai sebelumnya
     (#c49a45) hanya terpaut 5,2 derajat corak darinya, dan dua emas yang
     nyaris sama pada satu layar saling meniadakan: mata membacanya
     sebagai warna yang sama tetapi tidak persis, sehingga keduanya
     berhenti berarti apa-apa. Satu emas lebih berguna daripada dua.
     ================================================================== */
  --emas:      #c49a45;   /* palet sumber — peringatan & lencana hitungan */
  --emas-600:  #8a6a20;   /* emas pekat — teks putih aman, 5,0:1      */
  --emas-50:   #faf3e2;   /* rona emas                                */

  /* Biru, bukan teal. Tautan harus terbaca sebagai tautan, dan tautan
     berwarna teal di tengah kerangka teal berhenti terlihat sebagai
     sesuatu yang dapat diklik. */
  --tautan:    #1c6494;   /* 6,4:1 di atas putih                      */

  /* Hijau khusus penanda keberhasilan — bukan warna merek, jadi tidak
     ikut berubah saat tema diganti. */
  --sukses:     #0f9d58;
  --sukses-100: #d9f0e3;
  --sukses-50:  #eff9f3;

  /* Nama lama tetap dipertahankan sebagai alias agar seluruh gaya dan
     gaya sebaris yang sudah ada terus berjalan tanpa perlu diubah. */
  --hijau-900: var(--merek-900);
  --hijau-800: var(--merek-800);
  --hijau-700: var(--merek-700);
  --hijau-600: var(--merek-600);
  --hijau-500: var(--merek-500);
  --hijau-100: var(--merek-100);
  --hijau-50:  var(--merek-50);

  /* Netral abu kehijauan — bodi aplikasi, garis rambut, dan tingkatan teks.
     Nadanya digeser dari biru ke hijau mengikuti merek. Netral yang masih
     bernada biru di tengah kerangka hijau terbaca sebagai kotor, bukan
     sebagai netral; pergeseran sekecil ini tidak terlihat sendirian tetapi
     menyatukan seluruh halaman. */
  --teks:      #1f2422;
  --teks-2:    #4b544f;
  /* Digelapkan agar label kecil menembus ambang keterbacaan 4,5:1 baik di
     atas putih (5,3:1) maupun di atas --latar (4,9:1); kesan redupnya
     tetap terjaga. */
  --teks-3:    #656e69;
  --teks-4:    #9aa29d;
  --garis:     #e5e8e4;
  --garis-2:   #ccd3ce;
  /* Garis KISI TABEL, terpisah dari --garis dan --garis-2.
     Dua garis abu di atas dipakai untuk kartu, kotak isian, dan sekat halaman
     — di sana warna samar memang disengaja. Garis tabel menjalankan tugas yang
     lain: ia memisahkan kolom dan baris data yang harus dapat ditelusuri mata
     dari kiri ke kanan pada tabel selebar lima belas kolom, dan untuk itu
     #e5e8e4 terlalu samar. Satu token tersendiri supaya ketebalannya dapat
     diatur sekali untuk SELURUH tabel — layar maupun cetak — tanpa menyentuh
     garis-garis lain yang bukan kisi tabel. */
  --garis-tabel: #000000;
  /* Warna ISI SEL TABEL. Di luar tabel, --teks (#1f2422) dan --teks-2/-3 tetap
     berlaku: gradasi abu itu yang menata hierarki pada kartu dan halaman. Di
     DALAM tabel hierarki itu tidak diperlukan — yang ada di sana adalah data
     yang dimasukkan unit, dan semuanya setara pentingnya. Satu token
     tersendiri supaya dapat diatur sekali untuk seluruh tabel. */
  --teks-data: #000000;
  --latar:     #f7f8f6;
  --putih:     #ffffff;

  /* Semantik */
  --merah:     #c62828;
  --merah-50:  #fdecec;
  --jingga:    #e07c00;
  --jingga-50: #fff5e6;
  --biru:      #1565c0;
  --biru-50:   #e9f2fc;
  --ungu:      #6a3cb5;
  --ungu-50:   #f2edfb;

  /* Sudut lebih tegas dan bayangan tipis — kedalaman dibentuk garis rambut */
  --radius:    10px;
  --radius-sm: 7px;
  --radius-xs: 5px;
  /* Bayangan ikut bernada hijau. Bayangan abu murni di atas latar hijau
     pucat tampak kelabu dan mati; menariknya ke arah merek membuat kartu
     seolah menumpang pada halaman yang sama, bukan ditempel di atasnya. */
  --bayang:    0 1px 2px rgba(11,41,34,.06);
  --bayang-md: 0 1px 2px rgba(11,41,34,.07), 0 8px 20px -10px rgba(11,41,34,.15);
  --bayang-lg: 0 16px 40px -12px rgba(11,41,34,.20);
  --sidebar:   228px;
  --topbar:    62px;

  /* ==================================================================
     UKURAN HURUF ISI TABEL — satu nilai untuk seluruh sistem.
     Sebelumnya tiap jenis sel memakai ukurannya sendiri: isian .84rem, sel
     baca-saja .81rem, kolom turunan .85rem, kolom nomor .82rem, tabel biasa
     .855rem. Selisih sekecil itu tidak terbaca sebagai tingkatan, hanya
     sebagai ketidakrapian — kolom Deskripsi Kegiatan tampak lebih besar
     daripada tetangganya tanpa alasan. Satu token membuat seluruh sel
     sederajat, dan bila kelak perlu diubah cukup satu baris ini.

     --teks-tabel-kecil khusus KETERANGAN SEKUNDER di dalam sel, misalnya
     jenis unit di bawah namanya atau satuan di sebelah angka target. Itu
     memang harus lebih kecil: ia penjelas, bukan data yang dibandingkan
     antar-baris. Menyamakannya justru menghapus tingkatan yang berguna.
     ================================================================== */
  --teks-tabel:       .84rem;
  --teks-tabel-kecil: .78rem;

  /* ==================================================================
     GERAK — satu lengkung dan tiga lama waktu untuk seluruh sistem.
     Kesan "mahal" pada antarmuka datang dari lengkung perlambatannya,
     bukan dari durasi yang panjang: --lembut memulai cepat lalu melandai
     jauh di ujung, sehingga kursor terasa disambut, bukan disentak.
     Gerak di bawah 150 ms terbaca sebagai kedip; di atas 350 ms terbaca
     sebagai lamban. Ketiganya sengaja berada di antara itu.
     ================================================================== */
  --lembut:    cubic-bezier(.32, .72, 0, 1);
  --cepat:     .18s;
  --sedang:    .26s;
  --lambat:    .42s;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system,
               "Inter", "Helvetica Neue", Arial, sans-serif;
  font-size: 15px;
  line-height: 1.55;
  color: var(--teks);
  background: var(--latar);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Angka selalu rata lebar agar kolom rupiah sejajar sempurna */
.num, .nilai, table td, table th, input[type=number] {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

a { color: var(--tautan); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Judul dirapatkan sedikit — ciri khas tipografi terbitan, bukan bawaan peramban */
h1, h2, h3, h4 {
  margin: 0 0 .5em; line-height: 1.28; font-weight: 640;
  letter-spacing: -.012em; color: var(--teks);
}
h1 { font-size: 1.42rem; letter-spacing: -.018em; }
h2 { font-size: 1.06rem; }
h3 { font-size: .96rem; }

/* Ikon sebaris selalu sejajar dengan teks di sampingnya */
.ikon { flex: 0 0 auto; vertical-align: -.18em; }

/* ==========================================================  Tata letak  */
.tata-letak { display: flex; min-height: 100vh; }

.sisi {
  width: var(--sidebar);
  flex: 0 0 var(--sidebar);
  background: linear-gradient(180deg, var(--hijau-800) 0%, var(--hijau-900) 100%);
  color: #d7e6dc;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

/* ==================================================================
   TINGGI BILAH SISI
   Dengan tiga belas butir menu dalam enam kelompok, isi bilah sisi
   mencapai 932 px pada jendela setinggi 820 px sehingga menu terakhir
   hanya terjangkau dengan menggulir. Yang dipangkas adalah JARAK, bukan
   ukuran huruf: mengecilkan huruf menu membuatnya sulit dibaca, padahal
   sebagian besar tinggi itu sebenarnya ruang kosong. Sesudah dirapatkan
   isinya kembali muat utuh tanpa menggulir.
   ================================================================== */
.sisi-merek {
  display: flex; align-items: center; gap: 11px;
  padding: 12px 18px;
  border-bottom: 1px solid rgba(255,255,255,.1);
}
/* Tanpa latar putih — logo berupa PNG transparan, jadi warna bilah sisi
   terlihat menembus di belakangnya. Bayangan tipis menjaga ketegasan bentuk. */
.sisi-merek img {
  width: 40px; height: 40px; flex: 0 0 40px;
  object-fit: contain;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.35));
}
.sisi-merek .nm {
  font-weight: 700; color: #fff; font-size: 1.02rem;
  letter-spacing: .3px; line-height: 1.2;
}
/* Kapital seluruhnya membuat kalimat empat kata ini pecah menjadi tiga baris
   dan terbaca seperti teriakan; huruf biasa dengan awalan besar lebih ringkas
   sekaligus lebih tenang. Warnanya sengaja satu langkah lebih pekat daripada
   warna menu di bawahnya, tetapi BUKAN --aksen-terang: menu aktif memakai
   nilai itu sebagai latar, dan baris ini akan bertabrakan dengannya. */
.sisi-merek .sub {
  font-size: .72rem; color: var(--merek-100); font-weight: 500;
  letter-spacing: .1px; line-height: 1.3; margin-top: 2px;
}

/* Label kelompok memakan 37 px untuk teks setinggi 10 px, hampir
   seluruhnya jarak atas. Dirapatkan menjadi 24 px; jarak di atas tetap
   lebih besar daripada di bawah supaya label tetap terbaca melekat pada
   kelompok di bawahnya, bukan mengambang di antara keduanya. */
.sisi-grup {
  padding: 11px 18px 3px;
  font-size: .68rem; font-weight: 700; letter-spacing: 1px;
  text-transform: uppercase; color: rgba(255,255,255,.42);
}

.sisi-nav { display: flex; flex-direction: column; padding: 2px 10px; }
.sisi-nav a {
  display: flex; align-items: center; gap: 11px;
  padding: 7px 12px; margin-bottom: 1px;
  border-radius: var(--radius-sm);
  color: #d7e6dc; font-size: .9rem; text-decoration: none;
  transition: background var(--sedang) var(--lembut),
              color var(--sedang) var(--lembut);
}
.sisi-nav a:hover { background: rgba(255,255,255,.09); color: #fff; }
/* Menu aktif berdiri DI ATAS bilah sisi yang gelap, jadi ia memakai
   --aksen-terang, bukan --aksen. --aksen #1c5649 dirancang sebagai unsur
   paling pekat di atas halaman putih; di atas bilah setua ini ia justru
   lenyap. --aksen-terang #e8dcc4 dengan teks --merek-900 mencapai 7,17:1,
   jauh di atas ambang 4,5:1. */
.sisi-nav a.aktif {
  background: var(--aksen-terang); color: var(--merek-900); font-weight: 680;
  box-shadow: 0 2px 8px rgba(0,0,0,.30);
}
.sisi-nav a.aktif .ikon { color: var(--merek-900); }
/* Lencana dibalik di dalam menu aktif yang kini terang: latar gelap, huruf
   terang — 7,17:1. Huruf --aksen di atas --merek-900 menjadi gelap-di-atas-gelap. */
.sisi-nav a.aktif .lencana { background: var(--merek-900); color: var(--aksen-terang); }
.sisi-nav a.aktif .ikon { opacity: 1; }
.sisi-nav .ikon { width: 18px; height: 18px; flex: 0 0 18px; opacity: .75; }
/* Tetap amber: tugasnya lencana hitungan, bukan warna merek. Hurufnya
   digeser ke --merek-900 agar senada dengan bilahnya (4,87:1). */
.sisi-nav .lencana {
  margin-left: auto; background: var(--emas); color: var(--merek-900);
  border-radius: 20px; padding: 1px 8px; font-size: .7rem; font-weight: 700;
}

.sisi-kaki {
  margin-top: auto; padding: 10px 18px;
  border-top: 1px solid rgba(255,255,255,.1);
  font-size: .71rem; color: rgba(255,255,255,.44);
  line-height: 1.45;
}
.sisi-kaki .inst { display: block; color: rgba(255,255,255,.62); }
.sisi-kaki .hak {
  display: block; margin-top: 2px;
  font-size: .67rem; color: rgba(255,255,255,.34);
}

/* ---- Bilah sisi diciutkan: hanya ikon, agar tabel mendapat ruang lebih ---- */
.tata-letak.ringkas .sisi { width: 62px; flex: 0 0 62px; }
.tata-letak.ringkas .sisi-merek { justify-content: center; padding: 16px 0; }
.tata-letak.ringkas .sisi-merek div,
.tata-letak.ringkas .sisi-grup,
.tata-letak.ringkas .sisi-kaki,
.tata-letak.ringkas .sisi-nav a > span:not(.lencana) { display: none; }
.tata-letak.ringkas .sisi-nav { padding: 8px 8px; }
.tata-letak.ringkas .sisi-nav a { justify-content: center; padding: 11px 0; }
.tata-letak.ringkas .sisi-nav .lencana {
  position: absolute; margin: 0; transform: translate(14px, -11px);
  padding: 0 5px; font-size: .62rem;
}
.tata-letak.ringkas .sisi-nav a { position: relative; }

.tombol-ciut {
  background: none; border: 1px solid var(--garis-2); border-radius: 8px;
  cursor: pointer; padding: 6px 8px; color: var(--teks-2);
  display: inline-flex; align-items: center;
}
.tombol-ciut:hover { background: var(--hijau-50); border-color: var(--hijau-500); color: var(--hijau-700); }

.utama { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* ============================================================  Topbar  */
/* Dipatok ke elemen <header>, bukan ke kelas .atas saja. Nama kelas itu juga
   dipakai baris label pada grafik batang, dan selama aturan ini tidak terpatok,
   SETIAP baris grafik ikut mendapat tinggi 62 px, jarak dalam 22 px, latar
   putih, garis bawah, dan position: sticky — sehingga satu baris grafik
   membengkak dari 30 px menjadi 78 px dan labelnya terlempar jauh dari
   batangnya sendiri. */
header.atas {
  height: var(--topbar);
  background: var(--putih);
  border-bottom: 1px solid var(--garis);
  display: flex; align-items: center; gap: 14px;
  padding: 0 22px;
  position: sticky; top: 0; z-index: 30;
}
header.atas .judul { font-weight: 650; font-size: 1.02rem; min-width: 0; }
header.atas .judul small { display: block; font-weight: 400; font-size: .76rem; color: var(--teks-3); }
/* min-width: 0 membatalkan min-width:auto bawaan butir flex. Tanpa itu butir
   ini menolak menyusut di bawah lebar isinya, sehingga pemilih unit selebar
   250px mendorong seluruh halaman melebar dan memunculkan gulir mendatar
   pada layar sempit. */
header.atas .kanan {
  margin-left: auto; display: flex; align-items: center; gap: 12px;
  min-width: 0;
}
header.atas .kanan form { min-width: 0; }
header.atas .kanan .pilih-unit {
  width: 250px; min-width: 0; max-width: 100%;
  font-size: .82rem;
}

.pengguna-chip {
  display: flex; align-items: center; gap: 9px;
  padding: 5px 11px 5px 5px; border-radius: 30px;
  background: var(--hijau-50); border: 1px solid var(--garis);
}
.avatar {
  width: 32px; height: 32px; flex: 0 0 32px; border-radius: 50%;
  background: var(--hijau-700); color: #fff;
  display: grid; place-items: center; font-weight: 700; font-size: .8rem;
}
.pengguna-chip .info { line-height: 1.25; }
.pengguna-chip .info b { font-size: .82rem; display: block; max-width: 190px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pengguna-chip .info span { font-size: .7rem; color: var(--teks-3); }
/* Tanpa baris peran, nama disejajarkan vertikal dengan avatarnya. */
.pengguna-chip .info.satu-baris { display: flex; align-items: center; min-height: 32px; }

.isi { padding: 22px; flex: 1; }

/* ---- Tata letak setinggi layar ----
   Dipakai halaman yang isinya satu lembar kerja besar. Halamannya dikunci
   setinggi jendela dan tidak bergulir; yang bergulir hanya lembarnya. Dengan
   begitu bilah kendali di bawah tabel tetap pada tempatnya, dan tidak ada dua
   batang gulir bersaing di tepi kanan.

   min-height: 0 wajib ada di setiap tingkat. Butir flex secara bawaan menolak
   menyusut di bawah tinggi isinya, jadi tanpa itu rantai tingginya tidak
   pernah sampai ke .lembar dan halaman tetap memanjang seperti semula. */
body.layar-penuh { height: 100vh; overflow: hidden; }
body.layar-penuh .tata-letak { height: 100vh; min-height: 0; }
body.layar-penuh .utama { height: 100vh; min-height: 0; overflow: hidden; }
body.layar-penuh main.isi {
  flex: 1; min-height: 0; overflow: hidden;
  display: flex; flex-direction: column; gap: 0;
  /* Bantalan dipersempit dari 22 px. Pada tata letak yang dikunci setinggi
     layar, setiap piksel bantalan diambil langsung dari tinggi lembarnya. */
  padding: 12px 14px;
}
body.layar-penuh #formLembar {
  display: flex; flex-direction: column;
  flex: 1; min-height: 0;
}
body.layar-penuh .bar-simpan { margin-bottom: 8px; }
/* Bilah terakhir tidak perlu margin bawah: di bawahnya sudah tepi halaman,
   dan margin itu menjadi jalur kosong yang tidak pernah terpakai. */
body.layar-penuh #formLembar > .bar-simpan:last-child { margin-bottom: 0; }
body.layar-penuh .lembar { flex: 1; min-height: 0; max-height: none; }

/* =============================================================  Kartu  */
.kartu {
  background: var(--putih);
  border: 1px solid var(--garis);
  border-radius: var(--radius);
  box-shadow: var(--bayang);
  margin-bottom: 16px;
  transition: box-shadow var(--lambat) var(--lembut),
              border-color var(--lambat) var(--lembut);
}
/* Kartu besar tidak diangkat — hanya bayangannya yang mendalam, dan lebih
   lambat daripada kartu kecil. Bidang selebar layar yang ikut bergeser
   terbaca goyah, bukan mewah. */
.kartu:hover { box-shadow: var(--bayang-md); border-color: var(--garis-2); }
.kartu-kepala {
  padding: 14px 18px; border-bottom: 1px solid var(--garis);
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.kartu-kepala h2 { margin: 0; font-size: .98rem; letter-spacing: -.01em; }
.kartu-kepala .ket { font-size: .79rem; color: var(--teks-3); margin: 2px 0 0; }
.kartu-kepala .aksi { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }
.kartu-isi { padding: 18px; }
.kartu-isi.rapat { padding: 0; }

/* ==========================================================  Statistik  */
.grid-stat {
  display: grid; gap: 10px; margin-bottom: 12px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
/* ---- Kartu ringkasan ----
   Kartu-kartu ini bukan lima hal yang tak berhubungan: biasanya satu angka
   induk disusul pecahannya. Karena itu warnanya memakai SATU keluarga yang
   bergradasi — hijau tua ke hijau merek ke teal — bukan pelangi. Pelangi membuat tiap
   kartu berteriak sendiri-sendiri dan hubungan antar-angkanya hilang.
   Ronanya sangat tipis dan rata, bukan sapuan diagonal, supaya angkanya yang
   menonjol dan kartunya tetap terbaca tenang. */
/* Kartu berlatar putih polos. Warnanya tinggal satu titik kecil di samping
   label — cukup untuk membedakan kartu sekilas, tanpa rona latar yang membuat
   deretan kartu terlihat ramai.

   Tata letaknya petak dua baris: label membentang penuh di baris pertama,
   lalu angka dan keterangannya BERDAMPINGAN di baris kedua. Sebelumnya
   keterangan berdiri sebagai baris ketiga dan menambah tinggi tanpa perlu. */
.stat {
  --stat-warna: #1c5649;   /* titik penanda dan angka */

  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "label label" "nilai ket";
  align-items: baseline; column-gap: 9px; row-gap: 3px;
  align-content: center;

  background: var(--putih); border: 1px solid var(--garis);
  border-radius: var(--radius); padding: 10px 14px;
  min-height: 62px;
  transition: box-shadow var(--sedang) var(--lembut),
              border-color var(--sedang) var(--lembut),
              transform var(--sedang) var(--lembut);
}
.stat .label { grid-area: label; }
.stat .nilai { grid-area: nilai; }
.stat .ket   { grid-area: ket; }
/* Isi lain — misalnya batang serapan — membentang penuh di bawah keduanya. */
.stat > *:not(.label):not(.nilai):not(.ket) { grid-column: 1 / -1; }
/* Terangkat satu piksel saja. Lebih dari itu dan kartu terbaca melompat;
   satu piksel dengan bayangan yang ikut melebar sudah cukup membuat kursor
   terasa diikuti. */
.stat:hover {
  border-color: var(--garis-2);
  box-shadow: var(--bayang-md);
  transform: translateY(-1px);
}

.stat .label {
  display: flex; align-items: center; gap: 7px;
  font-size: .67rem; font-weight: 600; color: #545e58;
  text-transform: uppercase; letter-spacing: .06em; line-height: 1.2;
}
/* Titik penanda — satu-satunya warna yang tersisa pada kartu. */
.stat .label::before {
  content: ""; flex: 0 0 6px; width: 6px; height: 6px; border-radius: 50%;
  background: var(--stat-warna);
}

/* ---- Ragam warna ----
   Tiap ragam menetapkan empat nilai: sepasang untuk palang (tua→muda) dan
   sepasang untuk latar (berwarna→pucat), ditambah warna angkanya. Warna angka
   selalu jauh lebih gelap daripada latarnya — seluruh pasangan di bawah ini
   diukur dan berada di atas 6:1, jauh melampaui ambang AA 4,5:1.
   Kelima ragam pertama membentuk satu putaran nada berdekatan, sehingga
   deretan kartu terbaca sebagai satu keluarga, bukan pelangi.

   Dua ragam digeser setelah merek menjadi teal. Zamrud dinaikkan
   kejenuhannya agar tidak tinggal beberapa derajat corak dari merek. Dan
   toska digeser jauh ke arah biru: dahulu ia dibedakan dari merek yang
   navy, tetapi setelah merek sendiri menjadi teal, coraknya hanya terpaut
   dua belas derajat dan kedua kartu berhenti dapat dibedakan. Nama kelasnya
   dibiarkan supaya tidak ada templat yang perlu ikut disunting. */
.stat.induk {                                   /* teal paling tua — angka utama */
  --stat-warna: #123f36; --stat-tua: #123f36; --stat-muda: #2a6b5c;
  --stat-rona: #e3ece7; --stat-pudar: #f7f8f6;
}
.stat.biru  {                                   /* teal merek */
  --stat-warna: #1c5649; --stat-tua: #2a6b5c; --stat-muda: #8cbcae;
  --stat-rona: #f1f7f4; --stat-pudar: #f4f9f6;
}
.stat.toska {                                   /* biru — sengaja jauh dari merek */
  --stat-warna: #0f5470; --stat-tua: #1a7093; --stat-muda: #5fb4d4;
  --stat-rona: #dcedf6; --stat-pudar: #f4fafd;
}
.stat.hijau {                                   /* zamrud */
  --stat-warna: #06663c; --stat-tua: #0a8a4c; --stat-muda: #2ecc7a;
  --stat-rona: #d9f5e4; --stat-pudar: #f6fdf9;
}
.stat.ungu  {                                   /* lembayung */
  --stat-warna: #4a3399; --stat-tua: #5b3fc4; --stat-muda: #9b80f5;
  --stat-rona: #ece6fb; --stat-pudar: #faf8ff;
}
.stat.emas  {                                   /* hanya untuk sorotan */
  --stat-warna: #7d4f08; --stat-tua: #a5680f; --stat-muda: #eab551;
  --stat-rona: #fdf0dc; --stat-pudar: #fffbf4;
}
.stat.merah {                                   /* hanya untuk masalah */
  --stat-warna: #93281f; --stat-tua: #b3352a; --stat-muda: #ec7263;
  --stat-rona: #fde8e6; --stat-pudar: #fff8f7;
}

/* Warna cadangan bila kartu tidak menyebut ragamnya: melangkah sepanjang
   keluarga yang sama menurut urutan. Dibungkus :where() supaya kekhususannya
   nol — dengan begitu kelas ragam yang tersurat di atas selalu menang, tak
   peduli urutan penulisannya. Pemilih :not([class*=" "]) yang dipakai
   sebelumnya rapuh: satu spasi ekor pada class="stat " sudah menggagalkannya. */
:where(.grid-stat > .stat):nth-child(5n+1) {
  --stat-warna: #123f36; --stat-tua: #123f36; --stat-muda: #2a6b5c;
  --stat-rona: #e3ece7; --stat-pudar: #f7f8f6;
}
:where(.grid-stat > .stat):nth-child(5n+2) {
  --stat-warna: #1c5649; --stat-tua: #2a6b5c; --stat-muda: #8cbcae;
  --stat-rona: #f1f7f4; --stat-pudar: #f4f9f6;
}
:where(.grid-stat > .stat):nth-child(5n+3) {
  --stat-warna: #125a5f; --stat-tua: #17757c; --stat-muda: #4fb8b4;
  --stat-rona: #ddf1ef; --stat-pudar: #f3fcfa;
}
:where(.grid-stat > .stat):nth-child(5n+4) {
  --stat-warna: #06663c; --stat-tua: #0a8a4c; --stat-muda: #2ecc7a;
  --stat-rona: #d9f5e4; --stat-pudar: #f6fdf9;
}
:where(.grid-stat > .stat):nth-child(5n+5) {
  --stat-warna: #4a3399; --stat-tua: #5b3fc4; --stat-muda: #9b80f5;
  --stat-rona: #ece6fb; --stat-pudar: #faf8ff;
}

.stat .nilai {
  font-size: 1.32rem; font-weight: 680; color: var(--stat-warna);
  margin: 0; line-height: 1.15; letter-spacing: -.03em; white-space: nowrap;
}
.stat .nilai.kecil { font-size: 1.02rem; letter-spacing: -.018em; }
/* Keterangan duduk sebaris dengan angkanya, rata dasar huruf. */
.stat .ket { font-size: .72rem; color: #545e58; margin: 0; line-height: 1.3; }
/* Lencana di dalam keterangan kartu diciutkan. Ukuran bakunya dirancang untuk
   sel tabel; di sini ia meninggikan barisnya sendiri, dan karena tinggi baris
   grid mengikuti kartu tertinggi, satu lencana membuat empat kartu ikut naik. */
.stat .ket .lc { padding: 1px 6px; font-size: .68rem; line-height: 1.3; vertical-align: baseline; }
/* Batang serapan dipindah menjadi strip di dasar kartu, bukan baris tambahan
   di bawah teksnya. Dahulu ia memakai mt12 (12 px) yang dirancang untuk badan
   halaman; satu kartu memakainya dan keempat kartu ikut meninggi, sebab tinggi
   baris grid mengikuti kartu tertinggi. Sebagai strip ia tidak menambah tinggi
   sama sekali, dan bacaannya justru lebih jelas karena membentang penuh. */
.stat .meter {
  position: absolute; left: 0; right: 0; bottom: 0;
  margin: 0; height: 4px; border-radius: 0;
}

/* =============================================================  Tabel  */
.tabel-bungkus { overflow-x: auto; border-radius: var(--radius); }
table.tabel { width: 100%; border-collapse: collapse; font-size: var(--teks-tabel); }
/* Kisi penuh: tiap sel bergaris di keempat sisinya, sehingga kolom terpisah
   tegas dan bingkai luar tabel tertutup. Sebelumnya hanya ada garis BAWAH —
   tidak ada satu pun garis tegak — jadi pada tabel selebar lima belas kolom
   mata harus menebak sendiri sel mana milik kolom mana. Dengan
   border-collapse: collapse, garis sel yang bersebelahan dilebur menjadi satu,
   jadi kisinya tetap setebal 1 px, bukan 2 px. */
table.tabel th, table.tabel td {
  padding: 9px 11px; text-align: left;
  border: 1px solid var(--garis-tabel); vertical-align: top;
}
/* Kepala tabel tanpa blok warna — cukup label kecil dan satu garis rambut */
/* Kepala tabel berhijau pekat dengan huruf putih — 7,3:1, jauh di atas
   ambang 4,5:1. */
table.tabel thead th {
  background: var(--merek-700); color: #fff;
  font-weight: 600; font-size: .7rem; text-transform: uppercase; letter-spacing: .07em;
  position: sticky; top: 0; z-index: 2; white-space: nowrap;
  padding-top: 12px; padding-bottom: 11px;
  /* Kisi kepala tabel digambar dengan box-shadow, BUKAN border. Pada sel yang
     position: sticky dan tabel ber-border-collapse: collapse, peramban tidak
     menggambar bordernya sama sekali begitu sel itu menempel — kisinya akan
     hilang persis ketika tabel digulir, yaitu saat paling dibutuhkan.
     box-shadow tidak ikut dilebur border-collapse dan tetap tergambar. */
  border: 0;
  box-shadow: inset -1px 0 0 var(--garis-tabel), inset 0 -1px 0 var(--garis-tabel);
}
/* Judul kolom ditengahkan mendatar DAN tegak.
   Kelas .num dan .ctr ikut disebut di sini bukan karena lupa: keduanya
   mematok perataan untuk th maupun td sekaligus, dan kekhususannya (0,2,2)
   mengalahkan "table.tabel thead th" (0,1,3) — tanpa penyebutan ulang,
   judul VOLUME, FREKWENSI, HARGA SATUAN, dan JUMLAH akan tetap rata kanan
   mengikuti angkanya, sementara judul lain sudah di tengah.
   Yang ditengahkan hanya JUDULNYA; isi selnya tetap rata kiri dan rata atas,
   sebab kalimat panjang yang ditengahkan jauh lebih sulit dibaca. */
table.tabel thead th,
table.tabel thead th.num,
table.tabel thead th.ctr {
  text-align: center;
  vertical-align: middle;
}
table.tabel thead tr.kelompok th {
  background: var(--hijau-700); color: #fff; text-align: center; top: 0;
}
table.tabel thead tr.kelompok + tr th { top: 33px; }
table.tabel tbody tr { transition: background var(--sedang) var(--lembut); }
table.tabel tbody tr:hover { background: #f7f8f6; }
/* Baris total. Dahulu hanya "tbody tr.total" yang disebut, sedangkan baris
   jumlah pada lembar Monev dan Pemeriksaan Komite berada di dalam <tfoot> —
   sehingga keduanya tidak pernah bergaya sama sekali dan terbaca sebagai baris
   data biasa. Kedua tempat kini disebut bersama.
   Tebalnya 600, bukan 700: yang boleh paling menonjol dalam tabel adalah
   kepala kolom dan kepala kelompok, bukan angka di kakinya. */
table.tabel tbody tr.total,
table.tabel tfoot tr.total { background: var(--hijau-100); font-weight: 600; }
table.tabel tbody tr.total td,
table.tabel tfoot tr.total td { border-top: 2px solid var(--hijau-500); }
table.tabel td.num, table.tabel th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.tabel td.ctr, table.tabel th.ctr { text-align: center; }
/* Kolom CACAH — volume dan frekuensi. Ditengahkan mendatar dan tegak, berbeda
   dari kolom .num yang tetap rata kanan.

   Alasannya bukan selera: angka UANG dibandingkan menurut nilai tempatnya —
   ribuan harus sejajar ribuan — dan itu hanya terjadi bila rata kanan. Volume
   dan frekuensi bukan uang melainkan cacah satu-dua digit; dirata-kanankan, ia
   menempel jauh dari judulnya sendiri dan menggantung di puncak sel yang
   tingginya ditentukan kalimat panjang di kolom sebelah. */
/* Baris jumlah per program: menutup blok baris satu program, bukan baris data.
   Dibedakan oleh latar tipis dan garis atas, bukan oleh ketebalan huruf saja —
   pada tabel berkisi hitam, tebal huruf saja tidak cukup membedakannya dari
   baris item di atasnya. Latarnya lebih muda daripada baris TOTAL di kaki
   tabel supaya keduanya tidak tertukar. */
table.tabel tbody tr.jumlah-program > td {
  background: var(--hijau-50);
  font-weight: 650;
  border-top: 2px solid var(--garis-tabel);
  padding-top: 6px; padding-bottom: 6px;
}
table.tabel tbody tr.jumlah-program > td.rata-kanan {
  font-weight: 600; letter-spacing: .02em;
}

table.tabel td.cacah, table.tabel th.cacah,
table.xl td.cacah, table.xl th.cacah {
  text-align: center;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* ISI selnya rata ATAS, sejajar dengan baris pertama kalimat di kolom
   sebelahnya. Sebelumnya ditengahkan tegak, dan pada baris yang tingginya
   ditentukan kalimat panjang — satu KPI dapat setinggi dua belas baris —
   angka dua digit itu melayang di tengah ruang kosong, jauh dari kalimat yang
   ia jelaskan. JUDUL kolomnya tetap di tengah tegak, sebab kepala tabel memang
   diminta tertengahkan atas-bawah. */
table.tabel td.cacah, table.xl td.cacah { vertical-align: top; }
table.tabel th.cacah, table.xl th.cacah { vertical-align: middle; }
table.tabel .kecil { font-size: var(--teks-tabel-kecil); color: var(--teks-3); }
table.tabel.padat th, table.tabel.padat td { padding: 6px 9px; }

/* ============================================================
   ISI SEL TABEL DITULIS HITAM

   Yang dihitamkan hanya ISI SEL — bukan kepala tabel (putih di atas hijau),
   bukan lencana status, bukan tombol, dan bukan tautan. Ketiganya terakhir
   memakai warna sebagai ARTI: hijau "terima", merah "tolak", hijau merek
   "ini dapat diklik". Menghitamkannya akan menghapus keterangan, bukan
   memperjelas.

   Kelas .kecil dan .lemah disebut ulang di sini karena keduanya mematok
   warna abu dengan kekhususan (0,2,1); tanpa penyebutan ulang, keterangan
   sekunder di dalam sel — kode program, aktivitas, tanggal, baseline, KPI —
   akan tetap abu sementara teks di sebelahnya sudah hitam. Ukuran hurufnya
   TIDAK diubah: yang membedakan keterangan sekunder kini ukurannya saja. */
table.tabel tbody td,
table.tabel tfoot td,
/* Bentuk ELEMEN dan bentuk KETURUNAN keduanya disebut: .kecil dan .lemah
   kadang menempel pada <td>-nya sendiri — kolom Waktu Pelaksanaan begitu —
   dan kadang pada <span> di dalamnya. Pemilih keturunan saja melewatkan yang
   pertama, dan satu kolom tertinggal abu sendirian di antara yang hitam. */
table.tabel tbody td.kecil,
table.tabel tbody td.lemah,
table.tabel tfoot td.kecil,
table.tabel tbody td .kecil,
table.tabel tbody td .lemah,
table.tabel tbody td .nilai-medan,
table.tabel tbody td .nilai-aktivitas,
table.tabel tbody td .aktivitas-rab,
table.tabel tbody td .saran-teks,
table.tabel tbody td .no-program,
table.tabel tbody td .no-aktivitas,
table.tabel tbody td code {
  color: var(--teks-data);
}

/* Ringkasan: satu baris = satu item RAB, sehingga satu program menempati
   beberapa baris berturut-turut. Dua aturan di bawah inilah yang membuat
   kelompok baris itu terbaca.

   Aktivitas item menumpang di bawah nama programnya, digeser masuk dan
   bergaris tegak supaya terbaca sebagai rincian milik program di atasnya,
   bukan sebagai program lain yang berdiri sendiri. */
table.tabel .aktivitas-rab {
  display: block; margin-top: 4px; padding-left: 9px;
  border-left: 2px solid var(--garis-2);
  font-size: var(--teks-tabel-kecil); color: var(--teks-3);
}
/* Baris pertama tiap program diberi garis atas yang lebih tegas daripada garis
   antar-baris biasa. Tanpa ini, 3.312 baris terbaca sama derajatnya dan batas
   antar-program hanya ditandai oleh sel yang kebetulan kosong. */
/* Batas antar-program dibuat 2 px, sebab sejak kisinya hitam seluruh baris
   sudah bergaris 1 px hitam — garis 1 px lagi tidak akan membedakan apa pun. */
table.tabel tbody tr.awal-program > td { border-top: 2px solid var(--garis-tabel); }

/* Kolom yang dipersempit sampai selebar judulnya.

   overflow-wrap:anywhere wajib ada, bukan hiasan: dalam tata letak tabel
   otomatis peramban TIDAK PERNAH menyempitkan kolom di bawah lebar kata
   terpanjang di dalamnya, sehingga tanpa aturan ini lebar yang ditulis pada
   kolomnya diabaikan diam-diam. Dipakai "anywhere" dan bukan "break-word"
   karena hanya "anywhere" yang ikut mengecilkan lebar min-content; itulah
   perbedaan yang menentukan di sini.

   Isi selnya dipangkas tiga baris. Pada kolom selebar 44 px, satu kalimat KPI
   87 aksara akan menjadi belasan baris dan menyeret tinggi seluruh barisnya;
   teks utuhnya tetap terbaca dari atribut title saat disinggung tetikus. */
/* Sel keputusan komite di dalam baris tabel: lencana status, lalu tiga tombol
   berdampingan di bawahnya.

   Ketiganya tampil BERGARIS, dan hanya keputusan yang sedang berlaku yang
   berlatar penuh. Memberi warna penuh pada ketiganya sekaligus — seperti pada
   kartu Pemeriksaan Komite, tempatnya memang hanya ada satu baris tombol —
   akan menaruh tiga blok warna pekat pada SETIAP baris tabel, dan ketika
   semuanya menonjol tidak ada lagi yang menonjol. Warnanya sendiri sama persis
   dengan tombol pada kartu itu, supaya keduanya terbaca sebagai tindakan yang
   sama. */
.putus { display: inline-flex; flex-direction: column; align-items: center; gap: 5px; }
.putus-lencana { white-space: normal; line-height: 1.25; }
.putus-tombol { display: inline-flex; gap: 3px; }
.putus-tombol .btn { padding: 3px 6px; line-height: 1; background: var(--putih); }
.putus-tombol .btn-terima { color: #0f7a45;      border-color: #a8d8bf; }
.putus-tombol .btn-revisi { color: #8a6a20;      border-color: #e3cf9a; }
.putus-tombol .btn-bahaya { color: var(--merah); border-color: #f0c8c8; }
.putus-tombol .btn-terima:hover, .putus-tombol .btn-terima.aktif {
  background: #0f7a45; color: #fff; border-color: #0f7a45;
}
.putus-tombol .btn-revisi:hover, .putus-tombol .btn-revisi.aktif {
  background: #8a6a20; color: #fff; border-color: #8a6a20;
}
.putus-tombol .btn-bahaya:hover, .putus-tombol .btn-bahaya.aktif {
  background: #b3352a; color: #fff; border-color: #b3352a;
}
/* Baris yang sedang menunggu jawaban peladen tidak boleh diketuk dua kali. */
.putus[data-sibuk="1"] .putus-tombol { opacity: .5; pointer-events: none; }

/* Dokumen laporan: tombol, lencana status, dan tautan berkasnya ditumpuk
   di bawah tombol keputusan komite pada sel yang sama. */
.laporan {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  margin-top: 7px; padding-top: 7px; border-top: 1px dashed var(--garis-2);
}
.laporan .laporan-buka { padding: 3px 8px; white-space: nowrap; }
.laporan .laporan-status { white-space: normal; line-height: 1.25; }
.laporan .laporan-tautan { text-decoration: underline; }
.laporan[data-sibuk="1"] { opacity: .55; pointer-events: none; }

/* Kotak status di dalam penyunting laporan. */
.lap-status {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 9px 11px; border: 1px solid var(--garis); border-radius: var(--radius-sm);
  background: var(--latar);
}
/* Kotak yang dikunci bagi pembaca tanpa wewenang. .terkunci dikecualikan
   karena kekhususan pemilih ini (1,1,1) mengalahkan .isi-auto (0,1,0),
   sehingga tanpa pengecualian itu hijau "otomatis" tidak akan pernah tampak
   pada kotak tanggal. */
#tiraiLaporan input[readonly]:not(.terkunci), #tiraiLaporan textarea[readonly] {
  background: var(--latar); cursor: default;
}
#tiraiLaporan textarea { width: 100%; resize: vertical; }

/* Tanggal unggah terisi sendiri dari tanggal peladen. Kotaknya dibuat jelas
   BUKAN tempat mengetik — tanpa pembeda ini pengguna akan mencoba mengubahnya
   lalu menyangka aplikasinya macet.

   Latarnya memakai token yang SAMA dengan .isi-auto ("hijau = otomatis"),
   tetapi disetel di sini karena .isi-auto sendiri (0,1,0) kalah khusus
   terhadap aturan dasar input[type="text"] (0,1,1) dan karena itu tidak
   pernah tampak pada sebuah <input>. Kelas .isi-auto tetap dipasang pada
   elemennya sebagai penanda makna. */
#tiraiLaporan input.terkunci {
  background: var(--hijau-50);
  border-style: dashed;
  color: var(--teks-data);
  font-weight: 600;
  cursor: default;
}
#tiraiLaporan input.terkunci:focus { outline: none; box-shadow: none; }

/* Tabel yang tingginya ribuan piksel — Ringkasan satu unit dapat mencapai
   12.942 px. Bilah geser MENDATAR sebuah kotak selalu duduk di dasar kotak
   itu, jadi untuk menggeser tabel ke kanan orang harus turun dua belas ribu
   piksel lebih dahulu, menggeser, lalu naik lagi.

   Dengan tingginya dibatasi, tabel bergulir di dalam kotaknya sendiri: bilah
   geser mendatar tinggal tetap di bawah layar, kepala kolom yang memang sudah
   sticky menempel di atas, dan baris TOTAL menempel di kaki. Tidak ada
   JavaScript sama sekali.

   200 px adalah tinggi kepala halaman, bilah ringkas, dan keterangan di bawah
   tabel. Batas bawah 320 px dipasang pada max() dan BUKAN sebagai min-height:
   yang perlu dijaga adalah batas atasnya agar pada layar pendek kotak ini
   tidak menyusut sampai tinggal dua baris, sedangkan min-height justru akan
   memaksa kotak setinggi 320 px juga pada unit yang hanya punya dua program —
   menyisakan ruang kosong yang tidak ada gunanya. */
.tabel-bungkus.beku {
  max-height: max(320px, calc(100vh - 200px));
  overflow: auto;
}
/* Latar ditulis ulang PADA SEL, bukan dibiarkan diwarisi dari barisnya:
   elemen sticky melepaskan diri dari aliran normal, dan latar yang hanya
   dipasang pada <tr> tidak ikut tercetak di belakangnya — barisnya akan
   tembus pandang dan isi tabel terbaca menumpuk di baliknya.

   KISINYA pun digambar box-shadow, bukan border — persis alasan yang sudah
   ditulis pada kepala tabel di atas, dan persis cacat yang sama: pada sel
   yang position: sticky di dalam tabel ber-border-collapse: collapse,
   peramban TIDAK menggambar bordernya sama sekali. Garisnya memang ada pada
   gaya terhitung (2px/1px/1px/1px), jadi memeriksanya lewat getComputedStyle
   tidak akan memperlihatkan apa pun — yang hilang penggambarannya.

   Akibatnya baris TOTAL tampil sebagai pita hijau polos tanpa satu pun garis
   tegak, sementara baris jumlah per program tepat di atasnya bergaris
   lengkap. Dua baris berdampingan dengan kisi yang berbeda itulah yang
   terbaca sebagai "garis tabel berantakan".

   Bayangannya menggambar empat sisi: garis hijau 2px di atas (pengganti
   border-top yang menandai baris jumlah), garis kisi di kanan dan bawah.
   Sel PERTAMA mendapat tambahan garis kiri supaya bingkai tabel tertutup;
   sel lain tidak, sebab garis kiri mereka sudah digambar sebagai garis kanan
   sel sebelumnya — kalau keduanya dipasang, kisinya menebal jadi 2px. */
.tabel-bungkus.beku table.tabel tfoot tr.total td {
  position: sticky; bottom: 0; z-index: 3;
  background: var(--hijau-100);
  border: 0;
  box-shadow: inset 0 2px 0 var(--hijau-500),
              inset -1px 0 0 var(--garis-tabel),
              inset 0 -1px 0 var(--garis-tabel);
}
.tabel-bungkus.beku table.tabel tfoot tr.total td:first-child {
  box-shadow: inset 0 2px 0 var(--hijau-500),
              inset 1px 0 0 var(--garis-tabel),
              inset -1px 0 0 var(--garis-tabel),
              inset 0 -1px 0 var(--garis-tabel);
}

/* Tombol sunting narasi program: duduk tetap di pojok kanan atas sel Nama
   Program, bukan mengikuti akhir teksnya. Nama program panjangnya 98 aksara
   rata-rata dan sampai 615; tombol yang mengekor teks akan berpindah-pindah
   tempat dari baris ke baris dan menjadi mustahil ditemukan dengan cepat. */
table.tabel td.nama-sel { position: relative; padding-right: 24px; }
.sunting-narasi {
  position: absolute; top: 7px; right: 5px; line-height: 0;
  padding: 2px; border-radius: 5px; color: var(--teks-3);
  border: 1px solid transparent;
}
/* Tombol sunting aktivitas menempel pada barisnya sendiri, sebab satu sel
   dapat memuat satu nama program dan satu aktivitas sekaligus — dua objek
   berbeda yang tidak boleh tertukar tombolnya. */
.sunting-aktivitas {
  display: inline-block; margin-left: 5px; vertical-align: -2px;
  line-height: 0; padding: 1px; border-radius: 4px;
  color: var(--teks-3); border: 1px solid transparent;
}
.sunting-narasi:hover, .sunting-narasi:focus-visible,
.sunting-aktivitas:hover, .sunting-aktivitas:focus-visible {
  color: var(--merek-700); background: var(--merek-50); border-color: var(--garis-2);
}
.nama-sel[data-sibuk="1"], .aktivitas-rab[data-sibuk="1"] { opacity: .55; }
#tiraiNarasi textarea, #tiraiAktivitas textarea { width: 100%; resize: vertical; }

/* Sel saran perbaikan. Pemangkasan tiga barisnya DICABUT: seluruh narasi kini
   ditampilkan utuh di dalam sel, bukan disembunyikan di balik tooltip. Tombol
   suntingnya duduk di kanan atas sel supaya tidak ikut bergeser turun
   mengikuti panjang teks. */
.saran { display: block; position: relative; padding-right: 22px; }
.saran-teks {
  display: block; line-height: 1.4;
  /* Baris baru dihormati di sini, bukan diubah menjadi <br> oleh PHP: sesudah
     disimpan, app.js menulis ulang sel ini dengan textContent. */
  white-space: pre-line;
}
.saran-sunting {
  position: absolute; top: 0; right: 0; line-height: 0;
  padding: 2px; border-radius: 5px; color: var(--teks-3);
  border: 1px solid transparent;
}
.saran-sunting:hover, .saran-sunting:focus-visible {
  color: var(--merek-700); background: var(--merek-50); border-color: var(--garis-2);
}
.saran[data-sibuk="1"] { opacity: .55; }
/* Penyunting saran memakai tirai yang sama dengan lembar RAB. */
#tiraiSaran textarea { width: 100%; resize: vertical; }

/* ============================================================
   SELURUH NARASI DITAMPILKAN, DIRATAKAN KIRI-KANAN

   Kelas .sempit (memenggal kata) dan .pangkas/.pangkas-4 (memangkas tiga atau
   empat baris) DICABUT seluruhnya. Keduanya dahulu diperlukan untuk menahan
   kolom tetap sempit; sekarang yang diminta kebalikannya — tiap kalimat
   terbaca utuh di dalam selnya.

   Dua akibat yang perlu diketahui sebelum salah satunya dikembalikan:
   - Kolom yang isinya panjang kini menentukan tinggi barisnya sendiri. Satu
     saran perbaikan 2.621 aksara akan menjadi baris yang sangat tinggi.
   - Tanpa izin memenggal kata, kolom tidak dapat lagi lebih sempit daripada
     kata terpanjang di dalamnya: Baseline dan PIC melebar sendiri sampai
     lantainya.

   Perataan kiri-kanan hanya dikenakan pada sel yang isinya KALIMAT. Sel angka
   (.num) dan sel bertengah (.ctr) dikecualikan oleh kekhususannya sendiri —
   "table.tabel td.num" (0,2,2) mengalahkan aturan di bawah (0,1,3) — jadi
   rupiah tetap rata kanan dan lencana tetap di tengah tanpa perlu disebut. */
table.tabel tbody td {
  text-align: justify;
  text-justify: inter-word;
}
/* Baris terakhir sebuah paragraf tidak ikut direnggangkan — itu perilaku
   bawaan justify dan memang yang dikehendaki. */

/* Kolom No pada Ringkasan memuat dua jenis penanda yang tidak boleh tertukar:
   nomor PROGRAM dan huruf AKTIVITAS di bawahnya. Nomornya ditebalkan dan
   berwarna normal, hurufnya dibiarkan pucat dan digeser masuk sedikit —
   sehingga satu pandang pada kolom paling kiri sudah cukup untuk melihat di
   mana satu program mulai dan berapa aktivitas yang menumpang padanya. */
.no-program   { font-weight: 650; color: var(--teks-2); }
.no-aktivitas { color: var(--teks-3); font-size: .9em; padding-left: 6px; }

/* Kartu yang isinya tabel ringkas ikut menyempit dan berdiri di tengah, supaya
   yang terlihat adalah satu panel utuh yang disengaja — bukan tabel sempit
   yang mengambang di dalam kotak selebar layar. */
.kartu-ringkas {
  max-width: 1330px;
  margin-inline: auto;
}

/* Baris pemisah kelompok di dalam tabel: menandai awal satu fakultas, biro,
   atau lembaga. Dibuat rata kiri dan berlatar tipis supaya terbaca sebagai
   sekat, bukan sebagai baris data yang ikut dibandingkan angkanya. */
table.tabel tbody tr.baris-kelompok > td {
  background: var(--merek-50);
  border-top: 1px solid var(--garis-2);
  border-bottom: 1px solid var(--garis-2);
  padding-top: 9px; padding-bottom: 9px;
  /* Pita aksen di tepi kiri: penanda awal kelompok yang terbaca sekilas tanpa
     menambah satu huruf pun, dan tetap terlihat andai warna latar hilang.
     6,3:1 di atas --merek-50, jauh di atas ambang 3:1 untuk unsur non-teks. */
  box-shadow: inset 3px 0 0 var(--aksen);
}
table.tabel tbody tr.baris-kelompok:hover > td { background: var(--merek-50); }
table.tabel tbody tr.baris-kelompok:first-child > td { border-top: 0; }
.baris-kelompok .nm {
  font-weight: 700; color: var(--merek-700); font-size: .83rem;
}
.baris-kelompok .rinci {
  margin-left: 10px; font-size: .76rem; color: var(--teks-3);
  font-variant-numeric: tabular-nums;
}
.baris-kelompok .rinci b { color: var(--jingga); font-weight: 650; }

/* Angka yang masih menunggu diperiksa dibedakan oleh warna, bukan ketebalan.
   Ketika puluhan baris sama-sama tebal, tidak ada satu pun yang menonjol dan
   tebalnya justru menghapus batas antar kelompok. */
.perlu-periksa { color: var(--jingga); }

/* Keadaan kosong: ikon garis dalam bingkai lembut, bukan emoji */
.kosong {
  padding: 46px 22px; text-align: center; color: var(--teks-3);
  font-size: .87rem; line-height: 1.6;
}
.kosong .lambang {
  width: 46px; height: 46px; margin: 0 auto 13px;
  display: grid; place-items: center;
  border: 1px solid var(--garis-2); border-radius: 12px;
  background: var(--latar); color: var(--teks-4);
}
.kosong b { display: block; color: var(--teks); font-size: .95rem; margin-bottom: 3px; font-weight: 620; }

/* =============================================================  Tombol */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  padding: 8px 14px; font-size: .85rem; font-weight: 600; font-family: inherit;
  cursor: pointer; text-decoration: none; line-height: 1.35;
  letter-spacing: -.005em; white-space: nowrap;
  transition: background var(--cepat) var(--lembut),
              border-color var(--cepat) var(--lembut),
              color var(--cepat) var(--lembut),
              box-shadow var(--cepat) var(--lembut),
              transform var(--cepat) var(--lembut);
}
.btn:hover { text-decoration: none; }
/* Tekanan dibuat lebih dalam daripada angkatannya supaya klik terasa
   menjawab; keduanya memakai lengkung yang sama agar satu bahasa. */
.btn:active { transform: translateY(1px); transition-duration: .06s; }
.btn:focus-visible { outline: 2px solid var(--hijau-500); outline-offset: 2px; }
.btn .ikon { width: 15px; height: 15px; }
/* Tombol utama berdiri DI ATAS HALAMAN PUTIH, jadi ia memakai --aksen yang
   pekat dengan huruf PUTIH — 7,3:1. Huruf --merek-900 di atasnya adalah
   gelap-di-atas-gelap dan tidak terbaca. Menu aktif di bilah sisi memakai
   --aksen-terang; keduanya tetap satu tindakan, hanya dibalik terangnya
   mengikuti latar tempatnya berdiri. */
.btn-utama   { background: var(--aksen); color: #fff; font-weight: 650;
               box-shadow: 0 1px 2px rgba(11,41,34,.18); }
.btn-utama:hover { background: var(--aksen-600); color: #fff; }
.btn-aksen   { background: var(--merek-700); color: #fff; }
.btn-aksen:hover { background: var(--merek-600); color: #fff; }
.btn-emas    { background: var(--aksen); color: #fff; }
.btn-emas:hover { background: var(--aksen-600); color: #fff; }
.btn-garis   { background: var(--putih); color: var(--hijau-700); border-color: var(--garis-2); }
.btn-garis:hover { background: var(--hijau-50); border-color: var(--hijau-500); color: var(--hijau-800); }
.btn-bahaya  { background: var(--putih); color: var(--merah); border-color: #f0c8c8; }
.btn-bahaya:hover { background: var(--merah-50); }
.btn-kecil   { padding: 5px 10px; font-size: .78rem; }
.btn:disabled, .btn.mati { opacity: .5; pointer-events: none; }

/* ---- Tombol bertanda warna menurut keluarannya ----
   Sebelumnya seluruh tombol sekunder berwarna sama, sehingga "Ekspor Excel"
   dan "Cetak PDF" hanya dapat dibedakan dengan membaca tulisannya. Kini
   masing-masing memakai warna lazim berkasnya — hijau untuk Excel, merah
   untuk PDF — sehingga dikenali sekilas. Isiannya sengaja bernada lembut,
   bukan blok warna penuh, supaya tidak merebut perhatian dari tombol utama. */
/* Rona hijaunya dinaikkan kejenuhannya setelah merek menjadi hijau: nilai
   lamanya #eaf6ee praktis tidak dapat dibedakan dari --merek-50 #f1f7f4,
   sehingga tombol Excel terbaca sebagai sorotan merek, bukan sebagai warna
   berkasnya sendiri. Hurufnya tetap 6,1:1 di atas rona baru. */
.btn-excel { background: #e4f7ea; color: #10683a; border-color: #a9dcbd; }
.btn-excel:hover { background: #d2f0de; border-color: #10683a; color: #0b4d2a; }

.btn-cetak { background: #fdeceb; color: #a3271f; border-color: #f2c4c0; }
.btn-cetak:hover { background: #fadedb; border-color: #a3271f; color: #7f1d17; }

.btn-saring { background: var(--merek-700, #1c5649); color: #fff; border-color: transparent; }
.btn-saring:hover { background: var(--merek-600, #2a6b5c); color: #fff; }

/* ==========================================================  Formulir  */
.form-baris { margin-bottom: 15px; }
.form-grid  { display: grid; gap: 15px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.form-grid.dua { grid-template-columns: repeat(2, 1fr); }
label.fl { display: block; font-size: .81rem; font-weight: 600; color: var(--teks-2); margin-bottom: 5px; }
label.fl .wajib { color: var(--merah); }
.bantuan { font-size: .76rem; color: var(--teks-3); margin-top: 4px; line-height: 1.45; }

input[type=text], input[type=password], input[type=number], input[type=date],
input[type=email], input[type=search], select, textarea {
  width: 100%; padding: 9px 11px;
  border: 1px solid var(--garis-2); border-radius: var(--radius-sm);
  font-family: inherit; font-size: .88rem; color: var(--teks);
  background: var(--putih); transition: border-color .13s, box-shadow .13s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--hijau-500);
  box-shadow: 0 0 0 3px rgba(101,146,135,.28);
}
input:disabled, select:disabled, textarea:disabled { background: #f2f5f3; color: var(--teks-3); }
textarea { resize: vertical; min-height: 78px; line-height: 1.5; }
select { appearance: none; background-image:
  url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%234a5a50' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center; background-size: 11px; padding-right: 30px; }

/* Warna isian mengikuti konvensi berkas Excel */
.isi-unit   { border-left: 3px solid var(--biru); }      /* biru = diisi unit    */
.isi-auto   { background: var(--hijau-50); color: var(--teks-2); } /* hijau = otomatis */
.isi-manual { background: var(--emas-50); border-color: var(--emas-600); } /* kuning = AT COST */
.isi-galat  { background: var(--merah-50); border-color: var(--merah); }

/* ===========================================================  Lencana  */
/* Lencana persegi bersudut lembut — lebih tenang dibaca di dalam tabel
   dibanding pil bulat penuh, dan sejajar rapi antar-baris. */
.lc {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 8px; border-radius: var(--radius-xs);
  font-size: .71rem; font-weight: 620; white-space: nowrap; line-height: 1.5;
  letter-spacing: .005em;
  border: 1px solid rgba(0,0,0,.04);
}
.pri-p1    { background: var(--merah-50);  color: var(--merah); }
.pri-p2    { background: var(--jingga-50); color: var(--jingga); }
.pri-p3    { background: #e8eee9;          color: var(--teks-2); }
.pri-rutin { background: var(--biru-50);   color: var(--biru); }
.pri-nr    { background: var(--ungu-50);   color: var(--ungu); }

.lc-hijau  { background: var(--sukses-100); color: #0a6b3d; }
.lc-biru   { background: var(--biru-50);   color: var(--biru); }
.lc-kuning { background: var(--emas-50);   color: #8a6a20; }
.lc-merah  { background: var(--merah-50);  color: var(--merah); }
.lc-abu    { background: #e8eee9;          color: var(--teks-2); }
.lc-ungu   { background: var(--ungu-50);   color: var(--ungu); }

/* ===========================================================  Notifikasi */
.notif {
  display: flex; gap: 11px; align-items: flex-start;
  padding: 12px 15px; border-radius: var(--radius-sm);
  margin-bottom: 14px; font-size: .86rem; line-height: 1.55;
  border: 1px solid transparent;
}
.notif > .ikon { flex: 0 0 auto; margin-top: 1.5px; opacity: .85; }
.notif b { font-weight: 650; }
.notif-ok    { background: var(--sukses-50); border-color: #bde3ce; color: #0a6b3d; }
.notif-galat { background: var(--merah-50);  border-color: #f2c4c4; color: #8c1f1f; }
.notif-warn  { background: var(--emas-50);   border-color: #f0dd8a; color: #6f5700; }
.notif-info  { background: var(--biru-50);   border-color: #bcd6f2; color: #0d47a1; }
.notif .tutup { margin-left: auto; background: none; border: 0; cursor: pointer;
                font-size: 1.1rem; color: inherit; opacity: .55; line-height: 1; }
.notif .tutup:hover { opacity: 1; }

/* ==============================================================  Meter  */
.meter { height: 8px; background: #e5ebe6; border-radius: 20px; overflow: hidden; }
.meter > span { display: block; height: 100%; background: var(--merek-500); border-radius: 20px; }
.meter.lebih > span { background: var(--merah); }
.meter.sedang > span { background: var(--emas-600); }

/* ==================================================  Grafik  ==============
   Seluruh grafik digambar sebagai SVG atau elemen biasa — tanpa pustaka luar.
   ========================================================================== */
.grafik-kosong {
  padding: 34px 16px; text-align: center;
  color: var(--teks-3); font-size: .85rem;
}

/* Susunan dua grafik berdampingan yang menumpuk sendiri pada layar sempit. */
.grid-grafik {
  display: grid; gap: 16px; margin-bottom: 16px;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
}

/* Dua bagian halaman yang disandingkan kiri-kanan, masing-masing lengkap
   dengan judul bagiannya sendiri. Ambangnya 460 px — lebih lebar daripada
   .grid-grafik — karena salah satu sisinya memuat tabel lima kolom yang
   menjadi sesak bila dipaksa lebih sempit daripada itu.
   Kedua kartu dibuat SAMA TINGGI supaya tepi bawahnya lurus. Grid hanya
   meregangkan kolomnya, bukan kartunya; karena itu tiap kolom dijadikan flex
   menegak dan kartunya diberi flex: 1 — tanpa itu kartu yang pendek berhenti
   di tinggi isinya dan menyisakan bidang kosong yang tepinya tidak sejajar. */
.grid-dua {
  display: grid; gap: 16px 18px; margin-bottom: 16px;
  grid-template-columns: repeat(auto-fit, minmax(460px, 1fr));
  align-items: stretch;
}
.grid-dua > div { display: flex; flex-direction: column; min-width: 0; }
.grid-dua > div > .kartu { flex: 1; margin-bottom: 0; }
/* Judul bagian di dalam kolom tidak perlu jarak atas sebesar di aliran utama:
   ia sudah menjadi unsur pertama kolomnya. */
.grid-dua > div > .judul-bagian:first-child { margin-top: 4px; }

/* Penanda bagian: memecah halaman panjang menjadi beberapa babak bernomor
   supaya urutan bacanya jelas. Garis tipis menyambung ke tepi kanan agar
   pembatasnya terasa tanpa perlu latar atau bingkai tambahan. */
.judul-bagian {
  display: flex; align-items: center; gap: 12px;
  margin: 26px 0 13px;
}
.judul-bagian:first-child { margin-top: 4px; }
.judul-bagian span {
  font-size: .74rem; font-weight: 700; color: var(--teks-3);
  text-transform: uppercase; letter-spacing: .07em; white-space: nowrap;
}
.judul-bagian::after {
  content: ""; flex: 1; height: 1px; background: var(--garis);
}

/* Judul kecil di atas sebuah grafik yang berdiri di dalam kartu bersama. */
.judul-grafik {
  margin: 0 0 14px; font-size: .74rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--teks-3);
}

/* ---- Donat ---- */
.grafik-donat { display: block; margin: 0 auto; }
.grafik-donat circle { transition: stroke-width .15s ease; }
.grafik-donat circle:hover { stroke-width: 32; }
.grafik-donat .angka-pusat {
  font-size: 30px; font-weight: 680; fill: var(--teks);
  letter-spacing: -.03em; dominant-baseline: middle;
}
.grafik-donat .angka-pusat.ringkas { font-size: 21px; }
.grafik-donat .ket-pusat {
  font-size: 11px; fill: var(--teks-3); letter-spacing: .04em;
  text-transform: uppercase; font-weight: 600;
}

.grafik-legenda { list-style: none; margin: 16px 0 0; padding: 0; }
.grafik-legenda li {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 0; border-bottom: 1px solid var(--garis);
  font-size: .83rem; color: var(--teks-2);
}
.grafik-legenda li:last-child { border-bottom: 0; }
.grafik-legenda li.nol { opacity: .45; }
.grafik-legenda i {
  width: 10px; height: 10px; border-radius: 3px; flex: 0 0 10px;
  border: 1px solid rgba(0,0,0,.06);
}
.grafik-legenda .nm { flex: 1; }
.grafik-legenda b { color: var(--teks); font-weight: 680; }
.grafik-legenda em {
  font-style: normal; color: var(--teks-3); font-size: .78rem;
  min-width: 42px; text-align: right;
}

/* ---- Batang mendatar ---- */
.grafik-batang { display: grid; gap: 14px; }
.grafik-batang .atas {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 10px; margin-bottom: 6px; font-size: .83rem; color: var(--teks-2);
}
.grafik-batang .nilai { color: var(--teks); font-weight: 650; white-space: nowrap; }
.grafik-batang .nilai em { font-style: normal; color: var(--teks-3); font-weight: 400; }
.grafik-batang .jalur {
  height: 10px; border-radius: 6px; background: var(--garis); overflow: hidden;
}
.grafik-batang .jalur > span {
  display: block; height: 100%; border-radius: 6px;
  transition: width .45s cubic-bezier(.3,.8,.4,1);
}

/* ---- Kolom tegak ---- */
.grafik-kolom {
  display: flex; align-items: flex-end; gap: 4px;
  position: relative; padding-bottom: 2px;
}
.grafik-kolom .kolom {
  display: flex; flex-direction: column; align-items: center;
  justify-content: flex-end; height: 100%; gap: 6px;
}
.grafik-kolom .nilai {
  font-size: .74rem; font-weight: 650; color: var(--teks-2);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.grafik-kolom .bar {
  width: 72%; max-width: 54px; border-radius: 6px 6px 0 0;
  transition: height .45s cubic-bezier(.3,.8,.4,1), filter .15s ease;
}
.grafik-kolom .kolom:hover .bar { filter: brightness(1.12); }
.grafik-kolom .label {
  font-size: .73rem; color: var(--teks-3); text-align: center;
  line-height: 1.3; min-height: 26px;
}
.grafik-kolom .dasar {
  position: absolute; left: 0; right: 0; bottom: 26px;
  border-bottom: 1px solid var(--garis-2);
}

/* ==============================================  Rekap progres unit  */
/* Nama unit yang belum mengisi, sebagai tautan pintas */
.daftar-chip { display: flex; flex-wrap: wrap; gap: 7px; }
.daftar-chip .chip {
  display: inline-block; padding: 5px 11px;
  border: 1px solid var(--garis-2); border-radius: 20px;
  background: var(--putih); color: var(--teks-2);
  font-size: .79rem; line-height: 1.4; text-decoration: none;
  transition: border-color .13s ease, background .13s ease, color .13s ease;
}
.daftar-chip .chip:hover {
  border-color: var(--merek-500); background: var(--merek-50);
  color: var(--merek-800); text-decoration: none;
}

/* Chip dipecah per jenis unit; tiap kelompok diberi kepala kecil sendiri. */
.kelompok-chip + .kelompok-chip { margin-top: 15px; }
.kelompok-chip .kepala {
  display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
  font-size: .78rem; font-weight: 650; color: var(--teks-2);
}

.skor-titik {
  display: inline-grid; place-items: center;
  width: 26px; height: 26px; border-radius: 50%;
  font-size: .78rem; font-weight: 700; color: #fff;
}
.skor-4 { background: var(--sukses); }
.skor-3 { background: var(--biru); }
.skor-2 { background: var(--emas-600); }
.skor-1 { background: var(--jingga); }
.skor-0 { background: var(--merah); }
/* Titik "belum ada skor" berlatar paling pucat, jadi huruf putih bawaan
   .skor-titik lenyap di atasnya (1,5:1). Hurufnya digelapkan — 5,3:1. */
.skor-x { background: #ccd3ce; color: var(--teks-2); }

/* =================================================  Monitoring & Evaluasi
   Lembar ini mudah disalahpahami karena tiga kolomnya tidak boleh diisi:
   capaian, skor, dan status semuanya turunan dari angka triwulan. Dahulu
   ketiganya tampak persis sama dengan kolom isian di sebelahnya, sehingga
   pengisi mengira kolom itu rusak saat diklik dan tidak menerima apa pun.
   Sekarang beda tugas itu dinyatakan lewat warna: kolom isian berlatar
   putih, kolom turunan berlatar abu dan tidak menerima kursor teks.
   ----------------------------------------------------------------------- */
table.tabel thead tr.kelompok th.kel-isi  { background: var(--merek-600); }
table.tabel thead tr.kelompok th.kel-auto { background: #5a6b63; }

table.tabel thead th.kol-auto { background: #5a6b63; }

table.tabel tbody td.sel-auto {
  background: var(--latar);
  cursor: default;
}
/* Sorotan baris tidak boleh menghapus penanda abu ini, jika tidak kolom
   turunan akan tampak dapat diisi setiap kali kursor melintas. */
table.tabel tbody tr:hover td.sel-auto { background: #eaf1ec; }

table.tabel tbody td.sel-isi  { background: var(--putih); }

/* Isian dipadatkan supaya 20 baris program tetap muat dalam satu layar.
   Ukurannya dahulu ditulis sebagai gaya sebaris pada tiap elemen; dipindah
   ke sini agar dapat dikalahkan aturan responsif pada layar sempit. */
td.sel-isi input,
td.sel-isi textarea {
  padding: 5px 7px; font-size: var(--teks-tabel);
}
td.sel-isi input { text-align: right; }
td.sel-isi textarea { min-height: 44px; line-height: 1.4; }
td.sel-isi input::placeholder,
td.sel-isi textarea::placeholder { color: var(--teks-4); }

/* Nilai beserta satuannya dalam satu baris. Satuannya dibuat lebih kecil dan
   redup supaya angkanya tetap yang pertama terbaca. */
.nilai-satuan { white-space: nowrap; }
.nilai-satuan .satuan {
  font-size: var(--teks-tabel-kecil); color: var(--teks-3); margin-left: 3px; font-weight: 400;
}

/* Urutan langkah pengisian, dipadatkan menjadi satu baris di bawah judul. */
.alur-isi {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  margin-top: 6px; font-size: .76rem; color: var(--teks-3);
}
.alur-isi span { display: flex; align-items: center; gap: 6px; }
.alur-isi b {
  display: inline-grid; place-items: center;
  width: 17px; height: 17px; border-radius: 50%;
  /* --merek-700 di atas --merek-100 hanya 4,47:1 — meleset tipis dari ambang
     4,5:1 untuk huruf sekecil ini. --merek-800 mencapai 7,4:1. */
  background: var(--merek-100); color: var(--merek-800);
  font-size: .68rem; font-weight: 700;
}

/* ============================================================  Langkah */
.langkah { display: flex; gap: 0; margin-bottom: 18px; flex-wrap: wrap; }
.langkah .ln {
  flex: 1; min-width: 150px; padding: 11px 14px 11px 26px;
  background: var(--putih); border: 1px solid var(--garis);
  position: relative; font-size: .83rem; color: var(--teks-3);
}
.langkah .ln:first-child { border-radius: var(--radius) 0 0 var(--radius); padding-left: 16px; }
.langkah .ln:last-child  { border-radius: 0 var(--radius) var(--radius) 0; }
.langkah .ln::after {
  content: ""; position: absolute; right: -11px; top: 50%; z-index: 2;
  width: 20px; height: 20px; margin-top: -10px; transform: rotate(45deg);
  background: var(--putih); border-right: 1px solid var(--garis); border-top: 1px solid var(--garis);
}
.langkah .ln:last-child::after { display: none; }
.langkah .ln.lewat { background: var(--hijau-700); color: #fff; border-color: var(--hijau-700); }
.langkah .ln.lewat::after { background: var(--hijau-700); border-color: var(--hijau-700); }
/* --hijau-500 hanya 3,49:1 terhadap huruf putih; langkah berjalan diturunkan
   ke --hijau-600 (5,4:1) dan tetap terbedakan dari langkah lewat oleh
   terangnya sendiri ditambah tebal hurufnya. */
.langkah .ln.kini { background: var(--hijau-600); color: #fff; border-color: var(--hijau-600); font-weight: 600; }
.langkah .ln.kini::after { background: var(--hijau-600); border-color: var(--hijau-600); }
.langkah .ln b { display: block; font-size: .72rem; opacity: .8; text-transform: uppercase; letter-spacing: .5px; }

/* =============================================================  Modal  */
.tirai {
  position: fixed; inset: 0; background: rgba(11,41,34,.5);
  display: none; align-items: flex-start; justify-content: center;
  padding: 34px 16px; z-index: 100; overflow-y: auto;
}
.tirai.buka { display: flex; }
.modal {
  background: var(--putih); border-radius: var(--radius);
  width: 100%; max-width: 900px; box-shadow: var(--bayang-lg);
  animation: naik .18s ease-out;
}
.modal.sempit { max-width: 520px; }
@keyframes naik { from { opacity: 0; transform: translateY(-12px); } to { opacity: 1; transform: none; } }
.modal-kepala {
  padding: 16px 20px; border-bottom: 1px solid var(--garis);
  display: flex; align-items: center; gap: 12px;
}
.modal-kepala h2 { margin: 0; font-size: 1.02rem; }
.modal-kepala .tutup {
  margin-left: auto; background: none; border: 0; font-size: 1.5rem;
  cursor: pointer; color: var(--teks-3); line-height: 1; padding: 0 4px;
}
.modal-isi { padding: 20px; max-height: 68vh; overflow-y: auto; }
.modal-kaki {
  padding: 14px 20px; border-top: 1px solid var(--garis);
  display: flex; gap: 9px; justify-content: flex-end; background: #f7f8f6;
  border-radius: 0 0 var(--radius) var(--radius);
}

/* =========================================================  Pencarian  */
.cari-sbm { position: relative; }
.cari-hasil {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 50;
  background: var(--putih); border: 1px solid var(--garis-2);
  border-radius: var(--radius-sm); box-shadow: var(--bayang-lg);
  max-height: 320px; overflow-y: auto; display: none;
}
.cari-hasil.buka { display: block; }
.cari-hasil .item { padding: 9px 12px; cursor: pointer; border-bottom: 1px solid var(--garis); font-size: .83rem; }
.cari-hasil .item:last-child { border-bottom: 0; }
.cari-hasil .item:hover, .cari-hasil .item.sorot { background: var(--hijau-50); }
.cari-hasil .item .ur { font-weight: 600; }
.cari-hasil .item .mt { font-size: .75rem; color: var(--teks-3); margin-top: 2px; }
.cari-hasil .item .hg { color: var(--hijau-700); font-weight: 700; }
.cari-hasil .kosong-hasil { padding: 16px; text-align: center; color: var(--teks-3); font-size: .85rem; }

/* ====================================================  Lembar kerja ala Excel
   Dipakai pada halaman Program Kerja: satu baris = satu program, seluruh sel
   dapat langsung diketik tanpa berpindah halaman.
   Warna huruf mengikuti konvensi berkas Excel:
     biru  = diisi unit      hijau = tautan otomatis      hitam = hasil formula
   ========================================================================== */
.lembar {
  border: 1px solid var(--garis-2);
  border-radius: var(--radius);
  overflow: auto;
  /* Kepala halaman kini hanya bilah ringkas + bilah kendali, jadi lembarnya
     boleh mengambil ruang yang dahulu dipakai kartu identitas. */
  max-height: calc(100vh - 215px);
  background: var(--putih);
  position: relative;
}

/* Ukuran lembar sengaja dipadatkan. Sebelumnya satu baris program dapat
   setinggi 190 px, sehingga layar 768 px hanya memuat tiga baris dan
   membandingkan program satu dengan lainnya berarti menggulir terus-menerus.
   Yang dikecilkan hanya ukuran huruf dan jarak dalam sel — bukan lebar kolom —
   supaya teksnya tetap utuh dan tidak ada yang perlu digulir mendatar lebih
   jauh daripada sebelumnya. */
table.xl {
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--teks-tabel);
  table-layout: fixed;
  width: max-content;
  min-width: 100%;
}

table.xl th, table.xl td {
  border-right: 1px solid var(--garis-tabel);
  border-bottom: 1px solid var(--garis-tabel);
  padding: 0;
  vertical-align: middle;
  background: var(--putih);
}

/* ---- Isi sel rata ATAS, kepala tetap di tengah ----
   Dahulu seluruh sel ditengahkan atas-bawah meniru perataan bawaan Excel. Itu
   masuk akal ketika tiap sel berisi satu baris, dan berhenti masuk akal sejak
   pasTinggi() tidak lagi memangkas tinggi sel: satu kolom beruraian panjang
   kini dapat menjulang belasan baris, dan SELURUH sel lain pada baris itu ikut
   setinggi dirinya. Dengan perataan tengah, isi sel pendek — nomor, prioritas,
   satuan, angka triwulan — melayang di tengah ruang kosong, jauh dari baris
   yang ia jelaskan, sehingga mata harus mencarinya baris demi baris.

   Rata atas membuat seluruh isi satu baris berangkat dari garis yang sama,
   dan itulah yang membuat baris terbaca sebagai satu kesatuan.

   Hanya tbody yang diubah. KEPALA kolom (thead) tetap di tengah tegak: judul
   dua baris seperti "Lama Pekerjaan (satuan jam)" dan "TW1 Sep–Nov" memang
   dirancang tertengahkan pada baris kepala setinggi tetap. Baris jumlah
   (tfoot) juga dibiarkan, sebab isinya hanya satu baris.

   Aturan ini menang atas "table.xl th, table.xl td" di atas karena
   KEKHUSUSANNYA lebih tinggi — (0,1,3) lawan (0,1,2), sebab ia menyebut satu
   elemen lebih banyak — bukan karena urutannya. Jadi ia tetap berlaku di mana
   pun ia diletakkan, dan tidak dapat dibatalkan hanya dengan memindahkannya.
   Yang akan membatalkannya adalah menambahkan 'tbody' pada aturan di atas. */
table.xl tbody td { vertical-align: top; }

/* ---- Dua baris kepala yang menempel saat digulir ----
   Dahulu tiga baris, dengan baris huruf kolom ala Excel setinggi 23 px di
   paling atas. Baris itu dihapus, jadi nilai "top" kedua baris sisanya WAJIB
   ikut dikurangi 23 px — kalau tidak, baris grup menggantung 23 px di bawah
   tepi atas saat digulir dan baris kepala menindihnya. */
table.xl thead th { position: sticky; z-index: 6; }
table.xl thead tr.grup th {
  top: 0; height: 30px;
  background: var(--hijau-700); color: #fff;
  font-size: .78rem; font-weight: 650; text-align: center;
  letter-spacing: .3px; padding: 0 6px;
  border-right: 1px solid var(--garis-tabel);
}
table.xl thead tr.kepala th {
  top: 30px; height: 44px;
  background: var(--hijau-50); color: var(--hijau-800);
  font-size: .81rem; font-weight: 650; text-align: center;
  padding: 6px 7px; line-height: 1.3;
  border-bottom: 2px solid var(--garis-tabel);
}

/* ---- Kolom nomor yang menempel di kiri ---- */
table.xl .beku {
  position: sticky; left: 0; z-index: 4;
  background: var(--latar);
  border-right: 2px solid var(--garis-tabel);
  text-align: center; font-weight: 650; color: var(--teks-data);
  width: 40px; min-width: 40px; font-size: var(--teks-tabel);
}
/* Nomor baris TIDAK ditebalkan — hanya judul "No" di kepala tabel yang tebal.
   Angka urut bukan isi yang perlu ditonjolkan; menebalkannya membuat kolom
   paling kiri berteriak lebih keras daripada data di sebelahnya, padahal ia
   sekadar penunjuk tempat. */
table.xl tbody .beku { font-weight: 400; }
table.xl thead .beku { z-index: 7; }
table.xl tbody tr:hover .beku { background: var(--hijau-100); }

/* ---- Sel ---- */
table.xl td.sel { padding: 3px 3px; }
table.xl tbody tr { min-height: 34px; }
table.xl tbody tr:hover td { background: #f7f8f6; }

table.xl input[type=text],
table.xl input[type=number],
table.xl select,
table.xl textarea {
  width: 100%;
  border: 1px solid transparent; border-radius: 4px;
  background: transparent;
  padding: 5px 7px; font-family: inherit; font-size: var(--teks-tabel);
  line-height: 1.36; resize: none; display: block;
}
table.xl input[type=text],
table.xl input[type=number],
table.xl select { height: 32px; }

/* Isi kotak teks diratakan kiri-kanan, searah dengan sel .baca di sebelahnya.
   Yang berlaku hanya pada kotak BERBARIS BANYAK: pada input satu baris,
   justify tidak berpengaruh apa pun karena baris terakhir — satu-satunya
   baris — memang tidak pernah direnggangkan.

   Kotak ANGKA dikecualikan di bawah: nilainya sudah ditengahkan atau
   dirata-kanankan, dan justify akan membatalkannya. */
table.xl textarea,
table.xl input[type=text] {
  text-align: justify;
  text-justify: inter-word;
}

/* Tinggi kotak teks mengikuti isinya, lalu DIRATAKAN KE ATAS oleh sel induknya
   (lihat "table.xl tbody td" di atas). Dahulu ditengahkan, dan tingginya
   dahulu dibatasi pasTinggi() di app.js — kedua hal itu sudah tidak berlaku:
   pasTinggi() kini menumbuhkan kotak setinggi seluruh isinya tanpa batas. */
table.xl textarea { height: auto; min-height: 32px; overflow: hidden; }
table.xl textarea:focus { min-height: 88px; }

/* ---- Panel penyaring Rekap per Fakultas ----
   Seluruh pilihan tampil sekaligus, tidak disembunyikan di balik daftar pilih
   bertingkat: pimpinan lazim memadukan beberapa saringan dalam satu tarikan,
   dan pilihan yang terlihat lebih cepat dibaca daripada yang harus dibuka. */
.saring-rekap { margin-bottom: 12px; }
.saring-grid {
  display: grid; gap: 14px 20px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.pilih-banyak {
  display: flex; flex-wrap: wrap; gap: 4px 10px;
  max-height: 104px; overflow-y: auto;
  padding: 2px 2px 2px 0;
}
.pilih-banyak .cek {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .79rem; color: var(--teks-2); cursor: pointer;
  white-space: nowrap; margin: 0;
}
.pilih-banyak .cek input { width: auto; margin: 0; }
.baris-tanggal { display: flex; align-items: center; gap: 7px; }
.baris-tanggal input[type=date] { margin: 0; width: auto; flex: 1 1 0; min-width: 0; }
.saring-aksi {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--garis);
}
.angka-besar {
  font-size: 1.12rem; font-weight: 700; color: var(--merek-700, #1c5649);
  font-variant-numeric: tabular-nums;
}

/* Rincian unit di dalam baris fakultas pada laporan beranda. */
.baris-anak {
  display: flex; align-items: baseline; gap: 10px;
  padding: 3px 0 3px 14px; font-size: var(--teks-tabel);
  border-left: 2px solid var(--garis-2);
}
.baris-anak + .baris-anak { border-top: 1px dashed var(--garis); }
.baris-anak .dorong-kanan { margin-left: auto; font-variant-numeric: tabular-nums; }

/* Daftar pilihan program: lebarnya mengikuti ruang yang tersisa, karena
   daftar yang dibentangkan peramban selebar kotaknya sendiri — kotak sempit
   berarti nama program terpotong betapa pun panjangnya teks yang dikirim. */
.pilih-program {
  flex: 1 1 460px; min-width: 300px; max-width: 900px;
  font-size: .8rem; margin: 0;
}

/* ---- Keterangan ringkas di dalam bilah kendali ---- */
.rk-blok { display: flex; align-items: baseline; gap: 6px; min-width: 0; font-size: .82rem; }
.rk-blok b { font-size: .92rem; color: var(--teks); }
.rk-label {
  font-size: .68rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--teks-3); white-space: nowrap;
}
.rk-saring .rk-label { display: inline-flex; align-items: center; gap: 5px; }
.rk-lemah { color: var(--teks-3); white-space: nowrap; }

/* Meter Non-Renop diciutkan menjadi batang pendek di dalam barisnya. */
.rk-nr .meter { width: 74px; height: 5px; margin: 0 0 0 2px; align-self: center; }
.rk-nr.lebih b { color: var(--merah); }

.rk-saring {
  display: flex; align-items: center; gap: 6px; flex-wrap: nowrap;
  padding-left: 14px; border-left: 1px solid var(--garis);
}
.rk-saring input[type=date] {
  height: 28px; margin: 0; width: auto; font-size: .76rem; padding: 2px 5px;
}

/* Kotak pencarian program. Lebarnya menyusut sendiri pada layar sempit supaya
   tidak mendorong tombol Ekspor dan Cetak keluar dari bilah; .rk-saring memakai
   flex-wrap: nowrap, jadi kotak berlebar tetap akan merusak barisnya. */
.rk-saring .rk-cari {
  height: 28px; margin: 0; font-size: .78rem; padding: 2px 8px;
  width: clamp(130px, 17vw, 240px); min-width: 0;
}
.rk-saring .btn { padding: 4px 8px; }
.rk-saring .rk-label { display: inline-flex; align-items: center; color: var(--merek-700, #1c5649); }

/* ---- Tanggal pelaksanaan ----
   Jumlah tanggal per program bebas, dan SEL INILAH yang sebenarnya menentukan
   tinggi baris lembar — bukan kolom teksnya. Satu program dengan lima tanggal
   menumpuk lima kotak ke bawah dan mendorong seluruh baris menjadi 205 px,
   sementara kotak teks terpanjang di baris yang sama hanya 130 px.

   Karena itu kotaknya kini MENGALIR dua per baris, bukan bertumpuk satu
   kolom: lima tanggal menjadi tiga baris, bukan lima. Lebar kolomnya pada
   colgroup di rkat.php ikut dilebarkan supaya dua kotak benar-benar muat.

   Tanggal bertanda .perkiraan berasal dari alih jadwal triwulan lama dan
   diberi warna pengingat supaya terlihat mana yang belum dipersempit unit. */
table.xl td.sel-tanggal { padding: 3px; }
/* Yang menjadi kotak flex adalah PEMBUNGKUS di dalam sel, bukan <td>-nya.
   Sebuah td yang dijadikan kotak flex berhenti meregang setinggi barisnya,
   dan karena garis sel digambar pada kotak td itu, garis kolom ini akan
   putus di tengah baris. */
.sel-tanggal > .daftar-tgl {
  display: flex; flex-wrap: wrap; gap: 3px; align-items: flex-start;
}
/* Satu kotak tanggal per baris. Dahulu dua per baris supaya baris tidak
   menjulang, dan kolomnya harus 270 px untuk itu. Kolomnya kini dipersempit
   atas permintaan, dan pada lebar itu dua kotak berdampingan akan memotong
   tampilan tanggalnya sendiri — peramban menyembunyikan ikon kalender lalu
   memotong tahunnya. Satu per baris selalu terbaca utuh. */
table.xl .sel-tanggal input[type=date] {
  flex: 1 1 100%; min-width: 0; width: auto;
  height: 24px; padding: 1px 3px; font-size: var(--teks-tabel-kecil);
  font-variant-numeric: tabular-nums;
}
.sel-tanggal input[type=date].perkiraan {
  background: #fff8e6; border-color: #e6c77a; color: #7a5a00;
}
.tambah-tanggal {
  align-self: flex-start;
  border: 1px dashed var(--garis-2); border-radius: 4px; background: transparent;
  padding: 1px 7px; font: inherit; font-size: .72rem; color: var(--teks-3);
  cursor: pointer; line-height: 1.5;
}
.tambah-tanggal:hover { border-color: var(--merek-500, #4f9281); color: var(--merek-700, #1c5649); }

/* Pada formulir rinci kotaknya lebih lega daripada di dalam sel lembar. */
.daftar-tanggal { max-width: 260px; }
.daftar-tanggal input[type=date] { height: 38px; margin: 0; }

/* Aturan "table.xl textarea.terpangkas" DIBUANG bersama pemangkasannya.
   Dahulu sel lembar yang isinya terpotong dipudarkan di tepi bawah sebagai
   penanda bahwa masih ada lanjutannya. Sejak pasTinggi() di app.js tidak lagi
   memangkas apa pun, kelas itu tidak pernah dipasang lagi di lembar — dan
   aturan yang tidak pernah berlaku hanya menyesatkan penyunting berikutnya,
   yang akan mengira sel di sini masih dipotong.

   Pudar serupa MASIH dipakai pada kotak telaah Pemeriksaan Komite
   (.putus-telaah textarea.terpangkas, lihat jauh di bawah) — di sana
   pemangkasannya memang masih ada. */

/* ---- Penyembunyi kolom lembar kerja ----
   Panelnya mengambang di atas tabel, bukan mendorongnya: lembar ini sudah
   sangat lebar, dan panel yang menyisipkan diri ke dalam aliran akan membuat
   tabelnya melompat setiap kali dibuka. */
.pilih-kolom { position: relative; display: inline-block; }
.pilih-kolom .cacah-kolom { font-size: .72rem; color: var(--teks-3); margin-left: 3px; }
.panel-kolom {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30;
  width: 320px; max-height: 60vh; overflow-y: auto;
  background: var(--putih); border: 1px solid var(--garis-2);
  border-radius: var(--radius-sm); padding: 12px 14px;
  box-shadow: 0 10px 28px -8px rgba(11,41,34,.22);
}
.panel-kolom-kepala {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 9px;
}
.panel-kolom-isi { display: flex; flex-direction: column; gap: 2px; margin-bottom: 9px; }
.cek-kolom {
  display: flex; align-items: center; gap: 8px;
  font-size: .79rem; color: var(--teks-2); cursor: pointer;
  padding: 3px 4px; border-radius: 5px; margin: 0;
}
.cek-kolom:hover { background: var(--merek-50); }
.cek-kolom input { width: auto; margin: 0; }
/* Kolom No dan Aksi tidak dapat dimatikan — ditandai pudar, bukan
   disembunyikan dari daftar, supaya pembacanya tahu keduanya memang ada. */
.cek-kolom.terkunci { color: var(--teks-3); cursor: default; }
.cek-kolom.terkunci:hover { background: none; }

table.xl input:hover,
table.xl select:hover,
table.xl textarea:hover { border-color: var(--garis-2); }
table.xl input:focus,
table.xl select:focus,
table.xl textarea:focus {
  outline: 0;
  border-color: var(--hijau-500);
  box-shadow: 0 0 0 2px rgba(101,146,135,.30);
  background: #fff;
}
/* Jarak kiri daftar-pilih dirapatkan dari 11 px menjadi 6 px. Lebar sebuah
   daftar-pilih ditentukan PILIHAN TERPANJANG ditambah jarak dalam dan ruang
   panah — memangkas jarak dalamnya memberi 5 px kembali ke setiap kolom
   daftar-pilih tanpa memotong satu pilihan pun. */
table.xl select {
  padding-left: 6px; padding-right: 22px;
  background-position: right 6px center; background-size: 10px;
}

/* Kode Renop ditengahkan. Isinya kode berformat tetap sepanjang 13 aksara,
   jadi rata tengah membuat seluruh kolom sejajar rapi; rata kiri menyisakan
   ruang kosong di kanan yang terbaca seperti kolom yang kelebaran.
   padding-right dinolkan supaya ruang panah tidak menggeser teksnya ke kiri
   dari titik tengah yang sebenarnya. */
table.xl select.sel-kode {
  text-align: center;
  padding-left: 4px; padding-right: 4px;
  background-position: right 4px center;
}
table.xl td.hitung code { display: block; text-align: center; }
/* Angka hitungan ditengahkan: pada kolom target dan triwulan isinya satu atau
   dua digit, dan rata kanan membuat angka sependek itu menempel jauh dari
   judul kolomnya sehingga baris terbaca renggang.
   Kolom RUPIAH dikecualikan lewat .uang — angka uang dibandingkan menurut
   nilai tempatnya, dan itu hanya terjadi bila rata kanan. */
table.xl input[type=number] { text-align: center; font-variant-numeric: tabular-nums; }
table.xl td.hitung.uang,
table.xl input[type=number].uang { text-align: right; }

/* Warna isian mengikuti konvensi berkas Excel. Biru di sini BUKAN sisa warna
   merek melainkan penanda "diisi unit" — sama dengan pita var(--biru) pada
   .isi-unit — jadi ia dipindah ke token semantiknya, bukan dihijaukan. Bila
   dihijaukan, artinya bertabrakan dengan hijau "otomatis" di kolom sebelahnya. */
/* Isian unit dahulu BIRU, meniru konvensi berkas Excel "sel yang diisi
   manusia". Kini hitam atas permintaan: seluruh data yang diketik pada tabel
   mana pun berwarna sama. Penanda "diisi unit" tidak hilang — pita biru
   .isi-unit di tepi kiri medannya tetap ada, dan kolom terhitung tetap
   dibedakan oleh latarnya (.v-auto hijau muda, .v-hitung abu). */
table.xl .v-unit   { color: var(--teks-data); }
table.xl .v-auto   { background: var(--hijau-50); color: var(--teks-data); }
table.xl .v-hitung { background: #f7f8f6; font-weight: 650; color: var(--teks-data); }

table.xl td.baca {
  padding: 5px 7px; font-size: var(--teks-tabel); color: var(--teks-data);
  background: var(--hijau-50);
  /* overflow: hidden dicabut bersama pemangkasannya — selama sel masih
     memotong isinya, melepas -webkit-line-clamp saja tidak cukup. */
}
/* Sel terhitung dan sel apa pun yang isinya langsung diketik ikut hitam. */
table.xl td, table.xl td code, table.xl input, table.xl select, table.xl textarea {
  color: var(--teks-data);
}
/* Pemangkasan tiga baris dicabut: seluruh narasi pada lembar ini pun
   ditampilkan utuh dan diratakan kiri-kanan, sama dengan tabel lainnya. */
table.xl td.baca .potong {
  display: block; line-height: 1.4;
  text-align: justify; text-justify: inter-word;
}
table.xl td.hitung {
  padding: 5px 7px; text-align: center; font-size: var(--teks-tabel);
  background: #f7f8f6; font-variant-numeric: tabular-nums;
}
table.xl td.tengah { text-align: center; padding: 5px 4px; }

table.xl tfoot td {
  position: sticky; bottom: 0; z-index: 5;
  background: var(--hijau-100); font-weight: 700;
  padding: 8px 7px; border-top: 2px solid var(--hijau-500);
}
table.xl tfoot td.beku { background: var(--hijau-100); z-index: 6; }

table.xl tr.ditandai td { background: #fdecec !important; opacity: .45; }
table.xl tr.berubah .beku::after {
  content: "•"; color: var(--jingga); font-size: 1.1rem; margin-left: 2px;
}

/* Bilah kendali memuat seluruh kepala lembar dalam satu baris: tombol simpan,
   keterangan tahun anggaran, kontrol Non-Renop, saringan tanggal, dan ekspor.
   Dahulu ketiganya berdiri sebagai bilah terpisah dan menghabiskan lebih dari
   separuh tinggi layar sebelum lembar kerjanya mulai terlihat. */
.bar-simpan {
  display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap;
  padding: 9px 14px; background: var(--putih);
  border: 1px solid var(--garis); border-radius: var(--radius);
  box-shadow: var(--bayang); margin-bottom: 12px;
  position: sticky; top: 0; z-index: 25;
}
.bar-simpan .status { font-size: .8rem; color: var(--teks-3); }
.bar-simpan .status b { color: var(--jingga); }

/* ==========================================================  Halaman masuk */
body.masuk {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 28px clamp(16px, 4vw, 70px);
  /* Diputihkan bersamaan dengan penggantian SVG, bukan sesudahnya: bila warna
     ini tertinggal gelap, setiap pemuatan halaman masuk berkedip hitam
     sepersekian detik sebelum SVG tergambar. */
  background: var(--putih);
  overflow-x: hidden;
}

/* ---- Latar: lembar kerja putih dengan gambar elevasi kampus.
   Menggantikan pemandangan malam. Seluruh lapisan gelap yang dahulu menumpuk
   di sini — empat gradasi navy, vinyet .latar::after, selimut .lk-gradasi,
   kabut .lk-kabut, bintang, jendela menyala, riak air, dan kunang-kunang —
   dibuang, bukan dipucatkan. Warna gelap beropasitas rendah di atas putih
   tidak terbaca sebagai kesalahan; ia hanya membuat layar tampak kotor.

   Ikut dibuang pula .latar span/.b1–.b4, .aurora, .jaring, dan .kilau: markup
   yang memakainya sudah tidak ada di login.php, jadi aturan itu sudah lama
   mati dan hanya menyesatkan penyunting berikutnya. */
.latar {
  position: fixed; inset: 0; z-index: 0; overflow: hidden;
  background: var(--putih);
}

/* Panggung menempel tepat pada layar dan TIDAK diskalakan sama sekali.
   Gerak Ken Burns yang dahulu ada di sini dibuang untuk semua orang: menskala
   pelan garis setebal 1 px membuat garisnya merayap dan memunculkan pola
   moire — persis kesan gelisah yang pernah ditolak, dan di atas kertas putih
   jauh lebih kentara daripada di atas siluet gelap. */
.lk-panggung { position: absolute; inset: 0; }
.lk-svg { width: 100%; height: 100%; display: block; }

/* ---- Gambar menyelesaikan dirinya sekali, lalu diam selamanya ----
   Tidak ada satu pun gerak abadi. Itulah yang membedakan latar berwibawa dari
   latar yang gelisah: massa gedung tegak berurutan seperti gambar yang sedang
   disusun, selesai dalam kurang dari satu detik, dan setelah itu halaman
   benar-benar tenang. */
.lk-massa {
  animation: lk-tegak .62s cubic-bezier(.22,.7,.3,1) var(--d, 0s) both;
}
@keyframes lk-tegak {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
/* Mobil melintasi jalan dari kiri ke kanan, lalu mengulang.
   Lajunya sengaja pelan — satu lintasan penuh 38 detik untuk 1.760 satuan
   viewBox — supaya terbaca sebagai gerak yang tenang, bukan sebagai sesuatu
   yang meminta diperhatikan di belakang formulir masuk. Yang dianimasikan
   hanya transform, sehingga peramban cukup menggeser lapisan yang sudah
   digambar dan tidak menggambar ulang apa pun tiap bingkai. */
.lk-mobil {
  animation: lk-melintas 38s linear 1.2s infinite;
  will-change: transform;
}
@keyframes lk-melintas {
  from { transform: translateX(-110px); }
  to   { transform: translateX(1650px); }
}

/* ----------------------  Judul melayang di kiri atas  --------------------
   Berdiri langsung di atas gambar tanpa kartu, karena itu zona x 0–700,
   y 0–260 pada SVG sengaja dikosongkan. text-shadow gelap yang dahulu ada
   dibuang seluruhnya: di atas latar terang ia tidak menambah kontras
   sedikit pun, hanya membuat huruf tampak kotor. */
.masuk-judul {
  position: absolute; top: 6vh; left: 5vw; z-index: 2;
  max-width: 46vw; color: var(--merek-900);
  animation: muncul-judul .7s cubic-bezier(.2,.8,.3,1) both .1s;
}
.masuk-judul h1 {
  margin: 0; font-size: clamp(1.7rem, 3.4vw, 2.9rem);
  font-weight: 700; letter-spacing: -.02em; line-height: 1.2;
  color: var(--merek-900);                 /* 15,3:1 terhadap putih */
}
.masuk-judul p {
  display: flex; align-items: center; gap: 9px;
  margin: 12px 0 0; font-size: .88rem;
  color: var(--teks-2);                    /* 7,5:1 */
}
.masuk-judul .pisah {
  width: 1px; height: 14px; background: var(--garis-2);
}
@keyframes muncul-judul {
  from { opacity: 0; transform: translateY(-14px); }
  to   { opacity: 1; transform: none; }
}

/* ---- Penyesuaian untuk gaya latar yang BERLATAR GELAP ----
   Judul melayang berdiri langsung di atas gambar tanpa kartu, jadi warnanya
   wajib ikut berganti bersama latarnya. Hanya gaya 'pekat' yang gelap pada
   zona judul; gaya 'fajar' justru terang di bagian atas layar dan gelap di
   kaki, sehingga judulnya tetap hijau tua. Memindahkan salah satunya tanpa
   yang lain menghasilkan huruf hijau tua di atas bidang hijau tua — tidak
   terbaca sama sekali. */
body.masuk.latar-pekat { background: var(--merek-900); }
body.masuk.latar-pekat .masuk-judul h1 { color: #ffffff; }            /* 14,8:1 */
body.masuk.latar-pekat .masuk-judul p  { color: var(--merek-100); }   /*  9,9:1 */
body.masuk.latar-pekat .masuk-judul .pisah { background: var(--merek-500); }

/* ---- Kartu masuk ----
   Kartu putih polos di atas kertas putih. Pemisahannya TIDAK dikerjakan oleh
   warna, melainkan oleh tiga hal berlapis: pelat putih pada SVG yang membuat
   bidang di belakangnya sedikit lebih terang daripada kertas di sekitarnya,
   bayangan bernada hijau (bayangan hitam di atas kertas putih terbaca kotor,
   bayangan bernada merek terbaca sebagai kedalaman), dan rel aksen 3 px di
   kepala kartu. Rel itu penting: dengan 7,3:1 ia unsur tepi yang paling jauh
   melampaui ambang 3:1 untuk unsur non-teks, sehingga tepi kartu tetap
   terbaca walau bayangannya dibuang peramban.

   backdrop-filter dibuang, bukan dikecilkan: di atas bidang yang sudah nyaris
   putih ia tidak menghasilkan apa pun dan tetap memaksa jalur penggambaran
   mahal pada setiap bingkai. */
.masuk-kartu {
  position: relative; z-index: 1;
  width: 100%; max-width: 352px;
  display: grid; grid-template-columns: 1fr;
  background: var(--putih);
  border: 1px solid var(--garis-2);
  border-radius: 18px; overflow: hidden;
  box-shadow: 0 1px 2px rgba(11,41,34,.05),
              0 8px 20px -6px rgba(11,41,34,.10),
              0 28px 56px -20px rgba(11,41,34,.18);
  animation: muncul-kartu .55s cubic-bezier(.2,.8,.3,1) both;
}
.masuk-kartu::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--aksen);
}
@keyframes muncul-kartu {
  from { opacity: 0; transform: translateY(20px) scale(.98); }
  to   { opacity: 1; transform: none; }
}


/* ======================= Panel kiri: formulir ======================= */
/* Kartu masuk dikecilkan ±10% atas permintaan. Dikecilkan MENYELURUH — bidang
   dalam, logo, tajuk, tinggi medan, dan jarak antarbaris sekaligus — bukan
   lebarnya saja: menyempitkan lebar tanpa menyusutkan isinya hanya membuat
   kartu terasa sesak, bukan terasa ringkas. Tinggi medan ditahan di 40 px,
   tidak lebih kecil, karena itu batas bawah sasaran sentuh yang nyaman pada
   layar sentuh. */
.panel-form { padding: 26px 26px 20px; }
.panel-form .logo {
  width: 54px; height: 54px; display: block; margin: 0 auto 9px;
  filter: drop-shadow(0 3px 8px rgba(11,41,34,.16));
}
.panel-form .tajuk {
  text-align: center; font-size: 1.1rem; margin: 0 0 3px;
  color: var(--merek-700); letter-spacing: -.02em; font-weight: 700;
}
.panel-form .sub {
  text-align: center; font-size: .75rem; color: var(--teks-3);
  margin: 0 0 2px; line-height: 1.45;
}
.panel-form .inst {
  text-align: center; font-size: .78rem; font-weight: 650;
  color: var(--teks-2); margin: 0 0 15px;
}
.panel-form .form-baris { margin-bottom: 11px; }
.panel-form label.fl { font-size: .77rem; color: var(--teks); margin-bottom: 5px; }

/* Kolom isian dengan ikon di tepi kiri */
.medan { position: relative; }
.medan > .ikon-bungkus {
  position: absolute; left: 1px; top: 1px; bottom: 1px; width: 36px;
  display: grid; place-items: center; color: var(--teks-3);
  background: var(--latar); border-right: 1px solid var(--garis);
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
  pointer-events: none;
}
/* padding-left HARUS mengikuti lebar .ikon-bungkus (36 px) ditambah sela;
   bila salah satu diubah sendirian, huruf pertama merapat ke garis ikon. */
.medan input { height: 40px; padding-left: 47px; font-size: .85rem; }
.medan input:focus ~ .ikon-bungkus { color: var(--merek-500); border-color: var(--merek-500); }
.medan .mata {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 34px; height: 34px; border: 0; background: none; cursor: pointer;
  display: grid; place-items: center; color: var(--teks-3); border-radius: 6px;
}
.medan .mata:hover { color: var(--merek-600); background: var(--merek-50); }
.medan .mata .tutup,
.medan .mata.terlihat .buka { display: none; }
.medan .mata.terlihat .tutup { display: block; }

.baris-bantu {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin: -2px 0 14px; font-size: .78rem;
}
.baris-bantu label {
  display: flex; align-items: center; gap: 8px;
  color: var(--teks-2); cursor: pointer;
}
.baris-bantu input[type=checkbox] { width: auto; margin: 0; }

.panel-form .btn-masuk {
  width: 100%; justify-content: center; padding: 10px; font-size: .86rem;
}

.catatan-akses {
  display: flex; align-items: center; gap: 8px;
  margin-top: 12px; padding: 8px 11px;
  border: 1px solid var(--garis); border-radius: var(--radius-sm);
  background: var(--latar); color: var(--teks-2);
  font-size: .73rem; line-height: 1.42;
}
.catatan-akses .ikon { color: var(--merek-600); }

/* ---- Koreksi keterbacaan pada kartu terang ----
   Seluruh blok penimpa warna terang yang dahulu ada di sini dibuang: kartunya
   tidak lagi berupa kaca gelap, sehingga gaya terang bawaan .panel-form
   kembali berlaku apa adanya.

   Dua aturan di bawah ini bukan selera melainkan koreksi ambang:
     .sub dan .catatan-akses memakai --teks-3 #656e69. Di atas putih nilainya
     4,8:1 (lulus tipis), tetapi keduanya duduk di atas --latar #f7f8f6, dan
     di sana nilainya jatuh di bawah ambang 4,5:1. Karena itu dinaikkan ke
     --teks-2 #4b544f (7,5:1).

   Catatan warna aksen setelah tema hijau — ketiganya kini AMAN untuk huruf
   di atas putih, tidak seperti amber yang dahulu menempati nama ini:
     --aksen     #1c5649 =  7,3:1
     --aksen-600 #16463b =  9,6:1
     --aksen-700 #0f332b = 12,2:1 */
.panel-form .sub          { color: var(--teks-2); }
.catatan-akses            { color: var(--teks-2); }
.catatan-akses .ikon      { color: var(--aksen-700); }
.baris-bantu a            { color: var(--aksen-700); }
.baris-bantu a:hover      { color: var(--merek-700); }

/* Cincin fokus memakai --merek-500. Kepekatannya dinaikkan dari .22 ke .30
   bersamaan dengan penggantian warna: #4f9281 lebih terang daripada biru yang
   dahulu dipakai, jadi pada kepekatan lama cincinnya nyaris hilang di atas
   putih — padahal pengguna papan ketik bergantung penuh padanya. */
.masuk-kartu .medan input:focus {
  border-color: var(--merek-500);
  box-shadow: 0 0 0 3px rgba(101,146,135,.30);
}

/* Hormati pengguna yang mematikan animasi di pengaturan sistemnya.
   .lk-panggung dan turunannya kini ikut disebut — dahulu blok ini tidak
   menyebut satu pun selektor .lk-, sehingga seluruh animasi latar tetap
   berjalan bagi orang yang justru sudah mematikannya. Keadaan akhir disetel
   tegas, supaya yang tampil adalah gambar UTUH, bukan gambar setengah jadi. */
@media (prefers-reduced-motion: reduce) {
  .lk-massa, .masuk-kartu, .masuk-judul {
    animation: none;
    opacity: 1;
    transform: none;
  }
  /* Mobil disembunyikan, bukan sekadar dihentikan: kendaraan yang berhenti di
     tengah jalan terbaca sebagai gambar yang salah, bukan sebagai gambar diam. */
  .lk-mobil { display: none; }
}

/* Mode kontras tinggi Windows membuang bayangan. Tanpa aturan ini kartu putih
   melebur ke halaman putih dan tepinya hilang sama sekali, sementara kisi
   setipis rambut justru terangkat menjadi jaring hitam pekat. */
@media (forced-colors: active) {
  .latar { display: none; }
  .masuk-kartu { border: 1px solid CanvasText; }
  .masuk-kartu::before { background: Highlight; }
}

/* Pada layar sempit, preserveAspectRatio="slice" memotong keras ke tengah —
   tepat tempat kartu berdiri. Gambar elevasinya disembunyikan dan yang
   tersisa hanya kertas berkisi, supaya kartu tidak pernah menindih bentuk
   yang ramai. */
@media (max-width: 640px) {
  .lk-elevasi { display: none; }
  .masuk-judul { display: none; }
}

/* ===========================================================  Bantuan  */
.utilitas { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; }
.dorong-kanan { margin-left: auto; }
.mt0 { margin-top: 0; } .mb0 { margin-bottom: 0; }
.mt12 { margin-top: 12px; } .mb12 { margin-bottom: 12px; }
/* Jarak sempit antar-tingkat pemilih SBM: ketiganya satu kesatuan, jadi
   renggangnya harus lebih rapat daripada jarak antar-medan formulir. */
.mt4  { margin-top: 6px; }
.mt20 { margin-top: 20px; }
.kecil { font-size: .8rem; }
.lemah { color: var(--teks-3); }
.tebal { font-weight: 650; }
.rata-kanan { text-align: right; }
.nowrap { white-space: nowrap; }
.pot-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.pot-3 { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

.daftar-periksa { list-style: none; padding: 0; margin: 0; }
.daftar-periksa li {
  display: flex; gap: 11px; padding: 10px 0;
  border-bottom: 1px solid var(--garis); font-size: .86rem; line-height: 1.55;
  color: var(--teks-2);
}
.daftar-periksa li:last-child { border-bottom: 0; }
.daftar-periksa .tanda {
  flex: 0 0 18px; display: grid; place-items: center;
  margin-top: 1px;
}
/* Daftar subjek yang terkena satu aturan, dilipat supaya barisnya tetap
   pendek tetapi rinciannya tidak hilang. */
.rincian-temuan { margin-top: 5px; }
.rincian-temuan > summary {
  cursor: pointer; list-style: none;
  font-size: .78rem; font-weight: 650; color: var(--tautan);
  display: inline-flex; align-items: center; gap: 6px;
}
.rincian-temuan > summary::-webkit-details-marker { display: none; }
.rincian-temuan > summary::before {
  content: ""; width: 0; height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform .15s ease;
}
.rincian-temuan[open] > summary::before { transform: rotate(90deg); }
.rincian-temuan > div {
  margin-top: 6px; padding: 8px 11px;
  background: var(--latar); border: 1px solid var(--garis);
  border-radius: var(--radius-sm);
  font-size: .78rem; line-height: 1.7; color: var(--teks-2);
  max-height: 190px; overflow-y: auto;
}

.daftar-periksa .galat .tanda { color: var(--merah); }
.daftar-periksa .peringatan .tanda { color: var(--jingga); }

/* =====================================================  Pemeriksaan komite  */
/* Tiap program tampil sebagai satu kartu dengan tombol keputusan di kakinya,
   sehingga komite dapat memutus tanpa berpindah halaman. */
/* ---- Kartu program ----
   Pita tepi kiri dan rona kepala memakai satu warna untuk seluruh kartu, yaitu
   hijau merek tema sistem. Sebelumnya tiap kelompok kode Renop diberi warnanya
   sendiri; enam warna berderet terbaca terlalu ramai, jadi dikembalikan ke satu
   warna atas permintaan.

   Keduanya memakai token palet yang sudah ada — bukan warna baru — supaya
   kartunya sewarna dengan kepala tabel dan kop cetak di seluruh sistem. */
.periksa-program {
  margin-bottom: 10px;
  border-left: 4px solid var(--merek-700);
}
.periksa-program .kartu-kepala { background: var(--merek-50); }
/* Nama program memakai warna merek, bukan warna teks biasa. Sebelumnya ia
   sewarna dengan seluruh keterangan di sekelilingnya sehingga tenggelam,
   padahal justru itu yang dicari mata lebih dahulu ketika komite menelusuri
   daftar. Warnanya sengaja sama dengan garis aksen kiri kartu ini agar
   keduanya terbaca sebagai satu penanda. Rasio kontrasnya 8,48:1 terhadap
   latar putih kartu, jauh di atas ambang 4,5:1. */
.periksa-program .program-nama {
  margin: 0 0 7px; font-size: .92rem; font-weight: 600;
  color: var(--merek-700); line-height: 1.45;
}

.kartu-kaki {
  padding: 13px 18px; border-top: 1px solid var(--garis);
  background: var(--latar); border-radius: 0 0 var(--radius) var(--radius);
}
.baris-putus { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.baris-putus input[type=text] { flex: 1 1 240px; min-width: 0; margin: 0; height: 34px; }
.kartu-kaki .bantuan { margin: 8px 0 0; }

/* Telaah komite dibaca sebagai tiga langkah bernomor: tulis telaah, tulis
   rekomendasi, lalu ketuk keputusan. Urutan itu yang menentukan tata letaknya —
   dua kotak berdampingan di atas, baris keputusan di bawahnya. */
.putus-telaah {
  flex: 1 1 100%;
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  margin-bottom: 8px;
}
.putus-telaah .fl,
.putus-keputusan .fl {
  margin-bottom: 3px; font-size: .78rem; font-weight: 650;
  color: var(--merek-700, #1c5649); text-transform: none;
}
/* Kotak telaah adalah unsur TERTINGGI di dalam kartu: pada 118 px ia sendirian
   memakan sepertiga tinggi kartu, dan kartunya diulang 12 kali. Tingginya
   dipendekkan menjadi 74 px (sekitar empat baris) saat tidak disunting, lalu
   memanjang sendiri begitu diklik — tidak ada isi yang hilang, hanya tidak
   memakan ruang selagi belum dibaca. Tepi bawahnya tetap dapat ditarik manual
   lewat resize: vertical. */
.putus-telaah textarea {
  width: 100%; margin: 0; min-height: 74px;
  font-size: .82rem; line-height: 1.5; resize: vertical;
  transition: min-height var(--sedang) var(--lembut);
}
.putus-telaah textarea:focus { min-height: 78px; }

/* Kotak telaah yang isinya terpangkas dipudarkan di tepi bawah, penanda bahwa
   masih ada lanjutannya — sama seperti sel lembar kerja. */
.putus-telaah textarea.terpangkas {
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 20px), transparent 100%);
          mask-image: linear-gradient(180deg, #000 calc(100% - 20px), transparent 100%);
  cursor: pointer;
}
.putus-keputusan { flex: 1 1 100%; }
.baris-keputusan { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.baris-keputusan input[type=text] { flex: 1 1 260px; min-width: 0; margin: 0; height: 34px; }
@media (max-width: 860px) {
  .putus-telaah { grid-template-columns: 1fr; }
}

/* Bagian panjang disembunyikan di balik segitiga agar kartu tetap terbaca. */
.lipat { border-top: 1px solid var(--garis); }
.lipat:first-of-type { border-top: 0; }
.lipat > summary {
  cursor: pointer; padding: 5px 0; list-style: none;
  font-size: .79rem; font-weight: 650; color: var(--merek-700);
  display: flex; align-items: center; gap: 7px;
}
.lipat > summary::-webkit-details-marker { display: none; }
.lipat > summary::before {
  content: ""; width: 0; height: 0; flex: 0 0 auto;
  border-left: 5px solid var(--teks-3);
  border-top: 4px solid transparent; border-bottom: 4px solid transparent;
  transition: transform .15s ease;
}
.lipat[open] > summary::before { transform: rotate(90deg); }
.isi-lipat {
  padding: 0 0 9px 12px; font-size: var(--teks-tabel); line-height: 1.55;
  color: var(--teks-2); white-space: pre-line;
}

.kotak-rekomendasi {
  margin-top: 12px; padding: 12px 14px;
  border: 1px solid var(--emas); border-left-width: 3px;
  border-radius: var(--radius-sm); background: #fffdf5;
  font-size: .84rem; line-height: 1.6; color: var(--teks-2);
}
.kotak-rekomendasi > b {
  display: flex; align-items: center; gap: 7px; margin-bottom: 5px;
  color: var(--emas-600); font-size: .78rem;
  text-transform: uppercase; letter-spacing: .05em;
}

/* Pilihan keputusan per item RAB; sengaja sempit agar tidak mendesak tabel. */
.putus-mini { display: inline-block; margin: 0 0 4px; }
.putus-mini select { height: 30px; padding: 0 6px; font-size: .76rem; margin: 0; }

/* ==========================================================  Responsif  */
/* Di layar sempit kedua panel ditumpuk; panel keterangan pindah ke bawah
   formulir supaya isian tetap menjadi yang pertama terlihat. */
@media (max-width: 1180px) {
  /* Ruang tidak lagi cukup untuk judul di kiri dan kartu di kanan sekaligus,
     jadi judulnya disembunyikan dan kartunya kembali ke tengah. */
  body.masuk    { justify-items: center; }
  .masuk-judul  { display: none; }
}
@media (max-width: 900px) {
  .panel-form { padding: 28px 26px 22px; }
}
@media (max-width: 460px) {
  body.masuk { padding: 16px 12px; }
  .masuk-kartu { border-radius: 14px; }
  .panel-form { padding: 24px 20px 20px; }
  .panel-form .logo { width: 56px; height: 56px; }
  .panel-form .tajuk { font-size: 1.1rem; }
  .baris-bantu { flex-direction: column; align-items: flex-start; gap: 8px; }
  .latar span { filter: blur(52px); }
}
@media (max-width: 880px) {
  :root { --sidebar: 0px; }
  .sisi {
    position: fixed; left: -280px; width: 264px; flex-basis: 264px;
    z-index: 90; transition: left .22s ease; box-shadow: var(--bayang-lg);
  }
  .sisi.buka { left: 0; }
  .tombol-menu { display: inline-flex !important; }
  .isi { padding: 15px; }
  header.atas { padding: 0 14px; }
  .pengguna-chip .info { display: none; }
}
.tombol-menu { display: none; background: none; border: 0; cursor: pointer; padding: 6px; }

/* ==============================================================  Cetak  */
@media print {
  @page { size: A4 landscape; margin: 10mm 8mm; }
  body { background: #fff; font-size: 9pt; }
  .sisi, header.atas, .btn, .langkah, .tirai, .tanpa-cetak { display: none !important; }
  .isi { padding: 0; }
  .kartu { border: 0; box-shadow: none; margin: 0 0 8mm; break-inside: auto; }
  .kartu-kepala { display: none; }
  .kartu-isi { padding: 0; }
  table.tabel { font-size: 7.6pt; }
  /* Hitam juga saat halaman ini dicetak langsung dari peramban — garis abu
     setipis .4pt nyaris lenyap di atas kertas, apalagi hasil fotokopi. */
  table.tabel th, table.tabel td { padding: 3px 4px; border: 0.4pt solid #000; }
  table.tabel tbody td, table.tabel tfoot td { color: #000; }
  table.tabel thead th { background: var(--merek-700) !important; color: #fff !important;
                         -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  table.tabel thead { display: table-header-group; }
  tr { break-inside: avoid; }
  a { color: inherit; text-decoration: none; }
}

/* ================================================  Gerak: hormati pengaturan
   Satu aturan menyeluruh untuk seluruh sistem. Blok ini sengaja diletakkan
   paling akhir supaya selalu menang atas aturan mana pun di atasnya, termasuk
   yang ditambahkan kelak.

   Animasi tidak dimatikan dengan display:none atau animation:none saja,
   melainkan dipercepat menjadi hampir nol lalu dipaksa berhenti di keadaan
   akhirnya. Mematikan animasi begitu saja adalah kesalahan paling umum pada
   animasi yang "menggambar dirinya": yang tampil justru gambar setengah jadi.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0s !important;
    transition-duration: .01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
  /* Angkatan saat kursor lewat dilepas seluruhnya: bagi yang peka gerak,
     bidang yang bergeser tetap mengganggu betapapun cepatnya. */
  .stat:hover { transform: none; }
}
/* Kode program: huruf mesin ketik supaya kolomnya sejajar, tetapi ukurannya
   tetap mengikuti token isi tabel. Sebelumnya dipatok .7rem lewat gaya
   sebaris dan menjadi satu-satunya kolom data yang lebih kecil. */
table.xl td.hitung code { font-size: var(--teks-tabel); }
/* ---- Tombol keputusan komite ----
   Terima dan Revisi sebelumnya sama-sama bergaris abu dan nyaris tidak
   terbaca sebagai tombol, padahal inilah tiga tindakan terpenting di halaman
   itu. Warnanya mengikuti pita status yang sudah dipakai di seluruh sistem.
   Huruf putih di atas ketiganya melewati ambang keterbacaan 4,5:1. */
.btn-terima { background: #0f7a45; color: #fff; border-color: #0f7a45; }
.btn-terima:hover { background: #0c6339; border-color: #0c6339; }
.btn-revisi { background: #8a6a20; color: #fff; border-color: #8a6a20; }
.btn-revisi:hover { background: #73470d; border-color: #73470d; }
/* Tolak dibuat sewarna penuh seperti dua lainnya supaya ketiganya sederajat;
   sebelumnya ia satu-satunya yang berlatar putih. */
.baris-keputusan .btn-bahaya { background: #b3352a; color: #fff; border-color: #b3352a; }
.baris-keputusan .btn-bahaya:hover { background: #932b22; border-color: #932b22; }
/* Bantalan kartu program dirapatkan — hanya kartu ini, bukan .kartu di seluruh
   sistem. Kartu lain berdiri sendiri satu per halaman sehingga bantalannya
   boleh lega; kartu ini berderet dua belas ke bawah, dan setiap piksel yang
   dihemat dikalikan dua belas. */
.periksa-program > .kartu-kepala { padding: 9px 14px; }
.periksa-program > .kartu-isi    { padding: 12px 14px; }
.periksa-program > .kartu-kaki   { padding: 10px 14px; }
.periksa-program .kartu-kepala .ket { margin-top: 2px; }