*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* The app shell clips overflow rather than scrolling (see #app), so anything
   too wide is silently cut off instead of announcing itself. A long unbroken
   token — a product name, an address, a pasted URL — would simply disappear.
   Breaking as a last resort keeps content visible. */
body { overflow-wrap: break-word; }
html { height: 100%; }
body {
  min-height: 100%;
  background: radial-gradient(120% 90% at 50% 0%, var(--page-glow), var(--page-frame));
  font-family: 'Figtree', sans-serif;
}
.sr-only {
  position: fixed; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap;
  border: 0;
}
.skip-link {
  position: fixed; z-index: calc(var(--z-toast) + 1); top: var(--s-2); left: var(--s-2);
  min-height: var(--tap); padding: 0 var(--s-4);
  display: inline-flex; align-items: center;
  border-radius: var(--r-md); background: var(--dark); color: var(--card);
  font: 700 var(--t-base)/1 var(--font-body); text-decoration: none;
  transform: translateY(calc(-100% - var(--s-4)));
  transition: transform var(--dur-fast) ease;
}
.skip-link:focus { transform: none; }
/* ══ DESIGN TOKENS ══════════════════════════════════════════════════════════
   Single source of truth for the customer site. Anything hardcoded in app.js
   is legacy and moves here as its screen is redesigned.

   Rule of thumb: colour, radius, spacing, type, shadow and motion all come
   from this block. If a component needs a value that isn't here, the question
   is whether the scale is wrong — not whether to add one more literal. */
:root {
  /* ── Brand surfaces ──────────────────────────────────────────────────── */
  --accent: #C2402C;          /* tomato — primary actions, active states     */
  --bg: #F6EEE0;              /* cream page background                       */
  --dark: #2b1d13;            /* espresso — text, dark panels                */
  --card: #FFFDF8;            /* off-white card surface                      */
  --tray: #EADFCB;            /* beige tray — segmented controls, chips      */

  --accent-hover: #a9351f;
  --accent-text: #982f20;     /* accessible text/icon use of the brand hue    */
  --accent-soft: #f4e3df;     /* tinted accent background (errors, closed)   */
  --accent-on-dark: #e8a598;  /* accent legible on the espresso panel        */
  --dark-hover: #402c1c;
  --band: #f1e7d6;            /* menu band — sits under off-white cards      */
  --gold: #C9A366;            /* decorative only — never text or UI state    */
  --wa: #25D366;              /* WhatsApp brand green                        */

  /* ── Supporting surfaces ────────────────────────────────────────────── */
  --page-glow: #f0e8db;
  --page-frame: #E4DCCE;
  --pure-white: #fff;
  --warm-white: #fffaf6;
  --choice-hover: #fdf6f0;
  --skeleton-base: #eee3d2;
  --skeleton-highlight: #f4ecdd;
  --address-muted: #7d6b5a;
  --loading-line: #d6c8b5;

  /* ── Text ────────────────────────────────────────────────────────────── */
  --muted: #6b5a49;           /* body copy, descriptions                     */
  --muted2: #705d4c;          /* secondary text                              */
  --muted3: #705d4c;          /* dimmest permitted text                      */
  --on-dark: #FFFDF8;
  --on-dark-muted: rgba(255,253,248,0.72);

  /* ── Status ──────────────────────────────────────────────────────────── */
  --ok: #2f682b;      --ok-soft: #e7f0e2;
  --zone-ok: #2f6b2b;
  --warn: #72510f;    --warn-soft: #fdf1d7;
  --disabled: #c9bba8;

  /* ── Hairlines ───────────────────────────────────────────────────────── */
  --line-soft: rgba(43,29,19,0.08);
  --line-mid: rgba(43,29,19,0.11);
  --line: rgba(43,29,19,0.13);
  --input-line: rgba(43,29,19,0.14);
  --line-strong: rgba(43,29,19,0.22);
  --input-line-focus: rgba(43,29,19,0.35);
  --line-on-dark: rgba(255,253,248,0.16);
  --accent-line-soft: rgba(194,64,44,0.25);
  --accent-line: rgba(194,64,44,0.3);
  --accent-line-strong: rgba(194,64,44,0.35);
  --bg-transparent: rgba(246,238,224,0);
  --white-glass: rgba(255,255,255,0.55);
  --overlay: rgba(43,29,19,0.45);
  --overlay-strong: rgba(43,29,19,0.48);

  /* ── Radius ──────────────────────────────────────────────────────────────
     Controlled corners, not capsules. --r-full is reserved for genuine
     badges and avatars; a button rendered as a pill is a bug (see
     test/style-system.test.js). */
  --r-xs: 4px;      /* badges, tags, status dots                             */
  --r-sm: 8px;      /* inputs, chips, tabs, slot cells                       */
  --r-md: 10px;     /* buttons, steppers, option rows                        */
  --r-lg: 14px;     /* cards, panels, the primary CTA                        */
  --r-xl: 18px;     /* sheets and modals (top corners only on mobile sheets) */
  --r-full: 999px;  /* count badges and avatars — nothing else               */

  /* ── Spacing (4px base) ──────────────────────────────────────────────── */
  --s-1: 4px;   --s-2: 8px;   --s-3: 12px;  --s-4: 16px;
  --s-5: 20px;  --s-6: 24px;  --s-8: 32px;  --s-10: 40px; --s-12: 48px;

  /* ── Type ────────────────────────────────────────────────────────────── */
  --font-body: 'Figtree', system-ui, sans-serif;
  --font-display: 'DM Serif Display', Georgia, serif;
  --font-script: 'Pacifico', cursive;

  --t-2xs: 11px;    /* uppercase micro-labels, badges                        */
  --t-xs: 12px;     /* helper and legal text                                 */
  --t-sm: 13px;     /* descriptions, secondary rows                          */
  --t-base: 14px;   /* body, buttons                                         */
  --t-md: 16px;     /* form inputs — 16px keeps iOS from zooming on focus    */
  --t-lg: 18px;     /* card and section titles                               */
  --t-xl: 22px;     /* screen titles                                         */
  --t-2xl: 28px;    /* hero                                                  */
  --t-3xl: 34px;    /* display                                               */

  /* ── Elevation ───────────────────────────────────────────────────────────
     Five shadows for the whole site. Depth comes from hairlines and colour
     blocks; reach for a border before reaching for a shadow. */
  --shadow-sm: 0 1px 2px rgba(43,29,19,0.06);
  --shadow-card: 0 6px 16px rgba(43,29,19,0.06);
  --shadow-bar: 0 -2px 12px rgba(43,29,19,0.07);
  --shadow-sheet: 0 -8px 40px rgba(43,29,19,0.18);
  --shadow-focus: 0 0 0 3px var(--accent-text);

  /* ── Motion ──────────────────────────────────────────────────────────── */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-fast: 150ms;
  --dur: 200ms;
  --dur-slow: 300ms;

  /* ── Layering ────────────────────────────────────────────────────────── */
  --z-bar: 20; --z-sheet: 100; --z-toast: 200;

  /* ── Layout ──────────────────────────────────────────────────────────── */
  --scrim: rgba(43,29,19,0.28);  /* top-of-hero wash, control legibility only */
  --tap: 44px;                /* minimum interactive target                  */
  /* Sticky chrome heights. --header-h is the ONE source for how far down the
     menu's category rail sticks. The value below is only the pre-JS baseline
     (68px min-height + 1px hairline); .site-header's real height depends on the
     notch, so publishMenuChrome() measures it and republishes this property on
     #app. CSS positions the rail with it and menuStickyOffset() reads the same
     number, so the bar and the scroll-spy threshold cannot drift apart the way
     they did when CSS hardcoded 46px against a taller header. */
  --header-h: calc(var(--safe-top) + 47px);
  --menu-rail-h: 60px;        /* category strip: 44px tap + breathing room    */
  --toast-lift: 0px;          /* raised per screen by showToast()            */
  --shell-max: 560px;         /* width of the app shell (see #app)           */
  --content-max: 100%;        /* readable column inside a wide shell         */

  /* top padding of every screen — respects phone notches, comfortable everywhere */
  --safe-top: max(22px, env(safe-area-inset-top));
  --safe-bottom: max(30px, calc(env(safe-area-inset-bottom) + 12px));
}
@media (hover: none), (pointer: coarse) {
  * { scrollbar-width: none; }
  *::-webkit-scrollbar { display: none; }
}

/* Snappier, flash-free taps on mobile; no 300ms delay, no grey highlight */
button, a, [role="button"] { -webkit-tap-highlight-color: transparent; touch-action: manipulation; }

/* Visible focus ring for keyboard users (not shown on mouse click) */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:not([tabindex="-1"]):focus-visible {
  outline: 3px solid var(--accent-text); outline-offset: 2px; border-radius: var(--r-sm);
}
[data-step-focus]:focus, [data-substep-focus]:focus, #slot-title:focus { outline: none; }

/* Respect users who prefer less motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration:.001ms !important; scroll-behavior: auto !important; }
}

/* ── Responsive app shell ──
   Full-bleed on phones; a comfortable centered column on tablets; a wider,
   roomier panel on laptops/desktops. No fixed device sizes, no h-scroll.

   #app stays `position: fixed` deliberately. It is what pins each screen's
   header and bottom CTA bar without `position: sticky`, what makes setState's
   scroll restoration work, and what stops iOS rubber-banding the whole page.
   Desktop layouts are built *inside* .scr-scroll instead — sticky works fine
   there, because .scr-scroll is itself the scroll container. */
#app {
  position: fixed; inset: 0;
  width: 100%; max-width: var(--shell-max);
  margin: 0 auto;
  overflow: hidden;
  background: var(--bg);
}
@media (min-width: 561px) {
  #app { outline: 1px solid var(--line-soft); }
}
/* Tablet & up: give the menu two columns and the column more room */
@media (min-width: 760px) {
  :root { --shell-max: 720px; }
}

/* ── Per-screen desktop width ──
   render() stamps #app[data-screen] every paint, so a screen opts into a wider
   shell only once it has been designed for the space. Screens that have not
   been redesigned yet stay a centred column at every width — which is what
   lets the redesign ship one screen at a time. */
@media (min-width: 1024px) {
  :root { --content-max: 720px; }
}
.ph-art {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center; flex-direction: column;
  gap: var(--s-2); color: var(--muted);
}
.ph-art-mark { width: min(46%, 126px); height: auto; }
.ph-art-label {
  font-size: var(--t-2xs); font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase;
}
.line-ph {
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; background: var(--tray);
}
.line-ph .ph-art { gap: 1px; }
.line-ph .ph-art-mark { width: 52%; }
.line-ph .ph-art-label { font-size: var(--t-2xs); letter-spacing: .06em; }

