/* =============================================================================
   theme.css — LAPISAN TEMA KOMPONEN
   Tema: "EXECUTIVE CONSTRUCTION ERP" (Navy + Gold + White)

   -----------------------------------------------------------------------------
   DITULIS ULANG TOTAL (September 2026).
   Berkas ini sebelumnya berisi 10 lapisan "ROMBAK" yang saling menimpa
   (v5 Indigo & Gold, v7 Modern Minimalis, v8 Aurora Bold, v9 Aurora Live,
   v10 Premium Polish, dst) — banyak aturan di lapisan awal sudah tidak
   pernah terpakai karena dibatalkan lapisan berikutnya, dan setiap warna
   baru harus dikejar di belasan tempat. Seluruh tumpukan itu DIBUANG dan
   diganti satu lapisan tunggal yang koheren di bawah ini.

   ATURAN PEMELIHARAAN:
   - TIDAK BOLEH ada nilai hex di berkas ini. Semua warna lewat token
     assets/css/design-system.css.
   - Satu komponen = satu blok. Jangan menambah blok "perbaikan" baru di
     bawah; sunting bloknya langsung.
   - Tanpa gradasi dekoratif, tanpa glow, tanpa glassmorphism. Gold hanya
     sebagai aksen (menu aktif, angka finansial, status menunggu approval).
   - Berkas ini murni tampilan: tidak menyentuh struktur HTML/JS.
   ========================================================================== */


/* =============================================================================
   1. SIDEBAR
   Navy pekat, hierarki jelas, menu aktif beraksen Gold.
   ========================================================================== */
.sidebar {
  background: var(--shell);
  border-right: 1px solid var(--border-shell);
  box-shadow: var(--shadow-shell);
  color: var(--text-on-shell);
}

/* -- Kepala: logo + nama aplikasi ------------------------------------------ */
.sidebar-brand {
  gap: var(--sp-3);
  border-bottom: 1px solid var(--border-shell);
}
.sidebar-logo {
  background: var(--surface);
  border: 1px solid var(--border-shell);
  box-shadow: none;
}
.sidebar-brand-text {
  font-family: var(--font-heading);
  font-weight: var(--fw-bold);
  font-size: 15px;
  letter-spacing: .02em;
  color: var(--text-on-shell-strong);
  background: none;
  -webkit-background-clip: initial;
  -webkit-text-fill-color: currentColor;
}


/* -- Navigasi -------------------------------------------------------------- */
.sidebar-nav { padding: var(--sp-3) var(--sp-3); }

/* Label seksi: huruf kecil berspasi, tenang — bukan titik/aksen berwarna. */
.nav-section {
  font-family: var(--font-heading);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--text-on-shell-mute);
  padding: var(--sp-4) var(--sp-3) var(--sp-2);
}
.sidebar-nav > .nav-section:first-child,
.sidebar-nav > .nav-group-wrap:first-child .nav-section { padding-top: var(--sp-2); }

.sidebar .nav-link {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 8px var(--sp-3);
  margin: 1px 0;
  border-radius: var(--radius-button);
  color: var(--text-on-shell);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  text-decoration: none;
  position: relative;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.sidebar .nav-link i {
  width: 18px; flex: 0 0 18px;
  text-align: center;
  font-size: 13px;
  color: var(--text-on-shell-mute);
  transition: color var(--dur) var(--ease);
}
.sidebar .nav-link:hover {
  background: rgba(255,255,255,.06);
  color: var(--text-on-shell-strong);
  text-decoration: none;
}
.sidebar .nav-link:hover i { color: var(--text-on-shell-strong); }

/* Menu aktif: bidang navy terang + batang Gold di tepi kiri (brief §3). */
.sidebar .nav-link.active {
  background: rgba(255,255,255,.10);
  color: var(--text-on-shell-strong);
  font-weight: var(--fw-semibold);
}
.sidebar .nav-link.active::before {
  content: "";
  position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 62%;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}
.sidebar .nav-link.active i { color: var(--accent); }

/* -- Grup divisi yang bisa dilipat ----------------------------------------- */
button.nav-section.nav-toggle {
  border-radius: var(--radius-sm);
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
button.nav-section.nav-toggle:hover {
  color: var(--text-on-shell);
  background: rgba(255,255,255,.05);
}
.nav-toggle .nav-toggle-label i { color: var(--text-on-shell-mute); }
.nav-toggle .nav-chevron { color: var(--text-on-shell-mute); }
.nav-toggle:hover .nav-chevron { color: var(--text-on-shell); }

.nav-group {
  margin-left: var(--sp-3);
  padding-left: var(--sp-3);
  border-left: 1px solid var(--border-shell);
}
.nav-group .nav-link { font-size: var(--fs-caption); }
.nav-group .nav-group-wrap {
  margin-left: var(--sp-2);
  padding-left: var(--sp-2);
  border-left: 1px solid var(--border-shell);
}

/* Pemisah tipis antar grup level atas agar hierarki mudah dipindai. */
.sidebar-nav > .nav-group-wrap + .nav-group-wrap,
.sidebar-nav > .nav-group-wrap + .nav-section {
  border-top: 1px solid var(--border-shell);
  margin-top: var(--sp-2);
  padding-top: var(--sp-1);
}

.sidebar-nav::-webkit-scrollbar { width: 6px; }
.sidebar-nav::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,.14); border-radius: 999px; border: 0;
}
.sidebar-nav::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.24); }

.sidebar-backdrop { backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); }


/* =============================================================================
   2. TOPBAR
   PERBAIKAN (September 2026, permintaan pengguna: "buat agar topbar dan
   sidebar seragam") -- SEBELUMNYA "Putih bersih dengan garis bawah tipis
   (brief §4)" alias var(--surface), beda total dgn sidebar yg gelap netral
   var(--shell) (lihat .sidebar, assets/css/layout.css) -- disamakan persis
   memakai var(--shell)/var(--border-shell), token YANG SAMA dipakai sidebar,
   supaya topbar+sidebar membentuk satu "shell" gelap menyatu di kedua tema
   (dulu terang/gelapnya SELALU beda dgn sidebar krn var(--surface) ikut
   berubah per tema, var(--shell) TIDAK -- lihat design-system.css). Semua
   teks/ikon DI DALAM topbar ikut disamakan ke set token "on-shell" yang
   sama dipakai sidebar (--text-on-shell*, lihat .topbar .btn-icon &
   .topbar .user-name/.user-role di bawah, assets/css/layout.css) -- efek
   sampingnya, override khusus [data-theme="dark"] yg sebelumnya perlu utk
   topbar (topbar dulu ikut berubah gelap/terang) kini tidak perlu lagi
   krn topbar SELALU gelap terlepas dari mode tema, sama seperti sidebar.
   ========================================================================== */
.topbar {
  background: var(--shell);
  border-bottom: 1px solid var(--border-shell);
  box-shadow: none;
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.topbar::after { content: none; }

.topbar-title {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-section);
  color: var(--text-on-shell-strong);
}

/* Tombol ikon topbar */
.btn-icon {
  border-radius: var(--radius-button);
  color: var(--text-muted);
  border: 1px solid transparent;
  background: transparent;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.btn-icon:hover {
  background: var(--surface-hover);
  color: var(--brand-soft);
  border-color: var(--border);
  transform: none;
}
[data-theme="dark"] .btn-icon:hover { color: var(--accent); }

.user-avatar {
  background: var(--brand-tint);
  color: var(--brand-soft);
  box-shadow: none;
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
}
[data-theme="dark"] .user-avatar { color: var(--accent); }

/* Lencana jumlah notifikasi. Cincin border PERBAIKAN (September 2026,
   "buat agar topbar dan sidebar seragam") -- SEBELUMNYA var(--surface),
   dulu dipakai spy menyatu dgn latar topbar yg ikut berubah per tema.
   Topbar kini SELALU shell gelap (sama dgn sidebar), jadi disamakan
   var(--shell) -- catatan: rule INI (bukan yg di assets/css/layout.css)
   yang menang krn theme.css dimuat belakangan (lihat urutan <link> di
   views/layouts/app.php), spesifisitas sama-sama satu kelas. */
.notif-badge {
  background: var(--danger);
  color: #fff;
  font-family: var(--font-heading);
  font-weight: var(--fw-bold);
  border: 2px solid var(--shell);
}


/* =============================================================================
   3. KERANGKA KONTEN
   ========================================================================== */
.content {
  min-width: 0;
  animation: contentIn var(--dur-slow) var(--ease);
}
@keyframes contentIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}

