/* ===================================================
   SINARKEU — Emerald Trust Redesign
   Palette: Emerald Deep #0F5C4E, Abu Netral #F6F7F6/#E5E8E5,
            Ink #1C2620, Aksen Emas tipis #B8912E (highlight only),
            Success Green #2E7D5B, Brick #A83E3E
   Signature: an emerald sidebar that stays constant across
   light & dark mode, an emerald balance hero, tight warm-toned
   shadows, tighter corner radius, and a single thin gold
   accent reserved for active nav state and key highlights —
   the rest of the interface stays quiet, trustworthy, functional.
   Font: IBM Plex Sans (display/headings), Inter (body/UI),
   JetBrains Mono (angka)
=================================================== */

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  /* Emerald Trust palette: Emerald Deep #0F5C4E, Abu Netral #F6F7F6,
     Aksen Emas tipis #B8912E — dipakai sangat terbatas untuk highlight. */
  --ink:        #26231F;
  --ink-muted:  #6B655E;
  --ink-faint:  #A39D95;
  --paper:      #FFFFFF;
  --paper-warm: #F7F5F2;
  --rule:       #E8E4DE;
  --accent:     #2E6F5E;
  --accent-lt:  #E7EFEA;
  --success:    #3A7F62;
  --success-lt: #E7F0E9;
  --danger:     #A9524E;
  --danger-lt:  #F6EAE7;
  --warning:    #B39346;
  --warning-lt: #F3EEDF;
  --purple:     #55796F;
  --purple-lt:  #E8EEEB;
  --brand:      #2E6F5E; /* dipakai tombol utama & badge peran */
  --brand-dark: #245748;
  /* Sidebar & title bar — [NO-SURFACE] menyatu dengan warna background
     halaman (var(--paper-warm)), bukan lagi permukaan emerald terpisah.
     Teks/border jadi turunan var(--ink) supaya tetap kontras di atas
     background terang; state aktif pakai var(--accent) solid + teks putih
     supaya tetap kelihatan sebagai nav yang aktif. */
  --topbar-bg:          var(--paper-warm);
  --topbar-text:        var(--ink);
  --topbar-text-muted:  var(--ink-muted);
  --topbar-border:      var(--rule);
  --topbar-btn-bg:      rgba(38,35,31,0.05);
  --topbar-btn-hover-bg: rgba(38,35,31,0.1);
  --topbar-item-color:  var(--ink-muted);
  --topbar-item-hover-bg: rgba(38,35,31,0.05);
  /* [GAYA COPILOT] Menu aktif = sorotan abu hangat + teks ink (bukan blok
     emerald solid). Emerald tetap dipakai untuk tombol utama & aksen data. */
  --topbar-item-active-bg: rgba(38,35,31,0.08);
  --topbar-item-active-color: var(--ink);
  --topbar-footer-border: var(--rule);
  /* [FLAT] Semua efek shadow dimatikan (diset none) supaya tampilan flat
     total -- variabel ini masih dipertahankan (bukan dihapus) supaya
     semua selector yang mereferensikannya (.header, .modal-content,
     #appSidebar, .toast-message, .cs-dropdown, .app-nav-item.active)
     tidak perlu diedit satu-satu & gampang dikembalikan kalau suatu saat
     mau dipakai lagi. */
  --topbar-active-shadow: none;
  /* Balance Hero (kartu "Saldo Akhir") — [DIRATAKAN] sebelumnya gradasi
     navy formal senada sidebar dengan teks putih di atasnya; sekarang flat
     seperti kartu lain (var(--paper) + border), jadi teksnya dipetakan ke
     var(--ink)/var(--ink-muted) biasa (lihat .balance-hero di bawah).
     Variabel --hero-text* dipertahankan (bukan dihapus) supaya selector
     yang masih mereferensikannya (.balance-hero-label, -eye, -value) tidak
     perlu diubah satu-satu -- cukup ganti definisi variabelnya di sini &
     di override [data-theme="dark"]. */
  --hero-text:       var(--ink);
  --hero-text-muted: var(--ink-muted);
  /* Extended palette */
  --fase:       #55796F;
  --fase-lt:    #E8EEEB;
  --info:       #3F7A8F;
  --info-lt:    #E7EEF1;
  --chat-user:  #2E6B67;
  --ink-inv:    #EAF3EF;   /* teks di atas background gelap (btn-primary dark) */
  --paper-inv:  #26231F;  /* bg di atas ink terang */
  --row-alt:    #FBF9F6;
  /* Shape & elevation — radius diperkecil, shadow lebih tipis untuk kesan formal */
  --radius-xs:  1px;
  --radius-sm:  4px;
  --radius:     6px;
  --radius-lg:  10px;
  --radius-pill: 999px;
  /* [FLAT] Lihat catatan --topbar-active-shadow di atas -- sama, diset
     none supaya seluruh app (mode terang) flat total tanpa shadow. */
  --shadow-sm:  none;
  --shadow-md:  none;
  --shadow-lg:  none;
  --font-display: 'IBM Plex Sans', 'Inter', sans-serif;
  --font-body:    'Inter', sans-serif;
  --font-mono:    'JetBrains Mono', ui-monospace, monospace;

  /* Skala tipografi resmi — sebelumnya ada 32 nilai font-size berbeda
     (mis. .68rem/.7rem/.72rem/.74rem dipakai bergantian tanpa pola) yang
     bikin UI kelihatan tidak konsisten antar fitur. Sekarang disatukan ke
     12 langkah baku; setiap nilai lama "digeser" ke titik terdekat di
     skala ini (selisih maksimal ~0.05rem / <1px, tidak kasat mata). */
  --text-2xs:  0.62rem;  /* label kecil, badge, meta info */
  --text-xs:   0.70rem;  /* teks sekunder, caption */
  --text-sm:   0.76rem;  /* body kecil, input, tombol kecil */
  --text-base: 0.82rem;  /* body/teks utama komponen */
  --text-md:   0.92rem;  /* sub-heading kecil, label form */
  --text-lg:   1.00rem;  /* body besar / heading level 4 */
  --text-xl:   1.10rem;  /* heading level 3 */
  --text-2xl:  1.30rem;  /* heading level 2 */
  --text-3xl:  1.50rem;  /* heading level 1 / angka ringkasan */
  --text-4xl:  1.65rem;  /* angka besar sekunder */
  --text-5xl:  2.20rem;  /* angka hero (saldo dsb) */
  --text-6xl:  2.50rem;  /* display terbesar */

  /* Skala spacing resmi — grid 2px sudah dipakai secara konsisten,
     sekarang ditokenkan supaya jadi satu sumber kebenaran (nilai piksel
     TIDAK diubah, jadi tidak ada perubahan visual dari langkah ini). */
  --space-1: 1px;  --space-2: 2px;  --space-3: 3px;  --space-4: 4px;
  --space-5: 5px;  --space-6: 6px;  --space-7: 7px;  --space-8: 8px;
  --space-9: 9px;  --space-10: 10px; --space-11: 11px; --space-12: 12px;
  --space-13: 13px; --space-14: 14px; --space-15: 15px; --space-16: 16px;
  --space-18: 18px; --space-20: 20px; --space-22: 22px; --space-24: 24px;
  --space-26: 26px; --space-28: 28px; --space-30: 30px; --space-32: 32px;
  --space-36: 36px; --space-40: 40px; --space-50: 50px; --space-56: 56px;
}

/* ======================================================
   [GAYA COPILOT] Bentuk untuk KEDUA tema -- flat, outline tipis, sudut
   membulat, input & chip berbentuk kapsul. Warna ada di token :root /
   [data-theme="dark"]; blok ini hanya bentuk/ketebalan. Pengecualian:
   chip filter aktif (warna beda per tema, lihat paling bawah blok).
====================================================== */
:root {
  --radius-sm: 10px;
  --radius:    14px;
  --radius-lg: 20px;
}
/* Outline tipis 1px (sebelumnya 1.5px) */
:root .search-input,
:root .filter-btn,
:root .date-quick-preset,
:root button,
:root .btn,
:root .btn-secondary,
:root .form-control,
:root .stat-card,
:root .balance-hero,
:root .modal-content,
:root .table-container {
  border-width: 1px;
}
/* Kapsul: kolom cari & chip filter */
:root .search-input,
:root .filter-btn,
:root .date-quick-preset {
  border-radius: var(--radius-pill);
}
:root .search-input { padding-left: var(--space-16); padding-right: var(--space-16); }
:root:not([data-theme="dark"]) .filter-btn.active {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
/* Flat: kartu tidak "melompat" saat di-hover */
:root .stat-card:hover { transform: none; border-color: var(--ink-faint); }

/* ── Base ── */
body {
  font-family: var(--font-body);
  background: var(--paper-warm);
  color: var(--ink);
  padding: 0;
  font-size: var(--text-md);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* Judul fungsional (modal, section, dsb) tetap sans — formal & calm,
   supaya serif tidak dipakai berlebihan di seluruh UI. */
h1, h2, h3, h4,
.modal-header h3 {
  font-family: var(--font-body);
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* Momen signature — wordmark brand, angka saldo besar, layar kunci —
   memakai serif hangat Fraunces, dipakai secukupnya. */
.app-sidebar-brand,
.stat-value,
.lock-title {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.fc-metric-value,
.report-stat-value {
  font-family: var(--font-mono);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.container { max-width: 1440px; margin: 0 auto; padding: 0 var(--space-32) var(--space-40); }

/* ── Account Bar ── */
.account-bar {
  background: var(--ink);
  color: var(--paper);
  display: flex;
  align-items: center;
  gap: 0;
  padding: 0 var(--space-32);
  font-size: var(--text-xs);
  min-height: 38px;
  overflow-x: auto;
  flex-wrap: nowrap;
  border-bottom: 2px solid var(--accent);
}

.account-bar-label {
  font-size: var(--text-2xs);
  font-weight: 500;
  color: rgba(255,255,255,0.45);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-right: var(--space-12);
  white-space: nowrap;
}

.account-tabs {
  display: flex;
  align-items: stretch;
  gap: 0;
  flex: 1;
  overflow-x: auto;
}

.account-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-7);
  padding: 0 var(--space-16);
  height: 36px;
  font-size: var(--text-xs);
  font-weight: 400;
  color: rgba(255,255,255,0.5);
  background: transparent;
  border: none;
  cursor: pointer;
  border-right: 1px solid rgba(255,255,255,0.08);
  white-space: nowrap;
  transition: color 0.15s, background 0.15s;
  font-family: inherit;
  position: relative;
}

.account-tab:hover { color: #fff; background: rgba(255,255,255,0.06); }
.account-tab.active { color: #fff; background: rgba(255,255,255,0.08); }
.account-tab.active::after {
  content: '';
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: 1.5px;
  background: var(--accent);
  opacity: 0.7;
}

.account-tab .acc-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgba(255,255,255,0.3);
  flex-shrink: 0;
}
.account-tab.active .acc-dot { background: var(--accent); opacity: 0.8; }
.account-tab.offline-acc .acc-dot { background: var(--warning); }

.account-tab .acc-close {
  opacity: 0;
  font-size: var(--text-2xs);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-xs); /* [CONSISTENT-UI] dulu 2px hardcode, digeser ke token terdekat di skala radius */
  transition: opacity 0.15s, background 0.15s;
  line-height: 1;
}
.account-tab:hover .acc-close { opacity: 1; }
.account-tab .acc-close:hover { background: var(--danger); color: #fff; }

.account-bar-add {
  display: inline-flex;
  align-items: center;
  gap: var(--space-5);
  padding: 0 var(--space-16);
  height: 36px;
  font-size: var(--text-xs);
  font-weight: 400;
  color: rgba(255,255,255,0.45);
  background: transparent;
  border: none;
  border-left: 1px solid rgba(255,255,255,0.08);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.15s;
  font-family: inherit;
  margin-left: auto;
}
.account-bar-add:hover { color: #fff; }

/* ── Header (title bar) — warna disamakan dengan sidebar (var(--topbar-bg)) ── */
.header {
  margin: var(--space-28) 0 var(--space-24);
  padding: var(--space-14) var(--space-20);
  background: var(--topbar-bg);
  border: 1px solid var(--topbar-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: var(--space-16);
}

/* Kontras teks/ikon di atas title bar (mengikuti tema terang/gelap) */
.header .sync-time-badge { color: var(--topbar-text-muted); border-left-color: var(--topbar-border); }
.header .sync-status-container { border-color: var(--topbar-border); }
.header .hamburger-btn { background: none; color: var(--topbar-text); border: none; }
.header .hamburger-btn:hover { background: none; opacity: 0.7; }

.header p {
  font-size: var(--text-xs);
  color: var(--topbar-text-muted);
  margin-top: var(--space-3);
  font-weight: 400;
}

/* ── Book Selector ── */
.book-selector {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  flex-wrap: wrap;
}

.book-selector label {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--ink-muted);
  letter-spacing: 0.02em;
}

/* ── Tanya Sinarkeu: Floating Action Button ──
   Satu-satunya akses ke aiChatModal (dulu ada 2: header-ai-bar desktop +
   tombol toolbar). position:fixed relatif viewport, z-index tinggi supaya
   di atas UI app lain tapi tetap di bawah lockscreen (9999) -- lihat aturan
   body.lockscreen-restricted di bawah. */
.ai-chat-fab {
  display: flex;
  align-items: center;
  justify-content: center;
  position: fixed;
  right: 20px;
  bottom: 20px;
  width: 52px;
  height: 52px;
  padding: 0;
  border-radius: 50%;
  background: var(--chat-user);
  border: none;
  color: #fff;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0,0,0,.22);
  z-index: 9000;
  transition: transform .15s ease, box-shadow .15s ease;
}
.ai-chat-fab:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(0,0,0,.28);
}
.ai-chat-fab-icon {
  font-size: 22px;
  line-height: 1;
}
@media (min-width: 1024px) {
  /* Di layar lebar, geser sedikit dari tepi supaya tidak menempel scrollbar */
  .ai-chat-fab { right: 28px; bottom: 28px; }
}

.book-select {
  min-width: 160px;
  padding: var(--space-6) var(--space-10);
  font-size: var(--text-sm);
  font-weight: 400;
  border: 1.5px solid var(--rule);
  background: var(--paper);
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--ink);
  transition: border-color 0.15s, opacity .15s ease;
  font-family: inherit;
}
.book-select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-lt); }
/* [SMOOTH BOOK SWITCH] Dropdown dikunci sesaat selagi window.switchBook()
   memuat data buku baru (lihat js/book.js) -- opacity turun & kursor
   berubah supaya user tahu prosesnya sedang berjalan, bukan macet. */
.book-select:disabled { opacity: .6; cursor: wait; }

.manage-books-btn {
  padding: var(--space-6) var(--space-14);
  font-size: var(--text-xs);
  font-weight: 500;
  background: var(--ink);
  color: var(--paper);
  border: 1px solid var(--ink);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.15s;
  font-family: inherit;
}
.manage-books-btn:hover:not(:disabled) { background: var(--ink-muted); border-color: var(--ink-muted); }
.manage-books-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.manage-books-btn.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  width: 30px;
  height: 30px;
}
.manage-books-btn.icon-btn svg { display: block; }

/* ── Sync Status ── */
.sync-status-container {
  display: inline-flex;
  align-items: center;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  overflow: hidden;
  font-size: var(--text-2xs);
  font-weight: 500;
}
.sync-status-badge { padding: var(--space-4) var(--space-10); }
.sync-status-container.online .sync-status-badge { background: var(--success-lt); color: var(--success); }
.sync-status-container.offline .sync-status-badge { background: var(--danger-lt); color: var(--danger); }
.device-id-badge {
  background: var(--ink);
  color: var(--paper);
  padding: var(--space-4) var(--space-10);
  font-family: monospace;
  font-size: var(--text-2xs);
}
.sync-time-badge {
  padding: var(--space-4) var(--space-10);
  font-family: monospace;
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--ink-faint, #666);
  border-left: 1px solid var(--rule);
}
/* ── Offline Warning ── */
.offline-warning-bar {
  background: var(--warning-lt);
  border: 1px solid var(--warning);
  border-radius: var(--radius-sm);
  padding: var(--space-8) var(--space-16);
  margin-bottom: var(--space-16);
  display: none;
  align-items: center;
  gap: var(--space-10);
  font-size: var(--text-xs);
  color: var(--warning);
}
.offline-warning-bar.show { display: flex; }

/* ── Budget Mini ── */
.budget-mini {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-14) var(--space-20);
  margin-bottom: var(--space-20);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-12);
}

.budget-mini-info {
  display: flex;
  align-items: center;
  gap: var(--space-20);
  flex-wrap: wrap;
}

.budget-mini-item {
  display: flex;
  align-items: baseline;
  gap: var(--space-6);
  font-size: var(--text-sm);
}

.budget-mini-label { color: var(--ink-muted); font-weight: 400; }
.budget-mini-value { font-family: var(--font-mono); font-weight: 600; color: var(--ink); font-size: var(--text-base); }
.budget-mini-value.positive { color: var(--success); }
.budget-mini-value.negative { color: var(--danger); }

.budget-mini-progress {
  width: 180px;
  min-width: 80px;
  height: 7px;
  background: var(--rule);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.budget-mini-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--success);
  border-radius: var(--radius-pill);
  transition: width 0.3s;
}
.budget-mini-progress-fill.warning { background: var(--warning); }
.budget-mini-progress-fill.danger  { background: var(--danger); }

.budget-mini-actions { display: flex; gap: var(--space-8); }

.budget-select {
  padding: var(--space-5) var(--space-10);
  font-size: var(--text-xs);
  font-weight: 400;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  cursor: pointer;
  font-family: inherit;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 24 24' fill='none' stroke='%236B6B6B' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 30px;
}
.budget-select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-lt); }

/* ── Balance Hero Card (signature element) ── */
/* [DIRATAKAN] Sebelumnya kartu ini gradasi navy (var(--hero-bg-from/-to))
   + box-shadow besar + blob dekoratif putih transparan di pojok -- efek
   "glossy" itu cuma masuk akal di atas warna gelap. Sekarang flat sama
   seperti kartu lain di app (var(--paper) + border tipis, tanpa shadow),
   jadi blob dekoratifnya juga dilepas (disembunyikan lewat display:none
   di bawah, bukan dihapus elemennya dari index.html/app.js supaya tidak
   perlu sentuh JS) karena blob putih transparan itu nyaris tidak
   kelihatan/tidak masuk akal di atas latar terang. */
.balance-hero {
  position: relative;
  overflow: hidden;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: var(--space-26) var(--space-28);
  margin-bottom: var(--space-18);
}
.balance-hero-blob { display: none; }
.balance-hero-label {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-8);
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--hero-text-muted);
}
.balance-hero-eye {
  background: none; border: none; padding: 0; cursor: pointer;
  line-height: 1; color: var(--hero-text-muted);
}
.balance-hero-value {
  position: relative;
  font-family: var(--font-mono);
  /* [FONT DINAMIS] Sebelumnya font-size tetap (--text-5xl) dengan SATU
     lompatan statis ke --text-4xl di ≤480px -- saldo besar (mis. "Rp
     -999.999.999.999" gabungan Buku Induk beberapa Buku Anak) bisa lebih
     lebar dari kartu di layar sempit (320-390px) dan, karena
     .balance-hero pakai overflow:hidden, bagian digitnya bisa TERPOTONG
     tanpa indikasi apa pun ke user -- fatal untuk angka uang. Diganti
     clamp() supaya menyusut/mekar HALUS mengikuti lebar viewport (bukan
     lompatan satu titik), dengan batas bawah/atas tetap di skala token
     yang sama (--text-3xl..--text-5xl) supaya tidak ada nilai px lepas
     dari sistem desain. overflow-wrap ditambah sebagai jaring pengaman
     terakhir: kalau tetap lebih lebar dari kartu (angka ekstrem), teks
     pindah baris/pecah karakter alih-alih kepotong senyap. */
  font-size: clamp(var(--text-3xl), 8vw, var(--text-5xl));
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--hero-text);
  margin-top: var(--space-6);
  overflow-wrap: anywhere;
}
@media (max-width: 480px) {
  .balance-hero { padding: var(--space-20) var(--space-20); }
}

/* ── Balance Hero: panel kanan (tren + sparkline), khusus desktop ── */
/* [UI] Diisi lewat js/balance-trend.js. Disembunyikan default (mobile/
   tablet) -- di layar sempit .balance-hero sudah pas isinya cuma
   label+angka, nggak ada ruang sisa buat panel tambahan ini. */
.balance-hero-side { display: none; }
@media (min-width: 1024px) {
  .balance-hero {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-24);
  }
  .balance-hero-main { flex: 0 0 auto; }
  .balance-hero-side {
    display: flex;
    align-items: center;
    gap: var(--space-20);
    flex: 1 1 auto;
    justify-content: flex-end;
    min-width: 0;
  }
}

.balance-hero-trend {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-2);
  white-space: nowrap;
}
.balance-hero-trend-pct {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  font-size: var(--text-sm);
  font-weight: 700;
}
.balance-hero-trend-sub {
  font-size: var(--text-2xs);
  color: var(--hero-text-muted);
}
.balance-hero-spark {
  flex: 0 1 220px;
  min-width: 120px;
  height: 56px;
}
.balance-hero-spark svg { display: block; width: 100%; height: 100%; }
.balance-hero-empty-side {
  font-size: var(--text-2xs);
  color: var(--hero-text-muted);
}

/* ── Stats Grid ── */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--space-12);
  margin-bottom: var(--space-20);
}

.stat-card {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-16) var(--space-18);
  transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
}
.stat-card:hover { transform: translateY(-3px); border-color: var(--accent); }

.stat-label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--ink-muted);
  letter-spacing: 0.01em;
}

.stat-value {
  font-family: var(--font-mono);
  /* [UI OPTIMASI DASHBOARD] Sebelumnya calc(var(--text-lg) * 2) = 2.00rem --
     angka ad-hoc di luar skala --text-* yang sudah didefinisikan, dan
     ukurannya nyaris menyamai --text-5xl (2.20rem, dipakai balance-hero-value)
     padahal card ini bukan angka hero. Diselaraskan ke --text-3xl (1.50rem),
     token yang memang diberi keterangan "angka ringkasan" di :root -- cocok
     untuk stat-card (berlaku juga ke finCardsGrid lewat class yang sama),
     dan memberi jarak yang lebih jelas ke hero di atasnya maupun ke angka
     sekunder (stat-card-compact, fc-metric-value) yang sudah pakai --text-lg. */
  /* [FONT DINAMIS] Sama seperti .balance-hero-value di atas -- clamp()
     bukan nilai tetap, plus overflow-wrap jaring pengaman untuk angka
     ekstrem di kartu sempit (grid stat-card bisa turun ke ~190px per
     kartu di layar kecil, lihat .stats-grid minmax(190px,1fr)). */
  font-size: clamp(var(--text-lg), 5vw, var(--text-3xl));
  font-weight: 700;
  margin-top: var(--space-6);
  letter-spacing: -0.01em;
  color: var(--ink);
  overflow-wrap: anywhere;
}

.stat-card.income .stat-value,
.stat-card.expense .stat-value { color: var(--ink); }

/* [UI OPTIMASI DASHBOARD] Label kecil di atas grid "Info Pasar" (kurs/emas)
   -- menandai baris ini sebagai kelompok terpisah dari data pribadi
   (pemasukan/pengeluaran) di atasnya, mengikuti gaya label section lain
   (mis. expense-chart-title) tapi lebih senyap karena bukan section utama. */
.stats-submeta-label {
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: var(--space-4) 0 var(--space-6) var(--space-2);
}
.stats-grid-market { margin-bottom: 0; } /* jarak ke judul section diatur .fin-cards-header */
/* Card versi ringkas untuk info pasar -- padding & ukuran angka lebih kecil
   dari .stat-card biasa supaya bobot visualnya jelas lebih rendah dibanding
   card Pemasukan/Pengeluaran di baris pertama. */
.stat-card-compact { padding: var(--space-12) var(--space-14); }
/* [UI] Ukuran angka disamakan dengan .stat-value biasa (card Pemasukan/
   Pengeluaran) -- sebelumnya diskalakan turun satu tingkat (clamp(--text-md,
   4vw, --text-lg)) supaya terasa sebagai angka sekunder, tapi itu bikin
   kurs USD & harga emas terlihat kurang menonjol dibanding card lain.
   Sekarang pakai clamp() yang sama persis dengan base .stat-value; hanya
   margin-top yang tetap lebih kecil (space-4, bukan space-6) karena
   padding card compact ini juga lebih kecil. */
.stat-card-compact .stat-value { margin-top: var(--space-4); }

/* ── Dashboard utama: rapat & rapi ──
   [RAPIKAN & EFISIENKAN] Di layar lebar (1920x1080) bagian atas dashboard
   memakan >600px sebelum tabel/anggaran terlihat: banner pengingat 3 baris
   (~112px), kartu saldo ~150px, Pemasukan/Pengeluaran + label + Kurs/Emas
   ~330px dalam 2 baris. Sekarang: pengingat sejajar 1 baris, kartu saldo
   dipadatkan, dan keempat kartu angka sejajar dalam 1 baris. Semua aturan
   hanya aktif di layar/area lebar -- hape & tablet tidak berubah. */
.pr-banner-item { display: block; }
.stats-merged { container-type: inline-size; }

@media (min-width: 769px) {
  .pr-banner-body { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--space-2) var(--space-20); }
  .pr-banner-body .pr-banner-title { white-space: nowrap; }
  .pr-banner-body .pr-banner-text { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-20); line-height: 1.5; }
  .pr-banner-item { white-space: nowrap; }
}

@media (min-width: 1024px) {
  .balance-hero { padding: var(--space-14) var(--space-24); margin-bottom: var(--space-14); }
  .balance-hero-value { font-size: var(--text-4xl); margin-top: var(--space-2); }
  .balance-hero-spark { height: 44px; }
  /* Kartu Perencanaan Keuangan: padding & angka ikut dipadatkan. */
  #finCardsGrid { margin-bottom: var(--space-14); }
  #finCardsGrid .stat-card { padding: var(--space-12) var(--space-16); }
  #finCardsGrid .stat-value { font-size: var(--text-2xl); margin-top: var(--space-4); }
}

/* Container query (bukan media query) supaya keputusan "4 kartu sejajar"
   mengikuti lebar AREA KONTEN yang sebenarnya -- sidebar terbuka/ciut
   mengubah lebar ini tanpa mengubah lebar viewport. display:contents pada
   kedua .stats-grid membuat kartu-kartu di dalamnya ikut grid 4 kolom milik
   .stats-merged-inner; label "Info Pasar" disembunyikan (tiap kartu sudah
   berlabel sendiri). Browser tanpa container query: tampilan lama dipakai. */
@container (min-width: 880px) {
  .stats-merged-inner {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-12);
    margin-bottom: 0; /* jarak ke judul section diatur .fin-cards-header */
  }
  .stats-merged-inner > .stats-grid { display: contents; }
  .stats-merged-inner > .stats-submeta-label { display: none; }
  .stats-merged-inner .stat-card,
  .stats-merged-inner .stat-card-compact { padding: var(--space-12) var(--space-16); }
  .stats-merged-inner .stat-value { font-size: var(--text-2xl); margin-top: var(--space-4); }
}

/* ── Expense Chart Section ── */
/* ── Forecast Card ── */
.forecast-card {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: 0;
  margin-bottom: var(--space-16);
  overflow: hidden;
}
.fc-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-13) var(--space-18);
  border-bottom: 1px solid var(--rule);
  background: var(--paper-warm);
  font-size: var(--text-xs);
  font-weight: 600;
  font-family: var(--font-display);
  color: var(--ink-muted);
  letter-spacing: .2px;
}
.fc-status-badge {
  font-size: var(--text-2xs);
  font-weight: 700;
  padding: var(--space-2) var(--space-9);
  border-radius: var(--radius-pill);
  letter-spacing: .3px;
}
.fc-body {
  padding: var(--space-14) var(--space-16);
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
}
.fc-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-12);
}
.fc-metric {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.fc-metric-label {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  text-transform: none;
  letter-spacing: .4px;
  font-weight: 600;
}
.fc-metric-value {
  font-size: var(--text-lg);
  font-weight: 700;
  color: var(--ink);
  line-height: 1.3;
  display: flex;
  align-items: center;
  gap: var(--space-6);
  flex-wrap: wrap;
}
.fc-metric-sub {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
}
.fc-cats {
  padding-top: 10px;
  border-top: 1px solid var(--rule);
}
.fc-tag {
  font-size: var(--text-2xs);
  background: var(--paper-warm);
  border: 1.5px solid var(--rule);
  padding: var(--space-3) var(--space-9);
  color: var(--ink-muted);
}
.fc-tag b {
  color: var(--ink);
  font-weight: 600;
}
@media (max-width: 480px) {
  .fc-row { grid-template-columns: 1fr; gap: var(--space-10); }
  .fc-metric-value { font-size: var(--text-md); }
}
@media (min-width: 1024px) {
  /* [UI] Di desktop, ruang horizontal cukup untuk menampilkan ke-4 metrik
     (Pemasukan, Pengeluaran, Surplus/Defisit, Proyeksi Saldo) sejajar dalam
     satu baris, bukan 2 baris x 2 kolom seperti mobile -- lebih efisien
     ruang vertikal. .fc-body dijadikan grid 2 kolom; karena tiap .fc-row
     sudah berisi 2 metrik (grid 1fr 1fr), hasilnya 2x2=4 kolom total.
     .fc-cats (tag pengeluaran terbesar) tetap span penuh di bawahnya. */
  .fc-body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-14) var(--space-24);
  }
  .fc-cats { grid-column: 1 / -1; }
}

.expense-chart-section {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-16) var(--space-20);
  margin-bottom: var(--space-20);
}

.expense-chart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-14);
  gap: var(--space-10);
  flex-wrap: wrap;
}

/* [20 Okt 2026] Judul section "Perencanaan Keuangan": jarak ke kartu di atas
   dan ke kartu di bawah SAMA (14px, ritme yang sama dengan jarak antar-section
   dashboard di layar lebar). Sebelumnya margin-top 16 + margin-bottom kartu
   baris 1 (14/20) vs margin-bottom 8 => ~30px di atas tapi cuma ~10px di bawah.
   Ketika grid dilipat, jarak ke blok berikutnya tetap 14px. */
.expense-chart-header.fin-cards-header {
  margin-top: var(--space-14);
  margin-bottom: var(--space-14);
}

.expense-chart-title {
  font-size: var(--text-2xs);
  font-weight: 500;
  color: var(--ink-faint);
  text-transform: none;
  letter-spacing: 0.08em;
}

.expense-chart-toggle { display: flex; gap: var(--space-4); }
.expense-chart-toggle button {
  padding: var(--space-3) var(--space-10);
  font-size: var(--text-xs);
  font-weight: 500;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--ink-muted);
  cursor: pointer;
  transition: all 0.15s;
  font-family: inherit;
}
.expense-chart-toggle button.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

.expense-chart-body {
  display: flex;
  gap: var(--space-24);
  align-items: center;
  flex-wrap: wrap;
}

.expense-chart-canvas-wrap {
  flex: 0 0 200px;
  max-width: 200px;
  height: 200px;
  position: relative;
}
.expense-chart-canvas-wrap canvas { max-height: 200px !important; }

/* [HARGA KOMODITAS] Wrapper terpisah untuk grafik garis tren harga (js/harga-pangan.js)
   -- BEDA dari .expense-chart-canvas-wrap di atas yang sengaja di-fix 200x200px
   untuk grafik donut; line chart tren perlu lebar penuh kartu, bukan kotak kecil. */
.hk-trend-canvas-wrap {
  position: relative;
  width: 100%;
  height: 260px;
}

/* [20 Okt 2026] Modal Tren Harga diperkaya: harga terkini + perubahan, pilihan
   rentang 7/14/30 hari, grafik dgn garis rata-rata & titik min/maks, kartu
   statistik, bilah posisi harga, dan tabel riwayat harian. Hanya token var(--...). */
.hk-tr-hero { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-10) var(--space-16); margin-bottom: var(--space-14); }
.hk-tr-hero-label { font-size: var(--text-xs); font-weight: 600; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .03em; margin-bottom: var(--space-4); }
.hk-tr-price { font-family: var(--font-display); font-weight: 700; font-size: var(--text-3xl); line-height: 1.1; color: var(--ink); }
.hk-tr-unit { font-size: var(--text-sm); font-weight: 500; color: var(--ink-muted); }
.hk-tr-hero-delta { display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-4); }
.hk-tr-hero-sub { font-size: var(--text-2xs); color: var(--ink-faint); }
.hk-tr-delta { display: inline-flex; align-items: center; gap: var(--space-4); padding: var(--space-3) var(--space-8); border-radius: var(--radius-pill); font-size: var(--text-xs); font-weight: 600; white-space: nowrap; }
.hk-tr-delta.is-big { font-size: var(--text-sm); padding: var(--space-4) var(--space-10); }

.hk-tr-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-8) var(--space-12); margin-bottom: var(--space-8); }
.hk-tr-ranges { display: inline-flex; gap: var(--space-4); padding: var(--space-3); background: var(--paper-warm); border: 1px solid var(--rule); border-radius: var(--radius-pill); }
.hk-tr-range { font: inherit; font-size: var(--text-xs); font-weight: 600; padding: var(--space-4) var(--space-12); border: 0; border-radius: var(--radius-pill); background: transparent; color: var(--ink-muted); cursor: pointer; }
.hk-tr-range:hover { color: var(--ink); }
.hk-tr-range.is-active { background: var(--accent); color: var(--paper); }
.hk-tr-range:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.hk-tr-legend { display: flex; flex-wrap: wrap; gap: var(--space-4) var(--space-12); font-size: var(--text-2xs); color: var(--ink-muted); }
.hk-tr-legend span { display: inline-flex; align-items: center; gap: var(--space-4); }
.hk-tr-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.hk-tr-dash { width: 14px; height: 0; border-top: 2px dashed var(--ink-faint); display: inline-block; }

.hk-tr-pos { margin: var(--space-14) 0; padding: var(--space-12) var(--space-14); background: var(--paper-warm); border: 1px solid var(--rule); border-radius: var(--radius); }
.hk-tr-pos-head { display: flex; justify-content: space-between; gap: var(--space-8); font-size: var(--text-xs); color: var(--ink-muted); margin-bottom: var(--space-8); }
.hk-tr-pos-head strong { color: var(--ink); }
.hk-tr-pos-track { height: 8px; border-radius: var(--radius-pill); background: linear-gradient(90deg, var(--success-lt), var(--danger-lt)); border: 1px solid var(--rule); overflow: hidden; position: relative; }
.hk-tr-pos-fill { height: 100%; background: var(--accent); border-radius: var(--radius-pill); opacity: .85; }
.hk-tr-pos-scale { display: flex; justify-content: space-between; gap: var(--space-8); margin-top: var(--space-6); font-size: var(--text-2xs); color: var(--ink-faint); }
.hk-tr-pos-note { text-align: center; color: var(--ink-muted); }

.hk-tr-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--space-8); margin-bottom: var(--space-14); }
.hk-tr-stat { padding: var(--space-10) var(--space-12); background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius); min-width: 0; }
.hk-tr-stat-label { font-size: var(--text-2xs); font-weight: 600; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .03em; margin-bottom: var(--space-4); }
.hk-tr-stat-value { font-family: var(--font-display); font-weight: 700; font-size: var(--text-base); color: var(--ink); }
.hk-tr-stat-sub { font-size: var(--text-2xs); color: var(--ink-muted); margin-top: var(--space-2); }

/* [30 Okt 2026] Riwayat harian: kartu tanpa toggle (selalu terbuka), baris grid
   3 kolom -- tanggal (+penanda), harga + bilah posisi, pil perubahan. */
.hk-tr-history { border: 1px solid var(--rule); border-radius: var(--radius); overflow: hidden; background: var(--paper); display: flex; flex-direction: column; min-height: 0; }
.hk-tr-hist-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8); padding: var(--space-12) var(--space-14); background: var(--paper-warm); border-bottom: 1px solid var(--rule); }
.hk-tr-hist-title { font-size: var(--text-sm); font-weight: 700; color: var(--ink); }
.hk-tr-hist-count { font-size: var(--text-2xs); font-weight: 600; color: var(--ink-muted); padding: var(--space-2) var(--space-8); border: 1px solid var(--rule); border-radius: var(--radius-pill); background: var(--paper); }
.hk-tr-hist-cols, .hk-tr-row { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr) minmax(86px, .75fr); align-items: center; gap: var(--space-10); padding: var(--space-8) var(--space-14); }
.hk-tr-hist-cols { font-size: var(--text-2xs); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-faint); border-bottom: 1px solid var(--rule); background: var(--paper); }
.hk-tr-hist-cols span:nth-child(2) { text-align: right; }
.hk-tr-hist-cols span:nth-child(3) { text-align: right; }
.hk-tr-hist-list { list-style: none; margin: 0; padding: 0; max-height: 360px; overflow-y: auto; }
.hk-tr-row { border-top: 1px solid var(--rule); font-size: var(--text-xs); transition: background .12s; }
.hk-tr-row:first-child { border-top: 0; }
.hk-tr-row:hover { background: var(--paper-warm); }
.hk-tr-row.is-last { background: var(--paper-warm); box-shadow: inset 3px 0 0 var(--accent); }
.hk-tr-cell-date { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-4) var(--space-8); min-width: 0; }
.hk-tr-dayname { flex: 0 0 auto; min-width: 34px; text-align: center; padding: var(--space-2) var(--space-6); border-radius: var(--radius-sm); background: var(--paper-warm); border: 1px solid var(--rule); font-size: var(--text-2xs); font-weight: 700; color: var(--ink-muted); }
.hk-tr-datetxt { color: var(--ink-muted); white-space: nowrap; }
.hk-tr-datetxt b { color: var(--ink); font-weight: 600; }
.hk-tr-tag { font-size: 10px; font-weight: 700; line-height: 1; padding: var(--space-3) var(--space-6); border-radius: var(--radius-pill); white-space: nowrap; }
.hk-tr-tag.is-last { background: var(--accent); color: var(--paper); }
.hk-tr-tag.is-min { background: var(--success-lt); color: var(--success); }
.hk-tr-tag.is-max { background: var(--danger-lt); color: var(--danger); }
.hk-tr-cell-price { display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-4); min-width: 0; }
.hk-tr-cell-price strong { font-family: var(--font-display); font-size: var(--text-sm); font-weight: 700; color: var(--ink); white-space: nowrap; }
.hk-tr-bar { display: block; width: 100%; max-width: 110px; height: 4px; border-radius: var(--radius-pill); background: var(--rule); overflow: hidden; }
.hk-tr-bar-fill { display: block; height: 100%; border-radius: inherit; background: var(--accent); opacity: .75; }
.hk-tr-bar-fill.is-min { background: var(--success); opacity: 1; }
.hk-tr-bar-fill.is-max { background: var(--danger); opacity: 1; }
.hk-tr-cell-chg { display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-2); }
.hk-tr-chg { display: inline-flex; align-items: center; gap: var(--space-4); padding: var(--space-2) var(--space-8); border-radius: var(--radius-pill); font-size: var(--text-2xs); font-weight: 700; white-space: nowrap; }
.hk-tr-chg.is-up { color: var(--danger); background: var(--danger-lt); }
.hk-tr-chg.is-down { color: var(--success); background: var(--success-lt); }
.hk-tr-chg.is-flat { color: var(--ink-faint); background: var(--paper-warm); border: 1px solid var(--rule); }
.hk-tr-chg.is-start { color: var(--ink-faint); background: transparent; font-weight: 500; padding-right: 0; }
.hk-tr-chg-sub { font-size: 10px; color: var(--ink-faint); white-space: nowrap; }
.hk-tr-note { margin: var(--space-10) 0 0; font-size: var(--text-2xs); color: var(--ink-faint); }

/* [30 Okt 2026] Modal Tren Harga desktop: lebar 2x (660 -> 1320px), 2 kolom --
   kolom kanan = riwayat harian setinggi kolom kiri (tabel scroll di dalamnya).
   Di bawah 1024px tetap 1 kolom 660px seperti sebelumnya. */
/* Pakai #hkTrendModal supaya menang atas .modal-content { max-width: 520px } yang
   ditulis lebih bawah di file ini (spesifisitas sama = aturan terakhir menang). */
#hkTrendModal .hk-trend-modal-content { max-width: min(660px, calc(100% - 20px)); }
@media (min-width: 1024px) {
  #hkTrendModal .hk-trend-modal-content { max-width: min(1320px, 96vw); }
  .hk-tr-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-20); align-items: stretch; }
  .hk-tr-main { min-width: 0; }
  .hk-tr-side { position: relative; min-width: 0; min-height: 320px; }
  .hk-tr-side .hk-tr-history { position: absolute; inset: 0; }
  .hk-tr-side .hk-tr-hist-list { flex: 1 1 auto; min-height: 0; max-height: none; }
}

@media (max-width: 600px) {
  .hk-trend-canvas-wrap { height: 220px; }
  .hk-tr-price { font-size: var(--text-2xl); }
  .hk-tr-hero-delta { align-items: flex-start; }
  .hk-tr-stats { grid-template-columns: repeat(2, 1fr); }
  .hk-tr-pos-scale { flex-wrap: wrap; }
  .hk-tr-hist-cols, .hk-tr-row { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) auto; gap: var(--space-8); padding-left: var(--space-10); padding-right: var(--space-10); }
  .hk-tr-datetxt { font-size: var(--text-2xs); }
}

.expense-chart-legend {
  flex: 1;
  min-width: 180px;
  /* [UI OPTIMASI DESKTOP] Sebelumnya flex-direction:column 1 kolom dengan
     max-width:460px -- itu sendiri perbaikan dari bug flex:1 tanpa batas
     (legend melar penuh, .legend-label yang juga flex:1 di dalamnya jadi
     mendorong nominal & persen jauh ke ujung kanan, nyisain gap kosong
     aneh di tengah). Tapi di layar lebar, max-width:460px itu menyisakan
     ruang kosong besar DI LUAR legend (di sisi kanan kartu) begitu
     kategori sedikit -- ruang di samping donat tidak termaksimalkan.
     Solusi: grid multi-kolom, tiap kolom dibatasi lebar wajar
     (minmax(200px,240px), pola sama seperti max-width:460px lama tapi
     per-kolom) supaya .legend-label di dalamnya tidak melar aneh --
     TAPI begitu kartu makin lebar, grid otomatis nambah kolom baru
     (auto-fill) alih-alih nyisain whitespace kosong di sisi kanan.
     Di layar sempit (<=640px, lihat media query di bawah) otomatis balik
     jadi 1 kolom karena cuma itu yang muat -- tidak perlu override
     display terpisah. */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 240px));
  gap: var(--space-7) var(--space-20);
  align-content: start;
  max-height: 200px;
  overflow-y: auto;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  font-size: var(--text-xs);
}
.legend-dot {
  width: 8px; height: 8px;
  border-radius: var(--radius-xs);
  flex-shrink: 0;
}
.legend-label {
  flex: 1;
  color: var(--ink-muted);
  font-weight: 400;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.legend-amount {
  font-family: var(--font-mono);
  font-weight: 500;
  color: var(--danger);
  white-space: nowrap;
}
.legend-pct {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  min-width: 34px;
  text-align: right;
}
.expense-chart-empty {
  text-align: center;
  color: var(--ink-faint);
  font-size: var(--text-sm);
  padding: var(--space-30) 0;
  width: 100%;
}

canvas { max-height: 260px; width: 100%; }
.chart-container { max-width: 100%; margin: var(--space-20) 0; }

/* ── Controls ── */
.controls {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-12);
  gap: var(--space-12);
  flex-wrap: wrap;
}

.filters {
  display: flex;
  gap: var(--space-6);
  align-items: center;
  flex-wrap: wrap;
}

.search-input {
  padding: var(--space-7) var(--space-12);
  font-size: var(--text-sm);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  width: 180px;
  font-family: inherit;
  color: var(--ink);
  background: var(--paper);
  transition: border-color 0.15s;
}
.search-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-lt);
}
.search-input::placeholder { color: var(--ink-faint); }

.filter-btn {
  padding: var(--space-6) var(--space-12);
  font-size: var(--text-xs);
  font-weight: 500;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all 0.15s;
  font-family: inherit;
  color: var(--ink-muted);
}
.filter-btn:hover { background: var(--paper-warm); border-color: var(--ink-faint); }
.filter-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); font-weight: 700; }

.date-quick-preset {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  padding: var(--space-6) var(--space-10);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-family: inherit;
  color: var(--ink-muted);
  cursor: pointer;
}
.date-quick-preset:hover { border-color: var(--ink-faint); }

.date-filter-box {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  background: var(--paper);
  border: 1.5px solid var(--rule);
  padding: var(--space-4) var(--space-10);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
}
.date-filter-box input {
  border: none;
  font-family: inherit;
  font-size: var(--text-xs);
  outline: none;
  background: transparent;
  width: 105px;
  color: var(--ink);
}
/* [FIX] input[type="date"] punya aturan border/background/padding sendiri
   (lihat "Native Date Input" di bawah) dengan specificity yang sama, jadi
   tanpa selector lebih spesifik ini urutan file yang menang -> tampil
   sebagai kotak bulat sendiri di DALAM .date-filter-box (kotak dobel).
   Selector ini memastikan input selalu menyatu tanpa border/bg sendiri. */
.date-filter-box input[type="date"] {
  border: none;
  background: transparent;
  border-radius: 0;
  padding: 0;
}
.date-clear-btn {
  background: none;
  border: none;
  font-weight: 500;
  color: var(--danger);
  cursor: pointer;
  padding: 0 var(--space-4);
  font-size: var(--text-md);
  line-height: 1;
}

/* ── Actions / Buttons ── */
.actions { display: flex; gap: var(--space-6); flex-wrap: wrap; }
.actions .btn { border-radius: var(--radius-sm); }

button, .btn, .btn-secondary {
  padding: var(--space-6) var(--space-14);
  font-size: var(--text-xs);
  font-weight: 600;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  cursor: pointer;
  background: var(--paper);
  color: var(--ink-muted);
  font-family: inherit;
  transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.15s, box-shadow 0.15s;
  display: inline-flex;
  align-items: center;
  gap: var(--space-5);
}

button:hover:not(:disabled),
.btn:hover:not(:disabled) {
  background: var(--paper-warm);
  border-color: var(--ink-faint);
  color: var(--ink);
}

button:disabled, .btn:disabled,
.manage-books-btn:disabled, .btn-icon:disabled, .page-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.btn { border-radius: var(--radius-sm); padding: var(--space-7) var(--space-16); }

.btn-primary {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
  font-weight: 700;
  /* [FLAT] Shadow tombol utama dimatikan. */
  box-shadow: none;
}
.btn-primary:hover:not(:disabled) { background: var(--brand-dark); border-color: var(--brand-dark); transform: translateY(-1px); }
.btn-primary:disabled { opacity: 0.4; cursor: not-allowed; background: var(--ink-faint); border-color: var(--ink-faint); box-shadow: none; }

.btn-secondary {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--rule);
  border-width: 1.5px;
  font-weight: 600;
}
.btn-secondary:hover { background: var(--paper-warm); border-color: var(--ink-faint); }

.btn-danger {
  background: var(--danger-lt);
  color: var(--danger);
  border-color: var(--danger);
  opacity: 0.7;
}
.btn-danger:hover { background: var(--danger-lt); opacity: 1; }

.btn-success {
  background: var(--success-lt);
  color: var(--success);
  border-color: var(--success);
  opacity: 0.7;
}
.btn-success:hover { background: var(--success-lt); opacity: 1; }

.btn-icon {
  padding: var(--space-5) var(--space-12);
  font-size: var(--text-xs);
  font-weight: 500;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  cursor: pointer;
  transition: all 0.15s;
  font-family: inherit;
  color: var(--ink-muted);
  display: inline-flex;
  align-items: center;
  gap: var(--space-5);
}
.btn-icon:hover:not(:disabled) { background: var(--paper-warm); border-color: var(--ink-faint); color: var(--ink); }
.btn-icon:disabled { opacity: 0.35; cursor: not-allowed; }

.btn-mini {
  padding: var(--space-4) var(--space-10);
  font-size: var(--text-2xs);
  font-weight: 500;
  border-radius: var(--radius-sm);
  cursor: pointer;
  border: 1.5px solid var(--rule);
  background: var(--paper);
  color: var(--ink-muted);
  transition: all 0.15s;
  font-family: inherit;
}
.btn-mini:hover:not(:disabled) { background: var(--paper-warm); color: var(--ink); }
.btn-mini:disabled { opacity: 0.35; cursor: not-allowed; }

.btn-mini-danger {
  background: var(--danger-lt);
  color: var(--danger);
  border-color: var(--danger);
  opacity: 0.7;
}
.btn-mini-danger:hover:not(:disabled) { opacity: 1; }

/* [UI] Chip kecil untuk link aksi non-native (mis. "Atur Tampilan Card"),
   supaya tidak tampil sebagai link biru bawaan browser. */
.link-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-2xs);
  font-weight: 600;
  font-family: inherit;
  color: var(--ink-muted);
  background: var(--paper-warm);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-8);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  cursor: pointer;
  transition: all 0.15s;
}
.link-chip:hover { background: var(--paper); color: var(--ink); border-color: var(--ink-faint); }
.link-chip:active { transform: scale(0.97); }

.hamburger-btn {
  /* [UI] Lingkaran/pill (background + border) dihapus sesuai permintaan --
     sekarang cuma icon polos tanpa bingkai. */
  padding: var(--space-6) var(--space-12);
  font-size: var(--text-lg);
  font-weight: 500;
  background: none;
  color: var(--ink);
  border: none;
  cursor: pointer;
  line-height: 1;
  transition: opacity 0.15s;
}
.hamburger-btn:hover { opacity: 0.7; }
.hamburger-btn:active { opacity: 0.5; }

/* Tombol pemicu sidebar (hamburger) dipakai di rentang lebar 0-1023px,
   mengikuti breakpoint sidebar (bukan breakpoint umum .mobile-only 640px) --
   supaya tidak ada celah lebar tablet (641-1023px) tanpa cara membuka
   sidebar untuk pindah ke menu Pengaturan. */
.hamburger-btn-icon { display: inline-flex !important; }
.hamburger-btn-icon {
  /* [UI] Kotak diperkecil dari 36x36 ke 28x28 -- tanpa lingkaran/border,
     kotak besar cuma jadi ruang kosong di sekitar icon. */
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  flex-shrink: 0;
}
@media (min-width: 1024px) {
  .hamburger-btn-icon { display: none !important; }
}

/* ── Sidebar Mobile Overlay (backdrop saat #appSidebar dibuka di layar sempit) ── */
.mdrawer-overlay {
  position: fixed;
  inset: 0;
  background: rgba(13,13,13,0.45);
  z-index: 3000;
  backdrop-filter: blur(2px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s;
}


/* ── Table ── */
.table-container {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  overflow-x: auto;
  margin-bottom: var(--space-20);
}

/* ── Harga Komoditas: kotak "Ringkasan Hari Ini" -- rekap 1-lirik di atas
   tabel/kartu supaya user tidak perlu baca baris komoditas satu-satu buat
   tahu apa yang berubah hari ini.
   [DIRATAKAN] Sebelumnya gradient navy gelap (pola sama dengan
   .dbudget-summary-card/.slist-summary-card di bawah) dengan teks putih
   manual -- sekarang flat seperti kartu lain (var(--paper) + border),
   warna teks dipetakan ke var(--ink)/var(--ink-muted)/var(--ink-faint)
   biasa, dan aksen naik/turun harga dipetakan ke var(--danger)/var(--success)
   standar (sebelumnya sengaja pakai warna custom #F2A7A0/#A7D9BE karena
   var(--danger)/var(--success) dianggap terlalu gelap di atas navy --
   sekarang di atas latar terang keduanya sudah kontras dengan baik). ── */
.hk-summary-box {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-16) var(--space-20);
  margin-bottom: var(--space-16);
  color: var(--ink);
}
.hk-summary-date {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: .03em;
  margin-bottom: var(--space-10);
}
/* ── Ringkasan Harga Komoditas: 3 chip naik/turun/stabil + kartu "top
   mover" berwarna -- sebelumnya baris teks polos semua warna netral, jadi
   sekilas kelihatan sama pentingnya. Sekarang tiap status punya bidang
   warna sendiri (tint danger/success, pola sama dengan badge-inc/badge-exp
   yang sudah ada), jadi status yang paling relevan (naik = butuh
   perhatian) langsung menonjol tanpa perlu baca angka satu-satu. */
.hk-summary-stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8);
  margin-bottom: var(--space-14);
}
.hk-stat-chip {
  flex: 1 1 80px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-9) var(--space-6);
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--rule);
  background: var(--paper-warm);
}
.hk-stat-chip-num {
  font-family: var(--font-mono);
  font-size: var(--text-3xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1;
}
.hk-stat-chip-label {
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: .03em;
}
/* [FIX MOBILE] var(--danger-lt)/var(--success-lt) polos ternyata terlalu
   pudar dipakai sebagai bidang warna seluas kartu (token itu didesain
   buat badge kecil dengan teks tebal sbg sinyal utama, bukan blok warna
   besar) -- di layar hp yang lebih terang/kecil nyaris tak kebeda dari
   var(--paper) putih polos, jadi kelihatan seperti tanpa styling sama
   sekali. Diperkuat dua arah: (1) tint dibikin lebih pekat pakai
   color-mix langsung dari var(--danger)/var(--success) (bukan token -lt
   bawaan), (2) ditambah border solid senada -- border tetap kelihatan
   jelas meski kebetulan browser/layar bikin tint-nya kurang kontras. */
.hk-stat-chip-naik {
  background: color-mix(in srgb, var(--danger) 14%, var(--paper));
  border-color: var(--danger);
}
.hk-stat-chip-naik .hk-stat-chip-num { color: var(--danger); }
.hk-stat-chip-turun {
  background: color-mix(in srgb, var(--success) 14%, var(--paper));
  border-color: var(--success);
}
.hk-stat-chip-turun .hk-stat-chip-num { color: var(--success); }
.hk-stat-chip-stabil .hk-stat-chip-num { color: var(--ink-muted); }

/* Kartu penyorot komoditas naik/turun paling tajam -- pengganti baris teks
   "▲ Naik paling tajam: ..." polos. Ikon SVG trending dipakai sebagai
   ganti karakter unicode ▲/▼ (konsisten dengan ikon aksi lain di app yang
   semuanya SVG, bukan karakter font). */
.hk-summary-movers {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-10);
}
.hk-mover-card {
  flex: 1 1 220px;
  display: flex;
  align-items: flex-start;
  gap: var(--space-8);
  padding: var(--space-10) var(--space-12);
  border-radius: var(--radius-sm);
  border: 1.5px solid transparent;
}
.hk-mover-card svg { flex: 0 0 auto; margin-top: var(--space-2); }
.hk-mover-body { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.hk-mover-label { font-size: var(--text-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: .03em; }
.hk-mover-name { color: var(--ink); font-size: var(--text-sm); font-weight: 700; overflow-wrap: anywhere; }
.hk-mover-detail { font-size: var(--text-xs); font-weight: 600; }
/* [FIX MOBILE] Sama seperti chip di atas -- tint diperkuat pakai color-mix
   & border solid (bukan cuma border-left tipis) supaya kartu ini tetap
   jelas kelihatan berwarna di kondisi layar apa pun. */
.hk-mover-up {
  background: color-mix(in srgb, var(--danger) 10%, var(--paper));
  border-color: var(--danger);
  color: var(--danger);
}
.hk-mover-down {
  background: color-mix(in srgb, var(--success) 10%, var(--paper));
  border-color: var(--success);
  color: var(--success);
}
.hk-summary-highlight-list {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--ink-muted);
}
.hk-summary-note {
  margin-top: var(--space-10);
  font-size: var(--text-xs);
  color: var(--ink-faint);
}
.hk-summary-empty { font-size: var(--text-sm); color: var(--ink-faint); }
.hk-summary-reminder {
  margin-top: var(--space-10);
  padding-top: 10px;
  border-top: 1px solid var(--rule);
  font-size: var(--text-sm);
  color: var(--ink-faint);
}

/* ── Modal "Deteksi Keuangan Tidak Wajar" (js/fraud-detection.js) --
   [RESTYLE, 8 Okt 2026] Fungsi & struktur data-action TIDAK berubah (filter,
   2 section, Abaikan / Abaikan semua / Lihat transaksi / Urungkan, Ringkasan
   AI). Yang berubah murni tampilan agar lebih padat & pas di mobile/desktop:
   (1) padding modal lebih ramping + header lengket (tombol tutup selalu
   terlihat saat daftar discroll); (2) baris jadi grid -- DESKTOP: pesan di
   atas, baris bawah = meta (kiri) + aksi (kanan) sehingga 1 flag hanya
   makan ~2 baris; MOBILE: aksi turun satu baris penuh dengan tombol
   berbagi lebar sama (target sentuh 36px); (3) di <=640px modal tampil
   sebagai bottom-sheet (menempel bawah, sudut atas membulat, mengikuti
   safe-area). Semua warna lewat token (otomatis ikut dark mode). */
.fraud-modal-content {
  max-width: 600px;
  padding: var(--space-20);
  padding-top: 0;
  overscroll-behavior: contain;
}
.fraud-modal-content .modal-header {
  position: sticky;
  top: 0;
  z-index: 3;
  margin: 0 calc(-1 * var(--space-20)) var(--space-10);
  padding: var(--space-16) var(--space-20) var(--space-10);
  background: var(--paper);
}
.fraud-modal-content .modal-header h3 {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  font-size: var(--text-base);
  min-width: 0;
}
.fraud-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  flex-wrap: wrap;
  margin-bottom: var(--space-8);
}
/* Tombol aksi bersama (modal fraud). Abaikan = outline ink (paling tegas di
   baris), ghost = teks aksen tanpa border, sm = versi kecil utk massal. */
.fraud-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-5);
  min-height: 30px;
  padding: 0 var(--space-12);
  font-family: inherit;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1;
  color: var(--ink);
  background: var(--paper);
  border: 1.5px solid var(--ink);
  border-radius: var(--radius-pill);
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s, transform .1s;
}
.fraud-btn .sk-icon { width: 13px; height: 13px; margin: 0; }
.fraud-btn:hover { background: var(--ink); color: var(--paper); }
.fraud-btn:active { transform: scale(.97); }
.fraud-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fraud-btn-ghost { border-color: var(--rule); background: none; color: var(--accent); padding: 0 var(--space-10); }
.fraud-btn-ghost:hover { background: var(--paper-warm); color: var(--accent); border-color: var(--ink-faint); }
.fraud-btn-sm { min-height: 26px; padding: 0 var(--space-10); font-size: var(--text-2xs); color: var(--ink-muted); border-color: var(--rule); }
.fraud-btn-sm:hover { background: var(--paper-warm); color: var(--ink); border-color: var(--ink-faint); }
.fraud-section { margin-top: var(--space-12); }
.fraud-section:first-of-type { margin-top: 0; }
.fraud-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  padding-bottom: var(--space-6);
  border-bottom: 1px solid var(--rule);
}
.fraud-section-title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-6);
  min-width: 0;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--ink-muted);
}
.fraud-section-title svg { flex-shrink: 0; width: 14px; height: 14px; }
.fraud-section-count {
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--ink-faint);
  background: var(--paper-warm);
  border-radius: var(--radius-pill);
  padding: 1px var(--space-7);
}
.fraud-list { border-top: 1px solid var(--rule); }
.fraud-section .fraud-list { border-top: none; } /* section sudah punya garis bawah di headernya */
.fraud-row {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  grid-template-areas:
    "icon msg  msg"
    "icon meta act";
  column-gap: var(--space-10);
  row-gap: var(--space-4);
  align-items: center;
  padding: var(--space-10) var(--space-2);
  border-bottom: 1px solid var(--rule);
}
.fraud-row:last-child { border-bottom: none; }
.fraud-row-icon {
  grid-area: icon;
  align-self: start;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.fraud-row-warning .fraud-row-icon { background: color-mix(in srgb, var(--danger) 14%, var(--paper)); color: var(--danger); }
.fraud-row-info .fraud-row-icon { background: color-mix(in srgb, var(--info) 14%, var(--paper)); color: var(--info); }
.fraud-row-msg { grid-area: msg; font-size: var(--text-sm); line-height: 1.4; color: var(--ink); overflow-wrap: anywhere; }
.fraud-row-meta { grid-area: meta; font-size: var(--text-2xs); color: var(--ink-faint); }
.fraud-row-level { font-weight: 600; }
.fraud-row-warning .fraud-row-level { color: var(--danger); }
.fraud-row-info .fraud-row-level { color: var(--info); }
.fraud-row-actions { grid-area: act; display: flex; align-items: center; gap: var(--space-6); }
/* Bar Urungkan setelah "Abaikan" -- tampil 8 detik di atas daftar. */
.fraud-undo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  margin-bottom: var(--space-8);
  padding: var(--space-4) var(--space-4) var(--space-4) var(--space-12);
  font-size: var(--text-xs);
  color: var(--paper);
  background: var(--ink);
  border-radius: var(--radius-sm);
}
.fraud-undo-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-5);
  min-height: 28px;
  padding: 0 var(--space-10);
  font-family: inherit;
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--paper);
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--paper) 45%, transparent);
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.fraud-undo-btn .sk-icon { width: 13px; height: 13px; margin: 0; }
.fraud-undo-btn:hover { background: color-mix(in srgb, var(--paper) 18%, transparent); }
@media (max-width: 640px) {
  #fraudAlertModal { padding: 0; align-items: flex-end; }
  #fraudAlertModal .fraud-modal-content {
    max-width: 100%;
    margin: 0;
    max-height: 92vh;
    max-height: 92dvh;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    padding: 0 var(--space-14) calc(var(--space-14) + env(safe-area-inset-bottom, 0px));
  }
  #fraudAlertModal .fraud-modal-content .modal-header {
    margin: 0 calc(-1 * var(--space-14)) var(--space-8);
    padding: var(--space-12) var(--space-14) var(--space-8);
  }
  .fraud-toolbar { flex-wrap: nowrap; }
  .fraud-toolbar .log-filter-bar { flex-wrap: nowrap; }
  .fraud-row {
    grid-template-columns: 26px minmax(0, 1fr);
    grid-template-areas:
      "icon msg"
      "icon meta"
      "act  act";
    padding: var(--space-10) 0;
  }
  .fraud-row-actions { margin-top: var(--space-6); }
  .fraud-row-actions .fraud-btn { flex: 1 1 0; min-height: 36px; }
}
/* Ringkasan AI -- pill kecil di BAWAH kedua section (pakai ulang
   .log-filter-chip supaya tidak menambah satu gaya tombol baru). */
.fraud-ai-block { margin-top: var(--space-14); padding-top: var(--space-12); border-top: 1px solid var(--rule); }
.fraud-ai-box { margin-top: var(--space-8); }
/* Empty-state (tidak ada flag sama sekali / tidak ada yg cocok filter)
   sengaja pakai ULANG .log-empty (panel Log Audit) -- pola ikon+teks
   center yg sama, tidak perlu duplikat aturan baru cuma ganti nama. */

/* ── Harga Komoditas: kartu ala-app untuk hape (pengganti tabel scroll
   horizontal yang terasa "native"/mentah di layar sempit) --
   disembunyikan by default, baru tampil di breakpoint mobile (lihat
   media query @max-width:640px) yang juga menyembunyikan .hk-compact-list. ── */
.hk-card-list { display: none; }
.hk-card {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-12) var(--space-14);
}
.hk-card-name { font-weight: 700; font-size: var(--text-base); color: var(--ink); margin-bottom: var(--space-6); display: block; }
.hk-card-bottom-row {
  display: flex;
  align-items: center;
  gap: var(--space-7);
  flex-wrap: wrap;
  row-gap: var(--space-4);
}
.hk-card-price { font-family: var(--font-mono); font-weight: 700; font-size: var(--text-lg); color: var(--ink); white-space: nowrap; }
.hk-card-unit { font-size: var(--text-2xs); color: var(--ink-faint); white-space: nowrap; }
.hk-card-change { font-size: var(--text-sm); font-weight: 600; white-space: nowrap; }
.hk-card-meta { font-size: var(--text-2xs); color: var(--ink-faint); }
.hk-card-trend-btn { padding: 4px 12px !important; font-size: var(--text-xs) !important; white-space: nowrap; flex-shrink: 0; }

/* Sparkline tren 30-hari mini, ditaruh sebaris di ujung kanan (setelah
   nama, harga, dan indikator naik/turun) -- tap untuk buka grafik lengkap
   di modal. Kecil & sejajar supaya kartu tetap ringkas, bukan lagi
   selebar penuh di bawah. */
.hk-card-spark-btn {
  display: block;
  margin-left: auto;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  line-height: 0;
  flex-shrink: 0;
}
.hk-card-spark-btn:active { opacity: 0.6; }
.hk-card-spark { display: block; width: 60px; height: 26px; }
.hk-card-spark-empty {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  margin-left: auto;
  white-space: nowrap;
  flex-shrink: 0;
}

table {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
  font-size: var(--text-sm);
  min-width: 800px;
}

th {
  background: var(--paper-warm);
  padding: var(--space-13) var(--space-16);
  font-weight: 700;
  font-family: var(--font-display);
  border-bottom: 1.5px solid var(--rule);
  font-size: var(--text-2xs);
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

td {
  padding: var(--space-12) var(--space-16);
  border-bottom: 1px solid var(--rule);
  vertical-align: middle;
  color: var(--ink);
}

tr:last-child td { border-bottom: none; }
tr:hover td { background: var(--accent-lt); }

/* [UI] Tanggal singkat (mis. 20/7/26) hanya tampil di hape;
   versi lengkap dengan jam tampil di desktop/tablet. */
.date-short { display: none; }

.type-badge {
  font-size: var(--text-2xs);
  font-weight: 700;
  padding: var(--space-3) var(--space-9);
  border-radius: var(--radius-pill);
  margin-right: var(--space-4);
  display: inline-block;
  letter-spacing: 0.01em;
}
.badge-inc { background: var(--success-lt); color: var(--success); }
.badge-exp { background: var(--danger-lt);  color: var(--danger); }

.category-badge {
  font-size: var(--text-2xs);
  font-weight: 600;
  background: var(--accent-lt);
  color: var(--accent);
  padding: var(--space-3) var(--space-9);
  border-radius: var(--radius-pill);
  display: inline-block;
  border: none;
}

/* Catatan: .text-right saat ini cuma dipakai untuk kolom nominal
   transaksi (masuk/keluar/saldo), jadi aman pakai font angka di sini. */
.text-right  { text-align: right; font-family: var(--font-mono); }
.col-saldo   { font-family: var(--font-mono); }
.text-center { text-align: center; }
/* [UI] Isi kolom nominal (Pemasukan/Pengeluaran/Saldo) & kolom
   Nota/Aksi sebelumnya rata kanan/tengah sementara headernya rata
   kiri, jadi terlihat tidak sejajar. .num-mono dipakai supaya
   angka tetap pakai font monospace tapi rata kiri mengikuti header. */
.num-mono { text-align: left; font-family: var(--font-mono); }

.action-btn {
  background: none;
  border: none;
  font-weight: 500;
  cursor: pointer;
  padding: var(--space-3) var(--space-8);
  font-size: var(--text-lg);
  border-radius: var(--radius-sm);
  transition: background 0.15s;
  color: var(--ink-muted);
}
.action-btn:hover:not(:disabled) { background: var(--paper-warm); color: var(--ink); }
.action-btn:disabled { opacity: 0.35; cursor: not-allowed; }

.attachment-link {
  cursor: pointer;
  font-size: var(--text-lg);
  text-decoration: none;
  color: var(--accent);
  transition: opacity 0.15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.attachment-link:hover { opacity: 0.6; }
.no-attachment { color: var(--rule); }

/* ── Tabel Neraca Utama (transaksi dashboard) ──
   [RAPIKAN & EFISIENKAN] Semua aturan di-scope ke .tx-table karena selector
   global table/th/td dipakai bersama tabel lain.
   Masalah sebelumnya (layar lebar): tiap baris ~56px sehingga cuma ~14 baris
   muat di satu layar; kolom angka rata kiri jadi digit tidak sejajar; kolom
   kosong (Pemasukan/Pengeluaran) menampilkan "-" setebal angka asli; Deskripsi
   panjang bisa memecah baris jadi 2-3 baris.
   Sekarang: padding baris dipadatkan, angka rata kanan + tabular-nums (header
   ikut rata kanan), Nota/Aksi di tengah, jam transaksi dibuat redup, sel kosong
   jadi strip redup, dan di desktop Deskripsi 1 baris + ellipsis (teks penuh
   lewat tooltip title). Hape (<=768px) TIDAK diubah -- aturan hape yang sudah
   ada di bawah tetap berlaku. Tablet (769-1024px) tidak dipotong ellipsis
   karena tidak ada hover untuk melihat teks penuh. */
.tx-table .tx-zero { color: var(--ink-faint); font-weight: 400; }
/* Header Saldo ikut kena .col-saldo (font mono) -- kembalikan ke font header. */
.tx-table th.col-saldo { font-family: var(--font-display); }
.tx-table .tx-time {
  color: var(--ink-faint);
  font-size: var(--text-xs);
  margin-left: var(--space-6);
}
@media (min-width: 769px) {
  /* [LEBIH LONGGAR 7 Okt 2026] Sebelumnya td 7px 14px (baris ~44px) terasa
     sesak. Sekarang td 10px 16px (baris ~50px) dan header 13px 16px. Di
     layar lebar (>=1025px) jarak horizontal dilebarkan lagi, lihat di bawah. */
  .tx-table th { padding: var(--space-13) var(--space-16); white-space: nowrap; letter-spacing: .06em; }
  .tx-table td { padding: var(--space-10) var(--space-16); }
  .tx-table td:not(.col-desc) { white-space: nowrap; }
  .tx-table .col-no { color: var(--ink-faint); font-variant-numeric: tabular-nums; }
  .tx-table th.col-num,
  .tx-table td.col-num { text-align: right; font-variant-numeric: tabular-nums; }
  .tx-table th.col-nota,
  .tx-table td.col-nota,
  .tx-table th.col-action,
  .tx-table td.col-action { text-align: center; }
  .tx-table .type-badge { margin-right: 0; }
  .tx-table .action-btn { padding: var(--space-2) var(--space-6); }
}
@media (min-width: 1025px) {
  .tx-table th,
  .tx-table td { padding-left: var(--space-20); padding-right: var(--space-20); }
  /* max-width:0 + width:100% = kolom Deskripsi menyerap semua sisa lebar
     (kolom lain menyusut sesuai isi karena nowrap) dan memotong teks panjang. */
  .tx-table td.col-desc {
    max-width: 340px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* [KOLOM BARU] Akun/Dompet + Catatan/Tag (desktop >=1025px). Catatan
     menyerap sisa lebar (max-width:0 + width:100%) sehingga bagian tengah
     tabel tidak lagi kosong; teks panjang dipotong ellipsis (penuh lewat title). */
  .tx-table th.col-wallet,
  .tx-table td.col-wallet,
  .tx-table th.col-note,
  .tx-table td.col-note { display: table-cell; }
  .tx-table td.col-wallet {
    color: var(--ink-muted);
    font-size: var(--text-xs);
  }
  .tx-table td.col-note {
    max-width: 0;
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--ink-muted);
    font-size: var(--text-xs);
  }
}
/* Akun & Catatan hanya tampil di desktop >=1025px (di tablet/hape disembunyikan).
   [FIX] Sebelumnya aturan display:none ini tanpa media query dan letaknya SETELAH
   blok desktop di atas (spesifisitas sama), sehingga menimpa display:table-cell
   dan kolom Akun/Catatan tidak pernah tampil di desktop (ruang tengah kosong). */
@media (max-width: 1024px) {
  .tx-table th.col-wallet,
  .tx-table td.col-wallet,
  .tx-table th.col-note,
  .tx-table td.col-note { display: none; }
}
/* Nama hari di samping tanggal + chip tag (#...) pada Catatan. */
.tx-table .tx-day {
  display: inline-block;
  min-width: 2.4em;
  margin-right: var(--space-6);
  color: var(--ink-faint);
  font-size: var(--text-xs);
}
.tx-table .tx-tag {
  display: inline-block;
  margin-right: var(--space-6);
  padding: 1px var(--space-8);
  border-radius: 999px;
  background: var(--rule);
  color: var(--ink-muted);
  font-size: var(--text-2xs);
  line-height: 1.6;
}

/* Kolom Kategori (kategori pengeluaran/pemasukan asli, mis. "Belanja Harian")
   -- khusus desktop >=1025px, memanfaatkan ruang kosong di kolom Deskripsi;
   posisinya setelah kolom Jenis (badge MASUK/KELUAR), sebelum Deskripsi.
   Di tablet & hp disembunyikan (tampilan lama tidak berubah). Kolom "Jenis"
   (badge MASUK/KELUAR, dulu berjudul "Kategori") tetap di tempatnya. */
.tx-table th.col-txcat,
.tx-table td.col-txcat { display: none; }
@media (min-width: 1025px) {
  .tx-table th.col-txcat,
  .tx-table td.col-txcat { display: table-cell; }
  .tx-table td.col-txcat {
    max-width: 170px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--ink-muted);
    font-size: var(--text-xs);
  }
}

/* [LEBIH LEGA DESKRIPSI] Desktop >=1025px: kolom No/Tanggal/Jenis/Kategori/Akun
   dipepatkan sesuai isi (width:1% + nowrap = selebar kontennya saja) supaya
   Jenis menempel dekat Tanggal dan tidak ada ruang kosong di antaranya. Sisa
   lebar dibagi ke Deskripsi (lebih besar) dan Catatan. */
@media (min-width: 1025px) {
  .tx-table th.col-no,   .tx-table td.col-no,
  .tx-table th.col-date, .tx-table td.col-date,
  .tx-table th.col-category, .tx-table td.col-category,
  .tx-table th.col-txcat, .tx-table td.col-txcat,
  .tx-table th.col-wallet, .tx-table td.col-wallet { width: 1%; white-space: nowrap; }
  .tx-table td.col-desc { max-width: 0; width: 40%; }
  .tx-table td.col-note { width: 30%; }
}

/* [PISAH PEMASUKAN / PENGELUARAN] >=641px: dua kolom terpisah (td.col-split);
   kolom gabungan Nominal (col-amount-m) khusus hape <=640px. */
.tx-table th.col-amount-m,
.tx-table td.col-amount-m { display: none; }
@media (max-width: 640px) {
  .tx-table th.col-inc-h,
  .tx-table th.col-exp-h,
  .tx-table td.col-split { display: none; }
  .tx-table th.col-amount-m,
  .tx-table td.col-amount-m { display: table-cell; }
}
@media (min-width: 1025px) {
  .tx-table th.col-inc-h, .tx-table th.col-exp-h, .tx-table td.col-split { width: 1%; white-space: nowrap; }
}

/* ── Pagination ── */
.pagination-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-10) var(--space-2);
  margin-bottom: var(--space-16);
  flex-wrap: wrap;
  gap: var(--space-10);
}

.pagination-info {
  font-size: var(--text-xs);
  color: var(--ink-faint);
  font-weight: 400;
}

.pagination-controls {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.page-btn {
  min-width: 30px;
  height: 30px;
  padding: 0 var(--space-8);
  font-size: var(--text-xs);
  font-weight: 500;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--ink-muted);
  cursor: pointer;
  transition: all 0.15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
}
.page-btn:hover:not(:disabled) { border-color: var(--ink-faint); background: var(--paper-warm); color: var(--ink); }
.page-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); font-weight: 700; }
.page-btn:disabled { opacity: 0.3; cursor: not-allowed; }

.page-ellipsis {
  font-size: var(--text-xs);
  color: var(--ink-faint);
  padding: 0 var(--space-4);
  line-height: 30px;
}

/* ── Footer daftar transaksi (pagination + Kelola Backup/Log Audit) ── */
.list-footer-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-10);
  border-top: 1px solid var(--rule);
  padding-top: 12px;
  margin-top: var(--space-16);
}
.list-footer-info {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-12);
}
.list-footer-actions {
  display: flex;
  gap: var(--space-10);
  flex-wrap: wrap;
}
@media (max-width: 480px) {
  /* Di hp, baris info+pagination dan baris tombol ditumpuk rapi &
     dipusatkan alih-alih nempel rapat rata kiri seperti sebelumnya
     (dua flex-child yang sama-sama wrap ke baris sendiri tapi tanpa
     jarak/alignment yang jelas). Tombol dibuat penuh-lebar & ditumpuk
     vertikal, konsisten dengan pola baris tombol lain di hp (lihat
     .setelan-actions-row di atas). */
  .list-footer-bar {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-14);
  }
  .list-footer-info {
    justify-content: center;
    text-align: center;
  }
  #paginationWrap {
    justify-content: center;
    width: 100%;
  }
  .list-footer-actions {
    flex-direction: column;
  }
  .list-footer-actions .btn {
    width: 100%;
  }
}

/* ── Footer ── */
.footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  padding-top: 10px;
  border-top: 1px solid var(--rule);
  margin-top: var(--space-16);
}

/* ── Modal ── */
.modal {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background: rgba(31,25,17,0.6);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: var(--space-20);
}
.modal.show { display: flex; }

/* Isolasi area halaman penuh agar perubahan daftar besar di satu menu tidak
   memaksa browser menghitung ulang layout Dashboard/sidebar secara luas. */
.fullview-modal { contain: layout paint style; }

/* ── [SMOOTH PAGE TRANSITION] Perpindahan antar menu sidebar & Dashboard ──
   Sebelumnya .fullview-modal.show/.container muncul SEKETIKA (cuma toggle
   display:none<->flex, tanpa transisi apa pun) -- terasa "patah" tiap
   klik menu. Animasi fade+naik tipis ini otomatis terpicu browser setiap
   kali selector di bawah BARU cocok (class .show ditambahkan, atau class
   body.view-fullpage/.view-settings dilepas), tanpa perlu logic JS
   tambahan -- dan otomatis dimatikan oleh aturan prefers-reduced-motion
   global di bawah untuk pengguna yang sensitif terhadap animasi. */
@keyframes skViewFadeIn {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: translateY(0); }
}
.fullview-modal.show .modal-content,
#setelanModal.show .modal-content,
body:not(.view-fullpage):not(.view-settings) #dashboardView {
  animation: skViewFadeIn .2s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── [SMOOTH BOOK SWITCH] Redupkan halus konten yang sedang tampil selagi
   window.switchBook() memuat data buku baru (js/book.js menambah/melepas
   class ini) -- daripada angka saldo/daftar transaksi tiba-tiba "meloncat"
   berganti isi tanpa aba-aba, konten meredup sesaat lalu pulih normal
   begitu data buku baru selesai dipasang. Dikecualikan dari transisi
   reduced-motion supaya tidak mengunci opacity rendah pada pengguna yang
   mematikan animasi (aturan global di bawah tetap membuat transisinya
   instan, bukan macet redup). ── */
#dashboardView,
.fullview-modal.show .modal-content {
  transition: opacity .18s ease, filter .18s ease;
}
body.sk-book-switching #dashboardView,
body.sk-book-switching .fullview-modal.show .modal-content {
  opacity: .55;
  filter: saturate(.75);
  pointer-events: none;
}

.modal-content {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-24);
  width: 100%;
  max-width: 520px;
  max-height: 88vh;
  overflow-y: auto;
}
.modal-content.wide      { max-width: 740px; }
.modal-content.report    { max-width: 960px; max-height: 90vh; }
.modal-content.extra-wide{ max-width: 740px; }

/* ── Setelan (Settings) Modal: taller + tabbed ── */
.setelan-modal-content {
  max-height: 92vh;
  min-height: 60vh;
  display: flex;
  flex-direction: column;
}
.setelan-modal-content .modal-header { flex: 0 0 auto; }

.setelan-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-14);
  min-height: 0;
  overflow: hidden;
}

.setelan-tab-content {
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-14);
}

/* Setiap section Setelan tampil sebagai card sendiri (lihat
   .data-management-panel) -- jaraknya diatur lewat gap flex di atas,
   jadi card ini tidak perlu tambahan margin/border/padding sendiri
   (dulu ada padding-top:22px + border-top di sini yang numpuk dengan
   margin card, hasilnya jarak antar-card 2x lebih lebar dari jarak
   header-ke-card pertama -- makanya terasa tidak balance). */
.data-management-panel.setelan-tab-panel {
  display: block;
  margin: 0;
}

/* ── App Sidebar: Dashboard / Pengaturan (Mobile + Desktop) ── */
#appSidebar {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  position: fixed;
  top: 0; left: 0;
  width: 240px;
  height: 100%;
  background: var(--topbar-bg);
  border-right: 1px solid var(--topbar-border);
  z-index: 3001;
  padding: var(--space-22) var(--space-14);
  overflow-y: auto;
  /* [FIX SIDEBAR HOVER-EXPAND JANK] overflow-x default browser itu
     'visible' -- kalau tidak dikunci 'hidden', teks nav (sekarang
     white-space:nowrap, lihat .app-nav-item) yang belum cukup ruang saat
     sidebar masih sempit (mode icon-only/lagi mulai melebar) akan
     nongol/bleed keluar tepi sidebar, bukan tersembunyi rapi. Dengan
     overflow-x:hidden, teks itu otomatis ke-crop pas di tepi sidebar dan
     "tersingkap" halus mengikuti lebar sidebar yang sedang animasi --
     bukan lompat/patah seperti sebelumnya.
     [FIX] overflow-x kombinasi dengan overflow-y:auto sengaja pakai dua
     properti terpisah (bukan shorthand overflow) supaya scroll vertikal
     tetap jalan seperti semula, cuma horizontal yang dikunci. */
  overflow-x: hidden;
  box-shadow: var(--shadow-lg);
  transform: translateX(-100%);
}
#appSidebar.open { transform: translateX(0); }

@media (max-width: 1023px) {
  /* Drawer mobile: rapatkan padding supaya konten (brand, label grup, item
     nav) lebih mepet ke tepi kiri/kanan drawer, bukan menyisakan margin
     lebar yang boros ruang di layar sempit. */
  #appSidebar { width: min(80vw, 260px); padding: var(--space-18) var(--space-8); }
  .app-sidebar-brand { padding: var(--space-4) var(--space-6) var(--space-16); }
  .app-nav-group-label { padding: var(--space-8) var(--space-6) var(--space-2); }
  .app-nav-item { padding: var(--space-11) var(--space-8); }
}

.app-sidebar-brand {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--topbar-text);
  padding: var(--space-4) var(--space-10) var(--space-18);
  border-bottom: 1px solid var(--topbar-footer-border);
  margin-bottom: var(--space-5);
  overflow: hidden;
}
/* [SIDEBAR-BOOK] Nama lengkap tampil normal; versi inisial disembunyikan
   sampai sidebar diciutkan ke mode icon-only (lihat aturan
   body.sidebar-collapsed di bawah). */
.app-sidebar-brand-full {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-sidebar-brand-initial {
  display: none;
}
/* [SMOOTH BOOK SWITCH] Titik berdenyut di sebelah nama buku aktif selagi
   window.switchBook() menarik data buku baru (body.sk-book-switching,
   ditambah/dilepas di js/book.js) -- penanda kecil supaya perpindahan
   buku tidak terasa seperti "diam saja" selama beberapa saat sebelum
   angka-angka di layar berubah. */
.app-sidebar-brand { position: relative; }
.app-sidebar-brand::after {
  content: '';
  display: none;
  position: absolute;
  top: var(--space-4);
  right: var(--space-8);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
}
body.sk-book-switching .app-sidebar-brand::after {
  display: block;
  animation: skSyncPulse .9s ease-in-out infinite;
}
@keyframes skSyncPulse {
  0%, 100% { opacity: .35; transform: scale(0.85); }
  50% { opacity: 1; transform: scale(1); }
}
.app-nav-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.app-nav-group-label {
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--topbar-text-muted);
  padding: var(--space-8) var(--space-13) var(--space-2);
}
.app-nav-footer {
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--topbar-footer-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.app-nav-item {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  width: 100%;
  padding: var(--space-11) var(--space-13);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  text-align: left;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--topbar-item-color);
  cursor: pointer;
  transition: background .15s, color .15s, box-shadow .15s, transform .1s ease;
  /* [FIX SIDEBAR HOVER-EXPAND JANK] Tanpa ini, saat sidebar mode icon-only
     (68px) di-hover, teks label (display:none -> inline) muncul SEKETIKA
     di frame pertama transisi width -- sebelum sidebar sempat melebar.
     Karena flex item ini defaultnya boleh wrap konten teksnya, teks
     "Dashboard" dkk yang tiba-tiba muncul di ruang sempit 68px langsung
     PATAH ke baris kedua, menaikkan tinggi baris itu -- lalu begitu width
     terus melebar tiap frame (durasi transisi width), teks berangsur
     muat satu baris lagi dan tinggi baris balik normal. Baris-baris nav
     DI BAWAHNYA ikut kedorong turun lalu naik lagi tiap frame perubahan
     tinggi itu -- itulah efek "patah-patah, geser dari atas ke bawah"
     yang terlihat. white-space:nowrap memaksa teks selalu satu baris
     (kalau belum cukup lebar, cukup KEPOTONG rapi oleh overflow-x:hidden
     #appSidebar di bawah, bukan wrap), jadi tinggi tiap item nav constant
     sepanjang animasi -- yang berubah cuma lebar area teks yang kelihatan. */
  white-space: nowrap;
}
.app-nav-item svg { stroke: currentColor; }
.app-nav-item:hover { background: var(--topbar-item-hover-bg); color: var(--topbar-text); }
.app-nav-item.active { background: var(--topbar-item-active-bg); color: var(--topbar-item-active-color); font-weight: 700; box-shadow: var(--topbar-active-shadow); }
/* [SMOOTH NAV] Feedback tekan halus saat pindah menu -- item sedikit
   mengecil sesaat saat ditekan, memberi kesan responsif sebelum halaman
   baru selesai tampil. */
.app-nav-item:active { transform: scale(0.97); }
.app-nav-badge {
  display: none;
  margin-left: auto;
  background: var(--danger);
  color: #fff;
  font-size: var(--text-2xs);
  font-weight: 700;
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-6);
  line-height: 1.5;
}

@media (max-width: 1023px) {
  /* Setelan di hp: tampil full-screen sebagai halaman biasa, bukan kotak
     dialog mengambang dengan latar gelap (pola sama dengan versi desktop
     di bawah, disesuaikan untuk layar sempit tanpa sidebar permanen). */
  body.view-settings .container { display: none; }
  body.view-settings #setelanModal {
    display: flex;
    position: fixed;
    inset: 0;
    background: var(--paper);
    z-index: 2000;
    padding: 0;
    align-items: stretch;
    justify-content: stretch;
  }
  body.view-settings #setelanModal .setelan-modal-content {
    width: 100%;
    max-width: none !important;
    height: 100%;
    max-height: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    /* Sama seperti .fullview-modal (Laporan, Anggaran, dst.) di layar hp:
       sisi 12px, bawah 12px, atas 0 (header yang mengatur jarak atas). */
    padding: 0 var(--space-12) var(--space-12);
  }
  body.view-settings #setelanModal .modal-header {
    background: var(--paper);
    padding: var(--space-16) 0 var(--space-12);
    margin: 0 0 var(--space-8);
    border-bottom: 1px solid var(--rule);
    justify-content: flex-start;
    gap: var(--space-10);
  }
  body.view-settings #setelanModal .modal-header .modal-close {
    order: -1;
    position: static;
  }
}

@media (min-width: 1024px) {
  /* [SIDEBAR-COLLAPSE] Lebar sidebar desktop dipusatkan lewat 1 variabel
     supaya semua tempat yang bergantung padanya (sidebar sendiri, margin
     .container, margin halaman Setelan & fullview-modal di bawah) ikut
     berubah otomatis saat diciutkan lewat class body.sidebar-collapsed
     (lihat window.toggleSidebarCollapse di js/app.js). */
  :root { --sidebar-w: 236px; }
  body.sidebar-collapsed { --sidebar-w: 68px; }

  #appSidebar {
    width: var(--sidebar-w);
    transform: translateX(0);
    box-shadow: none;
    transition: width .18s ease;
  }

  /* Konten mengisi penuh sisa layar di sebelah kanan sidebar, tidak lagi
     terpotong oleh max-width:1440px bawaan .container yang menyisakan
     ruang kosong di layar lebar.
     [RAPATKAN JARAK SIDEBAR-KONTEN] padding-left dipangkas dari 32px
     (default mobile/tablet di baris .container atas) jadi 16px KHUSUS di
     breakpoint ini -- di layar sempit paddingnya tetap 32px karena di situ
     tidak ada sidebar permanen yang bikin sisi kiri sudah "terpakai", jadi
     32px masih wajar sebagai jarak dari tepi layar. Di desktop, sidebar
     sudah jadi pembatas visual sendiri, jadi 32px tambahan setelahnya
     berlebihan/boros ruang. padding-right & padding-bottom TIDAK diubah
     (tetap 32px / 40px bawaan) supaya sisi kanan halaman tidak berubah.
     [SEIMBANGKAN KIRI-KANAN] padding-right sekarang IKUT 16px (sebelumnya
     32px) supaya jarak tabel/kartu ke sidebar di kiri dan ke tepi layar di
     kanan sama besar -- sebelumnya kiri 16px vs kanan 32px, terlihat miring
     ke kiri. Sama dengan fullview-modal & Setelan yang sudah 16px kiri-kanan.
     padding-bottom tetap 40px. */
  .container {
    margin-left: var(--sidebar-w);
    margin-right: 0;
    max-width: none;
    padding-left: 16px;
    padding-right: 16px;
    transition: margin-left .18s ease;
  }

  /* Setelan disembunyikan sampai menu "Setelan" di sidebar dipilih --
     saat aktif, kontennya muncul di layar utama (bukan modal/overlay). */
  body:not(.view-settings) #setelanModal { display: none !important; }

  body.view-settings .container { display: none; }
  body.view-settings #setelanModal {
    display: block;
    position: static;
    width: auto;
    max-width: none;
    height: auto;
    margin: 0 0 0 var(--sidebar-w);
    transition: margin-left .18s ease;
    background: none;
    border: none;
    z-index: auto;
    /* [SAMAKAN JARAK SIDEBAR] padding-left disamakan dengan .container
       (16px, lihat aturan @media min-width:1024px di atas) supaya jarak
       konten ke sidebar konsisten antara Dashboard/tampilan utama dan
       menu full-page lain (Setelan, Laporan, Anggaran, dst). Sebelumnya
       32px di sini vs 16px di .container bikin menu ini terasa lebih
       menjorok ke kanan dibanding Dashboard. */
    padding: var(--space-28) var(--space-16) var(--space-40);
  }
  body.view-settings #setelanModal .setelan-modal-content {
    width: 100%; height: auto;
    max-width: none !important; max-height: none !important;
    min-height: 0;
    border: 1.5px solid var(--rule);
    border-radius: var(--radius-sm);
    background: var(--paper);
    padding: var(--space-24);
    display: block;
  }
  body.view-settings #setelanModal .modal-close { display: none; }
  body.view-settings #setelanModal .setelan-tab-content { max-height: none; }
}

/* [ANTI-FLASH RESTORE] Dashboard disembunyikan (visibility, bukan display,
   supaya layout tidak loncat) selama menu full-page terakhir sedang dipulihkan
   setelah F5. Class dipasang skrip di <head> index.html & dilepas
   window.restoreLastFullviewModal (js/utils.js). Lock screen/login gate bukan
   anak .container jadi tetap tampil normal. */
html.sk-restoring-view .container { visibility: hidden; }
/* [LOADER HALAMAN] Penanda "Memuat halaman..." selama Dashboard disembunyikan
   (jangan layar kosong, supaya tidak terlihat seperti app hang). Markup:
   #skPageLoader di index.html (tepat setelah <body>). Tampil hanya saat
   <html> membawa class sk-restoring-view (pemulihan menu setelah F5) atau
   sk-gate-pending (menunggu keputusan layar login) -- class itu dipasang
   js/boot-early.js & dilepas js/utils.js / js/app.js, jadi loader otomatis
   hilang bersama penyembunyi Dashboard. Gaya: flat, outline tipis, sudut
   membulat seperti kartu lain -- logo, nama app, teks status, dan bar
   progres indeterminate (bar tipis di tepi atas + bar kecil di kartu).
   Area = sisi kanan sidebar di desktop; z-index di bawah lock screen/login
   gate (9999). Kartu baru muncul setelah jeda singkat (.15 dtk) supaya tidak
   berkedip pada pemuatan yang cepat. Warna lewat token -> ikut tema gelap. */
.sk-page-loader { display: none; }
html.sk-restoring-view .sk-page-loader,
html.sk-gate-pending .sk-page-loader {
  display: flex; align-items: center; justify-content: center;
  position: fixed; z-index: 1; pointer-events: none;
  top: 0; right: 0; bottom: 0; left: var(--sidebar-w, 0px);
}
html.sk-gate-pending .sk-page-loader { left: 0; }
.sk-page-loader-bar {
  position: absolute; top: 0; left: 0; right: 0; height: 3px; overflow: hidden;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.sk-page-loader-bar::after,
.sk-page-loader-fill {
  content: ""; display: block; height: 100%; width: 40%; border-radius: var(--radius-pill);
  background: var(--accent);
  animation: skLoaderSlide 1.25s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
.sk-page-loader-card {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-6);
  min-width: 190px; padding: var(--space-24) var(--space-32);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius-lg);
  animation: skLoaderIn .25s ease .15s both;
}
.sk-page-loader-logo {
  width: 44px; height: 44px; border-radius: var(--radius); margin-bottom: var(--space-4);
  animation: skLoaderPulse 1.6s ease-in-out infinite;
}
.sk-page-loader-title { font-family: var(--font-display); font-size: var(--text-md); font-weight: 600; letter-spacing: -0.01em; color: var(--ink); }
.sk-page-loader-sub { font-size: var(--text-xs); color: var(--ink-muted); }
.sk-page-loader-track {
  width: 120px; height: 3px; margin-top: var(--space-10); overflow: hidden;
  border-radius: var(--radius-pill); background: var(--rule);
}
@keyframes skLoaderSlide { from { transform: translateX(-100%); } to { transform: translateX(300%); } }
@keyframes skLoaderIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes skLoaderPulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(.94); opacity: .75; } }
@media (prefers-reduced-motion: reduce) {
  .sk-page-loader-bar::after, .sk-page-loader-fill, .sk-page-loader-logo, .sk-page-loader-card { animation: none; }
  .sk-page-loader-bar::after, .sk-page-loader-fill { width: 100%; opacity: .55; }
}

/* ── Menu sidebar full-page: Laporan, Anggaran, Pengingat Pembayaran,
   Buku Kas, Akun, Cadangan Data (pola sama seperti Setelan di atas, tapi
   digeneralisasi lewat class .fullview-modal + body.view-fullpage supaya
   tidak perlu selector per-ID). Lihat CLAUDE.md bagian "Sidebar/nav". ── */
@media (max-width: 1023px) {
  body.view-fullpage .container { display: none; }
  body.view-fullpage .fullview-modal.show {
    display: flex;
    position: fixed;
    inset: 0;
    background: var(--paper);
    z-index: 2000;
    padding: 0;
    align-items: stretch;
    justify-content: stretch;
  }
  body.view-fullpage .fullview-modal.show .modal-content {
    width: 100%;
    max-width: none !important;
    height: 100%;
    max-height: none;
    margin: 0;
    border: none;
    border-radius: 0;
    box-shadow: none;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: 0 var(--space-12) var(--space-12);
  }
  body.view-fullpage .fullview-modal.show .modal-header {
    background: var(--paper);
    padding: var(--space-16) 0 var(--space-12);
    margin: 0 0 var(--space-8);
    border-bottom: 1px solid var(--rule);
    justify-content: flex-start;
    gap: var(--space-10);
  }
  body.view-fullpage .fullview-modal.show .modal-header .modal-close {
    order: -1;
    position: static;
  }
  /* [SinarMedia] Header modal punya 1 tombol aksi ekstra di samping judul
     & tombol menu (mis. "Kembali ke Daftar Proyek", "+ Proyek Baru"). Di hp
     & tablet urutannya disusun ulang jadi: hamburger paling kiri, lalu
     judul, lalu tombol aksi mepet kanan -- bukan berdesakan di antara
     judul & tombol seperti bawaan flex-start. */
  body.view-fullpage .fullview-modal.show .modal-header .modal-header-action {
    margin-left: auto;
  }

  /* [FIX] Modal biasa (bukan fullview) yang dibuka SAAT halaman fullview
     sedang aktif -- mis. "Ubah Barang" (editShoppingListItemModal) yang
     dibuka dari atas Belanja Bulanan, atau modal lain yang dibuka dari
     atas Anggaran/Buku Kas/dst -- sebelumnya z-index bawaan .modal (1000)
     KALAH dari .fullview-modal.show (2000) di layar hp, sehingga modal
     itu render TIDAK TERLIHAT & TIDAK BISA DISENTUH di belakang halaman
     fullview (yang latarnya solid, bukan transparan). Efeknya: tombol
     Ubah/Tambah terlihat merespons (modal "show" ditambahkan ke DOM),
     tapi user tidak melihat apa-apa dan tidak bisa berinteraksi sama
     sekali -- padahal di desktop tidak bermasalah karena di sana
     .fullview-modal.show pakai position:static & z-index:auto (bukan
     overlay penuh layar), lihat media query min-width:1024px di bawah.
     Beberapa modal lain (mis. #manualModal, #customConfirmModal,
     #conflictModal, #accountUnlockModal) sudah dipatch manual lewat
     inline style="z-index:...", tapi modal seperti editShoppingListItemModal
     terlewat. Rule generik ini menaikkan SEMUA modal non-fullview yang
     terbuka di atas halaman fullview supaya konsisten tampil paling atas,
     tanpa perlu inline style satu-satu per modal. */
  body.view-fullpage .modal.show:not(.fullview-modal) {
    z-index: 2100;
  }
}

@media (min-width: 1024px) {
  body.view-fullpage .container { display: none; }
  body.view-fullpage .fullview-modal.show {
    display: block;
    position: static;
    width: auto;
    max-width: none;
    height: auto;
    margin: 0 0 0 var(--sidebar-w);
    transition: margin-left .18s ease;
    background: none;
    border: none;
    z-index: auto;
    /* [SAMAKAN JARAK SIDEBAR] padding-left disamakan dengan .container
       (16px) -- lihat catatan sama di aturan #setelanModal di atas. */
    padding: var(--space-28) var(--space-16) var(--space-40);
  }
  body.view-fullpage .fullview-modal.show .modal-content {
    width: 100%; height: auto;
    max-width: none !important; max-height: none !important;
    min-height: 0;
    border: 1.5px solid var(--rule);
    border-radius: var(--radius-sm);
    background: var(--paper);
    padding: var(--space-24);
    display: block;
  }
  body.view-fullpage .fullview-modal.show .modal-close { display: none; }
}

/* ── Sidebar Desktop: Minimize/collapse (icon-only) ──
   Dipicu dengan MENGKLIK SIDEBAR itu sendiri (area yang bukan tombol/link;
   listener di js/app.js, window.toggleSidebarCollapse) -- tidak ada tombol
   toggle terpisah lagi. State diterapkan lewat class body.sidebar-collapsed
   + variabel --sidebar-w di atas. Label teks, label grup, dan footer text
   disembunyikan; ikon dipusatkan; tooltip native (atribut title di tiap
   button, lihat index.html) menggantikan label saat diciutkan. */
@media (min-width: 1024px) {
  /* Kursor menunjukkan arah aksi klik di area kosong: panah kiri = klik
     untuk menciutkan, panah kanan (saat sudah ciut) = klik untuk
     memperluas. Tombol nav tetap cursor:pointer (aturan .app-nav-item).
     user-select:none supaya klik ganda di label/brand tidak menyorot teks. */
  #appSidebar {
    cursor: w-resize;
    -webkit-user-select: none;
    user-select: none;
  }
  body.sidebar-collapsed #appSidebar { cursor: e-resize; }
  .app-sidebar-brand:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
    border-radius: var(--radius-sm);
  }

  body.sidebar-collapsed #appSidebar {
    padding-left: 10px;
    padding-right: 10px;
  }
  body.sidebar-collapsed .app-nav-group-label {
    /* [FIX SIDEBAR HOVER-EXPAND JANK] display:none di sini SEBELUMNYA
       bentrok dengan transisi max-height/opacity yang ditambahkan di
       aturan :hover di bawah (elemen display:none tidak bisa
       dianimasikan sama sekali -- browser cuma bisa "meloncat" antara
       none dan block, bukan transisi berangsur). Sekarang dibiarkan
       tetap 'in flow' tapi mengecil ke max-height:0 (efek visual yang
       sama persis dengan display:none saat TIDAK di-hover), supaya versi
       hover di bawah bisa animasikan tinggi & opacity-nya secara mulus. */
    max-height: 0;
    opacity: 0;
    padding-top: 0;
    padding-bottom: 0;
    overflow: hidden;
    transition: max-height .2s cubic-bezier(0.4, 0, 0.2, 1), opacity .15s ease .05s, padding .2s cubic-bezier(0.4, 0, 0.2, 1);
  }
  /* [SIDEBAR-BOOK] Mode icon-only: nama buku penuh diganti inisialnya saja,
     dipusatkan seperti ikon menu lainnya. */
  body.sidebar-collapsed .app-sidebar-brand {
    padding-left: 0;
    padding-right: 0;
    text-align: center;
  }
  body.sidebar-collapsed .app-sidebar-brand-full {
    display: none;
  }
  body.sidebar-collapsed .app-sidebar-brand-initial {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    margin: 0 auto;
    border-radius: var(--radius-sm);
    background: var(--topbar-item-active-bg);
    color: var(--topbar-item-active-color);
    font-size: var(--text-xs);
    font-weight: 700;
  }
  body.sidebar-collapsed .app-nav-item {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
    position: relative;
  }
  body.sidebar-collapsed .app-nav-item span:not(.app-nav-badge) {
    display: none;
  }
  /* Badge notifikasi (mis. pengingat pembayaran) jadi titik kecil di
     pojok ikon saat diciutkan, bukan pil berisi angka -- angkanya
     disembunyikan (font-size:0) tapi textContent tetap ada untuk
     screen reader. */
  body.sidebar-collapsed .app-nav-badge {
    position: absolute;
    top: 2px;
    right: 10px;
    min-width: 8px;
    height: 8px;
    padding: 0;
    font-size: 0;
    line-height: 0;
    border-radius: 50%;
  }

  /* ---- Hover-to-expand (samain dengan dashboard-main): saat sidebar lagi
     ciut, arahkan mouse ke atasnya supaya melebar SEMENTARA sebagai overlay
     (posisinya sudah position:fixed dari awal, jadi tidak mendorong
     .container/konten di kanan) lalu otomatis menciut lagi begitu mouse
     keluar. Murni CSS :hover, tanpa perlu ubah js/app.js atau state
     body.sidebar-collapsed itu sendiri -- yang berubah cuma tampilan
     sidebar-nya doang selama di-hover.
     [HOVER-LOCK] Begitu sidebar DICIUTKAN lewat klik sementara mouse masih
     di atasnya, body.sidebar-hover-lock (js/app.js) menonaktifkan efek
     hover ini sampai mouse keluar dari sidebar -- kalau tidak, sidebar
     tetap tampak lebar dan klik seolah tidak berefek. ---- */
  body.sidebar-collapsed #appSidebar {
    transition: width .2s cubic-bezier(0.4, 0, 0.2, 1), padding .2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow .2s ease;
    /* [FIX SIDEBAR HOVER-EXPAND JANK] Beritahu browser lebih awal bahwa
       width akan berubah, supaya browser bisa siapkan layer/optimasinya
       sebelum animasi mulai (bukan baru dihitung di frame pertama
       transisi) -- mengurangi "hentakan" di awal hover. */
    will-change: width;
  }
  body.sidebar-collapsed:not(.sidebar-hover-lock) #appSidebar:hover {
    width: 236px;
    padding-left: 14px;
    padding-right: 14px;
    z-index: 9600; /* di atas UI app lain (maks 3002) saat melebar sementara sebagai overlay, tetap di bawah layar kunci (9999) */
  }
  /* [FIX SIDEBAR HOVER-EXPAND JANK] Sebelumnya label grup ("MENU UTAMA"
     dkk) muncul lewat display:none -> block SEKETIKA (tidak bisa
     dianimasikan) begitu hover mulai -- padahal transisi width sidebar
     masih berjalan .2s. Karena display:block langsung menambah tinggi
     baris itu SAAT ITU JUGA (bukan berangsur), semua item nav di
     bawahnya ikut ter-dorong turun secara MENDADAK di awal hover, baru
     kemudian sidebar-nya sendiri baru mulai melebar -- dua gerakan yang
     tidak sinkron ini yang terlihat "patah-patah, geser dari atas ke
     bawah". Transisi max-height+opacity di atas (durasi & easing SAMA
     PERSIS dengan transisi width sidebar) menggantikan itu, supaya label
     muncul berangsur bareng sidebar melebar, bukan meloncat duluan. */
  body.sidebar-collapsed:not(.sidebar-hover-lock) #appSidebar:hover .app-nav-group-label {
    display: block;
    max-height: 26px;
    opacity: 1;
    padding-top: 8px;
    padding-bottom: 2px;
  }
  body.sidebar-collapsed:not(.sidebar-hover-lock) #appSidebar:hover .app-sidebar-brand {
    padding-left: 10px;
    padding-right: 10px;
    text-align: left;
  }
  body.sidebar-collapsed:not(.sidebar-hover-lock) #appSidebar:hover .app-sidebar-brand-full {
    display: block;
  }
  body.sidebar-collapsed:not(.sidebar-hover-lock) #appSidebar:hover .app-sidebar-brand-initial {
    display: none;
  }
  body.sidebar-collapsed:not(.sidebar-hover-lock) #appSidebar:hover .app-nav-item {
    justify-content: flex-start;
    padding-left: 13px;
    padding-right: 13px;
  }
  body.sidebar-collapsed:not(.sidebar-hover-lock) #appSidebar:hover .app-nav-item span:not(.app-nav-badge) {
    display: inline;
  }
  body.sidebar-collapsed:not(.sidebar-hover-lock) #appSidebar:hover .app-nav-badge {
    position: static;
    margin-left: auto;
    min-width: 0;
    height: auto;
    padding: var(--space-1) var(--space-6);
    font-size: var(--text-2xs);
    line-height: 1.5;
    border-radius: var(--radius-pill);
  }
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-20);
  padding-bottom: 14px;
  border-bottom: 1.5px solid var(--rule);
}
.modal-header h3 {
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--ink);
}

.modal-close {
  background: none;
  border: none;
  font-size: var(--text-2xl);
  cursor: pointer;
  padding: var(--space-2) var(--space-6);
  border-radius: var(--radius-pill);
  color: var(--ink-faint);
  transition: color 0.15s, background 0.15s;
  line-height: 1;
}
.modal-close:hover { color: var(--danger); background: var(--danger-lt); }
body.view-fullpage .fullview-modal.show .modal-close:hover,
body.view-settings #setelanModal .modal-close:hover {
  color: var(--ink);
  background: var(--paper-warm);
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-10);
  margin-top: var(--space-24);
  padding-top: 14px;
  border-top: 1px solid var(--rule);
}

/* ── Tanya Sinarkeu (Modal Chat AI) ──────────────────────────────────────
   Dulu: kotak riwayat pendek (max-height:340px) yang duduk DI DALAM
   modal-content yang scroll sendiri, chip contoh pertanyaan nempel
   permanen di atas kotak riwayat, dan tombol kirim teks biasa -- terasa
   spt formulir "kotak saran", bukan chatbot. Dirombak jadi layout chat
   yang lazim: header ada identitas asisten, badan percakapan mengisi
   SEMUA ruang tersisa & jadi satu-satunya area yang scroll (bukan
   modal-content-nya lagi), input+tombol kirim nempel di bawah (sticky),
   avatar di tiap bubble, indikator "mengetik" animasi, dan layar sambutan
   dgn chip saran pertanyaan yang tampil HANYA saat riwayat masih kosong
   (bukan makan tempat terus-menerus). Full-screen di layar sempit spt
   app chat pada umumnya. */
.ai-chat-modal-content {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 560px;
  height: 78vh;
  max-height: 680px;
  padding: 0;
  overflow: hidden; /* area scroll ada di .ai-chat-body, bukan di sini */
}
.ai-chat-header {
  flex: 0 0 auto;
  margin-bottom: 0;
  padding: var(--space-16) var(--space-18);
  gap: var(--space-10);
}
.ai-chat-header-id { display: flex; align-items: center; gap: var(--space-10); min-width: 0; }
.ai-chat-header-avatar {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px;
  border-radius: var(--radius-pill);
  background: var(--chat-user);
  color: var(--ink-inv);
}
.ai-chat-header-text { min-width: 0; }
.ai-chat-header-text h3 { line-height: 1.25; }
.ai-chat-header-sub {
  display: block;
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ai-chat-header-actions { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-4); }
.ai-chat-icon-btn {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  background: none; border: none; border-radius: var(--radius-pill);
  color: var(--ink-faint); cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.ai-chat-icon-btn:hover { color: var(--danger); background: var(--danger-lt); }

.ai-chat-warning {
  flex: 0 0 auto;
  background: var(--danger-lt);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: var(--space-10) var(--space-18);
  font-size: var(--text-xs);
  color: var(--danger);
}
.ai-chat-warning a { color: var(--danger); font-weight: 600; text-decoration: underline; }

.ai-chat-body {
  flex: 1 1 auto;
  min-height: 0; /* wajib supaya flex child bisa scroll, bukan meluas terus */
  overflow-y: auto;
  padding: var(--space-16) var(--space-16);
  background: var(--paper-warm);
  display: flex;
  flex-direction: column;
  gap: var(--space-10);
}

/* -- Layar sambutan (riwayat kosong) -- */
.ai-chat-welcome {
  margin: auto 0;
  text-align: center;
  padding: var(--space-20) var(--space-10);
}
.ai-chat-welcome-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  border-radius: var(--radius-pill);
  background: var(--chat-user);
  color: var(--ink-inv);
  margin-bottom: var(--space-12);
}
.ai-chat-welcome-title { font-size: var(--text-md); font-weight: 700; color: var(--ink); margin-bottom: var(--space-6); }
.ai-chat-welcome-sub {
  font-size: var(--text-xs); color: var(--ink-faint); line-height: 1.6;
  max-width: 340px; margin: 0 auto var(--space-16);
}
.ai-chat-suggestions { display: flex; flex-wrap: wrap; gap: var(--space-6); justify-content: center; }
.ai-chat-chip {
  font-size: var(--text-2xs);
  padding: var(--space-6) var(--space-12);
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--rule);
  background: var(--paper);
  color: var(--ink-muted);
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.ai-chat-chip:hover { border-color: var(--chat-user); color: var(--chat-user); background: var(--accent-lt); }

/* -- Baris & bubble percakapan -- */
@keyframes skChatBubbleIn {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.ai-chat-row {
  display: flex;
  align-items: flex-end;
  gap: var(--space-8);
  animation: skChatBubbleIn 0.18s ease;
}
.ai-chat-row-user { justify-content: flex-end; }
.ai-chat-row-assistant { justify-content: flex-start; }
.ai-chat-avatar {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px;
  border-radius: var(--radius-pill);
}
.ai-chat-avatar-bot { background: var(--chat-user); color: var(--ink-inv); }
.ai-chat-avatar-bot.ai-chat-avatar-error { background: var(--danger); }
.ai-chat-avatar-user { background: var(--paper); border: 1.5px solid var(--rule); color: var(--ink-muted); }
.ai-chat-bubble {
  max-width: 78%;
  padding: var(--space-9) var(--space-12);
  font-size: var(--text-sm);
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-word;
}
.ai-chat-bubble-user {
  background: var(--chat-user);
  color: var(--ink-inv);
  border-radius: var(--radius-lg) var(--radius-lg) 2px var(--radius-lg);
}
.ai-chat-bubble-assistant {
  background: var(--paper);
  border: 1px solid var(--rule);
  color: var(--ink);
  border-radius: var(--radius-lg) var(--radius-lg) var(--radius-lg) 2px;
}
.ai-chat-bubble-error {
  background: var(--danger-lt);
  border: 1px solid var(--danger);
  color: var(--danger);
  border-radius: var(--radius-lg) var(--radius-lg) var(--radius-lg) 2px;
}

/* -- Indikator "sedang mengetik" (titik tiga animasi, ganti teks statis) -- */
.ai-chat-bubble-typing { display: flex; align-items: center; gap: 4px; padding: var(--space-11) var(--space-14); }
.ai-chat-typing-dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--ink-faint);
  animation: skChatTyping 1.1s infinite ease-in-out;
}
.ai-chat-typing-dot:nth-child(2) { animation-delay: 0.15s; }
.ai-chat-typing-dot:nth-child(3) { animation-delay: 0.3s; }
@keyframes skChatTyping {
  0%, 60%, 100% { opacity: 0.35; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-2.5px); }
}

/* -- Input bar (sticky di bawah, bukan bagian yang ikut scroll) -- */
.ai-chat-input-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-8);
  padding: var(--space-12) var(--space-16);
  border-top: 1.5px solid var(--rule);
  background: var(--paper);
}
.ai-chat-input {
  flex: 1 1 auto;
  min-width: 0;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-pill);
  padding: var(--space-10) var(--space-16);
  font-size: var(--text-sm);
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--paper-warm);
  transition: border-color 0.15s;
}
.ai-chat-input:focus { outline: none; border-color: var(--chat-user); background: var(--paper); }
.ai-chat-send-btn {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  width: 38px; height: 38px;
  border-radius: var(--radius-pill);
  border: none;
  background: var(--chat-user);
  color: var(--ink-inv);
  cursor: pointer;
  transition: opacity 0.15s, transform 0.1s;
}
.ai-chat-send-btn:hover { opacity: 0.9; }
.ai-chat-send-btn:active { transform: scale(0.94); }
.ai-chat-send-btn:disabled { opacity: 0.5; cursor: default; }
.ai-chat-footnote {
  flex: 0 0 auto;
  text-align: center;
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  padding: 0 var(--space-16) var(--space-12);
  background: var(--paper);
}

/* Layar sempit: chat penuh 1 layar spt app chat pada umumnya, drpd kotak
   mengambang kecil di tengah yang bikin area percakapan makin sempit. */
@media (max-width: 640px) {
  .ai-chat-modal.show { padding: 0; }
  .ai-chat-modal-content {
    height: 100vh;
    height: 100dvh;
    max-height: 100vh;
    max-height: 100dvh;
    max-width: 100%;
    border-radius: 0;
    border: none;
  }
}

/* ── Forms ── */
.form-group { margin-bottom: var(--space-14); }

.form-group label {
  display: block;
  font-size: var(--text-2xs);
  font-weight: 500;
  color: var(--ink-faint);
  margin-bottom: var(--space-5);
  text-transform: none;
  letter-spacing: 0.07em;
}

.form-control {
  width: 100%;
  padding: var(--space-10) var(--space-13);
  font-size: var(--text-sm);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  font-family: inherit;
  transition: border-color 0.15s, box-shadow 0.15s;
  background: var(--paper);
  color: var(--ink);
}
.form-control:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-lt);
}

/* ── Form field "utama" (dipertegas) ──
   Dipakai untuk field inti yang wajib/paling penting di sebuah form (mis.
   3 field pertama form Proyek SinarMedia: Nama Proyek, Jumlah Cetak,
   Harga Jual/Eksemplar) supaya lebih menonjol dibanding field opsional
   lain di bawahnya (Spek Majalah, dll). Cukup tambah class
   "form-group-emphasis" di .form-group yang ingin ditegaskan. */
.form-group-emphasis label {
  color: var(--ink);
  font-weight: 700;
  font-size: var(--text-xs);
}
.form-group-emphasis .form-control {
  border-width: 2px;
  border-color: var(--ink-faint);
  font-weight: 600;
  font-size: var(--text-base);
}
.form-group-emphasis .form-control:focus {
  border-color: var(--accent);
}
[data-theme="dark"] .form-group-emphasis .form-control {
  border-color: var(--ink-faint);
}

/* ── Styled Select Dropdown ── */
select.form-control {
  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='%236B6B6B' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 36px;
  cursor: pointer;
}
select.form-control:focus {
  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='%230D0D0D' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
select.form-control option {
  background: var(--paper);
  color: var(--ink);
  padding: var(--space-8) var(--space-12);
  font-size: var(--text-sm);
}
select.form-control option:hover,
select.form-control option:focus,
select.form-control option:checked {
  background: var(--accent-lt);
  color: var(--accent);
}
select.form-control option[value=""] {
  color: var(--ink-faint);
}

.radio-group { display: flex; gap: var(--space-20); margin-top: var(--space-6); }
.radio-label {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  font-size: var(--text-sm);
  cursor: pointer;
  color: var(--ink-muted);
}

/* ── [REDESIGN] Modal Tambah Transaksi (#addModal) ──
   Kelas berprefix sk-addtx-* dipakai KHUSUS di form #addForm (index.html) --
   #editForm (Ubah Transaksi) sengaja belum disentuh, jadi kelas ini tidak
   memengaruhi tampilan modal lain mana pun. Tujuan: toggle Jenis lebih besar
   & jelas warnanya (hijau/merah), Jumlah jadi elemen paling menonjol (font
   besar, auto-fokus lewat js/utils.js openModal), dan Lampiran Nota terasa
   opsional (dashed, bukan input file polos). */
.sk-vh {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

.sk-addtx-type { display: flex; gap: var(--space-8); margin-top: var(--space-6); }
.sk-addtx-type-opt {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  padding: var(--space-11) var(--space-10);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-muted);
  background: var(--paper);
  transition: border-color .15s, background .15s, color .15s;
}
.sk-addtx-type-opt:hover { border-color: var(--ink-faint); }
.sk-addtx-type-opt.sk-addtx-income:has(input:checked) {
  border-color: var(--success);
  background: var(--success-lt);
  color: var(--success);
}
.sk-addtx-type-opt.sk-addtx-expense:has(input:checked) {
  border-color: var(--danger);
  background: var(--danger-lt);
  color: var(--danger);
}

.sk-addtx-amount-group { margin-top: var(--space-16); }
.sk-addtx-amount-wrap {
  display: flex;
  align-items: center;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: 0 var(--space-14);
  background: var(--paper);
  transition: border-color .15s, box-shadow .15s;
}
.sk-addtx-amount-wrap:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-lt);
}
.sk-addtx-amount-prefix {
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--ink-faint);
  margin-right: var(--space-8);
}
.sk-addtx-amount-wrap .form-control {
  border: none !important;
  box-shadow: none !important;
  padding: var(--space-13) 0 !important;
  font-size: var(--text-2xl);
  font-weight: 700;
}
.sk-addtx-amount-wrap .form-control:focus { outline: none; }

.sk-addtx-suggest-chip {
  display: none;
  font-size: var(--text-xs);
  color: var(--purple);
  background: var(--accent-lt);
  border-radius: var(--radius-sm);
  padding: var(--space-7) var(--space-10);
  margin: -6px 0 var(--space-14);
}

.sk-addtx-optional { font-weight: 400; color: var(--ink-faint); text-transform: none; letter-spacing: 0; }

.sk-addtx-attach {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  border: 1.5px dashed var(--rule);
  border-radius: var(--radius);
  padding: var(--space-10) var(--space-12);
  cursor: pointer;
  color: var(--ink-faint);
  font-size: var(--text-xs);
  font-weight: 500;
}
.sk-addtx-attach:hover { border-color: var(--accent); color: var(--accent); }

.sk-addtx-footer { align-items: center; }
.sk-addtx-footer .btn-secondary { flex: 0 0 auto; }
.sk-addtx-footer .btn-primary { flex: 1 1 auto; padding-top: var(--space-11); padding-bottom: var(--space-11); font-size: var(--text-base); }

/* ── Native Radio & Checkbox (custom flat style) ── */
input[type="radio"],
input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  min-width: 16px;
  border: 1.5px solid var(--rule);
  background: var(--paper);
  cursor: pointer;
  position: relative;
  margin: 0;
  vertical-align: middle;
  transition: border-color 0.15s, background 0.15s;
  flex-shrink: 0;
}
input[type="radio"] {
  border-radius: 50%;
}
input[type="checkbox"] {
  border-radius: var(--radius-sm); /* [CONSISTENT-UI] dulu 3px hardcode */
}
input[type="radio"]:hover,
input[type="checkbox"]:hover {
  border-color: var(--ink-faint);
}
input[type="radio"]:checked,
input[type="checkbox"]:checked {
  border-color: var(--ink);
  background: var(--ink);
}
input[type="radio"]:checked::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--paper);
  transform: translate(-50%, -50%);
}
input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  top: 1px; left: 4px;
  width: 5px; height: 9px;
  border: solid var(--paper);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
input[type="radio"]:focus-visible,
input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── Native Date Input ── */
input[type="date"] {
  padding: var(--space-9) var(--space-12);
  font-size: var(--text-sm);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  font-family: inherit;
  background: var(--paper);
  color: var(--ink);
  transition: border-color 0.15s;
  cursor: pointer;
}
input[type="date"]:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-lt); }
input[type="date"]::-webkit-calendar-picker-indicator {
  cursor: pointer;
  opacity: .6;
  transition: opacity 0.15s;
}
input[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* ── Native File Input ── */
input[type="file"] {
  font-size: var(--text-xs);
  font-family: inherit;
  color: var(--ink-muted);
  cursor: pointer;
}
input[type="file"]::file-selector-button {
  padding: var(--space-7) var(--space-14);
  margin-right: var(--space-10);
  font-size: var(--text-xs);
  font-weight: 500;
  font-family: inherit;
  background: var(--ink);
  color: var(--paper);
  border: 1px solid var(--ink);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.15s;
}
input[type="file"]::file-selector-button:hover { background: var(--ink-muted); }

/* ── Data Management Panel ── */
.data-management-panel {
  background: var(--paper-warm);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-14) var(--space-16);
  margin: var(--space-14) 0;
}

.panel-title {
  font-size: var(--text-2xs);
  font-weight: 500;
  text-transform: none;
  margin-bottom: var(--space-10);
  letter-spacing: 0.08em;
  color: var(--ink-faint);
}

.panel-actions-row {
  display: flex;
  gap: var(--space-8);
  flex-wrap: wrap;
}

/* ===================================================
   MODAL SETELAN — helper class theme-aware
   (pengganti inline style agar ikut dark mode)
=================================================== */

.setelan-desc {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  margin-bottom: var(--space-10);
  line-height: 1.6;
}
.setelan-desc--tight { font-size: var(--text-xs); color: var(--ink-muted); line-height: 1.6; }
.setelan-hint        { font-size: var(--text-2xs); color: var(--ink-faint); margin-top: var(--space-4); }
.setelan-status-text { font-size: var(--text-xs);  color: var(--ink-faint); margin-top: var(--space-8); }
.setelan-status-row  { font-size: var(--text-xs);  min-height: 16px; }
.setelan-status-row--margin { font-size: var(--text-xs); min-height: 16px; margin-bottom: var(--space-8); }
.setelan-test-status  { font-size: var(--text-xs); margin-bottom: var(--space-10); min-height: 18px; }

.setelan-divider { border-top: 1px dashed var(--rule); margin: var(--space-14) 0; }

/* Blok penjelasan yang bisa dibuka/tutup (default tertutup) —
   dipakai untuk menyembunyikan teks panduan/hint yang panjang
   supaya tampilan Setelan lebih ringkas. */
.setelan-collapse {
  margin: var(--space-8) 0 var(--space-14);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper-warm);
}
.setelan-collapse summary {
  list-style: none;
  cursor: pointer;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--ink-muted);
  padding: var(--space-8) var(--space-10);
  display: flex;
  align-items: center;
  gap: var(--space-6);
  user-select: none;
}
.setelan-collapse summary::-webkit-details-marker { display: none; }
.setelan-collapse summary::before {
  /* Chevron Lucide (bukan karakter unicode) lewat mask, supaya ikut warna teks. */
  content: '';
  flex-shrink: 0;
  width: 1.4em; height: 1.4em;
  font-size: var(--text-2xs);
  background-color: var(--ink-faint);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform .15s ease;
}
.setelan-collapse[open] summary::before { transform: rotate(90deg); }
.setelan-collapse summary:hover { color: var(--ink); }
.setelan-collapse-body {
  font-size: var(--text-xs);
  line-height: 1.8;
  color: var(--ink-muted);
  padding: 0 var(--space-10) var(--space-12);
}

/* Judul tiap tab — warna kategori, otomatis ikut tema */
.setelan-title          { color: var(--ink); display: flex; align-items: center; gap: var(--space-8); }
.setelan-title--purple  { color: var(--purple); display: flex; align-items: center; gap: var(--space-8); }
.setelan-title--amber   { color: var(--warning); display: flex; align-items: center; gap: var(--space-8); }
.setelan-title--green   { color: var(--success); }
.setelan-title--blue    { color: var(--accent); display: flex; align-items: center; gap: var(--space-8); }
.setelan-title--red     { color: var(--danger); }

/* Badge kecil di sebelah judul tab */
.setelan-badge { font-size: var(--text-2xs); font-weight: 600; padding: var(--space-2) var(--space-8); border-radius: var(--radius-sm); }
.setelan-badge--neutral { background: var(--rule); color: var(--ink-muted); }
.setelan-badge--success { background: var(--success-lt); color: var(--success); }
.setelan-badge--warning { background: var(--warning-lt); color: var(--warning); }

/* Teks preview/hasil hitung kecil di bawah input */
.setelan-preview { font-size: var(--text-xs); margin-top: var(--space-5); min-height: 16px; }
.setelan-preview--amber { font-size: var(--text-xs); color: var(--warning); margin-top: var(--space-5); min-height: 16px; }
.setelan-preview--green { font-size: var(--text-xs); color: var(--success); margin-top: var(--space-5); min-height: 16px; }

/* Label kecil tebal (di atas input device name dll) */
.setelan-label-strong { font-size: var(--text-xs); font-weight: 600; color: var(--ink); margin-bottom: var(--space-6); display: block; }
.setelan-info-row     { font-size: var(--text-xs); font-weight: 700; color: var(--ink); margin-bottom: var(--space-10); display: flex; align-items: center; gap: var(--space-8); }

/* Baris flex umum di dalam tab setelan */
.setelan-row       { display: flex; gap: var(--space-8); }
.setelan-row--wrap { display: flex; gap: var(--space-8); flex-wrap: wrap; }
.setelan-row--center { display: flex; gap: var(--space-8); align-items: center; }

/* Baris tombol aksi di tiap panel Setelan (Tes/Hapus/Simpan, Migrasi,
   dll) -- disatukan lewat class ini (dulu tiap panel pakai inline style
   flex:1/flex:2 sendiri-sendiri, hasilnya beda-beda rasio & rapat di hp).
   Sejajar di desktop, ditumpuk penuh-lebar di layar sempit lewat media
   query di bawah supaya seragam antar-panel dan tombol tidak berdesakan. */
.setelan-actions-row { display: flex; gap: var(--space-8); flex-wrap: wrap; }
.setelan-sheets-row   { display: flex; gap: var(--space-8); flex-wrap: wrap; align-items: flex-start; }
.setelan-device-row   { display: flex; gap: var(--space-8); align-items: center; }

@media (max-width: 480px) {
  /* Tombol "Kembali ke Daftar Proyek" di header modal SinarMedia --
     dipindah sejajar judul "Proyek Baru" di kanan (sebaris dgn tombol
     close). Di layar sempit teksnya disembunyikan supaya hanya ikon
     panah yang tampil, biar tidak berdesakan dgn judul + tombol close. */
  #smediaBackBtn { padding-left: var(--space-10); padding-right: var(--space-10); }
  #smediaBackBtn .sk-icon-lead { margin: 0; }
  #smediaBackBtn .smedia-back-label { display: none; }

  /* Sama untuk tombol "+ Proyek Baru" di header daftar SinarMedia --
     di layar sangat sempit (mis. hp 320-360px) tulisannya disembunyikan,
     sisa ikon "+" saja, supaya tidak berdesakan dgn judul "SinarMedia" +
     tombol menu di sebelahnya. */
  #sinarMediaAddBtn { padding-left: var(--space-10); padding-right: var(--space-10); }
  #sinarMediaAddBtn .smedia-add-label { display: none; }
}

/* ── SinarMedia: optimasi tampilan hape & tablet (mis. iPad 9) ──────────
   Sebelumnya #sinarMediaList SELALU 1 kolom (flex-column) apapun lebar
   layarnya -- di hp pas, tapi di tablet (iPad 9 portrait ~810px, landscape
   ~1080px) modal fullview-nya melebar penuh sehingga tiap kartu proyek jadi
   sangat lebar & banyak ruang kosong terbuang di kanan. auto-fill+minmax
   di bawah membuatnya OTOMATIS menyesuaikan: tetap 1 kolom kalau ruang
   sempit (hp), jadi 2+ kolom begitu ruang cukup (tablet/desktop) -- tanpa
   perlu breakpoint manual per perangkat. */
.smedia-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(272px, 1fr));
  gap: var(--space-8) var(--space-10);
  padding-right: 4px;
}
/* ── Grafik keuntungan per edisi (kartu di atas daftar proyek) ──
   Dirender window._smediaRenderProfitChart (js/sinarmedia.js). Hanya token
   var(--...); tanpa garis aksen di tepi kartu. Struktur plot: .smedia-chart-body
   = sumbu-Y (tetap) + area scroll berisi .smedia-chart-plot; di dalam plot ada
   .smedia-chart-gridwrap (garis bantu absolut) lalu kolom-kolom batang. */
.smedia-chart-slot { padding-right: 4px; }
.smedia-chart-slot:empty { display: none; }
.smedia-chart-card {
  flex-shrink: 0;
  margin-bottom: var(--space-10);
  padding: var(--space-14) var(--space-16);
  border: 1.5px solid var(--rule); border-radius: var(--radius-sm);
  background: var(--paper-warm);
  display: flex; flex-direction: column; gap: var(--space-12);
}
.smedia-chart-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8) var(--space-12); flex-wrap: wrap; }
.smedia-chart-headtext { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.smedia-chart-title { display: inline-flex; align-items: center; gap: var(--space-6); font-size: var(--text-base); font-weight: 700; color: var(--ink); }
.smedia-chart-sub { font-size: var(--text-2xs); color: var(--ink-faint); }
.smedia-chart-seg { display: inline-flex; gap: var(--space-4); }

.smedia-chart-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-8); }
.smedia-chart-stat {
  display: flex; flex-direction: column; gap: var(--space-2); min-width: 0;
  padding: var(--space-8) var(--space-12);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius-sm);
}
.smedia-chart-stat b { font-size: var(--text-md); font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.smedia-chart-stat b.is-profit { color: var(--success); }
.smedia-chart-stat b.is-loss { color: var(--danger); }
.smedia-chart-stat small { font-size: var(--text-2xs); color: var(--ink-muted); font-variant-numeric: tabular-nums; }

.smedia-chart-body { display: flex; align-items: flex-start; gap: var(--space-6); }
.smedia-chart-yaxis { position: relative; flex: 0 0 auto; width: 44px; }
.smedia-chart-ytick {
  position: absolute; right: 0; transform: translateY(-50%);
  font-size: var(--text-2xs); color: var(--ink-faint); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.smedia-chart-scroll { flex: 1 1 auto; min-width: 0; overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; padding-bottom: var(--space-2); }
.smedia-chart-plot { position: relative; display: flex; align-items: flex-start; justify-content: center; gap: var(--space-8); min-width: min-content; }
.smedia-chart-gridwrap { position: absolute; left: 0; right: 0; top: 0; pointer-events: none; }
.smedia-chart-grid { position: absolute; left: 0; right: 0; border-top: 1px dashed var(--rule); }
.smedia-chart-grid.is-zero { border-top: 1px solid var(--ink-faint); }
.smedia-chart-avg { position: absolute; left: 0; right: 0; border-top: 1.5px dashed var(--accent); }
.smedia-chart-avg span {
  position: absolute; right: 0; bottom: 2px;
  padding: 0 var(--space-6); font-size: var(--text-2xs); font-weight: 600; color: var(--accent);
  background: var(--paper-warm); border-radius: var(--radius-pill);
}

.smedia-chart-col {
  position: relative; z-index: 1; flex: 1 1 0; min-width: 60px; max-width: 150px;
  display: flex; flex-direction: column; border-radius: var(--radius-sm);
  transition: background .15s;
}
.smedia-chart-col:hover { background: color-mix(in srgb, var(--ink) 4%, transparent); }
.smedia-chart-up { display: flex; flex-direction: column; justify-content: flex-end; align-items: center; }
.smedia-chart-down { display: flex; flex-direction: column; justify-content: flex-start; align-items: center; }
.smedia-chart-bar {
  display: block; width: min(56%, 40px);
  background: linear-gradient(to top, color-mix(in srgb, var(--success) 70%, var(--paper)), var(--success));
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  transform-origin: bottom; animation: smChartGrow .55s cubic-bezier(.2,.8,.2,1) both;
}
.smedia-chart-bar.is-loss {
  background: linear-gradient(to bottom, color-mix(in srgb, var(--danger) 70%, var(--paper)), var(--danger));
  border-radius: 0 0 var(--radius-sm) var(--radius-sm); transform-origin: top;
}
.smedia-chart-bar.is-best { box-shadow: 0 0 0 2px color-mix(in srgb, var(--success) 28%, transparent); }
.smedia-chart-col:hover .smedia-chart-bar { filter: brightness(1.08); }
@keyframes smChartGrow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@media (prefers-reduced-motion: reduce) { .smedia-chart-bar { animation: none; } }
.smedia-chart-val { font-size: var(--text-2xs); font-weight: 700; line-height: 20px; color: var(--success); font-variant-numeric: tabular-nums; white-space: nowrap; }
.smedia-chart-val.is-loss { color: var(--danger); }
.smedia-chart-x { margin-top: var(--space-6); text-align: center; font-size: var(--text-2xs); font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.smedia-chart-dl { min-height: 20px; display: flex; justify-content: center; align-items: center; padding-bottom: var(--space-2); }
.smedia-chart-delta { padding: 0 var(--space-6); font-size: var(--text-2xs); font-weight: 600; line-height: 16px; border-radius: var(--radius-pill); white-space: nowrap; font-variant-numeric: tabular-nums; }
.smedia-chart-delta.is-up { color: var(--success); background: var(--success-lt); }
.smedia-chart-delta.is-down { color: var(--danger); background: var(--danger-lt); }
.smedia-chart-note { font-size: var(--text-2xs); color: var(--ink-faint); }
@media (max-width: 480px) {
  .smedia-chart-card { padding: var(--space-12); gap: var(--space-10); }
  .smedia-chart-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .smedia-chart-stat:last-child { grid-column: 1 / -1; }
  .smedia-chart-yaxis { width: 38px; }
  .smedia-chart-col { min-width: 56px; }
}

.smedia-list:empty,
.smedia-list > div:only-child {
  /* Kalau isinya cuma 1 elemen (mis. pesan "Belum ada proyek"), jangan
     ikut melebar jadi kartu grid -- biarkan selebar penuh & rata tengah
     seperti sebelumnya. */
  grid-column: 1 / -1;
}

/* [ROMBAK TOTAL KARTU, 22 Sep 2026 - iterasi ke-6] Permintaan eksplisit
   user: di desktop, MAKSIMAL 1 kolom -- kartu sekarang punya hero 2 kolom
   sendiri di dalamnya (Nilai Proyek & Deadline, lihat .smedia-card-hero di
   bawah), jadi ikut melebar jadi 2+ kartu berdampingan lagi (perilaku
   auto-fill di atas, disengaja untuk desain kartu iterasi sebelumnya)
   sekarang malah bikin terlalu ramai/sempit. Override auto-fill KHUSUS
   >=1024px (breakpoint desktop yang sama dipakai .smedia-card-spec di
   bawah) supaya tablet (iPad 9, dll di bawah 1024px) tetap dapat manfaat
   auto-fill seperti sebelumnya -- cuma desktop lebar yang dipaksa 1
   kolom penuh. */
@media (min-width: 1024px) {
  .smedia-list {
    grid-template-columns: 1fr;
  }
}

/* Kartu proyek di daftar (window.renderSinarMediaList).
   [PERBAIKAN, 22 Sep 2026] CSS di bawah ini sebelumnya untuk struktur
   HTML "iterasi ke-6" (.smedia-card-head/.smedia-card-hero/.smedia-card-foot,
   dst) yang TIDAK PERNAH benar-benar dipakai window.renderSinarMediaList --
   fungsi itu memakai nama class lain (.smedia-card-top/.smedia-card-stats/
   .smedia-card-bottom, dst, lihat js/sinarmedia.js). Akibatnya class-class
   lama itu jadi mati (tidak match apa pun di HTML) dan elemen kartu
   (label & nilai, catatan deadline & opsi) dirender TANPA style sama
   sekali -- teks jadi menempel tanpa spasi/baris ("Total Nilai
   ProyekRp 30.800.000", "2 bln 1 mgg lagidisepakati ..."). CSS di bawah
   ditulis ulang supaya cocok 1:1 dengan struktur HTML yang benar-benar
   dihasilkan window.renderSinarMediaList:
   1) .smedia-card-top     -- nama proyek + ikon status
   2) .smedia-card-stats   -- 2 KOTAK BESAR berdampingan: Total Nilai
                              Proyek & Harga Jual/eks
   3) .smedia-card-bottom  -- baris kecil & pudar rata kiri-kanan: status
                              untung/rugi + eksemplar (kiri), deadline +
                              catatan opsi disepakati (kanan)
   4) .smedia-card-spec    -- ringkasan spek fisik majalah (desktop saja,
                              tidak berubah dari sebelumnya) */
.smedia-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  padding: var(--space-10) var(--space-12);
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--rule);
  background: var(--paper-warm);
  cursor: pointer;
  transition: border-color .15s ease, transform .15s ease;
}
.smedia-card:hover { border-color: var(--accent); transform: translateY(-2px); }

.smedia-card-top {
  display: flex;
  align-items: center;
  gap: var(--space-8);
}
.smedia-card-edition {
  flex: 0 0 auto;
  padding: var(--space-2) var(--space-10);
  font-size: var(--text-2xs);
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;
  color: var(--ink-muted);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
}
.smedia-card-name {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--ink);
  min-width: 0;
  overflow-wrap: anywhere;
}
.smedia-card-name svg { flex: 0 0 auto; color: var(--ink-faint); }

/* [STATS] 2 kotak besar berdampingan -- Total Nilai Proyek & Harga
   Jual/eks -- yang paling ditonjolkan di kartu. grid (bukan flex) supaya
   kedua kotak SELALU sama lebar & sama tinggi, tidak tergantung panjang
   isinya. minmax(0,1fr) mencegah kotak dengan teks panjang mendorong
   lebar kolom lain. */
.smedia-card-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-8);
}
/* [4 KOLOM, 20 Okt 2026] Total Nilai Proyek | Harga Jual/eks | Bruto | Netto.
   Di layar sempit (HP) 4 kotak sebaris terlalu sempit untuk angka Rupiah,
   jadi jadi 2x2; layar >= 600px tetap 4 kolom sebaris. */
@media (max-width: 599px) {
  .smedia-card-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.smedia-card-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  padding: var(--space-8) var(--space-10);
}
[data-theme="dark"] .smedia-card-stat { background: var(--paper-warm); border-color: var(--rule); }
.smedia-card-stat-label {
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: .03em;
}
.smedia-card-stat-value {
  display: block;
  font-size: var(--text-lg);
  font-weight: 800;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* [BOTTOM] Status untung/rugi + eksemplar (kiri) vs deadline + catatan
   opsi disepakati (kanan) -- dipadatkan jadi 1 baris kecil & pudar rata
   kiri-kanan yang wrap kalau perlu, bukan lagi fokus utama kartu. */
.smedia-card-bottom {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-8);
  flex-wrap: wrap;
  font-size: var(--text-2xs);
  color: var(--ink-faint);
}
.smedia-card-bottom-left {
  display: flex;
  align-items: baseline;
  gap: var(--space-6);
  min-width: 0;
}
.smedia-card-bottom-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  text-align: right;
  margin-left: auto;
}
.smedia-card-meta { white-space: nowrap; }
.smedia-card-result-value { font-weight: 700; color: var(--ink); }
.smedia-card-profit .smedia-card-result-value { color: var(--success); }
.smedia-card-loss .smedia-card-result-value { color: var(--danger); }
.smedia-card-result-empty { font-style: italic; color: var(--ink-faint); }
.smedia-card-result-note { display: block; }

/* [3 KOLOM STATISTIK, 20 Okt 2026] Kotak Netto (dulu Keuntungan/Kerugian; kini kotak ke-4, Bruto kotak ke-3). Warna
   ikut status kartu; kalau belum ada harga disepakati tampil teks netral
   kecil (boleh wrap 2 baris, kotak lain ikut setinggi karena grid stretch). */
.smedia-card-profit .smedia-card-stat-result { color: var(--success); }
.smedia-card-loss .smedia-card-stat-result { color: var(--danger); }
.smedia-card-stat-value.is-empty {
  font-size: var(--text-xs);
  font-weight: 600;
  font-style: italic;
  color: var(--ink-faint);
  white-space: normal;
  line-height: 1.3;
}
/* Ukuran kotak SAMA seperti sebelumnya (font, padding, label tidak diubah
   per breakpoint lagi). Satu-satunya penyesuaian: angka otomatis mengecil
   HANYA kalau lebarnya tidak muat di kotaknya (container
   query: cqw = lebar kotaknya sendiri), dengan batas bawah 11px dan batas
   atas = ukuran asli (--text-lg). Di desktop/tablet angka tetap ukuran asli. */
@supports (width: 1cqw) {
  .smedia-card-stat { container-type: inline-size; }
  .smedia-card-stat-value:not(.is-empty) { font-size: clamp(11px, 10.5cqw, var(--text-lg)); }
}

/* [DEADLINE CHIP, 23 Sep 2026] Chip deadline (window._smediaDeadlineChip,
   dipakai window._smediaCardDeadlineLine & window._smediaMilestoneBadge)
   -- sebelumnya cuma teks kecil pudar berwarna nyempil di kanan-bawah
   kartu, gampang tertelan sama catatan "disepakati ..." di sebelahnya.
   Sekarang jadi baris CHIP PENUH sendiri tepat di bawah nama proyek
   (posisi paling awal dilihat), dengan LATAR BERWARNA tint (bukan cuma
   teks berwarna) supaya proyek mepet/lewat tenggat benar-benar menonjol
   dari daftar. Hitungan mundur (mainText, di dalam <strong>) dibuat besar
   & tebal -- itu info yang paling sering dicari sekilas -- nama
   tahap/milestone (subText) jadi baris kedua kecil di bawahnya, TIDAK
   digabung 1 baris lagi supaya tidak saling menutupi saat nama tahapnya
   panjang. */
.smedia-card-deadline {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-6) var(--space-10);
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-size: var(--text-xs);
}
.smedia-card-deadline-icon { display: flex; flex: 0 0 auto; }
.smedia-card-deadline-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.25;
}
.smedia-card-deadline-text strong { font-size: var(--text-sm); font-weight: 800; }
.smedia-card-deadline-sub {
  font-size: var(--text-2xs);
  font-weight: 500;
  opacity: .85;
  overflow-wrap: anywhere;
}
/* Severity: latar tint + teks + border senada, dari token warna yang
   sudah ada (--danger/--warning/--ink-faint) supaya otomatis mengikuti
   tema terang/gelap lewat color-mix, sama seperti .smedia-ms-highlight. */
.smedia-deadline--danger {
  background: color-mix(in srgb, var(--danger) 14%, var(--paper));
  border-color: color-mix(in srgb, var(--danger) 35%, transparent);
  color: var(--danger);
}
.smedia-deadline--warning {
  background: color-mix(in srgb, var(--warning, #b45309) 14%, var(--paper));
  border-color: color-mix(in srgb, var(--warning, #b45309) 35%, transparent);
  color: var(--warning, #b45309);
}
.smedia-deadline--neutral {
  background: var(--paper);
  border-color: var(--rule);
  color: var(--ink-faint);
}
.smedia-card-deadline.is-urgent { animation: smediaDeadlinePulse 1.3s ease-in-out infinite; }
@keyframes smediaDeadlinePulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.85; transform: scale(1.01); }
}
@media (prefers-reduced-motion: reduce) {
  .smedia-card-deadline.is-urgent { animation: none; }
}

/* [SPEK MAJALAH] Baris ringkasan spek fisik (kertas isi/cover, halaman,
   jilid, laminasi) di kartu proyek -- KHUSUS DESKTOP (lihat
   window._smediaCardSpecLine di js/sinarmedia.js). Disembunyikan bawaan
   (mobile/tablet, kartu sudah padat) & baru ditampilkan di layar lebar
   lewat media query di bawah, supaya konsisten dengan pola fullview-modal
   lain di app ini yang membedakan tata letak hp vs desktop lewat
   breakpoint 1024px. */
.smedia-card-spec { display: none; }
@media (min-width: 1024px) {
  .smedia-card-spec {
    display: block;
    font-size: var(--text-2xs);
    color: var(--ink-faint);
    padding-top: var(--space-2);
    border-top: 1px dashed var(--rule);
    margin-top: var(--space-2);
  }
}

/* Baris opsi harga cetak (nama percetakan + harga/eksemplar + hapus) --
   dibiarkan wrap kalau ruangnya benar-benar sempit (hp kecil ~320px)
   supaya input tidak sampai gepeng/susah diketik, dan tombol hapusnya
   tetap punya target sentuh yang layak. */
.smedia-option-row { flex-wrap: wrap; }
.smedia-option-row .smedia-opt-label { min-width: 140px; }
.smedia-option-row .smedia-opt-price { min-width: 100px; }

/* "Simulasi Harga Cetak" di form proyek SinarMedia (js/sinarmedia.js) --
   dibungkus <details> supaya baris opsi harga cetak (label+harga per
   percetakan) BARU tampil kalau usernya klik buka bagian ini, bukan
   langsung penuh di form. Chevron & mekanisme buka/tutup pakai <details>
   native (sama polanya dengan .setelan-collapse di panel Setelan), tapi
   dibuat class terpisah karena isinya form field (input, tombol) bukan
   cuma teks hint -- summary & body-nya perlu ukuran/warna beda dari
   .setelan-collapse yang didesain untuk paragraf kecil. Dibuka otomatis
   lewat JS (elemen#smediaOptionsCollapse.open = true) kalau proyek yang
   diedit sudah punya opsi harga tersimpan, lihat
   window.openEditSinarMediaProjectModal. */
.smedia-options-collapse {
  margin-bottom: var(--space-12);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper-warm);
}
.smedia-options-collapse summary {
  list-style: none;
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--ink);
  padding: var(--space-8) var(--space-10);
  display: flex;
  align-items: center;
  gap: var(--space-6);
  user-select: none;
}
.smedia-options-collapse summary::-webkit-details-marker { display: none; }
.smedia-options-collapse summary::before {
  /* Chevron Lucide lewat mask, supaya ikut warna teks -- sama seperti
     .setelan-collapse summary::before. */
  content: '';
  flex-shrink: 0;
  width: 1.4em; height: 1.4em;
  background-color: var(--ink-faint);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform .15s ease;
}
.smedia-options-collapse[open] summary::before { transform: rotate(90deg); }
.smedia-options-collapse summary:hover { color: var(--accent); }
.smedia-options-collapse-body { padding: 0 var(--space-10) var(--space-10); }

/* [SPEK MAJALAH] Label <summary> collapse ini SENGAJA dinamis (diisi lewat
   JS, lihat window.openEditSinarMediaProjectModal/openAddSinarMediaProjectModal
   & window._smediaSpecSummaryHtml di js/sinarmedia.js) -- menampilkan
   ringkasan spek yang sudah terisi (mis. "Spek Majalah — Isi HVS 70gr ·
   32 hlm...") supaya user tahu isinya TANPA perlu membuka collapse dulu.
   flex:1 + ellipsis supaya ringkasan yang panjang terpotong rapi, bukan
   mendorong lebar summary/ikon chevron melebar ke luar kartu. */
.smedia-spec-summary-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Kartu hasil simulasi untung/rugi per opsi (window._smediaUpdatePreview)
   -- boleh wrap ke baris baru kalau nama opsi/percetakan panjang di layar
   sempit, daripada angka untung/rugi di kanan jadi terpepet kecil. */
.smedia-preview-row { flex-wrap: wrap; }

/* [TAHAPAN & DEADLINE BERTAHAP] Kalender ringkas (toggle mingguan/bulanan)
   + kotak highlight deadline terdekat + daftar tahapan, di dalam collapse
   "Tahapan & Deadline" (id smediaMsCollapse, lihat index.html &
   window._smediaRenderMilestoneSection di js/sinarmedia.js). */
.smedia-cal-header {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  flex-wrap: wrap;
  margin-bottom: var(--space-8);
}
.smedia-cal-label {
  font-weight: 700;
  font-size: var(--text-sm);
  color: var(--ink);
  flex: 1;
  text-align: center;
  min-width: 100px;
}
.smedia-cal-nav {
  background: none;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  padding: 4px 6px;
  cursor: pointer;
  color: var(--ink-muted);
  display: flex;
}
.smedia-cal-nav:hover { color: var(--accent); border-color: var(--accent); }
.smedia-cal-today {
  font-size: var(--text-2xs) !important;
  padding: 4px 8px !important;
}
.smedia-cal-toggle {
  display: flex;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  overflow: hidden;
  width: 100%;
  order: 1;
}
.smedia-cal-toggle button {
  flex: 1;
  background: var(--paper);
  border: none;
  padding: 6px 8px;
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--ink-muted);
  cursor: pointer;
}
.smedia-cal-toggle button.is-active { background: var(--accent); color: #fff; }
.smedia-cal-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 2px;
  width: 100%;
}
/* [KALENDER KOMPAK] Kalender tahapan dikecilkan: lebar dibatasi & dipusatkan
   (sebelumnya melebar penuh, sel persegi jadi besar di layar lebar), sel
   sedikit lebih pendek, font & titik lebih kecil. */
.smedia-cal-header,
.smedia-cal-grid { max-width: 280px; margin-left: auto; margin-right: auto; }
.smedia-cal-header { gap: var(--space-4); margin-bottom: var(--space-6); }
.smedia-cal-label { font-size: var(--text-xs); }
.smedia-cal-nav { padding: 2px 4px; }
.smedia-cal-toggle button { padding: 4px 6px; }
.smedia-cal-dow { font-size: 9px; padding-bottom: 2px; }
.smedia-cal-cell { aspect-ratio: 1.2; font-size: 10px; gap: 1px; padding: 1px; }
.smedia-cal-daynum { font-size: 10px; }
.smedia-cal-dot { width: 5px; height: 5px; }
.smedia-cal-dow {
  box-sizing: border-box;
  text-align: center;
  font-size: var(--text-2xs);
  font-weight: 700;
  color: var(--ink-faint);
  padding-bottom: 4px;
}
.smedia-cal-cell {
  box-sizing: border-box;
  aspect-ratio: 1;
  width: 100%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  background: var(--paper);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--ink);
  font-size: var(--text-2xs);
  padding: 2px;
  overflow: hidden;
}
/* Layar hp sangat sempit (<380px, mis. yang di screenshot) -- padatkan
   lagi gap & label supaya 7 kolom tetap muat rapi tanpa memaksa grid
   melebar/scroll horizontal. */
@media (max-width: 380px) {
  .smedia-cal-grid { gap: 1px; }
  .smedia-cal-dow { font-size: 9px; padding-bottom: 2px; }
  .smedia-cal-cell { font-size: 9px; padding: 1px; }
  .smedia-cal-daynum { font-size: 9px; }
}
.smedia-cal-cell:hover { border-color: var(--accent); }
.smedia-cal-cell.is-out { color: var(--ink-faint); opacity: 0.5; }
.smedia-cal-cell.is-today { background: var(--accent-lt); font-weight: 700; }
.smedia-cal-cell.has-items { font-weight: 700; }
.smedia-cal-dot { border-radius: 50%; flex-shrink: 0; }

/* Kotak highlight "Deadline Terdekat" -- di atas kalender.
   [REDESAIN UI] Kartu flat dengan ubin ikon di kiri, label kecil + nama +
   tanggal di tengah, dan kapsul hitung mundur di kanan (pola .type-badge).
   Warna status lewat token: biasa = aksen, is-urgent (<= 7 hari) = danger,
   sehingga ikut tema gelap. */
.smedia-ms-highlight {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  padding: var(--space-12) var(--space-14);
  margin-bottom: var(--space-10);
  border-radius: var(--radius);
  border: 1px solid var(--rule);
  background: var(--paper);
  font-size: var(--text-sm);
  color: var(--ink);
}
.smedia-ms-highlight.is-urgent { border-color: color-mix(in srgb, var(--danger) 55%, var(--rule)); background: color-mix(in srgb, var(--danger) 6%, var(--paper)); }
.smedia-ms-highlight.is-empty { color: var(--ink-faint); font-style: italic; font-size: var(--text-xs); background: var(--paper-warm); }
.smedia-ms-hl-icon {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  background: var(--accent-lt); color: var(--accent);
}
.smedia-ms-highlight.is-urgent .smedia-ms-hl-icon { background: var(--danger-lt); color: var(--danger); }
.smedia-ms-hl-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.smedia-ms-hl-eyebrow { font-size: var(--text-2xs); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-faint); }
.smedia-ms-hl-name { font-size: var(--text-base); font-weight: 700; color: var(--ink); overflow-wrap: anywhere; line-height: 1.35; }
.smedia-ms-highlight-date { display: flex; align-items: center; gap: var(--space-4); font-size: var(--text-xs); color: var(--ink-muted); margin-top: var(--space-2); }
.smedia-ms-highlight-date svg { flex: 0 0 auto; color: var(--ink-faint); }
.smedia-ms-hl-count {
  flex: 0 0 auto; white-space: nowrap;
  padding: var(--space-3) var(--space-10); border-radius: var(--radius-pill);
  border: 1px solid var(--rule); background: var(--paper-warm);
  font-size: var(--text-xs); font-weight: 700; color: var(--ink);
}
.smedia-ms-highlight.is-urgent .smedia-ms-hl-count { border-color: transparent; background: var(--danger-lt); color: var(--danger); }
@media (max-width: 480px) {
  .smedia-ms-highlight { flex-wrap: wrap; }
  .smedia-ms-hl-count { margin-left: calc(36px + var(--space-12)); }
}

/* Daftar tahapan (di bawah kalender) -- tiap baris: dot status (klik untuk
   siklus todo -> dikerjakan -> selesai), nama+meta, tombol ubah/hapus. */
.smedia-ms-list { margin: var(--space-10) 0; }
.smedia-ms-empty { font-size: var(--text-xs); color: var(--ink-faint); font-style: italic; padding: var(--space-6) 0; }
.smedia-ms-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 4px;
  border-bottom: 1px dashed var(--rule);
}
.smedia-ms-row:last-child { border-bottom: none; }
.smedia-ms-row.is-done .smedia-ms-row-name { text-decoration: line-through; color: var(--ink-faint); }
.smedia-ms-status-dot {
  width: 14px; height: 14px; min-width: 14px; padding: 0;
  border-radius: 50%;
  border: none;
  flex: 0 0 14px;
  cursor: pointer;
}
.smedia-ms-row-body { flex: 1; min-width: 0; }
.smedia-ms-row-name { font-weight: 600; font-size: var(--text-sm); }
.smedia-ms-row-meta { font-size: var(--text-2xs); color: var(--ink-faint); }
.smedia-ms-row-edit, .smedia-ms-row-del {
  background: none;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  padding: 5px 7px;
  cursor: pointer;
  color: var(--ink-muted);
  flex-shrink: 0;
}
.smedia-ms-row-del { color: var(--danger); border-color: var(--danger-lt); }
.smedia-ms-form { border-top: 1px dashed var(--rule); padding-top: var(--space-10); }

@media (max-width: 480px) {
  /* Semua baris tombol/aksi di Setelan ditumpuk penuh-lebar di hp --
     sebelumnya sebagian tombol pakai rasio flex:1/2 yang jadi terlalu
     sempit begitu layar mengecil (mis. "Tes Koneksi" / "Migrasi Semua
     Data" terpotong tulisannya). Ditumpuk vertikal jauh lebih mudah
     dibaca & konsisten di semua panel. */
  .setelan-actions-row,
  .setelan-sheets-row,
  .setelan-device-row,
  .panel-actions-row {
    flex-direction: column;
    align-items: stretch;
  }
  .setelan-actions-row .btn,
  .setelan-sheets-row .btn,
  .setelan-sheets-row .form-control,
  .setelan-device-row .btn,
  .setelan-device-row .form-control,
  .panel-actions-row .btn {
    width: 100%;
    flex: 1 1 auto;
  }

  /* Judul tab + badge status (mis. "Koneksi Database Cloud" + "Berlaku untuk
     semua buku") dibiarkan turun ke baris baru kalau tidak muat, supaya
     tidak memicu scroll horizontal di layar sempit. */
  .panel-title,
  .setelan-title,
  .setelan-title--purple,
  .setelan-title--amber,
  .setelan-title--blue,
  .setelan-info-row {
    flex-wrap: wrap;
    row-gap: var(--space-4);
  }

  /* Panel Setelan sendiri dirapatkan sedikit di hp supaya konten utama
     (label, input) dapat ruang lebih lega. */
  .data-management-panel { padding: var(--space-12) var(--space-14); }
}

/* Tombol pilih bahasa */
.btn-lang-active   { flex: 1; background: var(--accent); color: #fff; border-color: var(--accent); font-weight: 600; }
.btn-lang-inactive { flex: 1; background: var(--rule); color: var(--ink); border-color: var(--ink-faint); font-weight: 600; }

/* ── Book List ── */
.book-list-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-10) var(--space-12);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-8);
  background: var(--paper);
  transition: background 0.1s;
}
.book-list-item:hover { background: var(--paper-warm); }
.book-list-name { font-size: var(--text-sm); font-weight: 400; color: var(--ink); }
.book-list-actions { display: flex; gap: var(--space-6); flex-wrap: wrap; }

/* [RAPIKAN MOBILE] Di layar sempit, layout "nama kiri - tombol kanan"
   bikin tombol (Buka/Nama/Card/Hapus) numpuk jadi kolom sempit di kanan
   dan wrap tidak beraturan (kadang 1 tombol nyempil sendirian di baris
   ke-2, tidak sejajar dengan apa pun). Di bawah breakpoint mobile umum
   app ini (640px, lihat breakpoint lain di file ini): jadikan kartu
   1 kolom (nama & badge di atas, full width), lalu tombol aksi jadi
   BARIS TERPISAH di bawahnya yang melebar penuh & rapi (grid rata,
   bukan wrap ke kanan doang). */
@media (max-width: 640px) {
  .book-list-item {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-8);
  }
  .book-list-name { display: block; width: 100%; }
  .book-list-actions {
    width: 100%;
    justify-content: flex-start;
  }
  .book-list-actions .btn-mini {
    flex: 1 1 calc(50% - 6px); /* 2 tombol per baris, lebar rata */
    text-align: center;
    padding-top: 7px;
    padding-bottom: 7px;
  }
  /* Badge "SEDANG AKTIF" (span, bukan tombol) tidak ikut melebar seperti
     tombol lain -- biarkan seukuran teksnya saja di baris sendiri. */
  .book-list-actions > span { flex: 1 1 100%; }
}

/* ── Log Audit ── [OPTIMASI TAMPILAN] Sebelumnya satu baris monospace mentah
   ("[TAG] [jam] Device:xxx - detail") yang gampang overflow & susah dipindai
   sekilas. Sekarang tiap entri jadi baris kartu (ikon aksi + waktu relatif +
   detail yang boleh wrap + perangkat sebagai pill kecil), dikelompokkan per
   tanggal (sticky header "Hari Ini"/"Kemarin"/tanggal), dan bisa difilter
   per jenis aksi lewat chip di toolbar. Semua warna pakai token tema yang
   sudah ada supaya otomatis mengikuti light/dark mode tanpa override
   terpisah. Lihat window.renderLogs & sekitarnya di js/transaction.js. */
.log-section {
  background: var(--paper);
  border-radius: var(--radius-sm);
  padding: var(--space-14) var(--space-16);
  margin-top: var(--space-20);
}
.log-section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-10);
  padding-bottom: 8px;
  border-bottom: 1px solid var(--rule);
}
.log-section-header h2 { font-size: var(--text-xs); font-weight: 500; color: var(--ink); }

.log-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  flex-wrap: wrap;
  margin-bottom: var(--space-8);
}
.log-filter-bar { display: flex; align-items: center; gap: var(--space-6); flex-wrap: wrap; }
.log-filter-chip {
  font-family: inherit;
  font-size: var(--text-2xs);
  font-weight: 600;
  padding: var(--space-4) var(--space-11);
  border-radius: var(--radius-pill);
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink-muted);
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.log-filter-chip:hover { background: var(--paper-warm); color: var(--ink); }
.log-filter-chip.active { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.log-container-box {
  max-height: 320px;
  overflow-y: auto;
  background: var(--paper);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-6);
  font-size: var(--text-xs);
}
.log-date-divider {
  position: sticky;
  top: 0;
  background: var(--paper);
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-faint);
  padding: var(--space-9) var(--space-6) var(--space-4);
}
.log-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-10);
  padding: var(--space-8) var(--space-6);
  border-bottom: 1px solid var(--rule);
}
.log-row:last-child { border-bottom: none; }
.log-icon {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}
.log-icon svg { width: 14px; height: 14px; }
.log-icon.log-add    { background: var(--success); }
.log-icon.log-edit   { background: var(--warning); }
.log-icon.log-delete { background: var(--danger); }
.log-icon.log-import { background: var(--info); }
.log-icon.log-backup { background: var(--purple); }
.log-icon.log-system { background: var(--ink-muted); }

.log-row-body { flex: 1; min-width: 0; }
.log-row-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-6);
  margin-bottom: 2px;
}
.log-row-action { font-weight: 700; color: var(--ink); font-size: var(--text-xs); }
.log-row-time {
  margin-left: auto;
  color: var(--ink-faint);
  font-size: var(--text-2xs);
  white-space: nowrap;
  cursor: default;
}
.log-row-details {
  color: var(--ink-muted);
  line-height: 1.5;
  word-break: break-word;
}
.log-row-device {
  display: inline-flex;
  align-items: center;
  margin-top: var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  background: var(--paper-warm);
  border-radius: var(--radius-xs);
  padding: 1px var(--space-6);
}
.log-empty, .log-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  padding: var(--space-26) var(--space-12);
  color: var(--ink-faint);
  font-size: var(--text-xs);
  text-align: center;
}
.log-empty svg, .log-loading svg { opacity: .5; width: 26px; height: 26px; }
.log-loading svg { animation: skLogPulse 1.1s ease-in-out infinite; }
@keyframes skLogPulse { 0%, 100% { opacity: .3; } 50% { opacity: .65; } }

@media (max-width: 480px) {
  .log-row-head { flex-wrap: wrap; }
  .log-row-time { margin-left: 0; }
}

/* ── Attachment ── */
.attachment-preview {
  margin-top: var(--space-10);
  max-width: 100%;
  max-height: 140px;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--rule);
  display: none;
}
.file-info { font-size: var(--text-2xs); color: var(--ink-faint); margin-top: var(--space-5); }

/* ── Connection ── */
.cloud-connect-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  margin-top: var(--space-10);
}
.connection-status {
  font-size: var(--text-xs);
  padding: var(--space-6) var(--space-10);
  border-radius: var(--radius-sm);
  margin-top: var(--space-6);
}
.connection-status.success { background: var(--success-lt); color: var(--success); }
.connection-status.error   { background: var(--danger-lt);  color: var(--danger); }
.connection-status.testing { background: var(--warning-lt); color: var(--warning); }

/* ── Toast ── */
/* Toast tampil di tengah-BAWAH layar, naik dari bawah. bottom dibuat 84px
   (bukan 24px) supaya berada tepat DI ATAS FAB "Tanya Sinarkeu" (kanan-bawah:
   bottom 20-28px + tinggi 52px = maks. 80px) -- tidak bertabrakan walau
   pesannya lebar. z-index 9100: di atas modal/fullview (2000-2200) dan FAB
   (9000), tetap di bawah lockscreen (9999). */
.toast-message {
  position: fixed;
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  max-width: calc(100vw - 32px);
  background: var(--ink);
  color: var(--paper-warm);
  padding: var(--space-12) var(--space-20);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  font-size: var(--text-xs);
  z-index: 9100;
  display: none;
  align-items: center;
  gap: var(--space-10);
  animation: toastRiseIn 0.25s ease;
}
@keyframes toastRiseIn {
  from { transform: translate(-50%, 24px); opacity: 0; }
  to   { transform: translate(-50%, 0); opacity: 1; }
}
.toast-message.show { display: flex; }

/* ── Budget Form ── */
.budget-cat-row {
  display: flex;
  gap: var(--space-10);
  align-items: center;
  margin-bottom: var(--space-10);
}
.budget-cat-row .budget-cat-label {
  width: 150px;
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--ink-muted);
}
.budget-cat-row .form-control { flex: 1; }
@media (max-width: 480px) {
  .budget-cat-row {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-4);
  }
  .budget-cat-row .budget-cat-label { width: auto; }
}

/* ── Anggaran Tahunan: baris per-item ──
   Beda dari .budget-cat-row (label tetap + 1 input) di atas -- baris ini
   punya 2 input (nama & harga) + tombol Hapus opsional, jadi butuh susunan
   sendiri, bukan numpang class budget-cat-row (yang sebelumnya ditimpa lagi
   pakai inline style, sehingga aturan mobile budget-cat-row di atas tidak
   pernah kepakai sama sekali untuk baris ini). */
.annual-budget-row {
  display: flex;
  gap: var(--space-8);
  align-items: center;
  margin-bottom: var(--space-8);
}
.annual-budget-row .annual-budget-name { flex: 2; }
.annual-budget-row .annual-budget-amount { flex: 1; }
.annual-budget-row .annual-budget-remove-btn {
  background: none;
  border: 1.5px solid var(--danger);
  color: var(--danger);
  border-radius: var(--radius-sm);
  padding: var(--space-4) var(--space-10);
  cursor: pointer;
  font-size: var(--text-base);
  flex-shrink: 0;
}
@media (max-width: 480px) {
  /* Nama kebutuhan sering panjang ("Servis Kendaraan Tahunan", dst.) --
     dipaksa sejajar dengan harga & tombol Hapus di layar sempit membuat
     ketiganya kepotong/kelewat kecil. Susun ulang jadi grid 2 kolom: nama
     full-width di baris atas, harga & Hapus sejajar di baris bawah --
     pola yang sama seperti form tambah barang di Daftar Belanja
     (.slist-add-row), supaya konsisten & tetap nyaman diketuk di hp. */
  .annual-budget-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-6);
    align-items: stretch;
  }
  .annual-budget-row .annual-budget-name { grid-column: 1 / -1; }
  .annual-budget-row .annual-budget-amount,
  .annual-budget-row .annual-budget-remove-btn { flex: initial; }
  .annual-budget-row .annual-budget-remove-btn {
    width: 100%;
    padding: var(--space-8) var(--space-10);
    font-size: var(--text-sm);
  }
}

.budget-summary-row {
  background: var(--paper-warm);
  padding: var(--space-10) var(--space-14);
  border: 1.5px solid var(--rule);
  margin-top: var(--space-14);
  font-weight: 500;
  font-size: var(--text-sm);
}

.budget-info-badge {
  font-size: var(--text-2xs);
  font-weight: 400;
  color: var(--ink-faint);
  background: var(--paper-warm);
  padding: var(--space-2) var(--space-8);
  border-radius: var(--radius-sm);
  margin-left: var(--space-6);
  border: 1.5px solid var(--rule);
}
.budget-info-badge.custom { background: var(--accent-lt); color: var(--accent); border-color: var(--accent); }
.budget-info-badge.default { background: var(--success-lt); color: var(--success); border-color: var(--success); }

.budget-source-tag {
  display: inline-block;
  font-size: var(--text-2xs);
  font-weight: 500;
  padding: var(--space-2) var(--space-7);
  margin-left: var(--space-6);
}
.budget-source-tag.default { background: var(--success-lt); color: var(--success); }
.budget-source-tag.custom  { background: var(--accent-lt); color: var(--accent); }
.budget-source-tag.none    { background: var(--paper-warm); color: var(--ink-faint); }

/* ── Anggaran Dasar (kartu ringkasan + grid kategori) ──
   Khusus modal #defaultBudgetModal — sengaja pakai prefix .dbudget-
   supaya tidak menyentuh tampilan modal Anggaran Bulanan (.budget-cat-row dst.)
   yang masih dipakai di #budgetModal.
   [DIRATAKAN] Sama seperti .hk-summary-box & .slist-summary-card -- gradient
   navy diganti flat var(--paper)+border, teks putih dipetakan ke
   var(--ink)/var(--ink-muted), pill emas dipetakan ke token
   var(--warning)/var(--warning-lt) yang memang untuk itu (sebelumnya
   warna emas custom #E7C874 dituning khusus supaya kontras di atas navy
   gelap, sekarang di atas latar terang var(--warning) sudah pas). */
.dbudget-summary-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-14);
  flex-wrap: wrap;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-16) var(--space-20);
  margin-bottom: var(--space-14);
}
.dbudget-summary-label {
  display: block;
  font-size: var(--text-2xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-muted);
  margin-bottom: var(--space-5);
}
.dbudget-summary-value {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.dbudget-summary-meta {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--warning);
  background: var(--warning-lt);
  border: 1px solid var(--warning);
  padding: var(--space-5) var(--space-11);
  border-radius: var(--radius-pill);
  white-space: nowrap;
}

.dbudget-search-wrap { position: relative; margin-bottom: var(--space-12); }
.dbudget-search-wrap svg {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  color: var(--ink-faint); pointer-events: none;
}
.dbudget-search-wrap input.form-control { padding-left: 34px; }

.dbudget-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
}
@media (max-width: 640px) {
  .dbudget-grid { grid-template-columns: 1fr; }
}

.dbudget-item {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  padding: var(--space-8) var(--space-10);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  transition: border-color .15s ease, background .15s ease;
}
.dbudget-item.filled { border-color: var(--success); background: var(--success-lt); }
.dbudget-item:focus-within { border-color: var(--accent); }
.dbudget-item.dbudget-hidden { display: none; }

.dbudget-badge {
  flex: 0 0 30px;
  width: 30px; height: 30px;
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-sm);
}
.dbudget-badge.c0 { background: var(--accent-lt); color: var(--accent); }
.dbudget-badge.c1 { background: var(--success-lt); color: var(--success); }
.dbudget-badge.c2 { background: var(--warning-lt); color: var(--warning); }
.dbudget-badge.c3 { background: var(--info-lt); color: var(--info); }
.dbudget-badge.c4 { background: var(--purple-lt); color: var(--purple); }

.dbudget-body { flex: 1; min-width: 0; }
.dbudget-name {
  display: block;
  font-size: var(--text-xs);
  color: var(--ink-muted);
  margin-bottom: var(--space-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dbudget-input-row { display: flex; align-items: center; gap: var(--space-6); }
.dbudget-input-row .form-control { flex: 1; padding: var(--space-6) var(--space-8); font-size: var(--text-sm); }
.dbudget-clear-btn {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  border: none; background: var(--paper-warm); color: var(--ink-faint);
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  font-size: var(--text-base); line-height: 1;
}
.dbudget-clear-btn:hover { background: var(--danger-lt); color: var(--danger); }
.dbudget-empty-hint { font-size: var(--text-sm); color: var(--ink-faint); text-align: center; padding: var(--space-22) 0; }

/* ── Belanja Bulanan ── */
.slist-summary-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-12);
  margin-bottom: var(--space-14);
}
.slist-summary-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-14);
  flex-wrap: wrap;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-16) var(--space-20);
  margin-bottom: 0;
}
.slist-summary-value-sep {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 500;
  color: var(--ink-faint);
  margin: 0 var(--space-4);
}
.slist-summary-value-total {
  font-size: var(--text-xl);
  color: var(--ink-muted);
}
.slist-summary-value.is-negative {
  color: var(--danger);
}
@media (max-width: 760px) {
  .slist-summary-grid { grid-template-columns: 1fr; gap: var(--space-10); }
}

/* ── Daftar Belanja: ringkasan sebagai satu panel 3 sel ──
   Modifier .slist-summary-strip dipasang HANYA di ringkasan Daftar Belanja
   (index.html, #shoppingListModal); Anggaran Tahunan masih pakai 3 kartu
   terpisah gaya lama (.slist-summary-card polos) -- jangan disatukan.
   Tiga kartu terpisah yang isinya beda-beda tata letak (label kiri/nilai
   kanan, bertumpuk, sebaris) diganti satu panel: tiap sel selalu
   label -> nilai -> keterangan, dibatasi garis tipis. Dua sel terakhir
   punya gauge di dasar (.has-gauge): dibeli/total barang & penyerapan
   anggaran, lebarnya dari --gauge (0..1) yang di-set _updateShoppingListSummary
   (js/shopping-list.js) -- senada dengan garis progres di header kartu
   kategori (.sl-group-head). Radius dikecilkan ke --radius-sm. */
.slist-summary-strip {
  gap: 0;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.slist-summary-strip .slist-summary-card {
  position: relative;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: var(--space-16) var(--space-20) var(--space-18);
}
.slist-summary-strip .slist-summary-card + .slist-summary-card { border-left: 1px solid var(--rule); }
.slist-summary-strip .slist-summary-label {
  font-size: var(--text-xs);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  margin-bottom: var(--space-4);
}
.slist-summary-values {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--space-4);
}
/* "/" + total belanja satu paket: kalau sel sempit, keduanya turun baris
   bersama (tidak ada "/" menggantung di ujung baris). */
.slist-summary-total-part { white-space: nowrap; }
/* Total belanja = angka pendamping (lebih kecil & redup dari sisa perkiraan).
   Aturan dasar .slist-summary-value-total dulu selalu kalah karena
   .slist-summary-value ditulis belakangan -- di sini dibuat menang. */
.slist-summary-strip .slist-summary-value.slist-summary-value-total {
  font-size: var(--text-xl);
  font-weight: 500;
  color: var(--ink-muted);
}
.slist-summary-strip .slist-summary-meta { margin-top: var(--space-10); }
.slist-summary-strip .has-gauge::before,
.slist-summary-strip .has-gauge::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  height: 3px;
}
.slist-summary-strip .has-gauge::before { width: 100%; background: var(--rule); }
.slist-summary-strip .has-gauge::after {
  width: calc(var(--gauge, 0) * 100%);
  background: var(--success);
}
.slist-summary-strip .slist-summary-card:nth-child(3)::after { background: var(--warning); }
.slist-summary-strip .slist-summary-card.is-over::after { background: var(--danger); }
@media (max-width: 760px) {
  .slist-summary-strip .slist-summary-card + .slist-summary-card {
    border-left: 0;
    border-top: 1px solid var(--rule);
  }
}

/* ── Belanja Bulanan: rincian sisa anggaran per kategori ── */
.slist-cat-breakdown {
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-10) var(--space-12);
  margin-bottom: var(--space-14);
}
.slist-cat-breakdown-title {
  font-size: var(--text-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--ink-faint);
  margin-bottom: var(--space-6);
}
.slist-cat-rows {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-8) var(--space-16);
}
.slist-cat-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}
.slist-cat-row-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-8);
  min-width: 0;
}
.slist-cat-row-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.slist-cat-row-sisa {
  flex: 0 0 auto;
  white-space: nowrap;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--success);
}
.slist-cat-row-sisa.is-over { color: var(--danger); }
.slist-cat-row-bar {
  display: block;
  width: 100%;
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--paper-warm);
  overflow: hidden;
}
.slist-cat-row-bar-fill {
  display: block;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--success);
}
.slist-cat-row-bar-fill.is-over { background: var(--danger); }
.slist-cat-breakdown-empty {
  font-size: var(--text-xs);
  color: var(--ink-faint);
  text-align: center;
  padding: var(--space-4) 0;
}
@media (max-width: 640px) {
  .slist-cat-rows { grid-template-columns: repeat(2, 1fr); gap: var(--space-8) var(--space-10); }
  .slist-cat-row-name, .slist-cat-row-sisa { font-size: var(--text-xs); }
}
.slist-summary-label {
  display: block;
  font-size: var(--text-2xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-muted);
  margin-bottom: var(--space-5);
}
.slist-summary-value {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.slist-summary-meta {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--warning);
  background: var(--warning-lt);
  border: 1px solid color-mix(in srgb, var(--warning) 40%, var(--warning-lt));
  padding: var(--space-3) var(--space-8);
  border-radius: var(--radius-sm);
  white-space: nowrap;
}
.slist-summary-meta:empty { display: none; }
.slist-summary-meta.is-negative,
.slist-summary-meta.is-up {
  color: var(--danger);
  background: var(--danger-lt);
  border-color: color-mix(in srgb, var(--danger) 40%, var(--danger-lt));
}
.slist-summary-meta.is-down {
  color: var(--success);
  background: var(--success-lt);
  border-color: color-mix(in srgb, var(--success) 40%, var(--success-lt));
}

/* [KONTRAS] Label pill "Harga Komoditas" (Harga Pangan otomatis / Update
   terakhir / Komoditas Lain) sengaja TIDAK pakai .slist-summary-meta di
   atas. [CATATAN LAMA, SUDAH TIDAK BERLAKU] Dulu warna emas
   .slist-summary-meta dituning khusus untuk kartu gelap (.slist-summary-card
   waktu masih gradient navy) jadi lemah kalau dipakai di latar terang --
   sekarang .slist-summary-meta sendiri sudah dipetakan ke token
   var(--warning)/var(--warning-lt) yang aman di latar terang, tapi label
   ini tetap dibiarkan pakai --accent/--accent-lt (bukan disatukan) supaya
   dua elemen dengan makna beda -- badge kategori vs meta info tambahan --
   tetap gampang dibedakan visualnya. */
.hk-section-label {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-lt);
  border: 1px solid var(--accent);
  padding: var(--space-5) var(--space-11);
  border-radius: var(--radius-sm);
  white-space: nowrap;
}
.hk-label-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8);
  margin-bottom: var(--space-12);
}

/* Tombol "+ Tambah Barang" -- membuka pop up #addShoppingListItemModal
   (lihat js/shopping-list.js: window.openAddShoppingListItemModal).
   Sebelumnya tombol ini cuma tampak di hp (untuk expand/collapse form
   inline yang slide turun); sekarang formnya selalu berupa pop up di
   semua lebar layar, jadi tombolnya juga selalu tampak. */
.slist-add-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  width: 100%;
  height: 40px;
  margin-bottom: var(--space-14);
  border: 1.5px dashed var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--accent);
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
}
.slist-add-toggle:hover { border-style: solid; background: var(--accent-lt); }
.slist-add-toggle-icon { font-size: var(--text-lg); line-height: 1; }

.slist-cat-badge {
  font-size: var(--text-2xs);
  color: color-mix(in srgb, var(--cat-color, var(--info)) 70%, var(--ink));
  background: color-mix(in srgb, var(--cat-color, var(--info)) 16%, var(--paper));
  border: 1px solid color-mix(in srgb, var(--cat-color, var(--info)) 40%, var(--rule));
  padding: var(--space-1) var(--space-7);
  border-radius: var(--radius-pill);
}
.form-group-checkbox { display: flex; align-items: center; }
.checkbox-label {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  font-size: var(--text-base);
  font-weight: 500;
  cursor: pointer;
}
.checkbox-label input[type="checkbox"] { flex-shrink: 0; }

.slist-staple-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-2xs);
  font-weight: 600;
  padding: var(--space-1) var(--space-6);
  border-radius: var(--radius-sm);
  margin-left: var(--space-6);
  vertical-align: middle;
  white-space: nowrap;
  cursor: help;
}
.slist-staple-badge.is-pending,
.slist-staple-badge.is-ok {
  color: color-mix(in srgb, var(--info) 70%, var(--ink));
  background: color-mix(in srgb, var(--info) 14%, var(--paper));
  border: 1px solid color-mix(in srgb, var(--info) 35%, var(--rule));
}
.slist-staple-badge.is-soon {
  color: var(--warning);
  background: var(--warning-lt);
  border: 1px solid color-mix(in srgb, var(--warning) 35%, var(--warning-lt));
}
.slist-staple-badge.is-due {
  color: var(--danger);
  background: var(--danger-lt);
  border: 1px solid color-mix(in srgb, var(--danger) 35%, var(--danger-lt));
}

.slist-staple-reminders-wrap { margin-bottom: var(--space-12); }
.slist-staple-banner {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  flex-wrap: wrap;
  font-size: var(--text-sm);
  border-radius: var(--radius-sm);
  padding: var(--space-9) var(--space-13);
  border: 1px solid color-mix(in srgb, var(--danger) 35%, var(--danger-lt));
  background: var(--danger-lt);
  color: var(--danger);
}
.slist-staple-banner strong { font-weight: 700; }

.slist-budget-warnings { display: flex; flex-direction: column; gap: var(--space-8); margin-bottom: var(--space-14); }
.slist-budget-warning {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-10);
  flex-wrap: wrap;
  font-size: var(--text-xs);
  border-radius: var(--radius-sm);
  padding: var(--space-9) var(--space-13);
  border: 1px solid color-mix(in srgb, var(--warning) 35%, var(--warning-lt));
  background: var(--warning-lt);
  color: var(--warning);
}
.slist-budget-warning.is-over {
  border-color: color-mix(in srgb, var(--danger) 35%, var(--danger-lt));
  background: var(--danger-lt);
  color: var(--danger);
}
.slist-budget-warning b { font-weight: 700; }

/* Card "Proyeksi Keuangan" -- Belanja Bulanan. Pakai --paper-warm + border
   --rule (beda dari --paper polos di .slist-summary-card) supaya jelas
   ini kartu input/kalkulasi terpisah dari ringkasan sisa belanja di atas. */
.slist-forecast-card {
  background: var(--paper-warm);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-14) var(--space-16);
  margin-bottom: var(--space-14);
}
.slist-forecast-header {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  margin-bottom: var(--space-10);
}
.slist-forecast-title {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--ink);
}
.slist-forecast-hint {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid var(--ink-faint);
  color: var(--ink-faint);
  font-size: var(--text-2xs);
  font-weight: 600;
  cursor: help;
}
.slist-forecast-input-group { margin-bottom: var(--space-12); }
.slist-forecast-input-group label {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--ink-muted);
}
.slist-forecast-breakdown {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding-top: 10px;
  border-top: 1px dashed var(--rule);
  margin-bottom: var(--space-12);
}
.slist-forecast-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: var(--text-sm);
  color: var(--ink-muted);
}
.slist-forecast-row span:last-child {
  font-family: var(--font-mono);
  color: var(--ink);
  font-weight: 500;
}
.slist-forecast-row-total {
  padding-top: 6px;
  border-top: 1px solid var(--rule);
  font-weight: 600;
}
.slist-forecast-row-total span:last-child { font-weight: 700; }
.slist-forecast-row-total #slistForecastMonthlySurplus.is-negative { color: var(--danger); }
.slist-forecast-yearly {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-10);
  flex-wrap: wrap;
  background: var(--accent-lt);
  border-radius: var(--radius-sm);
  padding: var(--space-10) var(--space-13);
}
.slist-forecast-yearly-label {
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--ink-muted);
}
.slist-forecast-yearly-value {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 700;
  color: var(--brand);
}
.slist-forecast-yearly-value.is-negative { color: var(--danger); }
.slist-forecast-note {
  font-size: var(--text-xs);
  color: var(--ink-faint);
  margin: var(--space-8) 0 0;
  line-height: 1.4;
}

.slist-viewer-notice {
  font-size: var(--text-xs);
  border-radius: var(--radius-sm);
  padding: var(--space-9) var(--space-13);
  margin-bottom: var(--space-14);
  border: 1px solid color-mix(in srgb, var(--info) 35%, var(--info-lt));
  background: var(--info-lt);
  color: var(--info);
}
.slist-viewer-notice b { font-weight: 700; }

.slist-list { display: flex; flex-direction: column; gap: var(--space-6); margin-bottom: var(--space-14); }

/* Baris .slist-item (tabel datar: checkbox, nama, qty, kategori, harga,
   aksi) SEKARANG HANYA dipakai Anggaran Tahunan (js/budget.js). Daftar
   Belanja sudah pindah ke kartu per kategori -- lihat blok ".sl-*" di
   bawah (Daftar Belanja: kartu per kategori). */
.slist-item {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) 58px 128px 92px 100px 60px;
  column-gap: var(--space-12);
  align-items: center;
  padding: var(--space-9) var(--space-10);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  transition: border-color .15s ease, background .15s ease, opacity .15s ease;
}
.slist-item:hover { border-color: color-mix(in srgb, var(--accent) 25%, var(--rule)); }
.slist-item.done {
  border-color: var(--rule);
  background: var(--paper-warm);
  opacity: .65;
}
.slist-checkbox { flex: 0 0 auto; width: 17px; height: 17px; accent-color: var(--success); cursor: pointer; }
.slist-name { font-size: var(--text-base); color: var(--ink); overflow-wrap: anywhere; min-width: 0; }
/* Nomor urut barang di dalam kategorinya (1, 2, 3, ... -- direset tiap
   kategori baru, lihat _slistNoCounter di js/shopping-list.js). Kategori
   dengan Anggaran Bulanan terbesar ditaruh paling atas daftar. */
.slist-item-no { color: var(--ink-faint); font-weight: 700; margin-right: var(--space-3); }
.slist-item.done .slist-name { text-decoration: line-through; color: var(--ink-faint); }
.slist-qty {
  justify-self: end;
  font-size: var(--text-2xs);
  color: var(--ink-muted);
  background: var(--paper-warm);
  border: 1px solid var(--rule);
  padding: var(--space-2) var(--space-8);
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
/* Kalau kosong (barang tanpa qty/kategori), sembunyikan "pil"-nya tapi slot
   grid-nya tetap dipertahankan -- inilah kunci kolom selalu sejajar rapi,
   beda dari sebelumnya yang menghilangkan elemen sepenuhnya (bikin kolom
   harga/aksi geser tiap baris tergantung barang mana yang punya qty). */
.slist-qty:empty, .slist-cat-badge:empty { border: none; background: none; padding: 0; }
.slist-cat-badge {
  justify-self: start;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-2xs);
  color: color-mix(in srgb, var(--cat-color, var(--info)) 70%, var(--ink));
  background: color-mix(in srgb, var(--cat-color, var(--info)) 16%, var(--paper));
  border: 1px solid color-mix(in srgb, var(--cat-color, var(--info)) 40%, var(--rule));
  padding: var(--space-2) var(--space-8);
  border-radius: var(--radius-pill);
}
.slist-unit-price {
  justify-self: end;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--ink-faint);
  white-space: nowrap;
}
/* Harga yang diisi OTOMATIS dari referensi PIHPS BI (js/harga-pangan.js),
   bukan diketik manual oleh user -- dibedakan warnanya (pakai --accent,
   sama seperti indikator "belum dikonfirmasi" di bagian lain app) supaya
   sekilas kelihatan ini perkiraan, bukan harga yang sudah dicek sendiri. */
.slist-unit-price.is-ref-price { color: var(--accent); font-style: italic; }
.slist-price {
  justify-self: end;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--ink-muted);
  white-space: nowrap;
}
.slist-trail { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-8); }
.slist-del-btn {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  padding: 0;
  border: none; background: var(--paper-warm); color: var(--ink-faint);
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  font-size: var(--text-base); line-height: 1;
}
.slist-del-btn:hover { background: var(--danger-lt); color: var(--danger); }
.slist-edit-btn {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  padding: 0;
  border: none; background: var(--paper-warm); color: var(--ink-faint);
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  font-size: var(--text-sm); line-height: 1;
}
.slist-edit-btn:hover { background: var(--accent-lt, var(--paper-warm)); color: var(--accent, var(--ink)); }
/* Ikon SVG (dipakai di Daftar Menu) punya width/height tetap via atribut
   HTML -- tanpa flex-shrink:0 ia bisa "ditekan" mengecil oleh flexbox
   kalau ruang di dalam tombol sempit, sampai nyaris tidak kelihatan. */
.slist-edit-btn svg, .slist-del-btn svg { flex-shrink: 0; }

/* Anggaran Tahunan menambahkan aksi Ubah sebagai kolom tersendiri. */
#annualBudgetItemsContainer .slist-item {
  grid-template-columns: 20px minmax(0, 1fr) 58px 128px 92px 100px 22px 22px;
}
#annualBudgetItemsContainer > .slist-item > .slist-trail { gap: 0; }
/* ── Daftar Belanja: kartu per kategori ──
   Markup dibangun js/shopping-list.js (window.renderShoppingList): satu
   <section class="sl-group"> per kategori, isinya <header> (nama kategori,
   progres dibeli/total, subtotal) + <ul> baris barang. Dulu tabel datar
   dengan badge kategori di tiap baris; sekarang kategori jadi struktur
   (rel warna di kiri kartu + garis progres di bawah header), jadi badge
   per baris & header kolom tidak diperlukan lagi.
   Warna kategori datang dari --cat-color (inline di <section>, dari
   window.getCategoryColor) lalu diturunkan lewat color-mix() ke --sl-tone
   seperti .slist-cat-badge -- supaya tetap terbaca di mode gelap. Barang
   tanpa kategori tidak punya --cat-color, jatuh ke abu netral.
   Semua selector di-scope ke .sl-* / #shoppingListContainer: Anggaran
   Tahunan masih pakai .slist-item lama, jangan disatukan. */
#shoppingListContainer { gap: var(--space-12); }

.sl-group {
  --sl-tone: color-mix(in srgb, var(--cat-color, var(--ink-faint)) 70%, var(--ink));
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.sl-group-head {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: var(--space-10);
  padding: var(--space-9) var(--space-12);
  background: color-mix(in srgb, var(--cat-color, var(--ink-faint)) 8%, var(--paper));
  border-bottom: 1px solid var(--rule);
}
/* Garis progres: lebarnya = jumlah barang dibeli / total di kategori ini
   (--sl-done, 0..1, di-set inline oleh renderShoppingList). */
.sl-group-head::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 2px;
  width: calc(var(--sl-done, 0) * 100%);
  background: var(--sl-tone);
}
.sl-group-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--ink);
}
.sl-group-count {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  white-space: nowrap;
}
.sl-group-total {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-muted);
  white-space: nowrap;
}

.sl-rows { list-style: none; margin: 0; padding: 0; }
.sl-row {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) auto auto;
  grid-template-areas:
    "check name price act"
    "check meta price act";
  column-gap: var(--space-12);
  align-items: center;
  padding: var(--space-10) var(--space-12);
  transition: background .15s ease;
}
.sl-row.is-readonly {
  grid-template-columns: 20px minmax(0, 1fr) auto;
  grid-template-areas:
    "check name price"
    "check meta price";
}
.sl-row + .sl-row { border-top: 1px dashed var(--rule); }
.sl-row:hover { background: var(--paper-warm); }
.sl-row.done { background: var(--paper-warm); }

/* Checkbox bulat: hijau (--success, "sudah dibeli") + centang Lucide lewat
   mask. Menimpa gaya checkbox global (kotak + centang border-rotate) --
   makanya ::after di-reset penuh (top/left/border/transform). */
#shoppingListContainer .sl-check {
  grid-area: check;
  align-self: start;
  width: 20px;
  height: 20px;
  min-width: 20px;
  margin-top: var(--space-1);
  border: 1.5px solid var(--ink-faint);
  border-radius: 50%;
}
#shoppingListContainer .sl-check:hover:not(:disabled) { border-color: var(--success); }
#shoppingListContainer .sl-check:checked {
  background: var(--success);
  border-color: var(--success);
}
#shoppingListContainer .sl-check:checked::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 0;
  transform: none;
  background-color: var(--paper);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 62% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 62% no-repeat;
}
#shoppingListContainer .sl-check:disabled { cursor: default; }

.sl-name {
  grid-area: name;
  min-width: 0;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--ink);
  overflow-wrap: anywhere;
}
/* Nomor urut barang di dalam kategorinya (mulai dari 1 lagi tiap kategori). */
.sl-no {
  margin-right: var(--space-6);
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
}
.sl-meta {
  grid-area: meta;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--space-8);
  margin-top: var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  line-height: 1.4;
  color: var(--ink-faint);
}
.sl-qty { font-weight: 600; color: var(--ink-muted); }
.sl-unit { white-space: nowrap; }
.sl-unit::after { content: ' /satuan'; }
/* Harga otomatis dari referensi PIHPS BI (js/harga-pangan.js), bukan
   diketik manual -- dibedakan warnanya (--accent) supaya kelihatan ini
   perkiraan. Sama seperti .slist-unit-price.is-ref-price di tabel lama. */
.sl-unit.is-ref-price { color: var(--accent); font-style: italic; }
.sl-price {
  grid-area: price;
  align-self: start;
  justify-self: end;
  font-family: var(--font-mono);
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  white-space: nowrap;
}
.sl-row.done .sl-name { text-decoration: line-through; color: var(--ink-faint); }
.sl-row.done .sl-price { color: var(--ink-faint); }
.sl-row.done .sl-meta { opacity: .7; }

.sl-actions {
  grid-area: act;
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
#shoppingListContainer .sl-actions .slist-edit-btn,
#shoppingListContainer .sl-actions .slist-del-btn {
  width: 28px;
  height: 28px;
  background: transparent;
  color: var(--ink-muted);
  border-radius: var(--radius-pill);
  font-size: var(--text-base);
}
#shoppingListContainer .sl-actions .slist-edit-btn:hover { background: var(--accent-lt); color: var(--accent); }
#shoppingListContainer .sl-actions .slist-del-btn:hover { background: var(--danger-lt); color: var(--danger); }
#shoppingListContainer .sl-actions .slist-edit-btn:focus-visible,
#shoppingListContainer .sl-actions .slist-del-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
/* Mouse: aksi diredupkan sampai baris di-hover / difokus keyboard. Layar
   sentuh tidak punya hover, jadi di sana aksi selalu tampil penuh. */
@media (hover: hover) {
  .sl-actions { opacity: .45; transition: opacity .15s ease; }
  .sl-row:hover .sl-actions,
  .sl-row:focus-within .sl-actions { opacity: 1; }
}
/* Layar sentuh: area ketuk lebih besar (menimpa aturan global 40px milik
   .slist-edit-btn/.slist-del-btn -- 40px terlalu tinggi untuk baris 2-tingkat). */
@media (hover: none) and (pointer: coarse) {
  #shoppingListContainer .sl-actions .slist-edit-btn,
  #shoppingListContainer .sl-actions .slist-del-btn { width: 36px; height: 36px; }
}

/* Hp: harga naik ke baris nama, tombol aksi turun ke baris kedua (sejajar
   qty/harga satuan) supaya kolom nama tetap lebar. */
@media (max-width: 640px) {
  .sl-group-head { padding: var(--space-8) var(--space-10); gap: var(--space-8); }
  .sl-row {
    grid-template-columns: 20px minmax(0, 1fr) auto;
    grid-template-areas:
      "check name price"
      "check meta act";
    column-gap: var(--space-10);
    padding: var(--space-9) var(--space-10);
  }
  .sl-row.is-readonly {
    grid-template-areas:
      "check name price"
      "check meta meta";
  }
  .sl-actions { justify-self: end; }
}

.slist-empty { font-size: var(--text-sm); color: var(--ink-faint); text-align: center; padding: var(--space-26) 0; }
.slist-actions { display: flex; gap: var(--space-8); flex-wrap: wrap; }
.slist-actions .btn { flex: 1; min-width: 140px; }

/* Anggaran Tahunan hanya memiliki satu kartu ringkasan; buat kartu tersebut
   memakai seluruh lebar grid agar tidak meninggalkan dua kolom kosong. */
.annual-budget-summary-grid { grid-template-columns: minmax(0, 1fr); }

/* ── Belanja Bulanan: sedikit lebih lega di layar lebar (desktop/tablet)
   supaya 6 kolom (checkbox, nama, qty, kategori, harga, aksi) tidak
   berdesakan -- .slist-modal khusus dipakai di modal ini saja, jadi tidak
   memengaruhi modal ".wide" lain yang berbagi class yang sama. */
@media (min-width: 641px) {
  .modal-content.wide.slist-modal { max-width: 860px; }
}

/* ── Belanja Bulanan: optimasi layar hp ── */
@media (max-width: 640px) {
  .slist-summary-card { padding: var(--space-12) var(--space-15); margin-bottom: var(--space-10); }
  .slist-summary-strip { margin-bottom: var(--space-10); }
  .slist-summary-strip .slist-summary-card { padding: var(--space-12) var(--space-15) var(--space-14); margin-bottom: 0; }
  .slist-summary-value { font-size: var(--text-2xl); }
  .slist-budget-warnings { margin-bottom: var(--space-10); }
  .slist-forecast-card { padding: var(--space-12) var(--space-14); margin-bottom: var(--space-10); }
  .slist-forecast-yearly-value { font-size: var(--text-lg); }
  .slist-viewer-notice { margin-bottom: var(--space-10); }

  /* Kartu barang di hp: dari grid 6-kolom (desktop) balik jadi flexbox yang
     disusun ulang pakai `order`, TANPA mengubah urutan elemen di HTML (semua
     elemen sudah flat/sejajar, lihat js/budget.js -- Anggaran Tahunan; Daftar
     Belanja sendiri memakai .sl-*, di bawah). Hasilnya kartu
     PAS 2 baris (kalau ada harga) atau 1 baris (kalau tidak):
       Baris 1: checkbox + nama + badge kategori
       Baris 2: qty + harga satuan + subtotal (kiri) + tombol ubah/hapus (kanan)
     Baris baru dipaksa lewat ::before kosong (order di antara qty & harga,
     flex-basis 100%, tinggi 0) -- BUKAN dengan flex-basis 100% di elemen
     harga itu sendiri seperti sebelumnya, karena itu bikin harga satuan
     dan subtotal masing-masing dapat baris SENDIRI (3 baris, boros tempat)
     alih-alih sebaris berdua. Trik ::before ini cuma memaksa baris baru
     dimulai, elemen-elemen sesudahnya (order lebih besar) tetap dikemas
     berdampingan di baris baru itu seperti biasa. */
  .slist-item {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    row-gap: var(--space-3);
    padding: var(--space-9) var(--space-10);
  }
  .slist-checkbox { order: 1; }
  .slist-name { order: 2; flex: 1 1 auto; min-width: 0; }
  /* Badge kategori ditaruh sebaris dengan nama barang (bukan baris
     sendiri lagi) supaya lebih hemat ruang -- max-width dibatasi &
     ellipsis (aturan dasar .slist-cat-badge di atas) menjaga badge
     kategori panjang tidak mendesak nama barang jadi terlalu sempit. */
  .slist-cat-badge {
    order: 3;
    flex: 0 1 auto;
    max-width: 38%;
    margin-left: var(--space-6);
  }
  .slist-cat-badge:empty { flex-basis: 0; margin: 0; }
  .slist-item::before {
    content: '';
    order: 5;
    flex-basis: 100%;
    height: 0;
  }
  .slist-qty { order: 6; margin-right: var(--space-6); }
  .slist-unit-price {
    order: 7;
  }
  .slist-unit-price:empty { display: none; }
  .slist-unit-price::after {
    content: '/satuan';
    margin-left: var(--space-2);
    font-size: var(--text-2xs);
  }
  .slist-unit-price:empty::after { content: none; }
  .slist-price {
    order: 7;
    margin-left: var(--space-6);
  }
  .slist-price:not(:empty)::before {
    content: '· ';
  }
  .slist-trail {
    order: 8;
    margin-left: auto;
    gap: var(--space-6);
  }
  .slist-budget-warning { font-size: var(--text-xs); padding: var(--space-8) var(--space-11); }

  /* Target ketuk edit/hapus diperbesar khusus hp (jempol > kursor mouse),
     ukuran visual ikon tetap sama supaya tidak mendominasi baris. */
  .slist-edit-btn, .slist-del-btn { width: 30px; height: 30px; }
  #annualBudgetItemsContainer .slist-item > .slist-edit-btn { order: 8; margin-left: auto; }
  #annualBudgetItemsContainer .slist-item > .slist-trail { order: 8; margin-left: var(--space-6); }
}

/* ── Report ── */
.report-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-12);
  margin-bottom: var(--space-20);
}
.report-stat-card {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-14) var(--space-18);
  text-align: center;
}
.report-stat-label {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  text-transform: none;
  letter-spacing: 0.07em;
  font-weight: 500;
}
.report-stat-value {
  font-size: var(--text-xl);
  font-weight: 500;
  margin-top: var(--space-6);
  letter-spacing: -0.02em;
}

.report-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-xs);
  margin-top: var(--space-20);
}
.report-table th, .report-table td {
  border: 1.5px solid var(--rule);
  padding: var(--space-7) var(--space-10);
  text-align: left;
}
.report-table th {
  background: var(--paper-warm);
  font-weight: 500;
  color: var(--ink-faint);
  font-size: var(--text-2xs);
  text-transform: none;
  letter-spacing: 0.06em;
}
.report-table-wrap { overflow-x: auto; }

/* ── Laporan Bulanan (monthly report modal): dipakai generateMonthlyReport()
   di js/report.js. Sebelumnya wrapper tabel pakai overflow:hidden, jadi di
   hape konten yang lebih lebar dari layar KEPOTONG (bukan bisa di-scroll).
   Diganti overflow-x:auto (scroll horizontal), dan grid ringkasan jadi
   1 kolom di layar sempit supaya tidak gepeng. ── */
.laporan-summary-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-12);
}
.laporan-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
/* [UI OPTIMASI RUANG] Grid kartu kompak untuk "Pengeluaran per Kategori"
   di modal Laporan Bulanan (js/report.js generateMonthlyReport) -- pola
   sama seperti .expense-chart-legend di dashboard: tiap kartu dibatasi
   lebar wajar (minmax) supaya isinya tidak melar aneh, tapi grid otomatis
   nambah kolom (auto-fill) begitu modal cukup lebar, alih-alih nyisain
   whitespace kosong di sisi kanan seperti tabel 4-kolom lama. */
.laporan-cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr));
  gap: var(--space-10);
}
@media (max-width: 480px) {
  .laporan-summary-grid { grid-template-columns: 1fr; }
}

/* ── Account Modal ── */
.acc-modal-list { margin-bottom: var(--space-14); }
.acc-modal-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-10) var(--space-12);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  margin-bottom: var(--space-6);
  background: var(--paper);
  cursor: pointer;
  transition: all 0.12s;
}
.acc-modal-item:hover { background: var(--paper-warm); }
.acc-modal-item.current { border-color: var(--success); background: var(--success-lt); }
.acc-modal-item-name { font-size: var(--text-base); font-weight: 500; color: var(--ink); }
.acc-modal-item-url  { font-size: var(--text-2xs); color: var(--ink-faint); font-family: monospace; }

.acc-modal-item-badge {
  font-size: var(--text-2xs); font-weight: 500; padding: var(--space-2) var(--space-7);
  border-radius: var(--radius-sm); white-space: nowrap;
}
.acc-badge-active { background: var(--success-lt); color: var(--success); }
.acc-badge-locked { background: var(--warning-lt); color: var(--warning); }
.acc-badge-noconn { background: var(--paper-warm); color: var(--ink-faint); }

.acc-item-actions { display: flex; gap: var(--space-5); align-items: center; }

/* ── Setup ── */
.setup-step {
  display: flex;
  align-items: flex-start;
  gap: var(--space-12);
  margin-bottom: var(--space-14);
}
.setup-step-num {
  width: 22px; height: 22px; min-width: 22px;
  background: var(--ink);
  color: var(--paper);
  border-radius: 50%;
  font-size: var(--text-2xs);
  font-weight: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: var(--space-2);
  flex-shrink: 0;
}
.setup-step-text { font-size: var(--text-xs); color: var(--ink-muted); line-height: 1.5; }

.setup-status {
  font-size: var(--text-xs);
  padding: var(--space-7) var(--space-10);
  margin-bottom: var(--space-10);
  display: none;
}
.setup-status.error   { background: var(--danger-lt);  color: var(--danger);  display: block; }
.setup-status.warning { background: var(--warning-lt); color: var(--warning); display: block; }
.setup-status.session { background: var(--success-lt); color: var(--success); display: block; }

/* ── Setup Awal (#firstTimeSetupModal) — Layar Penuh ──
   [REDESIGN SETUP AWAL] Sama semangatnya dengan #passwordLockScreen /
   #skLoginGateScreen di bawah: selagi .show aktif, ini BUKAN modal
   mengambang dgn backdrop gelap di atas dashboard, tapi layar penuh
   sendiri (gradasi emerald-lembut yang sama supaya konsisten dgn layar
   kunci), dan sidebar/FAB app disembunyikan total lewat body.sk-setup-active
   di bawah (dipasang window.openSetupModal, dilepas window.closeModal --
   keduanya di js/settings.js & js/utils.js) supaya user tidak pernah
   melihat shell app kosong (sidebar "Dashboard" dsb tanpa data) di
   belakang form setup. z-index 9600 -- di atas UI app (maks ~3002) tapi
   sengaja di BAWAH #manualModal/#passwordLockScreen/#skLoginGateScreen
   (semua 9999) supaya "Panduan Pengguna & Setup" yang dibuka dari sini
   (window.toggleManual) tetap menimpa layar ini, bukan malah ketutupan. */
/* [FIX SETUP TIDAK BISA DI-SCROLL] Sebelumnya overflow-y:auto dipasang di
   .setup-screen-scroll (anak di dalam .modal-content), tapi .modal-content
   tidak punya height eksplisit -- height:100% di .setup-screen-scroll jadi
   TIDAK PERNAH resolve (aturan CSS: height persen butuh induk dengan height
   pasti), jadi elemen itu cuma auto-height selebar kontennya & TIDAK PERNAH
   benar-benar overflow di dalam dirinya sendiri. Sementara elemen TERLUAR
   (#firstTimeSetupModal.show sendiri, yang sudah punya height:100% pasti
   dari inset:0) sama sekali tidak diberi overflow-y -- akibatnya begitu
   section 3 "Keamanan" mendorong total tinggi konten melebihi viewport
   (lazim di layar laptop pendek), sisanya kepotong habis, tidak bisa
   dijangkau scroll apa pun. Sekarang overflow-y:auto dipindah ke elemen
   TERLUAR ini (yang tingginya sudah pasti = viewport), scroll-nya jadi
   nyata & selalu berfungsi berapa pun panjang kontennya. */
#firstTimeSetupModal.show {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(160deg, var(--accent-lt) 0%, var(--paper-warm) 55%, var(--paper-warm) 100%);
  z-index: 9600;
  display: block;
  padding: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
[data-theme="dark"] #firstTimeSetupModal.show { background: var(--paper-warm); }
#firstTimeSetupModal.show .modal-content {
  background: transparent;
  border: none;
  box-shadow: none;
  border-radius: 0;
  width: 100%;
  max-width: none;
  max-height: none;
  overflow: visible;
  padding: 0;
}
.setup-screen-scroll {
  /* [FIX] min-height pakai satuan viewport (100vh), BUKAN persen (100%) --
     persen butuh induk ber-height pasti (lihat catatan di atas), 100vh
     selalu resolve sendiri berapa pun tinggi induknya. Cuma dipakai supaya
     gradasi latar tetap penuh 1 layar saat konten pendek; scroll
     sesungguhnya sudah ditangani #firstTimeSetupModal.show di atas, bukan
     elemen ini lagi -- jangan pasang overflow-y di sini juga (double
     scrollbar bersarang, bukan perbaikan). */
  min-height: 100vh;
  min-height: 100dvh;
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  align-items: center; /* form di tengah layar (vertikal); konten tinggi tetap bisa di-scroll */
  padding: var(--space-40) var(--space-20) var(--space-50);
}
.setup-card { width: 100%; max-width: 460px; }

.setup-brand { display: flex; flex-direction: column; align-items: center; text-align: center; margin-bottom: var(--space-24); }
.setup-brand-badge {
  width: 44px; height: 44px;
  border-radius: var(--radius);
  background: var(--accent);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: var(--space-10);
}
.setup-brand-name { font-family: var(--font-display); font-weight: 700; font-size: var(--text-lg); color: var(--ink); letter-spacing: .01em; }

.setup-card-head { text-align: center; margin-bottom: var(--space-24); }
.setup-card-title { font-family: var(--font-display); font-weight: 700; font-size: var(--text-2xl); color: var(--ink); margin-bottom: var(--space-6); }
.setup-card-sub { font-size: var(--text-sm); color: var(--ink-muted); line-height: 1.6; max-width: 380px; margin: 0 auto; }

/* [PROFESIONAL] Sebelumnya kotak border penuh-lebar dgn ikon -- terasa
   seperti satu "langkah" tambahan yg mendesak dibaca. Sekarang link teks
   kecil biasa, tetap ada tapi tidak minta perhatian sebesar form itu sendiri. */
.setup-guide-link {
  display: inline-block;
  background: none;
  border: none;
  padding: var(--space-4) 0;
  margin-top: var(--space-10);
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--ink-faint);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color .15s;
}
.setup-guide-link:hover { color: var(--ink); }

.setup-section {
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: var(--space-18);
  margin-bottom: var(--space-14);
}
.setup-section-head { display: flex; align-items: center; gap: var(--space-10); margin-bottom: var(--space-16); }
.setup-section-num {
  flex-shrink: 0;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: var(--text-xs);
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.setup-section-title { font-weight: 700; font-size: var(--text-sm); color: var(--ink); }

.setup-field-hint { font-size: var(--text-2xs); color: var(--ink-faint); margin-top: var(--space-4); line-height: 1.5; }

/* Tombol "Tampilkan/Sembunyikan" di dalam field password/key -- sama
   pola dgn .lock-eye-btn di layar kunci, supaya bahasa UI konsisten. */
.setup-field-eye-wrap { position: relative; }
.setup-field-eye-wrap .form-control { padding-right: var(--space-56); }
.setup-eye-btn {
  position: absolute;
  right: 10px; top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--ink-faint);
  padding: var(--space-4);
}
.setup-eye-btn:hover { color: var(--ink); }

.setup-warning-box {
  display: flex; align-items: flex-start; gap: var(--space-8);
  background: var(--warning-lt);
  border: 1px solid color-mix(in srgb, var(--warning) 45%, var(--warning-lt));
  border-radius: var(--radius-sm);
  padding: var(--space-10) var(--space-12);
  font-size: var(--text-xs);
  color: var(--warning);
  line-height: 1.6;
  margin-top: var(--space-4);
}
.setup-warning-box .sk-icon { margin-top: 1px; flex-shrink: 0; }

.setup-submit-btn { width: 100%; padding: var(--space-12); font-size: var(--text-base); margin-bottom: var(--space-14); }
.setup-footnote { text-align: center; font-size: var(--text-2xs); color: var(--ink-faint); }

@media (max-width: 480px) {
  .setup-screen-scroll { padding: var(--space-24) var(--space-14) var(--space-40); }
  .setup-section { padding: var(--space-14); }
}

/* Selama layar Setup Sinarkeu aktif (body class dipasang oleh
   window.openSetupModal, dilepas oleh window.closeModal), sembunyikan
   total sidebar, FAB, dan sisa UI app (.container -- header/top bar dgn
   hamburger + Dashboard) supaya BENAR-BENAR cuma form setup yang
   kelihatan, persis semangat body.lockscreen-restricted di atas untuk
   #passwordLockScreen. */
body.sk-setup-active #appSidebar,
body.sk-setup-active #aiChatFab,
body.sk-setup-active #skCalcFab,
body.sk-setup-active #skCalcPanel,
body.sk-setup-active .container { display: none !important; }

/* ── Lock Screen ── */
#passwordLockScreen {
  position: fixed;
  inset: 0;
  background: linear-gradient(160deg, var(--accent-lt) 0%, var(--paper-warm) 55%, var(--paper-warm) 100%);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  padding: var(--space-24);
}
/* [ANTI-FLASH LOCKSCREEN] Sesi masih sah (class dipasang js/boot-early.js) -> layar kunci
   tidak digambar sama sekali selagi script dimuat. Inline style.display dari JS
   (mis. 'flex' saat memang harus mengunci) tetap menang atas aturan ini. */
html.sk-session-ok #passwordLockScreen { display: none; }

/* [SECURITY FIX] Saat user klik "＋ Tambah akun baru" di layar kunci
   (window.openAccountManagerFromLock, js/account.js), password BELUM
   diverifikasi sama sekali -- tapi sebelum fix ini, Setelan yang terbuka
   memberi akses penuh ke sidebar (Dashboard, Laporan, Cadangan Data, dst)
   DAN semua panel Setelan lain (Reset Total Aplikasi, Arsipkan & Kosongkan
   Database, kredensial Database Cloud/Telegram/AI, dll) tanpa password sama
   sekali. Selama body punya class ini, sembunyikan total sidebar & di
   halaman Setelan cuma tampilkan panel "akun" -- satu-satunya jalan keluar
   adalah tombol "Kembali ke Layar Kunci" (window.backToLockScreenFromAkun)
   yang melepas class ini lagi. Lihat juga pelepasan defensifnya di
   window.submitLockPassword (js/app.js) saat password benar. */
body.lockscreen-restricted #appSidebar { display: none !important; }
/* [SIDEBAR-COLLAPSE] Tombol ini sudah bukan child #appSidebar lagi (lihat
   index.html), jadi harus ikut disembunyikan manual saat sidebar
   disembunyikan oleh gate keamanan di atas -- kalau tidak, tombolnya akan
   tetap tampil (dan bisa diklik) walau sidebar-nya sendiri sudah
   disembunyikan. */
body.lockscreen-restricted #aiChatFab,
body.lockscreen-restricted #skCalcFab,
body.lockscreen-restricted #skCalcPanel { display: none !important; }
/* Tombol mengambang "Tanya Sinarkeu" disembunyikan selagi modal chat-nya
   sendiri terbuka (di hape tombol ini menimpa tombol kirim di kolom input).
   Class body.ai-chat-open dipasang oleh pengamat di akhir js/ai.js. */
body.ai-chat-open #aiChatFab,
body.ai-chat-open #skCalcFab,
body.ai-chat-open #skCalcPanel { display: none !important; }
/* [FAB HANYA DI DASHBOARD] Tombol mengambang "Tanya Sinarkeu" cuma relevan
   di layar Dashboard utama -- disembunyikan begitu user pindah ke Setelan
   (body.view-settings, lihat js/settings.js window.openSetelanModal) atau
   ke menu full-page manapun di sidebar seperti Laporan/Anggaran/SinarMedia/
   dst (body.view-fullpage, lihat window.FULLVIEW_MODALS & window.openModal
   di js/utils.js). Balik ke Dashboard (window.showDashboardView melepas
   kedua class ini) langsung memunculkan FAB lagi tanpa perlu logic JS
   tambahan -- murni CSS mengikuti class yang memang sudah dipasang app
   untuk menandai halaman aktif. */
body.view-settings #aiChatFab,
body.view-fullpage #aiChatFab,
body.view-settings #skCalcFab,
body.view-fullpage #skCalcFab,
body.view-settings #skCalcPanel,
body.view-fullpage #skCalcPanel,
html.sk-restoring-view #skCalcFab,
html.sk-restoring-view #skCalcPanel { display: none !important; }
body.lockscreen-restricted #setelanModal .setelan-tab-panel:not([data-tab-panel="akun"]) {
  display: none !important;
}
@media (min-width: 1024px) {
  body.lockscreen-restricted #setelanModal { margin-left: 0 !important; }
}

/* [MULTIROLE GATE] Sama persis posisinya dengan #passwordLockScreen (fixed,
   full-screen, z-index sama) supaya menutup total UI app di belakangnya --
   TIDAK ADA tombol tutup/skip di sini secara sengaja. Lihat
   window.skShowLoginGate di js/auth.js. */
#skLoginGateScreen {
  position: fixed;
  inset: 0;
  background: linear-gradient(160deg, var(--accent-lt) 0%, var(--paper-warm) 55%, var(--paper-warm) 100%);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  padding: var(--space-24);
  overflow-y: auto;
}

.lock-card-wrap {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}

.lock-footer {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-8);
  padding-top: 10px;
}

.lock-card {
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: var(--space-36) var(--space-32);
  width: 100%;
  max-width: 380px;
  text-align: center;
}

.lock-title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  margin-bottom: var(--space-24);
  color: var(--ink);
}

.lock-input-wrap {
  position: relative;
  margin-bottom: var(--space-12);
}

.lock-input {
  width: 100%;
  padding: var(--space-12) var(--space-56) var(--space-12) var(--space-14);
  font-size: var(--text-base);
  font-family: inherit;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  letter-spacing: 2px;
  color: var(--ink);
}
.lock-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-lt); }
.lock-input:disabled { background: var(--paper-warm); color: var(--ink-faint); cursor: wait; }
.lock-input.error-shake {
  border-color: var(--danger);
  animation: shake 0.4s ease;
}
@keyframes shake {
  0%,100%{ transform: translateX(0); }
  20%    { transform: translateX(-7px); }
  40%    { transform: translateX(7px); }
  60%    { transform: translateX(-4px); }
  80%    { transform: translateX(4px); }
}

.lock-eye-btn {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--ink-faint);
  padding: 0;
  line-height: 1;
}
.lock-eye-btn:disabled { cursor: wait; opacity: .5; }

.lock-status {
  font-size: var(--text-xs);
  margin-top: var(--space-10);
  min-height: 16px;
  color: var(--danger);
  font-weight: 400;
}

.lock-warning {
  background: var(--warning-lt);
  border: 1px solid var(--warning);
  border-radius: var(--radius-sm);
  padding: var(--space-10) var(--space-12);
  font-size: var(--text-xs);
  color: var(--warning);
  margin-top: var(--space-14);
  text-align: left;
  line-height: 1.6;
}

.pwd-strength {
  height: 2px;
  border-radius: var(--radius-sm);
  background: var(--rule);
  margin-top: var(--space-6);
  overflow: hidden;
}
.pwd-strength-fill {
  height: 100%;
  transition: width 0.3s, background 0.3s;
  width: 0%;
}

.lock-account-picker {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  margin-bottom: var(--space-18);
}
.lock-account-item {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  padding: var(--space-10) var(--space-14);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all 0.12s;
  text-align: left;
  background: var(--paper);
  font-family: inherit;
  width: 100%;
}
.lock-account-item:hover { border-color: var(--accent); background: var(--accent-lt); }
.lock-account-item.selected { border-color: var(--accent); background: var(--accent-lt); }

.lock-account-avatar {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-size: var(--text-sm);
  font-weight: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.lock-account-info { flex: 1; }
.lock-account-name { font-size: var(--text-base); font-weight: 500; color: var(--ink); }
.lock-account-sub  { font-size: var(--text-2xs); color: var(--ink-faint); margin-top: var(--space-1); }
.lock-account-check { font-size: var(--text-lg); opacity: 0; transition: opacity 0.12s; }
.lock-account-item.selected .lock-account-check { opacity: 1; }

.lock-add-account {
  font-size: var(--text-xs);
  color: var(--ink-faint);
  cursor: pointer;
  background: none;
  border: none;
  font-family: inherit;
  text-decoration: underline;
}
.lock-add-account:hover { color: var(--ink); }

.lock-footer-sep { font-size: var(--text-xs); color: var(--ink-faint); }

.lock-manual-btn {
  background: none;
  border: none;
  color: var(--accent);
  font-weight: 500;
  cursor: pointer;
  text-decoration: underline;
  font-size: var(--text-xs);
  font-family: inherit;
}
.lock-manual-btn:hover { color: var(--accent); }

/* ── Special Buttons ── */
.telegram-badge { background: #185FA5; color: var(--paper); border-color: #185FA5; }
.telegram-badge:hover:not(:disabled) { background: #0C447C; border-color: var(--accent); }

/* ── Scrollbar (disembunyikan di semua elemen; scroll tetap jalan) ── */
* {
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE/Edge lama */
}
::-webkit-scrollbar { width: 0; height: 0; display: none; } /* Chrome/Safari/WebView */

/* ── Responsive helpers ── */
.desktop-only { display: inline-flex; }
.mobile-only  { display: none; }

.budget-mini-progress-row { display: none; }

/* [UI] Dropdown pilih buku & tombol hamburger drawer harus SELALU sebaris
   (tidak boleh pindah baris terpisah) di sepanjang rentang lebar hamburger
   masih tampil (0-1023px, lihat .hamburger-btn-icon). Sebelumnya perbaikan
   "satu baris" (nowrap + scroll horizontal) cuma ada di breakpoint
   max-width:640px, jadi di rentang tablet 641-1023px .book-selector balik
   pakai flex-wrap:wrap bawaan (baris 296) dan bisa pecah ke baris baru kalau
   sempit. Diperlebar ke max-width:1023px, sejalan dengan breakpoint
   #appSidebar (sidebar desktop baru aktif >=1024px). */
@media (max-width: 1023px) {
  .book-selector {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 2px;
  }
  .book-selector > *:not(.book-select):not(.cs-wrapper) { flex-shrink: 0; }
  .book-select { min-width: 110px; }
  .book-selector > .cs-wrapper.compact {
    flex: 1 1 auto;
    min-width: 90px;
  }
  .book-selector > .cs-wrapper.compact .cs-trigger {
    min-width: 0;
  }
}

@media (max-width: 640px) {
  .desktop-only { display: none !important; }
  .mobile-only  { display: inline-flex !important; }
  /* Harga Komoditas: daftar kompak desktop diganti kartu ala-app di hape */
  .hk-compact-list { display: none !important; }
  .hk-card-list { display: flex; flex-direction: column; gap: var(--space-10); margin-bottom: var(--space-20); }
  body { padding: 0; }
  .container { padding: 0 var(--space-16) var(--space-32); }
  .account-bar { padding: 0 var(--space-16); }
  .header { flex-direction: column; align-items: flex-start; gap: var(--space-10); }
  /* [UI] Semua item top bar jadi SATU BARIS di hape: flex-wrap dimatikan
     (sebelumnya "wrap" bikin item pindah ke baris berikutnya kalau tidak
     muat), diganti scroll horizontal supaya tidak ada yang kepotong/hilang. */
  .book-selector {
    flex-wrap: nowrap;
    gap: var(--space-8);
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 2px;
  }
  /* Label, badge, dan tombol tidak boleh menyusut (nanti tulisannya gepeng);
     dropdown buku (.book-select) sengaja DIKECUALIKAN supaya lebar minimumnya
     sendiri (diatur di bawah) yang menentukan, bukan flex-shrink:0 di sini. */
  .book-selector > *:not(.book-select) { flex-shrink: 0; }
  .book-select { min-width: 110px; }

  /* [UI] Khusus tampilan hape: sembunyikan badge waktu sinkronisasi terakhir
     supaya top bar hanya berisi status DATABASE CLOUD ON, dropdown buku, dan
     tombol hamburger. */
  #syncTimeBadge { display: none !important; }

  /* [UI] Dropdown pilih buku melebar mengisi sisa ruang top bar (tidak ada
     ruang kosong) karena item lain sudah diminimalkan di tampilan hape. */
  .book-selector > .cs-wrapper.compact {
    flex: 1 1 auto;
    min-width: 0;
    width: auto;
  }
  .book-selector > .cs-wrapper.compact .cs-trigger {
    max-width: none;
    min-width: 0;
    width: 100%;
  }

  /* [UI] Tombol Menu jadi icon 3 garis (bukan teks) sejak lebar 0-1023px
     (lihat aturan .hamburger-btn-icon unconditional di dekat definisi
     .hamburger-btn), warna mengikuti tema (terang = bg terang, gelap = bg
     gelap) dan bentuk lebih rounded. */

  /* [UI] Tabel transaksi di hape: tampilkan hanya kolom Tanggal, Deskripsi,
     Pemasukan, Pengeluaran. Sembunyikan No, Kategori, Saldo, Nota, Aksi. */
  /* [FIX UX] Seluruh baris jadi area tap (lihat listener di render.js)
     untuk buka menu Ubah/Hapus, tapi tidak ada penanda visual bahwa baris
     bisa disentuh sejak kolom Aksi disembunyikan di hape. Chevron redup
     ini ditaruh di kolom terakhir yang masih tampil (Pengeluaran) sebagai
     affordance -- bukan tombol, cuma isyarat "baris ini bisa di-tap". */
  #transactionTableBody tr { position: relative; }
  #transactionTableBody td.col-amount { padding-right: 22px; }
  #transactionTableBody td.col-amount::after {
    content: "";
    position: absolute;
    right: 6px;
    top: 50%;
    width: 6px;
    height: 6px;
    border-right: 1.5px solid var(--ink-faint);
    border-bottom: 1.5px solid var(--ink-faint);
    transform: translateY(-50%) rotate(-45deg);
  }

  table .col-no,
  table .col-category,
  table .col-saldo,
  table .col-nota,
  table .col-action {
    display: none;
  }
  /* [UI] Tanggal di hape pakai format singkat d/m/yy (mis. 20/7/26)
     tanpa jam, supaya kolom lebih ringkas. */
  .date-full  { display: none; }
  .date-short { display: inline; }
  table tbody tr { cursor: pointer; }
}

@media(min-width:769px) and (max-width:1024px) {
  table { min-width: unset; }
  .col-no, .col-nota { display: none; }
  .budget-mini {
    flex-direction: column;
    align-items: stretch;
    padding: 0;
    gap: 0;
    border: 1.5px solid var(--rule);
    overflow: hidden;
    margin-bottom: var(--space-20);
  }
  .budget-mini-info {
    display: grid;
    grid-template-columns: auto 1fr 1fr 1fr;
    align-items: center;
    gap: 0;
    padding: var(--space-14) var(--space-18) var(--space-12);
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    flex-wrap: unset;
  }
  .budget-mini-item {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
    padding: 0 var(--space-14);
    border-right: 1px solid var(--rule);
  }
  .budget-mini-item:first-child { padding-left: 0; }
  .budget-mini-item:last-child  { border-right: none; padding-right: 0; }
  .budget-mini-label { font-size: var(--text-2xs); font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-faint); }
  .budget-mini-value { font-size: var(--text-md); font-weight: 500; letter-spacing: -0.02em; }
  .budget-mini-info > .budget-mini-progress { display: none; }
  .budget-mini-info > span[id="budgetProgressPct"] { display: none; }
  .budget-mini-progress-row {
    display: flex !important;
    align-items: center;
    gap: var(--space-12);
    padding: var(--space-8) var(--space-18);
    background: var(--paper-warm);
    border-bottom: 1px solid var(--rule);
  }
  .budget-mini-progress-row .budget-mini-progress {
    flex: 1; width: unset; min-width: unset; height: 2px; display: block;
  }
  .budget-mini-progress-row #budgetProgressPct {
    font-size: var(--text-xs); font-weight: 500; min-width: 36px; text-align: right;
  }
  .budget-mini-actions {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0;
    background: var(--paper);
  }
  .btn-icon {
    border-radius: var(--radius-sm);
    border: none;
    border-right: 1px solid var(--rule);
    padding: var(--space-12) var(--space-10);
    font-size: var(--text-xs);
    font-weight: 500;
    text-align: center;
    justify-content: center;
    background: var(--paper);
    color: var(--ink-muted);
  }
  .btn-icon:last-child { border-right: none; }
  .btn-icon:hover { background: var(--paper-warm); color: var(--ink); }
  .budget-select { padding: var(--space-6) var(--space-10); font-size: var(--text-xs); }
  .report-stat-value { font-size: var(--text-md); }
  .report-stat-card { padding: var(--space-10) var(--space-12); }
  .report-table { font-size: var(--text-xs); }
  .report-table th, .report-table td { padding: var(--space-6) var(--space-8); }
}

@media(max-width:768px) {
  .container { padding: 0 var(--space-14) var(--space-28); }
  .header { flex-direction: column; align-items: flex-start; gap: var(--space-10); }
  .book-selector { width: 100%; justify-content: space-between; }
  .book-select { flex: 1 1 100%; min-width: 0; width: 100%; }
  .cs-wrapper.compact { flex: 1 1 100%; width: 100%; }
  .cs-wrapper.compact .cs-trigger { max-width: none; min-width: 0; width: 100%; }
  .cs-wrapper.compact .cs-dropdown { max-width: none; }
  .sync-status-container { font-size: var(--text-2xs); }
  .device-id-badge { display: none; }
  .sync-status-badge { display: none; }
  .sync-time-badge { display: none; }
  .budget-mini {
    flex-direction: column;
    align-items: stretch;
    padding: 0;
    gap: 0;
    overflow: hidden;
    margin-bottom: var(--space-14);
  }
  /* [UI] Info anggaran mobile: baris 1 = periode (bulan/tahun) + tag sumber,
     baris 2 = Target/Realisasi/Sisa dalam 3 kolom sejajar (bukan grid 2x2)
     supaya lebih ringkas & tidak makan tempat vertikal. */
  .budget-mini-info {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas:
      "period period period"
      "target realisasi sisa";
    gap: 0;
    padding: var(--space-8) var(--space-10) var(--space-6);
    border-bottom: 1px solid var(--rule);
    flex-wrap: unset;
  }
  .budget-mini-item {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-1);
    padding: var(--space-4) var(--space-6);
  }
  .budget-mini-item:nth-child(1) {
    grid-area: period;
    flex-direction: row;
    align-items: center;
    gap: var(--space-6);
    padding: 0 0 var(--space-7);
    margin-bottom: var(--space-6);
    border-bottom: 1px solid var(--rule);
  }
  .budget-mini-item:nth-child(2) { grid-area: target; }
  .budget-mini-item:nth-child(3) { grid-area: realisasi; border-left: 1px solid var(--rule); }
  .budget-mini-item:nth-child(4) { grid-area: sisa; border-left: 1px solid var(--rule); }
  .budget-mini-label { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: 0.04em; }
  .budget-mini-value { font-size: var(--text-sm); }
  .budget-mini-info > .budget-mini-progress { display: none; }
  .budget-mini-info > span[id="budgetProgressPct"] { display: none; }
  .budget-source-tag { margin-left: 0; }
  .budget-mini-progress-row {
    display: flex !important;
    align-items: center;
    gap: var(--space-8);
    padding: var(--space-6) var(--space-12);
    background: var(--paper-warm);
    border-bottom: 1px solid var(--rule);
  }
  .budget-mini-progress-row .budget-mini-progress { flex: 1; width: unset; min-width: unset; height: 3px; }
  .budget-mini-actions {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0;
  }
  .btn-icon {
    border-radius: var(--radius-sm);
    border: none;
    border-right: 1px solid var(--rule);
    padding: var(--space-9) var(--space-6);
    font-size: var(--text-xs);
    font-weight: 500;
    text-align: center;
    justify-content: center;
    color: var(--ink-muted);
  }
  .btn-icon:last-child { border-right: none; }
  .budget-select {
    font-size: var(--text-xs);
    padding: var(--space-4) var(--space-22) var(--space-4) var(--space-8);
    background-position: right 6px center;
  }
  .cs-wrapper.mini .cs-trigger {
    font-size: var(--text-xs);
    padding: var(--space-4) var(--space-7) var(--space-4) var(--space-8);
    min-height: 0;
  }
  .stats-grid { grid-template-columns: 1fr 1fr; gap: var(--space-10); }
  .stat-card { padding: var(--space-12) var(--space-14); }
  /* [UI OPTIMASI DASHBOARD] Diselaraskan ke --text-lg -- sama dengan ukuran
     angka sekunder desktop (stat-card-compact, fc-metric-value), bukan
     --text-md yang sebelumnya beda skala sendiri di breakpoint ini. */
  .stat-value { font-size: var(--text-lg); }
  .stat-label { font-size: var(--text-2xs); }
  .expense-chart-canvas-wrap { flex: 0 0 150px; max-width: 150px; height: 150px; }
  .expense-chart-canvas-wrap canvas { max-height: 150px !important; }
  .expense-chart-legend { min-width: 130px; }
  .legend-item { font-size: var(--text-xs); }
  .controls { flex-direction: column; align-items: stretch; gap: var(--space-8); }
  .filters { width: 100%; flex-wrap: wrap; gap: var(--space-6); }
  .search-input { width: 100%; }
  .filter-btn { flex: 1; justify-content: center; text-align: center; padding: var(--space-7) var(--space-4); }
  .date-quick-preset { width: 100%; padding: var(--space-6) var(--space-10); }
  .cs-wrapper.mini[data-cs-for="dateQuickPreset"] { width: 100%; }
  .cs-wrapper.mini[data-cs-for="dateQuickPreset"] .cs-trigger { width: 100%; padding: var(--space-6) var(--space-10); }
  .date-filter-box { width: 100%; padding: var(--space-3) var(--space-10); gap: var(--space-4); }
  .date-filter-box input { flex: 1; min-width: 0; font-size: var(--text-xs); padding: var(--space-6) var(--space-2); }
  .actions { display: grid; grid-template-columns: repeat(3, 1fr); width: 100%; gap: var(--space-6); }
  .actions .btn { min-width: 0; justify-content: center; font-size: var(--text-xs); padding: var(--space-9) var(--space-4); white-space: nowrap; }
  table { min-width: unset; font-size: var(--text-xs); }
  .col-no, .col-nota, .col-saldo { display: none; }
  th, td { padding: var(--space-9) var(--space-8); }
  .modal-content { margin: var(--space-10); max-width: calc(100% - 20px); max-height: calc(100vh - 20px); max-height: calc(100dvh - 20px); }
  .modal-content.wide { max-width: calc(100% - 20px); }
  .form-row { flex-direction: column; }
  .panel-actions-row { flex-direction: column; }
  .report-stats { grid-template-columns: 1fr 1fr; }
  .report-stat-value { font-size: var(--text-md); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ── Balance Privacy Toggle ── */
#balanceToggleBtn {
  opacity: 0.45;
  transition: opacity 0.2s, transform 0.15s;
  vertical-align: middle;
}
#balanceToggleBtn:hover {
  opacity: 1;
  transform: scale(1.15);
}

/* ── Fase Kehidupan Custom Dropdown ── */
.fase-dropdown {
  position: relative;
  user-select: none;
}

.fase-dropdown-trigger {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  padding: var(--space-10) var(--space-14);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
  min-height: 46px;
}
.fase-dropdown-trigger:hover {
  border-color: var(--fase);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fase) 12%, transparent);
}
.fase-dropdown.open .fase-dropdown-trigger {
  border-color: var(--fase);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fase) 15%, transparent);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

.fase-trigger-icon {
  font-size: var(--text-2xl);
  line-height: 1;
  flex-shrink: 0;
}
.fase-trigger-text {
  flex: 1;
  font-size: var(--text-sm);
  color: var(--ink);
}
.fase-trigger-text.placeholder {
  color: var(--ink-faint);
}
.fase-trigger-arrow {
  color: var(--ink-faint);
  flex-shrink: 0;
  transition: transform 0.2s;
}
.fase-dropdown.open .fase-trigger-arrow {
  transform: rotate(180deg);
  color: var(--fase);
}

.fase-dropdown-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0; right: 0;
  background: var(--paper);
  border: 1.5px solid var(--fase);
  border-top: none;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  z-index: 3000;
  overflow: hidden;
  animation: fadeDropdown 0.15s ease;
}
.fase-dropdown.open .fase-dropdown-menu {
  display: block;
}
@keyframes fadeDropdown {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.fase-option {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  padding: var(--space-10) var(--space-14);
  cursor: pointer;
  transition: background 0.12s;
  border-bottom: 1px solid var(--rule);
}
.fase-option:last-child { border-bottom: none; }
.fase-option:hover {
  background: var(--fase-lt);
}
.fase-option.selected {
  background: var(--fase-lt);
}
.fase-option.selected .fase-opt-title {
  color: var(--fase);
  font-weight: 600;
}

.fase-opt-icon {
  font-size: var(--text-2xl);
  line-height: 1;
  flex-shrink: 0;
  width: 28px;
  text-align: center;
}
.fase-opt-body {
  flex: 1;
}
.fase-opt-title {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink);
  line-height: 1.3;
}
.fase-opt-sub {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  margin-top: var(--space-2);
}

/* ======================================================
   DARK MODE — [data-theme="dark"]
   [GAYA HANDBOOK] "Dark technical infographic": latar hitam pekat
   (#080A09 halaman / #0E1210 kartu), teks putih bersih, border tipis
   #1E2622, dan SATU aksen neon emerald #22E07A (dengan glow tipis)
   untuk state aktif, tombol utama, angka kunci. Label kecil/badge pakai
   monospace (lihat blok "DARK MODE — GAYA HANDBOOK" di paling bawah file).
   Sebelumnya: cokelat-abu hangat rendah kontras (#232220/#2A2825).
   Hue: nuansa emerald (hue sama, beda lightness) untuk semua aksen/
   semantik. DUA pengecualian: danger/pengeluaran = merah (pembeda
   pemasukan vs pengeluaran) dan KUNING #F5D90A = penanda item AKTIF/
   sedang dipilih + peringatan (sesuai desain Handbook). Jangan tambah
   hue baru lain (biru/ungu/oranye) di token dark mode.
====================================================== */
[data-theme="dark"] {
  --ink:        #E8E8EA;
  --ink-muted:  #9A9AA0;
  --ink-faint:  #6E6E6E;
  --paper:      #161617;
  --paper-warm: #0F0F10;
  --rule:       #262628;
  --accent:     #CDF543;
  --accent-lt:  #1B2008;
  --success:    #A9D957;
  --success-lt: #161D0B;
  --danger:     #F0786B;
  --danger-lt:  #2B1613;
  --warning:    #E3B34A;
  --warning-lt: #2A210C;
  --hb-yellow:  #E8E8EA;   /* penanda item aktif/terpilih */
  --purple:     #A3A3A3;
  --purple-lt:  #1C1C1C;
  /* Brand (tombol utama) -- neon emerald, teks di atasnya gelap (--ink-inv) */
  --brand:      #CDF543;
  --brand-dark: #B4DA33;
  /* Glow tipis dipakai hover kartu/tombol/fokus input (dark saja) */
  --hb-glow:    color-mix(in srgb, #CDF543 14%, transparent);
  /* Sidebar & title bar -- ikut var(--paper-warm) seperti sebelumnya. */
  --topbar-bg:          var(--paper-warm);
  --topbar-text:        var(--ink);
  --topbar-text-muted:  var(--ink-muted);
  --topbar-border:      var(--rule);
  --topbar-btn-bg:      rgba(237,237,237,0.06);
  --topbar-btn-hover-bg: rgba(237,237,237,0.12);
  --topbar-item-color:  var(--ink-muted);
  --topbar-item-hover-bg: rgba(237,237,237,0.06);
  /* Menu aktif = tint kuning tipis + teks kuning (+ garis kiri, lihat
     blok Handbook di bawah). */
  --topbar-item-active-bg: rgba(255,255,255,0.08);
  --topbar-item-active-color: var(--ink);
  --topbar-footer-border: var(--rule);
  /* [FLAT] Sama seperti mode terang -- lihat catatan di :root paling atas. */
  --topbar-active-shadow: none;
  /* Balance Hero -- flat, ikut var(--ink)/var(--ink-muted). */
  --hero-text:       var(--ink);
  --hero-text-muted: var(--ink-muted);
  /* Extended palette — dark overrides (ikut emerald, lihat catatan atas) */
  --fase:       #B5B5B5;
  --fase-lt:    #1C1C1C;
  --info:       #B5B5B5;   /* [30 Okt 2026] biru dihapus dari mode gelap -> abu netral (sama seperti --fase) */
  --info-lt:    #1C1C1C;
  --chat-user:  #CDF543;
  --ink-inv:    #131706;   /* teks gelap di atas aksen neon */
  --paper-inv:  #E8E8EA;
  --row-alt:    #101010;
  --shadow-sm:  none;
  --shadow-md:  none;
  --shadow-lg:  none;
}

[data-theme="dark"] body {
  background: var(--paper-warm);
  color: var(--ink);
}

/* Account bar stays dark — slightly deeper in dark mode */
[data-theme="dark"] .account-bar {
  background: var(--row-alt);
  border-bottom-color: rgba(255,255,255,0.05);
}
[data-theme="dark"] .account-tab { border-right-color: rgba(255,255,255,0.05); }
[data-theme="dark"] .account-bar-add { border-left-color: rgba(255,255,255,0.05); }
[data-theme="dark"] .account-tab:hover { background: rgba(255,255,255,0.06); }
[data-theme="dark"] .account-tab.active { background: rgba(255,255,255,0.08); }

/* Inputs & selects */
[data-theme="dark"] input,
[data-theme="dark"] textarea {
  background-color: var(--paper);
  color: var(--ink);
  border-color: var(--rule);
}
/* Select dipisah agar background-image SVG panah tidak ikut ter-reset */
[data-theme="dark"] select {
  background-color: var(--paper);
  color: var(--ink);
  border-color: var(--rule);
}
[data-theme="dark"] input::placeholder { color: var(--ink-faint); }
[data-theme="dark"] .form-control { background-color: var(--paper); color: var(--ink); border-color: var(--rule); }
[data-theme="dark"] .form-control:focus { border-color: var(--ink); }

/* Modal */
[data-theme="dark"] .modal { background: rgba(0,0,0,0.55); }
[data-theme="dark"] .modal-content { background: var(--paper); border-color: var(--rule); }

/* Buttons */
[data-theme="dark"] button,
[data-theme="dark"] .btn,
[data-theme="dark"] .btn-secondary {
  background: var(--paper);
  border-color: var(--rule);
  color: var(--ink-muted);
}
[data-theme="dark"] button:hover:not(:disabled),
[data-theme="dark"] .btn:hover:not(:disabled) {
  background: var(--paper-warm);
  border-color: var(--ink-faint);
  color: var(--ink);
}
[data-theme="dark"] .btn-primary {
  background: var(--brand);
  color: var(--ink-inv);
  border-color: var(--brand);
}
[data-theme="dark"] .btn-primary:hover:not(:disabled) { background: var(--brand-dark); border-color: var(--brand-dark); }
[data-theme="dark"] .manage-books-btn {
  background: var(--brand);
  color: var(--ink-inv);
  border-color: var(--brand);
}
[data-theme="dark"] .manage-books-btn:hover:not(:disabled) { background: var(--brand-dark); }

/* Table */
[data-theme="dark"] th { background: var(--paper-warm); color: var(--ink-faint); }
[data-theme="dark"] td { color: var(--ink); border-color: var(--rule); }
[data-theme="dark"] tr:hover td { background: var(--accent-lt); }
[data-theme="dark"] .table-container { background: var(--paper); border-color: var(--rule); }

/* Cards / panels */
[data-theme="dark"] .stat-card { background: var(--paper); }
[data-theme="dark"] .stat-card:hover { background: var(--paper-warm); }
[data-theme="dark"] .expense-chart-section,
[data-theme="dark"] .forecast-card,
[data-theme="dark"] .budget-mini,
[data-theme="dark"] .log-section,
[data-theme="dark"] .data-management-panel { background: var(--paper); border-color: var(--rule); }
[data-theme="dark"] .fc-header { background: var(--paper-warm); }
[data-theme="dark"] .fc-cats { border-top-color: var(--rule); }
[data-theme="dark"] .fc-tag { background: var(--paper-warm); border-color: var(--rule); }
[data-theme="dark"] .budget-mini-progress { background: var(--rule); }
[data-theme="dark"] .category-badge { background: var(--paper-warm); border-color: var(--rule); color: var(--ink-muted); }

/* Tanya Sinarkeu FAB */
[data-theme="dark"] .ai-chat-fab { box-shadow: 0 4px 14px rgba(0,0,0,.5); }

/* Book select & filter */
[data-theme="dark"] .book-select { background: var(--paper); border-color: var(--rule); color: var(--ink); }
[data-theme="dark"] .search-input { background: var(--paper); border-color: var(--rule); color: var(--ink); }
[data-theme="dark"] .filter-btn { background: var(--paper); border-color: var(--rule); color: var(--ink-muted); }
[data-theme="dark"] .filter-btn.active { background: color-mix(in srgb, var(--accent) 22%, var(--paper)); color: var(--ink); border-color: color-mix(in srgb, var(--accent) 40%, var(--paper)); font-weight: 700; }
[data-theme="dark"] .date-quick-preset { background: var(--paper); border-color: var(--rule); color: var(--ink-muted); }
[data-theme="dark"] .date-filter-box { background: var(--paper); border-color: var(--rule); }
[data-theme="dark"] .date-filter-box input { color: var(--ink); }
[data-theme="dark"] .date-filter-box input[type="date"] { border: none; background: transparent; }

/* Pagination */
[data-theme="dark"] .page-btn { background: var(--paper); border-color: var(--rule); color: var(--ink-muted); }
[data-theme="dark"] .page-btn:hover:not(:disabled) { background: var(--paper-warm); border-color: var(--ink-faint); }
[data-theme="dark"] .page-btn.active { background: color-mix(in srgb, var(--accent) 22%, var(--paper)); color: var(--ink); border-color: color-mix(in srgb, var(--accent) 40%, var(--paper)); font-weight: 700; }

/* Toast */
[data-theme="dark"] .toast-message { background: var(--ink); color: var(--paper-warm); }

/* Lock screen */
[data-theme="dark"] #passwordLockScreen { background: var(--paper-warm); }
[data-theme="dark"] .lock-card { background: transparent; border-color: transparent; }
[data-theme="dark"] .lock-input { background: var(--paper); border-color: var(--rule); color: var(--ink); }
[data-theme="dark"] .lock-account-item { background: var(--paper); border-color: var(--rule); }
[data-theme="dark"] .lock-account-item:hover,
[data-theme="dark"] .lock-account-item.selected { background: var(--paper-warm); }
[data-theme="dark"] .lock-account-avatar { background: var(--ink); color: var(--paper-warm); }

/* Sync badge */
[data-theme="dark"] .device-id-badge { background: var(--ink); color: var(--paper-warm); }
[data-theme="dark"] .sync-time-badge { color: var(--ink-faint); }

/* Select arrow untuk dark mode */
[data-theme="dark"] select.form-control {
  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='%239A9A96' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
[data-theme="dark"] select.form-control option { background: var(--paper); color: var(--ink); }

/* Fase dropdown */
[data-theme="dark"] .fase-dropdown-trigger { background: var(--paper); border-color: var(--rule); }
[data-theme="dark"] .fase-dropdown-menu { background: var(--paper); border-color: var(--fase); }
[data-theme="dark"] .fase-option:hover { background: var(--fase-lt); }
[data-theme="dark"] .fase-option.selected { background: var(--fase-lt); }

/* Budget select */
[data-theme="dark"] .budget-select {
  background-color: var(--paper);
  border-color: var(--rule);
  color: var(--ink);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 24 24' fill='none' stroke='%239A9A96' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
}

/* Radio, checkbox, date, file — dark mode */
[data-theme="dark"] input[type="radio"],
[data-theme="dark"] input[type="checkbox"] {
  background: var(--paper);
  border-color: var(--rule);
}
[data-theme="dark"] input[type="radio"]:checked,
[data-theme="dark"] input[type="checkbox"]:checked {
  background: var(--paper-warm);
  border-color: var(--paper-warm);
}
[data-theme="dark"] input[type="radio"]:checked::after { background: var(--ink); }
[data-theme="dark"] input[type="checkbox"]:checked::after { border-color: var(--ink); }
[data-theme="dark"] input[type="date"] { background: var(--paper); border-color: var(--rule); color: var(--ink); }
[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(1); }
[data-theme="dark"] input[type="file"] { color: var(--ink-muted); }
[data-theme="dark"] input[type="file"]::file-selector-button { background: var(--paper-warm); color: var(--ink); border-color: var(--rule); }
[data-theme="dark"] input[type="file"]::file-selector-button:hover { background: var(--rule); }

/* Offline warning */
[data-theme="dark"] .offline-warning-bar { background: var(--warning-lt); border-color: color-mix(in srgb, var(--warning) 55%, black); }

/* Setelan panel overrides — undo inline light colors */

/* ── Dark Mode: override inline styles pada stat-cards khusus ── */
[data-theme="dark"] #cardAnggaranTahunan,
[data-theme="dark"] #cardDanaDarurat,
[data-theme="dark"] #cardKebutuhanSetahun,
[data-theme="dark"] #cardFaseKehidupan,
[data-theme="dark"] #cardDanaSalingJaga,
[data-theme="dark"] #goldCard,
[data-theme="dark"] #zakatCard {
  background: var(--paper) !important;
}

/* Sub-label ink-faint di stat-card (dark mode) */
[data-theme="dark"] #goldSource,
[data-theme="dark"] #zakatSource {
  color: var(--ink-faint) !important;
}

/* goldValueRow border dan teks */
[data-theme="dark"] #goldValueRow {
  border-top-color: var(--warning-lt) !important;
}
[data-theme="dark"] #goldValueLabel,
[data-theme="dark"] #goldValue {
  color: var(--warning) !important;
}

/* Fase kehidupan desc text */
[data-theme="dark"] #fcFaseDesc {
  color: var(--ink-faint) !important;
}
[data-theme="dark"] #fcDanaDaruratNote,
[data-theme="dark"] #fcDSJNote {
  color: var(--ink-faint) !important;
}

/* ======================================================
   CUSTOM SELECT DROPDOWN
   Menggantikan native <select> untuk: pilih buku,
   kategori pengeluaran, kategori pemasukan
====================================================== */

.cs-wrapper {
  position: relative;
  display: inline-block;
  width: 100%;
}

/* Trigger button */
.cs-trigger {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  width: 100%;
  padding: var(--space-7) var(--space-10) var(--space-7) var(--space-12);
  font-size: var(--text-sm);
  font-weight: 400;
  font-family: inherit;
  background: var(--paper);
  color: var(--ink);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s, box-shadow 0.15s;
  min-height: 32px;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
}
.cs-trigger:hover { border-color: var(--ink-faint); }
.cs-trigger:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-lt); }
.cs-wrapper.open .cs-trigger {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-lt);
}

.cs-trigger-text {
  flex: 1;
  display: flex;
  align-items: center;
  gap: var(--space-8);
  overflow: hidden;
  min-width: 0;
}
.cs-trigger-text.placeholder { color: var(--ink-faint); }
.cs-trigger-name {
  /* [FIX] min-width:0 WAJIB ada supaya flex-item ini bisa menyusut di bawah
     lebar konten aslinya -- tanpa ini, default flex min-width:auto bikin
     ellipsis (text-overflow) di atas TIDAK PERNAH aktif saat ruang sempit.
     Akibatnya nama akun panjang (mis. "Bank Rakyat Indonesia") memaksa
     .cs-trigger-balance (flex-shrink:0) terdorong keluar & ke-crop kasar
     oleh overflow:hidden induknya (.cs-trigger) -- bukannya nama yang
     dipotong "...", malah ANGKA SALDO yang kepotong mentah tanpa elipsis. */
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cs-trigger-balance {
  flex-shrink: 0;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.cs-trigger-icon {
  flex-shrink: 0;
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  transition: transform 0.2s;
  line-height: 1;
  margin-left: auto;
  padding-left: 4px;
}
.cs-wrapper.open .cs-trigger-icon { transform: rotate(180deg); }

/* Dropdown panel */
.cs-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 100%;
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  /* Harus lebih tinggi dari z-index modal nested di mobile (2100, lihat
     body.view-fullpage .modal.show:not(.fullview-modal)), supaya dropdown
     kategori di modal Tambah/Ubah Barang Belanja tidak ke-render di
     belakang modal itu sendiri dan jadi tidak bisa dipilih di hape. */
  z-index: 2200;
  animation: csFadeIn 0.12s ease;
  max-height: 260px;
  display: none;
  flex-direction: column;
  overflow: hidden;
}
.cs-wrapper.open .cs-dropdown { display: flex; }

@keyframes csFadeIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Search box dalam dropdown */
.cs-search-wrap {
  padding: var(--space-6) var(--space-8);
  border-bottom: 1px solid var(--rule);
  flex-shrink: 0;
}
.cs-search {
  width: 100%;
  padding: var(--space-5) var(--space-9);
  font-size: var(--text-xs);
  font-family: inherit;
  background: var(--paper-warm);
  color: var(--ink);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color 0.15s;
}
.cs-search:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-lt); }
.cs-search::placeholder { color: var(--ink-faint); }

/* Options list */
.cs-options {
  overflow-y: auto;
  flex: 1;
}

.cs-option {
  display: flex;
  align-items: center;
  gap: var(--space-9);
  padding: var(--space-8) var(--space-12);
  font-size: var(--text-sm);
  font-family: inherit;
  color: var(--ink);
  cursor: pointer;
  border-bottom: 1px solid var(--rule);
  transition: background 0.1s;
  line-height: 1.4;
  background: transparent;
  border-left: none;
  border-right: none;
  border-top: none;
  width: 100%;
  text-align: left;
}
.cs-option:last-child { border-bottom: none; }
.cs-option:hover { background: var(--accent-lt); }
.cs-option.selected {
  background: var(--accent-lt);
  color: var(--accent);
  font-weight: 600;
}
.cs-option.selected::after {
  /* Centang Lucide lewat mask (bukan karakter unicode). */
  content: '';
  margin-left: auto;
  width: 1.3em; height: 1.3em;
  font-size: var(--text-xs);
  background-color: var(--accent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
  flex-shrink: 0;
}
.cs-option.child { padding-left: 24px; color: var(--ink-muted); }

.cs-option-label {
  display: flex;
  align-items: center;
  flex: 1;
  gap: var(--space-8);
  overflow: hidden;
  min-width: 0;
}
.cs-opt-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cs-opt-balance {
  flex-shrink: 0;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.cs-option.selected .cs-opt-balance { color: var(--accent); }
.cs-option.empty { color: var(--ink-faint); font-style: italic; cursor: default; }
.cs-option.empty:hover { background: transparent; }

/* Dot warna untuk pilih buku (akun) */
.cs-opt-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--ink-faint);
}

/* Kategori icon/color strip */
.cs-opt-strip {
  width: 3px;
  height: 16px;
  border-radius: var(--radius-xs);
  flex-shrink: 0;
}

/* Versi compact untuk header (pilih buku) */
.cs-wrapper.compact {
  width: auto;
}
.cs-wrapper.compact .cs-trigger {
  font-size: var(--text-xs);
  min-height: 30px;
  padding: var(--space-5) var(--space-9) var(--space-5) var(--space-10);
  max-width: none;
}
/* [FIX HEADER HAPE KEPOTONG] min-width 300px di bawah ini SEBELUMNYA
   tidak dibatasi breakpoint apa pun -- karena letaknya di sini (di luar
   media query, setelah blok @media (max-width:640px)/(max-width:768px)),
   dia menang lawan override min-width:0 di breakpoint mobile (spesifisitas
   selector sama, aturan yang datang TERAKHIR di file yang menang), jadi
   trigger dropdown buku dipaksa selebar 300px juga di hape -- lebih lebar
   dari sisa ruang top bar setelah hamburger & badge sync, sehingga
   .book-selector (overflow-x:auto) harus discroll horizontal supaya
   saldo buku di ujung kanan trigger kelihatan. Sekarang 300px HANYA
   berlaku mulai tablet ke atas; di hape trigger mengikuti sisa ruang
   top bar (lihat .book-selector > .cs-wrapper.compact .cs-trigger di
   breakpoint 640px) dan nama buku yang kepanjangan di-ellipsis lewat
   .cs-trigger-name, bukan didorong keluar layar. */
@media (min-width: 641px) {
  .cs-wrapper.compact .cs-trigger { min-width: 300px; }
}
.cs-wrapper.compact .cs-dropdown {
  min-width: 220px;
  max-width: none;
}

/* [UI] Dropdown pilih buku (.book-selector) dilebarkan 50% khusus di
   desktop (≥1024px) -- 220px -> 330px -- supaya nama buku yang panjang
   di daftar dropdown tidak tertutup/berdempetan dengan angka saldo di
   sebelahnya. Trigger-nya sendiri (kotak yang selalu terlihat di top
   bar) TIDAK ikut melebar, cuma panel dropdown-nya saat dibuka. */
@media (min-width: 1024px) {
  .book-selector .cs-wrapper.compact .cs-dropdown {
    min-width: 330px;
  }
}

/* Versi mini — pill kecil lebar-otomatis (dulu .budget-select /
   .date-quick-preset): filter bulan/tahun, preset tanggal cepat, dsb. */
.cs-wrapper.mini {
  width: auto;
  display: inline-flex;
}
.cs-wrapper.mini .cs-trigger {
  font-size: var(--text-xs);
  font-weight: 400;
  min-height: 0;
  padding: var(--space-5) var(--space-9) var(--space-5) var(--space-10);
  width: auto;
  min-width: 0;
  color: var(--ink-muted);
}
.cs-wrapper.mini .cs-trigger-icon { font-size: 9px; }
.cs-wrapper.mini .cs-dropdown { min-width: 160px; }

/* Versi form (kategori dalam modal) */
.cs-wrapper.form-style .cs-trigger {
  font-size: var(--text-sm);
  min-height: 36px;
  padding: var(--space-9) var(--space-12);
  border-radius: var(--radius-sm);
}
.cs-wrapper.form-style.open .cs-trigger {
  border-bottom-color: transparent;
}
.cs-wrapper.form-style .cs-dropdown {
  top: 100%;
  border-top: none;
}

/* Dark mode adjustments */
[data-theme="dark"] .cs-trigger {
  background: var(--paper);
  border-color: var(--rule);
  color: var(--ink);
}
[data-theme="dark"] .cs-wrapper.open .cs-trigger {
  border-color: var(--ink-faint);
  box-shadow: 0 0 0 2px rgba(232,232,229,0.06);
}
[data-theme="dark"] .cs-dropdown {
  background: var(--paper);
  border-color: var(--ink-faint);
}
[data-theme="dark"] .cs-search {
  background: var(--paper-warm);
  color: var(--ink);
  border-color: var(--rule);
}
[data-theme="dark"] .cs-option:hover,
[data-theme="dark"] .cs-option.selected { background: var(--paper-warm); }

/* ── PAYMENT REMINDER — Light mode defaults ── */
.pr-banner {
    background: var(--warning-lt);
    border: 1.5px solid var(--warning);
}
.pr-banner-title { color: var(--warning); }
.pr-banner-text  { color: var(--ink-muted); }
.pr-upcoming-alert {
    background: var(--warning-lt);
    border: 1.5px solid var(--warning);
    color: var(--warning);
}
.pr-form-divider {
    border-top: 1.5px dashed var(--rule);
}

/* ── PAYMENT REMINDER — Dark mode: variabel sudah handle otomatis ── */
[data-theme="dark"] .pr-banner-title { color: var(--warning); }
[data-theme="dark"] .pr-banner-text  { color: var(--ink-muted); }
[data-theme="dark"] .pr-form-divider {
    border-top-color: var(--rule);
}

/* ── SINARMEDIA — NOTIFIKASI HARGA DISEPAKATI (js/sinarmedia.js) ── */
.smedia-agreed-item + .smedia-agreed-item {
    border-top: 1px dashed var(--rule);
    margin-top: var(--space-8);
    padding-top: var(--space-8);
}

/* ==================== KONFLIK MULTI-DEVICE (js/sync-conflict.js) ==================== */
.conflict-compare {
    display: flex;
    flex-direction: column;
    gap: var(--space-12);
    margin-bottom: var(--space-4);
}
.conflict-side {
    border: 1.5px solid var(--rule);
    border-radius: var(--radius-sm);
    padding: var(--space-10) var(--space-12);
}
.conflict-side-label {
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: none;
    letter-spacing: .02em;
    color: var(--ink-faint);
    margin-bottom: var(--space-6);
}
.conflict-row {
    display: flex;
    justify-content: space-between;
    gap: var(--space-10);
    font-size: var(--text-base);
    padding: var(--space-3) 0;
    border-bottom: 1px dashed var(--rule);
}
.conflict-row:last-child { border-bottom: none; }
.conflict-row span { color: var(--ink-muted); }
.conflict-row b { color: var(--ink); text-align: right; }
.conflict-deleted-note {
    font-size: var(--text-sm);
    color: var(--danger);
    font-style: italic;
}

/* Dark mode: variabel sudah cukup, hanya pastikan kontras dash border */
[data-theme="dark"] .conflict-row { border-bottom-color: var(--rule); }

/* ==================== MANAJEMEN USER (js/auth.js — user manager) ==================== */
.um-select-wrap { margin-bottom: var(--space-14); }

.um-panel {
  background: var(--paper-warm);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-14) var(--space-16);
  margin-top: var(--space-14);
}
.um-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  margin-bottom: var(--space-10);
}
.um-panel-title {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--ink-muted);
}
.um-member-count {
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--ink-faint);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  padding: var(--space-1) var(--space-8);
}

/* [OPTIMASI TAMPILAN] Tombol "Lihat & Kelola Anggota" -- daftar anggota +
   form undang disembunyikan di balik tombol ini secara default (lihat
   skBuildMemberManagementHtml/js/auth.js), baru dimuat & ditampilkan
   begitu diklik. Ikon panah ikut berputar 180deg saat panel terbuka. */
.um-member-toggle-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  font-size: var(--text-xs);
}
.um-member-toggle-btn svg { flex-shrink: 0; transition: transform .18s ease; }
.um-member-toggle-btn.is-open svg { transform: rotate(180deg); }
.um-member-panel-body { margin-top: var(--space-12); }

.um-member-list { display: flex; flex-direction: column; gap: var(--space-6); margin-bottom: var(--space-12); }
.um-member-empty { font-size: var(--text-xs); color: var(--ink-faint); padding: var(--space-10) var(--space-2); }

.um-member-card {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  padding: var(--space-8) var(--space-10);
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
}
.um-member-avatar {
  width: 30px; height: 30px; min-width: 30px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-size: var(--text-xs);
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.um-member-avatar.role-admin  { background: var(--accent); }
.um-member-avatar.role-editor { background: var(--info); }
.um-member-avatar.role-viewer { background: var(--ink-faint); }

.um-member-info { flex: 1; min-width: 0; }
.um-member-email {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.um-member-meta { display: flex; align-items: center; gap: var(--space-6); margin-top: var(--space-2); flex-wrap: wrap; }
.um-member-you { font-size: var(--text-2xs); color: var(--ink-faint); font-style: italic; }
.um-member-lastlogin { font-size: var(--text-2xs); color: var(--ink-faint); margin-top: var(--space-3); }

.um-role-badge {
  font-size: var(--text-2xs);
  font-weight: 600;
  padding: var(--space-2) var(--space-8);
  border-radius: var(--radius-pill);
  text-transform: capitalize;
  white-space: nowrap;
}
.um-role-badge--admin  { background: var(--accent-lt); color: var(--accent); }
.um-role-badge--editor { background: var(--info-lt);   color: var(--info); }
.um-role-badge--viewer { background: var(--rule);       color: var(--ink-muted); }

/* Dropdown ubah peran langsung di kartu anggota (pengganti badge statis
   untuk anggota selain diri sendiri) -- ukurannya sengaja dibuat kompak
   supaya tetap terasa seperti badge, bukan input form biasa. */
.um-role-select {
  width: auto;
  font-size: var(--text-2xs);
  font-weight: 600;
  padding: var(--space-2) var(--space-20) var(--space-2) var(--space-8);
  border-radius: var(--radius-pill);
  border: 1px solid var(--rule);
  background-color: var(--paper);
  color: var(--ink-muted);
  cursor: pointer;
}
.um-role-select:disabled { opacity: .5; cursor: wait; }

/* Picker "Undang Anggota" -- daftar semua pengguna terdaftar yang bisa
   langsung ditambahkan tanpa ketik email (lihat skRenderInviteMemberPicker
   di js/auth.js) */
.um-invite-picker-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  max-height: 260px;
  overflow-y: auto;
  margin-bottom: var(--space-8);
  padding-right: 2px;
}
.um-invite-candidate {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  padding: var(--space-6) var(--space-8);
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
}
.um-invite-candidate .um-member-info { min-width: 0; }
.um-invite-candidate-role {
  width: auto;
  max-width: 92px;
  font-size: var(--text-2xs);
  padding: var(--space-5) var(--space-6);
  flex-shrink: 0;
}
.um-invite-candidate .btn-mini { flex-shrink: 0; white-space: nowrap; }

.um-invite-manual-toggle {
  display: block;
  width: 100%;
  text-align: center;
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  background: none;
  border: none;
  border-top: 1px dashed var(--rule);
  padding: var(--space-8) 0 0;
  margin-top: var(--space-2);
  cursor: pointer;
  font-family: inherit;
}
.um-invite-manual-toggle:hover { color: var(--accent); }

/* Segmented tab toggle: Undang vs Buatkan Akun Baru */
.um-invite-tabs {
  display: flex;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: var(--space-12);
}
.um-invite-tab {
  flex: 1;
  padding: var(--space-7) var(--space-6);
  font-size: var(--text-xs);
  font-weight: 600;
  font-family: inherit;
  text-align: center;
  border: none;
  background: var(--paper);
  color: var(--ink-faint);
  cursor: pointer;
  transition: all 0.12s;
}
.um-invite-tab + .um-invite-tab { border-left: 1.5px solid var(--rule); }
.um-invite-tab:hover { color: var(--ink); }
.um-invite-tab.active { background: var(--accent); color: #fff; }

.um-invite-tab-panel-note {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  line-height: 1.6;
  margin-top: var(--space-8);
}

/* Panel "Atur Tampilan Menu per Peran" */
.um-menu-table-wrap {
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.um-menu-table { width: 100%; border-collapse: collapse; }
.um-menu-table th {
  text-align: left;
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .03em;
  color: var(--ink-muted);
  background: var(--paper-warm);
  padding: var(--space-7) var(--space-10);
  border-bottom: 1.5px solid var(--rule);
}
.um-menu-table th.um-menu-role-col { text-align: center; width: 64px; }
.um-menu-table td {
  font-size: var(--text-xs);
  color: var(--ink);
  padding: var(--space-7) var(--space-10);
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
}
.um-menu-table tr:last-child td { border-bottom: none; }
.um-menu-table tr:nth-child(even) td { background: var(--row-alt); }
.um-menu-table td.um-menu-role-col { text-align: center; }
.um-menu-table input[type="checkbox"] {
  width: 15px; height: 15px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Empty / not-eligible states */
.um-empty-state {
  background: var(--paper-warm);
  border: 1.5px dashed var(--rule);
  border-radius: var(--radius);
  padding: var(--space-22) var(--space-18);
  text-align: center;
}
.um-empty-state-icon {
  width: 38px; height: 38px;
  margin: 0 auto var(--space-10);
  border-radius: 50%;
  background: var(--accent-lt);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
}
.um-empty-state-text {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  line-height: 1.7;
  max-width: 340px;
  margin: 0 auto;
}

/* ===================================================================
   Modal "Buku Kas" (#bookManagerModal) -- markup & styling diselaraskan
   dengan pola menu full-page lain (Cadangan Data, Manajemen User, dll):
   header polos (h3 + .setelan-desc di bawahnya, tanpa subjudul terpisah),
   seksi dibungkus .data-management-panel.setelan-tab-panel + .panel-title,
   dan kartu daftar buku pakai gaya .book-list-item standar (sama pola
   dengan .acc-modal-item di Setelan) -- tanpa aksen warna/ikon khusus
   yang dulu bikin menu ini terlihat beda sendiri dari menu lain.
   TIDAK menyentuh js/book.js -- markup dinamis (.book-list-item,
   .book-list-name, .book-list-actions, .btn-mini, .btn-mini-danger)
   tetap dihasilkan JS apa adanya. Beberapa tombol aksi (Nama/Card/
   Duplikat/Jadikan Bersama/dst.) punya inline style warna dari JS yang
   sengaja DIPERTAHANKAN (kode warna beda = jenis aksi beda).
   =================================================================== */

/* ── Daftar buku: kartu standar (samakan dengan .acc-modal-item),
   item yang sedang aktif ditandai border+bg sukses seperti pola akun
   aktif di Setelan, bukan aksen warna emas/kiri khusus. ── */
#bookManagerModal .book-manager-list { margin-bottom: var(--space-4); }

#bookManagerModal .book-list-item:has(.book-manager-active-badge) {
  border-color: var(--success);
  background: var(--success-lt);
}
#bookManagerModal .book-list-actions > span {
  display: inline-flex;
  align-items: center;
  font-size: var(--text-2xs) !important;
  font-weight: 500 !important;
  color: var(--success) !important;
  background: var(--success-lt);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-7);
}

#bookManagerModal .book-manager-new-form { display: flex; flex-direction: column; gap: var(--space-10); }
#bookManagerModal .book-manager-parent-field label {
  display: block;
  font-size: var(--text-2xs);
  font-weight: 500;
  color: var(--ink-faint);
  margin-bottom: var(--space-5);
}
#bookManagerModal .book-manager-parent-field select { font-size: var(--text-sm); }
#bookManagerModal .book-manager-submit { width: 100%; font-weight: 700; }

/* ── Empty state (dari js/book.js: satu <div> teks di dalam
   #bookListContainer saat window.books kosong) -- diberi bingkai putus-putus
   supaya jelas ini kondisi kosong yang valid, bukan area kosong tanpa
   penjelasan. Selector menyasar div langsung di bawah container yang TIDAK
   punya class .book-list-item, jadi tidak ikut mengubah kartu buku biasa. ── */
#bookManagerModal #bookListContainer > div:not(.book-list-item) {
  border: 1.5px dashed var(--rule);
  border-radius: var(--radius);
  background: var(--paper-warm);
}

[data-theme="dark"] #bookManagerModal #bookListContainer > div:not(.book-list-item) {
  background: var(--paper);
}

/* ── Panel "Buku Bersama (Shared)" login/status (skAuthPanelContent,
   js/auth-ui.js) -- dulu teks polos bertumpuk yang terlihat "mentah"/native
   karena tidak ada kartu pembungkus atau hierarki visual. Sekarang pakai
   layout kartu avatar+email+badge, reuse look & feel .um-member-card /
   .um-role-badge yang sudah ada di kartu anggota Manajemen User supaya
   konsisten satu sama lain. ── */
.sk-auth-card {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  padding: var(--space-10) var(--space-12);
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-sm);
}
.sk-auth-avatar {
  width: 34px; height: 34px; min-width: 34px;
  border-radius: 50%;
  background: var(--ink-faint);
  color: var(--paper);
  font-size: var(--text-sm);
  font-weight: 600;
  text-transform: uppercase;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.sk-auth-avatar.role-admin  { background: var(--accent); }
.sk-auth-avatar.role-editor { background: var(--info); }
.sk-auth-avatar.role-viewer { background: var(--ink-faint); }

.sk-auth-info { flex: 1; min-width: 0; }
.sk-auth-email {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sk-auth-meta {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  margin-top: var(--space-4);
  flex-wrap: wrap;
}
.sk-auth-booktag {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
}

/* ==================== DAFTAR MENU (jadwal menu masak mingguan) ==================== */
/* Mengikuti pola visual Belanja Bulanan (.slist-*) supaya konsisten --
   lihat js/menu-plan.js untuk logikanya.
   [ROMBAK-KOTAK] Semua border-radius di seksi ini (kartu hari, kartu
   estimasi, badge, chip, tab minggu, tombol ikon bulat) diseragamkan ke
   var(--radius-xs) -- sebelumnya campur antara var(--radius) (6px),
   var(--radius-sm) (4px), dan var(--radius-pill)/50% (kapsul/lingkaran
   penuh). Elemen yang tadinya pill/lingkaran (tab minggu, badge "HARI
   INI", tombol "+ Tambah Menu", tombol salin hari bulat, tag jam makan,
   chip makro gizi, titik indikator minggu aktif) sekarang jadi
   kotak/persegi senada dengan kartu-kartu di sekitarnya. */
.mplan-intro {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  margin: 0 0 var(--space-14);
  line-height: 1.5;
}
/* Tab pemilih minggu (Minggu 1..4) -- segmented control di atas
   kartu-kartu hari. Titik kecil menandai minggu yang cocok dengan minggu
   kalender berjalan (lihat window._mplanCurrentWeekKey). Pakai grid (bukan
   flex) supaya jumlah kolom gampang diatur beda antara layar lebar & HP
   sempit tanpa mengubah markup -- lihat media query di bawah untuk 2x2 di
   HP (4 tab "MINGGU 1".."MINGGU 4" kalau dipaksa 1 baris penuh di layar
   sempit jadi kepotong/kepenceng). */
.mplan-week-tabs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-6);
  margin-bottom: var(--space-14);
}
.mplan-week-tab {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  border: 1.5px solid var(--rule);
  background: var(--paper);
  color: var(--ink-muted);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  padding: var(--space-8) var(--space-10);
  border-radius: var(--radius-xs);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.mplan-week-tab:hover { border-color: var(--accent); color: var(--ink); }
.mplan-week-tab.is-active {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--paper);
}
.mplan-week-tab-dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-xs);
  background: currentColor;
  flex: 0 0 auto;
}
@media (max-width: 480px) {
  /* 4 tab minggu ("MINGGU 1".."MINGGU 4") dipaksa 1 baris di layar HP
     sempit bikin teksnya kepotong/kepenceng -- di lebar ini disusun 2x2
     supaya tiap tab tetap punya ruang cukup buat labelnya. */
  .mplan-week-tabs { grid-template-columns: repeat(2, 1fr); }
}
/* Baris pembungkus tab minggu + tombol "Salin Minggu" -- tab tetap grid
   4 kolom penuh, tombol salin ditaruh di bawahnya (bukan sejajar) supaya
   tidak memaksa tab jadi sempit di layar HP. */
.mplan-week-tabs-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  margin-bottom: var(--space-14);
}
.mplan-week-tabs-row .mplan-week-tabs { margin-bottom: 0; }
.mplan-copy-week-btn {
  align-self: flex-end;
  display: flex;
  align-items: center;
  gap: var(--space-6);
  border: none;
  background: none;
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  padding: var(--space-4) var(--space-6);
  cursor: pointer;
  transition: color .15s ease;
}
.mplan-copy-week-btn:hover { color: var(--accent); }
.mplan-copy-week-btn svg { flex: 0 0 auto; }
.mplan-days {
  display: flex;
  flex-direction: column;
  gap: var(--space-10);
  margin-bottom: var(--space-18);
}
.mplan-day-card {
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-xs);
  background: var(--paper);
  padding: var(--space-12) var(--space-14);
}
/* Kartu hari ini disorot -- border & sedikit tint aksen supaya langsung
   kelihatan mana yang perlu dimasak hari ini di antara 7 kartu. */
.mplan-day-card.is-today {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 4%, var(--paper));
  box-shadow: 0 0 0 1px var(--accent);
}
.mplan-today-badge {
  display: inline-block;
  margin-left: var(--space-8);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--accent);
  border-radius: var(--radius-xs);
  padding: var(--space-2) var(--space-8);
  vertical-align: middle;
}
.mplan-day-estimate {
  display: inline-block;
  margin-left: var(--space-8);
  font-size: var(--text-2xs);
  font-weight: 600;
  font-style: italic;
  color: var(--ink-faint);
  vertical-align: middle;
  cursor: help;
}
.mplan-day-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-10);
  margin-bottom: var(--space-8);
}
.mplan-day-label {
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--ink);
  text-transform: uppercase;
  letter-spacing: .03em;
}
.mplan-add-meal-btn {
  flex: 0 0 auto;
  border: 1.5px dashed var(--rule);
  background: none;
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: 600;
  padding: var(--space-5) var(--space-10);
  border-radius: var(--radius-xs);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.mplan-add-meal-btn:hover { border-style: solid; background: var(--accent-lt); }
.mplan-add-meal-btn-short { display: none; }
.mplan-day-header-actions { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-6); }
.mplan-copy-day-btn {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 27px;
  height: 27px;
  border: 1.5px solid var(--rule);
  background: var(--paper-warm);
  color: var(--ink-faint);
  border-radius: var(--radius-xs);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.mplan-copy-day-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-lt); }
/* Modal Salin Menu (day/week) */
.mplan-copy-hint {
  font-size: var(--text-xs);
  color: var(--ink-muted);
  line-height: 1.5;
  margin: 0 0 var(--space-12);
}
.mplan-copy-week-tabs { margin-bottom: var(--space-12); }
.mplan-copy-week-tabs:empty { margin-bottom: 0; }
.mplan-copy-day-list { display: flex; flex-direction: column; gap: var(--space-6); }
.mplan-copy-day-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-10);
  width: 100%;
  text-align: left;
  border: 1.5px solid var(--rule);
  background: var(--paper);
  border-radius: var(--radius-xs);
  padding: var(--space-8) var(--space-10);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.mplan-copy-day-item:hover:not(:disabled) { border-color: var(--accent); background: var(--accent-lt); }
.mplan-copy-day-item:disabled { opacity: .5; cursor: not-allowed; }
.mplan-copy-day-item-label {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--ink);
  text-transform: uppercase;
  letter-spacing: .03em;
}
.mplan-copy-day-item-desc {
  flex: 1 1 auto;
  font-size: var(--text-xs);
  color: var(--ink-muted);
  overflow-wrap: anywhere;
  text-align: right;
}
.mplan-meal-list { display: flex; flex-direction: column; gap: var(--space-6); }
/* [ROMBAK KARTU HARI, 23 Sep 2026] Menu 1 hari sekarang dikelompokkan per
   waktu makan (lihat js/menu-plan.js) -- tiap kelompok punya sub-judul
   sendiri (.mplan-meal-group-header, gantikan tag .mplan-meal-waktu lama
   yang dulu menempel di tiap baris menu) supaya kartu hari terasa seperti
   jadwal berjenjang (Sarapan -> Camilan), bukan daftar rata. */
.mplan-meal-group { margin-bottom: var(--space-10); }
.mplan-meal-group:last-child { margin-bottom: 0; }
.mplan-meal-group-header {
  display: inline-flex;
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: color-mix(in srgb, var(--accent) 70%, var(--ink));
  background: var(--accent-lt);
  border-radius: var(--radius-xs);
  padding: var(--space-2) var(--space-8);
  margin-bottom: var(--space-6);
}
.mplan-meal {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-10);
  padding: var(--space-8) var(--space-10);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-xs);
  background: var(--paper-warm);
}
/* Nama menu (baris atas, tebal) & daftar bahan (baris bawah, kecil/pudar)
   sekarang 2 baris bertumpuk -- sebelumnya digabung 1 baris yang wrap
   bareng tag waktu makan, jadi blok teks panjang susah dipisah mana nama
   mana bahan kalau bahannya banyak. */
.mplan-meal-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.mplan-meal-nama { font-size: var(--text-base); font-weight: 600; color: var(--ink); }
.mplan-meal-bahan {
  font-size: var(--text-xs);
  color: var(--ink-faint);
  overflow-wrap: anywhere;
}
.mplan-meal-trail { flex: 0 0 auto; display: flex; gap: var(--space-6); }
/* Isi tombol Ubah/Hapus di kartu menu memakai ikon SVG pensil & tempat
   sampah (bukan karakter teks ✎/✕) supaya render-nya konsisten di semua
   font/OS -- style kotaknya sendiri tetap pakai .slist-edit-btn/
   .slist-del-btn generik (sama seperti Daftar Belanja, dll). */
.mplan-meal-trail .slist-edit-btn svg,
.mplan-meal-trail .slist-del-btn svg { pointer-events: none; }


/* ── Kartu Estimasi Belanja Mingguan (di bawah jadwal 7 hari) ── */
.mplan-estimate-card {
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-xs);
  background: var(--paper);
  padding: var(--space-14) var(--space-16);
}
.mplan-estimate-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-10);
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 700;
  color: var(--ink);
  margin-bottom: var(--space-10);
}
.mplan-estimate-total {
  font-size: var(--text-lg);
  color: var(--accent);
}
.mplan-estimate-list { display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--space-4); }
.mplan-estimate-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 100px 110px;
  column-gap: var(--space-10);
  align-items: center;
  padding: var(--space-6) var(--space-8);
  border-radius: var(--radius-xs);
  font-size: var(--text-sm);
}
.mplan-estimate-row:nth-child(odd of .mplan-estimate-row) { background: var(--row-alt); }
.mplan-estimate-name { color: var(--ink); overflow-wrap: anywhere; }
.mplan-estimate-qty {
  justify-self: end;
  font-size: var(--text-xs);
  color: var(--ink-muted);
  white-space: nowrap;
}
.mplan-estimate-price {
  justify-self: end;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  white-space: nowrap;
  color: var(--ink-muted);
}
.mplan-estimate-price.is-ref-price { color: var(--accent); font-style: italic; }
.mplan-estimate-price.is-unknown { color: var(--ink-faint); font-size: var(--text-2xs); font-style: italic; }
/* [ROMBAK, 23 Sep 2026] Sub-judul pemisah antara bahan yang sudah ada
   harganya & yang belum (lihat window.renderMenuPlanEstimate) -- supaya
   dua kelompok itu kebeda sekilas, bukan lagi diselang-seling rata dalam
   1 daftar panjang. */
.mplan-estimate-group-header {
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-faint);
  padding: var(--space-8) var(--space-8) var(--space-4);
  margin-top: var(--space-2);
  border-top: 1px dashed var(--rule);
}
.mplan-estimate-note {
  font-size: var(--text-xs);
  color: var(--warning);
  margin: var(--space-6) 0 0;
}

/* ── Kartu Estimasi Gizi Mingguan -- SEKARANG DI ATAS (di bawah intro,
   sebelum tab minggu/jadwal hari), bukan lagi di bawah kartu Estimasi
   Belanja. Redesign jadi "kartu ringkasan" yang lebih ringkas: kalori
   total besar + chip makro langsung kelihatan tanpa scroll, rincian per
   bahan (yang isinya cenderung duplikat sama daftar bahan di kartu-kartu
   hari di bawahnya) disembunyikan di balik <details> supaya halaman tidak
   terasa penuh sebelum user benar-benar butuh rinciannya. ── */
.mplan-gizi-card.mplan-gizi-top {
  border: 1.5px solid var(--accent);
  border-radius: var(--radius-xs);
  background: var(--accent-lt);
  padding: var(--space-14) var(--space-16);
  margin-bottom: var(--space-16);
}
.mplan-gizi-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-10) var(--space-14);
}
.mplan-gizi-label {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--ink-muted);
  margin-bottom: var(--space-2);
}
.mplan-gizi-kalori {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: 700;
  color: var(--accent);
  line-height: 1.2;
}
.mplan-gizi-macros { display: flex; flex-wrap: wrap; gap: var(--space-6); align-content: flex-start; }
.mplan-gizi-chip {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-10);
  border-radius: var(--radius-xs); /* [ROMBAK-KOTAK] dulu pill (var(--radius-pill)), disquarekan biar senada sama kartu2 mplan lain */
  background: var(--paper);
  border: 1px solid var(--rule);
  color: var(--ink-muted);
  font-size: var(--text-xs);
}
.mplan-gizi-chip b { color: var(--accent); font-family: var(--font-mono); font-size: var(--text-sm); }
.mplan-gizi-card.mplan-gizi-top .slist-empty { margin: var(--space-10) 0 0; }
/* Evaluasi Menu Minggu Ini -- daftar insight kurang/lebih/seimbang di
   bawah chip makro, sebelum toggle rincian per bahan. */
.mplan-gizi-evaluasi-wrap {
  margin-top: var(--space-10);
  padding-top: 10px;
  border-top: 1px solid var(--rule);
}
.mplan-gizi-evaluasi-title {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: .03em;
  margin-bottom: var(--space-6);
}
.mplan-gizi-evaluasi { display: flex; flex-direction: column; gap: var(--space-5); }
.mplan-gizi-insight {
  display: flex;
  align-items: baseline;
  gap: var(--space-6);
  padding: var(--space-6) var(--space-9);
  border-radius: var(--radius-xs);
  font-size: var(--text-xs);
  line-height: 1.5;
}
.mplan-gizi-insight-label {
  flex: 0 0 auto;
  font-weight: 700;
}
.mplan-gizi-insight-text { color: var(--ink-muted); }
.mplan-gizi-insight.is-good { background: var(--success-lt); }
.mplan-gizi-insight.is-good .mplan-gizi-insight-label { color: var(--success); }
.mplan-gizi-insight.is-warning { background: var(--warning-lt); }
.mplan-gizi-insight.is-warning .mplan-gizi-insight-label { color: var(--warning); }
.mplan-gizi-insight.is-info { background: var(--paper-warm); }
.mplan-gizi-insight.is-info .mplan-gizi-insight-label { color: var(--ink-muted); }
@media (max-width: 480px) {
  .mplan-gizi-insight { flex-direction: column; align-items: flex-start; gap: var(--space-1); }
}
.mplan-gizi-details {
  margin-top: var(--space-10);
  padding-top: 10px;
  border-top: 1px solid color-mix(in srgb, var(--accent) 25%, var(--rule));
}
.mplan-gizi-details summary {
  cursor: pointer;
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--accent);
  list-style: none;
  user-select: none;
}
.mplan-gizi-details summary::-webkit-details-marker { display: none; }
.mplan-gizi-details summary::before {
  /* Chevron Lucide lewat mask (bukan karakter unicode). */
  content: '';
  display: inline-block;
  width: 1.2em; height: 1.2em;
  margin-right: .25em;
  vertical-align: -0.2em;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat;
}
.mplan-gizi-details[open] summary::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
.mplan-gizi-details .mplan-estimate-list { margin-top: var(--space-8); }
@media (max-width: 480px) {
  .mplan-gizi-kalori { font-size: var(--text-2xl); }
}

/* ── Form Tambah/Ubah Menu (modal biasa, menuPlanMealModal) ── */
.mplan-bahan-rows { display: flex; flex-direction: column; gap: var(--space-6); margin-bottom: var(--space-8); }
.mplan-bahan-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 74px 96px 26px;
  gap: var(--space-6);
  align-items: center;
}
.mplan-bahan-row .form-control { margin: 0; }
.mplan-add-bahan-btn {
  border: 1.5px dashed var(--rule);
  background: none;
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: 600;
  padding: var(--space-6) var(--space-10);
  border-radius: var(--radius-xs);
  cursor: pointer;
  width: 100%;
  transition: border-color .15s ease, background .15s ease;
}
.mplan-add-bahan-btn:hover { border-style: solid; background: var(--accent-lt); }

@media (min-width: 641px) {
  .modal-content.wide.mplan-modal { max-width: 860px; }
}

/* ── Daftar Menu: optimasi layar hp ── */
@media (max-width: 640px) {
  /* Jarak antar kartu hari & padding dalam kartu dipadatkan -- di layar
     sempit, 7 kartu berturutan jadi berat kalau tiap kartu masih pakai
     jarak versi desktop. */
  .mplan-days { gap: var(--space-7); }
  .mplan-day-card { padding: var(--space-9) var(--space-10); }
  .mplan-day-header { margin-bottom: var(--space-6); flex-wrap: wrap; }
  /* Kartu hari yang belum ada menunya (class `is-empty`, lihat
     js/menu-plan.js) tidak lagi punya konten di bawah header -- hilangkan
     margin-bottom header supaya tinggi kartu kosong menyusut ke ukuran
     minimal, bukan tetap menyisakan jarak untuk konten yang tidak ada. */
  .mplan-day-card.is-empty .mplan-day-header { margin-bottom: 0; }
  /* Tombol "+ Tambah Menu" jadi "+ Menu" di layar sempit supaya muat
     sebaris dengan label hari + badge tanpa household ke baris baru. */
  .mplan-add-meal-btn { padding: var(--space-4) var(--space-9); font-size: var(--text-2xs); }
  .mplan-add-meal-btn-full { display: none; }
  .mplan-add-meal-btn-short { display: inline; }
  .mplan-meal-list { gap: var(--space-5); }
  .mplan-meal { flex-direction: column; align-items: stretch; padding: var(--space-7) var(--space-9); gap: var(--space-6); }
  .mplan-meal-trail { justify-content: flex-end; }
  .mplan-estimate-row {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: var(--space-2);
  }
  .mplan-estimate-qty { grid-column: 2; grid-row: 1; }
  .mplan-estimate-price { grid-column: 2; grid-row: 2; }
  .mplan-bahan-row {
    grid-template-columns: minmax(0, 1fr) 64px 26px;
    grid-template-areas:
      "name qty del"
      "unit unit unit";
    row-gap: var(--space-4);
  }
  .mplan-bahan-row .mplan-bahan-name { grid-area: name; }
  .mplan-bahan-row .mplan-bahan-qty { grid-area: qty; }
  .mplan-bahan-row .slist-del-btn { grid-area: del; }
  .mplan-bahan-row .mplan-bahan-unit { grid-area: unit; }
  /* Tombol "Salin Minggu" jadi ikon saja di layar sempit -- labelnya
     sudah jelas dari ikon copy + posisinya di sebelah tab minggu. */
  .mplan-copy-week-btn-full { display: none; }
}

/* ── Daftar Menu: grid kalender mingguan di layar lebar ──
   Di bawah 1024px, 7 kartu hari tetap tumpukan vertikal (lebih gampang
   dibaca di layar sempit/medium). Mulai 1024px, modal dilebarkan dan
   kartu hari dijajar grid MAKSIMAL 4 KOLOM per baris (bukan 7 kolom
   sejajar seperti sebelumnya -- di lebar modal biasa, 7 kolom bikin tiap
   kartu terlalu sempit/kepenceng, terutama nama menu & bahan yang
   panjang). Dengan 4 kolom, Senin-Kamis di baris pertama & Jumat-Minggu
   di baris kedua (grid auto-flow bawaan, baris baru otomatis kalau
   kartu ke-5 kehabisan kolom) -- tiap kartu jadi lebih lega. Header hari
   & baris menu di dalam kartu diringkas jadi susunan vertikal supaya
   tetap terbaca di kolom yang tidak terlalu lebar. */
@media (min-width: 1024px) {
  .modal-content.wide.mplan-modal { max-width: min(96vw, 1440px); }
  .mplan-days {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-8);
    align-items: start;
  }
  .mplan-day-card { padding: var(--space-8) var(--space-9); }
  .mplan-day-header {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-4);
    margin-bottom: var(--space-7);
  }
  .mplan-day-label { font-size: var(--text-xs); }
  .mplan-day-estimate { display: block; margin-left: 0; margin-top: var(--space-2); }
  .mplan-day-header-actions { width: 100%; justify-content: space-between; }
  .mplan-add-meal-btn-full { display: none; }
  .mplan-add-meal-btn-short { display: inline; }
  .mplan-meal-list { gap: var(--space-5); }
  .mplan-meal {
    flex-direction: column;
    align-items: stretch;
    padding: var(--space-6) var(--space-8);
    gap: var(--space-5);
  }
  .mplan-meal-main { flex-direction: column; align-items: flex-start; gap: var(--space-3); }
  .mplan-meal-nama { font-size: var(--text-sm); }
  .mplan-meal-trail { justify-content: flex-end; }
  /* Sabtu & Minggu (anak ke-6 & ke-7 dalam urutan window.MENU_PLAN_DAYS,
     sekarang jatuh di baris kedua grid 4 kolom) diberi tint halus supaya
     akhir pekan langsung kebeda dari hari kerja tanpa perlu label
     tambahan. Selector nth-child menghitung urutan DOM, bukan posisi
     kolom grid, jadi tetap tepat kena Sabtu & Minggu walau sekarang
     wrap ke baris baru. */
  .mplan-day-card:nth-child(6),
  .mplan-day-card:nth-child(7) {
    background: color-mix(in srgb, var(--ink) 2.5%, var(--paper));
  }
  /* Kartu "hari ini" tetap menang atas tint akhir pekan kalau kebetulan
     jatuh di Sabtu/Minggu -- disorot lebih penting daripada tint biasa. */
  .mplan-day-card.is-today {
    background: color-mix(in srgb, var(--accent) 4%, var(--paper));
  }
}

/* [APPLE] Cegah Safari iOS membesarkan teks sendiri saat layar diputar landscape. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* ===================================================
   IPAD / TOUCH OPTIMIZATION
   [IPAD-AUDIT] Ditambahkan setelah audit tampilan khusus iPad 9
   (lebar CSS 810px portrait / 1080px landscape). Dua masalah utama
   yang ditemukan pada semua breakpoint lebar yang ada sebelumnya:

   1) SEMUA input/select/textarea pakai font-size di bawah 16px
      (--text-xs/--text-sm/--text-base, ~12-13px). Safari di iOS/iPadOS
      otomatis ZOOM IN setiap kali field itu di-tap/fokus kalau
      font-size-nya <16px -- ini bukan soal lebar layar (muncul di
      SEMUA breakpoint), makanya diperbaiki lewat media feature
      (hover:none)+(pointer:coarse) yang mendeteksi perangkat sentuh
      (iPad, termasuk saat mode sidebar permanen di landscape >=1024px)
      tanpa mengubah tampilan di desktop mouse/trackpad.
   2) Beberapa tombol ikon (aksi baris tabel, hamburger, tutup modal,
      tombol perangkat listrik) berukuran jauh di bawah 44x44px --
      target sentuh minimum yang direkomendasikan Apple HIG. Di
      desktop tidak masalah (presisi mouse tinggi), tapi di iPad jari
      sering meleset. Diperbesar AREA SENTUHnya (padding/min-height),
      bukan ukuran ikon visualnya, supaya tampilan tetap ringkas.
=================================================== */
@media (hover: none) and (pointer: coarse) {
  /* -- Cegah auto-zoom Safari saat fokus ke field manapun --
     [FIX FONT JUMBO DI ANDROID] Sebelumnya font-size:16px ini kena ke
     SEMUA perangkat sentuh (hover:none + pointer:coarse cocok untuk HP
     Android juga, bukan cuma iPad/iPhone) -- padahal auto-zoom on-focus
     yang mau dicegah cuma perilaku khas Safari/WebKit iOS, Chrome Android
     tidak melakukan itu. Akibatnya semua input di HP Android jadi
     terkesan "jumbo" (16px) dibanding label di atasnya yang tetap kecil
     (--text-2xs). Dibatasi lewat @supports (-webkit-touch-callout: none)
     -- fitur CSS yang cuma didukung WebKit/Safari (termasuk Safari iOS)
     -- supaya bump ke 16px ini HANYA berlaku di iPhone/iPad (yang memang
     butuh itu supaya tidak auto-zoom), sementara HP/tablet Android tetap
     pakai ukuran font normal (var(--text-sm) dari .form-control) yang
     proporsional dengan label & elemen form lainnya. */
  @supports (-webkit-touch-callout: none) {
    .form-control,
    select.form-control,
    .search-input,
    .lock-input,
    .budget-select,
    input[type="text"],
    input[type="number"],
    input[type="date"],
    input[type="email"],
    input[type="password"],
    input[type="tel"],
    input[type="search"],
    textarea {
      font-size: 16px;
    }
    /* input[type=date] & select punya padding vertikal ketat yang dihitung
       dari font-size lama yang lebih kecil -- ditambah dikit supaya tinggi
       kotaknya tidak terasa "meledak" begitu font naik ke 16px. Sengaja
       ikut dibatasi ke iOS saja -- di Android tidak perlu (font-size tidak
       berubah, jadi padding aslinya sudah pas). */
    .form-control, select.form-control, .lock-input {
      padding-top: var(--space-11);
      padding-bottom: var(--space-11);
    }
  }

  /* -- Perbesar area sentuh tombol ikon kecil (ukuran ikon tetap sama,
     cuma hit-area-nya yang dilebarkan lewat padding/min-height) -- */
  .hamburger-btn-icon { width: 44px; height: 44px; }
  .modal-close {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .btn-icon {
    min-height: 40px;
  }
  .elec-device-actions .btn-icon {
    width: 36px;
    height: 36px;
  }
  .slist-edit-btn, .slist-del-btn {
    width: 40px;
    height: 40px;
  }
  .page-btn {
    min-width: 36px;
    min-height: 36px;
  }
  /* Item nav sidebar: hover state tidak akan pernah kepicu di layar
     sentuh, tapi padding vertikal dilonggarkan sedikit supaya tiap
     baris menu lebih nyaman diketuk jari di sidebar permanen (landscape
     iPad >=1024px). */
  .app-nav-item { padding-top: var(--space-13); padding-bottom: var(--space-13); }
}

/* ============================================================
   IKON LUCIDE (inline SVG) -- lihat window.skIcon di js/utils.js.
   Ukuran default 1em (ikut font-size elemen induk, seperti glyph
   emoji/simbol yang digantikannya). Warna = currentColor.
   ============================================================ */
.sk-icon { flex-shrink: 0; vertical-align: -0.125em; }
.sk-icon-lead { margin-right: .4em; }
/* Tombol yang isinya HANYA ikon: hilangkan offset baseline & kecilkan
   sedikit supaya bobot visualnya setara karakter yang digantikannya. */
.modal-close .sk-icon { display: block; width: .75em; height: .75em; }
.date-clear-btn .sk-icon,
.dbudget-clear-btn .sk-icon,
.slist-del-btn .sk-icon,
.slist-edit-btn .sk-icon,
.action-btn .sk-icon { display: block; }
.slist-del-btn .sk-icon,
.slist-edit-btn .sk-icon { width: .95em; height: .95em; }
.page-btn .sk-icon { display: block; width: 1.35em; height: 1.35em; }
.cs-trigger-icon .sk-icon { display: block; width: 1.25em; height: 1.25em; }
.lock-account-check .sk-icon { display: block; }
.ai-chat-fab-icon { display: inline-flex; align-items: center; justify-content: center; }
.ai-chat-fab-icon .sk-icon { vertical-align: 0; }
.fase-trigger-icon,
.fase-opt-icon { display: inline-flex; align-items: center; justify-content: center; }
.fase-trigger-icon .sk-icon,
.fase-opt-icon .sk-icon { vertical-align: 0; }
.slist-staple-badge .sk-icon,
.acc-modal-item-badge .sk-icon { vertical-align: -0.1em; }

/* ============================================================
   HEADER MOBILE PADAT -- tombol drawer (hamburger) + pilih buku
   Tujuan: hemat ruang vertikal di hape/tablet (<1024px).
   - margin & padding bar dirapatkan (sebelumnya margin atas 28px,
     padding 14px 20px, tinggi total ~68px karena tombol hamburger 44px).
   - hamburger 44px -> 40px (masih aman untuk sentuhan; ikon tetap sama).
   - badge sinkronisasi (teks disembunyikan di <=768px) yang sebelumnya
     tersisa sebagai kotak kosong bergaris, kini jadi titik status 8px
     (hijau = cloud on, merah = off/mode baca saja).
   - drawer: padding atas & jarak brand/label grup dirapatkan.
   ============================================================ */
@media (max-width: 1023px) {
  .header {
    margin: var(--space-8) 0 var(--space-12);
    padding: var(--space-4) var(--space-8);
    gap: 0;
    box-shadow: none;
  }
  .header .hamburger-btn-icon { width: 40px; height: 40px; }
  .book-selector { gap: var(--space-4); padding-bottom: 0; }
  #appSidebar { padding-top: var(--space-12); }
  .app-sidebar-brand { padding-bottom: var(--space-10); }
  .app-nav-group-label { padding-top: var(--space-6); }
}
@media (max-width: 768px) {
  .header .sync-status-container {
    width: 8px; height: 8px; min-width: 8px;
    padding: 0; border: 0; border-radius: 50%;
    margin: 0 var(--space-6);
    flex-shrink: 0;
  }
  .header .sync-status-container.online  { background: var(--success); }
  .header .sync-status-container.offline { background: var(--danger); }
}

/* ============================================================
   LEGEND DONUT (Pengeluaran per Kategori) TERBACA DI HAPE
   Masalah: di layar sempit donut 150px + legend berdampingan --
   nominal (mono) & persen memakan hampir seluruh lebar legend, jadi
   .legend-label (flex:1 + ellipsis) menyusut ke ~0px dan nama kategori
   tidak terbaca sama sekali. Solusi (<=640px): donut di atas
   (ditengah), legend di bawah selebar kartu, nama kategori boleh
   turun baris (bukan dipotong "..."), dan semua kategori tampil
   (tanpa kotak scroll di dalam halaman).
   ============================================================ */
@media (max-width: 640px) {
  .expense-chart-body { flex-direction: column; align-items: center; gap: var(--space-14); }
  .expense-chart-canvas-wrap { flex: 0 0 auto; width: 170px; max-width: 170px; height: 170px; }
  .expense-chart-canvas-wrap canvas { max-height: 170px !important; }
  .expense-chart-legend {
    flex: 0 0 auto;
    align-self: stretch;
    width: 100%;
    min-width: 0;
    max-width: none;
    max-height: none;
    overflow: visible;
    gap: var(--space-8);
  }
  .legend-item { align-items: flex-start; font-size: var(--text-sm); }
  .legend-dot { margin-top: .4em; }
  .legend-label {
    min-width: 0;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: anywhere;
    line-height: 1.3;
  }
  .legend-amount { line-height: 1.3; }
  .legend-pct { font-size: var(--text-xs); line-height: 1.5; }
}

/* ============================================================
   FIX NAMA BUKU DI DRAWER TERPOTONG
   #appSidebar = flex column dengan tinggi tetap (100%) + overflow-y:auto.
   Saat isi drawer lebih tinggi dari layar (hape: item nav ber-padding
   besar untuk area sentuh), anak flex default flex-shrink:1 ikut
   dikempiskan -- .app-sidebar-brand punya overflow:hidden (min-height
   otomatis 0) sehingga tingginya dikempiskan sampai nama buku terpotong
   separuh. Semua anak langsung drawer dilarang menyusut; kelebihan
   tinggi ditangani scroll drawer, bukan memotong konten.
   ============================================================ */
#appSidebar > * { flex-shrink: 0; }

/* ============================================================
   FORM "JADWAL PEMBAYARAN" DI HAPE -- ukuran font & tinggi field seragam
   Masalah: di perangkat sentuh semua .form-control dipaksa 16px (anti
   auto-zoom Safari iOS, lihat blok "hover:none + pointer:coarse" di atas),
   sedangkan dropdown "Pengulangan" (custom select, .cs-trigger form-style)
   tetap 12px/36px -- jadi dalam satu form teks input terlihat jauh lebih
   besar daripada dropdown, label, dan tombol di sekitarnya.
   Solusi khusus modal ini: input & dropdown memakai ukuran yang sama
   (--text-md ~14.7px, tinggi ~38px). Di iOS (Safari) tetap 16px karena di
   bawah itu Safari zoom otomatis saat field difokus -- dideteksi lewat
   @supports (-webkit-touch-callout) yang hanya ada di WebKit iOS.
   ============================================================ */
@media (hover: none) and (pointer: coarse) {
  #paymentReminderModal .form-control,
  #paymentReminderModal select.form-control {
    font-size: var(--text-md);
    padding-top: var(--space-10);
    padding-bottom: var(--space-10);
  }
  #paymentReminderModal .cs-wrapper.form-style .cs-trigger {
    font-size: var(--text-md);
    min-height: 38px;
    padding-top: var(--space-8);
    padding-bottom: var(--space-8);
  }
}
@supports (-webkit-touch-callout: none) {
  @media (hover: none) and (pointer: coarse) {
    #paymentReminderModal .form-control,
    #paymentReminderModal select.form-control,
    #paymentReminderModal .cs-wrapper.form-style .cs-trigger { font-size: 16px; }
  }
}

/* ==================== SILSILAH KELUARGA (js/silsilah.js) ====================
   Kanvas tree SVG. Di layar sempit sengaja TIDAK diperkecil sampai tidak
   terbaca -- container pembungkus (.silsilah-tree-container) scroll ke
   samping (overflow-x:auto, sudah di-set inline di index.html pada wrapper
   modal), jadi kotak & teks tetap ukuran nyaman dibaca sambil digeser. */
/* [OPTIMASI] Kotak cari anggota -- makin banyak anggota tercatat, makin
   susah cari satu orang cuma dengan geser/zoom manual di kanvas. Ketik
   nama di sini langsung menyorot & memusatkan kotaknya di kanvas (lihat
   window._famOnSearchInput/_famFocusMember di js/silsilah.js), tanpa
   perlu geser-geser cari sendiri. */
.silsilah-search-bar {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-8);
  margin: 0 var(--space-16) var(--space-10);
  padding: 0 var(--space-10);
  height: 38px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--paper);
}
.silsilah-search-bar:focus-within {
  border-color: var(--accent);
}
/* [HEMAT TEMPAT] Kotak cari kini ada DI DALAM header modal Silsilah, di antara
   judul & tombol "+ Anggota Baru" (bukan baris tersendiri di bawah header).
   Lebarnya mengisi sisa ruang header; dropdown hasil dilebarkan supaya tetap
   terbaca walau kotaknya sempit. */
#silsilahModal .modal-header { position: relative; gap: var(--space-12); }
#silsilahModal .modal-header h3 { flex: 0 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#silsilahModal .modal-header .silsilah-search-bar {
  flex: 1 1 0;
  min-width: 90px;
  max-width: 420px;
  margin: 0 0 0 auto;
  height: 34px;
}
#silsilahModal .modal-header .modal-header-action { margin-left: 0; flex: 0 0 auto; }
#silsilahModal .modal-header .silsilah-search-results {
  right: auto;
  width: max(100%, 300px);
}
@media (max-width: 760px) {
  /* Hp: dropdown hasil menempel ke header (selebar header), bukan ke kotak
     cari yang sempit; tombol tambah jadi ikon "+" saja supaya kotak cari
     kebagian ruang. */
  #silsilahModal .modal-header .silsilah-search-bar { position: static; margin-left: 0; }
  #silsilahModal .modal-header .silsilah-search-results { top: calc(100% + 4px); left: 0; right: 0; width: auto; }
  #silsilahModal .modal-header .silsilah-add-label { display: none; }
  #silsilahModal .modal-header { gap: var(--space-8); }
}
.silsilah-search-icon {
  flex: none;
  color: var(--ink-faint);
}
.silsilah-search-input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-size: var(--text-sm);
  color: var(--ink);
}
.silsilah-search-input::-webkit-search-cancel-button { display: none; }
.silsilah-search-clear {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border: none;
  background: none;
  color: var(--ink-faint);
  cursor: pointer;
  border-radius: 50%;
}
.silsilah-search-clear:hover { background: var(--paper-warm); color: var(--ink); }
.silsilah-search-results {
  position: absolute;
  z-index: 10;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 240px;
  overflow-y: auto;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: 0 6px 20px rgba(0,0,0,0.12);
  padding: var(--space-4) 0;
}
.silsilah-search-result-item {
  display: flex;
  align-items: baseline;
  gap: var(--space-8);
  width: 100%;
  padding: var(--space-8) var(--space-12);
  border: none;
  background: none;
  text-align: left;
  font-size: var(--text-sm);
  color: var(--ink);
  cursor: pointer;
}
.silsilah-search-result-item:hover,
.silsilah-search-result-item.is-active {
  background: var(--paper-warm);
}
.silsilah-search-result-name { font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.silsilah-search-result-years { flex: none; font-size: var(--text-xs); color: var(--ink-faint); }
.silsilah-search-empty {
  padding: var(--space-8) var(--space-12);
  font-size: var(--text-xs);
  color: var(--ink-faint);
}
/* Kotak yang sedang disorot hasil pencarian -- outline tebal warna aksen
   + kedip pelan 2x supaya mata langsung tertuju ke sana di kanvas ramai,
   lalu diam (tetap outline) sampai pencarian diganti/dibersihkan. */
.silsilah-node-highlight rect.silsilah-node-box {
  stroke: var(--accent) !important;
  stroke-width: 3px !important;
  animation: silsilahHighlightPulse 0.5s ease-in-out 2;
}
@keyframes silsilahHighlightPulse {
  0%, 100% { filter: drop-shadow(0 0 0 rgba(0,0,0,0)); }
  50% { filter: drop-shadow(0 0 6px var(--accent)); }
}
/* [UX] Legenda statis di atas kanvas (di LUAR wrapper overflow-x:auto,
   supaya tidak ikut hilang tergeser saat pohon lebar digulir ke samping). */
.silsilah-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-12);
  justify-content: center; /* legenda di tengah */
  padding: var(--space-8) var(--space-16) 0;
  flex: 0 0 auto; /* kini di bawah kanvas pohon (flex-kolom): jangan ikut mengecil */
  font-size: var(--text-xs);
  color: var(--ink-faint);
}
.silsilah-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.silsilah-legend-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  display: inline-block;
}
.silsilah-legend-dot-l { background: var(--accent); }
.silsilah-legend-dot-p { background: var(--warning); }
.silsilah-legend-dot-u { background: var(--ink-faint); }
.silsilah-legend-dash {
  width: 14px;
  height: 0;
  border-top: 1.5px dashed var(--accent);
  display: inline-block;
}
/* [SINKRON DGN GARIS ASLI] Sebelumnya swatch ini masih dipakai utk item
   "Sudah wafat" & warnanya ikut var(--accent) -- dua-duanya sudah tidak
   cocok lagi dgn kanvas sungguhan: (1) status wafat individu SEKARANG
   ditandai lewat kartu hangat + strip aksen redup (lihat
   .silsilah-node-dead di bawah), BUKAN garis putus-putus lagi -- swatch
   dash ini dipakai ulang utk item baru "Pernikahan berakhir" yang memang
   masih digambar sbg garis putus-putus (.silsilah-line-spouse-ended).
   (2) warna cross-link sungguhan var(--info) & bentuknya TITIK bulat
   (.silsilah-line-cross, lihat js/silsilah.js), bukan garis putus-putus
   var(--accent) -- style dotted + var(--info) di bawah supaya swatch
   legenda benar-benar mewakili apa yg terlihat di kanvas. */
.silsilah-legend-dash-cross {
  border-top-style: dotted;
  border-top-color: var(--info);
  border-top-width: 2px;
}
/* Swatch "Cerai mati" -- override eksplisit ke var(--ink-faint), beda dari
   swatch dasar "Cerai hidup" di atas (var(--accent)) -- PERSIS sinkron dgn
   dua garis sungguhan di kanvas (.silsilah-line-spouse-ended vs
   .silsilah-line-spouse-wafat, lihat js/silsilah.js), supaya legenda
   benar-benar mewakili beda visual yang terlihat di pohon. */
.silsilah-legend-dash-wafat {
  border-top-color: var(--ink-faint);
}
/* [BARU] Swatch mini utk item "Sudah wafat" -- meniru PERSIS gaya kartu
   anggota yang sudah wafat sungguhan (.silsilah-node-dead di bawah: fill
   var(--paper-warm) + strip aksen kiri yang diredupkan opacity 0.4),
   supaya legenda mengajari mata mencari pola kartu yang benar, bukan
   pola garis yang sudah tidak dipakai lagi utk makna ini. */
.silsilah-legend-swatch-dead {
  width: 16px;
  height: 11px;
  border-radius: 3px;
  display: inline-block;
  position: relative;
  overflow: hidden;
  background: var(--paper-warm);
  border: 1.25px solid var(--rule);
}
.silsilah-legend-swatch-dead::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: var(--ink-faint);
  opacity: 0.4;
}

/* ── Rekapan Keluarga: kartu ringkasan statistik anggota, tampil di atas
   kanvas pohon (di bawah legenda). Diisi/di-update oleh
   window._famRenderRecap() di js/silsilah.js setiap kali tree dirender
   ulang (window.renderFamilyTreeView). Disembunyikan (hidden) saat belum
   ada anggota sama sekali. */
.silsilah-recap-card {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-10);
  margin: 0 var(--space-16) var(--space-12);
  padding: var(--space-12) var(--space-14);
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
}
.silsilah-recap-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 2px;
  padding: 0 var(--space-4);
}
.silsilah-recap-item + .silsilah-recap-item { border-left: 1px solid var(--rule); }
.silsilah-recap-value {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--ink);
  line-height: 1.2;
}
.silsilah-recap-label {
  font-size: 10px;
  color: var(--ink-faint);
  line-height: 1.25;
}
@media (max-width: 760px) {
  .silsilah-recap-card {
    grid-template-columns: repeat(3, 1fr);
    margin: 0 var(--space-12) var(--space-10);
    padding: var(--space-10) var(--space-8);
  }
  .silsilah-recap-item:nth-child(3n+1) { border-left: none; }
  .silsilah-recap-item { padding-bottom: var(--space-6); }
}

/* [REKAP PER GENERASI] Kartu chip G1, G2, G3, ... di bawah kartu rekap utama.
   Warna tiap chip = --gen-color dari kelas .silsilah-gen-N (sama dgn kotak
   pohon). Baris chip bisa di-scroll horizontal kalau generasinya banyak. */
.silsilah-genrecap-card {
  /* [SATU BARIS] Judul + semua chip generasi sejajar dalam 1 baris; isi
     tiap chip juga 1 baris (G# · jumlah · rincian). */
  display: flex;
  align-items: center;
  gap: var(--space-10);
  margin: 0 var(--space-16) var(--space-12);
  padding: var(--space-8) var(--space-14);
  background: var(--paper);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
}
.silsilah-genrecap-title {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}
.silsilah-genrecap-list {
  /* [FIT KE LAYAR] Semua chip berbagi sisa lebar kartu sama rata (flex: 1 1 0 +
     min-width: 0) -- tidak ada scroll horizontal; makin banyak generasi,
     makin sempit tiap chip, tapi selalu muat di layar. */
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  gap: var(--space-6);
}
.silsilah-genrecap-chip {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: row;
  align-items: baseline;
  justify-content: center;
  gap: var(--space-6);
  padding: var(--space-4) var(--space-6);
  overflow: hidden;
  white-space: nowrap;
  border-radius: var(--radius);
  border: 1.5px solid color-mix(in srgb, var(--gen-color) 45%, var(--rule));
  background: color-mix(in srgb, var(--gen-color) 12%, var(--paper));
}
[data-theme="dark"] .silsilah-genrecap-chip {
  background: color-mix(in srgb, var(--gen-color) 22%, var(--paper));
}
.silsilah-genrecap-gen {
  flex: 0 0 auto;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--gen-color);
}
.silsilah-genrecap-count {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.1;
  color: var(--ink);
}
.silsilah-genrecap-detail {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 10px;
  color: var(--ink-faint);
}
@media (max-width: 760px) {
  .silsilah-genrecap-card {
    margin: 0 var(--space-12) var(--space-10);
    padding: var(--space-6) var(--space-8);
  }
  /* Hp: judul & rincian L/P disembunyikan (rincian masih ada di tooltip/title)
     supaya 1 baris tetap muat -- tersisa G# + jumlah anggota per chip. */
  .silsilah-genrecap-title,
  .silsilah-genrecap-detail { display: none; }
  .silsilah-genrecap-list { gap: var(--space-4); }
  .silsilah-genrecap-chip { padding: var(--space-4) 2px; gap: var(--space-4); }
}

/* [REKAP WAFAT] Item "Masih Hidup / Wafat" di kartu rekap bisa diketuk ->
   membuka daftar almarhum/almarhumah (bin/binti). Lihat
   window.openSilsilahWafatModal di js/silsilah.js. */
button.silsilah-recap-item-btn {
  appearance: none;
  background: transparent;
  border: 0;
  border-left: 1px solid var(--rule);
  font: inherit;
  color: inherit;
  cursor: pointer;
  border-radius: var(--radius);
  transition: background .15s ease;
}
button.silsilah-recap-item-btn:hover,
button.silsilah-recap-item-btn:focus-visible { background: var(--paper-2, rgba(0,0,0,.04)); outline: none; }
.silsilah-recap-more { font-size: 10px; color: var(--accent, var(--ink-soft, var(--ink-faint))); line-height: 1.2; }

/* [KELOLA DATA SILSILAH] Bar Ekspor / Impor / Hapus Semua di atas kartu rekap
   (#silsilahDataBar, index.html; handler di js/silsilah.js), di BAWAH kanvas pohon supaya
   jauh dari tombol yang sering diketuk. "Hapus Semua" didorong
   ke kanan & berwarna danger supaya tidak tertekan tidak sengaja. */
.silsilah-data-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  flex: 0 0 auto; /* di bawah kanvas (flex-kolom): jangan ikut mengecil */
  margin: var(--space-8) var(--space-16);
}
/* [DIKECILKAN] Tombol dibuat "hantu": tanpa border & latar, font dan ikon
   lebih kecil, warna redup -- supaya tidak mencolok di bawah pohon. Baru
   terlihat jelas saat di-hover/fokus. */
.silsilah-data-btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  font: inherit;
  font-size: 10.5px;
  line-height: 1.3;
  color: var(--ink-faint);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.silsilah-data-btn svg { width: 12px; height: 12px; }
.silsilah-data-btn:hover,
.silsilah-data-btn:focus-visible {
  background: var(--paper-2, rgba(0,0,0,.04));
  color: var(--ink);
  border-color: var(--rule);
  outline: none;
}
.silsilah-data-btn[disabled] { opacity: .55; cursor: progress; }
.silsilah-data-btn-danger {
  margin-left: auto;
}
.silsilah-data-btn-danger:hover,
.silsilah-data-btn-danger:focus-visible {
  color: var(--danger, #b3261e);
  border-color: var(--danger, #b3261e);
  background: transparent;
}
/* [DI LUAR KARTU] Bar ini sekarang sibling .modal-content di #silsilahModal,
   yaitu DI BAWAH kartu Silsilah Keluarga (bukan di dalamnya). Desktop: modal
   berupa block, jadi bar otomatis turun di bawah kartu. Hp: modal berupa
   flex fixed layar penuh, jadi dijadikan kolom -- kartu mengisi sisa tinggi
   (scroll sendiri) dan bar menempel di bawahnya. */
#silsilahModal > .silsilah-data-bar { margin: var(--space-8) 0 0; }
@media (max-width: 1023px) {
  #silsilahModal.show { flex-direction: column; }
  #silsilahModal.show .modal-content { flex: 1 1 auto; height: auto; min-height: 0; }
  #silsilahModal > .silsilah-data-bar { margin: var(--space-4) var(--space-12) var(--space-8); }
}
@media (max-width: 760px) {
  .silsilah-data-bar { margin: var(--space-6, 6px) var(--space-12); }
}

/* [REKAP WAFAT - COMPACT] Toolbar 1 baris, baris daftar ~2 baris pendek
   (nama+nasab / gelar·tahun·usia) dengan tahun wafat rata kanan. */
#silsilahWafatModal .modal-header { padding-top: var(--space-10); padding-bottom: var(--space-10); }
.silsilah-wafat-toolbar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-8);
  padding: var(--space-6) var(--space-14);
  border-bottom: 1px solid var(--rule);
}
.silsilah-wafat-summary { font-size: 11px; color: var(--ink-faint); min-width: 0; }
.silsilah-wafat-sorts {
  display: inline-flex; flex-shrink: 0; padding: 2px;
  border: 1px solid var(--rule); border-radius: 999px; background: var(--paper);
}
.silsilah-wafat-sort {
  font: inherit; font-size: 11px; line-height: 1;
  padding: 5px 10px; border: 0; border-radius: 999px;
  background: transparent; color: var(--ink-faint); cursor: pointer;
}
.silsilah-wafat-sort.active { background: var(--ink); color: var(--paper); font-weight: 600; }
.silsilah-wafat-list { max-height: 60vh; overflow-y: auto; padding: 0 var(--space-6); overscroll-behavior: contain; }
.silsilah-wafat-empty { padding: var(--space-16) var(--space-8); text-align: center; font-size: var(--text-xs); color: var(--ink-faint); }
.silsilah-wafat-row {
  display: grid; grid-template-columns: 1.7em minmax(0, 1fr) auto; align-items: center; column-gap: var(--space-6);
  width: 100%; text-align: left; font: inherit; color: inherit;
  padding: 7px var(--space-8); background: transparent; border: 0;
  border-bottom: 1px solid var(--rule); cursor: pointer;
}
.silsilah-wafat-row:last-child { border-bottom: 0; }
.silsilah-wafat-row:hover, .silsilah-wafat-row:focus-visible { background: var(--paper-2, rgba(0,0,0,.04)); outline: none; }
.silsilah-wafat-num { font-size: 11px; color: var(--ink-faint); text-align: right; font-variant-numeric: tabular-nums; }
.silsilah-wafat-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.silsilah-wafat-name {
  font-size: var(--text-sm, 13px); font-weight: 600; color: var(--ink); line-height: 1.3;
  overflow-wrap: anywhere;
}
.silsilah-wafat-nasab { font-weight: 400; color: var(--ink-faint); }
.silsilah-wafat-meta { font-size: 10.5px; color: var(--ink-faint); line-height: 1.3; }
.silsilah-wafat-warn { margin-left: 6px; color: var(--warning, #b26a00); }
.silsilah-wafat-year {
  font-size: 11px; font-weight: 600; color: var(--ink-soft, var(--ink));
  padding: 2px 8px; border: 1px solid var(--rule); border-radius: 999px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.silsilah-wafat-footer {
  padding: var(--space-8) var(--space-14); border-top: 1px solid var(--rule);
  display: flex; justify-content: flex-end;
}
.silsilah-wafat-footer .btn { padding: 7px 14px; font-size: var(--text-xs); }

/* [ZOOM/PAN] Kanvas sekarang punya viewport tinggi tetap (overflow:hidden)
   dan pohonnya di-transform (translate+scale) lewat JS -- lihat
   window._famZoom* di js/silsilah.js. Wrapper luar (.silsilah-zoom-wrap)
   cuma penampung posisi relatif untuk tombol kontrol mengambang. */
/* [FULL HEIGHT] Kanvas SEKARANG mengisi semua sisa tinggi yang tersedia
   (bukan dibatasi 58vh/520px lagi) -- .silsilah-zoom-wrap & .silsilah-
   tree-viewport jadi flex item yang "flex:1" di dalam #silsilahModal
   .modal-content (lihat aturan #silsilahModal.show .modal-content di
   bawah utk desktop; di layar hp .modal-content SUDAH flex-column lewat
   aturan bawaan body.view-fullpage). Header & legenda di atasnya tetap
   ukuran alami (flex:0 default), sisanya diambil kanvas. */
.silsilah-zoom-wrap {
  position: relative;
  flex: 1 1 auto;
  display: flex;
  min-height: 0; /* penting dalam flex column: tanpa ini child tidak pernah mengecil dari ukuran kontennya */
}
.silsilah-tree-viewport {
  position: relative;
  overflow: hidden;
  flex: 1 1 auto;
  height: auto;
  min-height: 320px;
  border-radius: var(--radius-sm);
  background: var(--paper-warm);
  cursor: grab;
  touch-action: none; /* semua gesture (pan 1 jari, pinch 2 jari) ditangani manual lewat Pointer Events */
  -webkit-user-select: none;
  user-select: none;
}
.silsilah-tree-viewport.silsilah-panning {
  cursor: grabbing;
}
.silsilah-tree-container {
  position: absolute;
  top: 0;
  left: 0;
  padding: var(--space-12) var(--space-16);
  transform-origin: 0 0;
  /* Transisi hanya dinyalakan oleh JS saat perlu (tombol +/-/reset, atau
     akhir gesture pinch/drag) -- selama drag/pinch berlangsung transisi
     dimatikan supaya kanvas ikut jari/kursor tanpa lag "mengejar". */
}
.silsilah-tree-container.silsilah-zoom-animated {
  transition: transform 0.22s cubic-bezier(.2,.8,.2,1);
}
.silsilah-tree-svg {
  display: block;
  max-width: none;
  overflow: visible; /* biar shadow hover pada node tidak terpotong di tepi kanvas */
}
.silsilah-zoom-controls {
  position: absolute;
  right: var(--space-12);
  bottom: var(--space-12);
  display: flex;
  flex-direction: column;
  gap: 6px;
  z-index: 2;
}
.silsilah-zoom-btn {
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--shadow-sm, 0 1px 3px rgba(0,0,0,.12));
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, transform 0.1s ease;
}
.silsilah-zoom-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.silsilah-zoom-btn:active {
  transform: scale(0.92);
}
.silsilah-zoom-btn-reset {
  font-size: var(--text-xs);
}
/* [FULL HEIGHT - DESKTOP] Di layar hp, .modal-content halaman fullview
   SUDAH flex-column & height:100% (aturan bawaan body.view-fullpage),
   jadi .silsilah-zoom-wrap flex:1 otomatis mengisi penuh. Di desktop
   (>=1024px) modal-content default-nya height:auto/display:block (biar
   pas dgn tinggi konten) -- sengaja DIKECUALIKAN khusus utk modal ini
   (selector #ID menang atas aturan umum .fullview-modal tanpa perlu
   !important) supaya kanvas pohon ikut memenuhi sisa tinggi layar,
   bukan cuma setinggi 520px lalu menyisakan area kosong di bawahnya.
   calc: 100vh dikurangi padding atas+bawah .fullview-modal.show sendiri
   (var(--space-28) + var(--space-40), lihat media query min-width:1024px
   di atas). */
@media (min-width: 1024px) {
  #silsilahModal.show .modal-content {
    display: flex;
    flex-direction: column;
    /* tambahan var(--space-40) = ruang bar Ekspor/Impor/Hapus di bawah kartu,
       supaya tetap muat di layar tanpa perlu scroll */
    min-height: calc(100vh - var(--space-28) - var(--space-40) - var(--space-40));
    min-height: calc(100dvh - var(--space-28) - var(--space-40) - var(--space-40));
  }
}
/* [LEBIH HIDUP] Pita generasi selang-seling + label "G1/G2/.." di tepi
   kiri kanvas (lihat loop di window.renderFamilyTree) -- sangat halus,
   cuma utk membantu mata membaca pohon sebagai lapisan/tingkatan,
   bukan elemen dekoratif yang mencolok. */
.silsilah-gen-band {
  fill: var(--accent);
  opacity: 0.035;
}
.silsilah-gen-label {
  fill: var(--ink-faint);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.04em;
  opacity: 0.45;
  font-family: inherit;
}

/* [LEBIH HIDUP] Semua garis "tumbuh" dari 0 ke penuh saat pohon pertama
   kali dirender, mengalir dari generasi akar ke generasi paling bawah
   (--line-delay diisi per-garis di JS). pathLength="1" di elemen SVG
   menormalkan panjang garis apa pun bentuknya jadi 1 unit, jadi
   stroke-dasharray:1 + animasi dashoffset selalu pas tanpa perlu hitung
   panjang asli tiap garis. Dihormati prefers-reduced-motion di bawah. */
.silsilah-line {
  /* [FIX KONTRAS] Sebelumnya var(--rule) -- rasio kontras thd --paper
     nyaris 1:1 di mode terang (nyaris tak kelihatan), tipis juga di
     mode gelap. var(--ink-muted) sudah teruji kontrasnya di teks lain
     pada kedua tema, jadi dipakai ulang di sini supaya garis pohon
     benar-benar terbaca tanpa perlu warna baru di luar palet. */
  stroke: var(--ink-muted);
  opacity: 0.82;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: famLineGrow 0.55s cubic-bezier(.25,.75,.35,1) forwards;
  animation-delay: var(--line-delay, 0s);
}
@keyframes famLineGrow {
  to { stroke-dashoffset: 0; }
}
.silsilah-line-spouse {
  stroke: var(--accent);
  stroke-width: 2;
}
/* [TAHAP 4 -- BANYAK PASANGAN] Pernikahan yang sudah berakhir (cerai
   hidup/mati, lihat family_marriages.status & window.buildFamilyTree)
   -- putus-putus & lebih pudar drpd pernikahan aktif, supaya riwayat
   pasangan lama tetap terbaca di pohon tanpa disangka pasangan
   "sekarang". Titik penanda ikatan (.silsilah-spouse-mark) sengaja TIDAK
   ditampilkan di garis ini (lihat window.renderFamilyTree). */
.silsilah-line-spouse-ended {
  /* [PENTING] Garis ini pakai pathLength="1" (lihat .silsilah-line di
     atas) supaya animasi "tumbuh" konsisten -- jadi nilai dash di sini
     HARUS dalam satuan relatif thd panjang 1, BUKAN piksel (mis. "4 3"
     akan lebih panjang dari garisnya sendiri & jadi kelihatan solid). */
  stroke-dasharray: 0.05 0.035;
  opacity: 0.55;
}
/* [FIX GAP TAMPILAN] Sebelumnya cerai_hidup & cerai_mati sama-sama cuma
   pakai .silsilah-line-spouse-ended (warna var(--accent) yang sudah
   diredupkan opacity 0.55 di atas) -- dua status berbeda makna itu jadi
   tidak bisa dibedakan di kanvas walau form & database membedakannya
   jelas ("Cerai Hidup" vs "Cerai Mati"). Class tambahan ini HANYA dipakai
   utk cerai_mati (lihat window.renderFamilyTree) -- override warna ke
   var(--ink-faint) (netral, BUKAN nuansa hijau var(--accent)) supaya
   senada dgn bahasa visual "wafat" yang sudah dipakai di kotak anggota
   (.silsilah-node-dead) -- cerai_hidup TETAP ikut var(--accent) bawaan
   .silsilah-line-spouse (masih ada unsur "pasangan", cuma sudah pisah),
   cerai_mati jadi netral/pudar (menandakan salah satu sudah tiada).
   Tidak menambah hue baru -- cuma menukar var(--accent) -> var(--ink-faint)
   yang sudah ada di palet, sesuai batasan token warna di file ini. */
.silsilah-line-spouse-wafat {
  stroke: var(--ink-faint);
}
/* Penanda belah ketupat kecil di tengah garis cerai_mati -- pasangan
   dgn .silsilah-spouse-mark (lingkaran, pernikahan aktif) supaya bentuk
   ikut beda, bukan cuma warna, dari kejauhan/ukuran kecil. */
.silsilah-spouse-mark-wafat {
  fill: var(--ink-faint);
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: famDotPop 0.3s ease forwards;
  animation-delay: var(--line-delay, 0s);
}
/* Titik kecil di tengah garis pasangan -- penanda "ikatan", muncul
   sesaat setelah garisnya selesai tumbuh. */
.silsilah-spouse-mark {
  fill: var(--accent);
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: famDotPop 0.3s ease forwards;
  animation-delay: var(--line-delay, 0s);
}
/* [BEDA WARNA] Titik ujung garis cross-link dulu ikut var(--accent) --
   sama persis dgn warna garis pasangan (.silsilah-spouse-mark) di atas,
   jadi susah dibedakan sekilas mana penanda pernikahan mana penanda
   sambungan antar keluarga. Sekarang dipisah, pakai var(--info) yang
   sama dgn stroke garis cross-link-nya sendiri (lihat .silsilah-line-cross
   di bawah) supaya satu warna konsisten utk satu makna. */
.silsilah-cross-dot {
  fill: var(--info);
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: famDotPop 0.3s ease forwards;
  animation-delay: var(--line-delay, 0s);
}
@keyframes famDotPop {
  from { opacity: 0; transform: scale(0.3); }
  to { opacity: 1; transform: scale(1); }
}
/* [MULTI-KELUARGA] Garis penghubung antar pohon keluarga terpisah (mis.
   keluarga Ibu & keluarga Bapak yang bertemu lewat pernikahan) -- lihat
   crossLinks di window.buildFamilyTree/renderFamilyTree. Sengaja
   dibedakan dari garis ortu-anak biasa (solid, var(--rule)) & garis
   pasangan (solid, var(--accent)) supaya jelas ini "sambungan", bukan
   relasi ortu-anak langsung.
   [FIX] Sebelumnya "7 5" -- angka itu satuan PIKSEL, padahal elemen ini
   pakai pathLength="1" (lihat .silsilah-line), yang menormalkan seluruh
   panjang garis apa pun bentuknya jadi 1 unit. Dash "7" jauh lebih
   panjang dari 1 unit itu sendiri, jadi dash pertama sudah menutupi
   seluruh garis -- hasilnya kelihatan SOLID, bukan putus-putus. Diganti
   ke satuan relatif (pola lebih renggang/kasar drpd dash titik-titik
   halus punya garis pasangan "sudah berakhir" di atas, 0.05 0.035,
   supaya dua makna dash itu tidak tertukar).
   [BEDA WARNA] stroke juga dipindah dari var(--accent) (identik dgn
   warna garis pasangan) ke var(--info) -- warna biru-kehijauan yang
   sudah ada di palet (dipakai badge/status info), beda hue jelas dari
   hijau var(--accent), supaya sambungan antar keluarga langsung
   kebeda dari garis pasangan tanpa perlu warna baru di luar palet.
   [FIX GARIS KELIHATAN PUTUS DI BROWSER] Trik "tumbuh" bawaan
   .silsilah-line (stroke-dasharray:1 + stroke-dashoffset:1->0 lewat
   famLineGrow) didesain khusus utk SATU dash sepanjang PENUH garis --
   itu cara animasi dash yg umum dipakai utk efek garis "menggambar diri
   sendiri". Begitu class ini menimpa stroke-dasharray jadi pola
   berulang pendek TAPI stroke-dashoffset/animation bawaan tetap
   kepakai, browser jadi harus geser pola pendek itu sejauh 1 unit
   penuh -- hasilnya cuma sebagian pola yg kebagian "muncul" di titik
   mana pun selama & setelah animasi, jadi garis kelihatan patah-
   patah/putus alih-alih dash yg rapi. Jalan keluarnya: lepas total dari
   mekanisme dashoffset-tumbuh itu utk garis ini -- dashoffset dikunci 0
   (pola dash langsung penuh & stabil sejak awal), efek "muncul"-nya
   diganti fade opacity polos (famCrossFadeIn) yg tidak bersinggungan
   sama sekali dgn perhitungan dash.
   [FIX JADI TITIK BULAT KONSISTEN] Dulu path ini masih dibubuhi
   pathLength="1" (lihat window._famElbowPath di js/silsilah.js) --
   akibatnya angka stroke-dasharray di bawah ini bukan satuan px asli,
   tapi PECAHAN dari total panjang garisnya sendiri, jadi ukuran &
   jarak "titik" beda-beda tiap cross-link tergantung panjang aslinya
   (yang pendek nyaris tak kelihatan, yang panjang malah jadi strip
   garis, bukan titik). Sekarang path cross-link TIDAK lagi pakai
   pathLength (lihat js/silsilah.js), jadi angka di sini beneran satuan
   px sama seperti koordinat path -- konsisten di semua cross-link.
   Pola "0 7": dash sepanjang 0 + stroke-linecap:round (bawaan dari
   .silsilah-line) bikin tiap "dash" nol-panjang itu dirender sbg
   lingkaran penuh berdiameter = stroke-width -- trik SVG standar utk
   garis titik-titik (dotted), beda dari garis putus-putus (dashed)
   yang stripnya punya panjang. Jarak antar titik (gap) 7px cukup
   renggang supaya jelas beda dari garis ortu-anak/pasangan yang solid. */
.silsilah-line-cross {
  stroke: var(--info);
  stroke-width: 1.75;
  stroke-dasharray: 0 7;
  stroke-linecap: round;
  stroke-dashoffset: 0;
  opacity: 0;
  animation: famCrossFadeIn 0.35s ease forwards;
  animation-delay: var(--line-delay, 0s);
}
@keyframes famCrossFadeIn {
  from { opacity: 0; }
  to { opacity: 0.85; }
}
.silsilah-node {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.12s ease;
  opacity: 0;
  animation: famNodeEnter 0.4s cubic-bezier(.2,.8,.25,1) forwards;
  animation-delay: var(--node-delay, 0s);
}
@keyframes famNodeEnter {
  from { opacity: 0; transform: translateY(5px) scale(0.94); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
/* Pengguna yang minta animasi diminimalkan: langsung tampil penuh,
   tanpa garis "tumbuh" atau kotak yang muncul bertahap. */
@media (prefers-reduced-motion: reduce) {
  .silsilah-line, .silsilah-spouse-mark, .silsilah-spouse-mark-wafat, .silsilah-cross-dot, .silsilah-node {
    animation: none !important;
    opacity: 1 !important;
    stroke-dashoffset: 0 !important;
  }
}
/* [REDESIGN KOTAK ANGGOTA] Sebelumnya identitas gender ditandai lewat
   warna STROKE tipis di keliling kotak (1.5px, gampang lebur dengan
   garis pohon di sekitarnya). Sekarang kotak jadi kartu netral (stroke
   --rule + bayangan halus) dan gender ditandai lewat strip warna solid
   di sisi kiri (.silsilah-node-accent-bar, digambar dgn clipPath biar
   sudut kirinya ikut membulat mengikuti kotak) -- jauh lebih jelas
   dibaca sekilas tanpa perlu warna kompetisi dgn garis penghubung. */
.silsilah-node rect.silsilah-node-box {
  fill: var(--paper);
  stroke: var(--rule);
  stroke-width: 1.25;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.07));
  transition: stroke 0.15s ease, fill 0.15s ease, filter 0.15s ease;
}
.silsilah-node:hover,
.silsilah-node:focus {
  transform: scale(1.035);
}
.silsilah-node:hover rect.silsilah-node-box,
.silsilah-node:focus rect.silsilah-node-box {
  cursor: pointer;
  outline: none;
  filter: drop-shadow(0 5px 12px rgba(0,0,0,0.15));
}
.silsilah-node-accent-bar { fill: var(--ink-faint); }
.silsilah-node-l .silsilah-node-accent-bar { fill: var(--accent); }
.silsilah-node-p .silsilah-node-accent-bar { fill: var(--warning); }
.silsilah-node-l:hover rect.silsilah-node-box, .silsilah-node-l:focus rect.silsilah-node-box { stroke: var(--accent); }
.silsilah-node-p:hover rect.silsilah-node-box, .silsilah-node-p:focus rect.silsilah-node-box { stroke: var(--warning); }
.silsilah-node-u:hover rect.silsilah-node-box, .silsilah-node-u:focus rect.silsilah-node-box { stroke: var(--ink-faint); }
/* [A11Y] Kotak anggota bisa ditab (tabindex="0", role="button" -- lihat
   window.renderFamilyTree) tapi indikator fokusnya SEBELUMNYA sama
   samar dgn hover mouse biasa (cuma stroke tipis 1.25px ganti warna) --
   utk pohon dgn puluhan/ratusan kotak, pengguna keyboard gampang
   "kehilangan jejak" kotak mana yang sedang aktif saat menekan Tab
   berkali-kali. :focus-visible (BUKAN :focus polos, supaya klik mouse
   tetap dapat treatment hover yang sudah ada tanpa outline tambahan yg
   tidak perlu) menambah outline tebal terpisah dari stroke kotak --
   didukung browser modern & aman di-skip browser lama (progressive
   enhancement, tidak ada fallback yg rusak). */
.silsilah-node:focus-visible rect.silsilah-node-box {
  outline: 2.5px solid var(--accent);
  outline-offset: 3px;
}
/* [UX] Status wafat sekarang ditandai lewat strip aksen yang meredup +
   fill kartu lebih hangat -- sebelumnya seluruh keliling kotak jadi
   putus-putus (stroke-dasharray), yang sekilas mirip status "data
   error/tidak lengkap" alih-alih penanda "sudah tiada". */
/* [WARNA PER GENERASI] Tiap generasi punya warna sendiri (--gen-color),
   dipakai sebagai tint lembut di isi + stroke kotak, dan mewarnai label
   G1/G2/.. di tepi kiri. color-mix terhadap var(--paper) membuat tint
   otomatis menyesuaikan mode terang/gelap. Berputar tiap 8 generasi. */
.silsilah-gen-0 { --gen-color: #0F5C4E; }
.silsilah-gen-1 { --gen-color: #2E6B82; }
.silsilah-gen-2 { --gen-color: #7A55B5; }
.silsilah-gen-3 { --gen-color: #C2662D; }
.silsilah-gen-4 { --gen-color: #B0407A; }
.silsilah-gen-5 { --gen-color: #7F8F2A; }
.silsilah-gen-6 { --gen-color: #4A5FC1; }
.silsilah-gen-7 { --gen-color: #A83E3E; }
.silsilah-node[class*="silsilah-gen-"] rect.silsilah-node-box {
  fill: color-mix(in srgb, var(--gen-color) 14%, var(--paper));
  stroke: color-mix(in srgb, var(--gen-color) 45%, var(--rule));
}
[data-theme="dark"] .silsilah-node[class*="silsilah-gen-"] rect.silsilah-node-box {
  fill: color-mix(in srgb, var(--gen-color) 24%, var(--paper));
}
.silsilah-gen-label[class*="silsilah-gen-"] {
  fill: var(--gen-color);
  opacity: 0.85;
}
/* [BEDAKAN ANAK vs MENANTU] Kotak pasangan (masuk lewat pernikahan; lihat
   inLaw di window._famLayoutNode) = garis tepi putus-putus + tint generasi
   lebih tipis + label kecil "Menantu"/"Pasangan" di tepi atas kanan. */
.silsilah-node-inlaw rect.silsilah-node-box { stroke-dasharray: 5 3; }
.silsilah-node-inlaw[class*="silsilah-gen-"] rect.silsilah-node-box {
  fill: color-mix(in srgb, var(--gen-color) 6%, var(--paper));
}
[data-theme="dark"] .silsilah-node-inlaw[class*="silsilah-gen-"] rect.silsilah-node-box {
  fill: color-mix(in srgb, var(--gen-color) 13%, var(--paper));
}
.silsilah-node-tag-bg {
  fill: color-mix(in srgb, var(--info) 14%, var(--paper));
  stroke: color-mix(in srgb, var(--info) 45%, var(--rule));
  stroke-width: 1;
}
.silsilah-node-tag-text {
  fill: var(--info);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .02em;
  pointer-events: none;
}
.silsilah-legend-swatch-inlaw {
  width: 16px;
  height: 11px;
  border-radius: 3px;
  display: inline-block;
  background: var(--paper);
  border: 1.25px dashed var(--ink-faint);
}
.silsilah-node-dead rect.silsilah-node-box {
  fill: var(--paper-warm);
}
.silsilah-node-dead[class*="silsilah-gen-"] rect.silsilah-node-box {
  fill: color-mix(in srgb, var(--gen-color) 7%, var(--paper-warm));
}
[data-theme="dark"] .silsilah-node-dead[class*="silsilah-gen-"] rect.silsilah-node-box {
  fill: color-mix(in srgb, var(--gen-color) 12%, var(--paper-warm));
}
.silsilah-legend-gen {
  width: 11px;
  height: 11px;
  border-radius: 3px;
  display: inline-block;
  background: color-mix(in srgb, var(--gen-color) 30%, var(--paper));
  border: 1.5px solid var(--gen-color);
}
.silsilah-node-dead .silsilah-node-accent-bar {
  opacity: 0.4;
}
.silsilah-node-name {
  fill: var(--ink);
  font-size: 12.5px;
  font-weight: 600;
  font-family: inherit;
}
.silsilah-node-years {
  fill: var(--ink-faint);
  font-size: 11px;
  font-family: inherit;
}
.silsilah-node-address {
  fill: var(--ink-soft, var(--ink-faint));
  font-size: 10.5px;
  font-family: inherit;
}
/* [UX] Avatar rata kiri di dalam kotak: foto anggota (kalau ada, lihat
   .silsilah-avatar-ring) atau siluet kosong netral sebagai fallback --
   SENGAJA tidak diwarnai per-gender (beda dari sebelumnya yang pakai
   inisial berwarna) supaya "belum ada foto" langsung kelihatan sebagai
   state kosong yang konsisten, bukan data lain yang disamarkan. */
.silsilah-avatar-empty {
  fill: var(--rule);
}
.silsilah-avatar-silhouette {
  fill: var(--ink-faint);
  opacity: 0.75;
}
/* [FOTO ANGGOTA] Ring tipis di sekeliling avatar (foto ATAU siluet kosong,
   dipotong bulat lewat clipPath, lihat window.renderFamilyTree) supaya
   badge avatar tetap terlihat konsisten di kedua mode. */
.silsilah-avatar-ring {
  stroke: var(--paper);
  stroke-width: 2;
}
/* [BEDAKAN LAKI-LAKI vs PEREMPUAN] Ring avatar ikut warna gender (hijau
   aksen = laki-laki, emas = perempuan; sama dgn strip kiri & legenda) +
   lencana teks L/P di sudut avatar. Gender kosong tetap netral. */
.silsilah-node-l .silsilah-avatar-ring { stroke: var(--accent); }
.silsilah-node-p .silsilah-avatar-ring { stroke: var(--warning); }
.silsilah-gender-badge { stroke: var(--paper); stroke-width: 1.6; }
.silsilah-node-l .silsilah-gender-badge { fill: var(--accent); }
.silsilah-node-p .silsilah-gender-badge { fill: var(--warning); }
.silsilah-gender-text { fill: var(--paper); font-size: 10px; font-weight: 800; font-family: var(--font-mono); pointer-events: none; user-select: none; }
/* Legenda gender: lencana bulat berisi huruf L/P, sama dgn yang di kartu. */
.silsilah-legend-gender {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.silsilah-legend-gender { color: var(--paper); font-size: 9px; font-weight: 800; font-family: var(--font-mono); line-height: 1; }

/* [FOTO ANGGOTA] Widget upload foto di form tambah/ubah anggota -- lihat
   window._famPreviewPhoto/_famRemovePhoto di js/silsilah.js. Foto
   dikonversi ke WebP + di-resize di browser sebelum upload (bukan
   base64) lewat window.uploadFamilyPhotoToStorage, jadi ukuran final di
   Database Cloud Storage kecil & konsisten. */
.silsilah-photo-field {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  margin-bottom: var(--space-10);
}
.silsilah-photo-preview-wrap {
  position: relative;
  width: 56px;
  height: 56px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--paper-warm);
  border: 1.5px solid var(--rule);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.silsilah-photo-placeholder {
  color: var(--ink-faint);
  opacity: 0.75;
}
.silsilah-photo-preview {
  position: absolute;
  inset: 0;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  object-fit: cover;
  display: none;
}
.silsilah-photo-preview.has-photo { display: block; }
.silsilah-photo-actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}
.silsilah-photo-remove-btn {
  font-size: var(--text-2xs);
  color: var(--danger);
  background: none;
  border: none;
  padding: 0;
  text-align: left;
  cursor: pointer;
  display: none;
}
.silsilah-photo-remove-btn.show { display: inline-block; }
.silsilah-inline-add-btn {
  font-size: var(--text-2xs);
  color: var(--accent, var(--primary, #2563eb));
  background: none;
  border: none;
  padding: 0;
  margin-left: var(--space-6);
  cursor: pointer;
  font-weight: 600;
}
.silsilah-inline-add-btn:hover { text-decoration: underline; }
.silsilah-photo-hint {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
}

/* ==================== RIWAYAT PASANGAN (BANYAK PERNIKAHAN) ====================
   Dipakai di form tambah/edit anggota (index.html, #silsilahMarriagesGroup) --
   satu baris .silsilah-marriage-row per pernikahan (bisa lebih dari satu per
   orang, mis. cerai lalu menikah lagi -- lihat js/silsilah.js
   window._famRenderMarriagesList & sql/38_family_marriages_table.sql). */
.silsilah-marriages-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  margin-bottom: var(--space-8);
}
.silsilah-marriages-empty {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  padding: var(--space-6) 0;
}
.silsilah-marriage-row {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  flex-wrap: wrap;
  padding: var(--space-8);
  border: 1px solid var(--border, #e5e7eb);
  border-radius: var(--radius-sm, 6px);
  background: var(--surface-subtle, rgba(0,0,0,0.02));
}
.silsilah-marriage-name {
  font-weight: 600;
  font-size: var(--text-xs);
  flex: 1 1 120px;
  min-width: 100px;
}
.silsilah-marriage-row select.silsilah-marriage-status {
  flex: 1 1 110px;
  min-width: 100px;
  font-size: var(--text-2xs);
}
.silsilah-marriage-row input.silsilah-marriage-year {
  flex: 0 1 90px;
  min-width: 80px;
  font-size: var(--text-2xs);
}
.silsilah-marriage-remove {
  font-size: var(--text-sm);
  line-height: 1;
  color: var(--danger);
  background: none;
  border: none;
  cursor: pointer;
  padding: var(--space-4);
}
.silsilah-add-marriage-row {
  display: flex;
  gap: var(--space-8);
  flex-wrap: wrap;
}
.silsilah-add-marriage-row select {
  flex: 1;
  min-width: 150px;
}
.silsilah-add-marriage-btn {
  font-size: var(--text-2xs);
  white-space: nowrap;
}

/* ── [REDESIGN] Modal Anggota Silsilah (#silsilahMemberModal) ──
   Sebelumnya form ini cuma tumpukan <div class="form-group"> polos dengan
   style inline (persis tampilan default browser: label kecil di atas kotak
   putih, select bawaan, tombol foto berupa teks link) -- sekarang dipecah
   jadi "kartu identitas" (foto besar + nama) di atas, lalu berapa
   .sk-fam-section (Kelahiran & Wafat / Orang Tua / Riwayat Pasangan /
   Catatan) yang masing-masing punya judul kecil + ikon supaya form terasa
   seperti kartu data keluarga, bukan form generik. Kelas berprefix
   sk-fam-* KHUSUS dipakai di modal ini (semua selector di-scope lewat
   #silsilahMemberModal atau nama kelasnya sendiri) -- tidak menyentuh modal
   lain. Semua id/atribut onclick/onchange bawaan (dibaca js/silsilah.js)
   TIDAK diubah -- redesign ini murni tampilan. */

#silsilahMemberModal .modal-content { padding: var(--space-20) var(--space-24) var(--space-24); }

.sk-fam-form .form-group { margin-bottom: 0; }

/* ── Kartu identitas: foto + nama, disatukan sebagai "header" form ── */
.sk-fam-identity {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-8);
  text-align: center;
  padding-bottom: var(--space-16);
  margin-bottom: var(--space-16);
  border-bottom: 1px solid var(--rule);
}
.sk-fam-photo-frame { position: relative; width: 84px; height: 84px; }
.sk-fam-photo-frame .silsilah-photo-preview-wrap { width: 84px; height: 84px; }
.sk-fam-photo-frame .silsilah-photo-preview { width: 84px; height: 84px; }
.sk-fam-photo-frame .silsilah-photo-placeholder { width: 30px; height: 30px; }
/* [TOGGLE VIEWER] JS men-toggle style.display div ini ('' / 'none') --
   biarkan default-nya block (posisi anak2 diatur absolute, jadi tidak
   butuh flex di parent) supaya tetap kompatibel dgn window.
   openAddFamilyMemberModal/openEditFamilyMemberModal (lihat js/silsilah.js). */
.sk-fam-photo-actions { position: absolute; inset: 0; display: block; pointer-events: none; }
.sk-fam-photo-badge {
  position: absolute; right: -2px; bottom: -2px;
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  border: 2px solid var(--paper);
  cursor: pointer;
  pointer-events: auto;
  transition: background .15s;
}
.sk-fam-photo-badge:hover { background: var(--brand-dark); }
#silsilahMemberModal .silsilah-photo-remove-btn.sk-fam-photo-remove {
  position: absolute; left: -2px; top: -2px;
  width: 22px; height: 22px;
  display: none; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--danger);
  color: #fff;
  border: 2px solid var(--paper);
  cursor: pointer;
  pointer-events: auto;
  padding: 0;
}
#silsilahMemberModal .silsilah-photo-remove-btn.sk-fam-photo-remove.show { display: flex; }
.sk-fam-photo-hint { font-size: var(--text-2xs); color: var(--ink-faint); }
.sk-fam-name-group { width: 100%; max-width: 280px; margin-top: var(--space-2); }

/* ── Kartu seksi (Kelahiran & Wafat / Orang Tua / Pasangan / Catatan) ── */
.sk-fam-section { margin-bottom: var(--space-18); }
.sk-fam-section:last-of-type { margin-bottom: var(--space-14); }
.sk-fam-section-title {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  font-size: var(--text-2xs);
  font-weight: 700;
  color: var(--ink-faint);
  letter-spacing: 0.06em;
  padding-bottom: var(--space-6);
  margin-bottom: var(--space-10);
  border-bottom: 1px solid var(--rule);
}
.sk-fam-section-title svg { color: var(--accent); flex-shrink: 0; }
.sk-fam-row { display: flex; gap: var(--space-10); flex-wrap: wrap; }
.sk-fam-field { flex: 1; min-width: 150px; margin-bottom: var(--space-10); }
.sk-fam-field-sm { flex: 1; min-width: 110px; margin-bottom: var(--space-10); }
.sk-fam-row:last-child .sk-fam-field,
.sk-fam-row:last-child .sk-fam-field-sm { margin-bottom: 0; }

.sk-fam-age-chip {
  font-size: var(--text-2xs);
  color: var(--ink-muted);
  background: var(--paper-warm);
  border-radius: var(--radius-sm);
  padding: var(--space-6) var(--space-10);
  display: inline-block;
}
.sk-fam-age-chip:empty { display: none; padding: 0; }

/* "+ Baru" di sebelah label Ayah/Ibu -- jadi chip kecil, bukan link teks
   polos (spesifisitas 2 kelas otomatis menang atas .silsilah-inline-add-btn
   lama tanpa perlu !important). */
.silsilah-inline-add-btn.sk-fam-add-chip {
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-lt);
  padding: 1px var(--space-8);
  border-radius: var(--radius-pill);
  margin-left: var(--space-6);
}
.silsilah-inline-add-btn.sk-fam-add-chip:hover { background: var(--accent); color: #fff; text-decoration: none; }

/* Riwayat Pasangan & Catatan dibungkus kartu tipis senada Data Management
   Panel (lihat .data-management-panel di atas) supaya konsisten dgn pola
   "kartu" yang sudah ada di app, bukan motif baru. Pakai kelas biasa
   (.sk-fam-section-card), sengaja BUKAN :has() supaya tetap jalan di
   browser lama/WebView yang belum dukung :has(). */
.sk-fam-section-card {
  background: var(--paper-warm);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--space-12) var(--space-14);
}
.sk-fam-section-card .sk-fam-section-title { border-bottom: none; margin-bottom: var(--space-8); padding-bottom: 0; }
.sk-fam-section-notes .sk-fam-field { margin-bottom: 0; }
.sk-fam-section-notes .form-control { background: var(--paper); }

.sk-fam-form-status {
  font-size: var(--text-xs);
  color: var(--danger);
  margin-bottom: var(--space-8);
  min-height: 16px;
}

@media (max-width: 480px) {
  .sk-fam-row { gap: var(--space-8); }
  .sk-fam-field, .sk-fam-field-sm { min-width: 130px; }
}

/* ── Kotak "Cari & pilih pasangan" di baris "+ Tambah Pasangan" ──
   Menumpang class .silsilah-search-bar/.silsilah-search-results yang sama
   dipakai kotak cari pohon utama (lihat js/silsilah.js window.
   _famOnSpouseSearchInput dkk) supaya tampilan & perilakunya konsisten --
   dua override kecil di bawah cuma menyesuaikan konteks (di dalam baris
   flex bareng tombol "+ Tambah Pasangan", bukan toolbar full-width). */
.silsilah-add-marriage-row .sk-fam-combo {
  flex: 1;
  min-width: 180px;
  margin: 0;
}

/* [DETEKSI DATA RUSAK] Peringatan anggota yang tak tergambar di pohon
   (relasi Ayah/Ibu berputar) -- diisi window._famRenderOrphanWarning. */
.silsilah-orphan-warning {
  margin: 0 var(--space-16) var(--space-12);
  padding: var(--space-12) var(--space-14);
  background: var(--paper);
  border: 1.5px solid var(--danger, #b3261e);
  border-radius: var(--radius);
  font-size: var(--text-xs);
  color: var(--ink);
}
.silsilah-orphan-warning[hidden] { display: none; }
.silsilah-orphan-title { font-weight: 700; color: var(--danger, #b3261e); margin-bottom: 4px; }
.silsilah-orphan-text { color: var(--ink-faint); margin-bottom: 8px; line-height: 1.5; }
.silsilah-orphan-list { display: flex; flex-wrap: wrap; gap: 6px; }
.silsilah-orphan-chip {
  border: 1.5px solid var(--rule);
  background: var(--paper-warm);
  color: var(--ink);
  border-radius: 999px;
  padding: 4px 12px;
  font: inherit;
  cursor: pointer;
}
.silsilah-orphan-chip:hover { border-color: var(--danger, #b3261e); }

/* ── Jadwal Selamatan (Silsilah Keluarga): form anggota + daftar almarhum ── */
.silsilah-selamatan-box {
  margin-top: var(--space-10);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper-warm);
  padding: var(--space-8) var(--space-10);
}
.silsilah-selamatan-box[hidden] { display: none; }
.silsilah-selamatan-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-6); }
.silsilah-selamatan-title { font-size: var(--text-2xs); font-weight: 700; color: var(--ink); letter-spacing: .02em; }
.silsilah-selamatan-copy {
  font-size: var(--text-2xs); color: var(--ink-soft, var(--ink)); background: transparent;
  border: 1px solid var(--rule); border-radius: 999px; padding: 2px 10px; cursor: pointer;
}
.silsilah-selamatan-row {
  display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-10);
  padding: 5px 0; border-top: 1px solid var(--rule); font-size: 11.5px; line-height: 1.35;
}
.silsilah-selamatan-row:first-of-type { border-top: 0; }
.silsilah-selamatan-name { display: flex; flex-direction: column; font-weight: 600; color: var(--ink); min-width: 0; }
.silsilah-selamatan-label { font-weight: 400; font-size: 10px; color: var(--ink-faint); }
.silsilah-selamatan-date { display: flex; flex-direction: column; align-items: flex-end; text-align: right; color: var(--ink-soft, var(--ink)); }
.silsilah-selamatan-diff { font-size: 10px; color: var(--ink-faint); }
.silsilah-selamatan-past .silsilah-selamatan-name,
.silsilah-selamatan-past .silsilah-selamatan-date { opacity: .5; }
.silsilah-selamatan-next .silsilah-selamatan-diff,
.silsilah-selamatan-today .silsilah-selamatan-diff { color: var(--warning, #b26a00); font-weight: 600; }
.silsilah-selamatan-note { margin-top: var(--space-6); font-size: 10px; color: var(--ink-faint); line-height: 1.4; }
.silsilah-wafat-selamatan { font-size: 10.5px; color: var(--warning, #b26a00); line-height: 1.3; }
/* Weton/dina pasaran Jawa di bawah field tanggal lahir & wafat (form anggota Silsilah) */
.sk-fam-pasaran-hint {
  margin-top: var(--space-4, 4px);
  font-size: var(--text-2xs);
  font-weight: 600;
  color: var(--ink-muted);
}
.sk-fam-pasaran-hint:empty { display: none; margin: 0; }
.sk-fam-pasaran-note { flex: 1 0 100%; margin-top: calc(-1 * var(--space-4)); margin-bottom: var(--space-10); font-size: var(--text-2xs); color: var(--ink-faint); line-height: 1.4; }
.sk-fam-row:last-child .sk-fam-pasaran-note { margin-bottom: 0; }

/* ==================== BRANKAS KODE (js/vault.js) ====================
   [REDESIGN TOTAL] Layar buat/buka brankas, ringkasan, pencarian, kartu entri,
   dan form entri. Semua warna/radius/spacing memakai token yang sudah ada
   (otomatis ikut mode gelap); tanpa shadow supaya senada tampilan flat app. */
.vault-body { padding: 0 0 var(--space-16); }
.form-group[hidden] { display: none; }

/* Tombol header (ikon + label; label disembunyikan di layar sempit) */
.vault-hdr-btn { display: inline-flex; align-items: center; gap: var(--space-6); flex: 0 0 auto; }
#vaultModal .modal-header #vaultLockBtn { margin-left: auto; }
#vaultModal .modal-header #vaultAddBtn { margin-left: var(--space-8); }
@media (max-width: 520px) { .vault-add-label, .vault-lock-label { display: none; } }

/* ── Gerbang: buat / buka brankas ── */
.vault-gate-wrap { display: flex; justify-content: center; padding: var(--space-24) 0 var(--space-16); }
.vault-gate {
  width: 100%; max-width: 420px;
  display: flex; flex-direction: column; gap: var(--space-14);
  padding: var(--space-28) var(--space-24);
  border: 1.5px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--paper-warm);
  text-align: center;
}
.vault-gate-icon {
  width: 64px; height: 64px; margin: 0 auto;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--accent-lt); color: var(--accent);
  border: 1.5px solid color-mix(in srgb, var(--accent) 28%, transparent);
}
.vault-gate h4 { margin: 0 0 var(--space-4); font-size: var(--text-xl); color: var(--ink); }
.vault-gate-note { margin: 0; font-size: var(--text-sm); color: var(--ink-muted); line-height: 1.55; }
.vault-gate-field { text-align: left; margin: 0; }
.vault-gate-field label { display: block; margin-bottom: var(--space-4); }
.vault-gate-btn { width: 100%; padding: var(--space-10) var(--space-16); font-weight: 600; }
.vault-gate-foot {
  margin: 0; display: flex; align-items: center; justify-content: center; gap: var(--space-6);
  font-size: var(--text-xs); color: var(--ink-faint); line-height: 1.4;
}
.vault-loading {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-10);
  padding: var(--space-36) 0; color: var(--ink-faint); font-size: var(--text-sm);
}
.vault-pwfield { position: relative; }
.vault-pwfield .form-control { padding-right: 42px; }
.vault-eye {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--ink-faint); cursor: pointer;
  border-radius: var(--radius-sm);
}
.vault-eye:hover { color: var(--ink); background: var(--rule); }
.vault-caps { margin-top: var(--space-4); font-size: var(--text-xs); color: var(--warning); font-weight: 600; }

/* Pesan inline (menggantikan toast di layar gerbang) */
.vault-gate-msg {
  display: flex; align-items: center; justify-content: center; gap: var(--space-6);
  padding: var(--space-8) var(--space-10);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm); line-height: 1.45; text-align: left;
}
.vault-gate-msg[hidden] { display: none; }
.vault-gate-msg-error { background: var(--danger-lt); color: var(--danger); border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent); }
.vault-gate-msg-warn  { background: var(--warning-lt); color: var(--ink); border: 1px solid color-mix(in srgb, var(--warning) 45%, transparent); }
@keyframes vaultShake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-7px); } 40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); } 80% { transform: translateX(3px); }
}
.vault-shake { animation: vaultShake .38s ease; }
@media (prefers-reduced-motion: reduce) { .vault-shake { animation: none; } }

/* Meter kekuatan (4 segmen) + checklist aturan */
.vault-meter-row { display: flex; align-items: center; gap: var(--space-8); margin-top: var(--space-6); }
.vault-meter { flex: 1; display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4); }
.vault-meter span { height: 4px; border-radius: var(--radius-pill); background: var(--rule); transition: background .15s; }
.vault-meter[data-level="1"] span:nth-child(-n+1) { background: var(--danger); }
.vault-meter[data-level="2"] span:nth-child(-n+2) { background: var(--danger); }
.vault-meter[data-level="3"] span:nth-child(-n+3) { background: var(--warning); }
.vault-meter[data-level="4"] span:nth-child(-n+4) { background: var(--success); }
.vault-meter-lbl { min-width: 76px; text-align: right; font-size: var(--text-xs); color: var(--ink-muted); }
.vault-rules { list-style: none; margin: var(--space-6) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.vault-rules li { display: flex; align-items: center; gap: var(--space-6); font-size: var(--text-xs); color: var(--ink-faint); }
.vault-rules li[hidden] { display: none; }
.vault-rules li.ok { color: var(--success); }
.vault-rules li .sk-icon { opacity: .35; }
.vault-rules li.ok .sk-icon { opacity: 1; }

.vault-warning {
  display: flex; align-items: flex-start; gap: var(--space-8);
  padding: var(--space-10) var(--space-12);
  border-radius: var(--radius);
  border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent);
  background: var(--danger-lt);
  color: var(--ink);
  font-size: var(--text-xs); line-height: 1.5; text-align: left;
}
.vault-warning .sk-icon { color: var(--danger); margin-top: 1px; }
.vault-ack { display: flex; align-items: flex-start; gap: var(--space-8); text-align: left; font-size: var(--text-xs); color: var(--ink-muted); line-height: 1.45; cursor: pointer; }
.vault-ack input { margin-top: 2px; accent-color: var(--accent); }

/* ── Daftar: ringkasan, pencarian, filter ── */
.vault-summary { display: flex; align-items: center; justify-content: space-between; gap: var(--space-10); margin-bottom: var(--space-12); flex-wrap: wrap; }
.vault-summary-count { display: flex; align-items: baseline; gap: var(--space-6); }
.vault-summary-num { font-size: var(--text-3xl); font-weight: 700; color: var(--ink); line-height: 1; }
.vault-summary-lbl { font-size: var(--text-sm); color: var(--ink-muted); }
.vault-autolock {
  display: inline-flex; align-items: center; gap: var(--space-6);
  padding: var(--space-4) var(--space-10);
  border: 1px solid var(--rule); border-radius: var(--radius-pill);
  font-size: var(--text-xs); color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.vault-autolock strong { color: var(--ink); font-weight: 600; }
.vault-autolock.is-soon { border-color: var(--warning); background: var(--warning-lt); color: var(--ink); }
.vault-toolbar { display: flex; flex-direction: column; gap: var(--space-10); margin-bottom: var(--space-14); }
.vault-search-wrap { position: relative; }
.vault-search-wrap > .sk-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--ink-faint); pointer-events: none; }
.vault-search-wrap .vault-search { padding-left: 36px; }
.vault-cats { display: flex; flex-wrap: wrap; gap: var(--space-6); }
.vault-cats[hidden] { display: none; }
.vault-cat {
  display: inline-flex; align-items: center; gap: var(--space-6);
  padding: var(--space-5) var(--space-12);
  border-radius: var(--radius-pill);
  border: 1px solid var(--rule);
  background: transparent; color: var(--ink-muted);
  font-size: var(--text-xs); cursor: pointer; white-space: nowrap;
}
.vault-cat:hover { border-color: var(--accent); color: var(--ink); }
.vault-cat.active { border-color: var(--accent); background: var(--accent-lt); color: var(--accent); font-weight: 600; }
.vault-cat-n { font-size: var(--text-2xs); opacity: .75; font-variant-numeric: tabular-nums; }
@media (max-width: 520px) {
  .vault-cats { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin: 0 calc(-1 * var(--space-4)); padding: 0 var(--space-4) var(--space-2); }
  .vault-cats::-webkit-scrollbar { display: none; }
}

/* ── Kartu entri ── */
.vault-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); gap: var(--space-12); align-items: start; }
.vault-card {
  display: flex; flex-direction: column; gap: var(--space-10);
  padding: var(--space-12);
  border-radius: var(--radius-lg);
  border: 1.5px solid var(--rule);
  background: var(--paper-warm);
  min-width: 0;
  transition: border-color .15s;
}
.vault-card:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--rule)); }
.vault-card-top { display: flex; align-items: center; gap: var(--space-10); }
.vault-card-ico {
  flex: 0 0 38px; width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius); background: var(--accent-lt); color: var(--accent);
}
/* Warna per kategori: satu variabel --vc menggerakkan border,
   latar tipis, ikon, dan badge. Sengaja hue berbeda-beda (bukan token tema
   yang semuanya hijau) supaya kategori langsung terbedakan sekilas. */
.vault-card { --vc: #D9730D; --vc-mix: 7%;
  border-color: color-mix(in srgb, var(--vc) 38%, var(--rule));
  background: color-mix(in srgb, var(--vc) var(--vc-mix), var(--paper-warm));
}
.vault-card:hover { border-color: var(--vc); }
.vault-card[data-cat="pin"]      { --vc: #D9730D; } /* oranye */
.vault-card[data-cat="password"] { --vc: #2F6FDE; } /* biru */
.vault-card[data-cat="akun"]     { --vc: #7C4DDB; } /* ungu */
.vault-card[data-cat="bank"]     { --vc: #1E9A5A; } /* hijau */
.vault-card[data-cat="kunci"]    { --vc: #D0454C; } /* merah */
.vault-card[data-cat="lainnya"]  { --vc: #64748B; } /* abu-abu */
[data-theme="dark"] .vault-card { --vc-mix: 9%; }
[data-theme="dark"] .vault-card[data-cat="pin"]      { --vc: #F0A25C; }
[data-theme="dark"] .vault-card[data-cat="password"] { --vc: #B5B5B5; }
[data-theme="dark"] .vault-card[data-cat="akun"]     { --vc: #B394F2; }
[data-theme="dark"] .vault-card[data-cat="bank"]     { --vc: #4FC488; }
[data-theme="dark"] .vault-card[data-cat="kunci"]    { --vc: #F08A8F; }
[data-theme="dark"] .vault-card[data-cat="lainnya"]  { --vc: #9AA7B8; }
.vault-card .vault-card-ico { background: color-mix(in srgb, var(--vc) 18%, transparent); color: var(--vc); }
.vault-card .vault-badge {
  color: var(--vc); font-weight: 700;
  border-color: color-mix(in srgb, var(--vc) 45%, transparent);
  background: color-mix(in srgb, var(--vc) 12%, transparent);
}
.vault-card-heading { flex: 1; min-width: 0; }
.vault-card-title { font-weight: 600; font-size: var(--text-md); color: var(--ink); overflow-wrap: anywhere; line-height: 1.3; }
.vault-badge {
  font-size: var(--text-2xs); color: var(--ink-muted); font-weight: 600;
  border: 1px solid var(--rule); border-radius: var(--radius-pill);
  padding: 2px var(--space-8); white-space: nowrap; align-self: flex-start;
}
.vault-fields { display: flex; flex-direction: column; gap: var(--space-6); }
.vault-field {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-8);
  padding: var(--space-6) var(--space-6) var(--space-6) var(--space-10);
  border-radius: var(--radius); border: 1px solid var(--rule); background: var(--paper);
  min-height: 42px;
}
.vault-field-main { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.vault-field-label { font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: .05em; color: var(--ink-faint); font-weight: 600; }
.vault-field-val { font-size: var(--text-sm); color: var(--ink); overflow-wrap: anywhere; line-height: 1.35; }
.vault-secret { font-family: var(--font-mono); letter-spacing: .04em; }
.vault-secret.is-shown { color: var(--accent); }
.vault-url { color: var(--ink-muted); }
.vault-backup-val { white-space: pre-wrap; }
.vault-field-actions { display: inline-flex; gap: var(--space-4); flex: 0 0 auto; }
/* Kartu rekap (netral: tanpa strip/aksen tepi) */
.vault-recap { display: flex; flex-direction: column; gap: var(--space-10); padding: var(--space-12); margin-bottom: var(--space-14); border: 1.5px solid var(--rule); border-radius: var(--radius-lg); background: var(--paper-warm); }
.vault-recap-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8); flex-wrap: wrap; }
.vault-recap-head h4 { margin: 0; font-size: var(--text-md); color: var(--ink); }
.vault-recap-state { display: inline-flex; align-items: center; gap: var(--space-4); font-size: var(--text-2xs); font-weight: 600; padding: 2px var(--space-8); border-radius: var(--radius-pill); border: 1px solid var(--rule); color: var(--ink-muted); }
.vault-recap-state.is-ok { color: var(--success); background: var(--success-lt); border-color: transparent; }
.vault-recap-state.is-warn { color: var(--warning); background: var(--warning-lt); border-color: transparent; }
.vault-recap-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-8); }
.vault-recap-tile { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: var(--space-8) var(--space-10); border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper); color: var(--ink-muted); text-align: left; cursor: pointer; font: inherit; min-width: 0; }
.vault-recap-tile:disabled { cursor: default; opacity: .7; }
.vault-recap-tile.has-issue .vault-recap-num { color: var(--warning); }
.vault-recap-tile.has-issue:hover, .vault-recap-tile.active { border-color: var(--accent); background: var(--accent-lt); }
.vault-recap-num { font-size: var(--text-2xl); font-weight: 700; line-height: 1; color: var(--ink); font-variant-numeric: tabular-nums; }
.vault-recap-lbl { font-size: var(--text-2xs); line-height: 1.25; overflow-wrap: anywhere; }
.vault-recap-cats { display: flex; flex-wrap: wrap; gap: var(--space-6); }
.vault-recap-cat { display: inline-flex; align-items: center; gap: var(--space-4); font-size: var(--text-xs); color: var(--ink-muted); padding: 2px var(--space-8); border: 1px solid var(--rule); border-radius: var(--radius-pill); }
.vault-recap-cat strong { color: var(--ink); }
.vault-recap-foot { display: flex; align-items: center; gap: var(--space-4); font-size: var(--text-2xs); color: var(--ink-faint); }
@media (max-width: 380px) { .vault-recap-tiles { grid-template-columns: 1fr; } }
.vault-access { display: flex; flex-direction: column; gap: var(--space-6); margin-bottom: var(--space-10); }
.vault-access-line { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-6); font-size: var(--text-xs); color: var(--ink-muted); }
.vault-access-line strong { color: var(--ink); font-weight: 600; }
.vault-access-line .vault-link-btn { margin-left: auto; }
.vault-access-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1px; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--rule); overflow: hidden; }
.vault-access-list li { display: flex; justify-content: space-between; gap: var(--space-8); flex-wrap: wrap; padding: var(--space-6) var(--space-10); background: var(--paper); font-size: var(--text-xs); color: var(--ink-muted); }
.vault-access-list li em { color: var(--accent); font-style: normal; }
.vault-hist { display: flex; flex-direction: column; gap: var(--space-6); }
.vault-hist > .vault-link-btn { align-self: flex-start; }
.vault-hist-list { display: flex; flex-direction: column; gap: var(--space-6); }
.vault-hist-list > .vault-link-btn { align-self: flex-end; }
.vault-notes { font-size: var(--text-xs); color: var(--ink-muted); white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.5; padding: 0 var(--space-2); }
.vault-card-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-8); padding-top: var(--space-8); border-top: 1px solid var(--rule); margin-top: auto; }
.vault-card-date { font-size: var(--text-2xs); color: var(--ink-faint); }
.vault-card-actions { display: inline-flex; gap: var(--space-4); }

/* Tombol ikon 32px (area sentuh nyaman) */
.vault-ib {
  width: 32px; height: 32px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  border: 1px solid var(--rule); background: transparent;
  color: var(--ink-muted); cursor: pointer;
}
.vault-ib:hover { border-color: var(--accent); color: var(--accent); }
.vault-ib.vault-ib-ok { border-color: var(--success); color: var(--success); background: var(--success-lt); }
.vault-ib-lg { width: 40px; height: auto; align-self: stretch; }
.vault-link-btn {
  display: inline-flex; align-items: center; gap: var(--space-4);
  padding: var(--space-4) var(--space-8); border: none; background: transparent;
  border-radius: var(--radius-sm); font-size: var(--text-xs); color: var(--ink-muted); cursor: pointer;
}
.vault-link-btn:hover { background: var(--rule); color: var(--ink); }
.vault-link-btn.is-danger:hover { background: var(--danger-lt); color: var(--danger); }

/* Keadaan kosong */
.vault-empty-state { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-8); padding: var(--space-40) var(--space-16); }
.vault-empty-state.is-compact { padding: var(--space-28) var(--space-16); }
.vault-empty-ico {
  width: 64px; height: 64px; display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--accent-lt); color: var(--accent); margin-bottom: var(--space-4);
}
.vault-empty-state h4 { margin: 0; font-size: var(--text-lg); color: var(--ink); }
.vault-empty-state p { margin: 0 0 var(--space-8); max-width: 340px; font-size: var(--text-sm); color: var(--ink-muted); line-height: 1.55; }
.vault-empty-state .btn { display: inline-flex; align-items: center; gap: var(--space-6); }

/* ── Form entri ── */
.vault-opt { font-weight: 400; color: var(--ink-faint); font-size: var(--text-xs); margin-left: var(--space-4); }
.vault-catpick { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
.vault-catpick-btn {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-4);
  padding: var(--space-8) var(--space-4);
  border-radius: var(--radius); border: 1.5px solid var(--rule);
  background: transparent; color: var(--ink-muted);
  font-size: var(--text-xs); cursor: pointer; text-align: center; line-height: 1.2;
}
.vault-catpick-btn:hover { border-color: var(--accent); color: var(--ink); }
.vault-catpick-btn.active { border-color: var(--accent); background: var(--accent-lt); color: var(--accent); font-weight: 600; }
.vault-form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--space-10); }
.vault-form-row > .form-group { min-width: 0; }
.vault-form-row:has(> .form-group[hidden]) > .form-group:not([hidden]) { grid-column: 1 / -1; }
@media (max-width: 520px) { .vault-form-row { grid-template-columns: 1fr; } }
.vault-secret-input { display: flex; gap: var(--space-6); align-items: stretch; }
.vault-secret-input .form-control { flex: 1; min-width: 0; }
.vault-masked { -webkit-text-security: disc; text-security: disc; }
.vault-form-actions { display: flex; gap: var(--space-8); justify-content: flex-end; margin-top: var(--space-16); padding-top: var(--space-14); border-top: 1.5px solid var(--rule); }
.vault-form-actions .btn { min-width: 96px; }


/* ── Harga Komoditas: tampilan DESKTOP/TABLET kompak & hemat ruang ──
   Sebelumnya: kotak ringkasan 3-4 baris tinggi + tabel 6 kolom selebar
   layar dengan 1 komoditas per baris (banyak ruang kosong). Sekarang:
   ringkasan jadi 1-2 baris (tanggal, chip, top mover berjejer), dan daftar
   komoditas jadi baris ringkas yang mengalir ke 2-3 kolom (urutan tetap
   harga tertinggi -> terendah, dibaca dari atas ke bawah per kolom).
   Hp (<=640px) tidak berubah: tetap kartu (.hk-card-list). ── */
.hk-compact-list { display: none; }
@media (min-width: 641px) {
  .hk-compact-list {
    display: block;
    column-width: 360px;
    column-gap: var(--space-24);
    margin-bottom: var(--space-12);
  }
  .hk-row {
    break-inside: avoid;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 96px 66px 60px;
    align-items: center;
    column-gap: var(--space-8);
    padding: var(--space-5) var(--space-6);
    border-bottom: 1px solid var(--rule);
    min-height: 38px;
  }
  .hk-row:hover { background: var(--paper-warm); }
  .hk-row-name { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
  .hk-row-title {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .hk-row-unit { font-size: var(--text-2xs); color: var(--ink-faint); white-space: nowrap; }
  .hk-row-price {
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: var(--text-sm);
    color: var(--ink);
    text-align: right;
    white-space: nowrap;
  }
  .hk-row-change { font-size: var(--text-xs); font-weight: 600; text-align: right; white-space: nowrap; }
  .hk-row .hk-card-spark-btn, .hk-row .hk-card-spark-empty { margin-left: 0; justify-self: end; }

  /* Kotak ringkasan: tanggal, chip, dan top mover sebaris (wrap kalau sempit) */
  .hk-summary-box {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    column-gap: var(--space-16);
    row-gap: var(--space-6);
    padding: var(--space-8) var(--space-12);
    margin-bottom: var(--space-12);
  }
  .hk-summary-date { margin: 0; flex: 0 0 auto; }
  .hk-summary-stats { flex: 0 0 auto; flex-wrap: nowrap; gap: var(--space-6); margin: 0; }
  .hk-stat-chip {
    flex: 0 0 auto;
    flex-direction: row;
    align-items: baseline;
    gap: var(--space-5);
    padding: var(--space-3) var(--space-10);
  }
  .hk-stat-chip-num { font-size: var(--text-lg); }
  .hk-summary-movers { flex: 1 1 320px; flex-wrap: nowrap; gap: var(--space-8); margin: 0; }
  .hk-mover-card { flex: 1 1 0; min-width: 0; padding: var(--space-4) var(--space-10); align-items: center; }
  .hk-mover-card svg { margin-top: 0; }
  .hk-mover-body { flex-direction: row; flex-wrap: wrap; align-items: baseline; column-gap: var(--space-8); row-gap: 0; }
  .hk-mover-label { flex: 0 0 100%; }
  .hk-summary-highlight-list { flex: 1 1 320px; }
  .hk-summary-note, .hk-summary-reminder, .hk-summary-empty { flex: 0 0 100%; margin-top: 0; }
  .hk-label-row { margin-bottom: var(--space-8); }
}
@media (min-width: 1024px) {
  body.view-fullpage #hargaKomoditasModal.show .modal-content { padding: var(--space-16) var(--space-20); }
  .hk-compact-list { column-width: 400px; }
}


/* ── Harga Komoditas: info "Update terakhir" dipindah ke header modal
   (sebelumnya badge .hk-section-label di atas daftar, bersama label
   "Harga Pangan (otomatis dari BI)" yang sudah dihapus). Teks kecil polos,
   didorong ke kanan judul; di hp urutannya hamburger -> judul -> info. ── */
.hk-header-info {
  margin-left: auto;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--ink-faint);
  white-space: nowrap;
}
.hk-header-info:empty { display: none; }


/* ── Silsilah Keluarga: UI lebih kompak & hemat ruang (30 Sep 2026) ──
   Tujuan: pohon dapat ruang setinggi/selebar mungkin. Perubahan:
   (1) kartu rekap & rekap generasi rata dengan kanvas (sebelumnya menjorok
   16px kiri-kanan sementara kanvas penuh) dan jarak antarbloknya dirapatkan;
   (2) kartu rekap utama di layar >=761px jadi 1 baris tipis (angka + label
   sebaris, bukan ditumpuk) -- hp tidak diubah, tetap grid 3 kolom;
   (3) legenda lebih rapat & kecil; (4) header/padding modal di desktop
   dikurangi. Keputusan tata letak sebelumnya (cari di header, rekap
   generasi 1 baris, legenda di bawah pohon rata tengah, bar Ekspor/Impor/
   Hapus di luar kartu) TIDAK berubah. ── */
@media (min-width: 761px) {
  .silsilah-recap-card {
    margin: 0 0 var(--space-8);
    padding: var(--space-6) var(--space-10);
    gap: var(--space-6);
  }
  .silsilah-recap-item {
    flex-direction: row;
    justify-content: center;
    align-items: baseline;
    flex-wrap: wrap;
    column-gap: var(--space-6);
    row-gap: 0;
    padding: var(--space-2) var(--space-4);
  }
  .silsilah-recap-value { font-size: var(--text-base); }
  .silsilah-recap-label { font-size: 10.5px; }
  .silsilah-recap-more { display: none; } /* petunjuk "Lihat daftar" tetap ada di tooltip tombol */
  .silsilah-genrecap-card {
    margin: 0 0 var(--space-8);
    padding: var(--space-4) var(--space-10);
  }
  .silsilah-legend {
    gap: var(--space-4) var(--space-10);
    padding: var(--space-6) 0 0;
    font-size: 10.5px;
  }
}
@media (min-width: 1024px) {
  #silsilahModal.show .modal-content { padding: var(--space-16) var(--space-20); }
  #silsilahModal .modal-header { margin-bottom: var(--space-10); padding-bottom: var(--space-10); }
  #silsilahModal.show .modal-content {
    min-height: calc(100vh - var(--space-28) - var(--space-40) - var(--space-32));
    min-height: calc(100dvh - var(--space-28) - var(--space-40) - var(--space-32));
  }
  #silsilahModal > .silsilah-data-bar { margin: var(--space-4) 0 0; }
}


/* ── Silsilah Keluarga: pohon lebih interaktif (30 Sep 2026) ──
   Pilih kotak -> kerabat langsung (leluhur, keturunan, pasangan) disorot,
   sisanya diredupkan (lihat window._famPaintLineage, js/silsilah.js).
   Redup dipasang di ANAK kotak (bukan opacity di <g>) karena .silsilah-node
   punya animasi masuk beropacity (fill forwards) yang akan menimpanya, dan
   pada garis lewat stroke-opacity karena garis silang juga beranimasi
   opacity. Mode Fokus menyembunyikan rekap/legenda/bar data. ── */
.silsilah-tree-svg.silsilah-dim .silsilah-node > * { transition: opacity .18s ease; }
.silsilah-tree-svg.silsilah-dim .silsilah-node:not(.silsilah-rel) > * { opacity: .25; }
.silsilah-tree-svg.silsilah-dim .silsilah-line:not(.silsilah-line-rel) { stroke-opacity: .14; }
.silsilah-tree-svg.silsilah-dim .silsilah-cross-dot,
.silsilah-tree-svg.silsilah-dim .silsilah-spouse-mark,
.silsilah-tree-svg.silsilah-dim .silsilah-spouse-mark-wafat { opacity: .25; }
.silsilah-line.silsilah-line-rel {
  stroke: var(--accent);
  stroke-opacity: 1;
  stroke-width: 2.8px !important;
}
.silsilah-node-selected rect.silsilah-node-box {
  stroke: var(--accent);
  stroke-width: 3px;
}

.silsilah-zoom-pct {
  text-align: center;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  user-select: none;
}
.silsilah-zoom-btn[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-lt);
}

/* Bar info anggota terpilih: melayang di dasar kanvas, di kiri tombol zoom. */
.silsilah-selbar {
  position: absolute;
  left: var(--space-12);
  bottom: var(--space-12);
  right: 60px;
  max-width: 460px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--space-8);
  padding: var(--space-8) var(--space-8) var(--space-8) var(--space-12);
  background: var(--paper);
  border: 1.5px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm, 0 2px 8px rgba(0,0,0,.14));
}
.silsilah-selbar[hidden] { display: none; }
.silsilah-selbar-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.silsilah-selbar-name {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.silsilah-selbar-meta {
  font-size: 10.5px;
  color: var(--ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.silsilah-selbar-edit {
  flex: 0 0 auto;
  appearance: none;
  font: inherit;
  font-size: var(--text-xs);
  font-weight: 700;
  padding: var(--space-5) var(--space-12);
  border: none;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: #fff;
  cursor: pointer;
}
.silsilah-selbar-close {
  flex: 0 0 auto;
  appearance: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: none;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--ink-faint);
  cursor: pointer;
}
.silsilah-selbar-close:hover { background: var(--paper-warm); color: var(--ink); }

/* Mode Fokus */
#silsilahModal.silsilah-focus .silsilah-recap-card,
#silsilahModal.silsilah-focus .silsilah-genrecap-card,
#silsilahModal.silsilah-focus .silsilah-legend,
#silsilahModal.silsilah-focus .silsilah-orphan-warning,
#silsilahModal.silsilah-focus > .silsilah-data-bar { display: none !important; }
@media (min-width: 1024px) {
  #silsilahModal.silsilah-focus.show .modal-content {
    min-height: calc(100vh - var(--space-28) - var(--space-40) - var(--space-8));
    min-height: calc(100dvh - var(--space-28) - var(--space-40) - var(--space-8));
  }
}

/* Tombol ikon silsilah: aturan global `button { padding: 6px 14px }` ikut
   menekan ikon SVG di dalam kotak 26-34px sampai nyaris 0-4px (tampil
   seperti titik). Padding dinolkan & ikon dilarang menyusut. */
.silsilah-zoom-btn, .silsilah-selbar-close { padding: 0; }
.silsilah-zoom-btn svg, .silsilah-selbar-close svg { flex: 0 0 auto; }


/* ── Harga Komoditas: kanvas pas setinggi layar, tanpa ruang kosong di bawah ──
   Sebelumnya daftar pakai CSS columns dengan tinggi baris tetap, jadi kartu
   cuma setinggi isinya dan menyisakan area kosong di bawahnya. Sekarang:
   (1) modal-content jadi flex-column setinggi sisa layar (desktop >=1024px:
       min-height 100vh dikurangi padding atas+bawah halaman; tablet sudah
       height:100% dari aturan fullview bawaan);
   (2) #hkAutoSection & daftar flex:1 mengisi sisa tinggi;
   (3) daftar jadi grid (kolom & jumlah baris dihitung js/harga-pangan.js ->
       window.fitHargaKomoditasGrid lewat --hk-cols/--hk-rows), baris
       minmax(38px, 1fr) sehingga membesar merata mengisi tinggi tersedia dan
       tetap bisa di-scroll kalau layar terlalu pendek.
   Hp (<=640px) tidak berubah (tetap kartu .hk-card-list). ── */
@media (min-width: 641px) {
  body.view-fullpage #hargaKomoditasModal.show .modal-content {
    display: flex;
    flex-direction: column;
  }
  body.view-fullpage #hargaKomoditasModal.show .modal-content > .modal-header,
  body.view-fullpage #hargaKomoditasModal.show .modal-content > .hk-summary-box,
  body.view-fullpage #hargaKomoditasModal.show .modal-content > .slist-actions {
    flex: 0 0 auto;
  }
  body.view-fullpage #hargaKomoditasModal.show #hkAutoSection {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
  }
  body.view-fullpage #hargaKomoditasModal.show #hkAutoCompactList {
    flex: 1 1 auto;
    display: grid;
    grid-template-columns: repeat(var(--hk-cols, 3), minmax(0, 1fr));
    grid-template-rows: repeat(var(--hk-rows, 12), minmax(38px, var(--hk-row-max, 1fr)));
    grid-auto-flow: column;
    column-gap: var(--space-24);
    align-content: start;
    margin-bottom: var(--space-12);
  }
}
@media (min-width: 1024px) {
  /* Padding bawah halaman dirapatkan (40px -> 16px, sama dgn sisi kiri/kanan)
     supaya kartu benar-benar mentok ke bawah layar. */
  body.view-fullpage #hargaKomoditasModal.show {
    padding-bottom: var(--space-16);
  }
  body.view-fullpage #hargaKomoditasModal.show .modal-content {
    min-height: calc(100vh - var(--space-28) - var(--space-16));
    min-height: calc(100dvh - var(--space-28) - var(--space-16));
  }
}


/* ── Sidebar desktop: jarak antar menu dirapatkan, seirama dengan tabel Neraca ──
   Sebelumnya tiap menu ~51px (padding 11px + border + line-height 1.6 + gap
   5px) sementara baris tabel Neraca ~44px, jadi sidebar terasa lebih renggang
   dari konten di sebelahnya. Sekarang tinggi menu 40px + gap 4px = ~44px,
   sama dengan pitch baris .tx-table. Hanya desktop dgn mouse (pointer: fine)
   -- drawer hp/tablet dan iPad landscape (sentuh) tetap longgar utk jari.
   Padding horizontal, label grup, & mode ciut (icon-only) tidak berubah. ── */
@media (min-width: 1024px) and (pointer: fine) {
  /* [LEBIH LONGGAR 7 Okt 2026] padding menu 8px -> 10px (tinggi menu 44px,
     pitch ~48px dgn gap 4px) mengikuti tabel Neraca yang ikut dilonggarkan
     (baris ~50px). Kalau menu tidak muat di layar pendek, sidebar sudah
     overflow-y:auto sehingga bisa di-scroll. */
  .app-nav-item { padding-top: var(--space-10); padding-bottom: var(--space-10); }
  .app-nav-group,
  .app-nav-footer { gap: var(--space-4); }
}


/* ── Anggaran Bulanan / Anggaran Dasar (#defaultBudgetModal): seimbangkan
   dgn menu lain di desktop ──
   Sebelumnya: padding kartu 24px (jarak konten ke sidebar ~42px vs ~16px di
   Dashboard & ~16-20px di Harga Komoditas), grid kaku 2 kolom sehingga 21
   kategori memanjang ~11 baris dan harus di-scroll jauh, kartu ringkasan &
   item agak tinggi. Sekarang (>=1024px):
   (1) padding kartu disamakan dgn Harga Komoditas (16px 20px);
   (2) grid auto-fill (min 420px) -> 3 kolom di layar lebar / 2 kolom di
       laptop, jadi 21 kategori cukup ~7 baris dan muat tanpa scroll;
   (3) kartu ringkasan, kotak info, pencarian, dan item kategori dipadatkan.
   Hp/tablet (<1024px) tidak berubah. ── */
@media (min-width: 1024px) {
  body.view-fullpage #defaultBudgetModal.show .modal-content {
    padding: var(--space-16) var(--space-20);
  }
  body.view-fullpage #defaultBudgetModal.show .modal-content > div[style*="info-lt"] {
    padding: var(--space-8) var(--space-12) !important;
    margin-bottom: var(--space-10) !important;
  }
  #defaultBudgetModal .dbudget-summary-card {
    padding: var(--space-10) var(--space-16);
    margin-bottom: var(--space-10);
  }
  #defaultBudgetModal .dbudget-summary-label { margin-bottom: var(--space-2); }
  #defaultBudgetModal .dbudget-summary-value { font-size: var(--text-2xl); line-height: 1.2; }
  #defaultBudgetModal .dbudget-search-wrap { margin-bottom: var(--space-10); }
  #defaultBudgetModal .dbudget-search-wrap input.form-control { padding-top: var(--space-7); padding-bottom: var(--space-7); }
  #defaultBudgetModal .dbudget-grid {
    grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
    gap: var(--space-8);
  }
  #defaultBudgetModal .dbudget-item { padding: var(--space-6) var(--space-10); gap: var(--space-8); }
  #defaultBudgetModal .dbudget-badge { flex-basis: 28px; width: 28px; height: 28px; }
  #defaultBudgetModal .dbudget-name { margin-bottom: var(--space-2); }
  #defaultBudgetModal .dbudget-input-row .form-control { padding-top: var(--space-4); padding-bottom: var(--space-4); }
}


/* ── Menu Mingguan / Daftar Menu (#menuPlanModal): seimbangkan dgn menu lain di desktop ──
   Sebelumnya: padding kartu 24px (konten ~42px dari sidebar vs ~16-20px di
   menu lain), kartu Estimasi Gizi ~345px tinggi karena teks kosong
   (.slist-empty) punya padding 26px atas-bawah + evaluasi menumpuk di bawah
   kalori, kartu Estimasi Belanja juga lega berlebihan saat kosong, dan 7
   kartu hari dipaksa 4 kolom (2 baris) walau layar lebar. Sekarang (>=1024px):
   (1) padding kartu disamakan dgn Harga Komoditas (16px 20px);
   (2) teks kosong & jarak dalam kartu gizi/belanja dipadatkan;
   (3) >=1280px: kartu gizi 2 kolom (kalori+makro di kiri, evaluasi di kanan);
   (4) >=1880px: 7 hari dalam 1 baris. Hp/tablet (<1024px) tidak berubah. ── */
@media (min-width: 1024px) {
  body.view-fullpage #menuPlanModal.show .modal-content {
    padding: var(--space-16) var(--space-20);
  }
  #menuPlanModal .mplan-gizi-card.mplan-gizi-top {
    padding: var(--space-10) var(--space-14);
    margin-bottom: var(--space-10);
  }
  #menuPlanModal .mplan-gizi-kalori { font-size: var(--text-2xl); }
  #menuPlanModal .mplan-gizi-card.mplan-gizi-top .slist-empty {
    margin: var(--space-4) 0 0;
    padding: var(--space-4) 0;
    text-align: left;
  }
  #menuPlanModal .mplan-gizi-evaluasi-wrap {
    margin-top: var(--space-8);
    padding-top: var(--space-8);
  }
  #menuPlanModal .mplan-gizi-evaluasi-title { margin-bottom: var(--space-4); }
  #menuPlanModal .mplan-gizi-evaluasi { gap: var(--space-3); }
  #menuPlanModal .mplan-gizi-insight { padding: var(--space-4) var(--space-9); }
  #menuPlanModal .mplan-gizi-details { margin-top: var(--space-8); padding-top: var(--space-8); }
  #menuPlanModal .mplan-week-tab { padding: var(--space-6) var(--space-10); }
  #menuPlanModal .mplan-week-tabs-row { margin-bottom: var(--space-10); gap: var(--space-2); }
  #menuPlanModal .mplan-days { margin-bottom: var(--space-10); }
  #menuPlanModal .mplan-estimate-card { padding: var(--space-10) var(--space-14); }
  #menuPlanModal .mplan-estimate-header { margin-bottom: var(--space-4); }
  #menuPlanModal .mplan-estimate-card .slist-empty {
    padding: var(--space-8) 0;
  }
  #menuPlanModal .mplan-estimate-card .slist-actions { margin-top: var(--space-8); }
}
@media (min-width: 1280px) {
  #menuPlanModal .mplan-gizi-card.mplan-gizi-top {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
    column-gap: var(--space-24);
    align-items: start;
  }
  #menuPlanModal .mplan-gizi-top > .mplan-gizi-header { grid-column: 1; grid-row: 1; }
  #menuPlanModal .mplan-gizi-top > .slist-empty { grid-column: 1; grid-row: 2; }
  #menuPlanModal .mplan-gizi-top > .mplan-gizi-evaluasi-wrap {
    grid-column: 2;
    grid-row: 1 / span 2;
    margin-top: 0;
    padding-top: 0;
    border-top: none;
  }
  #menuPlanModal .mplan-gizi-top > .mplan-gizi-details { grid-column: 1 / -1; }
}
@media (min-width: 1880px) {
  #menuPlanModal .mplan-days {
    grid-template-columns: repeat(7, minmax(0, 1fr));
    align-items: stretch;
  }
}

/* ── Brankas terkunci: tampilan minimal & seamless ──
   Hanya input master password + tombol "Buka Brankas", tanpa kotak/border,
   dipusatkan dan pas satu layar (tanpa scroll). Header disembunyikan di desktop;
   di layar hp header tetap ada karena memuat tombol menu. */
#vaultModal.vault-lock-min .vault-gate-wrap {
  flex: 1; align-items: center; padding: 0;
}
#vaultModal.vault-lock-min .vault-gate {
  max-width: 340px; padding: 0; gap: var(--space-12);
  border: none; border-radius: 0; background: transparent;
}
#vaultModal.vault-lock-min .vault-caps { margin: 0; text-align: left; }
@media (min-width: 1024px) {
  body.view-fullpage #vaultModal.vault-lock-min.show .modal-content {
    border: none; background: transparent; padding: 0;
    display: flex; flex-direction: column;
    min-height: calc(100vh - var(--space-28) - var(--space-40));
    min-height: calc(100dvh - var(--space-28) - var(--space-40));
  }
  #vaultModal.vault-lock-min .modal-header { display: none; }
  #vaultModal.vault-lock-min .vault-body { flex: 1; display: flex; padding: 0; }
}
@media (max-width: 1023px) {
  #vaultModal.vault-lock-min .vault-body { flex: 1; display: flex; padding: 0 0 var(--space-40); }
}

/* ── Setelan: tampilan lebih padat ──
   Jarak antar kartu, padding kartu, tinggi input/tombol, dan area status
   kosong dirapatkan supaya kepadatannya seimbang dengan menu lain.
   Hanya CSS & hanya di #setelanModal; markup/JS tidak berubah. */
#setelanModal .setelan-tab-content { gap: var(--space-8); }
#setelanModal .data-management-panel.setelan-tab-panel { padding: var(--space-10) var(--space-14); }
#setelanModal .panel-title { margin-bottom: var(--space-6); }
#setelanModal .setelan-desc { margin-bottom: var(--space-6); line-height: 1.5; }
#setelanModal .form-group { margin-bottom: var(--space-8); }
#setelanModal .form-group label { margin-bottom: var(--space-3, 3px); }
#setelanModal .form-control { padding: var(--space-6) var(--space-10); }
#setelanModal .btn { padding: var(--space-5) var(--space-12); }
#setelanModal .setelan-collapse { margin: var(--space-4) 0 var(--space-8); }
#setelanModal .setelan-collapse summary { padding: var(--space-6) var(--space-10); }
#setelanModal .setelan-collapse-body { padding-bottom: var(--space-8); line-height: 1.6; }
#setelanModal .setelan-divider { margin: var(--space-8) 0; }
#setelanModal .acc-modal-list { margin-bottom: var(--space-8); }
#setelanModal .acc-modal-item { padding: var(--space-7) var(--space-12); margin-bottom: var(--space-4); }

/* Area status kosong tidak memakan ruang; saat terisi teks otomatis normal lagi. */
#setelanModal [id*="Status"]:empty,
#setelanModal .setelan-status-row:empty,
#setelanModal .setelan-status-row--margin:empty,
#setelanModal .setelan-test-status:empty,
#setelanModal .setelan-preview:empty,
#setelanModal .setelan-preview--amber:empty,
#setelanModal .setelan-preview--green:empty {
  min-height: 0 !important; margin: 0 !important; padding: 0 !important;
}

/* Margin/padding inline yang besar (tombol Panduan, pemisah Tambah Akun, kotak info). */
#setelanModal .setelan-tab-panel > button.btn[style*="margin-bottom"] { margin-bottom: var(--space-8) !important; }
#setelanModal .setelan-tab-panel div[style*="border-top:1.5px dashed"] { padding-top: var(--space-10) !important; margin-top: var(--space-6) !important; }
#setelanModal .setelan-tab-panel > div[style*="margin-top:var(--space-14)"],
#setelanModal .setelan-tab-panel > div[style*="margin-top:var(--space-16)"] { margin-top: var(--space-8) !important; }
#setelanModal .setelan-tab-panel > div[style*="var(--info-lt)"] {
  padding: var(--space-8) var(--space-12) !important; margin-top: var(--space-8) !important; line-height: 1.55 !important;
}

/* ── Buku Kas (desktop): daftar buku dibuat grid & kartu lebih padat ──
   Sebelumnya tiap buku 1 baris selebar layar -> ruang kosong besar di tengah
   kartu. Di >=1024px kartu disusun beberapa kolom (otomatis menyesuaikan lebar).
   Markup/JS (js/book.js) tidak berubah; layar kecil tetap pakai aturan lama. */
@media (min-width: 1024px) {
  #bookManagerModal #bookListContainer {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(460px, 1fr));
    gap: var(--space-8);
    margin-bottom: var(--space-8);
  }
  #bookManagerModal #bookListContainer > div:not(.book-list-item) { grid-column: 1 / -1; }
  #bookManagerModal .book-list-item {
    margin-bottom: 0;
    padding: var(--space-8) var(--space-12);
    gap: var(--space-10);
    min-width: 0;
  }
  #bookManagerModal .book-list-name { min-width: 0; line-height: 1.35; }
  #bookManagerModal .book-list-name > div { margin-top: 1px !important; }
  #bookManagerModal .book-list-actions { flex: 0 0 auto; flex-wrap: nowrap; }
}

/* ── Chip "Login terakhir" anggota lain (kanan pemilih buku) -- khusus desktop ──
   Diisi window.skUpdateOthersLastLogin (js/auth-members.js). Disembunyikan di
   <1024px (layar hp/tablet kecil) dan saat [hidden]. */
.others-login-chip { display: none; }
@media (min-width: 1024px) {
  .others-login-chip {
    display: inline-flex; align-items: center; gap: var(--space-8);
    flex-shrink: 0; cursor: default; user-select: none;
    padding: var(--space-3) var(--space-12) var(--space-3) var(--space-4);
    border: 1.5px solid var(--rule);
    border-radius: 999px;
    background: var(--paper);
    font-size: var(--text-2xs);
    line-height: 1.25;
    transition: border-color .15s, background .15s;
  }
  .others-login-chip[hidden] { display: none; }
  .others-login-chip:hover { border-color: var(--ink-faint); background: var(--paper-warm); }
  .olc-avatar {
    position: relative; flex: 0 0 auto;
    width: 26px; height: 26px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--accent-lt); color: var(--accent);
    font-size: var(--text-xs); font-weight: 700;
  }
  .others-login-chip.is-recent .olc-avatar::after {
    content: ''; position: absolute; right: -1px; bottom: -1px;
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--success); border: 1.5px solid var(--paper);
  }
  .olc-text { display: flex; flex-direction: column; min-width: 0; }
  .olc-label { color: var(--ink-faint); font-weight: 500; letter-spacing: .02em; }
  .olc-main { color: var(--ink-muted); white-space: nowrap; max-width: 260px; overflow: hidden; text-overflow: ellipsis; }
  .olc-main b { color: var(--ink); font-weight: 600; }
}

/* ── Info header desktop: hari/tanggal hari ini + pengeluaran/pemasukan terakhir ──
   Hanya desktop sungguhan (>=1440px + mouse/trackpad): layar kecil, tablet, dan iPad Pro
   landscape (maks 1366px) tidak menampilkan bar ini sama sekali. */
.header-info { display: none; }
@media (min-width: 1440px) and (hover: hover) and (pointer: fine) {
  .header-info {
    display: inline-flex; align-items: center; gap: var(--space-14);
    flex-shrink: 0; white-space: nowrap; user-select: none;
    font-size: var(--text-xs); color: var(--topbar-text-muted, var(--ink-muted));
  }
  .header-info .hi-date { font-weight: 600; color: var(--topbar-text, var(--ink)); }
  .header-info .hi-date-wrap { display: inline-flex; align-items: center; gap: var(--space-6); }
  .header-info .hi-cal-icon { flex: 0 0 auto; width: 1.15em; height: 1.15em; color: var(--accent, var(--ink-muted)); }
  .header-info .hi-last {
    display: flex; flex-direction: column; gap: 1px;
    padding-left: var(--space-14); border-left: 1px solid var(--topbar-border, var(--rule));
    font-size: var(--text-2xs); line-height: 1.3;
  }
  .header-info .hi-line b { color: var(--topbar-text, var(--ink)); font-weight: 600; }
  .header-info .hi-amt { font-weight: 600; margin-left: var(--space-4); }
  .header-info .hi-amt::before { content: '\00B7'; margin-right: var(--space-6); color: var(--ink-faint); font-weight: 400; }
  .header-info .hi-amt.hi-exp { color: var(--danger); }
  .header-info .hi-amt.hi-inc { color: var(--success); }
}
/* [HEADER SATU BARIS] Pemasukan & pengeluaran terakhir jadi 1 baris hanya kalau
   LEBAR HEADER-nya sendiri cukup (container query pada .header), bukan lebar
   layar. Sebelumnya dipakai @media (min-width:1560px) -- di laptop saat
   sidebar diperluas (236px) area header menyempit tapi lebar layar masih
   >=1560px, jadi info tetap 1 baris yang panjang dan chip "login terakhir"
   terdorong turun ke baris kedua. Bertingkat:
   - header >=1520px : info terakhir 1 baris (paling lebar)
   - 1150-1519px     : info terakhir 2 baris (lebih ringkas)
   - <1150px         : info terakhir disembunyikan, tanggal hari ini tetap tampil */
.header { container-type: inline-size; container-name: hdr; }
@container hdr (min-width: 1520px) {
  .header-info .hi-last { flex-direction: row; align-items: center; gap: 0; font-size: var(--text-xs); }
  .header-info .hi-line + .hi-line { margin-left: var(--space-16); padding-left: var(--space-16); border-left: 1px solid var(--topbar-border, var(--rule)); }
}
@container hdr (max-width: 1149px) {
  .header-info .hi-last { display: none; }
}

/* Chip login terakhir: rata kanan mentok (bukan menempel di sebelah dropdown buku).
   .book-selector dilebarkan memenuhi header, lalu chip didorong ke ujung kanan. */
@media (min-width: 1024px) {
  /* [HEADER SATU BARIS] flex-wrap dimatikan di desktop: item yang tidak muat
     tidak lagi pindah baris (chip login terakhir sempat turun sendirian).
     Yang mengalah adalah dropdown buku (boleh menyusut sampai 190px, nama
     buku di-ellipsis); badge sync, info tanggal, dan chip tidak menyusut. */
  .header .book-selector { flex: 1 1 auto; min-width: 0; flex-wrap: nowrap; }
  .header .book-selector > *:not(.cs-wrapper) { flex-shrink: 0; }
  .header .book-selector > .cs-wrapper.compact { flex: 0 1 300px; min-width: 190px; width: auto; }
  .header .book-selector > .cs-wrapper.compact .cs-trigger { min-width: 0; width: 100%; }
  .header .others-login-chip { margin-left: var(--space-8); }
}

/* ── Privasi: 5 transaksi terbaru disamarkan di tabel ──
   Aktif saat body.sk-privacy-on (mode privasi nominal, ikon mata di dashboard).
   Kategori, deskripsi, pemasukan/pengeluaran, dan saldo baris .tx-recent diganti
   titik-titik; nomor, tanggal, jenis, dan tombol aksi tetap tampil. */
body.sk-privacy-on .tx-table tr.tx-recent td.col-txcat,
body.sk-privacy-on .tx-table tr.tx-recent td.col-desc,
body.sk-privacy-on .tx-table tr.tx-recent td.col-note,
body.sk-privacy-on .tx-table tr.tx-recent td.col-wallet,
body.sk-privacy-on .tx-table tr.tx-recent td.col-income,
body.sk-privacy-on .tx-table tr.tx-recent td.col-expense,
body.sk-privacy-on .tx-table tr.tx-recent td.col-saldo {
  font-size: 0 !important;
  user-select: none;
}
body.sk-privacy-on .tx-table tr.tx-recent td.col-txcat::after,
body.sk-privacy-on .tx-table tr.tx-recent td.col-desc::after,
body.sk-privacy-on .tx-table tr.tx-recent td.col-note::after,
body.sk-privacy-on .tx-table tr.tx-recent td.col-wallet::after,
body.sk-privacy-on .tx-table tr.tx-recent td.col-income::after,
body.sk-privacy-on .tx-table tr.tx-recent td.col-expense::after,
body.sk-privacy-on .tx-table tr.tx-recent td.col-saldo::after {
  content: '\2022\2022\2022\2022\2022\2022';
  font-size: var(--text-sm);
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  font-weight: 400;
}

/* ── Layar login (skLoginGateScreen): sederhana, sama gayanya dengan layar
   kunci password (#passwordLockScreen) -- judul, 2 field .lock-input,
   tombol "Lihat" bertulisan, & 1 tombol Masuk. Tanpa logo/kartu/efek cahaya. */
#skLoginGateScreen .lock-title { margin-bottom: var(--space-20); }
#skLoginGateScreen .lock-input { letter-spacing: normal; }
.sk-gate-form { display: flex; flex-direction: column; text-align: left; }
.sk-gate-btn { width: 100%; margin-top: var(--space-4); padding-top: var(--space-12); padding-bottom: var(--space-12); font-size: var(--text-base); }
.sk-gate-btn:disabled { cursor: wait; }
.sk-gate-msg { font-size: var(--text-xs); line-height: 1.45; color: var(--danger); margin-bottom: var(--space-10); }
.sk-gate-caps { font-size: var(--text-xs); font-weight: 600; color: var(--warning); margin: 0 0 var(--space-8); }
.sk-gate-msg[hidden], .sk-gate-caps[hidden] { display: none; }
.sk-gate-shake { animation: shake .4s ease; }
@media (prefers-reduced-motion: reduce) { .sk-gate-shake { animation: none; } }

/* [KALENDER PENDIDIKAN] Popup matriks Kalender Pendidikan Jatim 2026/2027
   di SinarMedia (js/sinarmedia.js -> window._smediaRenderEduCalendar).
   [REDESAIN UI 28 Okt 2026] Disamakan dengan bahasa visual aplikasi: flat,
   outline tipis 1px, sudut membulat (--radius*), kartu statistik seperti
   .stat-card, chip kapsul seperti .type-badge, dan sel tanggal berupa ubin
   membulat (jarak antar-ubin = border 2px berwarna --paper, jadi kolom bulan
   yang sticky tetap menutup rapat tanpa celah). Warna kategori memakai token
   --edu-* (ikut tema gelap) dan diteruskan ke sel lewat variabel --cb, supaya
   tidak kalah oleh aturan global `tr:hover td`. Kategori tetap bisa dibedakan
   tanpa warna saja: tiap sel menampilkan kodenya (LHB, LU, LS, ...) atau
   nomor hari efektif, dan legenda ada di bawah tabel.
   Hierarki: merah pastel agak pekat + tebal = libur hari besar, merah pastel
   tipis = Minggu rutin. */
.smedia-edu-modal { max-width: none !important; }
.smedia-edu-modal {
  /* Semua warna sengaja LEMBUT: latar pastel + teks berwarna, tanpa blok
     solid. Ukuran kepentingan dibedakan lewat kedalaman pastel & tebal huruf. */
  --edu-head-bg:    var(--accent-lt);
  --edu-head-fg:    var(--accent);
  --edu-dh-bg:      var(--paper-warm);
  --edu-dh-fg:      var(--ink-muted);
  --edu-sem1-bg:    #D7E8E0;                 /* label bulan semester ganjil */
  --edu-sem1-fg:    #0F5C4E;
  --edu-sem2-bg:    #D9E7ED;                 /* label bulan semester genap */
  --edu-sem2-fg:    #2E6B82;
  --edu-e:          var(--paper-warm);       /* hari efektif: ubin netral hangat */
  --edu-ke:         transparent;             /* Sabtu / ekstrakurikuler: tanpa ubin, teks redup */
  --edu-ke-fg:      var(--ink-muted);
  --edu-lu-bg:      #FAF0F0;                 /* Minggu / libur umum */
  --edu-lu-fg:      #A83E3E;
  --edu-lhb-bg:     #EFD4D4;                 /* libur hari besar */
  --edu-lhb-fg:     #8A3030;
  --edu-ls-bg:      var(--warning-lt);       /* libur semester */
  --edu-ls-fg:      var(--ink);
  --edu-cb-bg:      #EFDFB0;                 /* cuti bersama */
  --edu-cb-fg:      #6E540F;
  --edu-kpp-bg:     var(--info-lt);          /* kegiatan permulaan puasa */
  --edu-kpp-fg:     var(--info);
  --edu-lhr-bg:     var(--purple-lt);        /* libur sekitar hari raya */
  --edu-lhr-fg:     var(--purple);
  --edu-kts-bg:     #CFE5DB;                 /* kegiatan tengah semester */
  --edu-kts-fg:     #0A4A3E;
  --edu-x:          var(--rule);             /* di luar tahun ajaran */
}
[data-theme="dark"] .smedia-edu-modal {
  /* [GAYA HANDBOOK] Palet ikut dark baru: emerald neon redup untuk
     semester/kegiatan, merah redup untuk libur, kuning untuk cuti bersama. */
  --edu-head-bg:    #1B2008;
  --edu-head-fg:    #CDF543;
  --edu-dh-bg:      var(--paper-warm);
  --edu-dh-fg:      #A1A1A1;
  --edu-sem1-bg:    #1F2A22;
  --edu-sem1-fg:    #6FDDA6;
  --edu-sem2-bg:    #1A2420;
  --edu-sem2-fg:    #52C690;
  --edu-ke-fg:      #A1A1A1;
  --edu-lu-bg:      #1F0F13;
  --edu-lu-fg:      #FF7B8B;
  --edu-lhb-bg:     #3A1620;
  --edu-lhb-fg:     #FF9AA7;
  --edu-ls-fg:      #EDEDED;
  --edu-cb-bg:      #2A200A;
  --edu-cb-fg:      #F2B84B;
  --edu-kpp-bg:     #1C1C1C;
  --edu-kpp-fg:     #B5B5B5;
  --edu-lhr-bg:     #1E1E1E;
  --edu-lhr-fg:     #52C690;
  --edu-kts-bg:     #123D2B;
  --edu-kts-fg:     #8CF0BE;
}

/* ── Kepala halaman: judul kiri, pilihan TA + tombol ubah kanan ── */
.smedia-edu-toolbar { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-12); flex-wrap: wrap; margin-bottom: var(--space-14); }
.smedia-edu-title { flex: 1 1 320px; min-width: 0; text-align: left; font-family: var(--font-body); color: var(--ink); }
.smedia-edu-title-main { display: block; font-weight: 700; font-size: var(--text-lg); letter-spacing: -0.01em; line-height: 1.35; }
.smedia-edu-title small { display: block; margin-top: var(--space-2); font-size: var(--text-xs); font-weight: 500; color: var(--ink-muted); }
.smedia-edu-actions { display: flex; align-items: center; gap: var(--space-10); flex: 0 0 auto; flex-wrap: wrap; }
.smedia-edu-actions > .btn { white-space: nowrap; }
.smedia-edu-sel-label { display: flex; align-items: center; gap: var(--space-8); font-size: var(--text-xs); font-weight: 600; color: var(--ink-muted); white-space: nowrap; }
.smedia-edu-sel-label .form-control { width: auto; min-width: 130px; color: var(--ink); }
.smedia-edu-viewer-note { font-size: var(--text-2xs); color: var(--ink-faint); }

/* ── Kartu ringkasan hari efektif (pola .stat-card, flat) ── */
.smedia-edu-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--space-10); margin-bottom: var(--space-14); }
.smedia-edu-stat { background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius); padding: var(--space-12) var(--space-14); min-width: 0; }
.smedia-edu-stat-label { font-size: var(--text-xs); font-weight: 600; color: var(--ink-muted); letter-spacing: 0.01em; }
.smedia-edu-stat-value { display: flex; align-items: baseline; gap: var(--space-6); margin-top: var(--space-4); font-family: var(--font-mono); font-size: var(--text-2xl); font-weight: 700; letter-spacing: -0.01em; color: var(--ink); }
.smedia-edu-stat-value small { font-family: var(--font-body); font-size: var(--text-xs); font-weight: 500; letter-spacing: 0; color: var(--ink-muted); }
.smedia-edu-stat-sub { margin-top: var(--space-2); font-size: var(--text-2xs); color: var(--ink-faint); }
[data-theme="dark"] .smedia-edu-stat-label { font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 500; font-size: var(--text-2xs); }

/* ── Matriks bulan x tanggal ── */
.smedia-edu-scroll { overflow-x: auto; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper); color: var(--ink); padding: var(--space-4); }
.smedia-edu-table { border-collapse: separate; border-spacing: 0; width: 100%; min-width: 900px; font-size: 10px; font-variant-numeric: tabular-nums; table-layout: fixed; text-align: center; }
.smedia-edu-modal .smedia-edu-table th,
.smedia-edu-modal .smedia-edu-table td {
  /* Border 2px berwarna latar = jarak antar-ubin; background-clip membuat
     warna sel berhenti di tepi dalam sehingga sudutnya membulat rapi. */
  border: 2px solid var(--paper);
  background-clip: padding-box;
  border-radius: 8px;
  text-align: center;
  padding: 0;
  height: 28px;
}
.smedia-edu-modal .smedia-edu-table thead th { text-transform: none; letter-spacing: 0; }
.smedia-edu-modal .smedia-edu-table th.smedia-edu-dh { height: 22px; background: transparent; color: var(--ink-faint); font-size: 10px; font-weight: 600; }
.smedia-edu-modal .smedia-edu-table th.smedia-edu-corner { width: 116px; position: sticky; left: 0; z-index: 2; background: var(--paper); color: var(--ink-faint); text-align: left; padding-left: var(--space-10); font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
.smedia-edu-modal .smedia-edu-table th.smedia-edu-month { position: sticky; left: 0; z-index: 1; width: 116px; text-align: left; padding-left: var(--space-10); font-family: var(--font-body); font-size: 10.5px; font-weight: 600; letter-spacing: 0; text-transform: none; white-space: nowrap; }
.smedia-edu-modal .smedia-edu-table th.smedia-edu-month.is-s1 { background: var(--edu-sem1-bg); color: var(--edu-sem1-fg); }
.smedia-edu-modal .smedia-edu-table th.smedia-edu-month.is-s2 { background: var(--edu-sem2-bg); color: var(--edu-sem2-fg); }

/* Sel: warna lewat --cb (lihat catatan di atas), jadi hover baris tidak menimpa. */
.smedia-edu-c { background-color: var(--cb, transparent); }
.smedia-edu-modal .smedia-edu-table td.smedia-edu-c { background-color: var(--cb, transparent); }
.smedia-edu-c.is-e   { --cb: var(--edu-e); }
.smedia-edu-c.is-ke  { --cb: var(--edu-ke); color: var(--edu-ke-fg); }
.smedia-edu-c.is-lu  { --cb: var(--edu-lu-bg); color: var(--edu-lu-fg); font-weight: 500; }
.smedia-edu-c.is-lhb { --cb: var(--edu-lhb-bg); color: var(--edu-lhb-fg); font-weight: 700; }
.smedia-edu-c.is-ls1, .smedia-edu-c.is-ls2 { --cb: var(--edu-ls-bg); color: var(--edu-ls-fg); font-weight: 600; }
.smedia-edu-c.is-cb  { --cb: var(--edu-cb-bg); color: var(--edu-cb-fg); font-weight: 700; }
.smedia-edu-c.is-kpp { --cb: var(--edu-kpp-bg); color: var(--edu-kpp-fg); font-weight: 700; }
.smedia-edu-c.is-lhr { --cb: var(--edu-lhr-bg); color: var(--edu-lhr-fg); font-weight: 700; }
.smedia-edu-c.is-kts { --cb: var(--edu-kts-bg); color: var(--edu-kts-fg); font-weight: 700; }
/* Di luar tahun ajaran: arsir tipis (bukan ubin), supaya jelas bukan hari sekolah */
.smedia-edu-c.is-x   { --cb: transparent; }
.smedia-edu-modal .smedia-edu-table td.smedia-edu-c.is-x { background-image: repeating-linear-gradient(45deg, var(--edu-x) 0 1px, transparent 1px 5px); }
.smedia-edu-c.is-na  { --cb: transparent; box-shadow: none; }
.smedia-edu-c.is-today { outline: 2px solid var(--ink); outline-offset: -2px; font-weight: 800; }
.smedia-edu-c.has-deadline { box-shadow: inset 0 -4px 0 var(--info); }

/* ── Keterangan di bawah matriks ── */
.smedia-edu-note { margin-top: var(--space-8); font-size: var(--text-2xs); color: var(--ink-faint); }
.smedia-edu-section { margin-top: var(--space-18); }
.smedia-edu-sectitle { display: flex; align-items: center; gap: var(--space-8); margin-bottom: var(--space-10); font-size: var(--text-md); font-weight: 700; color: var(--ink); }
.smedia-edu-count { padding: var(--space-1) var(--space-8); border: 1px solid var(--rule); border-radius: var(--radius-pill); background: var(--paper-warm); color: var(--ink-muted); font-size: var(--text-2xs); font-weight: 600; line-height: 1.5; }
.smedia-edu-hint { font-size: var(--text-2xs); color: var(--ink-muted); margin-bottom: var(--space-8); }

/* Chip kode (legenda & daftar libur): kapsul tipis seperti .type-badge */
.smedia-edu-legend-item .smedia-edu-c,
.smedia-edu-hol .smedia-edu-c { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; min-width: 38px; padding: var(--space-2) var(--space-8); border: 1px solid var(--rule); border-radius: var(--radius-pill); font-size: 10px; line-height: 1.5; text-align: center; }
.smedia-edu-legend { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--space-10) var(--space-16); padding: var(--space-12) var(--space-14); border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper); font-size: var(--text-xs); color: var(--ink); }
.smedia-edu-legend-item { display: flex; align-items: center; gap: var(--space-10); min-width: 0; }
.smedia-edu-legend-month { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; min-width: 38px; padding: var(--space-2) var(--space-8); border-radius: var(--radius-pill); font-size: 10px; font-weight: 600; line-height: 1.5; }
.smedia-edu-legend-month.is-s1 { background: var(--edu-sem1-bg); color: var(--edu-sem1-fg); }
.smedia-edu-legend-month.is-s2 { background: var(--edu-sem2-bg); color: var(--edu-sem2-fg); }

/* Daftar libur & pengecualian: kartu tipis, tanggal di atas nama */
.smedia-edu-hols { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--space-8); }
.smedia-edu-hol { display: flex; align-items: center; gap: var(--space-12); min-width: 0; padding: var(--space-10) var(--space-12); border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper); font-size: var(--text-xs); }
.smedia-edu-hol .smedia-edu-c { min-width: 44px; }
.smedia-edu-hol-text { display: flex; flex-direction: column; gap: var(--space-1); flex: 1 1 auto; min-width: 0; }
.smedia-edu-hol-date { font-size: var(--text-sm); font-weight: 700; color: var(--ink); }
.smedia-edu-hol-name { color: var(--ink-muted); overflow-wrap: anywhere; }
.smedia-edu-hol-del { flex: 0 0 auto; border: 0; background: transparent; color: var(--danger); font-size: 18px; line-height: 1; cursor: pointer; padding: 0 var(--space-6); border-radius: var(--radius-sm); }
.smedia-edu-hol-del:hover { background: var(--danger-lt); }

/* ── Mode ubah: panel pengaturan & panel "Tandai Tanggal", sel bisa diketuk ── */
.smedia-edu-panel { border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper-warm); padding: var(--space-14); margin: var(--space-12) 0; }
.smedia-edu-panel-title { font-weight: 700; font-size: var(--text-md); margin-bottom: var(--space-6); color: var(--ink); }
.smedia-edu-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: var(--space-10); }
.smedia-edu-fields label { display: flex; flex-direction: column; gap: var(--space-4); font-size: var(--text-2xs); font-weight: 600; color: var(--ink-muted); }
.smedia-edu-panel-actions { display: flex; gap: var(--space-8); flex-wrap: wrap; margin-top: var(--space-12); }
.smedia-edu-c.is-editable { cursor: pointer; }
.smedia-edu-c.is-editable:hover:not(.is-sel):not(.is-today) { outline: 1px solid var(--accent); outline-offset: -2px; }
.smedia-edu-c.is-sel { outline: 2px dashed var(--ink); outline-offset: -2px; }

@media (max-width: 860px) {
  .smedia-edu-actions { width: 100%; justify-content: space-between; }
}
@media (max-width: 480px) {
  .smedia-edu-stats { grid-template-columns: 1fr 1fr; gap: var(--space-8); }
  .smedia-edu-stat { padding: var(--space-10) var(--space-12); }
  .smedia-edu-stat-value { font-size: var(--text-xl); }
  .smedia-edu-hols { grid-template-columns: 1fr; }
  .smedia-edu-btn-label { display: none; }
  #smediaEduBackBtn { padding-left: var(--space-10); padding-right: var(--space-10); }
  #smediaEduBackBtn .sk-icon-lead { margin: 0; }
  #smediaEduBackBtn .smedia-back-label { display: none; }
  #sinarMediaEduCalBtn { padding-left: var(--space-10); padding-right: var(--space-10); }
  #sinarMediaEduCalBtn .sk-icon-lead { margin: 0; }
  .smedia-edu-modal .smedia-edu-table th.smedia-edu-corner,
  .smedia-edu-modal .smedia-edu-table th.smedia-edu-month { width: 92px; }
}

/* Tombol Kalender & + Proyek Baru di header SinarMedia dirapatkan: hanya
   Kalender yang mendorong ke kanan (margin-left:auto bawaan), Proyek Baru
   menempel di sampingnya -- sebelumnya keduanya sama-sama auto sehingga
   ruang kosong terbagi dan jaraknya jauh. */
#sinarMediaModal .modal-header #sinarMediaEduCalBtn { margin-left: auto; }
#sinarMediaModal .modal-header #sinarMediaAddBtn { margin-left: 0 !important; }
/* Beri jarak tetap antar elemen header (judul, Kalender, + Proyek Baru) di
   semua lebar layar -- gap sebelumnya cuma ada di mode halaman penuh, jadi di
   layar lebar kedua tombol menempel. */
#sinarMediaModal .modal-header { gap: var(--space-10); }

/* ==================== TOOLTIP / HINT KUSTOM (js/tooltip.js) ====================
   Pengganti tooltip bawaan browser untuk atribut title & <title> SVG.
   Flat seperti komponen lain (tanpa shadow): latar --paper, garis tipis,
   teks --ink -- otomatis ikut tema gelap lewat token. Berada di atas modal
   & toast (z-index tertinggi). pointer-events:none supaya tidak mencuri hover. */
.sk-tooltip {
  position: fixed; left: 0; top: 0; z-index: 10050;
  max-width: min(280px, calc(100vw - 16px));
  padding: var(--space-5) var(--space-8);
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--ink-faint); border-radius: var(--radius-sm);
  font-family: var(--font-body); font-size: var(--text-xs); font-weight: 500; line-height: 1.45;
  white-space: pre-line; overflow-wrap: anywhere; text-align: left;
  pointer-events: none;
  opacity: 0; visibility: hidden;
  transition: opacity 0.12s ease, visibility 0s linear 0.12s;
}
.sk-tooltip.is-show { opacity: 1; visibility: visible; transition: opacity 0.12s ease; }

/* Hint terstruktur (data-tip-rich) -- dipakai sel Kalender Pendidikan.
   Susunan: tanggal (+ lencana "Hari ini") -> chip kode + nama kategori ->
   catatan -> daftar deadline. Chip memakai warna sel aslinya (disalin lewat JS),
   jadi kategori & tema gelap ikut otomatis. Flat, tanpa garis aksen di tepi. */
.sk-tooltip--rich {
  display: flex; flex-direction: column; gap: var(--space-6);
  min-width: 176px; max-width: min(264px, calc(100vw - 16px));
  padding: var(--space-8) var(--space-10);
  white-space: normal;
}
.sk-tip-date { display: flex; align-items: center; justify-content: space-between; gap: var(--space-10); font-weight: 700; color: var(--ink); }
.sk-tip-today { flex: 0 0 auto; padding: 1px var(--space-6); border-radius: var(--radius-sm); background: var(--ink); color: var(--paper); font-size: var(--text-2xs); font-weight: 700; letter-spacing: 0.02em; }
.sk-tip-row { display: flex; align-items: center; gap: var(--space-8); }
.sk-tip-chip { flex: 0 0 auto; min-width: 32px; padding: 2px var(--space-6); border: 1px solid var(--rule); border-radius: var(--radius-xs); text-align: center; font-size: var(--text-2xs); font-weight: 700; font-variant-numeric: tabular-nums; }
.sk-tip-label { min-width: 0; font-weight: 500; color: var(--ink); }
.sk-tip-note { color: var(--ink-muted); font-size: var(--text-2xs); font-weight: 500; }
.sk-tip-dl { display: flex; flex-direction: column; gap: 3px; margin-top: 2px; padding-top: var(--space-6); border-top: 1px solid var(--rule); }
.sk-tip-dl-title { font-size: var(--text-2xs); font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--info); }
.sk-tip-dl-item { display: flex; align-items: baseline; gap: var(--space-6); color: var(--ink); }
.sk-tip-dl-item::before { content: ''; flex: 0 0 auto; width: 5px; height: 5px; border-radius: 50%; background: var(--info); transform: translateY(-1px); }
@media (prefers-reduced-motion: reduce) { .sk-tooltip, .sk-tooltip.is-show { transition: none; } }
@media (hover: none) and (pointer: coarse) { .sk-tooltip { display: none; } }

/* [DARK LEMBUT] Elemen hijau solid/tebal di Daftar Menu diganti tint halus:
   tab minggu aktif, badge HARI INI, kartu hari ini, kotak estimasi gizi. */
[data-theme="dark"] .mplan-week-tab.is-active {
  background: color-mix(in srgb, var(--accent) 22%, var(--paper));
  border-color: color-mix(in srgb, var(--accent) 40%, var(--paper));
  color: var(--ink);
}
[data-theme="dark"] .mplan-day-card.is-today {
  border-color: color-mix(in srgb, var(--accent) 50%, var(--rule));
  background: color-mix(in srgb, var(--accent) 5%, var(--paper));
  box-shadow: none;
}
[data-theme="dark"] .mplan-today-badge {
  background: color-mix(in srgb, var(--accent) 24%, var(--paper));
  color: var(--accent);
}
[data-theme="dark"] .mplan-gizi-card.mplan-gizi-top {
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--rule));
  background: color-mix(in srgb, var(--accent) 8%, var(--paper));
}

/* ======================================================
   [POLES GAYA COPILOT -- ronde 2] Berlaku di KEDUA tema.
   1) Item nav sidebar tanpa kotak/border (sebelumnya tombol global
      `button` & `[data-theme="dark"] button` ikut membungkus item nav
      dengan background + border, dan hover-nya menimpa state aktif).
   2) Sorotan teks (selection) lembut.
   3) Daftar Menu mode terang: tab/badge/kartu hijau solid -> tint halus
      (versi dark ada di blok [DARK LEMBUT] di atas).
====================================================== */
:root .app-nav-item {
  background: none;
  border-color: transparent;
  color: var(--topbar-item-color);
}
:root .app-nav-item:hover:not(:disabled) {
  background: var(--topbar-item-hover-bg);
  border-color: transparent;
  color: var(--topbar-text);
}
:root .app-nav-item.active:not(:disabled),
:root .app-nav-item.active:hover:not(:disabled) {
  background: var(--topbar-item-active-bg);
  border-color: transparent;
  color: var(--topbar-item-active-color);
}
::selection { background: color-mix(in srgb, var(--accent) 28%, transparent); }

:root:not([data-theme="dark"]) .mplan-week-tab.is-active {
  background: color-mix(in srgb, var(--accent) 12%, var(--paper));
  border-color: color-mix(in srgb, var(--accent) 35%, var(--paper));
  color: var(--accent);
}
:root:not([data-theme="dark"]) .mplan-day-card.is-today {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--rule));
  background: color-mix(in srgb, var(--accent) 4%, var(--paper));
  box-shadow: none;
}
:root:not([data-theme="dark"]) .mplan-today-badge {
  background: color-mix(in srgb, var(--accent) 14%, var(--paper));
  color: var(--accent);
}
:root:not([data-theme="dark"]) .mplan-gizi-card.mplan-gizi-top {
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--rule));
}
:root:not([data-theme="dark"]) .page-btn.active {
  background: color-mix(in srgb, var(--accent) 12%, var(--paper));
  border-color: color-mix(in srgb, var(--accent) 35%, var(--paper));
  color: var(--accent);
}

/* ======================================================
   [SETELAN RINGKAS] Panel Setelan jadi accordion (lihat js/settings.js
   initSetelanAccordion). Judul selalu tampil, isi dilipat. Semua panel
   memakai gaya netral yang sama; hanya zona bahaya (merah) tetap berwarna.
====================================================== */
#setelanModal .setelan-tab-content { gap: var(--space-6); }
#setelanModal .data-management-panel.setelan-acc {
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: var(--space-6) var(--space-14);
}
#setelanModal .setelan-acc-head {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  margin: 0;
  padding: var(--space-8) 0;
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0;
  cursor: pointer;
  user-select: none;
}
#setelanModal .setelan-acc-head:not([class*="setelan-title--"]) { color: var(--ink); }
#setelanModal .setelan-acc-head[class*="setelan-title--"]:not(.setelan-title--red) { color: var(--ink); }
#setelanModal .setelan-acc-head::before {
  content: '';
  flex: 0 0 auto;
  width: 1.1em; height: 1.1em;
  background-color: var(--ink-faint);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform .15s ease;
  transform: rotate(90deg);
}
#setelanModal .setelan-acc.is-collapsed .setelan-acc-head::before { transform: rotate(0deg); }
#setelanModal .setelan-acc-head:hover::before { background-color: var(--ink-muted); }
#setelanModal .setelan-acc-head:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }
#setelanModal .setelan-acc:not(.is-collapsed) > .setelan-acc-head {
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--space-10);
}
#setelanModal .setelan-acc.is-collapsed > :not(.setelan-acc-head) { display: none !important; }


/* ===================================================
   ASSET MANAGER (js/asset-manager.js)
   Ringkasan nilai + komposisi, filter jenis, urutan, tampilan kartu/daftar.
   Hanya memakai token var(--...) (lihat docs/STYLE_GUIDE.md).
=================================================== */
.asset-search-bar { position: relative; flex: 1 1 160px; min-width: 0; max-width: 340px; margin-left: auto; }
.asset-search-icon { position: absolute; left: var(--space-12); top: 50%; transform: translateY(-50%); display: flex; color: var(--ink-faint); pointer-events: none; }
.asset-search-input {
  width: 100%;
  padding: var(--space-6) var(--space-12) var(--space-6) var(--space-32);
  font: inherit;
  font-size: var(--text-xs);
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
}
.asset-search-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }

/* Ringkasan: angka utama = estimasi nilai seluruh aset, dibandingkan dengan harga perolehan */
.asset-summary {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--space-16) var(--space-24);
  align-items: end;
  margin: 0 var(--space-16) var(--space-14);
  padding: var(--space-16) var(--space-18);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.asset-summary[hidden], .asset-toolbar[hidden] { display: none; }
.asset-sum-label { font-size: var(--text-xs); color: var(--ink-muted); }
.asset-sum-value {
  font-family: var(--font-display);
  font-size: clamp(1.45rem, 4.2vw, var(--text-5xl));
  font-weight: 600; line-height: 1.1; letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--ink); overflow-wrap: anywhere;
  margin-top: var(--space-4);
}
.asset-sum-gain { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-6); margin-top: var(--space-8); font-size: var(--text-xs); color: var(--ink-muted); }
.asset-sum-stats { display: flex; justify-content: flex-end; gap: var(--space-24); }
.asset-sum-stat { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.asset-sum-stat b { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; color: var(--ink); overflow-wrap: anywhere; }
.asset-sum-stat span { font-size: var(--text-xs); color: var(--ink-muted); }
.asset-comp { grid-column: 1 / -1; padding-top: var(--space-14); border-top: 1px solid var(--rule); }
.asset-comp-bar { display: flex; gap: 2px; height: 8px; border-radius: var(--radius-pill); overflow: hidden; background: var(--paper-warm); }
.asset-comp-seg { min-width: 4px; }
.asset-comp-legend { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4) var(--space-16); margin-top: var(--space-8); font-size: var(--text-xs); color: var(--ink-muted); }
.asset-comp-cap { color: var(--ink-faint); margin-right: auto; }
.asset-comp-key { display: inline-flex; align-items: center; gap: var(--space-6); }
.asset-comp-key em { font-style: normal; color: var(--ink); font-variant-numeric: tabular-nums; }
.asset-comp-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.t-tanah { background: var(--accent); }
.t-bangunan { background: var(--info); }
.t-tanah_bangunan { background: var(--purple); }
.t-kendaraan { background: var(--warning); }
.t-lainnya { background: var(--ink-faint); }
/* Tema gelap: token aksen berdekatan (semua hijau) -> beda jenis dibedakan lewat token lain */
[data-theme="dark"] .t-bangunan { background: var(--ink); }
[data-theme="dark"] .t-tanah_bangunan { background: var(--info); }
[data-theme="dark"] .t-kendaraan { background: var(--danger); }

.asset-gain { display: inline-flex; align-items: center; gap: var(--space-4); font-size: var(--text-2xs); font-weight: 600; padding: var(--space-1) var(--space-8); border-radius: var(--radius-pill); white-space: nowrap; font-variant-numeric: tabular-nums; }
.asset-gain.up { color: var(--success); background: var(--success-lt); }
.asset-gain.down { color: var(--danger); background: var(--danger-lt); }

/* Toolbar: filter jenis di kiri, urutan + tampilan di kanan */
.asset-toolbar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-10); margin: 0 var(--space-16) var(--space-12); }
.asset-chips { display: flex; gap: var(--space-6); flex-wrap: wrap; }
.asset-chip {
  font: inherit;
  font-size: var(--text-2xs);
  color: var(--ink-muted);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: var(--space-4) var(--space-10);
  cursor: pointer;
}
.asset-chip:hover { border-color: var(--accent); }
.asset-chip:focus-visible, .asset-viewbtn:focus-visible, .asset-sort:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.asset-chip.active { color: var(--accent); background: var(--accent-lt); border-color: var(--accent); font-weight: 600; }
.asset-chip-n { color: var(--ink-faint); margin-left: 2px; }
.asset-toolbar-end { display: flex; align-items: center; gap: var(--space-8); margin-left: auto; }
.asset-sort { font: inherit; font-size: var(--text-xs); color: var(--ink); background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius-pill); padding: var(--space-4) var(--space-10); cursor: pointer; }
.asset-viewtoggle { display: inline-flex; padding: var(--space-2); background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius-pill); }
.asset-viewbtn { width: 28px; height: 26px; display: inline-flex; align-items: center; justify-content: center; color: var(--ink-muted); background: none; border: none; border-radius: var(--radius-pill); cursor: pointer; }
.asset-viewbtn[aria-pressed="true"] { color: var(--paper); background: var(--ink); }

.asset-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  gap: var(--space-14);
  padding: 0 var(--space-16) var(--space-20);
}
.asset-empty {
  grid-column: 1 / -1;
  display: flex; flex-direction: column; align-items: center; gap: var(--space-6);
  text-align: center;
  padding: var(--space-32) var(--space-16);
  color: var(--ink-muted);
}
.asset-empty-art { width: 132px; height: 82px; color: var(--ink-faint); margin-bottom: var(--space-8); border-radius: var(--radius-sm); overflow: hidden; background: var(--paper-warm); }
.asset-empty-art svg { width: 100%; height: 100%; display: block; }
.asset-empty-title { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; color: var(--ink); }
.asset-empty-text { font-size: var(--text-xs); max-width: 38ch; line-height: 1.5; }
.asset-empty .btn { margin-top: var(--space-10); }

.asset-card {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.15s;
}
.asset-card:hover { border-color: var(--ink-faint); }
.asset-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.asset-card-media { position: relative; flex-shrink: 0; aspect-ratio: 16 / 9; background: var(--paper-warm); color: var(--ink-faint); }
.asset-card-thumb { width: 100%; height: 100%; object-fit: cover; display: block; }
.asset-card-thumb-empty { position: absolute; inset: 0; }
.asset-parcel { width: 100%; height: 100%; display: block; }
.asset-card-media .asset-type-badge {
  position: absolute; left: var(--space-8); top: var(--space-8);
  font-size: var(--text-2xs); font-weight: 600; color: var(--ink); background: var(--paper);
  border: 1px solid var(--rule); border-radius: var(--radius-pill); padding: var(--space-2) var(--space-8);
}
.asset-card-imgcount {
  position: absolute; right: var(--space-8); bottom: var(--space-8);
  font-size: var(--text-2xs); font-weight: 600; color: var(--paper); background: var(--ink);
  padding: var(--space-2) var(--space-8); border-radius: var(--radius-pill);
}
.asset-card-body { display: flex; flex-direction: column; flex: 1; gap: var(--space-8); min-width: 0; padding: var(--space-12) var(--space-14) var(--space-14); }
.asset-card-main { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.asset-card-name { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); line-height: 1.3; color: var(--ink); overflow-wrap: anywhere; }
.asset-card-addr { display: flex; align-items: flex-start; gap: var(--space-4); font-size: var(--text-xs); color: var(--ink-muted); overflow-wrap: anywhere; }
.asset-card-addr .sk-icon { flex-shrink: 0; margin-top: 2px; color: var(--ink-faint); }
.asset-card-specs { display: flex; flex-wrap: wrap; gap: var(--space-4) var(--space-16); margin: 0; }
.asset-card-spec { display: flex; flex-direction: column; min-width: 0; }
.asset-card-spec dt { font-size: var(--text-2xs); color: var(--ink-faint); }
.asset-card-spec dd { margin: 0; font-size: var(--text-xs); color: var(--ink); font-variant-numeric: tabular-nums; }
.asset-card-foot { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-8); margin-top: auto; padding-top: var(--space-10); border-top: 1px solid var(--rule); }
.asset-card-valuebox { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-4); min-width: 0; }
.asset-card-valuelabel { font-size: var(--text-2xs); color: var(--ink-faint); }
.asset-card-value { font-family: var(--font-mono); font-weight: 600; font-size: var(--text-base); color: var(--ink); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.asset-card-value.is-empty { font-family: var(--font-body); font-weight: 400; font-size: var(--text-xs); color: var(--ink-faint); }
.asset-card-maps {
  flex-shrink: 0; width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent); border: 1px solid var(--rule); border-radius: 50%; text-decoration: none;
}
.asset-card-maps:hover { background: var(--accent-lt); border-color: var(--accent); }

/* Tampilan daftar: satu baris per aset, kolom: nama+alamat | ukuran | nilai */
.asset-list.is-list { grid-template-columns: 1fr; gap: var(--space-8); }
.asset-list.is-list .asset-card { flex-direction: row; }
.asset-list.is-list .asset-card-media { width: 152px; min-height: 100px; aspect-ratio: auto; }
.asset-list.is-list .asset-card-body { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) 210px; align-items: center; gap: var(--space-4) var(--space-18); padding: var(--space-10) var(--space-14); }
.asset-list.is-list .asset-card-foot { margin-top: 0; padding-top: 0; border-top: none; align-items: center; justify-content: space-between; gap: var(--space-12); }

/* Form */
.asset-hint { font-size: var(--text-2xs); color: var(--ink-faint); line-height: 1.45; margin: var(--space-4) 0 var(--space-10); }
.asset-maps-open-wrap { display: flex; align-items: flex-end; }
.asset-img-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: var(--text-xs); font-weight: 600; color: var(--ink); margin: var(--space-10) 0 var(--space-6);
}
.asset-img-count { font-size: var(--text-2xs); font-weight: 400; color: var(--ink-faint); }
.asset-img-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--space-10); }
.asset-img-empty {
  grid-column: 1 / -1;
  font-size: var(--text-2xs); color: var(--ink-faint); text-align: center;
  padding: var(--space-14) var(--space-10); background: var(--paper-warm); border-radius: var(--radius-sm);
}
.asset-img-item { position: relative; display: flex; flex-direction: column; gap: var(--space-6); min-width: 0; }
.asset-img-thumbbtn {
  width: 100%; aspect-ratio: 4 / 3; padding: 0; cursor: zoom-in;
  border: 1px solid var(--rule); border-radius: var(--radius-sm); overflow: hidden; background: var(--paper-warm);
}
.asset-img-thumbbtn img { width: 100%; height: 100%; object-fit: cover; display: block; }
.asset-img-cover {
  position: absolute; left: var(--space-6); top: var(--space-6); pointer-events: none;
  font-size: var(--text-2xs); font-weight: 600; color: var(--paper); background: var(--ink);
  padding: var(--space-1) var(--space-8); border-radius: var(--radius-pill);
}
.asset-img-caption { width: 100%; min-width: 0; }
.asset-img-remove {
  position: absolute; right: var(--space-6); top: var(--space-6); width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--danger); background: var(--paper); border: 1px solid var(--rule); border-radius: 50%; cursor: pointer;
}
.asset-img-remove:hover { background: var(--danger-lt); }
.asset-img-makecover { align-self: flex-start; font: inherit; font-size: var(--text-2xs); color: var(--accent); background: none; border: none; padding: 0; cursor: pointer; text-decoration: underline; }
.asset-img-addrow { display: flex; gap: var(--space-8); flex-wrap: wrap; margin-top: var(--space-8); }
.asset-img-pick { cursor: pointer; }

/* Penampil gambar */
.asset-viewer-body { padding: var(--space-8) var(--space-16); background: var(--paper-warm); display: flex; justify-content: center; }
.asset-viewer-img { max-width: 100%; max-height: 70vh; object-fit: contain; border-radius: var(--radius-sm); }
.asset-viewer-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-10); padding: var(--space-10) var(--space-16) var(--space-14); }
.asset-viewer-caption { font-size: var(--text-xs); color: var(--ink-muted); overflow-wrap: anywhere; }

@media (max-width: 760px) {
  .asset-summary { grid-template-columns: 1fr; padding: var(--space-14); }
  .asset-sum-stats { justify-content: flex-start; flex-wrap: wrap; gap: var(--space-8) var(--space-20); }
  .asset-add-label { display: none; }
  .asset-search-bar { max-width: none; }
  .asset-toolbar-end { margin-left: 0; width: 100%; justify-content: space-between; }
  .asset-chips { flex-wrap: nowrap; overflow-x: auto; width: 100%; scrollbar-width: none; }
  .asset-chips::-webkit-scrollbar { display: none; }
  .asset-chip { flex-shrink: 0; white-space: nowrap; }
  .asset-list { grid-template-columns: 1fr; }
  .asset-list.is-list .asset-card-media { width: 92px; min-height: 92px; }
  .asset-list.is-list .asset-card-body { grid-template-columns: 1fr; gap: var(--space-6); }
  .asset-list.is-list .asset-card-foot { justify-content: flex-start; }
  .asset-list.is-list .asset-card-specs { display: none; }
}
@media (prefers-reduced-motion: reduce) { .asset-card { transition: none; } }


/* Asset Manager -- peta penanda letak (Leaflet lokal di vendor/) */
.asset-map-toggle-row { margin-bottom: var(--space-8); }
.asset-map-panel { margin-bottom: var(--space-10); }
.asset-map-panel[hidden] { display: none; }
.asset-map-search { display: flex; gap: var(--space-8); margin-bottom: var(--space-8); }
.asset-map-search .form-control { flex: 1; min-width: 0; }
.asset-map-results {
  display: flex; flex-direction: column; margin-bottom: var(--space-8);
  background: var(--paper); border: 1.5px solid var(--rule); border-radius: var(--radius-sm); max-height: 180px; overflow-y: auto;
}
.asset-map-results[hidden] { display: none; }
.asset-map-result, .asset-map-result-msg { font: inherit; font-size: var(--text-2xs); text-align: left; padding: var(--space-8) var(--space-10); }
.asset-map-result { color: var(--ink); background: none; border: none; border-bottom: 1px solid var(--rule); cursor: pointer; }
.asset-map-result:last-child { border-bottom: none; }
.asset-map-result:hover { background: var(--accent-lt); }
.asset-map-result-msg { color: var(--ink-faint); }
.asset-map-box {
  width: 100%; height: 56vh; min-height: 300px; max-height: 480px;
  border: 1.5px solid var(--rule); border-radius: var(--radius-sm); overflow: hidden; background: var(--paper-warm);
  position: relative; z-index: 0;
}
.asset-map-tools { display: flex; gap: var(--space-8); flex-wrap: wrap; align-items: center; margin-top: var(--space-8); }
.asset-map-seg { display: inline-flex; gap: var(--space-4); }
.asset-pin { background: none; border: none; color: var(--danger); }
.asset-pin svg { display: block; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.45)); }


/* ===================================================
   KESEHATAN KELUARGA (js/kesehatan.js)
   [ROMBAK 20 Okt 2026 -- tahap 2] Halaman: ringkasan (3 angka + chip "Belum
   diisi") -> saringan -> kartu profil per anggota (avatar, golongan darah
   menonjol di kanan, kotak BPJS, catatan hanya yang terisi; pantangan makan
   bernada peringatan). Form: kepala identitas anggota, golongan darah =
   tombol pilih, hitung karakter langsung, footer tetap terlihat saat scroll.
   Hanya token var(--...) (lihat docs/STYLE_GUIDE.md); light & dark otomatis.
=================================================== */
/* [20 Okt 2026] Kotak pencarian dipindah dari header ke baris sendiri: di tengah, dengan jarak ke ringkasan/daftar data. */
.kes-search-row { display: flex; justify-content: center; margin: var(--space-4) var(--space-16) var(--space-16); }
.kes-search-bar { position: relative; width: 100%; max-width: 420px; }
.kes-search-icon { position: absolute; left: var(--space-12); top: 50%; transform: translateY(-50%); display: flex; color: var(--ink-faint); pointer-events: none; }
.kes-search-input {
  width: 100%;
  padding: var(--space-8) var(--space-12) var(--space-8) var(--space-32);
  font: inherit; font-size: var(--text-sm); color: var(--ink);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius-pill);
}
.kes-search-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }

/* Ringkasan */
.kes-summary {
  margin: 0 var(--space-16) var(--space-12); padding: var(--space-14) var(--space-18);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius);
  display: flex; flex-direction: column; gap: var(--space-12);
  font-size: var(--text-xs); color: var(--ink-muted);
}
.kes-summary[hidden] { display: none; }
.kes-sum-stats { display: flex; gap: var(--space-8) var(--space-28); flex-wrap: wrap; }
.kes-sum-stat { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.kes-sum-stat b { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; color: var(--ink); }
.kes-sum-stat span { font-size: var(--text-xs); color: var(--ink-muted); }
.kes-missing { display: flex; align-items: flex-start; gap: var(--space-8) var(--space-12); flex-wrap: wrap; }
.kes-sum-stats + .kes-missing { padding-top: var(--space-12); border-top: 1px solid var(--rule); }
.kes-missing-label { flex: 0 0 auto; padding-top: var(--space-4); font-size: var(--text-xs); font-weight: 600; color: var(--ink-muted); }
.kes-chips { display: flex; flex-wrap: wrap; gap: var(--space-6); flex: 1 1 200px; min-width: 0; }
.kes-chip-add {
  display: inline-flex; align-items: center; gap: var(--space-4);
  font: inherit; font-size: var(--text-2xs); font-weight: 600; color: var(--ink-muted); cursor: pointer;
  padding: var(--space-4) var(--space-10); background: transparent;
  border: 1px dashed var(--ink-faint); border-radius: var(--radius-pill); max-width: 100%;
  transition: color .15s, border-color .15s, background .15s;
}
.kes-chip-add span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kes-chip-add:hover { color: var(--accent); border-color: var(--accent); background: var(--accent-lt); }
.kes-chip-add:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Saringan (menumpang .log-filter-chip) */
.kes-filters { display: flex; flex-wrap: wrap; gap: var(--space-6); margin: 0 var(--space-16) var(--space-12); }
.kes-filters[hidden] { display: none; }
.kes-chip-n { font-variant-numeric: tabular-nums; opacity: .7; margin-left: var(--space-2); }

.kes-list { padding: 0 var(--space-16) var(--space-20); }
.kes-empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-6);
  text-align: center; padding: var(--space-32) var(--space-16); color: var(--ink-muted);
}
.kes-empty-art { color: var(--ink-faint); margin-bottom: var(--space-8); }
.kes-empty-title { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; color: var(--ink); }
.kes-empty-text { font-size: var(--text-xs); max-width: 40ch; line-height: 1.5; }
.kes-empty .btn { margin-top: var(--space-10); }

/* Kartu per anggota */
/* 2 kolom (kiri anggota A, kanan anggota B, baris berikutnya C & D), di semua lebar layar. */
.kes-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-12); align-items: start; }
.kes-card { background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius); display: flex; flex-direction: column; min-width: 0; overflow: hidden; }
.kes-card.is-orphan { border-style: dashed; }
.kes-card-head { display: flex; align-items: center; gap: var(--space-10); padding: var(--space-14); }
.kes-avatar {
  position: relative; flex: 0 0 auto; width: 40px; height: 40px; overflow: hidden;
  display: grid; place-items: center; border-radius: var(--radius);
  background: var(--accent-lt); color: var(--accent);
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-sm);
}
.kes-avatar.is-deceased { background: var(--paper-warm); color: var(--ink-muted); }
.kes-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.kes-card-who { flex: 1 1 auto; min-width: 0; }
.kes-card-name { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); line-height: 1.25; color: var(--ink); overflow-wrap: anywhere; }
.kes-card-sub { margin-top: var(--space-2); font-size: var(--text-xs); color: var(--ink-muted); }
.kes-blood-badge {
  flex: 0 0 auto; min-width: 40px; height: 40px; padding: 0 var(--space-6);
  display: grid; place-items: center; border-radius: var(--radius);
  border: 1.5px solid var(--danger); background: var(--danger-lt); color: var(--danger);
  font-family: var(--font-display); font-weight: 700; font-size: var(--text-md);
}
.kes-blood-badge.is-empty { border: 1px dashed var(--rule); background: transparent; color: var(--ink-faint); font-weight: 400; }
.kes-icon-btn {
  flex: 0 0 auto; width: 32px; height: 32px; display: inline-grid; place-items: center; padding: 0;
  background: none; border: none; border-radius: var(--radius-pill); color: var(--ink-faint); cursor: pointer;
  transition: color .15s, background .15s;
}
.kes-icon-btn:hover { color: var(--ink); background: var(--paper-warm); }
.kes-icon-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.kes-bpjs {
  display: flex; align-items: center; gap: var(--space-10); margin: 0 var(--space-14) var(--space-14);
  padding: var(--space-10) var(--space-8) var(--space-10) var(--space-12);
  background: var(--paper-warm); border: 1px solid var(--rule); border-radius: var(--radius-sm);
}
.kes-bpjs-ic { flex: 0 0 auto; color: var(--accent); }
.kes-bpjs-main { flex: 1 1 auto; min-width: 0; }
.kes-bpjs-title { font-size: var(--text-2xs); font-weight: 600; color: var(--ink-muted); }
.kes-bpjs-num { margin-top: var(--space-2); font-family: var(--font-mono); font-size: var(--text-base); letter-spacing: .03em; font-variant-numeric: tabular-nums; color: var(--ink); overflow-wrap: anywhere; }
.kes-bpjs-num.is-masked { color: var(--ink-muted); }
.kes-bpjs-faskes { margin-top: var(--space-2); font-size: var(--text-xs); color: var(--ink-muted); overflow-wrap: anywhere; }
.kes-bpjs-actions { display: flex; flex: 0 0 auto; }

.kes-notes { display: flex; flex-direction: column; gap: var(--space-8); padding: 0 var(--space-14) var(--space-14); }
.kes-note { display: grid; grid-template-columns: 15px minmax(0, 1fr); gap: var(--space-8); }
.kes-note-ic { margin-top: var(--space-2); color: var(--ink-faint); }
.kes-note-label { font-size: var(--text-xs); font-weight: 600; color: var(--ink-muted); }
.kes-note-text { margin-top: var(--space-2); font-size: var(--text-sm); line-height: 1.5; color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; }
.kes-note-text.is-clamped { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.kes-more { margin-top: var(--space-2); padding: 0; font: inherit; font-size: var(--text-2xs); font-weight: 600; color: var(--accent); background: none; border: none; cursor: pointer; }
.kes-more:hover { text-decoration: underline; }
.kes-more:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-xs); }
.kes-note.is-warn { padding: var(--space-8) var(--space-10); background: var(--warning-lt); border-radius: var(--radius-sm); }
.kes-note.is-warn .kes-note-ic { color: var(--warning); }

/* Form: kepala tetap, badan scroll, footer tetap terlihat */
.kes-form-content { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.kes-form-content > .modal-header { margin: 0; padding: var(--space-16) var(--space-20); }
.kes-form { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.kes-form-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: var(--space-16) var(--space-20) var(--space-8); }
.kes-form-content .modal-footer { margin-top: 0; padding: var(--space-12) var(--space-20); }

.kes-form-who { display: flex; align-items: center; gap: var(--space-12); margin-bottom: var(--space-18); padding: var(--space-12) var(--space-14); background: var(--paper-warm); border: 1px solid var(--rule); border-radius: var(--radius); }
.kes-form-who .kes-avatar { width: 44px; height: 44px; }
.kes-form-who-text { flex: 1 1 auto; min-width: 0; }
.kes-form-who-label { display: block; margin-bottom: var(--space-4); font-size: var(--text-2xs); font-weight: 600; color: var(--ink-muted); }
.kes-form-who-name { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); color: var(--ink); overflow-wrap: anywhere; }
.kes-form-who-age { margin-top: var(--space-4); font-size: var(--text-xs); color: var(--ink-muted); }
.kes-form-who.is-locked .kes-form-who-label,
.kes-form-who.is-locked #kesMember { display: none; }
.kes-form-who:not(.is-locked) .kes-form-who-name { display: none; }

.kes-form-sec { margin-bottom: var(--space-18); }
.kes-form-sec-title { display: flex; align-items: center; gap: var(--space-6); margin-bottom: var(--space-8); font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.kes-form-sec-title svg { color: var(--accent); flex: 0 0 auto; }
.kes-form-sec-hint { margin-left: auto; font-size: var(--text-2xs); font-weight: 400; color: var(--ink-faint); }
.kes-form .form-group { margin-bottom: var(--space-10); }
.kes-form .form-group:last-child { margin-bottom: 0; }
.kes-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-8); }
.kes-label-row em { font-style: normal; font-weight: 400; color: var(--ink-faint); }
.kes-count { flex: 0 0 auto; font-size: var(--text-2xs); font-weight: 400; font-variant-numeric: tabular-nums; color: var(--ink-faint); }
.kes-count.is-ok { color: var(--success); }
.kes-count.is-bad { color: var(--danger); }
.kes-input-num { font-variant-numeric: tabular-nums; letter-spacing: .04em; }
.kes-form textarea.form-control { min-height: 56px; resize: vertical; line-height: 1.45; }

.kes-blood-pick { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-8); }
/* Tombol pilih (golongan darah, status & tingkat sakit): teks di tengah, tinggi seragam, mudah diketuk. */
.kes-blood-opt {
  display: flex; align-items: center; justify-content: center; text-align: center;
  min-height: 44px; padding: var(--space-8) var(--space-6); line-height: 1.2;
  font: inherit; font-family: var(--font-display); font-weight: 600; font-size: var(--text-base); letter-spacing: .01em;
  color: var(--ink); background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius-sm); cursor: pointer;
  transition: border-color .15s, background .15s, color .15s, box-shadow .15s;
}
.kes-blood-opt:hover:not(:disabled) { border-color: var(--ink-faint); background: var(--paper-warm); }
.kes-blood-opt[aria-checked="true"] { background: var(--danger-lt); border-color: var(--danger); color: var(--danger); box-shadow: 0 0 0 1px var(--danger) inset; }
.kes-blood-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.kes-blood-opt:disabled { opacity: .5; cursor: default; }
#kesFormStatus:not(.is-error) { color: var(--ink-muted); }

@media (max-width: 760px) {
  .kes-summary { padding: var(--space-12) var(--space-14); }
  .kes-sum-stats { gap: var(--space-8) var(--space-20); }
  .kes-add-label { display: none; }
  .kes-search-row { margin-left: var(--space-12); margin-right: var(--space-12); }
  .kes-search-bar { max-width: none; }
}
/* [OPTIMASI HAPE 22 Okt 2026] Layar hape (<=600px): kartu jadi 1 kolom penuh.
   Sebelumnya tetap 2 kolom (+ isi dipadatkan) sehingga tiap kartu cuma ~175px:
   nama, nomor BPJS, catatan, dan timeline sakit terpotong/menumpuk. Di sini
   kartu selebar layar, isi kembali lega. Mau balik ke 2 kolom di hape? Ganti
   `grid-template-columns` di .kes-grid di bawah jadi repeat(2, minmax(0, 1fr)).
   Desktop/tablet (>600px) tidak berubah. */
@media (max-width: 600px) {
  .kes-list { padding-left: var(--space-12); padding-right: var(--space-12); padding-bottom: var(--space-32); }
  .kes-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-12); }

  /* Cari + ringkasan + saringan: lebar penuh, jarak seragam 12px */
  .kes-search-input { font-size: 16px; padding-top: var(--space-10); padding-bottom: var(--space-10); } /* 16px = iOS tidak zoom saat fokus */
  .kes-summary { margin-left: var(--space-12); margin-right: var(--space-12); }
  .kes-sum-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-10) var(--space-16); }
  .kes-missing { flex-direction: column; gap: var(--space-6); }
  .kes-chips { flex: 1 1 auto; width: 100%; }
  .kes-chip-add { min-height: 32px; }

  /* Saringan: satu baris yang bisa digeser, bukan menumpuk 2-3 baris */
  .kes-filters {
    flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
    margin-left: 0; margin-right: 0; padding: 0 var(--space-12) var(--space-4);
    scrollbar-width: none; scroll-padding: 0 var(--space-12);
  }
  .kes-filters::-webkit-scrollbar { display: none; }
  /* [FIX CHIP TERPOTONG] .modal-content fullview di hape = flex column setinggi layar.
     Elemen ber-overflow (di sini .kes-filters, overflow-x:auto) boleh menyusut sampai
     tinggi 0 di flex column, jadi baris chip kepotong setengah. flex-shrink:0 menahannya. */
  .kes-search-row, .kes-summary, .kes-filters, .kes-list { flex-shrink: 0; }
  .kes-filters .log-filter-chip { flex: 0 0 auto; padding: var(--space-6) var(--space-12); }

  /* Kartu */
  .kes-card-head { flex-wrap: nowrap; gap: var(--space-10); padding: var(--space-12); }
  .kes-card-head .kes-avatar { width: 40px; height: 40px; font-size: var(--text-sm); }
  .kes-card-head .kes-card-who { flex: 1 1 auto; min-width: 0; }
  .kes-card-name { font-size: var(--text-md); overflow-wrap: anywhere; }
  .kes-card-head .kes-blood-badge { min-width: 40px; height: 40px; font-size: var(--text-md); }
  .kes-icon-btn { width: 38px; height: 38px; } /* area sentuh lebih besar */
  .kes-bpjs { flex-wrap: nowrap; margin: 0 var(--space-12) var(--space-12); padding: var(--space-10) var(--space-6) var(--space-10) var(--space-12); gap: var(--space-8); }
  .kes-bpjs-num { font-size: var(--text-base); letter-spacing: .02em; }
  .kes-notes { padding: 0 var(--space-12) var(--space-12); }
  .kes-more { padding: var(--space-4) 0; }

  /* Catatan sakit di dalam kartu */
  .sakit-section { padding: var(--space-12); }
  .sakit-sec-head { flex-wrap: nowrap; }
  .sakit-add-btn { min-height: 32px; padding: var(--space-4) var(--space-12); }
  .sakit-timeline { margin-left: var(--space-4); padding-left: var(--space-12); }
  .sakit-entry::before { left: calc(-1 * var(--space-12) - 7px); }
  .sakit-entry-head { padding: var(--space-10) var(--space-12); }
  .sakit-fields { padding: 0 var(--space-12) var(--space-12); }
  .sakit-done-btn { min-height: 32px; }

  /* Form (isi data / catat sakit): input 16px supaya tidak di-zoom iOS, tombol bawah lebar rata */
  .kes-form .form-control,
  .kes-form select.form-control,
  .kes-form textarea.form-control { font-size: 16px; }
  .kes-blood-opt { min-height: 42px; }
  .kes-form-content .modal-footer { flex-wrap: wrap; gap: var(--space-8); }
  .kes-form-content .modal-footer .btn { flex: 1 1 0; min-width: 0; }
  .kes-form-content .modal-footer #kesDeleteBtn,
  .kes-form-content .modal-footer #sakitDeleteBtn { flex: 1 1 100%; margin-right: 0 !important; order: 3; }
}
@media (max-width: 480px) {
  .kes-form-content > .modal-header,
  .kes-form-body,
  .kes-form-content .modal-footer { padding-left: var(--space-16); padding-right: var(--space-16); }
  .kes-form-sec-hint { display: none; }
}


/* ======================================================
   CATATAN SAKIT -- rekam medis keluarga (js/catatan-sakit.js)
   [20 Okt 2026] DIGABUNG ke kartu profil Kesehatan Keluarga (bukan tab lagi):
   tiap kartu anggota punya bagian "Catatan sakit" -- 3 catatan terbaru (timeline),
   "Lihat semua", dan panel Ringkasan & saran AI. Memakai ulang .kes-card /
   .kes-icon-btn / .kes-more dan gaya form kes-form-*. Hanya token var(--...);
   light & dark otomatis.
=================================================== */
.kes-empty-actions { display: flex; flex-wrap: wrap; gap: var(--space-8); justify-content: center; }

.sakit-section { display: flex; flex-direction: column; gap: var(--space-10); padding: var(--space-14); border-top: 1px solid var(--rule); }
.sakit-sec-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-10); flex-wrap: wrap; }
.sakit-sec-title { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-6); min-width: 0; font-family: var(--font-display); font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.sakit-sec-title > svg { color: var(--accent); flex: 0 0 auto; }
.sakit-sec-count { font-family: var(--font-body, inherit); font-size: var(--text-2xs); font-weight: 600; color: var(--ink-muted); }
.sakit-add-btn { padding: var(--space-4) var(--space-10); font-size: var(--text-2xs); white-space: nowrap; }
.sakit-sec-empty { font-size: var(--text-xs); color: var(--ink-faint); }
.sakit-sec-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4) var(--space-14); }
.sakit-section .sakit-ai { margin: 0; }

/* Kartu ringkasan & saran AI */
.sakit-ai {
  margin-bottom: var(--space-16); padding: var(--space-14) var(--space-16);
  background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius);
  display: flex; flex-direction: column; gap: var(--space-12);
}
.sakit-ai-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-10); flex-wrap: wrap; }
.sakit-ai-title { display: flex; align-items: center; gap: var(--space-8); font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); color: var(--ink); }
.sakit-ai-title svg { color: var(--accent); }
.sakit-ai-btn { white-space: nowrap; }
.sakit-ai-hint, .sakit-ai-status { font-size: var(--text-xs); line-height: 1.5; color: var(--ink-muted); }
.sakit-ai-error { padding: var(--space-8) var(--space-10); font-size: var(--text-xs); line-height: 1.5; color: var(--danger); background: var(--danger-lt); border-radius: var(--radius-xs); overflow-wrap: anywhere; }
.sakit-ai-stale { display: flex; align-items: flex-start; gap: var(--space-8); padding: var(--space-8) var(--space-10); font-size: var(--text-xs); line-height: 1.5; color: var(--ink); background: var(--info-lt); border-radius: var(--radius-xs); }
.sakit-ai-stale svg { flex: 0 0 auto; margin-top: var(--space-2); color: var(--info); }
.sakit-ai-sec h5 { display: flex; align-items: center; gap: var(--space-6); margin: 0 0 var(--space-6); font-size: var(--text-xs); font-weight: 600; color: var(--ink-muted); }
.sakit-ai-sec h5 svg { color: var(--accent); flex: 0 0 auto; }
.sakit-ai-sec p { margin: 0; font-size: var(--text-sm); line-height: 1.6; color: var(--ink); overflow-wrap: anywhere; }
.sakit-ai-sec ul { margin: 0; padding-left: var(--space-18); display: flex; flex-direction: column; gap: var(--space-4); }
.sakit-ai-sec li { font-size: var(--text-sm); line-height: 1.55; color: var(--ink); overflow-wrap: anywhere; }
.sakit-ai-sec.is-warn { padding: var(--space-10) var(--space-12); background: var(--warning-lt); border-radius: var(--radius-xs); }
.sakit-ai-sec.is-warn h5, .sakit-ai-sec.is-warn h5 svg { color: var(--warning); }
.sakit-ai-time { font-size: var(--text-2xs); color: var(--ink-faint); }
.sakit-ai-disc { padding-top: var(--space-10); border-top: 1px solid var(--rule); font-size: var(--text-2xs); line-height: 1.5; color: var(--ink-faint); }

/* Timeline entri */
.sakit-timeline { display: flex; flex-direction: column; gap: var(--space-10); margin-left: var(--space-5); padding-left: var(--space-16); border-left: 2px solid var(--rule); }
.sakit-entry { position: relative; min-width: 0; background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius); }
.sakit-entry::before {
  content: ""; position: absolute; left: calc(-1 * var(--space-16) - 7px); top: var(--space-16);
  width: 10px; height: 10px; border-radius: 50%; background: var(--ink-faint); border: 2px solid var(--paper-warm);
}
.sakit-entry.is-active { border-color: color-mix(in srgb, var(--warning) 55%, var(--rule)); }
.sakit-entry.is-active::before { background: var(--warning); }
.sakit-entry-head { display: flex; align-items: flex-start; gap: var(--space-10); padding: var(--space-12) var(--space-14); }
.sakit-entry-main { flex: 1 1 auto; min-width: 0; }
.sakit-entry-date { font-size: var(--text-2xs); font-weight: 600; color: var(--ink-muted); }
.sakit-entry-title { margin: var(--space-2) 0 var(--space-6); font-family: var(--font-display); font-size: var(--text-md); font-weight: 600; line-height: 1.3; color: var(--ink); overflow-wrap: anywhere; }
.sakit-entry-meta { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.sakit-entry-actions { display: flex; align-items: center; gap: var(--space-4); flex: 0 0 auto; }
.sakit-done-btn { padding: var(--space-4) var(--space-10); font-size: var(--text-2xs); white-space: nowrap; }
.sakit-chip { padding: var(--space-2) var(--space-8); font-size: var(--text-2xs); font-weight: 600; line-height: 1.5; border-radius: var(--radius-pill); background: var(--paper-warm); color: var(--ink-muted); }
.sakit-chip.is-member { background: var(--accent-lt); color: var(--accent); }
.sakit-chip.is-active { background: var(--warning-lt); color: var(--warning); }
.sakit-chip.is-done { background: var(--success-lt); color: var(--success); }
.sakit-chip.sev-ringan { background: var(--info-lt); color: var(--info); }
.sakit-chip.sev-sedang { background: var(--warning-lt); color: var(--warning); }
.sakit-chip.sev-berat { background: var(--danger-lt); color: var(--danger); }
.sakit-fields { margin: 0; padding: 0 var(--space-14) var(--space-14); display: flex; flex-direction: column; gap: var(--space-8); }
.sakit-field dt { font-size: var(--text-2xs); font-weight: 600; color: var(--ink-muted); }
.sakit-field dd { margin: var(--space-2) 0 0; font-size: var(--text-sm); line-height: 1.5; color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; }

/* Form: tombol pilih status & tingkat (menumpang .kes-blood-opt; terpilih = warna aksen, bukan merah) */
.sakit-seg { display: grid; gap: var(--space-8); }
.sakit-seg .kes-blood-opt { font-size: var(--text-sm); }
.sakit-seg .kes-blood-opt[aria-checked="true"] { background: var(--accent-lt); border-color: var(--accent); color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.sakit-seg-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sakit-seg-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#sakitFormStatus:not(.is-error) { color: var(--ink-muted); }
.kes-form-who.is-locked .kes-form-who-label,
.kes-form-who.is-locked #sakitMember { display: none; }
.kes-form-who:not(.is-locked) #sakitMemberName { display: none; }
#sakitForm label em { font-style: normal; font-weight: 400; color: var(--ink-faint); }
#sakitForm textarea.form-control { min-height: 56px; resize: vertical; line-height: 1.45; }

@media (max-width: 480px) {
  .sakit-ai { padding: var(--space-12); }
  .sakit-entry-head { flex-wrap: wrap; }
  .sakit-entry-actions { width: 100%; justify-content: flex-end; }
  .sakit-section { padding: var(--space-12); }
}

/* ======================================================
   DARK MODE — GAYA HANDBOOK (18 Okt 2026)
   Lapisan bentuk/tipografi di atas token dark di atas. Hanya aktif di
   [data-theme="dark"]; mode terang TIDAK tersentuh. Ciri: kisi tipis di
   latar, label/badge monospace, badge outline transparan, aksen neon
   tunggal dengan glow tipis, menu aktif bergaris kiri.
====================================================== */
[data-theme="dark"] body {
  background-color: var(--paper-warm);
  background-image:
    linear-gradient(rgba(241,245,243,0.028) 1px, transparent 1px),
    linear-gradient(90deg, rgba(241,245,243,0.028) 1px, transparent 1px);
  background-size: 32px 32px;
}
[data-theme="dark"] ::selection { background: color-mix(in srgb, var(--accent) 35%, transparent); color: var(--ink); }
[data-theme="dark"] :focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }

/* Judul: putih tebal, rapat */
[data-theme="dark"] h1,
[data-theme="dark"] h2,
[data-theme="dark"] h3,
[data-theme="dark"] .modal-header h3 {
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--ink);
}

/* Label kecil: monospace + letter-spacing lebar */
[data-theme="dark"] th,
[data-theme="dark"] .stat-label,
[data-theme="dark"] .balance-hero-label {
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 500;
}
[data-theme="dark"] .form-group label {
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
}
[data-theme="dark"] th { border-bottom: 1px solid var(--rule); color: var(--ink-faint); }

/* Badge: outline transparan, monospace */
[data-theme="dark"] .type-badge,
[data-theme="dark"] .category-badge {
  font-family: var(--font-mono);
  font-weight: 500;
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--ink-muted);
}
[data-theme="dark"] .badge-inc {
  background: transparent;
  color: var(--success);
  border-color: color-mix(in srgb, var(--success) 45%, transparent);
}
[data-theme="dark"] .badge-exp {
  background: transparent;
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 45%, transparent);
}

/* Kartu: border tipis, hover = border neon + glow lembut */
[data-theme="dark"] .stat-card,
[data-theme="dark"] .table-container,
[data-theme="dark"] .modal-content {
  border-color: var(--rule);
}
[data-theme="dark"] .stat-card:hover {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--rule));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 18%, transparent), 0 0 22px var(--hb-glow);
}
[data-theme="dark"] .balance-hero {
  border-color: color-mix(in srgb, var(--accent) 30%, var(--rule));
  box-shadow: 0 0 28px color-mix(in srgb, var(--accent) 10%, transparent);
}
/* Angka saldo: glow tipis dari warna teksnya sendiri (aman utk saldo negatif) */
[data-theme="dark"] .balance-hero-value {
  text-shadow: 0 0 22px color-mix(in srgb, currentColor 30%, transparent);
}
[data-theme="dark"] .stat-card.income .stat-value { color: var(--success); }
[data-theme="dark"] .stat-card.expense .stat-value { color: var(--danger); }

/* Tombol */
[data-theme="dark"] .btn-primary,
[data-theme="dark"] .manage-books-btn {
  font-weight: 700;
}
[data-theme="dark"] .btn-primary:hover:not(:disabled),
[data-theme="dark"] .manage-books-btn:hover:not(:disabled) {
  box-shadow: 0 0 18px var(--hb-glow);
}
[data-theme="dark"] .btn:hover:not(:disabled):not(.btn-primary),
[data-theme="dark"] .btn-secondary:hover:not(:disabled) {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--rule));
}

/* Input & fokus */
[data-theme="dark"] .form-control,
[data-theme="dark"] .search-input { background-color: var(--paper-warm); }
[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .search-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);
  outline: none;
}

/* Chip filter & paginasi aktif: kuning (penanda item aktif) */
[data-theme="dark"] .filter-btn.active,
[data-theme="dark"] .page-btn.active {
  background: color-mix(in srgb, var(--hb-yellow) 10%, var(--paper));
  color: var(--hb-yellow);
  border-color: color-mix(in srgb, var(--hb-yellow) 60%, transparent);
}

/* Kalender Pendidikan: hari ini / sel terpilih = kotak kuning */
[data-theme="dark"] .smedia-edu-c.is-today { outline-color: var(--hb-yellow); color: var(--hb-yellow); }
[data-theme="dark"] .smedia-edu-c.is-sel { outline-color: var(--hb-yellow); }
[data-theme="dark"] .smedia-edu-c.is-editable:hover:not(.is-sel):not(.is-today) { outline-color: var(--accent); }

/* Kata kunci judul berwarna (gaya "HASH MAP"): span .hb-kw disisipkan
   otomatis oleh js/app.js ke kata terakhir judul modal/panel (>= 2 kata).
   Di mode terang span ini tidak diberi gaya, jadi tampil biasa. */
[data-theme="dark"] .hb-kw {
  color: var(--accent);
  text-shadow: 0 0 18px color-mix(in srgb, var(--accent) 35%, transparent);
}

/* Scrollbar tipis gelap */
[data-theme="dark"] * { scrollbar-color: var(--rule) transparent; }

/* [LENCANA GENDER TEKS] Mode gelap (gaya Handbook): lencana L/P diberi
   glow tipis seirama warna gendernya. */
[data-theme="dark"] .silsilah-node-l .silsilah-gender-badge { filter: drop-shadow(0 0 3px color-mix(in srgb, var(--accent) 70%, transparent)); }
[data-theme="dark"] .silsilah-node-p .silsilah-gender-badge { filter: drop-shadow(0 0 3px color-mix(in srgb, var(--warning) 70%, transparent)); }

/* ======================================================
   [REDESIGN TOTAL KOTAK ANGGOTA -- KARTU JENDELA] (18 Okt 2026)
   Struktur digambar di window.renderFamilyTree (js/silsilah.js):
   header (lencana teks gender kiri; titik dekoratif / label MENANTU-
   PASANGAN kanan) + isi (avatar persegi membulat, nama, tahun, alamat).
   Warna generasi -> header + garis tepi; isi kotak hampir netral.
   Gender -> lencana header + ring avatar (L = --accent, P = --warning).
   Aturan lama strip kiri (.silsilah-node-accent-bar) tidak dipakai lagi.
====================================================== */
.silsilah-node-l { --gc: var(--accent); }
.silsilah-node-p { --gc: var(--warning); }
.silsilah-node-u { --gc: var(--ink-faint); }

.silsilah-node rect.silsilah-node-box { fill: var(--paper); stroke-width: 1; filter: none; }
.silsilah-node[class*="silsilah-gen-"] rect.silsilah-node-box,
[data-theme="dark"] .silsilah-node[class*="silsilah-gen-"] rect.silsilah-node-box,
.silsilah-node-inlaw[class*="silsilah-gen-"] rect.silsilah-node-box,
[data-theme="dark"] .silsilah-node-inlaw[class*="silsilah-gen-"] rect.silsilah-node-box {
  fill: color-mix(in srgb, var(--gen-color) 5%, var(--paper));
  stroke: color-mix(in srgb, var(--gen-color) 50%, var(--rule));
}
.silsilah-node-dead[class*="silsilah-gen-"] rect.silsilah-node-box,
[data-theme="dark"] .silsilah-node-dead[class*="silsilah-gen-"] rect.silsilah-node-box {
  fill: color-mix(in srgb, var(--gen-color) 3%, var(--paper-warm));
}

/* Header */
.silsilah-node-head { fill: var(--rule); }
.silsilah-node[class*="silsilah-gen-"] .silsilah-node-head {
  fill: color-mix(in srgb, var(--gen-color) 20%, var(--paper));
}
.silsilah-node-dead[class*="silsilah-gen-"] .silsilah-node-head {
  fill: color-mix(in srgb, var(--gen-color) 9%, var(--paper-warm));
}
.silsilah-node-headline { stroke: color-mix(in srgb, var(--gen-color, var(--ink-faint)) 40%, var(--rule)); stroke-width: 1; }
.silsilah-node-dot { fill: var(--ink-faint); opacity: 0.55; }

/* Lencana teks gender di header */
.silsilah-gchip-bg {
  fill: color-mix(in srgb, var(--gc) 14%, var(--paper));
  stroke: color-mix(in srgb, var(--gc) 65%, transparent);
  stroke-width: 1;
}
.silsilah-gchip-text {
  fill: var(--gc);
  font-family: var(--font-mono);
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  pointer-events: none;
  user-select: none;
}
:root:not([data-theme="dark"]) .silsilah-node-p .silsilah-gchip-text { fill: color-mix(in srgb, var(--warning) 55%, #000); }
.silsilah-node-dead .silsilah-gchip-bg,
.silsilah-node-dead .silsilah-gchip-text { opacity: 0.6; }

/* Label MENANTU / PASANGAN (menggantikan pil melayang di tepi atas) */
.silsilah-node-tag-text {
  font-family: var(--font-mono);
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

/* Avatar persegi membulat */
.silsilah-avatar-ring { stroke-width: 1.6; }
.silsilah-node-dead .silsilah-avatar-ring { opacity: 0.55; }
.silsilah-node-dead image { opacity: 0.75; }

/* Teks isi: tahun & alamat monospace */
.silsilah-node-years { font-family: var(--font-mono); font-size: 10.5px; fill: var(--ink-muted); }
.silsilah-node-address { font-family: var(--font-mono); font-size: 9.5px; }

/* Mode gelap (gaya Handbook): hover = glow warna gender */
[data-theme="dark"] .silsilah-node-l:hover rect.silsilah-node-box,
[data-theme="dark"] .silsilah-node-l:focus rect.silsilah-node-box { filter: drop-shadow(0 0 8px color-mix(in srgb, var(--accent) 40%, transparent)); }
[data-theme="dark"] .silsilah-node-p:hover rect.silsilah-node-box,
[data-theme="dark"] .silsilah-node-p:focus rect.silsilah-node-box { filter: drop-shadow(0 0 8px color-mix(in srgb, var(--warning) 40%, transparent)); }
[data-theme="dark"] .silsilah-node-u:hover rect.silsilah-node-box,
[data-theme="dark"] .silsilah-node-u:focus rect.silsilah-node-box { filter: drop-shadow(0 0 8px color-mix(in srgb, var(--ink-faint) 40%, transparent)); }

/* Legenda gender: lencana teks yang sama dengan header kotak */
.silsilah-legend-gchip {
  display: inline-block;
  padding: 1px 7px;
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1.5;
  color: var(--gc);
  background: color-mix(in srgb, var(--gc) 14%, var(--paper));
  border: 1px solid color-mix(in srgb, var(--gc) 65%, transparent);
}
:root:not([data-theme="dark"]) .silsilah-legend-gchip.silsilah-node-p { color: color-mix(in srgb, var(--warning) 55%, #000); }


/* ======================================================
   [SETELAN SERAGAM] Perapian tampilan menu Setelan -- HANYA CSS (+ buang
   inline style di 3 judul panel). Markup, id, handler & JS tidak diubah.
   Aturan baku tiap baris/panel accordion:
     [chevron]  Judul  [badge status]  ............  [tombol aksi]
   - Jarak antar elemen header diatur margin (bukan gap) supaya kata
     terakhir judul yang dibungkus <span class="hb-kw"> (js/app.js) tidak
     terpisah jauh dari kata sebelumnya ("Database  Cloud").
   - Tinggi semua baris header sama; badge selalu tepat di kanan judul;
     tombol aksi (mis. Refresh) selalu di ujung kanan.
====================================================== */
#setelanModal .setelan-tab-content { gap: var(--space-8); }
#setelanModal .data-management-panel.setelan-acc {
  border-radius: var(--radius-md, var(--radius-sm));
  padding: 0 var(--space-16);
}
#setelanModal .setelan-acc-head {
  gap: 0;
  min-height: 44px;
  padding: var(--space-6) 0;
  box-sizing: border-box;
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.3;
  text-transform: none;
}
#setelanModal .setelan-acc-head::before {
  width: 16px; height: 16px;
  margin-right: var(--space-8);
}
/* Kata terakhir judul (span.hb-kw) menyambung normal dengan kata sebelumnya */
#setelanModal .setelan-acc-head > .hb-kw { margin-left: .28em; }
/* Badge status: tepat di kanan judul, ukuran & bentuk sama */
#setelanModal .setelan-acc-head > .setelan-badge,
#setelanModal .setelan-acc-head > span > .setelan-badge {
  margin-left: var(--space-10);
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-8);
  font-size: var(--text-2xs);
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  border-radius: 999px;
}
#setelanModal .setelan-badge:empty { display: none !important; }
/* Varian yang dipakai JS (badge-ok / badge-warn) -- sebelumnya tak punya gaya */
#setelanModal .setelan-badge.badge-ok   { background: var(--success-lt); color: var(--success); }
#setelanModal .setelan-badge.badge-warn { background: var(--warning-lt); color: var(--warning); }
/* Tombol aksi di header (Refresh, dll.) selalu di ujung kanan */
#setelanModal .setelan-acc-head > button,
#setelanModal .setelan-acc-head > .btn {
  margin-left: auto;
  flex: 0 0 auto;
  white-space: nowrap;
}
/* Zona bahaya: judul merah + garis tepi samar, sisanya sama persis */
#setelanModal .setelan-acc:has(> .setelan-title--red) {
  border-color: color-mix(in srgb, var(--danger) 28%, var(--rule));
}

/* ── Isi panel: ritme & ukuran kontrol seragam ── */
#setelanModal .setelan-acc:not(.is-collapsed) > .setelan-acc-head { margin-bottom: var(--space-12); }
#setelanModal .setelan-acc:not(.is-collapsed) { padding-bottom: var(--space-14); }
#setelanModal .setelan-acc .setelan-desc {
  font-size: var(--text-xs);
  line-height: 1.6;
  color: var(--ink-muted);
  margin-bottom: var(--space-12);
}
#setelanModal .setelan-acc .form-group { margin-bottom: var(--space-12); }
#setelanModal .setelan-acc .form-group label,
#setelanModal .setelan-acc .setelan-label-strong {
  font-size: var(--text-xs);
  font-weight: 600;
  margin-bottom: var(--space-4);
}
#setelanModal .setelan-acc .form-control {
  width: 100%;
  box-sizing: border-box;
  min-height: 38px;
  padding: var(--space-6) var(--space-12);
  font-size: var(--text-sm);
}
#setelanModal .setelan-acc .btn:not(.btn-mini) {
  min-height: 38px;
  padding: var(--space-6) var(--space-14);
  font-size: var(--text-xs);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  box-sizing: border-box;
}
#setelanModal .setelan-acc .setelan-actions-row,
#setelanModal .setelan-acc .cloud-connect-row,
#setelanModal .setelan-acc .setelan-device-row { gap: var(--space-8); margin-top: var(--space-4); }
#setelanModal .setelan-acc .setelan-actions-row .btn { flex: 1 1 0; }
/* Tombol Refresh di header sedikit lebih kecil dari tombol isi */
#setelanModal .setelan-acc > .setelan-acc-head > .btn {
  min-height: 28px;
  padding: var(--space-2) var(--space-12);
  font-size: var(--text-2xs);
  border-radius: 999px;
}
/* Teks status (hasil tes/simpan) tidak menyisakan celah kosong saat kosong */
#setelanModal .setelan-acc [id$="Status"]:empty,
#setelanModal .setelan-acc [id$="TestStatus"]:empty { min-height: 0 !important; margin-bottom: 0 !important; }
/* Pembagi & blok collapse dalam panel */
#setelanModal .setelan-acc .setelan-divider { margin: var(--space-14) 0; }
#setelanModal .setelan-acc .setelan-collapse { margin: 0 0 var(--space-12); }

/* ── Panel Akun: daftar akun & tombolnya sejajar dengan panel lain ── */
#setelanModal .setelan-acc .acc-modal-item {
  min-height: 44px;
  box-sizing: border-box;
  padding: var(--space-6) var(--space-14);
  margin-bottom: var(--space-6);
  border-width: 1px;
}
#setelanModal .setelan-acc .acc-modal-item-name { font-size: var(--text-sm); font-weight: 600; }
#setelanModal .setelan-acc .acc-modal-item-badge { border-radius: 999px; padding: 2px var(--space-8); font-weight: 600; }
#setelanModal .setelan-acc .acc-modal-list { margin-bottom: var(--space-12); }


/* ======================================================
   [MENU MINGGUAN ROUNDED] Halaman Daftar Menu (js/menu-plan.js) tadinya
   memakai --radius-xs (1px) di semua elemen sehingga terlihat kotak,
   beda dari menu lain. Disamakan dengan pola menu lain: kartu besar =
   var(--radius), item/tombol = var(--radius-sm), tab/chip/badge = pill.
   Hanya CSS; markup & JS tidak diubah.
====================================================== */
/* Kartu besar */
.mplan-gizi-card.mplan-gizi-top,
.mplan-estimate-card,
.mplan-day-card { border-radius: var(--radius); }
/* Item & blok di dalam kartu */
.mplan-meal,
.mplan-meal-group-header,
.mplan-estimate-row,
.mplan-estimate-group-header,
.mplan-gizi-insight,
.mplan-copy-day-item { border-radius: var(--radius-sm); }
/* Tombol */
.mplan-add-meal-btn,
.mplan-add-bahan-btn,
.mplan-copy-day-btn,
.mplan-copy-week-btn { border-radius: var(--radius-sm); }
/* Tab minggu, chip, badge, penanda: kapsul */
.mplan-week-tab,
.mplan-gizi-chip,
.mplan-today-badge { border-radius: var(--radius-pill); }
.mplan-week-tab-dot { border-radius: 50%; }


/* [CSP] dipindah dari <style> inline js/report.js (Preview Nota) */
      #notaPreviewModal .nota-pv-box { max-width:480px; max-height:100%; display:flex; flex-direction:column; overflow:hidden; }
      #notaPreviewModal .nota-pv-scroll { flex:1 1 auto; min-height:0; overflow:auto; -webkit-overflow-scrolling:touch; background:var(--paper-warm); border:1px solid var(--rule); border-radius:var(--radius-sm); padding:12px; text-align:center; }
      #notaPreviewModal .nota-pv-scroll img { display:inline-block; max-width:100%; height:auto; box-shadow:0 1px 6px rgba(31,25,17,.18); }
      @media (max-width: 480px) {
        #notaPreviewModal { padding:10px; }
        #notaPreviewModal .nota-pv-box { padding:14px; }
        #notaPreviewModal .modal-header { margin-bottom:10px; padding-bottom:10px; }
        #notaPreviewModal .modal-footer { margin-top:12px; padding-top:12px; }
        #notaPreviewModal .nota-pv-scroll { padding:8px; }
      }
      @media (max-height: 500px) {
        #notaPreviewModal { padding:8px; }
        #notaPreviewModal .nota-pv-box { padding:10px 14px; }
        #notaPreviewModal .modal-header { margin-bottom:6px; padding-bottom:6px; }
        #notaPreviewModal .modal-footer { margin-top:8px; padding-top:8px; }
      }

/* [RESTYLE PILIHAN AKSI, 20 Okt 2026] Action-sheet menu transaksi
   (#actionMenuModal: Lihat Nota / Ubah Data / Hapus Transaksi). Dulu 3 teks
   polos dgn inline style tanpa hover/fokus/ikon. Sekarang tiap aksi = baris
   penuh dgn ikon di kotak kecil + label, area tap >= 44px, hover/fokus jelas,
   dan aksi destruktif dipisah garis tipis + berwarna --danger supaya tidak
   ketekan tak sengaja. Warna semua dari token, jadi otomatis ikut tema
   terang/gelap. ID tombol & logika JS (js/render.js) TIDAK berubah. */
.action-sheet { padding: var(--space-16); }
.action-sheet-header { margin-bottom: var(--space-8); padding-bottom: var(--space-10); }
.action-sheet-header h3 { font-size: var(--text-base); }
.action-sheet-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.action-sheet-item {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  width: 100%;
  min-height: 44px;
  padding: var(--space-6) var(--space-8);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-base);
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
.action-sheet-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  background: var(--paper-warm);
  border: 1px solid var(--rule);
  color: var(--ink-muted);
  font-size: 15px;
  transition: background .15s, border-color .15s, color .15s;
}
.action-sheet-label { min-width: 0; overflow-wrap: anywhere; }
.action-sheet-item:hover,
.action-sheet-item:focus-visible { background: var(--paper-warm); border-color: var(--rule); }
.action-sheet-item:hover .action-sheet-icon,
.action-sheet-item:focus-visible .action-sheet-icon {
  background: var(--accent-lt);
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  color: var(--accent);
}
.action-sheet-item:active { background: var(--rule); }
.action-sheet-sep { height: 1px; margin: var(--space-6) var(--space-8); background: var(--rule); }
.action-sheet-item.is-danger { color: var(--danger); }
.action-sheet-item.is-danger .action-sheet-icon {
  background: var(--danger-lt);
  border-color: color-mix(in srgb, var(--danger) 30%, transparent);
  color: var(--danger);
}
.action-sheet-item.is-danger:hover,
.action-sheet-item.is-danger:focus-visible {
  background: var(--danger-lt);
  border-color: color-mix(in srgb, var(--danger) 35%, transparent);
}
.action-sheet-item.is-danger:hover .action-sheet-icon,
.action-sheet-item.is-danger:focus-visible .action-sheet-icon {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--paper);
}


/* ── Kalkulator mengambang (js/calculator.js) ──
   Tombol #skCalcFab ditumpuk DI ATAS FAB "Tanya Sinarkeu": bottom = 20px (jarak
   FAB AI) + 52px (tinggi FAB AI) + 12px (celah) = 84px; di desktop 28+52+12 = 92px.
   right digeser 4px karena tombol ini 44px (FAB AI 52px) supaya sumbunya sejajar.
   Visibilitas (hanya Dashboard) diatur oleh aturan body.view-* di dekat
   #aiChatFab di atas -- JANGAN taruh display di sini yang mengalahkan itu. */
.sk-calc-fab {
  display: flex; align-items: center; justify-content: center;
  position: fixed; right: 24px; bottom: 84px;
  width: 44px; height: 44px; padding: 0; border-radius: 50%;
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--rule); cursor: pointer;
  box-shadow: 0 4px 14px rgba(0,0,0,.18);
  z-index: 9000;
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease, color .15s ease;
}
.sk-calc-fab:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(0,0,0,.24); }
.sk-calc-fab.active { background: var(--accent); color: var(--ink-inv); border-color: var(--accent); }
.sk-calc-fab svg { width: 20px; height: 20px; }
[data-theme="dark"] .sk-calc-fab { box-shadow: 0 4px 14px rgba(0,0,0,.5); }
@media (min-width: 1024px) { .sk-calc-fab { right: 32px; bottom: 92px; } }

.sk-calc-panel {
  display: none; flex-direction: column;
  position: fixed; right: 16px; bottom: 140px;
  width: 340px; max-width: calc(100vw - 32px);
  max-height: calc(100vh - 156px); overflow-y: auto;
  padding: var(--space-16);
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--rule); border-radius: var(--radius-lg);
  box-shadow: 0 12px 36px rgba(0,0,0,.24);
  z-index: 9001; outline: none;
}
.sk-calc-panel.show { display: flex; }
[data-theme="dark"] .sk-calc-panel { box-shadow: 0 12px 36px rgba(0,0,0,.65); }
@media (min-width: 1024px) { .sk-calc-panel { right: 28px; bottom: 148px; width: 360px; } }

.sk-calc-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--space-12);
  font-size: var(--text-lg); font-weight: 600; color: var(--ink);
}
.sk-calc-head-actions { display: inline-flex; gap: 4px; }
.sk-calc-iconbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; border: none; border-radius: var(--radius);
  background: transparent; color: var(--ink-muted); cursor: pointer;
}
.sk-calc-iconbtn svg { width: 18px; height: 18px; }
.sk-calc-iconbtn:hover { background: var(--paper-warm); color: var(--ink); }

.sk-calc-screen {
  display: flex; flex-direction: column; justify-content: flex-end;
  min-height: 92px; padding: var(--space-12) var(--space-16); margin-bottom: var(--space-14);
  background: var(--paper-warm); border: 1px solid var(--rule); border-radius: var(--radius);
  text-align: right; overflow: hidden;
}
.sk-calc-expr {
  min-height: 1.4em; margin-bottom: 2px; font-size: var(--text-sm); color: var(--ink-muted);
  font-family: var(--font-mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  direction: rtl; /* kalau kepanjangan, yang terpotong bagian AWAL */
}
.sk-calc-expr > span { direction: ltr; unicode-bidi: isolate; }
.sk-calc-value {
  font-family: var(--font-mono); font-size: 2.3rem; line-height: 1.2; font-weight: 600;
  white-space: nowrap; overflow: hidden;
}
.sk-calc-value.sm { font-size: 1.8rem; }
.sk-calc-value.xs { font-size: 1.3rem; }
.sk-calc-value.err { font-size: 1.4rem; color: var(--danger); }

.sk-calc-keys { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.sk-calc-key {
  display: flex; align-items: center; justify-content: center; text-align: center;
  height: clamp(44px, 7.4vh, 58px); padding: 0; border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--paper-warm); color: var(--ink);
  font-family: var(--font-body); font-size: 1.35rem; line-height: 1; font-weight: 500; cursor: pointer;
  transition: background .1s ease, transform .05s ease;
}
.sk-calc-key:hover { background: var(--accent-lt); }
.sk-calc-key:active { transform: scale(.96); }
.sk-calc-key.sk-calc-fn { color: var(--ink-muted); font-size: 1.2rem; }
.sk-calc-key.sk-calc-fn.danger { color: var(--danger); font-weight: 600; }
.sk-calc-key.sk-calc-op { background: var(--accent-lt); color: var(--accent); font-size: 1.6rem; font-weight: 600; }
.sk-calc-key.sk-calc-eq { background: var(--accent); color: var(--ink-inv); border-color: var(--accent); font-size: 1.6rem; font-weight: 700; }
.sk-calc-key.sk-calc-eq:hover { filter: brightness(1.08); background: var(--accent); }
.sk-calc-iconbtn.active { background: var(--accent-lt); color: var(--accent); }

/* Riwayat: menggantikan grid tombol selagi tombol jam di header aktif */
.sk-calc-history { display: none; flex-direction: column; min-height: 0; }
.sk-calc-panel.show-history .sk-calc-keys { display: none; }
.sk-calc-panel.show-history .sk-calc-history { display: flex; }
.sk-calc-hist-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--space-8); font-size: var(--text-sm); font-weight: 600; color: var(--ink-muted);
}
.sk-calc-hist-clear {
  padding: var(--space-4) var(--space-8); border: none; border-radius: var(--radius);
  background: transparent; color: var(--danger); font-size: var(--text-sm); font-weight: 600; cursor: pointer;
}
.sk-calc-hist-clear:hover { background: var(--danger-lt); }
.sk-calc-hist-list {
  display: flex; flex-direction: column; gap: 6px;
  height: 322px; max-height: calc(100vh - 360px); min-height: 140px; overflow-y: auto;
}
.sk-calc-hist-empty { margin: auto; padding: var(--space-16); text-align: center; font-size: var(--text-sm); color: var(--ink-muted); }
.sk-calc-hist-item {
  display: grid; grid-template-columns: 1fr auto; grid-template-areas: "expr time" "res res";
  gap: 2px var(--space-8); width: 100%; padding: var(--space-8) var(--space-12); text-align: right;
  border: 1px solid var(--rule); border-radius: var(--radius); background: var(--paper-warm); color: var(--ink);
  cursor: pointer; flex: 0 0 auto;
}
.sk-calc-hist-item:hover { background: var(--accent-lt); }
.sk-calc-hist-expr { grid-area: expr; text-align: left; font-family: var(--font-mono); font-size: var(--text-sm); color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sk-calc-hist-time { grid-area: time; font-size: var(--text-xs); color: var(--ink-faint); white-space: nowrap; }
.sk-calc-hist-res { grid-area: res; font-family: var(--font-mono); font-size: 1.25rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-height: 560px) { .sk-calc-screen { min-height: 68px; } .sk-calc-value { font-size: 1.7rem; } }
@media (prefers-reduced-motion: reduce) { .sk-calc-fab, .sk-calc-key { transition: none; } }

/* ======================================================
   DARK MODE — GAYA CLOUDFLARE (27 Okt 2026)
   Lapisan akhir di atas blok "GAYA HANDBOOK" (menimpanya). Mengacu ke
   tampilan gelap blog.cloudflare.com: latar hitam netral (#0B0B0B),
   kartu #141414, teks abu terang, SATU aksen lime #CDF543, garis
   pembatas PUTUS-PUTUS, label meta monospace huruf kapital, judul
   bobot sedang, FLAT tanpa glow. Mode terang TIDAK tersentuh.
====================================================== */
[data-theme="dark"] body {
  background-image: none;
  background-color: var(--paper-warm);
}
[data-theme="dark"] h1,
[data-theme="dark"] h2,
[data-theme="dark"] h3,
[data-theme="dark"] .modal-header h3 {
  font-weight: 600;
  letter-spacing: -0.015em;
}
/* Garis pembatas putus-putus */
[data-theme="dark"] th { border-bottom: 1px dashed var(--rule); }
[data-theme="dark"] td { border-bottom-style: dashed; }
[data-theme="dark"] .fc-cats { border-top-style: dashed; }
/* Flat: tanpa glow */
[data-theme="dark"] .stat-card:hover {
  border-color: var(--accent);
  box-shadow: none;
}
[data-theme="dark"] .balance-hero {
  border-color: var(--rule);
  box-shadow: none;
}
[data-theme="dark"] .balance-hero-value { text-shadow: none; }
[data-theme="dark"] .btn-primary:hover:not(:disabled),
[data-theme="dark"] .manage-books-btn:hover:not(:disabled) { box-shadow: none; }
[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .search-input:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent);
}
[data-theme="dark"] .hb-kw { color: var(--accent); text-shadow: none; }
[data-theme="dark"] .silsilah-node-l .silsilah-gender-badge,
[data-theme="dark"] .silsilah-node-p .silsilah-gender-badge { filter: none; }
/* Tautan & item aktif = oranye */
[data-theme="dark"] .btn-primary,
[data-theme="dark"] .manage-books-btn { font-weight: 600; }
[data-theme="dark"] .modal-header { border-bottom-style: dashed; }
[data-theme="dark"] .modal-footer { border-top-style: dashed; }
[data-theme="dark"] #appSidebar { border-right-style: dashed; }

/* [PALET KALEM] Chip filter/paginasi aktif netral (bukan oranye); oranye hanya untuk aksi utama. */
[data-theme="dark"] .filter-btn.active,
[data-theme="dark"] .page-btn.active {
  background: rgba(255,255,255,0.08);
  color: var(--ink);
  border-color: color-mix(in srgb, var(--ink) 28%, transparent);
}

/* ======================================================
   DARK MODE — PALET LIME DALAM (27 Okt 2026)
   Menyelaraskan warna yang di-set inline lewat JS/HTML (chip pastel mode
   terang, strip kategori) supaya senada dengan aksen lime di mode gelap.
   Mode terang TIDAK tersentuh.
====================================================== */
/* Strip warna kategori di dropdown: terangkan & samakan kejenuhan */
[data-theme="dark"] .cs-opt-strip { filter: brightness(1.55) saturate(0.8); }
/* Chip pastel inline (book.js / account.js / settings.js) */
[data-theme="dark"] [style*="#E3ECF3"],
[data-theme="dark"] [style*="#E9EBF2"],
[data-theme="dark"] [style*="#EFEAF7"] {
  background: rgba(255,255,255,0.06) !important;
  color: var(--ink) !important;
  border-color: var(--rule) !important;
}
[data-theme="dark"] [style*="#E3F0E9"] {
  background: var(--accent-lt) !important;
  color: var(--accent) !important;
}
[data-theme="dark"] [style*="background:#5C4E72"] {
  background: rgba(255,255,255,0.12) !important;
  color: var(--ink) !important;
}
[data-theme="dark"] [style*="color:#5C4E72"] { color: var(--ink-muted) !important; }
[data-theme="dark"] [style*="color:#6B5320"] { color: var(--warning) !important; }
/* Tooltip / elemen Chart.js & legend ikut token */
[data-theme="dark"] .legend-dot { box-shadow: none; }
/* Silsilah: warna per generasi & kartu Brankas — pastel senada lime */
[data-theme="dark"] .silsilah-gen-0 { --gen-color: #CDF543; }
[data-theme="dark"] .silsilah-gen-1 { --gen-color: #6FD6B8; }
[data-theme="dark"] .silsilah-gen-2 { --gen-color: #B79CFF; }
[data-theme="dark"] .silsilah-gen-3 { --gen-color: #E3B34A; }
[data-theme="dark"] .silsilah-gen-4 { --gen-color: #E08BC0; }
[data-theme="dark"] .silsilah-gen-5 { --gen-color: #9BD05A; }
[data-theme="dark"] .silsilah-gen-6 { --gen-color: #B5B5B5; }
[data-theme="dark"] .silsilah-gen-7 { --gen-color: #F0786B; }
[data-theme="dark"] .vault-card[data-cat="pin"]      { --vc: #E3B34A; }
[data-theme="dark"] .vault-card[data-cat="password"] { --vc: #B5B5B5; }
[data-theme="dark"] .vault-card[data-cat="akun"]     { --vc: #B79CFF; }
[data-theme="dark"] .vault-card[data-cat="bank"]     { --vc: #CDF543; }
[data-theme="dark"] .vault-card[data-cat="kunci"]    { --vc: #F0786B; }
[data-theme="dark"] .vault-card[data-cat="lainnya"]  { --vc: #A8B0BA; }

/* ======================================================
   DARK MODE — TEKS DI ATAS LIME (27 Okt 2026) + SINARMEDIA
   Elemen berlatar aksen (lime) yang teksnya #fff di mode terang jadi
   tidak terbaca di atas lime; di mode gelap teksnya dipakai gelap
   (--ink-inv). Mencakup toggle kalender SinarMedia, tab, badge, FAB.
====================================================== */
[data-theme="dark"] .ai-chat-fab,
[data-theme="dark"] .expense-chart-toggle button.active,
[data-theme="dark"] .filter-btn.active,
[data-theme="dark"] .btn-primary,
[data-theme="dark"] .page-btn.active,
[data-theme="dark"] .smedia-cal-toggle button.is-active,
[data-theme="dark"] .btn-lang-active,
[data-theme="dark"] .setup-brand-badge,
[data-theme="dark"] .setup-section-num,
[data-theme="dark"] .um-invite-tab.active,
[data-theme="dark"] .sk-fam-photo-badge,
[data-theme="dark"] .silsilah-inline-add-btn.sk-fam-add-chip:hover,
[data-theme="dark"] .silsilah-selbar-edit {
  color: var(--ink-inv);
}
/* SinarMedia: batang untung/rugi & ring terbaik senada lime */
[data-theme="dark"] .smedia-chart-bar {
  background: linear-gradient(to top, color-mix(in srgb, var(--success) 55%, var(--paper)), var(--success));
}
[data-theme="dark"] .smedia-chart-bar.is-loss {
  background: linear-gradient(to bottom, color-mix(in srgb, var(--danger) 55%, var(--paper)), var(--danger));
}
[data-theme="dark"] .smedia-cal-toggle button.is-active { background: var(--accent); color: var(--ink-inv); }

/* ======================================================
   [TAHAPAN & DEADLINE — LAYOUT 2 KOLOM] (27 Okt 2026)
   Di lebar cukup (container query pada <details>), kalender di kiri
   dan "Deadline Terdekat" + daftar tahap di kanan, jadi tidak ada ruang
   kosong di kiri-kanan kalender. Form tambah tahap tetap selebar penuh.
   Di layar sempit tetap menumpuk seperti semula.
====================================================== */
#smediaMsCollapse { container-type: inline-size; container-name: smms; }
@container smms (min-width: 560px) {
  #smediaMsCollapse > .smedia-options-collapse-body {
    display: grid;
    grid-template-columns: minmax(280px, 380px) minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    column-gap: var(--space-16);
    align-items: start;
  }
  #smediaMsCalendar { grid-column: 1; grid-row: 1 / span 2; }
  #smediaMsCalendar .smedia-cal-header,
  #smediaMsCalendar .smedia-cal-grid { max-width: none; }
  /* Kalender diperbesar proporsional supaya tingginya menyamai kolom kanan */
  #smediaMsCalendar .smedia-cal-grid { gap: 4px; }
  #smediaMsCalendar .smedia-cal-cell { aspect-ratio: 1.08; font-size: 13px; gap: 3px; }
  #smediaMsCalendar .smedia-cal-daynum { font-size: 13px; }
  #smediaMsCalendar .smedia-cal-dot { width: 6px; height: 6px; }
  #smediaMsCalendar .smedia-cal-dow { font-size: 11px; padding-bottom: 4px; }
  #smediaMsCalendar .smedia-cal-label { font-size: var(--text-sm); }
  #smediaMsCalendar .smedia-cal-nav { padding: 4px 6px; }
  #smediaMsCalendar .smedia-cal-toggle button { padding: 5px 8px; font-size: var(--text-xs); }
  #smediaMsCalendar .smedia-cal-header { margin-bottom: var(--space-8); }
  #smediaMsHighlight { grid-column: 2; grid-row: 1; }
  #smediaMsList {
    grid-column: 2; grid-row: 2;
    margin: var(--space-8) 0 0;
    max-height: 320px; overflow-y: auto;
    padding-right: var(--space-4);
  }
  #smediaMsCollapse > .smedia-options-collapse-body > :not(#smediaMsCalendar):not(#smediaMsHighlight):not(#smediaMsList) {
    grid-column: 1 / -1;
  }
}

/* Kalender Tahapan SinarMedia (mode gelap): sel hari ini berborder merah supaya jelas. */
[data-theme="dark"] .smedia-cal-cell.is-today {
  border-color: var(--danger);
  box-shadow: inset 0 0 0 1px var(--danger);
}

/* Chip filter/paginasi aktif (netral): teks harus terang. Ditaruh PALING AKHIR
   karena blok "teks di atas lime" sebelumnya sempat menimpanya jadi gelap. */
[data-theme="dark"] .filter-btn.active,
[data-theme="dark"] .page-btn.active {
  background: rgba(255,255,255,0.10);
  color: var(--ink);
  border-color: color-mix(in srgb, var(--ink) 30%, transparent);
}

/* FAB "Tanya Sinarkeu" mode gelap: aturan generik tombol gelap menimpa latarnya
   sehingga tak terlihat. Pakai lime solid + ikon gelap (ditaruh paling akhir). */
[data-theme="dark"] button.ai-chat-fab {
  background: var(--accent);
  border: 1px solid var(--accent);
  color: var(--ink-inv);
  box-shadow: 0 4px 14px rgba(0,0,0,.55);
}
[data-theme="dark"] button.ai-chat-fab:hover:not(:disabled) {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
  color: var(--ink-inv);
}
[data-theme="dark"] .ai-chat-fab .sk-icon { stroke: currentColor; }

/* Kalender Tahapan SinarMedia: sel yang punya tahapan berborder hijau.
   Ditaruh PALING AKHIR supaya menang atas border merah hari ini (mode gelap). */
.smedia-cal-cell.has-items,
[data-theme="dark"] .smedia-cal-cell.has-items.is-today {
  border-color: var(--success);
  box-shadow: inset 0 0 0 1px var(--success);
}

/* [ANTI-FLASH LOGIN GATE] Shell app (sidebar, FAB, Dashboard) disembunyikan
   (visibility, bukan display, supaya layout tidak loncat) selagi menunggu
   keputusan gerbang login. Class dipasang js/boot-early.js, dilepas
   continueAppInit (js/app.js). Layar login/kunci bukan anak elemen-elemen ini. */
html.sk-gate-pending #appSidebar,
html.sk-gate-pending .container,
html.sk-gate-pending #aiChatFab,
html.sk-gate-pending #skCalcFab { visibility: hidden; }

/* ======================================================================
   [RESTYLE LAYAR KUNCI UTAMA] (4 Nov 2026)
   Hanya #passwordLockScreen -- layar login Buku Bersama (#skLoginGateScreen)
   tidak ikut berubah. Gaya mengikuti sisa aplikasi: flat, outline tipis,
   input & tombol kapsul, kartu seperti kartu loader (.sk-page-loader-card).
   Warna 100% dari token tema (terang/gelap); tanpa biru tambahan.
   Ditaruh PALING AKHIR supaya menang atas blok lock-* lama & aturan
   [data-theme="dark"] .lock-* di atas.
   ====================================================================== */
#passwordLockScreen {
  position: fixed;
  overflow-y: auto;
  padding-top: max(var(--space-24), env(safe-area-inset-top));
  padding-bottom: max(var(--space-24), env(safe-area-inset-bottom));
  padding-left: max(var(--space-16), env(safe-area-inset-left));
  padding-right: max(var(--space-16), env(safe-area-inset-right));
  background:
    radial-gradient(120% 70% at 50% 0%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 62%),
    var(--paper-warm);
}
/* Mode gelap: latar arang + kisi tipis yang memudar ke tepi (nuansa technical). */
[data-theme="dark"] #passwordLockScreen { background: var(--paper-warm); }
[data-theme="dark"] #passwordLockScreen::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(var(--rule) 1px, transparent 1px),
    linear-gradient(90deg, var(--rule) 1px, transparent 1px);
  background-size: 44px 44px;
  opacity: .55;
  -webkit-mask-image: radial-gradient(70% 60% at 50% 42%, #000 0%, transparent 100%);
          mask-image: radial-gradient(70% 60% at 50% 42%, #000 0%, transparent 100%);
}

#passwordLockScreen .lock-card-wrap {
  position: relative;
  z-index: 1;
  flex: 1 0 auto;      /* tumbuh mengikuti isi; layar pendek -> seluruh layar bisa di-scroll */
}
#passwordLockScreen .lock-footer { position: relative; z-index: 1; }

#passwordLockScreen .lock-card {
  max-width: 400px;
  padding: var(--space-28) var(--space-28) var(--space-24);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  animation: skLoaderIn .3s ease both;
}
@media (max-width: 480px) {
  #passwordLockScreen .lock-card { padding: var(--space-24) var(--space-20) var(--space-20); }
}

/* Merek */
.lock-brand {
  display: flex; align-items: center; justify-content: center;
  gap: var(--space-10);
  margin-bottom: var(--space-20);
}
.lock-brand-logo { width: 40px; height: 40px; border-radius: var(--radius); display: block; }
.lock-brand-name {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* Sambutan */
#passwordLockScreen .lock-title {
  font-size: var(--text-2xl);
  line-height: 1.2;
  margin-bottom: var(--space-6);
}
.lock-sub {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--ink-muted);
  margin-bottom: var(--space-20);
  min-height: calc(1.5em * 1);
}

/* Kartu ringkasan keuangan (js/lockscreen-insight.js) -- flat, garis status di kiri */
.lock-insight-card {
  --lk: var(--rule);
  text-align: left;
  margin: 0 0 var(--space-18);
  padding: var(--space-12) var(--space-14);
  background: var(--paper-warm);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--lk);
  border-radius: var(--radius);
}
.lock-insight-card.status--success { --lk: var(--success); }
.lock-insight-card.status--danger  { --lk: var(--danger); }
.lock-insight-card.status--warning { --lk: var(--warning); }
.lock-insight-card.status--info    { --lk: var(--info); }
.lock-insight-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: var(--space-6);
}
.lock-insight-head { display: flex; align-items: center; gap: var(--space-6); margin-bottom: var(--space-6); }
.lock-insight-badge {
  display: inline-block;
  padding: var(--space-2) var(--space-8);
  border-radius: var(--radius-pill);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: .02em;
  background: var(--rule);
  color: var(--ink-muted);
}
.lock-insight-badge--success { background: var(--success-lt); color: var(--success); }
.lock-insight-badge--danger  { background: var(--danger-lt);  color: var(--danger); }
.lock-insight-badge--warning { background: var(--warning-lt); color: var(--warning); }
.lock-insight-badge--info    { background: var(--info-lt);    color: var(--info); }
.lock-insight-ai-tag {
  font-size: var(--text-2xs);
  color: var(--ink-faint);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  padding: 0 var(--space-6);
}
.lock-insight-body { font-size: var(--text-xs); line-height: 1.55; color: var(--ink); }
.lock-insight-motivasi {
  margin-top: var(--space-8);
  padding-top: var(--space-8);
  border-top: 1px dashed var(--rule);
  font-size: var(--text-xs);
  line-height: 1.5;
  font-style: italic;
  color: var(--ink-muted);
}

/* Pilih akun */
#passwordLockScreen .lock-account-picker { margin-bottom: var(--space-16); }
#passwordLockScreen .lock-account-item {
  border-width: 1px;
  border-radius: var(--radius);
  background: var(--paper);
}
#passwordLockScreen .lock-account-item:hover,
#passwordLockScreen .lock-account-item.selected {
  border-color: var(--accent);
  background: var(--accent-lt);
}
#passwordLockScreen .lock-account-avatar {
  background: var(--accent-lt);
  color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  font-weight: 600;
}
#passwordLockScreen .lock-account-item:hover .lock-account-avatar,
#passwordLockScreen .lock-account-item.selected .lock-account-avatar { background: var(--paper); }
#passwordLockScreen .lock-account-check { color: var(--accent); }

/* Input password: kapsul */
#passwordLockScreen .lock-input {
  border-width: 1px;
  border-radius: var(--radius-pill);
  padding: var(--space-12) var(--space-56) var(--space-12) var(--space-20);
  background: var(--paper-warm);
}
#passwordLockScreen .lock-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
  background: var(--paper);
}
[data-theme="dark"] #passwordLockScreen .lock-input { background: var(--paper-warm); }
[data-theme="dark"] #passwordLockScreen .lock-input:focus { background: var(--paper); box-shadow: 0 0 0 3px var(--hb-glow); }
#passwordLockScreen .lock-eye-btn {
  right: var(--space-14);
  padding: var(--space-4) var(--space-6);
  border-radius: var(--radius-pill);
  color: var(--ink-muted);
}
#passwordLockScreen .lock-eye-btn:hover:not(:disabled) { color: var(--ink); background: var(--rule); }
#passwordLockScreen .lock-status { margin-top: var(--space-8); }

/* Footer: tombol ghost kapsul, tanpa garis bawah */
#passwordLockScreen .lock-footer { gap: var(--space-4); flex-wrap: wrap; padding-top: var(--space-12); }
#passwordLockScreen .lock-add-account,
#passwordLockScreen .lock-manual-btn {
  display: inline-flex;
  align-items: center;
  padding: var(--space-6) var(--space-12);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  text-decoration: none;
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--ink-muted);
  transition: border-color .12s, background .12s, color .12s;
}
#passwordLockScreen .lock-add-account:hover,
#passwordLockScreen .lock-manual-btn:hover {
  color: var(--ink);
  background: var(--paper);
  border-color: var(--rule);
}
#passwordLockScreen .lock-footer-sep { display: none; }

@media (prefers-reduced-motion: reduce) {
  #passwordLockScreen .lock-card { animation: none; }
}

/* ======================================================================
   [AUDIT MINGGUAN] banner Dashboard, kartu di menu Reminder, modal (4 Nov 2026)
   Flat & outline tipis, warna dari token tema -- js/weekly-audit.js
   ====================================================================== */
.wa-banner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-10); flex-wrap: wrap;
  margin-bottom: var(--space-10);
  padding: var(--space-10) var(--space-14);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
}
.wa-banner-title { font-size: var(--text-sm); font-weight: 700; color: var(--ink); }
.wa-banner-text { font-size: var(--text-xs); line-height: 1.5; color: var(--ink-muted); margin-top: var(--space-2); }
.wa-banner-actions { display: flex; gap: var(--space-6); }
.wa-banner-btn { font-size: var(--text-xs); padding: var(--space-5) var(--space-12); white-space: nowrap; }

.wa-entry {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-10);
  margin-bottom: var(--space-14);
  padding: var(--space-10) var(--space-14);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
}
.wa-entry-title { font-size: var(--text-sm); font-weight: 700; color: var(--ink); }
.wa-entry-text { font-size: var(--text-xs); color: var(--ink-muted); margin-top: var(--space-2); }

#waBody { padding-bottom: var(--space-4); }
.wa-period { font-size: var(--text-xs); color: var(--ink-muted); margin-bottom: var(--space-12); }
.wa-note { font-size: var(--text-xs); line-height: 1.5; color: var(--ink-muted); margin-bottom: var(--space-8); }
.wa-note--warn { padding: var(--space-8) var(--space-12); background: var(--warning-lt); border-left: 3px solid var(--warning); border-radius: var(--radius-sm); color: var(--ink); }
.wa-section-title { font-size: var(--text-sm); font-weight: 700; color: var(--ink); margin: var(--space-14) 0 var(--space-8); }
.wa-list { border: 1px solid var(--rule); border-radius: var(--radius-sm); overflow: hidden; }
.wa-list-row { display: flex; justify-content: space-between; gap: var(--space-10); padding: var(--space-8) var(--space-12); font-size: var(--text-xs); color: var(--ink); }
.wa-list-row + .wa-list-row { border-top: 1px solid var(--rule); }
.wa-list-row small { color: var(--ink-faint); }
.wa-list-row strong { font-variant-numeric: tabular-nums; white-space: nowrap; }
.wa-checklist, .wa-settings { display: flex; flex-direction: column; gap: var(--space-8); }
.wa-check { display: flex; align-items: flex-start; gap: var(--space-8); font-size: var(--text-sm); color: var(--ink); cursor: pointer; }
.wa-check input { margin-top: 3px; accent-color: var(--accent); }
.wa-actions { display: flex; gap: var(--space-8); flex-wrap: wrap; margin-top: var(--space-14); }
.wa-actions .btn { flex: 1; white-space: nowrap; }
.wa-settings-row { display: flex; gap: var(--space-8); }
.wa-settings-row .form-control { flex: 1; }
.wa-hint { font-size: var(--text-xs); line-height: 1.5; color: var(--ink-faint); }
.wa-footer { margin-top: var(--space-16); padding-top: var(--space-12); border-top: 1px solid var(--rule); }
@media (max-width: 480px) {
  .wa-banner-actions { width: 100%; }
  .wa-banner-actions .btn { flex: 1; }
}

/* [AUDIT MINGGUAN] status tanda selesai Buku Bersama (minimal 2 anggota) */
.wa-footer .btn[disabled] { opacity: .6; cursor: default; }

/* ── Tombol "Audit Mingguan" di header, di sebelah chip login terakhir -- khusus desktop (>=1024px) ── */
.wa-header-btn { display: none; }
@media (min-width: 1024px) {
  .wa-header-btn {
    display: inline-flex; align-items: center; gap: var(--space-6);
    flex-shrink: 0; margin-left: auto; cursor: pointer;
    padding: var(--space-6) var(--space-12);
    border: 1.5px solid var(--rule); border-radius: 999px;
    background: var(--paper); color: var(--ink-muted);
    font-size: var(--text-xs); font-weight: 600; white-space: nowrap;
    transition: border-color .15s, background .15s, color .15s;
  }
  .wa-header-btn:hover { border-color: var(--ink-faint); background: var(--paper-warm); color: var(--ink); }
}

/* ── [AUDIT MINGGUAN] toggle per buku di daftar Buku Kas ── */
.book-wa-toggle { display: inline-flex; align-items: center; gap: var(--space-6); margin-top: var(--space-4); font-size: var(--text-2xs); color: var(--ink-muted); cursor: pointer; user-select: none; }
.book-wa-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.book-wa-switch { position: relative; flex: 0 0 auto; width: 26px; height: 15px; border-radius: 999px; background: var(--rule); transition: background .15s; }
.book-wa-switch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 11px; height: 11px; border-radius: 50%; background: var(--paper); box-shadow: 0 1px 2px rgba(0,0,0,.25); transition: transform .15s; }
.book-wa-toggle input:checked + .book-wa-switch { background: var(--success); }
.book-wa-toggle input:checked + .book-wa-switch::after { transform: translateX(11px); }
.book-wa-toggle input:focus-visible + .book-wa-switch { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Audit Mingguan: rincian transaksi (6-8 Nov 2026) */
.wa-section-title small { font-weight: 400; }
.wa-count { margin-left: var(--space-4); padding: 1px var(--space-6); border-radius: 999px; background: var(--paper-warm); border: 1px solid var(--rule); color: var(--ink-muted); }
.wa-filters { display: flex; flex-wrap: wrap; gap: var(--space-6); margin-bottom: var(--space-10); }
.wa-chip { font: inherit; font-size: var(--text-xs); padding: var(--space-4) var(--space-10); border: 1px solid var(--rule); border-radius: 999px; background: var(--paper); color: var(--ink-muted); cursor: pointer; }
.wa-chip span { color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.wa-chip.is-active { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.wa-chip.is-active span { color: inherit; opacity: .75; }
.wa-days { display: flex; flex-direction: column; gap: var(--space-10); }
.wa-day-head { display: flex; justify-content: space-between; gap: var(--space-10); font-size: var(--text-2xs); font-weight: 700; color: var(--ink-muted); text-transform: uppercase; letter-spacing: .04em; margin-bottom: var(--space-4); }
.wa-day-head small { font-weight: 400; text-transform: none; letter-spacing: 0; font-variant-numeric: tabular-nums; }
.wa-tx { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-10); padding: var(--space-8) var(--space-12); font-size: var(--text-xs); color: var(--ink); }
.wa-tx + .wa-tx { border-top: 1px solid var(--rule); }
.wa-tx-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.wa-tx-title { overflow-wrap: anywhere; }
.wa-tx-main small { color: var(--ink-faint); }
.wa-tx-amt { font-variant-numeric: tabular-nums; white-space: nowrap; }
.wa-tx--income .wa-tx-amt { color: var(--success); }
.wa-nocat { color: var(--warning); font-style: normal; font-weight: 600; }
.wa-cat > summary { list-style: none; cursor: pointer; }
.wa-cat > summary::-webkit-details-marker { display: none; }
.wa-cat > summary > span::before { content: '\25B8'; display: inline-block; margin-right: var(--space-6); color: var(--ink-faint); transition: transform .15s; }
.wa-cat[open] > summary > span::before { transform: rotate(90deg); }
.wa-cat + .wa-cat { border-top: 1px solid var(--rule); }
.wa-cat-items { background: var(--paper-warm); border-top: 1px solid var(--rule); }
.wa-tx--sub { padding-left: var(--space-24); }
.wa-more { width: 100%; margin-top: var(--space-10); }

/* ── [AUDIT MINGGUAN] redesain modal (8 Nov 2026): hero + tab + panel tinjau ── */
.wa-modal-content { max-width: 560px; max-height: 92vh; overflow-y: auto; }
@media (min-width: 1024px) { .wa-modal-content { max-width: 1040px; width: 92vw; } }
.wa-hero { padding: var(--space-14) var(--space-16); background: var(--paper-warm); border: 1px solid var(--rule); border-radius: var(--radius-lg); margin-bottom: var(--space-14); }
.wa-hero-top { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-10); }
.wa-hero .wa-period { margin: 0; }
.wa-book { font-size: var(--text-sm); font-weight: 700; color: var(--ink); margin-top: var(--space-2); }
.wa-status { flex: 0 0 auto; font-size: var(--text-2xs); font-weight: 700; padding: var(--space-4) var(--space-10); border-radius: var(--radius-pill); white-space: nowrap; }
.wa-status--todo { background: var(--warning-lt); color: var(--ink); border: 1px solid var(--warning); }
.wa-status--ok { background: var(--success-lt); color: var(--success); border: 1px solid var(--success); }
.wa-hero-net { margin: var(--space-12) 0 var(--space-10); display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-4) var(--space-10); }
.wa-hero-net small { flex-basis: 100%; font-size: var(--text-2xs); color: var(--ink-faint); }
.wa-net { font-size: var(--text-xl, 1.5rem); font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; line-height: 1.1; }
.wa-net.is-neg { color: var(--danger); }
.wa-delta { font-size: var(--text-2xs); color: var(--ink-muted); }
.wa-delta--up { color: var(--danger); }
.wa-delta--down { color: var(--success); }
.wa-flow { height: 6px; border-radius: 999px; background: var(--danger-lt); overflow: hidden; }
.wa-flow i { display: block; height: 100%; background: var(--success); border-radius: 999px; }
.wa-flow-legend { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-4) var(--space-12); margin-top: var(--space-8); font-size: var(--text-2xs); color: var(--ink-muted); }
.wa-flow-legend strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.wa-in::before, .wa-out::before { content: ''; display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: var(--space-4); background: var(--success); }
.wa-out::before { background: var(--danger); }
.wa-layout { display: block; }
.wa-col-side { display: flex; flex-direction: column; gap: var(--space-12); margin-top: var(--space-14); }
@media (min-width: 1024px) {
  .wa-layout { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(300px, 1fr); gap: var(--space-24); align-items: start; }
  .wa-col-side { margin-top: 0; position: sticky; top: 0; }
}
.wa-tabs { display: flex; gap: var(--space-2); padding: var(--space-3, 3px); background: var(--paper-warm); border: 1px solid var(--rule); border-radius: var(--radius-pill); margin-bottom: var(--space-12); overflow-x: auto; }
.wa-tab { flex: 1 0 auto; font: inherit; font-size: var(--text-xs); padding: var(--space-6) var(--space-12); border: 0; border-radius: var(--radius-pill); background: transparent; color: var(--ink-muted); cursor: pointer; white-space: nowrap; }
.wa-tab span { color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.wa-tab.is-active { background: var(--paper); color: var(--ink); font-weight: 700; box-shadow: 0 0 0 1px var(--rule); }
.wa-empty { padding: var(--space-16); text-align: center; font-size: var(--text-xs); color: var(--ink-faint); border: 1px dashed var(--rule); border-radius: var(--radius-sm); }
.wa-link { font: inherit; background: none; border: 0; padding: 0; color: var(--accent); text-decoration: underline; cursor: pointer; }
.wa-cats { display: flex; flex-direction: column; gap: var(--space-8); }
.wa-cat { border: 1px solid var(--rule); border-radius: var(--radius-sm); overflow: hidden; background: var(--paper); }
.wa-cat + .wa-cat { border-top: 1px solid var(--rule); }
.wa-cat > summary { padding: var(--space-10) var(--space-12); cursor: pointer; list-style: none; }
.wa-cat > summary::-webkit-details-marker { display: none; }
.wa-cat > summary::before, .wa-cat > summary > span::before { content: none; }
.wa-cat-row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-10); font-size: var(--text-xs); color: var(--ink); }
.wa-cat-name { display: flex; flex-direction: column; gap: 2px; font-weight: 600; }
.wa-cat-name small { font-weight: 400; color: var(--ink-faint); }
.wa-cat-row strong { font-variant-numeric: tabular-nums; white-space: nowrap; }
.wa-bar { height: 4px; margin-top: var(--space-8); background: var(--rule); border-radius: 999px; overflow: hidden; }
.wa-bar i { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.wa-cat[open] > summary { border-bottom: 1px solid var(--rule); }
.wa-rank { display: flex; align-items: flex-start; }
.wa-rank + .wa-rank { border-top: 1px solid var(--rule); }
.wa-rank-n { flex: 0 0 auto; width: 22px; margin: var(--space-8) 0 0 var(--space-10); text-align: center; font-size: var(--text-2xs); font-weight: 700; color: var(--ink-muted); background: var(--paper-warm); border-radius: 50%; line-height: 22px; }
.wa-rank .wa-tx { flex: 1; min-width: 0; border-top: 0; }
.wa-card { padding: var(--space-12) var(--space-14); border: 1px solid var(--rule); border-radius: var(--radius-lg); background: var(--paper); }
.wa-card-head { display: flex; justify-content: space-between; gap: var(--space-10); font-size: var(--text-sm); color: var(--ink); }
.wa-card-head span { color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.wa-card .wa-hint { margin-top: var(--space-4); }
.wa-card .wa-list { margin-top: var(--space-8); }
.wa-signoff--ok { border-color: var(--success); background: var(--success-lt); }
.wa-progress { height: 4px; margin: var(--space-8) 0 var(--space-10); background: var(--rule); border-radius: 999px; overflow: hidden; }
.wa-progress i { display: block; height: 100%; background: var(--accent); transition: width .2s; }
.wa-card .wa-actions { margin-top: var(--space-12); }
.wa-fold { border: 1px solid var(--rule); border-radius: var(--radius-lg); background: var(--paper); }
.wa-fold > summary { display: flex; justify-content: space-between; gap: var(--space-10); padding: var(--space-10) var(--space-14); cursor: pointer; list-style: none; font-size: var(--text-sm); font-weight: 700; color: var(--ink); }
.wa-fold > summary::-webkit-details-marker { display: none; }
.wa-fold > summary small { font-weight: 400; color: var(--ink-muted); }
.wa-fold .wa-settings { padding: 0 var(--space-14) var(--space-14); }
.wa-footer { display: flex; flex-direction: column; gap: var(--space-8); margin: 0; padding: var(--space-10) 0; border-top: 1px solid var(--rule); background: var(--paper); position: sticky; bottom: 0; }
.wa-footer .btn { width: 100%; margin: 0; }
.wa-footer .btn[disabled] { opacity: .6; cursor: default; }
@media (min-width: 1024px) { .wa-footer { position: static; padding-bottom: 0; border-top: 0; } }

/* ======================================================
   DARK MODE — GAYA ZED (9 Nov 2026)
   Lapisan paling akhir (menimpa blok Handbook & Cloudflare). Acuan:
   panel agent editor Zed -- permukaan berlapis (sidebar paling gelap,
   konten sedikit lebih terang, kartu paling terang), garis pembatas
   TIPIS (di mode gelap tetap putus-putus ala Cloudflare), sidebar rapat dengan baris aktif
   berlatar halus, sel nominal ala diff (hijau/merah redup), dan warna
   hanya untuk makna. Aksen tetap lime; TIDAK ada biru (lihat catatan
   token dark). Versi mode terang ada di blok "GAYA ZED -- MODE TERANG"
   tepat di bawah blok ini.
====================================================== */
[data-theme="dark"] {
  --zed-bg-side:  #0A0A0A;   /* sidebar / title bar */
  --zed-bg-main:  #0F0F10;   /* area konten */
  --zed-bg-card:  #161617;   /* kartu / panel */
  --zed-line:     #232325;   /* garis tipis */
  --zed-hover:    rgba(255,255,255,0.045);
  --zed-active:   rgba(255,255,255,0.085);
  --zed-add:      color-mix(in srgb, var(--success) 13%, transparent);
  --zed-del:      color-mix(in srgb, var(--danger) 14%, transparent);
}
/* Garis pembatas PUTUS-PUTUS ala Cloudflare tetap dipertahankan di mode
   gelap (keputusan user, 9 Nov 2026) -- jangan diganti solid di sini. */

/* Permukaan berlapis */
[data-theme="dark"] body { background-color: var(--zed-bg-main); }
[data-theme="dark"] #appSidebar { background: var(--zed-bg-side); }

/* Sidebar rapat (desktop saja; di HP tetap longgar untuk jempol) */
@media (min-width: 1024px) {
  [data-theme="dark"] .app-nav-group-label {
    font-family: inherit;
    font-size: var(--text-xs);
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink-faint);
    padding: var(--space-10) var(--space-10) var(--space-3);
  }
  [data-theme="dark"] .app-nav-item {
    padding: var(--space-6) var(--space-10);
    font-weight: 500;
    border-radius: 6px;
  }
}
[data-theme="dark"] .app-nav-item:hover { background: var(--zed-hover); }
[data-theme="dark"] .app-nav-item.active,
[data-theme="dark"] .app-nav-item.active:hover {
  background: var(--zed-active);
  color: var(--ink);
  font-weight: 500;
}

/* Kartu: rata, garis tipis, tanpa bayangan */
[data-theme="dark"] .stat-card,
[data-theme="dark"] .balance-hero,
[data-theme="dark"] .wa-card,
[data-theme="dark"] .wa-fold {
  background: var(--zed-bg-card);
  border-color: var(--zed-line);
  box-shadow: none;
}

/* Tabel transaksi ala diff: sel yang berisi nominal diberi latar redup
   (hijau = pemasukan, merah = pengeluaran). Sel kosong (.tx-zero) polos. */
[data-theme="dark"] td.col-income:not(:has(.tx-zero)) { background: var(--zed-add); }
[data-theme="dark"] td.col-expense:not(:has(.tx-zero)) { background: var(--zed-del); }
[data-theme="dark"] td.col-no {
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
[data-theme="dark"] tbody tr:hover td { box-shadow: inset 0 0 0 999px var(--zed-hover); }

/* ======================================================
   MODE TERANG — GAYA ZED (9 Nov 2026)
   Padanan blok "DARK MODE — GAYA ZED" di atas, memakai palet hangat
   Emerald Trust yang sudah ada (warna dasar TIDAK diganti): sidebar
   sedikit lebih gelap dari konten, garis solid tipis, sidebar desktop
   rapat dengan label grup huruf biasa, item aktif berlatar halus, dan
   sel nominal ala diff. Selector memakai :root:not([data-theme="dark"])
   supaya tidak pernah menimpa mode gelap.
====================================================== */
:root:not([data-theme="dark"]) {
  --zed-bg-side:  #F1EEE9;   /* sidebar: sedikit lebih gelap dari konten */
  --zed-line:     #E4DFD8;
  --zed-hover:    rgba(38,35,31,0.05);
  --zed-active:   rgba(38,35,31,0.08);
  --zed-add:      color-mix(in srgb, var(--success) 10%, transparent);
  --zed-del:      color-mix(in srgb, var(--danger) 10%, transparent);
}
:root:not([data-theme="dark"]) #appSidebar {
  background: var(--zed-bg-side);
  border-right: 1px solid var(--zed-line);
}
@media (min-width: 1024px) {
  :root:not([data-theme="dark"]) .app-nav-group-label {
    font-size: var(--text-xs);
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink-faint);
    padding: var(--space-10) var(--space-10) var(--space-3);
  }
  :root:not([data-theme="dark"]) .app-nav-item {
    padding: var(--space-6) var(--space-10);
    font-weight: 500;
    border-radius: 6px;
  }
}
:root:not([data-theme="dark"]) .app-nav-item:hover:not(:disabled) { background: var(--zed-hover); }
:root:not([data-theme="dark"]) .app-nav-item.active:not(:disabled),
:root:not([data-theme="dark"]) .app-nav-item.active:hover:not(:disabled) {
  background: var(--zed-active);
  color: var(--ink);
  font-weight: 500;
}
:root:not([data-theme="dark"]) .modal-header { border-bottom: 1px solid var(--zed-line); }
:root:not([data-theme="dark"]) .modal-footer { border-top: 1px solid var(--zed-line); }
:root:not([data-theme="dark"]) th,
:root:not([data-theme="dark"]) td { border-bottom-color: var(--zed-line); }
/* Tabel transaksi ala diff */
:root:not([data-theme="dark"]) td.col-income:not(:has(.tx-zero)) { background: var(--zed-add); }
:root:not([data-theme="dark"]) td.col-expense:not(:has(.tx-zero)) { background: var(--zed-del); }
:root:not([data-theme="dark"]) td.col-no {
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
:root:not([data-theme="dark"]) tbody tr:hover td { box-shadow: inset 0 0 0 999px var(--zed-hover); }

/* ======================================================
   SILSILAH KELUARGA — GAYA ZED (9 Nov 2026)
   Lapisan akhir untuk kedua tema. Prinsip Zed: kartu rata dengan garis
   tipis netral, warna hanya untuk makna, tanpa bayangan/glow/zoom saat
   hover (hover = garis tepi berganti warna gender). TETAP dipertahankan
   (keputusan user sebelumnya): warna per generasi (di header kotak +
   tint tipis), lencana teks gender, kotak menantu putus-putus, label
   MENANTU/PASANGAN, dan semua garis penghubung (tidak disentuh).
====================================================== */
/* Kotak anggota: isi hampir netral, tepi hairline, jejak warna generasi tipis */
:root .silsilah-node[class*="silsilah-gen-"] rect.silsilah-node-box,
[data-theme="dark"] .silsilah-node[class*="silsilah-gen-"] rect.silsilah-node-box,
:root .silsilah-node-inlaw[class*="silsilah-gen-"] rect.silsilah-node-box,
[data-theme="dark"] .silsilah-node-inlaw[class*="silsilah-gen-"] rect.silsilah-node-box {
  fill: color-mix(in srgb, var(--gen-color) 3%, var(--paper));
  stroke: color-mix(in srgb, var(--gen-color) 24%, var(--zed-line));
  stroke-width: 1;
}
:root .silsilah-node[class*="silsilah-gen-"] .silsilah-node-head {
  fill: color-mix(in srgb, var(--gen-color) 12%, var(--paper));
}
:root .silsilah-node-headline {
  stroke: color-mix(in srgb, var(--gen-color, var(--ink-faint)) 22%, var(--zed-line));
}
/* Hover/fokus: statis (tanpa zoom, bayangan, glow); tepi ganti warna gender */
:root .silsilah-node:hover,
:root .silsilah-node:focus { transform: none; }
:root .silsilah-node:hover rect.silsilah-node-box,
:root .silsilah-node:focus rect.silsilah-node-box,
[data-theme="dark"] .silsilah-node:hover rect.silsilah-node-box,
[data-theme="dark"] .silsilah-node:focus rect.silsilah-node-box {
  filter: none;
  stroke: var(--gc, var(--ink-faint));
}
[data-theme="dark"] .silsilah-node-l .silsilah-gender-badge,
[data-theme="dark"] .silsilah-node-p .silsilah-gender-badge { filter: none; }

/* Kartu rekap, rekap generasi, viewport pohon, tombol zoom: hairline 1px, sudut 8px */
.silsilah-recap-card,
.silsilah-genrecap-card {
  border: 1px solid var(--zed-line);
  border-radius: 8px;
  box-shadow: none;
}
.silsilah-recap-item + .silsilah-recap-item { border-left-color: var(--zed-line); }
[data-theme="dark"] .silsilah-recap-item + .silsilah-recap-item { border-left-style: dashed; }
.silsilah-genrecap-chip,
[data-theme="dark"] .silsilah-genrecap-chip {
  border-width: 1px;
  border-radius: 6px;
  border-color: color-mix(in srgb, var(--gen-color) 28%, var(--zed-line));
  background: color-mix(in srgb, var(--gen-color) 7%, var(--paper));
}
.silsilah-tree-viewport {
  border: 1px solid var(--zed-line);
  border-radius: 8px;
}
.silsilah-zoom-btn {
  border-width: 1px;
  border-color: var(--zed-line);
  border-radius: 6px;
  box-shadow: none;
}
.silsilah-search-bar {
  border-width: 1px;
  border-color: var(--zed-line);
  border-radius: 6px;
}
.silsilah-data-btn { border-radius: 6px; }

/* ======================================================
   SILSILAH KELUARGA — MODE RINGAN (9 Nov 2026)
   Efek dikurangi supaya halaman lebih cepat dimuat & ringan di HP/iPad
   (pohon dengan puluhan-ratusan kotak/garis tadinya menjalankan ratusan
   animasi CSS bertahap + filter drop-shadow di SVG, yang berat untuk
   paint/composite). Sekarang pohon langsung tampil penuh:
   - animasi masuk kotak (famNodeEnter), garis "tumbuh" (famLineGrow),
     titik pasangan/silang (famDotPop, famCrossFadeIn) DIMATIKAN;
   - kedip highlight pencarian (filter drop-shadow) diganti outline diam;
   - transisi hover/redup & efek skala/bayangan dibuang.
   Keadaan akhirnya sama dengan jalur prefers-reduced-motion yang sudah
   ada. JS tidak bergantung pada animasi ini, jadi --line-delay/--node-delay
   yang masih ditulis js/silsilah.js tak berpengaruh (tidak perlu diubah).
   Fitur tetap utuh: zoom/geser, hover, mode fokus, pencarian.
====================================================== */
.silsilah-node,
.silsilah-line,
.silsilah-spouse-mark,
.silsilah-spouse-mark-wafat,
.silsilah-cross-dot,
.silsilah-node-highlight rect.silsilah-node-box {
  animation: none;
}
.silsilah-node { opacity: 1; transition: none; }
.silsilah-line { stroke-dashoffset: 0; }
.silsilah-line-cross { opacity: 0.85; }
.silsilah-spouse-mark,
.silsilah-spouse-mark-wafat,
.silsilah-cross-dot { opacity: 1; }
.silsilah-node rect.silsilah-node-box { transition: none; }
.silsilah-tree-svg.silsilah-dim .silsilah-node > * { transition: none; }

/* ======================================================
   HEADER DASHBOARD UTAMA — GAYA ZED (9 Nov 2026)
   Header jadi "title bar" ramping seperti Zed: latar sama dengan sidebar
   (--zed-bg-side), tepi hairline, tanpa bayangan, item-item rapat dengan
   sudut 6px, label status memakai monospace kecil, ikon netral (warna
   hanya untuk status online/offline & nominal). Hanya DESKTOP (>=1024px);
   layout HP/tablet (aturan ringkas yang sudah ada) tidak diubah. Berlaku
   di kedua tema; tepi header SOLID di kedua tema (keputusan user, 9 Nov
   2026), berbeda dari sidebar/tabel mode gelap yang tetap putus-putus.
====================================================== */
@media (min-width: 1024px) {
  .header {
    margin: var(--space-16) 0 var(--space-16);
    padding: var(--space-8) var(--space-12);
    background: var(--zed-bg-side);
    border: 1px solid var(--zed-line);
    border-radius: 8px;
    box-shadow: none;
    align-items: center;
    gap: var(--space-10);
  }
  .header .book-selector { gap: var(--space-8); }

  /* Badge sinkronisasi: kapsul hairline, teks mono, warna hanya utk status */
  .header .sync-status-container {
    border: 1px solid var(--zed-line);
    border-radius: 6px;
    font-family: var(--font-mono, monospace);
    letter-spacing: 0.03em;
  }
  .header .sync-status-container.online .sync-status-badge { background: var(--zed-add); }
  .header .sync-status-container.offline .sync-status-badge { background: var(--zed-del); }
  .header .device-id-badge {
    background: transparent;
    color: var(--ink-muted);
    border-left: 1px solid var(--zed-line);
  }
  .header .sync-time-badge { border-left-color: var(--zed-line); color: var(--ink-faint); }

  /* Pemilih buku (select native & dropdown kustom) */
  .header .book-select,
  .header .cs-trigger {
    border: 1px solid var(--zed-line);
    border-radius: 6px;
    background: var(--paper);
    box-shadow: none;
  }
  .header .book-select:focus,
  .header .cs-trigger:hover,
  .header .cs-trigger:focus-visible {
    border-color: var(--accent);
    box-shadow: none;
  }

  /* Info tanggal: ikon netral, pemisah hairline */
  .header-info .hi-cal-icon { color: var(--ink-faint); }
  .header-info .hi-last { border-left-color: var(--zed-line); }

  /* Tombol Audit Mingguan: bukan pil, hairline 6px, hover = latar halus */
  .wa-header-btn {
    border: 1px solid var(--zed-line);
    border-radius: 6px;
    background: transparent;
    font-weight: 500;
    padding: var(--space-4) var(--space-10);
    transition: none;
  }
  .wa-header-btn:hover { background: var(--zed-hover); border-color: var(--zed-line); }
}

/* ======================================================
   KARTU STATISTIK & PERENCANAAN KEUANGAN — PADAT ALA ZED (9 Nov 2026)
   Berlaku untuk .stat-card di dashboard utama: Total Pemasukan/Pengeluaran,
   Info Pasar (Kurs/Emas), dan kartu Perencanaan Keuangan (#finCardsGrid),
   di kedua tema. Padding & jarak dikecilkan, sudut 8px, tepi hairline 1px,
   angka satu tingkat lebih kecil, keterangan rapat, hover statis (tanpa
   terangkat): hanya kartu yang bisa diklik (punya data-onclick) berganti
   warna tepi. Hanya >=769px; HP tidak berubah (sudah ringkas).
====================================================== */
@media (min-width: 769px) {
  .stats-grid,
  .stats-merged-inner { gap: var(--space-8); }
  .stats-grid { margin-bottom: var(--space-10); }
  #finCardsGrid { margin-bottom: var(--space-10); }
  .expense-chart-header.fin-cards-header {
    margin-top: var(--space-10);
    margin-bottom: var(--space-8);
  }

  :root .stat-card,
  :root .stat-card-compact,
  :root .stats-merged-inner .stat-card,
  :root .stats-merged-inner .stat-card-compact,
  :root #finCardsGrid .stat-card {
    padding: var(--space-8) var(--space-12);
    border-width: 1px;
    border-color: var(--zed-line);
    border-radius: 8px;
    transition: none;
  }
  :root .stat-card:hover {
    transform: none;
    border-color: var(--zed-line);
  }
  :root .stat-card[data-onclick]:hover { border-color: var(--accent); }

  :root .stat-label {
    font-size: var(--text-2xs);
    font-weight: 500;
    letter-spacing: 0;
  }
  :root .stat-value,
  :root .stats-merged-inner .stat-value,
  :root #finCardsGrid .stat-value {
    font-size: var(--text-xl);
    margin-top: var(--space-2);
    letter-spacing: -0.01em;
  }
  /* Keterangan di bawah angka (teks kecil inline): rapatkan jarak & tinggi baris */
  .stat-card .stat-value ~ div { margin-top: 1px !important; line-height: 1.35; }
  #goldValueRow { margin-top: var(--space-4) !important; padding-top: var(--space-4) !important; }
  #fcKSGapInfo { margin-top: var(--space-4) !important; padding: var(--space-2) var(--space-6) !important; }
}

/* ======================================================
   DASHBOARD UTAMA — JARAK ANTAR CARD SERAGAM (9 Nov 2026)
   Sebelumnya jarak vertikal antar blok dashboard beda-beda (banner 10,
   hero 14, kartu statistik 10-20, judul Perencanaan 10/14, anggaran 20,
   forecast 16, grafik 20, tabel 12-20) dan beda dari jarak horizontal
   antar kartu (12). Sekarang SATU token --dash-gap dipakai untuk semuanya:
   jarak antar blok (vertikal), antar kartu dalam grid (horizontal), dan
   judul section -> kartunya. Ubah ritme dashboard cukup dari token ini.
   10px di desktop/tablet, 8px di HP. Margin-atas blok dinolkan supaya
   jarak tidak menumpuk/berselisih dengan margin-bawah blok sebelumnya.
====================================================== */
:root { --dash-gap: var(--space-10); }
@media (max-width: 768px) {
  :root { --dash-gap: var(--space-8); }
}
#dashboardView > .offline-warning-bar,
#dashboardView > .wa-banner,
#dashboardView > .balance-hero,
#dashboardView > .stats-merged,
#dashboardView > #finCardsGrid,
#dashboardView > .budget-mini,
#dashboardView > .forecast-card,
#dashboardView > .expense-chart-section,
#dashboardView > .controls,
#dashboardView > .table-container {
  margin-top: 0;
  margin-bottom: var(--dash-gap);
}
/* Banner pengingat menulis margin-bottom inline di index.html */
#dashboardView > .pr-banner {
  margin-top: 0;
  margin-bottom: var(--dash-gap) !important;
}
/* Judul section "Perencanaan Keuangan": jarak ke kartunya = jarak antar blok */
#dashboardView > .fin-cards-header {
  margin-top: 0;
  margin-bottom: var(--dash-gap);
}
/* Grid kartu: jarak horizontal = vertikal */
#dashboardView .stats-grid,
#dashboardView .stats-merged-inner { gap: var(--dash-gap); }
/* Grid yang menumpuk (area sempit): grid pertama memberi jarak ke label/grid berikutnya;
   grid Info Pasar tetap 0 karena jarak ke bawahnya diatur .stats-merged */
#dashboardView .stats-merged .stats-grid:not(.stats-grid-market) { margin-bottom: var(--dash-gap); }
#dashboardView .stats-merged .stats-grid-market { margin-bottom: 0; }

/* ======================================================
   Setelan: kartu Database Cloud (paling atas, tanpa toggle)
   Markup di index.html (.setelan-cloud-card, data-no-acc) -- dilewati
   accordion (js/settings.js). Hanya memakai token warna/radius yang
   sudah ada, jadi otomatis ikut mode terang & gelap.
====================================================== */
#setelanModal .data-management-panel.setelan-cloud-card {
  padding: var(--space-16);
  border-radius: var(--radius-lg, var(--radius));
  border-color: var(--rule);
  background: var(--paper-warm);
}
.setelan-cloud-card .cloud-card-head {
  display: flex; align-items: center; gap: var(--space-12);
  margin-bottom: var(--space-14);
}
.setelan-cloud-card .cloud-card-icon {
  flex: 0 0 auto; width: 40px; height: 40px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-lg, var(--radius));
  background: var(--accent-lt); color: var(--accent);
}
.setelan-cloud-card .cloud-card-titles { flex: 1 1 auto; min-width: 0; }
.setelan-cloud-card .cloud-card-title {
  font-size: var(--text-md, var(--text-sm)); font-weight: 700; color: var(--ink); line-height: 1.25;
}
.setelan-cloud-card .cloud-card-sub {
  font-size: var(--text-xs); color: var(--ink-muted); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.setelan-cloud-card .cloud-card-status {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--space-6);
  font-size: var(--text-2xs); font-weight: 600; white-space: nowrap;
  padding: var(--space-4) var(--space-10); border-radius: var(--radius-pill, 999px);
  background: var(--rule); color: var(--ink-muted);
}
.setelan-cloud-card .cloud-card-status i {
  width: 7px; height: 7px; border-radius: 50%; background: currentColor; display: inline-block;
}
.setelan-cloud-card .cloud-card-status[data-state="on"]   { background: var(--success-lt); color: var(--success); }
.setelan-cloud-card .cloud-card-status[data-state="warn"] { background: var(--warning-lt); color: var(--warning); }
.setelan-cloud-card .cloud-card-status[data-state="off"]  { background: var(--danger-lt);  color: var(--danger); }

.setelan-cloud-card .cloud-card-endpoint,
.setelan-cloud-card .cloud-card-block {
  background: var(--paper); border: 1px solid var(--rule);
  border-radius: var(--radius); padding: var(--space-12) var(--space-14);
}
.setelan-cloud-card .cloud-card-label {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-8);
  font-size: var(--text-xs); font-weight: 700; color: var(--ink);
  margin-bottom: var(--space-8);
}
.setelan-cloud-card .cloud-card-label--spaced {
  margin-top: var(--space-14); padding-top: var(--space-12); border-top: 1px dashed var(--rule);
}
.setelan-cloud-card .cloud-card-url {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--text-xs); color: var(--ink); word-break: break-all;
  background: var(--paper-warm); border: 1px solid var(--rule);
  border-radius: var(--radius-sm); padding: var(--space-8) var(--space-10);
}
.setelan-cloud-card .cloud-card-actions {
  display: flex; gap: var(--space-8); flex-wrap: wrap; margin-top: var(--space-10);
}
.setelan-cloud-card .cloud-card-actions .btn { flex: 1 1 160px; }
.setelan-cloud-card .cloud-card-grid {
  display: grid; grid-template-columns: 1fr; gap: var(--space-10); margin-top: var(--space-10);
}
@media (min-width: 760px) {
  .setelan-cloud-card .cloud-card-grid { grid-template-columns: 1fr 1fr; align-items: start; }
}
.setelan-cloud-card .cloud-card-refresh {
  font-size: var(--text-2xs); font-weight: 600; cursor: pointer;
  padding: var(--space-2) var(--space-10); border-radius: var(--radius-sm);
  border: 1px solid var(--rule); background: var(--paper); color: var(--ink-muted);
}
.setelan-cloud-card .cloud-card-refresh:hover:not(:disabled) { color: var(--ink); border-color: var(--ink-faint); }
.setelan-cloud-card .cloud-card-refresh:disabled { opacity: .6; cursor: default; }
.setelan-cloud-card .cloud-card-empty {
  font-size: var(--text-xs); color: var(--ink-faint); text-align: center; padding: var(--space-8) 0;
}
.setelan-cloud-card #connectionStatus:empty { display: none; }
.setelan-cloud-card .setelan-collapse { margin: var(--space-8) 0 0; }
@media (max-width: 480px) {
  .setelan-cloud-card .cloud-card-head { flex-wrap: wrap; }
  .setelan-cloud-card .cloud-card-status { order: 3; }
}

/* ======================================================
   POLES TOTAL UI SETELAN (v361+)
   - Kelompok bagian (Koneksi, Integrasi, Keamanan, Zona Bahaya) lewat
     CSS `order`; markup panel & id/handler TIDAK dipindah.
   - Baris panel: ikon di kiri, judul + badge, chevron di kanan.
   - Kontrol (input, tombol, catatan) seragam. Hanya token var(--...).
====================================================== */
#setelanModal .setelan-tab-content { gap: var(--space-8); padding-bottom: var(--space-16); }
#setelanModal .setelan-jump { order: -1; }
#setelanModal .setelan-group-label[data-grp="1"] { order: 0; }
#setelanModal .setelan-group-label[data-grp="2"] { order: 10; }
#setelanModal .setelan-group-label[data-grp="3"] { order: 20; }
#setelanModal .setelan-group-label[data-grp="4"] { order: 30; }
#setelanModal .setelan-tab-panel[data-tab-panel="supabase"] { order: 1; }
#setelanModal .setelan-tab-panel[data-tab-panel="akun"] { order: 2; }
#setelanModal .setelan-tab-panel[data-tab-panel="devices"] { order: 3; }
#setelanModal .setelan-tab-panel[data-tab-panel="telegram"] { order: 11; }
#setelanModal .setelan-tab-panel[data-tab-panel="ai"] { order: 12; }
#setelanModal .setelan-tab-panel[data-tab-panel="hargaPanganWorker"] { order: 13; }
#setelanModal .setelan-tab-panel[data-tab-panel="gold"] { order: 14; }
#setelanModal .setelan-tab-panel[data-tab-panel="emasWorker"] { order: 15; }
#setelanModal .setelan-tab-panel[data-tab-panel="password"] { order: 21; }
#setelanModal .setelan-tab-panel[data-tab-panel="errorlog"] { order: 22; }
#setelanModal .setelan-tab-panel[data-tab-panel="archive"] { order: 31; }
#setelanModal .setelan-tab-panel[data-tab-panel="reset"] { order: 32; }

/* Chip lompat cepat */
#setelanModal .setelan-jump {
  display: flex; gap: var(--space-6); overflow-x: auto; flex: 0 0 auto;
  padding: var(--space-2) 0 var(--space-6); scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
#setelanModal .setelan-jump::-webkit-scrollbar { display: none; }
#setelanModal .setelan-jump .link-chip { flex: 0 0 auto; white-space: nowrap; }

/* Label kelompok */
#setelanModal .setelan-group-label {
  display: flex; align-items: center; gap: var(--space-10); flex: 0 0 auto;
  margin: var(--space-10) 0 var(--space-2);
  font-size: var(--text-2xs); font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-faint);
}
#setelanModal .setelan-group-label::after { content: ''; flex: 1 1 auto; height: 1px; background: var(--rule); }
#setelanModal .setelan-group-label--danger { color: var(--danger); }
#setelanModal .setelan-group-label--danger::after { background: color-mix(in srgb, var(--danger) 28%, var(--rule)); }
body.lockscreen-restricted #setelanModal .setelan-jump,
body.lockscreen-restricted #setelanModal .setelan-group-label { display: none !important; }
#setelanModal .setelan-tab-panel { scroll-margin-top: var(--space-12); }

/* Kartu panel (accordion) */
#setelanModal .data-management-panel.setelan-acc {
  border-radius: var(--radius-lg, var(--radius));
  border: 1px solid var(--rule);
  background: var(--paper);
  padding: 0 var(--space-16);
  transition: border-color .15s ease;
}
#setelanModal .data-management-panel.setelan-acc:hover { border-color: var(--ink-faint); }
#setelanModal .data-management-panel.setelan-acc:not(.is-collapsed) {
  border-color: color-mix(in srgb, var(--accent) 35%, var(--rule));
  padding-bottom: var(--space-16);
}
#setelanModal .setelan-acc-head { min-height: 52px; gap: 0; }
#setelanModal .setelan-acc:not(.is-collapsed) > .setelan-acc-head {
  border-bottom: 1px solid var(--rule); margin-bottom: var(--space-14);
}

/* Ikon kiri per panel */
#setelanModal .data-management-panel.setelan-acc > .setelan-acc-head::before {
  width: 18px; height: 18px; margin-right: var(--space-10);
  background-color: var(--sk-ic-color, var(--accent));
  -webkit-mask: var(--sk-ic) center / contain no-repeat;
  mask: var(--sk-ic) center / contain no-repeat;
  transform: none !important;
}
#setelanModal .data-management-panel.setelan-acc > .setelan-acc-head:hover::before { background-color: var(--sk-ic-color, var(--accent)); }
#setelanModal .setelan-tab-panel[data-tab-panel="supabase"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17.5 19a4.5 4.5 0 0 0 0-9 6 6 0 0 0-11.4 1.5A4 4 0 0 0 6.5 19h11z'/%3E%3C/svg%3E"); --sk-ic-color: var(--accent); }
#setelanModal .setelan-tab-panel[data-tab-panel="akun"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='12' cy='7' r='4'/%3E%3C/svg%3E"); --sk-ic-color: var(--accent); }
#setelanModal .setelan-tab-panel[data-tab-panel="telegram"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m22 2-7 20-4-9-9-4Z'/%3E%3Cpath d='M22 2 11 13'/%3E%3C/svg%3E"); --sk-ic-color: var(--accent); }
#setelanModal .setelan-tab-panel[data-tab-panel="devices"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='14' height='20' x='5' y='2' rx='2'/%3E%3Cpath d='M12 18h.01'/%3E%3C/svg%3E"); --sk-ic-color: var(--accent); }
#setelanModal .setelan-tab-panel[data-tab-panel="errorlog"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E"); --sk-ic-color: var(--warning); }
#setelanModal .setelan-tab-panel[data-tab-panel="ai"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m12 3-1.9 5.8a2 2 0 0 1-1.3 1.3L3 12l5.8 1.9a2 2 0 0 1 1.3 1.3L12 21l1.9-5.8a2 2 0 0 1 1.3-1.3L21 12l-5.8-1.9a2 2 0 0 1-1.3-1.3Z'/%3E%3C/svg%3E"); --sk-ic-color: var(--purple); }
#setelanModal .setelan-tab-panel[data-tab-panel="hargaPanganWorker"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 11 4-7'/%3E%3Cpath d='m19 11-4-7'/%3E%3Cpath d='M2 11h20'/%3E%3Cpath d='m3.5 11 1.6 7.4a2 2 0 0 0 2 1.6h9.8a2 2 0 0 0 2-1.6l1.7-7.4'/%3E%3C/svg%3E"); --sk-ic-color: var(--success); }
#setelanModal .setelan-tab-panel[data-tab-panel="gold"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='8' cy='8' r='6'/%3E%3Cpath d='M18.09 10.37A6 6 0 1 1 10.34 18'/%3E%3Cpath d='M7 6h1v4'/%3E%3Cpath d='m16.71 13.88.7.71-2.82 2.82'/%3E%3C/svg%3E"); --sk-ic-color: var(--warning); }
#setelanModal .setelan-tab-panel[data-tab-panel="emasWorker"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z'/%3E%3C/svg%3E"); --sk-ic-color: var(--warning); }
#setelanModal .setelan-tab-panel[data-tab-panel="password"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z'/%3E%3Ccircle cx='16.5' cy='7.5' r='.5'/%3E%3C/svg%3E"); --sk-ic-color: var(--accent); }
#setelanModal .setelan-tab-panel[data-tab-panel="archive"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='20' height='5' x='2' y='3' rx='1'/%3E%3Cpath d='M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8'/%3E%3Cpath d='M10 12h4'/%3E%3C/svg%3E"); --sk-ic-color: var(--danger); }
#setelanModal .setelan-tab-panel[data-tab-panel="reset"] { --sk-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8'/%3E%3Cpath d='M3 3v5h5'/%3E%3C/svg%3E"); --sk-ic-color: var(--danger); }

/* Chevron kanan: buka = menghadap atas */
#setelanModal .data-management-panel.setelan-acc > .setelan-acc-head::after {
  content: ''; flex: 0 0 auto; width: 16px; height: 16px; margin-left: var(--space-8);
  background-color: var(--ink-faint);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform .18s ease; transform: rotate(180deg);
}
#setelanModal .setelan-acc.is-collapsed > .setelan-acc-head::after { transform: rotate(0deg); }
#setelanModal .setelan-acc-head:not(:has(> button, > .btn))::after { margin-left: auto; }
#setelanModal .setelan-acc-head > .setelan-badge,
#setelanModal .setelan-acc-head > span > .setelan-badge { margin-left: var(--space-10); }
#setelanModal .setelan-acc-head:hover::after { background-color: var(--ink-muted); }
#setelanModal .setelan-acc-head > span:first-child { font-weight: 600; }

/* Zona bahaya */
#setelanModal .setelan-acc:has(> .setelan-title--red) { border-color: color-mix(in srgb, var(--danger) 30%, var(--rule)); }
#setelanModal .setelan-acc:has(> .setelan-title--red):hover { border-color: var(--danger); }
#setelanModal .setelan-acc:has(> .setelan-title--red):not(.is-collapsed) > .setelan-acc-head {
  border-bottom-color: color-mix(in srgb, var(--danger) 28%, var(--rule));
}
#setelanModal .setelan-acc-head.setelan-title--red { color: var(--danger) !important; }

/* Kontrol seragam */
#setelanModal .form-control {
  border-radius: var(--radius); min-height: 40px;
  transition: border-color .12s ease, box-shadow .12s ease;
}
#setelanModal .form-control:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
#setelanModal .setelan-acc .btn:not(.btn-mini) { min-height: 40px; border-radius: var(--radius); }
#setelanModal .setelan-acc .setelan-actions-row { margin-top: var(--space-8); }
#setelanModal .setelan-acc .setelan-desc { color: var(--ink-muted); }
#setelanModal .setelan-hint { line-height: 1.5; }

/* Catatan info (pengganti kotak biru inline) */
#setelanModal .setelan-note {
  margin-top: var(--space-12); padding: var(--space-10) var(--space-14);
  font-size: var(--text-xs); line-height: 1.75; color: var(--ink-muted);
  background: var(--paper-warm); border: 1px solid var(--rule);
  border-left: 3px solid var(--info); border-radius: var(--radius-sm);
}
#setelanModal .setelan-note b { color: var(--ink); }

/* Tombol Telegram: warna merek, tetap terbaca di mode gelap */
#setelanModal .setelan-btn-tg { background: #0088cc; border-color: #0088cc; color: #fff; }
#setelanModal .setelan-btn-tg:hover { background: #0077b3; border-color: #0077b3; }

/* Layar sempit */
@media (max-width: 600px) {
  #setelanModal .data-management-panel.setelan-acc { padding: 0 var(--space-12); }
  #setelanModal .data-management-panel.setelan-acc:not(.is-collapsed) { padding-bottom: var(--space-12); }
  #setelanModal .setelan-acc-head { min-height: 48px; }
  #setelanModal .setelan-acc-head { flex-wrap: wrap; row-gap: var(--space-2); padding-top: var(--space-6); padding-bottom: var(--space-6); }
}
@media (prefers-reduced-motion: reduce) {
  #setelanModal .setelan-acc-head::after, #setelanModal .data-management-panel.setelan-acc { transition: none; }
}

/* ======================================================
   Kesehatan & Kuota Free Tier (js/book.js refreshStorageEstimate)
   Hanya token var(--...); state: ok | warn | bad | info
====================================================== */
.setelan-cloud-card .cloud-card-block--wide { grid-column: 1 / -1; }
#setelanModal .ch-loading { font-size: var(--text-xs); color: var(--ink-faint); text-align: center; padding: var(--space-14) 0; }
#setelanModal .ch-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: var(--ink-faint); }
#setelanModal .ch-dot--ok   { background: var(--success); }
#setelanModal .ch-dot--warn { background: var(--warning); }
#setelanModal .ch-dot--bad  { background: var(--danger); }
#setelanModal .ch-dot--info { background: var(--ink-faint); }

#setelanModal .ch-verdict {
  display: flex; align-items: center; gap: var(--space-12);
  padding: var(--space-12) var(--space-14); border-radius: var(--radius);
  background: var(--success-lt); color: var(--success); margin-bottom: var(--space-12);
}
#setelanModal .ch-verdict[data-state="warn"] { background: var(--warning-lt); color: var(--warning); }
#setelanModal .ch-verdict[data-state="bad"]  { background: var(--danger-lt);  color: var(--danger); }
#setelanModal .ch-verdict > i {
  flex: 0 0 auto; width: 12px; height: 12px; border-radius: 50%; background: currentColor;
  box-shadow: 0 0 0 4px color-mix(in srgb, currentColor 22%, transparent);
}
#setelanModal .ch-verdict > div { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
#setelanModal .ch-verdict b { font-size: var(--text-sm); }
#setelanModal .ch-verdict span { font-size: var(--text-xs); color: var(--ink-muted); line-height: 1.5; }
#setelanModal .ch-verdict em { flex: 0 0 auto; font-style: normal; font-size: var(--text-2xs); color: var(--ink-muted); white-space: nowrap; }

#setelanModal .ch-tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-8); }
@media (min-width: 760px) { #setelanModal .ch-tiles { grid-template-columns: repeat(4, 1fr); } }
#setelanModal .ch-tile {
  background: var(--paper-warm); border: 1px solid var(--rule); border-radius: var(--radius-sm);
  padding: var(--space-10) var(--space-12); display: flex; flex-direction: column; gap: 2px; min-width: 0;
}
#setelanModal .ch-tile-top { display: flex; align-items: center; gap: var(--space-6); font-size: var(--text-2xs); font-weight: 600; color: var(--ink-muted); }
#setelanModal .ch-tile b { font-size: var(--text-sm); color: var(--ink); }
#setelanModal .ch-tile small { font-size: var(--text-2xs); color: var(--ink-faint); line-height: 1.4; }

#setelanModal .ch-section {
  margin: var(--space-14) 0 var(--space-8); font-size: var(--text-2xs); font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint);
}
#setelanModal .ch-bar { margin-bottom: var(--space-10); }
#setelanModal .ch-bar-top { display: flex; justify-content: space-between; gap: var(--space-8); font-size: var(--text-xs); color: var(--ink-muted); margin-bottom: var(--space-4); flex-wrap: wrap; }
#setelanModal .ch-bar-top > span:first-child { font-weight: 600; color: var(--ink); }
#setelanModal .ch-bar-top b { color: var(--ink); margin-left: var(--space-4); }
#setelanModal .ch-bar-track { height: 8px; border-radius: 999px; background: var(--rule); overflow: hidden; }
#setelanModal .ch-bar-fill { height: 100%; border-radius: 999px; background: var(--success); transition: width .4s ease; }
#setelanModal .ch-bar[data-state="warn"] .ch-bar-fill { background: var(--warning); }
#setelanModal .ch-bar[data-state="bad"]  .ch-bar-fill { background: var(--danger); }
#setelanModal .ch-bar-note { font-size: var(--text-2xs); color: var(--ink-faint); margin-top: var(--space-4); line-height: 1.5; }

#setelanModal .ch-rows {
  display: grid; grid-template-columns: 1fr auto 1fr auto; gap: var(--space-4) var(--space-12);
  font-size: var(--text-xs); color: var(--ink-muted);
  background: var(--paper-warm); border-radius: var(--radius-sm); padding: var(--space-10) var(--space-12);
}
#setelanModal .ch-rows b { color: var(--ink); text-align: right; }
@media (max-width: 520px) { #setelanModal .ch-rows { grid-template-columns: 1fr auto; } }

#setelanModal .ch-checks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-8); }
#setelanModal .ch-checks li { display: flex; gap: var(--space-10); align-items: flex-start; }
#setelanModal .ch-checks .ch-dot { margin-top: 5px; }
#setelanModal .ch-checks li > div { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
#setelanModal .ch-checks b { font-size: var(--text-xs); color: var(--ink); }
#setelanModal .ch-checks span { font-size: var(--text-2xs); color: var(--ink-muted); line-height: 1.5; }

#setelanModal .ch-limits { display: flex; flex-wrap: wrap; gap: var(--space-6); }
#setelanModal .ch-limits span {
  font-size: var(--text-2xs); color: var(--ink-muted); background: var(--paper-warm);
  border: 1px solid var(--rule); border-radius: 999px; padding: var(--space-2) var(--space-10);
}
#setelanModal .ch-limits b { color: var(--ink); }
#setelanModal .ch-foot { margin-top: var(--space-12); font-size: var(--text-2xs); color: var(--ink-faint); line-height: 1.6; }

/* ======================================================
   [GAYA KARTU REFERENSI — MODE TERANG] 12 Nov 2026
   Meniru gaya kartu @githubprojects: kertas krem hangat, tinta hitam
   pekat, SATU aksen lime (#B8F02A) untuk penanda aktif/tombol utama/
   garis bawah label, garis hairline tipis, tipografi tebal & rapat.
   Hanya mode terang (:root:not([data-theme="dark"])); mode gelap tidak
   tersentuh. Lime dipakai sebagai ISIAN (bukan warna teks) karena
   kontrasnya rendah di atas krem -- teks di atasnya selalu --ink.
   --accent/--brand sengaja hitam supaya semua tempat lama yang memakai
   "background: var(--accent); color:#fff" tetap terbaca.
====================================================== */
:root:not([data-theme="dark"]) {
  --ink:        #111110;
  --ink-muted:  #5F5B53;
  --ink-faint:  #98938A;
  --paper:      #F8F6F1;
  --paper-warm: #EFEBE3;
  --rule:       #D9D3C8;
  --accent:     #111110;
  --accent-lt:  #E9F7B8;
  --lime:       #B8F02A;
  --lime-dark:  #A3DB17;
  --success:    #4C7A1E;
  --success-lt: #E6EFCF;
  --danger:     #B5432F;
  --danger-lt:  #F4E3DC;
  --warning:    #A87A12;
  --warning-lt: #F2EAD0;
  --purple:     #5F5B53;
  --purple-lt:  #E6E2D9;
  --brand:      #111110;
  --brand-dark: #000000;
  --fase:       #5F5B53;
  --fase-lt:    #E6E2D9;
  --info:       #5F5B53;
  --info-lt:    #E6E2D9;
  --chat-user:  #111110;
  --ink-inv:    #F8F6F1;
  --paper-inv:  #111110;
  --row-alt:    #F3F0E9;
  --topbar-btn-bg:        rgba(17,17,16,0.05);
  --topbar-btn-hover-bg:  rgba(17,17,16,0.10);
  --topbar-item-hover-bg: rgba(17,17,16,0.05);
  --topbar-item-active-bg: var(--lime);
  --topbar-item-active-color: var(--ink);
  --radius-sm: 10px;
  --radius:    16px;
  --radius-lg: 22px;
}

/* Latar: krem + grid hairline sangat tipis (seperti kertas di gambar).
   Kartu/tabel/modal bersolid --paper sehingga grid hanya tampak di celah. */
:root:not([data-theme="dark"]) body {
  background-color: var(--paper-warm);
  background-image:
    linear-gradient(rgba(17,17,16,0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(17,17,16,0.035) 1px, transparent 1px);
  background-size: 72px 72px;
}

/* Tipografi: judul tebal & rapat */
:root:not([data-theme="dark"]) h1,
:root:not([data-theme="dark"]) h2,
:root:not([data-theme="dark"]) h3,
:root:not([data-theme="dark"]) .modal-header h3 {
  font-weight: 800;
  letter-spacing: -0.03em;
}
:root:not([data-theme="dark"]) .app-sidebar-brand,
:root:not([data-theme="dark"]) .stat-value,
:root:not([data-theme="dark"]) .lock-title {
  font-weight: 800;
  letter-spacing: -0.03em;
}

/* Label kecil gaya "02 / TOP 5": kapital, rapat-lebar, garis bawah lime */
:root:not([data-theme="dark"]) .stat-label {
  display: inline-block;
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  padding-bottom: var(--space-5);
  background: linear-gradient(var(--lime), var(--lime)) left bottom / 22px 3px no-repeat;
}

/* Kartu: krem terang, hairline, tanpa shadow */
:root:not([data-theme="dark"]) .stat-card,
:root:not([data-theme="dark"]) .table-container,
:root:not([data-theme="dark"]) .modal-content {
  background: var(--paper);
  border-color: var(--rule);
}
:root:not([data-theme="dark"]) .stat-card:hover { border-color: var(--ink); }
/* Kartu hero saldo = "kartu ilustrasi" bergaris tinta, seperti di gambar */
:root:not([data-theme="dark"]) .balance-hero {
  background: var(--paper);
  border: 1.5px solid var(--ink);
}
:root:not([data-theme="dark"]) .header {
  background: var(--paper);
  border-color: var(--rule);
}

/* Tombol utama = pil lime, teks hitam tebal (seperti chip "PYTHON") */
:root:not([data-theme="dark"]) .btn-primary,
:root:not([data-theme="dark"]) .manage-books-btn {
  background: var(--lime);
  color: var(--ink);
  border-color: var(--lime);
  font-weight: 800;
  letter-spacing: -0.01em;
}
:root:not([data-theme="dark"]) .btn-primary:hover:not(:disabled),
:root:not([data-theme="dark"]) .manage-books-btn:hover:not(:disabled) {
  background: var(--lime-dark);
  border-color: var(--lime-dark);
}
:root:not([data-theme="dark"]) .btn-primary:disabled {
  background: var(--rule);
  border-color: var(--rule);
  color: var(--ink-faint);
}
:root:not([data-theme="dark"]) .btn-secondary {
  background: transparent;
  border-color: var(--ink);
  color: var(--ink);
}
:root:not([data-theme="dark"]) .btn-secondary:hover {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}

/* Chip filter aktif = lime + teks hitam (menggantikan blok hitam) */
:root:not([data-theme="dark"]) .filter-btn.active {
  background: var(--lime);
  border-color: var(--lime);
  color: var(--ink);
  font-weight: 800;
}

/* Input: fokus bergaris tinta */
:root:not([data-theme="dark"]) .form-control,
:root:not([data-theme="dark"]) input,
:root:not([data-theme="dark"]) textarea,
:root:not([data-theme="dark"]) select {
  background-color: var(--paper);
  border-color: var(--rule);
}
:root:not([data-theme="dark"]) .form-control:focus {
  border-color: var(--ink);
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lime) 55%, transparent);
}

/* Tabel: header kapital hitam di atas garis tinta tipis */
:root:not([data-theme="dark"]) th {
  background: var(--paper-warm);
  color: var(--ink);
  border-bottom: 1px solid var(--ink);
}
:root:not([data-theme="dark"]) tr:hover td { background: var(--accent-lt); }

/* Sidebar: menu aktif lime + teks hitam */
:root:not([data-theme="dark"]) .app-nav-item.active { font-weight: 800; }

/* ======================================================
   [GAYA KARTU REFERENSI — LAPISAN 2: LEBIH DALAM] 12 Nov 2026
   Lanjutan blok di atas. Hanya mode terang. Menambah: penomoran seksi
   "01 /", garis bawah lime di judul, motif "///", kartu modal bergaris
   tinta, layar kunci berkisi, badge pil, toast, progress, fokus/seleksi.
====================================================== */

/* Seleksi teks & fokus keyboard */
:root:not([data-theme="dark"]) ::selection { background: var(--lime); color: var(--ink); }
:root:not([data-theme="dark"]) :focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
:root:not([data-theme="dark"]) input[type="checkbox"],
:root:not([data-theme="dark"]) input[type="radio"],
:root:not([data-theme="dark"]) input[type="range"] { accent-color: var(--ink); }

/* Sidebar: label grup bernomor "01 / KEUANGAN" + garis bawah lime */
:root:not([data-theme="dark"]) #appSidebar { counter-reset: skgrp; }
:root:not([data-theme="dark"]) .app-nav-group-label {
  counter-increment: skgrp;
  color: var(--ink);
  font-weight: 800;
  letter-spacing: .1em;
}
:root:not([data-theme="dark"]) .app-nav-group-label::before {
  content: counter(skgrp, decimal-leading-zero) " / ";
  color: var(--ink-faint);
  font-weight: 700;
}
:root:not([data-theme="dark"]) .app-sidebar-brand {
  font-weight: 800;
  letter-spacing: -0.02em;
  border-bottom-color: var(--ink);
}
:root:not([data-theme="dark"]) .app-nav-footer { border-top-color: var(--ink); }

/* Judul panel: tebal, kapital kecil, garis bawah lime pendek */
:root:not([data-theme="dark"]) .panel-title {
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  padding-bottom: var(--space-6);
  background: linear-gradient(var(--lime), var(--lime)) left bottom / 28px 3px no-repeat;
}

/* Hero saldo: angka tebal + motif "///" lime di sudut (seperti gambar 3) */
:root:not([data-theme="dark"]) .balance-hero-value { font-weight: 800; letter-spacing: -0.03em; }
:root:not([data-theme="dark"]) .balance-hero::after {
  content: "///";
  position: absolute;
  top: var(--space-12);
  right: var(--space-16);
  font-family: var(--font-mono);
  font-size: var(--text-md);
  font-weight: 800;
  letter-spacing: .05em;
  color: var(--lime-dark);
  pointer-events: none;
}

/* Modal: latar redup netral, kartu bergaris tinta, header bergaris tinta */
:root:not([data-theme="dark"]) .modal { background: rgba(17,17,16,0.42); }
:root:not([data-theme="dark"]) .modal-content { border: 1.5px solid var(--ink); }
:root:not([data-theme="dark"]) .modal-header { border-bottom: 1px solid var(--ink); }
:root:not([data-theme="dark"]) .modal-header h3 { font-weight: 800; letter-spacing: -0.03em; }
:root:not([data-theme="dark"]) .modal-close:hover { color: var(--ink); background: var(--lime); }
:root:not([data-theme="dark"]) .modal-footer { border-top-color: var(--rule); }
:root:not([data-theme="dark"]) .cs-dropdown { border-color: var(--ink); background: var(--paper); }

/* Tombol pil (seperti chip "PYTHON" di gambar) */
:root:not([data-theme="dark"]) .btn-primary,
:root:not([data-theme="dark"]) .btn-secondary,
:root:not([data-theme="dark"]) .manage-books-btn { border-radius: var(--radius-pill); }

/* Badge pemasukan/pengeluaran = pil kecil kapital */
:root:not([data-theme="dark"]) .badge-inc,
:root:not([data-theme="dark"]) .badge-exp {
  border-radius: var(--radius-pill);
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
}
:root:not([data-theme="dark"]) .badge-inc { background: var(--lime); color: var(--ink); }
:root:not([data-theme="dark"]) .badge-exp { background: var(--danger-lt); color: var(--danger); }

/* Toast: kartu tinta, penanda lime di kiri */
:root:not([data-theme="dark"]) .toast-message {
  background: var(--ink);
  color: var(--paper);
  border-left: 4px solid var(--lime);
  font-weight: 600;
}

/* Progress/loader: trek krem-tua, isi tinta (loader lime di atas tinta) */
:root:not([data-theme="dark"]) .budget-mini-progress-fill { background: var(--ink); }
:root:not([data-theme="dark"]) .budget-mini-progress-fill.warning { background: var(--warning); }
:root:not([data-theme="dark"]) .budget-mini-progress-fill.danger  { background: var(--danger); }
:root:not([data-theme="dark"]) .sk-page-loader-bar { background: var(--ink); }
:root:not([data-theme="dark"]) .sk-page-loader-bar::after,
:root:not([data-theme="dark"]) .sk-page-loader-fill { background: var(--lime); }
:root:not([data-theme="dark"]) .sk-page-loader-card { border: 1.5px solid var(--ink); }
:root:not([data-theme="dark"]) .sk-page-loader-title { font-weight: 800; }

/* Layar kunci: kertas krem + kisi hairline yang memudar ke tepi */
:root:not([data-theme="dark"]) #passwordLockScreen { background: var(--paper-warm); }
:root:not([data-theme="dark"]) #passwordLockScreen::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(17,17,16,0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(17,17,16,0.07) 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: radial-gradient(70% 60% at 50% 42%, #000 0%, transparent 100%);
          mask-image: radial-gradient(70% 60% at 50% 42%, #000 0%, transparent 100%);
}
:root:not([data-theme="dark"]) #passwordLockScreen .lock-card { border: 1.5px solid var(--ink); }
:root:not([data-theme="dark"]) .lock-brand-name { font-weight: 800; letter-spacing: -0.02em; }
:root:not([data-theme="dark"]) .lock-input:focus {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lime) 55%, transparent);
}
:root:not([data-theme="dark"]) .lock-account-item:hover,
:root:not([data-theme="dark"]) .lock-account-item.selected { border-color: var(--ink); background: var(--accent-lt); }
:root:not([data-theme="dark"]) .lock-insight-card { background: var(--paper-warm); }
:root:not([data-theme="dark"]) .lock-insight-eyebrow { color: var(--ink); font-weight: 700; }

/* Scrollbar tipis */
:root:not([data-theme="dark"]) * { scrollbar-width: thin; scrollbar-color: var(--ink-faint) transparent; }

/* ======================================================
   [GAYA KARTU REFERENSI — LAPISAN 3: SELARASKAN DENGAN BLOK ZED TERANG]
   Blok "MODE TERANG — GAYA ZED" (9 Nov 2026) lebih awal di berkas ini
   masih memberi sidebar/header/menu aktif abu-abu & label grup huruf
   biasa di desktop. Di sini token --zed-* mode terang diselaraskan ke
   palet krem+lime, dan aturan yang sama-spesifik ditimpa (urutan akhir
   berkas menang). Mode gelap TIDAK tersentuh.
====================================================== */
:root:not([data-theme="dark"]) {
  --zed-bg-side: #E8E3D9;
  --zed-line:    var(--rule);
  --zed-hover:   rgba(17,17,16,0.06);
  --zed-active:  var(--lime);
  --zed-add:     color-mix(in srgb, var(--lime) 30%, transparent);
  --zed-del:     color-mix(in srgb, var(--danger) 12%, transparent);
}
:root:not([data-theme="dark"]) #appSidebar {
  background: var(--zed-bg-side);
  border-right: 1px solid var(--ink);
}
:root:not([data-theme="dark"]) .app-nav-item.active:not(:disabled),
:root:not([data-theme="dark"]) .app-nav-item.active:hover:not(:disabled) {
  background: var(--lime);
  color: var(--ink);
  font-weight: 800;
}
@media (min-width: 1024px) {
  :root:not([data-theme="dark"]) .app-nav-group-label {
    font-size: var(--text-2xs);
    font-weight: 800;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ink);
    padding: var(--space-12) var(--space-10) var(--space-4);
  }
  :root:not([data-theme="dark"]) .app-nav-item {
    border-radius: var(--radius-sm);
    font-weight: 600;
  }
  :root:not([data-theme="dark"]) .header {
    border-radius: var(--radius);
    background: var(--paper);
    border: 1px solid var(--rule);
  }
  :root:not([data-theme="dark"]) .header .book-select,
  :root:not([data-theme="dark"]) .header .cs-trigger,
  :root:not([data-theme="dark"]) .header .sync-status-container,
  :root:not([data-theme="dark"]) .wa-header-btn { border-radius: var(--radius-pill); }
  :root:not([data-theme="dark"]) .header .book-select:focus,
  :root:not([data-theme="dark"]) .header .cs-trigger:hover,
  :root:not([data-theme="dark"]) .header .cs-trigger:focus-visible { border-color: var(--ink); }
}
/* Kartu statistik: sudut sama dengan kartu lain (blok Zed memberi 8px) */
:root:not([data-theme="dark"]) .stat-card { border-radius: var(--radius); }

/* ======================================================
   [LOCK SCREEN FLAT] 12 Nov 2026 -- layar kunci & gerbang login didesain
   ulang: flat total (tanpa grid latar, gradasi, glow/shadow, animasi
   masuk), sudut nyaris siku (2px), tombol & input persegi. Warna tetap
   dari token tema (terang: krem + tinta + lime; gelap: arang + aksen),
   jadi otomatis ikut tema. Blok ini sengaja di PALING AKHIR berkas supaya
   menang atas aturan lock-* lama di atas.
====================================================== */
#passwordLockScreen,
#skLoginGateScreen {
  --lk-r: 2px;
  background: var(--paper-warm) !important;
  background-image: none !important;
}
#passwordLockScreen::before,
#skLoginGateScreen::before { content: none !important; display: none !important; }

#passwordLockScreen .lock-card,
#skLoginGateScreen .lock-card {
  max-width: 380px;
  padding: var(--space-28) var(--space-24) var(--space-24);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-top: 3px solid var(--ink);
  border-radius: var(--lk-r);
  box-shadow: none;
  animation: none;
  text-align: left;
}
@media (max-width: 480px) {
  #passwordLockScreen .lock-card,
  #skLoginGateScreen .lock-card { padding: var(--space-24) var(--space-18) var(--space-20); }
}

/* Merek: logo siku, nama kecil kapital */
#passwordLockScreen .lock-brand { justify-content: flex-start; margin-bottom: var(--space-24); }
.lock-brand-logo { border-radius: var(--lk-r, 2px); }
#passwordLockScreen .lock-brand-name {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}
#passwordLockScreen .lock-title,
#skLoginGateScreen .lock-title {
  font-size: var(--text-2xl);
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-align: left;
}
#skLoginGateScreen .lock-title { margin-bottom: var(--space-20); }
#passwordLockScreen .lock-sub { text-align: left; }

/* Kartu ringkasan: siku, garis status kiri tetap */
#passwordLockScreen .lock-insight-card { border-radius: 0; background: var(--paper-warm); }
#passwordLockScreen .lock-insight-badge,
#passwordLockScreen .lock-insight-ai-tag { border-radius: var(--lk-r); }

/* Pilih akun: baris datar, avatar persegi */
#passwordLockScreen .lock-account-picker { gap: var(--space-6); }
#passwordLockScreen .lock-account-item {
  border: 1px solid var(--rule);
  border-radius: var(--lk-r);
  background: var(--paper);
  transition: border-color .12s, background .12s;
}
#passwordLockScreen .lock-account-item:hover { border-color: var(--ink-faint); background: var(--paper-warm); }
#passwordLockScreen .lock-account-item.selected {
  border-color: var(--ink);
  background: var(--paper-warm);
  box-shadow: inset 3px 0 0 var(--ink);
}
#passwordLockScreen .lock-account-avatar {
  width: 32px; height: 32px;
  border-radius: var(--lk-r);
  background: var(--ink);
  color: var(--paper);
  border: none;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}
#passwordLockScreen .lock-account-item:hover .lock-account-avatar,
#passwordLockScreen .lock-account-item.selected .lock-account-avatar { background: var(--ink); }
#passwordLockScreen .lock-account-check { color: var(--ink); }

/* Input: persegi, tanpa glow; fokus = garis tinta */
#passwordLockScreen .lock-input,
#skLoginGateScreen .lock-input {
  border: 1px solid var(--rule);
  border-radius: var(--lk-r);
  background: var(--paper);
  padding-left: var(--space-14);
  box-shadow: none;
}
#passwordLockScreen .lock-input:focus,
#skLoginGateScreen .lock-input:focus {
  border-color: var(--ink);
  box-shadow: none;
  background: var(--paper);
  outline: 1px solid var(--ink);
  outline-offset: 0;
}
#passwordLockScreen .lock-input:disabled,
#skLoginGateScreen .lock-input:disabled { background: var(--paper-warm); }
#passwordLockScreen .lock-input.error-shake { border-color: var(--danger); outline-color: var(--danger); }
#passwordLockScreen .lock-eye-btn,
#skLoginGateScreen .lock-eye-btn {
  border-radius: var(--lk-r);
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-muted);
}
#passwordLockScreen .lock-eye-btn:hover:not(:disabled),
#skLoginGateScreen .lock-eye-btn:hover:not(:disabled) { color: var(--ink); background: transparent; }

/* Tombol Masuk (gerbang login): persegi, flat */
#skLoginGateScreen .sk-gate-btn { border-radius: var(--lk-r); box-shadow: none; transform: none; }
#skLoginGateScreen .sk-gate-btn:hover:not(:disabled) { transform: none; }

/* Footer: teks tautan datar, tanpa kapsul */
#passwordLockScreen .lock-add-account,
#passwordLockScreen .lock-manual-btn {
  border-radius: var(--lk-r);
  padding: var(--space-6) var(--space-10);
  font-weight: 500;
  color: var(--ink-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--rule);
  background: transparent;
  border-color: transparent;
}
#passwordLockScreen .lock-add-account:hover,
#passwordLockScreen .lock-manual-btn:hover {
  color: var(--ink);
  background: transparent;
  border-color: transparent;
  text-decoration-color: var(--ink);
}
#passwordLockScreen .lock-footer-sep { display: inline; }
:root:not([data-theme="dark"]) #passwordLockScreen .lock-card,
:root:not([data-theme="dark"]) #skLoginGateScreen .lock-card { border: 1px solid var(--rule); border-top: 3px solid var(--ink); }
[data-theme="dark"] #passwordLockScreen .lock-card,
[data-theme="dark"] #skLoginGateScreen .lock-card { background: var(--paper); border: 1px solid var(--rule); border-top: 3px solid var(--ink); }
[data-theme="dark"] #passwordLockScreen .lock-eye-btn,
[data-theme="dark"] #skLoginGateScreen .lock-eye-btn { background: transparent; }

/* ======================================================
   [RESTYLE MODAL FRAUD — SELARAS UI TERBARU] 13 Nov 2026
   Fungsi & markup js/fraud-detection.js TIDAK berubah (filter, 2 seksi,
   Abaikan / Abaikan semua / Lihat transaksi / Urungkan, Ringkasan AI).
   Murni lapisan tampilan, di PALING AKHIR berkas supaya menang atas blok
   fraud lama (8 Okt 2026) dan blok tema lain.
   Bahasa visual = UI sekarang: kartu bersudut var(--radius-sm) bergaris
   hairline, label seksi kapital rapat dgn garis bawah lime (terang),
   baris dgn penanda status 3px di kiri (seperti kartu akun layar kunci),
   tombol pil, undo-bar ala toast (tinta + penanda kiri). Mode terang
   memakai lime; mode gelap memakai --accent + garis putus-putus yang
   sudah jadi ciri mode gelap. Semua warna dari token.
====================================================== */
#fraudAlertModal .fraud-modal-content {
  max-width: 620px;
  padding: 0 var(--space-18) var(--space-18);
  border-radius: var(--radius);
}
#fraudAlertModal .fraud-modal-content .modal-header {
  margin: 0 calc(-1 * var(--space-18)) var(--space-12);
  padding: var(--space-14) var(--space-18) var(--space-12);
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
#fraudAlertModal .fraud-modal-content .modal-header h3 {
  font-size: var(--text-lg);
  font-weight: 800;
  letter-spacing: -0.02em;
  gap: var(--space-8);
}
#fraudAlertModal .fraud-modal-content .modal-header h3 .sk-icon { color: var(--danger); }
:root:not([data-theme="dark"]) #fraudAlertModal .fraud-modal-content .modal-header { border-bottom: 1px solid var(--ink); }

/* Toolbar filter: chip pil, aktif = lime (terang) / aksen (gelap) */
#fraudAlertModal .fraud-toolbar { margin-bottom: var(--space-12); gap: var(--space-8); }
#fraudAlertModal .log-filter-bar { display: flex; gap: var(--space-6); }
#fraudAlertModal .log-filter-chip {
  padding: var(--space-5) var(--space-12);
  font-size: var(--text-xs);
  font-weight: 700;
}
#fraudAlertModal .log-filter-chip:hover { border-color: var(--ink-faint); }
:root:not([data-theme="dark"]) #fraudAlertModal .log-filter-chip.active {
  background: var(--lime);
  border-color: var(--lime);
  color: var(--ink);
  font-weight: 800;
}
[data-theme="dark"] #fraudAlertModal .log-filter-chip.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--paper);
}

/* Tombol: pil flat. Abaikan = outline tinta, hover isi lime (terang) */
#fraudAlertModal .fraud-btn {
  min-height: 30px;
  padding: 0 var(--space-12);
  font-weight: 700;
  border-width: 1px;
  border-color: var(--ink);
  background: transparent;
  color: var(--ink);
}
:root:not([data-theme="dark"]) #fraudAlertModal .fraud-btn:hover {
  background: var(--lime);
  border-color: var(--ink);
  color: var(--ink);
}
[data-theme="dark"] #fraudAlertModal .fraud-btn:hover {
  background: var(--paper-warm);
  border-color: var(--ink-faint);
  color: var(--ink);
}
/* Lihat transaksi = tautan teks bergaris bawah (bukan tombol bergaris) */
#fraudAlertModal .fraud-btn-ghost {
  border-color: transparent;
  background: transparent;
  color: var(--ink);
  padding: 0 var(--space-4);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--ink-faint);
}
#fraudAlertModal .fraud-btn-ghost:hover { background: transparent; border-color: transparent; text-decoration-color: var(--ink); }
/* Abaikan semua = hairline kecil */
#fraudAlertModal .fraud-btn-sm {
  min-height: 26px;
  border-color: var(--rule);
  color: var(--ink-muted);
  font-weight: 600;
}
#fraudAlertModal .fraud-btn-sm:hover { background: var(--paper-warm); border-color: var(--ink); color: var(--ink); }

/* Seksi = kartu hairline; header kapital rapat + garis bawah lime */
#fraudAlertModal .fraud-section {
  margin-top: var(--space-12);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  overflow: hidden;
}
#fraudAlertModal .fraud-section:first-of-type { margin-top: 0; }
#fraudAlertModal .fraud-section-header {
  padding: var(--space-8) var(--space-12);
  background: var(--paper-warm);
  border-bottom: 1px solid var(--rule);
}
#fraudAlertModal .fraud-section-title {
  font-size: var(--text-2xs);
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink);
}
:root:not([data-theme="dark"]) #fraudAlertModal .fraud-section-title {
  align-self: flex-start;
}
#fraudAlertModal .fraud-section-count {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: 0;
  color: var(--paper);
  background: var(--ink);
  padding: 1px var(--space-7);
}
[data-theme="dark"] #fraudAlertModal .fraud-section { border-style: dashed; }
[data-theme="dark"] #fraudAlertModal .fraud-section-header { border-bottom-style: dashed; }
[data-theme="dark"] #fraudAlertModal .fraud-section-count { background: var(--paper); color: var(--ink-muted); border: 1px solid var(--rule); }

/* Baris flag: penanda status 3px di kiri, ikon persegi bulat-kecil, meta mono */
#fraudAlertModal .fraud-row {
  position: relative;
  padding: var(--space-10) var(--space-12) var(--space-10) var(--space-14);
  column-gap: var(--space-10);
  border-bottom: 1px solid var(--rule);
  transition: background .12s;
}
#fraudAlertModal .fraud-row::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--ink-faint);
}
#fraudAlertModal .fraud-row-warning::before { background: var(--danger); }
#fraudAlertModal .fraud-row-info::before { background: var(--ink-faint); }
#fraudAlertModal .fraud-row:hover { background: var(--paper-warm); }
#fraudAlertModal .fraud-row:last-child { border-bottom: none; }
[data-theme="dark"] #fraudAlertModal .fraud-row { border-bottom-style: dashed; }
#fraudAlertModal .fraud-row-icon {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--rule);
}
#fraudAlertModal .fraud-row-warning .fraud-row-icon {
  background: var(--danger-lt);
  border-color: color-mix(in srgb, var(--danger) 35%, var(--paper));
  color: var(--danger);
}
#fraudAlertModal .fraud-row-info .fraud-row-icon {
  background: var(--paper-warm);
  color: var(--ink-muted);
}
[data-theme="dark"] #fraudAlertModal .fraud-row-warning .fraud-row-icon { background: color-mix(in srgb, var(--danger) 14%, var(--paper)); }
#fraudAlertModal .fraud-row-msg { font-size: var(--text-sm); font-weight: 500; line-height: 1.45; }
#fraudAlertModal .fraud-row-meta {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--ink-faint);
}
#fraudAlertModal .fraud-row-level {
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
}
#fraudAlertModal .fraud-row-info .fraud-row-level { color: var(--ink-muted); }

/* Undo-bar: kartu tinta + penanda kiri (sama dgn toast) */
#fraudAlertModal .fraud-undo {
  border-radius: var(--radius-sm);
  border-left: 4px solid var(--accent);
  padding: var(--space-5) var(--space-6) var(--space-5) var(--space-12);
  font-weight: 600;
}
:root:not([data-theme="dark"]) #fraudAlertModal .fraud-undo { border-left-color: var(--lime); }
#fraudAlertModal .fraud-undo-btn { font-weight: 800; }

/* Ringkasan AI */
#fraudAlertModal .fraud-ai-block {
  margin-top: var(--space-16);
  padding-top: var(--space-12);
  border-top: 1px solid var(--rule);
}
[data-theme="dark"] #fraudAlertModal .fraud-ai-block { border-top-style: dashed; }

/* Empty-state ikut kartu hairline */
#fraudAlertModal .log-empty {
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--paper);
  padding: var(--space-24) var(--space-16);
}
[data-theme="dark"] #fraudAlertModal .log-empty { border-style: dashed; }

/* Mobile: bottom-sheet bergaris atas tinta, aksi satu baris penuh */
@media (max-width: 640px) {
  #fraudAlertModal .fraud-modal-content {
    padding: 0 var(--space-12) calc(var(--space-14) + env(safe-area-inset-bottom, 0px));
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    border-top: 3px solid var(--ink);
  }
  #fraudAlertModal .fraud-modal-content .modal-header {
    margin: 0 calc(-1 * var(--space-12)) var(--space-10);
    padding: var(--space-12) var(--space-14) var(--space-10);
  }
  #fraudAlertModal .fraud-row {
    padding: var(--space-10) var(--space-12) var(--space-10) var(--space-12);
  }
  #fraudAlertModal .fraud-row-actions { margin-top: var(--space-6); justify-content: flex-start; }
  #fraudAlertModal .fraud-row-actions .fraud-btn-ghost { flex: 0 0 auto; min-height: 36px; padding: 0 var(--space-10); }
  #fraudAlertModal .fraud-row-actions .fraud-btn-dismiss { flex: 1 1 0; }
  #fraudAlertModal .fraud-toolbar { margin-bottom: var(--space-10); }
}

/* ======================================================
   [RESTYLE PREVIEW NOTA] 13 Nov 2026 -- modal "Preview Nota" selaras UI
   sekarang: flat (tanpa shadow), gambar nota diberi garis hairline, area
   scroll krem-tua; mode gelap pakai garis putus-putus. Isi gambar nota
   sendiri dibuat di js/report.js (selalu tema kertas terang).
====================================================== */
#notaPreviewModal .nota-pv-box { border-radius: var(--radius); }
#notaPreviewModal .nota-pv-scroll {
  background: var(--paper-warm);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
}
#notaPreviewModal .nota-pv-scroll img {
  box-shadow: none;
  border: 1px solid var(--rule);
  border-radius: 2px;
}
[data-theme="dark"] #notaPreviewModal .nota-pv-scroll { border-style: dashed; }

/* ======================================================
   [FIX CHECKLIST TIDAK TERLIHAT] 13 Nov 2026
   Penyebab: blok "gaya kartu referensi" (mode terang) memberi
   `:root:not([data-theme="dark"]) input { background-color: var(--paper);
   border-color: var(--rule) }` -- spesifisitasnya SAMA dgn
   `input[type="checkbox"]:checked` dan letaknya lebih akhir, jadi kotak
   yang tercentang kembali berlatar --paper, padahal tanda centangnya
   juga --paper => centang "hilang" (terlihat di Setelan, Audit Mingguan,
   dan semua checkbox/radio lain). Di sini state :checked dikembalikan
   dgn spesifisitas lebih tinggi. Mode gelap tidak terpengaruh (sudah
   punya aturan sendiri yang lebih spesifik).
====================================================== */
:root:not([data-theme="dark"]) input[type="checkbox"]:checked,
:root:not([data-theme="dark"]) input[type="radio"]:checked {
  background-color: var(--ink);
  border-color: var(--ink);
}
:root:not([data-theme="dark"]) input[type="checkbox"]:checked::after { border-color: var(--lime); }
:root:not([data-theme="dark"]) input[type="radio"]:checked::after { background: var(--lime); }
/* Kotak belum tercentang: garis lebih tegas supaya jelas bisa dicentang */
:root:not([data-theme="dark"]) input[type="checkbox"]:not(:checked),
:root:not([data-theme="dark"]) input[type="radio"]:not(:checked) { border-color: var(--ink-faint); }
:root:not([data-theme="dark"]) input[type="checkbox"]:not(:checked):hover,
:root:not([data-theme="dark"]) input[type="radio"]:not(:checked):hover { border-color: var(--ink); }
/* Toggle Audit Mingguan per buku (daftar Buku Kas): ON = tinta di mode terang */
:root:not([data-theme="dark"]) .book-wa-toggle input:checked + .book-wa-switch { background: var(--ink); }
