/* ============================================================
   ERP Aroma Loka – "Aroma Loka Workspace" (model user 2026-10-18)
   Palet arah owner (12 Nov 2026): oat #EEE5D4 · forest #1D4A35 ·
   tomato #F2462E. Coklat-kopi hangat untuk bingkai (sidebar, bilah
   atas, kartu), forest untuk aksi utama, tomato HANYA untuk label
   peringatan dan seri data yang menandakan hal yang perlu dilihat.
   Font Inter self-host (public/fonts, tanpa CDN luar).
   Tema terang & gelap via [data-theme]; default ikuti perangkat.
   ============================================================ */
/* Font self-host: data staff tidak menyentuh layanan luar dan halaman tetap
   cepat terbuka di jaringan gerai. Cukup subset latin, 4 weight dipakai. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/inter-latin-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/inter-latin-500.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/inter-latin-600.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/inter-latin-700.woff2') format('woff2');
}

:root {
  /* Satu keluarga font untuk seluruh backoffice. Spek Stitch menyebut dua
     keluarga berbeda di dua dokumen (Poppins vs Inter) → diputuskan Inter
     saja supaya angka dan teks konsisten satu rupa. */
  --font-sans: 'Inter', -apple-system, 'Segoe UI', sans-serif;
  /* Inti palet terang (arah owner 12 Nov 2026): karena angka penjualan harus
     dibaca berjam-jam, kanvas dibuat oat hangat dan teks dibuat coklat kopi
     pekat, bukan hijau. Forest dipakai khusus untuk aksi utama dan judul
     supaya satu aksen saja yang "menyala". Tomato hanya untuk peringatan:
     di atas oat kontrasnya 2.95:1, jadi dilarang dipakai untuk teks biasa. */
  --pri: #1D4A35;
  --pri2: #2C6B4C;
  --on-pri: #FFFFFF;
  --p-container: #DCE8DA;
  --on-p-container: #173D2C;
  --surface: #F7F2E7;
  --surface2: #F7F2E7;
  --surface3: #E2D7C1;
  --outline: #8A7A5E;
  --outline-var: #E4D8C1;
  --on-surface: #2A2622;
  --on-surface-var: #5E5445;
  --ter: #6B4E00;
  --ter-container: #FFF3BF;
  --ter-border: #F1DC82;
  --error: #B33620;
  --error-container: #FDE3DE;
  --ok: #0E5A38;
  /* Tomato = peringatan. Dua wajahnya disimpan sebagai token supaya tidak
     dikarang ulang di renderer: --mark untuk garis/isi, --mark-ink untuk teks
     di atas latar terang (5.4:1), --mark-container/--on-mark-container untuk
     lencana berisi. */
  --mark: #F2462E;
  --mark-ink: #B33620;
  --mark-container: #FDE3DE;
  --on-mark-container: #8A2416;
  /* Bingkai aplikasi (sidebar + bilah atas) dan teks di atasnya. */
  --frame: #3A2E24;
  --frame-line: #4C3D30;
  --frame-inactive: #5B4838;
  --frame-hover: rgba(238, 229, 212, 0.08);
  --frame-active: #EEE5D4;
  --on-frame-active: #173D2C;
  --frame-ink: #F3EADB;
  --frame-ink-2: #C7B49B;
  --brand-mark-bg: #EEE5D4;
  /* Token semantik tema */
  --bg-card: var(--panel);
  --bg-input-focus: #FFFFFF;
  --bg-bottombar: rgba(247, 242, 231, 0.94);
  --chip-ok-bg: #DCE8DA;
  --chip-ok-ink: var(--ok);
  --bg-grad: linear-gradient(180deg, #EEE5D4 0%, #F7F2E7 45%, #F7F2E7 100%);
  --r-card: 16px;
  --r-row: 14px;
  --shadow-1: 0 6px 20px rgba(42, 38, 34, 0.08);
  --shadow-2: 0 4px 14px rgba(42, 38, 34, 0.06);

  /* Kanvas oat + kartu lebih terang: kedalaman dibaca dari nada, bukan dari
     bayangan yang membuat semua kartu terbang. */
  --canvas: #EEE5D4;
  --panel: #FFFFFF;
  --panel-2: #F7F2E7;
  --hairline: #E6DBC5;
  --r-panel: 24px;
  --shadow-panel: 0 1px 2px rgba(42, 38, 34, 0.04), 0 8px 24px rgba(42, 38, 34, 0.05);
  --nav-bar: var(--pri);
  --kpi-dark-bg: #1D4A35;
  --kpi-dark-ink: #FFF8EC;
  --kpi-dark-sub: rgba(255, 248, 236, 0.76);
  /* Palet seri chart – dibaca dashboard.js lewat cssVar(), bukan hex di JS.
     Urutannya mengikuti peran, bukan selera: forest = outlet utama yang
     pertama dibaca, tomato = pembanding kedua, sisanya turunan netral supaya
     satu layar tidak memakai lima warna yang bersaing. */
  --chart-1: #1D4A35;
  --chart-2: #F2462E;
  --chart-3: #2C6B4C;
  --chart-4: #C9A227;
  --chart-5: #7E9C8A;
  --chart-6: #A89880;
  --chart-grey: #B5A88F;
  /* Alias kompatibilitas untuk renderer divisi lama yang masih memakai token M3. */
  --md-primary: var(--pri);
  --md-on-primary: var(--on-pri);
  --md-p-container: var(--p-container);
  --md-on-p-container: var(--on-p-container);
  --md-surface: var(--surface);
  --md-surface2: var(--surface2);
  --md-surface3: var(--surface3);
  --md-outline: var(--outline);
  --md-outline-var: var(--outline-var);
  --md-on-surface: var(--on-surface);
  --md-on-surface-var: var(--on-surface-var);
  --md-ter: var(--ter);
  --md-ter-container: var(--ter-container);
  --md-error: var(--error);
  --md-error-container: var(--error-container);
}