/* ── Store status ── */
.status {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--t-xs); font-weight: 800;
  padding: 5px 11px; border-radius: var(--r-xs);
  white-space: nowrap;
}
.status i { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.status--open   { background: var(--ok-soft); color: var(--ok); }
.status--soon   { background: var(--warn-soft); color: var(--warn); }
.status--closed { background: var(--accent-soft); color: var(--accent-text); }

/* ── Checkout: opening hours stay visible beside the pickup/delivery
   choice, and pickup customers see exactly where to collect from. ── */
.hoursline { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin: -10px 0 16px; }
.hoursline-txt { font-size: var(--t-xs); color: var(--muted2); font-weight: 600; }
.pickup-panel {
  background: var(--card); border: 1px solid var(--line-soft);
  border-radius: var(--r-lg); padding: 12px 13px; margin-bottom: 14px;
}
.pickup-panel-t {
  display: flex; align-items: center; gap: 6px;
  font-size: var(--t-2xs); font-weight: 800; color: var(--muted2);
  text-transform: uppercase; letter-spacing: .07em; margin-bottom: 6px;
}
.pickup-panel-addr { font-weight: 700; color: var(--dark); font-size: var(--t-base); line-height: 1.4; }
.pickup-panel-note { font-size: var(--t-xs); color: var(--muted2); line-height: 1.5; margin-top: 6px; }

/* ── Product card media + shared pieces ──
   There is ONE card system: `.product-card.pcard`, laid out further down.
   This block holds only what that layout does not itself declare — the
   photo/placeholder rendering and the detail hero.

   A previous version kept a second, "reference-scaled" `.pcard` layout here
   driven by container queries. It was unreachable: `container-type` lived on
   `.pizza-list`, but the menu wraps cards in `.product-grid`, so the queries
   never matched — and where they did match they lost on specificity to
   `.product-card`. It has been removed rather than left to mislead. */
.pizza-list { display: flex; flex-direction: column; gap: var(--s-3); }
.pcard-img { overflow: hidden; background: var(--tray); }
.pcard-photo, .pcard-ph { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Per-product crop controls: photos with padded compositions can zoom in
   (set via --img-scale / --img-position from product data; defaults safe). */
.pcard-photo {
  object-position: var(--img-position, center);
  transform: scale(var(--img-scale, 1));
  transform-origin: center;
}
.pcard-ph {
  display: flex; align-items: center; justify-content: center;
  background: var(--tray);
}
.pcard-ph .ph-art-mark { width: min(54%, 118px); }
.pcard-ph .ph-art-label { font-size: var(--t-2xs); }
.pcard-choose svg { width: 1em; height: 1em; }

/* Product detail hero. Source photos are square (1000x1000), so a wider frame
   with object-fit:cover crops only top and bottom — the pizza stays whole and
   centred, never stretched. The height cap is the important part: the item
   screen overrides both the frame and the cap in `.item-hero .detail-img`. */
.detail-img {
  display: block; width: 100%; margin-inline: auto;
  aspect-ratio: 16 / 10; max-height: min(36vh, 320px);
  object-fit: cover; object-position: var(--img-position, center);
  transform: scale(var(--img-scale, 1));
  border-radius: var(--r-xl); background: var(--tray);
}
.detail-ph {
  display: flex; align-items: center; justify-content: center;
  background: var(--tray); transform: none;
}

/* ── Half & Half visual picker + pair summary ── */
.half-picker-header {
  position: relative; z-index: 2; flex: 0 0 auto;
  padding: var(--safe-top) 16px 12px;
  background: var(--bg); border-bottom: 1px solid var(--line-soft);
  box-shadow: var(--shadow-sm);
}
.half-picker-title-row { display: flex; align-items: flex-start; gap: 10px; }
.half-picker-title-row > div { flex: 1; min-width: 0; }
.half-picker-title { font-family: 'DM Serif Display', serif; font-size: var(--t-xl); line-height: 1.08; color: var(--dark); }
.half-picker-subtitle { margin-top: 3px; color: var(--muted2); font-size: var(--t-xs); line-height: 1.35; }
.half-first-summary {
  display: flex; align-items: center; gap: 11px; margin-top: 12px; padding: 9px 11px;
  background: var(--card); border: 1px solid var(--line-soft); border-radius: var(--r-lg);
}
.half-first-copy { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 2px; }
.half-first-copy span {
  color: var(--accent-text); font-size: var(--t-2xs); font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
}
.half-first-copy strong {
  overflow: hidden; color: var(--dark); font-family: 'DM Serif Display', serif;
  font-size: var(--t-lg); font-weight: 400; line-height: 1.1; text-overflow: ellipsis; white-space: nowrap;
}
.half-first-check {
  display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  background: var(--ok-soft); color: var(--ok); font-size: var(--t-base); font-weight: 900;
}
.half-picker-rule {
  margin: 14px 4px 0; color: var(--muted3); font-size: var(--t-2xs); line-height: 1.45; text-align: center;
}
.half-pair-card {
  display: flex; flex-direction: column; gap: 9px; margin: 14px 0 4px; padding: 11px;
  background: var(--card); border: 1px solid var(--line-soft); border-radius: var(--r-xl);
  box-shadow: var(--shadow-sm);
}
.half-pair-side { display: flex; align-items: center; gap: 10px; min-width: 0; }
.half-pair-side > div:last-child { display: flex; min-width: 0; flex-direction: column; gap: 2px; }
.half-pair-side span {
  color: var(--accent-text); font-size: var(--t-2xs); font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
}
.half-pair-side strong {
  overflow: hidden; color: var(--dark); font-family: 'DM Serif Display', serif;
  font-size: var(--t-md); font-weight: 400; text-overflow: ellipsis; white-space: nowrap;
}
.half-pair-divider { height: 1px; margin-left: 68px; background: var(--line-soft); }
.half-change {
  min-height: var(--tap); border: 1px solid var(--accent-line); border-radius: var(--r-md);
  background: var(--pure-white); color: var(--accent-text); cursor: pointer;
  font: 800 var(--t-xs) 'Figtree', sans-serif;
}
.half-empty-side {
  display: flex; align-items: center; gap: 10px; min-height: 58px; width: 100%; padding: 8px 10px;
  border: 1.5px dashed var(--accent-line-strong); border-radius: var(--r-lg); background: var(--warm-white);
  color: var(--accent-text); cursor: pointer; text-align: left;
}
.half-empty-side > span {
  display: grid; flex: 0 0 auto; place-items: center; width: 32px; height: 32px;
  border-radius: 50%; background: var(--accent-soft); font-size: var(--t-lg); font-weight: 500;
}
.half-empty-side > div { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 2px; }
.half-empty-side strong { color: var(--dark); font: 800 var(--t-sm) 'Figtree', sans-serif; }
.half-empty-side small { color: var(--muted2); font: 500 var(--t-2xs) 'Figtree', sans-serif; }
.half-price-note { margin: 7px 2px 0; color: var(--muted2); font-size: var(--t-xs); line-height: 1.4; }
.half-price-note strong { color: var(--dark); }
.half-price-note span { color: var(--muted3); }

@media (min-width: 600px) {
  .half-pair-card { display: grid; grid-template-columns: 1fr 1px 1fr; align-items: center; gap: 14px; }
  .half-pair-divider { width: 1px; height: 50px; margin: 0; }
  .half-change { grid-column: 1 / -1; }
  .half-empty-side { grid-column: 2 / -1; }
}

/* Skeleton loaders */
.skel {
  background: linear-gradient(90deg, var(--skeleton-base) 25%, var(--skeleton-highlight) 37%, var(--skeleton-base) 63%);
  background-size: 800px 100%;
  border-radius: var(--r-md);
}

.scr { height:100%; display:flex; flex-direction:column; background:var(--bg); }
.scr-scroll { flex:1; overflow-y:auto; overflow-x:hidden; -webkit-overflow-scrolling:touch; }

/* ── Floating action ──
   Absolutely positioned inside #app, NOT fixed. #app is already
   `position: fixed; inset: 0` with a centred max-width, so:
     · fixed would resolve against the viewport and ignore the shell;
     · absolute keeps the button inside #app's box, which means it moves with
       the rest of the app when Safari's toolbar collapses instead of being
       re-anchored on its own — no jump.
   Being out of flow is the point: the tab bar this replaced was a flex child
   and cost 93px of scroll area on every phone screen. --safe-bottom is already
   max(30px, env(safe-area-inset-bottom) + 12px). */
.floating-cta {
  position: absolute; z-index: var(--z-bar);
  bottom: var(--safe-bottom); left: 50%;
  display: flex; align-items: center; justify-content: center; gap: var(--s-3);
  width: max-content; max-width: calc(100% - var(--s-8));
  min-height: 50px; padding: 0 var(--s-6);
  border: none;
  /* 18px on a 50px button: generously rounded, deliberately not a capsule. */
  border-radius: var(--r-xl);
  background: var(--accent); color: var(--card);
  box-shadow: var(--shadow-card);
  font-family: var(--font-body); font-size: var(--t-md); font-weight: 800;
  letter-spacing: .01em; white-space: nowrap; cursor: pointer;
  /* Hidden until the hero's own Order button scrolls away (startCtaWatch).
     visibility, not opacity alone, so it leaves the accessibility tree and
     cannot be tapped while invisible. */
  visibility: hidden; opacity: 0;
  transform: translateX(-50%) translateY(var(--s-2));
  pointer-events: none;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease), visibility var(--dur);
}
.floating-cta.is-shown {
  visibility: visible; opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
.floating-cta strong { font-weight: 800; font-variant-numeric: tabular-nums; }
.floating-cta--cart { background: var(--dark); }
.floating-cta-count {
  display: grid; place-items: center;
  min-width: 22px; height: 22px; padding: 0 6px;
  border-radius: var(--r-sm);
  background: var(--card); color: var(--dark);
  font-size: var(--t-xs); font-weight: 900;
}
/* Desktop keeps the header, which already carries Menu, Orders, Cart, Account. */
@media (min-width: 820px) { .floating-cta { display: none; } }

.cart-bar {
  padding:12px 16px var(--safe-bottom);
  background:linear-gradient(to top, var(--bg) 74%, var(--bg-transparent));
}
.cart-bar-btn {
  width:100%; border:none; cursor:pointer; background:var(--dark);
  border-radius:var(--r-xl); padding:14px 18px;
  display:flex; align-items:center; justify-content:space-between;
  font-family:'Figtree',sans-serif;
}
.back-btn {
  width:var(--tap); height:var(--tap); border:none; background:var(--pure-white);
  border-radius:var(--r-md); box-shadow:var(--shadow-sm);
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  flex-shrink:0;
}
.inp {
  width:100%; padding:13px 14px; border-radius:var(--r-md);
  border:1px solid var(--input-line); background:var(--card);
  font-family:'Figtree',sans-serif; font-size:var(--t-md); color:var(--dark);
  margin-bottom:10px; outline:none;
}
.inp::placeholder { color:var(--muted3); opacity:1; }
.inp:focus { border-color:var(--input-line-focus); }

select.inp {
  appearance:none; -webkit-appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' stroke='%236b5a49' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 14px center;
  padding-right:38px; cursor:pointer;
}

/* ── Bottom sheet (delivery-location mismatch prompt) ── */
.sheet-overlay {
  position:absolute; inset:0; z-index:300;
  background:var(--overlay);
  display:flex; align-items:flex-end;
}
.sheet {
  width:100%; background:var(--bg);
  border-radius:var(--r-xl) var(--r-xl) 0 0; padding:22px 18px var(--safe-bottom);
  max-height:80%; overflow-y:auto;
}

.spinner {
  width:44px; height:44px;
  border:3px solid var(--tray);
  border-top-color: var(--accent-text);
  border-radius:50%;
}

/* ── Delivery-location flow (screen 'dloc') ──
   Locality → Address → Pin → Details → Confirm. */
/* Three steps, read as a line of text. A tick for what is done, bold for where
   you are, a hairline connector between — no numbered circles, no pills. */
.dlsteps { display:flex; align-items:center; gap:var(--s-2); margin:var(--s-3) 0 2px; }
.dlstep {
  display:flex; align-items:center; gap:4px;
  min-height:28px; border:none; background:none; padding:0; cursor:default;
  font-family:var(--font-body);
}
.dlstep + .dlstep::before {
  content:''; flex:0 0 auto; width:var(--s-4); height:1px;
  margin-right:var(--s-2); background:var(--line-strong);
}
.dlstep-mark {
  display:inline-flex; align-items:center; justify-content:center;
  min-width:12px; font-size:var(--t-2xs); font-weight:800; color:var(--ok);
}
.dlstep span:last-child { font-size:var(--t-2xs); font-weight:700; color:var(--muted3); white-space:nowrap; }
.dlstep--done { cursor:pointer; }
.dlstep--done span:last-child { color:var(--muted); }
.dlstep--on span:last-child { color:var(--dark); font-weight:800; }

.dl-note { font-size:var(--t-xs); color:var(--muted2); line-height:1.5; margin-top:8px; }
.dl-link {
  border:none; background:none; padding:0; cursor:pointer;
  font-family:'Figtree',sans-serif; font-size:inherit; font-weight:700;
  color: var(--accent-text); text-decoration:underline; text-underline-offset:2px;
}

/* Locality cards */
.loccard {
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  width:100%; text-align:left; cursor:pointer;
  background:var(--card); border:1.5px solid var(--line-soft);
  border-radius:var(--r-lg); padding:13px 15px; font-family:'Figtree',sans-serif;
  transition:border-color .15s, background .15s;
}
.loccard--sel { border-color: var(--accent-text); background:var(--choice-hover); }
.loccard--off { opacity:.62; cursor:not-allowed; }
.loccard-main { min-width:0; display:flex; flex-direction:column; gap:2px; }
.loccard-name { font-weight:800; font-size:var(--t-base); color:var(--dark); }
.loccard-meta { font-size:var(--t-xs); color:var(--muted2); font-weight:600; }
.loccard-go { flex:0 0 auto; font-size:var(--t-lg); font-weight:800; color: var(--accent-text); }

/* Locality-restricted Google address suggestions. A contained list stays
   readable above mobile keyboards and never floats outside the sheet. */
.dl-sugs { display:block; margin-top:7px; }
.dl-sugs [role="listbox"] {
  overflow:hidden; border:1px solid var(--line-mid); border-radius:var(--r-lg);
  background:var(--card); box-shadow:var(--shadow-card);
}
.sugbtn {
  display:flex; align-items:flex-start; gap:11px; width:100%; min-height:62px;
  text-align:left; background:var(--card); border:0; border-bottom:1px solid var(--line-soft);
  padding:11px 13px; cursor:pointer; font-family:'Figtree',sans-serif;
  color:var(--dark); transition:background .15s;
}
.sugbtn:last-child { border-bottom:0; }
.sugbtn:hover, .sugbtn--active { background:var(--choice-hover); }
.sugbtn:focus-visible { background:var(--choice-hover); outline:3px solid var(--accent-text); outline-offset:-3px; }
.sugpin {
  flex:0 0 auto; width:22px; height:22px; margin-top:2px; border-radius:50%;
  display:grid; place-items:center; background:var(--accent-soft); color: var(--accent-text); font-size:var(--t-2xs);
}
.sugcopy { flex:1; min-width:0; display:flex; flex-direction:column; line-height:1.25; }
.sugcopy strong { font-size:var(--t-sm); font-weight:800; color:var(--dark); }
.sugcopy small { font-size:var(--t-2xs); color:var(--address-muted); margin-top:2px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.sugcopy em { font-size:var(--t-2xs); color:var(--ok); font-style:normal; font-weight:800; margin-top:4px; }
.suggo { align-self:center; color: var(--accent-text); font-size:var(--t-lg); font-weight:800; }
.dl-google-credit { display:flex; justify-content:flex-end; min-height:20px; padding:5px 3px 0; }
.dl-google-credit img { display:block; width:120px; height:auto; object-fit:contain; }
.dl-searching {
  display:flex; align-items:center; gap:9px; min-height:48px; padding:10px 12px;
  border-radius:var(--r-md); background:var(--white-glass); color:var(--muted);
  font-size:var(--t-xs); font-weight:700;
}
.dl-search-dot {
  width:16px; height:16px; border:2px solid var(--loading-line); border-top-color: var(--accent-text);
  border-radius:50%;
}

/* Google delivery map with a fixed centre pin. The customer moves the map
   beneath it, a reliable one-thumb interaction on small screens. */
.dl-map-wrap, .dl-mini-wrap { position:relative; z-index:0; overflow:hidden; border-radius:var(--r-xl); }
.dl-map {
  width:100%; height:min(52vh, 420px);
  border-radius:var(--r-xl); background:var(--tray);
  position:relative; z-index:0; overflow:hidden;
}
.dl-center-pin {
  position:absolute; z-index:3; pointer-events:none; left:50%; top:50%;
  width:34px; height:44px; transform:translate(-50%,-100%);
}
.dl-center-pin::before {
  content:''; position:absolute; left:4px; top:1px; width:26px; height:26px;
  border-radius:var(--r-lg) var(--r-lg) var(--r-lg) 0; background:var(--accent); transform:rotate(-45deg);
  border:3px solid var(--pure-white);
}
.dl-center-pin span {
  position:absolute; z-index:1; left:13px; top:10px; width:8px; height:8px;
  border-radius:50%; background:var(--pure-white);
}
.dl-center-pin::after {
  content:''; position:absolute; left:10px; bottom:0; width:14px; height:5px;
  border-radius:var(--r-xs); background:var(--line-strong);
}
.dl-zone-status {
  display:flex; align-items:center; justify-content:center; min-height:40px;
  margin-top:9px; border-radius:var(--r-md); padding:8px 11px; text-align:center;
  font-size:var(--t-xs); line-height:1.35; font-weight:800;
}
.dl-zone-status--unchecked { background:var(--tray); color:var(--muted); }
.dl-zone-status--inside { background:var(--ok-soft); color:var(--zone-ok); }
.dl-zone-status--inside::before { content:'✓'; margin-right:6px; }
.dl-zone-status--outside { background:var(--accent-soft); color: var(--accent-text); }
.dl-zone-status--outside::before { content:'!'; display:grid; place-items:center; width:17px; height:17px; margin-right:7px; border:1.5px solid currentColor; border-radius:50%; }
.dl-mini {
  width:100%; height:150px; border-radius:var(--r-lg); background:var(--tray);
  position:relative; z-index:0; overflow:hidden; pointer-events:none;
}
.dl-mini-wrap { margin-bottom:9px; border-radius:var(--r-lg); }
.dl-mini-pin {
  position:absolute; z-index:3; pointer-events:none; left:50%; top:50%;
  width:16px; height:16px; transform:translate(-50%,-50%); border-radius:50%;
  background:var(--accent); border:3px solid var(--pure-white); box-shadow:var(--shadow-sm);
}
.dl-mapbtns { display:flex; gap:8px; margin-top:10px; }
.dl-mapbtns > * { flex:1; min-height:var(--tap); font-size:var(--t-xs); }
.dl-fallback {
  background:var(--tray); border-radius:var(--r-lg); padding:14px 15px;
  font-size:var(--t-sm); color:var(--muted); line-height:1.5;
}

/* Checkout: delivery-location card */
.dl-card {
  background:var(--card); border:1px solid var(--line-soft);
  border-radius:var(--r-lg); padding:13px 14px; margin-bottom:12px;
}
.dl-card-t { font-size:var(--t-sm); font-weight:800; color:var(--dark); }
.dl-card-sub { font-size:var(--t-xs); color:var(--muted2); line-height:1.5; margin:5px 0 11px; }
.dl-card-row { font-size:var(--t-sm); color:var(--dark); margin-top:6px; line-height:1.4; }
.dl-card-dim { color:var(--muted2); font-size:var(--t-xs); }

/* Slot banners & empty state — friendly, never an alert() */
.slot-banner {
  background:var(--accent-soft); border:1px solid var(--accent-line-soft); border-radius:var(--r-md);
  padding:11px 13px; margin-bottom:10px;
  font-size:var(--t-sm); color: var(--accent-text); font-weight:600; line-height:1.45;
}
.slot-empty {
  background:var(--card); border:1px solid var(--line-soft); border-radius:var(--r-lg);
  padding:14px 15px; margin-bottom:12px;
  font-size:var(--t-sm); color:var(--muted); line-height:1.5;
}

/* ══ CONTROL SYSTEM ═════════════════════════════════════════════════════════
   Shared interaction primitives used across every redesigned screen.

   Two rules hold the aesthetic together:
     1. Corners come from the radius scale. Capsules are for badges only.
     2. At most one solid --accent control is visible at a time. If a screen
        wants two, one of them is secondary or a text action.                */

/* ── Buttons ─────────────────────────────────────────────────────────────
   .btn is the shape and rhythm; a modifier supplies the hierarchy. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-2);
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: none;
  font-family: var(--font-body);
  font-size: var(--t-base); font-weight: 700; line-height: 1.2;
  color: var(--dark);
  cursor: pointer;
  transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease,
              color var(--dur-fast) ease, opacity var(--dur-fast) ease;
}
.btn:disabled { cursor: not-allowed; }

/* PRIMARY — the one obvious action on a screen. */
.btn--primary { background: var(--accent); color: var(--card); }
.btn--primary:disabled { background: var(--disabled); color: var(--card); }

/* SECONDARY — real alternatives that should not compete with primary. */
.btn--secondary { border-color: var(--line-strong); color: var(--dark); }
.btn--secondary:disabled { border-color: var(--line); color: var(--muted3); }

/* TEXT — tertiary actions. No border, no fill; hierarchy by weight alone. */
.btn--text {
  min-height: var(--tap); padding: var(--s-2);
  font-weight: 600; color: var(--muted);
}
.btn--text:disabled { color: var(--muted3); }

/* DANGER — destructive, and deliberately NOT a filled red button: the primary
   CTA is already red, and a solid destructive control would outweigh it. */
.btn--danger { min-height: var(--tap); padding: var(--s-2); font-weight: 600; color: var(--accent-text); }

/* CTA — the full-width commit action. Label left, live price right. */
.btn--cta {
  width: 100%; min-height: 52px;
  justify-content: space-between;
  padding: 0 var(--s-5);
  border-color: var(--accent); border-radius: var(--r-lg);
  background: var(--accent); color: var(--card);
  font-size: var(--t-md);
}
.btn--cta:disabled { border-color: var(--disabled); background: var(--disabled); color: var(--card); }

.btn--block { width: 100%; }

/* Press feedback everywhere; hover only where a real pointer exists, so
   touch devices never get a stuck hover state. */
.btn:active:not(:disabled) { transform: translateY(1px); }
@media (hover: hover) and (pointer: fine) {
  .btn--primary:not(:disabled):hover { background: var(--accent-hover); }
  .btn--cta:not(:disabled):hover { border-color: var(--accent-hover); background: var(--accent-hover); }
  .btn--secondary:not(:disabled):hover { background: var(--tray); border-color: var(--line-strong); }
  .btn--text:not(:disabled):hover,
  .btn--danger:not(:disabled):hover { text-decoration: underline; }
}

/* ── Category tabs ───────────────────────────────────────────────────────
   Replaces the capsule filter row. Text with an underline for the active
   item — a filter should not read as important as "Add to order". Scrolls
   horizontally when it must, with a fade to signal there is more. */
/* Horizontal ONLY.
   `overflow-x: auto` alone is not enough: when one axis is not `visible` the
   other computes from `visible` to `auto`, so declaring just the x axis made
   this a scroll container on BOTH. The tabs used to hang 1px below it
   (`margin-bottom: -1px`), which gave that y axis a real 1px scroll range — and
   on iOS Safari a diagonal drag panned it, which is why the strip visibly
   drifted up and down while you swiped sideways. `overflow-y: hidden` is the
   fix; the hairline moved to .tabs-wrap so nothing overflows this box again.

   No `touch-action: pan-x` here on purpose. It would lock the axis, but it also
   blocks vertical PAGE scrolling for any gesture starting on the strip. With no
   vertical scroll range left, the browser already routes vertical drags to
   .scr-scroll and horizontal ones here, which is the behaviour we want. */
.tabs {
  position: relative;
  display: flex; align-items: center; gap: var(--s-1);
  min-height: var(--menu-rail-h);
  padding-inline: var(--s-2);
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}
.tab {
  flex: 0 0 auto;
  display: inline-flex; align-items: center;
  min-width: var(--tap); min-height: var(--tap);
  padding: var(--s-3) var(--s-3) calc(var(--s-3) - 2px);
  border: none; border-bottom: 2px solid transparent;
  background: none;
  font-family: var(--font-body);
  font-size: var(--t-md); font-weight: 500; line-height: 1.2;
  color: var(--muted2);
  white-space: nowrap; cursor: pointer;
  user-select: none; -webkit-user-select: none;
  transition: color var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.tab[aria-selected="true"], .tab[aria-pressed="true"], .tab[aria-current="true"] {
  color: var(--dark); font-weight: 600; border-bottom-color: var(--accent-text);
}
@media (hover: hover) and (pointer: fine) {
  .tab:not([aria-selected="true"]):not([aria-pressed="true"]):not([aria-current="true"]):hover { color: var(--dark); }
}
/* Fade hint on the scrolling edge. Sits above the row, never eats taps.
   The hairline lives here rather than on .tabs so the scroller's content box
   stays exactly as tall as its content. */
.tabs-wrap { position: relative; border-bottom: 1px solid var(--line); }
.tabs-wrap::after {
  content: ''; position: absolute; inset: 0 0 1px auto; width: 32px;
  background: linear-gradient(to right, transparent, var(--bg));
  pointer-events: none;
}

/* ── Quantity stepper ────────────────────────────────────────────────────
   One bordered group, not three separate buttons. 44px targets. */
.stepper {
  display: inline-flex; align-items: center;
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
  overflow: hidden;
}
.stepper button {
  width: var(--tap); height: var(--tap);
  border: none; background: none;
  font-size: var(--t-lg); font-weight: 600; color: var(--dark);
  cursor: pointer;
  transition: background var(--dur-fast) ease, color var(--dur-fast) ease;
}
.stepper button:disabled { color: var(--muted3); cursor: not-allowed; }
.stepper span, .stepper output {
  min-width: 34px; padding: 0 var(--s-1);
  font-size: var(--t-base); font-weight: 700; text-align: center;
  font-variant-numeric: tabular-nums;
}
@media (hover: hover) and (pointer: fine) {
  .stepper button:not(:disabled):hover { background: var(--tray); }
}

/* ── Segmented control ───────────────────────────────────────────────────
   Two or three mutually exclusive options (delivery/pickup, slice count). */
.seg {
  display: inline-flex; width: 100%;
  padding: 3px; gap: 3px;
  background: var(--tray); border-radius: var(--r-md);
}
.seg button {
  flex: 1; min-height: var(--tap);
  border: none; border-radius: var(--r-sm);
  background: none;
  font-family: var(--font-body);
  font-size: var(--t-base); font-weight: 700; color: var(--muted);
  cursor: pointer;
  transition: background var(--dur-fast) ease, color var(--dur-fast) ease;
}
.seg button[aria-pressed="true"] { background: var(--card); color: var(--dark); box-shadow: var(--shadow-sm); }

/* ── Option rows ─────────────────────────────────────────────────────────
   Toppings, extras and removals. Hairline-separated rows instead
   of a boxed card per option — nineteen bordered boxes in one sheet is the
   clutter this redesign removes. The whole row is the target. */
.optlist { display: flex; flex-direction: column; }
.optrow {
  display: flex; align-items: center; gap: var(--s-3);
  width: 100%;
  min-height: var(--tap);
  padding: var(--s-3) 0;
  border: none; border-bottom: 1px solid var(--line-soft);
  background: none; text-align: left;
  font-family: var(--font-body); font-size: var(--t-base); color: var(--dark);
  cursor: pointer;
}
.optlist > .optrow:last-child { border-bottom: none; }
.optrow:disabled { cursor: not-allowed; }

/* ── Hairline list ───────────────────────────────────────────────────────
   Opening hours, delivery areas, receipt lines. Whitespace and a rule, not a
   card per row. */
.rows { display: flex; flex-direction: column; }
.rows > * {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: var(--t-base);
}
.rows > *:last-child { border-bottom: none; }

/* ── Badges ──────────────────────────────────────────────────────────────
   Small status marks. These may be capsules — that is what a badge is. */
.badge {
  display: inline-flex; align-items: center; gap: var(--s-1);
  padding: 3px var(--s-2);
  border-radius: var(--r-xs);
  font-size: var(--t-2xs); font-weight: 800;
  letter-spacing: 0.06em; text-transform: uppercase;
  white-space: nowrap;
}
.badge--new { background: var(--ok-soft); color: var(--ok); }
.badge--best { background: var(--warn-soft); color: var(--warn); }
.badge--out { background: var(--tray); color: var(--muted2); }
.badge--soon { background: var(--tray); color: var(--muted2); }
.badge--count {
  border-radius: var(--r-full);
  min-width: 20px; height: 20px; justify-content: center;
  background: var(--accent); color: var(--card);
  letter-spacing: 0;
}

/* ── Eyebrow ─────────────────────────────────────────────────────────────
   Uppercase micro-label. The one place all-caps earns its place. */
.eyebrow {
  font-size: var(--t-2xs); font-weight: 800;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted2);
}

/* ── Form fields ─────────────────────────────────────────────────────────
   A real <label>, not a placeholder pretending to be one. */
.field { display: flex; flex-direction: column; gap: var(--s-2); margin-bottom: var(--s-4); }
.field-label { font-size: var(--t-sm); font-weight: 600; color: var(--muted); }
.field input, .field textarea, .field select {
  width: 100%;
  min-height: var(--tap);
  padding: var(--s-3);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--card);
  font-family: var(--font-body);
  font-size: var(--t-md);   /* 16px — stops iOS zooming on focus */
  color: var(--dark);
}
.field input::placeholder, .field textarea::placeholder { color: var(--muted3); }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: 3px solid var(--accent-text); outline-offset: 1px; border-color: var(--accent-text); box-shadow: none;
}
.field[data-invalid] input, .field[data-invalid] textarea { border-color: var(--accent-text); }
.field-error { font-size: var(--t-sm); color: var(--accent-text); font-weight: 600; }

/* ══ ORDER START — how, then when ═══════════════════════════════════════
   Step one of ordering. Two selectable cards rather than the two oversized
   capsule buttons the entry gate used: a card has room for the fee and the
   pickup address, which is what makes the choice meaningful. */
.order-scroll { background: var(--bg); }
/* Header, body and footer share one inset so the back button, the headline and
   the CTA all sit on the same left edge, while the header rule and the footer
   bar still run the full width of the shell. */
.order-screen .screen-header,
.order-main,
.order-footer { --order-inset: max(var(--s-4), calc((100% - var(--content-max)) / 2)); }
.order-main { padding: var(--s-6) var(--order-inset) var(--s-8); }
.order-main h1 {
  max-width: 16ch;
  margin: var(--s-2) 0 var(--s-3);
  font-family: var(--font-display);
  font-size: clamp(var(--t-2xl), 7vw, var(--t-3xl));
  font-weight: 400; line-height: 1.06; color: var(--dark);
}
.order-lede {
  max-width: 46ch;
  margin-bottom: var(--s-6);
  color: var(--muted); font-size: var(--t-base); line-height: 1.55;
}
.order-closed-actions { display: grid; gap: var(--s-2); }
.mode-cards { display: grid; gap: var(--s-3); }
.mode-card {
  display: flex; flex-direction: column; gap: 4px;
  width: 100%; padding: var(--s-4);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--card); color: var(--dark);
  text-align: left; cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.mode-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.mode-card-head strong { font-size: var(--t-md); font-weight: 800; }
.mode-card-line { color: var(--dark); font-size: var(--t-sm); font-weight: 700; }
.mode-card-sub { color: var(--muted); font-size: var(--t-xs); font-weight: 600; line-height: 1.45; }
/* The tick occupies its slot at all times so selecting a card never reflows
   the text beside it. */
.mode-card-tick {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 22px; height: 22px;
  border: 1px solid var(--line-strong); border-radius: var(--r-xs);
  color: transparent; font-size: var(--t-xs); font-weight: 800;
}
.mode-card.is-selected { border-color: var(--accent-text); background: var(--accent-soft); }
.mode-card.is-selected .mode-card-tick {
  border-color: var(--accent-text); background: var(--accent-text); color: var(--card);
}
.mode-card.is-selected .mode-card-line { color: var(--accent-text); }
.order-footer {
  position: relative; z-index: var(--z-bar); flex: 0 0 auto;
  padding: var(--s-3) var(--order-inset) var(--safe-bottom);
  border-top: 1px solid var(--line-soft); background: var(--bg); box-shadow: var(--shadow-bar);
}
.order-footer .btn--cta {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  width: 100%;
  padding-inline: var(--s-5); font-size: var(--t-md);
}
@media (min-width: 640px) {
  .mode-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.sheet-grab {
  width: 42px; height: 4px; margin: 0 auto var(--s-5);
  border-radius: var(--r-xs); background: var(--line-strong);
}
.icon-btn {
  display: grid; flex: 0 0 auto; place-items: center;
  width: var(--tap); height: var(--tap);
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--card); color: var(--dark);
  font-family: var(--font-body); font-size: var(--t-xl); cursor: pointer;
}
@media (min-width: 640px) {
}

/* ══ HOME + MENU ══════════════════════════════════════════════════════════ */
.menu-skeleton { min-height: 100%; background: var(--bg); }
.menu-skeleton-header {
  display: flex; align-items: center; min-height: 68px;
  padding: var(--safe-top) var(--s-4) var(--s-3);
  border-bottom: 1px solid var(--line-soft);
}
.menu-skeleton-heading, .menu-skeleton-grid {
  width: min(100%, 1180px); margin-inline: auto;
}
.menu-skeleton-heading {
  display: grid; gap: var(--s-2);
  padding: var(--s-8) var(--s-4) var(--s-5);
}
.menu-skeleton-heading .skel:first-child { width: min(52%, 320px); height: 34px; }
.menu-skeleton-heading .skel:last-child { width: min(72%, 520px); height: 13px; }
.menu-skeleton-grid { padding: 0 var(--s-4) var(--safe-bottom); }
.skeleton-product {
  display: grid; gap: var(--s-3); padding: var(--s-3);
  border: 1px solid var(--line-soft); border-radius: var(--r-lg);
  background: var(--card);
}
.skeleton-product .skel:first-child { width: 100%; height: 140px; }
.skeleton-product .skel:nth-child(2) { width: 68%; height: 18px; }
.skeleton-product .skel:last-child { width: 44%; height: 13px; }
@media (min-width: 760px) {
  .menu-skeleton-heading { padding-top: var(--s-10); }
  .skeleton-product .skel:first-child { height: 180px; }
}

@media (min-width: 1024px) {
  #app[data-screen="home"],
  #app[data-screen="menu"] { --shell-max: 1240px; }
}

.site-header {
  position: sticky; top: 0; z-index: 12;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
  min-height: 68px;
  padding: var(--safe-top) var(--s-4) var(--s-3);
  border-bottom: 1px solid var(--line-soft);
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter: blur(14px);
}
/* The logo is how you get home now that the bottom bar is gone, so it carries a
   real tap target and a pressed state rather than reading as decoration. */
.brand-home {
  display: inline-flex; flex: 0 0 auto; align-items: center;
  min-height: var(--tap); padding: var(--s-1) var(--s-2);
  margin-left: calc(var(--s-2) * -1);
  border: 0; border-radius: var(--r-md); background: none; cursor: pointer;
  transition: background var(--dur-fast) var(--ease);
}
.brand-home:active { background: var(--tray); }
.site-nav { display: flex; align-items: center; justify-content: flex-end; gap: var(--s-1); min-width: 0; }
.site-nav-link, .header-cart {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-width: var(--tap); min-height: var(--tap); padding: 0 var(--s-3);
  border: 0; border-radius: var(--r-md);
  background: none; color: var(--muted);
  font-family: var(--font-body); font-size: var(--t-sm); font-weight: 700;
  white-space: nowrap; cursor: pointer;
}
.site-nav-link.is-current { color: var(--accent-text); background: var(--accent-soft); }
.site-nav-link svg { flex: 0 0 auto; }
.nav-avatar {
  display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: var(--r-full);
  background: var(--dark); color: var(--card);
  font-size: var(--t-xs); font-weight: 800;
}
.header-cart {
  border: 1px solid var(--line-strong);
  color: var(--dark); margin-left: var(--s-1);
}
.header-cart strong { font-size: var(--t-sm); font-variant-numeric: tabular-nums; }
@media (max-width: 560px) {
  .site-header { padding-inline: var(--s-3); }
  .site-nav { gap: 0; }
  .site-nav-link { padding-inline: var(--s-2); }
  .site-nav-orders span, .site-nav-account > span:last-child { display: none; }
}
@media (max-width: 360px) {
  .site-nav-link { padding-inline: var(--s-1); }
}
@media (max-width: 819px) { .header-cart { display: none; } }

.home-main, .menu-main {
  width: min(100%, 1180px); margin: 0 auto;
  padding: var(--s-5) var(--s-4) calc(var(--s-12) + var(--safe-bottom));
}
/* ── Typographic hero ────────────────────────────────────────────────────
   No photograph. The only product imagery available is square studio crops,
   which is precisely the pale-framed cut-out pizza this replaced. Type and
   the brand mark carry it instead. A single full-bleed image can be dropped
   into .home-hero-ground later without touching the layout. */
.home-hero {
  position: relative; isolation: isolate;
  display: flex; flex-direction: column; justify-content: center;
  min-height: min(62vh, 460px);
  padding: var(--s-8) 0 var(--s-10);
  overflow: hidden;
}
.home-hero-ground {
  position: absolute; z-index: -1;
  top: 6%; right: -14%;
  opacity: .07; pointer-events: none;
}
.home-hero-copy { display: flex; flex-direction: column; align-items: flex-start; }
.home-hero h1 {
  margin-top: var(--s-2);
  font-family: var(--font-display); font-size: clamp(var(--t-3xl), 13vw, 68px);
  font-weight: 400; line-height: .98; letter-spacing: -0.02em; color: var(--dark);
}
.home-hero-lede {
  max-width: 34ch; margin-top: var(--s-4);
  color: var(--muted); font-size: var(--t-base); line-height: 1.55;
}
/* The one prominent action on the page. Rectangular with controlled rounding —
   never a capsule. */
.home-order-cta {
  width: 100%; max-width: 320px; min-height: 56px;
  margin-top: var(--s-6);
  justify-content: space-between; padding-inline: var(--s-5);
  border-radius: var(--r-lg);
  font-size: var(--t-lg); letter-spacing: 0.02em;
}
.home-hero-closed {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-3);
  margin-top: var(--s-5); padding: var(--s-4);
  border: 1px solid var(--accent-line); border-radius: var(--r-lg);
  background: var(--accent-soft);
}
.home-hero-closed strong { color: var(--dark); font-size: var(--t-base); line-height: 1.45; }
.home-hero-status {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2);
  margin-top: var(--s-5);
  color: var(--muted2); font-size: var(--t-sm); font-weight: 600;
}
.site-header--minimal .site-nav { gap: var(--s-2); }
@media (min-width: 760px) {
  .home-hero { min-height: min(64vh, 520px); }
  .home-hero h1 { font-size: clamp(56px, 7vw, 76px); }
  .home-hero-ground { top: 4%; right: 4%; opacity: .08; }
}

