/* ============================================================
   ARIES ONE — Base Stylesheet
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  color-scheme: light;

  /* ── Permukaan ───────────────────────────────────────────────────── */
  --bg:            #f4f5f7;   /* latar halaman                          */
  --surface:       #ffffff;   /* kartu, modal, dropdown, input          */
  --surface-2:     #f8fafc;   /* card-header, readonly, hover baris     */
  --surface-3:     #f1f5f9;   /* thead, tombol tutup, badge abu         */
  --surface-4:     #e2e8f0;   /* hover tombol tutup                     */
  --border:        #dde1e7;
  --border-2:      #e5e7eb;   /* garis kartu & modal                    */
  --border-3:      #f0f2f5;   /* garis antar baris tabel                */

  /* ── Teks ────────────────────────────────────────────────────────── */
  --text:          #1e293b;
  --text-muted:    #5c6b80;
  --text-soft:     #475569;
  --text-label:    #374151;
  --text-dim:      #7c8ca1;
  --on-accent:     #ffffff;   /* teks di atas warna aksen pekat         */
  --on-accent-dim: rgba(255,255,255,.78); /* teks sekunder di atas latar gelap tetap */

  /* ── Aksen ───────────────────────────────────────────────────────── */
  --primary:       #2563eb;
  --primary-h:     #1d4ed8;
  --primary-soft:  #eff6ff;
  --primary-soft2: #dbeafe;
  --primary-brd:   #bfdbfe;
  --primary-ink:   #1d4ed8;   /* teks di atas --primary-soft            */
  --primary-dim:   #60a5fa;
  --row-hover:     #f0f7ff;

  --danger:        #dc2626;
  --danger-h:      #b91c1c;
  --danger-soft:   #fee2e2;
  --danger-soft2:  #fef2f2;
  --danger-brd:    #fca5a5;
  --danger-ink:    #b91c1c;

  --success:       #15803d;
  --success-soft:  #dcfce7;
  --success-soft2: #f0fdf4;
  --success-brd:   #22c55e;
  --success-ink:   #15803d;

  --warn:          #d97706;
  --warn-soft:     #fef3c7;
  --warn-soft2:    #fffbeb;
  --warn-brd:      #fde68a;
  --warn-ink:      #92400e;

  --purple-soft:   #ede9fe;
  --purple-brd:    #8b5cf6;
  --purple-ink:    #5b21b6;
  --slate-soft:    #f1f5f9;
  --slate-brd:     #94a3b8;
  --slate-ink:     #334155;

  /* ── Topbar & navigasi ───────────────────────────────────────────── */
  /* Dipisah dari --primary supaya tema bisa memakai warna topbar yang
     berbeda dari warna tombol utama (dipakai tema Navy & Army).        */
  --topbar-bg:     var(--primary);
  --topbar-fg:     #ffffff;
  --topbar-fg-dim: #ffffffcc;
  --topbar-hover:  rgba(255,255,255,.10);
  --topbar-active: rgba(255,255,255,.15);
  --topbar-line:   rgba(255,255,255,.8);

  /* ── Lain-lain ───────────────────────────────────────────────────── */
  --radius:        6px;

  /* ── Warna "solid": TETAP di semua tema ──────────────────────────
     Dipakai untuk latar pekat yang di atasnya selalu ada teks putih —
     header tabel laporan, badge status, pita judul.

     Kenapa tidak memakai --primary-ink / --warn-ink / --text saja?
     Karena variabel itu MEMBALIK antar tema: --warn-ink bernilai #92400e
     (cokelat tua) di tema terang tapi #fcd34d (kuning muda) di tema gelap.
     Sebagai warna TEKS itu benar — ia harus ikut membalik mengikuti latar
     lembutnya. Tapi sebagai LATAR, hasilnya teks putih di atas kuning muda
     alias tidak terbaca. Warna di bawah ini sengaja tidak ikut tema. */
  --solid-slate:  #1e293b;
  --solid-blue:   #1d4ed8;
  --solid-green:  #15803d;
  --solid-amber:  #92400e;
  --solid-red:    #b91c1c;
  --solid-purple: #5b21b6;

  --shadow:        0 1px 3px rgba(0,0,0,.1);
  --shadow-card:   0 2px 8px rgba(0,0,0,.07);
  --shadow-topbar: 0 2px 8px rgba(0,0,0,.22);
  --shadow-modal:  0 8px 30px rgba(0,0,0,.18);
  --overlay:       rgba(0,0,0,.45);
}
/* ── Huruf ──────────────────────────────────────────────────────────────
   Plus Jakarta Sans, berkasnya di assets/fonts — BUKAN dari Google Fonts.
   Banyak toko sengaja dipasang tanpa internet; font yang diambil dari luar
   di sana diam-diam jatuh ke huruf sistem, dan tampilannya berbeda antara
   komputer kantor dan komputer kasir tanpa ada yang tahu sebabnya.
   Lisensinya OFL (assets/fonts/OFL.txt), boleh ikut dibagikan. */
@font-face {
  font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url('../fonts/jakarta-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url('../fonts/jakarta-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Plus Jakarta Sans'; font-style: italic; font-weight: 200 800; font-display: swap;
  src: url('../fonts/jakarta-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ── Bentuk: BUKAN warna ────────────────────────────────────────────────
   Semua yang di bawah ini sama di setiap tema. Warnanya tetap datang dari
   token di atas; yang diatur di sini cuma lengkung, bayangan, dan jarak.

   Bayangan memakai hitam tembus pandang, tidak memakai warna tema: hitam
   10-35% terbaca sebagai "terangkat" baik di atas putih maupun di atas
   navy, sementara bayangan berwarna di tema gelap justru jadi pendar. */
:root {
  --font-ui:      'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-kode:    ui-monospace, 'Cascadia Mono', Consolas, monospace;

  --radius-sm:    6px;
  --radius-lg:    14px;   /* kartu, bilah atas, panel kiri                */
  --radius-xl:    16px;   /* jendela modal                                */

  /* Bilah atas MENGAMBANG: ada jarak dari tepi layar dan sudutnya
     melengkung. Tingginya ditulis sebagai variabel karena tiga tempat
     menghitung dari situ — dropdown mode sempit, panel kiri, dan lencana
     versi. */
  --ao-tb-h:      52px;
  --ao-tb-gap:    10px;
  --ao-tb-bawah:  calc(var(--ao-tb-gap) + var(--ao-tb-h));

  --shadow-float: 0 1px 2px rgba(0,0,0,.06), 0 10px 28px -10px rgba(0,0,0,.30);
  --shadow-pop:   0 2px 6px -2px rgba(0,0,0,.10), 0 18px 44px -12px rgba(0,0,0,.34);
  --shadow-soft:  0 1px 2px rgba(0,0,0,.04), 0 4px 14px -8px rgba(0,0,0,.12);

  /* Cincin fokus. Dulu rgba(37,99,235,...) ditulis mentah — biru tema
     terang — jadi di tema Army fokusnya tetap biru di atas hijau. Bawaan
     --primary-soft2 untuk peramban lama; color-mix untuk yang mendukung. */
  --ring:         var(--primary-soft2);
}
@supports (color: color-mix(in srgb, red, blue)) {
  :root { --ring: color-mix(in srgb, var(--primary) 26%, transparent); }
}

body {
  font-family: var(--font-ui);
  font-size: 14px;
  line-height: 1.45;
  background: var(--bg);
  color: var(--text);
  min-height: var(--ao-tinggi-layar, 100vh);
  -webkit-font-smoothing: antialiased;
  /* flow-root: jarak atas bilah mengambang (margin-top .topbar) tidak boleh
     "runtuh" keluar dari body. Kalau runtuh, tinggi dokumen = 10px + tinggi
     layar penuh, dan halaman sependek apa pun bisa digulir 10px. */
  display: flow-root;
}
/* Kontrol isian tidak mewarisi huruf dari body kecuali disuruh. Tanpa ini
   tombol dan kotak pilihan tetap memakai Segoe UI di tengah halaman yang
   sudah berganti huruf. */
button, input, select, textarea { font-family: inherit; }

/* Ikon garis (SVG). Ukurannya mengikuti huruf di sekitarnya, warnanya
   mengikuti teks — jadi ikon yang sama terbaca di bilah atas berwarna dan
   di atas kartu putih tanpa perlu dua versi. */
.ikon {
  width: 1.15em; height: 1.15em; flex-shrink: 0; vertical-align: -.2em;
  fill: none; stroke: currentColor; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}

/* ---- Topbar (mengambang) ---- */
.topbar {
  background: var(--topbar-bg);
  color: var(--topbar-fg);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 0 8px 0 6px;
  height: var(--ao-tb-h);
  margin: var(--ao-tb-gap) var(--ao-tb-gap) 0;
  border-radius: var(--radius-lg);
  position: sticky;
  top: var(--ao-tb-gap);
  z-index: 200;
  box-shadow: var(--shadow-topbar), var(--shadow-float);
}
.topbar-brand {
  font-weight: 800; font-size: 15px; letter-spacing: -.01em;
  padding: 0 14px 0 10px; height: 36px; border-radius: 10px;
  display: flex; align-items: center; gap: 9px;
  white-space: nowrap; flex-shrink: 0;
  color: var(--topbar-fg); text-decoration: none; cursor: pointer;
}
.topbar-brand:hover { background: var(--topbar-hover); }
.topbar-logo { width: 28px; height: 21px; flex-shrink: 0; }
.topbar-right {
  display: flex; align-items: center; gap: 4px;
  font-size: 13px; flex-shrink: 0;
}
.topbar-right a { color: var(--topbar-fg-dim); text-decoration: none; }
.topbar-right a:hover { color: var(--topbar-fg); }
/* Tombol ikon bulat di bilah atas: gerigi, lonceng, keluar, hamburger. */
.tb-ikon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: 10px; flex-shrink: 0;
  background: none; border: none; cursor: pointer; position: relative;
  color: var(--topbar-fg-dim); font-size: 18px; line-height: 1;
  transition: background .15s, color .15s;
}
.topbar-right a.tb-ikon:hover,
.tb-ikon:hover { background: var(--topbar-hover); color: var(--topbar-fg); }
.tb-ikon.active { background: var(--topbar-active); color: var(--topbar-fg); }
.tb-pemakai {
  display: flex; align-items: center; gap: 8px;
  padding: 0 6px 0 10px; margin-left: 4px; height: 36px;
  border-left: 1px solid var(--topbar-active);
  color: var(--topbar-fg); font-weight: 600; font-size: 12.5px; white-space: nowrap;
}
.tb-avatar {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--topbar-active); color: var(--topbar-fg);
  font-size: 11px; font-weight: 800; letter-spacing: .02em;
}
.hamburger { display: none; }

/* ---- Top Navigation ---- */
.topnav {
  display: flex; align-items: center; gap: 2px; flex: 1;
  overflow: visible; height: 100%;
}
.tnav-item {
  position: relative; display: flex; align-items: center; height: 100%;
}
.tnav-link {
  display: flex; align-items: center; gap: 7px;
  padding: 0 11px; height: 36px; border-radius: 10px;
  font-size: 13px; font-weight: 600;
  color: var(--topbar-fg-dim); text-decoration: none;
  cursor: pointer; white-space: nowrap; border: none;
  background: none;
  transition: color .15s, background .15s;
}
.tnav-link:hover,
.tnav-item:hover > .tnav-link,
.tnav-item.open > .tnav-link { color: var(--topbar-fg); background: var(--topbar-hover); }
.tnav-link.active { color: var(--topbar-fg); background: var(--topbar-active); }
.tnav-arrow { display: inline-flex; opacity: .65; transition: transform .2s; }
.tnav-arrow .ikon { width: 14px; height: 14px; }
.tnav-item:hover > .tnav-link .tnav-arrow { transform: rotate(180deg); }
.tnav-ikon { display: inline-flex; align-items: center; justify-content: center; width: 18px; flex-shrink: 0; font-size: 13px; font-weight: 800; }
.tnav-ikon .ikon { width: 17px; height: 17px; }

/* Dropdown: kartu melayang di BAWAH bilah, terpisah beberapa piksel.
   ::before menjembatani celah itu — tanpa jembatan, kursor yang turun dari
   menu ke dropdown melewati ruang kosong, :hover lepas, dan dropdownnya
   menutup tepat sebelum bisa diklik. */
.tnav-dropdown {
  display: none;
  position: absolute; top: calc(100% + 4px); left: -4px;
  background: var(--surface); border: 1px solid var(--border-2);
  border-radius: 12px;
  box-shadow: var(--shadow-pop);
  min-width: 220px; max-width: 300px;
  z-index: 300; padding: 6px;
  animation: ao-muncul .14s ease;
}
.tnav-dropdown::before {
  content: ""; position: absolute; left: 0; right: 0; top: -12px; height: 12px;
}
.tnav-item:hover .tnav-dropdown,
.tnav-item.open  .tnav-dropdown { display: block; }
@keyframes ao-muncul { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.tnav-dd-item {
  display: block; padding: 8px 12px; border-radius: 8px;
  font-size: 13px; font-weight: 500; color: var(--text); text-decoration: none;
  transition: background .1s, color .1s;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tnav-dd-item:hover { background: var(--primary-soft); color: var(--primary-ink); }
.tnav-dd-item.active { background: var(--primary-soft); color: var(--primary-ink); font-weight: 700; }

/* Group header inside dropdown */
.tnav-group { border-top: 1px solid var(--border-2); padding-top: 4px; margin-top: 4px; }
.tnav-group:first-child { border-top: none; padding-top: 0; margin-top: 0; }
.tnav-group-label {
  padding: 6px 12px 3px;
  font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--text-muted);
}

/* ── Flyout submenu (level-2) ── */
.tnav-flyout-item {
  position: relative;
}
.tnav-flyout-trigger {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px 8px 12px; border-radius: 8px;
  font-size: 13px; font-weight: 500; color: var(--text); text-decoration: none;
  transition: background .1s; white-space: nowrap; cursor: default;
  gap: 12px;
}
.tnav-flyout-trigger:hover,
.tnav-flyout-item:hover > .tnav-flyout-trigger { background: var(--surface-3); }
.tnav-flyout-trigger.active { color: var(--primary-ink); font-weight: 700; }
.tnav-flyout-arrow { display: inline-flex; opacity: .55; flex-shrink: 0; }
.tnav-flyout-arrow .ikon { width: 14px; height: 14px; }

.tnav-flyout {
  display: none;
  position: absolute; top: -7px; left: calc(100% + 8px);
  background: var(--surface); border: 1px solid var(--border-2);
  border-radius: 12px;
  box-shadow: var(--shadow-pop);
  min-width: 220px; z-index: 400; padding: 6px;
  animation: ao-muncul .12s ease;
}
/* Jembatan kursor ke flyout, sama alasannya dengan dropdown di atas. */
.tnav-flyout::before { content: ""; position: absolute; top: 0; bottom: 0; left: -12px; width: 12px; }
/* Buka flyout saat hover pada item */
.tnav-flyout-item:hover > .tnav-flyout { display: block; }

/* Jika flyout akan terpotong di kanan layar, buka ke kiri */
.tnav-flyout-item.flyout-left > .tnav-flyout {
  left: auto; right: calc(100% + 8px);
}
.tnav-flyout-item.flyout-left > .tnav-flyout::before { left: auto; right: -12px; }

/* ── Mega-menu (menu atas di layar lebar) ──
   Panel selebar bilah atas, mengambang di bawahnya: judul menu + jumlah
   butir, lalu isinya berkolom — grup jadi kolom berjudul, tidak ada lagi
   sub-menu yang membuka ke samping. Dibuka dengan hover (jeda tutup 180ms
   diatur skrip di layout.php). Panel menu kiri dan menu HP TIDAK memakai
   ini: keduanya tetap .tnav-dropdown yang dibuka dengan klik. */
.tnav-mega { display: none; }
html:not([data-nav="kiri"]):not([data-topnav="sempit"]) .tnav-item { position: static; }
html:not([data-nav="kiri"]):not([data-topnav="sempit"]) .tnav-dropdown { display: none !important; }
html:not([data-nav="kiri"]):not([data-topnav="sempit"]) .tnav-item.mega-buka > .tnav-mega { display: block; }
.tnav-item.mega-buka:not(.mega-tutup) > .tnav-link { color: var(--topbar-fg); background: var(--topbar-hover); }
.tnav-item.mega-buka:not(.mega-tutup) > .tnav-link .tnav-arrow { transform: rotate(180deg); }
.tnav-mega {
  position: absolute; left: 0; right: 0; top: calc(100% + 8px); z-index: 300;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border-2); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  padding: 18px 24px 20px; cursor: default;
  transform-origin: 50% 0;
  animation: ao-mega-masuk .22s cubic-bezier(.2,.8,.2,1);
}
/* Animasi (skrip di layout.php memasang kelasnya):
   • muncul  — panel memudar masuk sambil turun sedikit; judul dan kolom
     menyusul satu per satu (--i = urutan kolom), jadi mata dibawa dari
     kiri ke kanan, bukan disuguhi semuanya sekaligus;
   • hilang  — .mega-tutup: memudar sambil naik, lalu baru disembunyikan;
   • pindah ke menu sebelah — .mega-ganti: bingkai panel TIDAK diulang
     animasinya (akan terlihat berkedip); tingginya dianimasikan skrip dari
     tinggi panel lama ke yang baru, dan isinya saja yang memudar masuk. */
.tnav-item.mega-ganti > .tnav-mega { animation: none; }
.tnav-item.mega-tutup > .tnav-mega { animation: ao-mega-keluar .15s ease-in forwards; pointer-events: none; }
.tnav-item.mega-buka > .tnav-mega .tnav-mega-kepala { animation: ao-mega-isi .2s ease both; }
.tnav-item.mega-buka > .tnav-mega .tnav-mega-kol {
  animation: ao-mega-isi .24s cubic-bezier(.2,.8,.2,1) both;
  animation-delay: calc(var(--i, 0) * 22ms + 30ms);
}
.tnav-item.mega-ganti > .tnav-mega .tnav-mega-kol { animation-delay: calc(var(--i, 0) * 14ms); }
@keyframes ao-mega-masuk { from { opacity: 0; transform: translateY(-10px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes ao-mega-keluar { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(-8px) scale(.99); } }
@keyframes ao-mega-isi { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .tnav-mega, .tnav-mega .tnav-mega-kepala, .tnav-mega .tnav-mega-kol { animation: none !important; }
}
.tnav-mega::before { content: ""; position: absolute; left: 0; right: 0; top: -12px; height: 12px; }
.tnav-mega-kepala {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--border-2);
}
.tnav-mega-ikon {
  width: 30px; height: 30px; border-radius: 9px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary-soft); color: var(--primary-ink); font-size: 14px; font-weight: 800;
}
.tnav-mega-ikon .ikon { width: 17px; height: 17px; }
.tnav-mega-kepala b { font-size: 16px; font-weight: 800; letter-spacing: -.01em; color: var(--text); }
.tnav-mega-kepala > span:last-child { font-size: 12.5px; color: var(--text-muted); }
.tnav-mega-isi {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 4px 24px;
  max-height: calc(var(--ao-tinggi-layar, 100vh) - var(--ao-tb-bawah) - 120px); overflow-y: auto;
  padding: 0 8px; margin: 0 -8px;
}
.tnav-mega-kol { min-width: 0; }
.tnav-mega-kol h4 {
  margin: 2px 0 6px; font-size: 10.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .08em; color: var(--text-muted);
}
.tnav-mega-kol h4.kosong { visibility: hidden; }
.tnav-mega-link {
  display: block; padding: 6px 8px; margin: 0 -8px 1px; border-radius: 8px;
  font-size: 13.5px; font-weight: 500; color: var(--text); text-decoration: none;
  transition: background .1s, color .1s;
}
.tnav-mega-link:hover { background: var(--primary-soft); color: var(--primary-ink); }
.tnav-mega-link.active { color: var(--primary-ink); font-weight: 700; }
.tnav-mega-link.active::before {
  content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--primary); margin: 0 7px 1px 0; vertical-align: middle;
}
@media print { .tnav-mega { display: none !important; } }