/* ===== Tema gelap (coklat-kopi hangat, kontras AA) ===== */
[data-theme="dark"] {
  /* --pri terang (forest terang) + --on-pri gelap: pola checkbox centang-gelap
     tetap jalan, dan tombol utama tetap terbaca di kanvas gelap. */
  --pri: #A9CFB5;
  --pri2: #7FB495;
  --on-pri: #14261C;
  --p-container: #27472F;
  --on-p-container: #CFE6D3;
  --surface: #14120E;
  /* Panel #1C1915; field/select butuh sedikit lebih terang dari panel supaya
     form tidak terlihat hilang (masalah lama sebelum surface2 dipisah). */
  --surface2: #1B2B22;
  --surface3: #2A2620;
  --outline: #8C7D66;
  --outline-var: #332E26;
  --on-surface: #EFE7D7;
  --on-surface-var: #B9AE9A;
  --ter: #E9C46A;
  --ter-container: #453A1A;
  --ter-border: #5C4C22;
  --error: #FFB4A9;
  --error-container: #5C1F1B;
  --ok: #93E6A8;
  --mark: #FF8A72;
  --mark-ink: #FF8A72;
  --mark-container: #5C1F1B;
  --on-mark-container: #FFB4A9;
  /* Bingkai gelap: lebih gelap dari panel supaya sidebar dan bilah atas
     menyatu sebagai satu bidang, dan item aktif tidak perlu warna aksen. */
  --frame: #0C0B09;
  --frame-line: #2A2520;
  --frame-inactive: #12100D;
  --frame-hover: rgba(239, 231, 215, 0.07);
  --frame-active: #EFE7D7;
  --on-frame-active: #173D2C;
  --frame-ink: #EFE7D7;
  --frame-ink-2: #A99C87;
  --brand-mark-bg: #EFE7D7;
  --bg-card: var(--panel);
  --bg-input-focus: #1C1915;
  --bg-bottombar: rgba(28, 25, 21, 0.94);
  --chip-ok-bg: #1E3B2A;
  --chip-ok-ink: var(--ok);
  --bg-grad: linear-gradient(180deg, #1B1814 0%, #14120E 45%, #12100D 100%);
  --shadow-1: 0 6px 20px rgba(0, 0, 0, 0.45);
  --shadow-2: 0 4px 14px rgba(0, 0, 0, 0.35);

  /* Kanvas lebih gelap dari panel supaya panel tetap terbaca sebagai melayang. */
  --canvas: #12100D;
  --panel: #1C1915;
  --panel-2: #232019;
  --hairline: #332E26;
  --shadow-panel: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.35);
  /* KPI pertama = permukaan lebih gelap dari panel, bukan ink terang: teks
     putih di atasnya tetap tinggi kontras di dua tema. */
  --kpi-dark-bg: #1E3A2B;
  --kpi-dark-ink: #F6F1E6;
  --kpi-dark-sub: rgba(246, 241, 230, 0.72);
  --chart-1: #A9CFB5;
  --chart-2: #FF8A72;
  --chart-3: #7FB495;
  --chart-4: #E4C36A;
  --chart-5: #A9B9AE;
  --chart-6: #C3B49A;
  --chart-grey: #6E6455;
}
/* Logo monokrom hitam → putih di tema gelap */
[data-theme="dark"] .login-mark { filter: brightness(0) invert(1); }

* { box-sizing: border-box; }
/* Atribut `hidden` harus menang atas `display` dari kelas mana pun. Tanpa ini,
   elemen seperti .tb-badge (display:grid) tetap tampil walau punya `hidden`. */
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font-sans);
  background: var(--canvas);
  color: var(--on-surface);
  font-size: 15px;
  line-height: 1.45;
}
body.lock { overflow: hidden; }
::selection { background: var(--p-container); }
:focus-visible { outline: 2px solid var(--pri2); outline-offset: 2px; border-radius: 6px; }

h1 { font-size: 24px; font-weight: 800; letter-spacing: -0.3px; margin: 6px 0 10px; }
h2 { font-size: 16px; font-weight: 700; margin: 20px 0 10px; }
/* Desktop ≥900px: kerja data padat — body turun satu tangga (15→14px) supaya
   lebih banyak baris terlihat tanpa scroll, judul kartu naik satu tangga
   (16→18px) agar hierarki tetap terbaca. HP tetap 15px: dibaca jelas tanpa
   zoom, sesuai spek Stitch (skala terpisah tabled vs mobile). */
@media (min-width: 900px) {
  body { font-size: 14px; }
  h2 { font-size: 18px; }
  /* Baris tabel bernapas lebih di desktop; HP tetap 10px karena kolomnya sudah
     sempit (absensi 7 kolom). */
  th, td { padding: 12px 14px; }
}
/* Anak pertama kartu tidak butuh jarak atas: padding kartu sudah memberi ruang,
   tanpa ini judul kartu turun 20px dari tepi atas. */