.section-heading { margin-bottom: var(--s-5); }
.section-heading h2, .visit-copy h2 {
  font-family: var(--font-display); font-size: var(--t-2xl); font-weight: 400; line-height: 1.08; color: var(--dark);
}
.section-heading p { max-width: 44ch; margin-top: var(--s-2); color: var(--muted); font-size: var(--t-sm); }
.brand-strip {
  display: grid; gap: var(--s-2);
  margin: var(--s-6) 0; padding: var(--s-6);
  border-radius: var(--r-lg);
  background: var(--dark); color: var(--on-dark);
}
.brand-strip .eyebrow { color: var(--accent-on-dark); }
.brand-strip > p:last-child {
  max-width: 42ch;
  font-family: var(--font-display); font-size: var(--t-xl); line-height: 1.2;
}
.visit-block {
  display: grid; gap: var(--s-5);
  padding: var(--s-8) 0;
  border-top: 1px solid var(--line);
}
.visit-copy > p:not(.eyebrow) { margin-top: var(--s-2); color: var(--muted); font-size: var(--t-sm); }
.visit-copy h2 { margin-top: var(--s-2); }
.visit-status { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; margin-top: var(--s-4); color: var(--muted2); font-size: var(--t-sm); }
.visit-actions { display: flex; align-items: flex-start; flex-direction: column; gap: var(--s-2); }
@media (min-width: 700px) {
  .visit-block { grid-template-columns: minmax(0, 1fr) auto; align-items: end; }
  .visit-actions { align-items: flex-end; }
}

