/* components.css — reusable UI primitives. All references go through tokens. */

/* ── Buttons ──────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 10px 16px;
  /* WCAG-min touch target; Mila TZ #5 calls 44px the baseline so the
     thumb can always hit a button on a phone. */
  min-height: 44px;
  border-radius: var(--radius);
  font-size: var(--fs-base);
  font-weight: 600;
  line-height: 1;
  border: 1px solid transparent;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  transition: background var(--t), border-color var(--t), color var(--t), transform var(--t-fast);
  white-space: nowrap;
}
.btn:hover:not(:disabled) { background: var(--surface-2); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
/* sm-v44: tighter press feedback. scale(.97) feels more "button-like"
   than the legacy translateY(1px) and is consistent with the
   product-card touch press. Motion-only branch — reduced-motion
   users get the static color hover but no transform. */
@media (prefers-reduced-motion: no-preference) {
  .btn:active:not(:disabled) { transform: scale(.97); transition-duration: .12s; }
  .btn-primary:hover:not(:disabled) { filter: brightness(1.06); }
}

.btn-primary {
  background: var(--accent);
  color: var(--text-inv);
  border-color: var(--accent);
}
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }

.btn-outline {
  background: transparent;
  color: var(--text);
  border-color: var(--border-2);
}
.btn-outline:hover:not(:disabled) { background: var(--surface-2); border-color: var(--text-3); }

.btn-ghost {
  background: transparent;
  color: var(--text-2);
  border-color: transparent;
}
.btn-ghost:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }

.btn-success {
  background: var(--success);
  color: var(--text-inv);
  border-color: var(--success);
}
.btn-success:hover:not(:disabled) { background: var(--success-dark); border-color: var(--success-dark); }

.btn-danger {
  background: var(--surface);
  color: var(--danger-dark);
  border-color: var(--danger-light);
}
.btn-danger:hover:not(:disabled) { background: var(--danger-light); border-color: var(--danger); }

.btn-block { width: 100%; }
.btn-lg { min-height: 48px; padding: 12px 20px; font-size: var(--fs-md); }
.btn-sm { min-height: 32px; padding: 6px 12px; font-size: var(--fs-xs); }

/* Icon-only button */
.btn-icon {
  width: 36px; min-height: 36px; padding: 0;
  border-radius: var(--radius-sm);
}

/* Floating action (+) on product card */
.fab {
  width: 36px; height: 36px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--text-inv);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: var(--shadow-md);
  border: 0;
  transition: background var(--t), transform var(--t-fast);
}
.fab:hover { background: var(--accent-hover); }
.fab:active { transform: scale(.94); }

/* Qty stepper used inline (on product card when in cart) */
.qty-stepper {
  display: inline-flex;
  align-items: stretch;
  background: var(--accent);
  color: var(--text-inv);
  border-radius: var(--radius-pill);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  font-weight: 600;
  user-select: none;
}
.qty-stepper button {
  background: transparent;
  color: var(--text-inv);
  border: 0;
  font-size: 18px;
  width: 32px;
  cursor: pointer;
  transition: background var(--t);
}
.qty-stepper button:hover { background: rgba(255,255,255,.15); }
.qty-stepper button:disabled { opacity: .4; cursor: default; }
.qty-stepper .qty-val {
  min-width: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  padding: 0 4px;
}
.qty-stepper .qty-val-input {
  width: 52px;
  min-width: 52px;
  border: 0;
  background: transparent;
  color: var(--text-inv);
  text-align: center;
  font: inherit;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
  appearance: textfield;
  outline: none;
}
.qty-stepper .qty-val-input::-webkit-outer-spin-button,
.qty-stepper .qty-val-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.qty-stepper .qty-val-input:focus { background: rgba(255,255,255,.12); }

/* Two-row qty/stock block on product cards while item is in cart */
.qty-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-end;
  width: 100%;
}
.qty-stepper-row {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  /* sm-v26: 'end' is the logical / direction-aware synonym of
     'flex-end' in flex containers. flex-end already mirrors in RTL
     (main axis reverses with direction:rtl), but the audit asked for
     an explicit RTL guard; we use the logical keyword so future
     refactors don't have to remember to add an html[dir=rtl] rule. */
  justify-content: end;
}
/* sm-v26: belt-and-suspenders — explicit identical RTL rule so any
   future cascade override on the bare class can't silently leave RTL
   pinned to the LTR end. Same value, just a higher-specificity guard. */
html[dir="rtl"] .qty-stepper-row { justify-content: end; }
.qty-stepper-row-label {
  font-size: var(--fs-xs);
  color: var(--text-3);
  text-transform: uppercase;
  letter-spacing: .04em;
  min-width: 38px;
  text-align: end;
}
.qty-stepper-row-stock .qty-stepper {
  background: var(--surface-3);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}
.qty-stepper-row-stock .qty-stepper button,
.qty-stepper-row-stock .qty-stepper input { color: var(--text); }
.qty-stepper-row-stock.is-empty .qty-stepper {
  background: var(--danger-light);
  outline: 2px solid var(--danger);
}
.qty-stepper-sm button { width: 26px; font-size: 16px; }
.qty-stepper-sm .qty-val-input { width: 44px; min-width: 44px; }

/* Inline counter on the product card once an item is in the cart and
   has a current_stock value. Replaces the 2-row stock+order form with
   a compact [−][N unit][+] stepper so the card reads as "this is in
   your cart, qty N". Buttons are 44×44 (WCAG minimum touch target)
   because the chef taps these on a phone. */
.card-counter {
  display: inline-flex;
  align-items: stretch;
  background: var(--terracotta);
  color: var(--text-inv);
  border-radius: var(--radius-pill);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  font-weight: 700;
  user-select: none;
  min-height: 44px;
}
.card-counter button {
  background: transparent;
  color: var(--text-inv);
  border: 0;
  width: 44px;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--t);
}
.card-counter button:hover { background: rgba(255,255,255,.18); }
.card-counter button:active { background: rgba(255,255,255,.28); }
.card-counter-val {
  min-width: 56px;
  padding: 0 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-md);
}
.card-counter-edit {
  font-size: var(--fs-xs);
  color: var(--text-2);
  background: transparent;
  border: 0;
  margin-top: 4px;
  cursor: pointer;
  padding: 4px 8px;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.card-counter-edit:hover { color: var(--text); }

/* One-time onboarding hint above /order — clarifies that "Restaurant
   Stock" means the chef's current bar/kitchen inventory, NOT the
   warehouse. Dismissible (✕) — order.js writes the dismiss flag to
   localStorage so returning users don't see it again. RTL-aware via
   logical paddings + inset-inline. */
.order-hint {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  margin: 12px 16px 16px;
  background: #fdf6ec;
  color: var(--text);
  border: 1px solid #f1e3c4;
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.45;
}
/* Class selector beats the [hidden] UA rule by source-order at equal
   specificity; restore the hide explicitly. */
.order-hint[hidden] { display: none; }
.order-hint-icon { font-size: 16px; line-height: 1.4; flex-shrink: 0; }
.order-hint-text { flex: 1; min-width: 0; }
.order-hint-close {
  flex-shrink: 0;
  background: transparent;
  border: 0;
  color: var(--text-2);
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  padding: 4px 6px;
  border-radius: 4px;
  margin-inline-start: 4px;
}
.order-hint-close:hover { background: rgba(0,0,0,.06); color: var(--text); }
@media (max-width: 600px) {
  .order-hint { margin: 8px 8px 12px; padding: 10px 12px; font-size: 12px; }
}

/* Cart drawer is now grouped: one section per warehouse with items.
   Section title shows the warehouse emoji + name so the chef can see
   at a glance "this is what's going to Busten". Sections stack with
   16px gap; only warehouses with non-empty carts render. */
.cart-section + .cart-section { margin-top: var(--sp-4); }
.cart-section-title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  padding: var(--sp-2) 0 var(--sp-2);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--sp-2);
}
.cart-section-icon { font-size: var(--fs-md); line-height: 1; }
.cart-section-label { letter-spacing: .01em; }

