/* sisma-ci3.css — aturan khusus SISMA CI3 di atas Vuexy 3 + app.css sisma_ci4. Hanya dimuat kerangka v3. (R0.7.3) */

/*
 | UKURAN PAKEM JARAK (KP-189, pemilik 21 Sep 2026: "coba seragamkan saja semuanya, buat ukuran pakem nya, jika
 | ada yang lain sendiri baru dibedakan", lalu "jarak antar card, jarak antar table dll").
 |
 | Dua angka saja, dan keduanya ditulis DI SINI — bukan disebar sebagai `mb-6`, `mt-2`, `p-3 pt-0` di tiap view,
 | yang selama ini membuat jarak terlihat naik-turun antar halaman dan menyulitkan menjawab pertanyaan sesederhana
 | "berapa seharusnya".
 |
 |   --sisma-jarak        24 px   jarak baku ANTAR BLOK: kartu ke kartu, kartu ke tabel, baris ke baris.
 |                                Sama dengan gutter `g-6` yang sudah dipakai mayoritas view.
 |   --sisma-jarak-rapat  16 px   jarak baku di sekitar TEKS penunjuk: breadcrumb atas dan bawah.
 |   --sisma-jarak-bilah   8 px   jarak di atas bilah tabel (cari / jumlah baris / tombol). Lebih rapat
 |                                daripada dua angka di atas dengan sengaja: bilah itu bagian dari kepala
 |                                tabelnya, bukan blok yang berdiri sendiri (KP-192).
 |
 | Yang memang harus lain — halaman cetak, isi modal, kartu dalam kartu — dibedakan dengan aturannya sendiri di
 | bawah, dan setiap pengecualian menyebutkan alasannya. Penjaganya `tools/tema/jarak-kartu.php`: kartu wajib
 | berjarak 16-40 px, breadcrumb 16 px (+-4) di atas dan di bawah.
 */
:root {
  --sisma-jarak: 1.5rem;
  --sisma-jarak-rapat: 1rem;
  --sisma-jarak-bilah: 0.5rem;
}

/* Kartu di dalam modal: view modal lama membungkus isinya dengan .card; di dalam modal kartu itu diratakan
   (kelas dipasang sismaModalRapikan() di backend/v3/modal.php sesudah isi termuat). */
.modal .sisma-modal-kartu { box-shadow: none; border: 0; margin: 0; background: transparent; }
.modal .sisma-modal-kartu > .card-body { padding: 0; }
.modal .sisma-modal-kartu > .card-header { padding: 0 0 1rem; }
.modal .sisma-modal-kartu > .table-responsive { margin: 0; }
.modal .modal-body > .row > [class*='col'] > .card { box-shadow: none; border: 0; margin: 0; }

/* Modal yang ditulis di dalam isi halaman harus tetap tersembunyi sampai dibuka (R0.7.11).
   Sebabnya: app.css dari sisma_ci4 memberi `display: flex` kepada SETIAP anak langsung .sisma-page-content
   yang punya id — di CI4 itu pembungkus dashboard (<div id="sisma-dashboard">), tetapi di CI3 modal juga anak
   langsung dan punya id. Kekhususan selektornya (satu kelas + satu atribut) mengalahkan `.modal{display:none}`
   Bootstrap, jadi modal itu ikut dirender: tak terlihat (opacity 0 dari .fade) tetapi position fixed
   z-index 1090 seukuran layar — MENUTUPI SELURUH HALAMAN dan menelan semua klik. Ketahuan di dashboard:
   tidak satu pun tautan atau select bisa diklik (dilaporkan pemilik, dibuktikan dengan document.elementFromPoint).
   Modal yang sedang dibuka tidak terpengaruh: Bootstrap menyetel display lewat gaya inline. */
/* ------------------------------------------------------------------ breadcrumb tertutup kartu (KP-185)
   Pemilik 21 Sep 2026, dengan tangkapan layar breadcrumb yang terpotong: "pastikan juga breadcrumbs posisinya
   terlihat tidak tertutup, dan jarak atas dan bawah proporsional".

   Sebabnya bukan breadcrumb-nya, melainkan baris Bootstrap sesudahnya. `.row` memakai
   `margin-top: calc(-1 * var(--bs-gutter-y))` — pada `g-6` itu -24 px — sedangkan anaknya di build ini TIDAK
   mendapat `padding-top` penyeimbangnya (terukur 0 px). Jadi halaman yang isinya DIAWALI sebuah `.row` naik
   24 px utuh: dengan `margin-bottom: 16px` milik breadcrumb, kartu pertama berhenti 8 px DI ATAS dasar
   breadcrumb dan menutupi teksnya. Terukur persis -8 px di ketujuh halaman pengaturan.

   Halaman yang isinya diawali `<section>` (mayoritas halaman lama) tidak kena, dan itu sebabnya cacat ini bisa
   hidup lama tanpa terlihat.

   Yang dimatikan hanya tarikan pada baris PERTAMA: di situ tidak ada apa pun di atasnya yang perlu dirapatkan.
   `:first-of-type` ikut disebut karena banyak view diawali <style> atau blok PHP — elemen <style> membuat baris
   pertamanya bukan lagi :first-child, dan empat halaman akademik/presensi lolos dari perbaikan pertama karena itu.
*/

/*
 | KP-187 — pemilik 21 Sep 2026: "seragamkan semua jarak bawah breadcrumbs nya".
 |
 | Sebelum ini jarak di bawah breadcrumb berbeda-beda antar halaman: terukur 16 px di `sdm/slip_gaji` dan
 | `pengaturan/*`, tetapi 40 px di `presensi/utama` dan `administrasi/tahun_ajaran`. Sebabnya kolom baris
 | pertama mendapat `margin-top: 24px` di sebagian halaman dan 0 di sebagian lain — tergantung bentuk
 | pembungkusnya (`<section id>` yang dijadikan flex oleh app.css sisma_ci4 berperilaku lain dari `.row`
 | telanjang). Menelusuri tiap bentuk pembungkus satu per satu tidak menyelesaikan apa pun untuk bentuk
 | kedelapan yang belum ada hari ini.
 |
 | Jadi yang diseragamkan HASILNYA: baris pertama dan anaknya tidak menyumbang jarak apa pun, dan seluruh jarak
 | datang dari satu tempat — `margin-bottom` milik breadcrumb di bawah (16 px). Satu angka, satu tempat mengubahnya.
 |
 | Anak baris PERTAMA saja yang dinolkan. Kalau baris itu sampai membungkus ke baris kedua, kartunya akan
 | menempel — dan itu tertangkap `jarak-kartu.php` sebagai RAPAT, bukan lolos diam-diam.
 */

/*
 | KP-189 — view yang membungkus dirinya dengan container KEDUA. Kerangka sudah menaruh isi halaman di dalam
 | `.container-xxl.container-p-y`; view yang menambahkan satu lagi (mis. `siswa/profil`) menumpuk bantalan
 | tegaknya — terukur 40 px di bawah breadcrumb, bukan 16 px pakem.
 |
 | Tidak ditimpa dari sini, dan itu disengaja: `.container-p-y` memakai `!important` (core.css), jadi aturan apa
 | pun di berkas ini kalah. Sama seperti `mb-*`, yang benar membuang kelasnya dari view — kerangka sudah
 | menyediakan containernya. Kalau suatu view memang perlu container sendiri, `pt-0 pb-0` mematikan bantalannya
 | (core.css sengaja menyediakan celah `:not([class^=pt-])` untuk itu).
 */
/* Satu-satunya sumber jarak di bawah breadcrumb, sesudah aturan di atas menolkan sumbangan baris pertama. */
/* Breadcrumb: jarak atas dan bawah SAMA, memakai angka pakem. Pemilik menolak 8/16 (sempit di atas),
   16/24 ("tidak proporsional"), dan 24/24 ("terlalu renggang") sebelum 16/16 diterima. */
.sisma-page-breadcrumb {
    margin-bottom: var(--sisma-jarak-rapat);
}

.sisma-page-content .modal:not(.show) {
  display: none !important;
}

/* Akibat kedua dari aturan yang sama: kartu yang punya id (halaman daftar CI3 memakai
   <section class="card" id="basic-datatable">) ikut mendapat gap 1,5 rem, sehingga ada celah kosong antara
   kepala kartu dan tabelnya. Di sisma_ci4 section daftar tidak berid, jadi tidak bercelah — disamakan. */
.sisma-page-content > .card[id] {
  gap: 0;
}