/* ---- Mobile nav ---- */
/* Dulu @media (max-width:900px). Diganti atribut karena lebar tempat menu
   berhenti muat TIDAK TETAP — ia bergantung pada panjang label menu, yang
   berbeda di tiap pemasangan. Di antara 901px dan lebar yang dibutuhkan
   menu, .topnav yang ber-flex:1 tanpa min-width mendorong .topbar-right
   keluar layar: lonceng notifikasi dan tombol Keluar hilang dari pandangan.
   Sekarang tema.js yang memasang data-topnav="sempit" — dari matchMedia
   lebih dulu (sebelum halaman tergambar), lalu dikoreksi dengan mengukur
   apakah menunya benar-benar meluber. */
html[data-topnav="sempit"] .hamburger { display: inline-flex; }
html[data-topnav="sempit"] .topnav { display: none; flex-direction: column; align-items: stretch;
    position: absolute; top: calc(100% + 8px); left: 0; right: 0; height: auto;
    max-height: calc(var(--ao-tinggi-layar, 100vh) - var(--ao-tb-bawah) - 24px); overflow-y: auto;
    background: var(--topbar-bg); z-index: 250; border-radius: var(--radius-lg);
    padding: 8px; box-shadow: var(--shadow-pop); }
html[data-topnav="sempit"] .topnav.open { display: flex; }
html[data-topnav="sempit"] .tnav-item { flex-direction: column; align-items: stretch; height: auto; }
html[data-topnav="sempit"] .tnav-link { padding: 0 12px; height: 40px; }
html[data-topnav="sempit"] .tnav-arrow { margin-left: auto; }
html[data-topnav="sempit"] .tnav-dropdown { position: static; box-shadow: none; border: none;
    background: none; border-radius: 0; animation: none;
    padding: 2px 0 6px; display: none; min-width: 0; max-width: none; }
html[data-topnav="sempit"] .tnav-dropdown::before { display: none; }
html[data-topnav="sempit"] .tnav-item.open .tnav-dropdown { display: block; }
html[data-topnav="sempit"] .tnav-dd-item { color: var(--topbar-fg-dim); padding: 8px 12px 8px 37px; }
html[data-topnav="sempit"] .tnav-dd-item:hover { background: var(--topbar-hover); color: var(--topbar-fg); }
html[data-topnav="sempit"] .tnav-dd-item.active { background: var(--topbar-active); color: var(--topbar-fg); }
html[data-topnav="sempit"] .tnav-group-label { color: var(--topbar-fg-dim); padding-left: 37px; }
html[data-topnav="sempit"] .tnav-group { border-top-color: var(--topbar-active); }
/* Mobile: flyout jadi flat expand */
html[data-topnav="sempit"] .tnav-flyout-trigger { color: var(--topbar-fg-dim); padding: 8px 12px 8px 37px; }
html[data-topnav="sempit"] .tnav-flyout-trigger:hover { background: var(--topbar-hover); color: var(--topbar-fg); }
html[data-topnav="sempit"] .tnav-flyout-trigger.active { background: var(--topbar-active); color: var(--topbar-fg); }
html[data-topnav="sempit"] .tnav-flyout { position: static; box-shadow: none; border: none; border-radius: 0; background: none; padding: 0; display: none; animation: none; }
html[data-topnav="sempit"] .tnav-flyout::before { display: none; }
html[data-topnav="sempit"] .tnav-flyout-item.open > .tnav-flyout { display: block; }
html[data-topnav="sempit"] .tnav-flyout .tnav-dd-item { padding-left: 52px; }
/* Nama pengguna di bilah sempit cuma memakan tempat lonceng. Inisialnya
   tetap tinggal, dan nama lengkapnya ada di title. */
html[data-topnav="sempit"] .tb-pemakai-nama { display: none; }

/* ---- Layout ---- */
/* Bawaannya PENUH. Sebagian besar layar di aplikasi ini isinya tabel —
   laporan, daftar master, baris transaksi — dan membatasinya di 1200px
   menyisakan pita kosong di kiri-kanan justru waktu tabelnya paling butuh
   ruang. Halaman yang isinya borang menandai dirinya sendiri dengan
   .sempit lewat $PAGE_SEMPIT di layout.php: isian selebar 2500px tidak
   lebih mudah dibaca, cuma lebih jauh dijangkau mata. */
.page-wrapper { max-width: none; margin: 0 auto; padding: 22px 20px 32px; }
.page-wrapper.sempit { max-width: 1200px; }
.page-title {
  font-size: 22px; font-weight: 800; letter-spacing: -.02em; line-height: 1.25;
  margin-bottom: 18px; color: var(--text);
  text-wrap: balance;
}
.page-title span { color: var(--text-muted); font-weight: 500; font-size: 13.5px; letter-spacing: 0; margin-left: 10px; }

/* ---- Card ---- */
/* Garis tipis + bayangan lembut, tanpa kepala abu-abu. Kartu yang semua
   sisinya diberi garis, bayangan, DAN kepala berwarna membuat setiap kotak
   sama kerasnya berteriak — tidak ada lagi yang terbaca sebagai pokok. */
.card {
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  margin-bottom: 20px;
}
.card-header {
  padding: 14px 20px;
  border-bottom: 1px solid var(--border-2);
  font-weight: 700;
  font-size: 14.5px;
  background: transparent;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.card-body { padding: 20px; }

/* ---- Form ---- */
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 14px 16px;
}
.form-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.form-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.form-group { display: flex; flex-direction: column; gap: 5px; }
.form-group.full { grid-column: 1 / -1; }
label { font-size: 13px; font-weight: 600; color: var(--text-label); }
input[type=text], input[type=number], input[type=password],
input[type=date], input[type=email], input[type=search], input[type=tel],
select, textarea {
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 8px 11px;
  font-size: 14px;
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  transition: border-color .15s, box-shadow .15s;
  width: 100%;
}
input[type=text]:hover, input[type=number]:hover, input[type=password]:hover,
input[type=date]:hover, select:hover, textarea:hover { border-color: var(--text-dim); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--ring);
}
input[readonly] { background: var(--surface-2); color: var(--text-muted); }
input[readonly]:hover { border-color: var(--border); }
textarea { resize: vertical; min-height: 60px; }
input[type=checkbox], input[type=radio] { accent-color: var(--primary); }

/* ---- Buttons ---- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 8px 15px; border-radius: 9px;
  font-size: 13.5px; font-weight: 600; font-family: inherit; line-height: 1.35;
  border: 1px solid transparent; cursor: pointer;
  text-decoration: none;
  transition: background .15s, border-color .15s, box-shadow .15s, transform .06s;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); }
.btn-primary  { background: var(--primary); color: var(--on-accent); border-color: var(--primary);
                box-shadow: 0 1px 2px rgba(0,0,0,.12); }
.btn-primary:hover { background: var(--primary-h); border-color: var(--primary-h); }
.btn-danger   { background: var(--danger); color: var(--on-accent); border-color: var(--danger);
                box-shadow: 0 1px 2px rgba(0,0,0,.12); }
.btn-danger:hover { background: var(--danger-h); border-color: var(--danger-h); }
.btn-secondary { background: var(--surface); color: var(--text); border-color: var(--border);
                 box-shadow: 0 1px 2px rgba(0,0,0,.05); }
.btn-secondary:hover { background: var(--surface-2); border-color: var(--text-dim); }
.btn-success  { background: var(--success); color: var(--on-accent); border-color: var(--success);
                box-shadow: 0 1px 2px rgba(0,0,0,.12); }
.btn-success:hover { filter: brightness(.93); }
.btn-sm { padding: 5px 11px; font-size: 12.5px; border-radius: 8px; }
.btn[disabled], .btn:disabled { opacity: .55; cursor: not-allowed; transform: none; }

/* ---- Toolbar (above table) ---- */
.toolbar {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 10px; margin-bottom: 16px;
}
.toolbar-left, .toolbar-right { display: flex; gap: 8px; align-items: center; }
.search-box {
  display: flex; align-items: stretch; gap: 0;
  border: 1px solid var(--border); border-radius: 9px;
  overflow: hidden; background: var(--surface);
  transition: border-color .15s, box-shadow .15s;
}
.search-box:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--ring); }
.search-box input {
  border: none; border-radius: 0; width: 260px; padding: 8px 12px;
  font-size: 14px; box-shadow: none;
}
.search-box input:focus { box-shadow: none; border: none; }
.search-box button {
  background: var(--primary); color: var(--on-accent); border: none;
  padding: 0 14px; cursor: pointer; font-size: 14px;
}
.search-box button:hover { background: var(--primary-h); }

/* ---- Table ---- */
.table-wrap { overflow-x: auto; border-radius: 10px; }
table { width: 100%; border-collapse: collapse; font-size: 14px; font-variant-numeric: tabular-nums; }
thead th {
  background: var(--surface-2); color: var(--text-muted);
  font-size: 12px; font-weight: 700; letter-spacing: .02em;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border); text-align: left;
  white-space: nowrap;
}
thead th.center { text-align: center; }
/* Pasangan dari tbody td.right di bawah. Selama ini tidak ada, jadi SETIAP
   judul kolom angka rata kiri sementara angkanya rata kanan — makin lebar
   kolomnya makin jauh judulnya dari angka yang dijudulinya. Paling terasa
   di Master Barang waktu sebagian tingkat harga disembunyikan: kolom yang
   tersisa melebar, dan "HARGA BELI" berdiri di atas kolom sebelahnya. */
thead th.right  { text-align: right; }
tbody tr { border-bottom: 1px solid var(--border-2); transition: background .1s; }
tbody tr:last-child { border-bottom: none; }
tbody tr:hover { background: var(--row-hover); }
tbody td { padding: 10px 14px; vertical-align: middle; }
tbody td.center { text-align: center; }
tbody td.right  { text-align: right; }
.td-actions { display: flex; gap: 6px; justify-content: center; }

/* ---- Badge ---- */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 9px; border-radius: 99px;
  font-size: 11.5px; font-weight: 600; line-height: 1.5; white-space: nowrap;
}
.badge-green  { background: var(--success-soft); color: var(--success-ink); }
.badge-gray   { background: var(--surface-3); color: var(--text-muted); }
.badge-blue   { background: var(--primary-soft2); color: var(--primary-ink); }
.badge-red    { background: var(--danger-soft); color: var(--danger-ink); }
.badge-amber  { background: var(--warn-soft); color: var(--warn-ink); }

/* ---- Alert ---- */
.alert {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 14px; border-radius: 12px;
  font-size: 13.5px; font-weight: 500; margin-bottom: 14px;
  border: 1px solid transparent;
  box-shadow: var(--shadow-soft);
}
.alert::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
  margin-top: .45em; background: currentColor;
}
.alert-success { background: var(--success-soft2); border-color: var(--success-soft); color: var(--success-ink); }
.alert-danger  { background: var(--danger-soft2); border-color: var(--danger-soft);  color: var(--danger-ink); }
.alert-info    { background: var(--primary-soft); border-color: var(--primary-soft2);  color: var(--primary-ink); }

/* ---- Subscription warning banner (BUKAN .alert - sengaja terpisah supaya
   tidak ikut ke-auto-hide oleh script 4 detik di layout.php) ---- */
.subs-warning-banner {
  background: var(--warn-soft2); border: 1px solid var(--warn-brd); color: var(--warn-ink);
  padding: 11px 16px; border-radius: 12px; font-size: 13px;
  margin-bottom: 16px; display: flex; align-items: center;
  justify-content: space-between; gap: 12px; flex-wrap: wrap;
}
.subs-warning-banner a { color: var(--warn-ink); font-weight: 700; text-decoration: underline; white-space: nowrap; }
@media print { .salinan-banner { display: none !important; } }

/* ---- Modal ---- */
/* Tirai meredupkan halaman di belakangnya. SENGAJA tanpa backdrop-filter
   blur: di PC kasir berkartu grafis seadanya, mengaburkan satu layar penuh
   membuat animasi membuka popup tersendat — terasa seperti berkedip,
   persis di popup yang paling sering dibuka (F5 cari barang). */