/* Success splash list — used when N orders are sent at once. Each line
   shows order#  emoji + warehouse name. The partial-success variant
   adds ok/fail marks at the start. */
.success-splash-list {
  margin: var(--sp-3) auto var(--sp-3);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  width: max-content;
  max-width: 100%;
}
.success-splash-line {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-sm);
}
.success-splash-id-cell {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--accent);
  min-width: 56px;
}
.success-splash-wh { color: var(--text); }
.success-splash-mark { font-weight: 700; }
.success-splash-line-ok  .success-splash-mark { color: var(--success); }
.success-splash-line-fail .success-splash-mark { color: var(--danger); }
.success-splash-partial .success-splash-tick { color: var(--warning); }

/* "Done" button at the bottom of the expanded stock+order form — closes
   the form back to the compact counter. Only renders when current_stock
   has been entered (collapse would be useless without it). */
.qty-block-done {
  align-self: flex-end;
  margin-top: 4px;
  background: var(--surface-3);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 4px 10px;
  font-size: var(--fs-xs);
  font-weight: 600;
  cursor: pointer;
}
.qty-block-done:hover { background: var(--border-2); }

/* Cart drawer item — two-row layout with inline edit fields */
.cart-item-2line { align-items: flex-start; padding: 10px; }
.cart-item-missing-stock { outline: 2px solid var(--danger); }
.cart-item-edit {
  display: flex;
  gap: 8px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.cart-item-edit-row {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 2px 6px;
}
.cart-item-edit-label {
  font-size: var(--fs-xs);
  color: var(--text-2);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.cart-item-edit-row input {
  width: 64px;
  border: 0;
  background: transparent;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  text-align: end;
  outline: none;
  padding: 4px 0;
}
.cart-item-edit-row input::-webkit-outer-spin-button,
.cart-item-edit-row input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.cart-item-missing-stock .cart-item-edit-row input { background: var(--danger-light); }

/* Order-id link in /reports tables — looks like a normal link but inherits
   the table cell typography so the row scan is clean. */
.order-id-link {
  color: var(--accent);
  font-family: var(--font-mono);
  text-decoration: none;
  font-weight: 600;
}
.order-id-link:hover { text-decoration: underline; }

/* ── Inputs / selects / textareas ─────────────────────────────────────────── */

.input, .select, .textarea {
  width: 100%;
  padding: 10px 12px;
  min-height: 40px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-sm);
  transition: border-color var(--t), box-shadow var(--t);
  font-family: inherit;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}
.input::placeholder, .textarea::placeholder { color: var(--text-3); }
.textarea { min-height: 80px; resize: vertical; line-height: 1.5; }

.input-search {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 10px center;
  padding-inline-start: 34px;
}
html[dir="rtl"] .input-search {
  background-position: right 10px center;
  padding-inline-start: 12px;
  padding-inline-end: 34px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.field-label {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-2);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.field-hint {
  font-size: var(--fs-xs);
  color: var(--text-3);
}
.field-row {
  display: flex;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.field-row > .field { flex: 1; min-width: 160px; }

/* Toggle switch */
.toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  cursor: pointer;
  user-select: none;
}
.toggle input { display: none; }
.toggle-track {
  width: 36px; height: 20px;
  background: var(--border-2);
  border-radius: var(--radius-pill);
  position: relative;
  transition: background var(--t);
}
.toggle-track::after {
  content: '';
  position: absolute;
  top: 2px; inset-inline-start: 2px;
  width: 16px; height: 16px;
  background: var(--text-inv);
  border-radius: 50%;
  transition: transform var(--t);
}
.toggle input:checked + .toggle-track { background: var(--accent); }
.toggle input:checked + .toggle-track::after { transform: translateX(16px); }
html[dir="rtl"] .toggle input:checked + .toggle-track::after { transform: translateX(-16px); }

/* ── Cards ────────────────────────────────────────────────────────────────── */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-5);
}
.card-tight { padding: var(--sp-4); }

/* ── Product card (Wolt/Glovo style) ──────────────────────────────────────── */

.product-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow);
  /* sm-v44: lifted to .3s + transform/box-shadow on the same timing
     for a coherent "lift" feel on hover. .15s was too snappy with
     the new accent — felt twitchy. */
  transition: transform .3s ease, box-shadow .3s ease, border-color .3s ease;
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .product-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-md);
    border-color: var(--border-2);
  }
}
/* Touch-tap acknowledgement on mobile — a subtle press-in.
   Pointer:fine devices skip this branch so a mouse user doesn't
   double-press visually with the hover lift. */
@media (pointer: coarse) and (prefers-reduced-motion: no-preference) {
  .product-card:active { transform: scale(.985); transition-duration: .12s; }
}

.product-card-media {
  aspect-ratio: 1 / 1;
  background: var(--warm-cream);
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.product-card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Placeholder (no photo): neutral warm-cream tile with the product's
   two-letter initials. Switched from emoji icons per Mila TZ #5. */
.product-card-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--sp-3);
  background: var(--warm-cream);
}
.product-card-placeholder-initials {
  font-size: 30px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--medium-text);
  line-height: 1;
  font-variant: tabular-nums;
}
.product-card-placeholder-text {
  margin-top: var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--medium-text);
  line-height: 1.25;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
  opacity: .82;
}

.product-card-body {
  padding: 10px 12px 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
}
.product-card-name {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}
.product-card-unit {
  font-size: var(--fs-xs);
  color: var(--text-3);
}
.product-card-foot {
  margin-top: auto;
  display: flex;
  justify-content: flex-end;
  padding-top: var(--sp-2);
}

/* Bigger touch targets on mobile */
@media (max-width: 767px) {
  .product-card-body { padding: 8px 10px 10px; }
  .fab { width: 40px; height: 40px; font-size: 22px; }
}

/* ── Badges / chips ──────────────────────────────────────────────────────── */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
}
.badge-neutral { background: var(--surface-3); color: var(--text-2); }
.badge-accent  { background: var(--accent-light); color: var(--accent); }
.badge-success { background: var(--success-light); color: var(--success-dark); }
.badge-danger  { background: var(--danger-light);  color: var(--danger-dark); }
.badge-warning { background: var(--warning-light); color: var(--warning); }

/* status-specific colors */
/* Status badges — pinned to the warm Terracotta+Olive palette per
   Mila TZ #5. "Sent" no longer uses purple; it now reads as olive
   (in-flight = trusted-progress) until the kitchen confirms. */
.badge-status-new      { background: var(--surface-2); color: var(--medium-text); }
.badge-status-picking  { background: var(--warning-light); color: var(--warning-dark); }
.badge-status-ready    { background: var(--accent-light); color: var(--accent-hover); }
.badge-status-sent     { background: var(--olive-light); color: var(--olive); }
.badge-status-received { background: var(--olive-light); color: var(--olive); }
.badge-status-confirmed{ background: var(--olive-light); color: var(--olive); }
.badge-status-cancelled{ background: var(--danger-light); color: var(--danger-dark); }

/* Active / Hidden — deeper backgrounds + 1px border + leading glyph
   so the distinction reads at a glance in dense admin tables. The
   pseudo-element keeps the JS callers simple (just toggle the class). */
.badge-active {
  background: #DEE9D0;
  color: #4A5F3B;
  border: 1px solid #B8CFA0;
  padding: 4px 10px;
  border-radius: 12px;
  font-weight: 500;
}
.badge-active::before {
  content: '✓ ';
  color: #4A5F3B;
  font-weight: 700;
}
.badge-hidden {
  background: #EEEAE2;
  color: #888880;
  border: 1px solid #DDD8CD;
  padding: 4px 10px;
  border-radius: 12px;
  font-weight: 500;
}
.badge-hidden::before {
  content: '— ';
}

