/* ==========================================================================
   Dibs — customer app stylesheet.
   Consumes assets/tokens.css only. No colour is defined here; every value is
   a var(). Mobile-first: 375px is the design target, desktop is the
   adaptation (a two-column layout, not a phone in a frame).

   Sections
     1  base + utilities
     2  app shell, screens, scrolling
     3  top header
     4  bottom nav / desktop rail
     5  section heads, chips, rails
     6  cards (shop, product, order)
     7  badges + the status system (colour-blind safe)
     8  slot picker
     9  order flow (cart, checkout, confirm)
    10  order status
    11  account
    12  sheets, dialogs, toasts, empty states
    13  desktop
   ========================================================================== */

/* ============================================================ 1. base ==== */
*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--font-body);
  font-size: var(--t-base);
  line-height: 1.55;
  color: var(--ink);
  background: var(--paper-sink);
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
svg { display: block; }
img { max-width: 100%; }

button {
  font: inherit;
  color: inherit;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
}

a { color: var(--brand); text-decoration: none; }
a:hover { color: var(--brand-deep); text-decoration: underline; }

input, select, textarea {
  font: inherit;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line-input);
  border-radius: var(--r-sm);
  padding: 11px 12px;
  width: 100%;
  min-height: 44px;
}
input::placeholder, textarea::placeholder { color: var(--ink-soft); }
textarea { min-height: 76px; resize: vertical; }

/* Screen-reader only, but focusable (skip links). */
.vh {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap;
}
.hidden { display: none !important; }

/* Touch target floor. Some controls are visually compact by design (a 34px
   star, a 36px secondary pill). This expands the *hit* box to 44px without
   changing the drawn size. Do not use it inside an `overflow:hidden` parent —
   the expansion would be clipped; give that control a real 44px instead. */
.hit44 { position: relative; }
.hit44::after {
  content: "";
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: max(100%, 44px);
  height: max(100%, 44px);
}

/* Screen headings are focused programmatically after a route change so screen
   readers announce the new screen. That is not a keyboard landing spot, so it
   must not paint a focus ring. Real focusable controls keep theirs. */
[data-focus][tabindex="-1"]:focus,
[data-focus][tabindex="-1"]:focus-visible { outline: none; }

/* Keyboard focus. Ink rather than brand green: it stays visible on white, on
   the warm and sink tints and on the green primary button alike, and it does
   not ask the eye to resolve a hue. Never remove this without a replacement.
   Measured by tools/check-contrast.py. */
:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }

/* CONTRAST RULE. --ink-faint was #77877D (3.79:1 on white), which failed the
   4.5:1 bar for text everywhere it was used. It is now #647269: 5.06:1 on
   white, 4.78:1 on --paper-warm, 4.50:1 on --paper-sink, so it is safe for
   fine print. --ink-soft (7.3:1) remains the choice for anything a customer
   actually has to read. --amber stays 3.3:1 on --amber-wash, so amber is a
   fill, a border and an icon colour — never a text colour.
   Re-measure with: python3 tools/check-contrast.py */
.ico { width: 20px; height: 20px; flex: 0 0 auto; }
.ico-sm { width: 15px; height: 15px; }
.ico-lg { width: 24px; height: 24px; }

/* Skip link for keyboard users. */
.skip {
  position: absolute; left: 8px; top: -60px; z-index: 900;
  background: var(--ink); color: var(--paper);
  padding: 10px 14px; border-radius: var(--r-sm); font-weight: 600;
}
.skip:focus { top: 8px; color: var(--paper); text-decoration: none; }

/* ======================================================= 2. app shell ==== */
.app {
  position: relative;
  width: 100%;
  max-width: 440px;
  min-height: 100dvh;
  margin-inline: auto;
  background: var(--paper-warm);
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
}

/* Each screen is its own block so tabs keep their scroll position. */
.screens { flex: 1 1 auto; position: relative; }

/* NOTE: this animation is opacity-only on purpose. Animating `transform` here
   would turn .screen into a containing block for `position: fixed`, which
   silently drops the basket bar and the flow footer into the page flow. */
.screen {
  display: none;
  padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px) + 24px);
  animation: fadeIn .22s ease both;
}
.screen.is-active { display: block; }

@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

/* The order flow has no bottom nav; it reserves room for its sticky footer. */
.app--flow .screen { padding-bottom: calc(104px + env(safe-area-inset-bottom, 0px)); }

@keyframes riseIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* Standard horizontal gutter. One value, no exceptions. */
.gut { padding-inline: 16px; }
.stack > * + * { margin-top: 12px; }

/* ====================================================== 3. top header ==== */
.hd {
  position: sticky;
  top: 0;
  z-index: 400;
  background: color-mix(in srgb, var(--paper-warm) 92%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid transparent;
  padding: 12px 16px 10px;
  transition: border-color .18s ease;
}
.hd.is-stuck { border-bottom-color: var(--line); }

.hd-row { display: flex; align-items: center; gap: 10px; }
.hd-row + .hd-row { margin-top: 10px; }

/* The wordmark is always the file in brand/ — never type plus a dot. The
   reservation token IS the tittle of the i, which is the whole idea; a
   hand-rolled version puts the dot after the word and loses it. */
.wm { display: block; height: auto; flex: 0 0 auto; }

.hd-place {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 36px; padding: 0 11px;
  border-radius: var(--r-pill);
  background: var(--paper);
  border: 1px solid var(--line);
  font-size: var(--t-sm); font-weight: 600;
  min-width: 0;
}
.hd-place span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hd-place .ico { color: var(--brand); }

.hd-spacer { flex: 1 1 auto; }

.hd-btn {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  color: var(--ink-soft);
  flex: 0 0 auto;
}
.hd-btn:hover { background: var(--paper-sink); color: var(--ink); }
.hd-btn:active { transform: scale(.94); }

.hd-title {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.02em;
}
.hd-sub { font-size: var(--t-xs); color: var(--ink-soft); margin-top: 2px; }

/* Language switch — small, always reachable. */
.langwrap { position: relative; flex: 0 0 auto; }
.langbtn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 13px;
  border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  background: var(--paper); color: var(--ink);
  font-size: var(--t-sm); font-weight: 700;
  cursor: pointer;
  min-height: 40px;
}
.langbtn:hover { border-color: var(--ink); }
.langbtn .lg-ico { width: 16px; height: 16px; opacity: .8; }
.langbtn .lg-cur { letter-spacing: .02em; }
.langbtn .lg-caret { width: 13px; height: 13px; opacity: .55; }
.langmenu {
  position: absolute; top: calc(100% + 8px); right: 0;
  min-width: 170px; max-height: 320px; overflow-y: auto;
  background: var(--paper); border: 1px solid var(--line-strong);
  border-radius: var(--r-md); padding: 5px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .14); z-index: 80;
}
.langmenu .lang-opt {
  display: block; width: 100%; text-align: left;
  padding: 8px 12px;
  font-size: var(--t-sm); font-weight: 600; letter-spacing: 0;
  color: var(--ink);
  border-radius: 8px;
}
.langmenu .lang-opt:hover { background: var(--paper-warm); }
.langmenu .lang-opt[aria-selected="true"] {
  background: var(--ink); color: var(--paper); font-weight: 700;
}