.card > :first-child,
.card > .form > :first-child { margin-top: 0; }
.muted { color: var(--on-surface-var); font-size: 14px; }
.err { color: var(--error); min-height: 1.2em; font-size: 14px; }
ul { margin: 8px 0; padding-left: 18px; }
li { font-size: 14px; color: var(--on-surface-var); margin: 3px 0; }
a { color: var(--pri); }

/* ===== Komponen umum ===== */
.card {
  background: var(--bg-card);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  box-shadow: none;
  padding: 16px;
  margin: 10px 0;
}
/* Kartu KPI pertama dashboard digelapkan lewat .sd-kpi.dark – aturannya ada di
   renderer dashboard.js bersama .sd-kpi lainnya, supaya satu komponen satu tempat. */
button:disabled { opacity: .55; cursor: not-allowed; }
/* 16px juga untuk input di luar .form: di bawah 16px Safari/iOS auto-zoom. */
input, select, textarea { color-scheme: light; font: inherit; font-size: 16px; }
[data-theme="dark"] input, [data-theme="dark"] select, [data-theme="dark"] textarea { color-scheme: dark; }
/* Tabel: struktur dipasang di elemen dasar supaya tabel tanpa class (dipakai di
   HR) dan tabel berclass tampil sama. Header memakai kalimat biasa, bukan
   uppercase ber-tracking: header yang berteriak membuat tabel padat terbaca
   seperti template. Semua angka tabular supaya kolom nominal rata. */
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid var(--outline-var);
  font-variant-numeric: tabular-nums;
}
th { font-size: 12px; font-weight: 600; color: var(--on-surface-var); }
tr:last-child > td { border-bottom: none; }
td.num, th.num { text-align: right; }
.tbl {
  background: var(--bg-card);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  overflow: hidden;
  margin: 10px 0;
}
/* Mobile: tabel lebar (absensi 7 kolom sejak koreksi absen) terpotong oleh
   .view overflow-x:clip – jadikan blok scroll-horizontal agar semua kolom
   terjangkau dengan geser. */
@media (max-width: 899px) {
  /* Target jempol: kontrol form & tombol 48px di HP supaya tidak salah tekan
     saat staff berdiri melayani customer (spek Stitch: ergonomis untuk staf
     outlet). Desktop tetap 44px supaya tabel padat tetap rapat. */
  :root { --field-h: 48px; --tap: 48px; }
  .tbl { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

.chip {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  background: var(--surface2);
  color: var(--on-surface-var);
}
/* Chip berisi kalimat (banner jadwal absensi), bukan label status: teksnya
   boleh turun baris supaya tidak terpotong di 390px. */
.chip--wrap { white-space: normal; display: block; }
.chip.ok { background: var(--chip-ok-bg); color: var(--chip-ok-ink); }
.chip.warn { background: var(--ter-container); color: var(--ter); border: 1px solid var(--ter-border); }
.chip.no { background: var(--error-container); color: var(--error); }
.chip.off { background: var(--surface3); color: var(--on-surface-var); }

/* Picker chip: daftar centang jamak (staff tugas luar, outlet staff) yang
   dibungkus label. Checkbox asli TIDAK di-display:none – cukup dibuat tak
   terlihat – supaya tetap masuk urutan Tab dan dibaca screen reader; cincin
   fokusnya digambar pada span. Aktif ditandai isi warna DAN tanda centang,
   bukan warna saja. */
.pick-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0;
  margin: 0;
  cursor: pointer;
}
.pick-chip input[type="checkbox"] {
  position: absolute;
  left: 0;
  top: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  opacity: 0;
  pointer-events: none;
}
.pick-chip span {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 8px 14px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-field, 10px);
  background: var(--panel-2);
  color: var(--on-surface);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.25;
  transition: background-color .12s, border-color .12s, color .12s, transform .12s;
}
/* Centang = dua garis border yang diputar. Ruangnya dilipat (-7px) saat tidak
   dipilih supaya chip tidak berongga di kiri. */
.pick-chip span::before {
  content: '';
  flex: none;
  width: 7px;
  height: 4px;
  margin-right: -7px;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  opacity: 0;
  transform: rotate(-45deg) scale(.96);
  transition: transform .12s, margin-right .12s, opacity .12s;
}
.pick-chip:hover span { border-color: var(--pri2); }
.pick-chip:active span { transform: scale(.98); }
.pick-chip input:checked + span {
  background: var(--p-container);
  border-color: var(--pri2);
  color: var(--on-p-container);
  font-weight: 700;
}
.pick-chip input:checked + span::before { opacity: 1; transform: rotate(-45deg) scale(1); margin-right: 8px; }
.pick-chip input:focus-visible + span {
  border-color: var(--pri2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pri2) 26%, transparent); /* taste-skill-ignore: cincin fokus keyboard, bukan bayangan dekoratif */
}

/* Status teks & pil persentase. Dipakai dashboard, laporan, dan tugas –
   sebelumnya disalin di tiap renderer dengan hex tersendiri. */
.ok { color: var(--ok); }
.wa { color: var(--ter); }
.ng { color: var(--error); }
.up { color: var(--ok); }
.dn { color: var(--error); }
.pill {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 99px;
  font-weight: 600;
  font-size: 11px;
  border: 1px solid currentColor;
}