/* A previous order offered on the homepage rather than hijacking the screen. */
.recovery {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-3);
  margin: var(--s-4) 0 0; padding: var(--s-4);
  border: 1px solid var(--accent-line); border-left: 3px solid var(--accent);
  border-radius: var(--r-lg); background: var(--accent-soft);
}
.recovery-copy { display: flex; min-width: 0; flex: 1 1 260px; flex-direction: column; gap: 2px; }
.recovery-copy strong { color: var(--dark); font-size: var(--t-base); font-weight: 800; }
.recovery-copy span { color: var(--muted); font-size: var(--t-sm); line-height: 1.45; }
.recovery-actions { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); }

.menu-heading {
  display: flex; align-items: end; justify-content: space-between; gap: var(--s-6);
  padding: var(--s-4) 0 var(--s-8);
}
.menu-heading h1 {
  margin-top: var(--s-1);
  font-family: var(--font-display); font-size: clamp(var(--t-2xl), 6vw, var(--t-3xl)); font-weight: 400; color: var(--dark);
}
.menu-heading > p { max-width: 48ch; color: var(--muted); font-size: var(--t-sm); line-height: 1.5; }
/* minmax(0, 1fr), not the implicit auto: an auto column takes its width from
   content, so anything wider than the container silently widens the whole
   grid and pushes the rows past the right edge. */
.menu-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }
/* Every category is a section in one continuous scroll. The tab strip sticks
   below the site header and tracks position rather than filtering. */
/* Solid, not a translucent blur: iOS Safari repaints a backdrop-filter on every
   sticky reposition, which showed up as the strip flickering during a scroll. */
.menu-category-rail {
  position: sticky; z-index: 11; top: var(--header-h);
  min-width: 0;
  background: var(--bg);
}
.menu-products { min-width: 0; }
.menu-section + .menu-section { margin-top: var(--s-8); }
/* Jump offsets are computed in app.js (menuStickyOffset) against the measured
   header and tab-strip heights, so no scroll-margin guess is needed here. */
.menu-section-title {
  margin-bottom: var(--s-3);
  font-family: var(--font-display); font-size: var(--t-xl); font-weight: 400; color: var(--dark);
}
/* 640px, matching the card's own switch to a stacked layout. When these two
   disagreed, 640-679px rendered one full-width 4:3 photo per row. */
@media (min-width: 640px) {
  .product-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .menu-layout { grid-template-columns: 210px minmax(0, 1fr); align-items: start; gap: clamp(32px, 5vw, 68px); }
  /* A vertical rail instead of a strip; no band needed beside content. */
  .menu-category-rail {
    top: 92px;
    background: none;
  }
  .menu-category-rail .tabs {
    flex-direction: column; align-items: stretch; gap: 0;
    min-height: 0; padding-inline: 0;
    overflow: visible;
  }
  .menu-category-rail .tab {
    display: flex; width: 100%; margin: 0; padding: var(--s-3) 0;
    border-bottom: 1px solid var(--line-soft); text-align: left;
    font-size: var(--t-base);
  }
  .menu-category-rail .tab[aria-pressed="true"],
  .menu-category-rail .tab[aria-current="true"] {
    padding-left: var(--s-3);
    border-bottom-color: var(--line-soft); border-left: 3px solid var(--accent-text);
  }
  .menu-category-rail .tabs-wrap { border-bottom: 0; }
  .menu-category-rail .tabs-wrap::after { display: none; }
}

