:root {
  --scm-accent: #4f46e5;
  /* Poles 2026-07-23 (permintaan owner): sidebar diramping 15.5rem → 14rem +
     item/ikon/header dipadatkan, meniru kepadatan sidebar legacy. Lebar 14rem
     = batas aman label terpanjang ("Monitoring Transaksi (Beta)") tanpa wrap. */
  --scm-sidebar-w: 14rem;
}

html, body.scm-body {
  height: 100%;
}
body.scm-body {
  background: #f1f5f9;
  color: #1e293b;
  overflow: hidden; /* halaman tak ikut scroll; sidebar & konten scroll sendiri */
}

/* Tinggi tetap = viewport, jadi <nav> sidebar & <main> yang overflow-y-auto
   masing-masing scroll SENDIRI (perbaikan: dulu min-h-screen bikin body
   tumbuh & seluruh isi ikut ter-scroll). dvh mengikuti URL-bar HP. */
#app.scm-app {
  height: 100vh;
  height: 100dvh;
}

/* Picker tenant-outlet: ringkas di layar kecil, melebar di layar besar. */
.scm-ctx-select {
  /* Mobile: kedua picker di baris sendiri (flex-1) → biar bagi rata, jangan
     dibatasi lebar; min-width:0 supaya bisa menyusut & truncate. */
  min-width: 0;
}
@media (min-width: 640px) {
  .scm-ctx-select { max-width: 14rem; }
}
.scm-ctx-select optgroup {
  font-weight: 600;
  color: #4f46e5;
}

.panel-card {
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 0.75rem;
}

.scm-sidebar {
  width: var(--scm-sidebar-w);
  background: #fff;
  border-right: 1px solid #e2e8f0;
}

.scm-nav-link {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.65rem;
  border-radius: 0.5rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: #4b5563;
  cursor: pointer;
  transition: background-color 150ms, color 150ms;
  margin-bottom: 1px;
  border: none;
  background: transparent;
  width: 100%;
  text-align: left;
  text-decoration: none;
}

.scm-nav-link:hover {
  background: #f3f4f6;
  color: #1f2937;
}