/* ===== Kartu absen beranda staff ===== */
.absen-card { display: flex; flex-direction: column; gap: 6px; }
.absen-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.absen-lbl {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--on-surface-var);
}
.absen-main { font-size: 19px; font-weight: 800; margin: 0; }
.absen-sub { font-size: 13.5px; color: var(--on-surface-var); margin: 0; }
.absen-cam {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: var(--tap);
  margin-top: 8px;
  padding: 8px 12px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-btn);
  background: var(--panel-2);
  cursor: pointer;
  font-size: 14px;
  align-self: flex-start;
}
.absen-cam input { display: none; }
.absen-prev {
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: 10px;
  display: none;
  margin-top: 8px;
}
.absen-prev.show { display: block; }
.absen-btn {
  margin-top: 10px;
  width: 100%;
  min-height: 48px;
  border: none;
  border-radius: 14px;
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  background: var(--pri);
  color: var(--on-pri);
}
.absen-btn:disabled { background: var(--surface3); color: var(--on-surface-var); opacity: 1; cursor: default; }
.absen-btn.out {
  background: var(--ter-container);
  color: var(--ter);
  border: 1px solid var(--ter-border);
}

/* ===== Sistem field =====
   Satu sumber untuk label, kontrol, teks bantu, dan keadaan error.
   Label di atas kontrol: bentuk label inline ("Tanggal [input]") kehabisan
   ruang di 390px dan memaksa label berebut satu baris dengan input; dengan
   label di atas, form dua kolom tetap terbaca di HP.
   Tinggi kontrol 44px supaya tap target terpenuhi tanpa padding tambahan. */
:root { --field-h: 44px; --r-field: 10px; }

/* Tampilan kontrol dipasang global supaya input di luar .form (sel tabel,
   baris filter) tidak lagi memakai gaya bawaan browser. Lebar tidak diatur di
   sini: input di judul atau sel harus tetap selebar isinya. Lebar penuh
   diberikan oleh .form, .field, dan .wide.
   Dibalut :where() supaya spesifisitasnya nol: gaya input ber-class milik
   divisi (mis. .au-filter di audit) tetap menang tanpa perlu diubah. */
:where(
  input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]),
  select,
  textarea
) {
  min-height: var(--field-h);
  padding: 10px 12px;
  /* 16px: di bawah ini Safari/iOS auto-zoom dan halaman "terjebak" ter-zoom. */
  font-family: inherit;
  font-size: 16px;
  color: var(--on-surface);
  background: var(--panel-2);
  border: 1px solid var(--hairline);
  border-radius: var(--r-field);
  accent-color: var(--pri2);
}
textarea { min-height: calc(var(--field-h) * 2); line-height: 1.45; resize: vertical; }
input:disabled, select:disabled, textarea:disabled { color: var(--on-surface-var); opacity: .6; cursor: not-allowed; }
input[readonly] { color: var(--on-surface-var); }
input::placeholder, textarea::placeholder { color: var(--on-surface-var); opacity: .85; }
.placeholders-grey::placeholder { color: var(--on-surface-var); opacity: .85; }
:where(
  input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]),
  select,
  textarea
):focus {
  outline: none;
  border-color: var(--pri2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pri2) 26%, transparent);
}

/* ===== Kotak centang & pilihan =====
   Kontrol bawaan browser tidak ikut tema: di mode gelap kotaknya tetap putih
   dan ukurannya 13px. Satu bentuk untuk centang dan radio: kotak 20px berisi
   --panel-2 bergaris --outline; saat dipilih terisi --pri dengan tanda
   --on-pri. Sasaran ketuk 44px disediakan oleh labelnya. */
:root { --box: 20px; }

input[type="checkbox"],
input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: var(--box);
  height: var(--box);
  margin: 0;
  padding: 0;
  border: 1.5px solid var(--outline);
  border-radius: 6px;
  background-color: var(--panel-2);
  background-repeat: no-repeat;
  background-position: center;
  cursor: pointer;
  transition: background-color .12s, border-color .12s;
}
input[type="radio"] { border-radius: 50%; }
input[type="checkbox"]:hover,
input[type="radio"]:hover { border-color: var(--pri2); }
input[type="checkbox"]:checked,
input[type="radio"]:checked { background-color: var(--pri); border-color: var(--pri); }
input[type="checkbox"]:checked {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
  background-size: 13px;
}
/* Di mode gelap --pri terang, jadi tanda centangnya harus gelap. */
[data-theme="dark"] input[type="checkbox"]:checked {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230E2A24' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
}
input[type="radio"]:checked {
  /* Radio dipilih = cincin tebal berwarna --pri dengan inti --panel, jadi
     tidak butuh gambar maupun gradien dan tetap terbaca di dua tema. */
  border-width: 6px;
  border-color: var(--pri);
  background-color: var(--panel);
}
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
  outline: none;
  border-color: var(--pri2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pri2) 26%, transparent); /* taste-skill-ignore: cincin fokus keyboard, bukan bayangan dekoratif */
}
input[type="checkbox"]:disabled,
input[type="radio"]:disabled { opacity: .55; cursor: not-allowed; }