.modal-backdrop {
  display: none; position: fixed; inset: 0;
  background: var(--overlay); z-index: 500;
  align-items: center; justify-content: center;
  padding: 16px;

}
.modal-backdrop.open { display: flex; animation: ao-tirai .15s ease; }
.modal {
  background: var(--surface); border-radius: var(--radius-xl); width: 100%;
  border: 1px solid var(--border-2);
  max-height: 92vh; overflow-y: auto;
  box-shadow: var(--shadow-pop);
  animation: modal-in .2s cubic-bezier(.2,.8,.2,1);
}
.modal-sm  { max-width: 440px; }
.modal-md  { max-width: 640px; }
.modal-lg  { max-width: 860px; }
.modal-xl  { max-width: 1040px; }
@keyframes modal-in {
  from { transform: translateY(10px) scale(.97); opacity: 0; }
  to   { transform: none; opacity: 1; }
}
@keyframes ao-tirai { from { opacity: 0; } to { opacity: 1; } }
.modal-header {
  padding: 16px 20px; border-bottom: 1px solid var(--border-2);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: 16.5px; font-weight: 800; letter-spacing: -.01em; color: var(--text);
  position: sticky; top: 0; background: var(--surface); z-index: 10;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
}
.modal-body   { padding: 20px; }
.modal-footer {
  padding: 12px 20px; border-top: 1px solid var(--border-2);
  display: flex; justify-content: flex-end; gap: 8px;
  position: sticky; bottom: 0; background: var(--surface-2);
  border-radius: 0 0 var(--radius-xl) var(--radius-xl);
}
.btn-close {
  background: none; border: none; cursor: pointer; flex-shrink: 0;
  width: 32px; height: 32px; border-radius: 9px;
  font-size: 16px; color: var(--text-muted); display: flex;
  align-items: center; justify-content: center;
  transition: background .15s, color .15s;
}
.btn-close:hover { background: var(--surface-3); color: var(--text); }

/* ---- Pagination ---- */
.pagination { display: flex; gap: 4px; align-items: center; margin-top: 14px; flex-wrap: wrap; }
.pagination a, .pagination span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; height: 32px; padding: 0 8px;
  border: 1px solid transparent; border-radius: 8px;
  font-size: 12.5px; font-weight: 600; text-decoration: none; color: var(--text-soft);
  background: none;
}
.pagination a:hover { background: var(--surface-3); color: var(--text); }
.pagination .active { background: var(--primary); color: var(--on-accent); border-color: var(--primary);
                      box-shadow: 0 1px 2px rgba(0,0,0,.12); }
.pagination .disabled { color: var(--text-dim); pointer-events: none; }
/* Keterangan posisi: bukan tombol, jadi tanpa kotak. */
.pagination .pg-info { border: 0; background: none; color: var(--text-muted); min-width: 0; padding-left: 10px; font-weight: 500; }

/* ---- Bilah saringan daftar ----
   Dipakai Master Barang; ditulis umum supaya master lain bisa menyusul
   tanpa menyalin gaya lagi. */
.fbar { margin-bottom: 14px; }
.fbar-baris { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
/* Kotak pilihan di baris atas mengikuti isinya, tidak melebar penuh:
   aturan umum select{width:100%} membuat tiap kotak makan satu baris
   sendiri, dan lima saringan jadi lima baris. */
.fbar-baris select { width: auto; min-width: 132px; max-width: 220px; }
/* ── KOTAK CARI DI BILAH SARINGAN ─────────────────────────────────────
   .search-box umum memberi input lebar TETAP (220px, 260px di layar
   besar). Di dalam bilah yang sudah berisi lima kotak lain, wadahnya
   terjepit sampai 2px sementara inputnya tetap 185px — jadi inputnya
   menjorok keluar, tombol kacanya gepeng setinggi separuh, dan seluruh
   halaman ikut bergeser ke samping. Di sini lebarnya dibuat mengikuti
   wadah, dan tingginya disamakan dengan kotak pilihan di sebelahnya. */
.fbar-baris .search-box { flex: 1 1 220px; min-width: 190px; max-width: 340px; }
.fbar-baris .search-box input { width: 100%; min-width: 0; padding: 8px 10px; font-size: 13.5px; }
.fbar-baris .search-box button { height: auto; align-self: stretch; display: flex;
  align-items: center; justify-content: center; padding: 0 12px; }
.fbar-lanjut select, .fbar-lanjut input[type=text] { width: 100%; }
.fbar-harga select { width: auto; min-width: 150px; }
.fbar-harga input[type=text] { width: 96px; }
/* Dua kotak berdampingan: yang kiri memakai sisa ruang, yang kanan
   (arah urutan) selebar isinya. */
.fbar-urut { grid-column: span 2; }
.fbar-urut select:first-child { flex: 1 1 auto; width: auto; min-width: 0; }
.fbar-urut select:last-child  { flex: 0 0 auto; width: auto; }
.fbar-lanjut {
  display: grid; gap: 12px 14px; margin-top: 10px; padding: 14px 16px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  border: 1px solid var(--border-2); border-radius: 12px; background: var(--surface-2);
}
.fbar-lanjut label { display: flex; flex-direction: column; gap: 5px; font-size: 11.5px;
  font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
.fbar-lanjut .fbar-harga { grid-column: 1 / -1; }
.fchips { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 12px; }
.fchip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface);
  font-size: 12px; font-weight: 500; color: var(--text); text-decoration: none;
  transition: background .12s, border-color .12s; }
.fchip:hover { background: var(--danger-soft, var(--bg)); border-color: var(--danger); }
.fchip b { color: var(--text-muted); font-weight: 700; }
/* Judul kolom yang mengurutkan. Warna & panah hanya pada kolom yang aktif. */
.th-urut { color: inherit; text-decoration: none; white-space: nowrap; }
.th-urut:hover { color: var(--text); }
.th-urut.aktif { color: var(--primary-ink); }

/* Kotak pilih lewat jendela cari (grup, supplier) di bilah saringan. */
.fpick { position: relative; display: inline-flex; align-items: center; }
.fpick input[type=text] { width: 150px; cursor: pointer; background: var(--surface);
  font-size: 13.5px; padding: 8px 24px 8px 10px; }
.fpick-x { position: absolute; right: 7px; color: var(--text-muted); text-decoration: none;
  font-size: 15px; line-height: 1; }
.fpick-x:hover { color: var(--danger); }

/* Ringkasan hasil saringan. */
.fring { display: flex; gap: 18px; flex-wrap: wrap; align-items: center;
  margin: 0 0 12px; padding: 9px 16px; border: 1px solid var(--border-2);
  border-radius: 12px; background: var(--surface); font-size: 12.5px;
  color: var(--text-muted); box-shadow: var(--shadow-soft); }
.fring b { color: var(--text); font-size: 13.5px; }

/* Bilah ubah massal — melayang di atas tabel begitu ada yang dicentang. */
.fmassal { position: sticky; top: calc(var(--ao-tb-bawah) + 8px); z-index: 6; display: flex; gap: 8px;
  align-items: center; flex-wrap: wrap; margin-bottom: 10px; padding: 10px 14px;
  border: 1px solid var(--primary-brd); border-radius: 12px;
  background: var(--primary-soft); font-size: 13px; box-shadow: var(--shadow-float); }
.fmassal select, .fmassal input[type=text] { width: auto; font-size: 13px; padding: 6px 9px; }
.fmassal .mss { display: inline-flex; gap: 6px; align-items: center; }

/* Sisa stok dalam satuan bertingkat: baris kedua, kecil, tidak melebarkan
   kolom karena angkanya sendiri biasanya lebih panjang. */
.sal-tingkat { display: block; font-size: 10.5px; color: var(--text-muted);
  font-weight: 400; white-space: nowrap; margin-top: 1px; }

/* Nama satuan di belakang harga, saat Master Barang menampilkan harga per
   satuan terbesar. Sengaja SEBARIS dengan angkanya, bukan di bawahnya:
   enam kolom harga yang masing-masing jadi dua baris membuat tabelnya dua
   kali lebih tinggi untuk satu keterangan yang sama di semua kolom. */
.hrg-sat { font-size: 10px; color: var(--text-dim); font-weight: 400; margin-left: 2px; }

/* ---- Misc ---- */
.text-muted  { color: var(--text-muted); }
.text-danger { color: var(--danger); }
.text-right  { text-align: right; }
.mt-1 { margin-top: 8px; }
.mt-2 { margin-top: 16px; }
.flex { display: flex; }
.gap-2 { gap: 8px; }

/* ---- Confirm dialog ---- */
#confirm-backdrop {
  display: none; position: fixed; inset: 0;
  background: var(--overlay); z-index: 600;
  align-items: center; justify-content: center; padding: 16px;

}
#confirm-backdrop.open { display: flex; animation: ao-tirai .15s ease; }
#confirm-box {
  background: var(--surface); border: 1px solid var(--border-2);
  border-radius: var(--radius-xl); padding: 26px 24px 22px;
  max-width: 380px; width: 100%; text-align: center;
  box-shadow: var(--shadow-pop);
  animation: modal-in .2s cubic-bezier(.2,.8,.2,1);
}
#confirm-box .ci {
  width: 52px; height: 52px; border-radius: 50%; margin: 0 auto 14px;
  display: flex; align-items: center; justify-content: center;
  background: var(--danger-soft); color: var(--danger-ink); font-size: 24px;
}
#confirm-box p { font-size: 14.5px; font-weight: 600; margin-bottom: 20px; color: var(--text); }
#confirm-box .btns { display: flex; gap: 10px; justify-content: center; }
#confirm-box .btns .btn { flex: 1; }

/* ---- Section header inside modal/form ----
   Dulu kotak berwarna dengan garis tebal di kiri. Sekarang judul kecil
   dengan titik warna dan garis tipis yang menyambung ke kanan: warnanya
   masih membedakan kelompok, tapi tidak lagi berebut perhatian dengan
   isian di bawahnya. */
.section-hdr {
  font-size: 11.5px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .08em; padding: 0; border-radius: 0;
  margin: 22px 0 12px; display: flex; align-items: center; gap: 9px;
  color: var(--text-soft);
}
.section-hdr::before {
  content: ""; width: 8px; height: 8px; border-radius: 3px; flex-shrink: 0;
  background: currentColor;
}
.section-hdr::after {
  content: ""; flex: 1; height: 1px; background: var(--border-2);
}
.section-hdr:first-child { margin-top: 2px; }
.section-hdr.blue   { color: var(--primary-ink); }
.section-hdr.green  { color: var(--success-ink); }
.section-hdr.amber  { color: var(--warn-ink); }
.section-hdr.purple { color: var(--purple-ink); }
.section-hdr.slate  { color: var(--slate-ink); }

/* ---- Auto-code badge ---- */
.auto-code {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--primary-soft); color: var(--primary-ink); border: 1px solid var(--primary-brd);
  border-radius: 9px; padding: 8px 14px; font-size: 14px;
  font-family: var(--font-kode); font-weight: 700; letter-spacing: .03em;
}
.auto-code small { font-size: 11px; color: var(--primary-dim); font-family: var(--font-ui); font-weight: 500; display: block; margin-top: 1px; }

/* ---- Satuan builder (setstok) ---- */
.satuan-row {
  display: grid;
  grid-template-columns: 28px minmax(90px,1.2fr) 70px minmax(110px,1.5fr) 28px;
  gap: 8px; align-items: end;
  padding: 10px 12px; background: var(--surface-2);
  border: 1px solid var(--border-2); border-radius: 12px; margin-bottom: 8px;
}
.satuan-row .level-badge {
  width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700;
  background: var(--primary-soft2); color: var(--primary-ink); flex-shrink: 0;
}
.satuan-row.level-1 { background: var(--primary-soft); border-color: var(--primary-brd); }
.satuan-row.level-1 .level-badge { background: var(--primary); color: var(--on-accent); }
.satuan-remove {
  background: none; border: none; cursor: pointer;
  color: var(--text-dim); font-size: 18px; padding: 0;
  transition: color .15s;
}
.satuan-remove:hover { color: var(--danger-ink); }

/* ---- Barcode row ---- */
.barcode-row {
  display: grid; grid-template-columns: 1fr auto;
  gap: 8px; align-items: center;
  margin-bottom: 8px;
}
.barcode-remove {
  background: none; border: 1px solid var(--danger-brd); color: var(--danger-ink);
  border-radius: 8px; cursor: pointer; padding: 6px 10px; font-size: 13px;
  transition: background .15s;
}
.barcode-remove:hover { background: var(--danger-soft); }

/* ---- Harga table ---- */
.harga-table { width: 100%; border-collapse: separate; border-spacing: 0;
  border: 1px solid var(--border-2); border-radius: 12px; overflow: hidden; }
.harga-table th {
  background: var(--warn-soft2); color: var(--warn-ink); font-size: 12px;
  font-weight: 700; padding: 9px 12px; text-align: left;
  border-bottom: 1px solid var(--warn-brd); position: static;
}
.harga-table td { padding: 8px 12px; border-bottom: 1px solid var(--border-3); }
.harga-table tr:last-child td { border-bottom: none; }
.harga-table tr.eceran td { background: var(--warn-soft2); }
.harga-table input { width: 100%; }

/* ---- Satuan list header ---- */
.satuan-hdr {
  display: grid;
  grid-template-columns: 28px minmax(90px,1.2fr) 70px minmax(110px,1.5fr) 28px;
  gap: 8px; padding: 0 12px; margin-bottom: 4px;
}
.satuan-hdr span { font-size: 11px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }

/* Kolom kalkulasi harga per satuan turunan */
.harga-table td[id^="hcalc-"] { color: var(--text-muted); font-size: 12px; line-height: 1.7; }

/* Input harga per satuan turunan — 2 arah, bisa diketik langsung */
.hcalc-item { display: inline-flex; align-items: center; gap: 4px; margin: 0 10px 4px 0; }
input.hcalc-inp {
  width: 82px; padding: 4px 7px; font-size: 12px; border-radius: 6px;
  text-align: right;
}
.hcalc-unit { font-size: 11px; color: var(--text-muted); white-space: nowrap; }

/* Gulir yang tipis dan membulat, mengikuti tema. Wadah tabel dan menu
   punya gulungan sendiri; batang abu-abu tebal bawaan Windows di tengah
   kartu yang membulat terlihat seperti bagian yang tertinggal. */
* { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 99px; border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background-color: var(--text-dim); }
::-webkit-scrollbar-track { background: transparent; }

@media (prefers-reduced-motion: reduce) {
  .modal, .modal-backdrop.open, #confirm-box, #confirm-backdrop.open,
  .tnav-dropdown, .tnav-flyout { animation: none !important; }
}

/* ============================================================
   TEMA
   ------------------------------------------------------------
   Tema bekerja dengan menimpa variabel di :root lewat atribut
   data-theme pada elemen <html>. Atribut itu dipasang oleh skrip
   kecil di config/layout.php SEBELUM <body> dirender, supaya tidak
   ada kedipan putih sesaat (flash of unstyled theme).

   Tema "custom" memakai palet dasar terang/gelap sesuai data-base,
   lalu 5 warna pilihan user ditimpa sebagai inline style di <html>
   oleh assets/js/tema.js (inline style menang atas stylesheet).
   ============================================================ */

