/* ══════════════════════════════════════════════════
   SP.Wasm — Shared Component Styles
   Konsisten: pill shape (20px) untuk input/select/button — Ledger identity
   ══════════════════════════════════════════════════ */

/* ── Font IKON disajikan SENDIRI (bukan dari fonts.googleapis.com) ──
   Nyata 2026-09-21: aplikasi TIDAK punya definisi `.material-symbols-rounded` sendiri, jadi
   seluruh ikon 100% bergantung stylesheet CDN. Begitu CDN tak terjangkau (instalasi lembaga di
   LAN tanpa internet), yang tampil bukan ikon melainkan NAMA LIGATUR apa adanya —
   `receipt_long`, `edit_square`, `account_balance` — yaitu teks BER-UNDERSCORE di label
   tombol/tab (dilaporkan user: "label tab pakai underscore"). Font kini ikut dipublikasikan
   (`wwwroot/fonts/material-symbols-rounded.woff2`, disalin dari Google Fonts, lisensi Apache 2.0)
   dan `font-display: block` mencegah teks ligatur sempat terlihat sebelum font siap.

   540 KB = SELURUH ikon, sumbu `FILL` variabel (efek isi-saat-hover tetap hidup). Jangan diganti
   dengan subset `&icon_names=…`: diuji 2026-09-21, Google memotong daftar nama yang panjang
   tanpa pesan apa pun sehingga hanya sebagian ikon terbentuk — persis bug yang sedang
   diperbaiki, dan uji-render yang menangkapnya (`artifacts/font-ikon/ukur.py`, 69/69 ikon).
   Bangun ulang font: `python scripts/gen_font_ikon.py`. */
@font-face {
    font-family: 'Material Symbols Rounded';
    font-style: normal;
    font-weight: 100 700;
    font-display: block;
    src: url('../fonts/material-symbols-rounded.woff2') format('woff2');
}
.material-symbols-rounded {
    font-family: 'Material Symbols Rounded';
    font-weight: normal;
    font-style: normal;
    font-size: 24px;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    font-feature-settings: 'liga';
    -webkit-font-feature-settings: 'liga';
    -moz-osx-font-smoothing: grayscale;
}

/* ── Scrollbar: reserve space agar konten tidak flicker saat scrollbar muncul/hilang ── */
html { scrollbar-gutter: stable; }

/* ── Page Header (ringkas agar muat di 1366×768) ── */
.page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; flex-wrap: wrap; gap: 8px; }
.page-title { margin: 0; font-weight: 700; font-size: 20px; letter-spacing: -0.5px; color: var(--text-primary); }
.page-sub { margin: 2px 0 0; font-size: 12px; color: var(--text-muted); }

/* ── Text Input (pill) ── */
.sp-input {
    width: 100%; padding: 13px 16px 9px; border-radius: 10px;
    border: 1px solid var(--input-border); background: transparent;
    font-size: 13px; font-family: var(--font-body); color: var(--input-text);
    outline: none; transition: border-color 0.15s, background 0.15s;
}
.sp-input:focus { border-color: var(--accent); }
.sp-input::placeholder { color: var(--text-tertiary); }
.dark .sp-input { background: transparent; border-color: var(--input-border); color: var(--input-text); }
.dark .sp-input:focus { border-color: var(--accent); }
.dark .sp-input::placeholder { color: var(--text-tertiary); }


/* ── Input tanpa label (search/filter/saldo) — ikut gaya M3 ──
   Field di luar .form-group tidak kena aturan M3 (tidak ada label/notch);
   border sendiri tetap 1px, transparan, hover menggelap ala M3. */
input.sp-input:not(:focus):hover,
select.sp-select:not(:focus):hover { border-color: var(--input-border-hover); }

