:root{
  --bg:#FFFBFE; --surface:#F3EDF7; --surface2:#ECE6F0; --surface3:#E0D6E9;
  --ink:#1D1B1E; --muted:#49454F; --hint:#938F99;
  --brand:#6750A4; --brand2:#E8DEF8; --brand3:#D0BCFF;
  --accent:#EADDFF;
  --success:#4F6354; --okbg:#D9E6DC;
  --warn:#B3261E; --warnbg:#F9DEDC;
  --line:#E7E0EC;
  --shadow:0 2px 6px rgba(27,22,30,.08),0 1px 2px rgba(27,22,30,.04);
  --shadow-elev:0 4px 12px rgba(27,22,30,.12),0 1px 3px rgba(27,22,30,.06);
}
*{box-sizing:border-box; -webkit-tap-highlight-color:transparent;}
html,body{margin:0; height:100%;}
body{background:var(--bg); color:var(--ink); font:16px/1.45 'Inter',system-ui,-apple-system,Roboto,sans-serif;}
button,input,select,textarea{font:inherit; color:inherit;}
a{color:var(--brand); text-decoration:none;}
.app{max-width:640px; margin:0 auto; min-height:100%; padding-bottom:80px;}
#view{padding:12px;}
.row{display:flex; gap:8px; align-items:center;}
.row.wrap{flex-wrap:wrap;}
.grow{flex:1;}
.muted{color:var(--muted);}
.center{text-align:center;}
.right{text-align:right;}
.mono{font-variant-numeric:tabular-nums; letter-spacing:-0.01em;}
.card{background:var(--surface); border:none; border-radius:16px; padding:14px; margin:8px 0; box-shadow:var(--shadow);}
input,select,textarea{background:#FFFFFF; border:1px solid var(--line); border-radius:12px; padding:12px 14px; width:100%; transition:background .15s, box-shadow .15s, border-color .15s;}
input:focus,select:focus,textarea:focus{outline:none; background:#FFFFFF; border-color:var(--brand3); box-shadow:0 0 0 3px var(--brand2);}
input::placeholder,textarea::placeholder{color:var(--hint);}
.btn{background:var(--brand); color:#fff; border:none; border-radius:12px; padding:12px 18px; font-weight:600; cursor:pointer; box-shadow:var(--shadow); transition:transform .08s, background .15s;}
.btn:active{transform:scale(.98);}
.btn.block{width:100%;}
.btn.sec{background:var(--surface2); color:var(--brand); box-shadow:none;}
.btn.ok{background:var(--success); color:#fff;}
.btn.danger{background:var(--warn); color:#fff;}
.btn.sm{padding:8px 12px; font-size:14px; border-radius:10px;}
.btn[disabled]{opacity:.5; cursor:not-allowed; box-shadow:none;}
.tag{display:inline-block; font-size:12px; padding:3px 10px; border-radius:999px; background:var(--surface2); color:var(--muted); font-weight:500; line-height:1.4;}
.tag.warn{background:#FCE7A8; color:#5F4B0A;}
.tag.ok{background:var(--okbg); color:var(--success);}
.tag.danger{background:var(--warnbg); color:var(--warn);}
.tag.api{background:var(--accent); color:var(--brand);}
h1,h2,h3{margin:.35em 0; font-weight:700;}
h2{font-size:18px;}
ul.list{list-style:none; margin:0; padding:0;}
ul.list li{padding:14px; border:none; border-radius:16px; margin:8px 0; background:var(--surface); box-shadow:var(--shadow);}
ul.list li:active{background:var(--surface2); transform:scale(.99);}
.search-row{display:flex; gap:8px;}
.clear-input-wrap{position:relative;display:block;flex:1 1 auto;min-width:0;}
.clear-input-pad{padding-right:2.75rem;}
.clear-input-btn{position:absolute;right:.25rem;top:50%;transform:translateY(-50%);width:44px;height:44px;display:none;align-items:center;justify-content:center;background:transparent;border:none;color:var(--muted);}
.clear-input-wrap.has-value .clear-input-btn{display:flex;}
.clear-input-wrap > [data-results]{position:absolute; top:100%; left:0; right:0; max-height:min(360px,50vh); overflow-y:auto; z-index:45; background:var(--surface); border:1px solid var(--line); border-radius:12px; box-shadow:var(--shadow); margin-top:4px;}
.clear-input-wrap > [data-results].flip-up{top:auto; bottom:100%; margin-top:0; margin-bottom:4px;}
.clear-input-wrap > [data-results]:empty{display:none;}
#results{max-height:min(360px, 50vh); overflow-y:auto; padding-right:4px;}
#results ul.list li{padding:10px 12px; margin:6px 0; border-radius:12px;}
#results ul.list li .row{align-items:center !important;}
#results ul.list li .grow{min-width:0; padding-right:8px;}
#results ul.list li .name{font-size:14px; overflow-wrap:anywhere;}
#results ul.list li button{flex:0 0 auto; margin-top:0 !important;}
#results::-webkit-scrollbar{width:6px;}
#results::-webkit-scrollbar-thumb{background:var(--surface3); border-radius:3px;}
.item-line{display:block; padding:10px 12px; border:none; border-radius:14px; margin:8px 0; background:var(--surface); box-shadow:var(--shadow);}
.item-line .il-main{display:flex; gap:10px; align-items:flex-start; justify-content:space-between;}
.item-line .il-info{min-width:0; flex:1;}
.item-line .name{font-weight:600; font-size:15px; line-height:1.25; overflow-wrap:anywhere;}
.item-line .meta{color:var(--muted); font-size:12px; margin-top:2px;}
.item-line .subtotal{text-align:right; font-weight:700; color:var(--brand); font-size:16px; line-height:1.2; white-space:nowrap;}
.item-line .il-controls{display:flex; gap:8px; align-items:center; margin-top:8px;}
.item-line .qty{display:flex; gap:4px; align-items:center; flex:0 0 auto;}
.item-line .qty input{width:90px; text-align:center; font-weight:700; font-size:15px; padding:8px 6px; border-radius:10px;}
.item-line .qty .btn.icon{width:34px; height:34px; padding:0; font-size:18px;}
.item-line .disc-rm{flex:1; min-width:0; display:flex; gap:6px; align-items:center;}
.item-line .disc-rm input{flex:1; min-width:0; text-align:right; font-weight:600; padding:8px 10px; border-radius:10px;}
.item-line .disc-rm [data-rm]{width:34px; height:34px; padding:0; border-radius:50%; font-size:16px; background:var(--warn); color:#fff; box-shadow:none; flex:0 0 auto;}
.totals{margin:12px 0 6px;}
.totals.compact{margin:10px 0 4px;}
.totals .trow{display:flex; justify-content:space-between; padding:3px 0; font-size:14px;}
.totals.compact .trow{padding:2px 0; font-size:14px;}
.totals .trow.grand{border-top:2px solid var(--line); margin-top:6px; padding-top:8px; font-weight:800; font-size:18px; color:var(--brand);}
.btn.icon{width:40px; height:40px; padding:0; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; font-size:0; line-height:1;}
.btn.icon svg{width:20px; height:20px;}
#sheet-close{width:36px; height:36px;}
.card.compact{padding:12px;}
.card.compact label{font-size:13px; display:block; margin-bottom:4px;}
.card.compact input{padding:10px 12px;}
.hint{font-size:13px; color:var(--muted); margin:6px 0;}
.err{color:#8C1D18; background:var(--warnbg); border:none; border-radius:12px; padding:10px 12px; margin:8px 0; font-weight:500;}
.okbox{color:#1B4D35; background:var(--okbg); border:none; border-radius:12px; padding:12px; margin:8px 0; font-weight:500;}
nav.bottom{position:fixed; bottom:0; left:0; right:0; max-width:640px; margin:0 auto; display:flex; background:var(--surface); border-radius:20px 20px 0 0; box-shadow:var(--shadow-elev); padding:8px 0 calc(8px + env(safe-area-inset-bottom)); z-index:40;}
nav.bottom a{flex:1; text-align:center; padding:10px 0 6px; color:var(--muted); font-size:12px; font-weight:500; display:flex; flex-direction:column; align-items:center; gap:2px;}
nav.bottom a .nav-icon{display:block; line-height:1;}
nav.bottom a .nav-icon svg{display:block; width:24px; height:24px; margin:0 auto;}
nav.bottom a.active{color:var(--brand);}
nav.bottom a.hide{display:none;}
nav.bottom.hide{display:none;}
body:not(.auth) .app{padding-bottom:0;}
.head{display:flex; align-items:center; justify-content:space-between; margin:4px 2px 10px;}
.head .who{color:var(--muted); font-size:13px;}
.nota{background:#fff; color:#111; border-radius:16px; padding:20px; font-size:14px; box-shadow:var(--shadow-elev);}
.nota h3{margin:0 0 6px; font-weight:700;} .nota .c{font-size:12px; color:#444;}
.nota .nota-head{display:flex; justify-content:space-between; align-items:baseline; gap:8px; margin:0 0 6px;}
.nota .nota-head h3{margin:0;}
.nota .nota-date{font-size:12px; color:#444; text-align:right; white-space:nowrap;}
.nota .nota-meta{display:grid; grid-template-columns:1fr 1fr; gap:2px 12px; font-size:12px; color:#444; margin:0 0 6px;}
.nota .nota-meta > div{min-width:0; overflow-wrap:anywhere;}
.nota .nota-meta .span2{grid-column:1 / -1;}
.nota .nota-meta .k{color:#777;}
.nota .nota-meta .r{text-align:right;}
.nota th{text-align:left;}
.nota .nota-foot{text-align:center; margin-top:10px;}
.nota table{width:100%; border-collapse:collapse; margin:8px 0;} .nota td,.nota th{padding:4px 0; vertical-align:top; overflow-wrap:anywhere;}
.nota .rt{text-align:right;} .nota .tot{border-top:2px dashed #999; margin-top:6px; padding-top:6px; font-weight:800; font-size:20px;}
.nota .stamp{text-align:center; margin-top:10px; font-weight:700;}
header.top{position:sticky; top:0; z-index:20; display:flex; align-items:center; justify-content:space-between; gap:8px; padding:max(10px, env(safe-area-inset-top)) 14px 10px; background:var(--surface); border-radius:0 0 16px 16px; box-shadow:var(--shadow);}
body:not(.auth) header.top{display:none;}
header.top h2{margin:0; font-size:18px; font-weight:800; color:var(--brand);}
header.top .top-right{display:flex; align-items:center; gap:8px;}
header.top .who{color:var(--muted); font-size:13px;}
header.top .clock{color:var(--hint); font-size:12px; white-space:nowrap;}
dialog.sheet{position:fixed; left:0; right:0; bottom:0; top:auto; margin:0 auto; max-width:640px; width:100%; max-height:85vh; overflow:auto; border:none; border-radius:28px 28px 0 0; background:var(--surface); color:var(--ink); padding:0; transform:translateY(100%); transition:transform .25s cubic-bezier(.2,.8,.2,1); z-index:60; box-shadow:var(--shadow-elev);}
dialog.sheet.open{transform:translateY(0);}
dialog.sheet::backdrop{background:rgba(29,27,30,.45);}
.sheet-card{padding:20px; padding-bottom:max(20px, env(safe-area-inset-bottom));}
.sheet-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:14px;}
.sheet-head h3{margin:0; font-size:18px; font-weight:700; color:var(--brand);}
.fab{position:fixed; bottom:calc(78px + env(safe-area-inset-bottom)); right:14px; width:56px; height:56px; border-radius:50%; background:var(--brand); color:#fff; display:flex; align-items:center; justify-content:center; font-size:28px; box-shadow:var(--shadow-elev); z-index:50; cursor:pointer; border:none;}
.fab:active{transform:scale(.95);}
dialog.confirm-dialog{position:fixed; inset:0; margin:auto; max-width:360px; width:calc(100% - 48px); max-height:85vh; overflow:auto; border:none; border-radius:20px; background:var(--surface); color:var(--ink); padding:0; z-index:70; box-shadow:var(--shadow-elev);}
dialog.confirm-dialog::backdrop{background:rgba(29,27,30,.45);}
.confirm-card{padding:24px;}
.confirm-card h3{margin:0 0 8px; font-size:18px; font-weight:700; color:var(--brand);}
.confirm-card p{margin:0 0 20px; font-size:15px; line-height:1.45; color:var(--ink); overflow-wrap:anywhere;}
.confirm-actions{display:flex; flex-direction:column; gap:10px;}
@media print{
  @page{ size:A5; margin:6mm; }
  body{background:#fff;}
  header.top, nav.bottom, .fab, .noprint{display:none;}
  .app{max-width:none; padding:0; margin:0;}
  #view{padding:0;}
  .printonly{display:block;}
  .nota{max-width:136mm; margin:0 auto; box-shadow:none; padding:6px; font-size:11px;}
  .nota h3{margin:0 0 4px;}
  .nota .c{font-size:10px;}
  .nota .nota-foot{margin-top:6px;}
  .nota .nota-head{margin:0 0 4px;}
  .nota .nota-date{font-size:10px;}
  .nota .nota-meta{font-size:10px; margin:0 0 4px;}
  .nota table{margin:4px 0;}
  .nota td,.nota th{padding:2px 0;}
  .nota .rt{white-space:nowrap;}
  .nota .tot{border-top:2px dashed #999; margin-top:4px; padding-top:4px; font-weight:800; font-size:15px;}
  .nota .stamp{margin-top:6px; color:#111 !important;}
  /* Stack item subtotal below name (print): hide thead, block-ify rows,
     inline the detail with the name (hide the <br> so name+detail share
     line 1), drop the subtotal to its own line below, right + bold.
     Net-zero height vs the 2-col table: the detail trades its own line
     for the subtotal's, so 2 lines -> 2 lines. .items-only — the summary
     and statusLine tables keep their 2-col layout. */
  .nota table.items thead{ display:none; }
  .nota table.items tbody tr{ display:block; padding:2px 0; border-bottom:1px dashed #ddd; }
  .nota table.items tbody tr:last-child{ border-bottom:none; }
  .nota table.items tbody td{ display:block; padding:0; }
  .nota table.items tbody td.rt{ text-align:right; font-weight:600; }
  .nota table.items tbody td br{ display:none; }
}
.printonly{display:none;}
/* ── Nota: stack item subtotal below name on screen at ALL widths (3-line:
   name / detail / subtotal) and in print (compact 2-line: name+detail /
   subtotal, to preserve the A5 1-page fit). Screen stacks at every width so
   a long item name never crams the subtotal into a wrapping column. ── */
@media screen{
  .nota table.items thead{ display:none; }
  .nota table.items tbody tr{ display:block; padding:8px 0; border-bottom:1px dashed var(--line); }
  .nota table.items tbody tr:last-child{ border-bottom:none; }
  .nota table.items tbody td{ display:block; padding:0; }
  .nota table.items tbody td.rt{ text-align:right; font-weight:600; }
}
/* ── Jual responsive + cart UX (2026-07-27) ── */
.search-row{ position:sticky; top: calc(max(10px, env(safe-area-inset-top)) + 36px + 4px); z-index:10; background:var(--bg); }
.item-line .item-no{ color:var(--muted); font-weight:700; margin-right:4px; }
.item-line[data-just-added]{ animation: item-flash 1.2s ease-out; }
@keyframes item-flash{ 0%{ background:var(--brand2); } 100%{ background:var(--surface); } }
@media (prefers-reduced-motion: reduce){ .item-line[data-just-added]{ animation:none; background:var(--brand2); } }
/* ── Jual desktop 2-col + sticky checkout (2026-07-28) ── */
/* Mobile (<900px): flex column so `order` can place the cart between the chip
   and the checkout. .jual-left unwraps (display:contents) so its children
   (chip + checkout card) become flex items reorderable around the cart.
   Visual order on mobile: chip → cart → checkout (unchanged). Desktop overrides
   display:contents below, so desktop never depends on display:contents. */
body[data-route="jual"] .jual-grid{ display:flex; flex-direction:column; }
body[data-route="jual"] .jual-left{ display:contents; }
body[data-route="jual"] .jual-input{ order:1; }
body[data-route="jual"] .jual-basket{ order:2; }
body[data-route="jual"] .jual-left > .card{ order:3; }
@media (min-width: 900px){
  /* Shell: stable 1000px for ALL routes so tab switches never reflow the frame
     (was jual-only; only the shell widens, not the readable content). */
  .app{ max-width:1000px; }
  nav.bottom{ max-width:1000px; }
  /* Non-jual routes: center each direct child of #view at 640px (readable
     content) while keeping #view itself at 1000px (stable frame — no reflow
     on tab switch). Jual excluded — its .jual-grid fills the 1000px #view. */
  body:not([data-route="jual"]) #view > *{ max-width:640px; margin-inline:auto; }
  body[data-route="jual"] .jual-grid{ display:grid; grid-template-columns: minmax(0,0.6fr) minmax(0,1fr); gap:16px; align-items:start; }
  body[data-route="jual"] .jual-left{
    grid-column:1;
    display:flex; flex-direction:column; gap:12px;
    position:sticky; top:var(--jual-sticky-top);
    max-height: calc(100vh - var(--jual-sticky-top) - 80px);   /* reserve for fixed nav.bottom (~78px+safe-area) so Simpan is never hidden behind it */
    overflow-y:auto; overscroll-behavior:contain;
    background:var(--bg);                                      /* opaque when pinned (matches page bg) */
    z-index:9;                                                /* below search-row(10) & header(20) so any residual overlap is hidden */
  }
  body[data-route="jual"] .jual-basket{ grid-column:2; }
  body[data-route="jual"] .jual-left > .card{ margin:0; }     /* flex gap:12px handles spacing, not the 8px .card margin */
}

/* ── Jual top total bar + scan/reset icons (2026-07-28) ── */
/* --jual-sticky-top = top safe inset + header(36) + gap(4) + search-row(52).
   Shared by the mobile sticky total bar and the desktop sticky left column
   (the desktop media block no longer redefines it). */
body[data-route="jual"]{ --jual-sticky-top: calc(max(10px, env(safe-area-inset-top)) + 36px + 4px + 52px); }
body[data-route="jual"] .jual-totalbar{
  position:sticky; top:var(--jual-sticky-top); z-index:9; background:var(--bg);
  display:flex; align-items:center; justify-content:space-between;
  padding:8px 12px; margin:0 0 4px; border-radius:12px;
}
body[data-route="jual"] .top-total-val{ font-weight:800; font-size:18px; color:var(--brand); font-variant-numeric:tabular-nums; white-space:nowrap; }
/* Align the qrcode glyph with the "Scan" label inside the scan button. */
body[data-route="jual"] #scan{ display:inline-flex; align-items:center; gap:6px; }
/* Make #reset a circle whose diameter matches #scan's height. .btn.icon sets
   40×40; id specificity overrides it. A fixed 49×49 square (= the #q input box
   height: 12+12 padding + 16*1.45 line + 2px border ≈ 49px, which #scan stretches
   to) → circle via .btn.icon border-radius:50%. align-self:center keeps it
   vertically centered with #scan if the row is taller (e.g. iOS input min-height).
   NB: aspect-ratio:1 was tried first, but in a flex ROW the main-axis width is
   resolved before the cross-axis stretch, so the button rendered as a tall oval
   instead of a square — hardcode the square instead. */
body[data-route="jual"] #reset{ width:49px; height:49px; align-self:center; }
/* Breathing room above Simpan so it isn't dempet with the Catatan/#totals block
   above (esp. when the cart is empty and #totals collapses to 0 height). Scoped
   to jual; does not affect nota print (nota is a separate route). */
body[data-route="jual"] #submit{ margin-top:8px; }
@media (min-width: 900px){
  /* Desktop already shows the full totals in the sticky left column; hide the
     redundant top total bar there. */
  body[data-route="jual"] .jual-totalbar{ display:none; }
}