.item-badges { display: inline-flex; flex-wrap: wrap; gap: var(--s-1); }
.product-card.pcard {
  position: relative;
  /* Copy first, media second — the name and price are what people scan.
     The media track is proportional, not a fixed 116px: at 320px that fixed
     track took 44% of the usable card and squeezed the description into a
     ~44-character box, which is what made descriptions look "cut off". */
  display: grid; grid-template-columns: minmax(0, 1fr) clamp(88px, 26vw, 104px);
  align-items: start; gap: var(--s-3);
  min-height: 0; padding: var(--s-3);
  border: 1px solid var(--line-soft); border-radius: var(--r-lg);
  background: var(--card); box-shadow: none;
  font-family: var(--font-body); color: var(--dark);
  width: 100%; text-align: left;
}
.product-card.is-unavailable { opacity: .58; }
/* Same clipping requirement as .item-hero: .pcard-photo is scaled by
   --img-scale, and nothing has caught this because no product carries one yet. */
.product-card .pcard-media { position: relative; min-width: 0; overflow: hidden; border-radius: var(--r-md); }
.product-card .pcard-img {
  width: 100%; min-width: 0; aspect-ratio: 1 / 1;
  border-radius: var(--r-md); background: var(--tray);
}
/* Per-row availability, above the name — the reference app's status line. */
.product-card .pcard-avail {
  display: flex; align-items: center; gap: var(--s-1);
  margin-bottom: var(--s-1);
  color: var(--ok); font-size: var(--t-2xs); font-weight: 700;
}
.product-card .pcard-avail::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; flex: 0 0 auto;
}
.product-card .pcard-avail--neutral { color: var(--muted); }
.pcard-avail--out,
.product-card .pcard-avail--soon { color: var(--muted2); }
.product-card .pcard-body { display: flex; min-width: 0; flex-direction: column; padding: 0; }
/* Wraps rather than overflowing: a long name beside a "Best seller" badge
   used to exceed the text column and get clipped by the scroller. */
.product-card .pcard-top {
  display: flex; align-items: flex-start; justify-content: space-between;
  flex-wrap: wrap; gap: var(--s-1) var(--s-2);
}
.product-card .pcard-name {
  min-width: 0; flex: 1 1 auto;
  font-family: var(--font-display); font-size: var(--t-lg); line-height: 1.08; color: var(--dark);
}
.product-card .pcard-category {
  margin-top: var(--s-2); padding: 2px var(--s-2); border-radius: var(--r-xs);
  background: var(--tray); color: var(--muted); font-size: var(--t-2xs); font-weight: 800;
}
.product-card .pcard-desc {
  margin-top: var(--s-2);
  color: var(--muted2); font-size: var(--t-xs); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* The price sits directly under the name, above the description — no
   `margin-top: auto`. Pushing it to the bottom of a box stretched to the
   image's height is what left a dead band under short descriptions. */
.product-card .pcard-foot {
  display: flex; align-items: baseline;
  flex-wrap: wrap; gap: var(--s-1) var(--s-2);
  margin-top: var(--s-1);
}
.product-card .pcard-price { color: var(--dark); font-size: var(--t-base); font-weight: 800; }
.product-card .pcard-choose {
  display: inline-flex; align-items: center; gap: var(--s-1);
  padding: 0; border-radius: 0; background: none; color: var(--accent-text);
  font-size: var(--t-xs); font-weight: 800; white-space: nowrap;
}
.product-card .pcard-choose--off { color: var(--muted3); }
.product-card .pcard-choose--selected { color: var(--ok); }
.product-card.pcard--selected { border-color: var(--accent-text); box-shadow: var(--shadow-focus); }

/* The add control, on the photo's corner. Outlined, never solid accent — a
   browsing row is not the screen's primary action.
   Two forms, one button per row either way:
     .pcard-plus                 an inert mark; .pcard-hit takes the taps
     .pcard-plus--button         the button itself, for actions that must not
                                 fire from a stray tap on the row */
.pcard-plus {
  position: absolute; z-index: 2;
  top: -6px; right: -6px;
  display: grid; place-items: center;
  width: var(--tap); height: var(--tap);
  padding: 0;
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
  background: var(--card); color: var(--accent-text);
  box-shadow: var(--shadow-sm);
  pointer-events: none;   /* the mark: taps fall through to .pcard-hit */
  transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
/* 44px stays the tap target; the drawn control is smaller so it sits on the
   photo's corner rather than covering it. */
.pcard-plus svg { width: 18px; height: 18px; }
.pcard-plus--button { pointer-events: auto; cursor: pointer; }
/* Full-card overlay. Transparent, so the row reads normally, but it is the
   row's only interactive element and covers the whole surface. */
.pcard-hit {
  position: absolute; z-index: 1; inset: 0;
  border: none; background: none; padding: 0;
  cursor: pointer;
}
.pcard-hit:focus-visible { outline: 3px solid var(--accent-text); outline-offset: -3px; border-radius: var(--r-lg); }
.in-cart-note { color: var(--ok); font-size: var(--t-xs); font-weight: 800; }
/* The row keeps its copy-then-media shape at every width. Two columns of the
   same row read consistently; stacking the media on top only reintroduced the
   oversized-photo problem on a narrower card. */
@media (min-width: 640px) {
  .product-grid > .product-card .pcard-name,
}
@media (hover: hover) and (pointer: fine) {
  /* Hover lives on the card but is triggered by its overlay button, so a
     disabled (unavailable) row — which renders no button — never lifts. */
  .product-card.pcard:has(.pcard-hit:hover),
  .product-card.pcard:has(.pcard-plus--button:hover) {
    border-color: var(--line-strong); box-shadow: var(--shadow-card);
  }
  .product-card.pcard:has(.pcard-hit:hover) .pcard-plus,
  .pcard-plus--button:hover { background: var(--tray); }
  .site-nav-link:hover, .header-cart:hover { background: var(--tray); color: var(--dark); }
}

.empty-state {
  padding: var(--s-8); border: 1px solid var(--line); border-radius: var(--r-lg);
  color: var(--muted); text-align: center;
}
.empty-state h2 { font-family: var(--font-display); font-size: var(--t-xl); font-weight: 400; color: var(--dark); }
.empty-state p { margin-top: var(--s-2); font-size: var(--t-sm); line-height: 1.5; }
.empty-state--compact { grid-column: 1 / -1; padding: var(--s-5); }

.cart-bar-count { color: var(--card); font-size: var(--t-sm); font-weight: 700; }
.cart-bar-total { display: flex; align-items: center; gap: var(--s-2); color: var(--card); font-size: var(--t-base); font-weight: 800; }
.cart-bar-btn { border-radius: var(--r-lg); box-shadow: var(--shadow-bar); }
@media (min-width: 820px) { .cart-bar { display: none; } }
@media (min-width: 1024px) {
  .scr-scroll { scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
  .scr-scroll::-webkit-scrollbar { display: block; width: 8px; }
  .scr-scroll::-webkit-scrollbar-thumb { border-radius: var(--r-xs); background: var(--line-strong); }
}

/* ══ PHASE 4: ITEM CUSTOMISER + HALF & HALF ═════════════════════════════ */
.screen-header {
  display: flex; flex: 0 0 auto; align-items: center; gap: var(--s-3);
  min-height: calc(var(--safe-top) + 54px);
  padding: var(--safe-top) var(--s-4) var(--s-3);
  border-bottom: 1px solid var(--line-soft); background: var(--bg);
}
.screen-header .back-btn, .half-picker-header .back-btn { width: var(--tap); height: var(--tap); }
.order-screen .screen-header { padding-inline: var(--order-inset); }
.item-header > div, .order-screen .screen-header > div { display: flex; min-width: 0; flex: 1; flex-direction: column; }
.item-header > div > span, .order-screen .screen-header > div > span {
  color: var(--muted2); font-size: var(--t-2xs); font-weight: 800;
  letter-spacing: .06em; text-transform: uppercase;
}
.item-header > div > strong, .order-screen .screen-header > div > strong {
  overflow: hidden; color: var(--dark); font-family: var(--font-display);
  font-size: var(--t-lg); font-weight: 400; text-overflow: ellipsis; white-space: nowrap;
}
.item-cart-shortcut {
  position: relative; display: none; place-items: center;
  width: var(--tap); height: var(--tap); border: 1px solid var(--line);
  border-radius: var(--r-md); background: var(--card); color: var(--dark); cursor: pointer;
}
.item-cart-shortcut > span {
  position: absolute; top: -5px; right: -5px; display: grid; place-items: center;
  min-width: 20px; height: 20px; padding: 0 5px; border-radius: var(--r-full);
  background: var(--accent); color: var(--card); font-size: var(--t-2xs); font-weight: 900;
}
.item-scroll { background: var(--bg); }
.item-dialog { min-height: 100%; background: var(--bg); }
/* Image-led: full-bleed, no frame, no header above it.
   Square frame against square source photos, so `cover` crops essentially
   nothing and the whole pizza is shown. The cap is what actually sets the
   height — 45vh on every phone — and the ratio only governs if a screen is
   ever wider than it is tall. A 4/3 frame here left the hero at 35% of a
   390px screen, well short of dominating the fold. */
/* One unified hero. Its height is stated here rather than inherited from the
   photo's proportions: when the image's own aspect-ratio drove it, the ratio
   won at phone widths and the max-height cap never engaged, which is why the
   hero came out at 35% instead of the intended 45%.
   overflow:hidden is load-bearing twice over — the photo is scaled past its
   frame, and it is absolutely positioned to fill this box. */
.item-hero {
  position: relative; overflow: hidden;
  height: clamp(280px, 45vh, 460px);
  background: var(--card);
}
/* A short scrim at the top only, so the floating controls stay legible over a
   pale crust. Deliberately not a wash over the whole photo. */
.item-hero::before {
  content: ''; position: absolute; z-index: 1; inset: 0 0 auto;
  height: calc(var(--safe-top) + 72px);
  background: linear-gradient(to bottom, var(--scrim), transparent);
  pointer-events: none;
}
/* The product shots are cut-outs with cream padding baked in — measured, the
   pizza fills 83–95% of its own file, and that cream is near-identical to the
   page background, so the slack reads as a layout gap rather than as part of
   the photo. A small zoom pushes the pizza out to the frame edges.
   1.12 is a DEFAULT, expressed as the var() fallback: once products carry a
   real image_scale it overrides this automatically, with no edit here. */
.item-hero .detail-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  aspect-ratio: auto; max-height: none;
  border-radius: 0; background: var(--tray);
  object-fit: cover; object-position: var(--img-position, center);
  transform: scale(var(--img-scale, 1.12));
}
/* The branded placeholder has no baked-in margin to recover, and it is drawn
   to fit — zooming it would just crop its own artwork. This needs the same
   specificity as the rule above, which out-ranks the base .detail-ph. */
.item-hero .detail-ph { transform: none; }
/* Floats on the photo. Named "circle" deliberately: the pill-button guard in
   test/style-system.test.js allows a fully round corner only on ornaments, and
   a round control is exactly what this is. */
.item-back-circle, .item-cart-circle {
  position: absolute; z-index: 2;
  top: calc(var(--safe-top) + var(--s-2));
  display: grid; place-items: center;
  width: var(--tap); height: var(--tap);
  border: none; border-radius: 50%;
  background: var(--pure-white); box-shadow: var(--shadow-card);
  cursor: pointer;
}
.item-back-circle { left: var(--s-3); }
.item-cart-circle { right: var(--s-3); color: var(--dark); }
.item-cart-circle .badge--count {
  position: absolute; top: -4px; right: -4px;
}
/* Lifted over the photo's lower edge so the seam is a soft rounded transition
   rather than a hard horizontal cut. The negative margin is the whole trick:
   the panel keeps its own background, so it reads as a sheet resting on the
   image. Its top edge landing just inside the fold is deliberate — it is what
   tells you there is more below without stealing height from the pizza. */
.item-info {
  position: relative; z-index: 1;
  margin-top: calc(var(--s-6) * -1);
  padding: var(--s-6) var(--s-4) var(--s-4);
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  background: var(--bg);
}
.item-avail {
  color: var(--ok); font-size: var(--t-xs); font-weight: 700;
}
.item-avail--out, .item-avail--soon { color: var(--muted2); }
.item-info h1 {
  margin-top: var(--s-2); color: var(--dark); font-family: var(--font-display);
  font-size: var(--t-2xl); font-weight: 400; line-height: 1.08;
}
.item-desc {
  margin-top: var(--s-3); max-width: 52ch;
  color: var(--muted); font-size: var(--t-base); line-height: 1.55;
}
.item-badge-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2);
  margin-top: var(--s-4);
}
.badge--veg { background: var(--ok-soft); color: var(--ok); }
.badge--nonveg, .badge--soon { background: var(--accent-soft); color: var(--accent-text); }
.badge--neutral { background: var(--tray); color: var(--muted); }
/* The starting price, in the content rather than only in the CTA. */
.item-price {
  display: flex; align-items: baseline; gap: var(--s-2);
  margin-top: var(--s-4);
  font-variant-numeric: tabular-nums;
}
.item-price > span { color: var(--muted); font-size: var(--t-sm); font-weight: 600; }
.item-price > strong { color: var(--dark); font-size: var(--t-xl); font-weight: 800; }
.item-config {
  padding: 0 var(--s-4) var(--s-8);
  border-top: 1px solid var(--line);
}
.item-section { padding: var(--s-5) 0; border-bottom: 1px solid var(--line); }
.item-section:last-child { border-bottom: 0; }
/* Full pizza / Half & Half rows read as cards, not hairline list rows: this is
   the first and most consequential choice on the screen. */