/* .container-fluid di dalam konten tidak boleh menambah padding ganda. */
.content > .container-fluid,
.content > .container { padding-left: 0; padding-right: 0; max-width: none; }

/* Pengerasan anti-overflow (aman untuk desktop & mobile). */
.content .row { min-width: 0; }
.content img, .content svg, .content video { max-width: 100%; height: auto; }


/* =============================================================================
   4. HEADER HALAMAN  (.page-*)
   Satu pola judul untuk SEMUA halaman: ikon, judul, sub-judul, aksi kanan.
   ========================================================================== */
.page-head { margin-bottom: var(--sp-6); }

.page-title {
  font-family: var(--font-heading);
  font-size: var(--fs-display);
  font-weight: var(--fw-bold);
  line-height: var(--lh-display);
  letter-spacing: -.015em;
  color: var(--text-strong);
  margin: 0 0 2px;
  display: flex; align-items: center; gap: var(--sp-3);
}
.page-title > i,
.page-title > .fa-solid,
.page-title > .fas { color: var(--brand-soft); font-size: .82em; }
[data-theme="dark"] .page-title > i,
[data-theme="dark"] .page-title > .fa-solid,
[data-theme="dark"] .page-title > .fas { color: var(--accent); }

.page-sub {
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--text-muted);
  margin: 0;
}

/* Normalisasi .h3 warisan di sejumlah view.
   AUDIT September 2026: selektor tambal `.content h1[style*="font-size:22px"]`
   DIHAPUS dari sini -- 23 view yang memakai inline style itu sudah diubah ke
   class .page-title, jadi tambalannya tidak punya sasaran lagi. Menyisakannya
   justru mengundang inline style baru ditulis lagi karena "toh ditimpa". */
.content h1.h3 {
  font-family: var(--font-heading);
  font-size: var(--fs-display);
  font-weight: var(--fw-bold);
  line-height: var(--lh-display);
  letter-spacing: -.015em;
  color: var(--text-strong);
}

/* Ikon hero: kotak tint navy tenang — tanpa gradasi/glow. */
.page-hero-icon,
.settings-hero-icon,
.karyawan-hero-icon {
  width: 44px; height: 44px; flex: 0 0 44px;
  border-radius: var(--radius-chip);
  display: grid; place-items: center;
  font-size: 18px;
  background: var(--brand-tint);
  color: var(--brand-soft);
  border: 1px solid var(--border);
}
[data-theme="dark"] .page-hero-icon,
[data-theme="dark"] .settings-hero-icon,
[data-theme="dark"] .karyawan-hero-icon { color: var(--accent); }

/* Chip statistik di sebelah hero */
.page-stat-row { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.page-stat {
  display: flex; align-items: baseline; gap: var(--sp-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-chip);
  padding: var(--sp-2) var(--sp-4);
  box-shadow: var(--shadow-xs);
}
.page-stat-num {
  font-family: var(--font-heading);
  font-weight: var(--fw-bold);
  font-size: var(--fs-section);
  color: var(--text-strong);
}
.page-stat-label { font-size: var(--fs-caption); color: var(--text-muted); white-space: nowrap; }
.page-stat-label i { margin-right: 2px; }

/* Ikon kecil di kepala kartu */
.page-card-icon {
  width: 30px; height: 30px; flex: 0 0 30px;
  border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px;
  background: var(--brand-tint);
  color: var(--brand-soft);
}
[data-theme="dark"] .page-card-icon { color: var(--accent); }
.page-card-desc { font-size: var(--fs-caption); color: var(--text-muted); font-weight: var(--fw-normal); }

/* Catatan kecil di bawah kartu/tabel */
.page-note {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  font-size: var(--fs-caption);
  color: var(--text-muted);
  padding: var(--sp-3) var(--pad-card) var(--sp-4);
}
.page-note i { color: var(--info); margin-top: 2px; }

/* Sub-bagian bertajuk di dalam form/modal panjang */
.page-subgroup {
  padding-top: var(--sp-4);
  margin-top: var(--sp-4);
  border-top: 1px solid var(--border-subtle);
}
.page-subgroup:first-child { padding-top: 0; margin-top: 0; border-top: 0; }
.page-subgroup-title {
  font-family: var(--font-heading);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--text-muted);
  margin-bottom: var(--sp-3);
  display: flex; align-items: center; gap: var(--sp-2);
}

/* Actionbar footer form */
.page-actionbar {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--sp-4) var(--pad-card);
}
.page-dirty-note { font-size: var(--fs-caption); color: var(--text-muted); }
.page-dirty-note i { color: var(--warning); }
@media (max-width: 575.98px) {
  .page-actionbar { justify-content: space-between; flex-wrap: wrap; }
}

/* Baris header standar: judul kiri, aksi kanan — tidak pernah turun baris. */
.content > .d-flex.justify-content-between { gap: var(--sp-3); }
@media (min-width: 576px) {
  .d-flex.justify-content-between:has(.page-hero-icon) { flex-wrap: nowrap !important; }
  .d-flex.justify-content-between:has(.page-hero-icon) > *:first-child { min-width: 0; }
  .d-flex.justify-content-between:has(.page-hero-icon) > *:last-child  { flex-shrink: 0; }
}


/* =============================================================================
   5. KARTU & KPI
   ========================================================================== */
.card {
  /* 4 sudut independen (var(--radius-card-tl/tr/br/bl), lihat
     design-system.css §6) -- bawaan sama persis var(--radius-card) di
     tiap sisi, jadi tidak ada perubahan tampilan kecuali pengguna
     men-custom salah satu sudut lewat panel Customizer. */
  border-radius: var(--radius-card-tl) var(--radius-card-tr) var(--radius-card-br) var(--radius-card-bl);
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.content .card:hover { box-shadow: var(--shadow-md); }

.card-header {
  background: transparent;
  border-bottom: 1px solid var(--border-subtle);
  padding: var(--sp-4) var(--pad-card);
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  color: var(--text-strong);
  border-radius: var(--radius-card-tl) var(--radius-card-tr) 0 0;
}
.card-footer {
  background: var(--surface-alt);
  border-top: 1px solid var(--border-subtle);
  padding: var(--sp-3) var(--pad-card);
  border-radius: 0 0 var(--radius-card-br) var(--radius-card-bl);
}

/* -- Kartu KPI: hierarki angka jelas, tanpa glow (brief §5 & §6) ----------- */
.kpi { position: relative; overflow: hidden; }
.kpi::after { content: none; }

.kpi-value {
  font-family: var(--font-numeric);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-kpi);
  line-height: var(--lh-kpi);
  font-weight: var(--fw-bold);
  letter-spacing: -.02em;
  color: var(--text-strong);
}

