/* ==========================================================================
   Kasir Asia — panel back-office & kasir (asal: kasir PHP MBG CAFÉ)
   DITULIS MOBILE-FIRST: aturan dasar = layar HP, lalu naik lewat min-width.
   Struktur: font → token → dasar → shell → komponen → tabel → form → sheet
             → spreadsheet → utilitas → layar besar → cetak
   ========================================================================== */

/* ---------- font di-host sendiri (tanpa permintaan ke Google, tanpa render-block) ----------
   SENGAJA TIDAK di-<link rel="preload">. Diukur di produksi 2026-10-08 (HP, 4G
   lambat): preload tiga font (60 KB) berebut jalur dengan CSS yang memblokir
   render — cat pertama kunjungan pertama 800–880 ms; tanpa preload 530–580 ms.
   Kunjungan ulang sama cepat (font dari cache sudah siap sebelum cat pertama),
   dan pergantian font saat swap hampir tak menggeser apa pun (CLS 0,001). */
@font-face{font-family:"Inter";font-style:normal;font-weight:400;font-display:swap;
  src:url("/assets/fonts/inter-400.woff2") format("woff2")}
@font-face{font-family:"Inter";font-style:normal;font-weight:600;font-display:swap;
  src:url("/assets/fonts/inter-600.woff2") format("woff2")}
@font-face{font-family:"Jakarta";font-style:normal;font-weight:800;font-display:swap;
  src:url("/assets/fonts/jakarta-800.woff2") format("woff2")}

:root{
  --oranye:#F2622E; --oranye-tua:#D9501E; --oranye-muda:#FFF1EA; --oranye-garis:#F6C6B1;
  --tinta:#0E1116; --tinta-2:#161B24; --tinta-3:#1F2632;
  --teks:#161B24; --teks-2:#5A6473; --teks-3:#8A93A2;
  --garis:#E6E8EC; --garis-2:#EFF1F4;
  --latar:#F5F6F8; --latar-2:#FAFBFC; --putih:#fff;
  /* Permukaan gelap (menu kiri, topbar kasir, toolbar lembar audit): satu
     keluarga nilai, bukan hex lepas di tiap aturan. */
  --permukaan-gelap:#1B2230; --garis-gelap:#2A3241;
  --teks-gelap:#C9D1DE; --teks-gelap-2:#8A94A6; --teks-gelap-3:#6B7688;
  /* Status: warna dasar · latar muda · garis tepi · teks tua (dipakai di atas
     latar muda supaya kontrasnya lulus AA). */
  --hijau:#0F8A5F; --hijau-muda:#E7F6EF; --hijau-garis:#BFE6D5; --hijau-tua:#0B6647;
  --kuning:#B7791F; --kuning-muda:#FFF6E5; --kuning-garis:#F3DFB4; --kuning-tua:#8A5B12;
  --merah:#C63329; --merah-muda:#FDECEA; --merah-garis:#F3C9C4; --merah-tua:#9E2B22;
  --biru:#2F5BEA; --biru-muda:#EDF1FE; --biru-garis:#CBD7FB; --biru-tua:#22409E;

  /* satu tangga jarak dipakai seluruh aplikasi — sumber kerapian */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px; --s8:32px;
  /* Ritme vertikal: jarak antar-section & padding dalam kartu. Keduanya tumbuh
     bersama di layar besar, jadi proporsinya tetap sama.
     Angkanya sengaja RAPAT: aplikasi kasir dipakai sambil berdiri melayani
     pembeli — makin banyak baris yang muat dalam satu layar, makin sedikit
     menggulir. Longgar itu enak dilihat di halaman promosi, bukan di panel. */
  --seksi:8px; --pad-kartu:12px;
  /* radius: kecil (tombol/isian kecil) · baku (kotak, tombol besar) · lebar (kartu) */
  --r:12px; --r-l:14px; --r-s:9px;
  --bayang:0 1px 2px rgba(16,24,40,.05), 0 4px 12px rgba(16,24,40,.05);
  --bayang-l:0 8px 28px rgba(16,24,40,.10);
  --sisi-lebar:236px;
  --sisi-ruang:0px;             /* ruang yang BENAR-BENAR dimakan menu (0 selama menu melayang) */
  --tepi:12px;                  /* padding tepi halaman, tumbuh di layar besar */
  --atas-tinggi:52px;
  --isi-maks:1560px;            /* di layar ultra-lebar isi berhenti melebar & dipusatkan */
  --font:"Inter",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --font-judul:"Jakarta","Inter",system-ui,sans-serif;

  /* ---- TANGGA TIPOGRAFI: sembilan langkah, tidak boleh ada ukuran lain ----
     Aplikasi ini sempat memakai 28 ukuran font berbeda (9 · 9,5 · 10 · 10,5 · 11
     · 11,5 · 12 · 12,5 · 13 · 13,5 · 14 · 14,5 …). Selisih setengah piksel tidak
     terbaca sebagai pilihan desain — yang terbaca cuma halaman yang tidak terasa
     satu keluarga. tools/audit-ui.js menolak ukuran di luar tangga ini.
     16px WAJIB ada: di bawah itu Safari/iOS memperbesar halaman sendiri begitu
     kolom isian disentuh. */
  --f1:11px;   /* mikro: grup menu, versi, header tabel */
  --f2:12px;   /* meta: bantuan, caption, tombol kecil */
  --f3:13px;   /* sekunder: isi tabel, tombol, menu */
  --f4:14px;   /* badan */
  --f5:16px;   /* judul kartu, tombol besar, isian di HP */
  --f6:18px;   /* judul halaman */
  --f7:21px;   /* angka KPI */
  --f8:26px;   /* angka besar */
  --f9:32px;   /* judul besar */
  /* dua langkah DISPLAY, hanya untuk hero & judul halaman publik — tidak boleh
     dipakai di panel, di sana f9 sudah yang terbesar */
  --f10:42px; --f11:56px;

  /* ---- TINGGI KONTROL: isian dan tombol berbagi SATU angka ----
     Kotak cari dan tombol di sebelahnya harus berdiri sama tinggi; dulu isian
     46–49px berdampingan dengan tombol 40px dan barisnya terlihat timpang di
     264 tempat. Di HP 44px (sasaran sentuh nyaman), di layar besar 40px. */
  --kontrol:44px;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}
body{margin:0;font-family:var(--font);font-size:var(--f4);line-height:1.55;color:var(--teks);
  background:var(--latar);-webkit-font-smoothing:antialiased;overscroll-behavior-y:none}
h1,h2,h3,h4{font-family:var(--font-judul);margin:0;letter-spacing:-.02em;line-height:1.25;font-weight:800}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
button,input,select,textarea{font:inherit}
/* <small> bawaan browser = 0,8333em, jadi di badan 14px ia jadi 11,67px —
   ukuran yang tidak ada di tangga mana pun dan muncul di setiap halaman yang
   memakainya tanpa kelas. Dikunci ke langkah terkecil. */
small{font-size:var(--f1)}
.ikon{flex:none}
.lewati{position:absolute;left:-9999px}
.lewati:focus{left:8px;top:8px;z-index:99;background:var(--putih);padding:8px 14px;border-radius:8px}
:focus-visible{outline:2px solid var(--oranye);outline-offset:2px}
::selection{background:var(--oranye);color:var(--putih)}