/* Akibat ketiga dari aturan yang sama (R0.7.34): tab Bootstrap yang ditulis langsung di isi halaman
   (<ul class="nav nav-tabs" id="…"> + <div class="tab-content" id="…">) ikut dijadikan flex KOLOM, sehingga
   tab-tabnya menumpuk ke bawah — dilaporkan pemilik di halaman anti-fraud ("tab dibuat pojok kiri dan
   menyamping bukan atas bawah"). .nav memang flex; yang dikembalikan hanya arahnya. .tab-content dikembalikan
   ke blok supaya transisi .fade Bootstrap bekerja seperti biasa. */
.sisma-page-content > .nav[id] {
  flex-direction: row;
  flex-wrap: wrap;
  gap: 0;
}

.sisma-page-content > .tab-content[id] {
  display: block;
}

/* Pane tab bermarkup lama kosong saat halaman dimuat (R0.7.37). core.css Vuexy 3 menyembunyikan SETIAP pane
   (`.tab-content:not(.doc-example-content) .tab-pane { opacity: 0; transform: translateX(-30px) }`) dan hanya
   memunculkan `.tab-pane.show` — ia mengandaikan markup Bootstrap 5 `tab-pane fade show active`. View lama menulis
   `tab-pane active` (Bootstrap 4), jadi pane pertama tidak pernah mendapat `show` dan tetap tak terlihat sampai
   pemakai memindah tab dan kembali (Bootstrap menambahkan `show` saat mengaktifkan pane lewat klik). Terkena 8
   halaman daftar bertab yang pindah di R0.7.17 dan modal detail pegawai. Pane bermarkup lama dipaksa tampak;
   pane ber-`fade` (markup Vuexy 3, mis. anti-fraud) tetap lewat jalur animasi Bootstrap. */
.tab-content > .tab-pane.active:not(.fade) {
  opacity: 1;
  transform: none;
}

/* Nama aplikasi di kepala sidebar (R0.7.12: pemilik minta hanya huruf, tanpa kotak logo). Bawaan Vuexy
   menyetelnya 15 px — sama besar dengan teks menu, sehingga tidak terbaca sebagai logo dan tampak tidak
   berjenjang. Dinaikkan sedikit jadi 20 px (pemilik: "tidak proporsional", "bisa dibuat lebih besar sedikit");
   teks menu tetap 15 px, judul grup 13 px. */
#layout-menu .app-brand-text {
  font-size: 1.25rem;
  line-height: 1.2;
  letter-spacing: 0.01em;
}

/* Pola daftar: di bawah lebar xl kepala kartu menumpuk (flex-column), dan tombol tindakan ikut melebar penuh
   karena flex-item menumpuk itu meregang. Tombolnya dibuat selebar isinya saja. (R0.7.11) */
@media (max-width: 1199.98px) {
  .card-header > .d-flex.flex-column > .btn {
    align-self: flex-start;
  }
}

/* Akun demo (level 99): angka dikaburkan, sama seperti tema lama (dulu <style> inline di index.php). */
.demo { filter: blur(5px); user-select: none; pointer-events: none; }

/* ===== Sel tabel yang menempel (sticky) wajib berlatar penuh (R0.7.16) =====
   Dilaporkan pemilik: di halaman Rekapitulasi Saldo, kolom rekening dan kepala tabelnya tembus — angka dari
   kolom yang tergulir terbaca menumpuk di atasnya. Sebabnya bukan halamannya: DataTables 2 memasang
   `table.table.dataTable > :not(caption) > * > * { background-color: var(--bs-table-bg) }` (kekhususan 0,2,2)
   yang MENGALAHKAN aturan latar halaman `.rekap-table tbody .rekap-col-rekening` (0,2,1); `--bs-table-bg`
   sendiri transparan. Di tema lama aturan DataTables itu belum ada, jadi halamannya baik-baik saja.
   Terukur di peramban: latar sel menempel = rgba(0, 0, 0, 0), termasuk kolom beku DataTables sendiri
   (`.dtfc-fixed-start`) di 17 halaman yang memakai `fixedColumns`.

   Latar memakai --bs-paper-bg (warna kartu) supaya ikut tema terang/gelap. Lapisan (z-index) disusun:
   kolom menempel 2, kepala menempel 3, persilangan keduanya 4 — supaya kepala tetap di atas kolom. */
.sisma-page-content .dtfc-fixed-start,
.sisma-page-content .dtfc-fixed-end,
.sisma-page-content .tableFixHead thead th,
.sisma-page-content .tableFixHead thead td,
.sisma-page-content .th1,
.sisma-page-content .rekap-col-no,
.sisma-page-content .rekap-col-rekening,
.sisma-page-content .rekap-sticky-head-1,
.sisma-page-content .rekap-sticky-head-2 {
  background-color: var(--bs-paper-bg) !important;
}

.sisma-page-content .dtfc-fixed-start,
.sisma-page-content .dtfc-fixed-end,
.sisma-page-content .th1 {
  z-index: 2;
}

.sisma-page-content .tableFixHead thead th,
.sisma-page-content .tableFixHead thead td {
  z-index: 3;
}

.sisma-page-content thead .dtfc-fixed-start,
.sisma-page-content thead .dtfc-fixed-end,
.sisma-page-content .tableFixHead thead .th1 {
  z-index: 4;
}

/* Kolom "Opsi" menempel di kanan (R0.7.18, permintaan pemilik: "setiap kolom opsi juga dibuat sticky").
   Kelas dipasang assets/vuexy-sisma/kolom-opsi.js — CSS tidak bisa memilih kolom berdasarkan teks judulnya.
   Tabel yang sudah memakai FixedColumns DataTables dilewati skrip itu, jadi tidak dobel.

   Garis pemisah di kiri sel dibuat dengan pseudo-elemen, bukan border (menggeser lebar kolom) dan bukan
   box-shadow seperti semula (R0.7.18). R0.7.36: Bootstrap 5.3 mewarnai baris belang (.table-striped) dan
   sorotan hover (.table-hover) lewat `box-shadow: inset 0 0 0 9999px …` di setiap sel (core.css), dan
   datatables.bootstrap5.css menimpanya lagi untuk baris ganjil tabel belang. box-shadow milik kita menimpa
   semuanya, sehingga sel Opsi tampak putih di baris belang (6 halaman) dan tidak ikut tersorot saat hover
   (semua tabel table-hover). Dengan pseudo-elemen, box-shadow sel dibiarkan milik Bootstrap/DataTables —
   sel Opsi berwarna sama dengan sel-sel lain di barisnya, apa pun aturannya. */
.sisma-page-content .sisma-col-opsi {
  position: sticky;
  right: 0;
  z-index: 2;
  background-color: var(--bs-paper-bg) !important;
}

.sisma-page-content .sisma-col-opsi::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 1px;
  background-color: var(--bs-border-color);
}

.sisma-page-content thead .sisma-col-opsi,
.sisma-page-content tfoot .sisma-col-opsi {
  z-index: 4;
}

/*
 | KP-201 — pemilik 21 Sep 2026: "kolom opsi tidak terlihat".
 |
 | Latar kertas di atas WAJIB dan ber-!important: kolom Opsi lengket (`position: sticky`), dan kolom lengket
 | yang latarnya tembus pandang membuat isi kolom lain lewat di belakangnya. Tetapi dua tabel di
 | `keuangan/pembayaran_siswa` memakai `<thead class="table-dark">` — sel kepalanya gelap dengan teks PUTIH.
 | Latar kertas menimpanya, teksnya tetap putih, jadi tulisan "Opsi" hilang: putih di atas putih. Terukur
 | latar rgb(255,255,255) dengan warna rgb(255,255,255), sementara sel tetangganya rgb(47,51,73).
 |
 | Yang dikembalikan hanya LATARNYA, ke warna yang memang dipakai baris itu (`--bs-table-bg` milik
 | `.table-dark`), jadi kolomnya tetap tidak tembus pandang saat digulir mendatar.
 */
.sisma-page-content .table-dark .sisma-col-opsi {
  background-color: var(--bs-table-bg) !important;
}

/* Kelas tabel DataTables yang dipakai banyak view lama */
.dt-body-right  { text-align: right; }
.dt-body-center { text-align: center; vertical-align: middle; }
.dt-body-nowrap, .dt-body-nowarp { white-space: nowrap; }
/* `.dt-body-white-space` SENGAJA TIDAK ADA DI SINI (KP-153). R0.7.28 memasukkannya ke aturan pusat ini
   dengan anggapan kelas itu memang berarti nowrap — padahal di produksi ia hanya berlaku pada view yang
   membawa aturannya sendiri di <style>. Tiga view memakai kelasnya TANPA aturan lokal
   (sarpras_aset_inven, sarpras_aset_list_inven, sarpras_pj_ruang), jadi di produksi selnya MEMBUNGKUS;
   aturan pusat membuat ketiganya nowrap, dan tabel Aset Inventaris melar 1.079 px -> 1.438 px di wadah
   1.043 px sehingga kolom Jumlah/Total Harga/Unit lari ke balik kolom Opsi yang ditambatkan — baris
   tfoot TOTAL pun tampak kosong (temuan mata KP-151). Tiga view yang di produksi memang nowrap tetapi
   <style> lokalnya dibuang R0.7.28 kini memakai `dt-body-nowrap` supaya tetap nowrap lewat aturan ini. */

