/* Clean Industrial, Job Order Management System. */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --bg:       #f7f2e9;
  --surface:  #fdfbf6;
  --border:   #e6ddcc;
  --hover:    #f0e9da;
  --text:     #1f2937;
  --text-dim: #566474;
  --accent:   #0e7c6b;
  --accent-hover: #0a6355;
  --accent-light: rgba(14,124,107,.12);
  --accent-dark: #0a6355;
  --success:  #16a34a;
  --danger:   #dc2626;
  --warning:  #92400e;
  --info:     #0891b2;
  --radius:   10px;
  --shadow:   0 1px 3px rgba(0,0,0,.04), 0 1px 2px rgba(0,0,0,.03);
  --shadow-md: 0 4px 12px rgba(0,0,0,.06);
  --font:     'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono:     'IBM Plex Mono', 'JetBrains Mono', monospace;
}

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
  line-height: 1.6;
  padding: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

.container {
  max-width: 1000px;
  margin: 0 auto;
  background: var(--surface);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  padding: 24px 20px;
}

h1, h2 {
  font-size: 20px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 4px;
}
.subtitle {
  font-size: 13px;
  color: var(--text-dim);
  margin-bottom: 20px;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 14px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .3px;
  text-transform: uppercase;
}
/* Warna badge status = SATU per status (label boleh ganti, warna tetap).
   BERES hijau zamrud (bukan hijau muda Selesai), SELESAI ungu (tinta arsip,
   bukan duplikat biru Finishing) — tiap status beda rona sekilas. */