/* ---- Gelap (dark mode) ---- */
html[data-theme="dark"],
html[data-theme="custom"][data-base="dark"] {
  color-scheme: dark;
  --bg:            #0f172a;
  --surface:       #1e293b;
  --surface-2:     #172234;
  --surface-3:     #24344d;
  --surface-4:     #334155;
  --border:        #334155;
  --border-2:      #2c3d55;
  --border-3:      #223047;

  --text:          #e2e8f0;
  --text-muted:    #94a3b8;
  --text-soft:     #cbd5e1;
  --text-label:    #cbd5e1;
  --text-dim:      #7c8ba1;
  --on-accent:     #ffffff;
  --on-accent-dim: rgba(255,255,255,.78); /* teks sekunder di atas latar gelap tetap */

  --primary:       #5b96f8;
  --primary-h:     #3b82f6;
  --primary-soft:  #16304f;
  --primary-soft2: #1d3a5f;
  --primary-brd:   #2f5a8f;
  --primary-ink:   #93c5fd;
  --primary-dim:   #60a5fa;
  --row-hover:     #1c2b42;

  --danger:        #f87171;
  --danger-h:      #ef4444;
  --danger-soft:   #3f1d1d;
  --danger-soft2:  #2a1616;
  --danger-brd:    #7f2a2a;
  --danger-ink:    #fca5a5;

  --success:       #22c55e;
  --success-soft:  #14331f;
  --success-soft2: #10281a;
  --success-brd:   #2f7d4f;
  --success-ink:   #86efac;

  --warn:          #f59e0b;
  --warn-soft:     #3a2d10;
  --warn-soft2:    #2c220c;
  --warn-brd:      #7a5a1a;
  --warn-ink:      #fcd34d;

  --purple-soft:   #2a1f4a;
  --purple-brd:    #7c5cd6;
  --purple-ink:    #c4b5fd;
  --slate-soft:    #24344d;
  --slate-brd:     #64748b;
  --slate-ink:     #cbd5e1;

  --topbar-bg:     #16233a;
  --topbar-fg:     #e2e8f0;
  --topbar-fg-dim: #a8b6c9;
  --topbar-hover:  rgba(255,255,255,.07);
  --topbar-active: rgba(255,255,255,.12);
  --topbar-line:   rgba(226,232,240,.85);


  /* ── Warna "solid": TETAP di semua tema ──────────────────────────
     Dipakai untuk latar pekat yang di atasnya selalu ada teks putih —
     header tabel laporan, badge status, pita judul.

     Kenapa tidak memakai --primary-ink / --warn-ink / --text saja?
     Karena variabel itu MEMBALIK antar tema: --warn-ink bernilai #92400e
     (cokelat tua) di tema terang tapi #fcd34d (kuning muda) di tema gelap.
     Sebagai warna TEKS itu benar — ia harus ikut membalik mengikuti latar
     lembutnya. Tapi sebagai LATAR, hasilnya teks putih di atas kuning muda
     alias tidak terbaca. Warna di bawah ini sengaja tidak ikut tema. */
  --solid-slate:  #1e293b;
  --solid-blue:   #1d4ed8;
  --solid-green:  #15803d;
  --solid-amber:  #92400e;
  --solid-red:    #b91c1c;
  --solid-purple: #5b21b6;

  --shadow:        0 1px 3px rgba(0,0,0,.5);
  --shadow-card:   0 2px 8px rgba(0,0,0,.4);
  --shadow-topbar: 0 2px 8px rgba(0,0,0,.55);
  --shadow-modal:  0 8px 30px rgba(0,0,0,.6);
  --overlay:       rgba(0,0,0,.65);
}

/* ---- Navy (biru tua) ---- */
html[data-theme="blue"] {
  color-scheme: dark;
  --bg:            #0a1a33;
  --surface:       #123056;
  --surface-2:     #0e2645;
  --surface-3:     #16395f;
  --surface-4:     #1d4675;
  --border:        #1e4272;
  --border-2:      #1a3a66;
  --border-3:      #14304f;

  --text:          #e8f0fb;
  --text-muted:    #9db6d6;
  --text-soft:     #c5d8ef;
  --text-label:    #c5d8ef;
  --text-dim:      #7a97ba;
  --on-accent:     #ffffff;
  --on-accent-dim: rgba(255,255,255,.78); /* teks sekunder di atas latar gelap tetap */

  --primary:       #5aa0ec;
  --primary-h:     #3f88db;
  --primary-soft:  #14355e;
  --primary-soft2: #1a4173;
  --primary-brd:   #2f6bab;
  --primary-ink:   #a8cdfb;
  --primary-dim:   #7ab4fb;
  --row-hover:     #16395f;

  --danger:        #f47272;
  --danger-h:      #f05252;
  --danger-soft:   #4a1c22;
  --danger-soft2:  #331419;
  --danger-brd:    #8c2f38;
  --danger-ink:    #fbb3b3;

  --success:       #2fc46b;
  --success-soft:  #10352a;
  --success-soft2: #0c2a21;
  --success-brd:   #2b7f57;
  --success-ink:   #8ce9b5;

  --warn:          #f0a92c;
  --warn-soft:     #3d3113;
  --warn-soft2:    #2e250e;
  --warn-brd:      #7d611d;
  --warn-ink:      #fbd47c;

  --purple-soft:   #26235c;
  --purple-brd:    #7d6de0;
  --purple-ink:    #c3bcfa;
  --slate-soft:    #16395f;
  --slate-brd:     #6b8bb0;
  --slate-ink:     #c5d8ef;

  --topbar-bg:     #061428;
  --topbar-fg:     #e8f0fb;
  --topbar-fg-dim: #a9c2e0;
  --topbar-hover:  rgba(255,255,255,.08);
  --topbar-active: rgba(255,255,255,.14);
  --topbar-line:   rgba(232,240,251,.85);


  /* ── Warna "solid": TETAP di semua tema ──────────────────────────
     Dipakai untuk latar pekat yang di atasnya selalu ada teks putih —
     header tabel laporan, badge status, pita judul.

     Kenapa tidak memakai --primary-ink / --warn-ink / --text saja?
     Karena variabel itu MEMBALIK antar tema: --warn-ink bernilai #92400e
     (cokelat tua) di tema terang tapi #fcd34d (kuning muda) di tema gelap.
     Sebagai warna TEKS itu benar — ia harus ikut membalik mengikuti latar
     lembutnya. Tapi sebagai LATAR, hasilnya teks putih di atas kuning muda
     alias tidak terbaca. Warna di bawah ini sengaja tidak ikut tema. */
  --solid-slate:  #1e293b;
  --solid-blue:   #1d4ed8;
  --solid-green:  #15803d;
  --solid-amber:  #92400e;
  --solid-red:    #b91c1c;
  --solid-purple: #5b21b6;

  --shadow:        0 1px 3px rgba(0,0,0,.5);
  --shadow-card:   0 2px 8px rgba(0,0,0,.42);
  --shadow-topbar: 0 2px 8px rgba(0,0,0,.6);
  --shadow-modal:  0 8px 30px rgba(0,0,0,.62);
  --overlay:       rgba(2,10,22,.7);
}

/* ---- Army (hijau militer) ---- */
html[data-theme="green"] {
  color-scheme: dark;
  --bg:            #1c2418;
  --surface:       #27321f;
  --surface-2:     #212b1a;
  --surface-3:     #2f3b25;
  --surface-4:     #3a4930;
  --border:        #3c4a30;
  --border-2:      #35422b;
  --border-3:      #2a3421;

  --text:          #e9efdf;
  --text-muted:    #a8b795;
  --text-soft:     #cbd8b8;
  --text-label:    #cbd8b8;
  --text-dim:      #8a9877;
  --on-accent:     #ffffff;
  --on-accent-dim: rgba(255,255,255,.78); /* teks sekunder di atas latar gelap tetap */

  --primary:       #87ad42;
  --primary-h:     #6f9134;
  --primary-soft:  #26301a;
  --primary-soft2: #2e3b20;
  --primary-brd:   #4e6528;
  --primary-ink:   #b9d47f;
  --primary-dim:   #93b357;
  --row-hover:     #2f3b25;

  --danger:        #e8836e;
  --danger-h:      #d4553f;
  --danger-soft:   #3d211a;
  --danger-soft2:  #2e1913;
  --danger-brd:    #7d3627;
  --danger-ink:    #eda893;

  --success:       #5fa855;
  --success-soft:  #1f3320;
  --success-soft2: #182818;
  --success-brd:   #467a40;
  --success-ink:   #a8dda0;

  --warn:          #c99a2e;
  --warn-soft:     #362c13;
  --warn-soft2:    #29220e;
  --warn-brd:      #6f5a1c;
  --warn-ink:      #e8c878;

  --purple-soft:   #2b2740;
  --purple-brd:    #7a6cb3;
  --purple-ink:    #c0b6e4;
  --slate-soft:    #2f3b25;
  --slate-brd:     #7d8b6a;
  --slate-ink:     #cbd8b8;

  --topbar-bg:     #161d12;
  --topbar-fg:     #e9efdf;
  --topbar-fg-dim: #b3c19c;
  --topbar-hover:  rgba(255,255,255,.07);
  --topbar-active: rgba(255,255,255,.13);
  --topbar-line:   rgba(233,239,223,.85);


  /* ── Warna "solid": TETAP di semua tema ──────────────────────────
     Dipakai untuk latar pekat yang di atasnya selalu ada teks putih —
     header tabel laporan, badge status, pita judul.

     Kenapa tidak memakai --primary-ink / --warn-ink / --text saja?
     Karena variabel itu MEMBALIK antar tema: --warn-ink bernilai #92400e
     (cokelat tua) di tema terang tapi #fcd34d (kuning muda) di tema gelap.
     Sebagai warna TEKS itu benar — ia harus ikut membalik mengikuti latar
     lembutnya. Tapi sebagai LATAR, hasilnya teks putih di atas kuning muda
     alias tidak terbaca. Warna di bawah ini sengaja tidak ikut tema. */
  --solid-slate:  #1e293b;
  --solid-blue:   #1d4ed8;
  --solid-green:  #15803d;
  --solid-amber:  #92400e;
  --solid-red:    #b91c1c;
  --solid-purple: #5b21b6;

  --shadow:        0 1px 3px rgba(0,0,0,.45);
  --shadow-card:   0 2px 8px rgba(0,0,0,.38);
  --shadow-topbar: 0 2px 8px rgba(0,0,0,.55);
  --shadow-modal:  0 8px 30px rgba(0,0,0,.58);
  --overlay:       rgba(8,12,6,.68);
}
html[data-theme="sky"] {
  color-scheme: light;
  --bg: #e9f2fb;
  --surface: #ffffff;
  --surface-2: #f4f9fe;
  --surface-3: #e4eff9;
  --surface-4: #cee2f3;
  --border: #c3daee;
  --border-2: #d7e7f5;
  --border-3: #e8f1fa;
  --text: #12314c;
  --text-muted: #4a6377;
  --text-soft: #2c4d69;
  --text-label: #26455f;
  --text-dim: #6a8399;
  --on-accent: #ffffff;
  --on-accent-dim: rgba(255,255,255,.78);
  --primary: #0b6bb3;
  --primary-h: #08558f;
  --primary-soft: #eaf4fc;
  --primary-soft2: #d4e9f8;
  --primary-brd: #a6d1ee;
  --primary-ink: #0a5c99;
  --primary-dim: #4aa3dd;
  --row-hover: #eaf4fd;
  --danger: #c62828;
  --danger-h: #a51f1f;
  --danger-soft: #fde3e3;
  --danger-soft2: #fef3f3;
  --danger-brd: #f2a3a3;
  --danger-ink: #b21f1f;
  --success: #14784a;
  --success-soft: #d8f3e4;
  --success-soft2: #eefaf3;
  --success-brd: #5cbf8c;
  --success-ink: #116340;
  --warn: #b06a05;
  --warn-soft: #fdf0d2;
  --warn-soft2: #fefaf0;
  --warn-brd: #f0cf8c;
  --warn-ink: #7d4a04;
  --purple-soft: #e9e6fb;
  --purple-brd: #7c5cd6;
  --purple-ink: #4c2f9e;
  --slate-soft: #e4eff9;
  --slate-brd: #7d97ac;
  --slate-ink: #2c4d69;
  --topbar-bg: #0b6bb3;
  --topbar-fg: #ffffff;
  --topbar-fg-dim: #ffffffcc;
  --topbar-hover: rgba(255,255,255,.12);
  --topbar-active: rgba(255,255,255,.18);
  --topbar-line: rgba(255,255,255,.85);
  --solid-slate: #1e293b;
  --solid-blue: #1d4ed8;
  --solid-green: #15803d;
  --solid-amber: #92400e;
  --solid-red: #b91c1c;
  --solid-purple: #5b21b6;
  --shadow: 0 1px 3px rgba(16,52,86,.10);
  --shadow-card: 0 2px 8px rgba(16,52,86,.09);
  --shadow-topbar: 0 2px 8px rgba(11,107,179,.28);
  --shadow-modal: 0 8px 30px rgba(16,52,86,.20);
  --overlay: rgba(12,40,66,.45);
}

html[data-theme="mint"] {
  color-scheme: light;
  --bg: #eaf5ee;
  --surface: #ffffff;
  --surface-2: #f3faf5;
  --surface-3: #e4f2e9;
  --surface-4: #cbe6d5;
  --border: #c0dccd;
  --border-2: #d5e9dd;
  --border-3: #e7f3ec;
  --text: #16352a;
  --text-muted: #4a6759;
  --text-soft: #2d5344;
  --text-label: #274b3d;
  --text-dim: #6a887a;
  --on-accent: #ffffff;
  --on-accent-dim: rgba(255,255,255,.78);
  --primary: #12775a;
  --primary-h: #0d5f48;
  --primary-soft: #e7f6ee;
  --primary-soft2: #d1ecdf;
  --primary-brd: #9dd6ba;
  --primary-ink: #0f6349;
  --primary-dim: #4fae8a;
  --row-hover: #eaf7f0;
  --danger: #c62828;
  --danger-h: #a51f1f;
  --danger-soft: #fde3e3;
  --danger-soft2: #fef3f3;
  --danger-brd: #f2a3a3;
  --danger-ink: #b21f1f;
  --success: #14784a;
  --success-soft: #d8f3e4;
  --success-soft2: #eefaf3;
  --success-brd: #5cbf8c;
  --success-ink: #116340;
  --warn: #a86a08;
  --warn-soft: #fbefd4;
  --warn-soft2: #fdf9f0;
  --warn-brd: #e8cb8e;
  --warn-ink: #764806;
  --purple-soft: #e9e6fb;
  --purple-brd: #7c5cd6;
  --purple-ink: #4c2f9e;
  --slate-soft: #e4f2e9;
  --slate-brd: #7ea394;
  --slate-ink: #2d5344;
  --topbar-bg: #12775a;
  --topbar-fg: #ffffff;
  --topbar-fg-dim: #ffffffcc;
  --topbar-hover: rgba(255,255,255,.12);
  --topbar-active: rgba(255,255,255,.18);
  --topbar-line: rgba(255,255,255,.85);
  --solid-slate: #1e293b;
  --solid-blue: #1d4ed8;
  --solid-green: #15803d;
  --solid-amber: #92400e;
  --solid-red: #b91c1c;
  --solid-purple: #5b21b6;
  --shadow: 0 1px 3px rgba(20,60,44,.10);
  --shadow-card: 0 2px 8px rgba(20,60,44,.09);
  --shadow-topbar: 0 2px 8px rgba(18,119,90,.26);
  --shadow-modal: 0 8px 30px rgba(20,60,44,.20);
  --overlay: rgba(16,48,36,.45);
}


/* ============================================================
   CETAK — mode HITAM PUTIH (hemat tinta)
   ------------------------------------------------------------
   Dipasang lewat data-print="bw" pada <html>. Tujuannya menekan
   pemakaian tinta pada laporan rutin (kas harian, laporan penjualan)
   yang dicetak tiap hari.

   Selektornya sengaja mengulang [data-print=bw] tiga kali. Alasannya
   teknis: banyak file di laporan/ punya aturan @media print sendiri
   seperti

       .lt thead tr.th-grp th { background:#1e3a5f!important;
                                print-color-adjust: exact }

   Aturan itu sudah !important DAN spesifisitasnya (0,1,3) lebih tinggi
   daripada `html[data-print=bw] *` yang cuma (0,1,0) — jadi kalau
   ditulis sekali saja, header tabel laporan TETAP tercetak biru tua
   dan mode hemat tinta tidak berpengaruh sama sekali. Dengan tiga
   atribut, spesifisitas naik ke (0,3,0) dan menang atas semuanya
   tanpa perlu menyunting 27 file laporan satu per satu.
   ============================================================ */