/* Kotak angka dashboard (R0.7.4) */
.sisma-kotak-angka .h3, .sisma-kotak-angka .h4, .sisma-kotak-angka .h5 { font-variant-numeric: tabular-nums; }

/* Angka di kotak TIDAK BOLEH pecah di tengah (KP-153). `342,057,800` yang patah jadi `342,05` lalu
   `7,800` terbaca sebagai dua angka lain — temuan mata KP-151 pada keenam kartu Penerimaan SPP & PPDB. */
.sisma-kotak-angka .h3, .sisma-kotak-angka .h4, .sisma-kotak-angka .h5 { white-space: nowrap; }

/* Jajaran kartu angka yang lebarnya mengikuti isi, bukan pecahan kolom tetap (KP-153).
   Sebelumnya `row g-6` + `col-6 col-md-4 col-xl-2`: pada 1366 px enam kartu sebaris membuat tiap kartu
   154 px, dan sesudah padding 48 px + lambang 38 px + sela 16 px hanya tersisa 54 px untuk angka 11 huruf
   yang butuh ±105 px. Dengan auto-fit tiap kartu dijamin >= 230 px (cukup untuk `9,999,999,999`), dan
   jumlah kartu sebaris menyesuaikan lebar layar sendiri — juga ketika menu samping dibuka/dilipat. */
.sisma-grid-kartu {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1.5rem;
}

.sisma-grid-kartu .sisma-grid-penuh { grid-column: 1 / -1; }

/* Kartu folder/file File Manager dan Drive Manager (R0.7.52, KP-73) — disalin dari <style> halaman
   sisma_ci4 backend/administrasi/dokumen/index.php supaya kedua halaman memakai kartu yang sama. */
.sisma-file-folder-card {
  cursor: pointer;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.sisma-file-folder-card:hover,
.sisma-file-folder-card:focus-within {
  border-color: color-mix(in srgb, var(--bs-primary) 55%, var(--bs-border-color)) !important;
  box-shadow: 0 .25rem .75rem rgba(34, 48, 62, .08);
  transform: translateY(-1px);
}

/* Gambar berita Monthly News (R0.7.54, KP-73) — dulu .custom-image di <style> view */
.sisma-news-gambar {
  max-height: 220px;
  max-width: 100%;
  width: auto;
  object-fit: contain;
}

/* Layar kecil: gambar boleh selebar kartu (aturan lama .custom-image di dashboard TK, R0.7.57) */
@media (max-width: 575.98px) {
  .sisma-news-gambar {
    max-height: none;
    width: 100%;
  }
}

/* KP-262 — foto di samping teks hanya kalau KARTUNYA cukup lebar, bukan layarnya.
   `flex-sm-row` menaruh foto (lebar 300 px) di samping teks mulai layar 576 px, padahal kartu lini masa hanya selebar
   separuh area isi: di layar 1280 px sisa kolom teks tinggal ±100 px dan kata terpotong ("Septembe / r"). Kartu kini
   mengukur lebarnya sendiri; di bawah 520 px foto pindah ke atas teks. 520 = foto 300 + jarak 16 + teks ±200.
   Peramban tanpa container query tetap berperilaku seperti sebelumnya. */
.sisma-news-kartu {
  container-type: inline-size;
}
@container (max-width: 520px) {
  .sisma-news-kartu .sisma-news-baris {
    flex-direction: column !important;   /* mengalahkan .flex-sm-row / .flex-sm-row-reverse (juga !important) */
  }
}

/* Modal besar (R0.7.56, KP-74): tema lama memberi `.modal-xl` max-width 94 % di layar >=1200 px
   (app-assets/css/bootstrap.min.css), Bootstrap 5.3 Vuexy 3 hanya 1140 px — modal besar terasa mengecil
   di layar lebar. Dua kelas supaya menang atas `.modal-xl` tanpa !important; --bs-modal-width adalah
   yang dipakai `.modal-dialog { max-width: … }` Bootstrap 5. */
@media (min-width: 1200px) {
  .modal-dialog.sisma-modal-besar {
    --bs-modal-width: 94%;
  }
}
/* KP-387 (pemilik 30 Sep 2026: tab modal Detail Pegawai "melebihi modal saat ukuran layar kecil", "pada modal letaknya jadi berantakan"):
   di bawah 1200 px modal besar dulu 800 px (992–1199) dan 500 px (576–991), padahal isinya dua kolom halaman — kolom
   mengikuti lebar LAYAR, bukan lebar modal, jadi di tablet modal 500 px dibelah dua. Modal besar = "hampir menutupi page
   browser" (KP-74) di semua lebar; kecil dan sedang tidak berubah. Di bawah 576 px Bootstrap sudah penuh selebar layar. */
@media (min-width: 576px) and (max-width: 1199.98px) {
  .modal-dialog.sisma-modal-besar {
    --bs-modal-width: 94%;
  }
}

/* Notifikasi (R0.7.59): garis jenis hanya di sisi kiri. Kelas `border-success` dsb. Bootstrap 5 mewarnai
   KEEMPAT sisi (kotaknya jadi hijau seluruh), sedangkan bentuk lamanya kotak abu bergaris warna 3 px di kiri.
   Jenisnya dibaca dari atribut `data-type` yang sudah ada di markup. */
.notification-item {
  border-inline-start-width: 3px !important;
}
.notification-item[data-type="success"] { border-inline-start-color: var(--bs-success) !important; }
.notification-item[data-type="danger"]  { border-inline-start-color: var(--bs-danger)  !important; }
.notification-item[data-type="warning"] { border-inline-start-color: var(--bs-warning) !important; }
.notification-item[data-type="info"]    { border-inline-start-color: var(--bs-info)    !important; }

/* Baris ber-gutter (`row g-*`) yang menjadi ANAK LANGSUNG `.sisma-page-content` (R0.7.60, laporan pemilik
   7 Sep 2026 pada baris kotak SPMB dashboard: "g-6 dihilangkan saja, jaraknya jadi tidak proporsional").
   Bootstrap membuat gutter-y dari `margin-top` di setiap kolom lalu membatalkannya dengan `margin-top`
   negatif di barisnya. `app.css` menolkan `margin-block` anak langsung `.sisma-page-content` (jarak halaman
   memang datang dari `gap`), jadi pembatal itu hilang dan tersisa ruang kosong sebesar gutter-y di ATAS
   kartu baris pertama. Di sini gutter-y diubah menjadi `row-gap` sejati: tidak ada ruang di atas, jarak
   antar baris saat membungkus (layar kecil) tetap ada. */
.sisma-page-content > .row {
  row-gap: var(--bs-gutter-y);
  /*
   | KP-189: tarikan `margin-top` negatif milik `.row` ikut dinolkan. Gutter-nya sudah diubah jadi `row-gap`
   | di atas dan margin anaknya dinolkan di bawah, jadi pembatal negatif itu tidak punya lagi yang dibatalkan —
   | yang tersisa hanya tarikan 24 px ke atas, dan itulah yang membuat kartu pertama menimpa breadcrumb
   | (pemilik 21 Sep 2026, tangkapan layar "Dashboard / Pengaturan Umum" yang terpotong). Baris yang BUKAN anak
   | langsung tidak tersentuh: di situ mekanisme bawaan Bootstrap masih lengkap dan sudah benar.
   */
  margin-top: 0;

  /*
   | KP-189 — jarak antar blok di wilayah isi datang dari `gap` punya `.sisma-page-content` (app.css), SATU
   | sumber. Baris yang menambah `mb-6` sendiri menumpuk di atasnya dan jadi 48 px; terukur lima pasang begitu
   | di `zoom/utama`.
   |
   | Aturan di sini TIDAK menimpanya, dan itu disengaja: utility `mb-*` Bootstrap memakai `!important`, jadi
   | aturan apa pun di berkas ini akan kalah. Menambahkan `!important` balasan berarti memulai perang yang juga
   | akan mematikan `mb-*` yang memang disengaja di tempat lain. Yang benar membuang `mb-*` dari view-nya, dan
   | `tools/tema/jarak-kartu.php` yang menjaga: jarak di atas 40 px dilaporkan RENGGANG.
   */
}

.sisma-page-content > .row > * {
  margin-top: 0;
}

/* Dashboard keuangan */
/* `min-w-0` dipakai dashboard (R0.7.4) dan dashboard2 supaya teks panjang di dalam kotak flex boleh
   dipendekkan, tetapi Vuexy 3 tidak membawa utilitas itu — tanpa ini kotak angka melebar melewati kartunya. */
.min-w-0 {
  min-width: 0 !important;
}

/* Dua kolom pertama tabel keuangan dashboard menempel saat tabelnya digulir ke samping
   (R0.7.66 untuk Rekapitulasi Keuangan Unit, R0.7.68 untuk Tunggakan per Tahun Ajaran; permintaan
   pemilik) — pola yang sama dengan kolom Opsi (`sisma-col-opsi`, R0.7.18). `sisma-col-no` adalah
   kolom nomor, `sisma-col-unit` kolom pengenal baris (nama unit di tabel rekap, tahun ajaran di
   tabel tunggakan).
   Kelasnya dipasang di markup, bukan lewat :nth-child, karena kepala tabelnya bertingkat: baris
   kedua dan ketiga dimulai dengan kolom lain (Siswa Baru, SPP), jadi pemilih berdasarkan urutan
   akan menempelkan kolom yang salah. Lebar kolom nomor dipatok supaya `left` kolom kedua pasti;
   di tabel tunggakan lebarnya ditentukan DataTables, jadi `left`-nya dipasang ulang dari lebar
   sebenarnya oleh `pasangOffsetKolomMenempel()` di dashboard_skrip.php. */
.sisma-page-content .sisma-tabel-rekap .sisma-col-no {
  position: sticky;
  left: 0;
  z-index: 2;
  width: 3rem;
  min-width: 3rem;
  background-color: var(--bs-paper-bg) !important;
}

.sisma-page-content .sisma-tabel-rekap .sisma-col-unit {
  position: sticky;
  left: 3rem;
  z-index: 2;
  background-color: var(--bs-paper-bg) !important;
}

.sisma-page-content .sisma-tabel-rekap .sisma-col-unit::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 1px;
  background-color: var(--bs-border-color);
}