/* Back bar for pushed views (shop, order status, flow steps). */
.backbar {
  position: sticky; top: 0; z-index: 400;
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px 6px 4px;
  background: color-mix(in srgb, var(--paper-warm) 94%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
  min-height: 52px;
}
.btn-back {
  display: inline-flex; align-items: center; gap: 4px;
  min-height: 44px; padding: 0 10px;
  border-radius: var(--r-sm);
  font-size: var(--t-sm); font-weight: 600; color: var(--ink-soft);
  flex: 0 0 auto;
}
.btn-back:hover { background: var(--paper-sink); color: var(--ink); }
.backbar-title {
  flex: 1 1 auto; min-width: 0;
  font-size: var(--t-sm); font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Step counter in the order flow. */
.steps-dots { display: flex; align-items: center; gap: 4px; padding-right: 6px; flex: 0 0 auto; }
.steps-dots i {
  width: 18px; height: 4px; border-radius: 2px;
  background: var(--line-strong);
}
.steps-dots i.on { background: var(--brand); }

/* ====================================================== 4. bottom nav ==== */
.tabbar {
  position: fixed;
  left: 50%; transform: translateX(-50%);
  bottom: 0;
  width: 100%; max-width: 440px;
  z-index: 600;
  display: grid; grid-template-columns: repeat(3, 1fr);
  background: color-mix(in srgb, var(--paper) 94%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.rail-brand { display: none; }

.tab {
  position: relative;
  height: 64px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  font-size: 11px; font-weight: 600;
  color: var(--ink-soft);
  transition: color .15s ease, transform .15s ease;
}
.tab:active { transform: scale(.94); }
.tab .ico { width: 23px; height: 23px; }
.tab[aria-current="page"] { color: var(--brand-deep); }
.tab[aria-current="page"]::before {
  content: "";
  position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
  width: 40px; height: 28px; border-radius: var(--r-pill);
  background: var(--brand-wash);
  z-index: -1;
}
.tab-badge {
  position: absolute; top: 6px; right: calc(50% - 23px);
  min-width: 18px; height: 18px; padding: 0 4px;
  border-radius: var(--r-pill);
  background: var(--brand); color: var(--paper);
  border: 2px solid var(--paper);
  font-size: 10px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  display: grid; place-items: center;
}

/* ==================================== 5. section heads, chips, rails ==== */
.sect { padding: 18px 16px 4px; }
.sect-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-bottom: 10px;
}
.sect-head-l { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1 1 auto; }
.sect-title {
  font-family: var(--font-display);
  font-size: var(--t-md); font-weight: 700; letter-spacing: -.02em;
  line-height: 1.25;
}
.sect-count {
  font-size: var(--t-xs); font-weight: 600; color: var(--ink-soft);
  white-space: nowrap; flex: 0 0 auto;
}

/* Search field with the magnifier tucked inside. */
.searchwrap { position: relative; }
.searchwrap > .ico {
  position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
  color: var(--ink-faint); pointer-events: none;
}
.searchwrap input { padding-left: 42px; border-radius: var(--r-pill); }

/* The trade filters overflow at 375px by design. The mask makes the last chip
   fade instead of being sliced mid-word, which reads as "scroll me" rather
   than "broken". */
.chips {
  display: flex; gap: 8px;
  overflow-x: auto;
  padding: 12px 16px 6px;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
  -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 34px), transparent 100%);
          mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 34px), transparent 100%);
}
.chips::-webkit-scrollbar { display: none; }
.chips > .chip { scroll-snap-align: start; }
/* Once everything fits there is nothing to scroll, so drop the fade. */
@media (min-width: 1024px) {
  .chips { -webkit-mask-image: none; mask-image: none; flex-wrap: wrap; overflow: visible; }
}
.chip {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 6px;
  height: 44px; padding: 0 15px;
  border-radius: var(--r-pill);
  background: var(--paper);
  border: 1px solid var(--line);
  font-size: var(--t-sm); font-weight: 600; color: var(--ink-soft);
  transition: background .18s ease, color .18s ease, border-color .18s ease;
  white-space: nowrap;
}
.chip .ico { width: 17px; height: 17px; }
.chip:hover { border-color: var(--line-strong); color: var(--ink); }
.chip:active { transform: scale(.96); }
.chip[aria-pressed="true"] {
  background: var(--ink); border-color: var(--ink); color: var(--paper);
}

/* Horizontal rail: gutters live in the padding so cards bleed to the edge. */
.rail {
  display: flex; gap: 10px;
  overflow-x: auto;
  padding: 2px 16px 10px;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
  scroll-padding-left: 16px;
}
.rail::-webkit-scrollbar { display: none; }
.rail > * { scroll-snap-align: start; }

/* ============================================================ 6. cards ==== */
.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
}