.scm-nav-link.active {
  background: color-mix(in srgb, var(--scm-accent) 14%, white);
  color: color-mix(in srgb, var(--scm-accent) 72%, #1e1b4b);
  font-weight: 600;
}

.scm-nav-link .nav-icon {
  width: 1.25rem;
  height: 1.25rem;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 0.3rem;
  font-size: 0.65rem;
}

.scm-nav-link.active .nav-icon {
  background: color-mix(in srgb, var(--scm-accent) 28%, white);
  color: var(--scm-accent);
}

/* Titik berwarna: menandai menu yang datanya jadi sumber di Monitoring Transaksi
   Sumber, diwarnai per ARAH transaksi (hijau=pemasukan, merah=pengeluaran,
   kuning=mutasi). Didorong ke ujung kanan baris menu (margin-left:auto). */
.scm-nav-link .scm-nav-dot {
  margin-left: auto;
  width: 0.5rem;
  height: 0.5rem;
  flex-shrink: 0;
  border-radius: 9999px;
}
.scm-nav-dot-pemasukan {
  background: #22c55e; /* green-500 */
  box-shadow: 0 0 0 3px color-mix(in srgb, #22c55e 22%, transparent);
}
.scm-nav-dot-pengeluaran {
  background: #ef4444; /* red-500 */
  box-shadow: 0 0 0 3px color-mix(in srgb, #ef4444 22%, transparent);
}
.scm-nav-dot-mutasi {
  background: #eab308; /* yellow-500 */
  box-shadow: 0 0 0 3px color-mix(in srgb, #eab308 22%, transparent);
}

/* Section akordeon: header bisa diklik buka/tutup, chevron menandai status. */
.scm-nav-group {
  margin-top: 0.25rem;
}

/* Logo header sidebar ringkas (dulu w-10/40px lewat kelas tailwind). */
.scm-brand-logo {
  width: 2rem;
  height: 2rem;
}

.scm-nav-section-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  padding: 0.3rem 0.65rem;
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 0.6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #94a3b8;
  border-radius: 0.5rem;
  transition: background-color 150ms, color 150ms;
}

.scm-nav-section-btn:hover {
  background: #f3f4f6;
  color: #64748b;
}

.scm-nav-section-btn.is-open {
  color: #64748b;
}

.scm-nav-section-btn i {
  font-size: 0.6rem;
  transition: transform 150ms;
}

.scm-nav-items {
  display: flex;
  flex-direction: column;
  padding: 0.1rem 0 0.15rem;
}

.scm-nav-items.hidden {
  display: none;
}

/* Tombol "Pasang App" menempel ke ujung kanan baris judul (mobile & desktop).
   Pakai margin-left:auto (kelas ml-auto tak ada di tailwind precompiled). */
#pwa-install-btn {
  margin-left: auto;
}

/* Jebakan urutan CSS yang sama dgn .btn-secondary.hidden di bawah: md:hidden
   (tailwind, dimuat duluan) kalah dari display:inline-flex .btn-secondary,
   jadi hamburger ikut tampil di desktop. Paksa sembunyi di ≥768px. */
@media (min-width: 768px) {
  #btn-menu {
    display: none;
  }
}

/* .btn-secondary set display:inline-flex (di app.css, dimuat SETELAH tailwind),
   jadi kelas .hidden bawaan tailwind kalah urutan & tak menyembunyikan. Selector
   gabungan ini menang lewat specificity — dipakai tombol "Pasang App" (PWA) yg
   default tersembunyi sampai pwa-install.js memutuskan menampilkannya. */
.btn-secondary.hidden {
  display: none;
}

/* Jebakan sama utk .btn-primary (display:inline-flex) — tanpa ini tombol
   "Coba lagi" di layar "Gagal memuat SCM" langsung tampil walau ber-.hidden,
   padahal harus tersembunyi sampai koneksi pulih (permintaan owner 2026-07-23). */
.btn-primary.hidden {
  display: none;
}

.data-table {
  width: 100%;
  font-size: 0.8125rem;
  border-collapse: collapse;
}

.data-table thead th {
  text-align: left;
  color: #64748b;
  font-weight: 600;
  border-bottom: 1px solid #e2e8f0;
  padding: 0.5rem 0.75rem;
  white-space: nowrap;
}

.data-table tbody td {
  padding: 0.55rem 0.75rem;
  border-bottom: 1px solid #f1f5f9;
  vertical-align: middle;
}

/* HEADER IKUT PERATAAN ISINYA (owner 19 Sep 2026: "sejajarkan juga header dan
   isi tabel").

   `.data-table thead th { text-align: left }` di atas berkekuatan (0,1,2),
   sedangkan utilitas Tailwind `.text-right` cuma (0,1,0) — dan app.css dimuat
   SESUDAH tailwind.css. Jadi setiap `<th class="text-right">` di seluruh SCM
   selama ini tetap rata KIRI sementara sel isinya rata kanan: 237 header di
   modul ini menulis perataan yang tak pernah berlaku, tanpa satu pun galat.

   Diperbaiki di sini, bukan dengan `!text-right` per berkas: kelas arbitrer
   yang tak pernah muncul di sumber bisa tak ikut terbuild di subset Tailwind
   (lihat memori scm-tailwind-subset-gotcha), dan 237 tempat berarti 237
   kesempatan lupa. Rata KIRI tetap bawaan — yang berubah hanya header yang
   memang sudah menuliskan perataannya. */
.data-table thead th.text-right { text-align: right; }
.data-table thead th.text-center { text-align: center; }

/* Baris bertinggi tak sama (mis. kolom Metode di kartu Keuangan yang memuat
   cabang + nomor rekening + atas nama) harus rata ATAS, kalau tidak angka di
   kolom sebelahnya melayang di tengah. Perlu CSS sungguhan dengan alasan yang
   sama seperti di atas: `.align-top` kalah kuat dari aturan `vertical-align`
   milik `.data-table tbody td`. */
.data-table tbody td.align-top { vertical-align: top; }

.data-table tbody tr:hover {
  background: #f8fafc;
}

/* Poles tabel /products (2026-07-29): header lengket saat scroll + baris zebra +
   hover indigo lebih jelas. Scoped ke .products-table agar tak mengubah tabel lain. */
.products-table thead th, .prodout-table thead th, .raw-table thead th {
  position: sticky;
  top: 0;
  z-index: 5;
  background: #f8fafc;
  box-shadow: inset 0 -1px 0 #e2e8f0;
}
.products-table tbody tr:nth-child(even), .prodout-table tbody tr:nth-child(even), .raw-table tbody tr:nth-child(even) { background: #fcfcfd; }
.products-table tbody tr:hover, .prodout-table tbody tr:hover, .raw-table tbody tr:hover { background: #eef2ff; }

/* Lebar kolom (restrukturisasi 2026-07-29): Stok memuat angka + tombol Stok/Analisa
   → beri ruang; Urutan cuma input kecil → sempit. Resep memuat chip + tombol. */
.products-table td.col-stok, .prodout-table td.col-stok { min-width: 8rem; }
.raw-table td.col-stok { min-width: 11rem; }
.products-table td.col-urutan { width: 3.25rem; }
.products-table td.col-resep, .prodout-table td.col-resep { min-width: 7rem; }
/* Kolom "Tampil / Penanda" memuat grid 2 kolom berisi 6 ceklis berlabel.
   Aturan lebarnya dulu HANYA ada di @media (max-width:640px), jadi di desktop
   kolomnya terjepit dan label-labelnya terpotong jadi satu huruf. */
.products-table td.col-storefront { min-width: 12.5rem; }
.products-table td.col-stokmin { white-space: nowrap; }
/* Kelola Stok: kolom ceklis, selebar isinya saja — tanpa ini kolomnya
   ikut melar mengambil sisa lebar tabel dan ceklisnya terdampar jauh
   dari judulnya. */
.products-table th.col-kelolastok,
.products-table td.col-kelolastok { width: 1%; white-space: nowrap; text-align: center; }

/* Kolom Aksi: tombol di dalam flex, BUKAN space-x + nowrap di <td>.
   nowrap di sel terakhir tabel width:100% membuat isi melebihi kotak sel,
   sementara scrollWidth tabel tak ikut — di HP sisa tombol terpotong. */
.aksi-btns {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
}
.aksi-btns > .btn-primary,
.aksi-btns > .btn-secondary,
.aksi-btns > .btn-danger,
.aksi-btns > a {
  flex: 0 0 auto;
}

.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.45rem 0.85rem;
  border-radius: 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  background: var(--scm-accent);
  color: #fff;
  border: none;
  cursor: pointer;
}

.btn-primary:hover {
  filter: brightness(1.05);
}

.btn-secondary {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.45rem 0.85rem;
  border-radius: 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  background: #fff;
  color: #374151;
  border: 1px solid #d1d5db;
  cursor: pointer;
}

.btn-secondary:hover {
  background: #f9fafb;
}

/* Preset periode yang sedang aktif (Hari Ini / Kemarin / Bulan Ini). Kelas ini
   sudah dipakai transfers.js sejak lama TAPI tak pernah punya aturan CSS di mana
   pun, jadi sorotan preset aktif tak pernah muncul — di halaman itu pun. Dipakai
   bersama /partner-orders. */
.btn-secondary.is-active-preset {
  background: #eef2ff;
  border-color: #a5b4fc;
  color: #4338ca;
  font-weight: 600;
}

.btn-danger {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.45rem 0.85rem;
  border-radius: 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  background: #fef2f2;
  color: #b91c1c;
  border: 1px solid #fecaca;
  cursor: pointer;
}

.status-badge {
  display: inline-flex;
  align-items: center;
  border-radius: 9999px;
  padding: 0.15rem 0.55rem;
  font-size: 0.6875rem;
  font-weight: 600;
}

.status-pending { background: #fef3c7; color: #b45309; }
.status-process { background: #e0f2fe; color: #0369a1; }
.status-finish { background: #e0e7ff; color: #4338ca; }
.status-approved { background: #d1fae5; color: #047857; }
.status-rejected { background: #fee2e2; color: #b91c1c; }
.status-received { background: #dbeafe; color: #1d4ed8; }

.field-label {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  color: #475569;
  margin-bottom: 0.25rem;
}

.field-input {
  width: 100%;
  border: 1px solid #d1d5db;
  border-radius: 0.5rem;
  padding: 0.45rem 0.65rem;
  font-size: 0.8125rem;
  outline: none;
}

.field-input:focus {
  border-color: var(--scm-accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--scm-accent) 20%, transparent);
}

/* Isian NOMINAL UANG di modal. <input type="number"> menampilkan nilai mentah
   ("95392,00") sehingga tak kebaca sebagai uang. Penggantinya: kotak teks dgn
   awalan "Rp" menempel di dalam kotak + angka tabular. Kelasnya ditulis di sini
   (bukan utility Tailwind) karena tailwind.css SCM cuma subset pra-kompilasi —
   utility posisi seperti pl-9 / -translate-y-1/2 tidak tersedia di sana. */
.money-field {
  position: relative;
}

.money-field > .money-prefix {
  position: absolute;
  left: 0.65rem;
  top: 50%;
  transform: translateY(-50%);
  font-size: 0.75rem;
  color: #9ca3af;
  pointer-events: none;
}

.money-field > .field-input {
  padding-left: 2.1rem;
  font-variant-numeric: tabular-nums;
}

/* JEBAKAN (jangan hapus jatah padding-left di atas): aturan kepadatan di
   @media bawah memakai shorthand `padding` dgn selektor 3-kelas (mis.
   `.modal-backdrop.modal-dense .field-input`), jadi ia menang atas
   `.money-field > .field-input` (2 kelas) DAN mereset padding-left — "Rp" yang
   absolut di left:.65rem lalu duduk DI ATAS angkanya. Terukur di iPhone:
   tumpang tindih 19,2px (owner, 2026-08-15, /production-outputs).
   Padanan `unitField()` selamat dari gejala serupa semata-mata karena ia
   memakai inline style (`padding-right:2.8rem`), bukan kelas.
   Penawarnya ada di @media (max-width:640px) — cari "jatah prefiks Rp". */

/* ===== Upload foto item (modal Tambah/Edit) ===== */
/* Ganti input file telanjang → kotak klik ber-preview + placeholder. */
.photo-upload {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 7rem;
  padding: 0.5rem;
  border: 1.5px dashed #cbd5e1;
  border-radius: 0.6rem;
  background: #f8fafc;
  cursor: pointer;
  overflow: hidden;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.photo-upload:hover {
  border-color: #6366f1;
  background: #f1f5f9;
}
.photo-upload-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}
.photo-upload-preview {
  max-height: 6.5rem;
  max-width: 100%;
  object-fit: contain;
  border-radius: 0.4rem;
}
.photo-upload-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  color: #94a3b8;
  font-size: 0.8rem;
  text-align: center;
  pointer-events: none;
}
.photo-upload-empty > i {
  font-size: 1.6rem;
  color: #cbd5e1;
}
.photo-upload-sub {
  font-size: 0.68rem;
  color: #cbd5e1;
}
/* Specificity 2-kelas → menang atas .photo-upload-empty{display:flex} (urutan
   cascade sama dgn jebakan .btn-secondary.hidden), jadi .hidden benar2 sembunyi. */
.photo-upload-empty.hidden,
.photo-upload-preview.hidden {
  display: none;
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.modal-panel {
  background: #fff;
  border-radius: 0.875rem;
  width: 100%;
  max-width: 32rem;
  /* max-height: 100% — BUKAN 90vh. Di iOS Safari `vh` mengacu ke viewport
     BESAR (seolah toolbar tersembunyi), sementara .modal-backdrop yang
     position:fixed;inset:0 mengikuti area yang BENAR-BENAR terlihat. Selisihnya
     = tinggi toolbar bawah Safari, dan panel setinggi 90–96vh jadi menjulur ke
     bawah area terlihat sampai .modal-footer (tombol Batal/Simpan) tertutup
     toolbar — dilaporkan owner 2026-08-15 dari iPhone di halaman
     /production-outputs. Persen mengacu ke kotak-isi backdrop, jadi ia otomatis
     benar di semua peramban tanpa perlu menebak-nebak unit viewport. */
  max-height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}

.modal-panel.lg {
  /* Modal konten-banyak → FULL LAYAR (permintaan owner 2026-07-23): lebar
     mengisi penuh layar (width:100% dari base, minus margin 1rem backdrop —
     aman di mobile) tanpa batas max-width. Tinggi ikut max-height:100% dari
     base (dulu 94vh — lihat catatan iOS di atas). */
  max-width: none;
}

.modal-header {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid #e2e8f0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.modal-body {
  padding: 1.25rem;
  overflow-y: auto;
  flex: 1;
}

.modal-footer {
  padding: 0.85rem 1.25rem;
  border-top: 1px solid #e2e8f0;
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}

.stat-card {
  padding: 1rem;
}

/* Kartu ringkasan 5 kolom (Total/Tersedia/Menipis/Habis/Nilai) — md:grid-cols-5
   TAK ADA di subset tailwind.css (cek dulu sebelum pakai kelas Tailwind baru,
   lihat scm-tailwind-subset-gotcha), jadi aturannya ditaruh di sini. */
@media (min-width: 768px) {
  .stat-grid-5 {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

.stat-card .stat-label {
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #64748b;
  margin-bottom: 0.25rem;
}

.stat-card .stat-value {
  font-size: 1.25rem;
  font-weight: 700;
  color: #0f172a;
}

/* Kartu ringkasan yang bisa DIKLIK untuk menyaring tabel (Bahan Baku): kartu
   aktif = status yang sedang ditampilkan. Ditulis di sini, bukan pakai kelas
   Tailwind, karena subset tailwind.css tak punya ring-*/hover:border-* (lihat
   scm-tailwind-subset-gotcha). */
.stat-card-clickable {
  cursor: pointer;
  user-select: none;
  transition: border-color 150ms, box-shadow 150ms, background-color 150ms;
}

.stat-card-clickable:hover {
  border-color: #a5b4fc;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08);
}

.stat-card-clickable:focus-visible {
  outline: 2px solid #6366f1;
  outline-offset: 2px;
}

.stat-card-active {
  border-color: #6366f1;
  background: #eef2ff;
  box-shadow: inset 0 0 0 1px #6366f1;
}

.empty-state {
  text-align: center;
  padding: 2.5rem 1rem;
  color: #94a3b8;
  font-size: 0.875rem;
}

.table-loading {
  text-align: center;
  padding: 1.75rem 0.75rem;
  color: #64748b;
  font-size: 0.8125rem;
}
.table-loading i {
  margin-right: 0.45rem;
  color: #7c3aed;
}
.table-loading-row td { border-bottom: none; }

@media (max-width: 767.98px) {
  .scm-sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    /* 100dvh (bukan 100vh/min-h-screen): tinggi mengikuti viewport terlihat
       saat URL-bar HP tampil, supaya item paling bawah bisa di-scroll masuk. */
    height: 100dvh;
    min-height: 0;
    z-index: 40;
    transform: translateX(-100%);
    transition: transform 200ms;
    overscroll-behavior: contain;
    padding-bottom: env(safe-area-inset-bottom);
  }

  .scm-sidebar.open {
    transform: translateX(0);
  }

  .scm-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.3);
    z-index: 35;
  }
}

/* ── Gerbang "Pilih Outlet" (#ctx-gate-card, dibuat ctxGate() di app.js) ───────
   BUG (ditemukan 2026-08-18): kartunya diberi kelas `max-h-[80vh]`, tapi kelas
   itu TIDAK ADA di subset tailwind.css (yang ter-generate cuma max-h-56/72/96
   dan max-h-[70vh]) — lihat komentar "Utility Tailwind yang HILANG" di bawah.
   Tanpa batas tinggi, `overflow-y-auto` di kartu tak pernah aktif; dan karena
   body.scm-body dikunci `overflow:hidden`, TIDAK ADA yang bisa di-scroll. Di HP
   dengan outlet banyak, tombol outlet paling bawah jadi mustahil dijangkau —
   user terkunci di gerbang dan tak pernah masuk SCM sama sekali.
   Ditulis tangan di sini (bukan kelas Tailwind baru) mengikuti preseden berkas
   ini. dvh menyusul URL-bar HP, sama seperti .scm-sidebar di atas. */
#ctx-gate-card {
  max-height: 80vh;
  max-height: 80dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* ═══ Poles mobile: panel Inventory (Hasil Produksi/Produk/Bahan Baku) & modal
       Resep ══════════════════════════════════════════════════════════════════
   Keluhan owner 2026-07-28: di HP font kebesaran sehingga teks terpotong. Diukur
   di viewport 390px (Chromium headless):
     - modal Resep: tabel 569px di dalam panel 318px → 251px (44%) di luar layar,
       kolom Konversi/Biaya/Hapus tak terjangkau; dropdown bahan cuma sisa 92px
       sehingga hanya terbaca "— pilih" (Qty malah kebagian 112px).
     - kartu ringkasan: "Rp 12.480.500" pecah 2 baris di stat-value 20px.
     - tombol aksi baris pakai .btn-secondary 13px (kelas text-xs/py-1 KALAH
       urutan cascade dari .btn-secondary di app.css) → kolom Aksi melar.
   Perubahan kepadatan sengaja OPT-IN lewat pembungkus .scm-dense (panel
   inventory) dan .modal-dense (dipasang openRecipeModal) supaya panel/modal lain
   tak ikut berubah sebelum ditinjau. */

/* ── Utility Tailwind yang HILANG dari subset pra-kompilasi ────────────────────
   tailwind.css SCM di-generate sekali (tak ada build step di repo), jadi kelas
   yang tak ikut ter-generate diam-diam tak bergaya. Yang di bawah dipakai panel
   inventory dan terbukti kosong saat diperiksa di browser:
     - gap-x-2 / gap-y-0.5  : chip BB/HP di sel BOM menempel tanpa jarak.
     - max-w-[15rem]        : sel BOM tak punya batas → kolom melar, tabel lebar.
     - max-w-[11rem]/[14rem]: pasangan `truncate` di sel Catatan & Riwayat tak
                              pernah aktif, jadi catatan panjang ikut melebarkan
                              tabel (penyumbang utama lebar 1767px di mobile).
     - w-5/h-5/leading-none : tombol "×" hapus foto di modal item.
   Nilai mengikuti skala Tailwind bawaan. Beberapa (mis. bg-violet-100) mungkin
   sudah ditambahkan di blok utility lain — deklarasi kembar tak masalah. */
.gap-x-2 { column-gap: 0.5rem; }
.gap-y-0\.5 { row-gap: 0.125rem; }
.ml-0\.5 { margin-left: 0.125rem; }
.leading-4 { line-height: 1rem; }
.leading-none { line-height: 1; }
.w-5 { width: 1.25rem; }
.h-5 { height: 1.25rem; }
.text-rose-500 { color: #f43f5e; }
.bg-violet-100 { background-color: #ede9fe; }
.max-w-\[11rem\] { max-width: 11rem; }
.max-w-\[14rem\] { max-width: 14rem; }
.max-w-\[15rem\] { max-width: 15rem; }
.max-w-\[16rem\] { max-width: 16rem; }
/* mr-3: jarak antar-toggle Storefront di halaman Produk (tanpa ini kelima
   label "Aplikasi/Web Order/Rekomendasi/Wajib/Terlaris" menempel jadi satu).
   pt-3: jarak atas pemisah antar-seksi di form Tambah/Edit item. */
.mr-3 { margin-right: 0.75rem; }
.pt-3 { padding-top: 0.75rem; }

/* ═══ Riwayat Perubahan halaman Pengaturan (panels/pengaturan.js) ════════════
   Ditulis tangan di sini, BUKAN kelas Tailwind: subset pra-kompilasi SCM tak
   punya varian breakpoint yang dibutuhkan (`sm:table-cell`, `sm:hidden`,
   `md:table-cell` semuanya TIDAK ter-generate — lihat "Utility Tailwind yang
   HILANG" di atas), padahal justru di HP-lah bentuknya harus berubah.

   Blok ini semula tabel 5 kolom (Waktu|Pelaku|Setelan|Dari|Jadi). Diukur di
   viewport 390px: kolom "Dari" dan "Jadi" — satu-satunya yang menjawab
   "berubah JADI apa" — jatuh SELURUHNYA di luar layar, dan label setelan
   mengurai jadi menara 6 baris. Pengelompokan "satu kali Simpan" pun cuma
   ditandai panah ↳ kecil di kolom Waktu yang kosong, tak terbaca sebagai satu
   tindakan.

   Sekarang SATU markup melayani keduanya: tiap penyimpanan jadi satu kartu
   berkepala (waktu · pelaku · jumlah setelan), isinya grid dua kolom di layar
   >=640px dan menumpuk di bawah itu. Tak ada gulir mendatar di lebar mana pun. */
.rwp-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.625rem; }

.rwp-event {
  border: 1px solid #e2e8f0;
  border-radius: 0.5rem;
  overflow: hidden;
  background: #fff;
}

.rwp-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.625rem;
  padding: 0.4rem 0.7rem;
  background: #f8fafc;
  border-bottom: 1px solid #e2e8f0;
  font-size: 0.75rem;
  color: #64748b;
}
.rwp-head .rwp-ikon { color: #a5b4fc; font-size: 0.6875rem; }
/* tabular-nums: deretan jam sejajar rapi walau angkanya beda lebar */
.rwp-when { font-weight: 600; color: #334155; font-variant-numeric: tabular-nums; }
.rwp-rel { color: #94a3b8; }
.rwp-who { color: #4f46e5; font-weight: 600; }
/* Jumlah setelan didorong ke kanan di layar lebar; di HP ia ikut membungkus
   ke baris berikut, jadi margin-left:auto sengaja hanya dipasang >=640px. */
.rwp-count {
  background: #eef2ff; color: #4338ca; border-radius: 999px;
  padding: 0.05rem 0.5rem; font-size: 0.6875rem; font-weight: 600;
}

.rwp-change {
  display: grid;
  gap: 0.2rem 1rem;
  padding: 0.5rem 0.7rem;
  border-top: 1px solid #f1f5f9;
}
.rwp-change:first-child { border-top: 0; }
.rwp-label { display: block; font-size: 0.8125rem; color: #1e293b; line-height: 1.35; }
.rwp-cat { display: block; font-size: 0.6875rem; color: #94a3b8; margin-top: 0.05rem; }

.rwp-move { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem; font-size: 0.75rem; min-width: 0; }
.rwp-from { color: #94a3b8; }
.rwp-to { color: #1e293b; font-weight: 600; }
/* Panah lewat ::before, bukan <i> Font Awesome, karena dua alasan: ia MELEKAT
   pada nilai baru sehingga saat nilainya panjang dan `rwp-move` membungkus,
   panahnya ikut turun memimpin baris kedua ("→ Foto Kirim + Foto Terima")
   alih-alih menggantung di ujung baris pertama; dan karakter teks tak bisa
   gagal muat seperti ikon font — "Aktif Nonaktif" tanpa panah kehilangan arah
   perubahannya, justru bagian yang paling penting di sini. */
.rwp-to::before { content: "\2192"; color: #cbd5e1; font-weight: 400; margin-right: 0.3rem; }
/* Setelan hidup/mati paling sering diubah dan paling cepat dibaca sebagai
   warna, bukan kata — chip dipakai HANYA untuk tipe bool (lihat _nilaiHtml). */
.rwp-chip { border-radius: 0.25rem; padding: 0.05rem 0.4rem; font-weight: 600; }
.rwp-chip.on { background: #d1fae5; color: #047857; }
.rwp-chip.off { background: #f1f5f9; color: #64748b; }
.rwp-from .rwp-chip { opacity: 0.7; font-weight: 500; }

@media (min-width: 640px) {
  .rwp-count { margin-left: auto; }
  /* Dua kolom: apa yang diubah | jadi apa. `baseline` menyejajarkan label
     setelan dengan nilainya walau labelnya membungkus dua baris. */
  .rwp-change { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); align-items: baseline; }
}

/* Utang Piutang (daftar + detail): kelas yang belum ikut tercetak di subset.
   - h-24/w-24 & cursor-zoom-in : kartu bukti foto yang bisa diperbesar.
   - border-amber-300           : pembeda tegas bukti PEMBERIAN pinjaman (amber)
                                  dari bukti PEMBAYARAN (emerald) — dua hal yang
                                  gampang tertukar dan berbeda arti kasnya.
   - whitespace-pre-wrap        : catatan multi-baris apa adanya.
   - btn:disabled               : tombol "Simpan" rekonsiliasi tampak mati saat
                                  belum ada perubahan (tanpa ini tetap pekat). */
.h-24 { height: 6rem; }
.w-24 { width: 6rem; }
.cursor-zoom-in { cursor: zoom-in; }
.border-amber-300 { border-color: #fcd34d; }
.whitespace-pre-wrap { white-space: pre-wrap; }
.btn-primary:disabled,
.btn-secondary:disabled { opacity: 0.45; cursor: default; }

/* ── Susulan sapu-bersih 2026-08-18 (audit kelas vs subset, lihat catatan di atas)
   Diaudit dengan mengekstrak SEMUA token class="…" dari index.html + 77 berkas JS
   lalu mencocokkannya ke tailwind.css + app.css (dengan escape CSS). Yang di bawah
   terbukti TIDAK punya aturan di mana pun — jadi selama ini diam-diam tak bergaya.
   Nilainya = nilai baku Tailwind, jadi menambahkannya hanya MEWUJUDKAN maksud
   markup yang sudah ada; tak ada tampilan yang berubah dari kondisi "benar".
     - h-8            : <img> avatar di performa-karyawan.js:158 & transfer-add.js:536
                        pakai `w-8 h-8`. w-8 ADA tapi h-8 TIDAK → foto melar tinggi
                        aslinya (32px lebar × ratusan px tinggi). Ini bug HP nyata.
     - object-contain : logo sidebar index.html:41 & foto lokasi bahan baku →
                        gambar teregang, bukan proporsional.
     - h-14 / w-14    : lingkaran ikon layar "Tidak Punya Akses" (app.js:314) kempis.
     - border-2       : preflight Tailwind menyetel border-width:0, jadi kotak unggah
                        foto bergaris putus-putus selama ini TANPA BINGKAI sama sekali.
     - sisanya        : ikon/badge kecil & tabel detail yang ukurannya tak terkendali. */
.h-4 { height: 1rem; }
.w-4 { width: 1rem; }
.h-6 { height: 1.5rem; }
.w-6 { width: 1.5rem; }
.h-8 { height: 2rem; }
.h-14 { height: 3.5rem; }
.w-14 { width: 3.5rem; }
.w-1\.5 { width: 0.375rem; }
.object-contain { object-fit: contain; }
.max-h-40 { max-height: 10rem; }
.max-h-44 { max-height: 11rem; }
.max-h-48 { max-height: 12rem; }
.top-0\.5 { top: 0.125rem; }
.right-0\.5 { right: 0.125rem; }
.border-2 { border-width: 2px; }
.align-middle { vertical-align: middle; }
.border-collapse { border-collapse: collapse; }

/* Dua kelas RESPONSIF yang dipakai tapi tak pernah ter-generate ke subset. Karena
   varian `sm:` hanya berlaku ≥640px, keduanya tak berpengaruh di HP — tapi di
   tablet/desktop efeknya nyata: baris filter /finance-requests terkunci 2 kolom
   (mestinya 5), dan tombol "Muat semua" di /source-monitoring meregang setinggi
   kotak peringatan karena align-self default flex = stretch. */
.self-start { align-self: flex-start; }
@media (min-width: 640px) {
  .sm\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .sm\:self-auto { align-self: auto; }
}

/* SKU itu identitas — tak pernah pantas dipenggal. Di HP kolomnya diperas
   auto-layout sampai 42px sehingga "PRD-RSC-001" pecah jadi 3 baris dan tinggi
   barisnya membengkak ke 105px. */
.data-table td.col-sku { white-space: nowrap; }

/* ── Modal Resep: lebar field (dulu inline style di inventory.js) ──────────────
   Dipindah ke CSS supaya bisa dibatalkan di breakpoint HP — inline style hanya
   bisa dikalahkan !important, dan itu bikin aturan mobile rapuh. */
/* ═══ Modal Resep — kartu per bahan ═══════════════════════════════════════════
   Dulu <table> 6 kolom (Bahan / Qty / Satuan / Konversi / Biaya / hapus) yang
   di HP disulap jadi kartu lewat CSS. Owner melaporkan modalnya sulit dibaca
   orang awam, dan memang: memahami SATU bahan menuntut mata melompat antar
   empat kolom, "Konversi" tak berarti apa-apa tanpa penjelasan, dan singkatan
   BB/HP hanya terbaca oleh yang sudah hafal.

   Sekarang tiap bahan adalah satu kartu yang bisa dibaca berurutan ke bawah,
   ditutup kalimat hasil ("Memotong 0,18 kg dari stok"). Kotak konversi hanya
   muncul saat satuannya memang beda jenis — lihat perluKonversi() di
   panels/inventory.js. */

.rcp-intro { font-size: 0.8125rem; line-height: 1.5; color: #374151; margin-bottom: 0.75rem; }
.rcp-warn {
  border: 1px solid #fcd34d; background: #fffbeb; color: #92400e;
  border-radius: 0.5rem; padding: 0.5rem 0.625rem;
  font-size: 0.6875rem; line-height: 1.5; margin-bottom: 0.75rem;
}
.rcp-lines { display: flex; flex-direction: column; gap: 0.5rem; }

.rcp-line { border: 1px solid #e5e7eb; border-radius: 0.625rem; padding: 0.625rem; background: #fff; }
.rcp-line-top { display: flex; align-items: flex-start; gap: 0.5rem; }
.rcp-line-ing { flex: 1 1 auto; min-width: 0; }
.rcp-del {
  flex: 0 0 auto; border-radius: 0.375rem; padding: 0.3125rem 0.4375rem;
  color: #9ca3af; background: transparent; line-height: 1;
}
.rcp-del:hover { color: #b91c1c; background: #fef2f2; }

/* Dua isian angka berdampingan — cukup lebar untuk dibaca, tak lebih. */
.rcp-line-num { display: grid; grid-template-columns: minmax(0, 7rem) minmax(0, 1fr); gap: 0.5rem; margin-top: 0.5rem; }
.rcp-mini { display: flex; flex-direction: column; gap: 0.1875rem; min-width: 0; }
.rcp-mini > span { font-size: 0.6875rem; font-weight: 600; color: #6b7280; }
.rcp-mini .field-input { padding: 0.3125rem 0.5rem; font-size: 0.8125rem; width: 100%; max-width: none; }

/* Kalimat hasil: menerjemahkan angka jadi akibat nyata di stok. */
.rcp-hasil {
  margin-top: 0.5rem; border-radius: 0.375rem; background: #f8fafc;
  padding: 0.3125rem 0.5rem; font-size: 0.75rem; line-height: 1.4; color: #475569;
}
.rcp-hasil:empty { display: none; }
.rcp-hasil-konv { color: #94a3b8; }
.rcp-hasil-perlu { background: #fffbeb; color: #92400e; }

/* Modal Resep /products — FORMAT TABEL (2026-07-29). Kartu .rcp-line masih dipakai
   modal resep Hasil Produksi (inventory.js), jadi ini aturan TAMBAHAN saja. Baris
   memakai .rcp-row (bukan .rcp-line) supaya tak kena gaya kartu. */
.rcp-table-wrap { overflow-x: auto; margin-bottom: 0.5rem; }
.rcp-table { width: 100%; border-collapse: collapse; font-size: 0.8125rem; }
.rcp-table thead th {
  text-align: left; color: #64748b; font-weight: 600; font-size: 0.625rem;
  text-transform: uppercase; letter-spacing: 0.03em; padding: 0.4rem 0.5rem;
  border-bottom: 1px solid #e2e8f0; white-space: nowrap; background: #f8fafc;
}
.rcp-table td { padding: 0.45rem 0.5rem; border-bottom: 1px solid #f1f5f9; vertical-align: top; }
.rcp-table .rcp-takaran { display: flex; gap: 0.25rem; align-items: center; }
.rcp-table .rcp-qty { width: 4.25rem; }
.rcp-table .rcp-uom { width: 6.5rem; }
.rcp-table .rcp-konvin { width: 5rem; }
.rcp-table .rcp-konv-lbl { font-size: 0.625rem; color: #94a3b8; margin-bottom: 0.15rem; }
.rcp-table .rcp-konv-hint { font-size: 0.625rem; color: #94a3b8; margin-top: 0.15rem; max-width: 13rem; line-height: 1.25; }
.rcp-table .rcp-c-ing { min-width: 11rem; }
.rcp-table .rcp-c-terpakai { min-width: 9rem; }
.rcp-table .rcp-c-del { text-align: center; }
/* Kolom Aktif: centang untuk pakai baris resep, hilangkan untuk mengabaikannya. */
.rcp-table .rcp-c-aktif { text-align: center; white-space: nowrap; }
.rcp-aktif { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.6875rem; font-weight: 600; color: #6b7280; cursor: pointer; user-select: none; }
.rcp-aktif input { cursor: pointer; margin: 0; }
/* Baris resep non-aktif: diredupkan (kecuali kolom Aktif & Hapus yang tetap bisa
   dipakai) + coretan pada bahan supaya jelas "diabaikan dari perhitungan". */
.rcp-table tr.rcp-inactive td:not(.rcp-c-aktif):not(.rcp-c-wajib):not(.rcp-c-del) { opacity: 0.4; }
/* Kolom Wajib: centang = bahan menahan stok produk (default). Tanpa centang,
   bahan boleh habis & produknya tetap bisa dipesan — ditandai kuning supaya
   pengecualian itu kelihatan sekilas, bukan tersembunyi di antara centang. */
.rcp-table .rcp-c-wajib { text-align: center; white-space: nowrap; }
.rcp-table .rcp-c-wajib .rcp-aktif:has(input:not(:checked)) { color: #b45309; }
.rcp-table tr.rcp-inactive .ing-combo-label { text-decoration: line-through; }
.rcp-table tr.rcp-inactive .rcp-aktif { color: #b91c1c; }
/* .rcp-hasil di dalam tabel: tak perlu margin/background kotak (biar rapat di sel). */
.rcp-table .rcp-hasil { margin-top: 0; background: transparent; padding: 0; }
.rcp-table .rcp-hasil-perlu { background: #fffbeb; padding: 0.15rem 0.35rem; border-radius: 0.25rem; }
.rcp-table .rcp-biaya { font-weight: 600; }

/* ── Buat Transfer Stok: kini wizard 4-langkah (owner 2026-08-15), memakai
   ULANG kelas .pb-* dari Buat Pembelian (purchase-add.js) apa adanya supaya
   gayanya identik tanpa duplikasi CSS. Sisa kelas transfer-spesifik: foto
   PER BARIS (belum ada padanannya di purchase-add — .fotoPath di sana masih
   scaffolding tanpa UI), jadi ditulis di sini. ── */
.pb-file-sm { padding: 0.35rem 0.55rem; font-size: 0.6875rem; border-radius: 0.5rem; gap: 0.375rem; }
.pb-file-sm i { font-size: 0.8125rem; }
.trfadd-foto-ok { display: inline-flex; align-items: center; gap: 0.375rem; }

/* Dropdown filter toolbar (mis. "Semua kategori") — batasi lebar di DESKTOP supaya
   nama kategori panjang tak melebarkan dropdown. (Mobile sudah dibatasi 9.5rem di
   media query .scm-dense.) */
select.toolbar-field { max-width: 12rem; }

/* Toggle switch (Pengaturan SCM 2026-07-29) — pengganti checkbox polos, lebih jelas
   on/off untuk management. */
.scm-switch { position: relative; display: inline-block; width: 2.4rem; height: 1.35rem; }
.scm-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.scm-switch-slider {
  position: absolute; inset: 0; background: #cbd5e1; border-radius: 999px;
  transition: background .18s ease; cursor: pointer;
}
.scm-switch-slider::before {
  content: ""; position: absolute; height: 1.05rem; width: 1.05rem; left: 0.15rem; top: 0.15rem;
  background: #fff; border-radius: 50%; box-shadow: 0 1px 2px rgba(0,0,0,.2); transition: transform .18s ease;
}
.scm-switch input:checked + .scm-switch-slider { background: #4f46e5; }
.scm-switch input:checked + .scm-switch-slider::before { transform: translateX(1.05rem); }
.scm-switch input:focus-visible + .scm-switch-slider { outline: 2px solid #a5b4fc; outline-offset: 2px; }

/* Kotak konversi — hanya tampil bila satuannya memang beda jenis. */
.rcp-konv { margin-top: 0.5rem; border-top: 1px dashed #e5e7eb; padding-top: 0.5rem; }
.rcp-konv-hint { margin-top: 0.25rem; font-size: 0.6875rem; line-height: 1.45; color: #9ca3af; }
.rcp-perlu { color: #b45309; }

.rcp-line-bot { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.5rem; }
.rcp-linkbtn { background: none; padding: 0; font-size: 0.6875rem; font-weight: 600; color: #4f46e5; text-decoration: underline; }
.rcp-linkbtn:hover { color: #3730a3; }
.rcp-biaya { margin-left: auto; font-size: 0.9375rem; font-weight: 700; color: #111827; }
.rcp-biaya-kosong { color: #d1d5db; font-weight: 400; }

/* Jenis bahan ditulis UTUH di dalam kartu; singkatan BB/HP hanya di daftar
   picker yang padat. */
.rcp-kind {
  flex: 0 0 auto; border-radius: 0.25rem; padding: 0.0625rem 0.3125rem;
  font-size: 0.5625rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em;
}
.rcp-kind-bb { background: #e0f2fe; color: #0369a1; }
.rcp-kind-hp { background: #ede9fe; color: #6d28d9; }

.rcp-add {
  margin-top: 0.625rem; width: 100%; border: 1px dashed #c7d2fe; background: #eef2ff;
  color: #4338ca; border-radius: 0.5rem; padding: 0.5rem; font-size: 0.8125rem; font-weight: 600;
}
.rcp-add:hover { background: #e0e7ff; }
/* "Kosongkan resep" — varian MERAH dari .rcp-add supaya jelas ini tindakan
   merusak, dan tak tertukar dgn "Tambah bahan" yang warnanya indigo. Ditulis
   eksplisit di sini (bukan kelas Tailwind) karena subset pra-kompilasi. */
.rcp-clear { border-color: #fecaca; background: #fef2f2; color: #b91c1c; }
.rcp-clear:hover { background: #fee2e2; }

.rcp-total { margin-top: 0.875rem; border: 1px solid #e5e7eb; border-radius: 0.625rem; padding: 0.75rem; background: #fafafa; }
.rcp-total-utama { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; }
.rcp-total-utama > span { font-size: 0.8125rem; font-weight: 600; color: #374151; }
.rcp-total-utama > b { font-size: 1.125rem; font-weight: 700; color: #4338ca; }
.rcp-total-lain {
  display: flex; justify-content: space-between; gap: 0.75rem; margin-top: 0.375rem;
  border-top: 1px solid #eef2f7; padding-top: 0.375rem; font-size: 0.75rem; color: #6b7280;
}
.rcp-total-catatan { margin-top: 0.5rem; font-size: 0.6875rem; line-height: 1.5; color: #9ca3af; }

/* Bahan yang tercatat lebih dari sekali — ditandai pada kartunya, bukan cuma
   diberi tahu di kotak peringatan atas. */
.recipe-line-dup { background: #fffbeb; box-shadow: inset 3px 0 0 #f59e0b; }

/* Nama bahan panjang dibiarkan membungkus: di kartu ada ruang vertikal, jadi
   memotongnya dengan "…" hanya menyembunyikan pembeda antar-varian. */
.rcp-line .ing-combo-btn { align-items: flex-start; height: auto; min-height: 2.25rem; }
.rcp-line .ing-combo-label { flex-wrap: wrap; }
.rcp-line .ing-combo-label .ing-name {
  white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere;
}

@media (min-width: 640px) {
  .rcp-line-num { grid-template-columns: minmax(0, 8rem) minmax(0, 16rem); }
}


/* Penanda bahan di kolom BOM. Merah = stoknya habis sehingga produk tak bisa
   dibuat; kuning = bahan yang paling membatasi jumlah yang bisa dibuat.
   Warna DAN ikon dipakai bersama supaya tetap terbaca oleh yang sulit
   membedakan warna. */
.bom-habis {
  color: #b91c1c;
  font-weight: 600;
  background: #fef2f2;
  border-radius: 0.25rem;
  padding: 0 0.25rem;
}
.bom-pembatas {
  color: #92400e;
  background: #fffbeb;
  border-radius: 0.25rem;
  padding: 0 0.25rem;
}

/* Isian terkunci (SKU): tampil jelas tapi tak bisa diubah sampai ikon pensil
   diklik — mencegah SKU berubah karena kelewat mengetik, padahal ia dipakai
   mencocokkan item antar-outlet saat transfer & salin. */
.lock-field { position: relative; }
.lock-field .field-input { padding-right: 2.3rem; }
.lock-field .field-input[readonly] {
  background: #f1f5f9;
  color: #64748b;
  cursor: default;
}
.lock-btn {
  position: absolute;
  right: 0.3rem;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.7rem;
  height: 1.7rem;
  border: none;
  border-radius: 0.35rem;
  background: transparent;
  color: #94a3b8;
  cursor: pointer;
  font-size: 0.75rem;
}
.lock-btn:hover { background: #e2e8f0; color: #475569; }
.lock-btn:focus-visible { outline: 2px solid var(--scm-accent); outline-offset: 1px; }
.lock-btn.is-open { color: var(--scm-accent); background: #eef2ff; }
.lock-hint {
  font-size: 0.6875rem;
  line-height: 1.35;
  color: #92400e;
  margin-top: 0.3rem;
}
.lock-hint.hidden { display: none; }

/* ── Picker bahan ber-pencarian (buatIngPicker di inventory.js) ────────────── */
.ing-combo { position: relative; }
.ing-combo-btn {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  width: 100%;
  text-align: left;
  background: #fff;
  cursor: pointer;
  overflow: hidden;
}
.ing-combo-label {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  overflow: hidden;
}
.ing-combo-label .ing-name,
.ing-pop-item .ing-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ing-pop-item .ing-name { flex: 1; }
.ing-combo-label .ing-sku,
.ing-pop-item .ing-sku {
  color: #94a3b8;
  font-size: 0.6875rem;
  flex-shrink: 0;
}
.ing-combo-label .ing-ph { color: #9ca3af; }
/* Penanda bahan milik OUTLET LAIN. Bahan boleh diambil lintas-outlet, tapi harus
   kelihatan — nama bahan banyak yang kembar antar-outlet, dan stok yang dipotong
   saat produksi mengikuti outlet si bahan. */
.ing-combo-label .ing-outlet,
.ing-pop-item .ing-outlet {
  flex-shrink: 0;
  font-size: 0.625rem;
  font-weight: 600;
  padding: 0.05rem 0.3rem;
  border-radius: 0.25rem;
  background: #fef3c7;
  color: #92400e;
  white-space: nowrap;
}
.ing-combo-caret { color: #9ca3af; font-size: 0.7rem; flex-shrink: 0; }

.ing-pop {
  position: fixed;
  /* di atas .modal-backdrop (z-index 50) */
  z-index: 60;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #fff;
  border: 1px solid #d1d5db;
  border-radius: 0.6rem;
  box-shadow: 0 12px 28px -8px rgba(15, 23, 42, 0.35);
}
/* Jebakan urutan CSS yang sama dgn .btn-secondary.hidden di atas: .hidden dari
   tailwind.css (dimuat duluan) kalah dari display:flex di sini. */
.ing-pop.hidden { display: none; }
.ing-pop-head { padding: 0.5rem; border-bottom: 1px solid #f1f5f9; }
.ing-pop-luar {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.4rem;
  font-size: 0.6875rem;
  color: #64748b;
  cursor: pointer;
}
.ing-pop-list {
  list-style: none;
  margin: 0;
  padding: 0.25rem;
  overflow-y: auto;
  max-height: 15rem;
  -webkit-overflow-scrolling: touch;
}
.ing-pop-item {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.5rem;
  border-radius: 0.4rem;
  cursor: pointer;
  font-size: 0.8125rem;
}
.ing-pop-item.is-hi,
.ing-pop-item:hover { background: #eef2ff; }
.ing-pop-note {
  padding: 0.55rem;
  text-align: center;
  color: #94a3b8;
  font-size: 0.6875rem;
  border-top: 1px solid #f1f5f9;
}
.ing-pop-note.hidden { display: none; }

@media (max-width: 640px) {
  /* Kepadatan panel inventory. Angka dipilih supaya "Rp 12.480.500" muat satu
     baris di kartu ringkasan 2-kolom dan kolom Aksi tak lagi mendominasi. */
  .scm-dense h2 { font-size: 0.8125rem; }

  .scm-dense .panel-card { padding: 0.6rem; }
  .scm-dense .stat-card { padding: 0.5rem 0.6rem; }
  .scm-dense .stat-card .stat-label { font-size: 0.5625rem; letter-spacing: 0.02em; margin-bottom: 0.1rem; }
  .scm-dense .stat-card .stat-value { font-size: 0.9375rem; }

  .scm-dense .data-table { font-size: 0.6875rem; }
  .scm-dense .data-table thead th { padding: 0.3rem 0.4rem; font-size: 0.625rem; }
  .scm-dense .data-table tbody td { padding: 0.35rem 0.4rem; }
  /* Tanpa ini kolom Nama menyempit sampai satu kata per baris ("Roti / Sobek /
     Coklat / Premium") karena tabel auto-layout memerasnya. Kolom teks sempit
     lain kena gejala sama di halaman Produk (15 kolom): Outlet "Houssi Central
     Kitchen" pecah 3 baris, dan sel Storefront berisi 5 toggle diperas ke 91px.
     Lebar minimum ini menambah lebar tabel sedikit, tapi tinggi baris turun jauh
     — tabelnya toh memang di-scroll horizontal. */
  .scm-dense .data-table td.col-nama { min-width: 8.5rem; }
  .scm-dense .data-table td.col-outlet { min-width: 6.5rem; }
  .scm-dense .data-table td.col-kategori { min-width: 5rem; }
  .scm-dense .data-table td.col-supplier { min-width: 6.5rem; }
  /* 13rem = titik optimal hasil ukur: sel Storefront (5 toggle) yang menentukan
     tinggi baris halaman Produk. 8rem→105px, 10.5rem→86px, 13rem→68px,
     16rem→66px. Ambil 13rem: tinggi baris turun 21% cuma dgn +40px lebar tabel;
     melebar lagi nyaris tak menambah apa-apa. */
  .scm-dense .data-table td.col-storefront { min-width: 13rem; }

  /* Kolom Aksi Bahan Baku & Hasil Produksi: di HP lengket di tepi kanan supaya
     Edit/Resep/Salin/Arsipkan/Riwayat (dan tombol senada di Hasil Produksi)
     selalu kelihatan, ditumpuk vertikal. nowrap 5 tombol dulu terpotong. */
  .scm-dense .data-table th.col-aksi,
  .scm-dense .data-table td.col-aksi {
    position: sticky;
    right: 0;
    z-index: 4;
    min-width: 5.75rem;
    width: 5.75rem;
    white-space: normal;
    background: #fff;
    box-shadow: -6px 0 10px -6px rgba(15, 23, 42, 0.22);
    vertical-align: top;
  }
  .scm-dense .data-table thead th.col-aksi {
    z-index: 6;
    background: #f8fafc;
  }
  .scm-dense .data-table tbody tr:nth-child(even) td.col-aksi { background: #fcfcfd; }
  .scm-dense .data-table tbody tr:hover td.col-aksi { background: #eef2ff; }
  .scm-dense .aksi-btns {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 0.2rem;
  }
  .scm-dense .aksi-btns > .btn-primary,
  .scm-dense .aksi-btns > .btn-secondary,
  .scm-dense .aksi-btns > a {
    width: 100%;
    justify-content: center;
    padding: 0.28rem 0.35rem;
    font-size: 0.625rem;
  }

  .scm-dense .btn-primary,
  .scm-dense .btn-secondary,
  .scm-dense .btn-danger { font-size: 0.6875rem; padding: 0.3rem 0.5rem; gap: 0.25rem; border-radius: 0.4rem; }
  /* 16px, BUKAN 0.75rem — lihat blok "Zoom paksa iOS" di bawah. Padding
     dipangkas supaya tinggi kotaknya tetap sepadat sebelumnya walau fontnya
     naik. */
  .scm-dense .field-input { font-size: 16px; padding: 0.25rem 0.5rem; }
  .scm-dense .status-badge { font-size: 0.5625rem; padding: 0.1rem 0.4rem; }
  /* Kotak Cari penuh selebar toolbar di HP. Dulu ini khusus halaman Produk
     (kelas .prod-search, permintaan owner 2026-08-12) sementara panel lain
     dicap 9.5rem supaya Cari + filter muat sebaris. Cap itu tak lagi bisa
     dipertahankan setelah isian naik ke 16px (lihat "Zoom paksa iOS"): pada
     9.5–11.5rem placeholder terpotong jadi "Cari SKU / na…". Karena alasan
     owner memilih Cari-penuh di Produk berlaku sama persis di sini, aturannya
     dilepas dari .prod-search agar berlaku utk semua panel inventory.
     CATATAN: aturan ini hanya BERBUNYI kalau baris toolbarnya ber-flex-wrap —
     tanpa itu flex-basis:100% langsung diciutkan lagi oleh flex-shrink. Produk
     sudah wrap (panelToolbar), Hasil Produksi baru diberi flex-wrap bersama
     perubahan ini. Bahan Baku toolbarnya BELUM wrap, jadi utk sekarang ia tak
     terpengaruh — bukan kelalaian, sengaja di luar lingkup.
     Aturan .prod-search yg lama DILEBUR ke sini; kelasnya masih dipancarkan
     products.js tapi kini inert — membuangnya perkara rapi-rapi tersendiri. */
  .scm-dense input[type="search"].field-input { max-width: none; flex: 1 1 100%; }
  /* Filter tetap dicap supaya beberapa filter muat sebaris; 11.5rem (dulu
     9.5rem) karena teks 16px butuh ruang lebih — pada 9.5rem opsi "Semua
     kategori" terpotong. */
  .scm-dense select.toolbar-field { max-width: 11.5rem; }

  /* Pemilih outlet/tenant di HEADER berada DI LUAR #panel-root, jadi tak ikut
     terjangkau .scm-dense (fix 2026-08-18). Padahal ini kontrol yang paling
     sering disentuh di tiap halaman — dengan font 13px iOS Safari mem-zoom
     halaman tiap kali dibuka dan tak pernah zoom balik. Dua kelas dipakai
     bersama supaya menang atas .text-xs bawaan Tailwind. */
  .scm-ctx-select.field-input { font-size: 16px; }

  /* ── Modal padat (.modal-dense dipasang ke .modal-backdrop) ───────────────── */
  .modal-backdrop.modal-dense { padding: 0.5rem; }
  /* max-height diwarisi dari base (100%) — dulu 96vh, lihat catatan iOS di
     .modal-panel: `vh` di iOS Safari melampaui area terlihat & menyembunyikan
     tombol Batal/Simpan di balik toolbar bawah. */
  .modal-backdrop.modal-dense .modal-panel { border-radius: 0.75rem; }
  .modal-backdrop.modal-dense .modal-header { padding: 0.7rem 0.85rem; }
  .modal-backdrop.modal-dense .modal-header h3 { font-size: 0.875rem; line-height: 1.3; }
  .modal-backdrop.modal-dense .modal-body { padding: 0.85rem; }
  .modal-backdrop.modal-dense .modal-footer { padding: 0.7rem 0.85rem; }
  .modal-backdrop.modal-dense .btn-primary,
  .modal-backdrop.modal-dense .btn-secondary { font-size: 0.75rem; padding: 0.4rem 0.7rem; }
  /* Form isian panjang (Tambah/Edit item ±12 field): label & isian dipadatkan
     dan jarak antar-field 1rem → 0.65rem, supaya tak perlu scroll sejauh itu.
     Nilai field-input disamakan dgn blok .recipe-line di bawah agar tak saling
     menimpa (specificity-nya lebih tinggi). */
  .modal-backdrop.modal-dense .field-label { font-size: 0.6875rem; margin-bottom: 0.15rem; }
  .modal-backdrop.modal-dense .field-input { font-size: 16px; padding: 0.25rem 0.45rem; }
  .modal-backdrop.modal-dense .modal-body > .grid { gap: 0.65rem; }

  /* ── Zoom paksa iOS ────────────────────────────────────────────────────────
     iOS Safari MEN-ZOOM halaman begitu isian ber-font <16px disentuh, dan tak
     pernah mengembalikan zoom-nya. Di modal Edit Hasil Produksi (11 isian
     @12px) tiap pindah field = satu lompatan zoom, lalu pengguna harus mencubit
     balik — inilah "masalah saat pakai iPhone" yg dilaporkan owner 2026-08-15.
     Viewport kita `width=device-width, initial-scale=1` TANPA maximum-scale,
     dan itu memang disengaja: `maximum-scale=1`/`user-scalable=no` mematikan
     cubit-zoom & melanggar aksesibilitas. Jadi obatnya di sisi CSS: isian yang
     BISA DIFOKUS wajib ≥16px. Padding dipangkas sbg ganti rugi tinggi.
     Yang TIDAK ikut naik: label, tombol, badge, sel tabel — semuanya tak bisa
     difokus untuk mengetik, jadi tak memicu zoom & kepadatannya tetap.
     Penerapannya di dua aturan .field-input di atas; input, select, DAN textarea
     semuanya memakai kelas itu, jadi tak perlu aturan per-elemen. */

  /* Jatah prefiks Rp — penawar jebakan shorthand `padding` di atas (lihat
     catatan di .money-field). WAJIB berada SETELAH aturan kepadatan agar menang
     pada spesifisitas yang sama. 1.9rem (bukan 2.1rem) karena padding kiri
     dasar di modal padat memang lebih rapat. */
  .scm-dense .money-field > .field-input,
  .modal-backdrop.modal-dense .money-field > .field-input { padding-left: 1.9rem; }

  /* Home indicator iPhone: .modal-footer menempel di dasar panel, dan panel kini
     boleh setinggi backdrop — tanpa ini tombol Batal/Simpan bisa bersinggungan
     dgn garis home. env() aman di peramban lain (fallback 0.7rem). */
  .modal-backdrop.modal-dense .modal-footer {
    padding-bottom: max(0.7rem, env(safe-area-inset-bottom));
  }
}



/* Popup picker di HP: disematkan di atas layar (lihat tempatkan() di
   inventory.js), daftarnya boleh lebih tinggi karena tak menempel tombol. */
@media (max-width: 640px) {
  .ing-pop-luar {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.4rem;
  font-size: 0.6875rem;
  color: #64748b;
  cursor: pointer;
}
.ing-pop-list { max-height: 50vh; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Buat Pembelian — wizard 4 langkah (panels/purchase-add.js)

   Kelas sendiri, bukan utilitas Tailwind: berkas tailwind.css di sini adalah
   SUBSET yang sudah dicetak, jadi kelas yang belum pernah dipakai diam-diam
   tak berefek. Tata letak sepenting ini tak boleh bergantung pada itu.
   ═══════════════════════════════════════════════════════════════════════════ */

.pb-wrap { max-width: 56rem; margin: 0 auto; padding-bottom: 1rem; }
.pb-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.75rem; }
.pb-title { font-size: 1.125rem; font-weight: 700; color: #111827; line-height: 1.2; }
.pb-sub { font-size: 0.75rem; color: #6b7280; margin-top: 0.125rem; }
.pb-keluar { flex: 0 0 auto; }

/* Rel langkah — selalu terlihat supaya orang tahu ada di mana dan sisa berapa */
.pb-steps { display: flex; gap: 0.25rem; margin-bottom: 1rem; }
.pb-stepitem {
  flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: 0.25rem;
  min-width: 0; padding: 0.5rem 0.125rem; border-radius: 0.5rem; text-align: center;
  border-top: 3px solid #e5e7eb; color: #9ca3af;
}
.pb-stepitem[data-st="1"] { border-top-color: #4f46e5; color: #4338ca; background: #eef2ff; }
.pb-stepitem[data-st="2"] { border-top-color: #34d399; color: #047857; cursor: pointer; }
.pb-stepitem[data-st="2"]:hover { background: #ecfdf5; }
.pb-stepnum {
  display: flex; align-items: center; justify-content: center;
  height: 1.75rem; width: 1.75rem; border-radius: 9999px;
  background: #f3f4f6; font-size: 0.75rem;
}
.pb-stepitem[data-st="1"] .pb-stepnum { background: #4f46e5; color: #fff; }
.pb-stepitem[data-st="2"] .pb-stepnum { background: #34d399; color: #fff; }
.pb-steptext { display: block; min-width: 0; font-size: 0.6875rem; line-height: 1.15; }
.pb-steptext b { display: block; font-size: 0.5625rem; text-transform: uppercase; letter-spacing: 0.03em; opacity: 0.75; }
@media (max-width: 380px) { .pb-steptext { display: none; } }

/* Satu langkah = satu layar */
.pb-pane { background: #fff; border: 1px solid #e5e7eb; border-radius: 0.75rem; padding: 1rem; }
.pb-h { font-size: 1rem; font-weight: 700; color: #111827; }
.pb-help { margin-top: 0.125rem; margin-bottom: 1rem; font-size: 0.8125rem; color: #6b7280; line-height: 1.4; }
.pb-field { margin-bottom: 1rem; }
.pb-label { display: block; margin-bottom: 0.25rem; font-size: 0.8125rem; font-weight: 600; color: #374151; }
.pb-hint { margin-top: 0.25rem; font-size: 0.6875rem; line-height: 1.45; color: #9ca3af; }
.pb-linkbtn { background: none; padding: 0; font-size: 0.6875rem; font-weight: 600; color: #4f46e5; text-decoration: underline; }
.pb-linkbtn:hover { color: #3730a3; }
.pb-a { display: inline-block; margin-top: 0.25rem; font-weight: 600; color: #0369a1; text-decoration: underline; }

/* Pilihan berbentuk kartu, bukan dropdown — lebih terbaca bagi yang jarang
   memakai komputer, dan pilihannya terlihat semua sekaligus. */
.pb-choices { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.5rem; }
.pb-choices-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 480px) { .pb-choices { grid-template-columns: 1fr; } }
.pb-choice {
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.125rem;
  border: 2px solid #e5e7eb; border-radius: 0.625rem; background: #fff;
  padding: 0.625rem 0.75rem; text-align: left; min-width: 0;
}
.pb-choice i { font-size: 1rem; color: #9ca3af; margin-bottom: 0.125rem; }
.pb-choice b { font-size: 0.8125rem; font-weight: 700; color: #374151; }
.pb-choice span { font-size: 0.6875rem; color: #9ca3af; line-height: 1.3; }
.pb-choice[data-act="1"] { border-color: #4f46e5; background: #eef2ff; }
.pb-choice[data-act="1"] i, .pb-choice[data-act="1"] b { color: #4338ca; }
.pb-choice[data-act="1"] span { color: #6366f1; }
/* Varian sumber pembelian: SELALU 3 kolom sebaris (termasuk mobile) — override
   aturan .pb-choices yang menumpuk jadi 1 kolom di ≤480px. Di layar sempit
   kartu dipadatkan & diketengahkan supaya 3 tetap muat rapi. */
.pb-choices-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
@media (max-width: 480px) {
  .pb-choices-3 { gap: 0.375rem; }
  .pb-choices-3 .pb-choice { align-items: center; text-align: center; padding: 0.5rem 0.35rem; }
  .pb-choices-3 .pb-choice i { font-size: 0.95rem; }
  .pb-choices-3 .pb-choice b { font-size: 0.72rem; line-height: 1.15; }
  .pb-choices-3 .pb-choice span { font-size: 0.6rem; line-height: 1.25; }
}

.pb-note { display: flex; gap: 0.5rem; border-radius: 0.5rem; padding: 0.625rem 0.75rem; font-size: 0.75rem; line-height: 1.5; margin-bottom: 1rem; }
.pb-note i { flex: 0 0 auto; margin-top: 0.125rem; }
.pb-note-info { border: 1px solid #bae6fd; background: #f0f9ff; color: #0c4a6e; }
.pb-note-warn { border: 1px solid #fcd34d; background: #fffbeb; color: #92400e; }

/* Supplier */
.pb-sup { position: relative; }
.pb-sup-panel {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 60; margin-top: 0.25rem;
  max-height: 15rem; overflow-y: auto; background: #fff;
  border: 1px solid #e5e7eb; border-radius: 0.5rem; box-shadow: 0 8px 20px rgba(15, 23, 42, 0.12);
}
.pb-sup-row { display: block; width: 100%; text-align: left; padding: 0.375rem 0.75rem; font-size: 0.8125rem; }
.pb-sup-row:hover { background: #eef2ff; }
.pb-picked {
  display: flex; align-items: center; gap: 0.5rem; margin-top: 0.375rem;
  border: 1px solid #a7f3d0; background: #ecfdf5; border-radius: 0.5rem;
  padding: 0.4375rem 0.625rem; font-size: 0.8125rem; color: #065f46;
}
.pb-picked i { color: #059669; }

/* Isian rupiah: prefiks "Rp" menempel supaya tak ada yang mengetik "Rp" lagi */
.pb-rp { display: flex; align-items: stretch; }
.pb-rp > span {
  display: flex; align-items: center; padding: 0 0.625rem;
  border: 1px solid #e5e7eb; border-right: 0; border-radius: 0.5rem 0 0 0.5rem;
  background: #f9fafb; font-size: 0.8125rem; font-weight: 600; color: #6b7280;
}
.pb-rp > .field-input { border-radius: 0 0.5rem 0.5rem 0; flex: 1 1 auto; min-width: 0; }
.pb-rp-sm > span { padding: 0 0.4375rem; font-size: 0.75rem; }
.pb-rp-sm > .field-input { padding: 0.3125rem 0.5rem; font-size: 0.8125rem; }

/* Tombol unggah foto — dulu garis putus-putus tipis (kurang jelas sbg tombol).
   Kini terisi indigo muda + border solid + ikon kamera → jelas bisa diketuk. */
.pb-file {
  display: flex; align-items: center; gap: 0.5rem; cursor: pointer;
  border: 1.5px solid #c7d2fe; background: #eef2ff; border-radius: 0.625rem;
  padding: 0.7rem 0.85rem; font-size: 0.8125rem; font-weight: 600; color: #4338ca;
}
.pb-file i { font-size: 1rem; }
.pb-file:hover { background: #e0e7ff; border-color: #a5b4fc; }
.pb-file:active { background: #c7d2fe; }
.pb-file span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Langkah 2: katalog + keranjang */
.pb-two { display: flex; flex-direction: column; gap: 1rem; }
.pb-col { min-width: 0; }
.pb-collabel { display: flex; align-items: center; gap: 0.375rem; margin-bottom: 0.5rem; font-size: 0.8125rem; font-weight: 700; color: #374151; }
.pb-badge {
  display: inline-block; min-width: 1.25rem; border-radius: 9999px;
  background: #4f46e5; color: #fff; padding: 0 0.375rem;
  font-size: 0.6875rem; font-weight: 700; text-align: center;
}
.pb-tabs { display: flex; gap: 0.375rem; overflow-x: auto; }
.pb-tabs::-webkit-scrollbar { display: none; }
.pb-tab {
  flex: 0 0 auto; border: 1px solid #e5e7eb; background: #fff; color: #6b7280;
  border-radius: 9999px; padding: 0.375rem 0.75rem; font-size: 0.75rem; font-weight: 600;
}
.pb-tab[data-act="1"] { border-color: #4f46e5; background: #4f46e5; color: #fff; }
.pb-katalog { max-height: 26rem; overflow-y: auto; border: 1px solid #f1f5f9; border-radius: 0.5rem; padding: 0.5rem; background: #f9fafb; }
.pb-kosongtxt { padding: 1.25rem 0.5rem; text-align: center; font-size: 0.75rem; color: #6b7280; line-height: 1.5; }
.pb-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.5rem; }
@media (min-width: 640px) { .pb-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.pb-card {
  position: relative; display: flex; flex-direction: column; gap: 0.25rem; text-align: left;
  border: 1px solid #e5e7eb; border-radius: 0.5rem; background: #fff; padding: 0.5rem; min-width: 0;
}
.pb-card:hover { border-color: #a5b4fc; box-shadow: 0 1px 6px rgba(79, 70, 229, 0.12); }
.pb-card-img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: 0.375rem; background: #f3f4f6; }
.pb-card-noimg { display: flex; align-items: center; justify-content: center; color: #d1d5db; font-size: 1.25rem; }
.pb-card-name {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: 0.75rem; font-weight: 600; line-height: 1.25; color: #1f2937;
}
.pb-card-meta { font-size: 0.625rem; color: #9ca3af; }
.pb-card-cost { font-size: 0.6875rem; font-weight: 700; color: #4338ca; }
.pb-card-per { font-weight: 400; color: #9ca3af; }
/* Harga per satuan DASAR sebagai pembanding di bawah harga per kemasan.
   Sengaja block + lebih kecil: yang dipakai bertransaksi adalah harga per
   kemasan, ini cuma rujukan agar konversinya tetap terbaca. */
.pb-card-per2 {
  display: block; font-weight: 400; color: #9ca3af;
  font-size: 0.625rem; line-height: 1.3; margin-top: 0.0625rem;
}
.pb-card-qty {
  position: absolute; top: 0.375rem; right: 0.375rem; min-width: 1.375rem;
  border-radius: 9999px; background: #4f46e5; color: #fff;
  padding: 0.0625rem 0.375rem; font-size: 0.6875rem; font-weight: 700; text-align: center;
}
.pb-empty {
  display: flex; flex-direction: column; align-items: center; gap: 0.375rem;
  border: 1px dashed #e5e7eb; border-radius: 0.5rem; padding: 1.5rem 1rem;
  text-align: center; font-size: 0.75rem; line-height: 1.5; color: #9ca3af;
}
.pb-empty i { font-size: 1.5rem; opacity: 0.6; }

/* Baris keranjang */
.pb-line { border: 1px solid #e5e7eb; border-radius: 0.625rem; padding: 0.625rem; background: #fff; }
.pb-line-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.5rem; }
.pb-line-name { font-size: 0.8125rem; font-weight: 600; color: #1f2937; line-height: 1.3; min-width: 0; }
.pb-line-del { flex: 0 0 auto; border-radius: 0.375rem; padding: 0.1875rem 0.375rem; color: #9ca3af; }
.pb-line-del:hover { color: #b91c1c; background: #fef2f2; }
.pb-line-row { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.5rem; }
.pb-line-lab { flex: 0 0 5rem; font-size: 0.6875rem; color: #6b7280; }
.pb-line-uom { flex: 1 1 0; min-width: 0; padding: 0.3125rem 0.5rem; font-size: 0.75rem; }
.pb-line-uom-txt { font-size: 0.75rem; color: #6b7280; }
.pb-line-per { font-size: 0.6875rem; color: #9ca3af; white-space: nowrap; }
.pb-line-kalimat {
  margin-top: 0.5rem; border-radius: 0.375rem; background: #f8fafc;
  padding: 0.3125rem 0.5rem; font-size: 0.6875rem; line-height: 1.4; color: #475569;
}
.pb-line-satuan1 { color: #b45309; }
.pb-line-bot { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.5rem; }
.pb-line-total { font-size: 0.9375rem; font-weight: 700; color: #111827; }
.pb-line-koreksi { margin-top: 0.5rem; border-top: 1px dashed #e5e7eb; padding-top: 0.5rem; }

/* Penambah/pengurang jumlah — mengetik angka di HP itu paling sering salah */
.pb-step { display: flex; align-items: stretch; }
.pb-step-b {
  width: 2rem; border: 1px solid #e5e7eb; background: #f9fafb;
  font-size: 1rem; font-weight: 700; color: #4b5563; line-height: 1;
}
.pb-step-b:first-child { border-radius: 0.5rem 0 0 0.5rem; }
.pb-step-b:last-child { border-radius: 0 0.5rem 0.5rem 0; }
.pb-step-b:hover { background: #eef2ff; color: #4338ca; }
.pb-step-i {
  width: 3.25rem; border-top: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb;
  border-left: 0; border-right: 0; text-align: center;
  font-size: 0.875rem; font-weight: 600; color: #111827; padding: 0.3125rem 0;
}

/* Langkah 4: rekap seperti struk */
.pb-rk { border: 1px solid #e5e7eb; border-radius: 0.625rem; padding: 0.75rem; margin-bottom: 0.625rem; }
.pb-rk-head {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  margin-bottom: 0.5rem; padding-bottom: 0.375rem; border-bottom: 1px solid #f1f5f9;
  font-size: 0.6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.03em; color: #6b7280;
}
.pb-rk-row { display: flex; justify-content: space-between; gap: 0.75rem; font-size: 0.8125rem; padding: 0.1875rem 0; }
.pb-rk-row > span:first-child { color: #6b7280; flex: 0 0 auto; }
.pb-rk-row > span:last-child { text-align: right; min-width: 0; color: #1f2937; }
.pb-rk-item { display: grid; grid-template-columns: 1fr auto; gap: 0 0.5rem; padding: 0.375rem 0; border-bottom: 1px dashed #f1f5f9; }
.pb-rk-item:last-child { border-bottom: 0; }
.pb-rk-item-n { grid-column: 1; grid-row: 1; font-size: 0.8125rem; font-weight: 600; color: #1f2937; min-width: 0; }
.pb-rk-item-q { grid-column: 1; grid-row: 2; font-size: 0.6875rem; color: #6b7280; }
/* Kolom & barisnya WAJIB disebut eksplisit. Tanpa itu penempatan otomatis grid
   menaruh nilai (yang membentang 2 baris) di kolom 1, sehingga harga tampil di
   kiri dan nama barang terlempar ke kanan. */
.pb-rk-item-t { grid-column: 2; grid-row: 1 / span 2; align-self: center; text-align: right; font-size: 0.8125rem; font-weight: 700; color: #111827; white-space: nowrap; }
.pb-rk-konv { color: #9ca3af; }
.pb-rk-total {
  display: flex; justify-content: space-between; gap: 0.75rem; margin-top: 0.375rem;
  border-top: 1px solid #e5e7eb; padding-top: 0.375rem; font-size: 0.9375rem; font-weight: 700; color: #111827;
}

/* Kaki lengket: total + alasan + navigasi selalu terlihat */
.pb-foot {
  position: sticky; bottom: 0; z-index: 20; margin-top: 0.75rem;
  border-top: 1px solid #e5e7eb; background: rgba(255, 255, 255, 0.97);
  padding: 0.625rem 0 max(0.625rem, env(safe-area-inset-bottom, 0px));
  backdrop-filter: blur(4px);
}
.pb-totalbar {
  display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem;
  margin-bottom: 0.5rem; border-radius: 0.5rem; background: #eef2ff; padding: 0.4375rem 0.75rem;
}
.pb-totalbar-l { font-size: 0.75rem; font-weight: 600; color: #4338ca; }
.pb-totalbar-v { font-size: 1rem; font-weight: 700; color: #3730a3; }
.pb-alasan {
  margin-bottom: 0.5rem; border-radius: 0.5rem; border: 1px solid #fcd34d; background: #fffbeb;
  padding: 0.4375rem 0.625rem; font-size: 0.75rem; line-height: 1.4; color: #92400e;
}
.pb-nav { display: flex; gap: 0.5rem; }
.pb-nav-back { flex: 0 0 auto; }
.pb-nav-next { flex: 1 1 auto; font-weight: 700; }
.pb-nav-next:disabled { opacity: 0.45; cursor: default; }

/* PENTING — app.css dimuat SETELAH tailwind.css, jadi `display:flex` pada
   .pb-note / .pb-empty / .pb-totalbar mengalahkan `.hidden` milik Tailwind yang
   kespesifikannya sama tapi urutannya lebih dulu. Akibatnya kotak yang
   di-`classList.add("hidden")` tetap terlihat (kotak "outlet mitra" muncul
   padahal sumbernya Supplier). Satu aturan berkespesifikan lebih tinggi,
   dilingkupi .pb-wrap supaya tak menyentuh halaman lain. */
.pb-wrap .hidden { display: none; }

/* Layar lebar: langkah 2 jadi dua kolom (katalog | keranjang) */
@media (min-width: 900px) {
  .pb-two { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: 1.25rem; align-items: start; }
  .pb-katalog { max-height: 30rem; }
  .pb-pane { padding: 1.25rem; }
}


/* Utilitas yang dipakai halaman Buat Pembelian tapi belum ikut tercetak di
   subset tailwind.css. Tanpa ini kelasnya diam-diam tak berefek — `lg:hidden`
   khususnya: tombol langkah 1-2-3 (khusus HP) akan ikut muncul di layar lebar
   padahal ketiga panelnya sudah tampil berdampingan. */
.leading-relaxed { line-height: 1.625; }
.border-sky-200 { border-color: #bae6fd; }
.text-sky-900 { color: #0c4a6e; }
.flex-\[1\.4\] { flex: 1.4 1 0%; }
@media (min-width: 1024px) { .lg\:hidden { display: none; } }

/* Thumbnail foto per-baris di /purchase-detail. Kelas Tailwind h-14/w-14 TAK ada
   di subset pra-kompilasi → dulu <img> tak terbatasi & render seukuran aslinya
   (foto kamera jadi raksasa). Dikunci di sini (bukan Tailwind) supaya pasti. */
.pd-thumb { width: 3.5rem; height: 3.5rem; flex: 0 0 auto; }
img.pd-thumb { object-fit: cover; }

/* Deretan foto SEBARIS (kartu papan, sel tabel). `img` di preflight Tailwind
   ber-display:block, jadi dua thumbnail dalam satu <p> berdiri sendiri-sendiri
   dan menaikkan tinggi tiap baris. Flex yang merapatkannya. */
/* Bilah aksi massal LENGKET di tepi atas area gulir (owner 8 Sep 2026:
   "saya mau ceklis Pembelian dibayar Kas Kecil tapi tombol ganti sekaligusnya
   terlalu di atas"). Kotak centang kini tersebar di TIGA tempat pada satu
   halaman — papan, tabel pengeluaran, tabel pembelian — dan yang paling bawah
   berjarak beberapa layar dari tombolnya. Lengket menyelesaikan ketiganya
   sekaligus tanpa menggandakan tombol.
   Wadah gulirnya <main> di index.html, jadi `top:0` menempel di tepi atas
   panel — bukan di tepi jendela. Latarnya WAJIB pekat: isi halaman lewat di
   bawahnya. */
.bulk-sticky {
  position: sticky;
  top: 0;
  z-index: 20;
  box-shadow: 0 2px 10px rgba(15, 23, 42, 0.10);
}

.sd-thumb-row { display: flex; flex-wrap: nowrap; align-items: center; gap: 0.375rem; }
/* Yang jadi item flex adalah <a>-nya, bukan img. Tanpa aturan ini <a> boleh
   menyusut (flex-shrink bawaan 1) di sel tabel yang sempit sementara img di
   dalamnya tetap 3,5rem — hasilnya kedua foto SALING MENUMPUK, dan itu terlihat
   seperti satu foto rusak, bukan seperti kolom yang kurang lebar. */
.sd-thumb-row > a { flex: 0 0 auto; display: block; }
/* "+N" di ujung deretan foto: sisa foto yang tak muat di kartu. Ia TAUTAN
   (bukan hiasan) — mengkliknya membuka overlay yang sama, jadi foto ke-4 dan
   seterusnya tetap bisa diperiksa. Ukurannya disamakan dengan `.pd-thumb`
   supaya barisnya tak berubah tinggi. */
.sd-thumb-lebih {
  flex: 0 0 auto;
  width: 2rem; height: 3.5rem;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.6875rem; font-weight: 700; line-height: 1;
  color: #4f46e5; background: #eef2ff;
  border: 1px solid #c7d2fe; border-radius: 0.5rem;
  text-decoration: none; cursor: pointer;
}
.sd-thumb-lebih:hover { background: #e0e7ff; }

/* Overlay foto: BERDAMPINGAN di layar besar, ATAS-BAWAH di layar kecil.
   Ambang 768px sama dengan yang dipakai kartu detail lain.
   Batas tingginya dibagi saat ada dua foto — kalau tidak, dua foto setinggi
   88vh saling dorong keluar layar dan yang kedua tak pernah terlihat.

   TIGA FOTO ATAU LEBIH (`.sd-zoom-banyak`, 30 Sep 2026). Sampai hari itu
   tinggi gambar HANYA diatur untuk `data-n="1"` dan `"2"`. Pada tiga foto atau
   lebih tak ada batas sama sekali, jadi flexbox kolom yang dibatasi 90vh
   MENYUSUTKAN tiap item sampai fotonya jadi serpihan selebar ~100px — nota
   yang tak mungkin dibaca — dan yang tak muat terpotong tepi layar tanpa bisa
   digulir. Owner melaporkannya dari iPhone di /petty-cash dengan 5 foto;
   `thumbRow` memang bisa membuka 13 sekaligus.

   DUA hal yang membuatnya bisa digulir, dan keduanya wajib:
     1. `flex: 0 0 auto` pada itemnya — tanpa itu flexbox tetap menyusutkan
        isinya agar "muat", dan tak pernah ada yang meluber untuk digulir;
     2. `justify-content: flex-start` saat menggulir. Dengan `center`, isi yang
        lebih tinggi dari wadahnya terpotong di bagian ATAS dan tak bisa
        dijangkau scroll sama sekali — jebakan flexbox yang klasik, dan
        gejalanya persis "foto pertama hilang". */
.sd-zoom-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  width: 100%;
  max-width: 100%;
  max-height: 90vh;
  max-height: min(90vh, 90dvh);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* Gulir di dalam overlay tak boleh merembet menggulir halaman di belakangnya. */
  overscroll-behavior: contain;
}
.sd-zoom-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
  min-height: 0;
  margin: 0;
  flex: 0 0 auto;
}
/* Spesifisitas (0,2,0) SENGAJA: `.sd-zoom-item { display:flex }` di atas punya
   spesifisitas yang sama dengan utilitas `[hidden]`/`.hidden` dan app.css dimuat
   belakangan, jadi tanpa aturan ini menyembunyikan slot tak akan berpengaruh. */
.sd-zoom-item[hidden] { display: none; }
.sd-zoom-item img {
  max-width: 100%;
  min-height: 0;
  object-fit: contain;
  background: #fff;
}
.sd-zoom-cap { color: #e5e7eb; font-size: 12px; text-align: center; }
.sd-zoom-cap b { color: #fff; font-weight: 600; }
.sd-zoom-wrap[data-n="1"] .sd-zoom-item img { max-height: 86vh; max-height: min(86vh, 86dvh); }
.sd-zoom-wrap[data-n="2"] .sd-zoom-item img { max-height: 38vh; max-height: min(38vh, 38dvh); }
/* Galeri digulir: tiap foto tetap sebesar yang bisa dibaca, sisanya di bawah. */
.sd-zoom-wrap.sd-zoom-banyak { justify-content: flex-start; }
.sd-zoom-wrap.sd-zoom-banyak .sd-zoom-item img { max-height: 70vh; max-height: min(70vh, 70dvh); }

/* Tombol tutup. Sebelum ini SATU-SATUNYA cara menutup adalah mengetuk di mana
   pun — tak terlihat, dan di layar yang penuh foto tak ada "mana pun" yang
   aman disentuh. Posisinya absolut terhadap overlay (yang `fixed`), dan
   menghormati poni iPhone lewat safe-area. */
.sd-zoom-tutup {
  position: absolute;
  top: calc(0.5rem + env(safe-area-inset-top, 0px));
  right: calc(0.5rem + env(safe-area-inset-right, 0px));
  z-index: 1;
  width: 2.5rem;
  height: 2.5rem;
  line-height: 1;
  font-size: 1.75rem;
  color: #fff;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 9999px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.sd-zoom-tutup:hover { background: rgba(0, 0, 0, 0.8); }

@media (min-width: 768px) {
  .sd-zoom-wrap { flex-direction: row; align-items: center; }
  .sd-zoom-wrap[data-n="2"] .sd-zoom-item { max-width: 48%; }
  .sd-zoom-wrap[data-n="2"] .sd-zoom-item img { max-height: 82vh; max-height: min(82vh, 82dvh); }
  /* Di layar besar galeri banyak-foto jadi KISI yang membungkus, bukan satu
     baris panjang: `flex: 0 0 auto` di atas berarti baris tunggal akan meluber
     mendatar, dan overlay ini hanya menggulir tegak. */
  .sd-zoom-wrap.sd-zoom-banyak { flex-wrap: wrap; align-content: flex-start; }
  .sd-zoom-wrap.sd-zoom-banyak .sd-zoom-item { max-width: 48%; }
  .sd-zoom-wrap.sd-zoom-banyak .sd-zoom-item img { max-height: 40vh; max-height: min(40vh, 40dvh); }
}

/* Utilitas yang DIPAKAI halaman-halaman detail tapi TAK ADA di subset Tailwind
   pra-kompilasi (ketahuan saat penyelarasan 2026-08-01). Akibatnya selama ini:
   label baris info tanpa jarak kanan (pr-4), body menempel tepi (pb-6), tombol
   salin tanpa garis (border-indigo-100), tombol ringkasan sempit (!px-2.5). */
.pb-6 { padding-bottom: 1.5rem; }
.pr-4 { padding-right: 1rem; }
.border-indigo-100 { border-color: #e0e7ff; }
.px-2\.5 { padding-left: 0.625rem; padding-right: 0.625rem; }
.\!px-2\.5 { padding-left: 0.625rem !important; padding-right: 0.625rem !important; }
.\!py-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; }
.\!py-1\.5 { padding-top: 0.375rem !important; padding-bottom: 0.375rem !important; }

/* Tombol aksi MERUSAK yang memakai kerangka `btn-secondary` (Hapus di
   /petty-cash-detail & /setup-expense-detail, Batalkan transfer di
   /penggantian-detail, dua tombol di /partner-order-detail). Varian `!`-nya
   tak ada di subset, jadi selama ini tombol-tombol itu tampil ABU-ABU seperti
   tombol biasa — satu-satunya tanda "ini menarik uang kembali" hilang tanpa
   galat apa pun. Warna = red-700 / rose-700 Tailwind. */
.\!text-red-700 { color: #b91c1c !important; }
.\!text-rose-700 { color: #be123c !important; }
.\!text-rose-600 { color: #e11d48 !important; }

/* `text-xl` juga tak ada di subset — dipakai untuk TOTAL TRANSFER di banner
   penggantian (/petty-cash & /purchases) dan di app.js. Angka yang mestinya
   paling besar di layar selama ini tampil seukuran teks biasa, tepat di tempat
   orang membaca "berapa yang harus saya kirim". */
.text-xl { font-size: 1.25rem; line-height: 1.75rem; }

/* Overlay perbesar foto: `max-w-full`/`max-h-full`/`shadow-2xl` juga TAK ADA di
   subset, sehingga foto beresolusi tinggi MELIMPAH keluar layar saat diperbesar
   di /purchase-detail, /transfer-detail, /partner-order-detail. */
.max-w-full { max-width: 100%; }
.max-h-full { max-height: 100%; }
.shadow-2xl { box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); }

/* ── Picker Outlet PWA (baris sendiri di bawah header) ──────────────────────
   Owner 2026-08-02: di HP tombol outlet yang menumpang di header terlalu sempit.
   Dibuat baris penuh, ikut sticky menempel di bawah header, dan cukup besar
   untuk disentuh. Ditulis eksplisit (bukan kelas Tailwind) karena subset
   pra-kompilasi tak memuat semua utilitas yang dibutuhkan. */
.beli-outletbar {
  /* Menempel TEPAT di bawah header. Tinggi header = padding-atas
     max(10px, safe-area) + logo 34px + padding-bawah 10px + border 1px,
     jadi offsetnya ikut safe-area (ponsel berponi) — bukan angka tetap. */
  position: sticky; top: calc(45px + max(10px, env(safe-area-inset-top, 0px))); z-index: 25;
  background: #fff; border-bottom: 1px solid #e5e7eb;
  padding: 8px 12px;
}
.beli-outlet-btn {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px;
  padding: 10px 12px; cursor: pointer; text-align: left; color: #1f2937;
  font-size: 13.5px; font-weight: 600; min-height: 42px;
}
.beli-outlet-btn:hover { background: #f1f5f9; }
.beli-outlet-btn > .fa-store { color: #4f46e5; flex: 0 0 auto; }
.beli-outlet-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.beli-outlet-caret { color: #94a3b8; flex: 0 0 auto; font-size: 12px; }
@media (min-width: 640px) { .beli-outletbar { padding: 10px 18px; } }

/* ── Tooltip "sumber data" ──────────────────────────────────────────────────
   Dipakai untuk angka TURUNAN (dihitung ulang tiap render, tak ada di DB),
   mis. "Harga/satuan beli" di Bahan Baku. Kotaknya ditempel ke <body> dengan
   position:fixed supaya tak terpotong wadah tabel yang overflow-x:auto.
   Kelasnya ditulis di sini, BUKAN utilitas Tailwind — build Tailwind SCM
   memakai subset pra-kompilasi, kelas baru diam-diam tak bergaya. */
.src-tip-anchor {
  border-bottom: 1px dotted #9ca3af;
  cursor: help;
}
.src-tip-anchor:focus-visible { outline: 2px solid #6366f1; outline-offset: 2px; border-radius: 3px; }
.src-tip {
  position: fixed; left: 0; top: 0; z-index: 3000;
  max-width: 310px; width: max-content;
  background: #111827; color: #e5e7eb;
  font-size: 11.5px; line-height: 1.55; font-weight: 400;
  text-align: left; white-space: normal;
  padding: 9px 11px; border-radius: 9px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .28);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .12s ease;
}
.src-tip-on { opacity: 1; visibility: visible; }
.src-tip b { color: #fff; font-weight: 700; }
.src-tip-h {
  display: block; color: #fff; font-weight: 700;
  font-size: 11.5px; margin-bottom: 6px;
}
.src-tip-r { display: flex; justify-content: space-between; gap: 14px; }
.src-tip-n { color: #9ca3af; flex: 0 1 auto; }
.src-tip-sep { display: block; border-top: 1px solid #374151; margin: 6px 0; }
.src-tip-note {
  display: block; margin-top: 7px; color: #9ca3af;
  font-size: 10.5px; line-height: 1.5;
}
/* Baris pendukung di dalam tooltip: keterangan kecil di bawah sebuah nilai,
   dan peringatan bila dua sumber angka saling bertentangan. */
.src-tip-sub {
  display: block; color: #9ca3af; font-size: 10px;
  line-height: 1.45; margin: 1px 0 5px; padding-left: 2px;
}
.src-tip-warn {
  display: block; margin-top: 7px; padding: 6px 8px;
  background: rgba(180, 83, 9, .22); border-left: 2px solid #f59e0b;
  border-radius: 0 5px 5px 0; color: #fde68a;
  font-size: 10.5px; line-height: 1.5;
}
.src-tip-warn i { margin-right: 4px; }

/* ── Kanban Dashboard Operasional ───────────────────────────────────────────
   Tiga kolom (Pembelian / Transfer / Pesanan mitra). Di HP kolomnya lebih
   lebar dari layar supaya bisa di-swipe menyamping (scroll-snap); di desktop
   ketiga kolom muat berdampingan. Tinggi kolom diikat ke viewport supaya
   tumpukan kartu di dalam kolom yang scroll, bukan halaman. */
.ops-kanban {
  display: flex;
  gap: 0.75rem;
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 0.5rem;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}
/* Papan bertinggi terbatas: dipakai saat ADA ISI LAIN di bawahnya (tabel
   /petty-cash). Kolomnya sudah `overflow-y:auto` sejak awal; yang kurang cuma
   batas tinggi induknya, tanpa itu kolom tumbuh sepanjang isinya dan apa pun di
   bawah papan terdorong beberapa layar ke bawah. */
/* `hidden` (tailwind.css) kalah melawan `.ops-kanban{display:flex}` di berkas
   ini — spesifisitas sama, dan berkas ini dimuat belakangan. Tanpa aturan ini
   papan yang "disembunyikan" tetap tampil sebagai kotak kosong setinggi
   min-height-nya. Hanya menyentuh elemen yang memang membawa kelas `hidden`. */
.ops-kanban.hidden {
  display: none;
}
.ops-kanban-terbatas {
  /* 90% TINGGI LAYAR (owner 21 Sep 2026: "tambah tinggi kanban menjadi 90%
     tinggi layar"), dari 66%. `vh` lebih dulu sebagai cadangan untuk peramban
     tanpa `dvh`; `dvh` yang menang karena ia menyusut saat bilah alamat
     ponsel muncul. */
  max-height: 90vh;
  max-height: min(90vh, 90dvh);
  min-height: 16rem;
}
/* WAJIB ADA, dan ini yang mudah terlewat: batas tinggi KOLOM-nya sendiri
   (`.ops-kanban-col` di bawah) berbunyi `calc(100dvh - 11rem)`, yang baru
   mencapai 90% bila viewport >= 1760px — tak pernah. Jadi menaikkan batas
   papan di atas SAJA tak mengubah apa pun yang terlihat: yang mengikat tetap
   batas kolomnya. Dibatasi ke `.ops-kanban-terbatas` supaya kanban
   /dashboard-operasional — yang tak memakai kelas itu — tak ikut berubah. */
.ops-kanban-terbatas .ops-kanban-col {
  max-height: 90vh;
  max-height: min(90vh, 90dvh);
}
.ops-kanban-col {
  scroll-snap-align: start;
  flex: 1 0 min(85vw, 20rem);
  min-width: min(85vw, 20rem);
  max-width: 24rem;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-top-width: 4px;
  border-radius: 1rem;
  padding: 0.75rem;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06);
  display: flex;
  flex-direction: column;
  min-height: 0;
  max-height: calc(100dvh - 11rem);
}
.ops-kanban-col .ops-kanban-cards {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding-right: 0.125rem;
}
.ops-kanban-card {
  display: block;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 0.75rem;
  padding: 0.75rem;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.ops-kanban-card:hover {
  border-color: #a5b4fc;
  box-shadow: 0 1px 4px rgba(99, 102, 241, 0.12);
}
@media (min-width: 900px) {
  .ops-kanban {
    scroll-snap-type: none;
  }
  .ops-kanban-col {
    flex: 1 1 0;
    min-width: 0;
    max-width: none;
  }
}

/* Opname operasional — lembar kerja hitung fisik (blind count) */
.opn-wrap { max-width: 40rem; margin: 0 auto; padding-bottom: 1.5rem; }
.opn-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.75rem; }
.opn-title { font-size: 1.125rem; font-weight: 700; color: #111827; line-height: 1.2; }
.opn-sub { font-size: 0.8125rem; color: #6b7280; margin-top: 0.25rem; line-height: 1.4; }
.opn-tabs { display: flex; gap: 0.25rem; margin-bottom: 0.75rem; background: #f3f4f6; border-radius: 0.625rem; padding: 0.25rem; }
.opn-tab {
  flex: 1 1 0; border: 0; background: transparent; border-radius: 0.5rem;
  padding: 0.5rem 0.75rem; font-size: 0.8125rem; font-weight: 600; color: #6b7280;
}
.opn-tab[aria-selected="true"] { background: #fff; color: #111827; box-shadow: 0 1px 2px rgba(0,0,0,0.06); }
.opn-search-row { display: flex; gap: 0.5rem; align-items: stretch; }
.opn-search { width: 100%; }
.opn-scan-btn { flex: 0 0 auto; min-width: 2.75rem; }
.opn-kind {
  display: inline-block; font-size: 0.625rem; font-weight: 800; letter-spacing: 0.04em;
  border-radius: 0.25rem; padding: 0.05rem 0.35rem; vertical-align: middle; margin-right: 0.25rem;
}
.opn-kind-bb { background: #e0f2fe; color: #0369a7; }
.opn-kind-hp { background: #ede9fe; color: #6d28d9; }
.opn-kind-pr { background: #fef3c7; color: #92400e; }  /* Produk — halaman Penyesuaian Stok */
.opn-scan-overlay {
  position: fixed; inset: 0; z-index: 80; background: rgba(17, 24, 39, 0.8);
  display: flex; align-items: stretch; justify-content: center; padding: 0;
}
.opn-scan-box {
  width: min(28rem, 100%); margin: auto; background: #111827; color: #fff; border-radius: 0.75rem;
  padding: 0.75rem; display: flex; flex-direction: column; gap: 0.75rem;
}
.opn-scan-title { font-size: 0.9375rem; font-weight: 600; text-align: center; }
.opn-scan-hint { font-size: 0.75rem; color: #9ca3af; text-align: center; margin: 0; }
.opn-scan-foto { display: block; text-align: center; cursor: pointer; }
.opn-scan-reader { width: 100%; min-height: 14rem; overflow: hidden; border-radius: 0.5rem; background: #000; }
.opn-scan-reader video { width: 100% !important; height: auto !important; object-fit: cover; }
.opn-scan-lock { overflow: hidden; }
@media (max-width: 640px) {
  .opn-scan-overlay { padding: 0; }
  .opn-scan-box {
    width: 100%; height: 100%; max-width: none; margin: 0; border-radius: 0;
    padding: 0.75rem 0.75rem calc(0.75rem + env(safe-area-inset-bottom));
  }
  .opn-scan-reader { flex: 1 1 auto; min-height: 0; display: flex; align-items: center; }
}
.opn-filters { display: flex; flex-wrap: wrap; gap: 0.375rem; margin-bottom: 0.75rem; }
.opn-chip {
  border: 1px solid #e5e7eb; background: #fff; border-radius: 9999px;
  padding: 0.375rem 0.75rem; font-size: 0.75rem; font-weight: 600; color: #4b5563;
}
.opn-chip.is-on { border-color: #4f46e5; background: #eef2ff; color: #3730a3; }
.opn-list { display: flex; flex-direction: column; gap: 0.5rem; }
.opn-card {
  display: grid; grid-template-columns: 3.5rem 1fr auto; gap: 0.625rem; align-items: center;
  border: 1px solid #e5e7eb; border-radius: 0.75rem; padding: 0.625rem; background: #fff;
}
.opn-card-done { border-color: #a7f3d0; background: #f0fdf4; }
.opn-card-img { width: 3.5rem; height: 3.5rem; object-fit: cover; border-radius: 0.5rem; background: #f3f4f6; }
.opn-card-noimg { display: flex; align-items: center; justify-content: center; color: #d1d5db; }
.opn-card-name { font-size: 0.875rem; font-weight: 600; color: #111827; line-height: 1.3; }
.opn-card-meta { font-size: 0.6875rem; color: #9ca3af; margin-top: 0.125rem; }
.opn-card-hasil { font-size: 0.6875rem; font-weight: 600; margin-top: 0.25rem; line-height: 1.35; }
.opn-card-btn { flex: 0 0 auto; font-size: 0.75rem; padding: 0.5rem 0.75rem; white-space: nowrap; }
.opn-badge {
  display: inline-block; margin-top: 0.25rem; margin-right: 0.25rem;
  font-size: 0.625rem; font-weight: 700; border-radius: 9999px;
  padding: 0.125rem 0.5rem; background: #f3f4f6; color: #6b7280;
}
.opn-badge-telat { background: #fef3c7; color: #92400e; }
.opn-badge-aman { background: #ecfdf5; color: #047857; }
.opn-empty {
  text-align: center; padding: 2rem 1rem; color: #6b7280; font-size: 0.875rem; line-height: 1.45;
}
.opn-empty i { display: block; font-size: 1.5rem; color: #d1d5db; margin-bottom: 0.5rem; }
.opn-blind-note {
  font-size: 0.75rem; line-height: 1.45; color: #3730a3;
  background: #eef2ff; border: 1px solid #c7d2fe; border-radius: 0.5rem; padding: 0.625rem 0.75rem;
}
.opn-blind-img { width: 100%; max-height: 8rem; object-fit: contain; border-radius: 0.5rem; background: #f9fafb; margin: 0.5rem 0; }
.opn-blind-sku { font-size: 0.75rem; color: #6b7280; margin: 0.25rem 0 0.75rem; }
.opn-hint { font-size: 0.6875rem; color: #9ca3af; margin-top: 0.25rem; line-height: 1.4; }
.opn-stepper { display: flex; align-items: stretch; gap: 0.5rem; }
.opn-step {
  flex: 0 0 3rem; border: 1px solid #e5e7eb; border-radius: 0.5rem; background: #f9fafb;
  font-size: 1.5rem; font-weight: 600; color: #374151;
}
.opn-qty { flex: 1 1 0; text-align: center; font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; height: 3.25rem; }
.opn-hasil-nama { font-size: 1rem; font-weight: 700; color: #111827; margin-bottom: 0.75rem; }
.opn-hasil-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.5rem; margin-bottom: 0.75rem; }
.opn-hasil-grid-sm { margin: 0.5rem 0; }
.opn-hasil-grid dt { font-size: 0.625rem; text-transform: uppercase; letter-spacing: 0.04em; color: #9ca3af; }
.opn-hasil-grid dd { font-size: 0.9375rem; font-weight: 700; color: #111827; }
.opn-diff-min { color: #b91c1c !important; }
.opn-diff-plus { color: #047857 !important; }
.opn-diff-ok { color: #6b7280 !important; }
.opn-hist { display: flex; flex-direction: column; gap: 0.5rem; }
.opn-hist-card { border: 1px solid #e5e7eb; border-radius: 0.75rem; padding: 0.75rem; background: #fff; }
.opn-hist-top { display: flex; justify-content: space-between; gap: 0.5rem; align-items: baseline; font-size: 0.8125rem; }
.opn-hist-top span { font-size: 0.6875rem; color: #9ca3af; white-space: nowrap; }
.opn-hist-who { font-size: 0.6875rem; color: #6b7280; margin-top: 0.125rem; }
.opn-hist-note { font-size: 0.75rem; color: #6b7280; margin-top: 0.25rem; }
.opn-hist-foto { color: #4f46e5; font-weight: 600; }
@media (max-width: 480px) {
  .opn-card { grid-template-columns: 2.75rem 1fr auto; gap: 0.5rem; padding: 0.5rem; }
  .opn-card-img { width: 2.75rem; height: 2.75rem; }
  .opn-card-btn { font-size: 0.6875rem; padding: 0.4375rem 0.625rem; }
}

/* ── Pengeluaran Rutin (2026-08-23) ────────────────────────────────────────
   Ditulis sebagai KOMPONEN, bukan rangkaian utilitas Tailwind: `tailwind.css`
   di sini adalah SUBSET, dan utilitas yang dibutuhkan lencana/tab ini
   (-top-1, -right-1, min-w-[1.1rem], border-b-2, border-indigo-600,
   border-transparent, bg-rose-600) TIDAK ADA di dalamnya — memakainya berarti
   gaya hilang diam-diam tanpa galat apa pun. Nama ber-awalan scm- supaya tak
   bertabrakan dengan utilitas mana pun. */
.scm-jt-badge {
  position: absolute;
  top: -0.25rem;
  right: -0.25rem;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 0.25rem;
  border-radius: 9999px;
  background: #e11d48;          /* rose-600 */
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 1.1rem;
  text-align: center;
}
/* Lencana kuning bila belum ada yang telat — mendesak, tapi belum merah. */
.scm-jt-badge.scm-jt-akan { background: #d97706; }  /* amber-600 */

.scm-tab {
  padding: 0.5rem 0.75rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: #6b7280;
  border-bottom: 2px solid transparent;
  background: none;
}
.scm-tab-aktif { color: #4338ca; border-bottom-color: #4f46e5; }
.scm-nonaktif { opacity: 0.5; }

/* Angka yang bisa diklik pada tabel Dashboard Gudang (2026-08-24).
   Komponen, bukan rangkaian utilitas: `underline`, `decoration-dotted`,
   `underline-offset-2`, dan `hover:opacity-70` tak ada di subset tailwind.css
   yang di-build — memakainya berarti angkanya terlihat biasa saja dan pengguna
   tak pernah tahu itu bisa diklik. Warna diwarisi dari sel supaya kode warna
   status (hijau/kuning/merah) tetap terbaca. */
.scm-drill {
  color: inherit;
  font: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  /* Dipakai juga sebagai <a> sejak /cash-accounts (20 Sep 2026): tanpa ini
     peramban menambah garis bawahnya sendiri DI ATAS border titik-titik. */
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
}
.scm-drill:hover { opacity: 0.65; }

/* Ceklis outlet pada tabel Dashboard Gudang (2026-08-24). Ditaruh DI DALAM sel
   Outlet, bukan sebagai kolom baru: kolom pertama itu sticky left-0, dan
   menyisipkan kolom di depannya menggeser offset lengketnya. */
.scm-cek {
  vertical-align: baseline;
  margin-right: 0.4rem;
  cursor: pointer;
  accent-color: #4f46e5;
}

/* Pita kartu KPI Dashboard Supply Chain (2026-08-27).
   Ditulis di sini, BUKAN mengandalkan Tailwind: `tailwind.css` adalah subset
   pra-kompilasi tanpa build step, dan tak ada aturan apa pun yang menyasar
   641–767px — zona mati antara batas `.scm-dense` (640px) dan prefix `md:`
   (768px). Tanpa aturan ini, di lebar tablet kecil kartu tetap 2 kolom
   sementara tipografi & padding sudah kembali ke ukuran desktop. */
@media (min-width: 641px) and (max-width: 767.98px) {
  .scm-kpi-band { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Tombol "sumber" di kartu KPI (owner 24 Sep 2026).
   Menggantikan pola "SELURUH kartu adalah tautan": tautan selebar kartu tak
   pernah terlihat sebagai tautan, jadi drill-down-nya tak pernah ditemukan
   orang. Tombol kecil ini juga satu-satunya cara memasang tautan di kartu yang
   isinya sudah memuat tautan/tooltip — <a> di dalam <a> tidak sah di HTML.
   Ditaruh di kanan-bawah kartu, di luar alur teks, supaya tak menggeser angka. */
.scm-kpi-src {
  position: absolute;
  right: .5rem;
  bottom: .4rem;
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  font-size: 10px;
  line-height: 1;
  padding: .2rem .4rem;
  border-radius: 9999px;
  color: #4f46e5;
  background: #eef2ff;
  border: 1px solid #e0e7ff;
  white-space: nowrap;
  transition: background-color .12s, color .12s, border-color .12s;
}
.scm-kpi-src:hover {
  background: #4f46e5;
  border-color: #4f46e5;
  color: #fff;
}
/* Kartu yang punya tombol sumber butuh ruang bawah supaya tombolnya tak
   menimpa sub-teks, dan `position: relative` supaya penempatannya mengikat. */
.panel-card.scm-kpi-ada-src {
  position: relative;
  padding-bottom: 1.6rem;
}

/* Strip "Sumber data" per halaman — dipindahkan dari modul CRM
   (2026-08-27). Struktur & kelasnya sengaja sama supaya kedua modul
   terbaca sebagai satu produk; hanya warna dasarnya digeser dari ungu CRM
   ke indigo SCM. Berbeda dari .src-tip* di atas: itu tooltip per ANGKA,
   ini keterangan per HALAMAN. */
.src-note {
  background: #f5f7ff;
  border: 1px solid #e0e7ff;
  border-radius: 0.625rem;
  /* Margin ATAS, bukan bawah: stripnya pindah ke bawah panel (owner 24 Sep
     2026), jadi jaraknya dibutuhkan terhadap isi panel di atasnya. Dibiarkan
     `margin-bottom` akan membuatnya menempel pada panel dan menyisakan ruang
     kosong di ujung halaman. */
  margin-top: 0.75rem;
  overflow: hidden;
}

.src-note-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.45rem 0.7rem;
  background: transparent;
  border: 0;
  cursor: pointer;
  text-align: left;
  font-size: 0.75rem;
  line-height: 1.35;
  color: #5b21b6;
}

.src-note-head:hover {
  background: #f5f0ff;
}

.src-note-icon {
  flex: 0 0 auto;
  color: #7c3aed;
}

.src-note-ringkas {
  flex: 1 1 auto;
  min-width: 0;
  color: #4c1d95;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.src-note-lead {
  font-weight: 600;
}

.src-note-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-weight: 600;
  color: #7c3aed;
  white-space: nowrap;
}

.src-note-toggle .fa-chevron-down {
  transition: transform 0.15s ease;
  font-size: 0.65rem;
}

.src-note-head[aria-expanded="true"] .fa-chevron-down {
  transform: rotate(180deg);
}

.src-note-body {
  background: #fff;
  border-top: 1px solid #e0e7ff;
  padding: 0.55rem 0.7rem 0.65rem;
  font-size: 0.75rem;
  line-height: 1.5;
  color: #334155;
}

.src-note-row {
  display: flex;
  gap: 0.75rem;
  padding: 0.28rem 0;
}

.src-note-row + .src-note-row {
  border-top: 1px dashed #f1f5f9;
}

.src-note-label {
  flex: 0 0 9.5rem;
  font-weight: 600;
  color: #6d28d9;
}

.src-note-value {
  flex: 1 1 auto;
  min-width: 0;
}

.src-note-value p {
  margin: 0;
}

/* Tailwind preflight menghapus bullet & indentasi bawaan <ul> — dikembalikan
   di sini supaya daftar "dari mana asalnya" tetap terbaca sebagai daftar. */
.src-note-list {
  margin: 0;
  padding-left: 1.05rem;
  list-style: disc;
}

.src-note-list li {
  margin: 0.12rem 0;
}

@media (max-width: 640px) {
  .src-note-row {
    flex-direction: column;
    gap: 0.15rem;
  }
  .src-note-label {
    flex: none;
  }
}

/* Sparkline batang Dashboard Supply Chain (2026-08-27).
   CSS murni, bukan Chart.js: satu grafik kecil di halaman PENDARATAN tak
   sepadan dengan ongkos memuat pustaka grafik saat tampilan pertama. Pola sama
   dengan bar Payment Mix di Dashboard Kasir. */
.scm-spark {
  display: flex;
  align-items: flex-end;
  gap: 1px;
  height: 22px;
  margin: 0.25rem 0 0.35rem;
}
.scm-spark-b {
  flex: 1 1 0;
  min-width: 1px;
  background: #c7d2fe;
  border-radius: 1px 1px 0 0;
  transition: background 0.12s;
}
.scm-spark-b:hover { background: var(--scm-accent); }

/* Pemilih rentang di toolbar Dashboard Supply Chain. `dateRangeField` dibuat
   untuk baris filter selebar halaman (isinya flex-1), jadi di toolbar yang
   padat ia melebar dan mendorong tombol Muat ke baris sendiri. Dikurung di
   sini, bukan diubah di helper-nya — helper itu dipakai belasan panel lain
   yang justru mengandalkan perilaku melebar. */
.scm-dash-range { display: inline-flex; width: 11.5rem; flex: none; }
.scm-dash-range > .field-input { width: 100%; }

/* Halaman Penyesuaian Stok. Sisanya (kartu, pencarian, overlay scan) memang
   sengaja memakai kelas .opn-* milik Opname — dua layar ini kembar bentuknya.
   Prefiks .pys-* dipakai HANYA untuk yang khas halaman ini: .opn-card-done
   sudah terpakai Opname (kartu hijau "sudah dihitung"), jadi nama itu tak boleh
   dipinjam ulang dengan arti lain. */
.pys-done {
  font-size: 0.75rem; color: #4b5563; background: #f9fafb;
  border: 1px solid #e5e7eb; border-radius: 0.375rem;
  padding: 0.375rem 0.5rem; margin-bottom: 0.25rem;
}
.pys-head { margin-bottom: 0.5rem; }

/* Umur hitungan fisik di kartu — inti urutan halaman ini (paling lama belum
   diopname di paling atas), jadi ia diberi warna supaya urutannya terbaca
   sekilas, bukan cuma tersirat dari posisi. Netral (abu) = baru dihitung,
   kuning = sudah lama, merah = belum pernah sama sekali. */
.pys-umur { display: inline-block; font-size: 0.6875rem; line-height: 1.25;
  padding: 0.0625rem 0.375rem; border-radius: 9999px;
  background: #f3f4f6; color: #6b7280; }
.pys-umur-lama { background: #fef3c7; color: #92400e; }
.pys-umur-never { background: #fee2e2; color: #991b1b; font-weight: 600; }

/* Kaki daftar: total + tombol muat lagi. */
.pys-kaki { display: flex; align-items: center; justify-content: space-between;
  gap: 0.5rem; flex-wrap: wrap; margin-top: 0.75rem; }
.pys-kaki-info { font-size: 0.6875rem; color: #9ca3af; }

/* ── Halaman Manajemen Rekening & Kas ──────────────────────────────────────
   Prefiks .ca-* khusus halaman ini. Gambar QRIS diberi bingkai berukuran tetap
   supaya modal tak melompat tingginya saat gambar dipilih — QRIS yang difoto
   pakai HP rasionya bermacam-macam, dan tanpa kotak tetap tombol di bawahnya
   berpindah tempat tepat saat orang hendak menekannya. */
.ca-qris { display: flex; gap: 0.75rem; align-items: flex-start; }
.ca-qris-prev {
  width: 6.5rem; height: 6.5rem; flex: 0 0 auto;
  border: 1px solid #e5e7eb; border-radius: 0.5rem; background: #f9fafb;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.ca-qris-prev img { max-width: 100%; max-height: 100%; object-fit: contain; }
.ca-qris-kosong {
  display: flex; flex-direction: column; align-items: center; gap: 0.25rem;
  font-size: 0.6875rem; color: #9ca3af;
}
.ca-qris-kosong i { font-size: 1.5rem; }
.ca-qris-aksi { flex: 1 1 auto; min-width: 0; }

/* Bilah saringan + ringkasan di atas tabel. */
.ca-tools { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem; margin-bottom: 0.75rem; }
.ca-tools .field-input { min-width: 0; }
.ca-ringkas { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.75rem; }
.ca-kartu {
  flex: 1 1 10rem; border: 1px solid #e5e7eb; border-radius: 0.75rem;
  background: #fff; padding: 0.5rem 0.75rem;
}
.ca-kartu dt { font-size: 0.6875rem; color: #6b7280; }
.ca-kartu dd { font-size: 1rem; font-weight: 700; color: #111827; margin: 0; }

/* Lencana peringatan di kolom Etalase: rekening QRIS yang tampil ke pembeli
   tapi tak punya gambar untuk dipindai. */
.ca-qris-mini { width: 1.5rem; height: 1.5rem; border-radius: 0.25rem; object-fit: cover;
  border: 1px solid #e5e7eb; vertical-align: middle; }
.ca-warn {
  display: inline-block; font-size: 0.625rem; font-weight: 600;
  padding: 0.0625rem 0.375rem; border-radius: 9999px;
  background: #fee2e2; color: #991b1b;
}

/* ── Setoran Bank: baris harian jadi KARTU di HP ───────────────────────────
   Tabel harian punya 7 kolom. Di HP itu berarti menggeser layar ke samping
   hanya untuk sampai ke tombol Unggah — padahal mengunggah bukti justru
   satu-satunya hal yang dikerjakan petugas di halaman ini, berulang tiap hari,
   dan hampir selalu dari HP. Di bawah 640px tiap <tr> dilipat jadi kartu:
   label kolom pindah ke `td::before` lewat data-label, tanggal+outlet jadi
   judul, dan barisan aksi duduk penuh di dasar kartu.

   Satu jalur render untuk kedua tampilan — JS-nya tetap memancarkan tabel yang
   sama, yang berubah hanya CSS. Karena itu tak ada cabang "kalau mobile" di
   panelnya yang bisa basi sendiri.

   Selektor sengaja memakai `.data-table.sb-harian-tabel` (bukan
   `.sb-harian-tabel` saja) supaya menang telak atas aturan `.scm-dense
   .data-table ...` di blok kepadatan atas — bukan menang tipis karena urutan
   berkas, yang akan patah diam-diam kalau blok itu dipindah. */
/* Lencana nomor shift di sel tanggal, dan penanda shift yang masih berjalan.
   Baris terkunci sengaja dibuat REDUP, bukan disembunyikan: management tetap
   perlu tahu shift itu ada & sedang berjalan, yang ditahan hanya angkanya. */
.sb-shift {
  display: inline-block; margin-left: 0.4rem; padding: 0.05rem 0.4rem;
  border-radius: 9999px; background: #eef2ff; color: #4338ca;
  font-size: 0.6875rem; font-weight: 600; vertical-align: middle;
}
.sb-kasir { color: #94a3b8; font-size: 0.6875rem; font-weight: 400; margin-left: 0.4rem; }
/* Nota "Sudah disetor" di kolom Setor memakai gaya yang SAMA dengan nota
   shift-terkunci: dua-duanya berarti "tak ada yang perlu kamu kerjakan di
   baris ini". Sengaja REDUP, bukan hijau — hijaunya sudah dipakai lencana
   "Lunas" di kolom Kurang Setor, dan dua tanda hijau di satu baris membuat
   mata mencari beda yang tak ada. */
.sb-terkunci-nota,
.sb-lunas-nota {
  display: inline-flex; align-items: center; gap: 0.3rem;
  color: #94a3b8; font-size: 0.75rem; font-weight: 500; white-space: nowrap;
}
.sb-harian-tabel tbody tr.sb-terkunci { background: #fafafa; }
.sb-harian-tabel tbody tr.sb-terkunci .sb-sel-tgl,
.sb-harian-tabel tbody tr.sb-terkunci .sb-sel-outlet { color: #94a3b8; }

/* ── Keadaan baris: warna tepi + lencana ───────────────────────────────────
   Owner 13 Sep 2026: "perjelas status setiap kartu bisa dengan membedakan
   warna bordernya ada yang sudah disetor, ditolak, menunggu konfirmasi,
   kurang setor dll".

   Warnanya dipakai DUA kali dalam bentuk berbeda, dari satu kelas `sb-stb-*`
   di <tr>: aksen kiri pada tabel desktop, dan tepi kartu di HP (blok
   @media di bawah). Satu sumber, jadi kedua tampilan tak bisa berbeda
   pendapat tentang warna sebuah baris.

   MERAH DIPAKAI SATU KEADAAN SAJA: "Ditolak". Versi pertama blok ini memberi
   merah kepada belum-setor, kurang-setor, DAN ditolak sekaligus — dan saat
   dilihat di layar, tiga dari empat kartu pertama berpinggir merah semua,
   persis dua hal yang justru diminta owner untuk dibedakan. Kekurangan setor
   kini JINGGA; merah tinggal menandai satu-satunya keadaan yang menuntut
   pekerjaan berbeda (mengunggah ULANG bukti, bukan menyetor lagi).

   "Belum setor" dan "Kurang setor" tetap berbagi jingga: bagi pembacanya
   artinya sama — uang tunai belum sampai bank. Yang berbeda cuma ceritanya,
   dan cerita itu sudah ada di lencananya. Menambah rona keenam untuk perbedaan
   yang tak mengubah pekerjaan hanya memaksa mata membandingkan warna.

   "Ditolak" ikut memakai GARIS PUTUS-PUTUS, jadi ia tak bergantung pada warna
   sendirian: ~8% laki-laki sulit memisahkan merah dari jingga/hijau, dan di
   halaman pencegahan kecurangan itu bukan detail yang bisa ditunda.
   Putus-putus juga kebetulan pas maknanya — ada rantai yang terputus dan harus
   disambung ulang. Shift berjalan ikut putus-putus dengan alasan sejenis:
   barisnya memang belum utuh.

   Tiap baris SELALU punya keadaan, termasuk `nihil` ("Tanpa kas"). Baris tanpa
   aksen akan terbaca sebagai baris yang lupa diberi status, dan itu persis
   keraguan yang seharusnya dihapus halaman ini. */
.sb-st-chip {
  display: inline-block; margin-left: 0.4rem; padding: 0.05rem 0.45rem;
  border-radius: 9999px; font-size: 0.6875rem; font-weight: 600;
  vertical-align: middle; white-space: nowrap;
}
.sb-st-berjalan { background: #f1f5f9; color: #64748b; }
.sb-st-nihil    { background: #f1f5f9; color: #94a3b8; }
.sb-st-ditolak  { background: #fee2e2; color: #b91c1c; }
.sb-st-belum,
.sb-st-kurang   { background: #ffedd5; color: #c2410c; }
.sb-st-menunggu { background: #fef3c7; color: #b45309; }
.sb-st-lebih    { background: #e0e7ff; color: #4338ca; }
.sb-st-masuk    { background: #d1fae5; color: #047857; }

/* Aksen kiri di TABEL (desktop). `box-shadow: inset`, bukan `border-left`:
   tabelnya `border-collapse: collapse`, dan border pada sel ikut dilebur
   dengan tetangganya sehingga tebalnya berubah-ubah menurut baris di atas/
   bawahnya. Bayangan inset tak ikut aturan peleburan itu — tebalnya tetap
   3px di setiap baris. */
.sb-harian-tabel tbody tr.sb-st-baris > td:first-child {
  box-shadow: inset 3px 0 0 var(--sb-st, transparent);
}
/* `--sb-st` = rona PEKAT untuk aksen/tepi kiri; `--sb-st-muda` = rona samar
   untuk tiga sisi kartu yang lain di HP. Kartu yang keempat sisinya pekat
   berteriak sekeras isinya, dan sepuluh kartu berteriak bersama sama saja
   dengan tak satu pun menonjol. */
.sb-stb-berjalan { --sb-st: #cbd5e1; --sb-st-muda: #e2e8f0; }
.sb-stb-nihil    { --sb-st: #e2e8f0; --sb-st-muda: #e5e7eb; }
.sb-stb-ditolak  { --sb-st: #dc2626; --sb-st-muda: #fecaca; }
.sb-stb-belum    { --sb-st: #ea580c; --sb-st-muda: #fed7aa; }
.sb-stb-kurang   { --sb-st: #ea580c; --sb-st-muda: #fed7aa; }
.sb-stb-menunggu { --sb-st: #f59e0b; --sb-st-muda: #fde68a; }
.sb-stb-lebih    { --sb-st: #6366f1; --sb-st-muda: #c7d2fe; }
.sb-stb-masuk    { --sb-st: #10b981; --sb-st-muda: #a7f3d0; }
/* Yang putus-putus tak bisa dibuat dari box-shadow; di desktop ia dibuat dari
   dua garis pendek yang berulang (gradien), memberi kesan garis terputus pada
   lebar 3px yang sama. */
.sb-harian-tabel tbody tr.sb-stb-ditolak > td:first-child,
.sb-harian-tabel tbody tr.sb-stb-berjalan > td:first-child {
  box-shadow: none;
  background-image: linear-gradient(var(--sb-st) 60%, transparent 60%);
  background-size: 3px 8px;
  background-repeat: repeat-y;
  background-position: left top;
}

.sb-bukti-mini { width: 2rem; height: 2rem; }

/* Bukti setoran dibuka sebagai PRATINJAU di halaman yang sama, bukan tab baru
   (owner 12 Sep 2026). Pemicunya kini <button>, bukan <a>, jadi chrome tombol
   bawaan peramban harus dilucuti sendiri — jangan bergantung pada preflight
   Tailwind, berkas ini memakai subset yang dibangun sebelumnya. */
.sb-bukti-btn {
  padding: 0; border: 0; background: none; line-height: 0;
  display: inline-flex; cursor: zoom-in;
}
.sb-bukti-lain,
.sb-tautan-bukti { padding: 0; border: 0; background: none; cursor: pointer; }
.sb-bukti-lain:hover,
.sb-tautan-bukti:hover { text-decoration: underline; }

.sb-pratinjau { display: flex; flex-direction: column; gap: 1.25rem; }
.sb-pratinjau-nota { font-size: 0.6875rem; color: #94a3b8; margin-bottom: 0.25rem; }
/* Tingginya dibatasi `rem`, SENGAJA bukan `vh`: lihat catatan iOS Safari di
   .modal-panel — `vh` di sana mengacu ke viewport besar, dan gambar setinggi
   itu mendorong isi modal keluar dari area yang benar-benar terlihat. Slip
   setoran umumnya potret; `contain` menjaga nominalnya tetap utuh terbaca
   walau kotaknya lebar. */
.sb-pratinjau-gbr {
  display: block; width: 100%; max-height: 30rem; object-fit: contain;
  border-radius: 0.5rem; background: #f1f5f9; cursor: zoom-in;
}
/* Diperbesar = batas tinggi dilepas, lebarnya tetap terkurung modal sehingga
   tak pernah ada geser mendatar; yang memanjang ke bawah digulir modal-body. */
.sb-pratinjau-item.diperbesar .sb-pratinjau-gbr { max-height: none; cursor: zoom-out; }
.sb-pratinjau-ket {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  margin-top: 0.5rem; font-size: 0.75rem;
}
/* Foto yang tadi diklik ditandai — galeri berisi lima slip jangan sampai
   membuat orang kehilangan yang ia tunjuk. */
.sb-pratinjau-sorot .sb-pratinjau-gbr { outline: 2px solid #6366f1; outline-offset: 2px; }
/* Setoran TANPA foto tetap punya kotaknya sendiri di pratinjau — sejak semua
   tombol aksi pindah ke sini (owner 12 Sep 2026), menyembunyikannya berarti
   setoran itu kehilangan satu-satunya pintu ke aksinya. Kotak putus-putus,
   bukan kosong: "tak ada bukti" adalah keterangan yang perlu dibaca sebelum
   memutuskan, bukan ketiadaan yang boleh lewat tanpa disadari. */
.sb-pratinjau-nofoto {
  display: flex; align-items: center; justify-content: center; gap: 0.4rem;
  min-height: 7rem; padding: 1rem; text-align: center;
  border: 1px dashed #cbd5e1; border-radius: 0.5rem;
  background: #f8fafc; color: #94a3b8; font-size: 0.8125rem;
}
/* Baris tombol aksi milik SATU setoran, menempel di bawah buktinya sendiri —
   di galeri berisi tiga slip, tombol yang melayang tanpa induk akan
   mengonfirmasi setoran yang salah. */
.sb-pratinjau-aksi { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.6rem; }
/* Footer pratinjau memuat tombol aksi DAN Tutup dalam satu baris. Ia wajib
   boleh melipat: .modal-footer bawaan `flex` tanpa wrap, dan lima tombol di
   layar 360px akan mendorong yang paling kanan keluar panel. Di-scope lewat
   kelas `sb-modal-bukti` yang dititipkan via parameter `size` — 66 modal lain
   sengaja tidak ikut berubah. */
.modal-panel.sb-modal-bukti .modal-footer { flex-wrap: wrap; }
/* Nilai + anak-keterangannya ("+Rp… menunggu") dibungkus jadi SATU item flex.
   Tanpa pembungkus ini keduanya jadi dua item terpisah yang dilempar
   space-between ke ujung kartu yang berlawanan. */
.sb-nilai { display: inline-block; }
.sb-aksi { display: inline-flex; align-items: center; justify-content: flex-end; gap: 0.25rem; }
.sb-amt { width: 7.5rem; }
.sb-setelan-baris { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem; }
.sb-setelan-medan { min-width: 11rem; }
.sb-setelan-medan:first-child { min-width: 13rem; }
.sb-setelan-nota { flex: 1 1 12rem; min-width: 12rem; }

@media (max-width: 640px) {
  /* Kartu ringkasan: 2 kolom di HP, jadi "Rp139.662.000" pada 18px melimpah
     keluar kotaknya. Angkanya diperkecil & padding dipangkas — bukan dibuat
     mengecil sendiri (text-overflow), karena nominal yang terpotong lebih buruk
     daripada nominal yang kecil. */
  .scm-dense .sb-kartu { padding: 0.5rem 0.6rem; }
  .scm-dense .sb-kartu-label { font-size: 0.625rem; }
  .scm-dense .sb-kartu-nilai { font-size: 0.875rem; margin-top: 0.15rem; }

  /* Setelan unggah cepat: dua medan penuh selebar layar, tumpuk. Notanya
     dibuang di HP — isinya sudah terbaca dari label medannya sendiri, dan di
     layar sempit ia cuma mendorong tabel turun. */
  .scm-dense .sb-setelan-medan,
  .scm-dense .sb-setelan-medan:first-child { flex: 1 1 100%; min-width: 0; }
  .scm-dense .sb-setelan-nota { display: none; }

  .scm-dense .data-table.sb-harian-tabel,
  .scm-dense .data-table.sb-harian-tabel tbody,
  .scm-dense .data-table.sb-harian-tabel tbody tr,
  .scm-dense .data-table.sb-harian-tabel tbody td { display: block; width: 100%; }
  .scm-dense .data-table.sb-harian-tabel thead { display: none; }

  /* JEBAKAN (sama jenisnya dgn .btn-secondary.hidden di atas): aturan
     `display:block` barusan spesifisitasnya jauh di atas `.hidden` bawaan
     Tailwind (0,1,0), jadi TANPA baris ini baris rincian yang mestinya
     terlipat akan selalu terbuka di HP. */
  .scm-dense .data-table.sb-harian-tabel tbody tr.hidden { display: none; }

  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari {
    display: flex; flex-wrap: wrap;
    border: 1px solid #e5e7eb; border-radius: 0.6rem; background: #fff;
    padding: 0.5rem 0.65rem; margin-bottom: 0.6rem;
  }

  /* TEPI KARTU = keadaan barisnya (owner 13 Sep 2026). Tepi kiri tebal & pekat
     supaya sederet kartu bisa dipindai menurun hanya dengan melihat pinggir
     kiri layar; tiga sisi lain memakai rona MUDA agar kartunya tetap tenang.

     Aksen desktop (`box-shadow`/gradien di td pertama) DIMATIKAN di sini —
     kalau tidak, garis kedua akan muncul DI DALAM kartu, sejajar dengan tepi
     kartunya sendiri, dan terbaca sebagai dua status yang berbeda. */
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari.sb-st-baris {
    border-color: var(--sb-st-muda, #e5e7eb);
    border-left-color: var(--sb-st, #e5e7eb);
    border-left-width: 4px;
  }
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-stb-ditolak,
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-stb-berjalan {
    border-left-style: dashed;
  }
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-st-baris > td:first-child {
    box-shadow: none;
    background-image: none;
  }

  /* Judul kartu kini memuat lencana keadaan di samping nomor shift, jadi ia
     harus boleh turun baris — tanpa ini lencananya terdorong keluar kartu di
     layar tersempit. */
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-tgl {
    flex-wrap: wrap;
  }
  .scm-dense .data-table.sb-harian-tabel tbody tr:hover { background: #fff; }
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td { flex: 1 1 100%; }

  .scm-dense .data-table.sb-harian-tabel tbody td {
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.75rem; padding: 0.22rem 0; border: 0;
    text-align: right; font-size: 0.8125rem;
  }
  .scm-dense .data-table.sb-harian-tabel tbody td::before {
    content: attr(data-label);
    color: #64748b; font-size: 0.6875rem; font-weight: 500;
    text-align: left; white-space: nowrap;
  }

  /* Judul kartu: tanggal kiri, outlet kanan, berbagi satu garis bawah.
     Selektor WAJIB lewat `tr.sb-hari >` seperti aturan flex umum di atasnya —
     tanpa itu spesifisitasnya (0,4,2) kalah dari `tr.sb-hari > td` (0,4,3) dan
     `flex-basis:100%` menang, sehingga tanggal & outlet jatuh ke baris
     masing-masing. Terukur di chromium headless 390px sebelum diperbaiki. */
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-tgl,
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-outlet {
    border-bottom: 1px solid #f1f5f9;
    padding-bottom: 0.4rem; margin-bottom: 0.35rem;
  }
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-tgl {
    flex: 1 1 100%; justify-content: flex-start; gap: 0.35rem;
    font-size: 0.9375rem; font-weight: 700; color: #111827;
    border-bottom: 0; padding-bottom: 0.1rem; margin-bottom: 0;
  }
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-tgl::before { display: none; }
  /* Outlet + kasir mendapat BARIS SENDIRI di HP, tidak lagi berdesakan di
     kanan tanggal. Sewaktu ia masih berbagi baris (max-width 55% + flex-end +
     overflow hidden), nama outlet terpotong dari KIRI begitu nama kasir ikut
     masuk — "Mizuke Panakkukang" terbaca "e Panakkukang". Membiarkannya
     membungkus jauh lebih murah daripada satu baris hemat yang tak terbaca. */
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-outlet {
    flex: 1 1 100%; justify-content: flex-start;
    min-width: 0; max-width: none;
    font-size: 0.75rem; font-weight: 500; color: #64748b;
    white-space: normal; overflow: visible;
  }
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-outlet::before { display: none; }
  /* Panah rincian jadi sasaran sentuh yang layak, bukan ikon 10px. */
  .scm-dense .data-table.sb-harian-tabel .sb-chevron {
    padding: 0.35rem; margin: -0.35rem 0.1rem -0.35rem -0.35rem;
  }

  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-kurang { font-size: 0.875rem; }
  /* "Harus setor" adalah angka yang orang datangi halaman ini untuk melihat —
     di kartu HP ia dibuat paling menonjol, bukan sekadar satu baris di antara
     baris lain. */
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-harus {
    font-size: 1rem; color: #111827;
  }
  .scm-dense .sb-bukti-mini { width: 2.25rem; height: 2.25rem; }
  /* Di tabel, sel kosong tetap perlu ada supaya kolomnya sejajar. Di kartu tak
     ada kolom untuk disejajarkan — baris "Bukti —" cuma menambah tinggi kartu
     tanpa memberi tahu apa pun, jadi dibuang di HP. Kelas .sb-sel-bukti dipakai
     sebagai pengait; sel yang berisi foto tetap tampil. */
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-bukti.sb-kosong { display: none; }

  /* Barisan aksi: medan jumlah melar, tombol Unggah tetap seukuran jempol. */
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-setor {
    margin-top: 0.4rem; padding-top: 0.5rem; border-top: 1px solid #f1f5f9;
  }
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-hari > td.sb-sel-setor::before { display: none; }
  .scm-dense .sb-aksi { display: flex; width: 100%; gap: 0.4rem; }
  /* Lebar dari CSS, bukan inline — lihat catatan di setoran-bank.js. */
  .scm-dense .sb-amt { flex: 1 1 auto; width: auto; min-width: 0; padding: 0.45rem 0.6rem; }
  .scm-dense .sb-unggah { flex: 0 0 auto; font-size: 0.8125rem; padding: 0.5rem 0.85rem; }

  /* Baris rincian menempel di bawah kartunya, bukan melayang sendiri. */
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-rincian {
    margin: -0.45rem 0 0.6rem; padding: 0.5rem 0.65rem;
    border: 1px solid #e5e7eb; border-top: 0;
    border-radius: 0 0 0.6rem 0.6rem; background: #f8fafc;
  }
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-rincian > td {
    display: block; text-align: left; padding: 0;
  }
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-rincian > td::before { display: none; }

  /* Baris "belum ada data" / "memuat" bukan kartu — dibiarkan rata tengah. */
  .scm-dense .data-table.sb-harian-tabel tbody td.empty-state,
  .scm-dense .data-table.sb-harian-tabel tbody td.table-loading {
    justify-content: center; text-align: center;
  }
  .scm-dense .data-table.sb-harian-tabel tbody td.empty-state::before,
  .scm-dense .data-table.sb-harian-tabel tbody td.table-loading::before { display: none; }
}

/* ===== Mutasi rekening kas (/cash-account-detail) — TABEL DATAR SEBULAN =====
   Owner 2026-09-12: "ubah UI nya agar seperti mutasi bank sungguhan ada kolom
   debit dan kredit" + "jangan pakai pagenation. di baris paling bawah saya mau
   ada total tiap kolom". Owner 2026-09-22: "UI nya masih sulit di baca saat
   baris datanya sangat banyak, ubah saja jadi bentuk tabel simple dan ringan"
   — lipatan per tanggal, baris rincian dua lapis yang menjorok, dan kartu per
   mutasi di HP DICABUT. Kini satu baris satu mutasi, satu lapis; hari dibedakan
   cukup dengan latar selang-seling (`.cad-belang`), kepala tabel lengket.
   Debit = uang KELUAR, Kredit = uang MASUK — konvensi rekening koran bank,
   BUKAN konvensi jurnal umum (di jurnal, kas bertambah justru di sisi debit).
   Alasan lengkapnya di kepala web/assets/js/panels/cash-account-detail.js.

   Seluruh gaya di sini CSS sendiri, bukan kelas Tailwind: tailwind.css SCM
   adalah subset PRA-BUILD, jadi kelas yang belum pernah dipakai di berkas lain
   tak ikut ter-generate dan gagal TANPA SUARA. Selektor tabel sengaja lewat
   `.data-table.cad-tabel` supaya menang telak atas blok kepadatan
   `.scm-dense .data-table ...` di HP — bukan menang tipis karena urutan berkas. */

/* --- bilah atas: bulan, keterangan arah kolom, saklar koreksi --- */
.cad-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.5rem 0.75rem; flex-wrap: wrap; margin-bottom: 0.5rem;
}
/* Keterangan arah kolom. JANGAN dihapus — tanpa ini Debit/Kredit bisa dibaca
   terbalik oleh siapa pun yang terbiasa jurnal umum. */
.cad-legenda { margin: 0; flex: 1 1 18rem; font-size: 0.6875rem; color: #64748b; line-height: 1.45; }
.cad-legenda b { color: #334155; font-weight: 600; }
/* Tombol teks ("Tampilkan N koreksi"). Chrome tombol bawaan peramban dilucuti
   sendiri — preflight subset Tailwind tak bisa diandalkan (lihat .sb-bukti-btn). */
.cad-aksi {
  background: none; border: 0; padding: 0; margin: 0; font: inherit;
  font-size: 0.6875rem; font-weight: 600; color: #4f46e5;
  cursor: pointer; white-space: nowrap; flex: 0 0 auto;
}
.cad-aksi:hover { text-decoration: underline; }
/* Pemilih bulan. Daftar bulan datang dari server (hanya bulan yang punya
   mutasi), bawaannya bulan TERBARU yang ada datanya, bukan bulan berjalan. */
.cad-bulan { display: inline-flex; align-items: center; gap: 0.45rem; flex: 0 0 auto; }
.cad-bulan > span { font-size: 0.6875rem; font-weight: 600; color: #64748b; }
.cad-bulan > select {
  width: auto; min-width: 10.5rem; padding: 0.3rem 0.55rem; font-size: 0.75rem;
}

/* --- PENCARIAN buku kas (owner 24 Sep 2026: "buatkan pencarian untuk cari
   transaksi berdasarkan type keterangan maupun kode"). Barisnya sendiri, DI ATAS
   pemilih bulan: pencarian menjangkau SEMUA bulan, jadi menaruhnya bersebelahan
   dengan pemilih bulan akan terbaca seolah ia menyaring bulan yang terpilih. */
.cad-bar-cari { margin-bottom: 0.4rem; }
/* Keterangan pencarian. Kelasnya SENDIRI, bukan .cad-legenda: kelas itu
   milik keterangan arah kolom (Debit/Kredit) dan dijaga
   uji_render_buku_kas.mjs, yang mengambil yang PERTAMA — dua pemakai satu
   kelas membuat penjaga itu menguji teks yang salah. */
.cad-cari-info { margin: 0; flex: 1 1 18rem; font-size: 0.6875rem; color: #64748b; line-height: 1.45; }
.cad-cari-info b { color: #334155; font-weight: 600; }
.cad-cari { position: relative; display: flex; align-items: center; flex: 1 1 22rem; min-width: 0; }
.cad-cari-ikon {
  position: absolute; left: 0.6rem; display: flex; align-items: center;
  color: #94a3b8; font-size: 0.75rem; pointer-events: none;
}
.cad-cari > input {
  width: 100%; padding: 0.4rem 0.6rem 0.4rem 1.9rem; font-size: 0.8125rem;
}
/* Silang bawaan Chrome pada type=search dilucuti: tombol "Hapus pencarian"
   sudah mengerjakannya dan terbaca jelas, sedangkan silangnya kecil & tak
   berlabel. */
.cad-cari > input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
/* KODE dokumen di dalam sel Jenis. Baris kecil di bawah namanya — bukan kolom
   sendiri: tabel ini sudah 8 kolom dan di HP sudah dipadatkan lewat @media. */
.cad-kode {
  display: block; margin-top: 0.1rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.625rem; color: #64748b; letter-spacing: 0.01em;
}

/* Penanda "tautan ini keluar dari SCM" (pembayaran DOKU -> detail penjualan
   di POS). Tanpa ikonnya, satu-satunya tautan yang membuka tab baru terlihat
   persis sama dengan yang tidak — dan tab yang tiba-tiba bertambah terbaca
   sebagai halaman yang salah, bukan sebagai pilihan yang disengaja. */
.cad-luar { font-size: 0.5625rem; opacity: 0.55; margin-left: 0.15rem; }

/* --- gulungan: tabel menggulir di dalam kotaknya sendiri supaya kepala kolom
   tetap terlihat. `position: sticky` tak bisa menempel ke halaman karena
   pembungkusnya wajib `overflow: auto` (tabelnya lebih lebar dari layar HP). */
/* Tabel buku kas DIGULIR BERSAMA HALAMAN, bukan dalam kotak sendiri (owner
   5 Okt 2026: "saat ini tabelnya bisa di scroll tersendiri, saya tidak mau
   seperti itu, biar saja di scroll bersama halamannya"). Dulu
   `max-height: max(22rem, 100vh - 14rem)` + `overflow: auto` — dua batang gulir
   bertumpuk. Kini tanpa batas tinggi; di layar sedang tabel 46rem boleh
   bergeser KE SAMPING di kotaknya (tanpa itu seluruh halaman ikut melebar), dan
   di layar lebar `overflow: visible` supaya kepala `sticky` menempel ke atas
   HALAMAN — kepala sticky di dalam kotak ber-overflow menempel ke kotaknya,
   bukan ke halaman. */
.cad-gulir {
  overflow-x: auto;
  border: 1px solid #e2e8f0; border-radius: 0.5rem;
}
@media (min-width: 64rem) {
  .cad-gulir { overflow: visible; }
}

/* --- tabel --- */
.data-table.cad-tabel { font-size: 0.75rem; min-width: 46rem; }
.data-table.cad-tabel thead th {
  position: sticky; top: 0; z-index: 1;
  background: #f8fafc; padding: 0.4rem 0.6rem; font-size: 0.6875rem;
  vertical-align: bottom; box-shadow: inset 0 -1px 0 #e2e8f0;
}
.data-table.cad-tabel tbody td {
  padding: 0.3rem 0.6rem; border-bottom: 1px solid #f1f5f9; white-space: nowrap;
}
/* Latar selang-seling PER HARI (bukan per baris): batas hari terbaca tanpa
   baris kelompok yang memakan tempat. */
.data-table.cad-tabel tbody tr.cad-belang > td { background: #f8fafc; }
.data-table.cad-tabel tbody tr:hover > td { background: #eef2ff; }
/* Sorotan sementara untuk hari yang dibuka lewat ?tanggal= di URL (mis. tautan
   "lihat di buku kas" dari /petty-cash-detail). */
.data-table.cad-tabel tbody tr.cad-disorot > td { background: #fef3c7; transition: background 0.6s ease; }

.cad-tabel th.cad-num, .cad-tabel td.cad-num {
  text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; width: 1%;
}
.cad-tabel th.cad-tgl, .cad-tabel td.cad-tgl { width: 1%; white-space: nowrap; }
.cad-tabel td.cad-tgl { color: #334155; font-variant-numeric: tabular-nums; }
.cad-jam { color: #94a3b8; margin-left: 0.2rem; }
.cad-tabel td.cad-jenis { color: #1e293b; font-weight: 500; }
.cad-tabel td.cad-jenis a { color: #4f46e5; }
.cad-tabel td.cad-jenis a:hover { text-decoration: underline; }
/* Keterangan menyerap sisa lebar dan DIPOTONG satu baris (isi penuhnya di
   tooltip). `max-width: 0` + `width: 100%` = pola baku supaya sel tabel mau
   memotong teks alih-alih melebarkan tabel. */
.cad-tabel td.cad-ket {
  color: #64748b; width: 100%; max-width: 0; overflow: hidden; text-overflow: ellipsis;
}
.cad-tabel td.cad-oleh {
  color: #94a3b8; max-width: 9rem; overflow: hidden; text-overflow: ellipsis;
}
.cad-tabel td.cad-debit, .cad-tabel td.cad-turun { color: #be123c; font-weight: 600; }
.cad-tabel td.cad-kredit, .cad-tabel td.cad-naik { color: #047857; font-weight: 600; }
.cad-tabel td.cad-saldo { color: #334155; font-weight: 600; }
/* Kolom Mutasi bertanda hanya untuk HP — di desktop Debit/Kredit sudah punya
   kolom sendiri. */
.cad-tabel .cad-mutasi { display: none; }
/* Saldo BISA minus (purchase_payment sengaja membolehkannya) — ditandai warna
   supaya tak terbaca sebagai angka biasa. */
.cad-tabel td.cad-saldo.cad-minus { color: #be123c; }
.cad-th-sub {
  display: block; font-size: 0.625rem; font-weight: 400; color: #94a3b8;
  letter-spacing: 0.01em; margin-top: 0.05rem;
}
/* Baris koreksi netral (hanya tampil bila diminta): pudar + bertanda, supaya
   tak terbaca sebagai transaksi yang berdiri sendiri. */
.cad-tabel tbody tr.cad-koreksi > td { opacity: 0.55; }
.cad-tanda {
  display: inline-block; margin-left: 0.25rem; padding: 0 0.3rem; border-radius: 0.25rem;
  font-size: 0.625rem; font-weight: 600; color: #92400e; background: #fef3c7;
}
.cad-redup { font-size: 0.6875rem; font-weight: 500; color: #94a3b8; }

/* --- kaki tabel: Saldo awal, lalu TOTAL tiap kolom --- */
.data-table.cad-tabel tfoot td {
  padding: 0.45rem 0.6rem; border-top: 1px solid #e2e8f0; background: #f8fafc; white-space: nowrap;
}
.data-table.cad-tabel tfoot tr.cad-awal td:first-child { color: #64748b; }
/* Warna debit/kredit SENGAJA tak ditimpa di sini (aturan ini tak menyetel
   `color` sama sekali) supaya angka total tetap merah/hijau seperti kolomnya. */
.data-table.cad-tabel tfoot tr.cad-total td {
  background: #eef2f7; border-top: 2px solid #cbd5e1; font-weight: 700; font-size: 0.8125rem;
}
.data-table.cad-tabel tfoot tr.cad-total td:first-child { color: #0f172a; letter-spacing: 0.02em; }

@media (max-width: 640px) {
  /* HP (lebar ~400px): tujuh kolom tak muat, dan versi-versi awal membuktikan
     dua jalan buntu — tabel yang digeser menyamping menyembunyikan NOMINAL,
     dan empat kolom sempit memecah "Terima Dana Utang Antar Outlet" jadi lima
     baris. Jadi tiap mutasi = SATU baris dua sisi, seperti aplikasi bank:
         31 Jul 17:28                 -6.920.000
         Pembayaran Pembelian   saldo -74.344.746
         Pembayaran pembelian PO-AAE3E5 (susulan…)
     Debit/Kredit digabung jadi angka bertanda (`cad-mutasi`), Oleh dilepas.
     Kepala tabel disembunyikan (susunannya sudah menjelaskan dirinya), jadi
     kotak gulir sendiri tak ada gunanya — halamannya saja yang digulir.
     Selektor sengaja selengkap aturan desktop di atas supaya menang karena
     urutan-dan-bobot, bukan kebetulan. */
  .cad-gulir { max-height: none; overflow: visible; }
  .data-table.cad-tabel,
  .data-table.cad-tabel tbody,
  .data-table.cad-tabel tfoot { display: block; width: 100%; min-width: 0; }
  .data-table.cad-tabel thead { display: none; }

  .data-table.cad-tabel tbody tr.cad-baris,
  .data-table.cad-tabel tfoot tr {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 0.75rem;
    padding: 0.4rem 0.6rem; border-bottom: 1px solid #f1f5f9;
  }
  .data-table.cad-tabel tbody tr.cad-baris > td,
  .data-table.cad-tabel tfoot tr.cad-awal > td,
  .data-table.cad-tabel tfoot tr.cad-total > td {
    display: block; padding: 0; border: 0; background: none; min-width: 0;
  }
  /* Latar hari & sorotan pindah ke BARIS — selnya kini transparan. */
  .data-table.cad-tabel tbody tr.cad-baris.cad-belang { background: #f8fafc; }
  .data-table.cad-tabel tbody tr.cad-baris.cad-disorot { background: #fef3c7; }
  .cad-tabel .cad-oleh, .cad-tabel .cad-debit, .cad-tabel .cad-kredit { display: none !important; }

  .data-table.cad-tabel tbody td.cad-tgl { grid-column: 1; grid-row: 1; font-size: 0.6875rem; color: #64748b; }
  .data-table.cad-tabel tbody td.cad-jenis {
    grid-column: 1; grid-row: 2; overflow: hidden; text-overflow: ellipsis;
  }
  .data-table.cad-tabel tbody td.cad-mutasi { grid-column: 2; grid-row: 1; font-size: 0.8125rem; }
  .data-table.cad-tabel tbody td.cad-saldo {
    grid-column: 2; grid-row: 2; font-size: 0.6875rem; font-weight: 500;
  }
  .data-table.cad-tabel tbody td.cad-saldo::before { content: "saldo "; color: #94a3b8; font-weight: 400; }
  .data-table.cad-tabel tbody td.cad-ket {
    grid-column: 1 / -1; grid-row: 3; width: auto; max-width: none;
    font-size: 0.6875rem; color: #94a3b8;
  }

  /* Kaki: judul di kiri, mutasi bersih & saldo di kanan. */
  .data-table.cad-tabel tfoot tr { background: #f8fafc; border-top: 1px solid #e2e8f0; border-bottom: 0; }
  .data-table.cad-tabel tfoot tr.cad-total { background: #eef2f7; border-top: 2px solid #cbd5e1; }
  .data-table.cad-tabel tfoot td.cad-kaki-judul { grid-column: 1; grid-row: 1 / span 2; white-space: normal; }
  .data-table.cad-tabel tfoot tr > td.cad-ket { display: none; }
  .data-table.cad-tabel tfoot td.cad-mutasi { grid-column: 2; grid-row: 1; }
  .data-table.cad-tabel tfoot td.cad-saldo { grid-column: 2; grid-row: 2; }
}

/* ===== Topup Saldo Outlet (/topup) — tabel ringan, dua sisi di HP =====
   Owner 23 Sep 2026: "refactor halaman /topup" — keluhannya alur ajukan
   top-up, terlalu banyak kolom, dan sulit dibaca di HP. Kedua tabelnya dulu
   `min-w-[44rem]`: di layar HP nominal dan tombolnya terdorong ke luar layar,
   dan orang harus menggeser menyamping hanya untuk melihat angkanya — keluhan
   yang sama persis dengan buku kas sehari sebelumnya.

   Desktop: kolom digabung, dan yang digabung turun jadi baris kecil (`.tw-sub`)
   — rekonsiliasi di bawah status, catatan admin di bawah catatan pengaju,
   keterangan di bawah jenis mutasi.

   HP: satu baris = satu kartu dua sisi. Kiri waktu & keterangan, kanan nominal
   & status/saldo, aksi melebar di bawah. Pola & jebakannya sama dengan
   `.cad-tabel`: selektor WAJIB lewat `.data-table.tw-tabel` supaya menang
   telak atas blok kepadatan `.scm-dense .data-table ...`, bukan menang tipis
   karena urutan berkas. */
.tw-tabel .tw-sub {
  display: block; font-size: 0.6875rem; color: #94a3b8; font-weight: 400;
  margin-top: 0.15rem; white-space: normal;
}
.data-table.tw-tabel td.tw-ket { max-width: 24rem; }
.data-table.tw-tabel td.tw-tgl { color: #64748b; }

@media (max-width: 640px) {
  .data-table.tw-tabel,
  .data-table.tw-tabel tbody { display: block; width: 100%; }
  .data-table.tw-tabel thead { display: none; }

  .data-table.tw-tabel tbody tr.tw-baris {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 0.75rem; padding: 0.55rem 0.7rem;
    border-bottom: 1px solid #f1f5f9;
  }
  .data-table.tw-tabel tbody tr.tw-baris:nth-child(even) { background: #f8fafc; }
  .data-table.tw-tabel tbody tr.tw-baris > td {
    display: block; padding: 0; border: 0; background: none; min-width: 0; max-width: none;
  }
  /* Kolom 1 = waktu lalu outlet; kolom 2 = nominal lalu status/saldo. Sisanya
     (keterangan, aksi) melebar penuh di bawahnya, mengikuti urutan alaminya. */
  .data-table.tw-tabel tbody tr.tw-baris > td.tw-tgl { grid-column: 1; grid-row: 1; }
  .data-table.tw-tabel tbody tr.tw-baris > td.tw-num { grid-column: 2; grid-row: 1; font-size: 0.8125rem; }
  .data-table.tw-tabel tbody tr.tw-baris > td.tw-outlet { grid-column: 1; grid-row: 2; color: #64748b; }
  .data-table.tw-tabel tbody tr.tw-baris > td.tw-status,
  .data-table.tw-tabel tbody tr.tw-baris > td.tw-saldo { grid-column: 2; grid-row: 2; text-align: right; }
  .data-table.tw-tabel tbody tr.tw-baris > td.tw-saldo::before { content: "saldo "; color: #94a3b8; }
  .data-table.tw-tabel tbody tr.tw-baris > td.tw-ket,
  .data-table.tw-tabel tbody tr.tw-baris > td.tw-aksi { grid-column: 1 / -1; }
  .data-table.tw-tabel tbody tr.tw-baris > td.tw-ket { margin-top: 0.2rem; }
  /* Aksi: tombol-tombol dibiarkan membungkus, bukan dipaksa satu baris —
     `whitespace-nowrap` di sel aslinya akan mendorongnya ke luar layar lagi. */
  .data-table.tw-tabel tbody tr.tw-baris > td.tw-aksi {
    margin-top: 0.35rem; white-space: normal; display: flex; flex-wrap: wrap;
    align-items: center; gap: 0.3rem;
  }
}

/* Tombol teks kecil di bilah saringan ("Bersihkan"). Dulu bagian dari aksi
   massal; aksi massalnya DICABUT 12 Sep 2026 (owner: bertolak belakang dengan
   aturan "setiap bukti harus dibuka dan diperiksa baru boleh konfirmasi"),
   kelasnya tinggal ini yang masih terpakai. */
.sb-tautan-aksi {
  background: none; border: 0; padding: 0; margin: 0; font: inherit;
  font-size: 0.75rem; color: #4f46e5; cursor: pointer;
}
.sb-tautan-aksi:hover { text-decoration: underline; }

/* Temuan penjaga uji_kelas_css 12 Sep: dipakai setoran-bank.js sejak lama,
   tak pernah ada aturannya, jadi jarak antar-ikon buktinya selama ini nol. */
.gap-0\.5 { gap: 0.125rem; }

.sb-riwayat-lencana {
  display: inline-block; margin-left: 0.5rem; padding: 0.05rem 0.45rem;
  border-radius: 9999px; background: #fef3c7; color: #b45309;
  font-size: 0.6875rem; font-weight: 600; vertical-align: middle;
}

/* ===== Rapikan Setoran Bank (12 Sep 2026) =====
   Owner: "halamannya terlihat berantakan". Akar masalahnya baris rincian dulu
   satu pita `colspan=8` berisi kalimat memanjang — induk & anak tampak
   sederajat dan tak ada yang bisa dibaca menurun. Kini satu baris per setoran
   dengan kolom sejajar, dan gaya di bawah yang membuatnya terbaca sebagai ANAK
   dari baris shift di atasnya (pola sama dengan `.cad-anak`). */
.sb-harian-tabel tbody tr.sb-anak > td {
  background: #fbfcfe;
  border-bottom: 1px solid #f1f5f9;
  font-size: 0.78125rem;
  color: #475569;
}
/* Garis aksen + jorokan cuma di sel PERTAMA: itu sudah cukup menandai
   kepemilikan tanpa membuat seluruh barisnya berwarna dan berebut perhatian
   dengan baris shift-nya. */
.sb-harian-tabel tbody tr.sb-anak > td.sb-anak-tgl {
  padding-left: 1.6rem;
  box-shadow: inset 3px 0 0 #c7d2fe;
  white-space: nowrap;
}
.sb-harian-tabel tbody tr.sb-anak:hover > td { background: #f5f8ff; }

/* Kolom "Tgl Transfer" di daftar rata. */
.sb-sel-transfer { white-space: nowrap; }

/* ===== Penamai dua tanggal ATURAN KAS (19 Sep 2026) =====
   Baris rincian memajang DUA stempel waktu berbentuk sama — Tanggal Transaksi
   (saat dicatat) dan Tanggal Mutasi (saat uangnya pindah) — dan hanya yang
   kedua yang menggerakkan buku kas. Tanpa penamai keduanya cuma dua tanggal
   yang mirip, dan yang keliru dibaca justru yang menentukan di hari mana
   barisnya duduk di buku kas. Kapsinya sengaja kecil & kelabu: ia penamai,
   bukan angka yang dibaca. */
.sb-kap {
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #94a3b8;
  line-height: 1.2;
}
/* Legenda di atas tabel — menjawab "tanggal yang mana yang menggerakkan
   saldo?" sekali untuk seluruh halaman, jadi tooltip tiap sel tak perlu
   mengulang seluruh aturannya. */
.sb-legenda-tgl {
  margin: 0 0 0.6rem;
  padding: 0.4rem 0.6rem;
  border-left: 3px solid #c7d2fe;
  border-radius: 0 0.4rem 0.4rem 0;
  background: #f8fafc;
  font-size: 0.6875rem;
  line-height: 1.5;
  color: #64748b;
}
.sb-legenda-tgl b { color: #475569; }
.sb-selisih {
  display: inline-block; margin-left: 0.3rem; padding: 0.02rem 0.3rem;
  border-radius: 9999px; font-size: 0.625rem; font-weight: 600;
}
/* Transfer SESUDAH hari kasnya = terlambat (amber). SEBELUM = mustahil secara
   alur, jadi merah — itu tanda tanggalnya salah ketik, bukan sekadar cepat. */
.sb-selisih-maju { background: #fef3c7; color: #b45309; }
.sb-selisih-mundur { background: #fee2e2; color: #b91c1c; }

@media (max-width: 640px) {
  /* Di kartu HP baris anak menempel di bawah kartu shift-nya, bukan berdiri
     sendiri — jorokan kolom tak berlaku, yang tinggal garis aksen kirinya. */
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-anak {
    margin: -0.45rem 0 0.6rem; padding: 0.45rem 0.6rem;
    border: 1px solid #e5e7eb; border-top: 0;
    border-radius: 0 0 0.6rem 0.6rem; background: #fbfcfe;
    box-shadow: inset 3px 0 0 #c7d2fe;
  }
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-anak > td.sb-anak-tgl {
    padding-left: 0; box-shadow: none;
  }
}

/* Lencana status tak boleh PECAH DUA BARIS ("Menunggu" / "Konfirmasi") — itu
   yang membuat kolom Disetor terlihat sesak dan tinggi barisnya melompat. */
.sb-harian-tabel .badge, .sb-riwayat-tabel .badge,
.sb-harian-tabel tbody tr.sb-anak [class*="rounded"] { white-space: nowrap; }
/* Kolom angka di tabel shift dijaga tetap satu baris; yang boleh melipat cuma
   kolom teks (outlet/kasir & nama pencatat). */
.sb-harian-tabel td.text-right, .sb-harian-tabel th.text-right { white-space: nowrap; }

/* Nama orang di baris anak dipotong, bukan dibiarkan melipat tiga baris —
   "Andi Muhammad Alif Nurcholish" berulang di tiap baris dan yang dicari mata
   di kolom ini sebetulnya REKENINGNYA, bukan namanya. Nama penuhnya tetap
   terbaca lewat title. */
.sb-nama-kecil {
  font-size: 0.6875rem; color: #94a3b8;
  max-width: 11rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Baris yang tercentang diberi latar supaya terlihat tanpa menelusuri kotaknya. */
.sb-arsip-nota { margin-left: 0.5rem; font-size: 0.6875rem; font-weight: 400; color: #94a3b8; }

/* Bilah saringan di atas tabel setoran. */
.sb-saring {
  display: flex; align-items: flex-end; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.6rem;
}
.sb-saring > label { display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.6875rem; color: #64748b; font-weight: 600; }
.sb-saring > label > * { width: auto; min-width: 11rem; padding: 0.3rem 0.55rem; font-size: 0.75rem; font-weight: 400; }
.sb-saring-info { font-size: 0.6875rem; color: #94a3b8; margin-bottom: 0.35rem; }
/* Baris yang tersaring keluar. Spesifisitasnya dinaikkan lewat `.data-table`
   supaya tetap menang atas aturan `display:block` blok kartu HP di bawah —
   jebakan yang sama dengan tr.hidden di .sb-harian-tabel. */
.data-table.sb-harian-tabel tbody tr.sb-tersaring { display: none; }
@media (max-width: 640px) {
  .scm-dense .data-table.sb-harian-tabel tbody tr.sb-tersaring { display: none; }
  .sb-saring > label, .sb-saring > label > * { width: 100%; min-width: 0; }
}

/* ──────────────────────────────────────────────────────────────────────────
   /debt-detail — baris yang bisa diperbaiki management (owner 2026-09-14)

   Ditulis di sini, BUKAN dengan utility Tailwind: tailwind.css SCM adalah
   subset pra-kompilasi, dan kelas yang tak terpakai di tempat lain (h-6, w-6,
   hover:bg-indigo-50 …) tak ada di dalamnya — tombolnya akan tampil sebagai
   teks polos tanpa galat apa pun.
   ────────────────────────────────────────────────────────────────────────── */
.dd-pen {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.5rem; height: 1.5rem; margin-left: 0.35rem; vertical-align: middle;
  border: 1px solid #e0e7ff; border-radius: 0.375rem;
  background: #eef2ff; color: #4f46e5; font-size: 0.625rem;
  cursor: pointer; transition: background .12s, border-color .12s;
}
.dd-pen:hover { background: #e0e7ff; border-color: #c7d2fe; }
.dd-pen:disabled { opacity: .5; cursor: progress; }
/* GOTCHA URUTAN CSS (sama jenisnya dengan `.btn-primary.hidden` di atas):
   `.hidden{display:none}` bawaan Tailwind spesifisitasnya 0,1,0 — sama dengan
   `.dd-pen` — dan tailwind.css dimuat SEBELUM app.css, jadi tanpa baris ini
   pensilnya tetap terlihat saat editornya terbuka. */
.dd-pen.hidden { display: none; }

/* Varian MERAH untuk tindakan yang tak bisa diurungkan (hapus baris cicilan di
   /debt-detail). Warnanya bagian dari peringatan, bukan hiasan: tombolnya
   duduk persis di sebelah pensil, sama bentuk & sama ukuran, dan tanpa beda
   warna satu meleset klik berarti satu baris pembayaran hilang beserta
   mutasi kas dua outlet. Ditulis di sini, BUKAN dengan utility Tailwind —
   tailwind.css SCM adalah subset pra-kompilasi (lihat catatan `.dd-pen` di
   atas). */
.dd-pen-bahaya { border-color: #fecaca; background: #fef2f2; color: #dc2626; }
.dd-pen-bahaya:hover { background: #fee2e2; border-color: #fca5a5; }

/* Editor sebaris. `flex-wrap` bukan kemewahan: di HP satu select rekening +
   dua tombol tak pernah muat sebaris, dan tanpa melipat ia mendorong seluruh
   tabel informasi melebar sehingga halaman menggeser mendatar. */
/* `display:flex` DAN TANPA `width:100%` — dua-duanya penting, dan keduanya
   ditemukan lewat pengukuran, bukan selera:

   Baris ini hidup di dalam SEL TABEL ber-layout `auto`. Lebar PERSEN di sana
   melingkar (lebar sel bergantung isinya, isinya bergantung lebar sel), jadi
   peramban menyerah dan memakai lebar MAX-CONTENT — medan tanggal + Simpan +
   Batal berjajar 423px di layar 390px, dan SELURUH halaman detail bergeser
   mendatar. `inline-flex` memperburuknya karena kotaknya jadi inline-level
   sehingga tak pernah menerima lebar sel sebagai batas.
   Terukur di chromium headless 390px: 446 -> 390. */
.dd-editor {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem;
  margin-top: 0.35rem;
}
.dd-editor .field-input { min-width: 0; }
.dd-editor-grid { display: flex; flex-direction: column; gap: 0.4rem; width: 100%; min-width: 0; }
.dd-lbl {
  display: flex; flex-direction: column; gap: 0.15rem;
  font-size: 0.6875rem; font-weight: 600; color: #64748b; min-width: 0;
}
.dd-lbl > * { font-weight: 400; width: 100%; }
.dd-nota { display: block; width: 100%; font-size: 0.6875rem; color: #94a3b8; }
/* Medan tanggal diberi lebar sendiri: bawaan `input[type=date]` chromium
   ~290px, dan itu mendorong tombol Batal turun ke baris kedua di desktop
   padahal ruangnya berlimpah. */
.dd-editor input[type="date"], .dd-lbl input[type="date"] { max-width: 11rem; }
@media (min-width: 640px) {
  .dd-editor .field-input { max-width: 18rem; }
  .dd-editor-grid { flex-direction: row; flex-wrap: wrap; align-items: flex-end; }
  .dd-lbl { flex: 1 1 12rem; }
}
@media (max-width: 640px) {
  /* KOLOM LABEL BOLEH MELIPAT DI HP. Baris info bersama (`info()` di
     _detail.js) memakai `whitespace-nowrap` pada sel kiri, jadi label
     terpanjang di halaman ini ("Rekening Tujuan (penerima dana)") mematok
     lantai 253px pada tabel selebar 350px — menyisakan 97px untuk nilainya.
     Apa pun yang lebih lebar dari itu, termasuk medan tanggal 168px, membuat
     SELURUH halaman bergeser mendatar.
     Dibatasi ke `#dd-body` dengan sengaja: aturan nowrap itu dipakai semua
     halaman detail SCM, dan melonggarkannya di sini terbukti aman karena
     terukur — 446px -> 390px di chromium headless 390px. */
  #dd-body table td:first-child { white-space: normal; }
}

/* ──────────────────────────────────────────────────────────────────────────
   /debts — bilah saringan, kotak cari, dan tabel yang jadi KARTU di HP
   (owner 2026-09-14: "ditambah filternya … dan dirapihkan UI-nya terutama di
   mobile").

   Halaman ini punya tabel terlebar di SCM (10 kolom di tab Utang Antar Outlet).
   Di layar 390px ia dulu cuma bisa digeser mendatar: kode dokumen terlihat,
   nominal dan statusnya tidak — persis dua hal yang orang datang untuk lihat.
   Polanya menyalin `.sb-harian-tabel` di atas (tabel -> kartu, label kolom
   lewat `::before` dari `data-label`), bukan bentuk ketiga yang harus dipelajari
   ulang.
   ────────────────────────────────────────────────────────────────────────── */
.hp-tabs { display: flex; gap: 0.5rem; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.hp-tabs::-webkit-scrollbar { height: 3px; }
.hp-tabs::-webkit-scrollbar-thumb { background: #e2e8f0; border-radius: 3px; }
.hp-tabs > .hp-tab { flex: 0 0 auto; white-space: nowrap; }

.hp-saring { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.6rem; }
.hp-saring > label { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.hp-saring .field-label { margin: 0; }
.hp-saring-medan { flex: 0 1 11rem; }
.hp-saring-medan > .field-input { width: 100%; }
/* Kotak cari mendapat sisa ruang: ia yang paling sering diketik & dibaca —
   tapi DIBATASI. Tanpa batas ia memakan seluruh sisa baris di layar lebar
   dan bilahnya terbaca sebagai satu medan raksasa dengan tiga sisa kecil. */
.hp-saring-cari { flex: 1 1 16rem; max-width: 28rem; }

.hp-cari-kotak { position: relative; display: block; }
.hp-cari-kotak > .field-input { width: 100%; padding-left: 2rem; padding-right: 2rem; }
/* `appearance:none` membuang tombol silang bawaan WebKit — ada tombol hapus
   sendiri di kanan yang juga MENJALANKAN pencarian ulang; dua silang yang
   berbeda perilakunya di satu kotak adalah kebingungan yang tak perlu. */
.hp-cari-kotak > input[type="search"]::-webkit-search-cancel-button { appearance: none; }
.hp-cari-ikon {
  position: absolute; left: 0.6rem; top: 50%; transform: translateY(-50%);
  font-size: 0.75rem; color: #94a3b8; pointer-events: none;
}
.hp-cari-hapus {
  position: absolute; right: 0.35rem; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.4rem; height: 1.4rem; border-radius: 9999px;
  border: 0; background: transparent; color: #94a3b8; cursor: pointer;
}
.hp-cari-hapus:hover { background: #f1f5f9; color: #475569; }
/* GOTCHA URUTAN CSS: `.hidden` bawaan Tailwind (0,1,0) tak bisa mengalahkan
   `display:inline-flex` di atas karena app.css dimuat BELAKANGAN. */
.hp-cari-hapus.hidden { display: none; }

.hp-preset { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.hp-kosong-hapus {
  border: 0; background: transparent; color: #4f46e5;
  text-decoration: underline; cursor: pointer; font-size: inherit;
}

@media (max-width: 640px) {
  /* Satu saringan per baris; setengah-setengah membuat "Dari"/"Sampai"
     sesempit 5rem dan tanggalnya terpotong di dalam medannya sendiri. */
  .hp-saring > label { flex: 1 1 100%; }
  .hp-preset > .btn-secondary { flex: 1 1 auto; justify-content: center; }

  .data-table.hp-tabel,
  .data-table.hp-tabel tbody,
  .data-table.hp-tabel tbody tr,
  .data-table.hp-tabel tbody td { display: block; width: 100%; }
  .data-table.hp-tabel thead { display: none; }
  /* Pembungkus `overflow-x-auto` tak lagi punya gunanya begitu tabelnya jadi
     blok — dan kalau dibiarkan, ia memunculkan bilah geser mendatar palsu. */
  .data-table.hp-tabel { min-width: 0; }

  .data-table.hp-tabel tbody tr {
    border: 1px solid #e5e7eb; border-radius: 0.6rem; background: #fff;
    padding: 0.55rem 0.7rem; margin-bottom: 0.6rem;
  }
  .data-table.hp-tabel tbody tr:hover { background: #fff; }
  .data-table.hp-tabel tbody td {
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.75rem; padding: 0.22rem 0; border: 0;
    text-align: right; font-size: 0.8125rem;
  }
  .data-table.hp-tabel tbody td::before {
    content: attr(data-label);
    color: #64748b; font-size: 0.6875rem; font-weight: 500;
    text-align: left; white-space: nowrap;
  }
  /* Sel pertama = judul kartu: kode dokumen + lencananya, rata kiri, tanpa
     label. Itulah yang dipakai mata untuk menemukan barisnya lagi. */
  .data-table.hp-tabel tbody td:first-child {
    justify-content: flex-start; flex-wrap: wrap; gap: 0.35rem;
    font-size: 0.875rem; text-align: left;
    border-bottom: 1px solid #f1f5f9; padding-bottom: 0.4rem; margin-bottom: 0.3rem;
  }
  .data-table.hp-tabel tbody td:first-child::before { display: none; }
  /* Baris "tidak ada data" tetap satu blok penuh, bukan kartu sesat. */
  .data-table.hp-tabel tbody td.empty-state {
    display: block; text-align: center; border: 0; padding: 0.9rem 0;
  }
  .data-table.hp-tabel tbody td.empty-state::before { display: none; }
  .data-table.hp-tabel tbody tr.hp-kosong {
    border: 0; background: transparent; padding: 0; margin-bottom: 0;
  }
}

/* ──────────────────────────────────────────────────────────────────────────
   /debts — kartu ringkasan yang BISA DIKLIK (owner 2026-09-14)

   Kartunya kini <button>, dan tombol bawaan peramban membawa serta rata
   tengah, border, latar abu, dan font-nya sendiri. Semua itu dinetralkan di
   sini supaya kartunya tetap terlihat persis seperti sebelumnya — yang
   berubah cuma bahwa ia bisa ditekan.
   ────────────────────────────────────────────────────────────────────────── */
.hp-kartu {
  display: block; width: 100%; text-align: left;
  font: inherit; color: inherit; cursor: pointer;
  transition: border-color .12s, box-shadow .12s, background .12s;
}
.hp-kartu:hover:not(:disabled) { border-color: #c7d2fe; background: #fbfbff; }
.hp-kartu:focus-visible { outline: 2px solid #6366f1; outline-offset: 2px; }
/* Kartu yang sedang menyaring. Ditandai TEPI + garis kiri tebal, bukan warna
   latar: angka di dalamnya sudah berwarna (merah/amber/hijau) dan latar
   berwarna akan bertengkar dengannya — yang kalah selalu angkanya. */
.hp-kartu.is-aktif {
  border-color: #6366f1; box-shadow: 0 0 0 1px #6366f1 inset; background: #fbfbff;
}
.hp-kartu.is-aktif::before {
  content: ""; position: absolute; left: 0; top: 0.6rem; bottom: 0.6rem;
  width: 3px; border-radius: 0 3px 3px 0; background: #6366f1;
}
.hp-kartu { position: relative; }
/* Kartu yang memang bukan irisan baris (Sisa Kewajiban & Sisa Pokok di tab
   Eksternal): tak diredupkan sampai pudar — angkanya tetap harus terbaca —
   cuma kehilangan tanda "bisa ditekan". */
.hp-kartu:disabled { cursor: default; }
.hp-kartu:disabled:hover { border-color: inherit; background: inherit; }

/* ===== Halaman Tutup Buku =====================================================
   Ditulis sebagai CSS biasa, BUKAN utility Tailwind: subset SCM dibangun lebih
   dulu dari kelas yang sudah terpakai, jadi kelas baru yang cuma muncul di sini
   tak akan ikut ter-build ([[scm-tailwind-subset-gotcha]]). */
.tb-intro p { margin: 0 0 .5rem; }
.tb-jelas { color: #6b7280; font-size: .85rem; line-height: 1.5; }
.tb-merah { color: #b91c1c; }

.tb-kartu-baris { display: flex; flex-wrap: wrap; gap: .75rem; margin: .75rem 0; }
.tb-kartu {
  flex: 1 1 12rem; display: flex; flex-direction: column; gap: .15rem;
  background: #fff; border: 1px solid #e5e7eb; border-radius: .5rem; padding: .85rem 1rem;
}
.tb-kartu-angka { font-size: 1.6rem; font-weight: 700; line-height: 1.1; }
.tb-kartu-label { font-weight: 600; font-size: .9rem; }
.tb-kartu-jelas { color: #6b7280; font-size: .78rem; }
/* Kartu "ditahan" sengaja TIDAK merah: ini bukan galat, ini fitur menolak
   melakukan sesuatu yang berbahaya. Merah akan memancing orang mencari cara
   menghabiskannya. */
.tb-kartu-tahan { border-color: #fcd34d; background: #fffbeb; }

.tb-peringatan { list-style: none; margin: .75rem 0; padding: 0; display: flex; flex-direction: column; gap: .4rem; }
.tb-peringatan li { display: flex; gap: .55rem; align-items: flex-start; padding: .6rem .8rem; border-radius: .45rem; font-size: .88rem; }
.tb-peringatan li i { margin-top: .15rem; }
.tb-p-penting { background: #fef2f2; border: 1px solid #fecaca; color: #991b1b; }
.tb-p-tahan { background: #fffbeb; border: 1px solid #fcd34d; color: #92400e; }
.tb-aman { color: #166534; background: #f0fdf4; border: 1px solid #bbf7d0; padding: .6rem .8rem; border-radius: .45rem; font-size: .88rem; }

.tb-langkah { margin-top: 1.25rem; }
.tb-langkah > h3 { display: flex; align-items: center; gap: .5rem; font-size: 1rem; font-weight: 700; margin: 0 0 .35rem; }
.tb-no {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.6rem; border-radius: 999px;
  background: #1f2937; color: #fff; font-size: .85rem;
}
.tb-aku { display: inline-flex; align-items: center; gap: .45rem; margin-left: .75rem; font-size: .88rem; }

.tb-grp-label { display: flex; gap: .55rem; align-items: flex-start; cursor: pointer; }
.tb-grp-label input:disabled { cursor: default; }
.tb-tahan-jelas {
  display: flex; gap: .5rem; margin-top: .5rem; padding: .5rem .65rem;
  background: #fffbeb; border: 1px solid #fcd34d; border-radius: .4rem;
  font-size: .8rem; color: #92400e; line-height: 1.45;
}
.tb-contoh { font-family: ui-monospace, monospace; font-size: .75rem; }

.tb-aksi { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; margin-top: .75rem; }
.tb-aksi #tb-catatan { flex: 1 1 18rem; }
.tb-simulasi { margin-top: .75rem; padding: .75rem .9rem; background: #f8fafc; border: 1px solid #e2e8f0; border-radius: .45rem; font-size: .88rem; }
.tb-simulasi ul { margin: .4rem 0 .5rem 1.1rem; }

.tb-fisik { max-width: 9rem; text-align: right; }
.tb-tanda { font-size: .75rem; padding: .15rem .45rem; border-radius: 999px; background: #f1f5f9; color: #475569; }
.tb-tanda-awas { background: #fef3c7; color: #92400e; }
.tb-nonaktif { font-size: .72rem; color: #94a3b8; }

@media (max-width: 640px) {
  .tb-kartu-baris { flex-direction: column; }
  .tb-aksi { flex-direction: column; align-items: stretch; }
}

/* Wizard Tutup Buku (15 Sep): stepper 5 tahap + isi tahap. Status "selesai"
   tiap tahap datang dari server — kelas di sini cuma menggambarnya. */
.tbw-sesi-kepala { display: flex; flex-wrap: wrap; justify-content: space-between; gap: .5rem; align-items: flex-start; }
.tbw-sesi-judul { font-weight: 700; font-size: 1.02rem; margin: 0; }
.tbw-judul { font-size: 1.05rem; font-weight: 700; margin: 0 0 .4rem; }
.tbw-stepper {
  list-style: none; margin: 1rem 0; padding: 0; display: flex; gap: .25rem;
  counter-reset: none; overflow-x: auto;
}
.tbw-step { flex: 1 1 0; min-width: 5.5rem; position: relative; }
.tbw-step::before {
  content: ""; position: absolute; top: 1.05rem; left: -50%; right: 50%; height: 2px; background: #e5e7eb;
}
.tbw-step:first-child::before { display: none; }
.tbw-step.is-selesai::before, .tbw-step.is-sekarang::before { background: #16a34a; }
.tbw-step > button {
  position: relative; width: 100%; display: flex; flex-direction: column; align-items: center; gap: .3rem;
  background: none; border: 0; padding: .1rem .2rem .35rem; cursor: pointer; border-radius: .4rem; color: #6b7280;
}
.tbw-step-bulat {
  display: inline-flex; align-items: center; justify-content: center; width: 2.1rem; height: 2.1rem;
  border-radius: 999px; background: #fff; border: 2px solid #d1d5db; font-weight: 700; font-size: .9rem;
}
.tbw-step-label { font-size: .78rem; font-weight: 600; text-align: center; line-height: 1.2; }
.tbw-step.is-selesai .tbw-step-bulat { background: #16a34a; border-color: #16a34a; color: #fff; }
.tbw-step.is-sekarang .tbw-step-bulat { border-color: #2563eb; color: #2563eb; box-shadow: 0 0 0 4px #dbeafe; }
.tbw-step.is-sekarang > button { color: #1d4ed8; }
.tbw-step.is-dilihat > button { background: #f1f5f9; }
.tbw-step.is-dilihat .tbw-step-label { color: #111827; }
.tbw-isi { border-top: 1px solid #e5e7eb; padding-top: 1rem; }

.tbw-rencana { margin: .75rem 0 0 1.2rem; font-size: .9rem; line-height: 1.6; }
.tbw-aksi-bawah { display: flex; flex-wrap: wrap; gap: .6rem; justify-content: flex-end; margin-top: 1rem; }
.tbw-aksi-kiri { justify-content: flex-start; }
.tbw-tombol-besar { padding: .65rem 1.2rem; font-size: .95rem; }
.tbw-tautan { background: none; border: 0; padding: 0; color: #2563eb; cursor: pointer; font-size: .85rem; }
.tbw-tautan:hover { text-decoration: underline; }
.tbw-tautan-redup { color: #6b7280; }

.tbw-progres { height: .6rem; background: #e5e7eb; border-radius: 999px; overflow: hidden; margin: .75rem 0 .35rem; }
.tbw-progres-isi { height: 100%; background: #16a34a; transition: width .3s; }
.tbw-progres-teks { font-size: .88rem; margin: 0 0 .6rem; display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.tbw-cari-baris { margin: .5rem 0; }
.tbw-hitung { white-space: nowrap; font-size: .8rem; padding: .3rem .6rem; }

.tbw-rek-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); gap: .75rem; margin-top: .5rem; }
.tbw-rek { border: 1px solid #e5e7eb; border-radius: .5rem; padding: .8rem .9rem; background: #fff; }
.tbw-rek-selesai { background: #f9fafb; }
.tbw-rek-kepala { display: flex; justify-content: space-between; gap: .5rem; align-items: flex-start; }
.tbw-rek-form { margin-top: .6rem; }
.tbw-rek-baris { display: flex; gap: .5rem; }
.tbw-rek-baris input { flex: 1 1 auto; min-width: 0; text-align: right; }
.tbw-rek-hasil { margin: .5rem 0 0; font-size: .86rem; display: flex; flex-direction: column; gap: .15rem; }
.tbw-lencana { font-size: .72rem; font-weight: 600; padding: .15rem .5rem; border-radius: 999px; background: #f1f5f9; color: #475569; white-space: nowrap; }
.tbw-lencana-cocok { background: #dcfce7; color: #166534; }
.tbw-lencana-setel { background: #fef3c7; color: #92400e; }

.tbw-kurang { list-style: none; padding: 0; margin: .5rem 0; display: flex; flex-direction: column; gap: .4rem; }
.tbw-kurang .tbw-tautan { color: #b45309; font-size: .9rem; }
.tbw-ringkas { display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); gap: .5rem .9rem; margin: .75rem 0; }
.tbw-ringkas > div { border: 1px solid #e5e7eb; border-radius: .45rem; padding: .55rem .75rem; }
.tbw-ringkas dt { font-size: .75rem; color: #6b7280; }
.tbw-ringkas dd { margin: 0; font-weight: 600; font-size: .9rem; }
#tbw-catatan { width: 100%; }

/* Daftar dokumen DITAHAN (16 Sep): tertutup secara bawaan — ia jawaban atas
   "dokumen mana", bukan hal pertama yang perlu dibaca di tahap ini. */
.tbw-ditahan { margin-top: .75rem; border: 1px solid #fcd34d; background: #fffbeb; border-radius: .45rem; }
.tbw-ditahan > summary {
  cursor: pointer; padding: .6rem .8rem; font-size: .88rem; font-weight: 600; color: #92400e;
  display: flex; align-items: center; gap: .5rem;
}
.tbw-ditahan[open] > summary { border-bottom: 1px solid #fcd34d; }
.tbw-ditahan > *:not(summary) { margin: .6rem .8rem; }
.tbw-ditahan .data-table { background: #fff; }
.tbw-kode { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .8rem; color: #1d4ed8; white-space: nowrap; }
.tbw-kode:hover { text-decoration: underline; }
.tbw-kode i { font-size: .65rem; opacity: .7; }
.tb-kartu-tombol { cursor: pointer; text-align: left; font: inherit; }
.tb-kartu-tombol:hover { border-color: #f59e0b; }
.tbw-nilai { font-variant-numeric: tabular-nums; white-space: nowrap; }
.tbw-total > td { font-weight: 700; background: #fef3c7; border-top: 2px solid #fcd34d; font-variant-numeric: tabular-nums; }
.tbw-total-samar > td { font-weight: 600; background: #fffbeb; border-top: 0; color: #92400e; font-size: .85rem; }
.tbw-pilihan { display: flex; gap: .5rem; align-items: flex-start; font-size: .82rem; line-height: 1.5; margin-top: .4rem; }
.tbw-pilihan input { margin-top: .25rem; flex: none; }

/* Hitung cepat (17 Sep): jumlah fisik diketik langsung di baris barangnya.
   Kolom isian dibuat SEMPIT dan rata kanan supaya ratusan baris tetap terbaca
   sebagai satu kolom angka, dan `tabular-nums` menjaga digitnya sejajar. */
.tbw-isi-kepala { text-align: right; white-space: nowrap; }
.tbw-isi-sel { white-space: nowrap; text-align: right; }
.tbw-isi-input {
  width: 6.5rem; max-width: 40vw; display: inline-block; text-align: right;
  font-variant-numeric: tabular-nums; padding-top: .3rem; padding-bottom: .3rem;
}
.tbw-satuan { font-size: .75rem; color: #6b7280; margin-left: .35rem; }
/* Kelas KEDUA, bukan menimpa `.tbw-hitung`: di outlet yang mewajibkan foto,
   baris yang sama masih memakai tombol `btn-secondary tbw-hitung` yang lama. */
.tbw-hitung-tautan { padding: 0; font-size: .78rem; color: #2563eb; }
.tbw-hitung-tautan:hover { text-decoration: underline; }
.tbw-hitung-tautan i { font-size: .65rem; opacity: .7; }

/* Bilah simpan MENEMPEL di bawah layar: pada 341 baris, tombol yang duduk di
   ujung tabel berarti menggulir sejauh itu tiap kali mau menyimpan. */
.tbw-simpan-bilah {
  position: sticky; bottom: 0; z-index: 5; display: flex; flex-wrap: wrap; gap: .6rem;
  align-items: center; justify-content: flex-end; margin-top: .6rem;
  padding: .6rem .75rem; background: #f8fafc; border: 1px solid #e2e8f0; border-radius: .5rem;
  box-shadow: 0 -2px 8px rgba(15, 23, 42, .06);
}
.tbw-simpan-info { margin-right: auto; font-size: .86rem; color: #334155; }
.tbw-hasil-simpan {
  margin: .75rem 0; padding: .7rem .85rem; border: 1px solid #bbf7d0; background: #f0fdf4; border-radius: .45rem;
}
.tbw-hasil-simpan > p { margin: 0 0 .4rem; font-size: .88rem; color: #166534; }
.tbw-hasil-simpan .data-table { background: #fff; }
.tb-hijau { color: #15803d; }

.tbw-mulai-baris { display: flex; flex-wrap: wrap; gap: .75rem; align-items: flex-end; margin: .9rem 0; }
.tbw-berhasil { text-align: center; }
.tbw-berhasil h3 { font-size: 1.15rem; font-weight: 700; margin: .4rem 0; }
.tbw-berhasil .tbw-rencana { text-align: left; display: inline-block; }
.tbw-berhasil .tbw-aksi-bawah { justify-content: center; }
.tbw-berhasil-ikon { font-size: 2.6rem; color: #16a34a; }

@media (max-width: 640px) {
  .tbw-step { min-width: 3.6rem; }
  .tbw-step-label { font-size: .68rem; }
  .tbw-step-bulat { width: 1.8rem; height: 1.8rem; }
  .tbw-step::before { top: .9rem; }
  .tbw-aksi-bawah .btn-primary { flex: 1 1 auto; }
  .tbw-rek-grid { grid-template-columns: 1fr; }
}

/* ===== Cari Transaksi (/cari) ==============================================
   CSS biasa, BUKAN utility Tailwind: subset SCM dibangun dari kelas yang sudah
   terpakai, jadi kelas baru yang cuma muncul di sini tak ikut ter-build. */
.cari-kotak { margin-bottom: .75rem; }
.cari-input-bungkus { position: relative; }
.cari-ikon { position: absolute; left: .85rem; top: 50%; transform: translateY(-50%); color: #9ca3af; pointer-events: none; }
.cari-input { padding-left: 2.4rem !important; padding-right: 2.4rem !important; font-size: 1rem; height: 2.9rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .01em; }
.cari-muat { position: absolute; right: .85rem; top: 50%; transform: translateY(-50%); color: #6366f1; }
.cari-bantu { margin: .5rem 0 0; font-size: .78rem; color: #6b7280; line-height: 1.5; }
.cari-pintas { display: inline-block; margin-left: .25rem; color: #9ca3af; }
.cari-pintas kbd, .cari-bantu kbd { font-family: inherit; font-size: .72rem; padding: 0 .3rem; border: 1px solid #d1d5db; border-bottom-width: 2px; border-radius: .25rem; background: #fff; color: #4b5563; }

.cari-ringkas { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin: 0 0 .5rem; min-height: 1rem; }
.cari-jumlah { font-size: .8rem; font-weight: 600; color: #374151; margin-right: .25rem; }
.cari-chip-diam { font-size: .72rem; padding: .1rem .5rem; border-radius: 999px; background: #f1f5f9; color: #475569; }
.cari-catatan { font-size: .72rem; color: #b45309; }

.cari-hasil { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .4rem; }
.cari-baris {
  display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem;
  padding: .7rem .9rem; background: #fff; border: 1px solid #e5e7eb; border-radius: .6rem;
  text-decoration: none; color: inherit;
}
.cari-baris:hover { border-color: #c7d2fe; background: #fafaff; }
.cari-baris.is-terpilih { border-color: #6366f1; box-shadow: 0 0 0 1px #6366f1 inset; background: #f5f7ff; }
.cari-baris-kiri { min-width: 0; flex: 1 1 auto; }
.cari-baris-kanan { display: flex; flex-direction: column; align-items: flex-end; gap: .25rem; flex-shrink: 0; }
.cari-kode-baris { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }
.cari-kode { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .92rem; font-weight: 600; color: #3730a3; word-break: break-all; }
.cari-sorot { background: #fef08a; color: inherit; border-radius: .15rem; padding: 0 .05rem; }
.cari-jenis { font-size: .7rem; padding: .05rem .45rem; border-radius: 999px; background: #eef2ff; color: #4338ca; white-space: nowrap; }
.cari-lencana { font-size: .66rem; padding: .02rem .4rem; border-radius: 999px; white-space: nowrap; }
.cari-lencana-persis { background: #dcfce7; color: #166534; }
.cari-ket { font-size: .8rem; color: #374151; margin-top: .15rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cari-meta { font-size: .72rem; color: #6b7280; margin-top: .15rem; }
.cari-titik { margin: 0 .35rem; color: #d1d5db; }
.cari-tenant { color: #7c3aed; }
.cari-nominal { font-size: .85rem; font-weight: 600; color: #111827; white-space: nowrap; }
.cari-status { font-size: .7rem; padding: .05rem .45rem; border-radius: 999px; background: #f3f4f6; color: #4b5563; white-space: nowrap; }
/* Tanda Mutasi Kas (22 Sep 2026): hijau = masuk, merah = keluar, kuning =
   perpindahan antar kas. Warnanya CSS biasa — subset Tailwind SCM tak memuat
   kelas yellow-*, dan panah kuning polos di atas putih nyaris tak terbaca,
   jadi tiap panah duduk di lingkaran berlatar muda. */
.cari-nominal-baris { display: flex; align-items: center; gap: .4rem; }
.cari-kas { display: inline-flex; gap: .2rem; }
.cari-kas-tanda { display: inline-flex; align-items: center; justify-content: center; width: 1.3rem; height: 1.3rem; border-radius: 999px; font-size: .7rem; flex-shrink: 0; }
.cari-kas-masuk { background: #dcfce7; color: #16a34a; }
.cari-kas-keluar { background: #ffe4e6; color: #e11d48; }
.cari-kas-mutasi { background: #fef9c3; color: #ca8a04; }
.cari-kas-legenda { display: inline-flex; flex-wrap: wrap; align-items: center; gap: .3rem; font-size: .72rem; color: #6b7280; margin-left: auto; }
.cari-kas-legenda .cari-kas-tanda { width: 1.1rem; height: 1.1rem; font-size: .6rem; margin-left: .2rem; }
.cari-kas-tanpa { color: #9ca3af; }
.cari-awalan-atas { display: flex; align-items: center; justify-content: space-between; gap: .4rem; width: 100%; }
.cari-kas-legenda-awalan { display: flex; margin: -.2rem 0 .6rem; }

.cari-pesan { font-size: .85rem; color: #6b7280; margin: .25rem 0 .75rem; }
.cari-pesan-kosong { font-size: .88rem; color: #374151; margin: 0 0 .25rem; }
.cari-pesan-kosong i { color: #6366f1; margin-right: .25rem; }
.cari-seksi { margin-bottom: .75rem; }
.cari-seksi-judul { font-size: .75rem; font-weight: 600; color: #6b7280; text-transform: uppercase; letter-spacing: .04em; margin: 0 0 .5rem; }
.cari-chip-baris { display: flex; flex-wrap: wrap; gap: .4rem; }
.cari-chip { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .8rem; padding: .25rem .6rem; border: 1px solid #e5e7eb; border-radius: 999px; background: #fff; color: #374151; cursor: pointer; }
.cari-chip:hover { border-color: #a5b4fc; color: #3730a3; }
.cari-awalan-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: .4rem; }
.cari-awalan { display: flex; flex-direction: column; align-items: flex-start; gap: .1rem; padding: .5rem .65rem; border: 1px solid #e5e7eb; border-radius: .5rem; background: #fff; cursor: pointer; text-align: left; }
.cari-awalan:hover { border-color: #a5b4fc; background: #fafaff; }
.cari-awalan-kode { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .82rem; font-weight: 700; color: #3730a3; }
.cari-awalan-label { font-size: .74rem; color: #6b7280; }

@media (max-width: 640px) {
  .cari-baris { flex-direction: column; gap: .35rem; }
  .cari-baris-kanan { flex-direction: row; align-items: center; }
  .cari-ket { white-space: normal; }
}

/* Lencana jenis dokumen di kartu papan Kas Kecil (16 Sep 2026): pembelian &
   belanja aset yang dibayar kas kecil kini tampil sebagai kartu di papan yang
   sama dengan pengeluaran. CSS biasa, bukan utility Tailwind — subset SCM tak
   memuat kelas yang baru muncul di sini. */
.ptc-jenis { display: inline-block; margin-left: .35rem; padding: 0 .4rem; border-radius: 999px;
  font-size: .62rem; font-weight: 700; line-height: 1.35rem; vertical-align: middle; letter-spacing: .02em; }
.ptc-jenis-pembelian { background: #e0e7ff; color: #3730a3; }
.ptc-jenis-aset { background: #fae8ff; color: #86198f; }

/* TERTAHAN (owner 21 Sep 2026) — pita catatan pemeriksa di kartu kas kecil.
   Warnanya sengaja OREN, bukan merah: merah sudah berarti "Ditolak" di papan
   ini (tepi kolom #f43f5e), dan dokumen tertahan justru BELUM ditolak — ia
   masih hidup, cuma menunggu diperbaiki. Menyamakan warnanya akan membuat dua
   keadaan yang berlawanan akibatnya terbaca sama sekilas pandang. */
.ptc-tahan {
  display: flex; gap: .375rem; align-items: flex-start;
  margin-top: .25rem; padding: .25rem .375rem;
  font-size: 10px; line-height: 1.35;
  color: #9a3412; background: #fff7ed;
  border: 1px solid #fed7aa; border-radius: .375rem;
}
.ptc-tahan > i { margin-top: .1rem; flex: 0 0 auto; }
/* Siapa & kapan, satu baris di bawah catatannya — bukan di belakangnya:
   catatan bisa panjang, dan nama yang menempel di ujung kalimat terbaca
   seperti bagian dari catatan itu. */
.ptc-tahan-oleh { display: block; color: #c2743a; margin-top: .1rem; }
/* Bentuk HALAMAN DETAIL: lebih besar, dan duduk di paling atas. Yang membuka
   halaman ini karena kartunya tertahan datang untuk MEMBACA alasannya — di
   kartu papan pita ini cuma penanda, di sini ia instruksinya. */
.ptc-tahan-besar { font-size: 12px; padding: .5rem .625rem; gap: .5rem; border-radius: .5rem; }
.ptc-tahan-isi { display: block; margin-top: .15rem; color: #7c2d12; }

/* ===== Lengkapi Tanggal Mutasi (19 Sep 2026) =====
   Halaman kerja, bukan laporan: orang duduk di sini mengisi ratusan tanggal
   berturut-turut. Gayanya dibuat tenang & padat — barisnya rapat, isian
   tanggalnya sempit, dan tak ada warna yang berebut perhatian kecuali angka
   sisa di tab. */
.lm-nota {
  margin-bottom: 0.75rem;
  padding: 0.6rem 0.8rem;
  border-left: 3px solid #c7d2fe;
  border-radius: 0 0.5rem 0.5rem 0;
  background: #f8fafc;
  font-size: 0.75rem;
  line-height: 1.6;
  color: #475569;
}
.lm-nota b { color: #334155; }

.lm-tab { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.75rem; }
.lm-tab-btn {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.4rem 0.75rem;
  border: 1px solid #e2e8f0; border-radius: 9999px;
  background: #fff; color: #475569;
  font-size: 0.8125rem; font-weight: 600;
}
.lm-tab-btn:hover { border-color: #c7d2fe; }
.lm-tab-aktif { border-color: #4f46e5; color: #4338ca; background: #eef2ff; }
/* Angka sisa = alasan halaman ini dibuka. Ia yang harus menyusut, jadi ia yang
   paling terbaca di tabnya. */
.lm-jml {
  min-width: 1.6rem; padding: 0.05rem 0.4rem;
  border-radius: 9999px; background: #e2e8f0; color: #334155;
  font-size: 0.6875rem; font-weight: 700; text-align: center;
}
.lm-tab-aktif .lm-jml { background: #4f46e5; color: #fff; }

.lm-tabel td { vertical-align: middle; }
.lm-tabel .lm-tgl { max-width: 10rem; padding-top: 0.3rem; padding-bottom: 0.3rem; }
.lm-tanpa-kas {
  display: inline-block; margin-right: 0.4rem;
  padding: 0.05rem 0.4rem; border-radius: 9999px;
  background: #f1f5f9; color: #64748b;
  font-size: 0.625rem; font-weight: 600;
}
/* Kode dokumen = tautan ke dokumennya, dibuka di TAB BARU. Ikon panah-keluar
   ikut dicetak supaya "akan membuka tab baru" terbaca SEBELUM diklik — tautan
   yang diam-diam berpindah tab membuat orang mengira daftarnya hilang. */
.lm-kode {
  color: #4338ca; font-weight: 600;
  display: inline-flex; align-items: center; gap: 0.3rem;
}
.lm-kode:hover { text-decoration: underline; }
.lm-kode i { font-size: 0.625rem; opacity: 0.55; }
.lm-kode:hover i { opacity: 1; }

/* Tanggal yang dipakai buku kas selagi sumbernya kosong. Ditulis kelabu +
   berlencana "cadangan" dengan alasan yang sama seperti "(tgl. unggah)" di
   /purchase-detail: ia harus terbaca sebagai TITIPAN, bukan sebagai jawaban —
   kalau tidak, orang mengira dokumennya sudah beres dan daftar ini salah. */
.lm-sekarang { display: inline-flex; align-items: center; gap: 0.3rem; color: #64748b; }
.lm-cadangan {
  padding: 0.02rem 0.3rem; border-radius: 9999px;
  background: #fef3c7; color: #b45309;
  font-size: 0.5625rem; font-weight: 700; text-transform: uppercase;
}
/* "pakai" = menyalin tanggal cadangan ke kotak isian. Sengaja kecil & sekunder:
   ia jalan pintas, bukan tindakan yang dianjurkan lebih dulu. */
.lm-pakai {
  margin-left: 0.35rem; padding: 0.05rem 0.35rem;
  border: 1px solid #e2e8f0; border-radius: 0.3rem;
  background: #fff; color: #475569;
  font-size: 0.625rem; font-weight: 600;
}
.lm-pakai:hover { border-color: #c7d2fe; color: #4338ca; }

.lm-tautan { color: #4338ca; font-size: 0.75rem; font-weight: 600; }
.lm-tautan:hover { text-decoration: underline; }
.lm-lagi {
  margin-top: 0.6rem; padding: 0.4rem 0.6rem;
  border-radius: 0.5rem; background: #f8fafc;
  font-size: 0.6875rem; color: #64748b;
}

/* Kartu "tak ada yang tertinggal" — dipakai saat SELURUH jenis sudah nol.
   Halaman kosong tanpa keterangan terbaca seperti gagal memuat, dan orang akan
   memuat ulang berkali-kali mencari daftar yang memang sudah habis. */
.lm-selesai {
  padding: 2.5rem 1.5rem; text-align: center;
  border: 1px solid #d1fae5; border-radius: 0.9rem; background: #f0fdf4;
}
.lm-selesai-ikon { font-size: 2.25rem; color: #059669; margin-bottom: 0.5rem; }
.lm-selesai h3 { font-size: 1rem; font-weight: 700; color: #065f46; margin-bottom: 0.4rem; }
.lm-selesai p { font-size: 0.8125rem; color: #047857; max-width: 34rem; margin: 0 auto; line-height: 1.6; }
.lm-selesai-kecil { margin-top: 0.5rem !important; font-size: 0.6875rem !important; color: #6b7280 !important; }

/* ---------------------------------------------------------------------------
   Rekonsiliasi Bank (/rekonsiliasi-bank) — 20 Sep 2026.
   Prefiks .rkb-*. Yang paling menentukan di sini KOTAK REKONSILIASI: ia harus
   terbaca sebagai perhitungan yang menutup, bukan sebagai daftar angka. Karena
   itu barisnya berjarak tetap, nominalnya rata kanan dengan angka tabular, dan
   baris totalnya dipisah garis — sama seperti kertas yang dipegang orang
   keuangan sehari-hari.
--------------------------------------------------------------------------- */

.rkb-pita {
  display: flex; align-items: flex-start; gap: 0.5rem;
  padding: 0.6rem 0.85rem; border-radius: 0.6rem;
  font-size: 0.8125rem; line-height: 1.55;
}
.rkb-pita i { margin-top: 0.15rem; flex-shrink: 0; }
.rkb-pita-amber { background: #fffbeb; border: 1px solid #fde68a; color: #92400e; }
.rkb-pita-rose { background: #fff1f2; border: 1px solid #fecdd3; color: #9f1239; }

.rkb-ok { color: #047857; font-size: 0.75rem; font-weight: 600; }
.rkb-bad { color: #be123c; font-size: 0.75rem; font-weight: 600; }

/* Selisih hari pada pasangan yang cocok. Karena pencocokannya LONGGAR (nominal
   + arah, tanggal diabaikan), inilah satu-satunya tempat selisih tanggal masih
   terlihat — jadi ia sengaja dibuat menonjol, bukan diperhalus. */
.rkb-drift {
  display: inline-block; padding: 0.05rem 0.4rem;
  border-radius: 9999px; background: #fef3c7; color: #92400e;
  font-size: 0.6875rem; font-weight: 700; white-space: nowrap;
}
.rkb-baris-drift td { background: #fffdf5; }

.rkb-manual {
  display: inline-block; padding: 0.05rem 0.4rem;
  border-radius: 9999px; background: #eef2ff; color: #4338ca;
  font-size: 0.6875rem; font-weight: 700;
}

.rkb-catatan {
  margin-top: 0.2rem; display: flex; align-items: center; gap: 0.35rem;
  font-size: 0.6875rem; color: #64748b;
}
.rkb-catatan i { color: #94a3b8; }

/* --- kotak rekonsiliasi --- */
.rkb-kotak {
  border: 1px solid #e2e8f0; border-radius: 0.75rem;
  padding: 0.35rem 0.9rem; background: #f8fafc;
}
.rkb-kotak-baris {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding: 0.45rem 0; font-size: 0.8125rem; color: #475569;
}
.rkb-kotak-baris + .rkb-kotak-baris { border-top: 1px dashed #e2e8f0; }
.rkb-kotak-sub { display: block; font-size: 0.6875rem; color: #94a3b8; font-weight: 400; }
.rkb-kotak-nilai {
  font-weight: 700; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.rkb-kotak-total { border-top: 2px solid #cbd5e1 !important; font-weight: 700; color: #1e293b; }
.rkb-kotak-cek {
  margin: 0.15rem -0.9rem -0.35rem; padding: 0.5rem 0.9rem;
  border-top: 1px solid #d1fae5; border-radius: 0 0 0.75rem 0.75rem;
  background: #f0fdf4; color: #047857;
  font-size: 0.75rem; font-weight: 600;
}

.rkb-stat {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
  gap: 0.5rem; margin-top: 0.75rem;
}
.rkb-stat > div {
  padding: 0.5rem 0.65rem; border: 1px solid #e2e8f0; border-radius: 0.6rem;
  background: #fff;
}
.rkb-stat b { display: block; font-size: 1.05rem; color: #1e293b; font-variant-numeric: tabular-nums; }
.rkb-stat span { font-size: 0.6875rem; color: #64748b; line-height: 1.35; display: block; }
.rkb-stat-sorot { border-color: #fcd34d; background: #fffbeb; }
.rkb-stat-sorot b { color: #92400e; }

/* --- modal: pilih lawan pasangan --- */
.rkb-asal {
  padding: 0.55rem 0.75rem; border-radius: 0.6rem;
  border: 1px solid #e2e8f0; background: #f8fafc;
}
.rkb-pilih-wrap { max-height: 18rem; overflow-y: auto; display: flex; flex-direction: column; gap: 0.3rem; }
.rkb-pilih {
  display: flex; align-items: center; gap: 0.55rem;
  padding: 0.45rem 0.6rem; border: 1px solid #e2e8f0; border-radius: 0.5rem;
  font-size: 0.8125rem; cursor: pointer;
}
.rkb-pilih:hover { border-color: #c7d2fe; background: #f8fafc; }
.rkb-pilih input { flex-shrink: 0; }

/* Di ponsel tabel perbandingan tetap bisa digeser mendatar (tableWrap sudah
   overflow-x-auto); yang dirapatkan hanya kotak & statistiknya. */
@media (max-width: 640px) {
  .rkb-kotak-baris { font-size: 0.78125rem; }
  .rkb-stat { grid-template-columns: repeat(2, 1fr); }
}

/* Kartu ringkasan /cash-accounts yang lingkupnya OUTLET, bukan per rekening
   (20 Sep 2026). Utang supplier & piutang melekat ke outlet — `purchase_orders`
   tak punya kolom kas sama sekali — jadi keduanya TAK BOLEH terbaca sebagai
   penjumlahan kolom tabel di bawahnya. Beda latar + kata "outlet ini" adalah
   satu-satunya yang membedakannya; menghapus salah satunya membuat angka
   outlet tampak seperti angka rekening. */
.ca-kartu-outlet { border-color: #c7d2fe; background: #eef2ff; }
.ca-kartu-outlet dt { color: #4338ca; }
.ca-lingkup {
  display: inline-block; margin-left: 0.15rem; padding: 0 0.3rem;
  border-radius: 9999px; background: #c7d2fe; color: #312e81;
  font-size: 0.5625rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.02em; vertical-align: middle;
}

/* Chip "sedang disaring per rekening kas" — dipakai /debts & /setoran-bank saat
   didatangi dari kolom angka /cash-accounts (20 Sep 2026). WAJIB terlihat:
   halaman yang menampilkan sebagian data tanpa mengatakan bahwa ia sedang
   menyaring akan dibaca sebagai halaman yang kehilangan datanya. */
.hp-chip-kas {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.45rem;
  margin-bottom: 0.6rem; padding: 0.4rem 0.7rem;
  border: 1px solid #c7d2fe; border-radius: 9999px; background: #eef2ff;
  color: #3730a3; font-size: 0.75rem;
}
.hp-chip-kas i { color: #6366f1; }
.hp-chip-nota { color: #6366f1; font-size: 0.6875rem; }
.hp-chip-kas button {
  margin-left: auto; border: 0; background: none; cursor: pointer;
  color: #4338ca; font-size: 1rem; line-height: 1; padding: 0 0.2rem;
}
.hp-chip-kas button:hover { color: #1e1b4b; }

/* Blok Vendor di /ftr-detail (21 Sep 2026). Catatan jangkauan pada modal
   "Ubah info supplier": data bank supplier dibaca LIVE oleh setiap dokumen
   yang menunjuknya, jadi menyuntingnya dari halaman SATU dokumen ikut
   mengubah tujuan transfer di semua dokumen lain. Peringatannya harus terbaca
   sebelum tombol simpan, bukan sesudah. */
.ftr-sup-nota {
  display: flex; align-items: flex-start; gap: 0.45rem;
  margin-bottom: 0.6rem; padding: 0.5rem 0.7rem;
  border: 1px solid #fde68a; border-radius: 0.5rem; background: #fffbeb;
  color: #92400e; font-size: 0.75rem; line-height: 1.5;
}
.ftr-sup-nota i { margin-top: 0.15rem; flex-shrink: 0; }
.ftr-sup-nota-biru { border-color: #c7d2fe; background: #eef2ff; color: #3730a3; }
.ftr-sup-nota-biru i { color: #6366f1; }

/* Tombol aksi di baris Vendor — kecil, menempel di kanan namanya. */
.ftr-sup-aksi { display: inline-flex; gap: 0.25rem; flex-wrap: wrap; }

/* --- /reports: Tabel Pengeluaran berkelompok (KODE > kebutuhan) ------------
   Owner 24 Sep 2026. Kelompok dan anaknya WAJIB bisa dibedakan sekilas: tanpa
   itu baris induk terbaca sebagai transaksi tersendiri dan totalnya terlihat
   seperti baris yang terhitung dua kali. Pembedanya latar + garis atas untuk
   induk, dan lekukan untuk anak — bukan warna teks saja, yang hilang begitu
   barisnya dipudarkan (`opacity-60`) karena tak tercentang. */
.rpt-grup > td { background: #f8fafc; border-top: 1px solid #e2e8f0; }
.rpt-grup:first-child > td { border-top: 0; }
.rpt-anak > td:nth-child(2) { padding-left: 1.5rem; }
.rpt-kode {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.625rem; letter-spacing: 0.02em;
  color: #4f46e5; background: #eef2ff;
  border-radius: 0.25rem; padding: 0.05rem 0.3rem;
}
/* Tombol buka/tutup per KODE. Sasaran kliknya dibuat 1.25rem penuh — chevron
   9px saja terlalu kecil untuk jari, dan meleset sedikit di baris ini berarti
   mengenai kotak centang di sebelahnya, yang MEMATIKAN sekelompok pengeluaran
   dari perhitungan alih-alih melipatnya. */
.rpt-lipat {
  flex: none; width: 1.25rem; height: 1.25rem;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; background: transparent; cursor: pointer;
  color: #64748b; font-size: 0.5625rem; border-radius: 0.25rem;
}
.rpt-lipat:hover { background: #e2e8f0; color: #334155; }
/* Kelompok tertutup tetap menampilkan totalnya, jadi garis bawahnya dipertegas
   supaya ia tak terbaca menyatu dengan kelompok berikutnya. */
.rpt-grup.rpt-tutup > td { border-bottom: 1px solid #e2e8f0; }

/* Pita penjelas di atas Tabel Pengeluaran. Ada sejak kelompoknya tertutup
   secara bawaan: tanpa keterangan, yang membuka halaman melihat delapan baris
   ringkas dan tak ada apa pun yang memberi tahu bahwa di baliknya masih ada
   rincian — persis kelas cacat "terlihat benar selamanya". */
.rpt-penjelas {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem; flex-wrap: wrap;
  margin-bottom: .5rem; padding: .35rem .6rem;
  border: 1px solid #e2e8f0; border-radius: .5rem; background: #f8fafc;
  font-size: 11px; line-height: 1.45; color: #475569;
}
.rpt-penjelas b { color: #334155; }
.rpt-penjelas > span:first-child > .fa-layer-group { color: #94a3b8; margin-right: .3rem; }
.rpt-penjelas-ikon {
  font-size: .5rem; color: #64748b;
  background: #e2e8f0; border-radius: .2rem; padding: .12rem .22rem;
}
.rpt-penjelas-aksi { display: inline-flex; align-items: center; gap: .4rem; flex: none; }
/* Tombol yang BERPERILAKU seperti tautan, tapi tetap <button>: elemen yang
   tak menuju ke mana pun bukan tautan, dan <a href="#"> akan menambah entri
   riwayat browser tiap kali ditekan. */
.rpt-tautan {
  border: 0; background: transparent; padding: 0; cursor: pointer;
  color: #4f46e5; font-size: 11px; text-decoration: underline;
}
.rpt-tautan:hover { color: #3730a3; }

/* "N transaksi" yang bisa diklik. Digarisbawahi putus-putus, bukan polos:
   angka yang bisa diklik harus TERLIHAT bisa diklik — kalau tidak, ia tetap
   angka buntu seperti sebelumnya, cuma kebetulan responsif. */
.rpt-qty {
  border: 0; background: transparent; padding: 0; cursor: pointer;
  color: #64748b; font-size: 11px;
  text-decoration: underline dotted; text-underline-offset: 2px;
}
.rpt-qty:hover { color: #4f46e5; text-decoration-style: solid; }
/* Daftar kode di dalam modal: rapat, monospace, dan MENGGULIR — satu baris
   agregat bisa memuat ratusan dokumen, dan modal yang memanjang tanpa batas
   mendorong tombol tutupnya keluar layar. */
.rpt-dok-grid {
  display: flex; flex-wrap: wrap; gap: .3rem;
  max-height: 22rem; overflow-y: auto;
  padding: .5rem; border: 1px solid #e2e8f0; border-radius: .5rem; background: #f8fafc;
}
.rpt-dok-kode {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px; line-height: 1;
  padding: .25rem .4rem; border-radius: .25rem;
  background: #fff; border: 1px solid #e2e8f0; color: #475569;
  white-space: nowrap;
}
.rpt-dok-taut { color: #4f46e5; border-color: #c7d2fe; text-decoration: none; }
.rpt-dok-taut:hover { background: #eef2ff; border-color: #a5b4fc; }
.rpt-dok-nota {
  font-size: 11px; color: #92400e; background: #fffbeb;
  border: 1px solid #fde68a; border-radius: .4rem;
  padding: .35rem .5rem; margin-bottom: .5rem;
}

/* --- /purchase-detail: kebutuhan turunan dengan NOMINALnya ----------------
   Daftar, bukan satu baris berpemisah titik: begitu tiap kebutuhan membawa
   cacah barang DAN rupiah, teks sebaris berubah jadi deret angka yang harus
   diurai mata — dan nominal yang salah dibaca di sini berakhir di anggaran.
   Nilainya dirata KANAN supaya digitnya sejajar dan bisa dibandingkan sekilas. */
.pd-keb-daftar { display: block; }
.pd-keb-baris {
  display: flex; align-items: baseline; gap: .4rem;
  padding: .1rem 0;
}
.pd-keb-nama { flex: 1 1 auto; min-width: 0; }
.pd-keb-brg { flex: none; font-size: 11px; color: #94a3b8; }
.pd-keb-nilai {
  flex: none; min-width: 6.5rem; text-align: right;
  font-variant-numeric: tabular-nums; color: #334155;
}
/* Sisa tanpa kebutuhan: dibedakan warnanya, sebab ia BUKAN pos anggaran —
   ia barang yang belum punya jawaban, dan cara membetulkannya berbeda. */
.pd-keb-sisa .pd-keb-nama { color: #b45309; }
.pd-keb-sisa .pd-keb-nilai { color: #b45309; }

/* --- /reports: pemilih versi HPP ------------------------------------------
   Dua tombol SALING-KUNCI, bukan dua kotak centang. Kotak centang mengizinkan
   keadaan "keduanya menyala", dan menjumlahkan dua HPP menghitung bahan baku
   dua kali — keadaan terlarang yang bisa DIWAKILI cepat atau lambat tercapai.
   Bentuk kendalinya yang menegakkan aturannya, bukan cuma kode di belakang. */
.rpt-hpp {
  display: inline-flex; padding: 2px; gap: 2px;
  background: #f1f5f9; border: 1px solid #e2e8f0; border-radius: .5rem;
}
.rpt-hpp-opsi {
  border: 0; background: transparent; cursor: pointer;
  font-size: 11px; font-weight: 600; color: #64748b;
  padding: .25rem .6rem; border-radius: .375rem; white-space: nowrap;
  /* Tombol ini DITEKAN-TAHAN untuk memunculkan penjelasnya (owner 25 Sep
     2026). Tanpa ketiganya, tahan di sentuh memicu pilih-teks, gagang seret,
     dan callout iOS — semuanya membatalkan pointer-nya, jadi penjelasnya tak
     pernah terbuka justru di perangkat tempat gerakan itu paling lazim. */
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  touch-action: manipulation;
}
.rpt-hpp-opsi:hover { color: #334155; }
.rpt-hpp-opsi.rpt-hpp-on { background: #fff; color: #4f46e5; box-shadow: 0 1px 2px rgba(15,23,42,.08); }
/* Penjelasnya: dua angka bernama sama ("HPP") yang isinya berbeda adalah cara
   termudah membuat orang membaca yang salah tanpa pernah tahu. */
/* SAKELAR dua tabel beban (Per Kode / Per Kebutuhan, owner 24 Sep 2026).
   Kelasnya SENDIRI, tidak menumpang `.rpt-hpp-opsi`: dua tempat memanggil
   `querySelectorAll(".rpt-hpp-opsi")` untuk memilih versi HPP, dan tombol yang
   ikut tertangkap di sana akan menyetel `hppMode` jadi undefined. Satu kelas,
   satu pemakai — pelajaran `.cad-legenda`. */
/* CHIP STATUS TRANSAKSI: bobot yang diaturnya, dan yang NOL mengaku nol
   (owner 25 Sep 2026: *"filter berdasarkan Status Transaksi sepertinya belum
   berfungsi"*). Saringannya bekerja; yang tak bekerja cuma chip "Menunggu",
   sebab NOL baris berstatus itu sejak sumbunya pindah ke status transaksi
   (keputusan owner 24 Sep). Chip yang tak pernah bisa mengubah apa pun tak
   bisa dibedakan dari saringan yang rusak — jadi ia mengatakannya. */
.rpt-st-bobot { font-size: 10px; color: #94a3b8; white-space: nowrap; }
.rpt-stchip.rpt-st-kosong { opacity: .6; border-style: dashed; }
.rpt-stchip.rpt-st-kosong .rpt-st-bobot { font-style: italic; }

.rpt-tab {
  display: inline-flex; padding: 2px; gap: 2px;
  background: #f1f5f9; border: 1px solid #e2e8f0; border-radius: .5rem;
}
.rpt-tab-opsi, .rpt-in-opsi {
  border: 0; background: transparent; cursor: pointer;
  font-size: 11px; font-weight: 600; color: #64748b;
  padding: .25rem .6rem; border-radius: .375rem; white-space: nowrap;
}
.rpt-tab-opsi:hover, .rpt-in-opsi:hover { color: #334155; }
.rpt-tab-opsi.rpt-tab-on { background: #fff; color: #be123c; box-shadow: 0 1px 2px rgba(15,23,42,.08); }
/* Sakelar PEMASUKAN: kelas sendiri (`.rpt-in-opsi`), bukan menumpang
   `.rpt-tab-opsi` — pengikat sakelar beban memanggil
   `querySelectorAll(".rpt-tab-opsi")`, jadi tombol yang ikut tertangkap di sana
   akan menukar tabel BEBAN saat orang menekan sakelar PEMASUKAN. Warnanya
   hijau mengikuti warna pemasukan di seluruh halaman ini. */
.rpt-in-opsi.rpt-in-on { background: #fff; color: #047857; box-shadow: 0 1px 2px rgba(15,23,42,.08); }
/* Penjelas versi HPP. Sejak 25 Sep 2026 ia TIDAK lagi duduk di dalam kartu
   Laba/Rugi — satu-satunya pemakainya adalah popover `.rpt-hpp-pop`, jadi
   `margin-bottom` yang dulu memberi jarak ke barisan angka dibuang; di dalam
   popover ia hanya menyisakan ruang mati di bawah teks. */
/* Nominal di kartu Laba/Rugi — BISA DIKLIK untuk melihat sumbernya (owner
   25 Sep 2026). Tampilannya sengaja nyaris sama dengan teks biasa: yang dicari
   orang di kartu ini angkanya, dan enam tombol bergaya penuh akan bersaing
   dengan angka yang justru ingin dibaca. Yang menandainya bisa ditekan cuma
   garis putus-putus tipis — muncul jelas saat disentuh kursor atau difokus
   papan ketik. `font: inherit` wajib: tombol mewarisi font peramban, dan tanpa
   ini barisan angkanya berganti rupa. */
.rpt-pl-nilai {
  font: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline dotted;
  text-decoration-color: #cbd5e1;
  text-underline-offset: 3px;
  border-radius: .25rem;
}
/* JANGAN menyetel `color` di sini. Tiap baris membawa kelas warnanya sendiri
   (`text-emerald-700` untuk pemasukan, `text-red-600` untuk beban,
   `text-indigo-700` untuk Laba Bersih, `text-sky-700` untuk Laba Kotor), dan
   `.rpt-pl-nilai` berspesifisitas SAMA dengan kelas-kelas itu — sementara
   app.css dimuat SESUDAH tailwind.css. Jadi satu `color: inherit` di sini
   memenangkan urutan sumber dan memucatkan seluruh barisan angka sekaligus,
   tanpa satu pun kelas hilang dari markup. Persis itu yang terjadi 25 Sep 2026
   dan langsung disadari owner: *"saya suka tadi nominalnya berwarna"*.
   Warna tombol datang dari preflight (`button { color: inherit }`,
   berspesifisitas elemen) yang memang KALAH oleh kelas warnanya — itulah yang
   diinginkan. */
.rpt-pl-nilai:hover { text-decoration-color: currentColor; }
.rpt-pl-nilai:focus-visible {
  outline: 2px solid #6366f1;
  outline-offset: 2px;
  text-decoration-color: currentColor;
}
/* Kelas tata letak dari barisnya (mis. `border-t pt-2` pada Laba Bersih) ikut
   menempel di tombol ini; `border: 0` di atas akan membatalkannya, jadi garis
   atasnya dikembalikan. Tanpa ini pemisah sebelum Laba Bersih hilang sebelah. */
.rpt-pl-nilai.border-t { border-top-width: 1px; }

.rpt-hpp-ket {
  font-size: 11px; line-height: 1.5; border-radius: .5rem;
  padding: .4rem .6rem; border: 1px solid;
}
.rpt-hpp-penjualan { background: #f8fafc; border-color: #e2e8f0; color: #475569; }
.rpt-hpp-belanja { background: #eef2ff; border-color: #c7d2fe; color: #3730a3; }
/* Wadah popovernya. `position: fixed` + menempel ke <body> (lihat alasannya di
   `penjelasHpp`, panels/reports.js): kartu & tabel halaman ini hidup di dalam
   `overflow-x-auto`, dan popover di dalamnya akan terpotong di layar sempit.
   Lebarnya dibatasi supaya dua kalimat tak melebar jadi satu baris panjang,
   dan tetap menyisakan tepi di layar ponsel. */
.rpt-hpp-pop {
  position: fixed; z-index: 60;
  width: max-content; max-width: min(24rem, calc(100vw - 1rem));
  filter: drop-shadow(0 6px 16px rgba(15, 23, 42, .18));
}
.rpt-hpp-pop[hidden] { display: none; }

/* ── Pembayaran Vendor Titip (/titip-payouts & /titip-payout-detail) ───────
   Tata letak & tipografi halaman ini memakai kelas SISTEM (panel-card,
   status-badge, field-input, text-right, grid-cols-*). Yang tinggal di sini
   HANYA yang tak punya padanan di sistem, karena tiap aturan privat adalah
   aturan yang bisa hilang: app.css dipakai bersama seluruh sesi dan pernah
   disalin utuh antar pohon kerja, dan 33 aturan `tp-*` versi pertama lenyap
   dari produksi dengan akibat kedua halaman tampil TANPA GAYA sama sekali.
   Menyusutkannya dari 33 ke 12 memperkecil permukaan itu.

   Ditulis di app.css, bukan <style> inline di panel, supaya
   scripts/uji_kelas_css.py bisa membuktikannya — penjaga itu tak membaca
   <style> di dalam JS. */

/* Kartu vendor. Yang diurusnya cuma SATU: kolom bertinggi sama supaya
   tombolnya sejajar walau satu kartu punya baris "menunggu bukti" dan yang
   lain tidak. Sisanya (bingkai, latar, sudut, padding) dari `panel-card p-3`.
   `mt-auto` tak ikut ter-generate di subset Tailwind di sini, jadi pendorong
   tombol ke dasar kartu ditulis sendiri. */
/* Lebar medan saringan — tiga aturan, satu sebab.
   `.field-input` adalah `width:100%`. Persentase TIDAK dihitung saat peramban
   mengukur lebar intrinsik wadah flex, jadi baris saringan diukur seolah tiap
   medannya selebar teksnya saja, lalu medannya mengembang sesudah wadahnya
   terlanjur disempitkan — dan kontrol terakhir terlempar ke baris berikutnya.
   Gejalanya: tombol yang "kadang turun sendiri" tergantung panjang label.
   Batas `max-w-*` tak menyembuhkan (ia tetap persentase di bawahnya); lebar
   PASTI menyembuhkan. Ditulis di sini, bukan dengan mengubah `dateRangeField`
   atau `.field-input` — keduanya dipakai puluhan panel lain. */
.tp-rentang{width:14rem;flex:0 0 auto}
.tp-saring{width:11.5rem;flex:0 0 auto}
.tp-status{width:10.5rem;flex:0 0 auto}

.tp-k{display:flex;flex-direction:column;gap:4px;height:100%}
.tp-k-aksi{margin-top:auto;padding-top:6px}

/* Kotak keterangan/kabar. Tiap modul SCM punya versinya sendiri (.dd-nota,
   .lm-nota, .pb-note-warn, .sb-arsip-nota …) — tak ada yang berbagi, jadi
   punya sendiri di sini mengikuti kebiasaan yang ada, bukan menyimpang. */
.tp-kabar{font-size:12px;color:#6b7280;background:#f9fafb;border:1px solid #e5e7eb;border-radius:10px;padding:8px 10px;margin-bottom:10px}
.tp-kabar-merah{background:#fef2f2;border-color:#fecaca;color:#b91c1c}

/* Blok rekening tujuan: nama bank, nomor yang bisa disalin, nama pemilik.
   Dipakai di modal pembayaran DAN di halaman detail. */
.tp-rek-kotak{border:1px solid #e5e7eb;border-radius:10px;padding:8px 10px;margin-bottom:12px;background:#f9fafb}
.tp-rek-cap{margin:0 0 4px;font-size:11px;color:#6b7280}
.tp-rek-wrap{margin-top:4px}
.tp-rek{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.tp-rek-bank{font-size:12px;font-weight:600;color:#374151}
.tp-rek-an{font-size:12px;color:#6b7280}

/* Layar sukses sesudah kode terbit. Kodenya SENGAJA besar: ini satu-satunya
   momen orang menyalinnya ke berita transfer bank. */
.tp-sukses{border:1px solid #a7f3d0;background:#ecfdf5;border-radius:12px;padding:12px;text-align:center}
.tp-sukses-cap{margin:0;font-size:12px;color:#065f46}
.tp-sukses-kode{margin:4px 0 8px;font-size:24px;font-weight:700;letter-spacing:.04em;color:#064e3b;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}

/* Petak istilah–nilai di modal (Vendor, Nominal, Kas Sumber, Keadaan). */
.tp-ringkas{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px;margin-top:12px}
.tp-ringkas-atas{margin-top:0;margin-bottom:12px}
.tp-ringkas div{border:1px solid #e5e7eb;border-radius:10px;padding:6px 10px;background:#fff}
.tp-ringkas span{display:block;font-size:11px;color:#6b7280}
.tp-ringkas b{font-size:14px;color:#1f2937}


/* ── /purchases: baris Saring (owner 24 Sep 2026) ─────────────────────────
   Baris kedua kartu kendali: Jenis, chip Status Bayar (pilih-banyak), centang
   saringan, dan Reset. Kelas sendiri, bukan utilitas Tailwind: subset
   tailwind.css tak punya sebagian besar yang dibutuhkan (lihat uji_kelas_css). */
.pur-saring {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.875rem;
  margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px dashed #e5e7eb;
}
.pur-saring-judul {
  display: inline-flex; align-items: center; gap: 0.375rem;
  font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: #9ca3af;
}
.pur-saring-grup { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.375rem; }
.pur-saring-label { font-size: 0.75rem; font-weight: 600; color: #4b5563; margin-right: 0.125rem; }
.pur-saring-select {
  height: 2rem; padding: 0 1.75rem 0 0.625rem; font-size: 0.75rem; color: #374151;
  border: 1px solid #e5e7eb; border-radius: 9999px; background-color: #fff; cursor: pointer;
}
.pur-saring-select:focus-visible { outline: 2px solid #a5b4fc; outline-offset: 1px; }
.pur-chip {
  display: inline-flex; align-items: center; gap: 0.375rem; height: 2rem;
  padding: 0 0.75rem; border: 1px solid #e5e7eb; border-radius: 9999px;
  background: #fff; color: #4b5563; font-size: 0.75rem; font-weight: 600;
  cursor: pointer; transition: border-color .15s, background-color .15s, color .15s;
}
.pur-chip:hover { border-color: #a5b4fc; color: #3730a3; }
.pur-chip:focus-visible { outline: 2px solid #a5b4fc; outline-offset: 1px; }
.pur-chip.is-on { border-color: #6366f1; background: #eef2ff; color: #3730a3; }
.pur-dot { width: 0.5rem; height: 0.5rem; border-radius: 9999px; flex: none; }
.pur-dot-belum { background: #f43f5e; }
.pur-dot-sebagian { background: #f59e0b; }
.pur-dot-lunas { background: #10b981; }
.pur-chip-n {
  min-width: 1.25rem; padding: 0 0.375rem; border-radius: 9999px; text-align: center;
  background: #f3f4f6; color: #6b7280; font-size: 0.6875rem; font-weight: 600;
  font-variant-numeric: tabular-nums; line-height: 1.125rem;
}
.pur-chip-n:empty { display: none; }
.pur-chip.is-on .pur-chip-n { background: #e0e7ff; color: #3730a3; }
.pur-saring-sep { width: 1px; height: 1.25rem; background: #e5e7eb; }
.pur-cek {
  display: inline-flex; align-items: center; gap: 0.375rem; height: 2rem;
  font-size: 0.75rem; color: #4b5563; cursor: pointer; user-select: none;
}
.pur-cek input { width: 0.9rem; height: 0.9rem; accent-color: #4f46e5; cursor: pointer; }
.pur-cek:has(input:checked) { color: #3730a3; font-weight: 600; }
.pur-reset {
  display: inline-flex; align-items: center; gap: 0.375rem; height: 2rem; margin-left: auto;
  padding: 0 0.625rem; border-radius: 0.5rem; font-size: 0.75rem; font-weight: 600;
  color: #e11d48; background: transparent; cursor: pointer;
}
.pur-reset:hover { background: #fff1f2; }
.pur-reset.hidden { display: none; }
@media (max-width: 640px) {
  .pur-saring { gap: 0.5rem; }
  .pur-saring-sep { display: none; }
  .pur-reset { margin-left: 0; }
}

/* ── /kirim-terima ──────────────────────────────────────────────────────────
   Lebar potong kolom Rute & Barang. Dulu `style="max-width:14rem"` SEBARIS di
   tiap sel — dan gaya inline TAK BISA disusutkan media query, jadi kedua kolom
   itu tak pernah menyusut di HP walau `.scm-dense` sudah aktif. Ambangnya 640px,
   sama dengan `.scm-dense` dan `.sb-harian-tabel`: jangan menambah ambang
   keempat, app.css sudah mencatat adanya zona mati 641–767px.

   `basis-full` dipakai keterangan "pencarian mengabaikan saringan" supaya ia
   mendapat BARISNYA SENDIRI di bawah bilah saringan; kelasnya tak pernah ada di
   subset Tailwind, jadi selama ini keterangan itu berdesakan di ujung baris. */
.kt-potong { max-width: 14rem; }
.kt-potong-kecil { max-width: 9rem; }
.basis-full { flex-basis: 100%; }

@media (max-width: 640px) {
  .kt-potong { max-width: 9rem; }
  .kt-potong-kecil { max-width: 6.5rem; }
}

/* Bilah "Saringan lanjutan" /kirim-terima: tombolnya HANYA ada di layar sempit,
   dan lipatnya hanya berlaku di sana. Di layar lebar keempat ceklis tetap
   tampil seperti dulu — `.kt-lipat-tutup` sengaja tak punya aturan di luar
   media query, jadi kelas yang tertinggal menyala tak bisa menyembunyikan
   apa pun di desktop. */
.kt-hanya-sempit { display: none; }

@media (max-width: 640px) {
  .kt-hanya-sempit { display: inline-flex; }
  .kt-lipat-tutup { display: none; }
}