.sisma-page-content .sisma-tabel-rekap thead .sisma-col-no,
.sisma-page-content .sisma-tabel-rekap thead .sisma-col-unit,
.sisma-page-content .sisma-tabel-rekap tfoot .sisma-col-no,
.sisma-page-content .sisma-tabel-rekap tfoot .sisma-col-unit {
  z-index: 4;
}

/* Blok Statistik dashboard (R0.7.71, KP-79). Empat grafik dipatok 320 px supaya kartu-kartunya sejajar
   (dulu min-height 350 px lewat <style> di halaman, saran 4). Kartu bertab Grafik | Tabel: pane tanpa
   bantalan/bayangan tambahan dari Vuexy, tinggi minimum sama dengan grafiknya supaya kartu tidak melompat
   saat tab berganti; pil tabnya dibuat kecil karena duduk di kepala kartu sebelah judul. */
.sisma-page-content .sisma-grafik {
  width: 100%;
  min-height: 320px;
}

.sisma-page-content .sisma-kartu-statistik .tab-content {
  padding: 0;
  box-shadow: none;
  min-height: 320px;
}

.sisma-page-content .sisma-kartu-statistik .nav-pills .nav-link {
  padding: 0.25rem 0.75rem;
  font-size: 0.8125rem;
}

/* Bilah tabel ala sisma_ci4 (R0.7.80, KP-87). Markup-nya disusun ulang tabel-v3.js dari hasil render DataTables —
   string `dom` 87 view tidak disentuh. Kotak cari berikon di kiri, jumlah baris + Export + penyaring milik halaman
   di kelompok kanan; ukuran kecil (form-control-sm/form-select-sm) dilepas supaya setinggi tombol Vuexy. */
/*
 | KP-112: kepala kartu tabel. Sebelumnya ada 13 bentuk kelas kepala (`py-3`, `pb-1`, `pb-75`, `p-1`, tanpa
 | bantalan, dengan/tanpa garis) dan tombolnya diletakkan bermacam cara (`col text-end`, `d-flex`, menempel
 | begitu saja). `tabel-v3.js` melepas kelas bantalan tempelan dan memberi kelas di bawah; ukurannya satu.
 | Penyaring tetap di kiri, tombol dikelompokkan ke kanan.
 */
.card > .sisma-dt-kepala,
.dt-container > .sisma-dt-kepala {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--bs-border-color);
}

.sisma-dt-kepala > .sisma-dt-kepala-kanan {
  margin-inline-start: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

/* Isi penyaring di kepala: satu baris rapat, sejajar dasar, tanpa jarak tempelan tiap halaman. */
.sisma-dt-kepala form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem 0.75rem;
  margin: 0;
}

/*
 | Kepala kini flex, jadi anaknya adalah ITEM flex dan tanpa aturan ini menciut ke selebar isinya - medan
 | penyaring 18 halaman laporan KP-100 langsung terlihat lebih sempit, dan tombol Tambah di `administrasi/
 | pegawai` melompat dari ujung kanan kartu ke sisi select. Yang ditumbuhkan hanya anak PEMBAWA KONTROL
 | (ditandai tabel-v3.js): kalau semuanya ditumbuhkan, pembungkus judul + keterangan panjang di dashboard
 | ikut melar dan pemilih bulan di sebelahnya turun baris.
 */
.sisma-dt-kepala > .sisma-dt-kepala-isi {
  flex: 1 1 auto;
}

/*
 | KP-202 — pemilik 21 Sep 2026: "tidak sejajar" (tangkapan layar Data Wisuda Al-Quran dan Data Prestasi
 | Siswa), lalu "tombolnya apakah bisa sejajar dan proporsional? responsive juga".
 |
 | Beberapa penyaring di kepala kartu menyisakan `<div></div>` kosong di dalam `.row`-nya. Anak `.row` yang
 | tidak berkelas kolom mendapat `width: 100%` dari Bootstrap, jadi div kosong itu membuat BARIS KEDUA di
 | dalam form dan mendorong dasar form ke bawah — sementara tombol di sebelahnya menyejajarkan diri ke dasar
 | FORM, bukan ke kotak isiannya. Terukur di `akademik/wisuda_quran`: dasar select 186, dasar tombol 202.
 |
 | Sekeluarga dengan pita kosong KP-192..195: yang tidak menampilkan apa pun tidak boleh memakan tata letak.
 */
/* KP-202: pembungkus isi kepala (bekas `flex-column flex-xl-row`) — sebaris, membungkus sendiri saat sempit,
   dan semuanya sejajar DASAR supaya tombol sebaris dengan kotak isian, bukan melayang di tengah. */
.sisma-dt-kepala > .sisma-dt-kepala-baris {
  flex-wrap: wrap;
  align-items: flex-end;
  flex-grow: 1;
}

.sisma-dt-kepala .row > div:empty {
  display: none;
}

.sisma-dt-kepala form .row {
  --bs-gutter-x: 0.75rem;
  --bs-gutter-y: 0.5rem;
  flex-grow: 1;
  align-items: flex-end;
  /*
   | KP-203 — pemilik 21 Sep 2026: "jarak atas dan bawah nya jadi beda?"
   |
   | `margin: 0` dulu ikut membuang KOMPENSASI gutter Bootstrap. Di Bootstrap 5 `.row` memakai
   | `margin-top: calc(-1 * var(--bs-gutter-y))` untuk mengimbangi `margin-top: var(--bs-gutter-y)` yang
   | dipasang pada tiap anaknya. Kompensasinya hilang, margin anaknya tetap, jadi ada 8 px kosong di ATAS isi
   | form — dan kepala kartu terukur 24 px di atas lawan 17 px di bawah.
   |
   | Yang perlu dinolkan hanya sisi MENDATAR (negative margin `.row` menggeser isi ke luar kepala); sisi tegak
   | dikembalikan supaya penyaring yang membungkus tetap berjarak dan isinya tetap di tengah.
   */
  margin: calc(-1 * var(--bs-gutter-y)) 0 0 0;
}

.sisma-dt-kepala .card-title {
  margin-bottom: 0;
}

/*
 | KP-112: form penyaring milik tabel (`sisma-dt-penyaring`, ditandai tabel-v3.js). Penyaring ditulis dua cara
 | di aplikasi ini: pola laporan KP-100 memakai flex sehingga tombol Tampilkan menempel sesudah medan terakhir,
 | sedangkan sebagian halaman memakai kisi Bootstrap (`row` + `col-md-5/5/2`) sehingga medannya melar selebar
 | kolom dan Submit terlempar ke ujung kanan kartu. Aturan di bawah menyamakan yang kedua ke bentuk pertama:
 | kisi dilepas, medan berbagi ruang, kolom yang isinya hanya tombol tidak ikut melar.
 |
 | `align-items` sengaja tidak dipasang pada form yang ber-`flex-column` (pola KP-100 di layar kecil menyusun
 | medannya ke bawah dan sudah punya `align-items-md-end` sendiri) - kalau dipasang, medannya menciut ke kanan.
 */