/* Lis warna di tepi atas DIKEMBALIKAN (September 2026, permintaan pengguna:
   "buat juga lis kartu KPI nya berwarna dengan tema") -- SEBELUMNYA (revisi
   sebelum ini) tiap varian dinetralkan jadi SATU garis abu yang sama
   (var(--border-strong)) di seluruh app supaya "rapi". Pengguna sekarang
   minta lis itu berwarna LAGI, TAPI warnanya harus otomatis IKUT tema
   (preset warna aksen di panel Customizer utk teal/amber, warna status utk
   ok/danger/info) -- bukan hex tetap seperti versi paling awal dulu. Jadi
   border-top-color di sini SELALU disamakan persis dgn token `color:` di
   baris yang sama (bukan var(--border-strong) lagi): kalau customizer.js
   mengganti --gold-400/700, teal & amber (warna & garisnya, dua-duanya
   turunan --gold-*) ikut berubah otomatis; ok/danger/info tetap warna
   status masing-masing (hijau/merah/biru, TIDAK ikut aksen -- makna
   status/risiko harus tetap konsisten terlepas dari preset warna yang
   dipilih pengguna). */
.kpi           { border-top: 3px solid var(--border-strong); }
.kpi-teal      { border-top-color: var(--brand-soft);   color: var(--brand-soft); }
.kpi-amber     { border-top-color: var(--gold-fg);      color: var(--gold-fg); }
.kpi-ok        { border-top-color: var(--success-fg);   color: var(--success); }
.kpi-danger    { border-top-color: var(--danger-fg);    color: var(--danger); }
.kpi-info      { border-top-color: var(--info-fg);      color: var(--info); }
/* [data-theme="dark"] .kpi-teal DULU dipatok var(--navy-300) (warna navy
   tetap, TIDAK ikut berubah walau preset warna aksen di panel Customizer
   diganti -- laporan pengguna September 2026: "kartu KPI yang mempunyai
   tulisan seperti tema lisnya juga [harus] mengikuti ... warna temanya").
   Disamakan ke var(--brand-soft) -- token YANG SAMA dipakai versi terang
   di atas (baris ".kpi-teal" dasar), turunan var(--gold-400) di mode gelap
   (lihat design-system.css §1 blok [data-theme="dark"]) sehingga IKUT
   berubah tiap kali pengguna ganti preset warna aksen (customizer.js
   ACCENT_PRESETS menimpa --gold-400 dkk secara inline). Garisnya kini
   disamakan persis (bukan var(--border-strong)) spy lis JUGA ikut aksen di
   mode gelap, bukan cuma teksnya. */
[data-theme="dark"] .kpi-teal { border-top-color: var(--brand-soft); color: var(--brand-soft); }

/* PERBAIKAN logika warna tulisan (September 2026, permintaan pengguna:
   "perbaiki logika warna tulisan yang mengikuti tema"): ".kpi-value" (angka
   nominal besar) di atas SELALU dipatok var(--text-strong) (netral) apapun
   varian kartunya -- `color:` per varian (.kpi-teal/.kpi-amber/.kpi-ok/dst
   di atas) TIDAK pernah sampai ke angka krn ".kpi-value" mendeklarasikan
   color sendiri (menimpa inherit). Akibatnya HANYA ikon (".kpi-icon", lewat
   currentColor) yang berwarna sesuai jenis kartu, angkanya sendiri selalu
   abu-abu -- utk .kpi-teal/.kpi-amber ini sudah ditambal terpisah di
   dashboard.css (".kpi-teal .kpi-value"/".kpi-amber .kpi-value" pakai
   var(--gold-fg)), tapi .kpi-ok/.kpi-danger/.kpi-info tidak pernah dapat
   tambalan yang sama. Ditambahkan di sini, pola SAMA persis (token "-fg" yg
   memang dirancang utk teks kontras-aman di atas kartu putih, lihat
   design-system.css §1 -- --success-fg/--danger-fg/--info-fg, sebelumnya
   hanya dipakai di badge/alert) supaya angka KPI status juga ikut berwarna
   sesuai jenisnya, konsisten dgn teal/amber & dgn lis warnanya di atas. */
.kpi-ok        .kpi-value { color: var(--success-fg); }
.kpi-danger    .kpi-value { color: var(--danger-fg); }
.kpi-info      .kpi-value { color: var(--info-fg); }

.kpi-icon {
  position: absolute; top: var(--sp-4); right: var(--pad-card);
  width: 36px; height: 36px;
  border-radius: var(--radius-chip);
  display: grid; place-items: center;
  font-size: 15px;
  opacity: 1;
  background: color-mix(in srgb, currentColor 12%, transparent);
}
.kpi:hover { transform: none; }

.divisi-chip { border-radius: var(--radius-chip); box-shadow: none; }


/* =============================================================================
   6. TABEL  (brief §9)
   Header tegas, garis tipis horizontal saja, angka rata kanan, hover baris.
   ========================================================================== */
.table {
  --bs-table-color: var(--text);
  --bs-table-bg: transparent;
  --bs-table-border-color: var(--border-subtle);
  --bs-table-striped-color: var(--text);
  --bs-table-striped-bg: var(--surface-alt);
  --bs-table-hover-color: var(--text);
  --bs-table-hover-bg: var(--surface-hover);
  --bs-table-active-color: var(--text);
  --bs-table-active-bg: var(--surface-hover);
  color: var(--text);
  font-size: var(--fs-sm);
  margin-bottom: 0;
  border-color: var(--border-subtle);
}

/* Wadah tabel: sudut membulat + garis luar tunggal (bukan border tiap sisi). */
.table-responsive,
.table-container {
  border: 1px solid var(--border);
  border-radius: var(--radius-table);
  overflow: auto;
  background: var(--surface);
}
/* Kartu yang isinya HANYA tabel: hilangkan garis ganda. */
.card > .table-responsive { border: 0; border-radius: 0; }
.card > .table-responsive:last-child { border-radius: 0 0 var(--radius-card-br) var(--radius-card-bl); }

.table > thead > tr > th,
.table > thead > tr > td,
.table-light > tr > th,
thead.table-light > tr > th {
  background: var(--bg-sunken);
  color: var(--text-muted-strong);
  font-family: var(--font-heading);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: .045em;
  white-space: nowrap;
  padding: var(--sp-3) var(--pad-cell-x);
  border-bottom: 1px solid var(--border);
  border-top: 0;
  vertical-align: middle;
}

.table > tbody > tr > td {
  padding: var(--pad-cell-y) var(--pad-cell-x);
  border-top: 0;
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: middle;
  color: var(--text);
}
.table > tbody > tr:last-child > td { border-bottom: 0; }

.table-hover > tbody > tr:hover > td,
.table-hover > tbody > tr:hover > th { background: var(--surface-hover); }

/* Baris terpilih & baris anak (nota, rincian) */
.table > tbody > tr.row-selected > td { background: var(--brand-tint); }
.table > tbody > tr.child > td,
.table > tbody > tr.nota-child > td {
  background: var(--surface-alt);
  font-size: var(--fs-caption);
  color: var(--text-muted);
}

/* Kaki tabel / baris total */
.table > tfoot > tr > td,
.table > tfoot > tr > th,
.table tr.total-row > td {
  background: var(--bg-sunken);
  font-family: var(--font-heading);
  font-weight: var(--fw-bold);
  color: var(--text-strong);
  border-top: 2px solid var(--border-strong);
  padding: var(--sp-3) var(--pad-cell-x);
}

/* Angka finansial: selalu rata kanan & tabular. */
.table td.num, .table th.num,
.table td.money, .table th.money,
.table .text-end { text-align: right; }
.table td.num, .table td.money {
  font-family: var(--font-numeric);
  font-variant-numeric: tabular-nums;
}

/* Kolom aksi: tombol kecil, tidak menyita lebar. */
.table td .btn-sm,
.table td .btn-icon { padding: 3px 9px; font-size: var(--fs-caption); }
.table td.col-aksi, .table th.col-aksi { width: 1%; white-space: nowrap; text-align: center; }

/* Judul kolom yang di dalamnya ada <a>/tombol sort */
.table thead a { color: inherit; text-decoration: none; }
.table thead a:hover { color: var(--brand-soft); }
[data-theme="dark"] .table thead a:hover { color: var(--accent); }