.optrow--style {
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--card);
}
.optlist > .optrow--style { border-bottom: 1px solid var(--line); }
.optrow--style + .optrow--style { margin-top: var(--s-2); }
.optrow--style.is-active {
  border-color: var(--accent-text); background: var(--accent-soft);
}
.optrow--style.is-active .optrow-copy strong { color: var(--accent-text); }
/* ── Option groups ───────────────────────────────────────────────────────
   Slices, removals and extras all render through optionGroup()/optionRow():
   a rule hint, a title with an optional Required badge, then rows. Separated
   by a band rather than a border so the groups read as distinct blocks. */
.optgroup { padding: var(--s-5) 0; border-bottom: 1px solid var(--line); }
.optgroup:last-of-type { border-bottom: 0; }
.optgroup-hint { color: var(--muted2); font-size: var(--t-xs); }
.optgroup-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); margin-top: var(--s-1); }
.optgroup-head h2 {
  min-width: 0;
  color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg); font-weight: 400;
}
.optgroup-required {
  flex: 0 0 auto;
  padding: 3px var(--s-2); border-radius: var(--r-xs);
  background: var(--tray); color: var(--muted);
  font-size: var(--t-2xs); font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
}
.optgroup-note { margin-top: var(--s-1); color: var(--muted2); font-size: var(--t-xs); line-height: 1.45; }
.option-list { margin-top: var(--s-2); }
.optrow-copy { display: flex; min-width: 0; flex: 1; flex-direction: column; }
.optrow-copy strong { color: var(--dark); font-size: var(--t-base); font-weight: 700; }
.optrow-copy small { margin-top: 2px; color: var(--muted2); font-size: var(--t-2xs); }
.optrow-delta {
  flex: 0 0 auto; color: var(--muted2);
  font-size: var(--t-sm); font-weight: 700; font-variant-numeric: tabular-nums;
}
.optrow--remove.off .optrow-copy strong { color: var(--muted3); text-decoration: line-through; }
.optrow-check {
  flex: 0 0 auto;
  display: grid; place-items: center; width: 22px; height: 22px;
  border: 1.5px solid var(--line-strong); border-radius: var(--r-xs);
  color: transparent; font-size: var(--t-xs);
  transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease;
}
/* One filled-tick treatment, each state class fixed by the patch function that
   toggles it: toggleRemove 'off', setSlices 'is-active'. Extras no longer use
   a tick — a selected extra carries a quantity control instead. */
.optrow--remove.off .optrow-check,
.optrow--slice.is-active .optrow-check {
  border-color: var(--accent-text); background: var(--accent); color: var(--card);
}

/* ── Extra with a quantity ──
   A selected extra is still an ordinary list row: same background, same
   height, same divider, same type. Only the right-hand control changes, from
   a price and tick to a stepper. It deliberately carries NO highlight — the
   quantity is the selection indicator, which is also why it does not depend
   on colour. (An accent-soft fill here turned one row into a card and pushed
   the rest of the list around.)
   Unselected the row is a <button>, so the whole surface is the tap target;
   selected it is a plain row, because three controls cannot live inside one
   button — the same one-button-per-row rule the product cards follow. */
/* The 42px stepper is taller than a plain row's text, so the block padding
   tightens to absorb it — otherwise selecting an extra grew the row from 47px
   to 69px and shunted the rest of the list down. */
.optrow--extra.is-on { background: none; padding-block: var(--s-1); }
.optrow--extra.is-on .optrow-copy small { color: var(--muted2); }
.qty-control {
  flex: 0 0 auto; display: inline-flex; align-items: center;
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
  background: var(--card); overflow: hidden;
}
.qty-btn {
  display: grid; place-items: center;
  width: 42px; height: 42px;
  border: none; background: none; color: var(--dark);
  font-family: var(--font-body); font-size: var(--t-lg); font-weight: 800;
  line-height: 1; cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.qty-btn:disabled { color: var(--muted3); cursor: not-allowed; }
.qty-btn:active:not(:disabled) { background: var(--tray); }
@media (hover: hover) and (pointer: fine) {
  .qty-btn:hover:not(:disabled) { background: var(--tray); }
}
.qty-count {
  min-width: 30px; padding: 0 var(--s-1);
  border-inline: 1px solid var(--line-soft);
  color: var(--dark); font-size: var(--t-md); font-weight: 800;
  line-height: 42px; text-align: center; font-variant-numeric: tabular-nums;
}
/* Reached-the-limit line, under the extras list. */
.optgroup-note--limit { color: var(--accent-text); font-weight: 700; }
.optrow--slice.is-active .optrow-check,
.optrow--style.is-active .optrow-check {
  border-color: var(--accent-text); background: var(--accent); color: var(--card);
}
.optrow--slice.is-active .optrow-copy strong { color: var(--dark); }
.seg__button.is-active { background: var(--card); color: var(--dark); box-shadow: var(--shadow-sm); }
.item-limit-note {
  margin: var(--s-2) 0 0; color: var(--accent-text);
  font-size: var(--t-xs); font-weight: 700; line-height: 1.4;
}
.limit-banner {
  margin-bottom: var(--s-5); padding: var(--s-3) var(--s-4);
  border-left: 3px solid var(--accent); background: var(--accent-soft);
  color: var(--dark); font-size: var(--t-sm); font-weight: 700; line-height: 1.45;
}
.stepper > span, .stepper > output {
  min-width: 36px; padding: 0 var(--s-1); color: var(--dark);
  font-size: var(--t-md); font-weight: 800; text-align: center; font-variant-numeric: tabular-nums;
}
.item-footer {
  position: relative; z-index: var(--z-bar); flex: 0 0 auto;
  padding: var(--s-3) var(--s-4) var(--safe-bottom);
  border-top: 1px solid var(--line-soft); background: var(--bg); box-shadow: var(--shadow-bar);
}
/* Quantity left, action right — the whole decision on one thumb-reachable row. */
.item-footer-row { display: flex; align-items: center; gap: var(--s-3); }
.item-footer .stepper { flex: 0 0 auto; }
.item-cta {
  display: flex; align-items: center; justify-content: center; gap: var(--s-2);
  flex: 1; min-width: 0; min-height: 54px; padding-inline: var(--s-4);
}
.item-cta strong { font-size: var(--t-base); font-variant-numeric: tabular-nums; }
.item-cta strong::before { content: '·'; margin-right: var(--s-2); font-weight: 400; }

.half-picker-scroll { padding: var(--s-3) var(--s-4) var(--s-8); }
.half-filter-row { margin: 0 0 var(--s-4); overflow: visible; }
.half-filter-row .tabs-wrap::after { background: linear-gradient(to right, transparent, var(--bg)); }
.half-picker-grid { display: grid; grid-template-columns: 1fr; gap: var(--s-3); }
.half-picker-grid > .product-card { margin: 0; }
.half-picker-rule { max-width: 54ch; margin: var(--s-5) auto 0; }
.half-price-note {
  margin: var(--s-3) 0 0; padding: var(--s-3);
  border-left: 3px solid var(--accent); background: var(--accent-soft);
  color: var(--muted); font-size: var(--t-xs); line-height: 1.5;
}
.half-price-note strong { color: var(--dark); }

@media (min-width: 640px) {
  .half-picker-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .item-footer { display: flex; justify-content: center; }
  .item-cta { max-width: 620px; }
}
/* 768px so an iPad in portrait gets the image beside the options rather than
   stacked above them. */
@media (min-width: 768px) {
  #app[data-screen="item"], #app[data-screen="halfselect"] { --shell-max: 1040px; }
  .item-cart-shortcut { display: grid; }
  .half-picker-title-row { align-items: center; }
  .half-picker-title-row .item-cart-shortcut { margin-left: auto; }
  .item-header, .half-picker-header { padding-inline: var(--s-6); }
  .item-scroll { display: flex; justify-content: center; padding: var(--s-8); }
  /* Minimums sized so the two columns still fit the 720px shell an iPad in
     portrait gets: 720 minus the 32px scroller padding either side leaves
     656px, and 260 + 320 + gap clears that. The previous 300/360 minimums
     needed 660px and would have overflowed. */
  .item-dialog {
    display: grid; grid-template-columns: minmax(260px, .9fr) minmax(320px, 1.1fr);
    grid-template-rows: auto 1fr;
    align-items: start; min-height: 0; width: 100%; max-width: 920px;
    overflow: hidden;
    border: 1px solid var(--line); border-radius: var(--r-xl); box-shadow: var(--shadow-sheet);
  }
  /* Photo down the left, copy and options down the right. The mobile hero's
     45vh cap is a phone rule — at 920px wide it would be an enormous band. */
  /* align-self: start keeps the panel exactly as tall as the photo — spanning
     both rows left a large empty band under it on a tall dialog. */
  .item-hero {
    grid-row: 1 / 3; align-self: start;
    position: sticky; top: 0;
    min-width: 0; border-right: 1px solid var(--line);
  }
  .item-hero .detail-img { aspect-ratio: 1 / 1; max-height: none; }
  /* The hero is the left column here, so its height comes from the grid, not
     from the mobile clamp(). */
  .item-hero { height: auto; }
  .item-hero .detail-img { position: static; aspect-ratio: 1 / 1; }
  .item-hero::before { display: none; }
  .item-back-circle, .item-cart-circle { top: var(--s-3); }
  /* The overlap is a mobile idea. Here the hero is the LEFT COLUMN, so lifting
     the panel would pull it up the page beside the photo rather than over it. */
  .item-info {
    grid-column: 2;
    margin-top: 0; border-radius: 0; background: none;
    padding: var(--s-6) var(--s-6) var(--s-4);
  }
  .item-config { grid-column: 2; min-width: 0; padding: 0 var(--s-6) var(--s-8); }
  .half-picker-scroll { padding: var(--s-5) var(--s-6) var(--s-10); }
  .half-picker-header { display: grid; grid-template-columns: 1fr minmax(280px, 420px); align-items: center; gap: var(--s-6); }
  .half-first-summary { margin-top: 0; }
}
@media (min-width: 1024px) {
  .half-picker-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ══ PHASE 6: CART + INLINE SUGGESTIONS ══════════════════════════════════ */
.cart-screen { position: relative; }
.cart-header > div { display: flex; min-width: 0; flex-direction: column; }
.cart-header > div > span {
  color: var(--muted2); font-size: var(--t-2xs); font-weight: 800;
  letter-spacing: .06em; text-transform: uppercase;
}
.cart-header h1 { color: var(--dark); font-family: var(--font-display); font-size: var(--t-xl); font-weight: 400; }
.cart-scroll { padding: var(--s-3) var(--s-4) 164px; }
.cart-layout { width: 100%; max-width: 1100px; margin: 0 auto; }
.cart-context {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4);
  margin-bottom: var(--s-3); padding: 0 0 var(--s-3); border-bottom: 1px solid var(--line);
  color: var(--muted); font-size: var(--t-sm);
}
.cart-context strong { color: var(--dark); text-align: right; }
.cart-lines { display: flex; flex-direction: column; }
.order-item-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start; gap: var(--s-3); padding: var(--s-4) 0;
  border-bottom: 1px solid var(--line);
}
.order-item-media { overflow: hidden; border-radius: var(--r-md); }
.order-item-copy { min-width: 0; }
.order-item-title { display: flex; align-items: flex-start; flex-wrap: wrap; gap: var(--s-2); }
.order-item-title h3 {
  color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg); font-weight: 400; line-height: 1.1;
}
.order-item-meta, .order-item-mods {
  margin-top: var(--s-1); color: var(--muted2); font-size: var(--t-2xs); line-height: 1.4;
}
.order-item-mods { color: var(--accent-text); font-weight: 700; }
.order-item-actions { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-3); }
.cart-stepper > span, .cart-stepper > output { min-width: 34px; text-align: center; font-weight: 800; }
.order-item-edit, .order-item-remove { min-width: var(--tap); min-height: var(--tap); padding-inline: var(--s-2); font-size: var(--t-xs); }
/* At a quantity of one the decrement is a delete. Swapping glyphs by class
   keeps it patchable — updLine() toggles .is-last and nothing structural
   changes — and the separate Remove is hidden so there is one way to do it. */
.cart-stepper .stepper-trash { display: none; }
.cart-stepper.is-last .stepper-minus { display: none; }
.cart-stepper.is-last .stepper-trash { display: grid; place-items: center; }
.cart-stepper.is-last { border-color: var(--accent-line); }
.cart-stepper.is-last > button:first-child { color: var(--accent-text); }
.cart-stepper.is-last ~ .order-item-remove { display: none; }
.order-item-price { color: var(--dark); font-size: var(--t-sm); font-variant-numeric: tabular-nums; white-space: nowrap; }
.order-item-qty { margin-top: var(--s-2); color: var(--muted); font-size: var(--t-xs); }
.cart-limit-note {
  margin-top: var(--s-3); padding: var(--s-3); border-left: 3px solid var(--accent);
  background: var(--accent-soft); color: var(--dark); font-size: var(--t-xs); font-weight: 700; line-height: 1.45;
}
.cart-add-more { width: 100%; margin-top: var(--s-4); }

.cart-upsell { margin-top: var(--s-8); padding-top: var(--s-5); border-top: 1px solid var(--line); }
.cart-upsell > header { display: grid; gap: var(--s-2); margin-bottom: var(--s-3); }
.cart-upsell h2 { color: var(--dark); font-family: var(--font-display); font-size: var(--t-xl); font-weight: 400; }
.cart-upsell > header > p { max-width: 54ch; color: var(--muted); font-size: var(--t-sm); line-height: 1.45; }
.upsell-list { display: flex; flex-direction: column; }
.upsell-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
  gap: var(--s-3); padding: var(--s-3) 0; border-bottom: 1px solid var(--line-soft);
}
.upsell-row-media { overflow: hidden; border-radius: var(--r-md); }
.upsell-row-copy { display: flex; min-width: 0; flex-direction: column; }
.upsell-row-copy strong { color: var(--dark); font-size: var(--t-sm); }
.upsell-row-copy span { margin-top: 2px; color: var(--muted); font-size: var(--t-xs); }
.upsell-count { display: none; color: var(--ok); font-size: var(--t-xs); font-weight: 800; }
.upsell-add { min-width: 72px; padding-inline: var(--s-3); }