.sisma-dt-penyaring {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  margin: 0;
  /* penandanya boleh dipasang pada elemen `.row` itu sendiri (KP-114), jadi selokan kisinya dinolkan
     di sini juga - kalau tidak, margin negatif `.row` menggeser isinya ke kiri 0,75rem */
  --bs-gutter-x: 0;
  --bs-gutter-y: 0;
}

.sisma-dt-penyaring:not(.flex-column) {
  align-items: flex-end;
}

/* Form yang MEMBUNGKUS kartu (markup form bersarang) tidak boleh menciutkan kartunya jadi selebar isinya. */
.sisma-dt-penyaring > .card {
  flex: 1 1 100%;
}

.sisma-dt-penyaring .row {
  --bs-gutter-x: 0;
  --bs-gutter-y: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem 0.75rem;
  flex: 1 1 100%;
  margin: 0;
}

/*
 | Kolom kisi disamakan jadi pembagi ruang seperti `.col` bawaan Bootstrap (`flex: 1 1 0`), bukan diberi
 | lebar dasar sendiri: lebar dasar membuat penyaring yang selama ini ringkas - tiga select pendek di satu
 | baris pada Rekap Presensi - melar dan pecah jadi dua baris.
 */
.sisma-dt-penyaring .col,
.sisma-dt-penyaring [class*="col-"] {
  flex: 1 1 0;
  width: auto;
  /* KP-114: satu medan penyaring tidak boleh melintang selebar kartu. Tanpa batas ini, halaman yang
     penyaringnya cuma satu (bulan di `administrasi/presensi_security`, unit di `administrasi/kelas`)
     terlihat lain sendiri dari halaman yang penyaringnya tiga atau empat. */
  max-width: 22rem;
  padding-right: 0;
  padding-left: 0;
}

.sisma-dt-penyaring .sisma-dt-penyaring-aksi {
  flex: 0 0 auto;
}

.sisma-dt-penyaring .form-label {
  margin-bottom: 0.25rem;
}

/*
 | KP-111: bantalan dan jarak bilah tabel dipusatkan di sini. Sebelumnya tiap keluarga `dom` menuliskannya
 | sendiri (`p-3 pt-0`, `mb-3`, `mt-2`, `mx-0`), sehingga bilah tabel terlihat naik-turun dan renggang-rapat
 | berbeda antar halaman; `tabel-v3.js` melepas kelas jarak itu dan ukurannya diambil alih aturan di bawah.
 */
/*
 | KP-192 — pemilik 21 Sep 2026, tangkapan layar keempat: "gambar 4 headernya kosong".
 |
 | Sebagian string `dom` menyediakan slot kepala kartu yang pada halaman tertentu tidak terisi apa pun. Di
 | `quran/rekap_nilai_iwr_bulanan` yang tersisa `div.card-header.border-bottom` setinggi 33 px berisi hanya
 | `<div class="head-label"></div>` — dan sebuah garis di bawahnya. Garis yang tidak memisahkan apa-apa.
 |
 | DISEMBUNYIKAN, BUKAN DIHAPUS, dan itu bukan kehati-hatian berlebihan: `CLAUDE.md` mencatat **34 view mengisi
 | `head-label` dari JavaScript** (penyaring bulan, judul akun, tombol tambah), dan "kalau penampungnya ikut
 | terganti, isinya hilang tanpa bekas". Percobaan pertama memang menghapus elemennya di `tabel-v3.js`; itu
 | dibatalkan sebelum sempat jalan.
 |
 | `:has()` membuat aturan ini HIDUP: begitu JavaScript halaman mengisi `head-label`, `:empty` berhenti cocok
 | dan kepalanya muncul kembali sendiri. Tidak ada tenggat waktu yang harus ditebak, dan tidak ada yang rusak
 | permanen. Peramban tanpa `:has()` mengabaikan aturan ini — yang terjadi persis keadaan hari ini, bukan lebih
 | buruk.
 |
 | `!important` di sini DISENGAJA, dan ini satu-satunya tempat hari ini yang memakainya. Kepala itu membawa
 | kelas `d-flex` — utility ber-`!important` seperti empat kasus sebelumnya (`mb-*`, `container-p-y`,
 | `border-bottom`, `pt-*`). Di empat kasus itu jawabannya membuang kelasnya; di sini TIDAK BOLEH, karena yang
 | harus dibuang adalah elemennya, dan elemen itu penampung `head-label` yang mungkin diisi JavaScript
 | halaman. Jadi yang dilawan hanya SATU properti, pada pemilih sesempit mungkin, dan hanya selama
 | penampungnya benar-benar kosong.
 |
 | Pengecualiannya sengaja ditulis sebagai "tidak ada SATU PUN anak yang berisi", bukan daftar kendali
 | (`input, select, button, …`) seperti tulisan pertamanya. Sepuluh string `dom` memasang `head-label2`
 | BERSAMA `head-label`, dan judul halaman bisa duduk di yang mana saja: kalau yang terisi `head-label2`
 | sedangkan `head-label` tetap kosong, daftar kendali tadi tidak melihat apa-apa dan kepalanya hilang
 | beserta judulnya. Bentuk ini belum dilaporkan pemilik — ditutup sebelum sempat.
 */
.sisma-page-content .card-header:has(> .head-label:empty):not(:has(> *:not(:empty))) {
  display: none !important;
}

/*
 | KP-208 — lapisan yang harus SELALU di atas modal.
 |
 | Sejak KP-207 modal bertingkat naik di atas z-index bawaan tema (1090 -> 1110 -> 1130 ...). SweetAlert2
 | memakai 1090 juga, dan sebelum KP-207 ia menang hanya karena wadahnya ditempel paling belakang di DOM.
 | Begitu ada modal kedua, dialog konfirmasi hapus yang dibuka DARI DALAM modal itu tersembunyi di
 | belakangnya - layar meredup tanpa ada yang bisa diklik. Terukur: swal 1090, modal teratas 1110.
 |
 | SweetAlert2 adalah dialog yang MEMBLOKIR; ia memang harus di atas apa pun. 20000 jauh di atas tumpukan
 | modal yang masuk akal (1090 + 20 per tingkat) dan tetap di bawah toastr (999999) yang memang paling atas.
 | 69 view memakai SweetAlert2, banyak di antaranya dari dalam modal.
 */
.swal2-container {
  z-index: 20000;
}

/*
 | KP-193 — pemilik 21 Sep 2026: "ini ada header kosong, cek lainnya juga yang kosong".
 |
 | Bentuk kedua sesudah kepala ber-`head-label` kosong (KP-192): baris tata letak DataTables yang tidak memuat
 | kendali apa pun. Di `quran/nilai_harian_iwr` string `dom`-nya menyediakan baris untuk kotak cari dan jumlah
 | baris, tetapi keduanya dimatikan, sehingga yang tersisa `div.d-flex` setinggi 12 px berisi NOL — pita kosong
 | di antara garis kepala dan tabelnya.
 |
 | `:empty` aman di sini: baris ini dibangun DataTables, bukan penampung yang diisi JavaScript halaman seperti
 | `head-label` — jadi tidak ada yang bisa hilang. Dan seperti KP-192, `!important` dipakai karena `d-flex`
 | membawanya juga.
 |
 | Pemilih kedua untuk bentuk yang ditemukan penjaga di `quran/rekap_guru_bulanan`: barisnya TIDAK kosong —
 | ia memuat dua pembungkus milik `dom` (`<"d-flex align-items-center gap-2"l>` dan pasangan `f`-nya) yang
 | masing-masing kosong karena kedua kontrolnya dimatikan. Jadi yang dituntut: ada anak elemen, dan tidak
 | ada satu pun keturunan yang berisi.
 |
 | Daftar penjaga di ujungnya BUKAN hiasan. `:empty` juga cocok untuk elemen void — `<input>`, `<img>`,
 | `<hr>` tidak punya anak menurut CSS — jadi tanpa daftar itu sebuah baris yang isinya persis satu kotak
 | isian akan dihitung kosong dan disembunyikan beserta isiannya.
 */
.sisma-page-content .dt-container > div:empty,
.sisma-page-content .dt-container > div:has(> *):not(:has(*:not(:empty))):not(:has(input, select, textarea, button, a, img, svg, canvas, table)) {
  display: none !important;
}