/* CSS MATI DIHAPUS (audit September 2026): `.table .row-empty > td` (padding
   32px atas+bawah) tidak dirujuk satu pun view/JS -- pola resmi untuk keadaan
   kosong adalah `.empty-state` di ui-components.css. */

/* BUG DITEMUKAN & DIPERBAIKI (audit September 2026): di sini dulu ada
   `.rekap-bar` sebagai PANEL flex (border + padding 12/16px). Nama yang sama
   dipakai dashboard.css sebagai BATANG PROGRES setinggi 6px -- dan itulah
   satu-satunya pemakai nyatanya (assets/js/dashboard.js merender
   <div class="rekap-bar"><span style="width:X%"></span></div>). Karena
   box-sizing:border-box, height:6px + padding + border membuat tinggi
   content-box jadi 0px, sehingga <span> persentasenya (height:100%)
   TIDAK PERNAH TERLIHAT sama sekali -- batang progres Dashboard kosong
   melompong. Blok panel ini dihapus (tidak ada satu pun view yang
   memakainya); definisi yang benar ada di dashboard.css. */


/* =============================================================================
   7. TOMBOL  (brief §7)
   Radius 9px, ukuran tenang, satu bahasa untuk semua varian.
   ========================================================================== */
.btn {
  --bs-btn-border-radius: var(--radius-button);
  border-radius: var(--radius-button);
  font-family: var(--font-heading);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  line-height: 1.5;
  padding: 7px 15px;
  border-width: 1px;
  box-shadow: none;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.btn:focus, .btn:active:focus { box-shadow: none; }
.btn:focus-visible { box-shadow: var(--ring); outline: none; }
.btn-sm { padding: 4px 11px; font-size: var(--fs-caption); border-radius: var(--radius-sm); }
.btn-lg { padding: 10px 20px; font-size: var(--fs-body); }
.btn i { font-size: .92em; }

/* Primer / merk — GOLD solid (permintaan pengguna: tombol utama Gold).
   Memakai token --accent (gold), BUKAN --brand (yang kini near-black netral).
   Karena Gold terang, teks di atasnya memakai --brand-foreground (ink gelap),
   BUKAN #fff — kalau putih akan hilang. */
.btn-primary, .btn-brand {
  --bs-btn-bg: var(--accent); --bs-btn-border-color: var(--accent); --bs-btn-color: var(--brand-foreground);
  --bs-btn-hover-bg: var(--accent-strong); --bs-btn-hover-border-color: var(--accent-strong); --bs-btn-hover-color: var(--brand-foreground);
  --bs-btn-active-bg: var(--accent-strong); --bs-btn-active-border-color: var(--accent-strong); --bs-btn-active-color: var(--brand-foreground);
  --bs-btn-disabled-bg: var(--accent); --bs-btn-disabled-border-color: var(--accent); --bs-btn-disabled-color: var(--brand-foreground);
  font-weight: var(--fw-semibold);
}
.btn-primary:focus-visible, .btn-brand:focus-visible { box-shadow: var(--ring-accent); }
/* PERBAIKAN KONTRAS (September 2026): kalau .btn-brand/.btn-primary dipakai di
   tag <a> (bukan <button> -- mis. tombol "Profil" di Data Karyawan & "Ubah Hak
   Akses di sini" di Profil Karyawan), di mode gelap selector umum
   "[data-theme=dark] a" (design-system.css §DASAR DOKUMEN) MENIMPA warna teks
   jadi --gold-400 krn spesifisitasnya (atribut+elemen) lebih tinggi drpd
   ".btn-brand"/".btn-primary" (cuma 1 class) -- --gold-400 (emas terang) di
   atas latar --accent (emas sedang, gold-500) kontrasnya cuma ~1.2:1, teks
   nyaris tak kelihatan. Tombol <button> aman krn selector "a" tidak match. */
[data-theme="dark"] a.btn-primary,
[data-theme="dark"] a.btn-brand { color: var(--brand-foreground); }

/* Aksen — gold, khusus tindakan finansial/penekanan (dipakai hemat) */
.btn-accent, .btn-warning {
  --bs-btn-bg: var(--accent); --bs-btn-border-color: var(--accent); --bs-btn-color: var(--navy-950);
  --bs-btn-hover-bg: var(--accent-strong); --bs-btn-hover-border-color: var(--accent-strong); --bs-btn-hover-color: var(--navy-950);
  --bs-btn-active-bg: var(--accent-strong); --bs-btn-active-border-color: var(--accent-strong); --bs-btn-active-color: var(--navy-950);
  --bs-btn-disabled-bg: var(--accent); --bs-btn-disabled-border-color: var(--accent); --bs-btn-disabled-color: var(--navy-950);
  font-weight: var(--fw-semibold);
}
.btn-accent:focus-visible, .btn-warning:focus-visible { box-shadow: var(--ring-accent); }

.btn-success {
  --bs-btn-bg: var(--success); --bs-btn-border-color: var(--success); --bs-btn-color: #fff;
  --bs-btn-hover-bg: color-mix(in srgb, var(--success) 85%, #000);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--success) 85%, #000);
  --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: color-mix(in srgb, var(--success) 80%, #000);
  --bs-btn-disabled-bg: var(--success); --bs-btn-disabled-border-color: var(--success);
}
.btn-danger {
  --bs-btn-bg: var(--danger); --bs-btn-border-color: var(--danger); --bs-btn-color: #fff;
  --bs-btn-hover-bg: color-mix(in srgb, var(--danger) 85%, #000);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--danger) 85%, #000);
  --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: color-mix(in srgb, var(--danger) 80%, #000);
  --bs-btn-disabled-bg: var(--danger); --bs-btn-disabled-border-color: var(--danger);
}
.btn-info {
  --bs-btn-bg: var(--info); --bs-btn-border-color: var(--info); --bs-btn-color: #fff;
  --bs-btn-hover-bg: color-mix(in srgb, var(--info) 85%, #000);
  --bs-btn-hover-border-color: color-mix(in srgb, var(--info) 85%, #000);
  --bs-btn-hover-color: #fff;
}

/* Sekunder / netral — putih dengan garis (brief §7) */
.btn-secondary, .btn-light, .btn-outline-secondary, .btn.grey {
  --bs-btn-bg: var(--surface); --bs-btn-border-color: var(--border-strong); --bs-btn-color: var(--text);
  --bs-btn-hover-bg: var(--surface-hover); --bs-btn-hover-border-color: var(--border-strong); --bs-btn-hover-color: var(--text-strong);
  --bs-btn-active-bg: var(--bg-sunken); --bs-btn-active-border-color: var(--border-strong); --bs-btn-active-color: var(--text-strong);
  --bs-btn-disabled-bg: var(--surface); --bs-btn-disabled-border-color: var(--border); --bs-btn-disabled-color: var(--text-faint);
}
/* Tombol "dark" = near-black netral (bukan Gold) supaya tetap ada varian gelap
   klasik di samping tombol primary Gold. */
.btn-dark, .btn-outline-dark {
  --bs-btn-bg: var(--navy-900); --bs-btn-border-color: var(--navy-900); --bs-btn-color: #fff;
  --bs-btn-hover-bg: var(--navy-800); --bs-btn-hover-border-color: var(--navy-800); --bs-btn-hover-color: #fff;
}

/* Varian outline */
.btn-outline-primary {
  --bs-btn-color: var(--brand-soft); --bs-btn-border-color: var(--border-strong);
  --bs-btn-hover-bg: var(--accent); --bs-btn-hover-border-color: var(--accent); --bs-btn-hover-color: var(--brand-foreground);
  --bs-btn-active-bg: var(--accent-strong); --bs-btn-active-border-color: var(--accent-strong); --bs-btn-active-color: var(--brand-foreground);
}
.btn-outline-danger {
  --bs-btn-color: var(--danger); --bs-btn-border-color: var(--danger-border);
  --bs-btn-hover-bg: var(--danger); --bs-btn-hover-border-color: var(--danger); --bs-btn-hover-color: #fff;
}
.btn-outline-success {
  --bs-btn-color: var(--success); --bs-btn-border-color: var(--success-border);
  --bs-btn-hover-bg: var(--success); --bs-btn-hover-border-color: var(--success); --bs-btn-hover-color: #fff;
}
.btn-outline-warning {
  --bs-btn-color: var(--gold-fg); --bs-btn-border-color: var(--gold-border);
  --bs-btn-hover-bg: var(--accent); --bs-btn-hover-border-color: var(--accent); --bs-btn-hover-color: var(--navy-950);
}
[data-theme="dark"] .btn-outline-primary { --bs-btn-color: var(--gold-400); }

.btn-link {
  --bs-btn-color: var(--brand-soft); --bs-btn-hover-color: var(--brand);
  text-decoration: none; font-weight: var(--fw-medium);
}
.btn-link:hover { text-decoration: underline; }
[data-theme="dark"] .btn-link { --bs-btn-color: var(--gold-400); --bs-btn-hover-color: var(--gold-300); }

.btn-group > .btn { box-shadow: none; }
.btn-close:focus { box-shadow: var(--ring); }
[data-theme="dark"] .btn-close { filter: invert(1) grayscale(100%) brightness(1.9); }


/* =============================================================================
   8. FORM & INPUT  (brief §8)
   Satu tampilan untuk input, select, textarea, date picker, search, filter.
   ========================================================================== */
.form-label {
  font-family: var(--font-heading);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--text);
  margin-bottom: 5px;
  letter-spacing: .005em;
}
.form-label .req, .form-label .text-danger { color: var(--danger); }

.form-control, .form-select,
input[type="text"].form-control, input[type="date"].form-control,
input[type="number"].form-control, textarea.form-control {
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  color: var(--text);
  font-size: var(--fs-sm);
  padding: 8px 12px;
  line-height: 1.5;
  box-shadow: none;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
              background-color var(--dur) var(--ease);
}
.form-control-sm, .form-select-sm { padding: 5px 10px; font-size: var(--fs-caption); border-radius: var(--radius-sm); }
.form-control-lg, .form-select-lg { padding: 10px 14px; font-size: var(--fs-body); }

.form-control::placeholder { color: var(--text-faint); opacity: 1; }

.form-control:hover:not(:disabled):not(:focus),
.form-select:hover:not(:disabled):not(:focus) { border-color: var(--border-strong); }

.form-control:focus, .form-select:focus {
  background-color: var(--surface);
  border-color: var(--brand-soft);
  box-shadow: var(--ring);
  outline: none;
  color: var(--text);
}
[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .form-select:focus { border-color: var(--accent); box-shadow: var(--ring-accent); }

.form-control:disabled, .form-select:disabled,
.form-control[readonly] {
  background-color: var(--bg-sunken);
  color: var(--text-muted);
  border-color: var(--border-subtle);
  cursor: not-allowed;
}

/* State error & valid — jelas, konsisten (brief §8). */
.form-control.is-invalid, .form-select.is-invalid, .was-validated .form-control:invalid {
  border-color: var(--danger);
  background-image: none;
  padding-right: 12px;
}
.form-control.is-invalid:focus, .form-select.is-invalid:focus { box-shadow: var(--ring-danger); border-color: var(--danger); }
.invalid-feedback, .form-error {
  display: block;
  color: var(--danger);
  font-size: var(--fs-caption);
  margin-top: 5px;
}
.invalid-feedback::before, .form-error::before {
  content: "\f06a"; font-family: "Font Awesome 6 Free"; font-weight: 900;
  margin-right: 5px; font-size: .92em;
}
.form-control.is-valid, .form-select.is-valid { border-color: var(--success); background-image: none; }
.valid-feedback { color: var(--success); font-size: var(--fs-caption); }

.form-text, .form-help {
  color: var(--text-muted);
  font-size: var(--fs-caption);
  margin-top: 5px;
}

/* Select: panah sendiri agar sama di semua peramban & kedua tema. */
.form-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%2364748B'%3E%3Cpath d='M8 11L3 6h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 14px;
  padding-right: 32px;
}

/* Checkbox & radio */
.form-check-input {
  border-color: var(--border-strong);
  background-color: var(--surface);
  width: 16px; height: 16px; margin-top: .18em;
}
.form-check-input:checked { background-color: var(--brand); border-color: var(--brand); }
.form-check-input:focus { border-color: var(--brand-soft); box-shadow: var(--ring); }
.form-check-label { font-size: var(--fs-sm); color: var(--text); }
.form-switch .form-check-input:checked { background-color: var(--success); border-color: var(--success); }

/* Kelompok input (prefix Rp, satuan, tombol cari) */
.input-group > .form-control, .input-group > .form-select { border-radius: var(--radius-input); }
.input-group-text {
  background: var(--bg-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  color: var(--text-muted);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  padding: 8px 12px;
}
.input-group:focus-within .input-group-text { border-color: var(--brand-soft); }

/* Panel filter — pola yang sama di semua halaman daftar. */
.filter-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  /* PADDING SENDIRI DIHAPUS (permintaan pengguna, September 2026: panel filter
     "terlalu berjarak" & "terlihat lebar sekali").
     SEBABNYA padding DOBEL: di SELURUH halaman, kelas ini selalu dipasang
     bersama .card dan isinya dibungkus .card-body py-3 --
       <div class="card mb-3 filter-panel"><div class="card-body py-3">
     -- sehingga jarak dalamnya = padding .filter-panel (16px/20px) DITAMBAH
     padding .card-body (12px vertikal dari py-3, 20px horizontal). Total 28px
     atas-bawah & 40px kiri-kanan: itulah kenapa tulisan FILTER terlihat
     menggantung jauh dari tepi kartu dan isinya terasa melebar.
     Sekarang padding sepenuhnya diserahkan ke .card-body (satu sumber), jadi
     rapat & konsisten dgn kartu lain di aplikasi. Tidak ada halaman yang
     memakai .filter-panel TANPA .card/.card-body (sudah diperiksa satu per
     satu), jadi tidak ada yang kehilangan padding karena perubahan ini. */
  margin-bottom: var(--gap-card);
  box-shadow: var(--shadow-xs);
}
.filter-panel-title {
  display: flex; align-items: center; gap: var(--sp-2);
  font-family: var(--font-heading);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  /* JARAK ANTAR HURUF (permintaan pengguna, September 2026: tulisan "FILTER"
     "terlihat lebar sekali ... spasinya berjarak sekali"). SEBELUMNYA memakai
     token bersama --tracking-caps (.07em) yang memang disetel untuk label
     kapital yang PANJANG & kecil (mis. judul kolom kartu KPI) -- di kata
     sependek "FILTER" jaraknya jadi terlalu renggang & hurufnya terbaca
     terpisah-pisah. Diberi nilai sendiri di sini (.02em: masih rapi sbg teks
     kapital, tidak lagi melebar) -- token --tracking-caps SENGAJA TIDAK
     diubah supaya seluruh label kapital lain di aplikasi tidak ikut berubah. */
  letter-spacing: .02em;
  color: var(--text-muted);
  margin-bottom: var(--sp-3);
}
.filter-panel-title i { color: var(--brand-soft); }
[data-theme="dark"] .filter-panel-title i { color: var(--accent); }
.filter-panel.has-active-filter { border-color: var(--brand-soft); }
[data-theme="dark"] .filter-panel.has-active-filter { border-color: var(--accent); }

/* Pencarian cepat */
.quick-search { position: relative; }
.quick-search input {
  padding-left: 34px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
}
.quick-search > i, .quick-search .qs-icon {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  color: var(--text-faint); font-size: 13px; pointer-events: none;
}


/* =============================================================================
   9. BADGE BOOTSTRAP  (selaras .badge-status di app.css)
   ========================================================================== */
.badge {
  border-radius: var(--radius-badge);
  font-family: var(--font-heading);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  padding: 3px 10px;
  letter-spacing: .01em;
}
.badge.bg-success, .badge.text-bg-success {
  background-color: var(--success-bg) !important; color: var(--success-fg) !important;
  border: 1px solid var(--success-border);
}
.badge.bg-danger, .badge.text-bg-danger {
  background-color: var(--danger-bg) !important; color: var(--danger-fg) !important;
  border: 1px solid var(--danger-border);
}
.badge.bg-warning, .badge.text-bg-warning {
  background-color: var(--gold-bg) !important; color: var(--gold-fg) !important;
  border: 1px solid var(--gold-border);
}
.badge.bg-info, .badge.text-bg-info {
  background-color: var(--info-bg) !important; color: var(--info-fg) !important;
  border: 1px solid var(--info-border);
}
.badge.bg-secondary, .badge.text-bg-secondary {
  background-color: var(--neutral-bg) !important; color: var(--neutral-fg) !important;
  border: 1px solid var(--neutral-border);
}
.badge.bg-primary, .badge.text-bg-primary {
  background-color: var(--brand-tint) !important; color: var(--brand-soft) !important;
  border: 1px solid var(--border-strong);
}
[data-theme="dark"] .badge.bg-primary, [data-theme="dark"] .badge.text-bg-primary { color: var(--navy-300) !important; }

/* Warna teks utilitas Bootstrap dipetakan ke token status. */
.text-success { color: var(--success-fg) !important; }
.text-danger  { color: var(--danger-fg)  !important; }
.text-warning { color: var(--gold-fg) !important; }
.text-info    { color: var(--info-fg)    !important; }
.text-primary { color: var(--brand-soft) !important; }
[data-theme="dark"] .text-primary { color: var(--navy-300) !important; }


/* =============================================================================
   10. CHIP ARUS KAS (Masuk / Keluar / Catat)
   ========================================================================== */
.arus-in, .arus-out, .arus-catat {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 10px;
  border-radius: var(--radius-badge);
  font-family: var(--font-heading);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  border: 1px solid transparent;
}
.arus-in    { background: var(--success-bg); color: var(--success-fg); border-color: var(--success-border); }
.arus-out   { background: var(--danger-bg);  color: var(--danger-fg);  border-color: var(--danger-border); }
.arus-catat { background: var(--neutral-bg); color: var(--neutral-fg); border-color: var(--neutral-border); }


/* =============================================================================
   11. MODAL  (radius 16px — brief §12)
   ========================================================================== */
.modal-content {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-modal);
  box-shadow: var(--shadow-modal);
}
.modal-header {
  border-bottom: 1px solid var(--border-subtle);
  padding: var(--sp-4) var(--sp-6);
  border-radius: var(--radius-modal) var(--radius-modal) 0 0;
}
.modal-title {
  font-family: var(--font-heading);
  font-size: var(--fs-section);
  font-weight: var(--fw-semibold);
  color: var(--text-strong);
  display: flex; align-items: center; gap: var(--sp-2);
}
.modal-title i { color: var(--brand-soft); font-size: .9em; }
[data-theme="dark"] .modal-title i { color: var(--accent); }
.modal-body   { padding: var(--sp-5) var(--sp-6); }
/* FIX (permintaan pengguna, September 2026: "form tidak dapat di scroll ke
   bawah sehingga tidak bisa edit keterangan transaksi") -- form Transaksi
   (& modal panjang lain yang pakai .modal-dialog-scrollable, mis. RAP di
   Daftar Pekerjaan) berisi banyak <div class="row g-3"> bersarang, yang
   masing-masing adalah flex container (Bootstrap .row = display:flex).
   .modal-body sendiri adalah flex ITEM di dalam .modal-content (flex
   column, dipasang Bootstrap). SECARA BAWAAN flex item punya
   `min-height: auto`, artinya tinggi minimumnya dihitung dari KONTEN di
   dalamnya (bukan 0) -- begitu konten (baris .row g-3 bersarang di atas)
   makin panjang/tinggi krn field bertambah (mis. field baru Sumber
   Pembayaran, Kegiatan, dst.), .modal-body ikut "memaksa" tinggi
   .modal-content melebihi batas layar alih-alih terpotong & memicu
   overflow-y:auto miliknya sendiri -- hasilnya modal terlihat "macet",
   tidak bisa discroll turun sampai ke field paling bawah (Keterangan,
   Lampiran, dst di dalam "Rincian opsional"). min-height:0 di sini
   MEMATIKAN pembesaran otomatis itu, memaksa .modal-body benar-benar
   terkurung tinggi .modal-content (yang sudah dibatasi max-height oleh
   .modal-dialog-scrollable bawaan Bootstrap) sehingga overflow-y:auto-nya
   betul-betul aktif & bisa discroll. Ini perbaikan CSS murni, tidak
   mengubah tampilan modal yang isinya sudah muat 1 layar. */
.modal-dialog-scrollable .modal-body { min-height: 0; }
.modal-footer {
  border-top: 1px solid var(--border-subtle);
  padding: var(--sp-4) var(--sp-6);
  gap: var(--sp-2);
  background: var(--surface-alt);
  border-radius: 0 0 var(--radius-modal) var(--radius-modal);
}
.modal-backdrop.show { opacity: .5; background: var(--navy-950); }


/* =============================================================================
   12. DROPDOWN
   ========================================================================== */
.dropdown-menu {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg);
  padding: 6px;
  color: var(--text);
  font-size: var(--fs-sm);
}
.dropdown-item {
  border-radius: var(--radius-sm);
  padding: 7px 12px;
  color: var(--text);
  display: flex; align-items: center; gap: var(--sp-2);
}
.dropdown-item i { width: 16px; text-align: center; color: var(--text-muted); font-size: .9em; }
.dropdown-item:hover, .dropdown-item:focus {
  background: var(--surface-hover); color: var(--text-strong);
}
.dropdown-item:hover i { color: var(--brand-soft); }
[data-theme="dark"] .dropdown-item:hover i { color: var(--accent); }
.dropdown-item.active, .dropdown-item:active {
  background: var(--brand); color: #fff;
}
.dropdown-item.active i, .dropdown-item:active i { color: #fff; }
.dropdown-item.disabled, .dropdown-item:disabled { color: var(--text-faint); }
.dropdown-divider { border-color: var(--border-subtle); margin: 5px 0; }
.dropdown-header {
  font-family: var(--font-heading);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--text-muted);
  padding: 8px 12px 4px;
}
.dropdown-item-danger, .dropdown-item.text-danger { color: var(--danger) !important; }
.dropdown-item-danger:hover, .dropdown-item.text-danger:hover { background: var(--danger-bg); }


/* =============================================================================
   13. TAB
   ========================================================================== */
.nav-tabs {
  border-bottom: 1px solid var(--border);
  gap: 2px;
  margin-bottom: var(--sp-5);
}
.nav-tabs .nav-link {
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  color: var(--text-muted);
  font-family: var(--font-heading);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  padding: 9px 14px;
  display: inline-flex; align-items: center; gap: var(--sp-2);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.nav-tabs .nav-link:hover { color: var(--text); border-bottom-color: var(--border-strong); }
.nav-tabs .nav-link.active {
  background: transparent;
  color: var(--brand);
  border-bottom-color: var(--accent);
  font-weight: var(--fw-semibold);
}
[data-theme="dark"] .nav-tabs .nav-link.active { color: var(--text-strong); }

/* Varian pil (dipakai halaman gaya admin) */
.page-pill-tabs { border-bottom: 0; gap: var(--sp-2); }
.page-pill-tabs .nav-link {
  border: 1px solid var(--border);
  border-radius: var(--radius-button);
  background: var(--surface);
  color: var(--text-muted);
  padding: 7px 16px;
  font-weight: var(--fw-medium);
}
.page-pill-tabs .nav-link:hover {
  background: var(--surface-hover); color: var(--text); border-color: var(--border-strong);
}
.page-pill-tabs .nav-link.active {
  background: var(--brand); border-color: var(--brand); color: #fff; box-shadow: none;
}
.page-pill-tabs--sub .nav-link { padding: 6px 14px; font-size: var(--fs-caption); }


/* =============================================================================
   14. PAGINATION  (brief §9)
   ========================================================================== */
.pagination {
  --bs-pagination-border-radius: var(--radius-button);
  gap: 4px;
  margin: 0;
}
.page-link {
  border: 1px solid var(--border);
  border-radius: var(--radius-button);
  color: var(--text);
  background: var(--surface);
  font-family: var(--font-heading);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  padding: 6px 12px;
  min-width: 34px;
  text-align: center;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.page-link:hover { background: var(--surface-hover); color: var(--text-strong); border-color: var(--border-strong); }
.page-link:focus { box-shadow: var(--ring); }
.page-item.active .page-link {
  background: var(--brand); border-color: var(--brand); color: #fff;
}
.page-item.disabled .page-link {
  background: var(--surface); color: var(--text-faint); border-color: var(--border-subtle);
}

/* Baris pagination + info jumlah data */
.pagination-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); flex-wrap: wrap;
  padding: var(--sp-3) var(--pad-card);
  border-top: 1px solid var(--border-subtle);
}
.pagination-info { font-size: var(--fs-caption); color: var(--text-muted); }


/* =============================================================================
   15. ALERT
   ========================================================================== */
.alert {
  border-radius: var(--radius-chip);
  border: 1px solid transparent;
  border-left-width: 3px;
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-sm);
  margin-bottom: var(--gap-card);
}
/* PERBAIKAN TAMPILAN (September 2026, laporan pengguna: kotak peringatan
   "Restore Database" di halaman Backup & Restore tampil patah/berantakan).
   Sebab: baris di atas dulu memaksa `display:flex` pada SEMUA .alert.
   Flexbox memperlakukan tiap teks lepas & elemen inline (<strong>, dst.)
   langsung di dalam .alert sebagai flex-item TERPISAH, sehingga paragraf
   yang isinya campuran teks + <strong> (mis. "Hati-hati. Restore akan
   menimpa seluruh data...") tidak lagi mengalir sebagai SATU paragraf --
   tiap potongan teks membungkus/patah sendiri-sendiri (persis pola yang
   terlihat di screenshot). Alert yang MEMANG butuh tata letak flex (ikon
   & tombol berdampingan) sudah menambahkan utility class Bootstrap
   `d-flex align-items-start gap-2` sendiri di markup-nya (lihat mis.
   views/pemakaian_material/index.php, views/admin/karyawan.php,
   views/rab/editor.php) -- itu TETAP flex seperti biasa karena utility
   class Bootstrap memakai `!important`, jadi tidak terpengaruh perubahan
   ini. .alert dasar dikembalikan ke alur blok normal (bawaan Bootstrap)
   supaya alert berisi paragraf/teks campuran mengalir wajar. */
.alert > i:first-child { margin-top: 2px; margin-right: var(--sp-2); font-size: .95em; }
.alert-success { background: var(--success-bg); color: var(--success-fg); border-color: var(--success-border); border-left-color: var(--success); }
.alert-danger  { background: var(--danger-bg);  color: var(--danger-fg);  border-color: var(--danger-border);  border-left-color: var(--danger); }
.alert-warning { background: var(--gold-bg);    color: var(--gold-fg); border-color: var(--gold-border);    border-left-color: var(--accent); }
.alert-info    { background: var(--info-bg);    color: var(--info-fg);    border-color: var(--info-border);    border-left-color: var(--info); }
.alert-secondary, .alert-light { background: var(--neutral-bg); color: var(--text); border-color: var(--neutral-border); border-left-color: var(--neutral); }
.alert .alert-link { color: inherit; font-weight: var(--fw-semibold); text-decoration: underline; }


/* =============================================================================
   16. KOMPONEN BOOTSTRAP LAIN
   ========================================================================== */
.list-group-item {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border-subtle);
  font-size: var(--fs-sm);
  padding: var(--sp-3) var(--sp-4);
}
.list-group-item:first-child { border-top-left-radius: var(--radius-chip); border-top-right-radius: var(--radius-chip); }
.list-group-item:last-child  { border-bottom-left-radius: var(--radius-chip); border-bottom-right-radius: var(--radius-chip); }
.list-group-item-action:hover { background: var(--surface-hover); color: var(--text-strong); }
.list-group-item.active { background: var(--brand); border-color: var(--brand); color: #fff; }

.accordion-item { background: var(--surface); border-color: var(--border); }
.accordion-item:first-of-type { border-top-left-radius: var(--radius-chip); border-top-right-radius: var(--radius-chip); }
.accordion-item:last-of-type  { border-bottom-left-radius: var(--radius-chip); border-bottom-right-radius: var(--radius-chip); }
.accordion-button {
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-heading);
  font-weight: var(--fw-medium);
  font-size: var(--fs-sm);
  box-shadow: none;
}
.accordion-button:not(.collapsed) {
  background: var(--bg-sunken);
  color: var(--text-strong);
  box-shadow: inset 0 -1px 0 var(--border);
}
.accordion-button:focus { box-shadow: var(--ring); border-color: var(--border); }
[data-theme="dark"] .accordion-button::after { filter: invert(1) grayscale(100%) brightness(1.8); }
.accordion-body { color: var(--text); font-size: var(--fs-sm); }

.popover { background: var(--surface); border-color: var(--border); border-radius: var(--radius-chip); box-shadow: var(--shadow-lg); }
.popover-header { background: var(--bg-sunken); color: var(--text-strong); border-color: var(--border-subtle); font-family: var(--font-heading); font-size: var(--fs-sm); }
.popover-body { color: var(--text); font-size: var(--fs-caption); }
.tooltip-inner {
  background: var(--navy-900); color: #fff;
  border-radius: var(--radius-sm);
  font-size: var(--fs-caption);
  padding: 6px 10px;
}
.tooltip .tooltip-arrow::before { border-top-color: var(--navy-900); border-bottom-color: var(--navy-900); }

.offcanvas { background: var(--surface); color: var(--text); }
.offcanvas-header { border-bottom: 1px solid var(--border-subtle); }

.spinner-border, .spinner-grow { color: var(--brand-soft); }
[data-theme="dark"] .spinner-border, [data-theme="dark"] .spinner-grow { color: var(--accent); }

.progress { background: var(--bg-sunken); border-radius: var(--radius-badge); height: 8px; }
.progress-bar { background: var(--brand); }
.progress-bar.bg-success { background: var(--success) !important; }
.progress-bar.bg-warning { background: var(--accent) !important; }
.progress-bar.bg-danger  { background: var(--danger)  !important; }

.breadcrumb { font-size: var(--fs-caption); margin-bottom: var(--sp-3); }
.breadcrumb-item, .breadcrumb-item a { color: var(--text-muted); }
.breadcrumb-item a:hover { color: var(--brand-soft); }
.breadcrumb-item.active { color: var(--text); font-weight: var(--fw-medium); }


/* =============================================================================
   17. PANEL TOPBAR (Notifikasi, Pengguna Online, Profil)
   ========================================================================== */
.notif-wrap { position: relative; }
.notif-panel, .online-panel, .profil-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg);
  color: var(--text);
  font-size: var(--fs-sm);
}
.notif-panel .notif-item, .online-panel .online-item {
  border-bottom: 1px solid var(--border-subtle);
  padding: var(--sp-3) var(--sp-4);
  transition: background var(--dur) var(--ease);
}
.notif-panel .notif-item:last-child, .online-panel .online-item:last-child { border-bottom: 0; }
.notif-panel .notif-item:hover, .online-panel .online-item:hover { background: var(--surface-hover); }
.notif-panel .notif-item.unread { background: var(--brand-tint); }
.notif-panel .notif-item.unread:hover { background: var(--surface-hover); }