/* ---- shop card (the discover workhorse) ---- */
.shopcard {
  position: relative;
  display: flex; gap: 12px; align-items: stretch;
  padding: 12px;
  margin-bottom: 10px;
  width: 100%; text-align: left;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  animation: riseIn .3s cubic-bezier(.32, .72, .35, 1) both;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.shopcard:nth-child(2) { animation-delay: .04s; }
.shopcard:nth-child(3) { animation-delay: .08s; }
.shopcard:nth-child(4) { animation-delay: .12s; }
.shopcard:hover { border-color: var(--line-strong); box-shadow: var(--shadow-lift); }
.shopcard:active { transform: scale(.995); }
.shopcard.is-closed { background: var(--paper-warm); }

.tile {
  flex: 0 0 48px; width: 48px; height: 48px;
  border-radius: 14px;
  display: grid; place-items: center;
  color: var(--brand-deep);
  background: var(--brand-wash);
  border: 1px solid color-mix(in srgb, var(--brand) 18%, transparent);
}
.tile .ico { width: 25px; height: 25px; }
.tile--cafe        { background: var(--slate-wash);  color: var(--slate);      border-color: color-mix(in srgb, var(--slate) 18%, transparent); }
.tile--boulangerie { background: var(--amber-wash);  color: var(--amber);      border-color: color-mix(in srgb, var(--amber) 22%, transparent); }
.tile--boucherie   { background: var(--alert-wash);  color: var(--alert);      border-color: color-mix(in srgb, var(--alert) 18%, transparent); }
.tile--traiteur    { background: var(--brand-wash);  color: var(--brand-deep); border-color: color-mix(in srgb, var(--brand) 20%, transparent); }
.tile--sm { flex-basis: 38px; width: 38px; height: 38px; border-radius: 11px; }
.tile--sm .ico { width: 20px; height: 20px; }
.tile--lg { flex-basis: 60px; width: 60px; height: 60px; border-radius: 17px; }
.tile--lg .ico { width: 31px; height: 31px; }

.shop-main { flex: 1 1 auto; min-width: 0; }
.shop-name {
  display: block;
  font-size: 15px; font-weight: 700; letter-spacing: -.01em;
  color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
a.shop-name:hover { color: var(--ink); text-decoration: none; }
/* Stretched link: the whole card is the target, but the star button and any
   other control inside stays independently clickable. */
a.shop-name::after { content: ""; position: absolute; inset: 0; z-index: 0; }
.shopcard .pin-btn, .shopcard .btn { position: relative; z-index: 1; }
/* Metadata atoms are separated by space, not by "·" glyphs: a separator is
   its own inline box and gets stranded at the end of a wrapped line. */
.shop-meta {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 2px 11px;
  font-size: var(--t-xs); color: var(--ink-soft);
  margin-top: 3px;
}
.shop-meta .mi { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.shop-meta .ico { width: 13px; height: 13px; }
.shop-meta .star { color: var(--amber); }
.shop-meta .num { font-weight: 600; font-variant-numeric: tabular-nums; }

.shop-line {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin-top: 8px; min-width: 0;
}
/* A long availability label must clip, never push into the price column. */
.shop-line .pill { max-width: 100%; min-width: 0; }
.shop-line .pill > span { overflow: hidden; text-overflow: ellipsis; }

.shop-side {
  display: flex; flex-direction: column; align-items: flex-end;
  justify-content: space-between; gap: 8px;
  flex: 0 0 auto;
}
.shop-from {
  display: inline-flex; align-items: baseline; gap: 4px;
  font-size: 10.5px; color: var(--ink-soft);
  white-space: nowrap; line-height: 1.25;
}
.shop-from b {
  font-size: var(--t-sm); font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
}

/* Regular-shop marker: a "dibs" token you place on a shop. */
.pin-btn {
  position: relative;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  color: var(--ink-faint);
  border: 1px solid var(--line);
  background: var(--paper);
  flex: 0 0 auto;
}
.pin-btn::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%); width: 44px; height: 44px;
}
.pin-btn:hover { color: var(--brand); border-color: var(--brand); }
.pin-btn[aria-pressed="true"] {
  color: var(--paper); background: var(--brand); border-color: var(--brand);
}

.shoplist { padding-inline: 16px; }

/* ---- rail card: last slots of the day ---- */
.slotcard {
  flex: 0 0 218px;
  position: relative; overflow: hidden;
  padding: 12px;
  text-align: left;
  background: var(--paper);
  border: 1px solid color-mix(in srgb, var(--amber) 34%, transparent);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
}
.slotcard::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--amber);
}
.slotcard-top {
  display: flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 700; color: var(--ink);
  margin-bottom: 6px;
  font-variant-numeric: tabular-nums;
}
.slotcard-top .ico { width: 14px; height: 14px; color: var(--amber); }
.slotcard-name {
  font-size: var(--t-sm); font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.slotcard-meta {
  font-size: 11.5px; color: var(--ink-soft); margin: 2px 0 10px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.slotcard-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; }

/* ---- grouped list card ---- */
.listcard {
  margin: 0 16px 12px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.listcard-title {
  font-size: var(--t-sm); font-weight: 700;
  padding: 14px 14px 8px;
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.listcard-title span { font-size: var(--t-xs); font-weight: 600; color: var(--ink-soft); }
.row {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 14px;
  border-top: 1px solid var(--line);
  width: 100%; text-align: left;
}
.row:first-of-type { border-top: 0; }
.row-main { flex: 1 1 auto; min-width: 0; }
.row-name {
  font-size: 13.5px; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row-meta { font-size: 11.5px; color: var(--ink-soft); }
.nowrap { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.clamp2 {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.35;
}
.row-end { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; color: var(--ink-faint); }
svg.row-end { width: 18px; height: 18px; }
button.row:hover { background: var(--paper-warm); }

/* ---- product row (shop screen) ---- */
.prod {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 12px 14px;
  border-top: 1px solid var(--line);
}
.prod:first-of-type { border-top: 0; }
.prod.is-out { background: var(--paper-warm); }
.prod.is-out .prod-name, .prod.is-out .prod-price { color: var(--ink-soft); }
.prod-main { flex: 1 1 auto; min-width: 0; }
.prod-name { font-size: 14.5px; font-weight: 700; letter-spacing: -.01em; }
.prod-desc {
  font-size: var(--t-xs); color: var(--ink-soft); line-height: 1.45;
  margin-top: 2px;
}
.prod-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.prod-side {
  flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
}
.prod-price {
  font-size: var(--t-sm); font-weight: 700; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.prod-unit { font-size: 10.5px; color: var(--ink-soft); font-weight: 500; }

/* Round add button — 44px hit area, "+" glyph carries the meaning. */
.add-btn {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  background: var(--brand); color: var(--paper);
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.add-btn:hover { background: var(--brand-deep); box-shadow: 0 4px 12px rgba(15, 122, 67, .28); }
.add-btn:active { transform: scale(.92); }
.add-btn[disabled] {
  background: var(--paper-sink); color: var(--ink-faint);
  cursor: not-allowed; box-shadow: none;
}

/* ================================== 7. badges + status (CVD-safe) ======== */
/* Every pill carries a text label. Colour is reinforcement, never the message.
   Icons come from the shared sprite and differ in SHAPE, so the set stays
   readable in greyscale. */
.pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  font-size: 11.5px; font-weight: 700; line-height: 1.5;
  white-space: nowrap;
  background: var(--paper-sink); color: var(--ink-soft);
  border: 1px solid transparent;
}
.pill .ico { width: 13px; height: 13px; }
.pill .num { font-variant-numeric: tabular-nums; }
.pill--brand { background: var(--brand-wash); color: var(--brand-deep); }
.pill--amber { background: var(--amber-wash); color: var(--ink); }
.pill--amber .ico { color: var(--amber); }
.pill--slate { background: var(--slate-wash); color: var(--slate); }
.pill--alert { background: var(--alert-wash); color: var(--alert); }
.pill--ink   { background: var(--ink); color: var(--paper); }
.pill--out   { background: var(--paper); border-color: var(--line-strong); color: var(--ink-soft); }
.pill--lg { font-size: var(--t-xs); padding: 5px 11px; }

.tag {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 7px;
  border-radius: var(--r-sm);
  font-size: 11px; font-weight: 600;
  background: var(--paper-sink); color: var(--ink-soft);
}
.tag--diet { background: var(--brand-wash); color: var(--brand-deep); }
.tag--allergen { background: var(--paper); border: 1px solid var(--line); color: var(--ink-soft); }

/* Status chip. .st--<status> sets the hue; the label and icon do the work. */
.st {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  font-size: var(--t-xs); font-weight: 700;
  border: 1px solid transparent;
  white-space: nowrap;
}
.st .ico { width: 15px; height: 15px; }
.st--placed    { background: var(--slate-wash); color: var(--slate);      border-color: color-mix(in srgb, var(--slate) 24%, transparent); }
.st--ready     { background: var(--brand-wash); color: var(--brand-deep); border-color: color-mix(in srgb, var(--brand) 28%, transparent); }
.st--collected { background: var(--paper-sink); color: var(--ink);        border-color: var(--line-strong); }
.st--cancelled,
.st--no_show   { background: var(--alert-wash); color: var(--alert);      border-color: color-mix(in srgb, var(--alert) 26%, transparent); }

/* Buttons ---------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 0 18px;
  border-radius: var(--r-pill);
  font-size: var(--t-sm); font-weight: 700;
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease, border-color .15s ease;
  text-decoration: none;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: scale(.98); }
.btn .ico { width: 18px; height: 18px; }
.btn--primary { background: var(--brand); color: var(--paper); }
.btn--primary:hover { background: var(--brand-deep); color: var(--paper); box-shadow: 0 6px 16px rgba(15, 122, 67, .26); }
.btn--ghost { background: var(--paper); color: var(--ink); border: 1px solid var(--line-strong); }
.btn--ghost:hover { background: var(--paper-warm); color: var(--ink); border-color: var(--ink-faint); }
.btn--quiet { background: transparent; color: var(--ink-soft); }
.btn--quiet:hover { background: var(--paper-sink); color: var(--ink); }
.btn--danger { background: var(--paper); color: var(--alert); border: 1px solid color-mix(in srgb, var(--alert) 42%, transparent); }
.btn--danger:hover { background: var(--alert-wash); color: var(--alert); }
.btn--block { width: 100%; }
.btn--sm { position: relative; min-height: 38px; padding: 0 13px; font-size: var(--t-xs); }
.btn--sm .ico { width: 15px; height: 15px; }
.btn--sm::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%); width: 100%; height: 44px;
}
.btn--lg { min-height: 52px; font-size: var(--t-base); }
.btn[disabled], .btn[aria-disabled="true"] {
  background: var(--paper-sink); color: var(--ink-faint);
  border-color: transparent; cursor: not-allowed; box-shadow: none;
}
.btn[disabled]:active { transform: none; }

/* ===================================================== 8. slot picker ==== */
.slotpick { padding: 0 16px; }

.daytabs { display: flex; gap: 8px; margin-bottom: 16px; }
.daytab {
  flex: 1 1 0; min-width: 0;
  min-height: 68px; padding: 8px 6px;
  border-radius: var(--r);
  border: 1.5px solid var(--line);
  background: var(--paper);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px;
  font-size: var(--t-sm); font-weight: 700; color: var(--ink-soft);
  transition: border-color .18s ease, background .18s ease, color .18s ease;
}
.daytab small { font-size: 11px; font-weight: 600; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.daytab:hover { border-color: var(--line-strong); }
.daytab[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.daytab[aria-pressed="true"] small { color: color-mix(in srgb, var(--paper) 72%, transparent); }

.slotgroup { margin-bottom: 18px; }
.slotgroup-head {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-bottom: 8px;
}
.slotgroup-name {
  font-size: 11.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-soft);
}
.slotgroup-count { font-size: 11.5px; font-weight: 600; color: var(--ink-soft); }

.slotgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }

/* One slot. Free / tight / full / past differ by label AND border style AND
   capacity bar — greyscale-safe by construction. */
.slot {
  position: relative;
  min-height: 64px;
  padding: 8px 4px 7px;
  border-radius: var(--r);
  border: 1.5px solid var(--line);
  background: var(--paper);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  transition: border-color .16s ease, background .16s ease, transform .16s ease;
}
.slot:hover:not([disabled]) { border-color: var(--brand); }
.slot:active:not([disabled]) { transform: scale(.96); }
.slot-time {
  font-size: var(--t-sm); font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
.slot-note {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 10.5px; font-weight: 600; color: var(--ink-soft);
  line-height: 1.2;
}
.slot-note .ico { width: 11px; height: 11px; }

/* capacity bar: ticks, filled = taken. Reads as a shape, not a hue. */
.slot-cap { display: flex; gap: 2px; margin-top: 1px; }
.slot-cap i { width: 6px; height: 3px; border-radius: 1px; background: var(--line-strong); }
.slot-cap i.on { background: var(--ink-faint); }

.slot--tight { border-color: color-mix(in srgb, var(--amber) 48%, transparent); background: var(--amber-wash); }
.slot--tight .slot-note { color: var(--ink); }
.slot--tight .slot-note .ico { color: var(--amber); }
.slot--tight .slot-cap i.on { background: var(--amber); }

.slot--full {
  border-style: dashed;
  border-color: var(--line-strong);
  background: var(--paper-sink);
  cursor: not-allowed;
}
.slot--full .slot-time { color: var(--ink-faint); text-decoration: line-through; }
.slot--full .slot-note { color: var(--alert); }

.slot--past, .slot--tooSoon {
  background: var(--paper-sink); border-color: var(--line);
  cursor: not-allowed;
}
.slot--past .slot-time, .slot--tooSoon .slot-time { color: var(--ink-faint); }

.slot[aria-pressed="true"] {
  background: var(--brand); border-color: var(--brand-deep); color: var(--paper);
  box-shadow: 0 6px 16px rgba(15, 122, 67, .26);
}
.slot[aria-pressed="true"] .slot-time,
.slot[aria-pressed="true"] .slot-note { color: var(--paper); }
.slot[aria-pressed="true"] .slot-cap i { background: color-mix(in srgb, var(--paper) 45%, transparent); }
.slot[aria-pressed="true"] .slot-cap i.on { background: var(--paper); }

.slot-check {
  position: absolute; top: 4px; right: 4px;
  width: 14px; height: 14px; color: var(--paper);
  display: none;
}
.slot[aria-pressed="true"] .slot-check { display: block; }

/* The commitment recap that follows the picker. */
.slotrecap {
  display: flex; align-items: flex-start; gap: 10px;
  margin: 0 16px 14px;
  padding: 12px 14px;
  border-radius: var(--r);
  background: var(--brand-wash);
  border: 1px solid color-mix(in srgb, var(--brand) 24%, transparent);
}
.slotrecap .ico { color: var(--brand-deep); margin-top: 1px; }
.slotrecap-t { font-size: var(--t-sm); font-weight: 700; color: var(--brand-deep); font-variant-numeric: tabular-nums; }
.slotrecap-s { font-size: var(--t-xs); color: var(--ink-soft); margin-top: 1px; }

/* Explanatory notes. */
.note {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 11px 13px;
  border-radius: var(--r);
  background: var(--paper-sink);
  font-size: var(--t-xs); line-height: 1.5; color: var(--ink-soft);
}
.note .ico { flex: 0 0 auto; margin-top: 1px; color: var(--ink-faint); }
.note b { color: var(--ink); }
.note--amber { background: var(--amber-wash); }
.note--amber .ico { color: var(--amber); }
.note--slate { background: var(--slate-wash); }
.note--slate .ico { color: var(--slate); }
.note--brand { background: var(--brand-wash); }
.note--brand .ico { color: var(--brand-deep); }

/* ---- past order row ----
   The whole row links to the order; the repeat button sits outside that link
   so it stays a button, not a nested control inside an anchor. */
.row--past { display: block; padding: 0; }
.row--past .row-link {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 14px 8px;
  text-decoration: none; color: inherit;
}
.row--past .row-repeat { margin: 0 14px 12px 51px; }

/* ---- notification preferences ---- */
.notif-intro {
  margin: 0; padding: 0 14px 10px;
  font-size: var(--t-xs); color: var(--ink-soft); line-height: 1.5;
}
/* Aligns the lead-time picker with the switch rows above it. */
.kv > .ico:empty { width: 16px; height: 16px; }
.leadsel { margin-top: 5px; width: 100%; max-width: 240px; }

/* ---- loyalty card ----
   A stamp is filled or hollow, and a filled one carries a tick. The state
   never rests on hue alone, so the card counts correctly for a colourblind
   reader and in a black-and-white screenshot. */
.loycard-body { padding: 0 14px 14px; }
.loycard-rule {
  margin: 0; font-size: var(--t-sm); font-weight: 600; line-height: 1.45;
}
.loycard-state {
  margin: 10px 0 0; font-size: var(--t-xs); color: var(--ink-soft); line-height: 1.5;
}
.loycard-fine {
  margin: 4px 0 0; font-size: 11px; color: var(--ink-faint);
}
.loycard.is-ready { border-color: var(--brand); }
.loycard.is-ready .loycard-state { color: var(--brand-deep); font-weight: 600; }

.stamps { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 12px; }
.stamp {
  width: 26px; height: 26px; border-radius: 50%;
  border: 1.5px dashed var(--line-strong);
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
}
.stamp.is-on {
  border: 1.5px solid var(--brand-deep);
  background: var(--brand-deep);
  color: var(--paper);
}
.stamp .ico { width: 14px; height: 14px; }

/* ================================================== 9. the order flow ==== */
.flowfoot {
  position: fixed; bottom: 0; left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 440px; z-index: 500;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
  background: color-mix(in srgb, var(--paper) 95%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
}
.flowfoot-row { display: flex; align-items: center; gap: 12px; }
.flowfoot-sum { flex: 1 1 auto; min-width: 0; }
/* The CTA must never wrap: it is the only way forward on the screen. */
.flowfoot .btn { flex: 0 0 auto; white-space: nowrap; font-size: var(--t-sm); }
.flowfoot-lab { font-size: 10.5px; color: var(--ink-soft); font-weight: 600; }
.flowfoot-val {
  font-size: var(--t-md); font-weight: 700;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}

/* Sticky "view basket" bar on the shop screen. */
.basketbar {
  position: fixed; bottom: calc(64px + env(safe-area-inset-bottom, 0px));
  left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 440px; z-index: 500;
  padding: 10px 16px;
  pointer-events: none;
}
.basketbar .btn { width: 100%; box-shadow: var(--shadow-lift); pointer-events: auto; }
.basketbar-count {
  display: inline-grid; place-items: center;
  min-width: 22px; height: 22px; padding: 0 6px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--paper) 26%, transparent);
  font-size: var(--t-xs); font-variant-numeric: tabular-nums;
}

/* Cart lines. */
.cartline {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 12px 14px;
  border-top: 1px solid var(--line);
}
.cartline:first-of-type { border-top: 0; }
.cartline-main { flex: 1 1 auto; min-width: 0; }
.cartline-name { font-size: 14px; font-weight: 700; }
.cartline-opts { font-size: var(--t-xs); color: var(--ink-soft); margin-top: 2px; line-height: 1.45; }
.cartline-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 8px; }
.cartline-price {
  font-size: var(--t-sm); font-weight: 700;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

.qty {
  display: inline-flex; align-items: center;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--paper);
  overflow: hidden;
}
.qty button { width: 40px; height: 40px; display: grid; place-items: center; color: var(--ink-soft); }
.qty button:hover:not([disabled]) { background: var(--paper-sink); color: var(--ink); }
.qty button[disabled] { color: var(--line-strong); cursor: not-allowed; }
.qty output {
  min-width: 26px; text-align: center;
  font-size: var(--t-sm); font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Totals block. */
.totals { padding: 12px 14px; border-top: 1px solid var(--line); background: var(--paper-warm); }
.totals-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  font-size: var(--t-sm); color: var(--ink-soft);
}
.totals-row + .totals-row { margin-top: 6px; }
.totals-row.is-total { font-size: var(--t-base); color: var(--ink); font-weight: 700; }
.totals-row .amount { font-variant-numeric: tabular-nums; font-weight: 700; }

/* Form fields. */
.field { margin-bottom: 14px; }
.field-label { display: block; font-size: var(--t-sm); font-weight: 600; margin-bottom: 6px; }
.field-hint { font-size: var(--t-xs); color: var(--ink-soft); margin-top: 6px; line-height: 1.45; }
.field-err {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--t-xs); font-weight: 600; color: var(--alert); margin-top: 6px;
}
.field-err .ico { width: 14px; height: 14px; }
input[aria-invalid="true"], select[aria-invalid="true"] { border-color: var(--alert); }
.phonerow { display: flex; gap: 8px; }
.phonerow select { width: 128px; flex: 0 0 auto; }

/* Option groups in the product sheet. */
.optgroup { margin-bottom: 18px; }
.optgroup-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.optgroup-name { font-size: var(--t-sm); font-weight: 700; }
.optgroup-rule { font-size: 11.5px; color: var(--ink-soft); font-weight: 600; }
.opt {
  display: flex; align-items: center; gap: 11px;
  width: 100%; text-align: left;
  min-height: 48px; padding: 8px 12px;
  border: 1.5px solid var(--line);
  border-radius: var(--r);
  background: var(--paper);
  margin-bottom: 8px;
  font-size: var(--t-sm);
  transition: border-color .16s ease, background .16s ease;
}
.opt:hover { border-color: var(--line-strong); }
.opt-mark {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  border-radius: var(--r-pill);
  border: 1.5px solid var(--line-strong);
  display: grid; place-items: center;
  color: transparent;
}
.opt-mark .ico { width: 14px; height: 14px; }
.opt-mark.square { border-radius: 6px; }
.opt-name { flex: 1 1 auto; }
.opt-delta { font-size: var(--t-xs); font-weight: 700; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.opt[aria-pressed="true"] { border-color: var(--brand); background: var(--brand-wash); }
.opt[aria-pressed="true"] .opt-mark { background: var(--brand); border-color: var(--brand); color: var(--paper); }
.opt[aria-pressed="true"] .opt-name { font-weight: 600; }

/* Confirmation. */
.done { padding: 26px 16px 8px; text-align: center; }
.done-mark {
  width: 64px; height: 64px; margin: 0 auto 14px;
  border-radius: var(--r-pill);
  background: var(--brand-wash);
  border: 2px solid var(--brand);
  color: var(--brand-deep);
  display: grid; place-items: center;
  animation: popIn .38s cubic-bezier(.32, .72, .35, 1) both;
}
.done-mark .ico { width: 32px; height: 32px; }
@keyframes popIn { 0% { transform: scale(.6); opacity: 0; } 60% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); } }
.done-title {
  font-family: var(--font-display);
  font-size: var(--t-xl); font-weight: 700; letter-spacing: -.03em; line-height: 1.15;
}
.done-sub { font-size: var(--t-sm); color: var(--ink-soft); margin-top: 8px; }

/* Pickup code — the handover moment. A ticket you show, not a receipt. */
.codebox {
  position: relative;
  margin: 18px 16px;
  padding: 18px 16px 16px;
  border-radius: var(--r-lg);
  background: var(--ink);
  color: var(--paper);
  text-align: center;
  overflow: hidden;
}
.codebox::before, .codebox::after {
  content: "";
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; border-radius: var(--r-pill);
  background: var(--paper-warm);
}
.codebox::before { left: -10px; }
.codebox::after { right: -10px; }
.codebox-lab {
  font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: color-mix(in srgb, var(--paper) 82%, transparent);
}
.codebox-code {
  font-family: var(--font-display);
  font-size: var(--t-2xl);
  font-weight: 700;
  letter-spacing: .18em;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  margin: 6px 0 2px;
  padding-left: .18em; /* optical centring against the letter-spacing */
}
.codebox-hint { font-size: var(--t-xs); color: color-mix(in srgb, var(--paper) 76%, transparent); }
.codebox-rule {
  height: 1px; margin: 14px -16px 12px;
  background: repeating-linear-gradient(
    to right,
    color-mix(in srgb, var(--paper) 34%, transparent) 0 6px,
    transparent 6px 12px
  );
}
.codebox-foot {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 10px; text-align: left;
  font-size: 10.5px;
  color: color-mix(in srgb, var(--paper) 88%, transparent);
}
.codebox-foot b {
  display: block; color: var(--paper); font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
}
.codebox-foot > div:last-child { text-align: right; }
.codebox-brand { display: flex; justify-content: center; margin-top: 14px; opacity: .72; }

/* =================================================== 10. order status ==== */
.track { padding: 12px 14px; }
.track-step { position: relative; display: flex; gap: 12px; padding-bottom: 14px; }
.track-step:last-child { padding-bottom: 0; }
.track-step::before {
  content: "";
  position: absolute; left: 15px; top: 34px; bottom: 0;
  width: 2px; background: var(--line);
}
.track-step:last-child::before { display: none; }
.track-step.is-done::before { background: var(--brand); }

.track-mark {
  flex: 0 0 32px; width: 32px; height: 32px;
  border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--paper);
  border: 2px solid var(--line);
  color: var(--ink-faint);
  position: relative; z-index: 1;
}
.track-mark .ico { width: 17px; height: 17px; }
.track-step.is-done .track-mark { background: var(--brand); border-color: var(--brand); color: var(--paper); }
.track-step.is-now .track-mark {
  background: var(--paper); border-color: var(--ink); color: var(--ink);
  box-shadow: 0 0 0 4px var(--brand-wash);
}
.track-step.is-off .track-mark { border-style: dashed; }
.track-step.is-bad .track-mark { background: var(--alert); border-color: var(--alert); color: var(--paper); }
.track-body { flex: 1 1 auto; min-width: 0; padding-top: 5px; }
.track-name { font-size: var(--t-sm); font-weight: 700; }
.track-step.is-off .track-name { color: var(--ink-soft); font-weight: 600; }
.track-when { font-size: var(--t-xs); color: var(--ink-soft); font-variant-numeric: tabular-nums; }

/* Big status banner at the top of the status screen. */
.stbanner {
  margin: 0 16px 12px;
  padding: 16px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--paper);
  box-shadow: var(--shadow);
}
.stbanner-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.stbanner-say {
  font-family: var(--font-display);
  font-size: var(--t-md); font-weight: 700; letter-spacing: -.02em; line-height: 1.3;
  margin-top: 10px;
}
.stbanner-when { font-size: var(--t-sm); color: var(--ink-soft); margin-top: 4px; font-variant-numeric: tabular-nums; }

.kv { display: flex; align-items: flex-start; gap: 11px; padding: 12px 14px; border-top: 1px solid var(--line); }
.kv:first-of-type { border-top: 0; }
.kv > .ico { color: var(--ink-faint); margin-top: 2px; }
.kv-main { flex: 1 1 auto; min-width: 0; }
.kv-lab { font-size: 11px; font-weight: 600; color: var(--ink-soft); }
.kv-val { font-size: var(--t-sm); font-weight: 600; }
.kv-val small { display: block; font-weight: 400; color: var(--ink-soft); font-size: var(--t-xs); }
.kv-end { flex: 0 0 auto; }

/* ======================================================= 11. account ==== */
.acct-head { display: flex; align-items: center; gap: 13px; padding: 4px 16px 16px; }
.avatar {
  flex: 0 0 54px; width: 54px; height: 54px;
  border-radius: var(--r-pill);
  background: var(--brand-wash);
  border: 1px solid color-mix(in srgb, var(--brand) 24%, transparent);
  color: var(--brand-deep);
  display: grid; place-items: center;
  font-family: var(--font-display);
  font-size: var(--t-lg); font-weight: 700;
}
.acct-name { font-family: var(--font-display); font-size: var(--t-lg); font-weight: 700; letter-spacing: -.02em; }
.acct-sub { font-size: var(--t-xs); color: var(--ink-soft); }

.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 0 16px 4px; }
.stat {
  padding: 12px 8px;
  border-radius: var(--r);
  background: var(--paper);
  border: 1px solid var(--line);
  text-align: center;
}
.stat-num {
  font-family: var(--font-display);
  font-size: var(--t-lg); font-weight: 700;
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.stat-lab { font-size: 10.5px; color: var(--ink-soft); margin-top: 2px; line-height: 1.3; }

.switch {
  position: relative;
  flex: 0 0 auto;
  width: 46px; height: 28px;
  border-radius: var(--r-pill);
  background: var(--line-strong);
  position: relative;
  transition: background .18s ease;
}
.switch::after {
  content: "";
  position: absolute; top: 3px; left: 3px;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--paper);
  box-shadow: 0 1px 3px rgba(16, 28, 22, .25);
  transition: transform .18s cubic-bezier(.32, .72, .35, 1);
}
.switch::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%); width: 52px; height: 44px;
}
.switch[aria-checked="true"] { background: var(--brand); }
.switch[aria-checked="true"]::after { transform: translateX(18px); }