@media print {
  html[data-print="bw"],
  html[data-print="bw"] body { background: #fff !important; }

  html[data-print="bw"][data-print="bw"][data-print="bw"] *,
  html[data-print="bw"][data-print="bw"][data-print="bw"] *::before,
  html[data-print="bw"][data-print="bw"][data-print="bw"] *::after {
    background-color: transparent !important;
    background-image: none !important;
    color: #000 !important;
    border-color: #000 !important;
    box-shadow: none !important;
    text-shadow: none !important;
    -webkit-print-color-adjust: economy !important;
    print-color-adjust: economy !important;
  }
  /* Struktur tabel tetap terbaca lewat garis, bukan blok warna. */
  html[data-print="bw"][data-print="bw"][data-print="bw"] thead th {
    border-bottom: 1.5px solid #000 !important;
    font-weight: 700 !important;
  }
}

/* Mode berwarna: pastikan browser tidak "menghemat" warna sendiri. */
@media print {
  html[data-print="color"] { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ============================================================
   CETAK — netralkan wadah bergulir
   ------------------------------------------------------------
   Beberapa laporan membungkus tabelnya dalam wadah ber-overflow
   supaya bisa digeser di layar sempit:

       .lt-wrap { overflow-x: auto }      (lapdaftarhutang, lapdaftarpiutang,
                                           lapkrtlgn, lapkrtstok, lapkrtsup)
       .bk-wrap { overflow-x: auto }      (lapbkbesar)

   Saat DICETAK, wadah itu tidak ikut melebar mengikuti kertas — dia tetap
   selebar viewport, sehingga kolom di luar area terlihat TERPOTONG dan
   batang scroll-nya ikut tercetak sebagai garis horizontal. Persis gejala
   pada cetak Daftar Hutang & Daftar Piutang.

   lapdaftarstok.php dan lapnrclajur.php sudah punya penetral ini di
   @media print masing-masing — makanya keduanya tercetak normal. Enam
   laporan sisanya tidak punya. Diletakkan global di sini, bukan ditambal
   satu per satu, supaya laporan baru pun otomatis ikut benar.
   ============================================================ */
@media print {
  .lt-wrap, .bk-wrap, .tbl-wrap, .table-wrap, .pk-list {
    overflow: visible !important;
    max-height: none !important;
  }
  .lt, .bk-tbl { width: 100% !important; }
}

/* ============================================================
   CETAK — sembunyikan kerangka aplikasi
   ------------------------------------------------------------
   Sebagian besar file di laporan/ sudah menyembunyikan .topbar dan
   kawan-kawan lewat @media print masing-masing. Tapi tiap laporan
   menuliskannya ulang sendiri, sehingga laporan yang lupa (mis.
   lapdaftarstokpromo.php, yang memang tidak punya blok @media print
   sama sekali) ikut mencetak batang menu dan navigasinya.

   Aturan global di sini menutup celah itu sekali untuk semua halaman —
   termasuk halaman non-laporan yang sesekali dicetak.
   ============================================================ */
@media print {
  .topbar, .tnav, .tnav-dropdown, .tnav-flyout, .hamburger,
  .mobile-nav, .sidebar, .btn-toolbar, .pagination,
  .modal-backdrop, .subs-warning-banner, .confirm-backdrop, #confirm-backdrop {
    display: none !important;
  }
  .page-wrapper, .main-content { padding: 0 !important; margin: 0 !important; }
  .card { box-shadow: none !important; border: none !important; }
}

/* ══ Panel navigasi di kiri ════════════════════════════════════════════════
   Pilihan per orang, disimpan di localStorage bersama tema (kunci ao_nav).
   tema.js memasang data-nav pada <html> di dalam <head> — sebelum <body>
   dirender — supaya halaman tidak sempat tergambar dengan menu di atas lalu
   melompat ke kiri di setiap perpindahan halaman.

   Bilah atas TETAP ADA di mode ini: lonceng notifikasi harus selalu terlihat,
   dan menurunkannya ke kiri bawah membuatnya lebih mudah terlewat — padahal
   seluruh gunanya justru memberi tahu tanpa diminta.

   Panelnya position:fixed, bukan sticky: isinya bisa lebih panjang dari layar
   di pemasangan bermenu banyak, dan ia harus bisa digulir sendiri tanpa ikut
   menyeret halaman. */
html[data-nav="kiri"] { --ao-sidebar-w: 236px; }
html[data-nav="kiri"][data-nav-ciut="1"] { --ao-sidebar-w: 60px; }

/* Panelnya ikut MENGAMBANG seperti bilah atas: berjarak dari tepi layar,
   sudutnya melengkung, dan bayangannya sama. Dua kartu sewarna yang
   terpisah celah tipis terbaca sebagai satu rangka — bukan dua pita
   yang kebetulan bersentuhan di pojok kiri atas. */
html[data-nav="kiri"] .topnav {
  position: fixed; top: calc(var(--ao-tb-bawah) + var(--ao-tb-gap));
  left: var(--ao-tb-gap); bottom: var(--ao-tb-gap);
  width: var(--ao-sidebar-w); height: auto;
  flex-direction: column; align-items: stretch; gap: 2px;
  background: var(--topbar-bg);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-topbar), var(--shadow-float);
  overflow-y: auto; overflow-x: hidden;
  z-index: 150; padding: 8px 8px 54px;
  transition: width .15s ease;
}
html[data-nav="kiri"] .page-wrapper { margin-left: calc(var(--ao-sidebar-w) + var(--ao-tb-gap)); }

/* Isi menu jadi tumpukan tegak — pola yang sama dengan mode sempit:
   dropdown melebar ke bawah di tempat, bukan melayang. */
html[data-nav="kiri"] .tnav-item { flex-direction: column; align-items: stretch; height: auto; }
/* Di panel kiri submenu dibuka dengan KLIK, tidak dengan menyorot. Panel
   kiri adalah daftar yang dilewati kursor setiap kali menuju halaman —
   kalau menyorot saja sudah membuka submenu, isi panel melompat-lompat
   mengikuti jalannya tetikus dan orang kehilangan apa yang tadi ia lihat.
   Aturan :hover umum (untuk bilah atas) dikalahkan di sini; .open — yang
   dipasang oleh klik — dimenangkan sesudahnya. */
html[data-nav="kiri"] .tnav-item:hover .tnav-dropdown { display: none; }
html[data-nav="kiri"] .tnav-item.open .tnav-dropdown { display: block; }
html[data-nav="kiri"] .tnav-link {
  padding: 0 10px; height: 38px;
  display: flex; align-items: center; gap: 10px; white-space: nowrap;
}
html[data-nav="kiri"] .tnav-item:hover > .tnav-link .tnav-arrow { transform: none; }
html[data-nav="kiri"] .tnav-item.open > .tnav-link .tnav-arrow { transform: rotate(180deg); }
html[data-nav="kiri"] .tnav-arrow { margin-left: auto; }
html[data-nav="kiri"] .tnav-dropdown {
  position: static; box-shadow: none; border: none; border-radius: 0;
  background: none; padding: 2px 0 6px; display: none; animation: none;
  min-width: 0; max-width: none;
}
html[data-nav="kiri"] .tnav-dropdown::before { display: none; }
html[data-nav="kiri"] .tnav-item.open .tnav-dropdown { display: block; }
html[data-nav="kiri"] .tnav-dd-item {
  color: var(--topbar-fg-dim); padding: 7px 10px 7px 38px; white-space: normal;
}
html[data-nav="kiri"] .tnav-dd-item:hover  { background: var(--topbar-hover); color: var(--topbar-fg); }
html[data-nav="kiri"] .tnav-dd-item.active { background: var(--topbar-active); color: var(--topbar-fg); }
html[data-nav="kiri"] .tnav-flyout-trigger { padding: 7px 10px 7px 38px; color: var(--topbar-fg-dim); cursor: pointer; }
html[data-nav="kiri"] .tnav-flyout-trigger:hover,
html[data-nav="kiri"] .tnav-flyout-item:hover > .tnav-flyout-trigger { background: var(--topbar-hover); color: var(--topbar-fg); }
html[data-nav="kiri"] .tnav-flyout-trigger.active { color: var(--topbar-fg); }
html[data-nav="kiri"] .tnav-flyout-arrow { margin-left: auto; }
html[data-nav="kiri"] .tnav-flyout {
  position: static; box-shadow: none; border: none; border-radius: 0;
  background: none; padding: 0; display: none; animation: none;
  min-width: 0; max-width: none;
}
html[data-nav="kiri"] .tnav-flyout::before { display: none; }
html[data-nav="kiri"] .tnav-flyout-item:hover > .tnav-flyout { display: none; }
html[data-nav="kiri"] .tnav-flyout-item.open > .tnav-flyout { display: block; }
html[data-nav="kiri"] .tnav-flyout .tnav-dd-item { padding-left: 52px; }

/* Diciutkan: label hilang, ikon tinggal. Menu tanpa ikon bawaan memakai
   huruf pertamanya — pemasangan bisa punya menu buatan sendiri, dan
   panel berisi kotak-kotak kosong lebih buruk daripada huruf. */
html[data-nav="kiri"][data-nav-ciut="1"] .tnav-teks,
html[data-nav="kiri"][data-nav-ciut="1"] .tnav-arrow { display: none; }
html[data-nav="kiri"][data-nav-ciut="1"] .tnav-link { justify-content: center; padding: 0; }
html[data-nav="kiri"][data-nav-ciut="1"] .tnav-dropdown { display: none !important; }

/* Tombol ciutkan, menempel di dasar panel — di DALAM lengkungnya. */
.nav-ciut-btn { display: none; }
html[data-nav="kiri"] .nav-ciut-btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  position: fixed; left: var(--ao-tb-gap); bottom: var(--ao-tb-gap); width: var(--ao-sidebar-w);
  height: 42px; z-index: 151;
  background: var(--topbar-bg); color: var(--topbar-fg-dim);
  border: none; border-top: 1px solid var(--topbar-active);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  font-size: 12px; cursor: pointer; transition: width .15s ease, color .15s;
}
html[data-nav="kiri"] .nav-ciut-btn:hover { color: var(--topbar-fg); }

/* Lencana versi digeser supaya tidak tertimpa panel. */
html[data-nav="kiri"] .versi-cap { left: calc(var(--ao-sidebar-w) + var(--ao-tb-gap) + 8px); }

/* Tombol sembunyikan/tampilkan panel — hanya di mode kiri layar lebar. */
.tb-panel { display: none !important; }
html[data-nav="kiri"]:not([data-topnav="sempit"]) .tb-panel { display: inline-flex !important; }
/* Tombol panel + merek + sisi kanan: tanpa ini space-between menaruh merek di TENGAH bilah. */
html[data-nav="kiri"] .topbar-brand { margin-right: auto; }
/* Panel disembunyikan: seluruh lebar layar untuk isi halaman. */
html[data-nav="kiri"][data-nav-sembunyi="1"]:not([data-topnav="sempit"]) .topnav,
html[data-nav="kiri"][data-nav-sembunyi="1"]:not([data-topnav="sempit"]) .nav-ciut-btn { display: none; }
html[data-nav="kiri"][data-nav-sembunyi="1"] { --ao-sidebar-w: 0px; }
html[data-nav="kiri"][data-nav-sembunyi="1"]:not([data-topnav="sempit"]) .page-wrapper { margin-left: 0; }
html[data-nav="kiri"][data-nav-sembunyi="1"] .versi-cap { left: 8px; }

/* Layar sempit menang atas pilihan orang: panel kiri di layar 400px tidak
   menyisakan ruang untuk apa pun. Di sana ia kembali jadi menu tarik-turun
   dari hamburger, persis mode atas yang sempit. */
html[data-nav="kiri"][data-topnav="sempit"] .topnav {
  position: absolute; top: calc(100% + 8px); left: 0; right: 0; bottom: auto;
  width: auto; padding: 8px; box-shadow: var(--shadow-pop);
}
html[data-nav="kiri"][data-topnav="sempit"] .page-wrapper { margin-left: 0; }
html[data-nav="kiri"][data-topnav="sempit"] .nav-ciut-btn { display: none; }
html[data-nav="kiri"][data-topnav="sempit"] .versi-cap { left: 8px; }

@media print {
  html[data-nav="kiri"] .topnav,
  html[data-nav="kiri"] .nav-ciut-btn { display: none !important; }
  html[data-nav="kiri"] .page-wrapper { margin-left: 0 !important; }
}

/* ══ Kartu Beranda ═════════════════════════════════════════════════════════
   Kolomnya menyesuaikan sendiri lewat auto-fit: di layar 2560px kartunya
   berjajar lima, di 900px jadi dua, di ponsel satu — tanpa satu breakpoint
   pun yang harus ditebak. Kartu grafik mengambil dua kolom kalau muat. */
.dash-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
  gap:16px;margin-bottom:24px}
.dash-card{background:var(--surface);border:1px solid var(--border-2);
  border-radius:var(--radius-lg);box-shadow:var(--shadow-soft);display:flex;flex-direction:column}
@media (min-width:960px){ .dash-lebar{grid-column:span 2} }
.dash-head{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:13px 16px;border-bottom:1px solid var(--border-2);
  font-size:13px;font-weight:700}
.dash-head a{font-size:11px;font-weight:400;color:var(--text-muted);text-decoration:none}
.dash-head a:hover{color:var(--primary);text-decoration:underline}
.dash-body{padding:13px 15px;flex:1}
.dash-kosong{font-size:12.5px;color:var(--text-muted);padding:14px 0;text-align:center}
.dash-kaki{font-size:11px;color:var(--text-muted);line-height:1.5;margin-top:9px}
.dash-besar{font-size:23px;font-weight:700;font-variant-numeric:tabular-nums;line-height:1.2}
.dash-sedang{font-size:16px;font-weight:700;font-variant-numeric:tabular-nums;line-height:1.3}
.dash-kecil{font-size:11.5px;color:var(--text-muted)}
.dash-duo{display:flex;gap:20px;flex-wrap:wrap}
.dash-duo > div{min-width:130px}
.dash-delta{display:inline-block;margin-top:7px;font-size:12px;font-weight:700;
  padding:2px 9px;border-radius:20px}
.dash-delta.naik{background:var(--success-soft);color:var(--success-ink)}
.dash-delta.turun{background:var(--danger-soft);color:var(--danger-ink)}
.dash-delta.netral{background:var(--surface-3);color:var(--text-muted);font-weight:400}
.dash-tabel{width:100%;border-collapse:collapse;font-size:12.5px}
.dash-tabel td{padding:5px 0;border-bottom:1px solid var(--border-3);vertical-align:top}
.dash-tabel tr:last-child td{border-bottom:0}
.dash-tabel td.angka{text-align:right;white-space:nowrap;font-variant-numeric:tabular-nums;
  font-weight:600;padding-left:10px}
.dash-tabel td.angka.bahaya{color:var(--danger-ink)}
.dash-tabel td.angka.ingat{color:var(--warn-ink)}
.dash-sedang.bahaya{color:var(--danger-ink)}
.dash-sedang.ingat{color:var(--warn-ink)}
.dash-min{font-size:11px;color:var(--text-muted);font-weight:400}

/* Pemilih rentang grafik. */
.dash-rentang{display:flex;gap:4px}
.dash-rentang a{font-size:11px;padding:2px 8px;border-radius:20px;
  border:1px solid var(--border);color:var(--text-muted);text-decoration:none}
.dash-rentang a:hover{border-color:var(--primary);color:var(--primary);text-decoration:none}
.dash-rentang a.aktif{background:var(--primary-soft);border-color:var(--primary-brd);
  color:var(--primary-ink);font-weight:700}

/* Grafik. preserveAspectRatio="none" membuatnya melar mengikuti lebar kartu;
   vector-effect menjaga garisnya tetap setebal 2px walau ikut dilebarkan —
   tanpa itu garis akan menipis di kartu lebar dan menebal di kartu sempit. */
.dash-legenda{display:flex;gap:14px;font-size:11.5px;color:var(--text-muted);margin-bottom:6px}
.dash-legenda i{display:inline-block;width:11px;height:3px;border-radius:2px;
  vertical-align:middle;margin-right:5px}
.dash-svg{width:100%;height:190px;display:block;overflow:visible}
.dash-grid-line,.dash-svg .dash-grid{stroke:var(--border);stroke-width:1;
  vector-effect:non-scaling-stroke}
.dash-garis{fill:none;stroke-width:2;stroke-linejoin:round;stroke-linecap:round;
  vector-effect:non-scaling-stroke}
.dash-area{opacity:.12;stroke:none}
.dash-sumbu{font-size:11px;fill:var(--text-muted)}
.dash-duagrafik{display:grid;gap:12px}
@media (min-width:1200px){ .dash-duagrafik{grid-template-columns:1fr 1fr} }
/* 210, bukan 150. Grafiknya dibaca untuk melihat bentuk naik-turunnya,
   dan di 150px selisih hari yang satu dengan yang lain tinggal beberapa
   piksel — bedanya ada, tapi tidak terlihat. */
.dash-duagrafik .dash-svg{height:210px}
.dash-legenda b{margin-left:auto;color:var(--text);font-variant-numeric:tabular-nums}
.dash-legenda{align-items:center}