/* =============================================================================
   18. DIALOG SweetAlert2 (dipakai untuk konfirmasi hapus/approval)
   ========================================================================== */
.swal2-popup {
  background: var(--surface) !important;
  color: var(--text) !important;
  border-radius: var(--radius-modal) !important;
  border: 1px solid var(--border);
  font-family: var(--font-text) !important;
  box-shadow: var(--shadow-modal) !important;
}
.swal2-title { font-family: var(--font-heading) !important; color: var(--text-strong) !important; font-size: var(--fs-section) !important; }
.swal2-html-container { color: var(--text-muted) !important; font-size: var(--fs-sm) !important; }
.swal2-actions .swal2-confirm {
  background: var(--brand) !important; color: #fff !important; border-radius: var(--radius-button) !important;
  font-family: var(--font-heading) !important; font-weight: var(--fw-semibold) !important;
}
.swal2-actions .swal2-cancel {
  background: var(--surface) !important; color: var(--text) !important;
  border: 1px solid var(--border-strong) !important; border-radius: var(--radius-button) !important;
}
.swal2-actions .swal2-deny { background: var(--danger) !important; border-radius: var(--radius-button) !important; }


/* =============================================================================
   19. MODE GELAP — PEMETAAN VARIABEL BOOTSTRAP
   Bootstrap mengatur warnanya lewat --bs-*, yang TIDAK ikut berubah saat
   data-theme="dark". Dipetakan ke token tema di sini supaya seluruh komponen
   bawaan (kartu, tabel, teks bodi, tautan) otomatis ikut.
   ========================================================================== */