.form { display: flex; flex-direction: column; gap: 14px; }
.form label,
.field > label,
.field > .field-label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--on-surface-var);
}
/* Label yang isinya hanya centang/pilihan tetap satu baris. */
.form label:has(> input[type="checkbox"]),
.form label:has(> input[type="radio"]),
.field > label:has(> input[type="checkbox"]),
.field > label:has(> input[type="radio"]) {
  flex-direction: row;
  align-items: center;
  gap: 10px;
  min-height: var(--tap);
  font-weight: 500;
  cursor: pointer;
}
/* Centang/radio tidak boleh ikut selebar kolom: dia kotak 20px di dalam baris
   label. */
.form input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
.form select, .form textarea,
.field input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
.field select, .field textarea {
  display: block;
  width: 100%;
  margin: 0;
}
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 360px) { .field-row { grid-template-columns: 1fr; } }
.field .help { margin: 0; font-size: 12.5px; color: var(--on-surface-var); }
.field.invalid input, .field.invalid select, .field.invalid textarea { border-color: var(--error); }
.field.invalid .help { color: var(--error); }
.wide, .card > .wide { display: block; width: 100%; }
.card > .wide { margin-top: 10px; }
.nw { white-space: nowrap; }
/* Kelompok pilihan (mis. daftar staff yang ditugaskan). Border hairline tipis
   supaya setara dengan kartu di sekitarnya, bukan kotak fieldset bawaan. */
.pick-set {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-content: flex-start;
  /* Empat baris chip 44px + jarak, lalu menggulir sendiri. */
  max-height: 200px;
  overflow: auto;
  padding: 12px;
  border: 1px solid var(--hairline);
  border-radius: 14px;
}
.profile-card { text-align: center; }
.profile-avatar { width: 72px; height: 72px; margin: 4px auto 10px; display: grid; place-items: center; border-radius: 50%; background: var(--p-container); color: var(--on-p-container); font-size: 28px; font-weight: 800; }
.profile-card h2 { font-size: 20px; margin: 4px 0 0; }
.profile-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 18px; text-align: left; }
.profile-grid > div { padding: 12px; border: 1px solid var(--outline-var); border-radius: 14px; background: var(--surface2); }
.profile-grid b { display: block; margin-top: 4px; font-size: 15px; }
.lbl-mini { color: var(--on-surface-var); font-size: 12px; font-weight: 600; }
@media (max-width: 420px) { .profile-grid { grid-template-columns: 1fr; } }

/* ===== Sistem tombol =====
   Satu sumber tinggi, radius, dan perataan untuk semua tombol. Varian memakai
   .btn--*, bukan padding/radius ad-hoc di tiap divisi. margin-top sengaja 0:
   margin bawaan dulu membuat tombol di baris flex/tabel turun tidak sejajar. */
:root { --tap: 44px; --r-btn: 12px; }

button, .btn, .btn-sec {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--tap);
  margin: 0;
  padding: 10px 16px;
  border: 1px solid transparent;
  border-radius: var(--r-btn);
  background: var(--pri);
  color: var(--on-pri);
  font: inherit;
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: filter 0.15s, background-color 0.15s, border-color 0.15s, transform 0.05s;
}
button:hover, .btn:hover { filter: brightness(1.08); }
button:active, .btn:active { transform: translateY(1px); }
/* Nonaktif: jangan cuma diturunkan opacity-nya – teks putih di atas hijau
   pucat jadi tak terbaca. Ganti ke permukaan netral dengan teks sekunder. */
button:disabled, .btn:disabled, .btn[aria-disabled="true"] {
  background: var(--surface3);
  color: var(--on-surface-var);
  border-color: transparent;
  opacity: 1;
  cursor: not-allowed;
  filter: none;
  transform: none;
}
.btn--soft, .btn-sec { background: var(--surface2); color: var(--on-surface); border-color: var(--outline-var); }
.btn--soft:hover, .btn-sec:hover { background: var(--surface3); filter: none; }
.btn--ghost { background: transparent; color: var(--pri); border-color: transparent; }
.btn--ghost:hover { background: var(--surface2); filter: none; }
.btn--danger { background: transparent; color: var(--error); border-color: var(--error); }
.btn--danger:hover { background: var(--error-container); filter: none; }
.btn--sm { min-height: var(--tap); padding: 8px 12px; font-size: 13.5px; border-radius: 10px; }
.btn--block { width: 100%; }
.btn--icon { width: var(--tap); min-width: var(--tap); padding: 0; border-radius: 50%; }
.btn-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.btn-row > button, .form .btn-row > button { width: auto; margin-top: 0; }
button.link { background: transparent; color: var(--pri); border-color: transparent; padding: 8px 4px; }
button.link:hover { background: var(--surface2); filter: none; }
/* Tombol tunggal sebagai isi langsung kartu tetap punya jarak vertikal. */
.card > button { margin-top: 10px; }
/* Jarak antar item sudah dari gap .form, jadi tombol tidak perlu margin lagi. */
.form button { width: 100%; margin-top: 0; }
.form-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 10px; }
.form-grid2 .full { grid-column: 1 / -1; }
@media (min-width: 640px) { .form-grid2 { grid-template-columns: repeat(4, 1fr); } }

details.fold {
  background: var(--bg-card);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-2);
  margin: 10px 0;
}
details.fold summary {
  cursor: pointer;
  padding: 13px 16px;
  font-weight: 700;
  font-size: 14px;
  list-style: none;
}
details.fold summary::-webkit-details-marker { display: none; }
details.fold summary::after { content: '▾'; float: right; color: var(--on-surface-var); }
details.fold[open] summary::after { content: '▴'; }
.tabs { display: flex; gap: 8px; flex-wrap: wrap; }
.tabs button {
  background: var(--surface2);
  color: var(--on-surface);
  border-color: var(--outline-var);
}
.tabs button.on { background: var(--p-container); color: var(--on-p-container); border-color: transparent; font-weight: 700; }