/* Warehouse "tag" pill for dense tables and order-card headers —
   distinct from .wh-pill (the topbar warehouse-picker chip on /order).
   Color-coded by warehouse_id via data-wh="1|2|3" so admin / reports
   readers can spot a misrouted order at a glance. */
.wh-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 12px;
  font-size: var(--fs-xs);
  font-weight: 500;
  white-space: nowrap;
  border: 1px solid transparent;
}
.wh-tag[data-wh="1"] { background: #E6EFF5; color: #2C5A7E; border-color: #C9DDEA; }
.wh-tag[data-wh="2"] { background: var(--terracotta-light); color: var(--terracotta-hover); border-color: #F4D6CC; }
.wh-tag[data-wh="3"] { background: var(--olive-light); color: #4A5F3B; border-color: #C9D9B9; }
.wh-tag-icon { font-size: 13px; line-height: 1; }

/* Category-with-icon — small inline icon prefix in /admin/products
   category cell so the eye groups rows by category without reading. */
.cat-cell-icon { font-size: 14px; line-height: 1; margin-inline-end: 4px; }

/* Order-window banner above /order — shown only when the chef is
   currently outside the 22:00-01:00 intake window. Warm terracotta-
   light callout that doesn't BLOCK sending (the chef can still tap
   Send and the server stashes for approval), it just tells them what
   to expect. */
.order-window-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 14px;
  margin: 12px 16px;
  background: var(--terracotta-light);
  color: var(--terracotta-hover);
  border: 1px solid var(--terracotta);
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.45;
  font-weight: 500;
}
.order-window-banner[hidden] { display: none; }

/* "Approval pending" modal copy after a 202 POST response. */
.approval-pending-modal {
  text-align: center;
  padding: 20px;
}
.approval-pending-modal-icon { font-size: 40px; margin-bottom: 8px; }
.approval-pending-modal-title {
  font-size: var(--fs-lg);
  font-weight: 700;
  margin-bottom: 8px;
  color: var(--text);
}
.approval-pending-modal-body {
  color: var(--text-2);
  font-size: var(--fs-sm);
  line-height: 1.5;
  margin-bottom: 14px;
}
.approval-pending-modal-id {
  display: inline-block;
  background: var(--terracotta-light);
  color: var(--terracotta-hover);
  border: 1px solid var(--terracotta);
  padding: 4px 10px;
  border-radius: 6px;
  font-weight: 700;
  font-family: var(--font-mono);
}

/* "My approval requests" section on /order — shown only when the user
   has at least one approval in the last 24h. */
.my-approvals {
  margin: 0 16px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
}
.my-approvals-title {
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--text);
  margin-bottom: 8px;
}
.my-approval-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm);
}
.my-approval-row:first-of-type { border-top: 0; padding-top: 0; }
.my-approval-id { font-family: var(--font-mono); color: var(--text-2); min-width: 50px; }
.my-approval-status { font-weight: 700; }
.my-approval-status-pending { color: var(--warning-dark); }
.my-approval-status-approved { color: var(--olive); }
.my-approval-status-rejected { color: var(--danger-dark); }
.my-approval-status-expired { color: var(--text-3); }

/* /admin Approvals tab — list of pending off-window order requests
   waiting for an admin to OK them. */
.approvals-table .age-cell { color: var(--text-2); font-variant-numeric: tabular-nums; }
.approvals-actions-cell { display: flex; gap: 6px; }
.approval-empty {
  padding: 32px 16px;
  text-align: center;
  color: var(--text-2);
  font-size: var(--fs-sm);
}

/* Emergency tag on /reports order rows + detail modal. */
.emergency-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--terracotta-light);
  color: var(--terracotta-hover);
  border: 1px solid var(--terracotta);
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 700;
  white-space: nowrap;
}
.emergency-section {
  margin: 12px 0;
  padding: 10px 12px;
  border: 1px solid var(--terracotta);
  border-radius: 6px;
  background: var(--terracotta-light);
  font-size: var(--fs-sm);
  color: var(--terracotta-hover);
}
.emergency-section b { color: var(--text); }

/* ── Order purpose (Kitchen / Bar / Staff Meal / General) ───────────── */
/* Chip — picker buttons on the product card, cart-section headers,
   group headers in /warehouse + /receive, filter chips in /reports.
   Same element, 4 colour modifiers + a -selected state.
     kitchen → terracotta (default)
     staff   → olive
     bar     → muted blue (no other blue in the app, so it reads as
                a distinct semantic without polluting the palette)
     general → warm-grey */
.purpose-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 600;
  border: 1px solid transparent;
  white-space: nowrap;
  background: var(--surface-2);
  color: var(--text);
  user-select: none;
}
/* sm-v44: purpose colors decoupled from --accent. See tokens.css for
   the --purpose-* group rationale (Kitchen amber, Bar sea blue, Staff
   olive). Theme switches don't drag them along. */
.purpose-chip-kitchen { background: var(--purpose-kitchen-light); color: var(--purpose-kitchen-hover); border-color: #ECD8B0; }
.purpose-chip-staff   { background: var(--purpose-staff-light);   color: var(--purpose-staff-hover);   border-color: #C9D9B9; }
.purpose-chip-bar     { background: var(--purpose-bar-light);     color: var(--purpose-bar-hover);     border-color: #C9DDEA; }
.purpose-chip-general { background: var(--surface-2);             color: var(--text-2);                 border-color: var(--border); }

/* Picker variant: 44×44 minimum touch target, larger font, selected
   state has a stronger border + shadow. */
.purpose-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}
.purpose-pick-btn {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-height: 56px;
  min-width: 76px;
  flex: 1;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--surface);
  border: 2px solid var(--border);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  transition: border-color var(--t), background var(--t);
}
.purpose-pick-btn-emoji { font-size: 18px; line-height: 1; }
.purpose-pick-btn:hover { border-color: var(--border-2); }
.purpose-pick-btn.is-selected.purpose-pick-btn-kitchen { background: var(--purpose-kitchen-light); border-color: var(--purpose-kitchen); color: var(--purpose-kitchen-hover); }
.purpose-pick-btn.is-selected.purpose-pick-btn-staff   { background: var(--purpose-staff-light);   border-color: var(--purpose-staff);   color: var(--purpose-staff-hover); }
.purpose-pick-btn.is-selected.purpose-pick-btn-bar     { background: var(--purpose-bar-light);     border-color: var(--purpose-bar);     color: var(--purpose-bar-hover); }
.purpose-pick-btn.is-selected.purpose-pick-btn-general { background: #EEEAE2;                 border-color: #888880;           color: #555550; }

/* Fixed-purpose info row — shown instead of buttons when the category's
   purpose_mode is fixed_*. Read-only, just communicates the bucket. */
.purpose-fixed {
  margin-top: 8px;
  padding: 6px 10px;
  background: var(--surface-2);
  border-radius: 6px;
  font-size: var(--fs-xs);
  color: var(--text-2);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* Cart row purpose stripe — 4px left-bar with the purpose colour so
   the chef sees the bucket at a glance without the chip taking up
   space. The stripe lives on .cart-item via a data-purpose attribute. */
.cart-item[data-purpose="kitchen"] { border-inline-start: 4px solid var(--purpose-kitchen); }
.cart-item[data-purpose="staff"]   { border-inline-start: 4px solid var(--purpose-staff); }
.cart-item[data-purpose="bar"]     { border-inline-start: 4px solid var(--purpose-bar); }
.cart-item[data-purpose="general"] { border-inline-start: 4px solid #888880; }
.cart-item .cart-item-purpose {
  font-size: var(--fs-xs);
  font-weight: 600;
  margin-bottom: 2px;
  display: inline-flex;
  gap: 4px;
  align-items: center;
}

/* Purpose group headers in /warehouse + /receive cards. */
.purpose-group { margin: 6px 0 10px; }
.purpose-group-header {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-2);
  padding: 6px 12px 4px;
}
.purpose-group-header-icon { font-size: 14px; }

/* /reports purpose summary card row */
.purpose-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 12px 0;
}
.purpose-summary-cell {
  flex: 1;
  min-width: 140px;
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface);
}
.purpose-summary-cell .label { font-size: var(--fs-xs); color: var(--text-2); font-weight: 600; }
.purpose-summary-cell .value { font-size: var(--fs-xl); font-weight: 700; color: var(--text); margin-top: 2px; }
.purpose-summary-cell-kitchen { border-top: 3px solid var(--purpose-kitchen); }
.purpose-summary-cell-staff   { border-top: 3px solid var(--purpose-staff); }
.purpose-summary-cell-bar     { border-top: 3px solid var(--purpose-bar); }
.purpose-summary-cell-general { border-top: 3px solid #888880; }

/* ── Multi-purpose card form & in-cart summary (sm-v21) ─────────────── */
/* Summary tile: "✓ In cart: 🍳 30 · 🧑‍🍳 10" shown on the product card
   when ≥1 cart row already exists. Replaces the v17-v20 single-counter
   pill because one product can now occupy several rows. */
.qty-block-summary {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  width: 100%;
}
.card-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  background: var(--olive-light);
  color: #4A5F3B;
  border: 1px solid #C9D9B9;
  padding: 6px 10px;
  border-radius: 6px;
  font-size: var(--fs-xs);
  font-weight: 600;
  width: 100%;
}
.card-summary-prefix { color: var(--olive); }
.card-summary-list { display: inline-flex; flex-wrap: wrap; gap: 4px; align-items: baseline; }
.card-summary-cell { display: inline-flex; align-items: baseline; gap: 2px; font-variant-numeric: tabular-nums; }
.card-summary-sep { color: var(--text-3); }

/* Per-purpose qty row inside the multi-purpose form on the product
   card. Sibling to .qty-stepper-row-stock; one row per allowed
   purpose, each tinted to match its bucket. */
.qty-purpose-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  width: 100%;
  padding-block: 2px;
}
.qty-purpose-row-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
}
/* sm-v41 — larger purpose icons. The previous design used an
   inline emoji at the row label's font-size (~12px), which got
   lost next to the qty stepper. Bumping to 22px makes the
   Kitchen / Bar / Staff Meal bucket recognizable at a glance
   even on a 360-wide phone. The .label-text sits at the regular
   label font-size so the row reads "🍳 Kitchen" with the icon
   leading. */