[data-theme="dark"] {
  --bs-body-color: var(--text);
  --bs-body-bg: var(--bg);
  --bs-emphasis-color: var(--text-strong);
  --bs-secondary-color: var(--text-muted);
  --bs-secondary-bg: var(--surface);
  --bs-tertiary-color: var(--text-muted);
  --bs-tertiary-bg: var(--bg-sunken);
  --bs-heading-color: var(--text-strong);
  --bs-link-color: var(--gold-400);
  --bs-link-hover-color: var(--gold-300);
  --bs-border-color: var(--border);
  --bs-border-color-translucent: var(--border);
  --bs-highlight-bg: var(--accent-tint);
}
[data-theme="dark"] .card,
[data-theme="dark"] .card-body { color: var(--text); }

/* Zona yang SENGAJA tetap terang di kedua tema (kotak highlight, area cetak).
   Teksnya dikunci gelap supaya tidak pernah hilang di atas latar terang. */
[data-theme="dark"] .bg-light,
[data-theme="dark"] .bg-white {
  background-color: var(--navy-050) !important;
  color: var(--navy-900) !important;
}
[data-theme="dark"] .bg-light *:not(.badge):not([class*="text-"]),
[data-theme="dark"] .bg-white *:not(.badge):not([class*="text-"]) { color: var(--navy-900); }
[data-theme="dark"] .text-dark,
[data-theme="dark"] .text-black { color: var(--navy-900) !important; }
[data-theme="dark"] .text-muted { color: var(--text-muted) !important; }