.dt-container .sisma-dt-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  /*
   | KP-191 — bantalan ATAS bilah kini satu angka untuk semua, `--sisma-jarak-rapat` (16 px). Dulu 0, dengan
   | anggapan selalu ada kepala kartu di atasnya yang sudah memberi ruang; di kartu tanpa kepala bilahnya jadi
   | menempel tepi (pemilik: "search pada datatable mepet keatas"), dan di kartu berkepala ia menempel garis.
   | Pemilik: "tetap gunakan garis saja tapi jangan mepet dan jangan terlalu renggang", lalu menolak 16 px
   | dengan "ini terlalu renggang". Angkanya jadi `--sisma-jarak-bilah` = 8 px: jelas tidak menempel, tetapi
   | bilahnya tetap terbaca sebagai satu kesatuan dengan kepala di atasnya.
   */
  padding: var(--sisma-jarak-bilah) 1.25rem 1rem;
}

/*
 | KP-200 — pemilik 21 Sep 2026, tangkapan layar Kode Akun: "header table atas masih tidak proporsional".
 | Bilah yang jadi blok TERATAS kartu (tidak ada kepala terlihat di atasnya) memakai bantalan kepala kartu,
 | 16 px, supaya seimbang dengan 16 px di bawahnya. `--sisma-jarak-bilah` 8 px tetap berlaku untuk bilah yang
 | duduk TEPAT DI BAWAH garis kepala — di situ keduanya memang dibaca sebagai satu kesatuan (KP-192).
 | Penandanya dipasang `tabel-v3.js` dan dinilai ulang tiap `draw.dt`: kepala yang baru diisi JavaScript
 | membuat bilahnya bukan blok teratas lagi.
 */
.dt-container .sisma-dt-toolbar.sisma-dt-toolbar-atas {
  padding-top: var(--sisma-jarak-rapat);
}

/* Bilah yang berdiri sebagai kepala kartu memakai bantalan kepala kartu, bukan bantalan badan. */
.dt-container .sisma-dt-toolbar.card-header {
  padding: 1rem 1.25rem;
}

/*
 | KP-186 — pemilik 21 Sep 2026, dengan tangkapan layar halaman Slip Gaji: "search pada datatable mepet keatas".
 |
 | Bantalan atas bilah di atas sengaja 0, karena di kebanyakan halaman ada `.card-header` tepat di atasnya yang
 | sudah memberi ruang. Di kartu yang TIDAK punya kepala, bilahnya menempel persis di tepi atas kartu — terukur
 | 0 px di `sdm/slip_gaji`, dan itulah yang terlihat. Halaman pembanding `administrasi/tahun_ajaran` punya
 | kepala kartu, jadi tampak benar; bedanya bukan pada bilahnya, melainkan pada ada tidaknya kepala kartu.
 |
 | Angkanya disamakan dengan bantalan kepala kartu di atas (1rem) supaya kedua bentuk kartu terlihat sama.
 */

/*
 | KP-186 — jarak di ATAS breadcrumb. Navbar melayang berakhir di 72 px dan breadcrumb mulai di 80 px: 8 px saja.
 | Pemilik: "jarak atas dan bawah proporsional", lalu menolak hasil pertama (16 atas lawan 24 bawah) dengan
 | "tidak proporsional", lalu menolak 24/24 dengan "terlalu renggang". Yang dituju: SAMA di atas dan di bawah,
 | dan 16 px — 8 px bawaan + 8 px di sini. Tiga kali dicoba (8/16, 16/24, 24/24) sebelum angkanya pas; ini
 | jenis keputusan yang hanya bisa diputuskan mata pemilik, bukan diturunkan dari aturan.
 */
.sisma-page-breadcrumb {
  /* 8 px sudah datang dari bantalan wilayah isi; 8 px lagi di sini melengkapinya jadi angka pakem 16 px. */
  margin-top: calc(var(--sisma-jarak-rapat) - 8px);
}

.dt-container .sisma-dt-toolbar .dt-search {
  width: min(20rem, 100%);
  margin: 0;
}

.dt-container .sisma-dt-toolbar .dt-search .input-group-text {
  color: var(--bs-secondary-color);
}

.dt-container .sisma-dt-kanan {
  margin-inline-start: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
}

.dt-container .sisma-dt-kanan > * {
  margin: 0 !important;
}

/*
 | KP-319 — KAKI tabel: info "Showing x to y of z entries" di kiri, tombol halaman di kanan. Pemilik 27 Sep 2026: "searagamkan
 | semua tabel menjadi seperti gambar 2" — gambar 1 kaki `dom` tulisan view tanpa bantalan (menempel ke tepi kartu), gambar 2
 | tata letak bawaan DataTables 2 yang berjarak dari tepi. Penandanya dipasang `tabel-v3.js` (`susunKaki`). Bantalan SAMPING
 | sama dengan bilah atas (1.25rem), jadi "Showing…" lurus di bawah kotak cari dan tombol halaman lurus di bawah Export;
 | atas-bawah `--sisma-jarak-rapat` (16 px), seimbang dengan bantalan bawah bilah atas di atas tabel. Dijaga `jarak-kartu.php`.
 */
.dt-container .sisma-dt-kaki {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
  margin: 0;
  padding: var(--sisma-jarak-rapat) 1.25rem;
}

.dt-container .sisma-dt-kaki > * {
  margin: 0 !important;
  padding: 0;
}

.dt-container .sisma-dt-kaki > .sisma-dt-kaki-halaman {
  margin-inline-start: auto !important;
}

.dt-container .sisma-dt-kaki .dt-info,
.dt-container .sisma-dt-kaki .dt-paging,
.dt-container .sisma-dt-kaki .dt-paging .pagination {
  margin: 0;
  padding: 0;
}

.dt-container .dt-length {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
}

/*
 | KP-194 — pemilik 21 Sep 2026, dua tangkapan layar berdampingan: bilah `sarpras/aset_item` jauh lebih tinggi
 | daripada bilah `administrasi/statistik_pd`. Terukur 110 px lawan 62 px.
 |
 | Sebabnya adu KEKHUSUSAN. Tema menulis `div.dt-container div.dt-length { margin: 1.5rem 0 }` (0,2,2), dan
 | aturan di atas hanya (0,2,0) — kalah. Selama ini tidak kelihatan karena `.dt-length` biasanya jadi anak
 | LANGSUNG `.sisma-dt-kanan`, yang menolnya dengan `!important`. Begitu view membungkus kontrolnya sendiri di
 | `dom` (`<"d-flex align-items-center gap-2"l>`), pembungkus itu memutus pemilih `> *` dan 24 px atas + 24 px
 | bawah kembali hidup — bilahnya membengkak 48 px tanpa satu pun isi tambahan.
 |
 | Cukup menambah satu kelas di pemilih untuk memenangkannya (0,3,0 lawan 0,2,2); `!important` tidak perlu.
 | Berlaku untuk kontrol mana pun di dalam bilah, sedalam apa pun view membungkusnya.
 */
.dt-container .sisma-dt-toolbar .dt-length,
.dt-container .sisma-dt-toolbar .dt-buttons {
  margin: 0;
}

.dt-container .dt-length label {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--bs-secondary-color);
  white-space: nowrap;
}

.dt-container .dt-length select {
  min-width: 4.75rem;
}

/* Ikon aksi di kolom Opsi yang ditulis sebagai <button class="btn btn-icon btn-text-*"> — dipakai tiga view yang
   memang butuh <button> karena ada syarat `disabled`: List Mesin Finger, Data Finger Gukar (R0.7.79) dan halaman
   Notifikasi (R0.7.74). Bentuk bawaan Vuexy untuk tombol itu lebih besar, berjarak, dan kelabu, sehingga kolom
   Opsi-nya tidak seperti 53 view lain yang memakai `<a><i class="icon-base ti … ti-sm me-25"></i></a>` polos
   (dilaporkan pemilik 9 Sep 2026, KP-102). Di sini kotak dan ukurannya dinetralkan: ikon saja, sebesar `ti-sm`
   (1,376rem), sewarna tautan. Yang `btn-text-danger` tetap merah — sama dengan ikon hapus di view lain. Pengait
   kelas, atribut data-*, tooltip, dan syarat `disabled` tidak tersentuh; kolomnya ditandai `kolom-opsi.js`. */
.sisma-page-content .sisma-col-opsi .btn.btn-icon {
  padding: 0;
  width: auto;
  height: auto;
  min-width: 0;
  line-height: 1;
  border: 0;
  background: none;
  box-shadow: none;
  color: var(--bs-link-color);
}

.sisma-page-content .sisma-col-opsi .btn.btn-icon + .btn.btn-icon {
  margin-left: .375rem;
}