.qty-purpose-row-label .label-emoji {
  font-size: 22px;
  line-height: 1;
  flex-shrink: 0;
}
.qty-purpose-row-label .label-text {
  font-weight: 600;
  white-space: nowrap;
}
.qty-purpose-row-kitchen .qty-purpose-row-label { color: var(--purpose-kitchen-hover); }
.qty-purpose-row-staff   .qty-purpose-row-label { color: var(--purpose-staff-hover); }
.qty-purpose-row-bar     .qty-purpose-row-label { color: var(--purpose-bar-hover); }
.qty-purpose-row-general .qty-purpose-row-label { color: var(--text-2); }
/* Stepper background tinted with the bucket colour so the chef knows
   which input they're typing into without reading the label. */
.qty-stepper-kitchen { background: var(--purpose-kitchen) !important; }
.qty-stepper-staff   { background: var(--purpose-staff) !important; }
.qty-stepper-bar     { background: var(--purpose-bar) !important; }
.qty-stepper-general { background: #888880 !important; }

/* ── sm-v41 product-card two-zone redesign ──────────────────────
   Split the multi-purpose form into two visually distinct zones:
   ZONE 1 (top, accented): "How much is in stock?" — the first
   action. While untouched, a soft terracotta wash with a pulse
   guides the chef's eye to the stock input. The pulse stops the
   instant the input is consciously interacted with.
   ZONE 2 (below): "How much to order?" — purpose buckets. While
   stock is untouched, the zone is muted (low opacity + reduced
   saturation + pointer-events:none) so the chef literally can't
   tap a purpose stepper before recording stock. Once stock is
   touched the zone returns to full color and becomes interactive.
   Two stacked zones with their own titles keep the order of
   operations obvious: stock → order → add. */
.card-zone {
  /* sm-v41: pad only vertically — the card itself is already
     narrow on mobile (2-column layout), eating horizontal pixels
     with zone padding pushes the qty-stepper buttons outside the
     row's clip box. The visual separation comes from the border +
     background instead. */
  width: 100%;
  padding: 6px 4px;
  border-radius: var(--radius-sm);
  border: 1.5px solid transparent;
  background: var(--surface-2);
  box-sizing: border-box;
  transition: opacity .18s ease, filter .18s ease,
              border-color .18s ease, background .18s ease;
}
.card-zone + .card-zone { margin-top: 6px; }
.card-zone-title {
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--text);
  margin-bottom: 6px;
  line-height: 1.2;
}
.card-zone-hint {
  display: none;
  font-size: var(--fs-xs);
  color: var(--terracotta-hover);
  margin-top: 4px;
}
.card-zone-stock.is-untouched {
  border-color: var(--terracotta);
  background: var(--terracotta-soft, #fff5ee);
}
.card-zone-stock.is-untouched .card-zone-title { color: var(--terracotta-hover); }
.card-zone-stock.is-untouched .card-zone-hint { display: block; }
/* Pulse is opt-in for users who haven't asked the OS to reduce
   motion. Vestibular-disorder users + low-power phones get the
   border + tinted background as the visual cue without the
   shadow growing/fading. Animation is slow (2.4s) and the alpha
   peaks at 0.28 — a soft "breathing" shadow, not a strobe. */
@media (prefers-reduced-motion: no-preference) {
  .card-zone-stock.is-untouched {
    animation: card-zone-stock-pulse 2.4s ease-in-out infinite;
  }
  @keyframes card-zone-stock-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(192, 79, 21, 0.28); }
    50%      { box-shadow: 0 0 0 6px rgba(192, 79, 21, 0); }
  }
}
.card-zone-order.is-pending {
  opacity: 0.45;
  filter: saturate(0.4);
  pointer-events: none;
}
.card-zone-order.is-pending .card-zone-title { color: var(--text-3); }
/* Pin the stock row stepper inside the zone so the title sits
   on top and the stepper flows underneath. The .qty-stepper-row
   default is flex-end alignment which we want to keep — the
   .card-zone wrapper only adjusts the surrounding padding. */
.card-zone .qty-stepper-row { padding-block: 4px; }

/* Form action row: [Add to cart] + [Cancel] under the qty rows. */
.qty-block-actions {
  display: flex;
  gap: 6px;
  margin-top: 6px;
  justify-content: flex-end;
  width: 100%;
}
.qty-block-actions .btn { padding: 6px 10px; }

/* ── Tabs ─────────────────────────────────────────────────────────────────── */

.tabs {
  /* Prevent collapse in a flex column parent. When the parent .page
     becomes shorter than the sum of its children (e.g. when .adminBody
     filter row wraps to 2 lines on <1100px), the default flex-shrink:1
     combined with overflow:auto makes min-height collapse to 0, hiding
     the tab buttons. flex-shrink:0 locks min-height to content size. */
  flex-shrink: 0;
  display: flex;
  gap: 2px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 4px;
  overflow-x: auto;
}
.tab {
  /* Same rationale as .tabs above — individual tabs must keep their
     content width on narrow viewports (e.g. split-screen ~600px); the
     parent's overflow-x:auto handles horizontal scrolling if the row
     no longer fits. */
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 8px 14px;
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-2);
  cursor: pointer;
  transition: background var(--t), color var(--t);
  white-space: nowrap;
}
.tab:hover { background: var(--surface-2); color: var(--text); }
.tab.is-active { background: var(--accent); color: var(--text-inv); }
.tab-count {
  background: rgba(0,0,0,.08);
  color: inherit;
  border-radius: var(--radius-pill);
  padding: 1px 7px;
  font-size: var(--fs-xs);
  font-weight: 700;
}
.tab.is-active .tab-count { background: rgba(255,255,255,.22); }