/* ========================= 12. sheets, dialogs, toasts, empties ========== */
.scrim {
  position: fixed; inset: 0; z-index: 800;
  background: rgba(16, 28, 22, .48);
  opacity: 0;
  transition: opacity .22s ease;
}
.scrim.is-open { opacity: 1; }

.sheet {
  position: fixed; left: 50%; bottom: 0;
  width: 100%; max-width: 440px;
  z-index: 850;
  transform: translate(-50%, 105%);
  background: var(--paper);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  max-height: 88dvh;
  display: flex; flex-direction: column;
  transition: transform .3s cubic-bezier(.32, .72, .35, 1);
  box-shadow: var(--shadow-lift);
}
.sheet.is-open { transform: translate(-50%, 0); }
.sheet-grab { width: 40px; height: 4px; border-radius: 2px; background: var(--line-strong); margin: 8px auto 4px; flex: 0 0 auto; }
.sheet-head { display: flex; align-items: flex-start; gap: 10px; padding: 6px 16px 12px; flex: 0 0 auto; }
.sheet-title { flex: 1 1 auto; font-family: var(--font-display); font-size: var(--t-md); font-weight: 700; letter-spacing: -.02em; }
.sheet-sub { font-size: var(--t-xs); color: var(--ink-soft); margin-top: 3px; line-height: 1.45; }
.sheet-body { flex: 1 1 auto; overflow-y: auto; padding: 0 16px 8px; overscroll-behavior: contain; }
.sheet-foot {
  flex: 0 0 auto;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line);
  background: var(--paper);
}
.sheet-foot .btn + .btn { margin-top: 8px; }