/* ===== Halaman masuk ===== */
.card.login-card { max-width: 420px; margin: 12vh auto 40px; padding: 30px 26px; text-align: center; border-radius: 26px; }
.login-mark { height: 52px; width: auto; margin-bottom: 8px; filter: brightness(0); opacity: 0.88; }
.card h1 { color: var(--pri); font-size: 22px; }
/* Nama brand di halaman masuk: tracking lebar supaya terbaca sebagai wordmark,
   bukan judul biasa. Ukuran tetap kecil karena logo sudah jadi fokus. */
.login-title { letter-spacing: 0.02em; }
#g_btn { min-height: 44px; display: inline-block; }

/* ===== Shell backoffice =====
   Bingkai luar memakai coklat-kopi hangat (#3A2E24): satu-satunya bidang gelap
   di layar, jadi mata langsung tahu batas aplikasi. Isi kerja tetap di panel
   oat terang supaya angka penjualan dibaca di latar terang. */
.bo { display: flex; min-height: 100vh; gap: 12px; padding: 12px; }

@media (min-width: 900px) {
  /* Isi kerja memakai lebar penuh: angka per outlet dan tabel target butuh
     tempat supaya label outlet tidak terpotong jadi "Gallery Arom…". Tidak ada
     margin auto: baris filter yang menempel tepi atas (sd-nav) tetap selebar
     panel, bukan mengapung sebagai pita di tengah. */
  .view { max-width: none; }
}

.side {
  width: 250px;
  background: var(--frame);
  border: 1px solid var(--frame);
  border-radius: var(--r-panel);
  box-shadow: var(--shadow-panel);
  display: flex;
  flex-direction: column;
  padding: 22px 12px 12px;
  flex-shrink: 0;
  position: sticky;
  top: 12px;
  height: calc(100vh - 24px);
  overflow-y: auto;
}
.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 8px 18px;
  color: var(--frame-ink);
  font-size: 16px;
  font-weight: 800;
  letter-spacing: 0.01em;
}
.brand .brand-mark {
  height: 40px;
  width: 40px;
  padding: 8px;
  box-sizing: border-box;
  border-radius: 12px;
  /* Tombol tanda di dalam bingkai gelap: oat, bukan forest, karena forest di
     atas kopi hampir tidak terpisah. Logo hitam tetap terbaca di atas oat. */
  background: var(--brand-mark-bg);
  filter: none;
  opacity: 1;
}
.nav-item .nav-ic { display: grid; place-items: center; width: 20px; flex-shrink: 0; }
.nav-item .nav-ic svg { width: 19px; height: 19px; }
.brand .brand-sub { display: block; font-weight: 400; font-size: 12px; letter-spacing: 0.02em; color: var(--frame-ink-2); margin-top: 1px; }
.nav { flex: 1; overflow-y: auto; }
.nav-group {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--frame-ink-2);
  padding: 14px 12px 6px;
}
.nav-group:first-child { padding-top: 2px; }
.nav-empty { padding: 12px; }
.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 2px 2px;
  padding: 11px 12px;
  border-radius: 10px;
  color: var(--frame-ink-2);
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
}
.nav-item:hover { background: var(--frame-hover); color: var(--frame-ink); }
/* Item aktif: satu bidang oat penuh + teks forest tebal. Tidak ada batang
   warna kiri (garis samping dekoratif) karena bidang penuh sudah cukup jelas.
   .side di depan supaya aturan ini menang atas penyesuaian drawer di HP. */