/* =============================================================================
   20. RUANG HALAMAN (brief §13)
   Whitespace dinaikkan di desktop; layar sempit diatur mobile.css.
   ========================================================================== */
@media (min-width: 993px) {
  .content {
    padding: var(--pad-page);
    padding-top: calc(var(--header-h) + var(--sp-6));
  }
  .content > .row { --bs-gutter-x: var(--gap-card); --bs-gutter-y: var(--gap-card); }
}
.card + .card, .card + .filter-panel, .filter-panel + .card { margin-top: var(--gap-card); }


/* =============================================================================
   21. KONTRAS TOMBOL STATUS DI MODE GELAP  (aksesibilitas, WCAG AA)
   Di mode gelap warna status sengaja dicerahkan agar terbaca sebagai TEKS di
   atas latar malam. Sebagai LATAR tombol solid, warna cerah itu justru
   membuat teks putih di atasnya jatuh ke ~2–3:1 (gagal AA). Teksnya
   dibalik jadi navy pekat — rasio naik ke >8:1 tanpa mengubah warna status
   itu sendiri, jadi maknanya tetap konsisten dengan badge & teks.
   ========================================================================== */
[data-theme="dark"] .btn-success,
[data-theme="dark"] .btn-danger,
[data-theme="dark"] .btn-info {
  --bs-btn-color: var(--navy-950);
  --bs-btn-hover-color: var(--navy-950);
  --bs-btn-active-color: var(--navy-950);
  --bs-btn-disabled-color: var(--navy-950);
  font-weight: var(--fw-semibold);
}
[data-theme="dark"] .btn-outline-success:hover,
[data-theme="dark"] .btn-outline-danger:hover { color: var(--navy-950); }