/* Ukuran ikon ditentukan `width`/`height`, BUKAN `font-size` — ikonnya mask CSS (iconset.css), jadi kotaknya tidak
   ikut font-size (diukur di peramban, R0.6b.27): `icon-sm` (halaman Guru & Karyawan) 18×18 px, `ti-sm` (139 ikon di
   view lain) 20×20 px, sedangkan di dalam `btn-icon` tanpa kelas ukuran hanya 13×13 px — jauh lebih kecil, dan itu
   yang dilaporkan pemilik. Disetel 20 px, sama dengan mayoritas kolom Opsi; jarak .375rem membuat langkah antar ikon
   26 px, sama dengan halaman Guru & Karyawan. */
.sisma-page-content .sisma-col-opsi .btn.btn-icon .icon-base {
  width: 1.25rem;
  height: 1.25rem;
  font-size: 1.25rem;
}

.sisma-page-content .sisma-col-opsi .btn.btn-icon:hover,
.sisma-page-content .sisma-col-opsi .btn.btn-icon:focus,
.sisma-page-content .sisma-col-opsi .btn.btn-icon:active {
  background: none;
  box-shadow: none;
  color: var(--bs-link-hover-color);
}

.sisma-page-content .sisma-col-opsi .btn.btn-icon.btn-text-danger,
.sisma-page-content .sisma-col-opsi .btn.btn-icon.btn-text-danger:hover {
  color: var(--bs-danger);
}

.sisma-page-content .sisma-col-opsi .btn.btn-icon[disabled],
.sisma-page-content .sisma-col-opsi .btn.btn-icon:disabled {
  opacity: .4;
  cursor: not-allowed;
}

/*
 | KP-205 — editor denah lokasi (assets/vuexy-sisma/denah-v3.js).
 |
 | Satu kanvas per LANTAI, satu unit pada satu waktu, panel properti di samping. Ukurannya mengikuti pakem jarak
 | proyek ini: 16 px di sekitar blok, 8 px antar kendali dalam satu bilah.
 */
.sisma-denah {
  display: flex;
  flex-direction: column;
  gap: var(--sisma-jarak-bilah);
  outline: none;
}

.sisma-denah-bar,
.sisma-denah-alat {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sisma-jarak-bilah);
}

.sisma-denah-bar .sisma-denah-unit { width: min(16rem, 100%); }

.sisma-denah-label {
  font-size: 0.8125rem;
  color: var(--bs-secondary-color);
}

.sisma-denah-lantai {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.sisma-denah-bar-kanan {
  margin-inline-start: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
}

.sisma-denah-zoom {
  min-width: 3.5rem;
  text-align: center;
  font-size: 0.8125rem;
  color: var(--bs-secondary-color);
}

/* Isi: kanvas yang bisa digulir + panel properti. Di layar sempit panelnya turun ke bawah, bukan menghimpit. */
.sisma-denah-isi {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sisma-jarak-rapat);
  align-items: flex-start;
}

.sisma-denah-kanvas-wrap {
  flex: 1 1 28rem;
  min-width: 0;
  height: 70vh;
  overflow: auto;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  background-color: var(--bs-body-bg);
}

.sisma-denah-kanvas {
  position: relative;
  transform-origin: top left;
  background-size: 15px 15px;
  background-image:
    linear-gradient(to right, var(--bs-border-color) 1px, transparent 1px),
    linear-gradient(to bottom, var(--bs-border-color) 1px, transparent 1px);
}

.sisma-denah-kotak {
  position: absolute;
  box-sizing: border-box;
  border: 1px solid var(--bs-primary);
  background-color: rgba(var(--bs-primary-rgb), 0.18);
  color: var(--bs-body-color);
  font-size: 0.75rem;
  line-height: 1.2;
  padding: 2px 4px;
  overflow: hidden;
  cursor: move;
  touch-action: none;
  user-select: none;
}

.sisma-denah-kotak.terpilih {
  background-color: rgba(var(--bs-primary-rgb), 0.38);
  border-width: 2px;
  box-shadow: 0 0 0 1px var(--bs-primary);
}

.sisma-denah-nama {
  pointer-events: none;
  font-weight: 500;
}

/* Jaring pilih: kotak putus-putus saat menyeret di area kosong. */
.sisma-denah-jaring {
  position: absolute;
  border: 1px dashed var(--bs-primary);
  background-color: rgba(var(--bs-primary-rgb), 0.08);
  pointer-events: none;
}

.sisma-denah-panel {
  flex: 0 0 16rem;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--sisma-jarak-bilah);
}

.sisma-denah-panel-judul {
  font-weight: 600;
}

.sisma-denah-panel-kosong {
  font-size: 0.8125rem;
  color: var(--bs-secondary-color);
}

.sisma-denah-medan .form-label {
  margin-bottom: 0.125rem;
  font-size: 0.8125rem;
}

.sisma-denah-kisi {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
}

.sisma-denah-kisi .form-label {
  margin-bottom: 0.125rem;
  font-size: 0.8125rem;
}

/* KP-206: ringkasan aset yang sedang berada di ruang terpilih. */
.sisma-denah-aset {
  border-top: 1px solid var(--bs-border-color);
  padding-top: var(--sisma-jarak-bilah);
  font-size: 0.8125rem;
}

.sisma-denah-aset-judul {
  font-weight: 600;
  margin-bottom: 0.25rem;
}

.sisma-denah-aset-baris {
  color: var(--bs-secondary-color);
}

.sisma-denah-bantuan {
  font-size: 0.75rem;
  color: var(--bs-secondary-color);
}

.sisma-denah-galat {
  padding: var(--sisma-jarak-rapat);
  color: var(--bs-danger);
}

/*
 | KP-287 — status WhatsApp gateway dan scraping mutasi di header, di samping "TA : …". Titik hijau online, merah mati, abu-abu
 | belum/tidak diperiksa (pekerja cron status_kerja berhenti). Isinya dari tabel layanan_status, bukan panggilan langsung.
 */
.sisma-status-layanan {
  gap: 1rem;
  margin-inline-start: 1.5rem;
}
.sisma-status-butir {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.8125rem;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
}
.sisma-status-butir:hover {
  opacity: 0.8;
}
.sisma-status-dot {
  display: inline-block;
  flex: 0 0 auto;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
}
.sisma-status-dot.bg-success { box-shadow: 0 0 0 3px rgba(var(--bs-success-rgb), 0.2); }
.sisma-status-dot.bg-danger { box-shadow: 0 0 0 3px rgba(var(--bs-danger-rgb), 0.2); }

/*
 | KP-336 — lonceng notifikasi di header. Lencana angka (bukan titik) di pojok kanan atas ikon; daftar kabar memakai kelas Vuexy
 | dropdown-notifications. Teks kabar dibungkus (kabar panjang tidak melebarkan menu), menu selebar layar di ponsel.
 */
.sisma-kotak-lencana {
  inset-block-start: 0;
  inset-inline-start: 100%;
  min-inline-size: 1.05rem;
}
.sisma-kotak-menu {
  inline-size: 23rem;
  max-inline-size: calc(100vw - 2rem);
}
.sisma-kotak-menu .sisma-kotak-teks {
  min-inline-size: 0;
  white-space: normal;
  overflow-wrap: anywhere;
}

/*
 | KP-337 — ikon di kanan header (tema, status layanan, lonceng) berjarak rapat dan sama; titik ringkasan status layanan di pojok ikonnya
 | (layar < 1200 px — di atasnya tulisan "● WhatsApp ● Scraping" di kiri yang tampil).
 */
.layout-navbar .sisma-navbar-ikon + .sisma-navbar-ikon {
  margin-inline-start: 0.125rem;
}
.sisma-status-dot-ikon {
  position: absolute;
  inset-block-start: -0.125rem;
  inset-inline-end: -0.25rem;
  border: 2px solid var(--bs-paper-bg, var(--bs-body-bg));
  inline-size: 0.625rem;
  block-size: 0.625rem;
  box-shadow: none !important;
}
.sisma-status-menu {
  inline-size: 20rem;
  max-inline-size: calc(100vw - 2rem);
}

/*
 | KP-387 — deretan tab TURUN BARIS kalau tidak muat. core.css Vuexy 3 menulis `.nav { flex-wrap: inherit }` (+ `.nav-item
 | { white-space: nowrap }`), jadi tab yang tidak muat MELUBER ke luar kartu/modal — modal Detail Pegawai (7 tab bagi super_admin)
 | meluber di layar < ±1750 px, tab Profil di 1024 px, Aset per Unit (satu tab per unit) di semua lebar. Semua tab tetap
 | terlihat (bukan digulir tersembunyi); tab yang memang ingin satu baris bergulir tetap bisa memakai `.nav-scrollable` / `.flex-nowrap`.
 */
.nav-tabs:not(.nav-scrollable):not(.flex-nowrap),
.nav-pills:not(.nav-scrollable):not(.flex-nowrap) {
  flex-wrap: wrap;
}