.toast {
  position: fixed; left: 50%; top: 12px;
  transform: translateX(-50%);
  z-index: 900;
  display: flex; align-items: center; gap: 9px;
  max-width: min(400px, calc(100vw - 24px));
  padding: 11px 15px;
  border-radius: var(--r-pill);
  background: var(--ink); color: var(--paper);
  font-size: var(--t-sm); font-weight: 600;
  box-shadow: var(--shadow-lift);
  animation: toastIn .24s cubic-bezier(.32, .72, .35, 1) both;
}
.toast .ico { color: var(--brand-bright); }
.toast.is-out { animation: toastOut .24s ease both; }
@keyframes toastIn { from { opacity: 0; transform: translate(-50%, -14px) scale(.96); } to { opacity: 1; transform: translate(-50%, 0) scale(1); } }
@keyframes toastOut { to { opacity: 0; transform: translate(-50%, -10px); } }

.empty {
  margin: 8px 16px;
  padding: 28px 20px;
  text-align: center;
  border-radius: var(--r-lg);
  border: 1px dashed var(--line-strong);
  background: var(--paper);
}
.empty > .ico { width: 30px; height: 30px; margin: 0 auto 10px; color: var(--ink-faint); }
.empty-t { font-size: var(--t-sm); font-weight: 700; }
.empty-s { font-size: var(--t-xs); color: var(--ink-soft); margin-top: 4px; }
.empty .btn { margin-top: 14px; }