.badge--menunggu        { background: #fef9c3; color: #854d0e; }
.badge--sudah-tf         { background: #e0f2fe; color: #075985; }
.badge--proses-produksi { background: #ffedd5; color: #9a3412; }
.badge--proses-qc       { background: #dbeafe; color: #1e40af; }
.badge--siap-diambil    { background: #a7f3d0; color: #065f46; }
.badge--sudah-diambil   { background: #ede9fe; color: #5b21b6; }
.badge--dibatalkan      { background: #fee2e2; color: #991b1b; }
/* Alias lama (tak dipakai JO_STATUS, dipertahankan kompatibel). */
.badge--siap-produksi   { background: #dbeafe; color: #1e40af; }
.badge--selesai         { background: #dcfce7; color: #166534; }  .badge--default         { background: #f0e9da; color: #475569; }
.badge--fin             { background: #ede9fe; color: #5b21b6; cursor: pointer; }
.badge--acc             { background: #ffedd5; color: #9a3412; cursor: pointer; }

.seg { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; flex: 0 0 auto; }
.seg-btn { border: none; background: var(--bg); color: var(--text-dim); padding: 8px 12px; font-size: 12px; font-weight: 700; cursor: pointer; }
.seg-btn.active { background: var(--accent); color: #fff; }
[data-theme="dark"] .badge--fin { background: #2e1065; color: #c4b5fd; }
[data-theme="dark"] .badge--acc { background: #431407; color: #fdba74; }
[data-theme="dark"] .seg-btn.active { background: var(--accent); }

label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .5px;
  margin-bottom: 4px;
  margin-top: 16px;
}

input[type="text"], input[type="password"], textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1.5px solid var(--border);
  border-radius: 8px;
  font-size: 15px;
  font-family: var(--font);
  color: var(--text);
  background: var(--surface);
  transition: border-color .2s, box-shadow .2s;
  outline: none;
}
input:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
input::placeholder, textarea::placeholder {
  color: var(--text-dim);
  opacity: 1;
}
textarea { min-height: 60px; resize: vertical; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 16px 20px;
  margin-top: 12px;
  min-height: 48px;
  border: none;
  border-radius: 8px;
  font-size: 16px;
  font-weight: 700;
  font-family: var(--font);
  cursor: pointer;
  transition: background .15s, transform .1s, box-shadow .15s;
  -webkit-tap-highlight-color: transparent;
}
.btn:active { transform: scale(.98); }
.btn:hover { box-shadow: var(--shadow-md); }
/* Reset outline default untuk kontrol: browser/WebView menggambar outline
   "tebal" bawaan saat kontrol fokus (di APK/WebView terlihat sebagai kotak
   tebal). Aksesibilitas keyboard TETAP dijaga lewat :focus-visible di bawah. */
button:focus:not(:focus-visible),
select:focus:not(:focus-visible),
input:focus:not(:focus-visible),
textarea:focus:not(:focus-visible) { outline: none; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.seg-btn:focus-visible, .page-btn:focus-visible, .filter-btn:focus-visible,
.badge-clickable:focus-visible, .badge--fin:focus-visible,
.designer-link:focus-visible, .bahan-link:focus-visible,
.pending-item:focus-visible, .drill-so:focus-visible,
.mute-btn:focus-visible,
.theme-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.btn--primary   { background: var(--accent); color: #fff; }
.btn--primary:hover { background: var(--accent-hover); }
.btn--success   { background: var(--success); color: #fff; }
.btn--success:hover { background: #15803d; }
.btn--danger    { background: var(--danger); color: #fff; }
.btn--danger:hover { background: #b91c1c; }  .btn--secondary { background: #5b5145; color: #fff; }  .btn--secondary:hover { background: #4a4238; }
.btn--warning   { background: var(--warning); color: #fff; }
.btn--warning:hover { background: #b45309; }
.btn--outline {
  background: transparent;
  color: var(--text-dim);
  border: 1.5px solid var(--border);
  min-height: 48px;
  padding: 16px 20px;
  font-size: 16px;
}  .btn--outline:hover { background: #f5efe3; }

/* Ukuran tombol kecil. Nilai = hasil cascade dua definisi lama (yang kedua
   menang untuk properti yang sama, min-height hanya ada di yang pertama) —
   digabung di sini supaya satu sumber dan tak bergantung urutan stylesheet. */
.btn--sm { width: auto; padding: 6px 14px; font-size: 13px; margin-top: 0; min-height: 44px; }
.btn--xs { width: auto; padding: 3px 10px; font-size: 12px; margin-top: 0; border-radius: 6px; min-height: 40px; }

/* Touch-friendly action row */
.action-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 12px;
}
.action-row .btn { flex: 1; min-width: 0; }

/* Baris tombol aksi /scan compact (btn--sm): dua tombol sejajar horizontal,
   kiri & kanan (space-between). .act-row-start = hanya rata kiri (satu tombol).
   Dipakai: MUNDUR+LANJUTKAN (non-KASIR), BATALKAN+LANJUTKAN & PRINT (KASIR).
   nowrap + flex:0 1 auto: dua tombol tetap satu baris (menyusut bila sempit). */
.act-compact-row {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: space-between;
  margin-top: 10px;
  flex-wrap: nowrap;
}
.act-compact-row.act-row-start { justify-content: flex-start; }
.act-compact-row.act-row-end { justify-content: flex-end; }
/* Tombol TERAKHIR selalu rata KANAN, termasuk saat ia satu-satunya isi baris.
   space-between dengan satu anak menaruhnya di kiri — padahal tombol lanjut
   (PROSES/BERES/DIAMBIL) WAJIB tetap kanan walau tombol kiri (MUNDUR/BATALKAN)
   gugur, mis. JO masih tahap KASIR dibuka di FINISHING (revert tak tersedia).
   .act-row-start dikecualikan: baris "hanya MUNDUR" memang sengaja kiri. */
.act-compact-row:not(.act-row-start) .btn:last-child { margin-left: auto; }
.act-compact-row .btn {
  flex: 0 1 auto; width: auto; margin-top: 0;
  min-height: 40px; padding: 6px 12px; font-size: 12px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.filter-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 20px;
  padding: 12px 14px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.filter-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: .72rem;
  color: var(--text-dim);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  white-space: nowrap;
  padding-right: 10px;
  border-right: 1px solid var(--border);
  margin-right: 2px;
}
.filter-label__icon {
  font-size: 1rem;
  line-height: 1;
  color: var(--accent);
}
/* ikon SVG di label filter (funnel / layers) — dipakai /cek & dashboard */
.filter-label .flt-ico { color: var(--accent); flex-shrink: 0; }
/* Label filter ikon saja: teks periode dihapus karena tombol rentang di
   sebelahnya sudah menyebut periode. Ikon funnel = penanda "ini filter",
   dikecilkan seperlunya supaya tidak jadi kolom kosong. */
.filter-label--icon {
  padding-right: 4px;
  border-right: none;
  margin-right: 0;
  letter-spacing: 0;
}
.filter-label--icon .flt-ico { width: 18px; height: 18px; }
.filter-btns {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  flex: 1;
}
.filter-btn {
  padding: 7px 14px;
  border-radius: 999px;
  border: 1.5px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  font-size: .78rem;
  font-weight: 600;
  font-family: var(--font);
  cursor: pointer;
  transition: all .15s ease;
  -webkit-tap-highlight-color: transparent;
  white-space: nowrap;
}
.filter-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  box-shadow: var(--shadow);
}
.filter-btn:active { transform: scale(.97); }
.filter-btn.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
  box-shadow: 0 2px 6px color-mix(in srgb, var(--accent) 35%, transparent);
}
[data-theme="dark"] .filter-btn {
  background: #1e293b;
  border-color: #2b3445;
  color: #94a3b8;
}
[data-theme="dark"] .filter-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
[data-theme="dark"] .filter-btn.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

/* Dropdown select di filter-bar: pill penuh + chevron tema */
.filter-select {
  appearance: none;
  -webkit-appearance: none;
  flex: 1;
  min-width: 0;
  max-width: 100%;
  padding: 6px 34px 6px 14px;
  min-height: 34px;
  border-radius: 20px;
  border: 1.5px solid var(--border);
  background-color: var(--surface);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 14px;
  color: var(--text-dim);
  font-size: .8rem;
  font-weight: 600;
  font-family: var(--font);
  cursor: pointer;
  transition: all .15s ease;
  box-sizing: border-box;
}
.filter-select:hover { border-color: var(--accent); color: var(--accent); }
.filter-select:focus {
  outline: none;
  border-color: var(--accent);
  color: var(--text);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
}
[data-theme="dark"] .filter-select {
  background-color: #1e293b;
  border-color: #2b3445;
  color: #94a3b8;
  color-scheme: dark;
}
[data-theme="dark"] .filter-select:hover,
[data-theme="dark"] .filter-select:focus { border-color: var(--accent); color: var(--text); }
/* opsi dropdown mengikuti tema */
.filter-select option { background: var(--surface); color: var(--text); }
[data-theme="dark"] .filter-select option { background: #1e293b; color: #e2e8f0; }

/* Filter date / select, sejajar presisi dengan .filter-btn */
.filter-date {
  padding: 6px 14px;
  min-height: 34px;
  border-radius: 20px;
  border: 1.5px solid var(--border);
  background: var(--surface);
  color: var(--text-dim);
  font-size: .8rem;
  font-weight: 600;
  font-family: var(--font);
  cursor: pointer;
  transition: all .15s ease;
  box-sizing: border-box;
}
select.filter-date { padding-right: 28px; }
.filter-date:hover { border-color: var(--accent); color: var(--accent); }
.filter-date:focus {
  outline: none;
  border-color: var(--accent);
  color: var(--text);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
}
[data-theme="dark"] .filter-date {
  background: #1e293b;
  border-color: #2b3445;
  color: #94a3b8;
  color-scheme: dark;
}
[data-theme="dark"] .filter-date:hover,
[data-theme="dark"] .filter-date:focus { border-color: var(--accent); color: var(--text); }

/* Tombol aksi dalam filter-bar mengikuti tinggi pill filter */
.filter-bar .btn--xs,
.filter-bar .btn--sm {
  padding: 6px 16px;
  min-height: 34px;
  border-radius: 20px;
  font-size: .8rem;
  font-weight: 600;
  margin-top: 0;
}
.search-row {
  display: flex;
  gap: 12px;
  align-items: center;
}
.search-row input {
  flex: 1;
  margin-bottom: 0;
}
.search-row .btn--sm {
  white-space: nowrap;
}

.card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-top: 16px;
}
.card__header {
  background: #f6f1e6;
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
}

/* Flat compact: card INFO JOB ORDER — dipakai /cek (#cekInfoCard) dan
   /scan (.jo-info-card). Satu aturan agar keduanya tak bisa berbeda.
   Tanpa border kotak, sekat = garis horizontal di atas judul, tanpa shadow
   (shadow hanya menandai elevasi; di sini tidak ada elevasi). */
.card#cekInfoCard,
.card.jo-info-card {
  border: none;
  border-top: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
  margin-top: 24px;
  padding-top: 16px;
}
.card#cekInfoCard .card__header,
.card.jo-info-card .card__header {
  background: transparent;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
  padding: 10px 14px 9px;
}
/* QR baris identitas JOB ID: 72px di .jg-qr (di bawah). Aturan ini cadangan
   untuk .cek-qr-img di luar baris identitas (mis. label cetak _jopick.html:
   56px). Latar putih wajib (QR butuh kontras untuk dipindai). */
.card#cekInfoCard .cek-qr-img:not(.jg-qr),
.card.jo-info-card .cek-qr-img:not(.jg-qr) {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: 8px;
  background: #fff;
}
.card#cekInfoCard .card__body,
.card.jo-info-card .card__body { display: flex; flex-direction: column; gap: 12px; padding: 12px 14px 14px; }

/* Flat compact: history terintegrasi dalam INFO JOB ORDER */
/* RIWAYAT PROSES — timeline vertikal rata tengah.
   Prinsip antislop: satu card datar (tanpa card-per-baris melayang),
   warna dot = status (bukan dekorasi), accent hanya untuk entri terbaru. */
.jo-history-section {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.jo-section-title {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: .5px;
  margin-bottom: 14px;
  text-align: center;
}
.jo-history-empty {
  color: var(--text-dim);
  font-size: 13px;
  text-align: center;
  padding: 12px 0;
}
.timeline-center {
  position: relative;
  max-width: 560px;
  margin: 0 auto;
  padding: 4px 0;
}
/* Rel timeline digambar PER BARIS: dari dot baris ini ke dot baris berikutnya.
   Baris terakhir (JO MASUK — peristiwa paling lama) TIDAK menggambar, jadi
   garis berhenti di dot JO MASUK dan tak menggantung di bawahnya; ujung atas
   juga berhenti di dot entri terbaru. Netral --text-dim pekat; warna = status,
   dipegang dot (R-01/R-31). */
.jo-history-row:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 8px;
  bottom: -8px;
  width: 2px;
  background: var(--text-dim);
  z-index: 0;
}
.jo-history-row:nth-child(odd):not(:last-child)::after { left: -1px; }
.jo-history-row:nth-child(even):not(:last-child)::after { right: -1px; }
.jo-history-row {
  position: relative;
  width: 50%;
  padding: 0 26px 18px;
  box-sizing: border-box;
}
/* baris ganjil (pertama, ketiga, ...) kanan; genap kiri */
.jo-history-row:nth-child(odd) { margin-left: 50%; text-align: left; }
.jo-history-row:nth-child(even) { margin-right: 50%; text-align: right; }
/* titik pada sumbu tengah — offset diturunkan dari --dot-size, bukan
   angka hardcode, agar dot current (13px) tak pernah meleset dari rel */
.jo-hist-dot {
  --dot-size: 11px;
  position: absolute;
  top: calc(8.5px - var(--dot-size) / 2);
  width: var(--dot-size);
  height: var(--dot-size);
  border-radius: 50%;
  background: var(--text-dim);
  border: 2px solid var(--surface);
  box-sizing: border-box;
  z-index: 1;
}
.jo-history-row:nth-child(odd) .jo-hist-dot { left: calc(var(--dot-size) / -2); }
.jo-history-row:nth-child(even) .jo-hist-dot { right: calc(var(--dot-size) / -2); }
.jo-history-row.current .jo-hist-dot {
  --dot-size: 13px;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.jo-hist-content { min-width: 0; }
.jo-hist-checkpoint {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
}
.jo-hist-checkpoint svg { vertical-align: -2px; }
.jo-history-row.current .jo-hist-checkpoint { color: var(--accent); }
/* Tooltip modern tahap riwayat (ganti title bawaan): teks dari data-tip,
   bubble + panah murni CSS, fade + geser naik, hormati reduced-motion.
   Di atas judul; max-width + wrap agar muat di HP. */
.jo-hist-checkpoint[data-tip] { position:relative; cursor:help; }
.jo-hist-checkpoint[data-tip]::after {
  content:attr(data-tip);
  position:absolute; bottom:calc(100% + 8px); left:50%;
  width:max-content; max-width:min(260px, 70vw);
  padding:7px 12px; border-radius:8px;
  background:#1f2937; color:#fff;
  font-size:12px; font-weight:500; line-height:1.4; text-align:center;
  white-space:normal;
  box-shadow:0 8px 22px rgba(16,24,40,.25);
  opacity:0; visibility:hidden; pointer-events:none;
  transform:translateX(-50%) translateY(4px);
  transition:opacity .18s ease, transform .18s ease, visibility .18s ease;
  z-index:50;
}
.jo-hist-checkpoint[data-tip]::before {
  content:"";
  position:absolute; bottom:calc(100% + 2px); left:50%;
  border:6px solid transparent; border-top-color:#1f2937;
  opacity:0; visibility:hidden; pointer-events:none;
  transform:translateX(-50%);
  transition:opacity .18s ease, visibility .18s ease;
  z-index:50;
}
.jo-hist-checkpoint[data-tip]:hover::after,
.jo-hist-checkpoint[data-tip]:hover::before {
  opacity:1; visibility:visible;
}
.jo-hist-checkpoint[data-tip]:hover::after { transform:translateX(-50%) translateY(0); }
[data-theme="dark"] .jo-hist-checkpoint[data-tip]::after { background:#e8eaed; color:#111; }
[data-theme="dark"] .jo-hist-checkpoint[data-tip]::before { border-top-color:#e8eaed; }

.badge[data-tip], span[data-tip] { position:relative; cursor:help; }
.badge[data-tip]::after, span[data-tip]::after {
  content:attr(data-tip);
  position:absolute; bottom:calc(100% + 8px); left:50%;
  width:max-content; max-width:min(260px, 70vw);
  padding:7px 12px; border-radius:8px;
  background:#1f2937; color:#fff;
  font-size:12px; font-weight:500; line-height:1.4; text-align:center;
  white-space:normal;
  box-shadow:0 8px 22px rgba(16,24,40,.25);
  opacity:0; visibility:hidden; pointer-events:none;
  transform:translateX(-50%) translateY(4px);
  transition:opacity .18s ease, transform .18s ease, visibility .18s ease;
  z-index:50;
}
.badge[data-tip]::before, span[data-tip]::before {
  content:"";
  position:absolute; bottom:calc(100% + 2px); left:50%;
  transform:translateX(-50%);
  border:6px solid transparent; border-top-color:#1f2937;
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .18s ease, visibility .18s ease;
  z-index:51;
}
.badge[data-tip]:hover::after, .badge[data-tip]:hover::before,
span[data-tip]:hover::after, span[data-tip]:hover::before {
  opacity:1; visibility:visible;
}
.badge[data-tip]:hover::after, span[data-tip]:hover::after { transform:translateX(-50%) translateY(0); }
[data-theme="dark"] .badge[data-tip]::after, [data-theme="dark"] span[data-tip]::after { background:#e8eaed; color:#111; }
[data-theme="dark"] .badge[data-tip]::before, [data-theme="dark"] span[data-tip]::before { border-top-color:#e8eaed; }

@media (prefers-reduced-motion:reduce) {
  .jo-hist-checkpoint[data-tip]::after,
  .jo-hist-checkpoint[data-tip]::before { transition:none; transform:translateX(-50%); }
  .badge[data-tip]::after, .badge[data-tip]::before,
  span[data-tip]::after, span[data-tip]::before { transition:none; transform:translateX(-50%); }
}
.jo-hist-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 8px;
  align-items: baseline;
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 2px;
}
.jo-history-row:nth-child(even) .jo-hist-meta { justify-content: flex-end; }
.jo-hist-op { font-weight: 500; color: var(--text); }
.jo-hist-time { font-family: var(--mono); font-size: 11px; }
.jo-hist-notes {
  display: inline-block;
  margin-top: 6px;
  padding: 5px 9px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-dim);
  background: var(--hover);
  border-radius: var(--radius);
  max-width: 100%;
  overflow-wrap: anywhere;
  text-align: left;
}
/* Animasi masuk baris: stagger saat render pertama, slide dari sisi sumbu.
   Hanya baris baru yang animasi saat refresh realtime (lihat _histSeen). */
@keyframes histIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.jo-history-row.hist-in { animation: histIn .28s ease both; }
/* Pulse ring pada entri terbaru yang baru muncul */
@keyframes histFlash {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 45%, transparent); }
  100% { box-shadow: 0 0 0 8px transparent; }
}
.jo-history-row.hist-flash .jo-hist-dot { animation: histFlash .9s ease-out 1; }
@media (prefers-reduced-motion: reduce) {
  .jo-history-row.hist-in,
  .jo-history-row.hist-flash .jo-hist-dot { animation: none; }
}
/* HP: sumbu pindah ke kiri, semua baris ke kanan */
@media (max-width: 640px) {
  .jo-history-row,
  .jo-history-row:nth-child(odd),
  .jo-history-row:nth-child(even) {
    width: 100%;
    margin-left: 0;
    margin-right: 0;
    padding: 0 0 18px 26px;
    text-align: left;
  }
  /* sumbu pindah ke kiri: rel sejajar dot (dot left:1px + 5.5px = 6.5px) */
  .jo-history-row:nth-child(odd):not(:last-child)::after,
  .jo-history-row:nth-child(even):not(:last-child)::after { left: 5.5px; right: auto; }
  /* sumbu pindah ke kiri: dot & rel sama-sama center 6.5px dari tepi baris */
  .jo-history-row:nth-child(odd) .jo-hist-dot,
  .jo-history-row:nth-child(even) .jo-hist-dot { left: calc(6.5px - var(--dot-size) / 2); right: auto; }
  .jo-history-row:nth-child(even) .jo-hist-meta { justify-content: flex-start; }
}
.card__body { padding: 0; }

.batch-scan-toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  user-select: none;
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  transition: border-color .15s, background .15s;
}
.batch-scan-toggle:hover { border-color: var(--accent); }
.batch-scan-toggle input {
  width: 15px;
  height: 15px;
  accent-color: var(--accent);
  cursor: pointer;
}
.card__header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}
.pending-item.pi-flash {
  animation: piFlash .8s ease;
}
@keyframes piFlash {
  0% { background: rgba(45, 106, 79, 0.22); }
  100% { background: transparent; }
}

.pending-list { display: flex; flex-direction: column; }
/* Flat compact: hilangkan border/shadow pada card pending list */
.scanner-card { border: none; border-radius: 0; box-shadow: none; overflow: visible; }
.scanner-card .card__header { background: transparent; border-bottom: 1px solid var(--border); padding: 8px 14px; }
.scanner-card .card__body { padding: 0; }

.pending-search {
  position: relative;
  display: flex;
  align-items: center;
  padding: 10px 14px 0;
}
.pending-search .ps-ico {
  position: absolute;
  left: 26px;
  display: inline-flex;
  color: var(--text-dim);
  pointer-events: none;
  opacity: .75;
}
.pending-search input {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 12px 8px 32px;
  font-size: 0.85rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  outline: none;
  transition: border-color .18s, box-shadow .18s, background .18s;
}
.pending-search input::placeholder {
  color: var(--text-dim);
}
.pending-search input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
  background: var(--bg);
}
.op-label {
  text-transform: none;
  letter-spacing: 0;
}
.copy-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  margin-left: 6px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-dim);
  cursor: pointer;
  vertical-align: middle;
  transition: color .15s, border-color .15s, background .15s;
}
.copy-ico:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}
.copy-ico svg { width: 14px; height: 14px; }
.cancel-reason {
  border-left: 3px solid var(--danger, #dc2626);
  background: color-mix(in srgb, #dc2626 7%, var(--surface));
}
.cancel-reason-text {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  word-break: break-word;
  line-height: 1.45;
}
.cancel-op { color: var(--text-dim); font-size: 0.85em; }

/* Pending list = tabel kolom (gaya Excel) via CSS Grid. Header (.pending-head)
   dan tiap baris (.pending-item) memakai template kolom SAMA (--pi-cols, di-set
   scanner.js: pendingLayout()) -> semua kolom sejajar vertikal. Kolom per
   breakpoint juga ditentukan di pendingLayout() (bukan media query), karena
   grid-template-columns tidak bisa di-override media query saat inline. */
.pending-head,
.pending-item {
  display: grid;
  grid-template-columns: var(--pi-cols, 84px minmax(0, 1.6fr) 46px minmax(0, 1fr) 76px 72px);
  align-items: center;
  column-gap: 10px;
}
/* Header judul kolom: kecil, uppercase, redup, latar tipis — nuansa header Excel */
.pending-head {
  padding: 6px 14px;
  background: var(--hover);
  border-bottom: 1px solid var(--border);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.pending-head .pi-cell { display: flex; align-items: center; overflow: hidden; white-space: nowrap; }
/* Sel data: teks boleh menyusut + ellipsis (min-width:0 wajib di grid/flex) */
.pending-item .pi-cell { min-width: 0; display: flex; align-items: center; overflow: hidden; }
.pending-item .pi-cell .pi-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* WAKTU rata KIRI (sejajar dgn header + angka antar-baris; ikon peringatan di
   kanan angka tak menggeser titik mulai). TIPE rata tengah (pill). */
.pending-item .pi-c-waktu { justify-content: flex-start; }
.pending-item .pi-c-tipe { justify-content: center; }
.pending-head .pi-c-tipe { justify-content: center; }
/* STATUS = tag tahap JO (badge JO_STATUS, .pi-st versi ringkas): kolom >600px
   saja — di ≤600px (mobile) kolom gugur dan tag TIDAK dirender (permintaan
   user: /scan mobile tanpa tag status). Badge diringkas biar muat 1 baris;
   warna tetap milik .badge--* (ikut dark mode sendiri). */
.pending-item .pi-c-status { justify-content: flex-start; }
.pending-head .pi-c-status { justify-content: flex-start; }
.pending-item .pi-st {
  font-size: 10px;
  padding: 1.5px 8px;
  letter-spacing: .02em;
  line-height: 1.4;
  white-space: nowrap;
  flex: 0 0 auto;
}
/* Ceklis baris info (status di luar tahap stasiun ini): terlihat, tak bisa
   dipilih — pilihan batch tidak boleh memicu 409 dari server. */
.pending-item .pi-check:disabled { opacity: .3; cursor: default; }
/* HP (<=600): judul kolom CENTER; SO rapat KIRI, ANTRI rapat KANAN (nilai);
   CUSTOMER ambil sisa lebar (paling lebar). Desktop tak berubah. */
@media (max-width: 600px) {
  .pending-head .pi-cell { justify-content: center; }
  /* Kolom [cek] tetap rata KIRI (header & baris) supaya checkbox "pilih semua"
     sejajar vertikal dgn checkbox baris — bukan ikut ter-center. */
  .pending-head .pi-c-check, .pending-item .pi-c-check { justify-content: flex-start; }
  .pending-item .pi-c-so { justify-content: flex-start; }
  .pending-item .pi-c-customer { justify-content: flex-start; }
  .pending-item .pi-c-waktu { justify-content: flex-end; }
}

.pending-item {
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background .12s;
  font-size: 13px;
  min-height: 38px;
}
.pending-item:last-child { border-bottom: none; }

/* Pager hasil pencarian /scan (buildPagerHtml): chevron + posisi halaman. */
.search-pager { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 10px 0; flex-wrap: wrap; }
.pending-item:hover { background: var(--hover); }
.pending-item.active { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); border-left: 3px solid var(--accent); padding-left: 11px; }

/* SO = kunci baris (bold). Customer = teks utama (jelas dari jauh). */
.pending-item .pi-c-so .pi-txt { font-weight: 700; color: var(--text); }
.pending-item .pi-c-customer .pi-txt { color: var(--text); font-weight: 600; }
.pending-item .pi-c-ds .pi-txt { color: var(--text-dim); font-weight: 600; }
/* tag kecil tipe order — dipakai pending list & hasil pencarian /scan */
.pi-tipe {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .03em;
  padding: 1px 5px;
  border-radius: 3px;
  background: var(--accent-light);
  color: var(--accent);
  vertical-align: middle;
  margin-left: 2px;
  white-space: nowrap;
}
/* Base tag tipe order (SATU bentuk, dipakai SEMUA tempat: pending list /scan,
   list & hasil cari /cek, dashboard, DAN detail INFO JO). Dulu base ini hanya
   ada di inline <style> cekjo/dashboard; dipindah ke sini supaya /scan juga
   punya + warna ot-* konsisten di list maupun detail. */
.cek-ot-tag {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .03em;
  padding: 1px 5px;
  border-radius: 3px;
  background: var(--accent-light);
  color: var(--accent);
  vertical-align: middle;
  white-space: nowrap;
}
/* Di detail INFO JO tag dinaikkan sedikit (register detail, bukan baris list). */
.jo-info-body .cek-ot-tag { font-size: 11px; padding: 2px 8px; border-radius: 4px; }

/* Warna tag tipe order — satu warna per tipe (warna brand), tiga varian saja.
   Dua tempat pakai tag ini: /cek (flat list, .cek-ot-tag) dan pending list
   /scan/KASIR (.pi-tipe). Tipe tak dikenal tetap pakai warna dasar (accent).
   Teks SELALU dipilih yang lolos WCAG: putih di atas hijau #25D366 cuma
   1.98:1 (gagal), jadi pakai teks gelap (10.59:1).
   - ONLINE  = hijau WhatsApp #25D366 (teks gelap #052e16 = 7.52:1)
   - DIRECT  = merah bata #B22222 (teks putih = 6.68:1)
   - MARKET  = hitam-putih TikTok (hitam #010101 + teks putih = 20.87:1).
     Di DARK mode chip hitam nyaris hilang di latar #0a0a0a (1.05:1) ->
     DIBALIK jadi putih #f1f1f1 + teks hitam (18.48:1), tetap terbaca. */
.cek-ot-tag.ot-online, .pi-tipe.ot-online { background: #25d366; color: #052e16; }
.cek-ot-tag.ot-direct, .pi-tipe.ot-direct { background: #b22222; color: #ffffff; }
.cek-ot-tag.ot-market, .pi-tipe.ot-market { background: #010101; color: #ffffff; }
[data-theme="dark"] .cek-ot-tag.ot-online, [data-theme="dark"] .pi-tipe.ot-online { background: #25d366; color: #052e16; }
[data-theme="dark"] .cek-ot-tag.ot-direct, [data-theme="dark"] .pi-tipe.ot-direct { background: #b22222; color: #ffffff; }
[data-theme="dark"] .cek-ot-tag.ot-market, [data-theme="dark"] .pi-tipe.ot-market { background: #f1f1f1; color: #010101; }
/* Kolom checkbox OPSIONAL (penanda barang sudah diserahkan; berguna saat
   pengambilan SEBAGIAN). BUKAN syarat proses. Baris tercentang = redup +
   nama dicoret + ikon ceklis LINE di ujung NAMA FILE.
   Ditaruh di style.css (BUKAN inline scanner.html) supaya /cek juga dapat
   tanpa menyalin — dulu hanya di scanner.html sehingga /cek tak menampilkannya. */
.item-table .ci-ambil { width:34px; text-align:center; padding-left:8px; padding-right:0; }
.ci-ambil-check {
  appearance:none; -webkit-appearance:none;
  width:20px; height:20px; margin:0; flex-shrink:0;
  border:1.8px solid var(--border); border-radius:5px;
  background:var(--surface); cursor:pointer; position:relative;
  display:inline-grid; place-items:center; vertical-align:middle;
  transition:background .12s, border-color .12s;
}
.ci-ambil-check:hover { border-color:var(--accent); }
.ci-ambil-check:checked { background:var(--accent); border-color:var(--accent); }
.ci-ambil-check:checked::after {
  content:""; position:absolute; left:50%; top:50%;
  width:5px; height:10px; border:solid #fff; border-width:0 2px 2px 0;
  transform: translate(-50%,-60%) rotate(45deg);
}
.ci-ambil-check:focus-visible { outline:none; box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 30%, transparent); }
.ci-ambil-check:disabled { opacity:.5; cursor:default; }
.item-table tr.row-ambil-done .ci-nama,
.item-table tr.row-ambil-done .ci-bahan,
.item-table tr.row-ambil-done .ci-finishing { opacity:.45; }
.item-table tr.row-ambil-done .ci-nama { text-decoration:line-through; text-decoration-color:color-mix(in srgb, var(--text) 35%, transparent); }
/* Ikon ceklis LINE di ujung NAMA FILE (penanda sudah diambil). */
.ci-ambil-line { display:none; margin-left:6px; color:var(--success); vertical-align:-2px; }
.item-table tr.row-ambil-done .ci-ambil-line { display:inline-block; }

.pending-item .pi-wait {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-dim);
  white-space: nowrap;
}
/* Pill tipe di sel kolom TIPE: lebar dipatok sama karena ONLINE/DIRECT/MARKET
   beda lebar teks; sel sudah rata-tengah (lihat .pi-c-tipe). */
.pending-item .pi-tipe {
  min-width: 54px;
  text-align: center;
  margin-left: 0;
}
/* Urgent = kerjaan diminta didahulukan / sudah >8 jam menunggu. Garis batas kiri
   merah (bahasa visual sama dengan .stale/.active), plus latar lembut agar
   terbaca dari jauh di layar scanner. padding-left dikompensasi 3px supaya teks
   tidak bergeser saat border dipasang. */
.pending-item.urgent {
  background: #fffbeb;
  border-left: 3px solid var(--danger);
  padding-left: 11px;
}
.pending-item.urgent .pi-wait { color: var(--danger); }
.pending-item.stale { border-left: 3px solid var(--warning); }
.pending-item.stale .pi-wait { color: var(--warning); font-weight: 600; }
/* Tanda peringatan di ujung kanan kolom WAKTU, sesudah durasi tunggu. Warna ikut
   .pi-wait (danger >8 jam / warning >24 jam); .kw = accent (catatan didahulukan). */
.pending-item .pi-warn {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  margin-left: 4px;
  color: var(--text-dim);
}
.pending-item .pi-warn svg { display: block; }
.pending-item.urgent .pi-warn { color: var(--danger); }
/* Baris urgent yang sedang dipilih: batas merah tetap (info permanen), latar
   akcent kembali (penanda pilihan) -- kalau tidak, keduanya saling menimpa
   karena .active dan .urgent sama-sama spesifik dan .urgent belakangan. */
.pending-item.active.urgent { background: color-mix(in srgb, var(--accent) 14%, var(--surface)); }
.pending-item.stale .pi-warn { color: var(--warning); }
.pending-item .pi-warn.kw { color: var(--accent); }
/* Marketplace: ikon tas, warna hitam (senada tag MARKET TikTok #010101) supaya
   terbaca sebagai "tipe order", bukan "catatan minta didahulukan" (petir, accent). */
.pending-item .pi-warn.mkt { color: #010101; }
[data-theme="dark"] .pending-item .pi-warn.mkt { color: #f1f1f1; }

/* Ikon catatan (popup) di sel CUSTOMER: hanya tampil bila kolom CATATAN tidak
   ada (layar <=768; kolom CATATAN dihapus di pendingLayout()). Di desktop ikon
   tinggal di kolom CATATAN, jadi salinan ini disembunyikan. */
.pending-item .pi-note-m { display: none; }
.pending-item .pi-note-m .pi-note-ico { display: inline-flex; margin-left: 6px; }
@media (max-width: 768px) {
  .pending-item .pi-note-m { display: inline-flex; align-items: center; flex-shrink: 0; }
}
/* Catatan JO di kolom CATATAN (desktop): teks saja (tanpa ikon), ellipsis.
   DUA tingkat kekuatan supaya mata bisa memilah tanpa membaca teksnya:
   - umum   = kuning SOFT (tint tipis, tenang) -> catatan biasa
   - urgent = kuning TEGAS (sticky-note penuh) + teks hitam -> wajib dibaca
   Keduanya pakai teks hampir-hitam: kontras >= 9:1 di kedua latar (WCAG AA
   butuh 4.5:1), jadi tetap terbaca di layar produksi yang terang. */
.pending-item .pi-note-text {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 360px;
  font-size: 12px;
  line-height: 1.2;
  font-weight: 600;
  color: #1f2937;
  background: #fefce8;          /* soft: tint kuning sangat tipis */
  border: 1px solid #fde68a;
  border-radius: 4px;
  padding: 2px 7px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Catatan minta didahulukan (urgent): kuning TEGAS khas sticky-note + border
   amber lebih gelap, supaya beda dari catatan umum tanpa perlu dibaca. */
.pending-item .pi-note-text.pi-note--urg {
  color: #1f2937;
  background: #facc15;
  border-color: #d97706;
  font-weight: 700;
}
.pending-item .pi-note-ico {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 26px; height: 26px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(15, 23, 42, 0.06);
  color: var(--text-dim);
  cursor: pointer;
}
.pending-item .pi-note-ico svg { display: block; }
.pending-item .pi-note-ico.urg { background: #fef3c7; color: #92400e; }
.pending-item .pi-note-ico:active { background: var(--accent); color: #fff; }
[data-theme="dark"] .pending-item .pi-note-text {
  color: #1f2937;
  background: #d9d3a8;          /* soft di gelap: tetap tenang, tak menyilaukan */
  border-color: #a8a06f;
}
[data-theme="dark"] .pending-item .pi-note-text.pi-note--urg {
  color: #1f2937;
  background: #facc15;          /* urgent tetap tegas di gelap */
  border-color: #d97706;
}
/* (.pi-old-* dihapus: grup "Menunggu > 12 jam" kini via pagination server) */

.pending-empty {
  padding: 24px 14px;
  text-align: center;
  color: var(--text-dim);
  font-size: 14px;
}

/* Pagination */
.pending-pages {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 12px 14px;
  justify-content: center;
  background: #f5efe3;
  border-top: 1px solid var(--border);
}
/* Pager pending /scan: chevron 44px + posisi n/m (tanpa deretan angka) */
.pending-pages .page-nav { min-width:44px; min-height:44px; display:inline-flex; align-items:center; justify-content:center; padding:6px 12px; }
.pending-pages .page-pos { align-self:center; font-size:13px; font-weight:700; color:var(--text-dim); padding:0 10px; user-select:none; font-variant-numeric:tabular-nums; }
.page-dots {
  align-self: center;
  padding: 4px 3px;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-dim);
  user-select: none;
  letter-spacing: .04em;
}
/* Pager (daftar JO /cek, rekap, pending /scan, riwayat /scan, /admin/riwayat):
   satu bahasa bentuk. Warna SELALU var()/color-mix supaya ikut tema (biru publik
   + dark); dulu hover di-hardcode #f0e9da sehingga di dark perlu override
   terpisah. Angka pakai tabular-nums agar lebar tombol tidak bergeser saat
   halaman berubah (1 -> 2 -> 10), dan min-width menjaga baris tetap stabil.
   Gaya "smooth modern": radius 10px, transisi 0.16s (halus, bukan patah),
   hover = angkat halus (translateY -1px) + tint aksen tipis + shadow lembut,
   halaman aktif = aksen + glow lembut (menandai posisi tanpa perlu dibaca).
   Transisi murni visual (background/box-shadow/transform) — tidak menggeser
   layout, jadi header & baris tabel tetap sejajar. */
.page-btn {
  min-width: 36px;
  min-height: 34px;
  padding: 6px 11px;
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background .16s ease, border-color .16s ease, color .16s ease,
              box-shadow .16s ease, transform .16s ease;
}
.page-btn:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
  color: var(--accent);
  box-shadow: 0 2px 10px -2px color-mix(in srgb, var(--accent) 35%, transparent);
  transform: translateY(-1px);
}
.page-btn:active:not(:disabled) { transform: translateY(0); box-shadow: none; }
.page-btn:disabled { opacity: .38; cursor: default; }
.page-btn svg { width: 14px; height: 14px; display: block; }
.page-btn.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
  box-shadow: 0 2px 12px -2px color-mix(in srgb, var(--accent) 45%, transparent);
}
.page-btn.active:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
/* Gerak halus dimatikan bila user minta reduced-motion (aksesibilitas). */
@media (prefers-reduced-motion: reduce) {
  .page-btn { transition: background .12s ease, border-color .12s ease, color .12s ease; }
  .page-btn:hover:not(:disabled) { transform: none; }
}

.job-grid {
  display: grid;
  grid-template-columns: max-content 1fr max-content 1fr;
  background: #faf6ee;
}
.job-grid .jg-label {
  font-weight: 700;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .3px;
  color: var(--text-dim);
  background: #f0e9da;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  overflow-wrap: anywhere;
}
.job-grid .jg-value {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
  overflow-wrap: anywhere;
}

/* Scope .jo-info-body — dipakai /cek (cekjo.html) dan /scan (scanner.js).
   Datar tanpa bingkai: label kecil di atas nilai, jarak putih antar sel;
   kop penuh = JOB ID. */
.jo-info-body {
  background: transparent;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px 14px 14px;
}
.jo-info-body .job-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: transparent;
  gap: 10px 14px;
}
.jo-info-body .job-grid .jg-label {
  display: none;
}
.jo-info-body .job-grid .jg-value {
  display: flex;
  flex-direction: column;
  /* Nilai & badge menempel kiri. Tanpa ini, default flex = stretch sehingga
     badge status (Tipe/Status) melar memenuhi kolom jadi balok warna lebar. */
  align-items: flex-start;
  gap: 1px;
  background: transparent;
  padding: 0;
  border: none;
  border-radius: 0;
  min-width: 0;
  font-size: 13px;
}
.jo-info-body .job-grid .jg-value::before {
  content: attr(data-label);
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .35px;
  color: var(--text-dim);
}
.jo-info-body .job-grid .jg-value.jg-id {
  grid-column: 1 / -1;
  flex-direction: row;
  align-items: center;
  gap: 10px;
}
.jo-info-body .job-grid .jg-value.jg-id::before {
  content: "JOB ID";
  flex-shrink: 0;
}
.jo-info-body .job-grid .jg-value.jg-id > span:first-of-type {
  font-family: var(--mono);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: .2px;
}
.jo-info-body .job-grid .jg-value.jg-id .jo-copy-id {
  margin-left: 0;
}
.card__header .jo-info-title { font-weight:800; letter-spacing:.4px; }
/* Tanggal pembuatan di kanan header, berdampingan sebelum panah nav
   (satu kesatuan .jo-nav: tanggal + ‹ + n/m + ›). */
.card__header .jo-info-sub { font-weight:500; color:var(--text-dim); white-space:nowrap; }
.jo-nav .jo-info-sub { margin-right:2px; }
/* Header INFO JOB ORDER: judul + tanggal pembuatan (QR pindah ke baris
   identitas JOB ID supaya tampil besar dan mudah dipindai). */
.jo-info-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
/* QR di baris identitas JOB ID: 72px (dari 44px di kop) — cukup besar untuk
   dipindai HP, tetap sebaris dengan teks + tombol Salin. Satu sumber untuk
   /cek, /scan, /track. */
.jo-info-body .job-grid .jg-value.jg-id .jg-qr {
  width: 72px;
  height: 72px;
  margin-left: auto;
  flex-shrink: 0;
  border-radius: 8px;
  background: #fff;
}
.jo-copy-id { display:inline-flex; align-items:center; gap:5px; margin-left:6px; padding:2px 6px;
  border:1px solid var(--border); border-radius:6px; background:var(--surface); color:var(--text-dim);
  cursor:pointer; font:inherit; font-size:12px; line-height:1.4; vertical-align:middle; transition:all .15s; }
.jo-copy-id:hover { color:var(--accent); border-color:var(--accent); }
.jo-copy-id:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.jo-copy-id svg { flex-shrink:0; }
/* nilai + tombol salin sebaris (sel .jg-value flex column) */
.jg-row { display:inline-flex; align-items:center; gap:7px; min-width:0; }
/* tombol salin icon-only di field INFO (mis. NO. SO) */
.jg-copy { display:inline-flex; align-items:center; justify-content:center; flex-shrink:0; padding:1px;
  border:none; border-radius:4px; background:transparent; color:var(--text-dim);
  cursor:pointer; line-height:0; vertical-align:middle; transition:all .15s; }
.jg-copy:hover { color:var(--accent); background:color-mix(in srgb, var(--accent) 10%, transparent); }
.jg-copy:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
.jg-copy svg { flex-shrink:0; }
/* Tombol bagikan di judul INFO JO (dipakai /cek, /scan, /track). */
.jo-share { display:inline-flex; align-items:center; justify-content:center; flex-shrink:0; padding:4px;
  border:none; border-radius:6px; background:transparent; color:var(--text-dim);
  cursor:pointer; line-height:0; text-decoration:none; transition:all .15s; }
.jo-share:hover { color:var(--accent); background:color-mix(in srgb, var(--accent) 10%, transparent); }
.jo-share:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
.jo-share svg { flex-shrink:0; }
/* Nav JO sebelum/sesudah di header detail (kanan tanggal): panah rapat +
   posisi n/m. Tombol bulat 30px border aksen (beda dari .page-btn pager
   yang kotak). Satu sumber untuk /cek + /scan (joNavHtml di ui-common.js). */
.jo-nav { display:inline-flex; align-items:center; gap:6px; margin-left:auto; flex-shrink:0; }
/* Tombol bulat bertema: border aksen + teks aksen; hover = isi aksen.
   Ujung list = redup + tak bisa diklik (disabled ikut render joNavHtml). */
.jo-nav-btn { display:inline-flex; align-items:center; justify-content:center;
  width:30px; height:30px; padding:0; border:1.5px solid var(--accent);
  border-radius:50%; background:transparent; color:var(--accent);
  cursor:pointer; line-height:0; transition:all .15s; }
.jo-nav-btn:hover:not(:disabled) { background:var(--accent); color:#fff; }
.jo-nav-btn:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
.jo-nav-btn:disabled { border-color:var(--border); color:var(--text-dim); opacity:.45; cursor:default; }
.jo-nav-btn svg { width:14px; height:14px; display:block; }
.jo-nav-pos { font-size:11.5px; font-weight:700; color:var(--text-dim);
  font-variant-numeric:tabular-nums; letter-spacing:.3px; user-select:none;
  min-width:38px; text-align:center; }
.jo-info-body .job-grid .jg-value.jg-cols-2 { grid-column: span 2; }
.jo-info-body .job-grid .jg-value.jg-cols-4 { grid-column: 1 / -1; }
/* Hierarki detil JO — tiga tingkat, bukan 7 sel setara:
   identitas (jg-id) > kunci cari (jg-key) > metadata (jg-meta) */
.jo-info-body .job-grid .jg-value.jg-key {
  font-size: 15px;
  font-weight: 700;
}
.jo-info-body .job-grid .jg-value.jg-meta { font-size: 12.5px; }
.jo-info-body .job-grid .jg-value.jg-meta::before {
  font-size: 9px;
  letter-spacing: .3px;
}
/* Badge status di detail = segaris dengan tag tipe (11px/2px 8px): status
   sudah menonjol lewat warna latar sendiri, tak perlu lebih besar dari tipe. */
.jo-info-body .job-grid .jg-value .badge { font-size: 11px; padding: 2px 8px; }
/* Garis tipis ANTAR KOLOM — memisahkan medan data, bukan bingkai:
   tanpa garis atas/bawah/keliling. Sel yang MEMULAI baris tanpa garis.
   Pemula baris grid 4 kolom /cek & /scan: JOB ID | SO(+2) | DESIGNER | DURASI.
   Perlu ikut diubah bila urutan/span field berubah; di ≤900px aturan 2 kolom
   yang berlaku. */
.jo-info-body .job-grid { column-gap: 0; row-gap: 10px; }
.jo-info-body .job-grid .jg-value {
  padding-left: 16px;
  border-left: 1px solid var(--border);
}
.jo-info-body .job-grid .jg-value.jg-id,
.jo-info-body .job-grid .jg-value.jg-f-so,
.jo-info-body .job-grid .jg-value.jg-f-designer,
.jo-info-body .job-grid .jg-value.jg-f-durasi,
.jo-info-body .job-grid .jg-value.jg-f-catatan {
  border-left: none;
  padding-left: 0;
}
/* 2 kolom (≤900px): JOB ID sendiri di baris 1, SO/Customer span penuh, lalu
   berpasang DESIG|TIPE dan QTY|STATUS → yang bergaris tetap sel kolom kedua
   (sama seperti di 4 kolom), jadi garis tidak berpindah kolom antar lebar */
@media (max-width: 900px) {
  .jo-info-body .job-grid .jg-value { border-left: none; padding-left: 0; }
  .jo-info-body .job-grid .jg-value.jg-f-tipe,
  .jo-info-body .job-grid .jg-value.jg-f-status {
    border-left: 1px solid var(--border);
    padding-left: 16px;
  }
}
/* 1 kolom (≤560px): tak ada kolom → tak ada garis */
@media (max-width: 560px) {
  .jo-info-body .job-grid .jg-value,
  .jo-info-body .job-grid .jg-value.jg-f-tipe,
  .jo-info-body .job-grid .jg-value.jg-f-status {
    border-left: none;
    padding-left: 0;
  }
}
.jo-info-body .table-wrap.jo-inner {
  margin: 0;
  border: none;
  border-radius: 0;
  /* Item banyak (mis. J2607-31-0040, 89 baris) scroll di area sendiri:
     catatan/stepper/tombol aksi & riwayat di bawah tak terkubur. Self-gating:
     JO kecil di bawah 55vh = tanpa scrollbar, tampil persis seperti biasa. */
  max-height: 55vh;
  overflow: auto;
}
/* Sticky: judul kolom tetap terbaca saat scroll puluhan baris. */
.jo-info-body .table-wrap.jo-inner .item-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 6px 8px;
  font-size: 11px;
}
.jo-info-body .table-wrap.jo-inner .item-table tbody td { padding: 6px 8px; font-size: 13px; }
.jo-info-body .table-wrap.jo-inner .item-table {
  background: transparent;
  border-collapse: collapse;
}
/* Kerapatan kolom tabel item INFO JO: QTY & UKURAN rapat KIRI (fit konten),
   NAMA FILE paling lebar (menyerap sisa), BAHAN/FINISHING/VOLUME rapat KANAN
   (fit konten). `width:1%` + `white-space:nowrap` = kolom menyusut ke lebar isi
   (trik tabel auto-layout); kolom .ci-nama `width:100%` menyerap sisa ruang.
   SEMUA aturan di-scope ke sel .ci-* saja, supaya tabel item lain (mis. admin
   koreksi) yang juga memakai .jo-info-body .item-table tak ikut berubah. */
.jo-info-body .table-wrap.jo-inner .item-table .ci-qty,
.jo-info-body .table-wrap.jo-inner .item-table .ci-ukuran,
.jo-info-body .table-wrap.jo-inner .item-table .ci-menit,
.jo-info-body .table-wrap.jo-inner .item-table .ci-bahan,
.jo-info-body .table-wrap.jo-inner .item-table .ci-finishing,
.jo-info-body .table-wrap.jo-inner .item-table .ci-vol {
  width: 1%;
  white-space: nowrap;
}
.jo-info-body .table-wrap.jo-inner .item-table .ci-nama {
  width: 100%;
  white-space: normal;   /* nama file boleh wrap (kolom terlebar) */
}
/* Judul header sejajar dgn isinya (default thead th = center). */
.jo-info-body .table-wrap.jo-inner .item-table .ci-qty,
.jo-info-body .table-wrap.jo-inner .item-table .ci-ukuran,
.jo-info-body .table-wrap.jo-inner .item-table .ci-nama { text-align: left; }
.jo-info-body .table-wrap.jo-inner .item-table .ci-bahan,
.jo-info-body .table-wrap.jo-inner .item-table .ci-finishing,
.jo-info-body .table-wrap.jo-inner .item-table .ci-vol { text-align: right; }
/* Baris total: sel pengisi (colspan) tak ikut aturan kolom. */
.jo-info-body .table-wrap.jo-inner .item-table .ci-gap { width: auto; }
/* Header tabel item: tint tipis aksen tema (ikut biru publik / teal admin,
   ikut dark). Memisahkan judul kolom dari badan tabel tanpa jadi bar gelap
   penuh. Resep sama dengan flat.css supaya /cek, /scan, dan /admin seragam. */
.item-table thead th {
  background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  color: var(--text);
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border));
}
.jo-info-body .status-box.jo-inner {
  margin: 0;
  border: none;
  border-radius: 0;
  padding: 0;
  text-align: left;
  background: transparent;
}
/* Catatan JO: kuning sticky-note (beda dari teks polos lain).
   Alasan batal (cancel-reason) tidak ikut: itu domain danger. */
.jo-info-body .status-box.note-box {
  background: #fef3c7;
  border: 1px solid #fcd34d;
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 13px;
}
.jo-info-body .status-box.note-box .label { color: #92400e; }
[data-theme="dark"] .jo-info-body .status-box.note-box { background: #422006; border-color: #92610e; }
[data-theme="dark"] .jo-info-body .status-box.note-box .label { color: #fcd34d; }
.jo-info-body .status-box + .status-box.jo-inner,
.jo-info-body .status-box.cancel-reason { margin-top: 0; }

.table-wrap {
  overflow-x: auto;
  margin-top: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.rj-table { width: 100%; border-collapse: collapse; }
.rj-table th, .rj-table td { padding: 10px 12px; border-bottom: 1px solid var(--border); font-size: .85rem; text-align: left; }
.rj-table th { color: rgba(255,255,255,.85); font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 600; }
.rj-table td.num, .rj-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.queue-table th { text-align: center; }
.rj-table tr:hover td { background: var(--bg); }

/* Baris SO drill rekap designer/customer: chevron penanda bisa dibuka */
.drill-so-toggle { margin-left: 6px; vertical-align: -2px; color: var(--text-dim); transition: transform .15s, color .12s; }
.drill-so-open .drill-so-toggle { transform: rotate(90deg); color: var(--accent); }

/* Daftar JO ID di bawah baris SO (drill rekap designer/customer DAN drill
   bahan /admin/rekap): sub-panel bertint aksen + chip JO yang jelas bisa diklik */
.jo-list-cell {
  padding: 10px 14px 12px;
  background: color-mix(in srgb, var(--accent) 6%, var(--bg));
}
/* halaman rekap punya aturan `.rk-page .jo-detail-row > td` (0,2,1) yang
   menang atas `.jo-list-cell`; ditulis ulang agar tint panel tetap sama */
.rk-page .jo-detail-row > td.jo-list-cell {
  padding: 10px 14px 12px;
  background: color-mix(in srgb, var(--accent) 6%, var(--bg));
}
.jo-list-cell .badge-group-label { margin-bottom: 8px; }
.jo-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.jo-chip {
  display: inline-flex; align-items: center;
  padding: 4px 11px; border-radius: 999px;
  background: var(--surface);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border));
  color: var(--text); font-size: .76rem; font-weight: 700;
  font-variant-numeric: tabular-nums; text-decoration: none;
  transition: border-color .12s, background .12s, color .12s, transform .1s;
}
.jo-chip:hover {
  border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  transform: translateY(-1px);
}
.jo-chip:active { transform: translateY(0); }
.designer-link { color: var(--accent); text-decoration: none; cursor: pointer; font-weight: 700; }
.designer-link:hover { text-decoration: underline; }
.bahan-badge { display: inline-block; padding: 2px 8px; margin: 2px 3px 2px 0; border-radius: 12px; background: var(--bg); border: 1px solid var(--border); font-size: .72rem; color: var(--text-dim); }
.customer-badge { display: inline-block; padding: 2px 8px; margin: 2px 3px 2px 0; border-radius: 12px; background: var(--accent-light); border: 1px solid var(--accent); font-size: .72rem; color: var(--accent); font-weight: 600; }
[data-theme="dark"] .customer-badge { background: var(--accent-dark); border-color: var(--accent); color: var(--accent); }

.chip {
  display: inline-block;
  margin: 2px 4px 2px 0;
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--bg);
  border: 1px solid var(--border);
  font-size: .78rem;
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
thead th {
  background: var(--accent-dark);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .3px;
  text-transform: uppercase;
  padding: 10px 8px;
  text-align: center;
  white-space: nowrap;
}
tbody td {
  padding: 10px 8px;
  border-bottom: 1px solid #ece3d2;
  text-align: center;
  vertical-align: middle;
}
tbody tr { transition: background .1s; }
tbody tr:hover { background: #f5efe3; }
tbody tr:nth-child(even) { background: #faf6ee; }
tbody tr:nth-child(even):hover { background: #f0e9da; }
td.text-left { text-align: left; }

.history-row {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 12px;
  padding: 12px 14px;
  position: relative;
}
.history-row.last {
  background: #f0fdf4;
  font-weight: 600;
}
.history-track {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
  width: 12px;
  align-self: stretch;
}
.history-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  margin-top: 6px;
  box-shadow: 0 0 0 3px var(--bg, #fff);
  z-index: 1;
}
.history-line {
  flex: 1;
  width: 0;
  border-left: 2px dashed var(--text-dim);
  opacity: 0.4;
  margin-top: 2px;
  min-height: 18px;
}
.history-row.is-bottom .history-line {
  display: none;
}
.history-content { flex: 1; min-width: 0; text-align: right; }
.history-checkpoint {
  font-weight: 700;
  font-size: 14px;
  color: var(--text);
}
.history-status {
  font-size: 13px;
  color: var(--text-dim);
  margin-top: 2px;
}
.history-status .badge {
  display: inline-block;
  line-height: 1;
  padding: 4px 10px;
}
.history-time {
  font-size: 12px;
  color: var(--text-dim);
  white-space: nowrap;
  flex: 1;
  min-width: 150px;
  text-align: left;
  margin-top: 2px;
}
.history-operator {
  font-size: 12px;
  color: var(--text-dim);
}

.status-box {
  margin-top: 12px;
  padding: 12px 14px;
  border-radius: 8px;
  background: #f5efe3;
  border: 1px solid var(--border);
  font-size: 14px;
  text-align: center;
}
.status-box .label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--text-dim);
  margin-bottom: 4px;
}
.status-box .value {
  font-size: 16px;
  font-weight: 800;
  color: var(--accent);
}

/* Visual RIWAYAT/posisi tahap JO. Sengaja kecil + redup supaya TIDAK menyaingi
   fokus utama (item pekerjaan & tombol aksi). Warna tahap tetap jadi penanda,
   tapi bobotnya diturunkan (lingkaran lebih kecil, garis tipis, label dim). */
.stepper {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  /* sekat tipis: stepper duduk tepat di bawah card (yg berakhir di Catatan),
     tanpa garis ia terbaca menyatu dgn isi card */
  border-top: 1px solid var(--border);
  margin: 14px 0 14px;
  padding: 12px 8px 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.stepper__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  flex: 1;
  min-width: 60px;
}
.stepper__item:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 9px;
  left: calc(50% + 11px);
  width: calc(100% - 22px);
  height: 1px;
  /* rel proses harus terbaca: --border terlalu dekat dgn --surface
     (kontras ~1.1:1) shg tampak hilang. Pakai text-dim campur, tapi lebih tipis
     & redup dari sebelumnya (kecil/sedang, bukan aksen). */
  background: color-mix(in srgb, var(--text-dim) 45%, transparent);
  z-index: 0;
  transition: background .25s ease;
}
/* jalur progres: segmen setelah step selesai ikut warna tahapnya (redup) */
.stepper__item--done:not(:last-child)::after {
  background: color-mix(in srgb, var(--step, var(--success)) 45%, var(--border));
}
.stepper__circle {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--step, var(--border)) 45%, var(--border));
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: color-mix(in srgb, var(--step, var(--text-dim)) 60%, var(--text-dim));
  position: relative;
  z-index: 1;
  transition: background .25s ease, border-color .25s ease, color .25s ease;
}
.stepper__circle svg { width: 11px !important; height: 11px !important; display: block; }
/* selesai: warna tahap, tapi dilembutkan (bukan blok warna penuh) */
.stepper__item--done .stepper__circle {
  background: color-mix(in srgb, var(--step, var(--success)) 85%, var(--surface));
  border-color: color-mix(in srgb, var(--step, var(--success)) 85%, var(--surface));
  color: #fff;
}
/* aktif: cincin tipis, tanpa halo besar yang menarik mata */
.stepper__item--current .stepper__circle {
  background: color-mix(in srgb, var(--step, var(--accent)) 12%, var(--bg));
  border-color: color-mix(in srgb, var(--step, var(--accent)) 80%, var(--border));
  color: color-mix(in srgb, var(--step, var(--accent)) 85%, var(--text));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--step, var(--accent)) 12%, transparent);
}
/* satu-satunya motion: denyut SEKALI pada step aktif saat detail dirender
   (tujuan UX: tunjuk checkpoint berjalan). Bukan loop abadi (R-19);
   mati untuk reduced-motion. Amplitudo kecil supaya tidak mengganggu. */
@keyframes stepPulse {
  0%   { box-shadow: 0 0 0 2px color-mix(in srgb, var(--step, var(--accent)) 18%, transparent); }
  70%  { box-shadow: 0 0 0 5px transparent; }
  100% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--step, var(--accent)) 12%, transparent); }
}
.stepper__item--current .stepper__circle { animation: stepPulse .9s ease-out 1; }
@media (prefers-reduced-motion: reduce) {
  .stepper__item--current .stepper__circle { animation: none; }
}
.stepper__label {
  margin-top: 5px;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: .3px;
  text-transform: uppercase;
  text-align: center;
  /* Semua label pakai --text-dim (kontras AA ~5.4:1 di terang, ~5.9:1 di gelap).
     Warna tahap HANYA di lingkaran, bukan di teks: warna step terang (mis.
     PRODUKSI #0ea5e9) gagal AA bila dipakai sebagai teks kecil di latar terang. */
  color: var(--text-dim);
  white-space: nowrap;
  max-width: 72px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stepper__item--done .stepper__label {
  color: color-mix(in srgb, var(--text) 55%, var(--text-dim));
}
.stepper__item--current .stepper__label {
  font-weight: 700;
  color: var(--text);
}
/* Hover tooltip stepper, operator + catatan dari history checkpoint */
.stepper__item { cursor: help; }
.step-tip {
  position: fixed;
  z-index: 9999;
  display: none;
  max-width: 260px;
  padding: 8px 10px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  font-size: 12px;
  line-height: 1.45;
  pointer-events: none;
}
.step-tip__title { font-weight: 700; margin-bottom: 4px; color: var(--accent); }
.step-tip__op { font-weight: 600; white-space: normal; word-break: break-word; }
.step-tip__note { color: var(--text-dim); white-space: normal; word-break: break-word; margin-top: 2px; }
.edit-row {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.edit-row input {
  width: 140px;
  padding: 4px 8px;
  margin: 0;
  font-size: 14px;
}
.edit-row .btn--xs { vertical-align: middle; }

/* Nilai yang bisa diedit: tanpa ikon, double-klik untuk ubah (clean/minimal) */
.editable {
  cursor: pointer;
  user-select: none;
  border-bottom: 1px dotted transparent;
  border-radius: 3px;
  padding: 0 2px;
  transition: background .12s ease, border-color .12s ease;
}
.editable:hover {
  border-bottom-color: var(--border);
  background: rgba(15, 23, 42, 0.04);
}
[data-theme="dark"] .editable:hover { background: rgba(255, 255, 255, 0.05); }

/* Edit kompak 1:1 untuk kolom sempit (qty / ukuran) */
.edit-row--num { gap: 2px; }
.edit-row--num input {
  width: 4.5ch;
  min-width: 42px;
  max-width: 52px;
  padding: 2px 3px;
  margin: 0;
  font-size: 13px;
  text-align: center;
}
.btn-sq {
  width: 22px;
  height: 22px;
  padding: 0;
  margin-top: 0;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* Posisi: KIRI-BAWAH layar (fixed). Tombol kembali-ke-atas ada di kanan-bawah
   supaya keduanya tak bertumpuk. */
.msg {
  position: fixed;
  left: 18px;
  bottom: 18px;
  right: auto;
  top: auto;
  transform: none;
  z-index: 9999;
  width: auto;
  max-width: min(90vw, 420px);
  padding: 12px 18px;
  border-radius: 10px;
  font-size: 14px;
  display: none;
  font-weight: 600;
  text-align: left;
  box-shadow: 0 8px 30px rgba(0,0,0,.28);
  border: 1px solid transparent;
  animation: toast-in .25s ease-out;
}
.msg--ok  { background: #16a34a; color: #111; display: block; }
.msg--err { background: #dc2626; color: #fff; display: block; }
.msg.fade-out { animation: toast-out .3s ease-in forwards; }

@keyframes toast-in  { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
@keyframes toast-out { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(12px); } }

.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2.5px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .6s linear infinite;
  vertical-align: middle;
  margin-right: 6px;
}
@keyframes spin { to { transform: rotate(360deg); } }

#reader {
  width: 100%;
  margin-top: 12px;
  border-radius: var(--radius);
  overflow: hidden;
}
#reader.reader--square {
  max-width: 360px;
  aspect-ratio: 1 / 1;
  margin-left: auto;
  margin-right: auto;
  overflow: hidden;
}
#reader.reader--square video {
  width: 100% !important;
  height: 100% !important;
  object-fit: cover;
  object-position: center;
}
#reader.reader--square > div {
  width: 100% !important;
  height: 100% !important;
}

@media (max-width: 600px) {
  .filter-bar { flex-direction: column; align-items: stretch; gap: 8px; padding: 10px 12px; }
  .filter-label { border-right: none; border-bottom: 1px solid var(--border); padding-right: 0; margin-right: 0; padding-bottom: 8px; white-space: normal; }
  /* label ikon-saja tidak punya teks: garis bawah akan menggantung sendirian */
  .filter-label--icon { border-bottom: none; padding-bottom: 0; }
  .filter-btns { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; padding-bottom: 2px; min-width: 0; max-width: 100%; }
  .filter-btns::-webkit-scrollbar { display: none; }
  .filter-date { flex: 1; min-width: 0; max-width: 100%; }
  .filter-bar select.filter-date { width: 100%; }
  .filter-bar .filter-select { width: 100%; }
  .search-row { flex-direction: column; align-items: stretch; gap: 8px; }
  .search-row .btn--sm { width: 100%; }
}
@media (max-width: 900px) {
  .jo-info-body .job-grid { grid-template-columns: repeat(2, 1fr); }
}
/* HP sempit: sel INFO JOB ORDER jadi 1 kolom penuh (spesifisitas scoped,
   aturan global .job-grid di bawah kalah) */
@media (max-width: 560px) {
  .jo-info-body .job-grid { grid-template-columns: 1fr; }
  /* span di grid 1 kolom bikin kolom implisit → reset */
  .jo-info-body .job-grid .jg-value.jg-cols-2,
  .jo-info-body .job-grid .jg-value.jg-cols-4 { grid-column: auto; }
  .jo-info-body .job-grid .jg-value.jg-id { flex-wrap: wrap; gap: 4px 10px; }
  .jo-info-body .job-grid .jg-value.jg-id .jo-copy-id { margin-left: 0; }
}
@media (max-width: 600px) {
  body { padding: 10px; }
  .container { padding: 16px 14px; }
  /* job-grid polos (admin_batal): label di atas nilai, satu kolom */
  .job-grid { grid-template-columns: 1fr; }
  .job-grid .jg-label {
    border-right: none;
    border-bottom: none;
    padding: 6px 12px;
    background: transparent;
  }
  .job-grid .jg-value {
    padding: 6px 12px 10px;
    border-bottom: 1px solid var(--border);
  }
  .jo-info-body .job-grid .jg-label { display: none; }
  .jo-info-body .job-grid .jg-value { padding: 0; }
  .jo-info-body .job-grid { gap: 10px 16px; }
  .jo-info-body .job-grid .jg-value::before { font-size: 10px; }
  thead th, tbody td { padding: 8px 6px; font-size: 12px; }
}

/* ============================================================
   FULL LAYAR DI MOBILE (<=900px) — halaman ber-sidebar
   ============================================================
   Halaman /, /cek, /buat, /admin* memakai sidebar (kelas body `adm-shell`).
   Di HP, celah dari `body { padding: 10px }` (mobile) + `padding-left:16px;
   padding-top:72px` (media 900px) menyisakan bingkai kosong di sekeliling
   konten -> terlihat "terkurung" & menyia-nyiakan layar sempit. /scan tidak
   kena karena `body.scan-page { padding: 0 }`.

   Breakpoint WAJIB 900px (bukan 600px): aturan drawer lama memakai
   `@media (max-width:900px)`, jadi di 601-900px pun konten harus full layar.

   Ruang untuk BURGER (fixed 44px di top:12px/left:12px) disediakan padding
   ATAS pada `.container` (56px) supaya konten pertama tidak tertutup tombol.

   CATATAN: hanya di <=900px. Desktop TIDAK berubah (tetap ber-celah & center).
   Sidebar di mobile sudah DRAWER (translateX(-100%)) -> overlay, bukan
   mendorong konten; `body.adm-nav-open` tetap benar. */
@media (max-width: 900px) {
  body.adm-shell { padding: 0; }
  body.adm-shell .container {
    padding: 56px 14px 40px;
    max-width: 100%;
    border-radius: 0;
  }
  /* Dashboard (/) memakai .dash (bukan .container): beri ruang atas yang sama
     untuk burger, kalau tidak judulnya tertutup tombol. */
  body.adm-shell .dash { padding-top: 56px; }
  /* Bar atas (page-head) ikut menempel: padding dalam kecil supaya judul tidak
     menempel ke tepi layar. Kiri 60px: blok judul mulai di x≈14 (padding
     kontainer) sehingga ~40px pertamanya tertutup burger (44px di left:12px).
     Geser blok judul saja (bukan konten) supaya lebar tabel/kartu tetap penuh.
     Aturan yang sama untuk .dash-header (/). */
  body.adm-shell .page-head { padding: 0 2px 0 60px; }
  body.adm-shell .dash-header { padding-left: 60px; }
  /* Bar "kembali" mode fokus /cek?jo= (pengganti page-head yang disembunyikan
     di mode itu): sama-sama butuh lolos dari burger. */
  body.adm-shell .cek-focus-bar { padding-left: 60px; }
  /* Target scrollIntoView di /cek (hasil cari, detail JO, bar fokus):
     block:start menempelkan elemen tepat di tepi atas viewport — tepat di
     bawah burger fixed. Sisakan 70px supaya tidak tertutup tombol. */
  body.adm-shell #result,
  body.adm-shell #cekDetail { scroll-margin-top: 70px; }
}

@media (max-width: 700px) {
  .table-wrap {
    overflow-x:auto;
    -webkit-overflow-scrolling:touch;
    border:none;
    margin-top:10px;
  }
  .item-table, .rk-table {
    border-collapse:collapse;
  }
  .item-table thead th:first-child,
  .rk-table thead th:first-child {
    position:sticky;
    left:0;
    z-index:2;
    /* Solid (bukan tint transparan): kolom sticky harus menutup isi yang
       tergeser. Resep tint sama, tapi di-flatten ke surface. */
    background: color-mix(in srgb, var(--accent) 14%, var(--surface));
    /* Garis kanan: batas kolom beku, supaya isi yang lewat di belakangnya
       tidak terlihat seperti teks bocor/terpotong. */
    border-right:1px solid color-mix(in srgb, var(--accent) 30%, var(--border));
  }
  /* Header kolom pertama INFO JO harus di ATAS header kolom lain (semua
     thead th sticky top:0). Tanpa z lebih tinggi, header kolom kedua+ (DOM
     belakangan, z sama) menutupi judul kolom pertama saat scroll horizontal
     -> judul "QTY" hilang. Selector dibuat se-spesifik rule z:1-nya agar menang. */
  .jo-info-body .table-wrap.jo-inner .item-table thead th:first-child { z-index:3; }
  .item-table tbody td:first-child,
  .rk-table tbody td:first-child {
    position:sticky;
    left:0;
    z-index:2;
    background:var(--surface);
    border-right:1px solid color-mix(in srgb, var(--border) 70%, transparent);
  }
  [data-theme="dark"] .item-table thead th:first-child,
  [data-theme="dark"] .rk-table thead th:first-child {
    background:#0d1117;
  }
  [data-theme="dark"] .item-table tbody td:first-child,
  [data-theme="dark"] .rk-table tbody td:first-child {
    background:#1a1d27;
  }
  .item-table thead th,
  .rk-table thead th { white-space:nowrap; padding:8px 10px; font-size:11px; }
  .item-table tbody td,
  .rk-table tbody td { white-space:nowrap; padding:7px 10px; font-size:12px; }
  /* INFO JO di HP: kolom NAMA FILE fit-to-content (selebar nama terpanjang)
     & TIDAK wrap — tabel digeser horizontal (.table-wrap overflow-x:auto),
     jadi nama panjang tetap terbaca utuh di satu baris. */
  .jo-info-body .table-wrap.jo-inner .item-table .ci-nama {
    width: auto;
    white-space: nowrap;
  }
}

.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
  flex-wrap: nowrap;
}
.page-head h2 { margin-bottom: 4px; }
.page-head .subtitle { margin-bottom: 0; }

.head-toggles {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  margin-left: auto;
}
/* Link kembali ke Dashboard /admin — konsisten dgn .theme-btn/.nav-link */
.dash-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 40px;
  padding: 0 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--shadow);
  transition: border-color .12s ease, color .12s ease;
}
.dash-link:hover { border-color: var(--accent); color: var(--accent); }
.dash-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dash-link svg { width: 16px; height: 16px; flex-shrink: 0; display: block; }
@media (max-width: 480px) { .dash-link .dl-label { display: none; } .dash-link { padding: 0 10px; } }
.page-head h2,
.page-head h1 { flex-shrink:1; min-width:0; }

.theme-btn {
  display:inline-flex; align-items:center; justify-content:center;
  width:38px; height:38px; flex-shrink:0;
  border:1px solid var(--border); border-radius:10px;
  background:var(--surface); color:var(--text); cursor:pointer;
  transition:color .15s ease, border-color .15s ease, background .15s ease;
  -webkit-tap-highlight-color: transparent;
}
.theme-btn:hover { border-color:var(--accent); color:var(--accent); }
a.theme-btn { text-decoration:none; }
.theme-btn:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.theme-btn svg { width:20px; height:20px; display:block; }
.theme-btn[aria-pressed="true"] { color:var(--warning); background:var(--bg); }
@media (pointer:coarse) { .theme-btn { width:44px; height:44px; } }

/* Tombol mute suara scan — tombol ikon, konsisten tema (var border/surface) */
.mute-btn {
  display:inline-flex; align-items:center; justify-content:center;
  width:38px; height:38px; flex-shrink:0;
  border:1px solid var(--border); border-radius:10px;
  background:var(--surface); color:var(--text); cursor:pointer;
  transition:color .15s ease, border-color .15s ease, background .15s ease;
  -webkit-tap-highlight-color: transparent;
}
.mute-btn:hover { border-color:var(--accent); color:var(--accent); }
.mute-btn:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.mute-btn svg { width:20px; height:20px; display:block; }
.mute-btn[aria-pressed="true"] { color:var(--danger); background:var(--bg); }
@media (pointer:coarse) { .mute-btn { width:44px; height:44px; } }

[data-theme="dark"] {
  --bg:       #101815;
  --surface:  #18211d;
  --border:   #27332d;
  --hover:    #1e2130;
  --text:     #e4e7ec;
  --text-dim: #9aa79e;
  --accent:   #2dd4a8;
  --accent-hover: #5eeab8;
  --success:  #22c55e;
  --danger:   #ef4444;
  --warning:  #f59e0b;
  --info:     #06b6d4;
  --shadow:   0 1px 3px rgba(0,0,0,.3);
  --shadow-md: 0 4px 12px rgba(0,0,0,.4);
}
[data-theme="dark"] body { background: var(--bg); }
[data-theme="dark"] .container { border-color: var(--border); }

/* Badge dark */
[data-theme="dark"] .badge--menunggu        { background: #422006; color: #fde047; }
[data-theme="dark"] .badge--sudah-tf         { background: #0c4a6e; color: #7dd3fc; }
[data-theme="dark"] .badge--proses-produksi { background: #431407; color: #fdba74; }
[data-theme="dark"] .badge--proses-qc       { background: #172554; color: #93c5fd; }
[data-theme="dark"] .badge--siap-diambil    { background: #064e3b; color: #6ee7b7; }
[data-theme="dark"] .badge--sudah-diambil   { background: #2e1065; color: #c4b5fd; }
[data-theme="dark"] .badge--dibatalkan      { background: #450a0a; color: #fca5a5; }
[data-theme="dark"] .badge--siap-produksi   { background: #172554; color: #93c5fd; }
[data-theme="dark"] .badge--selesai         { background: #052e16; color: #86efac; }
[data-theme="dark"] .badge--default         { background: #1e293b; color: #94a3b8; }

/* Input dark */
[data-theme="dark"] input[type="text"],
[data-theme="dark"] input[type="password"],
[data-theme="dark"] textarea {
  background: #232733;
  color: var(--text);
  border-color: #3a3f4c;
}


/* Button outline dark */
[data-theme="dark"] .btn--outline { border-color: #3a3f4c; color: var(--text-dim); }
[data-theme="dark"] .btn--outline:hover { background: #232733; }

/* Card dark */
[data-theme="dark"] .card { border-color: var(--border); }
[data-theme="dark"] .card__header { background: #1e2130; border-color: var(--border); }

/* Flat compact dark: INFO JOB ORDER */
[data-theme="dark"] .card#cekInfoCard,
[data-theme="dark"] .card.jo-info-card { background: var(--surface); }
[data-theme="dark"] .card#cekInfoCard .card__header,
[data-theme="dark"] .card.jo-info-card .card__header {
  background: transparent;
  border-bottom-color: color-mix(in srgb, var(--border) 40%, transparent);
}

/* Pending dark */
[data-theme="dark"] .pending-item { border-color: #232733; }
[data-theme="dark"] .pending-head { background: #1e2130; border-color: #232733; color: var(--text-dim); }
[data-theme="dark"] .pending-item:hover { background: #1e2130; }
[data-theme="dark"] .pending-item:active { background: #232733; }
[data-theme="dark"] .pending-item.active { background: color-mix(in srgb, var(--accent) 22%, #1b1e29); border-left: 3px solid var(--accent); }
[data-theme="dark"] .pending-item.urgent { background: #2a2006; border-left-color: var(--danger); }
[data-theme="dark"] .pending-item.active.urgent { background: color-mix(in srgb, var(--accent) 22%, #1b1e29); }
[data-theme="dark"] .pending-item.stale { border-left-color: var(--warning); background: #2a2006; }
[data-theme="dark"] .pending-pages { background: #1a1d27; border-color: var(--border); }
/* .page-btn tidak butuh override dark: semua warnanya var()/color-mix sehingga
   ikut tema otomatis. Override lama (#232733) menimpa var() dan mematikan
   border aksen saat hover. */

/* Job grid dark */
[data-theme="dark"] .job-grid { background: #1a1d27; }
[data-theme="dark"] .job-grid .jg-label { background: #1e2130; color: var(--text-dim); }

/* /cek: sekat info */
[data-theme="dark"] .jo-info-body .job-grid { background: transparent; }
[data-theme="dark"] .jo-info-body .job-grid .jg-value { background: transparent; }
[data-theme="dark"] .jo-info-body .table-wrap.jo-inner .item-table { background: transparent; }
[data-theme="dark"] .jo-info-body .status-box.jo-inner { background: transparent; }

/* Table dark */
[data-theme="dark"] thead th { background: #0d1117; }
[data-theme="dark"] tbody td { border-color: #232733; }
[data-theme="dark"] tbody tr:hover { background: #1e2130; }
[data-theme="dark"] tbody tr:nth-child(even) { background: #1a1d27; }
[data-theme="dark"] tbody tr:nth-child(even):hover { background: #1e2130; }

/* History dark */
[data-theme="dark"] .history-row { border-color: #232733; }
[data-theme="dark"] .history-row.last { background: #052e16; }

/* Status box dark */
[data-theme="dark"] .status-box { background: #1e2130; border-color: var(--border); }

/* Message dark */
[data-theme="dark"] .msg--ok  { background: #15803d; color: #fff; }   /* #111 di hijau gelap = 3,8:1 */
[data-theme="dark"] .msg--err { background: #b91c1c; color: #fff; }

/* Spinner dark */
[data-theme="dark"] .spinner { border-color: #3a3f4c; border-top-color: var(--accent); }

/* Table wrap dark */
[data-theme="dark"] .table-wrap { border-color: var(--border); }

/* chevron collapse di /cek: gaya di template (butuh currentColor + rotasi) */

.result-nav { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 7px 12px; margin-bottom: 10px; font-size: 12px; color: var(--text-dim); background: var(--hover); border: 1px solid var(--border); border-radius: var(--radius); }
/* Tombol prev/next hasil pencarian memakai .page-btn (pager pending, satu
   halaman satu bahasa tombol). Di sini hanya ukuran + posisi yang diatur. */
.result-nav .page-btn { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
.result-nav .result-nav-pos { font-variant-numeric: tabular-nums; letter-spacing: .3px; font-size: 13px; font-weight: 700; color: var(--text-dim); user-select: none; }

.modal-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(15,23,42,.55);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  display: none; align-items: center; justify-content: center; padding: 16px;
}
.modal-overlay.show { display: flex; }
.modal {
  width: 100%; max-width: 400px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 22px;
  animation: modalIn .16s ease-out;
}
@keyframes modalIn { from { transform: translateY(10px); opacity: 0; } to { transform: none; opacity: 1; } }
.modal__title { margin: 0 0 8px; font-size: 1.02rem; font-weight: 800; color: var(--text); letter-spacing: .01em; }
.modal__msg { margin: 0 0 14px; font-size: .85rem; line-height: 1.55; color: var(--text-dim); }
.modal__input {
  width: 100%; padding: 10px 12px; font-size: .9rem;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg); color: var(--text); box-sizing: border-box;
}
.modal__input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
.modal__actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; }
.modal__actions .btn { min-width: 92px; }
[data-theme="dark"] .modal { background: #1c2230; }

/* Lightbox global: dipakai /cek + /scan. .modal standar (radius/shadow/tema ikut). */
.photo-grid { display:flex; gap:8px; flex-wrap:wrap; margin-top:4px; }
.photo-thumb { padding:0; border:none; background:none; cursor:pointer; }
.photo-thumb img { width:96px; height:96px; object-fit:cover; border-radius:8px; border:1px solid var(--border); display:block; }
.photo-thumb:focus-visible { outline:2px solid var(--accent); outline-offset:2px; border-radius:8px; }
.photo-modal { max-width:640px; position:relative; padding:16px; }
/* Lightbox ikut dimensi foto (contain, maks 82vh): bukti struk panjang
   tampil utuh tanpa bar 1:1; foto QC 1:1 tidak berubah tampilan. */
.photo-modal img { width:auto; max-width:100%; max-height:82vh; object-fit:contain; border-radius:8px; background:#000; display:block; margin:0 auto; }
.photo-x { position:absolute; top:6px; right:10px; width:32px; height:32px; border:none; border-radius:50%; background:var(--surface); color:var(--text); font-size:20px; line-height:1; cursor:pointer; }
/* Label catatan per foto bukti (DP / VIA BANK / VIA QRIS, cth "DP MAKE KADU").
   Satu sumber utk /scan/cs, /scan/kasir, /cek: kecil di bawah thumbnail. */
.proof-note-tag {
  display:block; max-width:96px; margin-top:2px; padding:0 5px;
  font-size:10px; font-weight:700; letter-spacing:.03em; text-align:center;
  color:var(--accent); background:var(--accent-light); border-radius:3px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.qc-photo-thumb .proof-note-tag { max-width:72px; }
/* Label kosong = ajakan isi (tetap kecil, tanpa border tombol): beda bahasa
   dari label terisi (accent) agar operator sadar catatan belum ada. */
.proof-note-tag.proof-note-empty { color:var(--text-dim); background:transparent; border:1px dashed var(--border); cursor:pointer; }
.proof-note-tag[role="button"] { cursor:pointer; }
.proof-note-tag[role="button"]:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.photo-cap { display:flex; align-items:center; justify-content:space-between; margin-top:10px; font-size:13px; color:var(--text-dim); }
.photo-nav { display:flex; gap:8px; }
.photo-nav .btn--xs { min-width:44px; min-height:44px; font-size:18px; }
.photo-err { margin-top:8px; font-size:13px; color:var(--danger); }
/* Indikator muat lightbox: spinner + teks, ganti bitmap lama yang disembunyikan
   selama foto baru diunduh (tanpa ini foto sebelumnya tampil dulu). */
.photo-loading { margin:18px 0 6px; font-size:13px; color:var(--text-dim); text-align:center; }
/* Judul collapse foto (dipakai <summary> di scanner): kiri, bold, tanpa marker */
.photo-collapse-title { font-size:11px; font-weight:800; color:var(--text-dim); text-transform:uppercase; letter-spacing:.5px; cursor:pointer; list-style:none; text-align:left; padding-left:0; }
.photo-collapse-title::-webkit-details-marker { display:none; }
.photo-collapse-title::marker { content:""; }
/* Ikon chevron judul collapse foto: inline tengah teks, putar saat open */
.jo-section-title .chev, .photo-collapse-title .chev { display:inline-block; vertical-align:-2px; transition:transform .15s; }
details[open] .jo-section-title .chev, details[open] .photo-collapse-title .chev { transform:rotate(180deg); }

.mb-4   { margin-bottom: 4px; }
.mb-6   { margin-bottom: 6px; }
.mb-8   { margin-bottom: 8px; }
.mb-10  { margin-bottom: 10px; }
.mb-12  { margin-bottom: 12px; }
.mb-16  { margin-bottom: 16px; }
.mb-20  { margin-bottom: 20px; }
.mt-4   { margin-top: 4px; }
.mt-6   { margin-top: 6px; }
.mt-8   { margin-top: 8px; }
.mt-10  { margin-top: 10px; }
.mt-12  { margin-top: 12px; }
.mt-16  { margin-top: 16px; }
.mt-20  { margin-top: 20px; }

.gap-4  { gap: 4px; }
.gap-6  { gap: 6px; }
.gap-8  { gap: 8px; }
.gap-10 { gap: 10px; }
.gap-12 { gap: 12px; }

.flex-wrap { flex-wrap: wrap; }
.flex-center { display: flex; align-items: center; justify-content: center; }
.flex-between { display: flex; align-items: center; justify-content: space-between; }
.flex-gap-4 { display: flex; gap: 4px; }
.flex-gap-6 { display: flex; gap: 6px; }
.flex-gap-8 { display: flex; gap: 8px; }
.flex-gap-10 { display: flex; gap: 10px; }
.flex-gap-12 { display: flex; gap: 12px; }
.flex-items-center { display: flex; align-items: center; }
.flex-items-center.gap-6 { gap: 6px; }
.flex-items-center.gap-8 { gap: 8px; }
.flex-items-center.gap-10 { gap: 10px; }

.text-dim { color: var(--text-dim); }
.text-sm  { font-size: 13px; }
.text-xs  { font-size: 12px; }
.text-lg  { font-size: 16px; }

.text-center { text-align: center; }
.text-left   { text-align: left; }
.text-right  { text-align: right; }

.mb-0  { margin-bottom: 0; }
.mt-0  { margin-top: 0; }
.ml-0  { margin-left: 0; }
.mr-0  { margin-right: 0; }
.mx-0  { margin-left: 0; margin-right: 0; }
.mx-4  { margin-left: 4px;  margin-right: 4px; }
.mx-6  { margin-left: 6px;  margin-right: 6px; }
.mx-8  { margin-left: 8px;  margin-right: 8px; }
.mx-10 { margin-left: 10px; margin-right: 10px; }
.mx-12 { margin-left: 12px; margin-right: 12px; }
.mx-16 { margin-left: 16px; margin-right: 16px; }

.flex { display: flex; }

.card__body--pad { padding: 14px; }


.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0 14px;
}

.badge-group-label {
  font-size: .68rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-dim);
  margin-bottom: 6px;
}
.badge-group-label b { color: var(--text); }

.badge-clickable { cursor: pointer; transition: transform .1s, filter .12s; }
.badge-clickable:hover { filter: brightness(.92); transform: translateY(-1px); }
.badge-clickable:active { transform: translateY(0); }

.map-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.map-row input { flex: 1; min-width: 180px; margin: 0; }
.map-row .seg { flex: 0 0 auto; }
.map-row .seg-btn { padding: 13px 14px; }

.dg-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: stretch; }
.dg-form input { margin: 0; }
.dg-form .btn { margin-top: 0; align-self: stretch; white-space: nowrap; }
.dg-form .dg-initials { width: 140px; flex: 0 0 auto; }
.dg-form .dg-fullname { flex: 1 1 180px; min-width: 160px; width: auto; }
/* Add-machine row: code flexible, label narrower */
.dg-form .mm-name { flex: 1 1 180px; min-width: 160px; width: auto; }
.dg-form .mm-label { width: 200px; flex: 0 0 auto; }

.dg-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  font-size: .78rem;
  font-weight: 800;
  letter-spacing: .04em;
}

.d-none { display: none !important; }
.d-block { display: block; }
.d-flex { display: flex; }
.d-inline-flex { display: inline-flex; }
.d-grid { display: grid; }

.skeleton {
  background: linear-gradient(90deg, var(--border) 25%, var(--hover) 50%, var(--border) 75%);
  background-size: 200% 100%;
  animation: skeleton-pulse 1.5s ease-in-out infinite;
  border-radius: 4px;
}
@keyframes skeleton-pulse {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton-text { height: 1rem; margin-bottom: 8px; }
.skeleton-text:last-child { width: 60%; }
.skeleton-title { height: 1.5rem; width: 40%; margin-bottom: 12px; }
.skeleton-card { padding: 16px; }
.skeleton-table-row { height: 48px; }
.skeleton-badge { width: 80px; height: 24px; border-radius: 12px; }

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
  text-align: center;
  color: var(--text-dim);
}
.empty-state__icon {
  font-size: 48px;
  margin-bottom: 16px;
  opacity: 0.4;
}
.empty-state__title {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 8px;
}
.empty-state__desc {
  font-size: 0.9rem;
  margin-bottom: 24px;
  max-width: 320px;
}
.empty-state__action {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.ws-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  margin-left: 6px;
  vertical-align: middle;
  transition: background-color .25s ease, box-shadow .25s ease;
}
.ws-dot--connected {
  background-color: var(--success);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--success) 30%, transparent);
}
.ws-dot--connecting {
  background-color: var(--warning);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--warning) 30%, transparent);
  animation: ws-pulse 1.4s infinite ease-in-out;
}
.ws-dot--disconnected {
  background-color: var(--danger);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--danger) 30%, transparent);
}
@keyframes ws-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.35; transform: scale(0.8); }
}

/* posisi: BAWAH-KIRI layar (fixed). Toast .msg juga di kiri-bawah, jadi saat
   toast tampil keduanya bertumpuk sebentar sampai toast hilang sendiri. */
.btn-scroll-top {
  position: fixed;
  bottom: 18px;
  top: auto;
  left: 18px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--surface);
  border: 1.5px solid var(--border);
  color: var(--accent);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  z-index: 1200;
  opacity: 0;
  pointer-events: none;
  transform: translateY(12px);
  transition: opacity .2s ease, transform .2s ease, border-color .15s ease, background-color .15s ease;
}
.btn-scroll-top.visible {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
.btn-scroll-top svg { width: 18px; height: 18px; }
.btn-scroll-top:hover {
  background: var(--hover);
  border-color: var(--accent);
  color: var(--accent-hover);
  box-shadow: 0 6px 18px rgba(0,0,0,.1);
}
.btn-scroll-top:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
[data-theme="dark"] .btn-scroll-top {
  background: var(--surface);
  border-color: var(--border);
  box-shadow: 0 4px 20px rgba(0,0,0,.45);
}
/* Halaman ber-sidebar (body.adm-shell): sidebar menempati kiri 236px dan
   tombol tema siang/malam ada di kaki sidebar (bawah-kiri). Tombol kembali-ke-
   atas yang fixed kiri-bawah menimpanya, jadi digeser ke kanan sidebar (= titik
   awal konten). Sidebar tersembunyi (collapsed) atau drawer mobile: balik ke
   18px lewat aturan di bawah. 252px = padding-left konten body.adm-shell. */
body.adm-shell:not(.adm-collapsed) .btn-scroll-top { left: 252px; }
/* Sidebar diringkas: tombol geser sejauh rel, jangan menimpa ikon menu. */
body.adm-collapsed .btn-scroll-top { left: calc(var(--adm-rail) + 16px); }
@media (max-width: 900px) {
  /* <=900px sidebar jadi drawer (tersembunyi), jadi tak ada yang ditimpa. */
  body.adm-shell:not(.adm-collapsed) .btn-scroll-top { left: 18px; }
  body.adm-collapsed .btn-scroll-top { left: 18px; }
  /* Drawer terbuka = overlay modal (backdrop menutup layar): sembunyikan
     tombol kembali-ke-atas supaya tidak mengapung di atas drawer / menimpa
     tombol tema siang-malam di kaki sidebar. */
  body.adm-nav-open .btn-scroll-top { display: none; }
}

@media print {
  .page-head,
  .filter-bar,
  .btn,
  .btn-scroll-top,
  .ws-dot,
  .theme-btn,
  .skipAllContainer,
  #reader,
  #pendingPagination,
  #message,
  .action-row,
  .edit-row,
  textarea,
  .modal-overlay { display: none !important; }
  .container { max-width: 100%; padding: 0; }
  .card { box-shadow: none; border: 1px solid #ccc; break-inside: avoid; page-break-inside: avoid; }
  .jo-info-body { padding: 0; background: #fff; }
  .jo-info-body .job-grid .jg-value { background: #fff; }
  .jo-copy-id, .jg-copy, .copy-ico { display: none; }
  .table-wrap { overflow: visible; }
  /* Cetak halaman: semua baris ikut, tanpa area scroll dalam. */
  .jo-info-body .table-wrap.jo-inner { max-height: none; }
  table { border-collapse: collapse; width: 100%; }
  th, td { border: 1px solid #999; padding: 6px 8px; font-size: 11px; }
  th { background: #f0f0f0; color: #000; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .rk-card { box-shadow: none; border: 1px solid #ccc; break-inside: avoid; }
  .rk-table th { background: #f0f0f0; color: #000; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .rj-table th { color: #000; }
  .badge { border: 1px solid #999; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  body { background: #fff; color: #000; }
  a[href]::after { content: none; }
  .rk-card.online .num,
  .rk-card.direct .num { color: #000; }
  @page { margin: 12mm; }
  @page :first { margin-top: 10mm; }
}

.stat-topbar { display:flex; gap:12px; margin-bottom:16px; }
/* HP: tombol nav rata selebar layar (3 kolom sejajar) */
@media (max-width: 600px) {
  .stat-topbar { gap: 8px; margin-bottom: 14px; }
  .stat-topbar .nav-link { flex: 1 1 0; justify-content: center; min-width: 0; }
}
.nav-link {
  display:inline-flex; align-items:center; gap:5px; padding:8px 14px; border-radius:var(--radius);
  background:var(--surface); border:1px solid var(--border); color:var(--text);
  text-decoration:none; font-size:.8rem; font-weight:500; transition:all .15s;
}
.nav-link:hover { border-color:var(--accent); color:var(--accent); box-shadow:var(--shadow); }
.nav-link--primary { background:var(--accent); color:#fff; border-color:var(--accent); }
.nav-link--primary:hover { background:var(--accent-dark, var(--accent)); color:#fff; box-shadow:var(--shadow); }
.nav-link:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.nav-link[aria-current="page"] { background:var(--accent); color:#fff; border-color:var(--accent); }
.nav-link[aria-current="page"]:hover { background:var(--accent-dark, var(--accent)); color:#fff; }
.nav-link svg { width:14px; height:14px; flex-shrink:0; }

/* Touch: target sentuh minimal 44px (R-03) */
@media (pointer: coarse) {
  .filter-btn { min-height: 44px; }
  .btn--xs { min-height: 44px; }
  .filter-bar .btn--xs,
  .filter-bar .btn--sm { min-height: 44px; }
  .page-btn { min-height: 44px; min-width: 44px; }
  /* Item sidebar app (/, /cek, /buat) di layar sentuh: 44px. Item /admin tidak
     diubah supaya tidak menambah tinggi menu yang sudah panjang. */
  .app-sidebar .adm-nav a { min-height: 44px; }
  .nav-link { min-height: 44px; }
  .recent-row { min-height: 44px; }
  .jo-copy-id { min-height: 44px; padding: 10px 10px; }
  .jg-copy { min-height: 36px; min-width: 36px; padding: 8px; }
  /* Tombol salin nama file (tabel item): 26px -> target jempol 36px di sentuh.
     Tidak 44px supaya tidak memaksa tinggi baris item naik saat ikon kecil. */
  .copy-ico { width: 36px; height: 36px; margin-left: 4px; }
  .copy-ico svg { width: 16px; height: 16px; }
  .filter-btns { gap: 8px; }
}

/* Guardrail: halaman tidak boleh bergeser kanan-kiri (R-03).
   Scroll horizontal tetap hidup di dalam kontainernya
   (.table-wrap, .filter-btns). */
html, body { overflow-x: clip; }
@supports not (overflow: clip) {
  html, body { overflow-x: hidden; }
}

/* ============================================================
   ADMIN SHELL: sidebar kiri statis + area konten.
   Dipakai SEMUA halaman /admin* (termasuk /admin/rekap/{mesin} yang
   tidak memuat flat.css), jadi aturannya berdiri sendiri, tidak
   di-scope `.flat`. Navigasi penuh: tiap tautan memuat halaman di tab
   yang sama. Sidebar = satu permukaan + garis pemisah kanan; tanpa
   shadow supaya bahasa bentuk flat tetap konsisten.
   ============================================================ */
.adm-sidebar {
  position: fixed; inset: 0 auto 0 0; width: 236px;
  display: flex; flex-direction: column;
  background: var(--surface);
  border-right: 1px solid var(--border);
  z-index: 1000;
}
.adm-brand { display: flex; align-items: center; gap: 10px; padding: 18px 18px 12px; }
.adm-brand__mark {
  width: 34px; height: 34px; flex-shrink: 0; border-radius: 9px;
  /* Teal brand tetap (bukan var(--accent)) supaya ikon putih tetap kontras
     di mode gelap, di mana --accent jadi mint terang. */
  background: #0e7c6b; color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.adm-brand__mark svg { width: 24px; height: 24px; display: block; }
/* Sidebar halaman PUBLIK (/, /buat, /cek): bentuk sama dengan sidebar /admin,
   warna ikut tema publik. Mark pakai biru tetap #2563eb (bukan var(--accent))
   dengan alasan sama seperti teal di atas: di mode gelap --accent jadi biru
   terang (#3b82f6) sehingga ikon putih turun ke ~3,6:1. Biru tetap = 5,2:1. */
.app-sidebar .adm-brand__mark { background: #2563eb; }
.adm-brand__txt strong { display: block; font-size: 14px; font-weight: 800; line-height: 1.2; }
.adm-brand__txt small {
  display: block; font-size: 10.5px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--text-dim);
}
.adm-nav { flex: 1; overflow-y: auto; padding: 4px 12px 12px; }
/* Scrollbar sidebar: gaya tipis "modern" yang MENYATU dengan tema (dulu
   memakai scrollbar bawaan browser: trek abu + tombol panah segitiga yang
   kontras & beda sendiri dari tema hangat sidebar).
   - Firefox: `scrollbar-width/color` (thumb = --border dulu, aksen saat hover)
   - Chromium/Safari: `::-webkit-scrollbar` + thumb membulat transparan
   Warna SELALU var()/color-mix supaya ikut [data-theme="dark"] tanpa override.
   Trek transparan -> tidak ada "bar" yang terlihat; thumb muncul saat ada
   konten lebih. Lebar 8px (bukan 12+ bawaan) supaya tidak memakan ruang menu. */
.adm-nav { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
.adm-nav:hover { scrollbar-color: color-mix(in srgb, var(--accent) 55%, var(--border)) transparent; }
.adm-nav::-webkit-scrollbar { width: 8px; height: 8px; }
.adm-nav::-webkit-scrollbar-track { background: transparent; }
.adm-nav::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--text) 18%, transparent);
  border-radius: 999px;
  /* border transparan + background-clip = thumb "mengapung" dengan jeda tepi */
  border: 2px solid transparent;
  background-clip: padding-box;
  transition: background-color .15s ease;
}
.adm-nav:hover::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--accent) 50%, var(--border));
  background-clip: padding-box;
}
.adm-nav::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--accent) 70%, var(--border));
  background-clip: padding-box;
}
/* Sudut pertemuan batang: transparan (jangan kotak putih bawaan). */
.adm-nav::-webkit-scrollbar-corner { background: transparent; }
/* Tombol panah ujung scrollbar bawaan: disembunyikan (modern pakai drag saja). */
.adm-nav::-webkit-scrollbar-button { display: none; height: 0; width: 0; }
.adm-nav__group {
  display: block; padding: 14px 10px 5px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-dim);
}
.adm-nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; margin-bottom: 2px; border-radius: 9px;
  color: var(--text); text-decoration: none;
  font-size: 13.5px; font-weight: 600;
  transition: background .12s ease, color .12s ease;
}
.adm-nav a svg { width: 17px; height: 17px; flex-shrink: 0; opacity: .85; }
.adm-nav a:hover { background: var(--hover); }
.adm-nav a.is-active {
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  color: var(--accent);
}
.adm-nav a.is-active svg { opacity: 1; }
.adm-nav a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.adm-sidebar__foot {
  display: flex; align-items: center; gap: 8px;
  padding: 12px; border-top: 1px solid var(--border);
}
.adm-sidebar__foot .adm-logout { margin-left: auto; }

/* Tombol "Masuk" (sidebar app, muncul hanya bila BELUM ada sesi): dorong ke
   kanan seperti logout, jadi tema & tombol sesi selalu di ujung kanan. */
.adm-login { margin-left: auto; }

/* Konten digeser sejauh lebar sidebar. Tanpa div pembungkus: body sudah
   punya padding, cukup padding-left di-override (satu titik, tak bisa
   salah tutup tag). Transisi halus saat sidebar disembunyikan/ditampilkan. */
body.adm-shell { padding-left: 252px; transition: padding-left .2s ease; }

/* Sidebar bisa DIRINGKAS jadi rel ikon (desktop) — bukan disembunyikan total.
   Logo tetap tampil dan tiap menu menyisakan ikon SVG-nya tanpa label, jadi
   navigasi tetap terjangkau sekali klik dan pengguna tidak kehilangan arah.
   Preferensi disimpan di localStorage lewat skrip di _admin_sidebar.html /
   _app_sidebar.html. Rel 68px = ikon 20px + 2x16px sisa + napas tepi. */
:root { --adm-rail: 68px; }
.adm-sidebar { transition: width .2s ease, transform .2s ease; }
@media (min-width: 901px) {
  body.adm-collapsed .adm-sidebar { width: var(--adm-rail); }
  body.adm-collapsed.adm-shell { padding-left: calc(var(--adm-rail) + 16px); }

  /* Label teks hilang saat diringkas: nama menu pakai font-size:0 sehingga
     teksnya tetap ada untuk screen reader, sedangkan "JO/Menu" di brand
     memang dekoratif jadi cukup disembunyikan. */
  body.adm-collapsed .adm-brand { justify-content: center; padding: 62px 0 6px; }
  body.adm-collapsed .adm-brand__txt { display: none; }

  /* Judul grup jadi garis pemisah tipis, bukan hilang begitu saja —
     pengelompokan menu masih terbaca sebagai sekat. */
  body.adm-collapsed .adm-nav { padding: 4px 8px 12px; }
  body.adm-collapsed .adm-nav__group {
    height: 0; padding: 0; margin: 8px 6px;
    font-size: 0; line-height: 0;
    border-top: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
  }
  body.adm-collapsed .adm-nav a {
    justify-content: center; gap: 0; padding: 9px 0; font-size: 0;
  }
  body.adm-collapsed .adm-nav a svg { width: 20px; height: 20px; opacity: 1; }

  /* Kaki sidebar: tombol tema & logout menumpuk, ikon saja. */
  body.adm-collapsed .adm-sidebar__foot {
    flex-direction: column; gap: 8px; padding: 12px 0;
  }
  /* Di mode collapse foot jadi kolom (menumpuk vertikal). `margin-left:auto`
     pada .adm-login/.adm-logout (yg dipakai saat foot BARIS untuk mendorong ke
     kanan) WAJIB di-nol-kan di sini — kalau tidak, di flex-column `auto`
     mendorong tombol ke KANAN (cross-axis) sehingga tidak sejajar dgn tombol
     lain. Dulu hanya .adm-logout yg di-reset -> tombol Masuk menjorok. */
  body.adm-collapsed .adm-sidebar__foot .adm-logout,
  body.adm-collapsed .adm-sidebar__foot .adm-login { margin-left: 0; }
}

/* Toggle sidebar (desktop): SATU tombol, selalu tampil.
   - Terbuka: duduk di kanan header sidebar, ikon chevron-left (◀ = sembunyikan).
   - Tertutup: pindah ke kiri-atas, ikon burger (☰ = tampilkan).
   Ikon berputar 180deg + cross-fade saat keadaan berubah (morph CSS murni). */
.adm-open {
  display: inline-flex;
  position: fixed; z-index: 1100;
  top: 15px; left: 184px;
  width: 40px; height: 40px;
  align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: 10px;
  background: transparent; color: var(--text-dim); cursor: pointer;
  transition: left .22s ease, top .22s ease, background .15s ease,
              border-color .15s ease, color .15s ease;
}
.adm-open:hover { background: var(--hover); color: var(--text); }
.adm-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Tertutup: tombol pindah ke ATAS logo di dalam rel (14px = rel 68px
   dikurangi lebar tombol 40px, dibagi dua). Brand diberi padding-atas
   sebagai ruangnya, jadi tombol tidak menimpa ikon menu mana pun. */
body.adm-collapsed .adm-open {
  top: 12px; left: 14px;
  border-color: var(--border); background: var(--surface); color: var(--text);
}
body.adm-collapsed .adm-open:hover { border-color: var(--accent); color: var(--accent); }
/* Morph ikon: chevron (terbuka) <-> burger (tertutup), diputar 180deg. */
.adm-toggle__ico {
  position: relative; width: 20px; height: 20px; display: block;
  transition: transform .35s cubic-bezier(.4, 0, .2, 1);
}
.adm-toggle__ico svg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  transition: opacity .25s ease;
}
.adm-toggle__ico .ico-burger { opacity: 0; transform: rotate(-180deg); }
body.adm-collapsed .adm-toggle__ico { transform: rotate(180deg); }
body.adm-collapsed .adm-toggle__ico .ico-chevron { opacity: 0; }
body.adm-collapsed .adm-toggle__ico .ico-burger { opacity: 1; transform: rotate(0); }

/* Burger + backdrop hanya hidup di layar sempit (drawer). */
.adm-burger { display: none; }
.adm-backdrop { display: none; }

@media (max-width: 900px) {
  .adm-sidebar {
    transform: translateX(-100%);
    box-shadow: var(--shadow-md);
  }
  body.adm-nav-open .adm-sidebar { transform: translateX(0); }
  /* FULL LAYAR di mobile: body TANPA padding samping supaya konten menempel ke
     tepi (sama seperti /scan). Dulu `padding-left:16px; padding-top:72px` di
     sini menyisakan celah -> konten terlihat "terkurung". Ruang untuk BURGER
     (fixed 44px di top:12px/left:12px) sekarang disediakan oleh padding ATAS
     pada `.container` (lihat aturan <=900px di bawah), bukan padding body. */
  body.adm-shell,
  body.adm-collapsed.adm-shell { padding-left: 0; padding-top: 0; }
  /* Di mobile drawer yang dipakai, bukan mode collapse desktop:
     toggle desktop (#admOpen) dimatikan, burger drawer yang berperan. */
  .adm-open { display: none; }
  .adm-burger {
    display: inline-flex; align-items: center; justify-content: center;
    position: fixed; top: 12px; left: 12px; z-index: 1100;
    width: 44px; height: 44px;
    border: 1px solid var(--border); border-radius: 10px;
    background: var(--surface); color: var(--text); cursor: pointer;
  }
  .adm-burger:hover { border-color: var(--accent); color: var(--accent); }
  .adm-burger:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  /* Samakan ukuran ikon burger dgn versi desktop (.adm-toggle__ico 20px) —
     tanpa batas ini SVG mengisi penuh tombol 44px dan tampak besar/kasar. */
  .adm-burger svg { width: 20px; height: 20px; display: block; }
  /* Drawer terbuka: burger disembunyikan. Ia berada di (12,12) dengan z-index
     lebih tinggi dari sidebar, sehingga menutupi logo di header sidebar.
     Menutup drawer tetap mudah: klik backdrop (seluruh layar) atau Escape. */
  body.adm-nav-open .adm-burger { display: none; }
  body.adm-nav-open .adm-backdrop {
    display: block; position: fixed; inset: 0;
    background: rgba(0, 0, 0, .42); z-index: 999;
  }
}

@media print {
  .adm-sidebar, .adm-burger, .adm-backdrop, .adm-open { display: none !important; }
  body.adm-shell, body.adm-collapsed.adm-shell { padding-left: 0; padding-top: 0; }
}