/*
 | KP-387 — kisi dokumen pegawai (view `pegawai_dokumen_bagian.php`: modal Detail Pegawai + tab Dokumen Profil), pengganti
 | bootstrap-fileinput. Kartu sama tinggi: bidang gambar 4:3 (gambar utuh, tidak dipotong), kaki berisi nama + tombol.
 */
.sisma-dok-kisi {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
  gap: 1rem;
  padding-block-start: 1rem;
}
.sisma-dok-kartu {
  display: flex;
  flex-direction: column;
  min-inline-size: 0;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  background: var(--bs-paper-bg, var(--bs-body-bg));
  overflow: hidden;
}
.sisma-dok-gambar {
  position: relative;
  display: block;
  inline-size: 100%;
  aspect-ratio: 4 / 3;
  padding: 0;
  border: 0;
  background: rgba(var(--bs-secondary-rgb), 0.08);
}
button.sisma-dok-gambar {
  cursor: zoom-in;
}
button.sisma-dok-gambar:focus-visible {
  outline: 2px solid var(--bs-primary);
  outline-offset: -2px;
}
.sisma-dok-gambar img {
  position: absolute;
  inset: 0.5rem;
  inline-size: calc(100% - 1rem);
  block-size: calc(100% - 1rem);
  object-fit: contain;
}
.sisma-dok-belum {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  color: var(--bs-secondary-color);
  font-size: 0.8125rem;
}
.sisma-dok-kaki {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem;
  min-block-size: 2.75rem;
  padding: 0.25rem 0.375rem 0.25rem 0.75rem;
  border-block-start: 1px solid var(--bs-border-color);
}
.sisma-dok-judul {
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
  color: var(--bs-heading-color);
}
/* Profil: Unggah/Ganti di baris sendiri — di kaki bersama nama, nama terpotong ("NP…", "Transk…") di kartu selebar 10,5 rem. */
.sisma-dok-ubah {
  padding: 0 0.5rem 0.5rem;
}

/* Penampil gambar dokumen (KP-387): layar gelap penuh di atas halaman ATAU modal yang sedang terbuka. */
.sisma-dok-lihat {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3.75rem 4.5rem 1.5rem;
  background: rgba(0, 0, 0, 0.85);
}
.sisma-dok-lihat > img {
  max-inline-size: 100%;
  max-block-size: 100%;
  object-fit: contain;
  border-radius: 0.375rem;
  background: #fff;
}
.sisma-dok-lihat-bilah {
  position: absolute;
  inset-block-start: 0.75rem;
  inset-inline: 1rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.sisma-dok-lihat-judul {
  flex: 1;
  min-inline-size: 0;
  color: #fff;
  font-weight: 500;
}
.sisma-dok-lihat-geser {
  position: absolute;
  inset-block-start: 50%;
  transform: translateY(-50%);
}
.sisma-dok-lihat-kiri {
  inset-inline-start: 1rem;
}
.sisma-dok-lihat-kanan {
  inset-inline-end: 1rem;
}
@media (max-width: 575.98px) {
  .sisma-dok-lihat {
    padding: 3.75rem 0.5rem 4.5rem;
  }
  .sisma-dok-lihat-geser {
    inset-block-start: auto;
    inset-block-end: 1rem;
    transform: none;
  }
}

/*
 | KP-450 — pencarian lintas modul di header (cari-global.js). Layar ≥ 992 px: kotak di kiri navbar sesudah TA. Di bawahnya kotaknya
 | tersembunyi dan diganti ikon kaca pembesar di kanan; diketuk → kotak yang SAMA menutupi navbar selebar penuh (.sisma-cari-terbuka).
 | Panel hasil memakai gaya dropdown Vuexy; tidak ada pustaka baru.
 |
 | KP-454: pembungkusnya `.sisma-cari-global`, BUKAN `.sisma-cari` — nama itu sudah dipakai kotak cari SETIAP tabel (tabel-v3.js, KP-111).
 | Sampai KP-454 aturan di bawah tertulis `.sisma-cari` dan ikut mengenai semua tabel: kotak cari bergeser 20 px, selebar 18rem, dan ikonnya
 | lepas dari isiannya (align-items: center). Jangan menulis aturan untuk `.sisma-cari` polos di sini — dijaga uji-cari-global.php B8.
 */
.sisma-cari-global {
  position: relative;
  align-items: center;
  margin-inline-start: 1.25rem;
  flex: 0 0 auto;           /* tidak ikut menyusut: sisi kanan navbar (#navbar-collapse) mengambil seluruh sisa ruang */
  inline-size: 18rem;
}
@media (min-width: 992px) and (max-width: 1199.98px) {
  .sisma-cari-global { inline-size: 14rem; margin-inline-start: 1rem; }
}
.sisma-cari-global .sisma-cari-kotak .form-control::-webkit-search-cancel-button { display: none; }
.sisma-cari-kbd {
  font-size: .6875rem;
  line-height: 1;
  padding: .25rem .375rem;
  border: 1px solid var(--bs-border-color);
  border-radius: .25rem;
  color: var(--bs-secondary-color);
  white-space: nowrap;
}
.sisma-cari-hasil {
  position: absolute;
  inset-block-start: calc(100% + .5rem);
  inset-inline-start: 0;
  min-inline-size: 24rem;
  max-block-size: min(70vh, 34rem);
  overflow-y: auto;
  padding-block: .5rem;
  z-index: 1100;
}
.sisma-cari-hasil.show { display: block; }
.sisma-cari-hasil .dropdown-header { padding-block: .375rem .25rem; }
.sisma-cari-butir {
  display: flex;
  align-items: center;
  gap: .75rem;
  white-space: normal;
}
.sisma-cari-butir.aktif { background-color: var(--bs-dropdown-link-hover-bg); }
.sisma-cari-butir mark {   /* latar tipis + tebal: terbaca di tema terang dan gelap (warna primer navy tenggelam di tema gelap) */
  padding: 0 .0625rem;
  border-radius: .125rem;
  background-color: rgba(var(--bs-primary-rgb), .16);
  color: inherit;
  font-weight: 600;
}
.sisma-cari-ikon { flex-shrink: 0; color: var(--bs-secondary-color); }
.sisma-cari-teks { flex: 1 1 auto; min-inline-size: 0; }
.sisma-cari-tanda { flex-shrink: 0; }
.sisma-cari-catatan { padding: .375rem 1.25rem; font-size: .8125rem; }
@media (max-width: 991.98px) {
  .layout-navbar.sisma-cari-terbuka .sisma-cari-global {
    display: flex !important;
    position: absolute;
    inset: 0;
    z-index: 1101;
    margin: 0;
    inline-size: auto;
    max-inline-size: none;
    padding-inline: 1rem;
    gap: .5rem;
    background-color: inherit;
    border-radius: inherit;
  }
  .layout-navbar.sisma-cari-terbuka .sisma-cari-global .sisma-cari-kotak { flex: 1 1 auto; }
  .layout-navbar.sisma-cari-terbuka .sisma-cari-hasil {
    inset-inline: 0;
    inset-block-start: calc(100% + .25rem);
    min-inline-size: 0;
    max-block-size: 75vh;
  }
}
/* KP-450: di HP navbar pegawai bertambah satu ikon (cari). Supaya avatar tidak terdorong keluar di 360–375 px (administrator juga punya ikon status),
   tulisan "TA : " disembunyikan (angka tahun ajarannya tetap) dan tombol ikon 32 px di < 400 px — hanya navbar yang memuat ikon cari. */
@media (max-width: 575.98px) {
  .layout-navbar:has([data-sisma-cari-buka]) .sisma-navbar-year-awal { display: none; }
}
@media (max-width: 399.98px) {
  .layout-navbar:has([data-sisma-cari-buka]) .sisma-navbar-ikon > .btn,
  .layout-navbar:has([data-sisma-cari-buka]) .sisma-navbar-ikon > .nav-link.btn {
    inline-size: 2rem; block-size: 2rem;   /* .btn-icon Vuexy berukuran tetap 38 px; bantalan saja tidak mengecilkannya */
    padding: 0 !important;
  }
}

/*
 | KP-459 — kartu Pengguna Online di dashboard (hadir.js). Daftar berkolom-otomatis, digulir di dalam kartu kalau panjang; titik status = titik avatar
 | Vuexy (avatar-online / -away / -busy). Chip hitungan memakai .sisma-status-dot KP-287.
 */
.sisma-hadir-chip { display: inline-flex; align-items: center; gap: .375rem; }
.sisma-hadir-chip .sisma-status-dot.bg-warning { box-shadow: 0 0 0 3px rgba(var(--bs-warning-rgb), 0.2); }
.sisma-hadir-daftar {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: .75rem 1.5rem;
  max-block-size: 21rem;
  overflow-y: auto;
}
.sisma-hadir-teks { min-inline-size: 0; }