.demobar {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  padding: 18px 20px 8px;
  font-size: 11px; color: var(--ink-soft); text-align: center; line-height: 1.4;
}
.demobar .ico { width: 13px; height: 13px; }

/* ======================================================= 13. desktop ==== */
/* Not a phone in a bezel: at desktop widths the tab bar becomes a left rail
   and the content column widens to a two-up card grid. */
@media (min-width: 1024px) {
  .app {
    max-width: 1080px;
    display: grid;
    grid-template-columns: 224px minmax(0, 1fr);
    align-items: start;
    /* .app keeps min-height:100dvh, and a grid with auto rows would otherwise
       stretch those rows to fill it, prising the flow's back bar off its
       panel. */
    align-content: start;
    background: transparent;
    gap: 20px;
    padding: 20px;
  }
  .app > .screens {
    grid-column: 2; grid-row: 1;
    background: var(--paper-warm);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    overflow: hidden;
    min-height: calc(100dvh - 40px);
  }
  .screen { padding-bottom: 40px; }

  /* The order flow is a single column with no rail. Its back bar is a grid
     item too, so it needs an explicit order — otherwise auto-placement drops
     it into row 2, underneath the content. */
  .app--flow {
    max-width: 720px;
    grid-template-columns: minmax(0, 1fr);
    row-gap: 0;               /* back bar and panel read as one card */
  }
  /* The base rule pins .screens to grid-row 1; the flow needs it in row 2 so
     the back bar can sit above it. */
  .app--flow > .backbar {
    grid-column: 1; grid-row: 1;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    border: 1px solid var(--line); border-bottom: 0;
    background: var(--paper);
  }
  .app--flow > .screens {
    grid-column: 1; grid-row: 2;
    min-height: 0;            /* let the funnel be as tall as its content */
    border-radius: 0 0 var(--r-lg) var(--r-lg);
    border-top: 0;
  }
  .app--flow .screen { padding-bottom: 24px; }

  /* Tab bar → sticky sidebar. */
  .tabbar {
    position: sticky; top: 20px;
    grid-column: 1; grid-row: 1;
    left: auto; bottom: auto;
    transform: none;
    max-width: none; width: auto;
    display: flex; flex-direction: column; gap: 4px;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: 10px;
    box-shadow: var(--shadow);
  }
  /* The rail carries the brand at desktop, so the screen header must not
     repeat it. */
  .hd .wordmark { display: none; }

  .rail-brand {
    display: block;
    padding: 8px 12px 14px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--line);
    text-decoration: none;
  }
  .rail-brand:hover { text-decoration: none; }
  
  .rail-tag { display: block; font-size: 11.5px; color: var(--ink-soft); margin-top: 2px; }

  .tab {
    flex-direction: row; justify-content: flex-start;
    gap: 11px; height: 46px; padding: 0 12px;
    border-radius: var(--r); font-size: var(--t-sm);
  }
  .tab::before { display: none !important; }
  .tab[aria-current="page"] { background: var(--brand-wash); color: var(--brand-deep); }
  .tab-badge { position: static; margin-left: auto; border-color: var(--brand-wash); }

  /* Two-up shop cards. */
  .shoplist { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .shoplist .shopcard { margin-bottom: 0; }
  .slotgrid { grid-template-columns: repeat(6, 1fr); }
  .stats { grid-template-columns: repeat(3, 1fr); }

  /* Sticky footers align to the content column instead of the viewport. */
  .flowfoot, .basketbar {
    position: sticky;
    left: auto; bottom: 0;
    transform: none;
    max-width: none; width: auto;
  }
  .basketbar { bottom: 12px; }

  .sheet { max-width: 520px; border-radius: var(--r-lg); bottom: 6vh; max-height: 78dvh; }
}