.nav-item.active,
.side .nav-item.active {
  background: var(--frame-active);
  color: var(--on-frame-active);
  font-weight: 700;
}
.nav-item.active .nav-ic svg { stroke: currentColor; }
.side-foot { padding: 10px 8px 0; border-top: 1px solid var(--frame-line); }
.side-foot .muted { color: var(--frame-ink-2); }
.side-foot button.link { color: var(--frame-ink); }
.side-foot button.link:hover { background: var(--frame-hover); }
.side-foot-actions { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.side .theme-btn:hover { background: var(--frame-hover); }

/* ===== Fase 2 pratinjau: kandidat chrome "teal" =====
   Dua kandidat untuk keputusan owner. Default: chrome putih melayang sudah
   aktif. Bila dokumen ber-attribute data-side="gelap" (dihidupkan lewat
   ?side=gelap di index.html), sidebar dirender hijau tua penuh sebagai
   identitas brand. Tema gelap sengaja tidak berubah — di sana kedua
   kandidat sudah gelap. Setelah owner memilih, varian yang tidak diambil
   dihapus supaya tidak jadi konfigurasi mati. */
html[data-side='gelap'][data-theme='light'] .side {
  background: var(--pri);
  border-color: rgba(244, 250, 248, 0.1);
  box-shadow: 0 1px 2px rgba(29, 74, 53, 0.35), 0 8px 24px rgba(29, 74, 53, 0.28);
}
html[data-side='gelap'][data-theme='light'] .brand { color: #F2F7F5; }
html[data-side='gelap'][data-theme='light'] .brand .brand-sub { color: rgba(242, 247, 245, 0.66); }
html[data-side='gelap'][data-theme='light'] .nav-group { color: rgba(242, 247, 245, 0.66); }
html[data-side='gelap'][data-theme='light'] .nav-item { color: rgba(240, 246, 244, 0.82); }
html[data-side='gelap'][data-theme='light'] .nav-item:hover { background: rgba(255, 255, 255, 0.09); }
/* Item aktif mint pekat: tidak di-buat transparan supaya tidak terlihat kotor
   di atas hijau tua; bar kiri & ikonnya ikut warna teks aktif. */
html[data-side='gelap'][data-theme='light'] .nav-item.active {
  background: var(--p-container);
  color: var(--on-p-container);
}
html[data-side='gelap'][data-theme='light'] .nav-item.active::before { background: var(--on-p-container); }
html[data-side='gelap'][data-theme='light'] .side-foot { border-top-color: rgba(244, 250, 248, 0.18); }
html[data-side='gelap'][data-theme='light'] .side-foot .muted { color: rgba(240, 246, 244, 0.75); }
html[data-side='gelap'][data-theme='light'] .side-foot button.link { color: #C9F3DF; }
html[data-side='gelap'][data-theme='light'] .side-foot button.link:hover { background: rgba(255, 255, 255, 0.09); }

/* Tombol toggle tema (topbar & sidebar) */
.theme-btn {
  margin-top: 0;
  margin-left: auto;
  width: var(--tap);
  height: var(--tap);
  padding: 0;
  border-radius: 50%;
  background: transparent;
  font-size: 18px;
  line-height: 1;
  display: grid;
  place-items: center;
  filter: none;
}
.theme-btn:hover, .tb-ico:hover { filter: none; }
.theme-btn:hover { background: var(--surface2); }
.side-foot .theme-btn { margin-left: 0; width: var(--tap); height: var(--tap); font-size: 15px; }

.main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
  border: 1px solid var(--hairline);
  border-radius: var(--r-panel);
  box-shadow: var(--shadow-panel);
  overflow: hidden;
}
.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 18px;
  min-height: 60px;
  /* Bilah atas ikut bingkai kopi: satu bidang gelap yang menyambung dari
     sidebar, jadi isi layar terasa "di dalam" aplikasi, bukan mengambang. */
  background: var(--frame);
  color: var(--frame-ink);
  border-bottom: 1px solid var(--frame-line);
}
.tb-left { min-width: 0; }
.topbar-name {
  font-weight: 800;
  letter-spacing: 0.01em;
  font-size: 16px;
  white-space: nowrap;
}
.topbar .brand-sub { display: block; font-size: 11px; font-weight: 400; color: var(--frame-ink-2); letter-spacing: 0.02em; }
/* Desktop: sidebar sudah menampilkan brand – topbar cukup judul view. */
@media (min-width: 900px) {
  .topbar .topbar-name { display: none; }
  .topbar .brand-sub { font-size: 14px; font-weight: 600; }
}
/* Chip pengguna di topbar: pintu ke "Profil Saya" (dulu div, sekarang <a>). */
.tb-right { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.tb-ico {
  position: relative;
  width: var(--tap);
  height: var(--tap);
  padding: 0;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--frame-line);
  background: transparent;
  color: var(--frame-ink);
  cursor: pointer;
  font-size: 15px;
}
.tb-ico:hover { background: var(--frame-hover); }
.tb-right .theme-btn { margin-left: 0; }
.tb-right .theme-btn:hover { background: var(--frame-hover); }
.tb-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 17px;
  height: 17px;
  border-radius: 9px;
  background: var(--error);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  display: grid;
  place-items: center;
}
/* Tema gelap: --error di sana adalah merah MUDA (#FFB4A9), jadi teks putih di
   atasnya cuma 1.70:1. Pasangan container/on-container memberi 12.6:1. */