/* ── Service-worker update toast ──────────────────────────────────────────── */
/* Shown by sw-update.js once 'controllerchange' fires (a new SW has taken
   over the page). Non-modal: user finishes whatever they're doing, then
   reloads when convenient. RTL-safe via inset-inline-* anchors. */
.update-toast {
  position: fixed;
  bottom: 16px;
  inset-inline-start: 50%;
  transform: translateX(-50%);
  background: var(--accent);
  color: var(--text-inv);
  padding: 12px 16px 12px 20px;
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font-size: var(--fs-sm);
  font-weight: 500;
  z-index: 9999;
  max-width: calc(100vw - 32px);
}
.update-toast button {
  background: var(--text-inv);
  color: var(--accent);
  border: 0;
  padding: 6px 14px;
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.update-toast button:hover { background: rgba(255,255,255,.9); }
.update-toast .update-toast-dismiss {
  background: transparent;
  color: rgba(255,255,255,.85);
  padding: 4px 8px;
  font-size: 16px;
  font-weight: 400;
}
.update-toast .update-toast-dismiss:hover {
  background: rgba(255,255,255,.15);
  color: var(--text-inv);
}
html[dir="rtl"] .update-toast { transform: translateX(50%); }

/* ── Modal ────────────────────────────────────────────────────────────────── */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15,23,42,.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-4);
  z-index: var(--z-modal);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-slow);
}
.modal-backdrop.is-open { opacity: 1; pointer-events: auto; }

.modal {
  background: var(--surface);
  border-radius: var(--radius-lg);
  width: 100%;
  max-width: 520px;
  max-height: calc(100vh - 32px);
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-xl);
  transform: translateY(8px) scale(.98);
  transition: transform var(--t-slow);
}
.modal-backdrop.is-open .modal { transform: translateY(0) scale(1); }

.modal-lg { max-width: 720px; }

/* sm-v36 — slim cart footer. Compact one-line name field at the top
   (always visible — Anton: "де імʼя щоб написати" — the answer is:
   in plain sight, every time, no modal surprise). Note collapsed
   behind a "+ Add note" ghost button that expands the textarea
   inline. Urgent flow opens a PIN-only modal; the name comes from
   the visible footer field, same source as the regular Send. */
.cart-name-field { margin-bottom: 6px; }
.cart-name-field .input { font-size: 15px; padding: 8px 10px; min-height: 40px; }

.cart-note-wrap { display: flex; flex-direction: column; gap: 6px; }
.cart-note-toggle {
  align-self: flex-start;
  padding: 6px 10px;
  font-size: 14px;
  color: var(--text-2);
}
.cart-note-toggle:hover { color: var(--text); }

/* sm-v34 — aggregated /receive screen. One big card with sections
   per warehouse → subsections per purpose → rows. One Received-by
   input + one Confirm All button at the bottom. Reuses the
   .order-card chrome; layout-only overrides here. */
.receive-aggregated { display: flex; flex-direction: column; gap: 0; }
.recv-wh-section {
  padding: 14px 16px;
  border-top: 1px solid var(--border);
}
.receive-aggregated > .recv-wh-section:first-of-type { border-top: 0; }
.recv-wh-header {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 10px;
}
.recv-wh-emoji { font-size: 20px; }
.recv-purpose-section { margin-top: 12px; }
.recv-purpose-section:first-of-type { margin-top: 0; }
.recv-purpose-header { margin-bottom: 6px; font-size: 13px; }
.recv-aggregated-name-wrap {
  padding: 14px 16px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}

/* sm-v33 — chef order history page. Simple list with day-grouped
   sections, collapsed summary row + expandable details. Reuses
   .order-card for the bones; layout-only overrides here. */
.history-stats {
  padding: 10px 14px;
  background: var(--surface-2);
  border-radius: var(--radius-md);
  font-size: 14px;
  margin-bottom: 12px;
  color: var(--text);
}
.history-day-header {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-3);
  margin: 16px 0 6px;
  padding: 0 4px;
}
.history-card { cursor: pointer; }
.history-row-summary {
  align-items: center;
  gap: 10px;
}
.history-row-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  flex: 1;
}
.history-id { font-weight: 700; font-size: 15px; }
.history-row-wh .wh-tag { font-size: 12px; padding: 2px 8px; }
.history-row-count {
  font-size: 13px;
  color: var(--text-3);
}
.history-chevron {
  color: var(--text-3);
  font-size: 18px;
  user-select: none;
  padding: 0 4px;
}
.history-body { padding: 12px 14px; }
.history-detail-line { font-size: 13px; margin-bottom: 4px; }
.history-purpose-group {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--border);
}
.history-purpose-group:first-of-type { border-top: 0; padding-top: 4px; }
.history-purpose-label {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-bottom: 6px;
}
.history-item-row { padding: 4px 0; }

.badge-status {
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 999px;
  font-weight: 600;
}
.badge-status-new      { background: var(--surface-3); color: var(--text-2); }
.badge-status-picking  { background: #FFF3E0;          color: #B25800; }
.badge-status-ready    { background: #E7F5FF;          color: #1864AB; }
.badge-status-sent     { background: var(--accent-light); color: var(--accent-hover); }
.badge-status-received { background: #E6F4EA;          color: #1E7E34; }

/* sm-v32 — Urgent order PIN modal. Smaller than the default, padded
   so the PIN input + actions sit comfortably on a phone. */
.urgent-pin-modal {
  padding: var(--sp-5);
  gap: var(--sp-3);
  max-width: 360px;
}
.urgent-pin-modal .modal-title {
  font-size: var(--fs-lg);
  margin-bottom: var(--sp-2);
}
.urgent-pin-modal .pin-input-single {
  font-size: 32px;
  letter-spacing: 8px;
  text-align: center;
  font-weight: 600;
  min-height: 56px;
  padding: 8px 12px;
}
.urgent-pin-modal .modal-actions {
  display: flex;
  gap: var(--sp-2);
  margin-top: var(--sp-2);
}
.urgent-pin-modal .modal-actions .btn { flex: 1; min-height: 44px; }

/* sm-v32 — .btn-urgent: distinct from .btn-primary so the chef can't
   mistake it for the regular Send. Terracotta outline + red accent,
   smaller height on the cart drawer so it doesn't dominate the
   primary Send when both are visible (in-window night-time). */
.btn-urgent {
  background: transparent;
  color: var(--danger);
  border: 2px solid var(--danger);
  font-weight: 600;
}
.btn-urgent:hover:not(:disabled) {
  background: var(--danger-light);
  color: var(--danger);
}
.btn-urgent.is-loading-window,
#sendOrderBtn.is-loading-window { visibility: hidden; }

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-5);
  border-bottom: 1px solid var(--border);
}
.modal-title { font-size: var(--fs-lg); font-weight: 700; margin: 0; }
.modal-close {
  width: 32px; height: 32px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-2);
  background: transparent;
  border: 0;
  cursor: pointer;
  font-size: 20px;
  transition: background var(--t), color var(--t);
}
.modal-close:hover { background: var(--surface-2); color: var(--text); }

.modal-body {
  padding: var(--sp-5);
  overflow-y: auto;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--border);
}
.modal-footer .btn { min-width: 100px; }

