/* Backoffice Warlok. Tampilan diangkat dari mockup docs/mockup/backoffice.html (desktop 1440, terang dan redup),
 * ditambah layar masuk, alat uji, dan tata letak sempit untuk tablet. */
:root { color-scheme: light; }
.app {
  --latar: #F4F2EC; --permukaan: #FFFFFF; --panel: #ECE8DF; --garis: #D6D0C4; --garis-isian: #7D8590; --teks: #18202A; --teks2: #4E5764;
  --nila: #2A3B8F; --on-nila: #FFFFFF; --nila-teks: #2A3B8F; --nila-muda: #E4E8F7; --hadir: #0B6E69; --hadir-wadah: #DDF1EE;
  --ok: #1A6B43; --ok-bg: #E3F2E9; --tunggu: #8A5A00; --tunggu-bg: #FDF0D2; --off: #3F4A56; --off-bg: #E4E7EB; --galat: #B3261E; --galat-bg: #FCE4E2; --bahaya: #B3261E; --on-bahaya: #FFFFFF;
  --tirai: rgba(24, 32, 42, .45); --bayang: rgba(24, 32, 42, .14); --snack-bg: #18202A; --snack-fg: #FFFFFF; --uji: #6B3FA0; --uji-bg: #EFE6FA;
}
.app[data-mode="redup"] {
  --latar: #11151B; --permukaan: #1A2028; --panel: #212833; --garis: #333C48; --garis-isian: #6B7684; --teks: #ECEFF3; --teks2: #A7B0BC;
  --nila: #4C5FCB; --nila-teks: #9AA8F0; --nila-muda: #252E52; --hadir: #5CCFD0; --hadir-wadah: #0F2E2F;
  --ok: #7BD4A0; --ok-bg: #15301F; --tunggu: #F0C05A; --tunggu-bg: #33270B; --off: #AEB8C4; --off-bg: #262D36; --galat: #FF8F85; --galat-bg: #3A1714; --bahaya: #C23A30;
  --tirai: rgba(0, 0, 0, .55); --bayang: rgba(0, 0, 0, .4); --snack-bg: #ECEFF3; --snack-fg: #11151B; --uji: #CDA8F5; --uji-bg: #2C1F3D;
  color-scheme: dark;
}
html, body { margin: 0; height: 100%; }
body { background: #F4F2EC; }
body.redup { background: #11151B; }
.app { font-family: Inter, "Segoe UI", system-ui, -apple-system, sans-serif; color: var(--teks); background: var(--latar); font-variant-numeric: tabular-nums; line-height: 1.4; -webkit-font-smoothing: antialiased; font-size: 15px; text-align: left; height: 100vh; height: 100dvh; }
:where(.app) *, :where(.app) *::before, :where(.app) *::after { box-sizing: border-box; }
:where(.app) :where(h1, h2, h3, p, ul, ol) { margin: 0; }
:where(.app) :where(h1, h2, h3) { font-size: inherit; }
:where(.app) :where(ul, ol) { padding: 0; list-style: none; }
:where(.app) :where(button, input, select, textarea) { font: inherit; color: inherit; }
:where(.app) button { cursor: pointer; }
:where(.app) a { color: inherit; text-decoration: none; }
:where(.app) svg { flex: none; }
.app :focus-visible { outline: 3px solid var(--nila-teks); outline-offset: 2px; }
/* Contoh isian memakai --teks2, sama dengan kasir.css:39; warna bawaan peramban (#757575) hanya 3,56:1 di mode redup */
.app ::placeholder { color: var(--teks2); opacity: 1; }
[v-cloak] { display: none; }

/* ---------- Kerangka ---------- */
.bo { width: 100%; height: 100%; display: grid; grid-template-columns: 248px minmax(0, 1fr); grid-template-rows: 64px minmax(0, 1fr); position: relative; overflow: hidden; }
.bilah { grid-column: 1 / -1; display: flex; align-items: center; gap: 14px; padding: 0 20px; background: var(--permukaan); border-bottom: 1px solid var(--garis); min-width: 0; }
.merek { width: 208px; flex: none; display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 17px; }
.logo { width: 32px; height: 32px; border-radius: 9px; background: var(--nila); color: var(--on-nila); display: flex; align-items: center; justify-content: center; font-weight: 800; }
.stempel { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 18px; font-size: 14px; font-weight: 600; min-width: 0; }
.stempel span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bilah-kanan { margin-left: auto; display: flex; align-items: center; gap: 10px; flex: none; }
.tombol-ikon { width: 40px; height: 40px; flex: none; border: 1px solid var(--garis-isian); border-radius: 9px; background: var(--permukaan); color: var(--teks); display: inline-flex; align-items: center; justify-content: center; }
/* Garis tombol ikon sama dengan .tombol dan .isian di sebelahnya. Di bilah atas tetap --garis seperti tombol bilah kasir: ikonnya sendiri sudah penanda, dan bilah tetap tenang */
.bilah .tombol-ikon { border-color: var(--garis); }
.hanya-sempit { display: none; }
.tirai-sisi { display: none; }
.sisi { background: var(--panel); border-right: 1px solid var(--garis); overflow-y: auto; padding: 14px 12px 24px; }
.sisi h3 { margin: 14px 10px 6px; font-size: 12px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--teks2); }
.sisi h3:first-child { margin-top: 2px; }
.menu { width: 100%; min-height: 40px; display: flex; align-items: center; gap: 10px; padding: 0 10px; border: 0; border-radius: 8px; background: transparent; color: var(--teks); text-align: left; font-size: 15px; font-weight: 500; }
.menu:hover { background: color-mix(in srgb, var(--permukaan) 60%, transparent); }
/* Mode redup: --permukaan lebih gelap dari --panel, jadi hover menu dicampur --teks supaya menerang, bukan menggelap */
.app[data-mode="redup"] .menu:hover:not([aria-current]) { background: color-mix(in srgb, var(--panel) 92%, var(--teks)); }
.menu[aria-current="page"] { background: var(--permukaan); color: var(--nila-teks); font-weight: 700; box-shadow: inset 3px 0 0 var(--nila-teks); }
.menu .lencana { margin-left: auto; min-width: 22px; height: 22px; padding: 0 6px; border-radius: 11px; background: var(--galat-bg); color: var(--galat); font-size: 12px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.menu .fase { margin-left: auto; font-size: 11px; font-weight: 700; color: var(--teks2); }
/* main.utama, bukan .utama: kelas yang sama dipakai tombol utama, jadi padding area tidak boleh ikut ke tombol */
main.utama { overflow-y: auto; padding: 24px 32px 48px; min-width: 0; scrollbar-gutter: stable; }
.kepala { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 18px; flex-wrap: wrap; }
.kepala h1 { font-size: 26px; font-weight: 800; line-height: 1.2; }
.kepala-kanan { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.kartu { background: var(--permukaan); border: 1px solid var(--garis); border-radius: 14px; padding: 16px 18px; min-width: 0; }
/* Kartu yang dipilih (calon pemilik cadangan): cincin nila di dalam, jadi isinya tidak bergeser seperti dengan garis 2 px */
.kartu[aria-checked="true"] { border-color: var(--nila-teks); box-shadow: inset 0 0 0 1px var(--nila-teks); }
.grid4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.grid3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.angka { font-size: 28px; font-weight: 800; line-height: 1.15; }
.peringatan { display: flex; align-items: center; gap: 14px; padding: 12px 14px 12px 16px; border-radius: 12px; font-size: 15px; }
.peringatan > span { flex: 1; min-width: 0; }
/* Teks pengganti tombol (Perlu ditinjau pemilik) setinggi tombol, supaya tumpukan peringatan sama tinggi */
.peringatan > span.nowrap { flex: none; margin-left: auto; min-height: 40px; display: inline-flex; align-items: center; }
.peringatan .tombol { margin-left: auto; flex: none; }
.peringatan.galat { background: var(--galat-bg); } .peringatan.galat > svg { color: var(--galat); }
.peringatan.tunggu { background: var(--tunggu-bg); } .peringatan.tunggu > svg { color: var(--tunggu); }
/* Label Pratinjau di bawah kepala halaman: jaraknya sama dengan jarak kepala ke isi */
.label-pratinjau { margin-bottom: 18px; }
.label-pratinjau > .chip { flex: none; box-shadow: inset 0 0 0 1px currentColor; }
.peringatan.ok { background: var(--ok-bg); } .peringatan.ok > svg { color: var(--ok); }
.peringatan.info, .peringatan.netral, .peringatan.off { background: var(--nila-muda); }
.stempel.ok { background: var(--ok-bg); color: var(--ok); } .stempel.tunggu { background: var(--tunggu-bg); color: var(--tunggu); } .stempel.galat { background: var(--galat-bg); color: var(--galat); }
.tombol { min-height: 40px; padding: 0 14px; border: 1px solid var(--garis-isian); border-radius: 9px; background: var(--permukaan); color: var(--teks); font-size: 14px; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; gap: 8px; white-space: nowrap; }
/* Hover: latar dicampur sedikit --teks (menggelap di terang, menerang di redup); filter brightness tidak terlihat di redup */
.tombol:hover:not(.mati):not(:disabled), .tombol-ikon:hover:not(:disabled), .segmen button:not([aria-checked="true"]):hover { background: color-mix(in srgb, var(--permukaan) 92%, var(--teks)); }
.tombol.utama { background: var(--nila); border-color: var(--nila); color: var(--on-nila); }
.tombol.bahaya { background: var(--bahaya); border-color: var(--bahaya); color: var(--on-bahaya); }
.tombol.bahaya-garis { color: var(--galat); border-color: var(--galat); }
.tombol.teks { border: 0; background: transparent; color: var(--nila-teks); padding: 0 6px; min-height: 32px; }
.tombol.kecil { min-height: 32px; padding: 0 10px; font-size: 13px; }
/* Hover khusus sesudah hover umum dan lebih spesifik, supaya tombol utama, bahaya, dan teks tidak tertimpa latar hover umum */
.tombol.utama:hover:not(.mati):not(:disabled) { background: color-mix(in srgb, var(--nila) 85%, var(--latar)); border-color: color-mix(in srgb, var(--nila) 85%, var(--latar)); }
.tombol.bahaya:hover:not(.mati):not(:disabled) { background: color-mix(in srgb, var(--bahaya) 85%, var(--latar)); border-color: color-mix(in srgb, var(--bahaya) 85%, var(--latar)); }
.tombol.teks:hover:not(.mati):not(:disabled) { background: transparent; text-decoration: underline; text-underline-offset: 3px; }
/* Tombol pilihan yang terpilih (aria-pressed): tinta gelap seperti segmen terpilih dan .dipilih di kasir. Nila tetap milik tombol utama, supaya Simpan menonjol */
.tombol[aria-pressed="true"], .tombol[aria-pressed="true"]:hover:not(.mati):not(:disabled) { background: var(--teks); border-color: var(--teks); color: var(--permukaan); }
/* Satu aturan tombol mati, ditulis sesudah rupa tombol teks dan terpilih supaya tombol semacam itu yang dimatikan juga tampak mati */
/* Tombol mati abu datar tanpa garis putus-putus (rekomendasi butir 13): garis putus-putus sudah dipakai chip mode coba, kotak kelompok wajib,
 * dan tempat logo. Abu tembus pandang terbaca di tema terang maupun gelap. */
.tombol.mati, .tombol:disabled, .tombol-ikon:disabled { background: rgba(128, 128, 128, .14); border-style: solid; border-color: transparent; color: var(--teks2); cursor: not-allowed; }
/* Tombol teks yang berdiri sendiri di kolom kartu atau dialog: teksnya rata dengan judul di atasnya; padding 6 px tetap jadi area ketuk */
.tombol.teks.awal { align-self: flex-start; margin-left: -6px; }
/* Tombol teks di tengah kalimat peringatan (nama item yang bisa dibuka): mengalir seperti tautan, bergaris bawah */
.tombol.teks.sebaris { display: inline; min-height: 0; padding: 0; margin: 0; font: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; vertical-align: baseline; }
/* Tombol pilih berkas (logo, foto): input aslinya tersembunyi (.sr), jadi kursor tangan dan cincin fokus dipasang di label */
label.tombol { cursor: pointer; }
label.tombol:has(> input:focus-visible) { outline: 3px solid var(--nila-teks); outline-offset: 2px; }
.chip { min-height: 24px; padding: 2px 9px; border: 0; border-radius: 12px; display: inline-flex; align-items: center; gap: 5px; font-size: 13px; font-weight: 600; white-space: nowrap; }
.chip.ok { background: var(--ok-bg); color: var(--ok); } .chip.tunggu { background: var(--tunggu-bg); color: var(--tunggu); } .chip.off { background: var(--off-bg); color: var(--off); } .chip.galat { background: var(--galat-bg); color: var(--galat); } .chip.netral { background: var(--panel); color: var(--teks); } .chip.nila { background: var(--nila-muda); color: var(--nila-teks); } .chip.hadir { background: var(--hadir-wadah); color: var(--hadir); }
.chip.uji { background: var(--uji-bg); color: var(--uji); border: 1px dashed var(--uji); cursor: pointer; letter-spacing: .04em; font-size: 12px; font-weight: 800; }
/* Chip yang boleh terlipat dua baris di kolom sempit (Belum tersambung di kolom Stok Katalog) */
.chip.chip-lipat { white-space: normal; text-align: right; justify-content: flex-end; line-height: 1.25; padding: 3px 9px; }
/* Chip yang bisa diketuk (tanggal di Reservasi): hover, dan yang terpilih bercincin selain berwarna */
button.chip.netral:hover { background: color-mix(in srgb, var(--panel) 90%, var(--teks)); }
button.chip[aria-pressed="true"] { box-shadow: inset 0 0 0 1px var(--nila-teks); }
table.tabel { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 14px; }
.tabel th { position: sticky; top: 0; background: var(--panel); text-align: left; font-weight: 700; font-size: 13px; color: var(--teks2); padding: 10px 12px; border-bottom: 1px solid var(--garis); white-space: nowrap; }
/* Sel tabel dipenggal lebih rapi (tidak menyisakan satu kata di baris terakhir). Pakai text-wrap-style, bukan singkatan text-wrap:
 * singkatan itu juga mengatur text-wrap-mode dan mengalahkan .nowrap pada td (tanggal Laporan, harga per sumber di halaman item) */
.tabel td { padding: 6px 12px; height: 46px; border-bottom: 1px solid var(--garis); vertical-align: middle; text-wrap-style: pretty; }
.tabel tr:last-child td { border-bottom: 0; }
.tabel .r, .tabel th.r { text-align: right; }
.tabel tr.pilih td { background: var(--nila-muda); }
.tabel tr.total td { font-weight: 700; background: var(--latar); }
/* Baris kategori atau kelompok di dalam tabel (matriks harga Sumber pesanan, daftar Resep); keterangan abu-abu di baris itu tidak ikut tebal */
.tabel tr.baris-kategori td { background: var(--latar); font-weight: 700; height: 40px; padding-top: 4px; padding-bottom: 4px; }
.tabel tr.baris-kategori .redam { font-weight: 500; }
.tabel tr.klik { cursor: pointer; }
.tabel tr.klik:hover td { background: color-mix(in srgb, var(--nila-muda) 55%, transparent); }
/* Cincin fokus baris di dalam baris: di luar baris ia terpotong .bungkus-tabel dan tertimpa baris tetangga */
.tabel tr.klik:focus-visible { outline-offset: -3px; }
.tabel td.kosong { height: 64px; color: var(--teks2); }
/* Status berupa chip dengan keterangan di bawahnya, misalnya "Dipesan" lalu "dicatat Sari di T1" */
.tabel td > .chip + div { margin-top: 4px; }
/* Keterangan abu-abu di bawah angka tebal (kasbon di kolom Poin, lama di kolom Jam) tidak ikut tebal */
.tabel td > div.redam { font-weight: 400; }
/* Tabel padat untuk tabel angka yang lebar (Laporan harian, Stok barang, Bahan baku): kepala kolom boleh dua baris dan sel lebih rapat, supaya muat di 1280 dan 1024 tanpa gulir samping */
.tabel.padat th { white-space: normal; vertical-align: bottom; text-wrap-style: balance; }
.tabel.padat :is(th, td) { padding-left: 8px; padding-right: 8px; }
/* Nama di sel tabel tidak terbelah per kata di layar 761 px ke atas; di ponsel tabel tetap boleh bergulir */
@media (min-width: 761px) { .tabel .utuh { white-space: nowrap; } }
/* Teks yang baru boleh utuh mulai 1024 px, karena di tablet tegak kolomnya membuat tabel bergulir (nomor struk Transaksi, acara Room) */
@media (min-width: 1024px) { .tabel .utuh-lebar { white-space: nowrap; } .tabel td.sel-acara { min-width: 200px; } }
/* Tombol ikon di baris tabel (panah urutan Sumber dan Promo) 32 px seperti .tombol.kecil, supaya baris tetap 46 px */
.tabel .tombol-ikon { width: 32px; height: 32px; }
/* Keterangan beberapa baris yang dipenggal seimbang (keterangan promo) */
.seimbang { text-wrap-style: balance; }
.bungkus-tabel { border: 1px solid var(--garis); border-radius: 12px; overflow: auto; background: var(--permukaan); }
/* Garis antar tombol dari celah 1px di atas latar garis, supaya tetap rapi bila segmen terbungkus jadi dua baris */
.segmen { display: inline-flex; gap: 1px; border: 1px solid var(--garis-isian); border-radius: 9px; overflow: hidden; flex-wrap: wrap; background: var(--garis); }
.segmen button { flex: 1 0 auto; min-height: 36px; padding: 0 14px; border: 0; background: var(--permukaan); font-size: 14px; font-weight: 600; }
.segmen button[aria-checked="true"] { background: var(--teks); color: var(--permukaan); }
/* Cincin fokus di dalam tombol segmen, karena .segmen memotong apa pun di luar tombol (overflow hidden) */
.segmen button:focus-visible { outline-offset: -4px; }
.segmen button[aria-checked="true"]:focus-visible { outline-color: var(--permukaan); }
/* Segmen empat pilihan sebagai kisi 2 x 2 (Pembulatan tunai), supaya pilihan terakhir tidak melebar sendirian */
.segmen.kisi2 { display: grid; grid-template-columns: 1fr 1fr; }
.panel-samping { position: fixed; top: 64px; right: 0; bottom: 0; width: 440px; max-width: 100%; background: var(--permukaan); border-left: 1px solid var(--garis); box-shadow: -10px 0 30px var(--bayang); display: flex; flex-direction: column; z-index: 20; }
.panel-samping header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 18px; border-bottom: 1px solid var(--garis); }
.panel-samping .isi { flex: 1; min-height: 0; overflow-y: auto; padding: 16px 18px; display: flex; flex-direction: column; gap: 14px; }
.tirai-panel { display: none; }
.tirai { position: fixed; inset: 0; background: var(--tirai); border: 0; z-index: 30; }
/* Dialog kode SMS dipasang di akar .app, di atas dialog halaman (di dalam main): tirainya ikut meredupkan dialog di bawahnya,
 * karena hanya dialog teratas yang menerima Escape dan Tab */
.app > div > .tirai { z-index: 32; } .app > div > .dialog { z-index: 33; }
.dialog { position: fixed; left: 50%; top: 96px; transform: translateX(-50%); width: 560px; max-width: calc(100% - 32px); max-height: calc(100% - 130px); overflow-y: auto; background: var(--permukaan); border-radius: 16px; box-shadow: 0 20px 50px var(--bayang); padding: 22px 24px; display: flex; flex-direction: column; gap: 16px; z-index: 31; }
.dialog h2 { font-size: 21px; font-weight: 800; }
/* Baris tombol terakhir menempel di dasar dialog yang bergulir (Tambah promo di 1280 x 800, dialog di ponsel). Margin atas -16 px sama dengan celah dialog, jadi tinggi dialog yang tidak bergulir tidak berubah */
.dialog > .row:last-child { position: sticky; bottom: -22px; margin: -10px -24px -22px; padding: 10px 24px 22px; background: var(--permukaan); }
/* Margin atas -10 px (bukan -16): tombol tetap 16 px di bawah isi, dan latar baris tidak menutupi cincin fokus kontrol terakhir.
 * scroll-padding: kontrol yang difokus dengan Tab digulir sampai di atas baris tombol, bukan di belakangnya */
.dialog { scroll-padding-bottom: 96px; }
/* Hanya dialog yang isinya bergulir (kelas dari dialog-bo di js/ui.js) diberi garis di atas baris tombol */
.dialog.bergulir > .row:last-child { box-shadow: 0 -1px 0 var(--garis); }
/* Mode redup: bayangan hitam tenggelam di tirai hitam (tepi dialog 1,21:1), jadi dialog diberi cincin 1 px --garis lewat box-shadow yang tidak menambah tinggi.
 * Chip netral dan off juga bercincin karena --panel nyaris sama dengan baris tabel (1,11:1) */
.app[data-mode="redup"] .dialog { box-shadow: 0 0 0 1px var(--garis), 0 20px 50px var(--bayang); }
.app[data-mode="redup"] .chip.netral, .app[data-mode="redup"] .chip.off { box-shadow: inset 0 0 0 1px var(--garis); }
/* Chip yang berupa tombol (tanggal di Reservasi) bergaris seperti .tombol di kedua mode, supaya tetap terbaca bisa diketuk (chip netral di atas latar hanya 1,09:1) */
.app button.chip.netral { box-shadow: inset 0 0 0 1px var(--garis-isian); }
.isian { min-height: 44px; border: 1.5px solid var(--garis-isian); border-radius: 10px; background: var(--permukaan); padding: 0 12px; display: flex; align-items: center; gap: 8px; }
.isian:focus-within { border-color: var(--nila-teks); box-shadow: 0 0 0 1.5px var(--nila-teks); }
/* Cincin fokus ada di pembungkus .isian, bukan di input di dalamnya, supaya tidak tergambar dua kali */
.app .isian :focus-visible { outline: none; }
.isian input, .isian select, .isian textarea { flex: 1; min-width: 0; border: 0; background: transparent; font-size: 15px; height: 40px; color: var(--teks); outline: none; }
.isian select option { background: var(--permukaan); color: var(--teks); }
.isian.salah { border-color: var(--galat); }
.isian.otp input { font-size: 22px; letter-spacing: .3em; font-weight: 800; }
.isian.otp input::placeholder { font-size: 16px; letter-spacing: normal; font-weight: 500; }
/* Isian di baris yang sama dengan .tombol (kepala halaman, baris aksi): 40 px seperti tombol */
.isian.sedang { min-height: 40px; } .isian.sedang input, .isian.sedang select { height: 38px; }
/* Isian di baris alat bersama segmen (cari item di Sumber pesanan): 38 px seperti segmen */
.isian.alat { min-height: 38px; padding: 0 10px; } .isian.alat input { height: 36px; font-size: 14px; }
/* Cari pelanggan: contoh isiannya (295 px) muat utuh */
.isian.cari-lebar { width: 380px; max-width: 100%; }
.label { font-size: 13px; font-weight: 600; }
/* Label kiri isian aturan harga (Harga, Diskon, Pajak) di dialog Atur sumber, sel item, dan sel kategori */
.label-aturan { min-width: 72px; }
.kode-besar { font-size: 44px; font-weight: 800; letter-spacing: .18em; font-family: "IBM Plex Mono", Consolas, monospace; }
.batang { height: 10px; border-radius: 5px; background: var(--panel); overflow: hidden; } .batang > span { display: block; height: 100%; background: var(--nila); }
.baris-form { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 18px; padding: 16px 0; border-bottom: 1px solid var(--garis); align-items: start; }
.baris-form > .segmen { justify-self: start; }
.sakelar { width: 46px; height: 28px; flex: none; border-radius: 14px; background: var(--garis-isian); position: relative; border: 0; }
.sakelar::after { content: ""; position: absolute; top: 4px; left: 4px; width: 20px; height: 20px; border-radius: 10px; background: #FFFFFF; transition: left .12s; }
.sakelar[aria-checked="true"] { background: var(--nila); } .sakelar[aria-checked="true"]::after { left: 22px; }
.sakelar:disabled { opacity: .5; cursor: not-allowed; }
.snack { position: fixed; left: var(--snack-kiri, 50%); bottom: var(--snack-bawah, 24px); transform: translateX(-50%); min-height: 48px; padding: 6px 8px 6px 18px; border-radius: 12px; background: var(--snack-bg); color: var(--snack-fg); display: flex; align-items: center; gap: 14px; font-size: 14px; box-shadow: 0 8px 24px var(--bayang); z-index: 40; max-width: min(var(--snack-lebar, 760px), calc(100% - 32px)); }
.snack button { min-height: 36px; padding: 0 10px; border: 0; background: transparent; color: inherit; font-weight: 700; text-decoration: underline; }
/* Snack tanpa tombol aksi: jarak teks ke tepi kanan sama dengan kiri */
.snack:not(:has(button)) { padding-right: 18px; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.row { display: flex; align-items: center; } .col { display: flex; flex-direction: column; } .sb { justify-content: space-between; } .je { justify-content: flex-end; } .ai-s { align-items: flex-start; } .ai-b { align-items: baseline; } .ai-e { align-items: flex-end; } .wrap { flex-wrap: wrap; } .grow { flex: 1; min-width: 0; }
.g2 { gap: 2px; } .g4 { gap: 4px; } .g6 { gap: 6px; } .g8 { gap: 8px; } .g10 { gap: 10px; } .g12 { gap: 12px; } .g14 { gap: 14px; } .g16 { gap: 16px; } .g20 { gap: 20px; } .g24 { gap: 24px; }
.t12 { font-size: 12px; } .t13 { font-size: 13px; } .t14 { font-size: 14px; } .t15 { font-size: 15px; } .t16 { font-size: 16px; } .t18 { font-size: 18px; } .t20 { font-size: 20px; } .t22 { font-size: 22px; }
.b6 { font-weight: 600; } .b7 { font-weight: 700; } .b8 { font-weight: 800; } .redam { color: var(--teks2); } .lh { line-height: 1.5; } .c-galat { color: var(--galat); } .c-ok { color: var(--ok); } .c-nila { color: var(--nila-teks); } .mt8 { margin-top: 8px; } .mt16 { margin-top: 16px; } .mt24 { margin-top: 24px; } .mb8 { margin-bottom: 8px; } .mb14 { margin-bottom: 14px; } .maks720 { max-width: 720px; } .maks480 { max-width: 480px; }
.nowrap { white-space: nowrap; } .r { text-align: right; } .mono { font-family: "IBM Plex Mono", Consolas, monospace; }
.ai-c { align-items: center; }
.isian textarea { height: auto; padding: 8px 0; resize: vertical; line-height: 1.4; }
/* Struk dan foto (1.4) */
.logo-pratinjau { min-width: 160px; min-height: 56px; padding: 8px; border: 1px dashed var(--garis); border-radius: 10px; display: flex; align-items: center; justify-content: center; background: #FFFFFF; }
.logo-pratinjau img { max-width: 240px; max-height: 80px; }
.kertas-pratinjau { width: 300px; max-width: 100%; padding: 16px 12px; background: #FFFFFF; color: #111111; border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,.18); display: flex; flex-direction: column; align-items: center; gap: 8px; }
.kertas-pratinjau pre { margin: 0; font: 11.5px/1.35 "IBM Plex Mono", Consolas, monospace; white-space: pre; }
.logo-kertas { max-width: 220px; max-height: 64px; }
.foto-kecil { width: 44px; height: 44px; border-radius: 8px; object-fit: cover; display: block; background: var(--garis); }
.foto-kosong-bo { width: 44px; height: 44px; border-radius: 8px; display: flex; align-items: center; justify-content: center; background: var(--garis); color: var(--teks2); font-weight: 700; }
.foto-dialog { width: 120px; height: 120px; border-radius: 12px; object-fit: cover; background: var(--garis); }
.garis-atas { padding-top: 10px; border-top: 1px solid var(--garis); }
.judul-kecil { font-size: 13px; font-weight: 700; color: var(--teks2); letter-spacing: .04em; text-transform: uppercase; }

/* ---------- Pilihan rentang tanggal ---------- */
.rentang { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Isian tanggal 38 px, sama dengan segmen rentang cepat di sebelahnya */
.rentang .isian { min-height: 38px; padding: 0 8px; }
.rentang .isian input { height: 36px; font-size: 14px; }
.isian.kecil { min-height: 36px; padding: 0 10px; } .isian.kecil input { height: 32px; font-size: 14px; }

/* ---------- Layar masuk ---------- */
.masuk { min-height: 100%; display: flex; align-items: center; justify-content: center; padding: 24px 16px; overflow-y: auto; }
.masuk-kartu { width: 440px; max-width: 100%; background: var(--permukaan); border: 1px solid var(--garis); border-radius: 18px; padding: 28px; display: flex; flex-direction: column; gap: 18px; box-shadow: 0 12px 40px var(--bayang); }
.akun-contoh { display: flex; flex-direction: column; gap: 8px; }
.akun-contoh button { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 48px; padding: 6px 12px; border: 1px solid var(--garis); border-radius: 10px; background: var(--latar); text-align: left; }
.akun-contoh button[aria-pressed="true"] { border: 2px solid var(--nila-teks); }

/* ---------- Alat uji ---------- */
/* z-index 29: di atas panel rincian (20) dan menu laci (25), di bawah tirai dialog (30), jadi alat uji tidak menutupi dialog */
.alat-uji { position: fixed; top: 72px; right: 16px; width: 400px; max-width: calc(100% - 32px); max-height: calc(100% - 96px); overflow-y: auto; background: var(--permukaan); border: 2px dashed var(--uji); border-radius: 14px; box-shadow: 0 16px 40px var(--bayang); padding: 18px; display: flex; flex-direction: column; gap: 14px; z-index: 29; }
.alat-uji h2 { font-size: 17px; font-weight: 800; color: var(--uji); }
.alat-uji .bagian { display: flex; flex-direction: column; gap: 8px; padding-top: 12px; border-top: 1px solid var(--garis); }

/* ---------- Penyusun laporan ---------- */
.batang-nilai { height: 8px; border-radius: 4px; background: var(--nila); min-width: 2px; }

/* Panel rincian berdampingan dengan tabel hanya di layar 1680 px ke atas (di 1600 tabel Stok, Bahan, dan Rekap shift masih terjepit).
 * Di bawahnya (termasuk 1280, 1440, dan 1536) panel menimpa tabel dengan tirai,
 * supaya tabel tidak terjepit sampai 511 px; ketuk tirai atau Escape menutup panel. Bilah atas dan menu samping tidak tertutup tirai. */
@media (min-width: 1680px) { main.utama:has(.panel-samping) { padding-right: 472px; } }
@media (max-width: 1679.98px) { .tirai-panel { display: block; position: fixed; top: 64px; left: 248px; right: 0; bottom: 0; z-index: 19; border: 0; padding: 0; background: var(--tirai); } }
/* Menu samping: bilah gulir tipis dan ruangnya selalu disediakan, supaya lebar tombol menu sama untuk semua peran */
@media (min-width: 1181px) { .sisi { scrollbar-width: thin; scrollbar-gutter: stable; } }

/* ---------- Layar sempit (tablet, ponsel) ---------- */
@media (max-width: 1180px) {
  .bo { grid-template-columns: minmax(0, 1fr); }
  /* Laci tertutup: tanpa bayangan (tidak bocor sebagai pita abu di tepi kiri) dan keluar dari urutan Tab; visibility berganti sesudah geser selesai */
  .sisi { position: fixed; top: 64px; left: 0; bottom: 0; width: 280px; z-index: 25; box-shadow: none; transform: translateX(-105%); transition: transform .15s, visibility .15s, box-shadow .15s; }
  .bo:not(.sisi-buka) .sisi { visibility: hidden; }
  .bo.sisi-buka .sisi { transform: none; box-shadow: 10px 0 30px var(--bayang); }
  .tirai-panel { left: 0; }
  /* Tirai di belakang menu laci: isi di belakangnya tidak bisa diketuk, ketuk tirai menutup menu */
  .tirai-sisi { display: block; position: fixed; top: 64px; left: 0; right: 0; bottom: 0; z-index: 24; border: 0; padding: 0; background: var(--tirai); }
  .hanya-sempit { display: inline-flex; }
  .merek { width: auto; }
  .grid4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  main.utama { padding: 20px 20px 48px; }
  .sembunyi-sempit { display: none !important; }
}
@media (max-width: 760px) {
  .bilah { padding: 0 12px; gap: 8px; }
  /* Bilah atas ponsel: nama pengguna boleh terpotong supaya tombol mode dan Keluar tetap di dalam layar */
  .bilah-kanan { gap: 6px; }
  /* Tombol mode dan Keluar tetap berjarak 8 px; yang menyusut hanya nama pengguna */
  .bilah-kanan .tombol-ikon + .tombol-ikon { margin-left: 2px; }
  .chip-pengguna { min-width: 0; max-width: 96px; overflow: hidden; text-overflow: ellipsis; display: block; line-height: 20px; }
  .stempel { padding: 6px 10px; font-size: 13px; }
  .merek span.nama-merek { display: none; }
  .grid4, .grid3, .grid2 { grid-template-columns: minmax(0, 1fr); }
  main.utama { padding: 16px 16px 48px; }
  .baris-form { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .kepala h1 { font-size: 22px; }
  .sembunyi-ponsel { display: none !important; }
  .peringatan { flex-wrap: wrap; }
  /* Teks peringatan mengambil lebar sendiri bila sempit; tombolnya turun ke baris berikutnya */
  .peringatan > span { flex: 1 1 200px; }
  /* Target ketuk 40 px di ponsel; di tablet dan desktop ukuran tetap */
  .tombol.kecil, .tombol.teks, .matriks-harga .sel-harga.sel-kategori, .segmen button { min-height: 40px; }
  .rentang .isian { min-height: 40px; } .rentang .isian input { height: 38px; }
  .isian.sedang, .isian.alat, .isian.kecil { min-height: 42px; } .isian.sedang input, .isian.alat input, .isian.kecil input { height: 40px; }
  .tabel .tombol-ikon { width: 40px; height: 40px; }
  /* Contoh isian cari pelanggan muat utuh di 390 px */
  .isian.cari-lebar input { font-size: 14px; }
  /* Baris tombol dialog bisa terbungkus dua atau tiga baris di ponsel (sampai 126 px) */
  .dialog { scroll-padding-bottom: 144px; }
  .sakelar::before { content: ""; position: absolute; inset: -6px -2px; }
  details > summary { padding: 10px 0; }
  /* Nomor tersamar di tabel tidak terbelah */
  .tabel td.mono { white-space: nowrap; }
  /* Isian aturan harga: label di baris sendiri, label kosong tidak memakan 72 px */
  .dialog .row.wrap > .label-aturan { flex-basis: 100%; }
  .dialog .row.wrap > .label-aturan:has(> .sr:only-child) { display: none; }
}
/* Ponsel tegak: teks stempel tidak muat lagi, tinggal ikon berwarna. Teksnya tetap dibacakan pembaca layar dan ada di tooltip serta dasbor. */
@media (max-width: 520px) {
  .stempel { width: 36px; height: 36px; padding: 0; justify-content: center; flex: none; }
  .stempel span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .bilah-kanan { flex: 0 1 auto; min-width: 0; }
  /* Baris resep di dialog: pilihan bahan selebar dialog, jumlah dan satuan di baris berikutnya (tanpa ini terpotong jadi "Pilih b") */
  .baris-resep { flex-wrap: wrap; } .baris-resep > .isian.grow { flex-basis: 100%; }
  /* Tombol hapus di baris kedua rata kanan dengan pilihan bahan di atasnya */
  .baris-resep > .tombol-ikon { margin-left: auto; }
}
/* 1.4: teks PO untuk WhatsApp, baris nonaktif, lembar cetak (PO dan slip gaji) yang menggantikan halaman saat dicetak */
.teks-po { white-space: pre-wrap; margin: 0; padding: 12px 14px; border: 1px solid var(--garis); border-radius: 10px; background: var(--latar); color: var(--teks); font: 13px/1.5 ui-monospace, SFMono-Regular, Consolas, monospace; max-height: 320px; overflow: auto; }
/* Bilah bawah lembar opname (rekomendasi butir 17): ringkasan dan Simpan tetap terlihat saat daftar panjang digulir */
/* Batas lekat sticky dihitung dari dalam padding bawah main.utama (48 px), jadi bottom dan margin bawah −48 px: bilah menempel ke tepi
 * bawah saat menggulir, dan di ujung gulir tetap di tepi bawah tanpa menutupi baris terakhir */
.bar-lembar { position: sticky; bottom: -48px; z-index: 2; display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin: 16px -32px -48px; padding: 12px 32px; background: var(--latar); border-top: 1px solid var(--garis); }
@media (max-width: 1180px) { .bar-lembar { margin: 16px -20px -48px; padding: 12px 20px; } }
@media (max-width: 760px) { .bar-lembar { margin: 16px -16px -48px; padding: 12px 16px; } }
.tabel td.sel-grup { height: 40px; background: var(--panel); }
/* Di ponsel lembar opname tidak bergulir ke samping: setiap baris menjadi kartu dua kolom, nama dengan catatannya di atas, isian dengan
 * selisihnya di bawah, supaya selisih tetap terlihat saat menghitung di gudang. Ringkasan bilah bawah di baris sendiri. */
@media (max-width: 760px) {
  .tabel-opname thead { display: none; }
  .tabel-opname tbody { display: block; }
  .tabel-opname tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px 12px; padding: 12px 14px; border-bottom: 1px solid var(--garis); }
  .tabel-opname tr:last-child { border-bottom: 0; }
  .tabel-opname td { display: block; height: auto; padding: 0; border: 0; min-width: 0; }
  .tabel-opname tr.baris-grup { display: block; padding: 10px 14px; background: var(--panel); }
  .tabel-opname tr.baris-grup td { height: auto; background: none; }
  .tabel-opname td.c-catatan::before { content: "Catatan "; font-size: 13px; color: var(--teks2); }
  .tabel-opname td.c-hitung, .tabel-opname td.c-selisih { grid-column: 1 / -1; }
  .tabel-opname td.c-selisih:empty { display: none; }
  .tabel-opname td.c-selisih > .col { flex-direction: row; justify-content: flex-end; align-items: baseline; gap: 8px; }
  .bar-lembar > .grow { flex-basis: 100%; }
  .bar-lembar > .row { margin-left: auto; }
}
/* Baris nonaktif ditandai warna teks --teks2 (7,3:1), bukan opacity yang menurunkan teks redam ke 2,95:1 dan membuat tombol di baris itu tampak mati */
.tabel tr.nonaktif td { color: var(--teks2); }
/* Item batal di rincian bill: dicoret dan abu-abu, bukan dipudarkan (opacity .6 = 4,37:1) */
.baris-batal { text-decoration: line-through; color: var(--teks2); }
.cetak-lembar { display: none; }
@media print {
  body.mencetak #app { display: none !important; }
  body.mencetak .cetak-lembar { display: block; color: #000; background: #fff; font: 11pt/1.45 system-ui, sans-serif; }
  .cetak-lembar h1 { font-size: 16pt; margin: 0 0 6pt; }
  .cetak-lembar table { width: 100%; border-collapse: collapse; margin: 10pt 0; }
  .cetak-lembar th, .cetak-lembar td { border-bottom: 1px solid #999; padding: 4pt 6pt; text-align: left; }
  .cetak-lembar tfoot td { font-weight: 700; border-bottom: 0; }
}
@media print {
  .sisi, .bilah, .snack, .chip.uji, .alat-uji { display: none !important; }
  .bo { display: block; height: auto; } main.utama { overflow: visible; padding: 0; } .app { height: auto; }
}
/* 1.5: isi sel yang bisa diketuk (kolom Pilihan di katalog, nama item di pratinjau harga): boleh beberapa baris, rata kiri */
.tombol.teks.sel-tautan { white-space: normal; text-align: left; justify-content: flex-start; padding: 4px 0; font-weight: 500; line-height: 1.4; text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--nila-teks) 45%, transparent); text-underline-offset: 3px; }
/* Kolom Pilihan katalog berisi ringkasan kelompok dan harganya; tanpa lebar minimum, teksnya terpecah per kata */
.tabel td.sel-pilihan { min-width: 220px; }
/* Kolom acara di Room: cukup lebar untuk judul acara; tanggal dan jamnya tidak terbelah */
.tabel td.sel-pilihan .sel-tautan { display: flex; }
/* 1.5: matriks harga per item di Sumber pesanan. Kolom nama item menempel di kiri saat tabel digulir ke samping. */
.matriks-harga th:first-child, .matriks-harga td:first-child { position: sticky; left: 0; background: var(--permukaan); z-index: 1; min-width: 150px; }
.matriks-harga th:first-child { z-index: 2; background: var(--panel); }
.matriks-harga tr.baris-kategori td:first-child { background: var(--latar); }
.sel-harga { width: 100%; min-height: 40px; padding: 4px 8px; border: 1px solid transparent; border-radius: 8px; background: transparent; color: var(--teks); display: flex; flex-direction: column; align-items: flex-end; gap: 1px; font-size: 14px; }
.sel-harga:hover { border-color: var(--garis-isian); background: var(--permukaan); }
/* Cincin fokus sel harga di dalam tombol: di kolom terakhir cincin di luar terpotong tepi tabel */
.matriks-harga .sel-harga:focus-visible { outline-offset: -3px; }
/* Angka sel harga sejajar dengan kepala kolomnya: padding sel 3 + garis 1 + padding tombol 8 = 12, sama dengan kepala */
.matriks-harga td:has(> .sel-harga) { padding-right: 3px; }
.sel-harga.sel-kategori { min-height: 32px; font-size: 12px; font-weight: 500; color: var(--teks2); }
/* Pilihan radio berukuran besar di dialog sel: ikut aturan atau harga khusus */
.pilihan-sel { display: flex; align-items: center; gap: 12px; width: 100%; padding: 10px 12px; border: 1px solid var(--garis); border-radius: 10px; background: var(--permukaan); color: var(--teks); text-align: left; }
.pilihan-sel[aria-checked="true"] { border-color: var(--nila-teks); box-shadow: inset 0 0 0 1px var(--nila-teks); }
.pilihan-sel .bulatan { width: 18px; height: 18px; flex: none; border-radius: 9px; border: 2px solid var(--garis-isian); }
.pilihan-sel[aria-checked="true"] .bulatan { border-color: var(--nila); background: radial-gradient(circle, var(--nila) 45%, transparent 50%); }
.isi-khusus { padding: 4px 0 4px 30px; }
/* 1.6: editor item (js/hal-item.js) sebagai panel kanan selebar 760 px di atas daftar Katalog atau Resep, di bawah bilah atas. Tirainya
 * tidak menutupi bilah atas dan menu samping, sama dengan panel rincian (butir 66); di 820 px ke bawah panel memenuhi layar di bawah bilah.
 * Kepala, isi, dan bar Simpan bertumpuk dan hanya isi yang bergulir, jadi bar selalu di dasar panel dan isian terakhir berakhir di atasnya.
 * Kepala dan bar menyisakan ruang bilah gulir yang sama dengan isi (scrollbar-gutter pada overflow hidden), supaya tombol Tutup, kartu, dan
 * Simpan rata kanan. Panel tanpa transform: dialog di dalamnya (position fixed) tetap diukur dari layar, bukan dari panel. */
.tirai-panel-item { position: fixed; top: 64px; left: 248px; right: 0; bottom: 0; z-index: 21; border: 0; padding: 0; background: var(--tirai); }
.app { --lebar-panel: 760px; }
.panel-item { position: fixed; top: 64px; right: 0; bottom: 0; z-index: 22; width: var(--lebar-panel); max-width: 100%; display: flex; flex-direction: column; background: var(--latar); border-left: 1px solid var(--garis); box-shadow: -10px 0 30px var(--bayang); }
.kepala-panel, .bar-simpan { flex: none; background: var(--permukaan); overflow: hidden; scrollbar-gutter: stable; }
.kepala-panel { display: flex; align-items: center; gap: 16px; padding: 14px 24px; border-bottom: 1px solid var(--garis); }
.kepala-panel h2 { font-size: 21px; font-weight: 800; line-height: 1.25; }
.isi-panel { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; padding: 20px 24px 24px; }
.bar-simpan { padding: 12px 24px; border-top: 1px solid var(--garis); }
/* Daftar di belakang panel tidak ikut bergulir (roda di atas tirai), jadi posisinya sama saat panel ditutup */
main.utama:has(.panel-item) { overflow: hidden; }
/* Snack muncul di atas bar Simpan, tidak menutupi tombolnya, dan selama panel terbuka di tengah panel, tidak memotong tepi kirinya.
 * Letak snack lewat variabel yang diwarisi dari .app: Chrome tidak selalu memperbarui ".app:has(.bar-simpan) .snack" saat bar hilang. */
.app:has(.bar-simpan) { --snack-bawah: 88px; }
.app:has(.panel-item) { --snack-kiri: calc(100% - var(--lebar-panel) / 2); --snack-lebar: calc(var(--lebar-panel) - 32px); }
@media (max-width: 1180px) { .tirai-panel-item { left: 0; } }
@media (max-width: 820px) {
  .panel-item { left: 0; width: auto; border-left: 0; box-shadow: none; }
  .kepala-panel, .isi-panel, .bar-simpan { padding-left: 16px; padding-right: 16px; }
  .app:has(.panel-item) { --snack-kiri: 50%; }
}
/* Satu pilihan di bagian Pilihan & tambahan: sakelar dan nama dengan harga untuk item ini, lalu resepnya menjorok sejajar nama
 * (sakelar 46 + celah 8) dengan tombol Ubah bahan di bawah isian harga. Di ponsel resep dan tombolnya turun ke baris sendiri. */
.pilihan-item { display: grid; grid-template-columns: minmax(0, 1fr) 140px; gap: 8px 12px; align-items: center; }
.pilihan-item > .resep-pilihan { padding-left: 54px; }
.pilihan-item > .tombol { justify-self: end; }
.pilihan-item > .salah-pilihan { grid-column: 1 / -1; justify-self: end; }
/* Harga pilihan yang disembunyikan tidak bisa diisi: bergaris putus seperti tombol mati */
.pilihan-item > .isian:has(> input:disabled) { border-style: dashed; background: transparent; }
@media (max-width: 520px) {
  .pilihan-item > .resep-pilihan { grid-column: 1 / -1; }
  .pilihan-item > .tombol { grid-column: 1 / -1; justify-self: start; margin-left: 54px; }
}
/* Tabel harga per sumber di halaman item: kolom harga dan tombol Ubah selebar isinya, nama dan asalnya mendapat sisanya.
 * Di ponsel sel lebih rapat (8 px), supaya nama sumber tidak terbelah dan asalnya tidak menyisakan satu kata. */
.tabel-sumber td + td { width: 1%; }
@media (max-width: 520px) {
  .tabel-sumber td { padding-left: 8px; padding-right: 8px; }
}
/* Daftar Resep (js/hal-bahan.js): mulai 1024 px tabel item, Nonaktif, dan resep bawaan memakai lebar kolom yang sama, jadi nama, resep,
 * harga pokok, dan tombol Ubah sejajar di ketiganya; kolom resep mendapat sisanya. Pokok muat tanda "belum lengkap". Kolom tombol resep
 * bawaan selebar Margin dan tombol tabel item, tombolnya rata kanan. Di ponsel tabel bergulir ke samping: nama dan resep diberi lebar
 * minimum supaya tidak terpecah per kata, sama dengan kolom Pilihan di Katalog. */
@media (min-width: 1024px) {
  .tabel-resep .k-nama { width: 176px; }
  .tabel-resep .k-angka { width: 76px; }
  .tabel-resep .k-pokok { width: 106px; }
  .tabel-resep .k-tombol { width: 77px; }
  .tabel-resep .k-tombol.k-lebar { width: 153px; }
}
/* Di ponsel daftar Resep, resep bawaan, dan Katalog tidak bergulir ke samping: setiap baris menjadi kartu. Baris pertama nama dengan
 * tombol Ubah, lalu resep atau isian, lalu angka berlabel (data-label) sejajar tiga kolom. Kelas c-* ada di sel js/hal-bahan.js dan
 * js/hal-kasir.js. */
@media (max-width: 760px) {
  .tabel-resep thead, .tabel-katalog thead { display: none; }
  .tabel-resep tbody, .tabel-katalog tbody { display: block; }
  .tabel-resep tr, .tabel-katalog tr { display: grid; gap: 6px 12px; padding: 12px 14px; border-bottom: 1px solid var(--garis); }
  .tabel-resep tr:last-child, .tabel-katalog tr:last-child { border-bottom: 0; }
  .tabel-resep td, .tabel-katalog td { display: block; height: auto; padding: 0; border: 0; min-width: 0; text-align: left; }
  .tabel-resep tr.baris-kategori { display: block; padding: 10px 14px; background: var(--latar); }
  .tabel-resep tr.baris-kategori td { background: none; height: auto; padding: 0; }
  .tabel-resep tr > td.kosong, .tabel-katalog tr > td.kosong { grid-column: 1 / -1; height: auto; padding: 8px 0; }
  .c-angka::before { content: attr(data-label); display: block; font-size: 13px; font-weight: 600; color: var(--teks2); }
  .tabel-resep td.c-angka, .tabel-katalog td.c-angka { text-align: left; }
  .tabel-resep tr { grid-template-columns: repeat(3, minmax(0, 1fr)) auto; }
  .tabel-resep td.c-nama { grid-column: 1 / 4; grid-row: 1; }
  .tabel-resep td.c-ubah { grid-column: 4; grid-row: 1; align-self: start; }
  .tabel-resep td.c-resep { grid-column: 1 / -1; }
  .tabel-katalog tr { grid-template-columns: 56px repeat(2, minmax(0, 1fr)) auto; align-items: start; }
  .tabel-katalog td.c-foto { grid-column: 1; grid-row: 1 / 3; }
  .tabel-katalog td.c-nama { grid-column: 2 / 4; grid-row: 1; }
  /* Tombol Ubah setinggi dua baris (nama dan kategori), jadi kategori tepat di bawah nama, tidak di bawah tombolnya */
  .tabel-katalog td.c-ubah { grid-column: 4; grid-row: 1 / 3; }
  .tabel-katalog td.c-kat { grid-column: 2 / 4; grid-row: 2; white-space: normal; color: var(--teks2); }
  .tabel-katalog td.c-isian { grid-column: 1 / -1; min-width: 0; }
  /* Isian satu baris (hanya keterangan item) menempel di atas tombolnya yang setinggi 40 px, sejarak isian dua baris dari kategori */
  .tabel-katalog td.c-isian .sel-tautan { align-items: flex-start; }
  .tabel-katalog td.c-harga { grid-column: 1 / 3; grid-row: 4; }
  .tabel-katalog td.c-stok { grid-column: 3; grid-row: 4; }
  .tabel-katalog td.c-stok .chip-lipat { text-align: left; justify-content: flex-start; }
  .tabel-katalog td.c-ada { grid-column: 4; grid-row: 4; align-self: end; justify-self: end; }
}
/* Ringkasan harga di panel Resep: harga jual, harga pokok, dan margin sejajar, juga di ponsel */
.ringkas-harga { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
/* Kotak jumlah isi paket dan harga dasar pilihan selebar isinya, supaya pilihan item dan nama pilihan tidak terpotong di ponsel */
.jumlah-isi { width: 64px; }
.isian.harga-dasar { width: 140px; }
@media (max-width: 520px) {
  .isian.harga-dasar { width: 112px; }
  /* Baris resep yang terlipat dua (bahan, lalu jumlah dan satuan) terpisah lebih jauh dari baris berikutnya */
  .daftar-baris-resep { gap: 16px; }
}
/* Daftar Katalog (js/hal-kasir.js): mulai 1024 px tabel item aktif dan Nonaktif memakai lebar kolom yang sama, jadi nama, harga, sakelar Tersedia,
 * dan tombol Ubah sejajar di keduanya; kolom Isian mendapat sisanya. */
@media (min-width: 1024px) {
  .tabel-katalog .k-foto { width: 68px; }
  .tabel-katalog .k-item { width: 144px; }
  .tabel-katalog .k-kat { width: 100px; }
  .tabel-katalog .k-harga { width: 112px; }
  .tabel-katalog .k-stok { width: 96px; }
  .tabel-katalog .k-ada { width: 112px; }
  .tabel-katalog .k-ubah { width: 77px; }
}

/* Tablet pemilik (layar sentuh lebar 761 sampai 1180 px): target sentuh tombol baris, sakelar, dan chip seperti di ponsel (observasi 26 Okt) */
@media (pointer: coarse) {
  .tombol.kecil { min-height: 40px; }
  .tabel .tombol-ikon { width: 40px; height: 40px; }
  .chip[aria-pressed] { min-height: 36px; }
  .sakelar::before { content: ""; position: absolute; inset: -6px -2px; }
}