.cart-summary {
  position: absolute; z-index: var(--z-bar); right: 0; bottom: 0; left: 0;
  padding: var(--s-3) var(--s-4) var(--safe-bottom);
  border-top: 1px solid var(--line); background: var(--card); box-shadow: var(--shadow-bar);
}
.cart-summary h2, .cart-summary > p, .summary-breakdown { display: none; }
.summary-breakdown > div, .summary-total {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4);
}
.summary-breakdown > div { padding: var(--s-2) 0; color: var(--muted); font-size: var(--t-sm); }
.summary-breakdown strong { color: var(--dark); text-align: right; }
.summary-total { margin-bottom: var(--s-2); color: var(--dark); }
.summary-total span { font-family: var(--font-display); font-size: var(--t-lg); }
.summary-total strong { font-family: var(--font-display); font-size: var(--t-xl); font-weight: 400; }
.cart-summary > p { color: var(--muted2); font-size: var(--t-2xs); }
.cart-checkout { margin-top: var(--s-2); }
.cart-checkout > strong::before { content: '→'; margin-right: var(--s-2); font-weight: 400; }
.cart-empty { max-width: 520px; margin: var(--s-8) auto; }
.cart-empty .btn { margin-top: var(--s-5); }

@media (min-width: 640px) {
  .upsell-row { grid-template-columns: auto minmax(0, 1fr) auto auto; }
  .upsell-count { display: inline; }
}
@media (min-width: 900px) {
  #app[data-screen="cart"] { --shell-max: 1160px; }
  .cart-scroll { padding: var(--s-6); }
  .cart-layout { display: grid; grid-template-columns: minmax(0, 1fr) 340px; align-items: start; gap: var(--s-10); }
  .cart-summary {
    position: sticky; top: var(--s-6); right: auto; bottom: auto; left: auto; z-index: auto;
    padding: var(--s-5); border: 1px solid var(--line); border-radius: var(--r-lg);
    background: var(--card); box-shadow: none;
  }
  .cart-summary h2 {
    display: block; padding-bottom: var(--s-3); border-bottom: 1px solid var(--line);
    color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg); font-weight: 400;
  }
  .summary-breakdown { display: block; padding: var(--s-2) 0; border-bottom: 1px solid var(--line); }
  .summary-total { margin: var(--s-3) 0 var(--s-1); }
  .cart-summary > p { display: block; }
  .cart-checkout { margin-top: var(--s-4); }
}

/* ══ PHASE 7: CHECKOUT + DELIVERY LOCATION ═══════════════════════════════ */
.checkout-header > div { display: flex; min-width: 0; flex-direction: column; }
.checkout-header > div > span {
  color: var(--muted2); font-size: var(--t-2xs); font-weight: 800;
  letter-spacing: .06em; text-transform: uppercase;
}
.checkout-header h1, .dloc-header h1 {
  color: var(--dark); font-family: var(--font-display); font-size: var(--t-xl); font-weight: 400;
}
.checkout-scroll { padding: var(--s-3) var(--s-4) var(--safe-bottom); }
.checkout-layout { width: 100%; max-width: 1120px; margin: 0 auto; }
.checkout-form { min-width: 0; }
.hp-field {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  opacity: 0; pointer-events: none;
}
.checkout-section { padding: var(--s-5) 0; border-bottom: 1px solid var(--line); }
.checkout-section:first-of-type { padding-top: 0; }
.checkout-section-heading { margin-bottom: var(--s-3); }
.checkout-section-heading h2, .slot-section > h2 {
  color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg); font-weight: 400;
}
.checkout-section-heading > p {
  margin-top: var(--s-1); color: var(--muted); font-size: var(--t-xs); line-height: 1.45;
}
.method-section .seg { margin-bottom: var(--s-3); }
.hoursline {
  display: flex; align-items: center; gap: var(--s-2); margin: 0;
  padding: var(--s-3) 0; border-top: 1px solid var(--line-soft);
}
.hoursline .btn { margin-left: auto; }
.pickup-panel {
  margin: var(--s-3) 0 0; padding: var(--s-3) 0 0;
  border: 0; border-top: 1px solid var(--line-soft); border-radius: 0; background: none;
}
.pickup-panel .btn { margin-top: var(--s-3); }
.account-context { color: var(--ok) !important; font-weight: 700; }
/* Only "Log in" is the control. The sentence around it is plain text, so the
   action is the one thing that reads as tappable rather than the whole line
   looking uniformly like a link — or uniformly like prose. */
.login-autofill {
  margin-top: var(--s-1);
  color: var(--muted); font-size: var(--t-sm); font-weight: 500; line-height: 1.6;
}
.login-autofill-link {
  padding: var(--s-2) 2px;
  border: none; background: none;
  color: var(--accent-text); font-family: var(--font-body);
  font-size: var(--t-sm); font-weight: 700;
  text-decoration: underline; text-underline-offset: 3px;
  cursor: pointer;
}
.checkout-note { min-height: 88px !important; resize: vertical; }
.field .inp { margin: 0; }
.notice {
  display: flex; flex-direction: column; gap: var(--s-1);
  margin-bottom: var(--s-3); padding: var(--s-3);
  border-left: 3px solid var(--line-strong); background: var(--card);
  color: var(--dark); font-size: var(--t-sm); line-height: 1.45;
}
.notice--error { border-left-color: var(--accent-text); background: var(--accent-soft); }
.notice--warning { border-left-color: var(--warn); background: var(--warn-soft); }
.notice--payment { border-left-color: var(--dark); background: var(--tray); }
.notice > span { color: var(--muted); font-size: var(--t-xs); }
.payment-notice { border-bottom: 0; }

/* The chosen-time summary that replaces the grid once a slot is picked. A full
   grid of times is only useful while choosing; afterwards it is the longest
   block on the page. */
.slot-chosen {
  display: flex; align-items: center; gap: var(--s-3);
  margin-top: var(--s-2); padding: var(--s-3);
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--card);
}
.slot-chosen-icon { display: grid; flex: 0 0 auto; place-items: center; color: var(--muted); }
.slot-chosen-copy { display: flex; min-width: 0; flex: 1; flex-direction: column; }
.slot-chosen-copy strong { color: var(--dark); font-size: var(--t-base); font-weight: 700; }
.slot-chosen-copy small { margin-top: 2px; color: var(--muted2); font-size: var(--t-xs); }
.slot-change { flex: 0 0 auto; min-height: var(--tap); padding-inline: var(--s-3); font-size: var(--t-xs); }
.slot-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-2); }
/* Delivery shows ranges ("19:30 – 20:30"), which do not fit three across on a
   phone — and an hourly grid has half as many slots to place anyway. */
.slot-grid--frames { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.slot-grid--frames .slot-choice { font-variant-numeric: tabular-nums; }
.slot-choice {
  display: flex; align-items: center; justify-content: center; flex-direction: column;
  min-height: 52px; padding: var(--s-2);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--card); color: var(--dark); cursor: pointer;
  font-family: var(--font-body); font-size: var(--t-sm); font-weight: 800;
}
.slot-choice.is-selected { border-color: var(--accent-text); background: var(--accent-soft); color: var(--accent-text); }
.slot-choice.is-hint { border-color: var(--accent-text); box-shadow: var(--shadow-focus); }
.slot-choice:disabled { background: var(--tray); color: var(--muted2); cursor: not-allowed; }
.slot-choice:disabled > span { text-decoration: line-through; }
.slot-choice small { margin-top: 2px; font-size: var(--t-2xs); font-weight: 700; }
.slot-help, .slot-loading { margin-top: var(--s-2); color: var(--muted2); font-size: var(--t-2xs); line-height: 1.4; }
.slot-empty {
  margin: 0; padding: var(--s-3); border: 0; border-left: 3px solid var(--accent);
  border-radius: 0; background: var(--accent-soft); color: var(--muted);
}
.slot-empty strong { color: var(--dark); }
.slot-empty p { margin-top: var(--s-1); }
.slot-empty .btn { margin-top: var(--s-3); }

.checkout-summary {
  margin-top: var(--s-5); padding: var(--s-4);
  border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--card);
}
.checkout-summary-details > summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  min-height: var(--tap); color: var(--dark); cursor: pointer;
  font-size: var(--t-base); font-weight: 800; list-style: none;
}
.checkout-summary-details > summary::-webkit-details-marker { display: none; }
.checkout-summary-details > summary::after {
  content: ''; flex: 0 0 auto; width: 8px; height: 8px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, 2px);
  transition: transform var(--dur-fast) ease;
}
.checkout-summary-details[open] > summary::after { transform: rotate(225deg) translate(-2px, 2px); }
.checkout-summary-details > summary > span {
  display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: var(--s-2);
}
.checkout-summary-details > summary small {
  color: var(--muted2); font-size: var(--t-2xs); font-weight: 700;
}
.checkout-summary-body {
  margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--line);
}
.checkout-summary-body > header {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  padding-bottom: var(--s-3); border-bottom: 1px solid var(--line);
}
.checkout-summary-body > header h2 {
  color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg); font-weight: 400;
}
.checkout-summary-items .order-item-row { grid-template-columns: auto minmax(0, 1fr) auto; padding: var(--s-3) 0; }
.checkout-summary-items .order-item-title h3 { font-family: var(--font-body); font-size: var(--t-sm); font-weight: 800; }
.checkout-summary-items .order-item-media > * { width: 44px !important; height: 44px !important; }
.checkout-totals { padding-top: var(--s-2); }
.checkout-totals > div { padding: var(--s-2) 0; color: var(--muted); font-size: var(--t-sm); }
.checkout-totals strong { color: var(--dark); text-align: right; }
.checkout-totals .checkout-total {
  margin-top: var(--s-1); padding-top: var(--s-3); border-top: 1px solid var(--line);
  color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg);
}
.checkout-totals .checkout-total strong { font-size: var(--t-xl); font-weight: 400; }
.checkout-place { margin-top: var(--s-4); }
.checkout-place > strong::before { content: '→'; margin-right: var(--s-2); font-weight: 400; }
.checkout-state-scroll { display: grid; place-items: center; padding: var(--s-8) var(--s-5); }
.checkout-state {
  display: flex; align-items: center; flex-direction: column; gap: var(--s-4);
  max-width: 440px; text-align: center;
}
.checkout-state h1 { color: var(--dark); font-family: var(--font-display); font-size: var(--t-xl); font-weight: 400; }
.checkout-state p { color: var(--muted); font-size: var(--t-sm); line-height: 1.55; }

.dloc-header { flex: 0 0 auto; border-bottom: 1px solid var(--line); background: var(--bg); }
.dloc-header .screen-header { min-height: 0; border-bottom: 0; }
.dloc-header .screen-header h1 { flex: 1; }
.dloc-header .screen-header > .btn { min-height: var(--tap); }
.dloc-header .dlsteps { max-width: 760px; margin: 0 auto; padding: 0 var(--s-3) var(--s-3); }
.dloc-scroll { padding: var(--s-4) var(--s-4) 120px; }
.dloc-panel { width: 100%; max-width: 720px; margin: 0 auto; }
.dloc-step-heading { margin-bottom: var(--s-5); }
.dloc-step-heading h2 {
  margin-top: var(--s-1); color: var(--dark); font-family: var(--font-display);
  font-size: var(--t-xl); font-weight: 400; line-height: 1.1;
}
.dloc-step-heading > p:last-child { margin-top: var(--s-2); color: var(--muted); font-size: var(--t-sm); line-height: 1.5; }
.dloc-panel > .field-label { display: block; margin-bottom: var(--s-2); }
.dloc-panel > .inp { margin-bottom: var(--s-3); }
.dl-error { color: var(--accent-text); font-weight: 700; }
.dl-not-listed { margin-top: var(--s-5); padding-top: var(--s-3); border-top: 1px solid var(--line); }
.dl-not-listed strong { display: block; color: var(--dark); }
.loclist { display: flex; flex-direction: column; border-top: 1px solid var(--line); }
.loccard {
  min-height: 64px; padding: var(--s-3) 0;
  border: 0; border-bottom: 1px solid var(--line); border-radius: 0; background: none;
}
.loccard--sel { border-bottom-color: var(--accent-text); background: var(--accent-soft); }
.loccard-go { color: var(--accent-text); font-size: var(--t-sm); }
.dl-map-wrap, .dl-mini-wrap { border-radius: var(--r-lg); }
.dl-map { border-radius: var(--r-lg); }
.dl-mapbtns > * { min-height: var(--tap); }
.dl-pin-help { text-align: center; }
.dl-fallback {
  display: flex; flex-direction: column; gap: var(--s-3);
  padding: var(--s-4); border-radius: var(--r-lg); background: var(--tray);
}
.dl-fallback strong { color: var(--dark); }
.dloc-footer {
  position: relative; z-index: var(--z-bar); flex: 0 0 auto;
  padding: var(--s-3) var(--s-4) var(--safe-bottom);
  border-top: 1px solid var(--line); background: var(--bg); box-shadow: var(--shadow-bar);
}
.dloc-footer .btn { max-width: 620px; margin: 0 auto; }
.mismatch-sheet h2 {
  color: var(--dark); font-family: var(--font-display); font-size: var(--t-xl); font-weight: 400; text-align: center;
}
.mismatch-sheet > p { margin: var(--s-2) 0 var(--s-4); color: var(--muted); font-size: var(--t-sm); line-height: 1.5; text-align: center; }
.sheet-actions { display: flex; flex-direction: column; gap: var(--s-2); }

.dl-card {
  margin: 0 0 var(--s-4); padding: var(--s-3) 0;
  border: 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  border-radius: 0; background: none;
}
.dl-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.dl-card-t { display: flex; align-items: center; gap: var(--s-2); }
.dl-card-sub { color: var(--muted); }