/* Warehouse picker — special variant of modal */
.wh-picker-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.wh-picker-card {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4);
  border: 2px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color var(--t), background var(--t), transform var(--t-fast);
  text-align: start;
  background: var(--surface);
}
.wh-picker-card:hover {
  border-color: var(--accent);
  background: var(--accent-light);
}
.wh-picker-card:active { transform: scale(.99); }
.wh-picker-emoji {
  font-size: 36px;
  width: 56px; height: 56px;
  background: var(--surface-2);
  border-radius: var(--radius);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.wh-picker-body { flex: 1; min-width: 0; }
.wh-picker-name { font-size: var(--fs-md); font-weight: 700; color: var(--text); }
.wh-picker-sub { font-size: var(--fs-xs); color: var(--text-2); margin-top: 2px; }

/* sm-v43 Stage-B — hierarchical picker chrome.
   * .wh-picker-chevron — leading hint on a root that has children
     ("tap to drill into 3 sections"). Sized 28px so it's visible
     but doesn't compete with the warehouse emoji.
   * .wh-picker-breadcrumb — header row inside the modal-body when
     the chef has drilled into a parent. Holds the back button +
     the parent-name path. Flex so the path sits next to the
     button on wide screens but the body still shrinks on phones.
   * .wh-picker-back — text-button styled. Underline on hover so
     it reads as a link, not a hard CTA.
   * .wh-picker-card-sub — subtle visual differentiation between
     the root tile and its children tiles: lighter background so
     the chef sees "you're one level deeper". */
.wh-picker-chevron {
  font-size: 28px;
  color: var(--text-3);
  flex-shrink: 0;
  margin-inline-start: auto;
  padding-inline-start: var(--sp-2);
  line-height: 1;
}
html[dir="rtl"] .wh-picker-chevron { transform: scaleX(-1); }

.wh-picker-breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding-block: var(--sp-2);
  margin-bottom: var(--sp-2);
  border-bottom: 1px dashed var(--border);
  flex-wrap: wrap;
}
.wh-picker-back {
  background: transparent;
  border: none;
  color: var(--accent);
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
}
.wh-picker-back:hover { background: var(--accent-light); text-decoration: underline; }
.wh-picker-breadcrumb-path {
  font-size: var(--fs-sm);
  color: var(--text-2);
  font-weight: 600;
}

.wh-picker-card-sub {
  background: var(--surface-2);
  border-color: var(--border-2, var(--border));
}
.wh-picker-card-sub:hover {
  background: var(--accent-light);
  border-color: var(--accent);
}

/* ── Drawer (right-side cart on desktop / bottom sheet on mobile) ──────── */

.drawer-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15,23,42,.4);
  z-index: var(--z-drawer);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-slow);
}
.drawer-backdrop.is-open { opacity: 1; pointer-events: auto; }

.drawer {
  position: fixed;
  top: 0; bottom: 0;
  inset-inline-end: 0;
  width: var(--drawer-w);
  max-width: 92vw;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  z-index: calc(var(--z-drawer) + 1);
  transform: translateX(100%);
  transition: transform var(--t-slow);
  box-shadow: var(--shadow-xl);
}
html[dir="rtl"] .drawer { transform: translateX(-100%); }
.drawer.is-open { transform: translateX(0); }
/* sm-v25: the RTL closed-state selector above has specificity (0,2,1)
   while the bare .drawer.is-open is only (0,2,0), so in RTL the
   off-screen translate WINS even when the open class is applied —
   backdrop fades in but the panel stays invisible behind it. Bump
   the open rule to (0,2,2) so it beats the dir override. */
html[dir="rtl"] .drawer.is-open { transform: translateX(0); }

.drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.drawer-title { font-size: var(--fs-lg); font-weight: 700; margin: 0; }
.drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--sp-4) var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.drawer-foot {
  border-top: 1px solid var(--border);
  padding: var(--sp-4) var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  flex-shrink: 0;
  background: var(--surface);
}

/* Mobile — sm-v35: cart drawer becomes a FULL-SCREEN page (was a
   92vh bottom sheet pre-v35; Mila/Anton's feedback: too narrow,
   too small on a phone). The flex column inside .drawer already
   gives us sticky header (.drawer-header, flex-shrink:0) + scrollable
   body (.drawer-body, flex:1 overflow-y:auto) + sticky footer
   (.drawer-foot, flex-shrink:0), so going full-screen automatically
   keeps the action button always within reach no matter how many
   items the cart has. 100dvh tracks the dynamic viewport so the iOS
   address bar collapsing doesn't briefly cover the Send button. */
@media (max-width: 767px) {
  .drawer-backdrop { display: none; }  /* nothing to dim — drawer covers everything */
  .drawer {
    top: 0;
    inset-inline-end: 0;
    inset-inline-start: 0;
    width: 100%;
    max-width: 100%;
    height: 100vh;       /* fallback for old browsers */
    height: 100dvh;      /* dynamic — matches the visible viewport */
    border-radius: 0;
    transform: translateY(100%);
    z-index: calc(var(--z-drawer) + 2);
  }
  html[dir="rtl"] .drawer { transform: translateY(100%); }
  .drawer.is-open { transform: translateY(0); }
  /* sm-v25: same specificity fix for the mobile bottom-sheet — the
     RTL closed translateY(100%) was beating the bare .is-open. */
  html[dir="rtl"] .drawer.is-open { transform: translateY(0); }

  /* Body: keep scroll inside the cart, not the page beneath. */
  .drawer-body {
    overscroll-behavior: contain;
    padding: var(--sp-3);
    gap: var(--sp-3);
  }

  /* Sticky footer with the Send/Urgent action — pad for the iPhone
     home indicator (safe-area) so the big button isn't covered. */
  .drawer-foot {
    padding: 12px 14px;
    padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -2px 8px rgba(0,0,0,0.06);
  }
  .drawer-foot .btn { min-height: 48px; font-size: 16px; }

}

/* Cart line item */
.cart-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.cart-item-photo {
  width: 44px; height: 44px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  flex-shrink: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}
.cart-item-photo img { width: 100%; height: 100%; object-fit: cover; }
.cart-item-body { flex: 1; min-width: 0; }
.cart-item-name {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
}
.cart-item-meta { font-size: var(--fs-xs); color: var(--text-3); }
.cart-item-qty {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface);
  flex-shrink: 0;
}
.cart-item-qty button {
  width: 30px; height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
  color: var(--text);
  border: 0;
  cursor: pointer;
  font-size: 16px;
}
.cart-item-qty button:hover { background: var(--surface-3); }
.cart-item-qty input {
  width: 44px;
  border: 0;
  text-align: center;
  font-size: var(--fs-sm);
  font-weight: 600;
  padding: 0;
  background: transparent;
}
.cart-item-qty input:focus { outline: none; box-shadow: 0 0 0 2px var(--accent-ring); }
.cart-item-remove {
  width: 30px; height: 30px;
  border-radius: var(--radius-sm);
  color: var(--text-3);
  background: transparent;
  border: 0;
  cursor: pointer;
  font-size: 18px;
  flex-shrink: 0;
}
.cart-item-remove:hover { color: var(--danger); background: var(--danger-light); }

/* sm-v35 — mobile cart rows enlarged so thumbs and tired eyes both
   work. Placed AFTER every .cart-item-* base rule so the
   same-specificity overrides win the cascade. Bigger photo (64),
   16 px name, 44 px-tall qty input + remove tap zone, 72 px row
   minimum so a 2- or 3-line row never feels cramped. */