/* ── Select (pill + chevron) ── */
.sp-select {
    width: 100%; padding: 13px 16px 9px; border-radius: 10px;
    border: 1px solid var(--input-border); background: transparent;
    font-size: 13px; font-family: var(--font-body); color: var(--input-text);
    outline: none; cursor: pointer; transition: border-color 0.15s, background 0.15s;
    appearance: none; -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 16px center;
}
.sp-select:focus { border-color: var(--accent); }
.dark .sp-select {
    background-color: transparent; border-color: var(--input-border); color: var(--input-text);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
.dark .sp-select:focus { border-color: var(--accent); }

/* ── Button (pill) ── */
.sp-btn {
    padding: 8px 20px; border-radius: 10px; border: none;
    font-size: 13px; font-weight: 600; font-family: var(--font-body);
    cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    transition: background 0.15s, opacity 0.15s; height: 38px;
}
.sp-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.sp-btn-primary { background: var(--accent); color: #fff; }
.sp-btn-primary:hover { background: var(--accent-hover); }
.sp-btn-green { background: var(--accent); color: white; }
.sp-btn-green:hover { background: var(--accent-dark); }
.sp-btn-orange { background: var(--accent-orange); color: white; }
.sp-btn-orange:hover { background: #9A3A18; }
.sp-btn-red { background: var(--accent-red); color: white; }
.sp-btn-red:hover { background: #8F2A20; }
.sp-btn-outline { background: transparent; border: 1px solid var(--border-color); color: var(--text-secondary); }
.sp-btn-outline:hover { background: var(--nav-hover-bg); }
.dark .sp-btn-outline { border-color: var(--border-color); color: var(--text-tertiary); }
.dark .sp-btn-outline:hover { background: var(--nav-hover-bg); }
.sp-btn-danger { background: transparent; border: 1px solid #E5B7AF; color: var(--accent-red); }
.sp-btn-danger:hover { background: #F6E0DC; }
.dark .sp-btn-danger { border-color: #5A2A22; color: #E89485; }
.dark .sp-btn-danger:hover { background: #331410; }
.sp-btn-sm { padding: 6px 14px; font-size: 12px; height: 30px; }


/* ── Search Box (responsive) ── */
.search-box { display: flex; align-items: center; gap: 8px; }
.search-box .sp-input { max-width: 260px; width: 260px; }
/* Responsive mobile (≤700px) → lihat css/mobile.css */

/* ── Form Groups (spacing vertikal seragam antar field; grid 12-slice) ──
   Nilai SATU untuk semua form (modal master, transaksi, login, filter):
   12px. Jangan menimpa dengan nilai lain per halaman — kalau perlu beda,
   pakai konteks (mis. toolbar kompak → margin-bottom:0). */
.form-group { margin-bottom: 12px; }
.form-label { display: block; font-size: 12px; font-weight: 600; color: var(--text-tertiary); margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.5px; }
/* gap: 0 12px — jarak antar BARIS ditangani margin-bottom .form-group (12px)
   saja, row-gap di-nol-kan agar spacing vertikal seragam (tidak bertumpuk
   dengan margin). Column-gap 12px tetap. */
.form-row { display: grid; grid-template-columns: repeat(12, 1fr); gap: 0 12px; }
.form-row-3 { display: grid; grid-template-columns: repeat(12, 1fr); gap: 0 12px; }
/* Default 2 kolom (6+6); form-row-3 default 3 kolom (4+4+4) — keduanya 12-slice
   sehingga class .col-* di bawah bisa menyempitkan/melebarkan field tertentu
   (maksimal 3 kolom; label floating tidak boleh melebihi input). */
.form-row > .form-group { grid-column: span 6; align-self: start; }
.form-row-3 > .form-group { grid-column: span 4; align-self: start; }
/* Preset lebar prediktif (12-slice) — pakai pada field yang nilainya pendek/panjang */
.form-row > .form-group.col-3, .form-row-3 > .form-group.col-3 { grid-column: span 3; }
.form-row > .form-group.col-4, .form-row-3 > .form-group.col-4 { grid-column: span 4; }
.form-row > .form-group.col-5, .form-row-3 > .form-group.col-5 { grid-column: span 5; }
.form-row > .form-group.col-7, .form-row-3 > .form-group.col-7 { grid-column: span 7; }
.form-row > .form-group.col-8, .form-row-3 > .form-group.col-8 { grid-column: span 8; }
.form-row > .form-group.col-9, .form-row-3 > .form-group.col-9 { grid-column: span 9; }
.form-row > .form-group.col-12, .form-row-3 > .form-group.col-12 { grid-column: 1 / -1; }
/* Group dalam satu baris mempertahankan tinggi naturalnya (jangan di-stretch
   oleh kolom sebelah yang kebetulan lebih tinggi, mis. label + toggle switch
   dengan margin hack) — mencegah field (mis. input tanggal) tampak "tinggi
   sekali" padahal isinya pendek. */

/* ── Expandable Card (panel riwayat per rekening di bawah form input) ── */
.expand-card {
    border: 1px solid var(--border-light); border-radius: 12px;
    background: var(--surface-solid); margin-top: 12px; overflow: hidden;
}
.expand-card-head {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 10px 14px; background: transparent; border: none; cursor: pointer;
    color: var(--text-primary); font-size: 13px; font-weight: 700; text-align: left;
}
.expand-card-head:hover { background: var(--nav-hover-bg); }
.expand-card-icon { color: var(--text-tertiary); }
.expand-card-title { flex: 1; min-width: 0; }
.expand-card-badge {
    font-size: 11px; font-weight: 600; color: var(--accent);
    background: var(--accent-light); padding: 2px 8px; border-radius: 10px;
}
.expand-card-chevron { color: var(--text-tertiary); transition: transform 0.15s ease; }
.expand-card.open .expand-card-chevron { transform: rotate(180deg); }
.expand-card-body {
    border-top: 1px solid var(--border-light); padding: 10px 14px;
    max-height: 320px; overflow-y: auto;
}

/* ── Card / Modal — solid modern, glass halus sebagai aksen ── */
.sp-card { background: var(--surface-solid); border-radius: var(--radius-card); padding: 16px 18px; box-shadow: var(--shadow-card); border: 1px solid var(--border-light); }
.dark .sp-card { background: var(--surface-solid); border-color: var(--glass-border); box-shadow: var(--shadow-card); }

/* ── Push pagination to bottom ── */
.app-content { display: flex; flex-direction: column; min-height: 0; }
/* Halaman menggulir, bukan menyusut: anak app-content tidak boleh dipipihkan
   oleh flex-shrink (card dengan overflow:hidden kehilangan floor min-height). */
.app-content > * { flex-shrink: 0; }


.card-amount {
    font-size: 15px;
    font-weight: 600;
    color: var(--accent);
    text-align: right;
    flex-shrink: 0;
    white-space: nowrap;
    letter-spacing: -0.2px;
    margin-left: auto;
    align-self: flex-start;
    padding-top: 2px;
}
.dark .card-amount { color: var(--accent); }

/* ── Master Data Grid (3 columns desktop, 1fr mobile) ── */
.master-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
}
.master-card {
    background: var(--surface-solid);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-card);
    padding: 16px 18px;
    transition: box-shadow 0.2s ease, border-color 0.2s ease;
    box-shadow: var(--shadow-card);
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.master-card:hover {
    border-color: var(--accent);
    box-shadow: 0 4px 16px rgba(37,99,235,0.12);
}
.dark .master-card { background: var(--surface-solid); border-color: var(--glass-border); box-shadow: var(--shadow-card); }
/* Responsive master-grid (≤1100/700px) → lihat css/mobile.css */

/* ── Sort Bar ── */
.sort-bar{display:flex;align-items:center;gap:4px;margin-bottom:10px;flex-wrap:wrap;}
.sort-label{font-size:11px;font-weight:600;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:0.5px;margin-right:4px;}
.sort-btn{background:transparent;border:1px solid var(--border-color);border-radius:16px;padding:3px 10px;font-size:11px;font-family:var(--font-body);color:var(--text-tertiary);cursor:pointer;transition:all 0.12s;white-space:nowrap;}
.sort-btn:hover{border-color:var(--accent);color:var(--accent);}
.sort-btn.active{background:var(--accent-light);border-color:var(--accent);color:var(--accent);font-weight:600;}

.modal-overlay { position: fixed; inset: 0; background: rgba(15, 23, 42, 0.3); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 1000; }
/* Latar modal = `--modal-bg` (0.96–0.98 = hampir solid), BUKAN `--glass-bg-strong`:
   token glass itu di tema gelap bernilai rgba(255,255,255,0.08) — dipakai sebagai permukaan
   kaca di atas latar GELAP, jadi memakainya untuk modal membuat SELURUH dialog master
   (29 halaman) tembus pandang sampai tulisan di belakangnya terbaca (temuan user 2026-09-21).
   Satu token untuk semua dialog supaya transparansinya seragam — FindModal & KonfirmasiKata
   memang sudah memakai `--modal-bg` sejak awal, dan versi berkas ini sebelum regresi glass
   juga begitu. `--modal-bg` ada di tiap tema (terang 0.96 / gelap 0.98 / gelap-biru 0.97). */
.modal { background: var(--modal-bg, var(--glass-bg-strong, rgba(255,255,255,0.96))); -webkit-backdrop-filter: blur(20px) saturate(1.5); backdrop-filter: blur(20px) saturate(1.5); border: 1px solid var(--glass-border, rgba(255,255,255,0.2)); border-radius: var(--radius-card); width: 540px; max-height: 90vh; overflow-y: auto; box-shadow: 0 8px 32px rgba(0,0,0,0.12); }
.modal-header { display: flex; align-items: center; justify-content: space-between; padding: 14px 20px 0; cursor: grab; user-select: none; -webkit-user-select: none; touch-action: none; }
.modal.dragging { transition: none; }
.find-header { cursor: grab; user-select: none; -webkit-user-select: none; touch-action: none; }
body.modal-drag-active { user-select: none; -webkit-user-select: none; }
body.modal-drag-active .modal-header, body.modal-drag-active .find-header { cursor: grabbing; }
.confirm-overlay .modal-header, .confirm-dialog { cursor: default; }
.modal-header h3 { margin: 0; font-size: 18px; font-weight: 700; }
.modal-close { background: none; border: none; font-size: 20px; cursor: pointer; color: var(--text-tertiary); padding: 4px; }
.modal-close:hover { color: var(--text-primary); }
.modal-body { padding: 14px 20px; }
.modal-footer { padding: 0 20px 14px; display: flex; justify-content: flex-end; gap: 8px; }
.dark .modal { background: var(--modal-bg, var(--glass-bg-strong, rgba(22,22,27,0.98))); border-color: var(--glass-border); }
.dark .modal-header h3 { color: var(--text-primary); }
.dark .modal-close:hover { color: var(--text-primary); }

/* ── Modal form lebar (desktop 1366): isi memakai ruang horizontal,
   header & footer tetap, body scroll sendiri. ── */
.modal-wide { width: min(880px, calc(100vw - 48px)); max-height: calc(100vh - 40px); display: flex; flex-direction: column; overflow: hidden; }
.modal-wide .modal-header, .modal-wide .modal-footer { flex-shrink: 0; }
.modal-wide .modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* Toggle inline (label kiri, switch center vertikal) — tinggi mengikuti
   field M3 (46px). !important: aturan global M3
   (.form-group:has(> .form-label):not(.m3-off) > .form-label, 0,4,0)
   menyembunyikan label grup switch. */
.inline-switch { display: flex; align-items: center; gap: 10px; min-height: 46px; margin-bottom: 12px; /* ikut spacing global form-group */ }
.inline-switch .form-label { margin: 0; font-size: 12px; font-weight: 400; text-transform: none; letter-spacing: normal; color: var(--text-tertiary); white-space: nowrap; visibility: visible !important; }

/* Responsive modal & page-header (≤899px) → lihat css/mobile.css */

/* ── Modal di desktop: JANGAN tertutup sidebar ──
   Sidebar fixed (z-1030) berada DI ATAS .modal-overlay (z-1000) — di layar
   sempit modal ter-center ke seluruh viewport sehingga tepi kirinya bisa
   tersembunyi di bawah sidebar. Solusi: di ≥900px (sidebar tampil), overlay
   digeser ke area konten (kanan sidebar 230px / 56px collapsed) dan lebar
   modal dibatasi sisa ruang, sehingga modal selalu utuh & sidebar tetap
   terlihat/terpakai. */
@media (min-width: 900px) {
    .modal-overlay { left: 230px; }
    .main-area.s-collapsed .modal-overlay { left: 56px; }
    .main-area .modal { width: min(540px, calc(100vw - 230px - 24px)); }
    .main-area .modal-wide { width: min(880px, calc(100vw - 230px - 48px)); }
    .main-area.s-collapsed .modal { width: min(540px, calc(100vw - 56px - 24px)); }
    .main-area.s-collapsed .modal-wide { width: min(880px, calc(100vw - 56px - 48px)); }
}

/* ── Table ── */
.data-table-wrap { overflow-x: auto; border: 1px solid var(--border-light); border-radius: 14px; background: var(--surface-solid); }
.data-table { width: 100%; border-collapse: separate; border-spacing: 0; background: transparent; table-layout: auto; }
.data-table th { background: var(--table-stripe); padding: 9px 12px; text-align: left; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.8px; color: var(--text-tertiary); border-bottom: 1px solid var(--border-light); white-space: nowrap; }
.data-table td { padding: 9px 12px; font-size: 13px; color: var(--text-primary); border-bottom: 1px solid var(--border-color); white-space: nowrap; }
.data-table td.col-wrap { white-space: normal; }
.data-table tr:last-child td { border-bottom: none; }
.data-table tr:hover td { background: var(--table-hover); }
.dark .data-table-wrap { background: var(--surface-solid); border-color: var(--glass-border); }
.dark .data-table th { background: var(--table-stripe); border-color: var(--border-color); color: var(--text-tertiary); }
.dark .data-table td { color: var(--text-primary); border-color: var(--border-color); }
.dark .data-table tr:hover td { background: var(--table-hover); }
.dark .data-table tfoot tr { background: var(--table-hover) !important; border-color: var(--border-color); }
.dark .data-table tfoot td { color: var(--text-primary); }

/* ── TRX TABLE — embedded transaction grids (forms, modals) ── */
.trx-wrap { overflow: auto; border: 1px solid var(--border-light); border-radius: 12px; background: var(--surface); }
.trx-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.trx-table thead th { background: var(--table-stripe); padding: 10px 12px; text-align: left; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-tertiary); border-bottom: 2px solid var(--accent); white-space: nowrap; }
.trx-table td { padding: 8px 12px; border-bottom: 1px solid var(--border-color); color: var(--text-primary); vertical-align: middle; }
.trx-table tr:last-child td { border-bottom: none; }
.trx-table tr:hover td { background: var(--table-hover); }
.trx-table .td-right { text-align: right; font-variant-numeric: tabular-nums; }
.trx-table .td-money { font-family: var(--font-mono); font-size: 12px; color: var(--accent-green); font-weight: 500; }
.trx-table .td-id { font-weight: 600; color: var(--text-tertiary); font-size: 12px; white-space: nowrap; }
.dark .trx-table thead th { background: var(--table-stripe); border-color: var(--border-color); color: var(--text-tertiary); }
.dark .trx-table td { color: var(--text-primary); border-color: var(--border-color); }
.dark .trx-table tr:hover td { background: var(--table-hover); }
/* ── Footer ringkasan pada trx-table (mirip Total Beban Bunga legacy) ── */
.trx-table tfoot td {
    padding: 9px 12px; font-size: 13px; font-weight: 700; color: var(--text-primary);
    border-top: 2px solid var(--accent);
}
.trx-table tfoot td.tfoot-label { font-size: 11px; text-transform: uppercase; letter-spacing: .6px; color: var(--text-tertiary); font-weight: 600; }
.trx-table tfoot td.td-money { color: var(--accent); }
.dark .trx-table tfoot td { border-top-color: var(--accent); }

/* ── CoA Tree container (Setup Penjurnalan / Account List) ── */
.coa-tree-container {
    background: var(--surface);
    border: 1px solid var(--border-light);
    border-radius: 12px;
    padding: 16px 12px;
    overflow: auto;
    max-height: calc(100vh - 200px);
}

/* ── Saldo Awal: 2-column side-by-side (legacy SplitContainer) ── */
.sa-split {
    display: flex;
    gap: 16px;
    flex: 1;
    min-height: 0;
}
.sa-panel {
    flex: 1;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border-light);
    border-radius: 12px;
    overflow: hidden;
    min-width: 0;
}
.sa-panel-header {
    padding: 10px 14px;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    border-bottom: 2px solid var(--accent);
    background: var(--bg-secondary);
    color: var(--text-primary);
    display: flex;
    align-items: center;
    gap: 6px;
}
.sa-panel-header .material-symbols-rounded { font-size: 18px; }
.sa-panel-body {
    flex: 1;
    overflow-y: auto;
    padding: 0;
}
.sa-panel-body .trx-table { margin: 0; }
.sa-panel-body .trx-table td { cursor: pointer; }
.sa-panel-body .trx-table tr:hover td { background: var(--table-hover); }
.sa-summary {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    background: var(--surface);
    border: 1px solid var(--border-light);
    border-radius: 12px;
    flex-wrap: wrap;
}
.sa-summary-item {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
}
.sa-summary-item .sa-label {
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    font-size: 11px;
    letter-spacing: 0.5px;
}
.sa-summary-item .sa-value {
    font-family: var(--font-mono);
    font-size: 14px;
    font-weight: 600;
}
.sa-balance-ok { color: var(--accent-green); }
.sa-balance-err { color: #ef4444; }
@media (max-width: 768px) {
    .sa-split { flex-direction: column; }
}

/* ── Connected Account (Setup Penjurnalan) ── */
.ca-group {
    background: var(--surface);
    border: 1px solid var(--border-light);
    border-radius: 12px;
    padding: 14px 16px;
    margin-bottom: 12px;
}
.ca-group-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-primary);
    margin-bottom: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border-light);
}
.ca-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 0;
    border-bottom: 1px solid var(--border-light);
}
.ca-row:last-child { border-bottom: none; }
.ca-label {
    min-width: 180px;
    font-size: 13px;
    color: var(--text-secondary);
    font-weight: 500;
}
.ca-kode {
    min-width: 90px;
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
}
.ca-nama {
    flex: 1;
    font-size: 13px;
    color: var(--text-primary);
}
@media (max-width: 600px) {
    .ca-label { min-width: 120px; font-size: 12px; }
    .ca-kode { min-width: 70px; }
}

/* ── Switch toggle ── */
.sp-switch { position: relative; display: inline-block; width: 40px; height: 22px; cursor: pointer; }
.sp-switch input { opacity: 0; width: 0; height: 0; }
.sp-slider { position: absolute; inset: 0; background: var(--gray-200); border-radius: 22px; transition: all 0.25s; }
.sp-slider::before { content: ""; position: absolute; left: 3px; top: 3px; width: 16px; height: 16px; background: #fff; border-radius: 50%; transition: all 0.25s; box-shadow: 0 1px 3px rgba(0,0,0,0.2); }
.sp-switch input:checked + .sp-slider { background: var(--accent); }
.sp-switch input:checked + .sp-slider::before { transform: translateX(18px); }
.dark .sp-switch .sp-slider { background: var(--gray-200); }
.dark .sp-switch input:checked + .sp-slider { background: var(--accent-dark); }
.switch-row { display: flex; align-items: center; gap: 10px; }
.switch-label { font-size: 13px; font-weight: 500; color: var(--text-primary); }

/* ── Icon button (no border, table action) — hover: tint pada ICON saja,
   container tetap transparan (tanpa background) ── */
.icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: none; background: none; border-radius: 6px; cursor: pointer; color: var(--text-tertiary); transition: color 0.12s; padding: 0; }
.icon-btn:hover { color: var(--accent); }
.icon-btn:hover .material-symbols-rounded { font-variation-settings: 'FILL' 1, 'wght' 400; }
.icon-btn-edit:hover { color: var(--accent-orange); }
.icon-btn-delete:hover { color: var(--accent-red); }
.dark .icon-btn:hover { color: var(--accent); }
.dark .icon-btn-edit:hover { color: var(--accent-orange); }
.dark .icon-btn-delete:hover { color: var(--accent-red); }

/* ── Badge ── */
.badge { padding: 4px 10px; border-radius: 10px; font-size: 11px; font-weight: 600; }
.badge-active { background: #DFF2E6; color: #1F6B45; }
.badge-inactive { background: #F8E2DE; color: #973B33; }
.dark .badge-active { background: rgba(95, 199, 158, 0.18); color: #7ED8AC; }
.dark .badge-inactive { background: rgba(224, 122, 112, 0.18); color: #EBA39A; }

/* ── Checkbox ── */
.sp-check { display: flex; align-items: center; gap: 8px; }
.sp-check input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); }
.sp-check label { font-size: 13px; color: var(--text-primary); margin: 0; }

/* ── Empty State ── */
.empty-state { text-align: center; padding: 60px 20px; color: var(--text-tertiary); }
.empty-state svg { margin-bottom: 12px; opacity: 0.3; }
.empty-state-icon { display: block; font-size: 34px; margin-bottom: 8px; opacity: 0.35; }
.empty-state-hint { font-size: 12px; margin-top: 6px; opacity: 0.85; }

/* ── Keadaan daftar (LoadingState / ErrorState) ──
   Satu tempat untuk tiga keadaan yang dulu diwakili teks "Loading..." yang sama:
   memuat (spinner berputar), gagal (merah + Coba lagi), kosong (.empty-state). */
.list-state { text-align: center; padding: 40px 20px; color: var(--text-tertiary); }
.list-state p { margin: 6px 0 0; }
.list-state-icon { display: block; font-size: 30px; }
.list-state-spinner { display: block; font-size: 32px; animation: list-state-spin 1.1s linear infinite; }
.list-state-error { color: var(--accent-red); }
.list-state-detail { font-size: 12px; opacity: 0.85; word-break: break-word; }
.list-state-retry { margin-top: 12px; }
@keyframes list-state-spin { to { transform: rotate(360deg); } }

/* ── Toast ── */
.toast { position: fixed; bottom: 24px; right: 24px; padding: 12px 20px; border-radius: 12px; font-size: 13px; font-weight: 500; z-index: 2000; animation: slideIn 0.3s ease; }
.toast-success { background: rgba(47,165,122,0.9); color: white; }
.toast-error { background: rgba(196,82,74,0.92); color: white; }
@keyframes slideIn { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0);    opacity: 1;
}

/* Fokus selalu memakai floating label; placeholder disembunyikan agar tidak
   tampil bersamaan dengan label. */
.form-group:has(> .form-label):not(.m3-off):focus-within > input::placeholder,
.form-group:has(> .form-label):not(.m3-off):focus-within > textarea::placeholder,
.form-group:has(> .form-label):not(.m3-off):focus-within > .numinput::placeholder,
.form-group:has(> .form-label):not(.m3-off):focus-within > .input-trailing-wrapper input::placeholder,
.form-group.m3-auto:not(.m3-off):focus-within input::placeholder,
.form-group.m3-auto:not(.m3-off):focus-within textarea::placeholder {
    opacity: 0 !important;
}
 }

/* ── DB Selector Badge ── */
.db-badge { padding: 5px 12px; border-radius: 10px; font-size: 11px; font-weight: 700; letter-spacing: 0.5px; cursor: pointer; border: none; transition: all 0.15s; }
.db-badge:hover { transform: scale(1.05); }
.db-splpd { background: #DFF2E6; color: #1F6B45; }
.db-spksp { background: var(--gold-soft); color: #7A5F1B; }

/* ── Warning Banner ── */
.warning-banner { text-align: center; padding: 40px 20px; color: var(--text-tertiary); }
.warning-banner p { margin: 8px 0 0; font-size: 13px; }

/* ── Filter Panel ── */
.filter-panel{background:var(--surface-solid);border:1px solid var(--border-light);border-radius:14px;padding:10px 14px;margin-bottom:10px;box-shadow:var(--shadow-card);}
/* Baris filter: rata **BAWAH**, bukan center.
   Yang dibaca mata sebagai "sejajar" adalah garis bawah KONTROL (input/select/tombol), bukan
   titik tengah kotak grup — sementara tiap `.filter-group` = label + kontrol, dan tombol telanjang
   tidak punya label sama sekali. Dengan `align-items: center` tombol duduk di tengah tinggi grup
   (±9 px di atas kontrolnya); dengan `flex-end` + `margin-bottom: 0` (lihat aturan berikutnya)
   dasar semua kontrol jatuh di garis yang sama. Nyata: laporan user 2026-09-22 pada halaman PPOB
   & QRIS — "banyak tombol di panel filter tidak vertically centered". */
.filter-row {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
}

.filter-actions {
    display: flex;
    align-items: center; /* Memastikan tombol di dalam actions pas di tengah */
    gap: 6px;
    padding-bottom: 0; /* Hapus padding 1px yang tidak perlu */
}
.filter-group{display:flex;flex-direction:column;gap:4px;min-width:160px;}
.filter-label{font-size:11px;font-weight:600;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:0.5px;}
.filter-group .sp-select{padding:6px 16px;height:30px;}
.sp-btn-active{background:var(--accent-light);color:var(--accent);border-color:var(--accent);}

/* ── Data Cards (Master pages) ── */
.data-card { background: var(--surface-solid); border: 1px solid var(--border-light); border-radius: 14px; padding: 12px 16px; transition: border-color 0.12s, background 0.12s; }
.data-card:hover { border-color: var(--accent); background: var(--surface-hover); }
.dark .data-card { background: var(--surface-solid); border-color: var(--glass-border); }
.dark .data-card:hover { border-color: var(--accent); }

/* Common card patterns */
.n-id, .d-id, .a-id { font-size: 11px; font-weight: 700; color: var(--text-tertiary); min-width: 80px; }
.n-name, .d-name, .a-name { font-size: 14px; font-weight: 600; color: var(--text-primary); flex: 1; }
.n-label, .d-label, .a-label { font-size: 12px; color: var(--text-muted); }
.n-addr, .d-addr, .a-addr { font-size: 12px; color: var(--text-secondary); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dark .n-id, .dark .d-id, .dark .a-id { color: var(--text-tertiary); }
.dark .n-name, .dark .d-name, .dark .a-name { color: var(--text-primary); }
.dark .n-label, .dark .d-label, .dark .a-label { color: var(--text-muted); }
.dark .n-addr, .dark .d-addr, .dark .a-addr { color: var(--text-secondary); }

/* ── View Grid (detail page) ── */
.view-grid { display: flex; flex-direction: column; gap: 0; }
.view-row { display: flex; justify-content: space-between; padding: 9px 0; border-bottom: 1px solid var(--border-color); }
.dark .view-row { border-bottom-color: var(--border-color); }
.view-label { font-size: 13px; color: var(--text-tertiary); }
.view-val { font-size: 13px; color: var(--text-primary); font-weight: 500; text-align: right; max-width: 55%; }
.view-money { letter-spacing: 0.3px; }
.view-divider { height: 1px; background: var(--border-color); margin: 8px 0; }
.dark .view-divider { background: var(--border-color); }

/* ── ═══ DATAGRID (dg-*) — didefinisikan SEKALI di sini; jangan duplikasi di halaman ═══ ── */
.dg-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.dg-toolbar .search-box { flex: 1; min-width: 200px; }
.dg-toolbar .search-box .sp-input { max-width: 300px; width: 100%; }
.dg-toolbar .sp-input { max-width: 300px; width: 100%; }
.dg-wrap { overflow: auto; border: 1px solid var(--border-light); border-radius: 12px; background: var(--surface); flex: 1; min-height: 0; }
.dg-body { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
.dg-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; }
.dg-table thead { position: sticky; top: 0; z-index: 5; }
.dg-table th {
    background: var(--th-bg, var(--table-stripe)); padding: 10px 12px; text-align: left;
    font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.6px;
    color: var(--text-tertiary); border-bottom: 2px solid var(--accent);
    white-space: nowrap;
    transition: color 0.12s;
}
.dg-table th:hover { color: var(--accent); }
.dg-table th.th-right { text-align: right; }
.dg-table th.th-center { text-align: center; }
.dg-table th .th-sort, .dg-table th.th-sort { display: inline-flex; align-items: center; gap: 2px; }
.dg-table th .th-sort .material-symbols-rounded, .dg-table th.th-sort .material-symbols-rounded { font-size: 14px; opacity: 0.3; transition: opacity 0.12s; }
.dg-table th.sorted .th-sort .material-symbols-rounded { opacity: 1; color: var(--accent); }
.dg-table th:has(.th-sort) { cursor: pointer; }
.dg-table th.no-sort { cursor: default; }
.dg-table th.no-sort:hover { color: var(--text-tertiary); }

.dg-table td { padding: 6px 12px; border-bottom: 1px solid var(--border-color); color: var(--text-primary); vertical-align: middle; }
.dg-table tr:last-child td { border-bottom: none; }
.dg-table tr:hover td { background: var(--table-hover); }
.dg-table td.td-right { text-align: right; font-variant-numeric: tabular-nums; }
.dg-table td.td-center { text-align: center; }
.dg-table td.td-money { font-family: var(--font-mono); font-size: 12px; color: var(--accent-green); font-weight: 500; }
.dark .dg-table td.td-money { color: var(--accent-green); }
.dg-table td.td-pct { color: var(--accent-cyan); font-weight: 600; }
.dark .dg-table td.td-pct { color: var(--accent-cyan); }
.dg-table td.td-red { color: var(--accent-red); font-weight: 600; }
.dark .dg-table td.td-red { color: var(--accent-red); }
.dg-table td.td-name { font-weight: 600; color: var(--text-primary); }
.dg-table td.td-id { font-weight: 600; color: var(--text-tertiary); font-size: 12px; }
.dg-table td.td-addr { color: var(--text-secondary); max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dg-table td.td-wrap { white-space: normal; word-break: break-word; }
.dg-table td.td-clip { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dg-table td.td-select { cursor: text; }
.dg-actions { display: flex; gap: 2px; }
/* Kolom Aksi = kolom PERTAMA di semua datagrid → center isi & header-nya sejajar */
.dg-table td:first-child .dg-actions { justify-content: center; }
.dg-status { display: inline-flex; align-items: center; gap: 4px; }
.dg-jenis { font-size: 11px; color: var(--text-tertiary); }
.dg-footer { display: flex; align-items: center; justify-content: space-between; padding: 10px 16px 6px; background: var(--table-stripe); border: 1px solid var(--border-light); border-radius: 12px; flex-wrap: wrap; gap: 8px; flex-shrink: 0; }
.dg-footer-summary { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-tertiary); }
.dg-footer-summary strong { color: var(--text-primary); font-weight: 700; }
.dg-footer-sep { color: var(--border-color); }

/* ══════════════════════════════════════════════════════════════════
   Material 3 — Outlined Text Field (SEJATI, ala Google)
   - Container transparan; OUTLINE digambar oleh ::before form-group
     sebagai ring rounded penuh (teknik mask padding-box), jadi sudut
     mengikuti radius 20px (sama dengan tombol) — TIDAK ada garis lurus
     yang menembus radius. Radius TIDAK diubah.
   - NOTCH: segmen atas outline dilubangi selebar label + padding 4px
     kiri & kanan (ala M3). Label mulai di x=16px (sejajar teks input),
     notch mulai di x=12px; --m3-lw di-set js/m3-outline.js dengan
     metrik label FLOATING. Label TRANSPARAN, tidak ada chip.
   - Label 2 posisi: RESTING (di dalam field, ukuran = teks input 13px,
     outline utuh karena --m3-lw:0) ↔ FLOATING (12px / 500 di garis
     outline saat fokus/terisi, outline berlubang di bawah label).
   - HOVER: outline menggelap (on-surface) — token --input-border-hover.
   - FOKUS: outline accent 2px (via --m3-bw), label accent, tanpa
     ring/box-shadow ganda. Caret accent.
   - DISABLED: outline & label meredup.
   - Notch & ketebalan outline beranimasi halus (@property --m3-lw/--m3-bw
     + transition 150ms, easing M3) — mengikuti gerak label.
   - Select/date/number/readonly selalu floating (nilai selalu ada).
   Berlaku global; label lepas di luar .form-group di-wrapper otomatis
   oleh js/m3-outline.js (.m3-auto). Form-group tanpa label tidak diubah.
   ══════════════════════════════════════════════════════════════════ */

/* Custom properties terdaftar agar perubahan nilai bisa dianimasikan
   (default browser: custom property tidak interpolable). */
@property --m3-lw { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --m3-bw { syntax: "<length>"; inherits: true; initial-value: 1px; }

/* ── Wrapper: posisi relatif + ketebalan outline (1px normal, 2px fokus) ── */
.form-group:has(> .form-label):has(> .sp-input),
.form-group:has(> .form-label):has(> .numinput),
.form-group:has(> .form-label):has(> .sp-select),
.form-group:has(> .form-label):has(> textarea),
.form-group:has(> .form-label):has(> .input-trailing-wrapper),
.form-group.m3-auto {
    position: relative;
    --m3-bw: 1px;
    transition: --m3-lw 0.15s cubic-bezier(0.4, 0, 0.2, 1),
                --m3-bw 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── OUTLINE rounded penuh + notch (satu pseudo, mengikuti radius) ── */
.form-group:has(> .form-label):has(> .sp-input)::before,
.form-group:has(> .form-label):has(> .numinput)::before,
.form-group:has(> .form-label):has(> .sp-select)::before,
.form-group:has(> .form-label):has(> textarea)::before,
.form-group:has(> .form-label):has(> .input-trailing-wrapper)::before,
.form-group.m3-auto::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 10px;
    padding: var(--m3-bw);
    /* clip = border-box: background harus menutupi BAND mask (ring 1px di
       area padding). content-box membuat bg hanya mengisi area dalam →
       irisan dengan mask band = kosong → outline TIDAK tergambar. */
    background: linear-gradient(var(--input-border), var(--input-border)) border-box;
    -webkit-mask:
        linear-gradient(#000 0 0) content-box,
        linear-gradient(#000 0 0),
        linear-gradient(transparent 0 0) 12px 0 no-repeat;
    -webkit-mask-composite: xor;
    mask:
        linear-gradient(#000 0 0) content-box,
        linear-gradient(#000 0 0),
        linear-gradient(transparent 0 0) 12px 0 no-repeat;
    mask-composite: exclude;
    /* ukuran notch di-set lewat longhand agar var() ter-resolve benar */
    -webkit-mask-size: auto, auto, var(--m3-lw, 0px) var(--m3-bw);
    mask-size: auto, auto, var(--m3-lw, 0px) var(--m3-bw);
    pointer-events: none;
    z-index: 2;
}

/* ── Field: tanpa border sendiri (outline dari pseudo), transparan ── */
.form-group:has(> .form-label):has(> .sp-input) > .sp-input,
.form-group:has(> .form-label):has(> .numinput) > .numinput,
.form-group:has(> .form-label):has(> .sp-select) > .sp-select,
.form-group:has(> .form-label):has(> textarea) > textarea,
.form-group:has(> .form-label):has(> .input-trailing-wrapper) > .input-trailing-wrapper .sp-input,
.form-group.m3-auto > .sp-input,
.form-group.m3-auto > .numinput,
.form-group.m3-auto > .sp-select,
.form-group.m3-auto > textarea,
.form-group.m3-auto > .input-trailing-wrapper .sp-input {
    border: none;
    background-color: transparent;
    border-radius: 10px;
    caret-color: var(--accent);
}

/* Select tetap punya panah chevron */
.form-group:has(> .form-label):has(> .sp-select) > .sp-select,
.form-group.m3-auto > .sp-select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
}

/* Placeholder adalah petunjuk tunggal ketika field kosong, baik resting maupun fokus. */
.form-group:has(> .form-label):has(> .sp-input) > .sp-input::placeholder,
.form-group:has(> .form-label):has(> .numinput) > .numinput::placeholder,
.form-group:has(> .form-label):has(> textarea) > textarea::placeholder,
.form-group:has(> .form-label):has(> .input-trailing-wrapper) > .input-trailing-wrapper .sp-input::placeholder,
.form-group.m3-auto > .sp-input::placeholder,
.form-group.m3-auto > .numinput::placeholder,
.form-group.m3-auto > .input-trailing-wrapper .sp-input::placeholder {    opacity: 1;
}

/* Fokus selalu memakai floating label; placeholder disembunyikan agar tidak
   tampil bersamaan dengan label. */
.form-group:has(> .form-label):not(.m3-off):focus-within > input::placeholder,
.form-group:has(> .form-label):not(.m3-off):focus-within > textarea::placeholder,
.form-group:has(> .form-label):not(.m3-off):focus-within > .numinput::placeholder,
.form-group:has(> .form-label):not(.m3-off):focus-within > .input-trailing-wrapper input::placeholder,
.form-group.m3-auto:not(.m3-off):focus-within input::placeholder,
.form-group.m3-auto:not(.m3-off):focus-within textarea::placeholder {
    opacity: 0 !important;
}


/* ── Label: transparan, RESTING ↔ FLOATING ── */
.form-group:has(> .form-label):has(> .sp-input) > .form-label,
.form-group:has(> .form-label):has(> .numinput) > .form-label,
.form-group:has(> .form-label):has(> .sp-select) > .form-label,
.form-group:has(> .form-label):has(> textarea) > .form-label,
.form-group:has(> .form-label):has(> .input-trailing-wrapper) > .form-label,
.form-group.m3-auto > .form-label {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    left: 16px;              /* sejajar teks input (padding 16px) — ala M3 */
    margin: 0;
    padding: 0;
    display: inline-block;
    font-size: 12px;         /* RESTING = ukuran teks input (M3 body-large) */
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
    line-height: 1.3;
    color: var(--text-tertiary);
    background: transparent;
    z-index: 3;
    pointer-events: none;
    white-space: nowrap;
    transition: top 0.15s cubic-bezier(0.4, 0, 0.2, 1),
                font-size 0.15s cubic-bezier(0.4, 0, 0.2, 1),
                color 0.15s cubic-bezier(0.4, 0, 0.2, 1),
                transform 0.15s cubic-bezier(0.4, 0, 0.2, 1),
                background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── HOVER (M3): outline menggelap saat pointer di atas field ── */
.form-group:has(> .form-label):has(> .sp-input):not(:focus-within):hover::before,
.form-group:has(> .form-label):has(> .numinput):not(:focus-within):hover::before,
.form-group:has(> .form-label):has(> .sp-select):not(:focus-within):hover::before,
.form-group:has(> .form-label):has(> textarea):not(:focus-within):hover::before,
.form-group:has(> .form-label):has(> .input-trailing-wrapper):not(:focus-within):hover::before,
.form-group.m3-auto:not(:focus-within):hover::before {
    background: linear-gradient(var(--input-border-hover), var(--input-border-hover)) border-box;
}

/* ── DISABLED (M3): outline & label meredup ── */
.form-group:has(> .form-label):has(> .sp-input:disabled)::before,
.form-group:has(> .form-label):has(> .numinput:disabled)::before,
.form-group:has(> .form-label):has(> textarea:disabled)::before,
.form-group.m3-auto:has(> .sp-input:disabled)::before {
    opacity: 0.45;
}
.form-group:has(> .form-label):has(> .sp-input:disabled) > .sp-input,
.form-group:has(> .form-label):has(> .numinput:disabled) > .numinput,
.form-group:has(> .form-label):has(> textarea:disabled) > textarea,
.form-group.m3-auto:has(> .sp-input:disabled) > .sp-input {
    color: var(--text-tertiary);
}
.form-group:has(> .form-label):has(> .sp-input:disabled) > .form-label,
.form-group:has(> .form-label):has(> .numinput:disabled) > .form-label,
.form-group:has(> .form-label):has(> textarea:disabled) > .form-label,
.form-group.m3-auto:has(> .sp-input:disabled) > .form-label {
    opacity: 0.55;
}

/* RESTING: label di dalam + outline UTUH (--m3-lw 0 → notch hilang) */
/* Field kosong: outline utuh dan label tetap menjadi placeholder di dalam field.
   Gunakan class dari JS, karena NumInput tidak selalu memiliki atribut placeholder. */
.form-group:not(.m3-filled) {
    --m3-lw: 0px !important;
}
.form-group:not(.m3-filled) > .form-label {
    visibility: hidden;
}/* FLOATING: label naik ke garis outline saat fokus/terisi/nilai tetap ada */
.form-group.m3-filled > .form-label,
.form-group:has(> .form-label):has(> .sp-select) > .form-label {
    top: -7px;               /* pusat label = tengah garis outline */
    transform: none;
    left: 12px;              /* box mulai di tepi notch; +padding 4px → teks tetap di 16px */
    padding: 0 4px;          /* patch menutup penuh lebar notch (w+8) */
    background: var(--m3-label-bg, var(--surface-solid, var(--surface)));
    font-size: 12px;         /* M3 label-small */
    font-weight: 400;
    letter-spacing: 0.4px;
}
/* ── FOKUS: outline accent 2px (tanpa ring/outline ganda dari snr-theme) ── */
.form-group:has(> .form-label):focus-within,
.form-group.m3-auto:focus-within {
    --m3-bw: 2px;
}
.form-group:has(> .form-label):focus-within::before,
.form-group.m3-auto:focus-within::before {
    background: linear-gradient(var(--accent), var(--accent)) border-box;
}
.form-group:has(> .form-label):focus-within > .sp-input,
.form-group:has(> .form-label):focus-within > .numinput,
.form-group:has(> .form-label):focus-within > .sp-select,
.form-group:has(> .form-label):focus-within > textarea,
.form-group:has(> .form-label):focus-within > .input-trailing-wrapper .sp-input,
.form-group.m3-auto:focus-within > .sp-input,
.form-group.m3-auto:focus-within > .numinput,
.form-group.m3-auto:focus-within > .sp-select,
.form-group.m3-auto:focus-within > textarea,
.form-group.m3-auto:focus-within > .input-trailing-wrapper .sp-input {
    box-shadow: none;
    outline: none;
    background-color: transparent;
}



/* ── OPT-OUT M3 untuk textbox CARI (datagrid search / debounced filter) ──
   Search box tampil polos: border asli 1px selalu tampak, placeholder
   selalu tampak, hover menggelap — M3 floating label DIIHILANGKAN.
   Otomatis untuk .search-box.form-group; manual via class .m3-off.
   (Catatan: aturan M3 memakai :has() ber-specifity tinggi, jadi di sini
   wajib !important untuk menang.) */
.search-box.form-group,
.form-group.m3-off {
    --m3-lw: 0px !important;
    --m3-bw: 1px !important;
}
.search-box.form-group::before,
.form-group.m3-off::before { content: none !important; }
/* Label M3 dihilangkan — placeholder yang menjadi petunjuk */
.search-box.form-group > .form-label,
.form-group.m3-off > .form-label { display: none !important; }
.search-box.form-group > .sp-input,
.search-box.form-group > .input-trailing-wrapper .sp-input,
.search-box.form-group > textarea,
.form-group.m3-off > .sp-input,
.form-group.m3-off > .input-trailing-wrapper .sp-input,
.form-group.m3-off > textarea {
    border: 1px solid var(--input-border) !important;
    background-color: transparent !important;
    box-shadow: none !important;
    outline: none !important;
}
.search-box.form-group > .sp-input:focus,
.search-box.form-group > .input-trailing-wrapper .sp-input:focus,
.form-group.m3-off > .sp-input:focus,
.form-group.m3-off > .input-trailing-wrapper .sp-input:focus {
    border-color: var(--accent) !important;
}
.search-box.form-group > .sp-input:not(:focus):hover,
.search-box.form-group > .input-trailing-wrapper .sp-input:not(:focus):hover,
.search-box.form-group > textarea:not(:focus):hover,
.form-group.m3-off > .sp-input:not(:focus):hover,
.form-group.m3-off > .input-trailing-wrapper .sp-input:not(:focus):hover,
.form-group.m3-off > textarea:not(:focus):hover {
    border-color: var(--input-border-hover) !important;
}
.search-box.form-group > .sp-input::placeholder,
.search-box.form-group > .input-trailing-wrapper .sp-input::placeholder,
.form-group.m3-off > .sp-input::placeholder,
.form-group.m3-off > .input-trailing-wrapper .sp-input::placeholder { opacity: 1 !important; }

/* ── Glassmorphism override: label floating tanpa notch/mask ──
   Outline dibiarkan utuh; label glass menutup garis secara optik dengan
   box-shadow. Ini lebih natural di atas surface transparan. */
.form-group:has(> .form-label):has(> .sp-input)::before,
.form-group:has(> .form-label):has(> .numinput)::before,
.form-group:has(> .form-label):has(> .sp-select)::before,
.form-group:has(> .form-label):has(> textarea)::before,
.form-group:has(> .form-label):has(> .input-trailing-wrapper)::before,
.form-group.m3-auto::before {
    border: var(--m3-bw) solid var(--input-border);
    padding: 0;
    background: none;
    -webkit-mask: none;
    mask: none;
}
.form-group:has(> .form-label):focus-within::before,
.form-group.m3-auto:focus-within::before {
    border-color: var(--accent);
}
.form-group.m3-filled > .form-label,
.form-group:has(> .form-label):has(> .sp-select) > .form-label,
.form-group:focus-within > .form-label {
    visibility: visible !important;
    background: var(--surface-solid);
    border: 1px solid var(--glass-border);
    border-radius: 6px;
    padding: 1px 7px;
}
.dark .form-group.m3-filled > .form-label,
.dark .form-group:has(> .form-label):has(> .sp-select) > .form-label,
.dark .form-group:focus-within > .form-label {
    visibility: visible !important;
    background: rgba(20, 24, 35, .72);
    box-shadow: 5px 0 0 rgba(20,24,35,.72),
                -5px 0 0 rgba(20,24,35,.72),
                0 0 8px rgba(0,0,0,.18);
}

/* ── Final M3 label treatment ──
   Empty field: placeholder only. Filled/select/focused field: floating label.
   Label diberi border yang sama dengan outline agar tampil sebagai bagian dari
   field, bukan chip glass yang terpisah. */
.form-group.m3-filled > .form-label,
.form-group:has(> .form-label):has(> .sp-select) > .form-label,
.form-group:focus-within > .form-label {
    visibility: visible !important;
    border-color: var(--input-border);
    left: 16px;
    z-index: 4;
    background: var(--surface-solid, var(--surface));
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
}
.form-group:focus-within > .form-label {
    border-color: var(--accent);
    color: var(--accent);
}
.dark .form-group.m3-filled > .form-label,
.dark .form-group:has(> .form-label):has(> .sp-select) > .form-label {
    background: var(--surface-solid, var(--surface));
    border-color: var(--input-border);
}
.dark .form-group:focus-within > .form-label {
    border-color: var(--accent);
    color: var(--accent);
}

/* ── Master filter controls ──
   Semua kontrol filter memakai tinggi field M3 yang sama, sehingga tombol
   Terapkan/Reset tidak lebih pendek dari input atau select di sebelahnya. */
.filter-panel {
    --filter-control-height: 46px;
}

/* ── SATU tinggi kontrol untuk SEMUA bentuk baris filter ────────────────────────────────────
   Sebelumnya hanya `select`/`numinput` DI DALAM `.filter-panel` yang dipaksa seragam (46 px),
   sedangkan `input` tetap tinggi alaminya (± 40 px) dan tombol 38 px — jadi di satu baris filter
   ada tiga tinggi berbeda dan tak ada yang sejajar (laporan user 2026-09-22: PPOB & QRIS).
   Tombol yang berada LANGSUNG di baris (bukan dibungkus `.filter-actions`) juga ikut diatur,
   karena itulah bentuk yang dipakai PPOB (tombol "Tampilkan" di dalam grup berlabel `&nbsp;`)
   dan QRIS (tombol telanjang di ujung baris).
   `--filter-control-height` tetap boleh ditimpa per halaman; nilai bawaan 40 px = tinggi alami
   `.sp-input`, jadi halaman di luar panel filter tidak berubah tinggi. */
.filter-row .filter-group > .sp-input,
.filter-row .filter-group > .sp-select,
.filter-row .filter-group > .numinput,
.filter-row .filter-group > .sp-btn,
.filter-row > .sp-input,
.filter-row > .sp-select,
.filter-row > .sp-btn,
.filter-panel .filter-group > .sp-input,
.filter-panel .filter-group > .sp-select,
.filter-panel .filter-group > .numinput,
.filter-panel .filter-group > .sp-btn {
    height: var(--filter-control-height, 40px);
    min-height: var(--filter-control-height, 40px);
    box-sizing: border-box;
}

/* Padding teks di dalam kontrol filter dibuat sama (13/9 → 12/12) supaya tulisan tidak menempel
   ke bawah pada tinggi 46 px; select sudah memakai angka ini sejak awal. */
.filter-row .filter-group > .sp-input,
.filter-row .filter-group > .sp-select,
.filter-panel .filter-group > .sp-input,
.filter-panel .filter-group > .sp-select {
    padding-top: 12px;
    padding-bottom: 12px;
}

.filter-panel .filter-actions {
    height: var(--filter-control-height);
    align-items: stretch;
}
.filter-panel .filter-actions > .sp-btn {
    height: var(--filter-control-height);
    min-height: var(--filter-control-height);
    padding-top: 10px;
    padding-bottom: 10px;
}

/* Supporting text M3 — DI LUAR container field (di bawah outline) */
.entry-akun-hint { font-size: 12px; color: var(--accent); margin: -4px 0 0 16px; }

/* Form-group di dalam toolbar/filter-bar: rapat (tanpa margin bawah) */
.filter-row .form-group,
.trx-toolbar .form-group,
.dg-toolbar .form-group { margin-bottom: 0; }

/* ── Kotak "Cari" di toolbar History (semua halaman transaksi & akuntansi) ──
   Dulu batas lebar dipasang sebagai style inline (`max-width:320px`) di tiap halaman,
   sehingga di layar sempit ruangnya terbuang dan kotak cari tetap sempit.
   Desktop: mengisi ruang tersisa, maksimum 320px (sama seperti sebelumnya).
   Mobile (≤899px, ambang yang sama dengan `.trx-entry` desktop→mobile): penuh lebar. */
.trx-cari { flex: 1 1 220px; min-width: 200px; max-width: 320px; margin-bottom: 0; }
.trx-cari .input-trailing-wrapper,
.trx-cari .input-trailing-wrapper .sp-input { width: 100%; }

/* Baris rentang tanggal ("Dari Tanggal" s/d "s/d Tanggal") di toolbar yang sama.
   Desktop: dua kotak sejajar, masing-masing maksimum 170px.
   Mobile: baris mengisi penuh dan kotak dibagi RATA (dulu keduanya mentok 160/170px
   lalu menyisakan lubang di kanan). */
.trx-toolbar .trx-dates { display: flex; gap: 8px; flex: 1 1 360px; align-items: flex-end; }
.trx-toolbar .trx-dates > .form-group { flex: 1 1 150px; max-width: 170px; min-width: 0; margin-bottom: 0; }
.trx-toolbar .trx-dates > .form-group > .sp-input { width: 100%; max-width: none; }

@media (max-width: 899px) {
    .trx-cari { flex: 1 1 100%; min-width: 0; max-width: none; }
    .trx-toolbar .trx-dates { flex: 1 1 100%; min-width: 0; }
    .trx-toolbar .trx-dates > .form-group { flex: 1 1 0; max-width: none; }
}

/* ── Panel entry transaksi — SATU definisi (dulu disalin di 8 halaman) ──
   Permukaan panel yang NAIK dari halaman: `--panel-fill` + `--panel-border` +
   `--panel-shadow`. Sebelumnya tiap halaman menulis sendiri
   `border: 1px solid var(--border-light); background: var(--table-stripe)`.
   Di mode terang kombinasi itu rusak dua kali: `--table-stripe` MENGELAP panel
   (2% hitam di atas halaman abu muda → kontras 1.04:1) dan `--border-light` putih
   70% praktis tidak terlihat (bahkan lebih terang dari panelnya), sehingga panel
   jadi abu di atas abu tanpa tepi dan tanpa elevasi. Di mode gelap kebetulan
   tampak benar (tint putih di atas near-black), jadi kerusakannya hanya muncul
   di mode terang.
   Halaman tetap memiliki layout-nya sendiri (display/gap/padding) — di sini hanya
   permukaan + tepi + bayangannya, supaya mengubah tampilan panel cukup di satu tempat. */
.trx-entry,
.tbstrx-entry,
.jum-entry,
.bukarek-entry {
    background: var(--panel-fill);
    border: 1px solid var(--panel-border);
    box-shadow: var(--panel-shadow);
}

/* ── Form entry transaksi di mobile: satu kolom ──
   Dulu aturan ini DISALIN di 8 halaman (`TbsTrx`, `TbbTrx`, `TbjTrx`, `KrkTrx`,
   `AnggotaTrx`, `TwTrx`, `PbTopupTrx`, `PbPerpanjangTrx`) dan salinannya sudah tidak
   seragam: 4 halaman memakai nama kelas `tbstrx-entry` (sisa salin-tempel dari halaman
   TBS) berikut dua aturan tambahan yang tidak ada di halaman lain. Satu definisi di sini
   berlaku untuk KEDUA nama kelas supaya menambah halaman baru tidak perlu menyalin apa pun;
   kelas `tbstrx-entry` sengaja tidak dinamai ulang di halaman lama agar tidak menyentuh
   selector lain. */
@media (max-width: 899px) {
    /* gap/padding di sini hanya DEFAULT untuk halaman yang tidak mendefinisikan kontainer
       entry-nya sendiri; halaman transaksi punya aturan `.trx-entry`/`.tbstrx-entry` sendiri
       di blok `<style>` halaman dan nilainya yang menang (dimuat setelah file ini). */
    .trx-entry,
    .tbstrx-entry { gap: 8px; padding: 12px 14px; }
    .trx-entry .form-group,
    .tbstrx-entry .form-group { display: flex; flex-direction: column; align-items: stretch; gap: 0; margin-bottom: 0; }
    .trx-entry .form-group > .sp-input,
    .trx-entry .form-group > .sp-select,
    .trx-entry .form-group > .input-trailing-wrapper,
    .tbstrx-entry .form-group > .sp-input,
    .tbstrx-entry .form-group > .sp-select,
    .tbstrx-entry .form-group > .input-trailing-wrapper { width: 100%; flex: none; min-width: 0; }
    .trx-entry .form-group .sp-input,
    .trx-entry .form-group .sp-select,
    .tbstrx-entry .form-group .sp-input,
    .tbstrx-entry .form-group .sp-select { width: 100%; }
}

/* ── Summary strip & footer halaman transaksi ──
   Dulu disalin di 9 halaman (TbsTrx, TbbTrx, TbjTrx, KrkTrx, AnggotaTrx, TwTrx,
   PbTopupTrx, PbPerpanjangTrx, PbTrx) dengan aturan yang identik — kecuali variasi
   warna `.val.kredit`/`.val.debet` yang memang per-halaman.
   Aturan yang dipindah: grid 4 kolom (desktop) → 2 kolom (mobile), padding/border/label/value
   summary, dan footer ringkasan. Yang TIDAK dipindah: `.trx-mobile`/`.trx-dg` display toggle
   (per-halaman, tergantung apakah ada data mobile) dan `.val.kredit`/`.val.debet` (warna
   spesifik produk). */
.trx-summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 12px; }
.trx-summary-item { padding: 8px 12px; border-radius: 10px; background: var(--table-stripe); border: 1px solid var(--border-light); }
.trx-summary-item .lbl { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-tertiary); }
.trx-summary-item .val { font-family: var(--font-mono); font-size: 14px; font-weight: 700; color: var(--text-primary); }
.trx-summary-item .val.kredit { color: var(--accent-green); }
.trx-summary-item .val.debet { color: var(--accent-red); }
.trx-footer { display: flex; align-items: center; justify-content: space-between; padding: 10px 16px 6px; flex-wrap: wrap; gap: 8px; }
.trx-footer-summary { font-size: 12px; color: var(--text-tertiary); }
.trx-footer-summary strong { color: var(--text-primary); }
@media (max-width: 899px) {
    .trx-summary { grid-template-columns: 1fr 1fr; }
}

/* ── Final authoritative M3 state ──
   Harus berada paling akhir agar tidak ditimpa selector legacy di atasnya.
   Empty = placeholder; focus/filled/select = floating label. */
.form-group:has(> .form-label):not(.m3-off) > .form-label,
.form-group.m3-auto:not(.m3-off) > .form-label {
    visibility: hidden;
}
.form-group:has(> .form-label):not(.m3-off):focus-within > .form-label,
.form-group.m3-filled:not(.m3-off) > .form-label,
.form-group:has(> .form-label):has(> input:not(:placeholder-shown)) > .form-label,
.form-group:has(> .form-label):has(> textarea:not(:placeholder-shown)) > .form-label,
.form-group:has(> .form-label):has(> .numinput:not(:placeholder-shown)) > .form-label,
.form-group:has(> .form-label):has(> .sp-select):not(.m3-off) > .form-label,
.form-group:has(> .form-label):has(> .input-trailing-wrapper):not(.m3-off) > .form-label,
.form-group:has(> .form-label):has(> input:disabled):not(.m3-off) > .form-label,
.form-group:has(> .form-label):has(> textarea:disabled):not(.m3-off) > .form-label,
.form-group.m3-auto:not(.m3-off):focus-within > .form-label,
.form-group.m3-auto.m3-filled:not(.m3-off) > .form-label {
    visibility: visible !important;
    top: -7px;
    left: 16px;
    transform: none;
    padding: 1px 7px;
    margin: 0;
    border: 1px solid var(--input-border);
    border-radius: 6px;
    background: var(--surface-solid, var(--surface));
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    color: var(--text-tertiary);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .4px;
    z-index: 4;
    box-shadow: none;
}
/* Posisi label menyesuaikan alignment isi field. */
.form-group.m3-label-end:not(.m3-off) > .form-label {
    left: auto !important;
    right: 16px !important;
}
.form-group.m3-label-start:not(.m3-off) > .form-label {
    left: 16px !important;
    right: auto !important;
}
/* Beri ruang vertikal sedikit lebih longgar agar isi tidak terlalu dekat
   dengan floating label, tanpa mengubah tinggi field secara berlebihan. */
.form-group:has(> .form-label):not(.m3-off) > input,
.form-group:has(> .form-label):not(.m3-off) > textarea,
.form-group:has(> .form-label):not(.m3-off) > .numinput,
.form-group:has(> .form-label):not(.m3-off) > .input-trailing-wrapper .sp-input {
    height: 46px;
    padding-top: 11px;
    padding-bottom: 11px;
}
.form-group:has(> .form-label):not(.m3-off) > .sp-select {
    height: 46px;
    padding-top: 11px;
    padding-bottom: 11px;
}
.form-group:has(> .form-label):not(.m3-off):focus-within > .form-label,
.form-group.m3-auto:not(.m3-off):focus-within > .form-label {
    border-color: var(--accent);
    color: var(--accent);
}
/* Search tetap plain, termasuk input pencarian di modal. */
.form-group.m3-off > .form-label,
.search-box.form-group > .form-label {
    visibility: hidden !important;
}
.form-group.m3-off::before,
.search-box.form-group::before {
    content: none !important;
}

/* Placeholder M3: disembunyikan saat field fokus agar area input bersih;
   muncul kembali saat field kosong dan tidak fokus. */
.form-group:has(> .form-label):not(.m3-off) > input::placeholder,
.form-group:has(> .form-label):not(.m3-off) > textarea::placeholder,
.form-group:has(> .form-label):not(.m3-off) > .numinput::placeholder,
.form-group:has(> .form-label):not(.m3-off) > .input-trailing-wrapper input::placeholder,
.form-group.m3-auto:not(.m3-off) input::placeholder,
.form-group.m3-auto:not(.m3-off) textarea::placeholder {
    opacity: 0;
}
.form-group:has(> .form-label):not(.m3-off):not(:focus-within):not(.m3-filled) > input::placeholder,
.form-group:has(> .form-label):not(.m3-off):not(:focus-within):not(.m3-filled) > textarea::placeholder,
.form-group:has(> .form-label):not(.m3-off):not(:focus-within):not(.m3-filled) > .numinput::placeholder,
.form-group:has(> .form-label):not(.m3-off):not(:focus-within):not(.m3-filled) > .input-trailing-wrapper input::placeholder,
.form-group.m3-auto:not(.m3-off):not(:focus-within):not(.m3-filled) input::placeholder,
.form-group.m3-auto:not(.m3-off):not(:focus-within):not(.m3-filled) textarea::placeholder {
    opacity: 1;
}
/* ── Peringatan "Perubahan belum disimpan" (dibuat js/modal-guard.js) ──
   Elemennya dibuat runtime oleh JS, jadi gayanya HARUS global (bukan <style> di
   komponen). z-index di atas semua dialog supaya selalu terlihat. */
.sp-guard-overlay {
    position: fixed; inset: 0; z-index: 1200;
    background: rgba(15, 23, 42, 0.5);
    display: flex; align-items: center; justify-content: center;
    animation: spGuardIn 0.12s ease;
}
.sp-guard {
    background: var(--modal-bg, var(--surface-solid));
    border: 1px solid var(--border-light);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-dropdown);
    width: min(440px, calc(100vw - 32px));
    padding: 18px 20px 16px;
}
.sp-guard-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.sp-guard-head .material-symbols-rounded { font-size: 22px; color: var(--gold, #B45309); }
.sp-guard-head h4 { margin: 0; font-size: 16px; font-weight: 700; color: var(--text-primary); }
.sp-guard-msg { margin: 0 0 16px; font-size: 13px; line-height: 1.55; color: var(--text-secondary); }
.sp-guard-actions { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }
@keyframes spGuardIn { from { opacity: 0; } to { opacity: 1; } }

/* ────────────────────────────────────────────────────────────────
   LAPORAN AKUNTANSI (Akuntansi ▸ Laporan)
   Dipakai sembilan halaman /laporan-akuntansi/* — satu blok CSS supaya
   halaman laporan tidak masing-masing menyalin <style> (dulu pola itu
   membuat tiap halaman punya tabel dengan kepadatan berbeda).
   ──────────────────────────────────────────────────────────────── */
.rep-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin-bottom: 12px; }
.rep-kpi { background: var(--surface-solid); border: 1px solid var(--border-light); border-radius: 12px; padding: 10px 13px; }
.rep-kpi .n { font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text-primary); line-height: 1.25; }
.rep-kpi .l { font-size: 10px; text-transform: uppercase; letter-spacing: .4px; color: var(--text-tertiary); margin-top: 3px; }
.rep-kpi.bad { border-color: rgba(196, 82, 74, .5); } .rep-kpi.bad .n { color: #c4524a; }
.rep-kpi.ok { border-color: rgba(46, 125, 50, .45); } .rep-kpi.ok .n { color: #2e7d32; }

.rep-sheet { background: var(--surface-solid); border: 1px solid var(--border-light); border-radius: 14px; padding: 14px 16px; margin-bottom: 14px; }
/* Pager laporan (`PagerBaris`): satu baris selebar kotak — sejajar dengan tepi tabel di
   atasnya (permintaan user 2026-09-22: "Ukur Pagination agar pas di kolom A4"). */
.rep-pager { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; margin-top: 10px; }
.rep-pager-info { font-size: 12px; color: var(--text-tertiary); }
.rep-pager-kertas { justify-content: flex-end; margin-top: 6px; }
.rep-sheet-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.rep-sheet-title { margin: 0; font-size: 15px; font-weight: 700; color: var(--text-primary); }
.rep-sheet-sub { margin: 3px 0 0; font-size: 12px; color: var(--text-tertiary); }
.rep-scroll { overflow-x: auto; }
.rep-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.rep-table th { padding: 8px 10px; text-align: left; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .5px; color: var(--text-tertiary); border-bottom: 2px solid var(--accent); white-space: nowrap; }
.rep-table td { padding: 6px 10px; border-bottom: 1px solid var(--border-color); color: var(--text-primary); vertical-align: top; }
.rep-table tr:hover td { background: var(--table-hover); }
.rep-table .r { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rep-table .mono { font-family: var(--font-mono); font-size: 12px; }
.rep-table .neg { color: #c4524a; }
.rep-table .pos { color: #2e7d32; }
.rep-table tfoot td { font-weight: 700; background: var(--table-stripe); border-top: 2px solid var(--accent); border-bottom: none; }
.rep-table tr.rep-group > td { background: var(--table-stripe); font-weight: 600; }
.rep-table tr.rep-sub > td:first-child { padding-left: 24px; }
.rep-table tr.rep-link { cursor: pointer; }
.rep-table tr.rep-link:hover td { background: var(--accent-light); }
.rep-empty { padding: 24px; text-align: center; color: var(--text-tertiary); font-size: 13px; }
.rep-note { font-size: 12px; color: var(--text-secondary); background: var(--table-stripe); border: 1px dashed var(--border-light); border-radius: 10px; padding: 10px 13px; margin-bottom: 12px; line-height: 1.6; }
.rep-ttd { display: flex; justify-content: space-between; gap: 24px; margin-top: 26px; text-align: center; font-size: 12px; color: var(--text-secondary); }
.rep-ttd .col { flex: 1; }
.rep-ttd .nm { margin-top: 56px; padding-top: 5px; border-top: 1px solid var(--border-light); font-weight: 700; color: var(--text-primary); }
.rep-chip { display: inline-flex; align-items: center; gap: 4px; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; background: var(--accent-light); color: var(--accent); }
.rep-chip.warn { background: rgba(196, 82, 74, .14); color: #c4524a; }

/* ── Spanduk "versi aplikasi baru tersedia" (dipasang `MainLayout`) ──
   Aplikasi ini SPA: tab yang sudah terbuka TETAP menjalankan klien lama setelah server
   di-deploy, jadi tanpa penanda ini tidak ada cara melihat build mana yang sedang jalan
   (nyata 2026-09-25: tiga kali perubahan bentuk garis Neraca dilaporkan "build berapa
   kalipun tetap sama" — yang dibaca ternyata klien lama). */
.sp-versi-baru {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    margin-bottom: 12px; padding: 10px 14px; border-radius: 12px;
    background: var(--accent-light); color: var(--accent);
    font-size: 12.5px; font-weight: 600;
}
.sp-versi-baru .material-symbols-rounded { font-size: 18px; }
.sp-versi-btn {
    margin-left: auto; border: 0; cursor: pointer; padding: 6px 14px; border-radius: 999px;
    background: var(--accent); color: #fff; font-size: 12.5px; font-weight: 600;
}
.sp-versi-btn:hover { filter: brightness(1.08); }
.rep-chip.ok { background: rgba(46, 125, 50, .14); color: #2e7d32; }

/* ── NeracaTampilan / NeracaSandiTampilan: bentuk Neraca skontro (AKTIVA kiri · PASSIVA kanan) ──
   Dipakai halaman layar DAN halaman cetak (`cetak.css` hanya menyesuaikan ukuran/kolom),
   jadi bentuk Neraca tidak pernah berbeda antara yang dilihat dan yang tercetak. */
.nt-wrap { font-size: 12.5px; }
.nt-kosong { padding: 18px; text-align: center; color: var(--text-tertiary); font-size: 12.5px; }
/* Kepala tabel `nt` generik. Pita judul sisi Neraca skontro (AKTIVA · PASSIVA) bukan ini —
   ia baris `tr.nt-band` di dalam tabel skontro (lihat `.nt-2sisi` di bawah). */
.nt { width: 100%; border-collapse: collapse; }
.nt th {
    text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .3px;
    color: var(--text-secondary); border-bottom: 1px solid var(--border-light); padding: 5px 6px;
}
.nt td { padding: 4px 6px; border-bottom: 1px solid var(--border-light); vertical-align: top; }
.nt tfoot td { font-weight: 700; border-bottom: none; }
/* ── Garis laporan (bentuk kertas lembaga `Contoh Laporan Keuangan/CoA/Neraca.pdf`) ──
   Garis KEPALA kolom, garis di atas setiap subtotal/kelompok, garis atas total, dan garis
   GANDA di bawah total terakhir. Kertas laporan lembaga tidak memakai grid per baris, jadi
   garis tipis antar baris tetap ada hanya di LAYAR (memudahkan mata mengikuti baris) dan
   dimatikan saat dicetak (`cetak.css`). Tanpa garis-garis ini laporan terlihat seperti
   daftar biasa — keluhan user 2026-09-17: "Neraca yang gak ada garis2 nya". */
.nt thead th { border-top: 1.2px solid var(--text-primary); border-bottom: 1px solid var(--text-primary); }
.nt > tbody > tr.nt-l0 > td { border-top: 1.2px solid var(--border-color); }
.nt > tbody > tr.nt-sub > td { border-top: 1px solid var(--border-color); }
/* ── Baris KEPALA KELOMPOK juga bergaris di BAWAHNYA (permintaan user 2026-09-24: "group header
   tidak memiliki bottom horizontal divider, jadinya aneh tampilannya"). Sebelumnya garis kelompok
   hanya digambar DI ATAS barisnya, jadi kepala kelompok tidak pernah tertutup dan barisnya
   menggantung. Karena `border-collapse: collapse`, dua garis bertetangga (bawah kepala
   bertingkat + atas kepala berikutnya) MENYATU — tidak ada garis ganda. */
.nt > tbody > tr.nt-l0 > td { border-bottom: 1.2px solid var(--border-color); }
.nt > tbody > tr.nt-sub > td { border-bottom: 1px solid var(--border-color); }
.nt tfoot > tr > td { border-top: 1.2px solid var(--text-primary); }
.nt tfoot > tr:last-child > td { border-bottom: 2.4px double var(--text-primary); }
/* Skontro: SATU tabel EMPAT kolom — [Uraian|Jumlah] AKTIVA · [Uraian|Jumlah] PASSIVA,
   baris ke-i memuat baris ke-i kedua sisi. Lihat komentar di `NeracaTampilan.razor`:
   itulah yang membuat baris TOTAL kedua sisi sejajar dan garis mendatar menyentuh garis
   tegak pemisah (catatan user 2026-09-16) tanpa penambal baris kosong. */
.nt-2sisi { table-layout: fixed; }
/* Garis tegak pemisah AKTIVA|PASSIVA. Dulu jarak ke garis itu padding pembungkus, jadi
   garis MENDATAR tiap sisi (border sel) berhenti 4mm sebelum garis tegak. Sekarang jarak
   itu padding SEL (variabel `--nt-jarak`), sehingga tepi sel = tepi garis. */
.nt-2sisi { --nt-jarak: 0px; }
.nt-2sisi th.nt-pisah, .nt-2sisi td.nt-pisah { border-left: 1px solid var(--border-color); }
.nt-2sisi td.nt-nama:nth-child(3) { --nt-jarak: 14px; }
/* Angka sisi kiri diberi jarak dari garis tegak — tanpa memindahkan garisnya. */
.nt-2sisi td.nt-nom:nth-child(2) { padding-right: 14px; }
/* Pita judul sisi (AKTIVA · PASSIVA) — satu baris, ikut terbelah garis tegak. */
.nt-2sisi thead tr.nt-band th {
    padding: 6px 8px; font-weight: 700; font-size: 12px; letter-spacing: .4px;
    background: var(--table-stripe);
}
/* Indentasi bertingkat di kolom Uraian: Kategori → Golongan → Header → Akun.
   `calc(… + var(--nt-jarak))` = indentasi + jarak dari garis tegak (0 untuk sisi kiri). */
.nt-2sisi td.nt-nama { padding-left: calc(6px + var(--nt-jarak)); }
.nt-2sisi td.nt-nama.nt-l1 { padding-left: calc(14px + var(--nt-jarak)); }
.nt-2sisi td.nt-nama.nt-l2 { padding-left: calc(28px + var(--nt-jarak)); }
.nt-2sisi td.nt-nama.nt-l3 { padding-left: calc(42px + var(--nt-jarak)); }
.nt-2sisi td.nt-l0 { font-weight: 700; }
.nt-2sisi td.nt-nama.nt-l0 { text-transform: uppercase; letter-spacing: .3px; padding-top: 9px; }
/* Garis mendatar per SISI — hanya sampai garis tegak pemisah, tidak menyeberang ke sisi lain
   (permintaan user 2026-09-16: "horizontal divider harusnya hanya sampai vertical divider
   yang di tengah, yang memisahkan Aktiva dan Passiva"). Kelasnya di SEL karena satu baris
   tabel memuat satu baris AKTIVA dan satu baris PASSIVA sekaligus. */
.nt-2sisi td.nt-l0 { font-weight: 700; border-top: 1.2px solid var(--border-color); border-bottom: 1.2px solid var(--border-color); }
.nt-2sisi td.nt-sub { font-weight: 600; background: var(--table-stripe); border-top: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color); }
/* Indentasi tabel `nt` lain (Rugi Laba, Lajur, Per Sandi): kelasnya di BARIS. */
.nt-l0 > td { font-weight: 700; text-transform: uppercase; letter-spacing: .3px; padding-top: 9px; }
.nt-l1 > td:first-child { padding-left: 14px; font-weight: 600; }
.nt-l2 > td:first-child { padding-left: 28px; }
.nt-l3 > td:first-child { padding-left: 42px; }
.nt-sub > td { font-weight: 600; background: var(--table-stripe); }
.nt-selisih { margin-top: 10px; font-size: 12px; color: var(--accent-red); }
/* Neraca ber-sandi = SATU kolom (No. / Pos-Pos / Sandi / Jumlah) — bentuk contoh
   `Contoh Laporan Keuangan/Sandi/Neraca.pdf`, berbeda dari skontro per akun. */
.nt-sandi .nt-no { text-align: right; color: var(--text-tertiary); padding-left: 6px; }
.nt-sandi .nt-l1 > td:first-child { font-weight: 400; }
.nt-sandi .nt-l0.nt-jarak > td { padding-top: 18px; }
/* Kolom angka & kepala dua tingkat — kelas `.r`/`.c` HARUS diumumkan di sini: aturan
   `.rep-table .r` / `table.ct .r` tidak berlaku untuk tabel `nt`, jadi tanpa ini angka
   laporan rata kiri (bug tampilan yang senyap, hanya terlihat di kertas). */
.nt th.r, .nt td.r, .nt .r { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.nt th.c, .nt td.c, .nt .c { text-align: center; }
/* Laporan Perubahan Ekuitas: satu kolom = satu akun ekuitas, dan namanya panjang
   ("Laba (SHU) Tahun Sebelumnya"). `nowrap` bawaan sel angka membuat nama kepala kolom itu
   MEMBANJIRI kolom sebelahnya — angkanya tetap `nowrap` (satu baris per sel, aturan kertas),
   hanya kepalanya yang boleh membungkus. */
.nt-ekuitas thead th { white-space: normal; }
.nt th.grup { text-align: center; text-transform: uppercase; letter-spacing: .6px; background: var(--table-stripe); }
/* Baris penutup di luar tabel (TOTAL PENDAPATAN / BIAYA / LABA-RUGI pada Neraca Percobaan). */
.nt-ringkas { margin-top: 12px; }
.nt-ringkas .baris { display: flex; justify-content: flex-end; gap: 24px; font-size: 12.5px; padding: 2px 6px; }
.nt-ringkas .baris span { min-width: 170px; text-align: right; color: var(--text-secondary); }
.nt-ringkas .baris b { min-width: 140px; text-align: right; font-family: var(--font-mono); }

/* ═══ Neraca Per Sandi — format Dinas LPD ═══
   Dua tabel terpisah (AKTIVA & PASSIVA), border hanya header + total,
   kolom tetap ada garis vertikal. Contoh: Contoh Laporan Keuangan/Sandi/Neraca.pdf. */
/* ═══ Dokumen bertab — SATU gaya PILL MODERN untuk seluruh aplikasi (keputusan user 2026-09-21) ═══
   Dipakai strip grup Transaksi (MainLayout) DAN strip di dalam halaman (Transaksi, Laporan,
   Akuntansi, Administrasi, PPOB/QRIS). Sebelumnya setiap halaman Transaksi punya gaya tab
   sendiri-sendiri (pb-tabs · bunga-tabs · ad-tabs · shu-tabs · sa-tabs) — semuanya kini memakai
   dua kelas ini saja. Tab boleh <button> (pindah tab di dalam halaman) atau <a> (tautan rute,
   mis. strip grup) — keduanya tampil sama. */
.tab-strip { display: flex; flex-wrap: wrap; gap: 4px; align-items: center;
    background: var(--table-stripe); border: 1px solid var(--border-light);
    padding: 4px; border-radius: 12px; width: fit-content; max-width: 100%;
    margin-bottom: 16px; }
.tab-btn { appearance: none; border: 0; background: none; margin: 0; border-radius: 8px;
    padding: 8px 16px; font: inherit; font-size: 13px; font-weight: 600;
    color: var(--text-secondary); cursor: pointer; white-space: nowrap;
    display: inline-flex; align-items: center; gap: 6px;
    transition: background .15s, color .15s; }
.tab-btn:hover { color: var(--text-primary); background: var(--surface); }
.tab-btn.aktif { background: var(--surface); color: var(--accent); box-shadow: var(--shadow-dropdown); }
/* Tab sebagai TAUTAN (strip grup Transaksi di MainLayout) — bukan <button>: tanpa garis bawah,
   tetap bisa diklik-tengah/di-bookmark karena alamatnya nyata. */
a.tab-btn, a.tab-btn:hover { text-decoration: none; }
/* Strip grup: pengganti sub-menu bersarang — diberi jarak dari kepala halaman. */
.tab-strip-grup { margin-bottom: 14px; margin-top: -4px; }

/* ═══ Placeholder sub-laporan yang belum dimigrasi (tab laporan bertab) ═══
   Jujur & rapi: tab tetap tampil supaya struktur menu final terlihat, isinya mengaku belum ada
   — bukan halaman kosong yang menyamar sebagai "tidak ada data". */
.sub-belum { display: flex; flex-direction: column; align-items: center; text-align: center;
    padding: 46px 24px; border: 1px dashed var(--border-color); border-radius: 14px;
    background: var(--table-stripe); }
.sub-belum-ikon { width: 64px; height: 64px; border-radius: 20px; display: flex;
    align-items: center; justify-content: center; background: var(--accent-light); margin-bottom: 14px; }
.sub-belum-ikon .material-symbols-rounded { font-size: 32px; color: var(--accent); }
.sub-belum-badge { display: inline-flex; align-items: center; gap: 6px; font-size: 12px;
    font-weight: 600; padding: 4px 12px; border-radius: 999px; background: var(--accent-light);
    color: var(--accent); margin-bottom: 12px; }
.sub-belum-judul { font-size: 1.1rem; font-weight: 700; color: var(--text-primary); margin: 0 0 8px; }
.sub-belum-teks { font-size: 13px; color: var(--text-secondary); max-width: 520px; line-height: 1.6; margin: 0; }
.sub-belum-sumber { font-size: 12px; color: var(--text-tertiary); margin-top: 10px; }
.sub-belum-sumber code { font-family: var(--font-mono); }

/* ═══ Daftar Perincian Laba Rugi (mode rl_perincian) — tampilan aplikasi ═══
   Bentuk kertas yang ditentukan Dinas ada di `cetak.css`; di layar laporan memakai tema
   aplikasi (catatan user 2026-09-17: "tampilan laporan di aplikasi tidak perlu persis
   seperti cetakan"). */
/* Kepala Laba Rugi Per Sandi: tiga baris identitas KIRI + kotak `SANDI` KANAN, sama bentuknya
   dengan lembar Neraca Per Sandi di atas kertas (`Contoh Laporan Keuangan/Sandi/Rugi Laba.pdf`). */
.perincian-lr .plr-kepala-baris { display: flex; gap: 20px; align-items: flex-start; }
.perincian-lr .plr-kepala-teks { flex: 1 1 auto; }
.perincian-lr .ns-sandi { width: 130px; flex: 0 0 130px; }
.perincian-lr .ns-sandi-judul { text-align: center; font-size: 12px; margin-bottom: 4px; }
.perincian-lr .ns-sandi-sel { display: flex; border: 1px solid var(--border-color); height: 30px; }
.perincian-lr .ns-sandi-sel > span { flex: 1; display: flex; align-items: center;
    justify-content: center; border-right: 1px solid var(--border-color); }
.perincian-lr .ns-sandi-sel > span:last-child { border-right: 0; }
.perincian-lr .plr-satuan { text-align: right; }
/* Kolom nomor alternatif baris rumus (C…J) — lebar tetap, sejajar dengan kolom prefiks. */
.perincian-lr .plr-sub { display: inline-block; min-width: 22px; }
/* Border luar tabel (kotak penuh) + divider tegak di kiri kolom Sandi & Jumlah — sama seperti
   lembar cetaknya (`Contoh Laporan Keuangan/Sandi/Rugi Laba.pdf`). */
.perincian-lr .plr-tabel { border: 1px solid var(--border-color); }
.perincian-lr .plr-tabel td.plr-sandi, .perincian-lr .plr-tabel th.plr-sandi,
.perincian-lr .plr-tabel td.plr-angka, .perincian-lr .plr-tabel th.plr-angka { border-left: 1px solid var(--border-color); }
.perincian-lr { width: 100%; }
.perincian-lr .plr-kepala { margin-bottom: 10px; }
.perincian-lr .plr-judul { font-size: 14px; font-weight: 700; color: var(--text-primary); margin-bottom: 6px; }
.perincian-lr .plr-baris { display: flex; gap: 6px; font-size: 12px; color: var(--text-secondary); }
.perincian-lr .plr-label { min-width: 180px; }
.perincian-lr .plr-satuan { font-size: 11px; color: var(--text-tertiary); margin-top: 4px; }
.plr-tabel { width: 100%; border-collapse: collapse; font-size: 13px; }
.plr-tabel th { text-align: left; padding: 6px 8px; border-bottom: 2px solid var(--border-color);
    font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--text-secondary); }
.plr-tabel td { padding: 3px 8px; vertical-align: top; }
.plr-tabel .plr-sandi { width: 70px; text-align: center; color: var(--text-secondary); }
.plr-tabel th.plr-sandi { text-align: center; }
.plr-tabel .plr-angka { width: 140px; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.plr-tabel th.plr-angka { text-align: right; }
.plr-tabel .plr-prefix { display: inline-block; min-width: 20px; }
.plr-tabel tr.plr-tebal > td { font-weight: 700; }
.plr-tabel tr.plr-t1 > .plr-nama { padding-left: 4px; }
.plr-tabel tr.plr-t2 > .plr-nama { padding-left: 24px; }
.plr-tabel tr.plr-t3 > .plr-nama { padding-left: 44px; }
.plr-tabel tr.plr-t4 > .plr-nama { padding-left: 64px; }

/* ── Neraca Per Sandi — dua tabel terpisah (AKTIVA & PASSIVA) ──
   LAYAR memakai TEMA APLIKASI (catatan user 2026-09-17: "tampilan laporan di aplikasi tidak
   perlu persis seperti cetakan") — warna dari token, jadi tetap benar di mode gelap.
   Gaya kertas format Dinas (Times New Roman, garis hitam, tanpa garis vertikal) ada di
   `cetak.css`. Contoh bentuk: `Contoh Laporan Keuangan/Sandi/Neraca.pdf`. */
/* Kepala laporan: judul TENGAH; identitas KIRI; kotak `SANDI` (nomor kantor pelapor) KANAN —
   sama bentuknya dengan lembar cetak (contoh Dinas `Contoh Laporan Keuangan/Sandi/Neraca.pdf`). */
.neraca-sandi .ns-kepala { text-align: center; margin: 0 0 12px; }
.neraca-sandi .ns-judul { font-size: 15px; font-weight: 700; text-transform: uppercase; margin-bottom: 6px; }
.neraca-sandi .ns-kepala-baris { display: flex; gap: 20px; align-items: flex-start; text-align: left; margin-top: 6px; }
.neraca-sandi .ns-kepala-teks { flex: 1 1 auto; }
.neraca-sandi .ns-baris { font-size: 12.5px; line-height: 1.5; }
.neraca-sandi .ns-sandi { width: 130px; flex: 0 0 130px; }
.neraca-sandi .ns-sandi-judul { text-align: center; font-size: 12px; margin-bottom: 4px; }
.neraca-sandi .ns-sandi-sel { display: flex; border: 1px solid var(--border-color); height: 30px; }
.neraca-sandi .ns-sandi-sel > span { flex: 1; display: flex; align-items: center; justify-content: center;
    border-right: 1px solid var(--border-color); }
.neraca-sandi .ns-sandi-sel > span:last-child { border-right: 0; }
/* Label sisi (`AKTIVA` / `PASSIVA`) KIRI, `(Nilai Dalam Rupiah)` KANAN di atas tabelnya. */
.neraca-sandi .ns-sisi { display: flex; justify-content: space-between; align-items: baseline; margin: 14px 0 4px; }
.neraca-sandi .ns-sisi > span:first-child { font-weight: 700; font-size: 12.5px; }
.neraca-sandi .ns-satuan { font-size: 11px; color: var(--text-secondary); }
.tbl-sandi { width: 100%; border-collapse: collapse; font-size: 12px; margin-bottom: 4px; }
.tbl-sandi th, .tbl-sandi td { padding: 3px 6px; vertical-align: top; }
/* Header kolom: border penuh, tanpa latar kelabu (kertas formulir polos) */
.tbl-sandi th { border: 1px solid var(--border-color); font-weight: 700; text-align: center; }
/* Baris data: hanya garis kolom (vertikal), tanpa garis horizontal */
.tbl-sandi td { border-left: 1px solid var(--border-color); border-right: 1px solid var(--border-color); }
/* Baris total: garis atas + bawah + garis kolom */
.tbl-sandi tfoot td { font-weight: 700; border-top: 2px solid var(--text-primary); border-bottom: 2px solid var(--text-primary); border-left: 1px solid var(--border-color); border-right: 1px solid var(--border-color); }
.tbl-sandi tfoot td:first-child { border-left: 0; }
/* Alignment */
.tbl-sandi td.r, .tbl-sandi th.r { text-align: right; white-space: nowrap; }
.tbl-sandi td.c, .tbl-sandi th.c { text-align: center; }
.tbl-sandi td.b { font-weight: 700; }
/* Judul kelompok pada Neraca Per Sandi/RL Per Sandi: garis mendatar di BAWAHNYA (permintaan user
   2026-09-24). Batang tabel ini hanya punya garis kolom (lihat catatan di atas), jadi tanpa garis
   ini kepala kelompok tampak menyatu dengan baris anaknya. */
.tbl-sandi tr.ns-grup > td { border-bottom: 1px solid var(--border-color); }
/* Anak kelompok (a., b., c. …) menjorok seperti contoh user — judulnya sendiri rata kiri.
   Hurufnya ditulis di kolom Pos-Pos dengan lebar tetap supaya nama barisnya rata. */
.tbl-sandi td.ns-anak { padding-left: 22px; }
.tbl-sandi .ns-prefix { display: inline-block; min-width: 20px; }

/* ── CALK (Catatan Atas Laporan Keuangan, Permenkop 2/2024) ───────────────────────────
   Satu komponen (CalkTampilan) dipakai layar & kertas; gaya layar memakai tema aplikasi,
   gaya kertas HANYA di cetak.css (aturan user 2026-09-17). */
.calk-seksi { margin-top: 10px; }
.calk-judul { font-size: .95rem; font-weight: 600; margin: 14px 0 6px; }
.calk-judul .calk-tag { font-size: .72rem; font-weight: 400; opacity: .7; margin-left: 6px; }
.calk-teks { white-space: pre-line; text-align: justify; line-height: 1.55; margin: 0 0 6px; }
.calk-halus { font-size: .78rem; opacity: .7; font-style: italic; margin-top: 4px; }
.calk-tag { font-size: .75rem; font-style: italic; }
.calk-aksi { margin: -2px 0 10px; }
.calk-aksi .sp-btn { font-size: .78rem; }