/* ══ Kepala tabel yang ikut menempel saat digulir ══════════════════════════
   Daftar 300 barang tidak bisa dibaca kalau nama kolomnya sudah lewat di atas
   layar — angka di kolom kelima berhenti punya arti.

   YANG MENGGULIR PEMBUNGKUSNYA, BUKAN HALAMAN. Ini bukan pilihan gaya:
   .lt-wrap dan .table-wrap sudah ber-overflow-x:auto untuk tabel lebar, dan
   itu MENJADIKANNYA wadah gulir. position:sticky di dalamnya menempel ke
   wadah itu — bukan ke layar — jadi selama wadahnya setinggi isinya, kepala
   tabel tetap ikut hanyut ke atas bersama halaman. Terukur: digulir 4000px,
   kepala tabelnya berada di y = -3541.

   Jadi wadahnya diberi tinggi maksimum dan menggulir sendiri. Tingginya
   diukur layout.php dari jarak wadah itu ke tepi bawah layar, karena ia
   berbeda di tiap halaman — laporan punya bilah saringan yang tinggi, master
   tidak.

   Latar kepala tabel WAJIB pekat. Yang tembus pandang akan menumpuk dengan
   baris yang lewat di belakangnya jadi bubur yang tidak terbaca — persis di
   saat kepala tabelnya paling dibutuhkan. */
.lt-wrap, .table-wrap {
  overflow: auto;
  max-height: var(--ao-tabel-tinggi, none);
}
thead th, .lt thead th { position: sticky; top: 0; z-index: 5; }

/* Kepala dua baris (mis. Laporan Daftar Stok): baris kedua menempel TEPAT di
   bawah baris pertama. Tingginya diukur, bukan ditebak — ia berubah mengikuti
   skala tampilan dan panjang judul kolomnya. */
.lt thead tr:nth-child(2) th { top: var(--ao-th1, 0px); }

/* Baris total ikut menempel di dasar: saldo akhir laporan panjang tidak lagi
   harus dicari sampai ujung gulungan. */
.lt tfoot td, .lt tfoot th { position: sticky; bottom: 0; z-index: 4; }

@media print {
  thead th, .lt thead th, .lt thead tr:nth-child(2) th,
  .lt tfoot td, .lt tfoot th { position: static !important; }
}

/* ══════════════════════════════════════════════════════════════════════
 * LAYAR TRANSAKSI — bilah alat, kepala nota, dan bilah bantuan
 * ----------------------------------------------------------------------
 * Empat layar bersaudara memakai blok ini: Retur Pembelian, Retur
 * Penjualan, Pelunasan Hutang, dan Pelunasan Piutang. Fungsinya sebangun
 * dua-dua, jadi tampilannya harus sebangun juga.
 *
 * KENAPA DISATUKAN. Sebelumnya tiap halaman membawa salinan gaya sendiri
 * dengan awalan sendiri — .rj-, .tb-, .lp- — dan salinan itu pelan-pelan
 * berbeda satu sama lain. Yang paling kelihatan: label kepala nota di sisi
 * penjualan tercetak KAPITAL, di sisi pembelian tidak, semata karena dua
 * aturan CSS yang kebetulan tidak ikut disalin. Tidak ada yang memutuskan
 * itu; ia cuma terjadi. Selama gayanya disalin per halaman, perbedaan
 * seperti itu akan lahir lagi.
 *
 * Yang TIDAK ikut ke sini: jumlah dan lebar kolom kepala nota. Tiap layar
 * punya isian yang berbeda banyaknya, jadi grid-template-columns tetap
 * ditulis di halamannya masing-masing — satu baris, tepat di bawah
 * pemakaian .trx-hdr.
 * ══════════════════════════════════════════════════════════════════════ */

/* ── Kepala dokumen: bilah atas, badge nota, kotak No. Nota, status ───
   Dulu ditulis ulang di sebelas halaman dengan empat nama kelas berbeda
   (.trx-toolbar, .tb-toolbar, .tj-toolbar, .po-toolbar) dan ukuran yang
   sedikit-sedikit berlainan. Nama lamanya tetap diterima di sini supaya
   JavaScript yang memakainya tidak perlu disentuh. */
.trx-toolbar,.tb-toolbar,.tj-toolbar,.po-toolbar{
  display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:12px;
}
.nota-badge{
  font-family:var(--font-kode);font-size:12.5px;font-weight:700;letter-spacing:.02em;
  padding:7px 12px;border-radius:9px;white-space:nowrap;
  background:var(--purple-soft);color:var(--purple-ink);border:1px solid var(--purple-brd);
}
.nota-badge.unsaved{background:var(--warn-soft);color:var(--warn-ink);border-color:var(--warn-brd)}

/* Kotak No. Nota: SATU bentuk di semua layar. Enter membuka nota bernomor
   itu; tombol kaca pembesar (atau F9) membuka daftar nota untuk dicari.
   Dulu ada yang "kotak + Buka + ▾", ada yang "kotak + ▾", ada yang
   "kotak + Buka + Cari Nota (F9)" — tiga cara untuk satu pekerjaan. */
.trx-nota{
  display:inline-flex;align-items:stretch;flex-shrink:0;
  border:1px solid var(--border);border-radius:9px;background:var(--surface);overflow:hidden;
  transition:border-color .15s,box-shadow .15s;
}
.trx-nota:focus-within{border-color:var(--primary);box-shadow:0 0 0 3px var(--ring)}
.trx-nota input[type=text]{
  border:0;border-radius:0;box-shadow:none!important;background:transparent;
  width:200px;padding:7px 10px;font-size:13px;font-family:var(--font-kode);
}
.trx-nota button{
  border:0;border-left:1px solid var(--border);background:var(--surface-2);color:var(--text-soft);
  padding:0 11px;cursor:pointer;display:flex;align-items:center;gap:6px;
  font-size:11.5px;font-weight:600;font-family:inherit;
}
.trx-nota button:hover{background:var(--primary-soft);color:var(--primary-ink)}
.trx-nota button kbd{font-family:var(--font-kode);font-size:10px;opacity:.75}
/* Tombol pencarian kecil di kepala layar penuh (Kasir, Pembelian, stok):
   kaca pembesar menggantikan "▾" — panah itu tidak memberi tahu bahwa
   yang terbuka adalah jendela cari. */
.btn-cari-mini{display:inline-flex;align-items:center;justify-content:center;padding-left:8px!important;padding-right:8px!important}

.trx-status,.tb-status,.tj-status{
  font-size:12px;font-weight:600;padding:5px 11px;border-radius:99px;white-space:nowrap;
  background:var(--surface-3);color:var(--text-muted);
}
.trx-status.saved,.tb-status.saved,.tj-status.saved{background:var(--success-soft);color:var(--success-ink)}
.trx-status.unsaved,.tb-status.unsaved,.tj-status.unsaved{background:var(--warn-soft);color:var(--warn-ink)}
.trx-status.error,.tb-status.error,.tj-status.error{background:var(--danger-soft);color:var(--danger-ink)}
.trx-tick,.tb-tick,.po-tick{font-size:12px;color:var(--text-dim);min-height:16px}
/* Label isian kepala nota — KAPITAL kecil, sama dengan .trx-hdr. Layar Kas,
   Jurnal Non-Kas, dan Tukar Poin dulu memakai label kalimat biasa sementara
   layar lain kapital, padahal posisinya sama persis. */
.trx-kepala label{
  display:block;font-size:11px;font-weight:700;color:var(--text-muted);
  text-transform:uppercase;letter-spacing:.04em;margin-bottom:4px;
}

/* align-items:start, BUKAN end. Kolom "Atas Nota" di kedua layar retur
   membawa kotak centang di bawah kotaknya, jadi selnya lebih tinggi dari
   yang lain. Dengan align-items:end, sel-sel pendek terdorong ke bawah dan
   labelnya jadi tidak sebaris — terlihat jelas di Retur Pembelian, dan
   samar-samar juga di Retur Penjualan. Semua kotak isian tingginya sama,
   jadi merapat ke atas menghasilkan baris yang rata. */
.trx-hdr{display:grid;gap:10px;align-items:start}
.trx-hdr label{
  font-size:11px;font-weight:700;color:var(--text-muted);
  display:block;margin-bottom:3px;
  text-transform:uppercase;letter-spacing:.04em;
}
.trx-hdr input,.trx-hdr select{
  width:100%;font-size:13px;padding:7px 10px;
  border:1.5px solid var(--border);border-radius:7px;
  background:var(--surface);color:var(--text);box-sizing:border-box;
}
.trx-hdr input:focus,.trx-hdr select:focus{border-color:var(--primary);outline:none}

/* Bilah bantuan tombol pintas, selalu di dasar halaman. */
/* ══ Bilah aksi + papan tombol — SEMUA layar transaksi ══════════════════
   Satu letak untuk tombol Simpan di setiap layar transaksi (Kasir dan
   Pembelian dikecualikan: keduanya punya panel bayar sendiri di kanan).
   Letaknya di BAWAH isian, rata kiri, dan Simpan selalu yang paling depan.

   Sebelumnya separuh layar menaruh Simpan di bilah atas dan separuh lagi di
   bawah; labelnya "Simpan", "Simpan F1", atau "Simpan (F1)"; dan tiga layar
   stok tidak punya tombolnya sama sekali. Orang yang berpindah dari Retur
   ke PO harus mencari ulang tombol yang paling sering ia tekan.

   Tombol yang MENGHAPUS dipisah ke ujung kanan (.trx-aksi-kanan), jauh
   dari Simpan: tangan yang terbiasa mengklik pojok kiri tidak boleh
   sesekali mendarat di "Hapus Nota". */
.trx-aksi{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:12px}
.trx-aksi-kanan{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap;align-items:center}
.btn kbd{
  font-family:var(--font-kode);font-size:10.5px;font-weight:600;line-height:1;
  padding:3px 5px;border-radius:5px;margin-left:3px;
  background:rgba(127,127,127,.13);border:1px solid rgba(127,127,127,.25);
  color:inherit;opacity:.9;
}
.btn-primary kbd,.btn-danger kbd,.btn-success kbd{background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.3)}

/* Papan tombol pintas. Tombol sungguhan, bukan tulisan mati: yang memakai
   mouse dapat tombolnya, yang memakai keyboard dapat petunjuknya, dan
   keduanya menjalankan fungsi yang sama persis. .trx-fk-info untuk
   petunjuk yang bukan aksi (Tab, panah) — tampil sebagai teks, tanpa
   bingkai, supaya tidak ada yang mengkliknya dan heran tidak terjadi apa-apa. */
.trx-fk{
  background:var(--surface-2);border:1px solid var(--border-2);border-radius:12px;
  padding:7px 10px;display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-top:10px;
}
.trx-fk button{
  background:var(--surface);border:1px solid var(--border);color:var(--text-soft);
  padding:3px 9px;border-radius:6px;font-size:11.5px;font-weight:500;cursor:pointer;
  font-family:inherit;transition:background .12s,color .12s,border-color .12s;white-space:nowrap;
}
.trx-fk button:hover{background:var(--primary);color:var(--on-accent);border-color:var(--primary)}
.trx-fk button.d{border-color:var(--danger-brd);color:var(--danger-ink)}
.trx-fk button.d:hover{background:var(--danger-soft);border-color:var(--danger-brd);color:var(--danger-ink)}
.trx-fk-info{font-size:11.5px;color:var(--text-muted);padding:3px 4px;white-space:nowrap}
.trx-fk-status{margin-left:auto;font-size:11.5px;color:var(--text-dim);white-space:nowrap}
.trx-catatan{font-size:11.5px;color:var(--text-muted);margin-top:8px;line-height:1.6}
@media print{ .trx-aksi,.trx-fk,.trx-catatan{display:none!important} }

/* Barang yang diretur atas sebuah nota tapi TIDAK ada di nota itu. Dipakai
   kedua layar retur — dulu hanya ada di transreturbeli.php, dan Retur
   Penjualan yang menyalinnya nanti pasti berbeda beberapa piksel. */
.bdg-luar{
  display:inline-block;padding:0 6px;border-radius:20px;font-size:9.5px;
  font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  white-space:nowrap;flex:0 0 auto;
  background:var(--warn-soft);color:var(--warn-ink);border:1px solid var(--warn-brd);
}

/* Kotak centang "tanpa nota asal" — sama di kedua layar retur. */
.trx-tn{
  display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;
  font-size:11px;font-weight:700;color:var(--text-muted);
  text-transform:uppercase;letter-spacing:.04em;margin-top:6px;
}
.trx-tn input{width:14px;height:14px;cursor:pointer;margin:0}

/* Isian yang hanya bisa dipilih lewat pencarian, bukan diketik. Digayakan
   berbeda supaya jelas bukan kotak ketik biasa — dulu tiap layar mengaturnya
   sendiri, dan dua di antaranya memakai #6366f1 mentah alih-alih var(--primary),
   jadi warna fokusnya tidak ikut berubah waktu tema diganti. */
.trx-hdr input[readonly]{background:var(--surface-2);color:var(--text-muted);cursor:pointer}
.trx-hdr input[readonly]:focus{background:var(--surface)}

/* Kaki tabel transaksi: keterangan di kiri, total di kanan. Dulu Retur
   Penjualan memakai .rj-foot dan Retur Pembelian memakai .total-bar —
   angkanya beda ukuran, beda warna, dan yang satu menulis "Rp" sementara
   yang lain tidak. */
.trx-foot{
  display:flex;justify-content:flex-end;align-items:center;gap:24px;flex-wrap:wrap;
  padding:10px 14px;background:var(--surface-2);border-top:1.5px solid var(--surface-3);
}
.trx-foot .lbl{font-size:11px;font-weight:700;color:var(--text-muted);
  text-transform:uppercase;letter-spacing:.04em}
.trx-foot .val{font-weight:700;font-family:monospace;font-size:17px;color:var(--purple-ink)}

/* Baris "belum ada isi" di tabel transaksi — miring, supaya jelas ia
   keterangan, bukan data. */
.trx-empty{padding:32px;text-align:center;color:var(--text-dim);font-size:13px;font-style:italic}

/* Isian berpasangan di kepala nota: kotak (atau dua) plus tombol cari di
   sebelahnya. Dipakai kolom Supplier/Pelanggan dan Atas Nota di kedua layar
   retur, supaya bentuknya sama persis. */
.trx-wrap{display:flex;gap:5px}
.trx-wrap input{flex:1;min-width:0}

/* Angka grafik waktu kursor lewat. Petaknya tak terlihat tapi menangkap
   kursor; garis tegak menandai hari yang sedang dibaca. */
.dash-grafik{position:relative}
.dash-petak rect{fill:transparent;cursor:crosshair}
.dash-tunjuk{stroke:var(--text-muted);stroke-width:1;stroke-dasharray:3 3;pointer-events:none}
.dash-tooltip{
  position:absolute;top:4px;z-index:3;pointer-events:none;
  background:var(--surface);border:1px solid var(--border);border-radius:7px;
  padding:6px 10px;font-size:11.5px;line-height:1.5;white-space:nowrap;
  box-shadow:0 4px 14px rgba(0,0,0,.13);color:var(--text);
}
.dash-tooltip b{display:block;font-size:11px;color:var(--text-muted);font-weight:700}
/* Angka yang belum beres — sisa alokasi, selisih bayar — diberi warna
   bahaya supaya kelihatan sebelum tombol Simpan ditekan. */
.trx-foot .val.warn{color:var(--danger-ink)}

/* ============================================================
   KOP LAPORAN
   ------------------------------------------------------------
   Disembunyikan di layar, ditampilkan saat dicetak. Aturan
   ".print-header{display:none}" milik sembilan laporan lama
   sudah melakukan separuhnya; yang di sini mengurus 25 laporan
   sisanya yang tidak punya aturan apa pun untuk kelas itu.

   !important pada cetak: sembilan laporan itu juga punya
   "@media print{.print-header{display:block!important}}"
   sendiri, dan tanpa !important di sini urutan muat yang
   menentukan siapa yang menang — sesuatu yang tidak boleh
   menentukan apakah nama toko muncul di kertas atau tidak.
   ============================================================ */