@media (max-width: 767px) {
  .cart-item {
    padding: 12px;
    gap: 12px;
    min-height: 72px;
    align-items: flex-start;
  }
  .cart-item-photo {
    width: 64px; height: 64px;
    font-size: 28px;
  }
  .cart-item-name {
    font-size: 16px;
    line-height: 1.35;
  }
  .cart-item-meta { font-size: 13px; }
  .cart-item-edit { gap: 10px; margin-top: 10px; }
  .cart-item-edit-row { padding: 4px 8px; }
  .cart-item-edit-row input {
    width: 56px;
    font-size: 16px;
    min-height: 44px;
    padding: 6px 0;
  }
  .cart-item-remove {
    width: 44px; height: 44px;
    font-size: 20px;
  }
}

/* ── Order card (used on /warehouse, /receive) ───────────────────────────── */

.order-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.order-card-head {
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  background: var(--surface-2);
}
.order-card-head-meta {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.order-card-restaurant {
  font-weight: 700;
  font-size: var(--fs-md);
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}
.order-card-id {
  font-family: var(--font-mono);
  background: var(--accent-light);
  color: var(--accent);
  padding: 2px 9px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 700;
}
.order-card-time { font-size: var(--fs-xs); color: var(--text-2); }
.order-card-wh {
  font-size: var(--fs-xs);
  color: var(--text-2);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.order-card-body { padding: var(--sp-4) var(--sp-5); }
.order-card-items { display: flex; flex-direction: column; gap: var(--sp-2); }
.order-item-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
  border-bottom: 1px dashed var(--border);
}
.order-item-row:last-child { border-bottom: 0; }
.order-item-photo {
  width: 32px; height: 32px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  overflow: hidden;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
}
.order-item-photo img { width: 100%; height: 100%; object-fit: cover; }
.order-item-name {
  flex: 1;
  font-size: var(--fs-sm);
  color: var(--text);
  min-width: 0;
}
.order-item-qty {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.order-item-qty.qty-diff { color: var(--danger-dark); }
.order-item-qty .qty-strike {
  color: var(--text-3);
  text-decoration: line-through;
  margin-inline-end: 4px;
  font-weight: 500;
}
.order-item-qty .qty-arrow {
  color: var(--text-3);
  margin-inline: 4px;
  font-weight: 500;
}
.order-item-qty .qty-short { color: var(--warning-dark); font-weight: 600; }
.order-item-qty .qty-loss  { color: var(--danger-dark);  font-weight: 600; }
.order-item-qty .qty-tag {
  font-size: 11px;
  font-weight: 500;
  padding: 1px 5px;
  border-radius: 4px;
  margin-inline-start: 4px;
  vertical-align: 1px;
}
.order-item-qty .qty-tag-short {
  background: var(--warning-light);
  color: var(--warning-dark);
}
.order-item-qty .qty-tag-loss {
  background: var(--danger-light);
  color: var(--danger-dark);
}

/* Reports table cell highlights — short = sent < ordered, loss = received < sent */
.table td.is-num.cell-short {
  background: var(--warning-light);
  color: var(--warning-dark);
  font-weight: 600;
}
.table td.is-num.cell-loss {
  background: var(--danger-light);
  color: var(--danger-dark);
  font-weight: 600;
}

.order-card-foot {
  padding: var(--sp-3) var(--sp-5);
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  background: var(--surface-2);
}

/* Inline send form on /warehouse */
.send-form {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-5);
  background: var(--surface-2);
  border-top: 1px solid var(--border);
}
.send-form-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.send-form-row .order-item-name { font-weight: 500; }
.send-form-row input {
  width: 84px;
  padding: 6px 8px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  text-align: end;
  font-variant-numeric: tabular-nums;
}
.send-form-row input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}
.send-form-row .unit-label { font-size: var(--fs-xs); color: var(--text-3); min-width: 28px; }

/* Receive issue-type picker — appears under a recv-row when the cook
   types a number that differs from qty_sent. Four touch-target tiles
   in a 2x2 grid (single line on wide screens). One selected at a time
   (radio behaviour driven by JS toggling .is-selected). */
.recv-issue-block {
  margin-top: var(--sp-2);
  padding: var(--sp-3);
  border: 1px dashed var(--warning);
  border-radius: var(--radius-sm);
  background: rgba(255,255,255,.55);
}
.recv-issue-prompt {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  margin-bottom: var(--sp-2);
}
.issue-types-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-2);
}
@media (min-width: 640px) {
  .issue-types-grid { grid-template-columns: repeat(4, 1fr); }
}
.issue-type-btn {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 10px 8px;
  min-height: 64px;
  background: var(--surface);
  color: var(--text);
  border: 2px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  font-weight: 600;
  cursor: pointer;
  text-align: center;
  transition: border-color var(--t), background var(--t);
}
.issue-type-btn-emoji { font-size: 22px; line-height: 1; }
.issue-type-btn:hover { border-color: var(--terracotta-hover); }
.issue-type-btn.is-selected {
  border-color: var(--terracotta);
  background: var(--terracotta-light);
  color: var(--terracotta-hover);
}
.recv-issue-comment {
  margin-top: var(--sp-2);
}
.recv-issue-comment input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  background: var(--surface);
}
.recv-issue-comment input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-ring);
}
.recv-issue-warning {
  font-size: var(--fs-xs);
  color: var(--danger-dark);
  font-weight: 600;
  margin-top: var(--sp-2);
}

/* Sticky date header above each calendar-day group in /receive list.
   Position sticky lifts the header to the top of the scroll viewport
   so the chef always knows which day they're scanning. */
.date-group { margin-bottom: var(--sp-4); }
.date-group-header {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--bg);
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--text);
  letter-spacing: .02em;
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--sp-2);
}

/* Detailed issue badge in order rows — shows the first issue inline so
   the chef/admin/keeper sees WHAT went wrong without opening details.
   "Lamb Shank: ordered 6 → received 4 kg (wrong qty)" + "+N more"
   if there are additional issues. */
.issue-detail {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-xs);
  color: var(--danger-dark);
  background: var(--danger-light);
  border: 1px solid var(--danger);
  border-radius: var(--radius-sm);
  padding: 6px 8px;
  margin-top: var(--sp-2);
}
.issue-detail-product { font-weight: 700; }
.issue-detail-chain   { color: var(--text-2); font-variant-numeric: tabular-nums; }
.issue-detail-type    { font-weight: 600; }
.issue-detail-more    { color: var(--text-2); font-style: italic; }

/* Issue-type tag inside the /reports detail modal — terracotta pill
   beside the per-item qty chain. */
.issue-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--terracotta-light);
  color: var(--terracotta-hover);
  border: 1px solid var(--terracotta);
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 700;
  white-space: nowrap;
}
.issue-comment {
  font-style: italic;
  color: var(--text-2);
  font-size: var(--fs-xs);
  margin-top: 2px;
}