/* Comfort bump for wider phones — same layout, a touch more air. */
@media (min-width: 400px) and (max-width: 1023px) {
  .gut, .sect, .chips, .rail, .slotpick, .shoplist { padding-inline: 18px; }
  .listcard, .stbanner, .slotrecap, .codebox, .empty { margin-inline: 18px; }
  .stats { padding-inline: 18px; }
  .acct-head { padding-inline: 18px; }
}

/* Allergen block on the product sheet. The shop owns this information; anyone
   with a severe allergy is told to confirm at the source. High contrast, and
   the warning reads as text, never as colour alone. */
.allergen-note {
  margin: 0 0 16px;
  padding: 10px 12px;
  border-left: 3px solid var(--ink-soft, #4C5A52);
  background: var(--paper-sink, #F1F5F1);
  border-radius: 6px;
  font-size: .86rem;
  line-height: 1.45;
  color: var(--ink, #13211B);
}

/* ========================================================== 14. payment ==== */
.paymethods {
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--s-3);
  margin: 0;
  background: var(--paper);
}
.paymethods legend {
  padding: 0 var(--s-2);
  font-weight: 600;
  font-family: var(--font-display, inherit);
}
.payopt {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-2);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background .12s;
}
.payopt:hover { background: var(--paper-warm); }
.payopt.is-chosen { background: var(--brand-wash); }
.payopt input { position: absolute; opacity: 0; width: 0; height: 0; }
.payopt-radio {
  width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid var(--line-strong);
  flex: none; margin-top: 2px;
  transition: border-color .12s, box-shadow .12s;
}
.payopt.is-chosen .payopt-radio {
  border-color: var(--brand);
  box-shadow: inset 0 0 0 5px var(--brand);
}
.payopt-body { min-width: 0; }
.payopt-label {
  display: flex; align-items: center; gap: var(--s-2);
  font-weight: 600; font-size: var(--t-sm);
}
.payopt-label svg { width: 18px; height: 18px; color: var(--brand); }
.payopt-desc {
  display: block; margin-top: var(--s-1);
  font-size: var(--t-xs); color: var(--ink-soft);
}

/* ========================================================== 15. policy ===== */
.policy-card {
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--s-4);
  background: var(--paper);
}
.policy-head {
  display: flex; align-items: center; gap: var(--s-2);
  margin-bottom: var(--s-3);
  font-size: var(--t-sm);
}
.policy-head svg { width: 18px; height: 18px; color: var(--brand); }
.policy-list {
  list-style: disc; padding-left: var(--s-5);
  font-size: var(--t-xs); color: var(--ink-soft); line-height: 1.7;
}
.policy-custom {
  margin-top: var(--s-3); padding-top: var(--s-3);
  border-top: 1px solid var(--line);
  font-size: var(--t-xs); color: var(--ink-soft);
  white-space: pre-line;
}
.policy-check {
  display: flex; align-items: center; gap: var(--s-2);
  margin-top: var(--s-3); padding-top: var(--s-3);
  border-top: 1px solid var(--line);
  cursor: pointer; font-size: var(--t-sm); font-weight: 600;
}
.policy-check input { width: 18px; height: 18px; accent-color: var(--brand); }
.policy-check-terms {
  margin-top: var(--s-2); padding-top: var(--s-2);
  font-weight: 500; color: var(--ink-soft);
}
.policy-check-terms a { color: var(--brand); text-decoration: underline; font-weight: 600; }


.row-price { font-weight: 700; font-size: 13.5px; color: var(--ink); margin-top: 2px; }