.lap-kop { display: none; }
@media print {
  .lap-kop { display: block !important; margin-bottom: 6px; text-align: center; }
  .lap-kop-toko   { font-size: 12pt; font-weight: 700; letter-spacing: .01em; }
  .lap-kop-alamat { font-size: 8pt; color: #444; margin-top: 1px; }
  .lap-kop h2     { font-size: 10.5pt !important; margin: 4px 0 1px !important;
                    text-transform: uppercase; letter-spacing: .03em; }
  .lap-kop p      { font-size: 8.5pt; color: #444; margin: 0; }
}

/* ══════════════════════════════════════════════════════════════════════
 * GERAK & MUAT
 * ----------------------------------------------------------------------
 * Animasi di aplikasi ini punya SATU tugas: memberi tahu bahwa sesuatu
 * terjadi. Baris yang dihapus tanpa gerak cuma "berkedip" — isi tabel
 * berubah dan orangnya harus membandingkan sendiri apa yang hilang. Pesan
 * galat yang muncul di tempat yang sama dengan pesan biasa gampang
 * terlewat. Jadi geraknya pendek (≤ 300 ms), tidak menghalangi ketikan
 * berikutnya, dan hilang sama sekali untuk yang memilih kurangi gerak.
 * ══════════════════════════════════════════════════════════════════════ */

/* Lingkaran berputar. Ukurannya ikut huruf, warnanya ikut teks. */
.ao-putar{
  display:inline-block;width:1em;height:1em;flex-shrink:0;vertical-align:-.15em;
  border:2px solid currentColor;border-right-color:transparent;border-radius:50%;
  animation:ao-putar .7s linear infinite;
}
.ikon.ikon-putar{animation:ao-putar 1s linear infinite}
@keyframes ao-putar{to{transform:rotate(360deg)}}

/* Hapus baris, baris baru, goyang, dan sorot pesan TIDAK di sini: semuanya
   lewat element.animate() di fungsi_umum.js (aoHapusBaris, aoBarisMasuk,
   aoGoyang, aoSorot). Kelas CSS + transition sempat dipakai dan tidak
   pernah terlihat: layar transaksi menulis "transition" sendiri pada
   barisnya dengan selektor yang lebih spesifik, dan transisi kita kalah. */

/* ── Muat laporan ────────────────────────────────────────────────────
   Laporan dihitung di server, jadi selama menunggu jawaban layar lama
   tetap terpampang — dan tanpa tanda apa pun orang mengira klik-nya
   tidak kena, lalu mengklik lagi. Tirai ini menutup ISI halaman (bukan
   bilah atas), meredupkan angka lama supaya tidak terbaca sebagai
   hasil baru, dan menaruh lingkaran berputar di tengah. */
.ao-muat{
  position:fixed;inset:var(--ao-tb-bawah) 0 0 0;z-index:150;
  display:flex;align-items:flex-start;justify-content:center;padding-top:18vh;
  background:color-mix(in srgb,var(--bg) 62%,transparent);
  animation:ao-tirai .18s ease;
}
@supports not (background:color-mix(in srgb,red,blue)){ .ao-muat{background:rgba(127,127,127,.25)} }
html[data-nav="kiri"] .ao-muat{left:calc(var(--ao-sidebar-w) + var(--ao-tb-gap))}
.ao-muat-kotak{
  display:flex;align-items:center;gap:12px;padding:14px 20px;
  background:var(--surface);border:1px solid var(--border-2);border-radius:14px;
  box-shadow:var(--shadow-pop);font-weight:600;font-size:13.5px;color:var(--text);
  animation:modal-in .2s cubic-bezier(.2,.8,.2,1);
}
.ao-muat-kotak .ao-putar{width:22px;height:22px;border-width:3px;color:var(--primary)}
.ao-muat-kotak small{display:block;font-weight:500;font-size:11.5px;color:var(--text-muted);margin-top:1px}

/* ── Kerangka (skeleton) ─────────────────────────────────────────────
   Untuk halaman yang isinya KARTU dan GRAFIK, bukan tabel: bentuk
   halamannya sudah terlihat sebelum angkanya datang, jadi mata tidak
   melompat waktu isinya muncul. */
.ao-kerangka{
  position:relative;overflow:hidden;border-radius:10px;
  /* --border-2, bukan --surface-3: di atas kartu putih yang kedua nyaris
     tidak terlihat, dan kerangka yang tidak terlihat sama saja dengan
     layar kosong. */
  background:var(--border-2);
}
.ao-kerangka::after{
  content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.45),transparent);
  animation:ao-kilau 1.3s ease-in-out infinite;
}
html[data-theme="dark"] .ao-kerangka::after,html[data-theme="blue"] .ao-kerangka::after,
html[data-theme="green"] .ao-kerangka::after,html[data-base="dark"] .ao-kerangka::after{
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.07),transparent);
}
@keyframes ao-kilau{to{transform:translateX(100%)}}
.ao-kerangka-tirai{
  position:fixed;inset:var(--ao-tb-bawah) 0 0 0;z-index:150;overflow:hidden;
  background:var(--bg);padding:22px 20px;animation:ao-tirai .15s ease;
}
html[data-nav="kiri"] .ao-kerangka-tirai{left:calc(var(--ao-sidebar-w) + var(--ao-tb-gap))}
.ao-kg{display:grid;gap:14px}
.ao-kg-2{grid-template-columns:1.1fr 1fr}
.ao-kg-4{grid-template-columns:repeat(4,1fr)}
.ao-kg-kartu{background:var(--surface);border:1px solid var(--border-2);border-radius:14px;padding:18px;display:grid;gap:10px}
@media (max-width:760px){ .ao-kg-2,.ao-kg-4{grid-template-columns:1fr 1fr} }

@media (prefers-reduced-motion: reduce){
  .ao-putar,.ikon.ikon-putar{animation-duration:2.4s}
  .ao-kerangka::after{animation:none}
  .ao-muat,.ao-muat-kotak,.ao-kerangka-tirai{animation:none}
}
@media print{ .ao-muat,.ao-kerangka-tirai{display:none!important} }

/* Kotak kode di grid transaksi: jarak dalam dipersempit. Huruf antarmuka
   sekarang lebih lebar daripada huruf sistem lama, dan kode barang 8
   karakter mulai terpotong di kotak 90-an piksel. Kolomnya ikut dilebarkan
   di masing-masing halaman (.tc-kode) — ini supaya pelebarannya cukup
   sedikit saja. */
td.tc-kode input[type=text]{padding-left:8px;padding-right:8px;font-variant-numeric:tabular-nums}

/* ══ Popup lookup: ukuran TETAP ═══════════════════════════════════════════
   Dulu tingginya mengikuti isi: membuka popup memperlihatkan daftar lama,
   lalu "Mencari…" (pendek), lalu hasil (panjang). Popup yang berada di
   tengah layar ikut naik-turun setiap kali tingginya berubah — terlihat
   seperti berkedip, dan mengetik satu huruf yang menyisakan satu barang
   membuat seluruh kotaknya menciut.

   Sekarang tingginya tetap; daftar hasilnya yang menggulir di dalam.
   ui.js menyiapkan susunan di dalamnya (daftar mengisi sisa ruang),
   karena markup tiap layar berbeda-beda. */
.modal.modal-lookup{
  height:min(620px, 86vh); max-height:none;
  display:flex; flex-direction:column; overflow:hidden;
}
.modal-lookup > .modal-header{flex-shrink:0}
.modal-lookup > .modal-body{flex:1 1 auto; min-height:0; overflow:auto}

/* Sedang memuat: daftar lama tetap terlihat tapi meredup — tidak dikosongkan
   menjadi satu baris "Mencari…" — dan kerangka baris kalau belum ada isi. */
.ao-memuat{opacity:.5;transition:opacity .12s;pointer-events:none}
.ao-lk-kerangka{display:flex;gap:14px;align-items:center;padding:12px 14px;border-bottom:1px solid var(--border-3)}
.ao-lk-kerangka .ao-kerangka{height:11px;flex:0 0 84px;border-radius:6px}
.ao-lk-kerangka .ao-kerangka + .ao-kerangka{flex:1 1 auto}
.ao-lk-kerangka .ao-kerangka + .ao-kerangka + .ao-kerangka{flex:0 0 70px}

/* ══ Toast & dialog ════════════════════════════════════════════════════════
   Pengganti alert() dan confirm() bawaan peramban. Kotak bawaan itu
   menghentikan seluruh halaman, bentuknya berbeda di tiap peramban, tidak
   ikut tema, dan judulnya "localhost says" — kasir tidak tahu itu pesan
   dari aplikasinya sendiri. Toast muncul di pojok kanan atas, di bawah
   bilah mengambang, dan pergi sendiri; dialog tetap menunggu jawaban tapi
   tampil sebagai bagian dari aplikasi. */
.ao-toast-wadah{
  position:fixed;top:calc(var(--ao-tb-bawah) + 12px);right:16px;z-index:1300;
  display:flex;flex-direction:column;gap:8px;width:min(380px,calc(100vw - 32px));pointer-events:none;
}
/* Layar penuh (Kasir, Pembelian, Mutasi): kanan atas adalah angka TOTAL
   yang paling sering dilirik. Toast pindah ke kanan bawah, di atas bilah
   tombol F. */
body:has(.kfoot) .ao-toast-wadah, body:has(.page-wrapper > .tbfoot) .ao-toast-wadah{
  top:auto;bottom:52px;flex-direction:column-reverse;
}
.ao-toast{
  pointer-events:auto;display:flex;align-items:flex-start;gap:10px;
  background:var(--surface);color:var(--text);border:1px solid var(--border-2);
  border-left:4px solid var(--primary);border-radius:12px;box-shadow:var(--shadow-pop);
  padding:11px 12px 11px 13px;font-size:13px;line-height:1.45;
}
.ao-toast.ok{border-left-color:var(--success)}
.ao-toast.warn{border-left-color:var(--warn)}
.ao-toast.err{border-left-color:var(--danger)}
.ao-toast-ikon{flex-shrink:0;width:22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:var(--primary-soft);color:var(--primary-ink);font-size:13px}
.ao-toast.ok .ao-toast-ikon{background:var(--success-soft);color:var(--success-ink)}
.ao-toast.warn .ao-toast-ikon{background:var(--warn-soft);color:var(--warn-ink)}
.ao-toast.err .ao-toast-ikon{background:var(--danger-soft);color:var(--danger-ink)}
.ao-toast-isi{flex:1;min-width:0;white-space:pre-line;overflow-wrap:anywhere}
.ao-toast-isi b{display:block;margin-bottom:1px}
.ao-toast-x{flex-shrink:0;border:0;background:none;color:var(--text-muted);cursor:pointer;
  width:24px;height:24px;border-radius:6px;font-size:14px;line-height:1}
.ao-toast-x:hover{background:var(--surface-3);color:var(--text)}

.ao-dialog-tirai{
  position:fixed;inset:0;z-index:1250;background:var(--overlay);
  display:flex;align-items:center;justify-content:center;padding:16px;
}
.ao-dialog{
  width:min(420px,100%);background:var(--surface);color:var(--text);
  border:1px solid var(--border-2);border-radius:var(--radius-xl);box-shadow:var(--shadow-pop);
  padding:22px 22px 18px;
}
.ao-dialog-kepala{display:flex;gap:14px;align-items:flex-start}
.ao-dialog-ikon{flex-shrink:0;width:42px;height:42px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:var(--primary-soft);color:var(--primary-ink);font-size:20px}
.ao-dialog.bahaya .ao-dialog-ikon{background:var(--danger-soft);color:var(--danger-ink)}
.ao-dialog-judul{font-size:15.5px;font-weight:800;letter-spacing:-.01em;margin-top:2px}
.ao-dialog-teks{font-size:13px;color:var(--text-soft);margin-top:5px;white-space:pre-line;line-height:1.55}
.ao-dialog-tombol{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}
@media print{ .ao-toast-wadah,.ao-dialog-tirai{display:none!important} }

/* Isian wajib yang belum terisi: bingkai merah yang TINGGAL sampai isiannya
   diubah, ditambah kedipan sesaat (aoTandaiBelumIsi di fungsi_umum.js). */
.ao-belum-isi,.ao-belum-isi:focus{
  border-color:var(--danger)!important;
  box-shadow:0 0 0 3px var(--danger-soft)!important;
}

/* ══ Identitas layar penuh: Kasir, Pembelian, layar stok ══════════════════
   Kasir dan Pembelian bentuknya bersaudara — grid barang di kiri, panel
   bayar di kanan — dan orang yang bergantian membuka keduanya bisa lupa
   sedang di layar yang mana. Panel kanannya sudah dibedakan warnanya; ini
   menambah PENANDA YANG DIBACA: label besar berikon di ujung kiri kepala
   layar, garis bawah kepala berwarna identitas, rona tipis yang memudar
   ke kanan, dan garis tepi panel bayar berwarna sama.
   Warnanya dari token tema (ikut berubah dengan tema):
     Kasir      → hijau  (--success): uang masuk dari pembeli
     Pembelian  → kuning (--warn):    barang masuk, uang keluar ke supplier
     layar stok → warna utama (--primary). */
.ident-kasir{--id:var(--success);--id-soft:var(--success-soft);--id-ink:var(--success-ink)}
.ident-beli {--id:var(--warn);   --id-soft:var(--warn-soft);   --id-ink:var(--warn-ink)}
.ident-stok {--id:var(--primary);--id-soft:var(--primary-soft);--id-ink:var(--primary-ink)}

.khead[class*="ident-"], .tbh[class*="ident-"]{
  border-bottom:3px solid var(--id);
  background:linear-gradient(90deg, var(--id-soft) 0, var(--surface) 420px);
}
.ident{
  display:inline-flex;align-items:center;gap:10px;flex-shrink:0;margin-right:6px;
  padding:3px 14px 3px 3px;border-radius:12px;
  background:var(--surface);border:1px solid color-mix(in srgb, var(--id) 30%, transparent);
  box-shadow:0 1px 2px rgba(0,0,0,.05);
}
@supports not (border-color: color-mix(in srgb, red, blue)){ .ident{border-color:var(--border-2)} }
.ident-ikon{
  width:34px;height:34px;border-radius:10px;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  background:var(--id);color:#fff;
  box-shadow:0 3px 8px -3px var(--id), inset 0 1px 0 rgba(255,255,255,.25);
}
.ident-ikon .ikon{width:19px;height:19px;stroke-width:2}
.ident-teks{display:flex;flex-direction:column;line-height:1.1}
.ident-teks b{font-size:16px;font-weight:800;letter-spacing:.07em;color:var(--id-ink)}
.ident-teks small{font-size:10.5px;font-weight:600;color:var(--text-muted);letter-spacing:.02em;margin-top:2px}
/* Panel bayar ikut bertepi warna identitas. */
.kpay.ident-kasir{border-left-color:var(--success)!important}
.tbpay.ident-beli{border-left:3px solid var(--warn)!important}
.tbpay.ident-beli .pay-bigbox{background:var(--warn-soft)}
.tbpay.ident-beli .pay-big-lbl{color:var(--warn-ink)}
/* Kepala Kasir: label identitas lebih lebar daripada judul
   lama, dan kepala yang dipaksa satu baris memeras kotak pendek (Kasir,
   Lokasi, Jam) sampai isinya tinggal "ADMI" / "U" / "09:0". Kotak pendek
   kini dipatok; kotak Member/Sales yang mengalah (nama panjang memang
   sudah terpotong di sana); dan kalau layarnya tetap tidak cukup, kepala
   turun ke baris kedua — bukan memotong isian. Titik pemisah di Kasir
   dibuang: label identitas sudah memberi susunan. */
.khead { flex-wrap: wrap !important; row-gap: 6px !important; }
.khead .kh-f { flex-shrink: 0; }
.khead .kh-sep { display: none; }
.khead { container: khead / inline-size; }
/* Kotak baca-saja selebar isinya (field-sizing); peramban lama memakai
   lebar patokan di baris sebelumnya. */
