/* ============================================================================
   ByteCraft POS — /static/core/ui.css
   Shared components (SPEC.md §2–§4) for BOTH the owner dashboard and the till.
   Requires /static/brand/colors.css + /static/core/tokens.css loaded first.
   Till-only screens (§5 keypad, method rows, verdict wells) live in /till/.

   Expected DOM skeletons:
   Dashboard:  <body class="shell-dash">
                 <header class="topbar is-navy">…</header>      (<768 only)
                 <nav class="sidenav is-navy">                  (≥768)
                   <div class="brand">logo + .mname + .sectag</div>
                   <div class="scrollarea"><nav class="snav">…</nav></div>
                   <div class="foot">mode + sign out rows</div>
                 </nav>
                 <main class="content"><div class="page">…</div></main>
                 <nav class="bnav">…</nav>                      (<768 only)
   Till:       <body class="shell-till">
                 <header class="topbar is-navy">…</header>
                 <div class="till-layout">
                   <main class="pane">scanwrap + pgrid …</main>
                   <aside class="cartcol">carthead/cartbody/cartfoot</aside>
                 </div>
                 <nav class="bnav">…</nav>                      (<768 only)
   ============================================================================ */

/* ====== 1. App shells ==================================================== */

/* Navy top header — dashboard <768, till at every width */
.topbar { position: sticky; top: 0; z-index: var(--z-nav); display: flex;
  align-items: center; gap: 12px; height: 56px; padding: 0 16px;
  background: var(--navy); color: #fff; }
.topbar .logo { height: 24px; display: block; }
.topbar .ttl { font: 600 var(--fs-base) var(--font-ui); color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar .grow { flex: 1; }

/* Sidenav — one element: icon rail 72px (768–1023), sidebar 248px (≥1024) */
.sidenav { display: none; }
@media (min-width: 768px) {
  .shell-dash .topbar { display: none; }
  .bnav { display: none; }
  .sidenav { display: flex; flex-direction: column; position: fixed;
    left: 0; top: 0; bottom: 0; width: 72px; background: var(--navy);
    z-index: var(--z-nav); }
  .sidenav .scrollarea { flex: 1; overflow-y: auto; overflow-x: hidden; }
  .sidenav .foot { margin-top: auto; flex: none; padding: 8px 12px 12px;
    border-top: 1px solid rgba(255,255,255,.1); }
  .shell-dash .content { margin-left: 72px; padding: 24px; }
}
@media (min-width: 1024px) {
  .sidenav { width: 248px; }
  .shell-dash .content { margin-left: 248px; padding: 32px; }
}
/* Sidebar brand block (≥1024); rail collapses it to the logo mark */
.sidenav .brand { padding: 24px; }
.sidenav .brand img { height: 28px; display: block; }
.sidenav .mname { margin-top: 12px; font: 600 0.9375rem/1.3 var(--font-ui);
  color: #fff; }
.sidenav .sectag { display: inline-flex; margin-top: 6px; padding: 2px 8px;
  border-radius: var(--r-full); background: rgba(241,181,39,.12);
  color: var(--gold); font: 600 var(--fs-2xs)/1.3 var(--font-ui); }
@media (min-width: 768px) and (max-width: 1023.98px) {
  .sidenav .brand { padding: 16px 0; display: flex; justify-content: center; }
  /* The wordmark PNG is ~5x wider than tall — crop to the dot mark so it
     can't bleed out of the 72px rail onto the page title. */
  .sidenav .brand img { height: 26px; width: 30px; object-fit: cover;
    object-position: left center; }
  .sidenav .mname, .sidenav .sectag, .snav .grp, .snav .lbl { display: none; }
  .snav { padding: 8px 14px; align-items: center; }
  .snav a, .snav button { width: 44px; height: 44px; justify-content: center;
    padding: 0; gap: 0; }
  .snav a.active::before { left: -14px; } /* bar hugs the rail's left edge */
}

/* Dashboard content column */
.shell-dash .content { padding: 16px;
  padding-bottom: calc(88px + env(safe-area-inset-bottom)); }
.page { display: flex; flex-direction: column; gap: var(--sp-6); }
.shell-dash .page { max-width: 1240px; margin: 0 auto; }

/* Page header: title + live indicator left, actions right */
.pagehead { display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); flex-wrap: wrap; }
.pagehead .phl { display: flex; align-items: baseline; gap: var(--sp-3); }
.pagehead h1 { margin: 0; font-size: var(--fs-xl); font-weight: 700;
  line-height: 1.25; color: var(--ink); }
.pagehead .actions { display: flex; align-items: center; gap: var(--sp-3); }

/* Block grids (§2.1): KPI row, chart row, list panels row */
.kpis { display: grid; gap: 16px; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 1280px) { .kpis { grid-template-columns: repeat(4, 1fr); } }
.kpis.cols5 { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.row-chart { display: grid; gap: var(--sp-6); grid-template-columns: 1fr; }
.row-2 { display: grid; gap: var(--sp-6); grid-template-columns: 1fr; }
@media (min-width: 1024px) {
  .row-chart { grid-template-columns: 1fr 360px; }
  .row-2 { grid-template-columns: repeat(2, 1fr); }
}

/* Till shell */
.shell-till .pane { padding: 12px;
  padding-bottom: calc(88px + env(safe-area-inset-bottom)); }
.shell-till .pane.with-cartbar {                    /* clears gold cart bar */
  padding-bottom: calc(156px + env(safe-area-inset-bottom)); }
.cartcol { display: none; }
@media (min-width: 768px) {
  .till-layout { display: grid; grid-template-columns: 1fr 340px;
    height: calc(100vh - 56px); }
  .shell-till .pane { overflow-y: auto; min-width: 0; padding: 16px; }
  .shell-till .scanwrap { top: 0; } /* header sits outside the scroll pane */
  .cartcol { display: flex; flex-direction: column; min-height: 0;
    background: var(--surface); border-left: 1px solid var(--line); }
}
@media (min-width: 1024px) {
  .till-layout { grid-template-columns: 1fr 384px; }
  .shell-till .pane { padding: 24px; }
}
/* Cart panel regions — shared by the cart column and the mobile cart sheet */
.carthead { flex: none; display: flex; align-items: center;
  justify-content: space-between; gap: 8px; padding: 16px;
  font: 600 var(--fs-base) var(--font-ui); color: var(--ink); }
.cartbody { flex: 1; min-height: 0; overflow-y: auto; padding: 0 16px; }
.cartfoot { flex: none; padding: 16px; border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: var(--sp-3); }

/* ====== 2. Cards ========================================================= */
.card { background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1); }
.card.pad { padding: var(--sp-5); }
.cardhead { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: var(--sp-5) var(--sp-5) 0;
  font-size: var(--fs-base); font-weight: 600; color: var(--ink); }
.cardbody { padding: var(--sp-2) var(--sp-5) var(--sp-3); }

/* ====== 3. KPI card (§3.1) =============================================== */
.kpi { background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1); padding: var(--sp-5); }
.kpi .label { font-size: var(--fs-xs); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: var(--sp-2); }
.kpi .value { font-size: var(--fs-2xl); font-weight: 700; line-height: 1.15;
  letter-spacing: -.01em; color: var(--ink); font-variant-numeric: tabular-nums; }
.kpi .value .cur { font-size: .65em; font-weight: 600; margin-right: 1px; }
.kpi .value.pos { color: var(--pos); }   /* profit when > 0 — used sparingly */
.kpi .value.neg { color: var(--neg); }
.kpi .delta { display: inline-flex; align-items: center; gap: 3px;
  font-size: var(--fs-xs); font-weight: 600; border-radius: var(--r-full);
  padding: 2px 8px; margin-left: var(--sp-2); vertical-align: 4px; }
.kpi .delta.up   { color: var(--pos); background: var(--pos-bg); }
.kpi .delta.down { color: var(--neg); background: var(--neg-bg); }
.kpi .sub { font-size: var(--fs-sm); color: var(--ink-3); margin-top: var(--sp-1); }
@media (max-width: 599px) { .kpi .value { font-size: 1.5rem; } }
@media (max-width: 599px) { .kpi { padding: var(--sp-4); } }

/* ====== 4. Chart frame, legend, tooltip, caption (§3.2 + §4) ============= */
.chartcard { background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1); padding: var(--sp-5); }
.chartcard .chead { display: flex; align-items: flex-start;
  justify-content: space-between; gap: 12px; flex-wrap: wrap;
  margin-bottom: var(--sp-3); }