/* =============================================================================
   22. ANIMASI PERGANTIAN TEMA (lingkaran membesar dari tombol yang diklik)
   Permintaan pengguna (September 2026): efek transisi tema meniru contoh
   website yang dikirim (template shadcn dashboard/landing -- tweakcn-style
   "circular reveal" via View Transitions API). Dipicu dari JS
   (assets/js/app.js #btnTheme, serta script toggle di views/layouts/absensi.php,
   views/auth/login.php, views/absensi/login.php) yang mengisi --tx/--ty
   (posisi klik dlm %) lalu membungkus document.documentElement.setAttribute
   ('data-theme', ...) di dalam document.startViewTransition(). Berkas ini
   HANYA berisi keyframe visualnya; logiknya murni di JS spy sesuai aturan
   berkas ini "murni tampilan". Browser tanpa dukungan View Transitions API
   (mis. Firefox lama) otomatis jatuh ke ganti tema instan tanpa animasi --
   fallback ditangani di JS, bukan di sini.
   ========================================================================== */
::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}
::view-transition-old(root) { z-index: 0; }
::view-transition-new(root) { z-index: 1; }

@keyframes sv-theme-reveal {
  from { clip-path: circle(0% at var(--tx, 50%) var(--ty, 50%)); }
  to   { clip-path: circle(150% at var(--tx, 50%) var(--ty, 50%)); }
}
/* PERBAIKAN (September 2026, laporan pengguna: "tombol gelap terang ada
   jedanya, tidak responsif, animasinya lambat & tidak halus"). Kurva
   "ease-in-out" MELAMBAT DI AWAL (percepatan dari nol) sebelum melambat
   lagi di akhir, jadi lingkaran terasa "diam sesaat" begitu tombol diklik
   sebelum benar-benar mulai membesar. Diganti var(--ease)
   (cubic-bezier(.4,0,.2,1), token yang SAMA dipakai seluruh hover/transisi
   lain di app -- lihat design-system.css §2) yang langsung punya kecepatan
   begitu dimulai (tanpa fase diam di awal), lebih responsif & konsisten
   dgn "rasa" animasi tombol lain di app. Durasi dikembalikan .5s (revisi
   berikutnya, permintaan pengguna: "durasinya seperti yang sebelumnya
   saja") -- jeda yang MASIH dirasakan pengguna setelah perubahan ini
   ternyata bukan dari durasi/kurva animasinya, tapi dari JEDA SEBELUM
   animasi ini SEMPAT mulai (lihat perbaikan forced-reflow di assets/js/
   app.js, event klik #btnTheme). will-change: clip-path dipertahankan
   supaya browser menyiapkan compositing layer lebih awal (bukan baru saat
   animasi dimulai), mengurangi kemungkinan patah/tersendat di frame
   pertama terutama di HP. */
::view-transition-new(root) {
  animation: sv-theme-reveal .5s var(--ease) forwards;
  will-change: clip-path;
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-new(root) { animation: none; }
}