.khead :where(#hd-nota) { width: 112px; } .khead :where(#hd-kasir) { width: 80px; } .khead :where(#hd-jam) { width: 84px; }
.khead #hd-lgnid, .khead #hd-salesid { width: 4ch; flex: 0 1 auto; min-width: 1ch; }
@supports (field-sizing: content) {
  .khead .kh-f input[readonly], .khead #hd-lgnid, .khead #hd-salesid { field-sizing: content; width: auto; }
  .khead .kh-f input[readonly] { min-width: 56px; max-width: 200px; }
}
.khead .kh-f select { width: auto; min-width: 110px; padding: 4px 8px; font-size: 13px; border-radius: 6px; }
/* Dasar 0 + min-width: Member/Sales mengisi sisa baris, dan kepala baru
   turun baris kalau keduanya sudah tinggal 110px. */
.khead .kh-member { flex: 1 1 0; min-width: 110px; overflow: hidden; }
/* Layar ~1280px: Member, Sales, dan lencana F3/F4 turun BERSAMA ke baris
   kedua (masing-masing lebar), bukan lencananya saja yang tertinggal. */
@container khead (max-width: 1300px) { .khead .kh-member { flex: 1 1 35%; } }
.khead .kh-member input[id$="nama"] { flex: 1 1 auto; min-width: 0; width: auto; }

/* ══ Layar HP & tablet kecil (≤760px) ═════════════════════════════════════
   Aplikasi ini dirancang untuk meja kasir dan PC kantor; di HP yang paling
   sering dibuka adalah laporan, daftar master, dan sesekali nota. Aturannya:
     • kepala nota yang berkolom-kolom (Tanggal | Nota | Pelanggan | …)
       bertumpuk — dua kolom di tablet kecil, satu kolom di HP;
     • tabel tidak diperas sampai tak terbaca: lebarnya tetap, wadahnya
       yang digulir ke samping;
     • layar penuh (Kasir, Pembelian, layar stok) berhenti menjadi "satu
       layar tanpa gulir" — panel bayar turun ke bawah grid, halaman
       digulir biasa;
     • petunjuk tombol keyboard (F1, F2, …) yang memang tidak bisa ditekan
       di HP disembunyikan; tombol F yang BISA diketuk tetap ada, satu
       baris yang digeser ke samping.
   Banyak aturan di sini memakai !important karena gaya tiap layar ditulis
   di <style> halamannya sendiri, yang dimuat SESUDAH berkas ini. */
@media (max-width: 760px) {
  .page-wrapper { padding: 14px 12px 28px; }
  .page-title { font-size: 19px; margin-bottom: 12px; }
  .card { margin-bottom: 14px; }
  .card-header { padding: 12px 14px; flex-wrap: wrap; gap: 8px; }
  .card-body { padding: 14px; }
  .modal-backdrop { padding: 8px; }
  .modal-header { padding: 13px 14px; }
  .modal-body { padding: 14px; }
  .modal-footer { padding: 10px 14px; flex-wrap: wrap; }
  .modal.modal-lookup { height: min(620px, 92vh); }

  /* Kepala nota bertumpuk */
  .trx-hdr, .po-hdr, .tj-head-grid, .km-form-header, .nk-header, .tp-hdr-row1 {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }
  .trx-hdr > *, .po-hdr > *, .tj-head-grid > *, .km-form-header > *, .nk-header > *, .tp-hdr-row1 > * {
    min-width: 0; grid-column: auto !important;
  }
  .trx-hdr input, .trx-hdr select, .po-hdr input, .po-hdr select, .tj-head-grid input, .tj-head-grid select,
  .km-form-header input, .km-form-header select, .nk-header input, .nk-header select {
    max-width: 100%;
  }
  .trx-toolbar, .tb-toolbar, .tj-toolbar, .po-toolbar { flex-wrap: wrap; row-gap: 8px; }
  .toolbar, .toolbar-left, .toolbar-right { flex-wrap: wrap; row-gap: 8px; }
  .trx-nota input { min-width: 0; }

  /* Tombol F di bawah form: yang bisa diketuk tinggal, catatan keyboard pergi */
  .trx-fk { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .trx-fk::-webkit-scrollbar { display: none; }
  .trx-fk-info, .trx-catatan { display: none !important; }
  .trx-aksi .btn kbd, .trx-aksi .btn .kunci { display: none; }

  /* Cap versi di pojok kiri bawah menutupi isi di layar sempit. Peringatan
     versi berbeda (.beda) tetap tampil — itu yang memang harus terlihat. */
  .versi-cap:not(.beda) { display: none !important; }

  /* ── Layar penuh: Kasir, Pembelian, Mutasi, Produksi, Penyesuaian ── */
  body:has(.kbody) .page-wrapper, body:has(.tb-body) .page-wrapper, body:has(.tp-body) .page-wrapper {
    height: auto !important; min-height: calc(var(--ao-tinggi-layar, 100vh) - var(--ao-tb-bawah, 48px));
    overflow: visible !important;
  }
  .khead, .tbh {
    display: grid !important; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 10px !important; padding: 10px 12px !important; align-items: end;
  }
  .khead[class*="ident-"], .tbh[class*="ident-"] {
    background: linear-gradient(180deg, var(--id-soft) 0, var(--surface) 120px);
  }
  .khead > .ident, .tbh > .ident, .khead > .kh-member, .khead > .mode-grp { grid-column: 1 / -1; }
  .khead > .ident, .tbh > .ident { justify-self: start; margin: 0 0 2px; }
  .kh-sep, .tbh-sep { display: none !important; }
  .kh-f, .tbh-f {
    display: grid !important; grid-template-columns: minmax(0, 1fr) auto;
    gap: 3px 4px; align-items: center; min-width: 0; white-space: normal;
  }
  .kh-f > label, .tbh-f > label { grid-column: 1 / -1; }
  .kh-f input, .kh-f select, .tbh-f input, .tbh-f select { width: 100% !important; min-width: 0; }
  .kh-member { min-width: 0; }
  .kh-member input[id$="nama"] { flex: 1 1 auto; min-width: 0; width: auto; }
  .mode-grp { margin-left: 0 !important; }

  .kbody, body:has(.tbpay) .tb-body { flex-direction: column; overflow: visible !important; flex: none !important; }
  .kgrid { flex: none !important; overflow: visible !important; }
  .kgrid-wrap, .tb-grid-wrap { flex: none !important; max-height: 62vh; overflow: auto; }
  .tb-body, .tp-body { flex: none !important; overflow: visible !important; }
  body:has(.tb-body) .tb-body:not(:has(.tbpay)) { overflow-x: auto !important; }
  .kpay[class], .tbpay[class] {
    width: auto !important; border-left: 0 !important; border-top: 3px solid var(--id, var(--primary));
    overflow: visible;
  }
  .kfoot, .tbfoot { flex-wrap: nowrap !important; overflow-x: auto; scrollbar-width: none; padding: 6px 10px !important; }
  .kfoot::-webkit-scrollbar, .tbfoot::-webkit-scrollbar { display: none; }
  .kfoot .fk, .tbfoot .fk { flex-shrink: 0; }
  body:has(.kfoot) .ao-toast-wadah, body:has(.page-wrapper > .tbfoot) .ao-toast-wadah {
    top: calc(var(--ao-tb-bawah) + 12px); bottom: auto; flex-direction: column;
  }
}
@media (max-width: 520px) {
  .trx-hdr, .po-hdr, .tj-head-grid, .km-form-header, .nk-header, .tp-hdr-row1 {
    grid-template-columns: minmax(0, 1fr) !important;
  }
  .page-title span { display: block; margin: 3px 0 0; }
  .ao-toast-wadah { right: 10px; width: calc(100vw - 20px); }
}
/* Baris lookup di HP — ditandai ui.js (tandaiLookupHp). */
@media (max-width: 520px) {
  .ao-lk-baris { display: flex !important; flex-wrap: wrap; align-items: baseline; gap: 2px 12px !important; }
  .ao-lk-baris > * { flex: 0 0 auto; min-width: 0; max-width: 100%; text-align: left !important; font-size: 12px; }
  .ao-lk-baris > .ao-lk-nama { order: -1; flex: 1 0 100%; font-size: 13.5px; font-weight: 600; color: var(--text); }
  .ao-lk-kepala { display: none !important; }
}
/* Pembungkus tabel yang lebih lebar dari layar — dipasang ui.js
   (bungkusTabelLebar) hanya bila perlu. */
.ao-gulir-x { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }
@media print { .ao-gulir-x { overflow: visible !important; } }

/* ══ Seret untuk mengurutkan (aoSeret di fungsi_umum.js) ════════════════
   Selama menyeret: kursor "menggenggam" di mana pun dan teks tidak ikut
   terseleksi. Butir aslinya tetap di daftar sebagai penanda tempat
   mendarat (pudar, bergaris putus); salinannya mengikuti kursor dengan
   bayangan — kalau butirnya kategori yang panjang, salinannya dipotong
   dan memudar di bawah, cukup untuk dikenali. */
html.ao-menyeret, html.ao-menyeret * { cursor: grabbing !important; user-select: none; -webkit-user-select: none; }
.ao-seret-asal { opacity: .4; outline: 2px dashed var(--primary-brd); outline-offset: -1px; border-radius: 8px; }
.ao-seret-hantu {
  background: var(--surface); border-radius: 10px; opacity: .97;
  box-shadow: var(--shadow-pop), 0 0 0 1px var(--primary-brd);
  max-height: 240px; overflow: hidden;
  -webkit-mask-image: linear-gradient(#000 170px, transparent 240px); mask-image: linear-gradient(#000 170px, transparent 240px);
}

/* ══ Cari cepat (Ctrl+K) — jendela & logikanya di ui.js ══════════════════
   Tombolnya di bilah atas: ikon saja di bilah yang sesak (1280–1439px dengan
   menu atas, dan HP), kotak "Cari halaman… Ctrl K" kalau ruangnya ada —
   layar ≥1440px, atau mode panel kiri yang bilah atasnya lega. */
.tb-cari {
  display: inline-flex; align-items: center; gap: 8px; flex-shrink: 0;
  height: 36px; min-width: 36px; padding: 0 9px; border: 0; border-radius: 10px;
  background: none; color: var(--topbar-fg-dim); cursor: pointer;
  font-family: inherit; font-size: 12.5px; font-weight: 500; line-height: 1; transition: background .15s, color .15s;
}
.tb-cari .ikon { width: 18px; height: 18px; flex-shrink: 0; }
.tb-cari:hover { background: var(--topbar-hover); color: var(--topbar-fg); }
.tb-cari-teks, .tb-cari kbd { display: none; }
.tb-cari kbd {
  margin-left: auto; padding: 3px 6px; border-radius: 6px; font: 700 10px/1 var(--font-kode, monospace);
  border: 1px solid color-mix(in srgb, var(--topbar-fg) 28%, transparent); color: var(--topbar-fg-dim);
}
@media (min-width: 1440px) {
  html:not([data-topnav="sempit"]) .tb-cari { background: var(--topbar-hover); min-width: 190px; padding: 0 7px 0 11px; margin-right: 6px; }
  html:not([data-topnav="sempit"]) .tb-cari-teks, html:not([data-topnav="sempit"]) .tb-cari kbd { display: inline; }
}
html[data-nav="kiri"]:not([data-topnav="sempit"]) .tb-cari { background: var(--topbar-hover); min-width: 240px; padding: 0 7px 0 11px; margin-right: 6px; }
html[data-nav="kiri"]:not([data-topnav="sempit"]) .tb-cari-teks, html[data-nav="kiri"]:not([data-topnav="sempit"]) .tb-cari kbd { display: inline; }

.ao-cari-tirai {
  position: fixed; inset: 0; z-index: 1400; background: var(--overlay);
  display: flex; justify-content: center; align-items: flex-start;
  padding: min(13vh, 110px) 16px 16px; animation: ao-tirai .14s ease;
}
.ao-cari-tirai[hidden] { display: none; }
.ao-cari {
  width: min(620px, 100%); max-height: min(560px, 78vh);
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border-2); border-radius: var(--radius-xl);
  box-shadow: var(--shadow-pop); animation: modal-in .2s cubic-bezier(.2,.8,.2,1);
}
.ao-cari-kepala { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--border-2); color: var(--text-muted); }
.ao-cari-kepala .ikon { width: 20px; height: 20px; flex-shrink: 0; }
.ao-cari-kepala input { flex: 1; border: 0 !important; box-shadow: none !important; outline: 0; background: none; padding: 6px 0; font-size: 16px; color: var(--text); }
.ao-cari-hasil { overflow-y: auto; padding: 6px; min-height: 64px; }
.ao-cari-judul { font-size: 10.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); padding: 8px 10px 4px; }
.ao-cari-item { display: flex; align-items: center; gap: 12px; padding: 8px 10px; border-radius: 10px; color: var(--text); text-decoration: none; }
.ao-cari-item .ik { width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: var(--surface-3); color: var(--text-soft); transition: background .1s, color .1s; }
.ao-cari-item .ik .ikon { width: 16px; height: 16px; }
.ao-cari-item .tt { flex: 1; min-width: 0; }
.ao-cari-item b { display: block; font-size: 13.5px; font-weight: 600; }
.ao-cari-item b mark { background: none; color: var(--primary-ink); font-weight: 800; }
.ao-cari-item small { display: block; font-size: 11.5px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ao-cari-item .ent { font-size: 11px; font-weight: 700; color: var(--primary-ink); opacity: 0; flex-shrink: 0; }
.ao-cari-item.pilih { background: var(--primary-soft); }
.ao-cari-item.pilih .ik { background: var(--primary); color: var(--on-accent); }
.ao-cari-item.pilih .ent { opacity: 1; }
.ao-cari-kosong { padding: 26px 16px; text-align: center; color: var(--text-muted); font-size: 13px; line-height: 1.6; }
.ao-cari-kaki { display: flex; gap: 18px; padding: 9px 14px; border-top: 1px solid var(--border-2); background: var(--surface-2); font-size: 11.5px; color: var(--text-muted); }
.ao-cari kbd {
  display: inline-block; min-width: 18px; padding: 2px 5px; margin-right: 3px; text-align: center;
  font: 700 10.5px/1.2 var(--font-kode, monospace); color: var(--text-soft);
  background: var(--surface); border: 1px solid var(--border); border-bottom-width: 2px; border-radius: 5px;
}
@media (max-width: 520px) {
  .ao-cari-tirai { padding: 10px 8px; }
  .ao-cari-kaki, .ao-cari-kepala kbd { display: none; }
}
@media print { .ao-cari-tirai { display: none !important; } }
/* Bilah atas di HP: tujuh tombol (cari, gerigi, lonceng, nama, keluar,
   menu) + merek harus muat di 360–420px. Tombolnya dirapatkan; di bawah
   380px tulisan "Aries One" disembunyikan — logonya tetap. */
@media (max-width: 440px) {
  .topbar { padding: 0 4px; gap: 2px; }
  .topbar-right { gap: 0; }
  .topbar-brand { padding: 0 8px 0 6px; gap: 7px; }
  .tb-ikon, .tb-cari { width: 33px; min-width: 33px; padding: 0; justify-content: center; }
  .tb-pemakai { padding: 0 2px 0 6px; margin-left: 2px; }
}
@media (max-width: 380px) {
  .topbar-brand > span { display: none; }
}

/* ══ Penyaring Lokasi di laporan (2.3.0) ═════════════════════════════════
   Satu gaya untuk semua laporan: tiap laporan punya kelas kelompok isian
   sendiri (.fg, .lf-grp, .nrc-fg, ...) yang tidak semuanya menata <select>. */
select[data-lokasi][name]{height:34px;min-width:160px;padding:0 8px;font-size:13px;font-family:inherit;
  border:1.5px solid var(--border);border-radius:7px;background:var(--surface);color:var(--text)}
select[data-lokasi][name]:focus{border-color:var(--primary);outline:none}
select[data-lokasi][name]:disabled{opacity:.75;cursor:not-allowed}

/* ══ Sakelar (toggle) standar (2.3.0) ════════════════════════════════════
   Semua pilihan nyala/mati memakai bentuk ini: <input type="checkbox"
   class="saklar">. Tetap checkbox asli — nilai borang, :checked, onchange,
   label, dan keyboard (Spasi) bekerja seperti biasa; yang berubah hanya
   rupanya: abu-abu dengan bulatan di kiri = mati, hijau dengan bulatan di
   kanan = nyala. Centang PILIH-BARIS di tabel dan daftar menu sengaja tetap
   kotak centang: itu memilih, bukan menyalakan. */
input[type=checkbox].saklar{
  -webkit-appearance:none!important;appearance:none!important;flex:0 0 auto;padding:0!important;
  width:40px!important;height:22px!important;min-width:40px;margin:0;border:0!important;border-radius:999px!important;
  background:var(--saklar-mati,#cdd2e3)!important;position:relative;cursor:pointer;vertical-align:middle;
  box-shadow:inset 0 1px 2px rgba(0,0,0,.10);transition:background .18s ease}
input[type=checkbox].saklar::before{
  content:'';position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;
  background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.28);transition:transform .18s ease}
input[type=checkbox].saklar:checked{background:var(--saklar-nyala,#3fbd87)!important}
input[type=checkbox].saklar:checked::before{transform:translateX(18px)}
input[type=checkbox].saklar:focus-visible{outline:2px solid var(--primary);outline-offset:2px}
input[type=checkbox].saklar:disabled{opacity:.5;cursor:not-allowed}
@media (prefers-reduced-motion:reduce){input[type=checkbox].saklar,input[type=checkbox].saklar::before{transition:none}}
