/* Zarwin Inventory design system: deep warm charcoal + premium gold (Arc Rewards language) */
:root{
  --bg0:#080706; --bg1:#0e0b09;
  --panel:#171310; --panel2:#1e1913; --panel3:#262019;
  --line:#3a311f; --line-soft:#2e2718;
  --gold:#d9a441; --gold-hi:#f6d488; --gold-lo:#a8742c;
  --gold-grad:linear-gradient(135deg,#f6d488 0%,#d9a441 48%,#b3802e 100%);
  --text:#f4ecdd; --muted:#ab9f89; --faint:#9a8e78;
  --danger:#e0655f; --green:#5dbb84;
  --fs-body:17px; --fs-small:14px;
  --radius:20px; --radius-sm:14px;
  --shadow:0 10px 30px rgba(0,0,0,.45), 0 2px 6px rgba(0,0,0,.35);
  --shadow-gold:0 8px 24px rgba(217,164,65,.28);
  --font:'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}
*{box-sizing:border-box; -webkit-tap-highlight-color:transparent}
html{overscroll-behavior:none; touch-action:manipulation}
body{
  margin:0; font-family:var(--font); color:var(--text); min-height:100vh; min-height:100dvh; font-size:var(--fs-body);
  background:var(--bg0);
}
body::before{
  content:''; position:fixed; inset:0; z-index:-1; pointer-events:none;
  background:
    radial-gradient(1100px 500px at 85% -10%, rgba(217,164,65,.13), transparent 60%),
    radial-gradient(900px 600px at -10% 110%, rgba(217,164,65,.07), transparent 55%),
    linear-gradient(180deg, var(--bg1), var(--bg0));
}
input,textarea,select{font-family:inherit; -webkit-user-select:text; user-select:text}
button{font-family:inherit; cursor:pointer; touch-action:manipulation}
.hidden{display:none !important}
.view{display:none}
.view.active{display:block}

/* ---------- login ---------- */
.login-wrap{min-height:100vh; min-height:100dvh; display:flex; align-items:center; justify-content:center; padding:22px}
.login-card{width:100%; max-width:420px; text-align:center}
.logo-badge{
  width:84px; height:84px; margin:0 auto 16px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--gold-grad); color:#171106; font-size:42px; font-weight:800;
  box-shadow:var(--shadow-gold);
}
.logo-badge.small{width:40px; height:40px; font-size:20px; margin:0}
.logo-name{font-weight:800; letter-spacing:.14em; font-size:24px; margin:0}
.logo-name span{color:var(--gold)}
.login-sub{color:var(--muted); margin:8px 0 26px}
label{display:block; text-align:left; font-size:var(--fs-small); color:var(--muted); font-weight:700; margin:0 0 14px; letter-spacing:.02em}
input,select,textarea{
  display:block; width:100%; margin-top:6px; padding:14px 16px; min-height:52px;
  background:var(--panel2); border:1px solid var(--line); border-radius:var(--radius-sm);
  color:var(--text); font-size:17px; font-weight:600; outline:none;
}
input:focus,select:focus,textarea:focus{border-color:var(--gold)}
.error-text{color:var(--danger); min-height:20px; font-weight:700}
.result-text{color:var(--green); min-height:20px; font-weight:600; font-size:var(--fs-small)}

/* ---------- buttons ---------- */
.btn{
  border:1px solid var(--line); background:var(--panel2); color:var(--text);
  font-weight:700; font-size:16px; padding:12px 20px; border-radius:999px; min-height:48px;
  display:inline-flex; align-items:center; justify-content:center; gap:8px; text-decoration:none;
  transition:transform .1s ease;
}
.btn:active{transform:scale(.97)}
.btn-gold{background:var(--gold-grad); color:#171106; border-color:transparent; box-shadow:var(--shadow-gold)}
.btn-outline{background:transparent; border-color:var(--gold-lo); color:var(--gold-hi)}
.btn-ghost{background:transparent; border-color:transparent; color:var(--muted)}
.btn-danger{background:transparent; border-color:var(--danger); color:var(--danger)}
.btn-big{min-height:58px; font-size:18px; width:100%}
.btn-block{width:100%}
.btn-row{display:flex; gap:10px; flex-wrap:wrap; margin:0 0 16px}
.btn-col{display:flex; flex-direction:column; gap:10px}
.btn[disabled]{opacity:.45; pointer-events:none}

/* ---------- top bar / store switch ---------- */
.topbar{
  position:sticky; top:0; z-index:40; display:flex; align-items:center; justify-content:space-between;
  gap:12px; padding:calc(12px + env(safe-area-inset-top)) 18px 12px; background:#0d0a08; border-bottom:1px solid var(--line-soft);
}
.brand{display:flex; align-items:center; gap:11px; min-width:0}
.brand-name{font-weight:800; letter-spacing:.12em; font-size:15px; line-height:1}
.brand-name span{color:var(--gold)}
.brand-sub{font-size:12.5px; color:var(--muted); margin-top:3px}
.store-switch{
  position:sticky; top:65px; z-index:39; display:flex; gap:10px; padding:12px 18px;
  background:rgba(8,7,6,.92); backdrop-filter:blur(8px); overflow-x:auto;
}
.store-chip{
  flex:1 0 auto; border:1px solid var(--line); background:var(--panel); color:var(--muted);
  border-radius:999px; padding:12px 20px; font-weight:800; font-size:16px; min-height:50px;
}
.store-chip.active{background:var(--gold-grad); color:#171106; border-color:transparent; box-shadow:var(--shadow-gold)}

main{max-width:860px; margin:0 auto; padding:18px 18px 110px; position:relative}
.screen{display:none}
.screen.active{display:block; animation:screenIn .16s ease-out}
@keyframes screenIn{from{opacity:0} to{opacity:1}}
/* tab switch crossfade (160ms, consult Q4): as the incoming screen
   fades in (screenIn above), showScreen keeps the outgoing screen
   painted over it for the fade window — out of flow, opacity only,
   never touchable — then the class comes off and it hides. */
.screen.tab-leaving{
  display:block; position:absolute; top:18px; left:18px; right:18px;
  pointer-events:none; animation:tabOut .16s ease-in forwards;
}
@keyframes tabOut{from{opacity:1} to{opacity:0}}
.screen-title{font-size:28px; font-weight:800; margin:4px 0 8px}
.screen-sub{color:var(--muted); line-height:1.5; margin:0 0 18px}
.section-title{font-size:19px; font-weight:800; margin:24px 0 12px}
.back-link{background:none; border:0; color:var(--gold); font-size:15px; font-weight:700; padding:8px 0; min-height:44px}

/* ---------- stats + home actions ---------- */
.stats-row{display:grid; grid-template-columns:repeat(3,1fr); gap:10px; margin-bottom:18px}
.stat{
  background:linear-gradient(180deg, var(--panel2), var(--panel)); border:1px solid var(--line-soft);
  border-radius:var(--radius); padding:14px 10px; text-align:center; box-shadow:var(--shadow);
}
.stat b{display:block; font-size:26px; line-height:1.1}
.stat span{font-size:12.5px; color:var(--muted); font-weight:700; letter-spacing:.03em}
.stat.warn b{color:var(--danger)}
.big-actions{display:grid; gap:12px}
.action-card{
  display:flex; flex-direction:column; align-items:flex-start; gap:2px; text-align:left;
  background:linear-gradient(180deg, var(--panel2), var(--panel)); border:1px solid var(--line-soft);
  border-radius:var(--radius); padding:20px; color:var(--text); box-shadow:var(--shadow); min-height:104px;
}
.action-card:active{transform:scale(.98)}
.action-icon{font-size:28px}
.action-title{font-size:21px; font-weight:800}
.action-sub{color:var(--muted); font-size:var(--fs-small)}

/* ---------- inventories / products ---------- */
.inv-list{display:grid; gap:10px}
.inv-row{
  display:flex; align-items:center; justify-content:space-between; gap:12px; width:100%;
  background:var(--panel2); border:1px solid var(--line-soft); border-radius:var(--radius-sm);
  padding:16px 18px; color:var(--text); text-align:left; min-height:64px;
}
.inv-row:active{transform:scale(.99)}
.inv-name{font-weight:800; font-size:17px}
.inv-meta{color:var(--muted); font-size:var(--fs-small); margin-top:2px}
.inv-arrow{color:var(--gold); font-size:22px; font-weight:800}
.pill{
  display:inline-block; background:var(--danger); color:#fff; border-radius:999px;
  font-size:12.5px; font-weight:800; padding:2px 9px; vertical-align:middle;
}
.card{
  background:linear-gradient(180deg, var(--panel2), var(--panel));
  border:1px solid var(--line-soft); border-radius:var(--radius);
  padding:20px; margin:0 0 16px; box-shadow:var(--shadow);
}
.card-title{margin:0 0 10px; font-size:18px; font-weight:800}
.card-sub{color:var(--muted); font-size:var(--fs-small); line-height:1.5; margin:0 0 14px}
.search-row{display:flex; gap:10px; margin-bottom:12px}
.search-row input{flex:1; margin-top:0}
.chip-row{display:flex; gap:8px; flex-wrap:wrap; margin-bottom:14px}
.chip{
  border:1px solid var(--line); background:var(--panel); color:var(--muted);
  border-radius:999px; padding:9px 15px; font-weight:700; font-size:14.5px; min-height:44px;
}
.chip.active{background:var(--gold-grad); color:#171106; border-color:transparent}
.product-list{display:grid; gap:9px}
.product-row{
  display:flex; align-items:center; gap:12px; width:100%; text-align:left;
  background:var(--panel2); border:1px solid var(--line-soft); border-radius:var(--radius-sm);
  padding:13px 15px; color:var(--text); min-height:62px;
}
.product-row:active{transform:scale(.99)}
.product-main{flex:1; min-width:0}
.product-name{font-weight:700; font-size:16.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.product-meta{color:var(--muted); font-size:13px; margin-top:2px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.stock-badge{
  flex:0 0 auto; min-width:52px; text-align:center; padding:8px 10px; border-radius:12px;
  background:var(--panel3); border:1px solid var(--line); font-weight:800; font-size:17px;
}
.stock-badge small{display:block; font-size:10.5px; color:var(--muted); font-weight:700; letter-spacing:.06em}
.stock-badge.low{background:rgba(224,101,95,.16); border-color:var(--danger); color:#ffb3ae}
.order-qty{flex:0 0 auto; text-align:center; color:var(--gold-hi); font-weight:800}
.order-qty small{display:block; color:var(--muted); font-size:10.5px; font-weight:700; letter-spacing:.06em}
.empty-note{color:var(--muted); text-align:center; padding:26px 10px; font-weight:600}

/* ---------- history ---------- */
.history-list{display:grid; gap:8px}
.history-row{
  background:var(--panel2); border:1px solid var(--line-soft); border-radius:var(--radius-sm); padding:12px 15px;
}
.history-top{display:flex; justify-content:space-between; gap:10px; font-weight:700}
.history-change.pos{color:var(--green)} .history-change.neg{color:var(--danger)}
.history-meta{color:var(--muted); font-size:13px; margin-top:3px; line-height:1.45}

/* ---------- tab bar ---------- */
.tabbar{
  position:fixed; left:0; right:0; bottom:0; z-index:40; display:flex;
  background:#0d0a08; border-top:1px solid var(--line-soft); padding:6px 8px calc(6px + env(safe-area-inset-bottom));
}
.tab{
  flex:1; background:none; border:0; color:var(--muted); font-weight:700; font-size:12.5px;
  display:flex; flex-direction:column; align-items:center; gap:2px; padding:8px 4px; min-height:56px; border-radius:12px;
}
.tab span{font-size:21px}
.tab.active{color:var(--gold-hi); background:var(--panel2)}

/* ---------- scanner overlay ---------- */
.overlay{
  position:fixed; inset:0; z-index:80; background:#050403; display:flex; flex-direction:column;
  padding:16px 16px calc(16px + env(safe-area-inset-bottom));
}
.scanner-head{display:flex; align-items:center; justify-content:space-between; font-weight:800; font-size:18px; margin-bottom:12px}
.scanner-video-wrap{position:relative; flex:1; flex-shrink:1; border-radius:var(--radius); overflow:hidden; background:#000; min-height:200px}
.scanner-video-wrap video{width:100%; height:100%; object-fit:cover; display:block}
.scanner-frame{
  /* matches the centre decode region used by the scan loop (92% x 62%) */
  position:absolute; inset:19% 4%; border:2px solid var(--gold); border-radius:16px;
  box-shadow:0 0 0 9999px rgba(0,0,0,.45); pointer-events:none;
}
.scanner-hint{text-align:center; color:var(--muted); font-weight:600; margin:14px 0 10px}
.torch-btn{
  position:absolute; right:12px; bottom:12px; z-index:2; width:56px; height:56px; border-radius:50%;
  border:1px solid var(--line); background:rgba(23,19,16,.85); color:var(--text); font-size:24px;
}
.torch-btn.on{background:var(--gold-grad); color:#171106}
.home-search{margin-bottom:12px}
.scanner-manual{display:flex; gap:10px}
.scanner-manual input{flex:1; margin-top:0}

/* ---------- bottom sheet ---------- */
.sheet-wrap{position:fixed; inset:0; z-index:70}
.sheet-backdrop{position:absolute; inset:0; background:rgba(0,0,0,.6); touch-action:none}
.sheet{
  position:absolute; left:0; right:0; bottom:var(--vv-bottom,0px); max-height:min(92vh, calc(100vh - var(--vv-bottom,0px))); max-height:min(92dvh, calc(100dvh - var(--vv-bottom,0px))); overflow-y:auto; overscroll-behavior:contain; touch-action:pan-y;
  background:var(--panel); border-top:1px solid var(--line); border-radius:24px 24px 0 0;
  padding:10px 20px calc(22px + env(safe-area-inset-bottom)); animation:sheetIn .28s cubic-bezier(.32,.72,0,1);
}
@keyframes sheetIn{from{transform:translateY(48px); opacity:.3} to{transform:none; opacity:1}}
.sheet-out{transform:translateY(30px); opacity:0; transition:transform .2s ease-in, opacity .2s ease-in}
.sheet-handle{width:46px; height:5px; border-radius:99px; background:var(--line); margin:4px auto 14px}
.sheet-name{font-size:22px; font-weight:800; margin:0 0 2px}
.sheet-meta{color:var(--muted); font-size:var(--fs-small); margin-bottom:14px; line-height:1.5}
.sheet-stock{text-align:center; padding:14px; background:var(--panel2); border:1px solid var(--line-soft); border-radius:var(--radius); margin-bottom:16px}
.sheet-stock b{font-size:40px; line-height:1}
.sheet-stock span{display:block; color:var(--muted); font-size:12.5px; font-weight:700; letter-spacing:.06em; margin-top:4px}
.sheet-stock.low b{color:var(--danger)}
.mode-tabs{display:flex; gap:8px; margin-bottom:14px}
.mode-tab{flex:1; border:1px solid var(--line); background:var(--panel2); color:var(--muted); border-radius:12px; padding:13px 6px; font-weight:800; font-size:15.5px; min-height:50px}
.mode-tab.active{background:var(--gold-grad); color:#171106; border-color:transparent}
.qty-row{display:flex; align-items:stretch; gap:10px; margin-bottom:14px}
.qty-btn{width:60px; flex:none; min-height:44px; border-radius:14px; border:1px solid var(--line); background:var(--panel3); color:var(--text); font-size:26px; font-weight:800}
.qty-row input{text-align:center; font-size:22px; font-weight:800; margin-top:0}
.quick-row{display:flex; gap:8px; flex-wrap:wrap; margin-bottom:16px}
.quick-chip{border:1px solid var(--line); background:var(--panel2); color:var(--gold-hi); border-radius:999px; padding:9px 16px; font-weight:800; min-height:44px}
.sheet details{margin-top:16px; border-top:1px solid var(--line-soft); padding-top:12px}
.sheet summary{font-weight:800; color:var(--gold-hi); cursor:pointer; min-height:44px; display:flex; align-items:center}
.mini-history{margin-top:10px; display:grid; gap:7px}
.mini-history .history-row{padding:9px 12px}

/* ---------- users ---------- */
.user-row{display:flex; align-items:center; justify-content:space-between; gap:10px; padding:10px 0; border-bottom:1px solid var(--line-soft)}
.user-row:last-of-type{border-bottom:0}
.user-meta{color:var(--muted); font-size:13px}
.user-row .btn{min-height:44px; padding:8px 14px; font-size:14px}

/* ---------- toast ---------- */
.toast{
  position:fixed; left:50%; transform:translateX(-50%); bottom:calc(92px + env(safe-area-inset-bottom)); z-index:90;
  background:var(--panel3); border:1px solid var(--gold-lo); color:var(--text); font-weight:700;
  padding:13px 20px; border-radius:999px; box-shadow:var(--shadow); max-width:92vw; text-align:center;
}
.toast.error{border-color:var(--danger); color:#ffb3ae}

@media (min-width:640px){
  .big-actions{grid-template-columns:repeat(3,1fr)}
  .inv-list{grid-template-columns:1fr 1fr}
}

/* ================= v2 additions ================= */
/* sync pill */
.sync-pill{
  margin:10px 14px 0; padding:10px 14px; border-radius:999px; font-size:var(--fs-small);
  font-weight:700; text-align:center; border:1px solid var(--line-soft); background:var(--panel);
  color:var(--muted);
}
.sync-pill.ok{color:var(--green); border-color:rgba(93,187,132,.35)}
.sync-pill.offline{color:var(--gold-hi); border-color:rgba(217,164,65,.4)}
.sync-pill.syncing{color:var(--gold-hi)}
.sync-pill.error{color:#ffd9d6; background:#3a1713; border-color:var(--danger)}
.pill-btn{
  margin-left:8px; padding:6px 12px; min-height:44px; border-radius:999px;
  border:1px solid var(--gold); background:transparent; color:var(--gold-hi); font-weight:800;
}
/* four scan modes */
.mode-grid{display:grid; grid-template-columns:1fr 1fr; gap:12px; margin:14px 0 4px}
.mode-grid .action-card{min-height:118px}
.mode-receive{border-color:rgba(93,187,132,.45)}
.mode-out{border-color:rgba(224,101,95,.4)}
.mode-switch{display:flex; gap:8px; padding:10px 14px 0; flex-wrap:wrap}
.mode-switch button{
  flex:1; min-height:56px; border-radius:999px; border:1px solid var(--line);
  background:var(--panel2); color:var(--text); font-weight:800; font-size:16px; padding:10px 6px;
}
.mode-switch button.active{background:var(--gold-grad); color:#171106; border-color:transparent}
.chip-static{
  display:inline-flex; align-items:center; padding:10px 14px; border-radius:999px;
  background:var(--panel3); color:var(--gold-hi); font-weight:700; font-size:var(--fs-small);
}
/* scan flash + tally */
.scan-flash{
  margin:10px 14px 0; padding:14px 16px; border-radius:var(--radius-sm);
  background:var(--panel2); border:1px solid var(--gold); color:var(--text);
  display:flex; flex-direction:column; gap:2px; font-size:16px;
}
.scan-flash span{color:var(--muted); font-size:var(--fs-small); font-weight:600}
/* v7.4: raw scanned digits — monospace + letter-spaced so a digit-by-digit
   match against the printed barcode on the package is easy. Display only;
   the value itself is never altered. */
.barcode-digits{font-family:ui-monospace,'SF Mono',Menlo,Consolas,monospace; letter-spacing:.14em; font-weight:700}
.scan-flash.error{border-color:var(--danger); background:#2c130f}
.scan-flash.case{border-color:var(--green)}
.scan-flash.case .btn{margin-top:10px}
.tally-head{
  display:flex; justify-content:space-between; align-items:center;
  padding:16px 14px 6px; font-weight:800; letter-spacing:.02em;
}
.tally-list{padding:0 14px 30px; display:flex; flex-direction:column; gap:8px}
.tally-row{
  display:flex; justify-content:space-between; align-items:center; gap:12px;
  background:var(--panel); border:1px solid var(--line-soft); border-radius:var(--radius-sm); padding:12px 14px;
}
.tally-row.transfer{border-color:var(--gold)}
.tally-main{display:flex; flex-direction:column; min-width:0}
.tally-main span{color:var(--muted); font-size:var(--fs-small); font-weight:600}
.tally-qty{font-size:22px; font-weight:800; color:var(--gold-hi)}
/* photos */
.row-photo{
  width:52px; height:52px; border-radius:12px; object-fit:cover; flex:none;
  background:var(--panel3); display:flex; align-items:center; justify-content:center;
  font-weight:800; color:var(--gold); font-size:22px;
}
.product-row{gap:12px}
.variant-label{color:var(--gold-hi); font-weight:700}
.tile-grid{display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-top:12px}
.tile{
  background:var(--panel2); border:1px solid var(--line); border-radius:var(--radius-sm);
  padding:12px; display:flex; flex-direction:column; gap:4px; align-items:flex-start; text-align:left; color:var(--text);
  min-height:120px;
}
.tile-photo{width:100%; height:110px; border-radius:10px; object-fit:cover; background:var(--panel3);
  display:flex; align-items:center; justify-content:center; font-size:34px; color:var(--gold); font-weight:800}
.tile-name{font-weight:800; font-size:16px}
.tile-sub{color:var(--muted); font-size:var(--fs-small); font-weight:600}
.sheet-photo-row{display:flex; align-items:center; gap:14px; margin-bottom:10px}
.sheet-photo{width:86px; height:86px; border-radius:16px; object-fit:cover; background:var(--panel3);
  display:flex; align-items:center; justify-content:center; font-size:38px; color:var(--gold); font-weight:800}
.qty-by-store{display:grid; grid-template-columns:1fr 1fr; gap:10px; margin:12px 0}
.qbs{background:var(--panel2); border:1px solid var(--line-soft); border-radius:var(--radius-sm); padding:12px; text-align:center}
.qbs.here{border-color:var(--gold)}
.qbs b{display:block; font-size:28px}
.qbs span{color:var(--muted); font-size:12px; font-weight:700; letter-spacing:.04em}
.lookup-banner{
  background:var(--panel3); border:1px solid var(--gold); border-radius:var(--radius-sm);
  padding:12px 14px; margin-bottom:14px; font-size:var(--fs-small); font-weight:600;
}
.lookup-banner .btn{margin-left:8px; min-height:44px}
/* install card */
.install-card{margin:12px 14px 0}
.install-steps{display:flex; flex-direction:column; gap:12px; margin:10px 0 14px}
.install-step{display:flex; gap:12px; align-items:flex-start}
.install-num{
  flex:none; width:34px; height:34px; border-radius:50%; background:var(--gold-grad); color:#171106;
  display:flex; align-items:center; justify-content:center; font-weight:800;
}
.install-step p{margin:4px 0 0; font-size:var(--fs-small); font-weight:600; color:var(--text)}
.install-icon{font-size:20px; color:var(--gold-hi)}
/* reorder groups */
.supplier-title{margin:22px 0 8px; font-size:18px; color:var(--gold-hi); letter-spacing:.02em}
/* two-col forms */
.two-col{display:grid; grid-template-columns:1fr 1fr; gap:12px}
/* labels: hidden on screen, the only thing printed */
#label-print{display:none}
@media print{
  body>*{display:none !important}
  body>#label-print{display:block !important}
  #label-print .label-grid{display:flex; flex-wrap:wrap; gap:6mm}
  #label-print .label{
    border:1px solid #999; border-radius:4px; padding:3mm; text-align:center;
    width:60mm; color:#000; background:#fff; page-break-inside:avoid; break-inside:avoid;
  }
  #label-print .label.thermal{width:57mm}
  #label-print .label img{max-width:100%; height:14mm; object-fit:contain}
  #label-print .label-name{font-weight:800; font-size:11pt}
  #label-print .label-variant{font-size:9pt}
  #label-print .label-code{font-size:9pt; font-family:monospace}
}

/* ---------- v3 additions ---------- */
.store-dot{display:inline-block; width:11px; height:11px; border-radius:50%; margin-right:8px; vertical-align:baseline}
.hold-badge{
  display:inline-block; background:#5a1710; color:#ffb4a2; border:1px solid var(--danger);
  border-radius:999px; padding:2px 9px; font-size:12px; font-weight:800; letter-spacing:.04em; margin-left:8px; vertical-align:middle;
}
.hold-banner{
  background:#2c130f; border:1px solid var(--danger); color:#ffb4a2; border-radius:12px;
  padding:12px 14px; font-weight:700; margin:10px 0; line-height:1.45;
}
.zoom-btn{left:12px; right:auto; bottom:12px; font-size:17px; font-weight:800; width:auto; min-width:56px; padding:0 12px}
.snap-btn{left:12px; right:auto; bottom:80px; font-size:14px; font-weight:800; width:auto; padding:0 14px; border-radius:999px}
.check-row{display:flex; gap:10px; align-items:flex-start; font-weight:600; line-height:1.4; margin:10px 0}
.check-row input{width:24px; height:24px; flex:0 0 auto; margin-top:1px}
.merge-row{display:flex; gap:10px; align-items:center}
.merge-row input{width:24px; height:24px; flex:0 0 auto}
.lock-overlay{
  position:fixed; inset:0; z-index:90; background:rgba(5,4,3,.96);
  display:flex; align-items:center; justify-content:center; padding:20px;
  overflow-y:auto; overscroll-behavior:contain; touch-action:pan-y;
}
/* v7.7.2 audit: margin:auto centring — with overflow-y:auto on the
   overlay, a card taller than the viewport (qty keypad, long user
   list, keyboard open) scrolls from its TOP instead of clipping it
   above the fold, unreachable (the ni-card trap's centred cousin). */
.lock-card{width:100%; max-width:380px; text-align:left; margin:auto}
.lock-card .logo-badge{margin-bottom:12px}
.lock-card .btn{min-height:56px}

/* ---------- v7.0: the mode is the colour of the whole screen ---------- */
#scanner.mode-count{background:linear-gradient(180deg,#2b1d05,#171106 240px)}
#scanner.mode-receive{background:linear-gradient(180deg,#0d2b1a,#0a1710 240px)}
#scanner.mode-out{background:linear-gradient(180deg,#33120e,#1a0d0a 240px)}
#scanner.mode-lookup{background:linear-gradient(180deg,#101d2e,#0b0f16 240px)}
#scanner.mode-count .scanner-head{border-bottom:3px solid var(--gold)}
#scanner.mode-receive .scanner-head{border-bottom:3px solid var(--green)}
#scanner.mode-out .scanner-head{border-bottom:3px solid var(--danger)}
#scanner.mode-lookup .scanner-head{border-bottom:3px solid #5b8dd9}
.scan-total{
  margin:12px 14px 0; padding:14px 16px; text-align:center;
  font-size:26px; font-weight:900; letter-spacing:.01em; color:var(--gold-hi);
  background:var(--panel2); border:1px solid var(--gold); border-radius:var(--radius-sm);
}
#scanner.mode-receive .scan-total{border-color:var(--green); color:#9fe8bb}
/* suggestion card (wholesaler / internet name) */
.scan-suggest{
  margin:10px 14px 0; padding:14px 16px; border-radius:var(--radius-sm);
  background:var(--panel2); border:2px solid var(--gold); display:flex; flex-direction:column; gap:8px;
}
.scan-suggest.hidden{display:none}
.suggest-src{font-weight:800; color:var(--gold-hi)}
.scan-suggest label{display:flex; flex-direction:column; gap:4px; font-size:var(--fs-small); color:var(--muted); font-weight:700}
.scan-suggest input,.scan-suggest select{
  min-height:52px; border-radius:10px; border:1px solid var(--line); background:var(--panel3);
  color:var(--text); font-size:17px; padding:10px 12px;
}
/* full-screen hold warning */
.hold-overlay{
  position:fixed; inset:0; z-index:90; background:#4a0d08;
  display:flex; align-items:center; justify-content:center; padding:20px;
  overflow-y:auto; overscroll-behavior:contain; touch-action:pan-y;
}
.hold-overlay.hidden{display:none}
.hold-card{text-align:center; max-width:420px; width:100%; margin:auto}
.hold-big{font-size:42px; font-weight:900; color:#ffb3ab; letter-spacing:.01em}
.hold-name{font-size:24px; font-weight:800; margin-top:14px}
.hold-meta{color:#ffd9d6; margin-top:6px}
.hold-note{color:#f3c6c0; margin:14px 0 20px}
/* quantity keypad */
.qty-display{
  font-size:44px; font-weight:900; text-align:center; padding:12px; margin:10px 0;
  background:var(--panel3); border:1px solid var(--gold); border-radius:var(--radius-sm); color:var(--gold-hi);
}
.qty-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:8px; margin-bottom:12px}
.qty-grid button{
  min-height:58px; font-size:22px; font-weight:800; border-radius:12px;
  background:var(--panel2); border:1px solid var(--line); color:var(--text);
}
.qty-grid button:active{background:var(--gold-grad); color:#171106}
.hold-banner.upcoming{border-color:var(--gold); background:#2b2108; color:var(--gold-hi)}
.scanner-actions{padding:2px 14px 0}
.scan-review{margin:10px 14px 0}

/* ================= v7.5: experience build ================= */
/* --- Pill-overlap fix (owner finding 4): every status element owns a
   layout slot. The scanner column never shrinks a status element
   (flex-shrink: 0), labels truncate with an ellipsis instead of
   pushing content around (min-width: 0 + nowrap), and the hint's
   height is reserved whether the camera is running, resting, or
   refused — filled values never shift the layout. --- */
.overlay{overflow-y:auto; overscroll-behavior:contain; touch-action:pan-y}
.overlay>*{flex-shrink:0}
.scanner-status{display:flex; flex-direction:column; flex-shrink:0; min-width:0}
.scanner-status .scanner-hint{
  flex-shrink:0; min-height:44px; margin:10px 0 0; padding:0 10px;
  display:flex; align-items:center; justify-content:center;
}
.scanner-status .scan-total{flex-shrink:0; margin:8px 14px 0}
.scan-flash{flex-shrink:0}
.tally-head #tally-title{min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.tally-main b{min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.tally-main span{min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.tally-main .barcode-digits{white-space:normal; overflow:visible}

/* --- scan feedback rings (consult Q4): 180ms success / 240ms error,
   transform + opacity only, on a pseudo ring over the decode frame --- */
.scanner-frame::after{
  content:''; position:absolute; inset:-3px; border-radius:18px; pointer-events:none;
  border:3px solid var(--green); opacity:0;
}
#scanner.pulse-ok .scanner-frame::after{animation:ringOk .18s ease-out}
#scanner.pulse-err .scanner-frame::after{border-color:var(--danger); animation:ringErr .24s ease-out}
@keyframes ringOk{0%{opacity:.95; transform:scale(1.05)} 100%{opacity:0; transform:scale(1)}}
@keyframes ringErr{0%{opacity:.95; transform:scale(1.05)} 100%{opacity:0; transform:scale(1)}}
/* mode switch crossfade (200ms) */
#scanner.mode-anim{animation:modeFade .2s ease-out}
@keyframes modeFade{from{opacity:.25} to{opacity:1}}
/* tally motion: new row 200ms in, count digit 120ms pop */
.tally-row.tally-in{animation:tallyIn .2s ease-out}
@keyframes tallyIn{from{opacity:0; transform:translateY(8px)} to{opacity:1; transform:none}}
.tally-qty.qty-pop{animation:qtyPop .12s ease-out}
@keyframes qtyPop{0%{transform:scale(1.3)} 100%{transform:scale(1)}}
/* chips: press 80ms, select 120ms (consult Q4) */
.chip{transition:transform .08s ease, background-color .12s ease, color .12s ease, border-color .12s ease}

/* --- undo bar: 200ms in, 5s scaleX countdown (consult Q4) --- */
.undo-bar{
  margin:8px 14px 0; padding:10px 12px 13px; border-radius:999px; position:relative; overflow:hidden;
  background:var(--panel3); border:1px solid var(--gold-lo);
  display:flex; align-items:center; gap:12px; animation:undoIn .2s ease-out;
}
@keyframes undoIn{from{opacity:0; transform:translateY(8px)} to{opacity:1; transform:none}}
.undo-bar span{flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; font-weight:700; font-size:var(--fs-small)}
.undo-bar .btn{min-height:44px; padding:6px 18px}
.undo-count{position:absolute; left:0; bottom:0; width:100%; height:3px; background:rgba(217,164,65,.18)}
#undo-count-fill{height:100%; width:100%; background:var(--gold); transform-origin:left center; transform:scaleX(1)}
#undo-count-fill.run{animation:undoCount 5s linear forwards}
@keyframes undoCount{from{transform:scaleX(1)} to{transform:scaleX(0)}}

/* --- variant run strip + summary --- */
.run-strip{
  margin:10px 14px 0; padding:10px 14px; border-radius:var(--radius-sm);
  background:var(--panel3); border:1px dashed var(--gold-lo);
  font-size:var(--fs-small); font-weight:600; display:flex; align-items:center; gap:10px; flex-wrap:wrap;
}
.run-strip .btn{margin-left:auto; min-height:44px; padding:6px 14px}
.run-row{display:flex; gap:12px; padding:12px 0; border-bottom:1px solid var(--line-soft)}
.run-row img{width:64px; height:64px; border-radius:12px; object-fit:cover; flex:none; background:var(--panel3)}
.run-nophoto{
  width:64px; height:64px; border-radius:12px; background:var(--panel3); color:var(--muted);
  font-size:11px; font-weight:700; display:flex; align-items:center; justify-content:center; text-align:center; flex:none; padding:4px;
}
.run-row-main{flex:1; min-width:0; display:flex; flex-direction:column; gap:4px}
.run-row-main input{margin-top:0; min-height:44px}
.run-row-main .sheet-meta{margin-bottom:0}
.run-flag{color:var(--gold-hi); font-size:13px; font-weight:700}

/* --- the new-item card (consult Q1): a bottom sheet over the live
   camera. Two heights — photo height (~38%) when a lookup found
   nothing, full (~62%) when a name exists or after the photo — with a
   240ms height change; in 280ms on the sheet easing, out 200ms. The
   top edge takes the mode colour, like the scanner itself. --- */
.ni-card{
  position:fixed; left:0; right:0; bottom:var(--vv-bottom,0px); z-index:85;
  height:38vh; height:38dvh; max-height:min(94vh, calc(100vh - var(--vv-bottom,0px))); max-height:min(94dvh, calc(100dvh - var(--vv-bottom,0px))); overflow-y:auto; overscroll-behavior:contain; touch-action:pan-y;
  background:var(--panel); border-top:3px solid var(--gold); border-radius:24px 24px 0 0;
  padding:12px 18px calc(16px + env(safe-area-inset-bottom));
  box-shadow:0 -12px 40px rgba(0,0,0,.55);
  animation:niIn .28s cubic-bezier(.32,.72,0,1);
  transition:height .24s cubic-bezier(.32,.72,0,1);
}
/* v7.7.1 (owner field bug, Nov 7 2026): the card must NOT be a flex
   container. It used to be display:flex column AND its own
   overflow-y:auto scroll container; iOS Safari does not scroll that
   combination (the flex items' automatic minimum size is their content
   height, and the content is ~1.6x the card height), so everything
   below the fold — pack/save included — was unreachable on the phone.
   The scrolled content is plain block flow now; the 10px rhythm the
   flex gap used to provide comes from this sibling margin instead. */
.ni-card>*+*{margin-top:10px}
.ni-card.ni-tall{height:62vh; height:62dvh}
/* v7.7.2 audit (§2.2): in an installed (standalone) app, WebKit bug
   254868 makes dvh report the height MINUS the safe-area insets, so
   the dvh-sized sheets sit shorter than intended there. vh includes
   the insets in standalone; size the sheets from vh in that mode. */
@media (display-mode: standalone){
  .sheet{max-height:min(92vh, calc(100vh - var(--vv-bottom,0px)))}
  .ni-card{height:38vh}
  .ni-card.ni-tall{height:62vh}
}
.ni-card.ni-out{transform:translateY(30px); opacity:0; transition:transform .2s ease-in, opacity .2s ease-in}
@keyframes niIn{from{transform:translateY(56px); opacity:.3} to{transform:none; opacity:1}}
#scanner.mode-receive .ni-card{border-top-color:var(--green)}
#scanner.mode-out .ni-card{border-top-color:var(--danger)}
#scanner.mode-lookup .ni-card{border-top-color:#5b8dd9}
.ni-session{font-size:12px; color:var(--faint); font-weight:700; letter-spacing:.05em; text-transform:uppercase; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-height:16px}
.ni-head{display:flex; align-items:center; gap:12px; min-height:40px}
.ni-title{font-weight:900; letter-spacing:.08em; font-size:15px; color:var(--gold-hi); flex:none}
.ni-digits{font-size:15px; flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.ni-x{margin-left:auto; width:44px; height:44px; border-radius:50%; border:1px solid var(--line); background:var(--panel2); color:var(--text); font-size:16px; flex:none}
.ni-banner{margin:0; color:var(--muted); font-size:var(--fs-small); line-height:1.45}
.ni-runline{margin:0; font-size:var(--fs-small); color:var(--muted)}
.ni-photo-row{display:flex; gap:12px; align-items:stretch}
.ni-photo{
  width:92px; height:92px; border-radius:16px; background:var(--panel3); border:1px solid var(--line-soft);
  overflow:hidden; flex:none; display:flex; align-items:center; justify-content:center; text-align:center;
}
.ni-photo img{width:100%; height:100%; object-fit:cover}
.ni-photo-none{color:var(--muted); font-size:12px; font-weight:700; padding:6px}
.ni-snap{flex:1; min-height:56px}
.ni-field{display:flex; flex-direction:column; gap:5px}
.ni-field-top{display:flex; align-items:baseline; gap:8px; min-height:20px}
.ni-label{font-size:12.5px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--muted); flex:none}
.ni-src{font-size:12px; color:var(--gold-hi); font-weight:600; flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.ni-pin{background:none; border:0; font-size:16px; padding:2px 4px; flex:none; min-width:44px; min-height:44px}
.ni-value{
  text-align:left; min-height:52px; padding:12px 14px; border-radius:var(--radius-sm); width:100%;
  background:var(--panel2); border:1px solid var(--line); color:var(--text); font-size:17px; font-weight:700;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.ni-value:not(.ni-filled){color:var(--faint); font-weight:600}
.ni-value.ni-filled{animation:fieldFill .12s ease-out}
@keyframes fieldFill{from{background:var(--panel3)} to{background:var(--panel2)}}
.ni-editor{display:flex; flex-wrap:wrap; gap:8px; align-items:center}
.ni-chip{
  border:1px solid var(--line); background:var(--panel); color:var(--text); border-radius:999px;
  padding:9px 14px; font-weight:700; font-size:14.5px; min-height:44px;
  display:inline-flex; align-items:center; gap:7px;
  transition:transform .08s ease, background-color .12s ease, color .12s ease, border-color .12s ease;
}
.ni-chip:active{transform:scale(.96)}
.ni-chip-sel{background:var(--gold-grad); color:#171106; border-color:transparent}
.ni-chip-src{font-size:11px; font-weight:700; opacity:.75}
.ni-typerow{display:flex; gap:8px; flex:1; min-width:200px; align-items:center}
.ni-typerow input{margin-top:0; flex:1}
.ni-cats{display:flex; flex-direction:column; gap:6px}
.ni-chips{display:flex; flex-wrap:wrap; gap:8px; min-height:44px}
.ni-morecats{display:flex; flex-wrap:wrap; gap:8px}
.ni-qtyrow{display:flex; align-items:center; gap:12px}
.ni-qtyrow .ni-label{flex:1}
.ni-qty-num{min-width:64px; min-height:52px; border-radius:14px; border:1px solid var(--gold-lo); background:var(--panel2); color:var(--gold-hi); font-size:20px; font-weight:800}
.ni-packrow{display:flex; gap:10px; position:sticky; bottom:0; background:var(--panel); padding:6px 0 2px}
.ni-pack{
  flex:1; min-height:60px; border-radius:16px; font-size:18px; font-weight:800;
  background:var(--panel2); border:1px solid var(--line); color:var(--text);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px; padding:8px;
}
.ni-pack span{font-size:12.5px; font-weight:700; color:var(--muted)}
.ni-pack:active{transform:scale(.98)}
.ni-boxchips{display:flex; flex-wrap:wrap; gap:8px}
.ni-note{margin:0; color:var(--muted); font-size:13px; line-height:1.45}

/* --- reduced motion (consult Q4): slides and scales become short
   fades; the undo countdown is information, so it still runs --- */
@keyframes sheetInR{from{opacity:0} to{opacity:1}}
@keyframes niInR{from{opacity:0} to{opacity:1}}
@media (prefers-reduced-motion: reduce){
  .sheet{animation-name:sheetInR; animation-duration:.2s}
  .sheet-out{transition-duration:.15s}
  /* v7.7.3 (stage-3 smoothness): under reduced motion the ni-card's
     HEIGHT transition is removed outright, not merely shortened —
     the bottom-anchored card grows by snapping (a transform cannot
     replicate a bottom-anchored sheet growing upward without
     distorting content or unpinning the edge, so the height
     transition stays for the motion-allowed case, 240ms, on a
     deliberate tap only — see the QA note). The .ni-out exit keeps
     its own higher-specificity transform/opacity transition below. */
  .ni-card{animation-name:niInR; animation-duration:.2s; transition:none}
  .ni-card.ni-out{transition-duration:.15s}
  #scanner.pulse-ok .scanner-frame::after, #scanner.pulse-err .scanner-frame::after{animation-duration:.01s}
  .screen.tab-leaving{animation-duration:.01s}
  .tally-row.tally-in{animation:none}
  .tally-qty.qty-pop{animation:none}
  .undo-bar{animation:none}
  #scanner.mode-anim{animation:none}
  .ni-value.ni-filled{animation:none}
  .btn:active, .ni-chip:active, .ni-pack:active{transform:none}
}
/* v7.7.3 (stage-3 smoothness): reduced transparency. The app's ONLY
   backdrop-filter is the store-switch bar's 8px blur over scrolling
   page content (never over the scanner video — the audit verified
   no filter sits on the camera layer). Under this preference the
   bar goes fully opaque and the blur comes off entirely. */
@media (prefers-reduced-transparency: reduce){
  .store-switch{
    background:rgb(8,7,6);
    backdrop-filter:none;
  }
}