[data-theme="dark"] .tb-badge { background: var(--error-container); color: var(--error); }
.tb-user { display: flex; align-items: center; gap: 8px; min-width: 0; min-height: var(--tap); padding: 2px 10px 2px 4px; border-radius: 999px; color: inherit; text-decoration: none; }
.tb-user:hover { background: var(--frame-hover); }
.tb-ava {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  flex: none;
  background: var(--frame-active);
  color: var(--on-frame-active);
  display: grid;
  place-items: center;
  font-weight: 800;
  font-size: 13px;
  overflow: hidden;
}
.tb-ava img,
.profile-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}
.tb-user-tx { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.tb-user-tx b { font-size: 13px; color: var(--frame-ink); font-weight: 600; }
.tb-user-tx i { font-size: 11.5px; font-style: normal; color: var(--frame-ink-2); }
@media (max-width: 899px) {
  .tb-user-tx { display: none; }
}
.view { padding: 14px 14px calc(110px + env(safe-area-inset-bottom, 0px)); width: 100%; max-width: 1240px; margin: 0 auto; overflow-x: clip; }
/* Baris filter dashboard memakai padding yang sama dengan isi (bukan tepi
   panel) supaya judul "Outlet" tidak menempel garis atas kartu isi. */
.sd-nav { padding-left: 14px; padding-right: 14px; }
@media (min-width: 900px) { .sd-nav { padding-left: 24px; padding-right: 24px; } }

/* Wadah render per layar (lihat beginRender di js/lib/shell.js). display:contents
   membuatnya tidak punya kotak sendiri, jadi tata letak anak-anaknya sama
   persis seperti sebelum ada wadah ini. */
.view-stage { display: contents; }

/* ===== Pemberitahuan sesi menganggur (auto logout 10 menit) =====
   Muncul satu menit sebelum keluar, di atas bilah bawah ponsel. Tombolnya
   mengulang jam diam, bukan menutup pemberitahuan tanpa efek. */
.idle-note {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 70;
  width: min(360px, calc(100vw - 32px));
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  padding: 14px 16px;
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  box-shadow: var(--shadow-panel);
}
.idle-note p { margin: 0; font-size: 14px; line-height: 1.45; }
.idle-note b { font-variant-numeric: tabular-nums; }
.idle-note .btn { width: auto; }
@media (max-width: 899px) {
  .idle-note { left: 12px; right: 12px; width: auto; bottom: calc(112px + env(safe-area-inset-bottom, 0px)); }
}

/* ===== Bottom nav (model: 4 modul + logo "AL" melayang di tengah → drawer) ===== */
.bottombar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 45;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  align-items: center;
  padding: 6px 6px calc(10px + env(safe-area-inset-bottom, 0px));
  /* Bilah bawah ikut bingkai kopi supaya navigasi di HP terbaca sebagai
     bagian aplikasi, bukan panel putih yang menutupi isi. */
  background: var(--frame);
  border-top: 1px solid var(--frame-line);
  border-radius: 22px 22px 0 0;
  box-shadow: 0 -6px 24px rgba(42, 38, 34, 0.18);
}
.bnav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 48px;
  padding: 4px 0;
  margin: 0;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 600;
  color: var(--frame-ink-2);
  text-decoration: none;
  background: none;
  cursor: pointer;
}
.bnav-item .nic {
  width: 54px;
  height: 30px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  font-size: 17px;
}
.bnav-item.active { color: var(--frame-active); font-weight: 700; }
.bnav-item.active .nic { background: var(--frame-active); color: var(--on-frame-active); }
/* Logo AL melayang (tombol tengah) */
.bnav-al {
  border: none;
  background: none;
  padding: 0;
  margin-top: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  font: inherit;
  font-size: 11px;
  font-weight: 700;
  color: var(--frame-ink);
  cursor: pointer;
  text-decoration: none;
  transform: translateY(-14px);
}
.bnav-al .al-mark {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: var(--pri);
  color: var(--on-pri);
  font-weight: 800;
  font-size: 20px;
  display: grid;
  place-items: center;
  box-shadow: 0 8px 18px rgba(29, 74, 53, 0.32);
}
.bnav-al:hover { filter: none; }
.bnav-al:active { transform: translateY(-12px) scale(0.97); }

/* ===== Drawer / scrim (mobile + tombol AL) ===== */
@media (max-width: 899px) {
  /* Ponsel: panel penuh, tanpa padding kanvas. Di 390px membuang 28px untuk
     padding terasa mahal, dan metafora "panel melayang" tidak terbaca.
     Sidebar tetap drawer dengan radius di sisi kanan. Bilah atas tetap gelap
     supaya identitas bingkai sama di HP dan desktop. */
  .bo { padding: 0; gap: 0; }
  .main { border: none; border-radius: 0; box-shadow: none; }
  .side {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    height: auto;
    z-index: 60;
    border: none;
    border-radius: 0 var(--r-panel) var(--r-panel) 0;
    /* Drawer di HP tetap bingkai kopi yang sama dengan sidebar desktop:
       identitas tidak berganti saat layar mengecil, dan item aktif memakai
       bidang oat yang sama. Lebar 250px, jadi sisanya tetap terlihat scrim. */
    background: var(--frame);
    transform: translateX(-104%);
    transition: transform 0.25s ease;
    box-shadow: none;
    padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  }
  .side.open { transform: translateX(0); box-shadow: 8px 0 30px rgba(42, 38, 34, 0.25); }
}
.scrim {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgba(42, 38, 34, 0.42);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s;
}
.scrim.on { opacity: 1; pointer-events: auto; }

/* ===== Opsi tema di Pengaturan ===== */
.theme-opt {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: var(--tap);
  padding: 10px 4px;
  cursor: pointer;
}
.theme-opt + .theme-opt { border-top: 1px solid var(--outline-var); }
.theme-opt input { width: var(--box); height: var(--box); margin: 0; }
.theme-opt-tx { display: flex; flex-direction: column; gap: 1px; }
.theme-opt-tx b { font-size: 14.5px; }

/* Desktop-only: tombol di dalam tabel jadi lebih pendek supaya baris tidak
   memanjang. Mobile tetap 44px; hanya >=900px yang dikecilkan. */
@media (min-width: 900px) {
  .tbl button, .tbl .btn, .tbl .btn-sec {
    min-height: 32px;
    padding: 6px 10px;
    font-size: 13px;
    border-radius: 10px;
  }
  .tbl .btn--sm { min-height: 30px; padding: 4px 10px; font-size: 12.5px; border-radius: 9px; }
  .tbl .btn-row { margin: 0; }
  .tbl td { vertical-align: middle; }
}

/* ===== Desktop ===== */
@media (min-width: 900px) {
  .bottombar { display: none; }
  .scrim { display: none; }
  .view { padding: 20px 24px 32px; }
  .card.login-card { margin-top: 9vh; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}