@media (min-width: 720px) {
  .slot-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .sheet { width: min(100% - 32px, 520px); margin: auto auto var(--s-6); border-radius: var(--r-xl); }
}
@media (min-width: 920px) {
  #app[data-screen="order"] { --shell-max: 900px; }
  #app[data-screen="checkout"] { --shell-max: 1180px; }
  #app[data-screen="dloc"] { --shell-max: 860px; }
  .checkout-scroll { padding: var(--s-6); }
  .checkout-layout { display: grid; grid-template-columns: minmax(0, 1fr) 360px; align-items: start; gap: var(--s-10); }
  .checkout-summary { position: sticky; top: var(--s-6); margin-top: 0; padding: var(--s-5); }
  .checkout-summary-details > summary { display: none; }
  .checkout-summary-details:not([open]) > .checkout-summary-body { display: block; }
  .checkout-summary-body { margin-top: 0; padding-top: 0; border-top: 0; }
  .dloc-scroll { padding: var(--s-6) var(--s-6) 120px; }
}

/* ══ PHASE 8: CONFIRMATION + ORDERS + ACCOUNT + INFO ═════════════════════ */
.status--pending { background: var(--warn-soft); color: var(--warn); }
.status--accepted, .status--preparing, .status--out_for_delivery { background: var(--tray); color: var(--dark); }
.status--ready { background: var(--ok-soft); color: var(--ok); }
.status--completed, .status--cancelled { background: var(--tray); color: var(--muted); }
.status--rejected { background: var(--accent-soft); color: var(--accent-text); }
.notice--success { border-left-color: var(--ok); background: var(--ok-soft); color: var(--ok); }

.confirm-scroll { padding: calc(var(--safe-top) + var(--s-5)) var(--s-4) 110px; }
.confirm-main { width: 100%; max-width: 980px; margin: 0 auto; }
.confirm-hero { max-width: 660px; margin: 0 auto var(--s-8); text-align: center; }
.confirm-mark {
  display: grid; place-items: center; width: 64px; height: 64px;
  margin: 0 auto var(--s-4); border-radius: 50%;
  background: var(--accent); color: var(--card);
}
.confirm-mark--muted { background: var(--disabled); }
.confirm-hero h1, .confirm-state h1 {
  margin-top: var(--s-1); color: var(--dark); font-family: var(--font-display);
  font-size: var(--t-2xl); font-weight: 400;
}
.confirm-promise {
  margin: var(--s-2) auto 0; max-width: 40ch;
  color: var(--dark); font-size: var(--t-md); font-weight: 800; line-height: 1.45;
}
.confirm-route { margin-top: var(--s-2); color: var(--muted); font-size: var(--t-sm); line-height: 1.45; }
.confirm-grid { display: grid; gap: var(--s-4); }
.tracking-card, .confirm-receipt {
  padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--card);
}
.tracking-card > header {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3);
  padding-bottom: var(--s-3); border-bottom: 1px solid var(--line);
}
.tracking-card h2, .confirm-receipt h2, .confirm-notice h2, .confirm-account h2 {
  margin-top: var(--s-1); color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg); font-weight: 400;
}
.tracking-announcement {
  margin: var(--s-3) 0; padding: var(--s-2) var(--s-3);
  border-left: 3px solid var(--accent); background: var(--accent-soft);
  color: var(--dark); font-size: var(--t-xs); font-weight: 700; line-height: 1.4;
}
.order-progress { display: flex; flex-direction: column; list-style: none; }
.order-progress li {
  display: flex; align-items: center; gap: var(--s-3); min-height: var(--tap);
  color: var(--muted2); font-size: var(--t-sm);
}
.order-progress li > span {
  display: grid; flex: 0 0 auto; place-items: center; width: 24px; height: 24px;
  border: 1.5px solid var(--line-strong); border-radius: 50%;
  color: var(--muted2); font-size: var(--t-2xs); font-weight: 900;
}
.order-progress li.is-done, .order-progress li.is-current { color: var(--dark); }
.order-progress li.is-done > span, .order-progress li.is-current > span {
  border-color: var(--accent-text); background: var(--accent); color: var(--card);
}
.confirm-receipt > header { padding-bottom: var(--s-3); border-bottom: 1px solid var(--line); }
.confirm-items .order-item-row { padding: var(--s-3) 0; }
.confirm-items .order-item-title h3 { font-family: var(--font-body); font-size: var(--t-sm); font-weight: 800; }
.confirm-items .order-item-media > * { width: 44px !important; height: 44px !important; }
.confirm-facts { padding-top: var(--s-2); }
.confirm-facts > div { color: var(--muted); font-size: var(--t-sm); }
.confirm-facts strong { color: var(--dark); text-align: right; }
.confirm-facts .confirm-total {
  margin-top: var(--s-1); padding-top: var(--s-3); border-top: 1px solid var(--line);
  color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg);
}
.confirm-facts .confirm-total strong { font-size: var(--t-xl); font-weight: 400; }
.confirm-paid { margin-top: var(--s-2); color: var(--muted); font-size: var(--t-xs); text-align: right; }
.confirm-support { display: grid; gap: var(--s-3); margin-top: var(--s-4); }
.confirm-notice {
  padding: var(--s-4) 0; border-top: 1px solid var(--line);
  color: var(--muted); font-size: var(--t-sm); line-height: 1.5;
}
.confirm-notice > p { margin: var(--s-1) 0 var(--s-3); }
.confirm-help-links { display: flex; flex-wrap: wrap; gap: var(--s-4); margin-top: var(--s-3); }
.confirm-help-links a {
  display: inline-flex; align-items: center; min-height: var(--tap);
  color: var(--accent-text); font-size: var(--t-xs); font-weight: 700;
}
.confirm-support .pickup-panel { border-top: 1px solid var(--line); }
.confirm-account {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: var(--s-4); margin-top: var(--s-4); padding: var(--s-4) 0; border-top: 1px solid var(--line);
}
.confirm-account p { margin-top: var(--s-1); color: var(--muted); font-size: var(--t-xs); line-height: 1.45; }
.confirm-saved { margin-top: var(--s-4); color: var(--ok); font-size: var(--t-xs); font-weight: 800; }
.confirm-footer {
  position: relative; z-index: var(--z-bar); flex: 0 0 auto;
  padding: var(--s-3) var(--s-4) var(--safe-bottom);
  border-top: 1px solid var(--line); background: var(--bg); box-shadow: var(--shadow-bar);
}
.confirm-home { width: 100%; max-width: 620px; margin: 0 auto; background: var(--dark); color: var(--card); }
.confirm-state {
  display: flex; align-items: center; flex-direction: column; justify-content: center;
  min-height: 65vh; max-width: 520px; margin: 0 auto; text-align: center;
}
.confirm-state > p { margin-top: var(--s-2); color: var(--muted); font-size: var(--t-sm); line-height: 1.5; }
.confirm-state a { color: var(--accent-text); font-weight: 800; }

.orders-header > div, .account-header > div, .info-header > div {
  display: flex; min-width: 0; flex-direction: column;
}
.orders-header > div > span, .account-header > div > span, .info-header > div > span {
  color: var(--muted2); font-size: var(--t-2xs); font-weight: 800;
  letter-spacing: .06em; text-transform: uppercase;
}
.orders-header h1, .account-header h1, .info-header h1 {
  color: var(--dark); font-family: var(--font-display); font-size: var(--t-xl); font-weight: 400;
}
.orders-scroll { padding: var(--s-3) var(--s-4) var(--safe-bottom); }
.orders-main { display: grid; gap: var(--s-3); width: 100%; max-width: 920px; margin: 0 auto; }
.order-history-card {
  padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--card);
}
.order-history-card > header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3); }
.order-history-card h2 { color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg); font-weight: 400; }
.order-history-card time { color: var(--muted2); font-size: var(--t-2xs); }
.order-history-note { margin-top: var(--s-2); color: var(--muted2); font-size: var(--t-xs); line-height: 1.4; }
.order-history-summary { margin-top: var(--s-3); color: var(--muted); font-size: var(--t-sm); line-height: 1.45; }
.order-history-card > footer {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: var(--s-3); margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--line);
}
.order-history-card > footer > strong { color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg); font-weight: 400; }
.order-history-actions { display: flex; align-items: center; gap: var(--s-2); }
.orders-empty { margin-top: var(--s-8); }
.orders-empty .btn { margin-top: var(--s-5); }
.orders-loading { display: grid; gap: var(--s-3); }
.skeleton-order { padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--card); }
.skeleton-order .skel:nth-child(1) { width: 38%; height: 16px; }
.skeleton-order .skel:nth-child(2) { width: 62%; height: 11px; margin-top: var(--s-2); }
.skeleton-order .skel:nth-child(3) { width: 30%; height: 14px; margin-top: var(--s-3); }

.account-scroll { padding: var(--s-3) var(--s-4) var(--safe-bottom); }
.account-main { width: 100%; max-width: 620px; margin: 0 auto; }
.auth-tabs { margin-bottom: var(--s-5); }
.auth-panel > h2, .profile-identity h2, .account-section-heading h2, .delete-confirm h2 {
  color: var(--dark); font-family: var(--font-display); font-size: var(--t-xl); font-weight: 400;
}
.auth-panel > p, .account-section-heading p, .delete-confirm > p {
  margin: var(--s-1) 0 var(--s-5); color: var(--muted); font-size: var(--t-sm); line-height: 1.5;
}
.auth-panel > .btn + .btn { margin-top: var(--s-2); }
.profile-identity { display: flex; align-items: center; gap: var(--s-3); padding-bottom: var(--s-5); border-bottom: 1px solid var(--line); }
.profile-avatar {
  display: grid; flex: 0 0 auto; place-items: center; width: 48px; height: 48px;
  border-radius: var(--r-full); background: var(--accent); color: var(--card); font-size: var(--t-xl); font-weight: 900;
}
.profile-identity > div:last-child { min-width: 0; }
.profile-identity p { overflow: hidden; color: var(--muted2); font-size: var(--t-xs); text-overflow: ellipsis; }
.profile-editor { padding: var(--s-5) 0; border-bottom: 1px solid var(--line); }
.profile-notice { margin-bottom: var(--s-3); color: var(--accent-text); font-size: var(--t-sm); font-weight: 800; }
.profile-notice.is-success { color: var(--ok); }
.account-links { display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-5) 0; border-bottom: 1px solid var(--line); }
.delete-zone { padding-top: var(--s-5); }
.delete-confirm { padding: var(--s-4); border-left: 3px solid var(--accent); background: var(--accent-soft); }
.delete-confirm > p { margin-bottom: var(--s-4); }
.delete-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--s-2); }

.info-scroll { padding: var(--s-3) var(--s-4) var(--safe-bottom); }
.info-main { width: 100%; max-width: 1040px; margin: 0 auto; }
.info-intro {
  display: flex; align-items: flex-start; justify-content: space-between; flex-wrap: wrap;
  gap: var(--s-5); padding: var(--s-6); background: var(--dark); color: var(--card);
}
.info-intro h2 {
  max-width: 18ch; margin-top: var(--s-2); font-family: var(--font-display);
  font-size: var(--t-2xl); font-weight: 400; line-height: 1.1;
}
.info-intro .eyebrow { color: var(--accent-on-dark); }
.info-status { display: flex; align-items: flex-end; flex-direction: column; gap: var(--s-2); text-align: right; }
.info-status p { max-width: 30ch; color: var(--on-dark-muted); font-size: var(--t-xs); line-height: 1.4; }
.info-grid { display: grid; gap: 0; margin-top: var(--s-6); }
.info-section { padding: var(--s-5) 0; border-bottom: 1px solid var(--line); }
.info-section > header { display: flex; align-items: center; gap: var(--s-2); }
.info-section h2 { color: var(--dark); font-family: var(--font-display); font-size: var(--t-lg); font-weight: 400; }
.info-section > p { margin-top: var(--s-3); color: var(--muted); font-size: var(--t-sm); line-height: 1.55; }
.info-section > .btn, .info-actions { margin-top: var(--s-4); }
.info-actions { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2); }
.delivery-area-rows, .hours-rows { margin-top: var(--s-2); }
.delivery-area-rows > div, .hours-rows > div { font-size: var(--t-sm); }
.hours-rows .is-today { margin-inline: calc(var(--s-2) * -1); padding-inline: var(--s-2); background: var(--tray); }
.hours-rows .is-today > span { font-weight: 800; }
.hours-rows .is-closed strong { color: var(--accent-text); }
.info-order { width: 100%; margin-top: var(--s-6); }

@media (min-width: 720px) {
  #app[data-screen="confirm"], #app[data-screen="myorders"], #app[data-screen="info"] { --shell-max: 1080px; }
  .confirm-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
  .confirm-support { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .orders-main, .orders-loading { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .info-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s-10); }
  .info-delivery, .info-hours { align-self: start; }
}

/* Global add-to-cart feedback lives outside #app, so a screen render cannot
   interrupt its announcement or presentation. */
.toast {
  position: fixed; z-index: var(--z-toast);
  /* --toast-lift is measured per screen in showToast() so the toast clears
     whatever bottom bar is pinned rather than landing on top of it. */
  right: var(--s-4); left: var(--s-4);
  bottom: calc(var(--safe-bottom) + var(--s-4) + var(--toast-lift, 0px));
  width: min(calc(100% - 32px), 420px); margin-inline: auto;
  padding: var(--s-3) var(--s-4); border-radius: var(--r-md);
  background: var(--dark); color: var(--card); box-shadow: var(--shadow-sheet);
  font-size: var(--t-sm); font-weight: 800; line-height: 1.4; text-align: center;
  opacity: 0; transform: translateY(12px); pointer-events: none;
  transition: opacity var(--dur) ease, transform var(--dur) var(--ease);
}
.toast.is-visible { opacity: 1; transform: none; }