.chartcard .ctitle { font-size: var(--fs-base); font-weight: 600;
  color: var(--ink); display: flex; align-items: center; gap: 8px; }
.chartcard .hero { display: block; margin-top: 2px; font-size: var(--fs-xl);
  font-weight: 700; color: var(--navy); font-variant-numeric: tabular-nums; }
.chartcard .plot { position: relative; height: 200px; }
.chartcard .plot svg { display: block; width: 100%; height: 100%; }
@media (max-width: 767px) { .chartcard .plot { height: 160px; } }

/* Legend: 10px swatch r3 + label + value */
.legend { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.legend .li { display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); color: var(--ink-3); }
.legend .sw { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.legend .lv { font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums; }
.legend.col { flex-direction: column; align-items: stretch; gap: 8px; }
.legend.col .li { display: flex; }
.legend.col .lv { margin-left: auto; }
.donutrow { display: flex; align-items: center; gap: var(--sp-5); }
.donutrow .legend.col { flex: 1; min-width: 0; }

/* Tooltip — HTML overlay, hover-capable devices only (§4) */
.charttip { position: absolute; z-index: var(--z-toast); background: #0e1b2c;
  color: #fff; font-size: var(--fs-xs); border-radius: var(--r-sm);
  padding: 8px 12px; box-shadow: var(--shadow-2); pointer-events: none;
  white-space: nowrap; }
.charttip .b { display: block; font-weight: 600; margin-bottom: 2px; }
.charttip .row { display: flex; align-items: center; gap: 6px; }
.charttip .sw { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.charttip .row .num { margin-left: auto; padding-left: 10px; }

/* Touch caption row under the SVG — replaces the floating tooltip on touch */
.chartcap { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px;
  margin-top: var(--sp-2); min-height: 18px; font-size: var(--fs-xs);
  color: var(--ink-2); font-variant-numeric: tabular-nums; }
.chartcap .b { font-weight: 600; color: var(--ink); }
.chartcap .sw { width: 8px; height: 8px; border-radius: 2px;
  display: inline-block; flex: none; }
@media (hover: hover) and (pointer: fine) { .chartcap { display: none; } }

/* Horizontal category bars (§4.3) — plain HTML+CSS, 32px pitch.
   The same .track/.fill pair renders the Share column inside tables. */
.hbar { display: flex; align-items: center; gap: 10px; min-height: 32px; }
.hbar .lbl { width: 40%; max-width: 40%; font-size: var(--fs-sm);
  color: var(--ink-2); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.track { flex: 1; height: 8px; border-radius: 4px; background: var(--surface-2); }
.fill { height: 8px; border-radius: 4px; background: var(--navy-600);
  width: 0; transition: width var(--dur-4) var(--ease-out); } /* first paint only */
.fill.max { background: var(--navy); }  /* the largest row's fill */
.hbar .val { width: 84px; text-align: right; font-size: var(--fs-sm);
  font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums;
  flex: none; }

/* ====== 5. Data table (§3.3) ============================================= */
.tablecard { background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1); overflow: hidden; }
.tablecard .scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.data { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
table.data th { position: sticky; top: 0; background: var(--surface-2);
  color: var(--ink-3); font-size: var(--fs-2xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: .06em; text-align: left;
  padding: 8px 16px; border-bottom: 1px solid var(--line); white-space: nowrap; }
table.data td { padding: 10px 16px; border-bottom: 1px solid var(--line);
  color: var(--ink-2); }
table.data tr:last-child td { border-bottom: 0; }
table.data td.strong { color: var(--ink); font-weight: 600; }
table.data th.num, table.data td.num { text-align: right;
  font-variant-numeric: tabular-nums; }
@media (hover: hover) { table.data tbody tr:hover td { background: var(--navy-50); } }
table.data tr.flag td:first-child { box-shadow: inset 3px 0 0 var(--neg); }
/* Total/footer rows */
table.data tr.total td { font-weight: 700; color: var(--ink);
  border-top: 2px solid var(--line-2); }
/* <600px: tables with >4 columns render as list rows instead — the engine
   renders both; these helpers pick one. */
@media (max-width: 599px) { .only-desktop { display: none !important; } }
@media (min-width: 600px) { .only-mobile  { display: none !important; } }

/* ====== 6. List row with photo (§3.4) + thumbs & fallback ================ */
.lrow { display: flex; align-items: center; gap: 12px; min-height: 56px;
  border-bottom: 1px solid var(--line); }
.lrow:last-child { border-bottom: 0; }
.lrow .rank { width: 20px; flex: none; color: var(--ink-4);
  font-variant-numeric: tabular-nums; }
.lrow .info { flex: 1; min-width: 0; }
.lrow .nm { font-size: var(--fs-base); font-weight: 600; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lrow .sub { font-size: var(--fs-xs); color: var(--ink-3); }
.lrow .sub.low { color: var(--neg); display: flex; align-items: center;
  gap: 4px; } /* [warningCircle 14px] 3 left · alert at 10 */
.lrow .metric { text-align: right; flex: none; }
.lrow .metric .v { font-size: var(--fs-base); font-weight: 600;
  color: var(--ink); font-variant-numeric: tabular-nums; }
.lrow .metric .c { font-size: var(--fs-2xs); color: var(--ink-3); }

/* Photo thumb 40×40 — list rows, cart lines */
.thumb { width: 40px; height: 40px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--photo-well);
  object-fit: cover; flex: none; display: block; }
/* Image fallback (never a broken img): same box, tinted initial.
   Tint = name.charCodeAt(0) % 4 → .t0 navy / .t1 green / .t2 purple /
   .t3 gold; empty name → package icon 20px in the same tint. */
.fb { display: flex; align-items: center; justify-content: center;
  font-weight: 600; text-transform: uppercase; font-size: var(--fs-sm); }
.fb.t0 { background: var(--navy-50); color: var(--navy); }
.fb.t1 { background: var(--pos-bg);  color: var(--pos); }
.fb.t2 { background: #f3ecf7;        color: #6d3f85; }
.fb.t3 { background: var(--warn-bg); color: var(--warn); }
.ph.fb { font-size: var(--fs-xl); }  /* tile-sized fallback initial */

/* ====== 7. Product tile + grid (§3.5) ==================================== */
.pgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 8px; }
@media (min-width: 600px) {
  .pgrid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
    gap: 10px; } }
@media (min-width: 1024px) {
  .pgrid { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
    gap: 12px; } }

.tile { background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 8px; text-align: left; cursor: pointer;
  user-select: none; position: relative;
  transition: transform 80ms var(--ease-out), border-color var(--dur-1); }
.tile:active { transform: scale(.97); border-color: var(--navy); }
.tile .ph { aspect-ratio: 1/1; width: 100%; border-radius: var(--r-sm);
  background: var(--photo-well); object-fit: cover; display: block; }
.tile .nm { font-size: var(--fs-sm); font-weight: 600; line-height: 1.25;
  margin-top: 6px; min-height: 2.5em; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tile .pr { font-size: var(--fs-base); font-weight: 700; color: var(--navy);
  font-variant-numeric: tabular-nums; margin-top: 2px; }
.tile .st { font-size: var(--fs-2xs); color: var(--ink-3); margin-top: 1px; }
.tile .st.low { color: var(--neg); font-weight: 600; } /* + warningCircle 12px */
.tile.oos { opacity: .55; } /* stock 0: still tappable (oversell allowed); price slot shows "Out" */
.tile .incart { position: absolute; top: 12px; right: 12px; min-width: 22px;
  height: 22px; border-radius: var(--r-full); background: var(--gold);
  color: var(--navy); font: 700 var(--fs-2xs)/22px var(--font-ui);
  text-align: center; padding: 0 6px; }
.tile .pr.ask { font-weight: 600; color: var(--ink-3); } /* price_cents null */

/* ====== 8. Cart line (§3.6) ==============================================
   Two-row grid: name + amount get the full width on row 1 (no 3-char
   truncation in narrow cart columns), the 44px qty steppers sit on row 2. */
.cartline { display: grid; align-items: center; column-gap: 10px;
  grid-template-columns: 40px minmax(0, 1fr) auto;
  grid-template-areas: "th info amt" "th qty qty";
  padding: 8px 0; border-bottom: 1px solid var(--line); }
.cartline:last-child { border-bottom: 0; }
.cartline .th { grid-area: th; align-self: start; margin-top: 2px;
  width: 40px; height: 40px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--photo-well);
  object-fit: cover; flex: none; }
.cartline .info { grid-area: info; min-width: 0; }
.cartline .nm { font-size: var(--fs-base); font-weight: 600; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.cartline .unit { font-size: var(--fs-xs); color: var(--ink-3);
  white-space: nowrap; font-variant-numeric: tabular-nums; }
.cartline .qty { grid-area: qty; justify-self: end; margin-top: 6px;
  display: flex; align-items: center; gap: 2px; flex: none; }
.cartline .qty button { width: 44px; height: 44px; border: 1px solid var(--line-2);
  background: var(--surface); color: var(--navy); border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center; cursor: pointer; }
.cartline .qty button:active { background: var(--navy-50); }
.cartline .qty .n { min-width: 28px; text-align: center; font-weight: 700;
  font-variant-numeric: tabular-nums; }
.cartline .amt { grid-area: amt; text-align: right; font-weight: 700;
  font-variant-numeric: tabular-nums; flex: none; }
.cartline.flash { animation: lineflash 600ms var(--ease-out); }
@keyframes lineflash { from { background: var(--gold-50); } to { background: transparent; } }
/* Remove (qty hits 0): height-collapse + fade, 160ms */
.cartline.removing { animation: lineout var(--dur-2) var(--ease-out) forwards;
  overflow: hidden; }
@keyframes lineout {
  from { opacity: 1; max-height: 110px; }
  to { opacity: 0; max-height: 0; padding-top: 0; padding-bottom: 0;
    border-bottom-width: 0; } }

/* ====== 9. Cart totals (§3.7) — region carries aria-live="polite" ======== */
.totals .trow { display: flex; align-items: center;
  justify-content: space-between; gap: 12px; padding: 3px 0;
  font-size: var(--fs-sm); color: var(--ink-3); }
.totals .rule { border-top: 1px solid var(--line-2); margin: 6px 0; }
.totals .ttotal { display: flex; align-items: baseline;
  justify-content: space-between; gap: 12px; }
.totals .ttotal .lbl { font-size: var(--fs-lg); font-weight: 700;
  color: var(--ink); }
.totals .ttotal .num { font-size: var(--fs-xl); font-weight: 700;
  color: var(--ink); }

/* ====== 10. Payment sheet container (§3.8) =============================== */
.paysheet { position: fixed; inset: 0; z-index: var(--z-sheet);
  background: var(--bg); display: flex; flex-direction: column;
  animation: sheetup var(--dur-3) var(--ease-out); }
@keyframes sheetup { from { opacity: 0; transform: translateY(8%); } }
.paysheet .phead { flex: none; display: flex; align-items: center; gap: 8px;
  height: 56px; padding: 0 12px; }
.paysheet .phead .ttl { font-size: var(--fs-base); font-weight: 600; }
.paysheet .phead .amt { margin-left: auto; font-size: var(--fs-base);
  font-weight: 700; font-variant-numeric: tabular-nums; }
.paysheet .pbody { flex: 1; min-height: 0; overflow-y: auto; padding: 16px; }
@media (min-width: 768px) { /* stages render inside the cart column — no overlay */
  .paysheet { position: static; inset: auto; z-index: auto; background: none;
    animation: none; flex: 1; min-height: 0; }
}

/* ====== 11. Nav items (§3.9) ============================================= */
/* Sidebar items (≥1024; sidebar root carries is-navy → gold focus rings) */
.snav { display: flex; flex-direction: column; gap: 2px; padding: 8px 12px; }
.snav .grp { font: 600 var(--fs-2xs)/1 var(--font-ui); letter-spacing: .08em;
  text-transform: uppercase; color: rgba(255,255,255,.55); margin: 20px 12px 6px; }
.snav a { position: relative; display: flex; align-items: center; gap: 12px;
  height: 40px; padding: 0 12px; border-radius: var(--r-sm);
  color: rgba(255,255,255,.75); font-size: var(--fs-base); font-weight: 500;
  text-decoration: none; transition: background var(--dur-1), color var(--dur-1); }
.snav a:hover { background: rgba(255,255,255,.06); color: rgba(255,255,255,.95); }
.snav a.active { background: rgba(241,181,39,.12); color: var(--gold);  /* 8.6:1 */
  font-weight: 600; }
.snav a.active::before { content: ""; position: absolute; left: -12px; top: 10px;
  width: 3px; height: 20px; background: var(--gold); border-radius: 2px; }
/* Mode switch / Sign out rows in the pinned foot use the same metrics */
.snav button { position: relative; display: flex; align-items: center; gap: 12px;
  height: 40px; padding: 0 12px; width: 100%; border: 0; background: none;
  border-radius: var(--r-sm); color: rgba(255,255,255,.75);
  font: 500 var(--fs-base) var(--font-ui); text-align: left; cursor: pointer;
  transition: background var(--dur-1), color var(--dur-1); }
.snav button:hover { background: rgba(255,255,255,.06); color: rgba(255,255,255,.95); }

/* Bottom nav (dashboard <768, till <768) — gold marks position, navy is text */
.bnav { position: fixed; inset: auto 0 0 0; z-index: var(--z-nav); display: flex;
  background: var(--surface); border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom); }
.bnav button { flex: 1; min-height: 64px; background: none; border: 0;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding-top: 10px; color: var(--ink-3); font: 600 var(--fs-2xs) var(--font-ui);
  cursor: pointer; position: relative; }
.bnav button.active { color: var(--navy); }
.bnav button.active::before { content: ""; position: absolute; top: 0;
  width: 24px; height: 3px; background: var(--gold); border-radius: 0 0 3px 3px; }
/* phone-only: this hide must FOLLOW the base .bnav rule to win the cascade */
@media (min-width: 768px) { .bnav { display: none; } }

/* "More" bottom sheet rows (48px) + group labels on white */
.sheetrow { display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: 48px; padding: 0 12px; border: 0; background: none;
  border-radius: var(--r-sm); color: var(--ink);
  font: 500 var(--fs-base) var(--font-ui); text-align: left; cursor: pointer; }
.sheetrow:active { background: var(--navy-50); }
.sheetrow.active { color: var(--navy); font-weight: 600;
  box-shadow: inset 3px 0 0 var(--gold); }
.sheet-grp { font: 600 var(--fs-2xs)/1 var(--font-ui); letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3); margin: 16px 12px 6px; }

/* ====== 12. Period toggle / segmented (§3.10) ============================ */
.seg { display: inline-flex; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: var(--r-md); padding: 3px; }
.seg button { border: 0; background: none; color: var(--ink-3); cursor: pointer;
  font: 600 var(--fs-sm) var(--font-ui); padding: 7px 14px; min-height: 32px;
  border-radius: 7px; transition: color var(--dur-1), background var(--dur-1); }
.seg button.active { background: var(--surface); color: var(--navy);
  box-shadow: var(--shadow-1); border: 1px solid var(--line); }
/* Till header variant: navy track, white inactive labels, 44px targets */
.is-navy .seg { background: rgba(255,255,255,.08);
  border-color: rgba(255,255,255,.12); }
.is-navy .seg button { color: rgba(255,255,255,.8); min-height: 44px; }
.is-navy .seg button.active { background: var(--surface); color: var(--navy); }

/* ====== 13. Status pills (§3.11) ========================================= */
/* ok = paid/completed/confirmed/delivered/redeemed · warn = pending/requested/
   submitted · bad = expired/failed/voided/cancelled/reversed/dead ·
   mute = everything else (incl. "ask price") */
.pill { display: inline-flex; align-items: center; gap: 4px; padding: 2px 10px;
  border-radius: var(--r-full); font-size: var(--fs-xs); font-weight: 600;
  border: 1px solid transparent; }
.pill.ok   { background: var(--pos-bg);  color: var(--pos);  border-color: var(--pos-line); }
.pill.warn { background: var(--warn-bg); color: var(--warn); border-color: var(--warn-line); }
.pill.bad  { background: var(--neg-bg);  color: var(--neg);  border-color: var(--neg-line); }
.pill.mute { background: var(--surface-2); color: var(--ink-3); border-color: var(--line); }
/* Tender pills: mute styling + 8px tender-color dot before the label */
.tdot { width: 8px; height: 8px; border-radius: var(--r-full); flex: none; }
.tdot.cash     { background: var(--t-cash); }
.tdot.ecocash  { background: var(--t-ecocash); }
.tdot.innbucks { background: var(--t-innbucks); }

/* Mode pill — TEST solid gold / LIVE solid green; 44px touch target */
.modepill { position: relative; display: inline-flex; align-items: center;
  gap: 6px; border: 0; border-radius: var(--r-full); padding: 5px 12px;
  font: 700 var(--fs-2xs) var(--font-ui); cursor: pointer; }
.modepill.test { background: var(--gold); color: var(--navy); } /* 8.6:1 */
.modepill.live { background: var(--pos); color: #fff; }         /* 5.4:1 */
@media (pointer: coarse) { .modepill::after { content: ""; position: absolute;
  left: 0; right: 0; top: 50%; height: 44px; transform: translateY(-50%); } }

/* Live indicator: 8px dot, 2s opacity pulse; test mode = gold + "Test data" */
.live { display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); color: var(--ink-3); }
.live .dot { width: 8px; height: 8px; border-radius: var(--r-full);
  background: var(--pos); animation: livepulse 2s ease-in-out infinite; }
.live.test .dot { background: var(--gold); }
@keyframes livepulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }

/* ====== 14. Buttons (§3.12) ============================================== */
.btn { display: inline-flex; align-items: center; justify-content: center;
  gap: 8px; border: 1px solid transparent; border-radius: var(--r-md);
  font: 600 var(--fs-base) var(--font-ui); min-height: 40px; padding: 0 16px;
  cursor: pointer; transition: background var(--dur-1), border-color var(--dur-1),
  transform 80ms var(--ease-out); }
.btn:active { transform: scale(.98); }
.btn:disabled { opacity: .45; cursor: default; transform: none; }
.btn-primary { background: var(--navy); color: #fff; }
.btn-primary:hover { background: var(--navy-700); }
.btn-secondary { background: var(--surface); color: var(--navy);
  border-color: var(--line-2); }
.btn-secondary:hover { background: var(--navy-50); }
.btn-ghost { background: transparent; color: var(--navy-600); }
.btn-ghost:hover { background: var(--navy-50); }
.btn-danger { background: var(--red); color: #fff; }
.btn-lg { min-height: 56px; font-size: var(--fs-md); border-radius: var(--r-lg); }
.btn-icon { width: 44px; min-height: 44px; padding: 0; }
@media (pointer: coarse) { .btn { min-height: 44px; } }
/* Ghost-danger (void action icon button) */
.btn-ghost.danger { color: var(--neg); }
.btn-ghost.danger:hover { background: var(--neg-bg); }

/* THE Charge button — the till's gold moment. Never reuse this style elsewhere. */
.charge { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; width: 100%; min-height: 56px; padding: 0 20px; border: 0;
  cursor: pointer; border-radius: var(--r-lg); background: var(--gold);
  color: var(--navy); font: 700 var(--fs-md)/1 var(--font-ui);
  box-shadow: var(--shadow-gold);
  transition: background var(--dur-1), transform 80ms var(--ease-out); }
.charge:hover { background: #e9a916; }
.charge:active { transform: scale(.99); background: var(--gold-600); }
.charge:disabled { background: var(--line); color: var(--ink-4); box-shadow: none; }
.charge .amt { font-size: var(--fs-lg); font-variant-numeric: tabular-nums; }

/* ====== 15. Cart bar (till, <768) (§3.13) ================================ */
.cartbar { position: fixed; left: 12px; right: 12px;
  bottom: calc(64px + env(safe-area-inset-bottom) + 8px); z-index: var(--z-cartbar);
  display: flex; background: var(--gold); border-radius: var(--r-lg);
  box-shadow: var(--shadow-gold); color: var(--navy); overflow: hidden;
  min-height: 60px; }
.cartbar .open { flex: 1; display: flex; align-items: center; gap: 10px;
  padding: 0 16px; background: none; border: 0; color: var(--navy);
  cursor: pointer; font: 600 var(--fs-base) var(--font-ui); text-align: left;
  border-right: 1px solid rgba(0,34,74,.25); }
.cartbar .open .count { background: var(--navy); color: #fff;
  border-radius: var(--r-full); min-width: 22px; height: 22px; display: flex;
  align-items: center; justify-content: center; font-size: var(--fs-xs);
  font-weight: 700; }
.cartbar .gocharge { border: 0; background: none; color: var(--navy);
  padding: 0 20px; font: 700 var(--fs-md) var(--font-ui); cursor: pointer;
  font-variant-numeric: tabular-nums; }
.cartbar .count.bump { animation: bump 200ms var(--ease-out); }
@keyframes bump { 50% { transform: scale(1.18); } }
.cartbar.enter { animation: sheetup var(--dur-3) var(--ease-out); } /* first item */
@media (min-width: 768px) { .cartbar { display: none; } }

/* ====== 16. Dialogs (§3.14) ============================================== */
dialog { width: min(94vw, 480px); max-height: calc(100vh - 48px); border: 0;
  border-radius: var(--r-lg); padding: 0; box-shadow: var(--shadow-3);
  background: var(--surface); color: var(--ink); }
dialog[open] { display: flex; flex-direction: column;
  animation: dlgin var(--dur-2) var(--ease-out); }
dialog::backdrop { background: rgba(10,18,32,.4); }
@keyframes dlgin { from { opacity: 0; transform: scale(.98); } }
@media (max-width: 767px) { /* bottom sheet */
  dialog { width: 100vw; max-width: none; margin: auto 0 0;
    border-radius: var(--r-lg) var(--r-lg) 0 0; max-height: 90vh; }
  dialog[open] { animation: sheetin var(--dur-3) var(--ease-out); }
}
@keyframes sheetin { from { opacity: 0; transform: translateY(24px); } }
dialog.tall { height: 90vh; max-height: 90vh; } /* mobile cart sheet */
.grab { width: 36px; height: 4px; border-radius: var(--r-full);
  background: var(--line-2); margin: 8px auto 0; flex: none; }
.dlg-head { flex: none; display: flex; align-items: center;
  justify-content: space-between; gap: 12px; padding: var(--sp-5); }
.dlg-title { font-size: var(--fs-lg); font-weight: 600; color: var(--ink); }
.dlg-body { padding: 0 var(--sp-5); overflow-y: auto; display: flex;
  flex-direction: column; gap: 12px; }
.dlg-foot { flex: none; display: flex; justify-content: flex-end; gap: 12px;
  padding: var(--sp-5); }
@media (max-width: 767px) { .dlg-foot .btn { flex: 1; } }
/* One-time key secret well */
code.secret { display: block; background: var(--surface-2);
  border: 1px dashed var(--line-2); border-radius: var(--r-sm); padding: 12px;
  font: 600 13px/1.5 ui-monospace, monospace; word-break: break-all; }

/* ====== 17. Inputs (§3.15) =============================================== */
.input { width: 100%; min-height: 44px; padding: 10px 14px;
  border: 1px solid var(--line-2); border-radius: var(--r-md);
  font: 400 var(--fs-md) var(--font-ui); color: var(--ink);
  background: var(--surface); transition: border-color var(--dur-1),
  box-shadow var(--dur-1); }
.input::placeholder { color: var(--ink-4); }
.input:focus { outline: none; border-color: var(--navy-600);
  box-shadow: 0 0 0 3px rgba(21,101,192,.18); }
.input.err { border-color: var(--neg);
  box-shadow: 0 0 0 3px rgba(179,21,26,.12); }
/* Scan field: the till's hero input */
.scanwrap { position: sticky; top: 56px; z-index: var(--z-sticky);
  background: var(--bg); padding: 12px 0; display: flex; gap: 8px; }
.scanwrap .input { min-height: 48px; padding-left: 42px; }
.scanwrap .ic { position: absolute; left: 14px; top: 50%;
  transform: translateY(-50%); color: var(--ink-4); } /* barcode icon 20px */
.scanwrap .btn { min-height: 48px; } /* plain [Add] .btn-secondary at 48px */
.scanwrap.err .input { animation: shake 200ms linear; }
@keyframes shake { 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }
/* Field label above input + error message line below */
.flabel { display: block; font: 600 var(--fs-xs) var(--font-ui);
  color: var(--ink-2); margin-bottom: 6px; }
.fielderr { font-size: var(--fs-xs); color: var(--neg); margin-top: 4px; }
/* New-product dialog: 96px live image preview (tile photo/fallback rules) */
.preview96 { width: 96px; height: 96px; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: var(--photo-well);
  object-fit: cover; }

/* ====== 18. Empty state (§3.16) ========================================== */
.empty { display: flex; flex-direction: column; align-items: center;
  text-align: center; padding: 40px 20px; }
.empty .eic { width: 48px; height: 48px; border-radius: var(--r-full);
  background: var(--surface-2); color: var(--ink-4); display: flex;
  align-items: center; justify-content: center; margin-bottom: var(--sp-3); }
.empty .et { font-size: var(--fs-base); font-weight: 600; color: var(--ink); }
.empty .eb { font-size: var(--fs-sm); color: var(--ink-3); max-width: 36ch;
  margin-top: var(--sp-1); }
.empty .btn { margin-top: var(--sp-4); }

/* ====== 19. Skeletons (§3.17) — first load ONLY, never on auto-refresh === */
.skel { border-radius: var(--r-sm);
  background: linear-gradient(90deg, #eef1f6 25%, #f6f8fb 37%, #eef1f6 63%);
  background-size: 400% 100%; animation: shimmer 1.2s linear infinite; }
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) { .skel { animation: none; background: #eef1f6; } }
/* Recipes — KPI: label/value/sub bars · table: 14px bars at 60/30/20% ·
   chart: full block at chart height · list row: 40px square + bars · tile:
   square + bars */
.skel-label { width: 72px;  height: 10px; }
.skel-value { width: 128px; height: 26px; margin-top: 10px; }
.skel-sub   { width: 96px;  height: 10px; margin-top: 10px; }
.skel-bar   { height: 14px; }
.skel-bar.w60 { width: 60%; } .skel-bar.w30 { width: 30%; } .skel-bar.w20 { width: 20%; }
.skel-chart { width: 100%; height: 200px; }
@media (max-width: 767px) { .skel-chart { height: 160px; } }
.skel-sq40  { width: 40px; height: 40px; flex: none; }
.skel-tile  { width: 100%; aspect-ratio: 1/1; }

/* ====== 20. Toast (§3.18) — never alert() ================================ */
.toast { position: fixed; top: max(16px, env(safe-area-inset-top)); left: 50%;
  transform: translateX(-50%); z-index: var(--z-toast); display: flex;
  align-items: center; gap: 8px; background: var(--navy); color: #fff;
  font: 600 var(--fs-sm) var(--font-ui); border-radius: var(--r-full);
  padding: 10px 18px; box-shadow: var(--shadow-2); max-width: calc(100vw - 32px);
  animation: toastin var(--dur-2) var(--ease-out); }
.toast.ok svg.icon { color: var(--green); }   /* success: checkCircle */
.toast.err { background: var(--neg); }        /* error: warningCircle */
.toast .act { background: none; border: 0; color: #fff;
  text-decoration: underline; font: inherit; cursor: pointer;
  min-height: 44px; padding: 0 6px; margin: -12px -6px -12px 0; }
.toast.out { animation: toastout var(--dur-2) var(--ease-out) forwards; }
@keyframes toastin { from { opacity: 0; transform: translate(-50%, 8px); } }
@keyframes toastout { to { opacity: 0; } }

/* ====== 21. Spinner ring + stage transition ============================== */
/* 16px SVG ring (stroke-dasharray arc built in JS), 1s linear rotation.
   Reduced motion: rotation is killed globally — JS swaps in static text. */
.spin { display: inline-flex; width: 16px; height: 16px; flex: none;
  animation: spin 1s linear infinite; }
.spin svg { width: 100%; height: 100%; display: block; }
@keyframes spin { to { transform: rotate(360deg); } }
/* Tab/stage transitions: incoming content fade + 8px rise (no exit anim) */
.stage-in { animation: risein var(--dur-2) var(--ease-out); }
@keyframes risein { from { opacity: 0; transform: translateY(8px); } }

/* ====== 22. Login (both surfaces) ======================================== */
.login { min-height: 100vh; display: flex; align-items: center;
  justify-content: center; background: var(--bg); padding: var(--sp-6); }
.logincard { width: 100%; max-width: 384px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-1); padding: var(--sp-8) var(--sp-6);
  display: flex; flex-direction: column; gap: var(--sp-3); }
.logincard .loginlogo { height: 32px; align-self: center;
  margin-bottom: var(--sp-2); }
.logincard h1 { margin: 0 0 var(--sp-2); font-size: var(--fs-lg);
  font-weight: 600; text-align: center; color: var(--ink); }
.logincard .loginerr { color: var(--neg); font-size: var(--fs-sm);
  text-align: center; }
.logincard .btn { width: 100%; }