/* Receive form variant — each row gets ✓/✗ buttons and a qty input */
.recv-row { padding: var(--sp-3); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); }
.recv-row.is-ok      { background: var(--success-light); border-color: var(--success); }
.recv-row.is-diff    { background: var(--warning-light); border-color: var(--warning); }
.recv-row-top {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
}
.recv-row-photo {
  width: 36px; height: 36px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  flex-shrink: 0;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.recv-row-photo img { width: 100%; height: 100%; object-fit: cover; }
.recv-row-name { flex: 1; min-width: 140px; font-size: var(--fs-sm); font-weight: 500; }
.recv-row-sent { font-size: var(--fs-xs); color: var(--text-2); }
.recv-row-controls {
  display: flex; align-items: center; gap: var(--sp-2);
  margin-inline-start: auto;
}
.recv-row-recv-label {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-2);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.recv-row-controls input.recv-qty-input {
  width: 72px;
  padding: 6px 8px;
  border: 2px solid var(--accent);
  border-radius: var(--radius-sm);
  text-align: end;
  font-size: var(--fs-md);
  font-weight: 700;
  background: var(--surface);
  font-variant-numeric: tabular-nums;
}
.recv-row.is-diff .recv-row-controls input.recv-qty-input {
  border-color: var(--warning-dark);
  background: var(--surface);
}
.recv-row-controls input {
  width: 72px;
  padding: 6px 8px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  text-align: end;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.recv-row-controls input:disabled { background: var(--surface-3); color: var(--text-3); }
.recv-row-btn {
  width: 36px; height: 36px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-2);
  background: var(--surface);
  font-size: 16px;
  cursor: pointer;
  transition: background var(--t), border-color var(--t), color var(--t);
}
.recv-row-btn.ok-btn:hover    { background: var(--success-light); border-color: var(--success); color: var(--success-dark); }
.recv-row-btn.diff-btn:hover  { background: var(--warning-light); border-color: var(--warning); color: var(--warning); }
.recv-row.is-ok   .ok-btn   { background: var(--success); border-color: var(--success); color: var(--text-inv); }
.recv-row.is-diff .diff-btn { background: var(--warning); border-color: var(--warning); color: var(--text-inv); }

/* ── Empty state ─────────────────────────────────────────────────────────── */

.empty {
  text-align: center;
  padding: var(--sp-10) var(--sp-5);
  color: var(--text-2);
}
.empty-icon { font-size: 48px; opacity: .5; margin-bottom: var(--sp-3); }
.empty-title { font-size: var(--fs-md); font-weight: 600; color: var(--text); margin-bottom: 4px; }
.empty-text { font-size: var(--fs-sm); color: var(--text-2); }

/* ── Skeleton / spinner ──────────────────────────────────────────────────── */

.spinner {
  display: inline-block;
  width: 16px; height: 16px;
  border-radius: 50%;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  animation: spin .8s linear infinite;
}
.spinner-lg { width: 28px; height: 28px; border-width: 3px; }
@keyframes spin { to { transform: rotate(360deg); } }

.loading {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: var(--sp-10);
  color: var(--text-3);
  gap: var(--sp-3);
}

/* ── Toast ───────────────────────────────────────────────────────────────── */

.toast-host {
  position: fixed;
  inset-block-end: var(--sp-5);
  inset-inline-start: 50%;
  transform: translateX(-50%);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  pointer-events: none;
}
html[dir="rtl"] .toast-host { transform: translateX(50%); }

.toast {
  background: var(--text);
  color: var(--text-inv);
  padding: 10px 16px;
  border-radius: var(--radius);
  font-size: var(--fs-sm);
  font-weight: 500;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--t-slow), transform var(--t-slow);
  pointer-events: auto;
  max-width: 360px;
}
.toast.is-open { opacity: 1; transform: translateY(0); }
.toast-success { background: var(--success-dark); }
.toast-error   { background: var(--danger-dark); }

/* ── Tables ──────────────────────────────────────────────────────────────── */

.table-wrap {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: auto;
  background: var(--surface);
}
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.table th, .table td {
  padding: 10px 14px;
  text-align: start;
  vertical-align: middle;
}
.table thead th {
  background: var(--surface-2);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-2);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 2;
}
.table tbody tr { border-bottom: 1px solid var(--border); }
.table tbody tr:last-child { border-bottom: 0; }
.table tbody tr:hover { background: var(--surface-2); }
.table td.is-num, .table th.is-num {
  text-align: end;
  font-variant-numeric: tabular-nums;
}

/* Stat card */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--sp-4);
}
.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.stat-card-label {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-2);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.stat-card-value {
  font-size: var(--fs-2xl);
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.stat-card-sub { font-size: var(--fs-xs); color: var(--text-3); }

/* Success splash (after order send) */
.success-splash {
  text-align: center;
  padding: var(--sp-10) var(--sp-5);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
}
.success-splash-tick {
  width: 64px; height: 64px;
  border-radius: 50%;
  background: var(--success);
  color: var(--text-inv);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 32px;
  box-shadow: 0 0 0 8px var(--success-light);
}
.success-splash-title { font-size: var(--fs-xl); font-weight: 700; }
.success-splash-id {
  font-family: var(--font-mono);
  background: var(--accent-light);
  color: var(--accent);
  padding: 4px 12px;
  border-radius: var(--radius-pill);
  font-weight: 700;
}

/* ─────────────────────────────────────────────────────────────────────────
   sm-v29 — bigger product cards on mobile (Mila feedback: too small).
   Two cards per row is preserved (.products-grid forces repeat(2, 1fr)
   in layout.css). On a 360px viewport the card body ends up ~140px wide,
   which is too narrow to fit a 44px button + decent input + label all
   on one horizontal line. So on mobile we stack the rows vertically:
   label above, full-width stepper below. The stepper itself uses
   44×44px buttons (WCAG touch target) and an 18px input — comfortable
   thumb territory.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 767px) {
  /* Card text — Mila TZ "більший шрифт, читабельніше". */
  .product-card-name { font-size: 16px; line-height: 1.35; }
  .product-card-unit { font-size: 13px; }
  .product-card-body { padding: 10px 11px 12px; gap: 6px; }
  .product-card-placeholder-initials { font-size: 32px; }
  .product-card-placeholder-text     { font-size: 13px; }

  /* Stack STOCK / per-purpose rows vertically so the stepper isn't
     fighting the label for horizontal room in a 140px-wide content area. */
  .qty-stepper-row,
  .qty-purpose-row {
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
  }
  .qty-stepper-row-label,
  .qty-purpose-row-label {
    text-align: start;       /* logical: left LTR / right RTL */
    min-width: 0;
    font-size: 13px;
  }

  /* Bigger touch targets — buttons 44×44px (WCAG 2.5.5 recommended),
     input grows to fill row, font 18px so digits are easy to read.
     Apply only to the small stepper variant (qty-stepper-sm) used on
     product cards; the larger ones already are big enough. */
  .qty-stepper-sm                  { box-shadow: var(--shadow-md); }
  .qty-stepper-sm button           { width: 44px; min-height: 44px; font-size: 22px; }
  .qty-stepper-sm .qty-val-input   { flex: 1; min-width: 50px; min-height: 44px; font-size: 18px; }

  /* Min-qty hint ("min 5 kg") — readable, not a tiny grey label. */
  .min-qty-hint { font-size: 13px; }

  /* sm-v31 — Add to cart / Cancel stacked on mobile.
     Pre-v31 the two buttons sat in a flex row with .btn-primary
     getting flex:1. On a 360–390 px card body (≈150 px content area)
     the row needed ~180 px and the primary button clipped past the
     LEFT edge of the card — Anton's iPhone screenshot showed "dd to
     cart". Stacking vertically with full-width buttons guarantees
     the label is never cropped, gives a comfortable 44 px touch
     target, and reads naturally as "primary action above, secondary
     below". Column flips correctly in RTL automatically (column is
     a logical-axis layout — direction:rtl only mirrors row axes). */
  .qty-block-actions {
    flex-direction: column;
    gap: 8px;
  }
  .qty-block-actions .btn {
    width: 100%;
    min-height: 44px;
    font-size: 14px;
    padding: 8px 14px;
  }
  /* Card padding-bottom — bump so the stacked buttons aren't flush
     with the rounded card edge. */
  .product-card-body { padding-bottom: 14px; }

  /* Cart summary on the product card ("✓ In cart: 🍳 30 · 🧑‍🍳 10") */
  .card-summary { font-size: 13px; padding: 8px 11px; }

  /* The legacy purpose picker (sm-v20 style, used by choice_all
     categories that still render explicit buttons) — make them
     thumb-friendly too. */
  .purpose-pick-btn         { min-height: 48px; font-size: 13px; }
  .purpose-pick-btn-emoji   { font-size: 22px; }

  /* FAB on a fresh product card — was 40×40 in the existing rule,
     bump to 48×48 so the chef's first tap is a comfortable target. */
  .product-card .fab        { width: 48px; height: 48px; font-size: 26px; }
}