/* batang gulir tipis di seluruh aplikasi — bawaan Windows terlalu kasar */
*{scrollbar-width:thin;scrollbar-color:#C7CCD6 transparent}
*::-webkit-scrollbar{width:9px;height:9px}
*::-webkit-scrollbar-track{background:transparent}
*::-webkit-scrollbar-thumb{background:#CFD4DD;border-radius:99px;border:3px solid transparent;
  background-clip:content-box}
*::-webkit-scrollbar-thumb:hover{background:#AEB5C2;background-clip:content-box;border:3px solid transparent}

/* ==========================================================================
   SHELL — HP dulu: sidebar jadi laci, topbar menempel di atas
   ========================================================================== */
.sisi{position:fixed;inset:0 auto 0 0;width:min(84vw,var(--sisi-lebar));background:var(--tinta);
  color:var(--teks-gelap);display:flex;flex-direction:column;z-index:40;
  transform:translateX(-100%);transition:transform .22s ease;box-shadow:var(--bayang-l)}
body.menu-buka .sisi{transform:none}
/* Kepala sidebar: setinggi topbar persis (var(--atas-tinggi)) supaya garis
   bawah menu dan garis bawah topbar berada di SATU garis horizontal. */
.sisi-merek{display:flex;align-items:center;gap:var(--s2);padding:0 var(--s3);flex:none;
  min-height:var(--atas-tinggi);border-bottom:1px solid var(--permukaan-gelap)}
.merek{display:flex;align-items:center;gap:9px;color:var(--putih);flex:1;min-width:0;min-height:var(--kontrol)}
/* logo toko terunggah mengisi kotak merek (panel & layar kasir); saat ada,
   latar oranye diganti putih supaya logo apa pun terbaca jelas. */
.merek-foto{width:100%;height:100%;object-fit:contain;border-radius:inherit}
.merek-logo:has(.merek-foto),.pos-merek .merek-logo:has(.merek-foto){background:var(--putih)!important}
.merek-logo{width:30px;height:30px;border-radius:var(--r-s);background:var(--oranye);display:grid;
  place-items:center;flex:none;color:var(--putih)}
.merek-teks{font-family:var(--font-judul);font-weight:800;font-size:var(--f3);letter-spacing:-.01em;
  display:flex;flex-direction:column;line-height:1.2;min-width:0}
.merek-teks small{font-family:var(--font);font-weight:500;font-size:var(--f1);color:#7C8798;letter-spacing:.02em}
/* padding 10px (bukan 6px): kotak sentuh 40px — 32px sebelumnya di bawah target
   sentuh nyaman, dan ini tombol yang dipakai berulang tiap menutup laci menu di HP */
.sisi-tutup{display:block;background:none;border:0;color:var(--teks-gelap-2);padding:10px;cursor:pointer}

/* Batang gulir menu kiri sengaja DISEMBUNYIKAN (tetap bisa digulir) — garis
   abu-abu vertikal di tepi menu gelap terlihat seperti cacat tampilan. */
.sisi-nav{flex:1;overflow-y:auto;padding:var(--s2) 9px var(--s3);overscroll-behavior:contain;
  scrollbar-width:none;-ms-overflow-style:none}
.sisi-nav::-webkit-scrollbar{width:0;height:0;display:none}
.sisi-grup{font-size:var(--f1);font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:var(--teks-gelap-3);padding:var(--s3) 9px 3px}
.sisi-nav > .sisi-grup:first-child{padding-top:2px}
.sisi-item{display:flex;align-items:center;gap:10px;padding:7px 9px;border-radius:var(--r-s);
  font-size:var(--f3);font-weight:500;color:#B9C2D0;transition:background .13s,color .13s}
.sisi-item span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sisi-item:hover{background:var(--permukaan-gelap);color:var(--putih)}
.sisi-item.aktif{background:var(--oranye);color:var(--putih);box-shadow:0 4px 12px rgba(242,98,46,.32)}
.sisi-item.aktif .ikon{color:var(--putih)}
.lencana{font-style:normal;font-size:var(--f1);font-weight:700;background:var(--merah);color:var(--putih);
  min-width:19px;height:19px;border-radius:10px;display:grid;place-items:center;padding:0 5px}
.sisi-item.aktif .lencana{background:rgba(255,255,255,.25)}
/* Kaki menu sengaja setipis mungkin: isinya cuma nomor versi, dan setiap piksel
   di sini memakan ruang daftar menu. */
.sisi-kaki{flex:none;padding:6px 9px;border-top:1px solid #202836;background:var(--tinta)}
.sisi-versi{text-align:center;font-size:var(--f1);color:#4E5866;padding:3px 0 0;letter-spacing:.03em}

.tirai{position:fixed;inset:0;background:rgba(14,17,22,.45);z-index:35;
  animation:pudar .16s ease}
@keyframes pudar{from{opacity:0}to{opacity:1}}

/* Latar nyaris opak TANPA backdrop-filter — blur memaksa repaint mahal tiap
   scroll di PC pelan, sedangkan pada latar 97% putih efeknya tak terlihat. */
.atas{position:sticky;top:0;z-index:30;background:rgba(255,255,255,.97);
  border-bottom:1px solid var(--garis);
  display:flex;align-items:center;gap:var(--s3);padding:var(--s2) var(--tepi);min-height:var(--atas-tinggi)}
/* Kartu yang jadi sasaran tautan dalam halaman (mis. tombol "Ubah" → #form).
   Bilah atas menempel, jadi tanpa jarak ini lompatannya mendarat tepat DI BAWAH
   bilah itu: judul kartunya tertutup, dan yang mengklik "Ubah" melihat form
   tanpa keterangan sedang mengubah siapa. */
.kartu[id]{scroll-margin-top:calc(var(--atas-tinggi) + var(--s3))}
.atas-judul{flex:1;min-width:0}
.atas-judul h1{font-size:var(--f5);font-weight:800;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  line-height:1.2}
.atas-judul p{margin:0;font-size:var(--f1);color:var(--teks-2);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;line-height:1.3}
/* Semua tombol di topbar dipaksa satu ukuran dari sini — halaman tidak perlu
   (dan tidak boleh) mengatur ukurannya sendiri. Di layar sempit label teksnya
   disembunyikan supaya deretan tombol tidak pernah mendorong judul halaman. */
.atas-aksi{display:flex;align-items:center;gap:6px;flex:none}
/* pembungkus tombol milik halaman (layout.php) — tidak ikut tata letak, hanya
   pegangan untuk disembunyikan selama pindah halaman */
.aksi-halaman{display:contents}
/* Tinggi 40px DIPAKSA dari sini (menang atas .tbl-kecil karena dua kelas):
   halaman tidak bisa lagi menyelipkan tombol berukuran lain ke topbar —
   itulah yang membuat tombol "Pasang" tampak lebih pendek dari tetangganya. */
.atas-aksi .tbl{--tbl-t:var(--kontrol);--tbl-x:12px;--tbl-f:var(--f3);--tbl-r:10px}
/* jam & profil ikut tinggi yang sama supaya seluruh deretan topbar satu garis */
.atas-aksi .jam-toko{height:40px}
.atas-aksi .tbl .lbl{display:none}
/* PENGAMAN: di layar sempit tombol topbar tidak boleh lebih lebar dari kotak
   ikonnya, apa pun isi markup-nya. Labelnya memang sudah disembunyikan lewat
   .lbl (dan tbl_atas() memastikan semua tombol memakainya), tapi satu tombol
   yang lupa membungkus pernah melebar 158px di layar 360px sampai judul halaman
   terperas jadi NOL dan halaman bisa digeser ke samping. Batas ini membuat
   kesalahan seperti itu memotong teksnya sendiri, bukan merusak tata letak.
   Menyusutkan .atas-aksi BUKAN jawabannya: dengan justify-content:flex-end ia
   malah membuat tombol meluber ke KIRI dan menimpa judul (28 kali). */
.atas-aksi .tbl{max-width:var(--tbl-t);overflow:hidden}
@media (min-width:900px){
  .atas-aksi .tbl{--tbl-x:15px;max-width:none;overflow:visible}
  .atas-aksi .tbl .lbl{display:inline}
}
/* padding 9px (bukan 7px): kotak sentuh 40px, sama seperti .sisi-tutup */
.tombol-menu{display:inline-flex;background:none;border:1px solid var(--garis);border-radius:var(--r-s);
  padding:9px;cursor:pointer;color:var(--teks);flex:none}
.jam-toko{display:none;align-items:center;gap:4px;padding:0 11px;border-radius:var(--r-s);
  background:var(--latar);border:1px solid var(--garis)}
.jam-toko strong{font-size:var(--f3);font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.jam-toko small{font-size:var(--f1);font-weight:700;color:var(--teks-3);letter-spacing:.04em}
.profil{display:flex;align-items:center;gap:8px}
.profil-avatar{width:32px;height:32px;border-radius:50%;background:var(--tinta);color:var(--putih);
  display:grid;place-items:center;font-size:var(--f1);font-weight:700;letter-spacing:.02em;flex:none}
.profil-teks{display:none;flex-direction:column;line-height:1.2}
.profil-teks strong{font-size:var(--f3)}
.profil-teks small{font-size:var(--f1);color:var(--teks-2)}

/* Ruang bawah dulu 72px — sisa dari masa ada pita melayang di dasar layar.
   Pita itu sudah tidak ada, jadi ruang itu murni menganggur. */
.isi{padding:var(--seksi) var(--tepi) var(--s5)}

/* Isi & topbar berbagi SATU rumus tepi, jadi judul di topbar selalu tepat sejajar
   dengan kartu di bawahnya, di lebar layar berapa pun.
   Isi berhenti melebar di --isi-maks lalu DIPUSATKAN pada ruang yang tersisa di
   sebelah menu. Dulu pemusatan ini hanya menyala di ≥1900px, sementara batas
   --isi-maks sudah mengikat sejak ~1800px — di sela itu konten menempel kiri dan
   menyisakan pita kosong di kanan (kiri 22px vs kanan 76px pada layar 1850px).
   Pakai 100% (lebar body, tanpa batang gulir), bukan 100vw yang ikut menghitung
   batang gulir dan membuat sisa kiri/kanan meleset beberapa piksel. */
.isi,.atas{padding-inline:max(var(--tepi),calc((100% - var(--sisi-ruang) - var(--isi-maks)) / 2))}

/* ---------- notifikasi ---------- */
.notif{display:flex;align-items:center;gap:10px;padding:var(--s2) var(--s3);border-radius:var(--r);
  margin-bottom:var(--seksi);font-weight:500;border:1px solid transparent;font-size:var(--f3)}
.notif .ikon{flex:none}
.notif-ok{background:var(--hijau-muda);color:var(--hijau-tua);border-color:var(--hijau-garis)}
.notif-galat{background:var(--merah-muda);color:var(--merah-tua);border-color:var(--merah-garis)}
.notif-info{background:var(--biru-muda);color:var(--biru-tua);border-color:var(--biru-garis)}
.notif-peringatan{background:var(--kuning-muda);color:var(--kuning-tua);border-color:var(--kuning-garis)}

/* ---------- panduan "Cara pakai" (app/bootstrap.php: panduan_html) ----------
   TERTUTUP: satu baris kecil berikon selebar teksnya — tidak boleh memakan
   ruang di halaman yang dibuka puluhan kali sehari oleh orang yang sudah hafal.
   TERBUKA: kotak penuh dengan langkah bernomor dan tips bertanda. Semua warna
   lewat variabel, jadi di mode pusat (pusat.css menimpa --oranye) ikut biru. */
.panduan{margin-bottom:var(--seksi);border:1px solid var(--garis);border-radius:var(--r);
  background:var(--putih);width:fit-content;max-width:100%}
.panduan[open]{width:auto;box-shadow:var(--bayang)}
.panduan > summary{display:flex;align-items:center;gap:var(--s2);min-height:34px;
  padding:0 var(--s3);cursor:pointer;list-style:none;font-size:var(--f2);font-weight:600;
  color:var(--teks-2);border-radius:var(--r);-webkit-tap-highlight-color:transparent;user-select:none}
.panduan > summary::-webkit-details-marker{display:none}
.panduan > summary > .ikon{color:var(--oranye)}
.panduan > summary > span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* panah lipat digambar CSS: menghadap bawah saat tertutup, atas saat terbuka */
.panduan > summary::after{content:"";flex:none;width:6px;height:6px;margin:0 2px 3px var(--s1);
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:rotate(45deg);transition:transform .16s;opacity:.7}
.panduan[open] > summary::after{transform:rotate(-135deg);margin-bottom:-3px}
.panduan > summary:hover{color:var(--teks)}
.panduan > summary:focus-visible{outline-offset:-2px}
.panduan[open] > summary{border-bottom:1px solid var(--garis-2);border-radius:var(--r) var(--r) 0 0}
.panduan-isi{padding:var(--s3) var(--pad-kartu) var(--pad-kartu);font-size:var(--f3);line-height:1.6;color:var(--teks)}
.panduan-isi > :first-child{margin-top:0}
.panduan-isi > :last-child{margin-bottom:0}
.panduan-isi p,.panduan-isi li{max-width:72ch}
.panduan-isi p{margin:0 0 var(--s2);color:var(--teks-2)}
.panduan-isi ol{margin:0 0 var(--s3);padding-left:1.5em;display:grid;gap:var(--s1)}
.panduan-isi ol li::marker{color:var(--oranye);font-weight:700}
/* tips: satu kotak berlabel "Tips", tiap butir bertitik aksen */
.panduan-tips{list-style:none;margin:0;padding:var(--s2) var(--s3);display:grid;gap:var(--s1);
  background:var(--oranye-muda);border-radius:var(--r-s);font-size:var(--f2);color:var(--teks)}
.panduan-tips::before{content:"Tips";font-size:var(--f1);font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--teks-2)}
.panduan-tips li{position:relative;padding-left:var(--s4)}
.panduan-tips li::before{content:"";position:absolute;left:3px;top:.6em;width:6px;height:6px;
  border-radius:50%;background:var(--oranye)}

/* ==========================================================================
   KARTU & GRID — kunci kerapian: kartu di dalam grid selalu setinggi barisnya
   ========================================================================== */
/* Jarak antar-section dikendalikan SATU variabel (--seksi) supaya semua
   halaman punya ritme vertikal yang sama, bukan margin ad-hoc per halaman. */
.kartu{background:var(--putih);border:1px solid var(--garis);border-radius:var(--r-l);
  box-shadow:var(--bayang);margin-bottom:var(--seksi);overflow:hidden;
  display:flex;flex-direction:column}
.kartu:last-child{margin-bottom:0}
.kartu-kepala{display:flex;align-items:center;gap:var(--s2);padding:var(--s2) var(--pad-kartu);
  border-bottom:1px solid var(--garis-2);flex-wrap:wrap;min-height:44px}
.kartu-kepala h2{font-size:var(--f4);font-weight:800;flex:1;min-width:140px}
/* Judul kartu naik satu langkah di layar besar, sejalan dengan judul halaman —
   kalau tidak, keduanya bertemu di ukuran yang sama dan hierarkinya rata. */
@media (min-width:900px){.kartu-kepala h2{font-size:var(--f5)}}
.kartu-kepala p{margin:1px 0 0;font-size:var(--f2);color:var(--teks-2);font-weight:400;
  letter-spacing:0;text-transform:none}
.kartu-kepala > .baris,.kartu-kepala > .tbl-deret{flex:none}
.kartu-isi{padding:var(--pad-kartu);flex:1}
.kartu-isi > :first-child{margin-top:0}
.kartu-isi > :last-child{margin-bottom:0}
/* tabel menempel tepi kartu — tanpa ini garis tabel tidak sejajar tepi kartu */
.kartu > .tabel-bungkus{margin:0}
.kartu-kaki{padding:var(--s2) var(--pad-kartu);border-top:1px solid var(--garis-2);background:var(--latar-2);
  display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;margin-top:auto;min-height:42px}

/* min-width:0 wajib untuk semua item grid — tanpa ini konten lebar (tabel, grafik)
   memaksa kolom melebihi layar dan halaman jadi bisa digeser ke samping di HP. */
.grid{display:grid;gap:var(--seksi);align-items:stretch;margin-bottom:var(--seksi)}
.grid:last-child{margin-bottom:0}
.grid > *{min-width:0}
/* Kartu diregangkan setinggi baris HANYA bila ia punya kaki. Kaki (tombol "Lihat
   semua", ringkasan total) turun ke dasar kartu lewat margin-top:auto, jadi
   regangannya terlihat disengaja. Kartu tanpa kaki yang diregangkan cuma
   menghasilkan ruang putih menganga — terukur 457px di Stok Opname, 386px di
   Daftar Pengguna, 246px di Laporan Penjualan.
   align-self WAJIB dipakai di sini, bukan cuma membuang height:100%: grid item
   diregangkan oleh align-items:stretch bawaan grid, jadi tanpa align-self:start
   kartunya tetap menganga meski height-nya sudah tidak 100%. */
.grid > .kartu{margin-bottom:0;align-self:start}
.grid > .kartu:has(> .kartu-kaki){align-self:stretch;height:100%}
.grid-4,.grid-3,.grid-2,.grid-2-1{grid-template-columns:1fr}
.grid-4{grid-template-columns:repeat(2,1fr)}     /* KPI tetap 2 kolom di HP */

/* Kolom dasbor: kartu ditumpuk rapat dan kartu TERAKHIR meregang, sehingga kedua
   kolom berakhir di garis yang sama — kaki kartu (tombol "Lihat semua") ikut turun
   ke bawah, bukan menyisakan ruang menganggur. */
.grid-2-1 > div{display:flex;flex-direction:column;gap:var(--seksi);min-width:0}
/* PENGAMAN: kartu di kolom TIDAK BOLEH menyusut. Kolom ini setinggi baris grid;
   begitu ada satu anak yang menuntut tinggi berlebih, flex-shrink bawaan
   memampatkan kartu lain dan overflow:hidden memotong isinya diam-diam — itulah
   yang membuat baris "Laba kotor" hilang dari kartu Ringkasan periode. */
.grid-2-1 > div > .kartu,.grid-2-1 > div > .kpi{margin-bottom:0;flex:none}
/* Kartu terakhir meregang hanya bila ia berkaki (alasan sama seperti .grid > .kartu). */
.grid-2-1 > div > .kartu:last-child:has(> .kartu-kaki){flex:1 1 auto}

/* Kartu DAFTAR (berisi tabel atau pesan "belum ada apa-apa") meregang setinggi
   baris grid, dan isinya ikut mengisi. Alasannya: daftar tumbuh seiring pemakaian
   — hari ini 2 baris, bulan depan 40. Membiarkannya setinggi isi berarti kartu
   berdiri 263px lebih pendek dari form di sebelahnya (terukur di Stok Opname),
   meninggalkan pita kosong memanjang yang bos tandai. Ruang lebihnya masuk ke
   DALAM kartu, di bawah baris terakhir — bentuk yang sudah biasa untuk tabel. */
.grid > .kartu:has(> .tabel-bungkus),.grid > .kartu:has(> .kosong){align-self:stretch}
.grid > .kartu > .tabel-bungkus{flex:1}
.grid > .kartu:has(> .kosong) > .kosong{flex:1;display:flex;flex-direction:column;
  align-items:center;justify-content:center}

/* ---------- KPI ---------- */
.kpi{background:var(--putih);border:1px solid var(--garis);border-radius:var(--r-l);
  padding:var(--s3);display:flex;gap:10px;align-items:stretch;box-shadow:var(--bayang);
  min-height:58px}
/* Isi KPI MENGISI tinggi kartu, tidak menggantung di atasnya. KPI diregangkan
   setinggi baris grid (supaya sederet sejajar), jadi kartu yang isinya lebih
   pendek dari tetangganya — "0 nota" di sebelah "Rp 1.234.567" yang pecah dua
   baris — menyisakan ruang kosong 43–52px di bawah. Dengan isi yang dipusatkan,
   ruang itu terbagi rata dan tidak lagi terbaca sebagai kartu menganga. */
.kpi > div{flex:1;display:flex;flex-direction:column;justify-content:center}
/* height:100% HANYA sebagai item grid — di sana ia berarti "setinggi baris KPI",
   yang memang tujuannya. Di kolom flex (.grid-2-1 > div) 100% berarti setinggi
   SELURUH kolom: KPI menuntut ±800px, kartu di atasnya ditekan flex-shrink, dan
   isinya terpotong. Itu akar kartu "Nilai stok" menganga 380px. */
.grid > .kpi{height:100%}
.kpi-ikon{width:32px;height:32px;border-radius:var(--r-s);background:var(--oranye-muda);color:var(--oranye);
  display:grid;place-items:center;flex:none;align-self:flex-start}
.kpi > div{min-width:0}
.kpi-label{font-size:var(--f1);color:var(--teks-2);font-weight:500;display:block}
/* overflow-wrap WAJIB di sini. Di layar 360px grid KPI turun jadi 2 kolom dan
   kartunya tinggal ±158px; angka seperti "Rp 4.032.000" pada 21px tebal
   menuntut ±136px di kolom teks selebar 92px, meluber keluar kartu, dan
   membuat SELURUH halaman bisa digeser ke samping. min-width:0 pada
   pembungkusnya tidak menolong — yang tidak mau menyusut adalah barisan
   teksnya sendiri. */
.kpi-nilai{font-family:var(--font-judul);font-size:var(--f7);font-weight:800;letter-spacing:-.025em;
  display:block;margin-top:1px;line-height:1.2;font-variant-numeric:tabular-nums;
  overflow-wrap:anywhere}
/* Catatan KPI dikunci SATU baris. Di kolom sempit (2 KPI berdampingan di layar
   360px) catatan yang pecah jadi dua baris membuat satu kartu jauh lebih tinggi
   dari tetangganya; karena KPI diregangkan setinggi baris, sisanya menganga
   43–52px. Satu baris + elipsis membuat tinggi isinya seragam. */
.kpi-catatan{font-size:var(--f1);color:var(--teks-3);display:block;margin-top:3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.kpi-hijau .kpi-ikon{background:var(--hijau-muda);color:var(--hijau)}
.kpi-merah .kpi-ikon{background:var(--merah-muda);color:var(--merah)}
.kpi-kuning .kpi-ikon{background:var(--kuning-muda);color:var(--kuning)}
.kpi-biru .kpi-ikon{background:var(--biru-muda);color:var(--biru)}
/* kartu_kpi(..., 'oranye'|'abu') dipakai halaman (mis. pusat/jaringan) tapi dulu
   tanpa aturan — jatuh ke gaya bawaan diam-diam. Oranye = aksen panel (biru di
   mode pusat, ikut variabel), abu = netral untuk angka tanpa makna baik/buruk. */
.kpi-oranye .kpi-ikon{background:var(--oranye-muda);color:var(--oranye)}
.kpi-abu .kpi-ikon{background:var(--garis-2);color:var(--teks-3)}

/* ==========================================================================
   TOMBOL — SATU sistem untuk seluruh aplikasi.
   Warna diatur lewat 4 variabel per varian (--bg/--bg-h/--fg/--bd), JANGAN
   dengan menimpa `background` langsung: dulu `.tbl:hover` (2 kelas) menang
   atas `.tbl-merah` (1 kelas), sehingga tombol merah/hijau berubah jadi
   putih ber-teks putih alias HILANG saat disorot.
   Ukuran dikunci pada 3 tinggi saja: 34 / --kontrol / 48.
   ========================================================================== */
.tbl{
  --bg:var(--putih); --bg-h:#F1F3F6; --fg:var(--teks); --bd:var(--garis); --bd-h:#D7DBE2;
  --tbl-t:var(--kontrol); --tbl-x:15px; --tbl-f:var(--f3); --tbl-r:10px;
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  height:var(--tbl-t);min-height:var(--tbl-t);padding:0 var(--tbl-x);
  border-radius:var(--tbl-r);border:1px solid var(--bd);font-weight:600;
  font-size:var(--tbl-f);line-height:1;cursor:pointer;text-align:center;
  transition:background .14s,border-color .14s,color .14s,transform .09s,box-shadow .14s;
  white-space:nowrap;background:var(--bg);color:var(--fg);
  -webkit-tap-highlight-color:transparent}
.tbl:hover{background:var(--bg-h);border-color:var(--bd-h)}
.tbl:active{transform:scale(.98)}
.tbl .ikon{width:1.15em;height:1.15em}

.tbl-utama{--bg:var(--oranye);--bg-h:var(--oranye-tua);--fg:var(--putih);--bd:var(--oranye);--bd-h:var(--oranye-tua)}
.tbl-gelap{--bg:var(--tinta);--bg-h:var(--tinta-3);--fg:var(--putih);--bd:var(--tinta);--bd-h:var(--tinta-3)}
.tbl-hijau{--bg:var(--hijau);--bg-h:#0C744F;--fg:var(--putih);--bd:var(--hijau);--bd-h:#0C744F}
.tbl-merah{--bg:var(--merah);--bg-h:#A82A21;--fg:var(--putih);--bd:var(--merah);--bd-h:#A82A21}
.tbl-hantu{--bg:transparent;--bg-h:var(--garis-2);--fg:var(--teks-2);--bd:transparent;--bd-h:var(--garis-2)}
.tbl-hantu:hover{color:var(--teks)}
.tbl-garis{--bg:transparent;--bg-h:var(--oranye-muda);--fg:var(--oranye-tua);--bd:var(--oranye-garis);--bd-h:var(--oranye)}

/* tiga ukuran resmi — tak ada tinggi tombol lain di aplikasi ini. Ukuran NORMAL
   mengikuti --kontrol supaya selalu setinggi kolom isian di sebelahnya. */
.tbl-kecil{--tbl-t:34px;--tbl-x:11px;--tbl-f:var(--f2);--tbl-r:8px}
.tbl-besar{--tbl-t:48px;--tbl-x:22px;--tbl-f:var(--f5);--tbl-r:12px}
.tbl-ikon{--tbl-x:0;width:var(--tbl-t);padding:0}
.tbl-blok{width:100%}
.tbl:disabled,.tbl[aria-disabled="true"]{opacity:.45;cursor:not-allowed;transform:none}

/* Tombol SIMPAN sebuah form selalu memakai kelas ini — satu kelas, satu ukuran.
   Dulu tiap halaman memilih sendiri: ada yang tbl-besar, ada yang biasa, ada
   yang merah; hasilnya tombol "Simpan" terlihat berbeda dari halaman ke halaman.
   Di HP ia memenuhi lebar (sasaran sentuh penuh), di layar besar melebar
   secukupnya dengan lebar minimum yang sama untuk semua halaman. */
.tbl-simpan{--tbl-t:48px;--tbl-x:22px;--tbl-f:var(--f5);--tbl-r:12px;width:100%}
@media (min-width:600px){.tbl-simpan{width:auto;min-width:184px}}

/* Deret tombol di kaki kartu ikut aturan yang sama: penuh & sama lebar di HP,
   menyusut ke kanan di layar besar. Tidak ada tombol "nanggung" lagi. */
.kartu-kaki > .tbl{flex:1 1 auto;justify-content:center}
@media (min-width:600px){.kartu-kaki > .tbl{flex:0 0 auto}}
/* Kalau satu kaki berisi tombol simpan, SEMUA tombol di kaki itu ikut tingginya.
   Ini yang mencegah pasangan "Simpan hitungan" (48px) + "Posting" (40px) berdiri
   bersebelahan dengan tinggi berbeda. */
.kartu-kaki:has(.tbl-simpan) > .tbl,
.tbl-deret:has(.tbl-simpan) > .tbl{--tbl-t:48px;--tbl-f:var(--f5);--tbl-r:12px}

/* deret tombol: jarak seragam, dan di HP tombol memenuhi lebar supaya
   tidak ada tombol nanggung yang bikin baris terlihat tidak simetris */
.tbl-deret{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center}
.tbl-deret > .tbl{flex:1 1 auto}
@media (min-width:600px){.tbl-deret > .tbl{flex:0 0 auto}}

/* ---------- pil / badge ---------- */
.pil{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:999px;
  font-size:var(--f1);font-weight:600;line-height:1.6;white-space:nowrap}
.pil-hijau{background:var(--hijau-muda);color:var(--hijau-tua)}
.pil-merah{background:var(--merah-muda);color:var(--merah-tua)}
.pil-kuning{background:var(--kuning-muda);color:var(--kuning-tua)}
.pil-biru{background:var(--biru-muda);color:var(--biru-tua)}
.pil-abu{background:#F0F2F5;color:var(--teks-2)}
.pil-oranye{background:var(--oranye-muda);color:var(--oranye-tua)}

/* ==========================================================================
   TABEL — SATU gaya untuk seluruh aplikasi.
   Setiap tabel wajib berkolom nomor (.kol-no) di paling kiri.
   ========================================================================== */
.tabel-bungkus{overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}
table.tabel{width:100%;border-collapse:collapse;font-size:var(--f3)}
.tabel th{text-align:left;font-size:var(--f1);letter-spacing:.06em;text-transform:uppercase;
  color:var(--teks-2);font-weight:700;padding:6px var(--s3);background:#F7F9FB;
  border-bottom:1px solid var(--garis);white-space:nowrap;vertical-align:middle}
.tabel td{padding:6px var(--s3);border-bottom:1px solid var(--garis-2);vertical-align:middle}
/* -of-type, bukan -child: tabel panjang menyimpan baris tertundanya di
   <template data-tunda> di ujung tbody (tunda_baris()) — elemen itu ikut
   terhitung oleh :last-child/:nth-child tapi tidak oleh :*-of-type. */
.tabel tbody tr:last-of-type td{border-bottom:0}
.tabel tbody tr{transition:background .1s}
.tabel tbody tr:hover td{background:#FBFCFD}
.tabel .kanan,.tabel th.kanan{text-align:right}
.tabel .tengah,.tabel th.tengah{text-align:center}
.tabel .angka{font-variant-numeric:tabular-nums;white-space:nowrap}
.tabel .aksi{display:flex;gap:6px;justify-content:flex-end;align-items:center}
/* Tempat kosong seukuran tombol ikon. Baris yang kehilangan satu aksi (mis. akun
   sendiri tidak bisa dihapus) tetap menaruh tombol sisanya di kolom yang sama —
   tanpa ini deretan ikon "Ubah" bergeser 40px di baris itu saja, dan tabelnya
   terbaca miring. */
.aksi-slot{flex:none;width:34px;height:34px}
/* Tombol hapus netral saat diam, merah baru saat disorot: merah permanen di tiap
   baris membuat seluruh tabel terlihat seperti daftar peringatan. */
.tbl-hapus{--bg-h:var(--merah-muda);--bd-h:var(--merah-garis)}
.tbl-hapus:hover{color:var(--merah)}
/* Baris yang sedang dibuka di form bawah — supaya jelas akun mana yang diubah
   setelah halaman melompat ke form. */
.tabel tbody tr.baris-sunting td{background:var(--oranye-muda)}
/* Penanda hanya di sel PERTAMA. Dipasang di semua sel, garisnya berulang di tiap
   kolom dan barisnya terlihat terpotong-potong. */
.tabel tbody tr.baris-sunting td:first-child{box-shadow:inset 3px 0 0 var(--oranye)}
.tabel-rapat td{padding:4px var(--s3)}
.baris-mati td{opacity:.55}
/* Kolom pelengkap disembunyikan di layar sempit.
   Tabel panel punya 8–10 kolom; di HP semuanya dipertahankan berarti tabel
   digeser 3–4 layar ke samping hanya untuk sampai ke tombol aksi di ujung
   kanan. Yang disembunyikan hanya kolom yang bisa dilihat di layar lain
   (omzet, jam masuk terakhir) — bukan yang menentukan keputusan. */
.kol-lengkap{display:none}
@media (min-width:900px){.kol-lengkap{display:table-cell}}
.tabel tfoot td{background:#F7F9FB;font-weight:700;border-top:1px solid var(--garis);border-bottom:0}

/* ---- kolom nomor urut: sama persis di semua tabel ---- */
.tabel th.kol-no{width:46px;padding-left:var(--s4);text-align:right;color:var(--teks-3)}
.tabel td.kol-no{width:46px;padding-left:var(--s4);text-align:right;color:var(--teks-3);
  font-variant-numeric:tabular-nums;font-size:var(--f2);font-weight:600;white-space:nowrap}
.tabel tbody tr:hover td.kol-no{color:var(--teks-2)}
/* Nomor otomatis: dihitung CSS, jadi ia benar sendiri setelah baris disaring
   ATAU diurutkan ulang — tanpa satu baris JavaScript pun. Dipakai tabel yang
   isinya dimainkan di peramban; tabel berhalaman memakai nomor dari server. */
.no-otomatis tbody{counter-reset:baris}
.no-otomatis tbody tr:not([hidden]){counter-increment:baris}
/* Angkanya digambar TEPAT SATU KALI. Tabel panel menaruhnya di sel; lembar
   audit menaruhnya di <span class="sel"> karena sel lembar tidak berpadding.
   Dua aturan ini WAJIB saling eksklusif — kalau keduanya kena sel yang sama,
   nomornya tercetak dua kali di baris yang sama. */
.tabel.no-otomatis tbody tr:not([hidden]) td.kol-no::before{content:counter(baris)}
.lembar.no-otomatis tbody tr:not([hidden]) td.kol-no > .sel::before{content:counter(baris)}
.tabel-satuan.no-otomatis tbody tr:not([hidden]) td.kol-no::before{content:counter(baris)}

/* ---- tabel riwayat (log): satu kejadian = satu baris (port panel.css cafe) ----
   Semua kolom selebar isinya dan tidak turun baris; hanya .kol-utama yang menyerap
   sisa lebar — tanpa ini table width:100% membagi sisa lebar ke SEMUA kolom dan
   angka rata-kanan terbaca menempel ke kolom teks sesudahnya. Teks bebas (.kol-teks)
   boleh turun baris. */
.tabel-log th,.tabel-log td{white-space:nowrap}
.tabel-log td{vertical-align:baseline}
.tabel-log .kol-utama{width:100%}
.tabel-log td.kol-teks{white-space:normal;min-width:240px}

/* ---- di HP tabel padat jadi terlalu sempit: beri lebar minimum lalu geser ---- */
@media (max-width:599px){
  .tabel th,.tabel td{padding:7px 10px}
  .tabel th.kol-no,.tabel td.kol-no{width:34px;padding-left:var(--s3);font-size:var(--f1)}
  .tabel-bungkus{margin:0 calc(var(--s4) * -1);padding:0}
  .tabel-bungkus > table{min-width:560px}
  .tabel-bungkus > table th:first-child,.tabel-bungkus > table td:first-child{padding-left:var(--s4)}
  .tabel-bungkus > table th:last-child,.tabel-bungkus > table td:last-child{padding-right:var(--s4)}
}

.produk-sel{display:flex;align-items:center;gap:9px;min-width:190px}
/* min-width JANGAN dikecilkan: kolom nama yang lebih sempit membuat nama produk
   pecah jadi dua baris, dan barisnya justru jadi LEBIH tinggi — terukur +4,4%
   di daftar transaksi pada layar 390px. */
/* contain + latar putih: foto produk (botol tinggi, bungkus mie) tetap terlihat
   utuh di kotak 36px — dengan cover, yang tampak cuma potongan tengahnya */
.produk-avatar{width:32px;height:32px;border-radius:var(--r-s);display:grid;place-items:center;
  font-weight:700;font-size:var(--f2);flex:none;object-fit:contain;letter-spacing:-.01em;
  background:var(--putih);border:1px solid var(--garis-2)}
.produk-nama{font-weight:600;line-height:1.3}
.produk-meta{font-size:var(--f1);color:var(--teks-3)}

.kosong{text-align:center;padding:var(--s6) var(--s4);color:var(--teks-2)}
.kosong-ikon{width:44px;height:44px;border-radius:var(--r);background:var(--garis-2);color:var(--teks-3);
  display:grid;place-items:center;margin:0 auto var(--s3)}
.kosong h3{font-size:var(--f5);margin-bottom:4px}
.kosong p{margin:0;font-size:var(--f3)}

/* ---------- form ---------- */
.form-baris{display:grid;gap:var(--s3);margin-bottom:var(--s3);grid-template-columns:1fr}
label.lb{display:block;font-size:var(--f2);font-weight:600;color:var(--teks-2);margin-bottom:5px}
/* min-width:0 WAJIB. Kolom isian punya lebar minimum bawaan (≈20 karakter) yang
   menang atas width:100%, jadi tanpa ini kotak cari menolak menyusut dan
   menembus keluar kartu di layar HP — bukan menggeser halaman, tapi menimpa
   apa pun di sebelahnya. */
/* Tinggi DIKUNCI ke --kontrol, bukan hasil padding + tinggi baris. Dulu ia
   ikut ukuran font: 46px di HP (font 16), 41px di desktop (font 14), dan 49px
   di beberapa halaman — sementara tombol di sebelahnya tetap 40px. Barisnya
   terlihat timpang di 264 tempat, dan tak satu pun bisa diperbaiki per halaman
   karena penyebabnya ada di sini. */
.inp,select.inp,textarea.inp{width:100%;min-width:0;height:var(--kontrol);padding:0 12px;
  border:1px solid var(--garis);border-radius:10px;font-size:var(--f5);background:var(--putih);
  color:var(--teks);transition:border-color .14s,box-shadow .14s}
/* 16px di HP mencegah Safari/iOS ikut memperbesar halaman saat kolom disentuh */
.inp:focus{border-color:var(--oranye);box-shadow:0 0 0 3px rgba(242,98,46,.13);outline:none}
.inp:disabled{background:var(--latar);color:var(--teks-3)}
/* isian yang tingginya memang tidak boleh dikunci */
textarea.inp{height:auto;min-height:88px;padding:10px 12px;resize:vertical}
input[type="file"].inp{height:auto;min-height:var(--kontrol);padding:9px 12px;font-size:var(--f3)}
input[type="file"].inp::file-selector-button{font:inherit;font-size:var(--f2);margin-right:10px;
  padding:5px 11px;border:1px solid var(--garis);border-radius:8px;background:var(--latar);
  color:var(--teks);cursor:pointer}
select.inp{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='m1 1 5 5 5-5' stroke='%235A6473' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center;padding-right:32px}
.bantuan{font-size:var(--f1);color:var(--teks-3);margin-top:5px}
/* Baris teks tidak boleh selebar monitor 34": di 2560px satu baris keterangan
   sampai 128 karakter dan mata kehilangan awal baris berikutnya. Batas nyaman
   ±70 karakter — dipasang di sini sekali, bukan ditambal per halaman. */
.bantuan,.kartu-isi > p,.kartu-isi .peran-blok p,.centang span,.kosong p,.pasang-tip{max-width:70ch}
.inp-grup{display:flex;gap:var(--s2)}
.inp-grup .inp{flex:1;min-width:0}
/* Pemisah blok di dalam satu kartu — dulu tiap halaman menulis
   style="margin-top:14px;padding-top:14px;border-top:1px dashed …" sendiri. */
.blok{margin-top:var(--s3);padding-top:var(--s3);border-top:1px dashed var(--garis)}
.blok:first-child{margin-top:0;padding-top:0;border-top:0}
/* Judul langkah di dalam form panjang. Form buat-akun punya lima kelompok;
   tanpa penanda langkah ia terbaca sebagai satu tumpukan isian tanpa awal dan
   akhir, dan orang berhenti di kelompok pertama karena mengira sudah selesai. */
.blok-judul{font-size:var(--f2);text-transform:uppercase;letter-spacing:.07em;color:var(--teks-3);
  margin:0 0 var(--s2);font-family:var(--font);font-weight:700}
/* Blok yang sedang mengikuti bawaan peran: masih terbaca, jelas tidak bisa diubah. */
.blok-terkunci .izin-grid{opacity:.62}
.blok-terkunci .centang-rapat{cursor:default}
.bantuan-galat{color:var(--merah)}
.bantuan-ok{color:var(--hijau)}
/* Keterangan di kaki kartu, didorong ke ujung supaya tidak mengapit tombol. */
.kaki-ket{margin-left:auto;text-align:right}
/* Kolom penjelas (arti peran, langkah opname): satu kolom per butir, dengan
   garis penanda di kiri supaya terbaca sebagai daftar, bukan paragraf lepas. */
.peran-blok{border-left:2px solid var(--garis);padding-left:var(--s3)}
.peran-blok .pil{display:inline-flex}

/* ---------- bintang penilaian ----------
   Lima bintang abu-abu ditimpa lima bintang emas yang dipotong selebar nilai.
   Cara ini menangani pecahan berapa pun (4,3 · 4,7) tanpa aset setengah-bintang
   dan tanpa clip-path per bintang yang rapuh saat ukurannya berubah. */
.bt-baris{position:relative;display:inline-flex;line-height:0;flex:none}
.bt-baris > span{display:inline-flex;line-height:0}
.bt-kosong-lapis{color:#DDE1E8}
.bt-isi-lapis{position:absolute;inset:0 auto 0 0;overflow:hidden;width:var(--isi,0%);
  color:#E8A33D;pointer-events:none}
.bt-baris svg{flex:none;fill:currentColor}
.bintang{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
.bintang b{font-size:var(--f2);font-weight:700;color:var(--teks-2)}
.bt-jml{font-size:var(--f2);color:var(--teks-3)}
.inp-imbuhan{display:flex;align-items:center;padding:0 12px;background:var(--latar);border:1px solid var(--garis);
  border-radius:10px;font-size:var(--f3);color:var(--teks-2);white-space:nowrap;flex:none}
/* pemilih ikon kategori — radio yang tampil sebagai petak ikon */
.pilih-ikon{display:flex;flex-wrap:wrap;gap:var(--s2)}
.pilih-ikon-item{cursor:pointer}
.pilih-ikon-item input{position:absolute;opacity:0;width:0;height:0}
.pilih-ikon-item span{width:42px;height:42px;border-radius:11px;border:1px solid var(--garis);
  background:var(--putih);color:var(--teks-2);display:grid;place-items:center;
  transition:border-color .13s,background .13s,color .13s}
.pilih-ikon-item:hover span{border-color:#C9CFD9;color:var(--teks)}
.pilih-ikon-item input:checked + span{background:var(--oranye-muda);border-color:var(--oranye);
  color:var(--oranye-tua);box-shadow:0 0 0 3px rgba(242,98,46,.13)}
.pilih-ikon-item input:focus-visible + span{outline:2px solid var(--oranye);outline-offset:2px}

.centang{display:flex;align-items:flex-start;gap:9px;font-size:var(--f3);cursor:pointer;padding:4px 0}
.centang input{width:18px;height:18px;accent-color:var(--oranye);margin-top:2px;flex:none}
.centang small{display:block;color:var(--teks-3);font-size:var(--f1)}

/* unggah kode QRIS: pratinjau + isian berdampingan, menumpuk di HP */
.qris-baris{display:flex;align-items:flex-start;gap:var(--s3);flex-wrap:wrap}
.qris-pratinjau{width:96px;height:96px;object-fit:contain;border:1px solid var(--garis);
  border-radius:var(--r);padding:6px;background:var(--putih);flex:none}
.qris-isian{flex:1 1 200px;min-width:0}

/* Di HP kotak cari mengambil satu baris penuh; saringan lain turun ke bawahnya.
   Memaksakan semuanya sebaris membuat kotak cari terhimpit jadi beberapa piksel. */
.pencarian{position:relative;flex:1 1 100%;min-width:0}
.pencarian .ikon{position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--teks-3)}
.pencarian .inp{padding-left:36px}

.saring{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center;width:100%}
/* saringan di dalam kepala kartu selalu mengambil sisa ruang — dulu tiap
   halaman menuliskan style="flex:1" sendiri, dan yang lupa jadi terlihat beda */
.kartu-kepala > .saring,.lembar-alat > .saring{flex:1 1 auto;min-width:0}
.saring-kanan{justify-content:flex-end;margin-left:auto}
/* "> " WAJIB: aturan ini mengubah isian jadi item flex berlebar-otomatis.
   Tanpa pembatas anak-langsung ia juga mengenai isian DI DALAM .pencarian,
   yang membuat isian itu kembali ke lebar bawaannya (±241px) lalu menembus
   keluar kotaknya di layar HP. */
.saring > .inp{width:auto;min-width:0;flex:1 1 140px;font-size:var(--f4)}
.saring > .tbl{flex:0 0 auto}
@media (min-width:600px){.pencarian{flex:1 1 220px}}

/* ---------- rentang tanggal: SATU tombol "pil" + panel melayang (FB Ads/DewaPush)
   Dulu: <select> preset DITAMBAH sepasang kotak tanggal yang selalu nongol di
   toolbar — dua kontrol sekaligus. Sekarang: satu tombol; presetnya di panel,
   dan "Pilih…" memunculkan kotak tanggal DI DALAM panel. Panel dijadikan
   position:fixed oleh panel.js (diposisikan ke tombol) supaya tak terpotong
   .kartu{overflow:hidden}. */
.rentang{position:relative;display:inline-flex;flex:0 0 auto}
/* Ukuran = .tbl-kecil (34px · x11 · f2 · radius 8) supaya pemilih rentang di
   9 halaman laporan berdiri di tangga yang sama dengan tombol lain. */
.rentang-tombol{display:inline-flex;align-items:center;gap:7px;height:34px;min-height:34px;
  padding:0 11px;border:1px solid var(--garis);border-radius:8px;background:var(--putih);
  color:var(--teks);font:inherit;font-size:var(--f2);font-weight:600;line-height:1;cursor:pointer;
  white-space:nowrap;transition:border-color .14s,box-shadow .14s,background .14s;
  -webkit-tap-highlight-color:transparent}
.rentang-tombol:hover{border-color:#D7DBE2}
.rentang-tombol[aria-expanded="true"]{border-color:var(--oranye);box-shadow:0 0 0 3px rgba(242,98,46,.13)}
.rentang-tombol > .ikon{color:var(--teks-3);flex:none}
.rentang-teks{overflow:hidden;text-overflow:ellipsis}
.rentang-kar{color:var(--teks-3);flex:none;transition:transform .16s}
.rentang-tombol[aria-expanded="true"] .rentang-kar{transform:rotate(180deg)}

.rentang-panel{position:fixed;z-index:70;min-width:212px;max-width:calc(100vw - 16px);
  background:var(--putih);border:1px solid var(--garis);border-radius:var(--r);
  box-shadow:var(--bayang-l);padding:6px;animation:pudar .12s ease}
.rentang-opsi{display:flex;flex-direction:column}
.rentang-item{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  width:100%;padding:9px 10px;border:0;border-radius:8px;background:transparent;font:inherit;
  font-size:var(--f3);font-weight:600;color:var(--teks);cursor:pointer;text-align:left}
.rentang-item:hover{background:var(--garis-2)}
.rentang-item > .ikon{color:var(--oranye);flex:none;opacity:0}
.rentang-item.aktif{color:var(--oranye-tua)}
.rentang-item.aktif > .ikon{opacity:1}
.rentang-kustom{display:flex;flex-direction:column;gap:var(--s2);
  margin-top:6px;padding-top:var(--s3);border-top:1px solid var(--garis-2)}
.rentang-kolom{display:flex;align-items:center;gap:var(--s2);font-size:var(--f2);
  color:var(--teks-2);font-weight:600}
.rentang-kolom > span{width:46px;flex:none}
/* kotak tanggal SELALU terang walau panel muncul di atas toolbar gelap */
.rentang-kustom .inp{height:38px;font-size:var(--f4);background:var(--putih);
  border-color:var(--garis);color:var(--teks)}
.rentang-kustom .tbl{margin-top:2px}
/* toolbar gelap (Lembar Audit layar-penuh) — samakan tombol dengan .inp gelap */
.layar-atas .rentang-tombol{background:var(--permukaan-gelap);border-color:var(--garis-gelap);color:var(--putih)}
.layar-atas .rentang-tombol > .ikon,.layar-atas .rentang-tombol .rentang-kar{color:var(--teks-gelap-2)}

/* ---------- halaman pesan (login, 403) ---------- */
.halaman-pesan{display:grid;place-items:center;min-height:100vh;min-height:100dvh;
  padding:var(--s5);background:var(--latar)}
.kotak-pesan{background:var(--putih);border:1px solid var(--garis);border-radius:20px;padding:28px 24px;
  max-width:420px;width:100%;text-align:center;box-shadow:var(--bayang-l)}
.ikon-pesan{width:60px;height:60px;border-radius:18px;background:var(--oranye-muda);
  color:var(--oranye);display:grid;place-items:center;margin:0 auto var(--s3)}
/* penanda naik/turun pada KPI — dulu karakter ▲▼, sekarang ikon SVG */
.tren{display:inline-flex;align-items:center;gap:3px;font-weight:600}
.tren .ikon{width:11px;height:11px}
.kotak-pesan h1{font-size:var(--f7);margin-bottom:10px}
.kotak-pesan p{color:var(--teks-2);margin:0 0 8px}
.kotak-pesan .kecil{font-size:var(--f2);color:var(--teks-3)}
.kotak-pesan .tbl{margin:14px 6px 0}
/* kotak-pesan berisi form (ganti sandi): rata kiri, tombol selebar kotak */
.kotak-pesan.kotak-form{text-align:left}
.kotak-pesan.kotak-form .tbl{margin:var(--s3) 0 0}
.kotak-pesan.kotak-form .notif{margin:var(--s3) 0}
.rata-tengah{text-align:center}

/* pita sesi habis (layar kasir): tetap di atas, satu ketukan untuk muat ulang */
.pita-sesi{position:fixed;top:calc(var(--s2) + env(safe-area-inset-top));left:50%;transform:translateX(-50%);
  z-index:90;display:flex;align-items:center;gap:var(--s3);width:max-content;max-width:calc(100% - var(--s4));
  padding:var(--s2) var(--s2) var(--s2) var(--s4);border-radius:var(--r);background:var(--merah-muda);
  border:1px solid var(--merah);color:var(--merah);font-size:var(--f3);font-weight:600;box-shadow:var(--bayang-l)}
.pita-sesi .tbl{flex:none}
/* varian info: "versi baru siap" — bukan galat, jadi biru, bukan merah */
.pita-sesi.pita-info{background:var(--biru-muda);border-color:var(--biru-garis);color:var(--biru-tua)}

/* ---------- modal ---------- */
.modal{position:fixed;inset:0;background:rgba(14,17,22,.55);display:grid;place-items:end center;
  padding:0;z-index:60;animation:pudar .14s ease}
/* Atribut hidden SELALU menang — tanpa ini .tbl{display:inline-flex} dan sejenisnya
   memunculkan elemen ber-hidden (mis. tombol Muat ulang di peramban biasa). */
[hidden]{display:none!important}
/* Kunci gulir halaman di belakang modal. kasir.js, panel.js, dan pasang.js
   sudah menyalakan body.modal-buka, tapi dulu tanpa aturan — di HP, menggeser
   isi modal yang pendek ikut menggulir halaman di belakangnya. */
body.modal-buka{overflow:hidden;overscroll-behavior:none}
/* Lebar kotak modal: tiga ukuran saja, dipilih lewat kelas — bukan
   style="max-width:…" per modal. */
.modal-kotak.modal-sempit{max-width:400px}
.modal-kotak.modal-sedang{max-width:460px}
.modal-kotak{background:var(--putih);border-radius:20px 20px 0 0;max-width:520px;width:100%;
  box-shadow:var(--bayang-l);max-height:92vh;max-height:92dvh;overflow:auto;
  animation:naik .2s cubic-bezier(.22,1,.36,1);padding-bottom:env(safe-area-inset-bottom)}
@keyframes naik{from{transform:translateY(14px);opacity:.6}to{transform:none;opacity:1}}
.modal-kepala{padding:var(--s4);border-bottom:1px solid var(--garis-2);display:flex;
  align-items:center;gap:var(--s3);position:sticky;top:0;background:var(--putih);z-index:1}
.modal-kepala h3{font-size:var(--f5);flex:1;min-width:0}
.modal-isi{padding:var(--s4)}
/* Kaki modal: sepasang tombol yang SELALU sama tinggi dan sama lebar.
   Dulu tiap modal menulis ukurannya sendiri — "Batal" 40px berdampingan dengan
   "Selesaikan" 48px, dan lebarnya mengikuti panjang teks. Ukuran diputuskan
   di sini, jadi halaman tidak perlu (dan tidak boleh) mengaturnya lagi. */
.modal-kaki{padding:var(--s3) var(--s4);border-top:1px solid var(--garis-2);
  display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:var(--s2);
  background:var(--latar-2);position:sticky;bottom:0;
  padding-bottom:calc(var(--s3) + env(safe-area-inset-bottom))}
.modal-kaki .tbl{--tbl-t:48px;--tbl-f:var(--f4);--tbl-r:12px;width:100%;min-width:0}
@media (min-width:600px){
  .modal-kaki{display:flex;justify-content:flex-end;padding-bottom:var(--s3)}
  .modal-kaki .tbl{width:auto;min-width:136px}
}

/* ==========================================================================
   SPREADSHEET (halaman audit) — grid padat bergaya lembar kerja
   ========================================================================== */
.lembar-bungkus{overflow:auto;max-height:calc(100dvh - 230px);overscroll-behavior:contain;
  border:1px solid var(--garis);border-radius:var(--r);background:var(--putih)}
table.lembar{border-collapse:separate;border-spacing:0;font-size:var(--f3);width:100%;
  font-variant-numeric:tabular-nums}
.lembar th,.lembar td{border-right:1px solid var(--garis-2);border-bottom:1px solid var(--garis-2);
  padding:0;white-space:nowrap}
.lembar thead th{position:sticky;top:0;z-index:3;background:#F3F5F8;color:var(--teks-2);
  font-size:var(--f1);letter-spacing:.06em;text-transform:uppercase;font-weight:700;
  padding:9px 10px;border-bottom:1px solid var(--garis);text-align:left;user-select:none}
.lembar thead th.urut{cursor:pointer}
.lembar thead th.urut:hover{background:#E9EDF3;color:var(--teks)}
.lembar thead th > span.kepala{display:inline-flex;align-items:center;gap:4px}
/* penanda arah urut: ikon SVG, bukan karakter ▲▼ */
.lembar thead th .arah{opacity:.35;flex:none;transition:opacity .12s,transform .12s,color .12s}
.lembar thead th.urut:hover .arah{opacity:.7}
.lembar thead th[aria-sort] .arah{opacity:1;color:var(--oranye)}
.lembar thead th[aria-sort="descending"] .arah{transform:rotate(180deg)}
/* Header tabel biasa yang bisa diklik untuk mengurutkan — pola sama persis
   dengan lembar audit di atas, dipakai mis. di Transaksi. Hanya menyala bila
   <th> ber-class .urut, jadi tabel lain sama sekali tak terpengaruh. */
.tabel thead th.urut{cursor:pointer;user-select:none}
.tabel thead th.urut:hover{color:var(--teks)}
.tabel thead th > span.kepala{display:inline-flex;align-items:center;gap:4px}
.tabel thead th .arah{opacity:.3;flex:none;transition:opacity .12s,transform .12s,color .12s}
.tabel thead th.urut:hover .arah{opacity:.7}
.tabel thead th[aria-sort] .arah{opacity:1;color:var(--oranye)}
.tabel thead th[aria-sort="descending"] .arah{transform:rotate(180deg)}
.tabel thead th.urut.kol-no > span.kepala{justify-content:flex-end}
.lembar th.kol-no,.lembar td.kol-no{width:44px;text-align:right;color:var(--teks-3);
  font-size:var(--f1);font-weight:600}
.lembar td.kol-no > .sel{text-align:right;padding-right:10px}
.lembar td{padding:0}
.lembar td > .sel{display:block;padding:8px 10px;min-height:34px;line-height:18px}
.lembar td.kanan > .sel{text-align:right}
.lembar td.tengah > .sel{text-align:center}
/* Dua kolom pertama (nomor + nama) ikut membeku supaya baris tetap bisa
   dikenali saat lembar digeser jauh ke kanan. */
.lembar .beku-no,.lembar .beku{position:sticky;z-index:2;background:var(--putih)}
.lembar .beku-no{left:0;width:44px}
.lembar .beku{left:44px;box-shadow:1px 0 0 var(--garis);max-width:150px}
.lembar .beku .sel{overflow:hidden;text-overflow:ellipsis}
.lembar thead .beku-no,.lembar thead .beku{z-index:4;background:#F3F5F8}
.lembar tbody tr:nth-of-type(even) td{background:#FCFDFE}
.lembar tbody tr:nth-of-type(even) .beku-no,
.lembar tbody tr:nth-of-type(even) .beku{background:#FCFDFE}
.lembar tbody tr:hover td{background:var(--oranye-muda)}
.lembar tbody tr:hover .beku-no,.lembar tbody tr:hover .beku{background:var(--oranye-muda)}
.lembar tbody tr.baris-pilih td{background:#FFF6F2}
.lembar-input{width:100%;border:0;background:transparent;padding:8px 10px;font:inherit;
  font-size:var(--f3);text-align:right;font-variant-numeric:tabular-nums;min-height:34px;color:var(--teks)}
.lembar-input:focus{outline:2px solid var(--oranye);outline-offset:-2px;background:var(--putih);
  box-shadow:inset 0 0 0 99px #FFF9F6}
.lembar-input::placeholder{color:#C2C8D2}
.lembar .plus{color:var(--hijau);font-weight:600}
.lembar .minus{color:var(--merah);font-weight:600}
.lembar-kaki{display:flex;flex-wrap:wrap;gap:var(--s3);align-items:center;padding:var(--s3) var(--s4);
  border-top:1px solid var(--garis);background:var(--latar-2);font-size:var(--f2);color:var(--teks-2)}
.lembar-kaki b{color:var(--teks);font-variant-numeric:tabular-nums}
.lembar-alat{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center;margin-bottom:var(--s3)}
.lembar-kolom{display:flex;gap:6px;flex-wrap:wrap}
/* tab lembar = ukuran .tbl-kecil (34px), dulu ±28px hasil padding */
.kol-tbl{display:inline-flex;align-items:center;height:34px;border:1px solid var(--garis);
  background:var(--putih);border-radius:8px;padding:0 11px;line-height:1;
  font-size:var(--f2);font-weight:600;color:var(--teks-2);cursor:pointer}
.kol-tbl[aria-pressed="true"]{background:var(--tinta);border-color:var(--tinta);color:var(--putih)}

/* ==========================================================================
   MODE LAYAR PENUH (Lembar Audit) — tanpa sidebar & topbar, lembar mengisi
   seluruh tinggi layar supaya satu layar = sebanyak mungkin baris.
   ========================================================================== */
body.layar-penuh{height:100dvh;overflow:hidden;background:var(--putih)}
.layar{position:fixed;inset:0;display:flex;flex-direction:column;background:var(--latar)}
.layar-atas{flex:none;display:flex;align-items:center;gap:var(--s2);padding:var(--s2) var(--s3);
  background:var(--tinta);color:var(--putih);min-height:52px;padding-top:max(var(--s2),env(safe-area-inset-top))}
.layar-atas h1{font-size:var(--f4);font-weight:800;color:var(--putih);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.layar-atas .redup{color:var(--teks-gelap-2)}
.layar-atas .tbl{--bg:var(--permukaan-gelap);--bg-h:#28303F;--fg:#D7DEE9;--bd:#28303F;--bd-h:#394355}
/* Di HP baris ini penuh: yang mengalah judul (sudah ber-elipsis), bukan tombol —
   dulu tombol kembali terperas jadi ±26px, di bawah sasaran ketuk. */
.layar-atas > .tbl{flex:none}
.layar-atas .tbl-utama{--bg:var(--oranye);--bg-h:var(--oranye-tua);--fg:var(--putih);
  --bd:var(--oranye);--bd-h:var(--oranye-tua)}
.layar-atas .inp{background:var(--permukaan-gelap);border-color:var(--garis-gelap);color:var(--putih);height:34px;padding:0 11px}
.layar-atas .inp::placeholder{color:var(--teks-gelap-3)}
/* Rantai flex WAJIB utuh dari .layar sampai .lembar-bungkus, kalau tidak
   lembar tidak tahu tinggi yang tersedia dan kembali setinggi isinya. */
.layar-isi{flex:1;min-height:0;display:flex;flex-direction:column;background:var(--putih)}
.layar-isi > .lembar-alat{flex:none}
.layar-isi > form{flex:1;min-height:0;display:flex;flex-direction:column}
.layar-isi .lembar-bungkus{flex:1;min-height:0;max-height:none;border:0;border-radius:0;
  margin:0}
.layar-isi .lembar-kaki{flex:none;padding-bottom:max(var(--s3),env(safe-area-inset-bottom))}
/* di layar penuh, tinggi baris dirapatkan supaya lebih banyak baris muat */
body.layar-penuh .lembar td > .sel{padding:6px 10px;min-height:30px}
body.layar-penuh .lembar-input{padding:6px 10px;min-height:30px}

/* ==========================================================================
   UPDATE STOK HARIAN — pencocokan bon belanja
   ========================================================================== */
/* lompatan cepat ke tanggal yang memang ada belanjanya */
.hari-cepat{display:flex;align-items:center;gap:var(--s1);flex-wrap:wrap;margin-left:auto}
.hari-cepat .pil{text-decoration:none}
.hari-cepat .pil:hover{background:var(--tinta);color:var(--putih)}

/* ---------- sasaran sentuh di HP / layar sentuh ----------
   Pil tanggal & tautan teks di tengah kalimat cuma ±20px tingginya. Di layar
   sentuh (atau layar sempit) sasarannya dibesarkan: pil jadi 36px, tautan
   teks inline mendapat padding vertikal — padding pada elemen inline
   memperbesar area ketuk TANPA mengubah tinggi baris, jadi tata letak tetap. */
@media (pointer:coarse),(max-width:899px){
  .hari-cepat .pil{min-height:36px;padding:0 12px}
  .isi a:not([class]),.isi a.redup-2,.notif a:not([class]){padding-block:9px}
}

/* Tiga sel setara: sistem — bon — selisih. Mobile-first: menumpuk di HP,
   berjajar mulai 640px. */
.cocok-grid{display:grid;gap:var(--s3)}
.cocok-sel{display:flex;flex-direction:column;gap:var(--s1);padding:var(--s3);
  border:1px solid var(--garis);border-radius:var(--r);background:var(--latar);min-width:0}
.cocok-label{font-size:var(--f2);color:var(--teks-2);font-weight:600}
.cocok-nilai{font-family:var(--font-judul);font-size:var(--f8);font-weight:800;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1.15;overflow-wrap:anywhere}
.cocok-catatan{font-size:var(--f2);color:var(--teks-3)}
#cocokHasil.cocok-pas{background:var(--hijau-muda);border-color:var(--hijau)}
#cocokHasil.cocok-pas .cocok-nilai,#cocokHasil.cocok-pas .cocok-catatan{color:var(--hijau)}
#cocokHasil.cocok-beda{background:var(--kuning-muda);border-color:var(--kuning)}
#cocokHasil.cocok-beda .cocok-nilai,#cocokHasil.cocok-beda .cocok-catatan{color:var(--kuning)}

.kol-centang{width:38px}
.kol-centang input{width:17px;height:17px;accent-color:var(--oranye);cursor:pointer;margin:0}
/* baris yang sudah diadu dengan bon sengaja DIREDUPKAN, bukan disorot: yang
   perlu menonjol justru sisa baris yang belum diperiksa */
.baris-cocok{background:var(--hijau-muda)}
.baris-cocok td{color:var(--teks-3)}
.baris-cocok td strong{color:var(--teks-2)}
/* Pola bug yang sama seperti dulu di .tbl:hover vs .tbl-merah: `.tabel tbody
   tr:hover td` (2 kelas) lebih spesifik dari `.baris-cocok td`/`.baris-tandai td`
   (1 kelas), jadi menyorot baris ini dengan mouse membuat warnanya HILANG —
   td dapat background hover sendiri yang menimpa hijau/kuningnya. */
.tabel tbody tr.baris-cocok:hover td{background:#DCF2E7}
.tabel tbody tr.baris-tandai:hover td{background:#FFEFCF}

/* ==========================================================================
   PENGAWASAN STOK (admin)
   ========================================================================== */
.kotak-rahasia{display:flex;gap:var(--s3);align-items:flex-start;padding:var(--s3) var(--pad-kartu);
  border:1px solid var(--biru);border-radius:var(--r);background:var(--biru-muda);
  color:var(--teks-2);font-size:var(--f3);line-height:1.5}
.kotak-rahasia svg{flex:none;color:var(--biru);margin-top:1px}
.kotak-rahasia strong{color:var(--teks);display:block}

/* Garis tebal di tepi kiri menggantikan latar berwarna: kartu temuan berisi
   tabel, dan latar merah di belakang tabel membuat angkanya susah dibaca. */
.kartu-awas{border-left:3px solid var(--garis)}
.kartu-awas.awas-tinggi{border-left-color:var(--merah)}
.kartu-awas.awas-sedang{border-left-color:var(--kuning)}
.awas-judul{display:flex;align-items:center;gap:var(--s3);min-width:0;flex:1}
.awas-judul h2{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.awas-alasan{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--s2)}
.awas-alasan li{display:flex;flex-direction:column;gap:2px;padding:var(--s2) var(--s3);
  border-radius:var(--r-s);background:var(--latar);font-size:var(--f3);line-height:1.5}
.awas-alasan strong{color:var(--teks)}
.awas-alasan span{color:var(--teks-2)}
.awas-kaki{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.awas-aksi{display:flex;gap:var(--s2);margin-left:auto;flex-wrap:wrap}

/* ==========================================================================
   PENGAMAN MARGIN
   ========================================================================== */
.margin-panel{display:flex;gap:var(--s3);align-items:flex-start;padding:var(--s3);
  border:1px solid var(--garis);border-radius:var(--r);background:var(--latar);
  font-size:var(--f3);line-height:1.5}
.margin-ikon{flex:none;display:grid;place-items:center;width:32px;height:32px;border-radius:var(--r-s);
  background:var(--putih);border:1px solid var(--garis);color:var(--teks-3)}
.margin-teks{display:flex;flex-direction:column;gap:1px;min-width:0}
.margin-teks strong{color:var(--teks)}
.margin-teks span{color:var(--teks-2)}
.margin-sehat{border-color:var(--hijau);background:var(--hijau-muda)}
.margin-sehat .margin-ikon{color:var(--hijau);border-color:var(--hijau)}
.margin-sehat .margin-teks strong{color:var(--hijau)}
.margin-tipis{border-color:var(--kuning);background:var(--kuning-muda)}
.margin-tipis .margin-ikon{color:var(--kuning);border-color:var(--kuning)}
.margin-tipis .margin-teks strong{color:var(--kuning)}
.margin-rugi{border-color:var(--merah);background:var(--merah-muda)}
.margin-rugi .margin-ikon{color:var(--merah);border-color:var(--merah)}
.margin-rugi .margin-teks strong{color:var(--merah)}

/* ringkasan stok yang dipotong (form produk) */
.potong-kotak{display:flex;flex-direction:column;gap:var(--s1);padding:var(--s3);
  border:1px dashed var(--garis);border-radius:var(--r-s);background:var(--latar);font-size:var(--f3);line-height:1.5}
.potong-judul{display:flex;align-items:center;gap:6px;font-size:var(--f2);font-weight:700;color:var(--teks-2)}
.potong-daftar{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--s1)}
.potong-daftar li{color:var(--teks-2)}
.potong-daftar strong{color:var(--teks)}

/* ---------- utilitas ---------- */
.baris{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.baris-antar{display:flex;gap:10px;align-items:center;justify-content:space-between;flex-wrap:wrap}
.dorong{margin-left:auto}
/* jarak: hanya tangga ini yang boleh dipakai — tidak ada margin inline ad-hoc */
.mt0{margin-top:0}.mb0{margin-bottom:0}
.mt8{margin-top:var(--s2)}.mt12{margin-top:var(--s3)}.mt16{margin-top:var(--s4)}
.mb8{margin-bottom:var(--s2)}.mb16{margin-bottom:var(--s4)}
.sebaris{display:inline}
.dr-total{background:var(--latar-2);border-top:1px solid var(--garis)}
.dr-total .dr-teks strong{font-weight:700}
.kecil{font-size:var(--f2)}
.redup{color:var(--teks-2)}
.redup-2{color:var(--teks-3)}
.tebal{font-weight:700}
/* Keterangan baris kedua di dalam sel tabel — dipakai supaya angka utama tetap
   satu baris yang bisa dipindai, sedangkan konteksnya ("3 nota") tidak
   memaksa kolomnya melebar. */
.sub{display:block;font-size:var(--f1);font-weight:400;color:var(--teks-3);margin-top:1px}
/* Warna teks status. Dua nama untuk satu aturan: `.merah` (lama, dipakai PHP &
   JS di puluhan tempat) dan `.teks-merah` (nama baru yang lebih jelas). Dulu
   keduanya ditulis sebagai dua aturan terpisah yang bisa berbeda diam-diam. */
.hijau,.teks-hijau{color:var(--hijau)}
.merah,.teks-merah{color:var(--merah)}
.kuning,.teks-kuning{color:var(--kuning)}
.pb0{padding-bottom:0}
/* Tombol yang tampil sebagai tautan dalam kalimat — tetap <button> supaya
   pembaca layar tahu ia melakukan sesuatu, bukan berpindah halaman. */
.tautan{background:0;border:0;padding:0;font:inherit;color:var(--oranye);font-weight:600;
  cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.tautan:hover{color:var(--oranye-tua)}
/* Isian sempit yang duduk di dalam sel tabel bersama tombolnya. Hanya LEBARNYA
   yang dipersempit — tingginya sengaja dibiarkan mengikuti `.inp` (40px di
   desktop, 44px di HP). Memendekkannya agar sejajar tombol kecil membuat sasaran
   ketuk di bawah ambang, dan isian ini diisi sambil memegang uang. */
.inp-kecil{width:104px;padding-left:var(--s2);padding-right:var(--s2);font-size:var(--f3)}
.sesi-tutup{display:flex;gap:var(--s1);justify-content:flex-end;align-items:center}
.angka{font-variant-numeric:tabular-nums}
.nowrap{white-space:nowrap}
.hanya-hp{display:initial}
.hanya-besar{display:none}

.bar{height:6px;border-radius:3px;background:var(--garis-2);overflow:hidden}
.bar i{display:block;width:var(--p,0%);height:100%;background:var(--oranye);border-radius:3px}

/* ---------- pengganti gaya inline ----------
   Nilai yang memang DATA dikirim dari server sebagai custom property — lebar
   batang (bar_html() → --p) dan warna produk (gaya_warna_produk() → --latar /
   --warna) — sedangkan rupanya tetap diatur di sini. Sisanya dulu gaya
   tempelan bernilai tetap di template; spesifisitas di bawah sengaja cukup
   tinggi untuk mengalahkan aturan dasar yang dulu dikalahkan style="". */
.warna-produk{background:var(--latar);color:var(--warna)}
.produk-avatar.av-oranye{background:var(--oranye-muda);color:var(--oranye)}
.produk-avatar.av-biru{background:var(--biru-muda);color:var(--biru)}
.produk-avatar.av-gelap{background:var(--tinta);color:var(--putih)}
.kol-porsi{width:38%}
.kol-urutan{width:60px}
.kol-hitung{min-width:260px}
.kol-progres{min-width:110px}
select.inp.inp-produk{min-width:230px}
.inp.inp-alasan{width:230px}
.baris.baris-lega{gap:26px}
.baris.layar-atas-aksi{gap:var(--s2);margin-left:auto;flex-wrap:nowrap}
label.lb.lb-sebaris{margin:0 6px 0 0;align-self:center}
.form-baris.form-baris-sempit{max-width:280px}
.centang.centang-tengah{justify-content:center;margin-top:10px}
.kotak-rahasia.kotak-bahaya{border-color:var(--merah);background:var(--merah-muda)}
.kartu.kartu-sukses{border-color:var(--hijau)}
/* Logo toko (Pengaturan → Identitas toko) */
.blok.logo-pilih{display:flex;gap:var(--s3);align-items:flex-start;margin-bottom:var(--s3)}
.pratinjau-logo{width:76px;height:76px;flex:none;border:1px solid var(--garis);border-radius:14px;
  background:var(--oranye-muda);display:grid;place-items:center;overflow:hidden;color:var(--oranye)}
.pratinjau-logo.ada-logo{background:var(--putih)}
.pratinjau-logo img{width:100%;height:100%;object-fit:contain}
.logo-pilih-isi{flex:1;min-width:0}

.daftar-ringkas{display:flex;flex-direction:column}
.dr-item{display:flex;align-items:center;gap:11px;padding:11px var(--s4);border-bottom:1px solid var(--garis-2)}
.dr-item:last-child{border-bottom:0}
.dr-teks{flex:1;min-width:0}
.dr-teks strong{display:block;font-size:var(--f3);font-weight:600;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.dr-teks span{font-size:var(--f1);color:var(--teks-3)}
.dr-nilai{font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}

/* ---------- ajakan pasang aplikasi (A2HS) ----------
   DULU: pita melayang di dasar layar. Di layar kasir pita itu masuk ke bawah
   panel keranjang (yang ber-z-index lebih tinggi) sehingga hanya ikonnya
   yang menyembul dan tampak seperti kotak hitam rusak.
   SEKARANG: tombol resmi di topbar — tidak pernah menutupi apa pun. */
.tbl-pasang{--bg:var(--tinta);--bg-h:var(--tinta-3);--fg:var(--putih);--bd:var(--tinta);--bd-h:var(--tinta-3)}

/* panduan pasang untuk iOS (Safari tak punya beforeinstallprompt) */
.pasang-tip{display:flex;gap:var(--s3);align-items:flex-start;padding:var(--s3);
  background:var(--latar);border:1px solid var(--garis);border-radius:var(--r);font-size:var(--f3)}
.pasang-tip .ikon{color:var(--oranye);flex:none;margin-top:1px}
.pasang-tip ol{margin:6px 0 0;padding-left:18px}
.pasang-tip li{margin-bottom:3px}

/* ==========================================================================
   LAYAR BESAR
   ========================================================================== */
/* ---- TABLET KECIL / HP REBAH (≥600) ---- */
@media (min-width:600px){
  :root{--tepi:14px}
  .form-baris.f2{grid-template-columns:1fr 1fr}
  /* Kolom kiri berisi kotak ketik + tombol, kolom kanan hanya satu centang.
     Dibagi rata, sisi kanan berakhir kosong dua pertiganya. */
  .form-baris.f-sandi{grid-template-columns:minmax(0,2fr) minmax(0,1fr)}
  .grid-2{grid-template-columns:repeat(2,1fr)}
  /* sistem — bon — selisih berjajar, urutan baca sama dengan urutan kerjanya */
  .cocok-grid{grid-template-columns:repeat(3,1fr)}
  .profil-teks{display:flex}
  .modal{place-items:center;padding:var(--s5)}
  .modal-kotak{border-radius:18px;max-height:90vh}
}
/* ---- TABLET BESAR (≥900) ----
   Di sini isian boleh turun ke 14px: layar selebar ini tidak lagi memicu
   pembesaran otomatis Safari saat kolom disentuh, dan --kontrol menyusut ke
   40px seperti tombolnya. Tablet tegak (768/834) sengaja TETAP 16px/44px —
   di sana jari masih jadi alat tunjuk utama. */
@media (min-width:900px){
  :root{--tepi:16px;--seksi:12px;--pad-kartu:14px;--kontrol:40px}
  .inp,select.inp,textarea.inp{font-size:var(--f4)}
  .grid-3{grid-template-columns:repeat(3,1fr)}
  .grid-4{grid-template-columns:repeat(4,1fr)}
  /* Dua kolom sudah menyala di sini, bukan menunggu 1100px. Selama menu masih
     berupa laci, tablet 900–1099px punya lebar isi yang sama dengan desktop
     1100px+ — membiarkannya menumpuk satu kolom membuat tablet terasa seperti
     "HP yang diperbesar", persis keluhan yang mau dihindari. */
  .grid-2-1{grid-template-columns:2fr 1fr}
  .form-baris.f3{grid-template-columns:repeat(3,1fr)}
  .form-baris.f4{grid-template-columns:repeat(2,1fr)}
  .atas-judul h1{font-size:var(--f6)}
  .atas-judul p{display:block}
  .jam-toko{display:flex}
  .profil{padding-left:var(--s3);border-left:1px solid var(--garis)}
  .kpi-nilai{font-size:var(--f7)}
  .lembar .beku{max-width:none}
}
@media (min-width:1100px){
  .sisi{transform:none;box-shadow:none;width:var(--sisi-lebar)}
  .sisi-tutup,.tombol-menu{display:none}
  .tirai{display:none!important}
  /* mulai di sini menu berhenti melayang dan benar-benar memakan ruang —
     rumus pemusat isi harus tahu itu supaya sisa kiri & kanan tetap sama */
  :root{--sisi-ruang:var(--sisi-lebar)}
  .atas,.isi{margin-left:var(--sisi-lebar)}
  .form-baris.f4{grid-template-columns:repeat(4,1fr)}
  .hanya-hp{display:none}
  .hanya-besar{display:initial}
  .lembar-bungkus{max-height:calc(100dvh - 226px)}
}
@media (min-width:1400px){
  :root{--tepi:22px}
}
/* ---- ULTRAWIDE (≥2000) ----
   Isi diberi sedikit napas lagi, tapi tetap berbatas: pada monitor 34" konten
   selebar layar berarti mata harus menyapu 3440px untuk membaca satu baris.
   Yang benar bukan "penuhi layar", melainkan "melebar sampai nyaman, lalu
   berhenti di tengah" — sisa kiri & kanan tetap sama (diuji di 2560 & 3440). */
@media (min-width:2000px){
  :root{--isi-maks:1720px;--tepi:26px}
}
/* Pemusatan isi di layar lebar TIDAK lagi punya breakpoint sendiri — rumusnya
   ada di .isi/.atas dan berlaku di semua lebar sekaligus. Breakpoint terpisah
   itulah yang dulu meninggalkan sela 1800–1899px tanpa pemusatan. */

/* ==========================================================================
   SHIFT — lencana, penyaring, dan kartu ringkasan dua shift.
   Warnanya SENGAJA netral (biru vs ungu), bukan hijau/merah: shift bukan status
   baik-buruk, dan mewarnainya begitu membuat shift malam terlihat bermasalah.
   ========================================================================== */
.pil-shift-1{background:var(--biru-muda);color:var(--biru-tua)}
.pil-shift-2{background:#F0EBFC;color:#5B3BB5}

.shift-tab{display:flex;gap:var(--s1);flex-wrap:wrap;margin-top:var(--s2)}
.shift-tab .tbl.aktif{--bg:var(--tinta);--bg-h:var(--tinta-3);--fg:var(--putih);--bd:var(--tinta);--bd-h:var(--tinta-3)}

.shift-pratinjau{display:grid;gap:var(--s2)}
.shift-pratinjau > div{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;
  padding:var(--s2) var(--s3);border:1px solid var(--garis);border-radius:var(--r-s);background:var(--latar)}
.shift-pratinjau strong{font-variant-numeric:tabular-nums}

.kartu-shift{border-top:3px solid var(--biru)}
.shift-angka{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s3)}
.shift-angka > div{display:flex;flex-direction:column;gap:2px;min-width:0}
.shift-angka span{font-size:var(--f2);color:var(--teks-3)}
.shift-angka strong{font-size:var(--f5);font-family:var(--font-judul);letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.shift-stok{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.shift-stok .ikon{vertical-align:-2px}
@media (min-width:900px){.shift-angka{grid-template-columns:repeat(4,1fr)}}

/* ---------- blok berjudul di dalam kartu ---------- */
.judul-blok{font-size:var(--f2);text-transform:uppercase;letter-spacing:.07em;
  color:var(--teks-3);margin:0 0 var(--s2);font-weight:600}

/* ---------- kotak centang rapat (matriks izin) ---------- */
.centang-rapat{padding:2px 0;font-size:var(--f2)}
.centang-rapat input{width:16px;height:16px}
/* align-items:start — kelompok izin berisi 2 butir tidak ikut ditarik setinggi
   kelompok berisi 7. Tanpa itu kotak "Kuasa penuh" menganga ±250px kosong di
   sebelah kotak "Lihat" yang penuh, dan bacaannya seperti ada isi yang gagal
   dimuat. */
.izin-grid{display:grid;gap:var(--s3);align-items:start;
  grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin-top:var(--s2)}
.izin-grup{border:1px solid var(--garis);border-radius:var(--r-s);padding:var(--s3);background:var(--latar);min-width:0}
.izin-grup h4{font-size:var(--f1);text-transform:uppercase;letter-spacing:.07em;
  color:var(--teks-3);margin:0 0 var(--s2)}
/* Daftar toko dibingkai sama seperti kelompok izin — dua daftar centang yang
   berdampingan di satu form tidak boleh terlihat berasal dari dua rancangan. */
.toko-centang{display:grid;gap:var(--s2);align-items:start;
  grid-template-columns:repeat(auto-fit,minmax(200px,1fr));margin-top:var(--s2);
  border:1px solid var(--garis);border-radius:var(--r-s);padding:var(--s3);background:var(--latar)}

/* ---------- pemilih peran berbentuk kartu ---------- */
.peran-pilih{display:grid;gap:var(--s2);grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.peran-kartu{display:flex;gap:var(--s2);align-items:flex-start;cursor:pointer;min-width:0;
  border:1px solid var(--garis);border-radius:var(--r-s);padding:var(--s3);background:var(--putih)}
.peran-kartu input{margin-top:3px;accent-color:var(--oranye);flex:none}
.peran-kartu strong{display:block;font-size:var(--f3)}
.peran-kartu small{display:block;color:var(--teks-3);font-size:var(--f1);line-height:1.5}
.peran-kartu:has(input:checked){border-color:var(--oranye);background:var(--oranye-muda)}
/* Peran yang mustahil disimpan (akun sendiri / admin besar terakhir): terbaca
   tapi jelas tidak bisa dipilih. Ditolak setelah form dikirim jauh lebih
   membingungkan daripada tidak bisa diklik sejak awal. */
.peran-kartu.peran-mati{opacity:.5;cursor:not-allowed}
.peran-kartu.peran-mati:hover{border-color:var(--garis);background:var(--putih)}
/* Keterangan kenapa sesuatu terkunci — nada netral, bukan galat: ini pagar yang
   memang disengaja, bukan kesalahan yang baru saja dibuat orangnya. */
.catatan-kunci{display:flex;gap:7px;align-items:flex-start;margin:0 0 var(--s2);
  padding:8px 10px;border:1px solid var(--garis);border-radius:var(--r-s);
  background:var(--latar);color:var(--teks-2);font-size:var(--f2);line-height:1.5}
.catatan-kunci .ikon{flex:none;margin-top:1px;color:var(--teks-3)}
.peran-kartu .peran-jml{color:var(--teks-2);font-weight:700;margin-top:3px}

/* ---------- sinkron katalog ---------- */
.sinkron-arah{display:flex;flex-direction:column;gap:4px;min-width:0;flex:1 1 200px}
.sinkron-panah{display:grid;place-items:center;color:var(--teks-3);padding-top:var(--s4);flex:none}

/* ---------- sandi sekali tampil ---------- */
.kartu-tandai{border-color:var(--hijau)}
.sandi-tampil{display:flex;flex-direction:column;gap:2px;padding:var(--s3);border-radius:var(--r-s);
  background:var(--hijau-muda);border:1px dashed #8FCFB4}
.sandi-tampil strong{font-size:var(--f6);letter-spacing:.02em;user-select:all}
.baris-tandai{background:var(--kuning-muda)}

/* ---------- lain-lain ---------- */
.bar-mini{height:4px;margin-top:5px}
.tbl-tumpuk{display:grid;gap:var(--s2)}
.notif-pusat{background:#EEF2FF;color:#2A3E86;border-color:#C9D5F8}

/* ---------- modal / harga pokok ---------- */
/* Pratinjau HPP di Stok Masuk: hasil perhitungan ditampilkan SEBELUM disimpan,
   jadi ia harus terbaca sebagai keterangan — bukan sebagai isian lain. */
.hpp-pratinjau{margin-top:var(--s2);padding:var(--s2) var(--s3);border-radius:var(--r-s);
  background:var(--latar);border:1px solid var(--garis-2);font-size:var(--f2)}
.hpp-pratinjau > div{display:flex;justify-content:space-between;align-items:baseline;
  gap:var(--s3);padding:3px 0;min-width:0}
.hpp-pratinjau > div + div{border-top:1px solid var(--garis-2)}
.hpp-pratinjau span{color:var(--teks-2);flex:none}
.hpp-pratinjau strong{text-align:right;min-width:0;font-variant-numeric:tabular-nums}
.hpp-pratinjau strong small{display:block;font-weight:500}
.hpp-pratinjau p{margin:var(--s2) 0 0;color:var(--teks-2);font-size:var(--f1);line-height:1.45}
.hpp-awas{background:var(--kuning-muda);border-color:var(--kuning-garis)}
.hpp-bahaya{background:var(--merah-muda);border-color:var(--merah-garis)}
.hpp-bahaya p,.hpp-awas p{color:var(--teks)}

/* Teks var(--oranye) di atas var(--oranye-muda) cuma kontras 2,90:1 (gagal AA
   4,5:1) — badge kecil ini gampang tak terbaca di layar yang kurang terang.
   #B8431A dipilih karena tepat 4,94:1, masih keluarga oranye yang sama. */
.lb-wajib{font-size:var(--f1);font-weight:700;color:#B8431A;background:var(--oranye-muda);
  border-radius:99px;padding:1px 7px;margin-left:5px;letter-spacing:.02em;text-transform:uppercase}

.awas-baris{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;min-width:0}
.awas-baris > svg{color:var(--kuning);flex:none}
/* Dibatasi panjang barisnya: kartu ini selebar halaman, dan di layar 2560px
   satu paragraf jadi 248 karakter per baris — mata kehilangan jejak saat
   berpindah ke baris berikutnya, jadi peringatannya justru tidak terbaca. */
/* Batasnya dipasang pada PARAGRAFNYA, bukan pada pembungkus: `ch` mengikuti
   font elemen tempat ia ditulis, dan pembungkus ini berfont lebih besar
   daripada paragraf di dalamnya — 78ch di pembungkus ternyata masih 96
   karakter bagi paragrafnya. */
.awas-baris > div{flex:1 1 240px;min-width:0}
/* 72ch, bukan 80: satu `ch` pada font ini ±0,63em, sedangkan batas kenyamanan
   dihitung dengan asumsi ±0,5em per karakter — 80ch ternyata masih setara 101
   karakter per baris. */
.awas-baris p{margin:2px 0 0;color:var(--teks-2);font-size:var(--f2);line-height:1.45;max-width:72ch}

/* Kolom isian harus SELALU muat tanpa menggeser tabel: kalau ia terdorong ke
   luar layar, tindakan utama halaman ini jadi tidak bisa dilakukan di HP. */
.inp-grup-kecil{min-width:132px}
.tabel-modal .kol-isi{width:148px}
.tabel-modal td.kol-isi{padding-top:5px;padding-bottom:5px}
.tabel-modal .hanya-hp{display:none}
.kaki-modal{justify-content:space-between}
@media (max-width:820px){
  /* stok & modal kini dilipat ke bawah nama produk; untung disembunyikan karena
     sudah terbaca dari modal dan harga jual */
  .tabel-modal .kol-lipat,.tabel-modal .kol-untung{display:none}
  .tabel-modal .hanya-hp{display:inline}

  /* Lebar dikunci, bukan diserahkan ke isi. Dengan tata letak otomatis, judul
     kolom yang tidak boleh patah ("HARGA JUAL", "MODAL BARU") plus nama produk
     panjang menyeret tabel jadi 560px di layar 396px — dan yang terdorong ke
     luar layar justru kolom isian, satu-satunya alasan halaman ini ada. */
  /* Tabel data lain sengaja diberi lebar minimum 560px lalu digeser mendatar
     (lihat aturan di ≤599px). Tabel ini dikecualikan: yang paling kanan bukan
     angka pelengkap melainkan KOLOM ISIAN, dan kolom yang harus digeser dulu
     sama saja dengan tidak ada. */
  .tabel-bungkus > table.tabel-modal{min-width:0;table-layout:fixed}
  .tabel-modal th{white-space:normal}
  .tabel-modal .kol-no{width:24px}
  .tabel-modal th:nth-child(4){width:66px}    /* harga jual */
  .tabel-modal .kol-isi{width:124px}
  /* "Rp" dilepas di layar sempit: judul kolomnya sudah menyebut modal, dan
     30px itu selisih antara isian yang bisa dibaca dan yang tidak. */
  .tabel-modal .inp-grup-kecil .inp-imbuhan{display:none}
  .tabel-modal .inp-grup-kecil .inp{border-radius:var(--r-s)}
  .tabel-modal td{padding-left:var(--s2);padding-right:var(--s2);word-break:break-word}
  .inp-grup-kecil{min-width:0}
}

/* ---------- cetak (struk & laporan) ---------- */
@media print{
  .sisi,.atas,.tirai,.tbl,.notif,.panduan,.no-cetak{display:none!important}
  .isi{margin:0;padding:0;max-width:none}
  .kartu{border:0;box-shadow:none;margin:0}
  .lembar-bungkus{max-height:none;overflow:visible;border:0}
  .lembar thead th{position:static}
  .lembar .beku{position:static;box-shadow:none}
  body{background:var(--putih);font-size:var(--f2)}
}

/* ---------- grafik interaktif (assets/js/grafik.js) ----------
   Batang + sumbu digambar SVG; pita sorot & tooltip mengikuti kursor.
   Angka dibaca lewat sumbu-Y dan tooltip — tidak ada label di tiap batang. */
/* Tinggi dipesan sejak HTML tiba (grafik_html() menulis --tinggi), jadi isi di
   bawahnya tidak melompat saat grafik selesai digambar; sebelum itu tampil
   sebagai kerangka berkilau (grafik.js memasang data-siap). */
.grafik-svg{position:relative;width:100%;min-height:var(--tinggi,0px)}
.grafik-svg:not([data-siap]){border-radius:var(--r)}
.grafik-svg svg{display:block;width:100%}
.grafik-svg .g-teks{font-size:var(--f1);fill:var(--teks-3);font-weight:500}
.grafik-svg .g-batang{transition:filter .12s}
.grafik-svg .g-batang.aktif{filter:brightness(1.07)}
.grafik-tip{position:absolute;left:0;top:0;z-index:30;pointer-events:none;background:var(--putih);
  border:1px solid var(--garis);border-radius:10px;box-shadow:var(--bayang-l);
  padding:7px 11px;font-size:var(--f2);line-height:1.45;white-space:nowrap;
  opacity:0;transition:opacity .12s}
.grafik-tip.tampak{opacity:1}
.grafik-tip strong{display:block;font-size:var(--f1);color:var(--teks-2);font-weight:600;margin-bottom:2px}
.grafik-tip b{display:block;font-size:var(--f3);font-weight:800;color:var(--teks);font-variant-numeric:tabular-nums}
.grafik-tip em{display:block;font-style:normal;font-size:var(--f1);color:var(--teks-3);margin-top:1px}
@media (prefers-reduced-motion:reduce){.grafik-svg .g-batang,.grafik-tip{transition:none}}

/* kolom samping yang jauh lebih pendek dari kolom utama (mis. Pengaturan)
   ikut menggulir menempel di bawah topbar — ruang kanan tidak pernah kosong */
@media (min-width:1000px){
  .lengket{position:sticky;top:calc(var(--atas-tinggi) + var(--seksi) + var(--tepi))}
  .grid-2-1 > .lengket{align-self:start}
}

/* ---------- transisi antar-halaman (View Transitions) ----------
   Aplikasi ini multi-halaman: tiap menu memuat dokumen HTML baru, jadi pindah
   halaman dulu terasa "kedip" putih sekejap. @view-transition lintas-dokumen
   membuat Chromium menyilang-samarkan halaman lama->baru tanpa satu baris JS.
   Sidebar & topbar identik antar-halaman, jadi cukup ditinggal di lapisan root
   (nyaris tak tampak berubah); hanya <main.isi> yang diberi nama sendiri supaya
   isinya meluncur naik + memudar halus. Peramban tanpa dukungan (Firefox/Safari
   lama) mengabaikan @view-transition lalu memakai animasi-masuk biasa di blok
   @supports di bawah -- tetap halus, tak ada yang patah. prefers-reduced-motion:
   blok global di atas sudah memangkas durasi animasi biasa; pseudo-elemen
   view-transition dimatikan eksplisit di bawah. */
@view-transition{navigation:auto}
main.isi{view-transition-name:isi-utama}

/* Crossfade "chrome" (sidebar+topbar+latar) cepat -- isinya identik jadi tak terlihat. */
::view-transition-old(root),::view-transition-new(root){animation-duration:.14s}

/* Konten: yang lama memudar cepat, yang baru muncul naik sedikit. SENGAJA
   singkat (±0,16 dtk; dulu 0,3 dtk): selama transisi berjalan halaman baru
   belum bisa diklik, jadi animasi panjang terasa lambat, bukan halus. */
::view-transition-old(isi-utama){animation:isi-keluar .09s linear both}
::view-transition-new(isi-utama){animation:isi-masuk .16s cubic-bezier(.22,1,.36,1) both}
@keyframes isi-keluar{to{opacity:0}}
@keyframes isi-masuk{from{opacity:0;transform:translateY(6px)}}

/* Peramban tanpa View Transitions: konten utama tetap muncul dengan animasi masuk. */
@supports not (view-transition-name:none){
  main.isi{animation:isi-masuk .16s cubic-bezier(.22,1,.36,1) both}
}

/* Hormati pengguna gerak-minimal (pseudo VT tak kena selektor * di blok global). */
@media (prefers-reduced-motion:reduce){
  ::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}
}

/* ---------- kerangka (skeleton) — panel.js & grafik.js ----------
   Pindah halaman: muncul hanya bila halaman tujuan belum datang 120 ms setelah
   diklik (yang sudah di-prerender tampil seketika). Isi lama disembunyikan,
   judul & tombol halaman lama disamarkan, kotak berkilau menandai "memuat".
   Grafik: wadahnya berkilau sampai grafik.js selesai menggambar. */
@keyframes kilau{from{background-position:100% 0}to{background-position:0 0}}
.kerangka i,.kerangka b,body.memuat .atas-judul::after,.grafik-svg:not([data-siap]){
  background:linear-gradient(90deg,var(--garis-2) 30%,var(--latar-2) 50%,var(--garis-2) 70%) 0 0/300% 100%;
  animation:kilau 1.1s linear infinite}
body.memuat .isi > :not(.kerangka){display:none}
body.memuat .atas-judul > *,body.memuat .aksi-halaman{visibility:hidden}
body.memuat .atas-judul{position:relative}
body.memuat .atas-judul::after{content:"";position:absolute;left:0;top:50%;width:min(200px,70%);
  height:14px;margin-top:-7px;border-radius:7px}
.kerangka{display:grid;gap:var(--seksi);animation:pudar .12s ease both}
.kerangka-kpi{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--seksi)}
.kerangka-kpi i{display:block;height:76px;border-radius:var(--r-l)}
.kerangka-kartu{display:grid;gap:10px;background:var(--putih);border:1px solid var(--garis);
  border-radius:var(--r-l);padding:var(--pad-kartu)}
.kerangka-kartu b{display:block;height:14px;width:32%;border-radius:7px}
.kerangka-kartu b + b{height:10px;width:56%;margin-bottom:6px}
.kerangka-kartu i{display:block;height:30px;border-radius:8px}

/* ==========================================================================
   KASIR ASIA 0.3 — DATA SALING TERTAUT, SARINGAN STANDAR, JASA, LABEL BARCODE
   (lib/tautan.ts · lib/rentang.ts · components/Ke.tsx · components/SaringTanggal.tsx)
   ========================================================================== */
/* tautan ke data tujuan di dalam teks/tabel: halus (garis putus-putus), jelas saat disorot */
.tautan-data{color:inherit;text-decoration:none;border-bottom:1px dashed var(--garis);transition:color .12s,border-color .12s}
.tautan-data:hover{color:var(--oranye-tua);border-bottom-color:var(--oranye)}
.tabel a.pil{text-decoration:none}
.tabel a.pil:hover{filter:brightness(.96);box-shadow:inset 0 0 0 1px currentColor}
/* KPI yang bisa diklik (drill-down ke daftar terfilter) */
a.kpi-tautan,.kpi-tautan{color:inherit;text-decoration:none;cursor:pointer;transition:border-color .12s,box-shadow .12s}
a.kpi-tautan:hover{border-color:var(--oranye);box-shadow:0 6px 18px rgba(242,98,46,.12)}
a.kpi-tautan .kpi-catatan::after{content:" →";color:var(--oranye)}
/* saringan: tombol rentang cepat + pil saringan aktif */
.kartu-kepala-saring{flex-wrap:wrap}
.kartu-kepala-saring > .saring{flex:1 1 100%}
.rentang-cepat{display:flex;gap:6px;flex-wrap:wrap;flex:1 1 100%}
.chip-kecil{display:inline-flex;align-items:center;height:30px;padding:0 12px;border-radius:999px;border:1px solid var(--garis);
  background:var(--putih);color:var(--teks-2);font-size:var(--f2);font-weight:600;text-decoration:none;white-space:nowrap}
.chip-kecil:hover{border-color:var(--teks-3);color:var(--teks)}
.chip-kecil.aktif{background:var(--tinta);border-color:var(--tinta);color:var(--putih)}
.saring-tanggal > .inp[type="date"]{flex:0 1 160px}
.saring > select.inp{flex:1 1 150px;width:auto}
.saring > .pencarian{flex:2 1 200px}
.saring-aktif{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:0 var(--pad-kartu) var(--s3)}
.saring-pil{text-decoration:none}
.saring-pil b{font-weight:800;margin-left:2px}
/* pilihan berbentuk kartu (jenis produk Barang/Jasa) */
.pilih-jenis{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}
.opsi-tbl{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;padding:var(--s3) 10px;
  border:1.5px solid var(--garis);background:var(--putih);border-radius:var(--r);font:inherit;font-size:var(--f4);font-weight:700;
  cursor:pointer;color:var(--teks-2);min-height:84px;-webkit-tap-highlight-color:transparent}
.opsi-tbl small{font-size:var(--f1);font-weight:500;color:var(--teks-3);text-align:center}
.opsi-tbl:hover:not(:disabled){border-color:var(--teks-3)}
.opsi-tbl.aktif{border-color:var(--oranye);background:var(--oranye-muda);color:var(--oranye-tua)}
.opsi-tbl.aktif small{color:var(--oranye-tua)}
.opsi-tbl:disabled{opacity:.45;cursor:not-allowed}
/* info ringkas nota (Kasir · Cara bayar · …) */
.info-baris{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:var(--s3);margin:0}
.info-baris dt{font-size:var(--f1);color:var(--teks-3);text-transform:uppercase;letter-spacing:.05em;margin-bottom:2px}
.info-baris dd{margin:0;font-size:var(--f4);font-weight:600}
/* kolom centang (pilih baris untuk aksi massal) */
.tabel th.kol-pilih,.tabel td.kol-pilih{width:36px;padding-right:0}
.kol-pilih input{width:17px;height:17px;accent-color:var(--oranye)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
/* daftar ringkas yang berupa tautan (kartu "Terkait") */
a.dr-item{color:inherit;text-decoration:none}
a.dr-item:hover{background:var(--latar-2)}
a.dr-item .dr-teks{flex:1}
/* ---------- label barcode (halaman Cetak label) ---------- */
.label-kertas{display:grid;grid-template-columns:repeat(var(--lb-kol),var(--lb-w));gap:2mm;justify-content:start;
  background:var(--putih);border:1px solid var(--garis);border-radius:var(--r-l);padding:var(--s4);margin-top:var(--seksi);overflow:auto}
.label-sel{width:var(--lb-w);height:var(--lb-h);border:1px dashed var(--garis);border-radius:2mm;padding:1.5mm 2mm;
  display:flex;flex-direction:column;align-items:center;justify-content:space-between;overflow:hidden;background:#fff;color:#000}
.label-nama{font-size:8.5pt;font-weight:700;line-height:1.15;text-align:center;max-height:2.3em;overflow:hidden}
.label-harga{font-size:9pt;font-weight:800}
.label-batang{width:100%;flex:1 1 auto;min-height:8mm;fill:#000;margin:1mm 0 .5mm}
.label-kode{font-size:7.5pt;letter-spacing:.06em;font-family:ui-monospace,Consolas,monospace}
@media print{
  .cetak-sembunyi,.isi:has(.label-kertas) > div:first-child{display:none!important}
  .label-kertas{border:0;padding:0;margin:0;border-radius:0;gap:0}
  .label-sel{border:0;border-radius:0;break-inside:avoid}
  .label-kertas[data-ukuran="termal-50"] .label-sel,.label-kertas[data-ukuran="struk-58"] .label-sel{break-after:page}
}/* pengaturan: blok saklar fitur (bawaan mati) + navigasi bagian + tombol simpan menempel */
.blok-saklar{border-top:1px solid var(--garis-2);border-bottom:1px solid var(--garis-2);padding:12px 0;margin:4px 0 14px}
.blok-saklar + .blok-saklar{border-top:0;margin-top:-14px}
.kartu-isi > .blok-saklar:first-child{border-top:0;padding-top:0;margin-top:0}
.kartu-isi > .blok-saklar:last-child{border-bottom:0;padding-bottom:0;margin-bottom:0}
.langkah-ringkas{margin:0 0 var(--s3);padding-left:1.3em;display:grid;gap:6px;font-size:var(--f3);color:var(--teks-2);line-height:1.5;max-width:80ch}
.langkah-ringkas li::marker{color:var(--oranye);font-weight:700}
.nav-bagian{margin-bottom:var(--seksi)}
.simpan-pengaturan{position:sticky;bottom:0;z-index:5;padding:var(--s3) 0 var(--s4);
  background:linear-gradient(to top,var(--latar) 72%,rgba(245,246,248,0))}/* batang porsi di tabel laporan (dulu style inline) */
.batang-porsi{display:block;height:8px;border-radius:999px;background:var(--garis-2);overflow:hidden}
.batang-porsi > span{display:block;height:100%;border-radius:999px;background:var(--hijau)}
/* ==========================================================================
   PENGINGAT WA/TELEGRAM (app/admin/pengingat) + PANDUAN — Kasir Asia 0.4
   ========================================================================== */
.kartu-kepala h2 .ikon{vertical-align:-3px;margin-right:4px;color:var(--oranye)}
.wa-tautan{display:grid;grid-template-columns:auto minmax(0,1fr);gap:var(--s4);align-items:center}
.wa-tautan img{border:1px solid var(--garis);border-radius:var(--r);background:#fff;padding:6px;width:220px;height:220px}
.wa-kode{font-family:ui-monospace,Consolas,monospace;font-size:28px;font-weight:800;letter-spacing:.12em;padding:14px 18px;
  border:2px dashed var(--oranye);border-radius:var(--r);background:var(--oranye-muda);color:var(--oranye-tua);white-space:nowrap}
@media (max-width:599px){.wa-tautan{grid-template-columns:1fr;justify-items:center}}
code{font-family:ui-monospace,Consolas,monospace;font-size:.92em;background:var(--latar);border:1px solid var(--garis-2);border-radius:5px;padding:1px 5px}
/* jenis pengingat: satu baris per jenis, kolom sejajar (judul | jadwal | tujuan | aksi) */
.aturan-daftar{display:flex;flex-direction:column}
.aturan-baris{display:grid;grid-template-columns:minmax(220px,1.4fr) minmax(170px,.8fr) minmax(200px,1.4fr) auto;gap:var(--s3);align-items:center;
  padding:var(--s3) var(--pad-kartu);border-top:1px solid var(--garis-2)}
.aturan-baris.nyala{background:linear-gradient(90deg,var(--oranye-muda),transparent 40%)}
.aturan-judul{margin:0}
.aturan-jadwal{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.aturan-jadwal .inp{width:auto;flex:0 1 120px;height:36px}
.aturan-tujuan{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.aturan-aksi{display:flex;gap:6px;justify-content:flex-end;flex-wrap:wrap}
.chip-pilih{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 10px;border-radius:999px;border:1px solid var(--garis);
  background:var(--putih);font-size:var(--f2);font-weight:600;color:var(--teks-2);cursor:pointer;user-select:none}
.chip-pilih input{position:absolute;opacity:0;pointer-events:none;width:0;height:0}
.chip-pilih em{font-style:normal;font-size:10px;font-weight:800;color:var(--teks-3)}
.chip-pilih.aktif{border-color:var(--oranye);background:var(--oranye-muda);color:var(--oranye-tua)}
.chip-pilih:focus-within{box-shadow:0 0 0 3px rgba(242,98,46,.25)}
@media (max-width:1099px){.aturan-baris{grid-template-columns:1fr 1fr}.aturan-aksi{justify-content:flex-start}}
@media (max-width:599px){.aturan-baris{grid-template-columns:1fr}}
.pratinjau-pesan{white-space:pre-wrap;word-break:break-word;font-family:ui-monospace,Consolas,monospace;font-size:var(--f3);line-height:1.55;
  background:#E8F5E9;border:1px solid #C8E6C9;border-radius:var(--r);padding:12px 14px;margin:0 0 10px;color:#1B3A1E}
/* panduan */
.panduan-teks h3{font-size:var(--f4);margin:var(--s4) 0 var(--s2)}
.panduan-teks h3:first-child{margin-top:0}
.panduan-teks p{font-size:var(--f3);line-height:1.6;color:var(--teks-2);max-width:80ch}
.panduan-teks .langkah-ringkas ul{margin:4px 0 0;padding-left:1.2em;display:grid;gap:3px}
.panduan-isi > .kartu{scroll-margin-top:calc(var(--atas-tinggi, 56px) + 12px)}
.panduan-tabel td{vertical-align:top;font-size:var(--f2)}
.faq details{border-bottom:1px solid var(--garis-2);padding:10px 0}
.faq details:last-child{border-bottom:0}
.faq summary{cursor:pointer;font-weight:700;font-size:var(--f3)}
.faq details p{margin:8px 0 0}.wa-batal{grid-column:1 / -1;justify-self:start}
