/* ============================================================================
   BISTRO — a warm, appetite-first restaurant design system.

   Translated from the "Restaurant UI/UX case study" wireframe: a slim hours
   bar above a centred-logo header, a full-bleed hero with paired CTAs, menu
   sections built from dish cards carrying a price token, a chef
   recommendation split, an event countdown, and a dark footer that repeats
   the nav, the hours and the two calls to action.

   The greyscale of the wireframe is interpreted as a warm palette: toasted
   paper, near-black olive ink, and a single olive-lime accent (the tint the
   wireframe used on the logotype). The merchant's accent_color is injected
   as --accent in the layout AFTER this file, so it always wins; everything
   tinted derives from it through color-mix and stays coherent.
   ========================================================================== */

:root {
  --font-display: "Poppins", "Segoe UI", system-ui, sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Neutrals — warm, toasted, never blue-grey. */
  --ink: #17190f;
  --ink-soft: #3f4234;
  --muted: #767869;
  --paper: #faf8f3;
  --surface: #ffffff;
  --surface-2: #f1efe7;
  --surface-3: #e8e5da;
  --line: #e3dfd2;
  --line-2: #d3cebd;

  /* Dark block used by the footer and the hours bar. */
  --dark: #23261c;
  --dark-2: #2e3125;
  --on-dark: #f3f1e9;
  --on-dark-muted: #a9ab9c;

  --accent: #6f8323;            /* fallback; overridden inline by settings.accent_color */
  --accent-contrast: #ffffff;
  --danger: #b23b2e;
  --success: #2c7a4b;

  --radius-sm: 8px;
  --radius: 14px;
  --radius-lg: 22px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(23, 25, 15, 0.05), 0 1px 3px rgba(23, 25, 15, 0.04);
  --shadow: 0 8px 24px -10px rgba(23, 25, 15, 0.18), 0 2px 6px -2px rgba(23, 25, 15, 0.07);
  --shadow-lg: 0 30px 60px -28px rgba(23, 25, 15, 0.32), 0 10px 22px -14px rgba(23, 25, 15, 0.14);
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 32%, transparent);

  /* The product page's hero photograph — "The Pass". Kept out of the shared
   * palette: --accent is merchant-set, so nothing that carries the page's
   * identity here leans on a hue. The photograph supplies the only saturated
   * colour; these two only supply the light and the lift. */
  --scrim-warm: linear-gradient(180deg, rgba(23, 25, 15, 0) 45%, rgba(23, 25, 15, 0.5) 82%, rgba(23, 25, 15, 0.82) 100%);
  --lift-1: 0 26px 50px -24px rgba(23, 25, 15, 0.3), 0 8px 20px -10px rgba(23, 25, 15, 0.14);

  --gutter: clamp(1.1rem, 4vw, 3rem);
  --maxw: 76rem;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);

  font-family: var(--font-body);
  color: var(--ink);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

* { box-sizing: border-box; }
/* The `hidden` attribute must win.
 *
 * A UA stylesheet's `[hidden] { display: none }` is a single attribute
 * selector, so any class rule setting `display` out-specifies it — and every
 * flex or grid component in this file does exactly that. The delivery panel's
 * footer stayed on screen through the step it was hidden for, and the DOM
 * reported `hidden === true` the whole time, which is the sort of thing that
 * costs an afternoon. */
[hidden] { display: none !important; }
/* The clip has to be on `html`, not only on `body`.
 *
 * `body { overflow-x: hidden }` alone is the classic half-fix: desktop
 * browsers clip and look correct, while iOS Safari still lets the document
 * pan sideways. Overflow set on `html` propagates to the viewport, which is
 * what actually stops the pan — and because it propagates rather than making
 * a new scroll container, `position: sticky` on the header and the menu rail
 * keeps working.
 *
 * `clip` is declared second so it wins where supported: unlike `hidden` it
 * cannot become a scroll container at all. Safari below 16 drops the line it
 * does not understand and keeps `hidden`. */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  overflow-x: hidden;
  overflow-x: clip;
  /* Keep focus out from under whatever is stuck to the edges.
   *
   * Tabbing scrolls the focused control just into view — and "just into view"
   * means underneath the sticky header, or behind the order bar pinned to the
   * bottom of a phone. The person tabbing then cannot see what they are about
   * to activate. `--stuck-top` is measured by the script for the header; the
   * bottom allowance is the tallest fixed bar this theme puts there. */
  scroll-padding-top: calc(var(--stuck-top, 0px) + 1rem);
  scroll-padding-bottom: 6rem;
}
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-size: 16px;
  overflow-x: hidden;
  overflow-x: clip;
}
img, svg, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
a:hover { color: var(--accent); }
::selection { background: color-mix(in srgb, var(--accent) 24%, transparent); }
:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--radius-sm); }
hr { border: 0; border-top: 1px solid var(--line); margin: 1.5rem 0; }

/* ---- Type ---------------------------------------------------------------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.15;
  color: var(--ink);
  margin: 0 0 0.6rem;
}
h1 { font-size: clamp(2rem, 4.4vw, 3rem); }
h2 { font-size: clamp(1.5rem, 3vw, 2.1rem); }
h3 { font-size: 1.15rem; }
p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }
.muted { color: var(--muted); }
.lede { color: var(--ink-soft); font-size: 1.02rem; max-width: 34rem; }
.eyebrow {
  font-family: var(--font-display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 0.55rem;
}
.price { font-family: var(--font-display); font-weight: 600; }

/* ---- Layout -------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gutter);
}
main.container { padding-top: 0; padding-bottom: 0; }
.section { padding: clamp(2.75rem, 6vw, 4.75rem) 0; }
.section--tint { background: var(--surface-2); }
.section--flush { padding-top: 0; }
.section__head { margin-bottom: clamp(1.5rem, 3vw, 2.25rem); }
.section__head--center { text-align: center; }
.section__head--between {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.25rem;
  flex-wrap: wrap;
}
.section__title { margin: 0; }

/* ---- Buttons ------------------------------------------------------------- */
.btn {
  --btn-bg: var(--surface-3);
  --btn-fg: var(--ink);
  --btn-bd: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.85rem 1.6rem;
  border: 1px solid var(--btn-bd);
  border-radius: var(--radius-sm);
  background: var(--btn-bg);
  color: var(--btn-fg);
  cursor: pointer;
  transition: transform 0.16s var(--ease), background-color 0.16s var(--ease), color 0.16s var(--ease), box-shadow 0.16s var(--ease);
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); color: var(--btn-fg); }
.btn:active { transform: translateY(0); }
.btn[disabled], .btn--disabled { opacity: 0.5; pointer-events: none; }
.btn--primary { --btn-bg: var(--accent); --btn-fg: var(--accent-contrast); }
.btn--primary:hover { --btn-bg: color-mix(in srgb, var(--accent) 86%, #000); }
.btn--dark { --btn-bg: var(--dark); --btn-fg: var(--on-dark); }
.btn--ghost { --btn-bg: transparent; --btn-fg: var(--ink); --btn-bd: var(--line-2); }
.btn--ghost:hover { --btn-bg: var(--surface); }
.btn--light { --btn-bg: var(--on-dark); --btn-fg: var(--dark); }
.btn--sm { padding: 0.55rem 1.05rem; font-size: 0.85rem; }
.btn--block { width: 100%; }
.btn--lg { padding: 1rem 2.1rem; font-size: 1.02rem; }

/* ---- Forms --------------------------------------------------------------- */
.field { display: block; margin-bottom: 1rem; }
.field__label {
  display: block;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink-soft);
  margin-bottom: 0.35rem;
}
.field__label .req { color: var(--danger); }
.field__hint { font-size: 0.8rem; color: var(--muted); margin: 0.3rem 0 0; }
.input, .select, .textarea {
  width: 100%;
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.75rem;
  transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease);
}
.textarea { min-height: 7rem; resize: vertical; }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1rem; }
@media (max-width: 34rem) { .form-grid { grid-template-columns: 1fr; } }

.search-field { position: relative; max-width: 20rem; width: 100%; }
/* Logical, like the icon's inset: in RTL the icon sits on the right, and a
 * physical padding-left left the text running under it. */
.search-field .input { padding-inline-start: 2.35rem; border-radius: var(--radius-pill); }
.search-field__icon {
  position: absolute;
  inset-inline-start: 0.85rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  pointer-events: none;
}

/* Radio cards — delivery type / payment on the cart. */
.radio-list { display: flex; flex-direction: column; gap: 0.6rem; margin: 0 0 1.75rem; padding: 0; list-style: none; }
.radio-row {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.95rem;
  cursor: pointer;
  padding: 0.35rem 0;
}
.radio-row input { accent-color: var(--accent); width: 1.15rem; height: 1.15rem; cursor: pointer; }
.radio-row--card {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: 0.7rem 0.9rem;
}
.radio-row--card:hover { border-color: var(--line-2); }

/* ---- Flash modal (layout/theme.liquid, theme.js "Flash modal") -----------
 * Same shell as the other dialogs (.delivery-modal); only the mark's colour
 * says which of the three kinds it is. Narrower than a picker sheet — it is
 * one line or two of text, not a list to scroll. */
.flash-modal { max-width: 26rem; }
.flash-modal .delivery-modal__body { padding-top: 0.25rem; }
.flash-modal .delivery-modal__body p { margin: 0; font-size: 0.95rem; line-height: 1.5; }
.flash-modal--error .delivery-modal__mark { background: #8f2c21; }
.flash-modal--error .delivery-modal__title { color: #8f2c21; }
.flash-modal--success .delivery-modal__mark { background: #1f5c39; }
.flash-modal--success .delivery-modal__title { color: #1f5c39; }
.flash-modal--info .delivery-modal__mark,
.flash-modal:not(.flash-modal--error):not(.flash-modal--success) .delivery-modal__mark { background: var(--accent); }

/* ---- Top bar ------------------------------------------------------------- */
.topbar {
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
}
.topbar__inner {
  display: flex;
  align-items: center;
  /* Service tabs at the start edge, switchers and account/order at the end. */
  justify-content: space-between;
  gap: 1rem;
  min-height: 2.75rem;
  padding-block: 0.35rem;
}
/* ---- Sub-bar (opening hours, under the header) --------------------------- */
.subbar {
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
}
.subbar__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 2.25rem;
  padding-block: 0.35rem;
}
.subbar__hours {
  /* It is a <p>, so the global `p { margin: 0 0 1rem }` applies, and flex
   * centres the MARGIN box rather than the text — that margin pushed the line
   * off-centre and inflated the bar well past its min-height. */
  margin: 0;
  text-align: center;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--ink-soft);
}
.subbar__hours .sep { color: var(--line-2); margin: 0 0.5rem; }
.topbar__links { display: flex; align-items: center; gap: 1.25rem; }
/* Icon beside the label, not stacked above it.
 *
 * Stacked, these two were the only things in the bar with a second line, so
 * they set the topbar's height on their own and sat oddly against the pill
 * switchers beside them. In a row the bar is one line throughout.
 *
 * 0.78rem matches `.switcher > summary` — at 0.66 the labels were sized to fit
 * under a 1.6rem icon, which is a constraint that no longer exists, and next
 * to the pills they read as a different tier of navigation. */
.topbar__link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: capitalize;
  color: var(--ink-soft);
  white-space: nowrap;
}
.topbar__icon {
  width: 1.6rem;
  height: 1.6rem;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  display: grid;
  place-items: center;
  color: var(--ink-soft);
  transition: background-color 0.16s var(--ease);
}
.topbar__link:hover .topbar__icon { background: color-mix(in srgb, var(--accent) 22%, var(--surface-3)); }
.topbar__count {
  position: absolute;
  transform: translate(0.65rem, -0.85rem);
  background: var(--accent);
  color: var(--accent-contrast);
  font-size: 0.6rem;
  line-height: 1;
  padding: 0.15rem 0.3rem;
  border-radius: var(--radius-pill);
}
@media (max-width: 48rem) {
  /* On its own row the second line now has the width to survive, so only the
   * type size comes down — it no longer competes with the switchers. */
  .subbar { font-size: 0.68rem; }
  .subbar__inner { min-height: 2rem; }

  /* Icons only on a phone. Beside rather than beneath, each label roughly
   * doubles its link's width, and the bar still has the hours and three
   * switcher pills to fit.
   *
   * Clipped, not `display: none`: the label is the link's accessible name —
   * the icon is a bare SVG with nothing else to read — so hiding it outright
   * would leave a screen reader announcing "link" and the destination URL. */
  .topbar__link > span:not(.topbar__icon) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .topbar__links { gap: 0.75rem; }
}

/* Very small screens — 320px and the 4.7" phones still in use.
 *
 * At 320px the utility row asked for more than the bar had: the service tabs
 * (148px) plus two switchers and two links with 12px gaps came to roughly
 * 300px inside a 285px content box, and `flex-wrap: nowrap` turned the
 * shortfall into ~5px of overflow. It never showed as a page scrollbar —
 * `html` and `body` carry `overflow-x: clip` — but the trailing control was
 * clipped, and in any context where that clip does not apply it is a scroll.
 *
 * Tighter gaps first; wrapping only if that is still not enough, which costs a
 * line of header height rather than a control. */
@media (max-width: 22.5rem) {
  .topbar__inner {
    flex-wrap: wrap;
    column-gap: 0.5rem;
    row-gap: 0.35rem;
  }
  .topbar__links { gap: 0.5rem; }
}

/* ---- Header -------------------------------------------------------------- */
.site-header { background: var(--surface); border-bottom: 1px solid var(--line); }
/* On by default, switchable from Preferences → Header.
 *
 * Only this element is pinned, and that is the point: the service row above it
 * and the hours strip below it are not inside it, so they scroll away and what
 * stays is one bar — the nav and the cart — rather than the three tiers the
 * header draws at the top of the page. That is what makes it affordable on a
 * short screen.
 *
 * `html` and `body` carry `overflow-x: clip` rather than `hidden` precisely so
 * this keeps working: `hidden` would make them scroll containers and a sticky
 * child of a scroll container it fills has nothing to stick to. */
.site-header--sticky { position: sticky; top: 0; z-index: 50; }

/* Sticky needs a containing block taller than itself, and the header does not
 * have one by default: the renderer wraps every section in a div of its own,
 * and that wrapper is exactly as tall as the header, the service row and the
 * hours strip together. A sticky element cannot leave its parent's box, so it
 * reached the top of the wrapper — which is where it already was — and then
 * scrolled away with it. The setting was on and nothing happened, which is
 * what it looked like.
 *
 * `display: contents` removes the wrapper's box without removing the element:
 * the three bars become children of `<body>` for layout, so the header sticks
 * against the page. The wrapper stays in the DOM, so the editor still finds
 * the section by walking up from a click.
 *
 * Matched by shape rather than by the wrapper's generated id — the theme does
 * not spell out the renderer's naming — and only when the merchant has asked
 * for a sticky header. */
body > div:has(> .site-header--sticky) { display: contents; }
/* The dialogs live in the top layer, above any z-index, so a sticky header
 * cannot cover them — nothing to guard against there. */
.site-header__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1.5rem;
  min-height: 5.25rem;
}
/* The lead grid cell: menu toggle and primary nav. */
.header__lead { display: flex; align-items: center; gap: clamp(0.75rem, 2vw, 1.75rem); min-width: 0; }

/* ---- Delivery location panel --------------------------------------------- */
.delivery-modal {
  width: min(34rem, calc(100vw - 2rem));
  max-height: calc(100dvh - 3rem);
  padding: 0;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.delivery-modal::backdrop { background: rgba(23, 25, 15, 0.55); }
/* The form is the scroll container, not the dialog, so the head and foot stay
 * put while a long map + fields area scrolls between them. */
.delivery-modal__form { display: flex; flex-direction: column; max-height: inherit; }
.delivery-modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 1.25rem;
  border-bottom: 1px solid var(--line);
}
.delivery-modal__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: 0 0 auto;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-contrast);
}
.delivery-modal__heads { display: flex; flex-direction: column; gap: 0.1rem; margin-inline-end: auto; }
.delivery-modal__title { font-family: var(--font-display); font-size: 1.05rem; color: var(--accent); }
.delivery-modal__sub { font-size: 0.85rem; color: var(--ink-soft); }

/* Search sits between the head and the list, on the tinted band, so it reads
 * as a filter over what is below rather than another field in the form. */
.delivery-modal__search {
  max-width: none;
  padding: 0.9rem 1.25rem;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
}
.delivery-modal__search .search-field__icon { inset-inline-start: 1.9rem; }
.delivery-modal__empty { margin: 1rem 0 0; text-align: center; color: var(--muted); font-size: 0.9rem; }

/* ---- Delivery areas ------------------------------------------------------ */
.delivery-modal__legend {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 0.75rem;
  font-family: var(--font-display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.area-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.area {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  padding: 0.75rem 0.9rem;
  text-align: start;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease);
}
.area:hover { border-color: var(--accent); box-shadow: var(--shadow-sm); }
.area__pin {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  flex: 0 0 auto;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--ink-soft);
}
.area__body { display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; margin-inline-end: auto; }
.area__name { font-family: var(--font-display); font-weight: 600; color: var(--accent); }
.area__meta { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.area__chip {
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.2rem 0.5rem;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--ink-soft);
}
/* The fee is the number that decides whether they order, so it is the one
 * thing in the row that is not the same grey as everything else. */
.area__addr { font-size: 0.8rem; color: var(--muted); }
.area__state { flex: 0 0 auto; }
.area.is-current { border-color: var(--accent); }
.badge {
  display: inline-block;
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-pill);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* Open/closed is the one thing in the row that must survive a colour-blind
 * reader, so the words carry it and the tint only reinforces. */
.badge--open   { background: color-mix(in srgb, var(--success) 14%, var(--surface)); color: var(--success); }
.badge--closed { background: color-mix(in srgb, var(--danger) 12%, var(--surface));  color: var(--danger); }
.badge--busy   { background: color-mix(in srgb, var(--accent) 14%, var(--surface));  color: var(--accent); }

.area__chip--fee {
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  color: var(--accent);
}
.delivery-modal__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink-soft);
  cursor: pointer;
}
.delivery-modal__close:hover { border-color: var(--line-2); color: var(--ink); }
.delivery-modal__body { padding: 1.25rem; overflow-y: auto; }
.delivery-modal__body .location-picker { margin-bottom: 0; }
.delivery-modal__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1rem 1.25rem;
  border-top: 1px solid var(--line);
  background: var(--surface-2);
}
.delivery-modal__back { padding: 0.6rem 1rem; font-size: 0.85rem; }
.delivery-modal__branch {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}
@media (max-width: 34rem) {
  /* Full-height sheet on a phone: the map needs the room, and a small centred
   * card leaves it too short to aim a pin in. */
  .delivery-modal { width: 100vw; max-width: 100vw; max-height: 100dvh; border-radius: 0; }
  .delivery-modal__confirm { width: 100%; }
}

/* ---- Service tabs -------------------------------------------------------- */
.service-tabs { display: flex; align-items: center; gap: 0.4rem; }
.service-tabs__form { margin: 0; }
.service-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.85rem;
  font-family: var(--font-display);
  font-size: 0.85rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: border-color 0.16s var(--ease), color 0.16s var(--ease), background-color 0.16s var(--ease);
}
.service-tab:hover { border-color: var(--line-2); color: var(--ink); }
/* Sized to sit level with the switcher pills sharing this row. */
.topbar .service-tab { padding: 0.3rem 0.75rem; font-size: 0.8rem; }
/* The active tab is carried by colour AND weight of border, not colour alone —
 * on a warm neutral palette a tint shift on its own is easy to miss. */
.service-tab.is-active {
  color: var(--accent);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}
.service-tabs__branch {
  font-size: 0.78rem;
  color: var(--muted);
  white-space: nowrap;
}
.service-tabs__dinein {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--accent);
}

.nav { display: flex; align-items: center; gap: clamp(1rem, 2.6vw, 2.1rem); }
.nav--end { justify-content: flex-end; }
.nav__link {
  font-family: var(--font-display);
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--ink);
  position: relative;
  padding: 0.3rem 0;
  white-space: nowrap;
}
.nav__link::after {
  content: "";
  position: absolute;
  /* Logical sides, so in RTL the rule grows from the right as the text reads. */
  inset-inline-start: 0;
  inset-inline-end: 100%;
  bottom: 0;
  height: 2px;
  background: var(--accent);
  transition: inset-inline-end 0.22s var(--ease);
}
.nav__link:hover::after, .nav__link[aria-current]::after { inset-inline-end: 0; }
.brand { display: inline-flex; align-items: center; justify-content: center; }
.brand__img { max-height: 4rem; width: auto; }
.brand__text {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: -0.02em;
  text-align: center;
  line-height: 1.15;
}
.brand__text em { font-style: normal; color: var(--accent); }
.nav-toggle {
  display: none;
  border: 1px solid var(--line-2);
  background: var(--surface);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.6rem;
  cursor: pointer;
}
.nav-toggle span {
  display: block;
  width: 1.15rem;
  height: 2px;
  background: var(--ink);
  border-radius: 2px;
}
.nav-toggle span + span { margin-top: 4px; }
/* ---- Mobile nav drawer --------------------------------------------------- */
/* Slides in from the inline start over a backdrop. `translateX` rather than
 * `inset-inline-start`, so the animation runs on the compositor and does not
 * relayout the page on every frame. */
.mobile-nav {
  position: fixed;
  inset-block: 0;
  inset-inline-start: 0;
  z-index: 70;
  width: min(80vw, 20rem);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  transform: translateX(-100%);
  transition: transform 0.24s var(--ease);
  overflow-y: auto;
  /* Notches and the home indicator. */
  padding-bottom: env(safe-area-inset-bottom);
}
[dir="rtl"] .mobile-nav { transform: translateX(100%); }
.mobile-nav[data-open] { transform: none; }

.mobile-nav__backdrop {
  position: fixed;
  inset: 0;
  z-index: 65;
  background: rgba(23, 25, 15, 0.5);
  opacity: 0;
  transition: opacity 0.24s var(--ease);
}
.mobile-nav__backdrop[data-open] { opacity: 1; }

.mobile-nav__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem var(--gutter);
  border-bottom: 1px solid var(--line);
}
.mobile-nav__title {
  font-family: var(--font-display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.mobile-nav__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink-soft);
  cursor: pointer;
}
.mobile-nav ul { list-style: none; margin: 0; padding: 0.5rem 0 1rem; }
.mobile-nav a {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--line);
}
/* One item per line.
 *
 * `nav-links` is the header's markup reused, and there `.nav__item` is
 * `inline-flex` so the links sit in a row — that rule is both later in this
 * file and no less specific than `.mobile-nav a`, so it won and the drawer
 * read "Menu Search" / "Reservation Order Track" on two crowded lines. These
 * are scoped to the drawer so the header keeps its row. */
.mobile-nav ul > li { display: block; }
.mobile-nav .nav__item,
.mobile-nav .nav__item > .nav__link { display: block; }
.mobile-nav .nav__link {
  padding: 0.8rem 0;
  border-bottom: 1px solid var(--line);
}
/* The sliding underline is a pointer affordance for a horizontal bar; in a
 * stacked list it just draws a second line under every row. */
.mobile-nav .nav__link::after { display: none; }
/* Submenus expand in place — there is no room to fly one out, and hover is
 * not a gesture a phone has. */
.mobile-nav .nav__submenu {
  position: static;
  display: block;
  min-width: 0;
  padding: 0 0 0 0.9rem;
  border: 0;
  box-shadow: none;
  background: none;
}
.mobile-nav .nav__submenu a { font-weight: 500; }

.mobile-nav__extra { padding-bottom: 1.5rem; }
.mobile-nav__link { display: flex; align-items: center; gap: 0.6rem; }
.mobile-nav__branch {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.9rem 0 0;
  font-size: 0.85rem;
  color: var(--muted);
}

/* The drawer is a phone pattern; above the breakpoint the nav is in the
 * header and the button that opens this is hidden. */
@media (min-width: 60.01rem) {
  .mobile-nav, .mobile-nav__backdrop { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .mobile-nav, .mobile-nav__backdrop { transition: none; }
}
@media (max-width: 60rem) {
  /* Kept as `1fr auto 1fr`, not `auto 1fr auto`.
   *
   * The trailing nav is hidden at this width, so the third column has no
   * child. With `auto 1fr auto` the wordmark landed in the middle column —
   * which is then everything to the right of the menu button — and centred
   * itself inside that, sitting half a button's width off true centre. Two
   * equal `1fr` flanks put it in the middle of the PAGE whether or not the
   * third column has anything in it. */
  .site-header__inner { grid-template-columns: 1fr auto 1fr; min-height: 4.25rem; }
  .site-header .nav { display: none; }
  /* The branch name goes first — it is context rather than control, and this
   * row has the tabs, two switchers and two links to fit. */
  .service-tabs__branch { display: none; }
  .topbar .service-tab { padding: 0.3rem 0.6rem; font-size: 0.75rem; }

  /* The bar scrolls sideways rather than pushing the page wide.
   *
   * Its contents are not fixed: two service tabs, a language switcher, a
   * currency switcher, account and order — and each of those appears only
   * when the tenant has something to put in it. A storefront with two
   * languages AND two currencies has noticeably more here than one with
   * neither, and at some combination it will not fit any phone. Letting the
   * row scroll inside itself means the widest case degrades to a swipe
   * instead of dragging the whole page sideways.
   *
   * `min-width: 0` on the children is what actually allows it: a flex item
   * defaults to `min-width: auto` and refuses to shrink below its content,
   * which is how a row like this pushes its parent wide in the first place. */
  .topbar__inner { gap: 0.5rem; }
  /* `min-width: 0` so a flex item may shrink below its content. The default is
   * `auto`, which refuses to — and that is how a row like this drags the page
   * wider than the screen. */
  .topbar__inner > * { min-width: 0; }

  /* Switchers collapse to their icon.
   *
   * `div.topbar__links` measured 185px on a 375px screen — two service tabs,
   * a language pill, a currency pill and two links do not fit beside each
   * other, and the row pushed the page sideways. The words are the cheapest
   * thing to drop: the globe and the coin are understood, the summary already
   * carries `aria-label="Change language"` / `"Change currency"`, and the
   * chosen value is still in the menu the pill opens.
   *
   * Clipped rather than `display: none` so the label stays the control's
   * accessible name. */
  .topbar .switcher > summary > span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  /* Nothing left for the caret to sit beside. */
  .topbar .switcher > summary .icon--caret { display: none; }
  .topbar .switcher > summary { padding: 0.35rem 0.5rem; gap: 0; }

  /* Anchored to the right edge of a pill that may itself be near the window
   * edge, so cap it to the screen rather than a fixed 11rem. */
  .popover { min-width: 0; width: max-content; max-width: min(80vw, 14rem); }
  .header__lead { gap: 0.5rem; }
  .nav-toggle { display: block; }
  .brand { justify-content: flex-start; }
  /* Placed explicitly: with the third column empty the wordmark would
   * otherwise flow into the gap the missing nav left behind. */
  .site-header__inner .brand { grid-column: 2; justify-self: center; }
}

/* ---- Hero ---------------------------------------------------------------- */
.hero {
  position: relative;
  background: var(--surface-2);
  background-size: cover;
  background-position: center;
  min-height: clamp(26rem, 52vw, 40rem);
  display: grid;
  place-items: center;
  text-align: center;
  isolation: isolate;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgba(23, 25, 15, 0.06), rgba(23, 25, 15, 0.42));
}
.hero--plain::after { background: none; }

/* Video background.
 *
 * Sits behind the ::after scrim (z-index -1) rather than in front of it, so a
 * video hero gets the same darkening a photograph does and the white heading
 * stays readable over whatever frame happens to be showing.
 *
 * object-fit: cover matches how the still behaves as `background-size: cover`.
 * Without it a video whose aspect ratio differs from the section's letterboxes
 * against the surface colour. */
.hero__video {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The poster is the section's background image too, so a video that has not
   * started yet shows the still rather than a black rectangle. */
  background: transparent;
}

/* The still stays as the section's background-image underneath — it is the
 * poster and the fallback — so nothing needs hiding when the video plays. */

@media (prefers-reduced-motion: reduce) {
  /* theme.js does not autoplay under this preference, so the element only ever
   * shows its poster. Hidden anyway: a paused first frame and the background
   * image are the same picture, and one of them is cheaper. */
  .hero__video { display: none; }
}
.hero__inner { padding: clamp(3rem, 8vw, 6rem) 0; max-width: 46rem; }
.hero__title { font-size: clamp(2.1rem, 5vw, 3.4rem); margin-bottom: 1rem; }
.hero__title em { font-style: normal; color: var(--accent); }
.hero__sub { color: var(--ink-soft); font-size: 1.05rem; margin: 0 auto 2rem; max-width: 34rem; }
.hero__cta { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }
.hero--on-image .hero__title,
.hero--on-image .hero__sub { color: #fff; text-shadow: 0 2px 18px rgba(0, 0, 0, 0.35); }
.hero--on-image .hero__title em { color: color-mix(in srgb, var(--accent) 55%, #fff); }

/* ---- Category cards (home "View Our Menu") ------------------------------- */
.cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: clamp(1rem, 2.4vw, 1.75rem);
  align-items: end;
}
.cat-card {
  position: relative;
  display: block;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface-3);
  aspect-ratio: 3 / 4;
  box-shadow: var(--shadow-sm);
  transition: transform 0.24s var(--ease), box-shadow 0.24s var(--ease);
}
/* The wireframe staggers the cards; every other card sits lower. */
.cat-card:nth-child(even) { transform: translateY(1.75rem); }
.cat-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.cat-card:nth-child(even):hover { transform: translateY(1.15rem); }
/* The even-numbered cards sit 1.75rem lower, so the row's visual bottom edge
 * is below its layout box; without the extra margin the button crowds them. */
.cat-more { display: flex; justify-content: center; margin-top: 2.5rem; }
.cat-more__btn { margin-top: 1.75rem; }

.cat-card__img { width: 100%; height: 100%; object-fit: cover; }
.cat-card__ph { width: 100%; height: 100%; background: linear-gradient(160deg, var(--surface-3), var(--line-2)); }
.cat-card__title {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: 2.5rem 1.1rem 1.1rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  color: #fff;
  background: linear-gradient(180deg, transparent, rgba(23, 25, 15, 0.78));
}
@media (max-width: 48rem) {
  .cat-card:nth-child(even), .cat-card:nth-child(even):hover { transform: none; }

  /* Two up on a phone.
   *
   * The 13rem track minimum can only fit ONE column in a phone's ~20rem
   * content width, so each 3:4 card filled most of the screen and the section
   * read as a list of one — you had to scroll a viewport per category. The
   * square ratio roughly halves each card's height again.
   *
   * 8rem, not 9: at 320px the content box is 18rem, and two 9rem tracks plus
   * the 0.75rem gap need 18.75 — so the grid quietly fell back to one column
   * on the narrowest phones, which is the exact case this is fixing.
   *
   * Still `auto-fit` rather than a hard `repeat(2, …)`, so a large phone or a
   * small tablet gets three without needing another breakpoint. */
  .cat-grid {
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
    gap: 0.75rem;
  }
  .cat-card { aspect-ratio: 1 / 1; }
  .cat-card__title {
    padding: 1.6rem 0.7rem 0.65rem;
    font-size: 0.85rem;
    /* Long category names wrapped to three lines inside a card this size and
     * pushed the gradient over most of the photograph. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* The stagger is off above, so the row's visual bottom is its layout bottom
   * and the button no longer needs to clear an overhang. */
  .cat-more { margin-top: 1.5rem; }
  .cat-more__btn { margin-top: 0; }
}

/* ---- Menu section rail --------------------------------------------------- */
/* A horizontal strip of the menu's sections that sticks under the header while
 * the bands scroll past it, with the one you are reading marked. */
.menu-rail {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  border-top: 1px solid var(--line);
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
/* `top` is a variable because what sits above the rail changes: the sticky
 * header is opt-in from Preferences, so theme.liquid publishes its measured
 * height and this follows it rather than hard-coding a number that is wrong
 * for half the configurations. */
.menu-rail--sticky {
  position: sticky;
  top: var(--stuck-top, 0px);
  z-index: 20;
}
/* The bar is full-bleed; this keeps its contents on the page's own measure so
 * the first link lines up with the headings above and below it. */
.menu-rail__inner { padding-inline: var(--gutter); }
.menu-rail__list {
  display: flex;
  gap: clamp(0.75rem, 2vw, 1.75rem);
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  /* The rail is wider than a phone on any real menu, so it scrolls sideways —
   * and the scrollbar itself is noise on a nav this short. */
  scrollbar-width: none;
  -ms-overflow-style: none;
  scroll-snap-type: x proximity;
}
.menu-rail__list::-webkit-scrollbar { display: none; }
.menu-rail__link {
  display: block;
  padding: 0.85rem 0.15rem;
  white-space: nowrap;
  scroll-snap-align: center;
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink-soft);
  /* A transparent border at rest, so the active state does not change the
   * link's height and shunt the row by two pixels as it moves. */
  border-bottom: 2px solid transparent;
  transition: color 0.16s var(--ease), border-color 0.16s var(--ease);
}
.menu-rail__link:hover { color: var(--ink); }
.menu-rail__link.is-active { color: var(--accent); border-bottom-color: var(--accent); }

/* Anchors land under the sticky rail without the script's help — this is what
 * makes a no-JS jump land in the right place, and it is also what the smooth
 * scroll uses. */
.menu-section { scroll-margin-top: calc(var(--stuck-top, 0px) + 4rem); }

/* The search rides in the rail, above the section links, so it sticks with
 * them. In the page head (single-section menus) it keeps its old spacing. */
.section__head .search-field { margin: 1.5rem auto 0; }
.menu-rail__search { padding: 0.6rem var(--gutter) 0; }
.menu-rail__search .search-field { max-width: 32rem; margin-inline: auto; }
.menu-rail__search .input { min-height: 2.6rem; }
/* Folded to a button at the end of the tabs (theme.js, "Rail search"): the
 * field opens above the tabs on a tap and folds back when left empty. The
 * fold only exists once the script has set it up — with the script off the
 * field simply stays open. */
.menu-rail__inner { display: flex; align-items: center; gap: 0.5rem; }
.menu-rail__inner .menu-rail__list { flex: 1 1 auto; min-width: 0; }
.menu-rail__search-btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
}
.menu-rail__search-btn[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }
.menu-rail__search-btn .when-open { display: none; }
.menu-rail__search-btn[aria-expanded="true"] .when-open { display: inline-flex; }
.menu-rail__search-btn[aria-expanded="true"] .when-closed { display: none; }
.menu-rail.is-search-folded:not(.is-search-open) .menu-rail__search { display: none; }
.menu-rail.is-search-open .menu-rail__search { animation: rail-search-in 0.2s var(--ease, ease-out); }
@keyframes rail-search-in { from { opacity: 0; transform: translateY(-0.35rem); } }
@media (prefers-reduced-motion: reduce) { .menu-rail.is-search-open .menu-rail__search { animation: none; } }

/* The rail is taller by the search row; a jump with the script off still has
 * to land below all of it. */
body:has(.menu-rail__search) .menu-section { scroll-margin-top: calc(var(--stuck-top, 0px) + 7.5rem); }

/* ---- Menu layout + order panel ------------------------------------------- */
/* One column by default; the aside only becomes a column when there is room
 * for it beside the bands without squeezing them. Below that the fixed bottom
 * bar does the job instead, so the panel is hidden rather than stacked — two
 * carts on one screen is one too many. */
.menu-layout__aside { display: none; }

@media (min-width: 64rem) {
  .menu-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 20rem;
    gap: clamp(1.5rem, 3vw, 2.5rem);
    align-items: start;
  }
  .menu-layout__aside { display: block; }
  .order-card {
    position: sticky;
    /* Clears whatever is stuck above: the header (measured into --stuck-top by
     * theme.js) plus the section rail, plus a little air. */
    top: calc(var(--stuck-top, 0px) + 5.5rem);
    padding: 1.25rem;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--surface);
    box-shadow: var(--shadow-sm);
  }
}

/* The card while a quick add is round-tripping (theme.js, "The order card
 * while its line list is stale"): the existing lines and total stay exactly
 * as they were — reflowing them to grey bars, or dimming them hard, read as
 * the cart having emptied rather than as it being about to change. Only a
 * light sweep crosses them, so the wait reads as "updating" without ever
 * looking like the order was lost.
 *
 * `pointer-events` only — no `position` here. `.order-card` is already
 * `position: sticky` on desktop (below), which is a containing block for
 * the `::after` overlay same as `relative` would be; overriding it TO
 * `relative` won for specificity (two classes beat one) and silently
 * dropped the sticky behaviour for as long as this class was on, so the
 * card snapped back to its normal-flow position — off the top of a
 * scrolled page — and back again once the class came off. That looked
 * exactly like the card vanishing and reappearing, because it did. */
.order-card.is-loading { pointer-events: none; }
.order-card.is-loading::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(100deg,
    transparent 30%,
    color-mix(in srgb, var(--ink) 8%, transparent) 50%,
    transparent 70%);
  background-size: 200% 100%;
  animation: order-card-sweep 1.1s ease-in-out infinite;
}
@keyframes order-card-sweep {
  from { background-position: 150% 0; }
  to { background-position: -50% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .order-card.is-loading::after { animation: none; }
}

.order-card__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 1rem;
  color: var(--accent);
}
.order-card__title { margin: 0; font-size: 1.05rem; color: var(--accent); }
.order-card__empty { color: var(--muted); font-size: 0.9rem; }
.order-card__lines {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  display: grid;
  gap: 0.5rem;
  /* A long order scrolls inside the card rather than pushing the total and
   * the button off the bottom of a sticky panel, where they cannot be
   * reached. */
  max-height: 40vh;
  overflow-y: auto;
}
.order-line {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0.5rem;
  font-size: 0.88rem;
}
.order-line__qty { color: var(--muted); }
.order-line__title { min-width: 0; overflow-wrap: anywhere; }
.order-line__price { font-family: var(--font-display); font-weight: 600; }
.order-card__totals { margin: 0 0 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--line); }
.order-card__row { display: flex; justify-content: space-between; gap: 1rem; font-size: 0.9rem; }
.order-card__row dt { color: var(--ink-soft); }
.order-card__row dd { margin: 0; color: var(--ink); }
.order-card__row--total {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--line);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
}
.order-card__note { margin: 0 0 0.9rem; font-size: 0.78rem; color: var(--muted); }

/* ---- Mobile order bar ---------------------------------------------------- */
/* Hidden by default and shown only on phones — see the media query below. The
 * default is "not shown" so a desktop that never reads the query is right. */
.order-bar { display: none; }

/* 63.99rem, not 48rem — the same width the side panel appears at.
 *
 * They were 48rem and 64rem, which left a 768–1024px band with the bar
 * already gone and the panel not yet there: a tablet had no way to see the
 * order at all. The two must be complements, so this is written against the
 * panel's breakpoint rather than the phone one. */
@media (max-width: 63.99rem) {
  .order-bar {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    /* The home indicator on a modern phone sits over the bottom of the screen;
     * without this the total is under it. */
    padding: 0.75rem var(--gutter) calc(0.75rem + env(safe-area-inset-bottom));
    background: var(--accent);
    color: var(--accent-contrast);
    font-family: var(--font-display);
    font-weight: 700;
    box-shadow: 0 -6px 20px -12px rgba(23, 25, 15, 0.5);
  }
  .order-bar:hover { color: var(--accent-contrast); }
  .order-bar__badge {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    flex: 0 0 auto;
    border-radius: var(--radius-pill);
    background: rgba(255, 255, 255, 0.18);
  }
  .order-bar__count {
    position: absolute;
    top: -0.25rem;
    inset-inline-end: -0.25rem;
    min-width: 1.15rem;
    padding: 0 0.25rem;
    border-radius: var(--radius-pill);
    background: var(--surface);
    color: var(--accent);
    font-size: 0.7rem;
    line-height: 1.15rem;
    text-align: center;
  }
  .order-bar__total { font-size: 1.05rem; }
  .order-bar__go { margin-inline-start: auto; font-size: 0.9rem; opacity: 0.9; }

  /* The product page's bar, so the two read as the same object: floating,
   * rounded, the accent gradient, and the action as a pill on it. */
  .order-bar {
    inset-inline: 0.75rem;
    bottom: calc(0.75rem + env(safe-area-inset-bottom));
    padding: 0.55rem 0.55rem 0.55rem 0.75rem;
    border-radius: 16px;
    background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 82%, #fff) 0%, var(--accent) 100%);
    box-shadow: 0 12px 28px -10px color-mix(in srgb, var(--accent) 70%, transparent);
  }
  .order-bar__go {
    padding: 0.7rem 1rem;
    border-radius: 10px;
    background: rgb(255 255 255 / 22%);
    box-shadow: inset 0 0 0 1px rgb(255 255 255 / 28%);
    opacity: 1;
  }
  /* Nothing in the order yet: the primary at half strength, as the product
   * bar is before its choices are made. */
  .order-bar:has(.order-bar__count[hidden]) {
    background: color-mix(in srgb, var(--accent) 50%, var(--surface));
    box-shadow: none;
  }

  /* Room for the bar, so the last dish is not sitting underneath it. */
  #menu-bands { padding-bottom: 6.5rem; }
}

/* ---- Dish grid ----------------------------------------------------------- */
.menu-section + .menu-section { margin-top: clamp(2.5rem, 5vw, 4rem); }
.menu-section__title {
  text-align: center;
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
.dish-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem) clamp(1rem, 2.4vw, 2rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
/* One card, every width.
 *
 * The circular medallion was the theme's signature, but it only ever worked
 * at one size: it cropped a wide plate to a coin, hung the price off an edge
 * where a long money string had to escape the shape, and centred names that
 * then sat wider than their column. The phone already had a rectangular card
 * for those reasons — this is that card, used everywhere, so a dish looks the
 * same on a laptop as it does in a hand. Image, name, price, action, read in
 * that order.
 *
 * `--dish-pad` is the text inset, declared once because five children share
 * it and the phone wants a smaller one. The image is deliberately NOT inset:
 * it runs to the card's edges, and the card's `overflow: hidden` is what
 * rounds its top corners. */
.dish {
  --dish-pad: 0.9rem;
  display: flex;
  flex-direction: column;
  height: 100%;
  text-align: start;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  padding-bottom: 0.9rem;
  transition: transform 0.24s var(--ease), box-shadow 0.24s var(--ease);
}
/* The whole card lifts now, not the image inside it — a picture that moved
 * within a still frame read as a glitch rather than as a response. */
.dish:hover { transform: translateY(-3px); box-shadow: var(--shadow); }
/* Every card's picture is the same size, and nothing inside it gets a vote.
 *
 * `aspect-ratio` alone did not hold. This is a flex item, and a flex item's
 * automatic minimum size is its content's — so a portrait photo pushed the
 * box past the ratio and a broken image collapsed it below, which is exactly
 * the row of mismatched pictures this replaces. `min-height: 0` gives up that
 * automatic minimum and `flex: none` stops the box being stretched or
 * squeezed by its siblings.
 *
 * The image is then taken out of flow entirely: absolutely positioned to fill
 * the box, it cannot contribute any size at all. A broken one shows its alt
 * text inside the frame instead of resizing it, and `overflow: hidden` keeps
 * that text in the frame. */
.dish__media {
  position: relative;
  display: block;
  flex: none;
  width: 100%;
  aspect-ratio: 4 / 3;
  min-height: 0;
  overflow: hidden;
  background: linear-gradient(160deg, var(--surface-3), var(--line-2));
  margin-bottom: 0.75rem;
}
.dish__img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Sized by its content, never cropped — currency codes and three-decimal
   minor units (BHD, KWD, OMR) make this string much wider than a "$14". It
   sits inside the image's corner: on a square edge there is nothing to hang
   off, and a token half outside the card would be clipped by it. */
.dish__badge {
  position: absolute;
  inset-inline-end: 0.5rem;
  bottom: 0.5rem;
  max-width: calc(100% - 1rem);
  padding: 0.4rem 0.75rem;
  border-radius: var(--radius-pill);
  background: var(--dark);
  color: var(--on-dark);
  font-family: var(--font-display);
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  text-align: center;
  box-shadow: var(--shadow-sm);
}
/* Catalogue names nobody chose the length of: let them wrap anywhere rather
 * than push the card wider than its column. */
.dish__title,
.dish__desc {
  max-width: 100%;
  overflow-wrap: anywhere;
}
/* The text block. Carries the inset for both children, so the two of them
 * stay one thing to place. */
.dish__text { padding-inline: var(--dish-pad); }
.dish__title {
  font-size: 1.02rem;
  margin: 0 0 0.35rem;
}
.dish__desc {
  color: var(--muted);
  font-size: 0.86rem;
  margin: 0 0 0.6rem;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* `margin-top: auto` pins the action to the bottom, so cards in a row line
 * their buttons up however tall the names above them run. The padding is the
 * floor for a card that is the tallest in its row, where `auto` resolves to
 * nothing and the button would otherwise sit against the name. */
.dish__actions { margin-top: auto; padding-top: 0.45rem; padding-inline: var(--dish-pad); }
/* Sold out as a badge — a state of the dish, not a line of copy. Sized to its
 * words and pinned to the card's foot where the add button would be. */
.dish__sold {
  align-self: flex-start;
  width: fit-content;
  /* Its cell (.dish__actions) already insets it by --dish-pad; a margin on
   * top of that set it twice as far in as the title. */
  margin: 0;
  padding: 0.25rem 0.65rem;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--danger) 12%, var(--surface));
  color: var(--danger);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.3;
}
.dish__actions .btn { width: 100%; }

/* The offer ribbon, across the corner of the picture — PLUS marks a
 * discounted card this way, and a corner is the one part of a photograph that
 * is never the subject. Rotated through the media's own clipped box, so the
 * ends disappear off the card rather than needing to be mitred.
 *
 * Not a link and not a button: the whole card already goes to the product. */
.dish__ribbon {
  position: absolute;
  z-index: 1;
  top: 0.85rem;
  inset-inline-start: -2.2rem;
  width: 9rem;
  padding: 0.22rem 0;
  transform: rotate(-45deg);
  background: var(--danger);
  color: #fff;
  font-family: var(--font-display);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
  pointer-events: none;
}
/* The ribbon is drawn in the start corner, so in RTL it leans the other way
 * or it would read as a fold on the wrong edge. */
[dir="rtl"] .dish__ribbon { transform: rotate(45deg); }
/* Was-price: quieter than the price it precedes, and never the thing read
 * first — the token's job is still to say what this costs now. */
.dish__was {
  opacity: 0.7;
  font-weight: 500;
  margin-inline-end: 0.15rem;
}

/* In the list view the picture is a thumbnail, and a ribbon across it would
 * cover most of the food. A tag on the row instead. */
[data-view="list"] .dish__ribbon {
  top: 0.3rem;
  inset-inline-start: 0.3rem;
  width: auto;
  padding: 0.12rem 0.4rem;
  border-radius: var(--radius-sm);
  transform: none;
  font-size: 0.6rem;
}
[dir="rtl"] [data-view="list"] .dish__ribbon { transform: none; }

/* Phone: two per row. Same card, tighter, and the description gives way —
 * there is no room for it beside a sibling card, and "Read more" already
 * leads to it. */
@media (max-width: 48rem) {
  .dish-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.75rem;
  }
  .dish {
    --dish-pad: 0.6rem;
    padding-bottom: 0.7rem;
  }
  .dish:hover { transform: none; box-shadow: none; }
  .dish__media { margin-bottom: 0.6rem; }
  .dish__badge {
    inset-inline-end: 0.4rem;
    bottom: 0.4rem;
    max-width: calc(100% - 0.8rem);
    font-size: 0.78rem;
  }
  .dish__title {
    font-size: 0.9rem;
    /* Two lines, then ellipsis: uneven card heights are worse than a
     * truncated name, and the full name is on the product page. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
  }
  .dish__desc { display: none; }
}

/* ---- Product strips: frequently bought, recently viewed ------------------
 *
 * Native horizontal scrolling with snap points, not a scripted track. It
 * swipes, it takes a trackpad's sideways gesture, the scrollbar stays real for
 * anyone who navigates by it, and it works with the script switched off. The
 * arrows only add a click target for a mouse.
 */
.strip-section { padding-block: clamp(2rem, 5vw, 3rem); border-top: 1px solid var(--line); }
.strip__head {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.25rem;
}
.strip__title { margin: 0; flex: 1; font-size: clamp(1.2rem, 2.4vw, 1.6rem); }
.strip__nav { display: flex; gap: 0.4rem; }
.strip__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.15s var(--ease), opacity 0.15s var(--ease);
}
.strip__btn:hover { border-color: var(--line-2); }
/* Disabled rather than hidden at the ends: a control that disappears moves
 * the one beside it, and the row's edges are exactly when someone is
 * clicking repeatedly. */
.strip__btn[disabled] { opacity: 0.35; cursor: default; }

.strip__track {
  list-style: none;
  margin: 0;
  padding: 0 0 0.5rem;
  display: flex;
  gap: clamp(0.75rem, 2vw, 1.5rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Room for a card's hover lift and shadow, which a scroll container would
   * otherwise clip. */
  padding-block-start: 0.25rem;
  scrollbar-width: none;
}
.strip__track::-webkit-scrollbar { display: none; }
/* Each card takes an equal share of the visible width, gaps accounted for, so
 * `--strip-cols: 4` really does show four. `flex: none` because a flex item's
 * default is to shrink, which would fit them all in and defeat the strip. */
.strip__item {
  flex: none;
  width: calc((100% - (var(--strip-cols) - 1) * clamp(0.75rem, 2vw, 1.5rem)) / var(--strip-cols));
  scroll-snap-align: start;
}
.strip__item > .product-card { height: 100%; }
@media (max-width: 63.99rem) {
  /* Two and a bit on a tablet, one and a half on a phone — the part-card at
   * the edge is what says the row continues. */
  .strip__item { width: calc((100% - 1rem) / 2.2); }
}
@media (max-width: 30rem) {
  .strip__item { width: calc((100% - 0.75rem) / 1.4); }
}

/* The card's square picture frame. */
.pcard__frame {
  position: relative;
  display: block;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.pcard__frame img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---- Combo groups: slots, contents, quantities ---------------------------
 *
 * A selection group is a combo's slots — "pick two" is two questions, not one
 * list with two ticks — and its items carry photographs, because choosing
 * between two burgers is a choice between two pictures. A package group is the
 * same tiles with nothing to decide. Both can hang their own questions off a
 * chosen item, and those appear underneath it.
 */
/* Top and bottom padding equal: a single-slot group (one "select 1", no
 * step-through) used to start its first tile flush against the header's
 * rule above it, with only the bottom getting room — asymmetric for no
 * reason once there was somewhere for that top space to come from. */
.combo-slot { padding: 0.9rem 0; }
.combo-slot + .combo-slot { padding-top: 0.3rem; }
.combo-slot__label {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin: 0.5rem 0 0.75rem;
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 600;
}
/* "1 of 2" — a position in a sequence, which is what a combo's slots are. */
.combo-slot__n { color: var(--ink); }
.combo-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.5rem;
}
.combo-grid--fixed { padding-bottom: 0.9rem; }
/* The cell, not the tile, is the grid item: a picked tile's own questions sit
 * under it inside the same cell — so the cell stacks them, and the tile sizes
 * to itself.
 *
 * `height: 100%` on the tile was the bug behind the overlap: the cell grows
 * when a pick reveals its questions, 100% of that taller cell is the tile, and
 * the tile then covered the very questions that made the cell tall — their
 * headings surfacing on top of the next slot's label. */
.combo-cell { min-width: 0; display: flex; flex-direction: column; }
.combo-tile {
  position: relative;                 /* the visually-hidden input's anchor */
  display: flex;
  flex-direction: column;
  flex: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.15s var(--ease);
}
.combo-tile:hover { border-color: var(--line-2); }
/* The radio itself is not drawn — the tile is the control, and a checked tile
 * says so with its border and its tick. Kept in the layout (not `display:
 * none`) so it stays focusable and reachable by keyboard. */
.combo-tile input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.combo-tile__media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  background: linear-gradient(160deg, var(--surface-3), var(--line-2));
}
.combo-tile__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.combo-tile__ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
}
.combo-tile__body {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.5rem 0.6rem 0.6rem;
}
/* Catalogue names run long and arrive without spaces
 * ("LaptopLaptopLaptop3333"), and an unbroken word does not wrap — it ran
 * straight out through the tile's edge. Break anywhere, then stop at two
 * lines so tiles in a row stay close in height. */
.combo-tile__name {
  font-size: 0.88rem;
  font-weight: 600;
  line-height: 1.25;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.combo-tile__price { color: var(--muted); font-size: 0.8rem; }
.combo-tile:has(input:checked) {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
/* The tick, so a chosen tile is obvious at grid size without reading it. */
.combo-tile:has(input:checked) .combo-tile__media::after {
  content: "";
  position: absolute;
  top: 0.4rem;
  inset-inline-end: 0.4rem;
  width: 1.15rem;
  height: 1.15rem;
  border-radius: var(--radius-pill);
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / 0.75rem no-repeat;
}
.combo-tile:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.combo-tile--fixed { cursor: default; }

/* A picked item's own questions. Hidden until it is picked — an unpicked
 * item's options are not questions anyone has been asked yet, and the server
 * ignores them too (it only walks into items that were chosen).
 *
 * A sibling of the tile grid, so it gets the group's full width; the rules
 * that open the right one are written per item by the snippet. */
.combo-sub {
  display: none;
  margin: 0.6rem 0.7rem 0.2rem;
  padding-inline-start: 0.7rem;
  border-inline-start: 2px solid var(--line-2);
}
.combo-sub--open { display: block; }
/* Which content item these questions belong to — with the tiles above rather
 * than beside them, the block has to name its subject. */
.combo-sub__for {
  margin: 0 0 0.35rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--muted);
}
.cfg--nested { margin: 0; }
.cfg--nested > .cfg__head { padding: 0.6rem 0; }
.cfg--nested .cfg__title { font-size: 0.92rem; }

/* An `options` group's row: name, unit price, stepper. */
.cfg__row--qty { cursor: default; }
.cfg__row--qty .cfg__name { flex: 1; }
/* Small, square, and out of the way: the picture is here to identify the
 * thing, not to sell it — the row is a line on a list, not a card. */
.cfg__thumb {
  position: relative;
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface-2);
}
.cfg__thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* A pill is a word; a thumbnail inside one turns it into a badge. */
.cfg__row--pill .cfg__thumb { display: none; }
.stepper--sm { transform: scale(0.85); transform-origin: right center; }
[dir="rtl"] .stepper--sm { transform-origin: left center; }

/* ---- Product page: stock, running total, action bar ----------------------
 *
 * The shape follows the PLUS app's item screen — stock on the photograph, the
 * price that answers "what will this cost me" rather than "what does the base
 * item cost", and quantity beside the button that uses it.
 */
.pdp__media { position: relative; }
.pdp__stock {
  position: absolute;
  top: 1rem;
  inset-inline-start: 1rem;
  z-index: 1;
  padding: 0.35rem 0.7rem;
  border-radius: var(--radius-pill);
  background: var(--dark);
  color: var(--on-dark);
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
}
.pdp__stock--out { background: var(--danger); }

.pdp__actions {
  display: flex;
  gap: 1rem;
  align-items: center;
  flex-wrap: wrap;
}
/* "Your plate" — what the shopper has actually built so far, in one line,
 * written where the button already is rather than requiring a scroll back
 * through the groups to check it. `flex-basis: 100%` puts it on its own row
 * inside `.pdp__actions` whether that's the ordinary inline layout or the
 * fixed phone bar below, with no separate rule needed for either. Empty
 * while nothing is chosen yet — a size product with one modifier group may
 * never have anything to say here. */
.pdp__plate {
  flex: 1 1 100%;
  margin: 0;
  font-size: 0.82rem;
  color: var(--ink-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pdp__plate:empty { display: none; }
.pdp__submit {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
}
/* The total is a second figure inside one button, so it is set apart rather
 * than run on: at a glance it reads as the price, not as part of the label. */
.pdp__submit-total {
  padding-inline-start: 0.6rem;
  border-inline-start: 1px solid currentColor;
  opacity: 0.85;
  font-variant-numeric: tabular-nums;
}
.pdp__submit-total:empty { display: none; }
/* The figure moves when it changes, and only when it changes.
 *
 * A running total that updates silently is a number people re-read to check
 * they saw it right. One short lift is enough to say "this just changed" —
 * short enough not to delay the next tap, and on the figure alone rather than
 * the button, so the target never moves under a thumb. */
@keyframes total-tick {
  0%   { transform: translateY(0); }
  35%  { transform: translateY(-0.18em); }
  100% { transform: translateY(0); }
}
.pdp__submit-total.is-changed {
  animation: total-tick 0.28s var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  /* The change still needs marking, so the movement becomes a brief lightening
   * instead of being dropped altogether. */
  @keyframes total-tick {
    0%, 100% { opacity: 1; }
    40%      { opacity: 0.55; }
  }
}

@media (max-width: 63.99rem) {
  /* Fixed to the bottom on a phone. The groups make this page taller than the
   * screen, and the decision to order is taken while reading them — not after
   * scrolling back past them. */
  .pdp__actions {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 40;
    margin: 0;
    padding: 0.7rem var(--gutter);
    padding-bottom: calc(0.7rem + env(safe-area-inset-bottom));
    background: var(--surface);
    border-top: 1px solid var(--line);
    box-shadow: 0 -6px 20px rgb(0 0 0 / 8%);
    /* Wrap, not nowrap.
     *
     * `.pdp__plate` is `flex-basis: 100%` precisely so it takes its own line;
     * `nowrap` overruled that and squeezed it into the row beside the stepper,
     * where a plate of two choices rendered as "C." and told nobody anything.
     * It costs one line of bar height to answer "what am I ordering" without
     * scrolling back through the groups. */
    flex-wrap: wrap;
    row-gap: 0.35rem;
  }
  /* Quieter and tighter in the bar than in the page: it is a reminder here,
   * not a heading. */
  .pdp__plate { font-size: 0.78rem; line-height: 1.3; }
  /* Clears the bar, so the last group is reachable rather than sitting under
   * it — the same reason the menu page pads for its order bar. */
  .pdp { padding-bottom: 5.5rem; }
  /* Label and total on one line: "Add to / cart" broken over two lines beside
   * the figure made the bar look cramped and the button ambiguous. */
  .pdp__submit { padding-inline: 0.9rem; font-size: 0.95rem; white-space: nowrap; }
  .pdp__submit-total { padding-inline-start: 0.5rem; }
}

/* ---- Quick add feedback --------------------------------------------------
 *
 * A quick add used to be a form post: the page reloaded, the shopper lost
 * their place in a long menu, and the only sign anything had happened was a
 * number that had already changed by the time they could look at it. The
 * script now posts in the background, so the number is the ONLY thing that
 * moves — and a number that changes silently is a number nobody notices. The
 * bounce is what points at it.
 *
 * Animation, not transition: the badge ends where it started, so there is no
 * end state to transition to. The class is removed on `animationend`, which
 * is what lets a second add replay it. */
@keyframes cart-bump {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.45); }
  55%  { transform: scale(0.92); }
  75%  { transform: scale(1.12); }
  100% { transform: scale(1); }
}
[data-cart-count].is-bumped { animation: cart-bump 0.5s var(--ease); }
/* Someone who has asked for less motion still needs to know it worked, so the
 * badge flashes its colours instead of moving. */
@media (prefers-reduced-motion: reduce) {
  @keyframes cart-bump {
    0%, 100% { filter: none; }
    40%      { filter: brightness(1.6); }
  }
}
/* A button cannot be pressed twice while its request is in flight — two taps
 * on a slow connection is two of the dish. The label stays in place (color
 * only, not `visibility` or `display`) so the button keeps its width and its
 * accessible name while a small ring spins over it — dimming alone (the
 * previous state here) reads the same as a plain disabled button, which
 * says "you can't do this" rather than "this is happening". `--btn-fg` is
 * used rather than `currentColor` precisely because the label's own color
 * is turned transparent right below it. */
.btn[aria-busy="true"] {
  position: relative;
  color: transparent;
  pointer-events: none;
}
.btn[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 1.1em;
  height: 1.1em;
  border: 2px solid var(--btn-fg);
  border-inline-end-color: transparent;
  border-radius: 50%;
  animation: btn-spin 0.6s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .btn[aria-busy="true"] { opacity: 0.65; }
  .btn[aria-busy="true"]::after { animation: none; }
}

/* ---- Menu view toggle ----------------------------------------------------
 *
 * Grid or list. The grid is the theme's default and sells the food on the
 * photograph; the list fits roughly twice as many dishes on a screen and
 * brings the description back, which is what someone reordering a usual wants.
 */
.menu-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: clamp(0.75rem, 2vw, 1.25rem);
}
.view-toggle {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface);
}
.view-toggle__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 0.8rem;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--muted);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
  transition: background 0.18s var(--ease), color 0.18s var(--ease);
}
.view-toggle__btn:hover { color: var(--ink); }
.view-toggle__btn.is-active { background: var(--dark); color: var(--on-dark); }

/* List: the same card turned on its side. The picture becomes a square rail
 * down the start edge spanning every row of the card, so the text column is
 * whatever is left — no second set of card styles, just a different flow. */
[data-view="list"] .dish-grid {
  grid-template-columns: 1fr;
  gap: 0.6rem;
}
/* Three columns, and the third is what makes it a list rather than a wide
 * card: picture, what it is, what it costs and how to get it. Stacking the
 * button under the name left a hole the height of the photograph in every
 * row — the picture sets the row's height, and a two-line name cannot fill
 * it. Beside the name, that space is the layout instead of a gap in it. */
[data-view="list"] .dish {
  display: grid;
  /* ONE row: picture, text, action, all centred on it. Two rows was the bug —
   * the picture spans them, and a spanning item hands its height to the
   * tracks it spans, so an absent description became a tall empty track
   * holding the name up at the top of the card. */
  grid-template-columns: clamp(4.5rem, 15%, 7rem) minmax(0, 1fr) auto;
  grid-template-rows: auto;
  align-items: center;
  column-gap: 0.9rem;
  /* Only the end side: the picture runs to the card's start edge, the action
   * keeps its distance from the end. Logical, so in RTL — picture on the
   * right — the gap is on the left, where the button or badge now sits. */
  padding: 0;
  padding-inline-end: 0.9rem;
}
[data-view="list"] .dish__media {
  grid-column: 1;
  grid-row: 1;
  aspect-ratio: 1;
  margin-bottom: 0;
}
/* Explicit placement, because the description is optional: without it the
 * rows would shuffle up and the name would sit where the description was. */
[data-view="list"] .dish__text { grid-column: 2; padding-inline: 0; }
[data-view="list"] .dish__actions,
[data-view="list"] .dish__sold {
  grid-column: 3;
  grid-row: 1;
  justify-self: end;
  margin: 0;
  padding: 0;
}
[data-view="list"] .dish__title { margin: 0; }
/* A row with neither description nor a second line still needs its own
 * height, or the picture alone decides it. */
[data-view="list"] .dish { min-height: 5.5rem; }
/* Room to read, and the reason someone picked this view — so it comes back on
 * a phone, where the grid card hides it. */
[data-view="list"] .dish__desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  margin: 0.2rem 0 0;
}
/* The picture is a third of its grid size here, so the token has to come
 * down with it — at the grid's size it covered most of an 88px thumbnail. */
[data-view="list"] .dish__badge {
  inset-inline-end: 0.3rem;
  bottom: 0.3rem;
  padding: 0.22rem 0.45rem;
  font-size: 0.72rem;
  border-radius: 0.5rem;
}
/* A button as wide as a laptop row is a target nobody needs. */
[data-view="list"] .dish__actions .btn { width: auto; min-width: 8rem; }
[data-view="list"] .dish:hover { transform: none; }

@media (max-width: 48rem) {
  /* No room for a third column beside a 5rem picture: the action drops under
   * the name, and the picture goes on spanning the rows beside both. */
  /* No room for a third column beside the picture, so the action drops under
   * the text and the picture spans both rows. Safe here: those two rows are
   * taller than the 5.5rem picture, so its span has nothing to inflate. */
  [data-view="list"] .dish {
    grid-template-columns: 5.5rem minmax(0, 1fr);
    grid-template-rows: auto auto;
    align-items: start;
    column-gap: 0.75rem;
    /* Logical, as on a wide screen: nothing on the picture's side, room on the
     * end — which is the left in RTL. */
    padding-block: 0.7rem;
    padding-inline: 0 0.7rem;
    min-height: 0;
  }
  [data-view="list"] .dish__media { grid-row: 1 / -1; align-self: start; }
  [data-view="list"] .dish__text { grid-row: 1; }
  [data-view="list"] .dish__title {
    /* The grid card clamps hard because two sit side by side; a full-width
     * row has space for the whole name. */
    display: block;
    font-size: 0.92rem;
  }
  [data-view="list"] .dish__actions,
  [data-view="list"] .dish__sold {
    grid-column: 2;
    grid-row: 2;
    justify-self: stretch;
    margin-top: 0.5rem;
  }
  [data-view="list"] .dish__actions .btn { min-width: 0; width: 100%; }
}
/* The list view zeroes its cell's padding and stretches it; the badge keeps
 * its own padding and stays the size of its words. */
[data-view="list"] .dish__sold { padding: 0.25rem 0.65rem; width: fit-content; }

/* ---- Chef recommendation ------------------------------------------------- */
.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.75rem, 5vw, 4rem);
  align-items: center;
}
.split--flip .split__media { order: 2; }
.split__media {
  aspect-ratio: 1;
  border-radius: var(--radius);
  overflow: hidden;
  background: linear-gradient(160deg, var(--surface-3), var(--line-2));
  box-shadow: var(--shadow);
}
.split__media--round { border-radius: var(--radius-pill); }
.split__media img { width: 100%; height: 100%; object-fit: cover; }
.split__body p { color: var(--ink-soft); max-width: 26rem; }
.split__cta { margin-top: 1.75rem; }
@media (max-width: 52rem) {
  .split { grid-template-columns: 1fr; }
  .split--flip .split__media { order: 0; }
}

/* ---- Event countdown ----------------------------------------------------- */
.event {
  position: relative;
  text-align: center;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface-2);
  background-size: cover;
  background-position: center;
  padding: clamp(2.5rem, 6vw, 4.5rem) var(--gutter);
  isolation: isolate;
}
.event--on-image::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(23, 25, 15, 0.55);
}
.event--on-image, .event--on-image h2, .event--on-image p { color: var(--on-dark); }
.event__body { max-width: 40rem; margin: 0 auto; }
.event__body p { color: inherit; opacity: 0.85; }
.countdown {
  display: flex;
  justify-content: center;
  gap: 0.75rem;
  margin: 2rem 0;
  list-style: none;
  padding: 0;
}
.countdown__cell {
  min-width: 4rem;
  padding: 0.7rem 0.5rem;
  border-radius: var(--radius-sm);
  background: var(--surface-3);
  color: var(--ink);
}
.event--on-image .countdown__cell { background: rgba(255, 255, 255, 0.16); color: var(--on-dark); backdrop-filter: blur(4px); }
.countdown__num { font-family: var(--font-display); font-weight: 700; font-size: 1.4rem; line-height: 1.1; display: block; }
.countdown__label { font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase; opacity: 0.7; }

/* ---- Product detail --------------------------------------------------------
 * "The Pass" — the counter where the kitchen hands the dish over. The photo
 * reads as the room, not a portrait in a circle: full height, full width of
 * its column, and on a wide screen it bleeds past --maxw to the viewport's
 * own edge, because a window onto the food is not supposed to feel gridded.
 * The copy card then rides up over its lower third — the interface arriving
 * after the food, not beside it. `.pdp__stage`/`.pdp__card` carry that
 * relationship; `.pdp__body` is only a card ON MOBILE, where the two stack.
 */
.pdp { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 clamp(2rem, 5vw, 4rem); align-items: start; }
.pdp__stage { order: 2; }
.pdp__card { order: 1; margin-top: 0; }
.pdp__body { padding: 0; }
/* Desktop: room between the hours strip and the dish name, which otherwise
 * sat flush against it. Phones lay this column out on their own. */
@media (min-width: 64rem) {
  .pdp__card { padding-top: clamp(1.5rem, 3vw, 2.5rem); }
}
.pdp__media {
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-lg);
  /* The trailing edge always ends flush with the viewport (see the bleed
   * margin below) — a round corner there would leave a sliver of the page's
   * own ground showing past the photo, which is the one thing a "window onto
   * the room" cannot do at its own sill. */
  border-start-end-radius: 0;
  border-end-end-radius: 0;
  overflow: hidden;
  background: linear-gradient(160deg, var(--surface-3), var(--line-2));
  box-shadow: var(--lift-1);
  /* Bleeds the trailing column to the viewport's own edge: the container's
   * own inset (its centring gap over --maxw, plus --gutter) pulled back out.
   * `max()` floors the centring term at 0 so this still resolves to exactly
   * --gutter on a screen narrower than --maxw, where there is no gap to add. */
  margin-inline-end: calc(-1 * (var(--gutter) + max(0px, (100vw - var(--maxw)) / 2)));
}
.pdp__media img { width: 100%; height: 100%; object-fit: cover; }
.pdp__media::after {
  /* Warmth under whatever sits on the photograph — the stock badge reads
   * without a chip drawn under it, because the scrim already carries the
   * contrast, not a solid ground. */
  content: "";
  position: absolute;
  inset: 0;
  background: var(--scrim-warm);
  pointer-events: none;
}
/* The track: one frame wide, snapping to each photo. `scroll-snap-type` plus
 * an id per slide is the whole mechanism — the thumbnails below are anchors
 * into it, so paging works with the script off and from the keyboard. */
.pdp__track {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.pdp__track::-webkit-scrollbar { display: none; }
.pdp__track:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.pdp__slide {
  flex: none;
  width: 100%;
  height: 100%;
  scroll-snap-align: center;
  /* A slide scrolled to by anchor would otherwise land under the sticky
   * header. */
  scroll-margin-top: var(--stuck-top, 0px);
}
.pdp__slide img { width: 100%; height: 100%; object-fit: cover; }

.pdp__thumbs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(3.5rem, 1fr));
  gap: 0.6rem;
  margin-top: 1rem;
  list-style: none;
  padding: 0;
}
/* A link, not a decorative image: it has a target, a focus ring and a name. */
.pdp__thumb {
  display: block;
  position: relative;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 2px solid transparent;
  transition: border-color 0.15s var(--ease);
}
.pdp__thumb:hover { border-color: var(--line-2); }
.pdp__thumb:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pdp__thumbs img { aspect-ratio: 1; object-fit: cover; width: 100%; display: block; }

/* Available to any control whose visible label is its picture. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .pdp__track { scroll-behavior: auto; }
}
/* Below --maxw + 2 × --gutter (nothing left to bleed into) and, more to the
 * point, below the stacking breakpoint: the photo goes full-bleed on BOTH
 * edges and the card rides up over its lower third. */
@media (max-width: 52rem) {
  .pdp { grid-template-columns: 1fr; }
  .pdp__stage { order: 1; }
  .pdp__card { order: 2; margin-top: -3.75rem; position: relative; z-index: 1; }
  .pdp__media {
    aspect-ratio: auto;
    height: min(65vh, 32rem);
    border-radius: 0;
    margin-inline-start: calc(var(--gutter) * -1);
  }
  .pdp__body {
    background: var(--paper);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    box-shadow: var(--lift-1);
    padding: 1.75rem var(--gutter) 0.25rem;
  }
}

.pdp__price { display: flex; align-items: baseline; gap: 0.7rem; flex-wrap: wrap; font-size: 1.4rem; margin-bottom: 1.25rem; }
.pdp__price s { color: var(--muted); font-size: 1rem; font-weight: 400; }
/* The description reads as a magazine standfirst rather than body copy: the
 * opening paragraph is set larger and looser, and the measure is capped near
 * 42 characters so the line breaks fall where a reader expects them instead of
 * running the width of the card. Everything after the first paragraph drops to
 * body size — a standfirst that never ends is just text. */
.pdp__desc {
  color: var(--ink-soft);
  margin-bottom: 1.75rem;
  max-width: 42ch;
  font-size: 1.02rem;
  line-height: 1.7;
}
.pdp__desc > :first-child {
  font-size: 1.12rem;
  line-height: 1.6;
  color: var(--ink);
}
.pdp__desc > * + * { margin-top: 0.7rem; }
.pdp__form { display: flex; flex-direction: column; gap: 1.1rem; max-width: 30rem; }
.pdp__foot { margin-top: 1.5rem; font-size: 0.85rem; color: var(--muted); }
.badge-save {
  background: var(--danger);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius-sm);
  align-self: center;
}
/* Product options — sizes, modifiers, combo picks.
 *
 * Read as a kitchen docket rather than a web form. A docket is a stack of
 * lines: each one asks something, each one carries its answer in writing, and
 * they are separated by a tear rather than boxed up individually. That gives
 * the page one structural device that means something — a rule between two
 * questions says they are different questions — instead of a card per group
 * whose border says only "this is a group".
 *
 * What was here before was the form vocabulary: a tracked-out capitalised
 * label, a red asterisk, a radio dot in every row. All three describe the
 * mechanism. None of them describe lunch.
 */
.cfg {
  border: 0;
  border-top: 1px dashed var(--line-2);
  border-radius: 0;
  background: none;
  padding: 0;
  margin: 0;
  overflow: visible;
}
.cfg:first-of-type { border-top: 0; }

/* The question stays put while its answers scroll.
 *
 * A group with a dozen modifiers is taller than a phone screen, and once its
 * header has scrolled away the rows underneath are unlabelled — you are
 * ticking boxes without the question in view, and "up to 3" has gone with it.
 * Sticking the header to the top of its own group keeps the question and the
 * allowance visible for exactly as long as its answers are.
 *
 * `top` clears the site header, which is itself sticky: `--stuck-top` is its
 * measured height, published on every page by theme.js. An opaque ground is
 * required — a transparent sticky header lets the rows slide through it. */
.cfg > .cfg__head {
  position: sticky;
  top: var(--stuck-top, 0px);
  z-index: 2;
  background: var(--paper);
}
/* A nested group is already inside a revealed pick and is short by
 * construction; two headers competing for the same edge is one too many. */
.cfg--nested > .cfg__head { position: static; }
/* The opaque ground has to match whatever the group is standing on, or the
 * stuck header is a cream band across a tinted section. */
.section--tint .cfg > .cfg__head { background: var(--surface-2); }
/* Only while open, and only then — a closed header has nothing below it to
 * separate itself from. */
/* The open question is a chit lifted off the pass.
 *
 * Closed groups stay flat on the page, separated by the dashed tear rule, so a
 * stack of answered questions reads as a stack of paper. The one being
 * answered rises onto its own ground with a shadow under it: the page then has
 * exactly one object in the foreground, and it is the question you are on.
 *
 * `--lift-1` and the surface are the same pair the copy card uses over the
 * photograph, so the two lifts on this page are the same gesture at two
 * scales rather than two unrelated effects. */
.cfg[open] {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  border-top-color: transparent;
  padding-inline: 0.85rem;
  margin-block: 0.35rem;
}
/* The sticky header has to match the ground it is stuck to, or it is a cream
 * band sliding over a white chit. */
.cfg[open] > .cfg__head {
  background: var(--surface);
  box-shadow: 0 1px 0 var(--line);
  /* Inset so the header's rule spans the chit's full width rather than
   * stopping short of its padding. */
  margin-inline: -0.85rem;
  padding-inline: 0.85rem;
}
/* A nested group is already inside a chit; a chit inside a chit is a box
 * inside a box. */
.cfg--nested[open] {
  background: none;
  box-shadow: none;
  padding-inline: 0;
  margin-block: 0;
}
.cfg__head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.95rem 0.1rem;
  cursor: pointer;
  list-style: none;
}
/* Safari draws its own triangle through `::-webkit-details-marker`, which the
 * standard `list-style: none` does not reach. */
.cfg__head::-webkit-details-marker { display: none; }
.cfg__heading { flex: 1; min-width: 0; }
.cfg__ask { display: flex; align-items: baseline; gap: 0.6rem; }
/* Sentence case, no tracking. A question set in spaced capitals is shouting a
 * label; this one is asking something. */
.cfg__title {
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
}
/* How many, in words. Sits with the question because it is part of it. */
.cfg__need {
  font-size: 0.82rem;
  color: var(--muted);
  white-space: nowrap;
}
.cfg__need--must { color: var(--accent); }
/* The answer, under the question. */
.cfg__chosen {
  display: block;
  margin-top: 0.2rem;
  color: var(--ink-soft, var(--muted));
  font-size: 0.88rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cfg__chosen:empty { display: none; }
.cfg__caret { flex: none; color: var(--muted); transition: transform 0.18s var(--ease); }
.cfg[open] > .cfg__head .cfg__caret { transform: rotate(180deg); }
.cfg .cfg__list { padding: 0 0 0.9rem; }

/* 0.5rem, not 0.3: adjacent tap targets need 8px between them or a thumb
 * lands on the row above the one it was aimed at. The gap was 4.8px. */
.cfg__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
/* A handful of short choices read side by side: sizes are compared, not
 * scanned down a column. */
.cfg__list--pills { flex-direction: row; flex-wrap: wrap; gap: 0.5rem; }

.cfg__row {
  position: relative;
  display: flex;
  gap: 0.7rem;
  align-items: center;
  /* 48px is the floor for a row a thumb has to hit. */
  min-height: 3rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}
.cfg__row:hover { border-color: var(--line-2); }
/* A real control, drawn by the browser.
 *
 * This was a 1×1 transparent input with the answer marked by a tick at the far
 * end of the row. That pattern is defensible — the input kept focus and the
 * label kept the click — but it throws away the two things the native control
 * gives for free: a shape that says how many answers the group takes, and a
 * state assistive technology and the platform both already understand.
 *
 * `accent-color` tints it with the brand without replacing it, so a radio is
 * round and a checkbox square automatically. The single-vs-multiple question
 * is then answered by the control itself rather than by a class. */
.cfg__row input {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.cfg__name { flex: 1; }
/* Tabular figures so a column of prices lines up on the decimal — three-digit
 * minor units make that visible. */
.cfg__price { color: var(--muted); font-size: 0.9rem; font-variant-numeric: tabular-nums; }
.cfg__flag { color: var(--danger); font-size: 0.78rem; }

/* Chosen: an olive spine at the leading edge and a tick at the trailing one —
 * the two marks a line gets when it is ticked off. */
.cfg__row:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
}
.cfg__row::before {
  content: "";
  position: absolute;
  inset-block: -1px;
  inset-inline-start: -1px;
  width: 3px;
  border-start-start-radius: var(--radius-sm);
  border-end-start-radius: var(--radius-sm);
  background: var(--accent);
  opacity: 0;
  transition: opacity 0.15s var(--ease);
}
.cfg__row:has(input:checked)::before { opacity: 1; }
/* No tick: the control now shows the state, and two marks for one answer is
 * one mark too many. The row keeps its tinted ground and its spine. */
.cfg__row:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Pills: same line, laid out as a chip. The tick would crowd a short label,
 * so a chosen pill is marked by its ground alone. */
.cfg__row--pill {
  padding: 0.5rem 0.9rem;
  border-radius: var(--radius-pill);
  gap: 0.45rem;
}
.cfg__row--pill::before { display: none; }
/* The one place the control stays hidden. A segmented pill IS the control:
 * its label is the accessible name, its ground is the state, and a checkbox
 * floating inside it would read as a second thing to press. The input keeps
 * its place in the tab order and the pill shows the focus ring below. */
.cfg__row--pill input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  margin: 0;
}
.cfg__row--pill:has(input:checked) {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast, #fff);
}
.cfg__row--pill:has(input:checked) .cfg__price { color: inherit; opacity: 0.85; }
.cfg__row--pill .cfg__name { flex: none; }

/* Sold out, or a package's fixed contents: shown because a customer needs to
 * know what is in the box, but not offered as a choice. */
.cfg__row--off {
  color: var(--muted);
  background: var(--surface-2);
  cursor: not-allowed;
  padding-inline-end: 0.85rem;
}
.cfg__row--off:hover { border-color: var(--line); }
.cfg__row--off::after, .cfg__row--off::before { display: none; }

/* ---- Quantity stepper ---------------------------------------------------- */
/* One look for "how many" everywhere — the cart line's: a bordered box with
 * square buttons either side and the count between thin rules. The product
 * page, the option quantities and the cart all take it from here; the phone
 * action bar only recolours it (see "The bar"). */
.stepper {
  display: inline-flex;
  align-items: center;
  gap: 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  overflow: hidden;
}
.stepper__btn {
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--ink);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background-color 0.16s var(--ease);
}
.stepper__btn:hover { background: color-mix(in srgb, var(--accent) 10%, var(--surface)); }
.stepper__input {
  width: 2.25rem;
  height: 40px;
  text-align: center;
  border: 0;
  border-inline: 1px solid var(--line);
  border-radius: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  color: var(--ink);
  -moz-appearance: textfield;
}
.stepper__input::-webkit-outer-spin-button,
.stepper__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---- Cart ---------------------------------------------------------------- */
.cart { display: grid; grid-template-columns: minmax(0, 1fr) 20rem; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.cart__lines { list-style: none; margin: 0 0 1.5rem; padding: 0; display: flex; flex-direction: column; gap: 1rem; }
.cart-line {
  display: grid;
  grid-template-columns: 6.5rem minmax(0, 1fr) auto;
  gap: 1.1rem;
  align-items: start;
  padding: 1.1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.cart-line__media {
  width: 6.5rem;
  height: 6.5rem;
  border-radius: 12px;               /* a rounded square, as the dish thumbnails elsewhere */
  overflow: hidden;
  background: linear-gradient(160deg, var(--surface-3), var(--line-2));
}
.cart-line__media img { width: 100%; height: 100%; object-fit: cover; }
.cart-line__title { font-family: var(--font-display); font-weight: 700; font-size: 1.02rem; margin: 0 0 0.3rem; }
.cart-line__desc { color: var(--muted); font-size: 0.86rem; margin: 0 0 0.7rem; }
.cart-line__sel { list-style: none; margin: 0 0 0.6rem; padding: 0; font-size: 0.83rem; color: var(--muted); }
.cart-line__sel b { color: var(--ink-soft); font-weight: 500; }
.cart-line__price { font-family: var(--font-display); font-weight: 700; white-space: nowrap; }
.cart-line__remove { border: 0; background: none; color: var(--muted); font-size: 0.82rem; cursor: pointer; padding: 0.3rem 0; }
.cart-line__remove:hover { color: var(--danger); }
.cart__total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  border-top: 1px solid var(--line-2);
  padding-top: 1.25rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.1rem;
}
.cart__total-value { background: var(--surface-3); border-radius: var(--radius-sm); padding: 0.5rem 1.75rem; }
.cart__side-title { font-family: var(--font-display); font-weight: 700; font-size: 1.02rem; margin: 0 0 0.9rem; }
.cart__place { margin-top: 2rem; text-align: center; }
.cart__place .btn { min-width: min(22rem, 100%); }
.cart-empty { text-align: center; padding: clamp(2rem, 6vw, 4rem) 0; }
@media (max-width: 60rem) {
  .cart { grid-template-columns: 1fr; }
  .cart-line { grid-template-columns: 4.5rem minmax(0, 1fr); }
  .cart-line__media { width: 4.5rem; height: 4.5rem; }
  .cart-line__price { grid-column: 2; }
}

/* ---- Reservation --------------------------------------------------------- */
.reserve { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.reserve__media {
  aspect-ratio: 3 / 4;
  border-radius: var(--radius);
  overflow: hidden;
  background: linear-gradient(160deg, var(--surface-3), var(--line-2));
  box-shadow: var(--shadow);
}
.reserve__media img { width: 100%; height: 100%; object-fit: cover; }
.reserve__form { max-width: 26rem; }
@media (max-width: 52rem) { .reserve { grid-template-columns: 1fr; } .reserve__media { order: -1; aspect-ratio: 16 / 10; } }

/* ---- Generic product card (shop / search / collections) ------------------ */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.card:hover { transform: translateY(-2px); box-shadow: var(--shadow); }

/* ---- Footer -------------------------------------------------------------- */
/* No margin above the footer: the last section's own bottom padding already
 * ends the page, and a margin on top of it was a band of bare page colour with
 * nothing in it. The brand badge (-2.75rem) still rises over the edge, into
 * that padding — above it, so nothing covers it. */
.site-footer {
  margin-top: 0;
  background: var(--dark);
  color: var(--on-dark);
  text-align: center;
  position: relative;
  padding: 0 0 2.25rem;
}
.site-footer a { color: var(--on-dark); }
.site-footer a:hover { color: color-mix(in srgb, var(--accent) 65%, #fff); }
/* Buttons keep their own foreground.
 *
 * The two rules above are `.site-footer a` — one class and one element, which
 * out-specifies the bare `.btn` that sets `color: var(--btn-fg)`. So every
 * button in the footer had its text repainted in the footer's link cream, and
 * `.btn--light` puts that cream on a cream background: "Reserve Now" was
 * invisible at rest and a washed-out olive on hover.
 *
 * Written against `.btn` rather than against `--btn-fg` so it holds for every
 * variant — a dark or ghost button dropped into the footer later inherits the
 * fix instead of rediscovering the bug. */
.site-footer .btn,
.site-footer .btn:hover { color: var(--btn-fg); }
.footer__brand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
  border-radius: var(--radius);
  padding: 0.9rem 1.5rem;
  margin-top: -2.75rem;
  margin-bottom: 1.75rem;
  box-shadow: var(--shadow);
  color: var(--ink);
}
.footer__brand:hover { color: var(--ink); }
.footer__brand img { max-height: 3rem; width: auto; }
.footer__nav {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.6rem clamp(1rem, 3vw, 2.25rem);
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.92rem;
}
.footer__text {
  max-width: 42rem;
  margin: 0 auto 1.25rem;
  color: var(--on-dark-muted);
  font-size: 0.88rem;
  line-height: 1.7;
}
.footer__hours {
  color: var(--on-dark);
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 0 0 2rem;
}
.footer__cta { display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap; margin-bottom: 2rem; }
.footer__social { display: flex; justify-content: center; gap: 1.1rem; margin-bottom: 1.75rem; }
.footer__social a {
  width: 2.1rem;
  height: 2.1rem;
  border-radius: var(--radius-pill);
  display: grid;
  place-items: center;
  border: 1px solid rgba(243, 241, 233, 0.28);
  transition: background-color 0.16s var(--ease), border-color 0.16s var(--ease);
}
.footer__social a:hover { background: rgba(243, 241, 233, 0.12); border-color: rgba(243, 241, 233, 0.5); }
.footer__legal { color: var(--on-dark-muted); font-size: 0.8rem; margin: 0; }
.footer__meta {
  display: flex;
  justify-content: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
  font-size: 0.8rem;
  color: var(--on-dark-muted);
}

/* ---- RTL ----------------------------------------------------------------- */
[dir="rtl"] body { text-align: right; }
/* `.dish` is deliberately absent: its card is start-aligned, which already
 * flips to the right in RTL. Centring it here would have undone that. */
[dir="rtl"] .hero, [dir="rtl"] .event, [dir="rtl"] .site-footer,
[dir="rtl"] .menu-section__title, [dir="rtl"] .section__head--center { text-align: center; }

/* ---- Motion preference --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
  html { scroll-behavior: auto; }
}

/* ---- Progressive-enhancement field swap ---------------------------------
   The reservation form draws Date and Time as two fields, and the name as
   First / Last, the way the design specifies. The platform wants one
   datetime and one name, so theme.js composes them on submit. With
   scripting off the composed fields are dropped and a single combined
   field takes their place — see the <noscript> block in the section. */
.no-js-field { display: none; }

/* ---- Order list ---------------------------------------------------------- */
.orders { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.85rem; }
.order-row {
  display: flex;
  justify-content: space-between;
  gap: 1.25rem;
  flex-wrap: wrap;
  padding: 1.15rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}
.order-row__no { font-family: var(--font-display); font-weight: 700; }
.order-row__meta { margin: 0.35rem 0 0; color: var(--muted); font-size: 0.86rem; }
.order-row__side { text-align: end; }
.order-row__total { font-family: var(--font-display); font-weight: 700; margin: 0 0 0.3rem; }
.order-row__links { display: flex; gap: 0.85rem; justify-content: flex-end; font-size: 0.86rem; font-weight: 600; }
.order-row__links a { color: var(--accent); }
.status-pill {
  display: inline-block;
  margin-inline-start: 0.5rem;
  padding: 0.15rem 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--ink-soft);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 600;
}
.empty-state {
  text-align: center;
  color: var(--muted);
  padding: clamp(2rem, 6vw, 3.5rem);
  border: 1px dashed var(--line-2);
  border-radius: var(--radius);
  background: var(--surface);
}
.page-head { margin-bottom: 1.75rem; }
.back-link { color: var(--accent); font-weight: 600; font-size: 0.9rem; }

/* ---- Inherited sections --------------------------------------------------
   The retail-side sections (shop, collections, search, wishlist, blog,
   checkout) come from the platform's default theme and carry their own
   inline styling, which already picks up settings.accent_color. These few
   overrides pull their surfaces onto Bistro's radii, borders and shadows so
   they sit inside the design rather than beside it. Inline styles win over
   the cascade, hence the (sparing) !important. */
.product-card {
  border-color: var(--line) !important;
  border-radius: var(--radius) !important;
  background: var(--surface) !important;
  box-shadow: var(--shadow-sm);
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.product-card:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.product-card img { border-radius: var(--radius-sm) !important; }
.product-grid { gap: clamp(1.25rem, 2.5vw, 2rem) !important; }
.dish__badge-from { font-weight: 500; opacity: 0.72; font-size: 0.72em; }

/* ---- Icons ---------------------------------------------------------------
   Every glyph is inline SVG from snippets/icon.liquid — no emoji, no icon
   font. They inherit currentColor and sit on the text baseline. */
.icon { display: inline-block; vertical-align: middle; flex: 0 0 auto; }
.icon--inline { margin-inline-end: 0.4rem; }
.link-arrow { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--accent); font-weight: 600; }
.link-arrow .icon { transition: transform 0.18s var(--ease); }
.link-arrow:hover .icon { transform: translateX(3px); }
[dir="rtl"] .link-arrow .icon { transform: scaleX(-1); }
[dir="rtl"] .link-arrow:hover .icon { transform: scaleX(-1) translateX(3px); }

/* ---- Switcher pills + popovers (language, currency, service) ------------- */
.switcher { position: relative; }
.switcher > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-pill);
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
}
.switcher > summary::-webkit-details-marker { display: none; }
.switcher > summary:hover { border-color: var(--line-2); color: var(--ink); }
.switcher[open] > summary { border-color: var(--accent); color: var(--ink); }
.switcher[open] > summary .icon--caret { transform: rotate(180deg); }
.icon--caret { transition: transform 0.18s var(--ease); opacity: 0.55; }

.popover {
  position: absolute;
  top: calc(100% + 0.45rem);
  inset-inline-end: 0;
  min-width: 11rem;
  padding: 0.35rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  z-index: 60;
  text-align: start;
}
.popover__label {
  margin: 0.3rem 0.6rem 0.45rem;
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.popover__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  text-align: start;
  padding: 0.5rem 0.6rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  font: inherit;
  font-size: 0.88rem;
  color: var(--ink);
  cursor: pointer;
}
.popover__item:hover { background: var(--surface-2); }
.popover__item[aria-current="true"] { background: var(--surface-2); font-weight: 600; }
.popover__item .icon { margin-inline-start: auto; color: var(--accent); }
.popover__note { color: var(--muted); font-size: 0.78rem; }

/* ---- Nav dropdowns ------------------------------------------------------- */
.nav__item { position: relative; display: inline-flex; align-items: center; }
.nav__item > .nav__link { display: inline-flex; align-items: center; gap: 0.3rem; }
.nav__submenu {
  position: absolute;
  top: 100%;
  inset-inline-start: 0;
  display: none;
  min-width: 12rem;
  margin: 0;
  padding: 0.35rem;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  z-index: 50;
}
.nav__item:hover > .nav__submenu,
.nav__item:focus-within > .nav__submenu { display: block; }
.nav__submenu a {
  display: block;
  padding: 0.5rem 0.65rem;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  font-weight: 500;
  white-space: nowrap;
}
.nav__submenu a:hover { background: var(--surface-2); color: var(--ink); }

/* ---- Departments mega-menu (two-pane) ------------------------------------ */
.nav__item--mega { position: relative; }
.nav__mega {
  position: absolute;
  top: 100%;
  inset-inline-start: 0;
  display: none;
  width: min(52rem, 92vw);
  min-height: 16rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  z-index: 50;
}
.nav__item--mega:hover > .nav__mega,
.nav__item--mega:focus-within > .nav__mega { display: block; }
.nav__mega-depts {
  list-style: none;
  margin: 0;
  padding: 0.5rem 0;
  width: 15rem;
  border-inline-end: 1px solid var(--line);
}
.nav__mega-depts > li { margin: 0; }
.nav__mega-depts > li > a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.55rem 1rem;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.nav__mega-depts > li > a::after { content: "\203A"; color: var(--muted); }
.nav__mega-depts > li:hover > a { background: var(--surface-2); }
.nav__mega-cats {
  display: none;
  position: absolute;
  top: 0;
  inset-inline-start: 15rem;
  inset-inline-end: 0;
  bottom: 0;
  padding: 1rem 1.25rem;
  overflow: auto;
}
.nav__mega-depts > li:hover > .nav__mega-cats { display: block; }
.nav__mega-depts > li:first-child > .nav__mega-cats { display: block; }
.nav__mega-depts:hover > li:first-child > .nav__mega-cats { display: none; }
.nav__mega-depts > li:first-child:hover > .nav__mega-cats { display: block; }
.nav__mega-cats-title {
  display: inline-block;
  margin: 0 0 0.6rem;
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
}
.nav__mega-cats-title:hover { text-decoration: underline; }
.nav__mega-cats ul {
  list-style: none;
  margin: 0;
  padding: 0;
  columns: 2;
  column-gap: 1.5rem;
}
.nav__mega-cats li { margin: 0; break-inside: avoid; }
.nav__mega-cats a {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.35rem 0;
  color: var(--ink);
  text-decoration: none;
}
.nav__mega-cats a:hover span:last-child { text-decoration: underline; }
.nav__mega-thumb {
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius-sm);
  object-fit: cover;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.nav__mega-thumb--ph {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 0.9rem;
}
.nav__mega-empty { color: var(--muted); font-size: 0.9rem; }

/* The wordmark plaque sits on the light paper, not on the dark block, so it
   must opt out of the footer's link colour — `.site-footer a` would otherwise
   out-specify `.footer__brand` and wash the first word out to near-invisible
   cream on cream. */
.site-footer .footer__brand,
.site-footer .footer__brand:hover { color: var(--ink); }
.site-footer .footer__brand .brand__text em { color: var(--accent); }

/* The footer nav falls back to the header's own nav markup, so give those
   items the footer's spacing and drop the hover underline animation. */
.footer__nav .nav__item { display: inline-flex; }
.footer__nav .nav__link { font-size: 0.92rem; }
.footer__nav .nav__link::after { display: none; }
.footer__nav .nav__submenu { background: var(--surface); border-color: var(--line); }
.footer__nav .nav__submenu a { color: var(--ink); }

/* ===========================================================================
 * Product page — "Food details" (phone layout after the reference mock-up).
 *
 * Appended last on purpose: it re-styles rules defined earlier in this file,
 * and at equal specificity the later rule wins. Selectors are prefixed with
 * `.pdp` where they override a bare class, so they also win on specificity
 * against the earlier mobile block and cannot be undone by source order.
 *
 * Nothing here changes what the page DOES — the same form, the same field
 * names, the same price-model maths. It is layout, surface and type.
 * ======================================================================== */

/* ---- All widths ---------------------------------------------------------- */
.pdp__titlerow {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}
.pdp__titlerow h1 { flex: 1; min-width: 0; margin: 0; }
.pdp__qty { flex: none; margin-top: 0.2rem; }
.pdp__label {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  margin: 1.25rem 0 0.4rem;
}
.pdp__summary { flex: 1 1 100%; min-width: 0; }
.pdp__count { display: none; margin: 0; }
.pdp__submit-bag { display: none; }
/* The photo's own controls exist for the phone, where there is no header
 * beside the photograph to carry them. */
.pdp__topbar { display: none; }

/* ---- Phone ---------------------------------------------------------------- */
@media (max-width: 63.99rem) {

  /* -- Hero: the dish, edge to edge ------------------------------------------
   * Square and full-bleed, no radius, no lift — the reference opens on the
   * food with nothing framing it. The copy then starts flat underneath rather
   * than riding up over the photo. */
  /* `minmax(0, 1fr)`, not `1fr`. A bare `1fr` is `minmax(auto, 1fr)`, whose
   * floor is the column's min-content width — and the size-tile grid below
   * reports its min-content as every tile side by side (five auto-fit tracks
   * of 4.4rem, ~387px). The column then outgrew the phone, the photo and the
   * copy ran off the right edge, and `overflow-x: clip` on <html> hid the
   * overflow instead of scrolling it, so nothing looked broken except the
   * content itself. */
  .pdp { grid-template-columns: minmax(0, 1fr); }
  .pdp .pdp__stage { position: relative; }
  .pdp .pdp__media {
    margin-inline: calc(-1 * var(--gutter));
    /* Width drives the square, never height. The earlier phone rule gives the
     * frame a viewport-relative height (~63vh), and with a definite height
     * `aspect-ratio` derives the WIDTH from it — a 512px-wide frame on a 375px
     * phone, with the heart button pushed past the edge. Undoing the height
     * hands the ratio back to the stretched width. */
    width: auto;
    height: auto;
    min-height: 0;
    max-height: none;
    aspect-ratio: 1 / 1;
    border-radius: 0;
    box-shadow: none;
  }

  .pdp__topbar {
    display: flex;
    position: absolute;
    z-index: 3;                           /* above the warm scrim */
    inset-block-start: 0.75rem;
    inset-inline: 0.9rem;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
  }
  .pdp__back {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 44px;
    color: #fff;
    text-decoration: none;
    font-family: var(--font-display);
    font-size: 1.1rem;
    font-weight: 600;
    /* Contrast over any photograph: a soft shadow under white type rather than
     * a chip, which would put a box on the food. */
    text-shadow: 0 1px 10px rgb(0 0 0 / 55%);
  }
  .pdp__back svg { filter: drop-shadow(0 1px 6px rgb(0 0 0 / 50%)); }
  /* Back points the way reading goes back — the one icon that should mirror. */
  [dir="rtl"] .pdp__back svg { transform: scaleX(-1); }
  .pdp__topbar-actions { display: flex; gap: 0.6rem; }
  .pdp__wl { margin: 0; }
  .pdp__round {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 0;
    border-radius: 50%;
    background: #fff;
    color: var(--ink);
    box-shadow: var(--shadow);
    cursor: pointer;
  }
  .pdp__round[aria-pressed="true"] { color: var(--danger); }
  .pdp__round:focus-visible,
  .pdp__back:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

  /* Low stock moves to the lower edge so it never sits under the back link. */
  .pdp .pdp__stock { top: auto; bottom: 2.6rem; }

  /* -- Dots -------------------------------------------------------------------
   * The thumbnail row becomes the reference's dots, laid on the photo. They
   * are still anchors into the snap track — paging works with the script off —
   * and each is a 24px target with the 6px dot drawn inside it, because a 6px
   * link is not something a thumb can hit. */
  .pdp .pdp__thumbs {
    position: absolute;
    z-index: 3;
    inset-inline: 0;
    bottom: 0.6rem;
    display: flex;
    justify-content: center;
    gap: 0.1rem;
    margin: 0;
  }
  .pdp .pdp__thumb {
    position: relative;
    width: 24px;
    height: 24px;
    border: 0;
    border-radius: 0;
    background: none;
    overflow: visible;
  }
  .pdp .pdp__thumb img { display: none; }
  .pdp .pdp__thumb::before {
    content: "";
    position: absolute;
    inset: 50% auto auto 50%;
    width: 7px;
    height: 7px;
    border-radius: 999px;
    background: rgb(255 255 255 / 60%);
    transform: translate(-50%, -50%);
    transition: width 0.2s var(--ease), background 0.2s var(--ease);
  }
  .pdp .pdp__thumb.is-active::before { width: 16px; background: #fff; }

  /* -- The sheet --------------------------------------------------------------- */
  /* No z-index: the sheet no longer rides over the photo, and a stacking
   * context here would trap the fixed order bar (z-index 40) inside it — the
   * cards further down the page, hearts and all, then painted over the bar. */
  .pdp .pdp__card { margin-top: 0; position: relative; z-index: auto; }
  .pdp .pdp__body {
    margin-inline: calc(-1 * var(--gutter));
    padding: 1.1rem var(--gutter) 0;
    background: var(--surface);
    border-radius: 0;
    box-shadow: none;
  }
  .pdp__titlerow h1 { font-size: 1.4rem; line-height: 1.25; font-weight: 600; }
  .pdp .pdp__price { font-size: 1.1rem; margin: 0.35rem 0 0; }

  /* Stepper as the reference draws it: one bordered box, the count between. */
  .pdp__qty {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--surface);
    padding: 0;
  }
  .pdp__qty .stepper__btn {
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: 0;
    background: none;
    color: var(--ink);
  }
  .pdp__qty .stepper__input {
    width: 2.25rem;
    border: 0;
    border-inline: 1px solid var(--line);
    height: 40px;
    text-align: center;
    font-weight: 600;
    background: none;
  }

  /* Description as plain supporting copy, not a standfirst. */
  .pdp .pdp__desc { max-width: none; font-size: 0.92rem; line-height: 1.65; color: var(--muted); }
  .pdp .pdp__desc > :first-child { font-size: inherit; line-height: inherit; color: inherit; }

  /* -- Option groups: one card each ---------------------------------------- */
  .pdp .pdp__form { max-width: none; gap: 0.9rem; margin-top: 1.1rem; }
  .pdp .cfg,
  .pdp .cfg[open] {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: none;
    padding: 0;
    margin: 0;
  }
  .pdp .cfg > .cfg__head,
  .pdp .cfg[open] > .cfg__head {
    margin: 0;
    padding: 0.85rem 1rem;
    background: var(--surface);
    box-shadow: none;
    border-radius: var(--radius);
  }
  .pdp .cfg[open] > .cfg__head {
    border-bottom: 1px solid var(--line);
    border-end-start-radius: 0;
    border-end-end-radius: 0;
  }
  /* Question above, its terms under it. */
  .pdp .cfg__ask { flex-direction: column; align-items: flex-start; gap: 0.15rem; }
  .pdp .cfg__title { font-size: 1rem; font-weight: 600; }
  .pdp .cfg__need,
  .pdp .cfg__need--must { color: var(--muted); font-size: 0.78rem; }
  .pdp .cfg .cfg__list { padding: 0.9rem 1rem 1rem; }
  .pdp .combo-slot { padding-inline: 1rem; }
  /* A package's contents sit in the same inset as a combo's slots — they ran
   * to the card's edges and against the header's rule, where a slot has its
   * "1 of 3" line to hold them off it. */
  .pdp .combo-grid--fixed { padding: 0.75rem 1rem 0.9rem; }
  /* A nested group sits inside a card already. */
  .pdp .cfg--nested,
  .pdp .cfg--nested[open] { border: 0; border-radius: 0; }
  .pdp .cfg--nested > .cfg__head { padding-inline: 0; border-bottom: 0; }
  .pdp .cfg--nested .cfg__list { padding-inline: 0; }

  /* -- Size tiles ------------------------------------------------------------
   * A short single-answer group — sizes — as a row of equal tiles: picture,
   * name, then the price in its own small pill. Chosen: the tile's border and
   * that pill take the accent, the tile itself stays white. */
  .pdp .cfg__list--pills {
    display: grid;
    /* `min(4.4rem, 100%)` so the track floor can never exceed the list itself,
     * even before the column above has a definite width. */
    /* 4.1rem: four tiles plus gaps must fit the ~306px inside a card on a
     * 375px phone; at 4.4rem they came up 2px short and wrapped to three. */
    grid-template-columns: repeat(auto-fit, minmax(min(4.1rem, 100%), 1fr));
    gap: 0.5rem;
  }
  .pdp .cfg__row--pill {
    flex-direction: column;
    justify-content: flex-start;
    align-items: center;
    gap: 0.35rem;
    min-height: 0;
    padding: 0.75rem 0.35rem 0.6rem;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--surface);
    color: var(--ink);
    text-align: center;
  }
  .pdp .cfg__row--pill .cfg__thumb { display: block; width: 2.3rem; height: 2.3rem; border-radius: 50%; }
  .pdp .cfg__row--pill .cfg__name { flex: none; font-size: 0.85rem; font-weight: 600; line-height: 1.2; }
  .pdp .cfg__row--pill .cfg__price {
    margin-top: auto;
    padding: 0.12rem 0.55rem;
    border: 1px solid var(--line);
    border-radius: 6px;
    color: var(--ink);
    font-size: 0.75rem;
    font-weight: 600;
  }
  .pdp .cfg__row--pill:has(input:checked) {
    background: var(--surface);
    color: var(--ink);
    border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);
  }
  .pdp .cfg__row--pill:has(input:checked) .cfg__price {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-contrast, #fff);
    opacity: 1;
  }

  /* -- Topping chips ------------------------------------------------------------
   * A multi-answer group as two columns of rounded chips: name, price, and the
   * checkbox at the trailing end, where the reference puts it. */
  .pdp .cfg__list:has(> li > .cfg__row > input[type="checkbox"]) {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.55rem;
  }
  .pdp .cfg__row {
    gap: 0.5rem;
    padding: 0.6rem 0.7rem;
    border-radius: 12px;
  }
  .pdp .cfg__row input { order: 9; }
  .pdp .cfg__row::before { display: none; }
  .pdp .cfg__row .cfg__name { font-size: 0.88rem; line-height: 1.25; }
  .pdp .cfg__row .cfg__price { color: var(--ink); font-size: 0.8rem; font-weight: 600; }

  /* -- The bar ------------------------------------------------------------------
   * Floating, rounded, in the accent — the reference's single strongest object
   * below the photo. The accent is the merchant's (settings.accent_color), so
   * the text uses --accent-contrast rather than assuming white will read. */
  .pdp .pdp__actions {
    inset-inline: 0.75rem;
    bottom: calc(0.75rem + env(safe-area-inset-bottom));
    padding-block: 0.55rem;
    padding-inline: 1rem 0.55rem;
    border: 0;
    border-radius: 16px;
    background: var(--accent);
    background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 82%, #fff) 0%, var(--accent) 100%);
    color: var(--accent-contrast, #fff);
    box-shadow: 0 12px 28px -10px color-mix(in srgb, var(--accent) 70%, transparent);
    flex-wrap: nowrap;
    gap: 0.75rem;
  }
  .pdp .pdp__summary { flex: 1 1 auto; }
  .pdp .pdp__count {
    display: block;
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 600;
    color: inherit;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .pdp .pdp__plate { color: inherit; opacity: 0.85; font-size: 0.75rem; }
  .pdp .pdp__submit {
    flex: none;
    min-height: 48px;
    padding: 0.65rem 0.95rem;
    border: 0;
    border-radius: 12px;
    background: rgb(255 255 255 / 22%);
    color: inherit;
    box-shadow: inset 0 0 0 1px rgb(255 255 255 / 28%);
  }
  .pdp .pdp__submit-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .pdp .pdp__submit-total {
    border: 0;
    padding: 0;
    opacity: 1;
    font-size: 1.1rem;
    font-weight: 700;
  }
  .pdp .pdp__submit-bag { display: inline-flex; }
  /* Not everything required is answered yet: the bar goes grey and flat so it
   * reads as "not yet", and the button stops taking presses (theme.js). */
  /* The primary colour at half strength — still the brand's bar, visibly not
   * ready. Mixed into the page colour rather than `opacity`, which would let
   * the content scrolling underneath show through. */
  .pdp .pdp__actions.is-incomplete {
    background: color-mix(in srgb, var(--accent) 50%, var(--surface));
    box-shadow: none;
  }
  .pdp .pdp__actions.is-incomplete .pdp__submit { opacity: 0.7; }
  /* Clears the floating bar — at the END of the page, where it would otherwise
   * cover the footer's last line. On the product itself it only left an empty
   * band before the sections that follow it. */
  /* The breathing room lives inside the white sheet, so the sheet runs to the
   * bottom of the product instead of stopping short on the page ground. */
  .pdp { padding-bottom: 0; }
  .pdp .pdp__body { padding-bottom: 1.5rem; }
  .section:has(> * > .pdp, > .pdp) { padding-bottom: 0; }
  body:has(.pdp) { padding-bottom: 6.75rem; }
}

/* ---- Phone: the dish name and quantity stay on screen ----------------------
 * Pinned under the site header while the options scroll, on white with a rule
 * under it, so "what am I ordering, how many" never scrolls away while the
 * questions below it are being answered. Full-bleed, so the band reads as a bar
 * rather than a box floating inside the gutter.
 *
 * The groups' own sticky headers then have to stop BELOW it rather than at the
 * same line, or the two would stack on top of each other. theme.js publishes
 * this bar's height as --pdp-title-h (0 wherever it isn't sticky), and the
 * focus scroll-padding takes it into account for the same reason. */
/* ---- Price pill and the quantity in the bar (PLUS) --------------------------
 * The pill beside the name is the phone's; wider screens keep the price line. */
.pdp__pill { display: none; }
.pdp__actions .pdp__qty { margin-top: 0; }
@media (max-width: 63.99rem) {
  .pdp__pill {
    display: inline-block;
    flex: none;
    align-self: flex-start;
    margin-top: 0.2rem;
    padding: 0.3rem 0.6rem;
    border-radius: 8px;
    background: var(--accent);
    color: var(--accent-contrast, #fff);
    font-weight: 600;
    font-size: 0.9rem;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
  }
  /* The pill already says the price: the line below keeps only the sale
   * story, and goes when there is none. */
  .pdp .pdp__price > span:first-child { display: none; }
  .pdp .pdp__price:not(:has(s)) { display: none; }

  /* The stepper at the start of the bar, drawn on the accent. */
  .pdp .pdp__actions { gap: 0.6rem; padding-inline-start: 0.55rem; }
  .pdp .pdp__actions .pdp__qty {
    order: -1;
    flex: none;
    border-color: rgb(255 255 255 / 35%);
    background: rgb(255 255 255 / 14%);
    color: inherit;
  }
  .pdp .pdp__actions .pdp__qty .stepper__btn { width: 34px; height: 40px; background: transparent; color: inherit; }
  .pdp .pdp__actions .pdp__qty .stepper__input {
    width: 2rem;
    border-inline-color: rgb(255 255 255 / 35%);
    background: transparent;
    color: inherit;
  }
  /* Two rows rather than three things squeezed on one: what's on the plate
   * across the top in small type, then — as PLUS has it — the stepper and a
   * wide button that says what it does and what it costs. */
  .pdp .pdp__actions {
    flex-wrap: wrap;
    row-gap: 0.4rem;
    padding: 0.55rem 0.55rem 0.55rem;
  }
  .pdp .pdp__actions .pdp__summary {
    order: -2;
    flex: 1 1 100%;
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    min-width: 0;
    padding-inline: 0.45rem;
  }
  .pdp .pdp__actions .pdp__count { flex: none; font-size: 0.82rem; }
  .pdp .pdp__actions .pdp__plate { flex: 1 1 auto; min-width: 0; }
  .pdp .pdp__actions .pdp__submit {
    flex: 1 1 auto;
    justify-content: space-between;
    min-height: 44px;
    border-radius: 10px;             /* the stepper's corners */
  }
  .pdp .pdp__actions .pdp__submit-label {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    clip-path: none;
    font-weight: 600;
  }
  .pdp .pdp__actions .pdp__qty .stepper__btn { height: 44px; }
  .pdp .pdp__actions .pdp__qty .stepper__input { height: 44px; }
  .pdp .pdp__actions .pdp__submit-bag { display: none; }
  body:has(.pdp) { padding-bottom: 8.5rem; }
}

/* Not orderable here: said with room around it, not jammed under the title
 * bar's rule. */
.pdp__unavailable {
  margin: 1rem 0 0.25rem;
  padding: 0.65rem 0.85rem;
  border-radius: 10px;
  background: color-mix(in srgb, var(--danger) 10%, var(--surface));
  color: var(--danger);
  font-weight: 600;
  font-size: 0.9rem;
}

/* ---- Phone: page transitions, the PLUS (Ionic) way --------------------------
 * Cross-document view transitions: the browser snapshots the old page and
 * animates to the new one on an ordinary link. No framework, no router — and
 * where it isn't supported, or the device asks for less motion, navigation is
 * simply instant, as before.
 *
 * Forward pushes the new page in from the trailing edge while the old one
 * drifts a little the other way and dims; back is the mirror. Which one is
 * decided in the head of layout/theme.liquid (the `pagereveal` script), which
 * tags the transition "back" or "forward". RTL flips the direction through
 * --vt-dir so Arabic pushes from the left. */
@media (max-width: 63.99rem) and (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
:root { --vt-dir: 1; --vt-ease: cubic-bezier(0.32, 0.72, 0, 1); --vt-time: 0.34s; }
:root[dir="rtl"] { --vt-dir: -1; }

@keyframes vt-push-in   { from { transform: translateX(calc(100% * var(--vt-dir))); } }
@keyframes vt-push-out  { to   { transform: translateX(calc(-30% * var(--vt-dir))); filter: brightness(0.85); } }
@keyframes vt-pop-in    { from { transform: translateX(calc(-30% * var(--vt-dir))); filter: brightness(0.85); } }
@keyframes vt-pop-out   { to   { transform: translateX(calc(100% * var(--vt-dir))); } }

::view-transition-group(root) { animation-duration: var(--vt-time); }
::view-transition-old(root) { animation: var(--vt-time) var(--vt-ease) both vt-push-out; }
::view-transition-new(root) { animation: var(--vt-time) var(--vt-ease) both vt-push-in; z-index: 1; }
/* Back: the page on top is the one leaving. */
html:active-view-transition-type(back)::view-transition-old(root) { animation-name: vt-pop-out; z-index: 1; }
html:active-view-transition-type(back)::view-transition-new(root) { animation-name: vt-pop-in; z-index: 0; }

/* The cart line's stepper, drawn as the product page draws its own: one
 * bordered box with square-cornered buttons and the count between rules — so
 * "how many" looks the same wherever it is asked. */
.cart-line .stepper {
  display: inline-flex;
  align-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  overflow: hidden;
}
.cart-line .stepper__btn {
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--ink);
}
.cart-line .stepper__input {
  width: 2.25rem;
  height: 40px;
  border: 0;
  border-inline: 1px solid var(--line);
  border-radius: 0;
  background: none;
  text-align: center;
  font-weight: 600;
}

/* ---- Phone: the order screen -----------------------------------------------
 * The cart as a screen of its own, like the dish and like PLUS's ticket: no
 * store header or footer, the title pinned at the top with a way back, and
 * the totals with "Add item" / "Place order" fixed at the bottom. The page's
 * own total and button stand down on a phone, since the footer carries both. */
.cart-bar,
.cart-foot { display: none; }
@media (max-width: 63.99rem) {
  body:has(.cart-page) .topbar,
  body:has(.cart-page) .site-header,
  body:has(.cart-page) .subbar,
  body:has(.cart-page) .site-footer { display: none; }

  .cart-page.section { padding-top: 0; }
  .cart-bar {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 3.5rem;
    margin-bottom: 1rem;
    padding: 0.75rem var(--gutter);
    background: var(--surface);
    border-bottom: 1px solid var(--line);
  }
  .cart-bar__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--accent);
  }
  .cart-bar__close {
    position: absolute;
    inset-inline-end: var(--gutter);
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    color: var(--accent);
  }

  .cart-page .cart__total,
  .cart-page .cart__place { display: none; }

  /* Delivery type and payment as the product page asks its questions: each
   * a white card, one choice per row with the radio at the end, the chosen
   * row in the accent. The hints' inline negative margins (written for the
   * desktop column) are overridden, since here they would ride up into the
   * card above. With the script, the delivery type applies on change, so its
   * Apply button stands down (theme.js, .is-autoapply). */
  /* One column here: the desktop's column gap (2–4rem) plus the lines' own
   * bottom margin left an empty band between the order and its questions. */
  .cart-page .cart { gap: 0; }
  .cart-page .cart__lines { margin-bottom: 0; }
  .cart-page .cart__side-title { margin: 1.5rem 0.2rem 0.6rem; font-size: 1rem; }
  .cart-page aside form {
    margin: 0;
    padding: 0.2rem 0.9rem;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 16px;
  }
  .cart-page aside .radio-list { gap: 0; margin: 0; }
  .cart-page aside .radio-list li + li { border-top: 1px solid var(--line); }
  .cart-page aside .radio-row {
    justify-content: space-between;
    min-height: 3.1rem;
    padding: 0.4rem 0;
    font-size: 0.92rem;
  }
  .cart-page aside .radio-row input { order: 9; }
  .cart-page aside .radio-row:has(input:checked) { color: var(--accent); }
  .cart-page aside form .btn { width: 100%; margin: 0.35rem 0 0.8rem !important; }
  .cart-page aside form.is-autoapply .btn { display: none; }
  .cart-page aside form .field__hint {
    margin: 0 !important;
    padding: 0.6rem 0 0.7rem;
    border-top: 1px solid var(--line);
    font-size: 0.8rem;
    color: var(--muted);
  }
  .cart-page aside > .field__hint {
    margin: 1.1rem 0 0 !important;
    text-align: center;
    font-size: 0.8rem;
    color: var(--muted);
  }

  .cart-foot {
    display: block;
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 40;
    padding: 0.85rem var(--gutter) calc(0.85rem + env(safe-area-inset-bottom));
    background: var(--surface);
    border-top: 1px solid var(--line);
    box-shadow: 0 -10px 24px -14px rgb(0 0 0 / 22%);
  }
  .cart-foot__rows { margin: 0 0 0.75rem; }
  .cart-foot__rows > div {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    font-size: 0.85rem;
    line-height: 1.6;
  }
  .cart-foot__rows dt { color: var(--muted); }
  .cart-foot__rows dd { margin: 0; font-weight: 600; text-align: end; }
  .cart-foot__total {
    margin-top: 0.3rem;
    padding-top: 0.4rem;
    border-top: 1px dashed var(--line);
    font-size: 1rem !important;
  }
  .cart-foot__total dt,
  .cart-foot__total dd { color: var(--ink); font-family: var(--font-display); font-weight: 700; }
  .cart-foot__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
  .cart-foot__actions .btn { min-height: 48px; border-radius: 10px; justify-content: center; }
  /* Room for the footer, so the last line is not underneath it. */
  body:has(.cart-foot) { padding-bottom: 12rem; }
}

/* The title bar's own back arrow: phone only, and only once the photo — which
 * carries the first one — is out of view (theme.js sets .is-photo-in-view). */
.pdp__titleback { display: none; }
@media (max-width: 63.99rem) {
  .pdp__titleback {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    margin-inline-start: -0.5rem;
    color: var(--ink);
    border-radius: var(--radius-pill);
  }
  [dir="rtl"] .pdp__titleback svg { transform: scaleX(-1); }
  .pdp.is-photo-in-view .pdp__titleback { display: none; }
}

/* The delivery map keeps its layers to itself. Leaflet stacks its panes at
 * z-index 400+ with nothing containing them, so the tiles and the zoom
 * buttons painted over the fixed order bar. A stacking context of its own
 * (z-index 0) keeps all of that inside the map. */
.checkout-page .leaflet-container { position: relative; z-index: 0; }

/* ---- Checkout: the date picker ---------------------------------------------
 * A field that reads "Order now" or the chosen day and time, and a sheet from
 * the bottom with a month calendar and that day's times (theme.js builds
 * both). Theme tokens throughout, so it sits with the rest of the checkout;
 * the sheet lives on <body>, outside the section's own variables. */
/* The native box, kept in the form but out of sight. `!important` on the size:
 * the platform checkout styles its field inputs `width: 100%` with a heavier
 * selector, and an absolutely placed 100%-wide input with no offsets anchors
 * at the start side — in RTL it ran 1400px off the left edge and widened the
 * whole page, shoving the header and every card sideways. */
.sched-native {
  position: absolute !important;
  inset-inline-start: 0;
  width: 1px !important;
  min-width: 0 !important;
  max-width: 1px !important;
  height: 1px !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  overflow: hidden;
  clip-path: inset(50%);
  opacity: 0;
  pointer-events: none;
}
.sched-trigger {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  min-height: 3.15rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.94rem;
  font-weight: 600;
  text-align: start;
  cursor: pointer;
}
.sched-trigger svg { flex: none; color: var(--accent); }
.sched-trigger__text { flex: 1; min-width: 0; }
.sched-trigger::after {
  content: "";
  flex: none;
  width: 0.5rem;
  height: 0.5rem;
  margin-top: -0.25rem;
  border-inline-end: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: rotate(45deg);
}
.sched-trigger.is-set { border-color: var(--accent); }

.sched-sheet {
  width: min(100%, 26rem);
  max-width: 100%;
  max-height: 92vh;
  margin: auto auto 0;
  padding: 0;
  border: 0;
  border-radius: 20px 20px 0 0;
  background: var(--surface);
  color: var(--ink);
  overflow: auto;
}
@media (min-width: 40rem) { .sched-sheet { margin: auto; border-radius: 20px; } }
.sched-sheet::backdrop { background: rgb(0 0 0 / 40%); }
.sched-sheet[open] { animation: sched-up 0.25s var(--ease, ease-out); }
@keyframes sched-up { from { transform: translateY(1.5rem); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .sched-sheet[open] { animation: none; } }
.sched-sheet__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1rem 1.1rem 0.6rem; }
.sched-sheet__title { margin: 0; font-family: var(--font-display); font-size: 1.05rem; font-weight: 700; }
.sched-sheet__x {
  flex: none;
  width: 2.25rem;
  height: 2.25rem;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 6%, var(--surface));
  color: var(--ink);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
}
.sched-cal { padding: 0 1.1rem; }
.sched-cal__nav { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.5rem; }
.sched-cal__month { margin: 0; font-weight: 700; }
.sched-cal__step {
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
}
.sched-cal__step:disabled { opacity: 0.35; cursor: default; }
/* Only the icon turns in RTL (previous on the right pointing right, next on
 * the left pointing left). Flipping the whole button mirrored text glyphs
 * the browser had already mirrored, so both arrows pointed inwards. */
.sched-cal__step svg { display: block; margin: auto; }
[dir="rtl"] .sched-cal__step svg { transform: scaleX(-1); }
.sched-cal__week,
.sched-cal__grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 0.2rem; text-align: center; }
.sched-cal__week span { padding: 0.25rem 0; font-size: 0.75rem; font-weight: 600; color: var(--muted); }
.sched-cal__day {
  aspect-ratio: 1;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.sched-cal__day:disabled { color: color-mix(in srgb, var(--ink) 25%, var(--surface)); cursor: default; }
.sched-cal__day.is-today { box-shadow: inset 0 0 0 1px var(--accent); }
.sched-cal__day[aria-pressed="true"] { background: var(--accent); color: var(--accent-contrast, #fff); box-shadow: none; }
.sched-sheet__label { margin: 1rem 1.1rem 0.5rem; font-size: 0.85rem; font-weight: 700; }
.sched-times {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.4rem;
  max-height: 11rem;
  padding: 0 1.1rem;
  overflow-y: auto;
}
.sched-time {
  min-height: 2.5rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
}
.sched-time[aria-pressed="true"] {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.sched-sheet__foot {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
  padding: 1rem 1.1rem calc(1rem + env(safe-area-inset-bottom));
}
.sched-sheet__foot .btn { min-height: 48px; border-radius: 10px; justify-content: center; }
.sched-sheet__foot .btn:disabled { opacity: 0.5; }

/* ---- Checkout: the delivery location card -----------------------------------
 * Where it is going, and one button to change it (the first page's panel).
 * The coverage message sits on the card, beside the button that fixes it.
 * The embedded map folds away when the first step already pinned a point;
 * its hidden fields still post. */
.co-loc {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0 0 1rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
}
.co-loc--out { border-color: color-mix(in srgb, var(--danger) 45%, var(--line)); background: color-mix(in srgb, var(--danger) 5%, var(--surface)); }
.co-loc__icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  color: var(--accent);
}
.co-loc--out .co-loc__icon { background: color-mix(in srgb, var(--danger) 12%, var(--surface)); color: var(--danger); }
.co-loc__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.co-loc__label { font-size: 0.78rem; color: var(--muted); }
.co-loc__value { font-size: 0.95rem; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.co-loc__error { margin-top: 0.15rem; font-size: 0.82rem; font-weight: 600; color: var(--danger); }
.co-loc__change {
  flex: none;
  min-height: 2.5rem;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--accent);
  border-radius: 10px;
  background: var(--surface);
  color: var(--accent);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}
.co-map--folded { display: none; }

/* ---- Phone: the checkout screen --------------------------------------------
 * The order screen's shape, one step on: no store header or footer, the title
 * pinned at the top with the arrow back to the order (the cart's bar, arrow at
 * the start), and "Place order" fixed at the bottom on white — the cart's
 * footer, not the section's own fade-out sticky strip.
 *
 * `.checkout-page`-prefixed where the section's own inline styles would
 * otherwise win: they come after this file in the page. */
@media (max-width: 63.99rem) {
  body:has(.checkout-page) .topbar,
  body:has(.checkout-page) .site-header,
  body:has(.checkout-page) .subbar,
  body:has(.checkout-page) .site-footer { display: none; }

  .checkout-page.checkout-page { padding-top: 0; }
  .cart-bar--back .cart-bar__close { inset-inline-start: var(--gutter); inset-inline-end: auto; }
  [dir="rtl"] .cart-bar--back .cart-bar__close svg { transform: scaleX(-1); }
  /* Edge to edge: the checkout section sits inside main.container, whose
   * gutter padding otherwise insets the bar on both sides. */
  .checkout-page .cart-bar { margin: 0 calc(-1 * var(--gutter)) 1rem; }

  /* The order screen's look, carried on: the theme's page ground rather than
   * the section's own tinted gradient, plain white cards with the theme's
   * line and 16px corners, no drop shadows, no accent strips or heading rings.
   * The section draws everything through --co-* variables, so pointing those
   * at the theme's tokens does most of it. Doubled class: the section's own
   * <style> comes after this file. */
  .checkout-page.checkout-page {
    --co-page: transparent;
    --co-card: var(--surface);
    --co-card-soft: color-mix(in srgb, var(--ink) 4%, var(--surface));
    --co-border: var(--line);
    --co-border-strong: var(--line-2, var(--line));
    --co-ink: var(--ink);
    --co-muted: var(--muted);
    --co-accent: var(--accent);
    --co-accent-ink: var(--accent-contrast, #fff);
    --co-accent-soft: color-mix(in srgb, var(--accent) 10%, var(--surface));
    --co-shadow: none;
    --co-shadow-soft: none;
    background: none;
    min-height: 0;
    font-family: inherit;
  }
  /* One gutter, as the order screen has: the section pads its own container
   * inside main.container, which already pads — the cards sat twice as far
   * from the edge as the cart's. */
  .checkout-page.checkout-page .container { padding-inline: 0; }
  .checkout-page .co-block,
  .checkout-page .co-summary,
  .checkout-page .co-context {
    padding: 1rem;
    border-radius: 16px;
    box-shadow: none;
  }
  .checkout-page .co-block { margin-bottom: 0.9rem; }
  .checkout-page .co-block::before,
  .checkout-page .co-summary::before,
  .checkout-page .co-block > h2::before { display: none; }
  .checkout-page .co-block > h2 { font-family: var(--font-display); font-size: 1rem; }
  .checkout-page .co-grid { gap: 0.9rem; }
  .checkout-page .co-summary { margin-bottom: 0; }

  /* Choice lists — delivery method, delivery zones, shipping rates, payment —
   * as the order screen draws them, PLUS-style: one white card, one choice per
   * row with a rule between, the name first and the radio at the end, centred,
   * the chosen row in the accent. Replaces a grey segmented box that stacked
   * into a tall slab on a phone, and a stack of separate boxes with the radio
   * pinned to the top corner. The section's rules for these carry !important,
   * so these do too, one class stronger. */
  /* Flush inside the block's own card — a bordered list inside a bordered
   * card read as a box in a box. */
  .checkout-page #delivery-method,
  .checkout-page .co-block .co-lines {
    display: block;
    margin: 0 0 1rem;
    padding: 0;
    background: none;
    border: 0;
    border-radius: 0;
  }
  .checkout-page .co-block .co-lines:last-child { margin-bottom: 0; }
  .checkout-page .co-block .co-lines > li + li,
  .checkout-page #delivery-method > .co-choice + .co-choice,
  .checkout-page .co-shipping-option + .co-shipping-option { border-top: 1px solid var(--line) !important; }
  /* Doubled class: the section's own `:has(input:checked)` rule is as strong
   * as a single-class one and comes later, and drew a box around the chosen
   * row. */
  .checkout-page.checkout-page .co-block .co-lines > li > label,
  .checkout-page.checkout-page .co-block .co-lines > li > label:has(input:checked),
  .checkout-page.checkout-page .co-block .co-shipping-option,
  .checkout-page.checkout-page .co-block .co-shipping-option:has(input:checked),
  .checkout-page #delivery-method > .co-choice {
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    gap: 0.75rem !important;
    min-height: 3.1rem;
    margin: 0 !important;
    padding: 0.55rem 0 !important;
    background: none !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    transform: none !important;
    font-size: 0.92rem;
    font-weight: 600;
    text-align: start;
  }
  .checkout-page .co-block .co-lines > li > label > :not(input),
  .checkout-page .co-block .co-shipping-option > :not(input) { flex: 1; min-width: 0; }
  .checkout-page .co-block .co-lines > li > label > input,
  .checkout-page .co-block .co-shipping-option > input,
  .checkout-page #delivery-method > .co-choice > input {
    order: 9;
    width: 1.15rem;
    height: 1.15rem;
    margin: 0 !important;
    accent-color: var(--accent);
  }
  .checkout-page .co-block .co-lines > li > label:has(input:checked),
  .checkout-page .co-block .co-shipping-option:has(input:checked),
  .checkout-page #delivery-method > .co-choice:has(input:checked) { color: var(--accent); }

  /* The page's own headline says what the bar already says. */
  .checkout-page .co-page-header > div:first-child { display: none; }
  .checkout-page .co-page-header { margin-bottom: 1rem; }
  .checkout-page .co-context { margin-top: 0; }

  .checkout-page .co-submit-area {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 40;
    margin: 0;
    padding: 0.85rem var(--gutter) calc(0.85rem + env(safe-area-inset-bottom));
    background: var(--surface);
    border-top: 1px solid var(--line);
    box-shadow: 0 -10px 24px -14px rgb(0 0 0 / 22%);
  }
  .checkout-page .co-submit { min-height: 48px; border-radius: 10px; }
  .checkout-page .co-submit:hover { transform: none; }
  .checkout-page .co-trust-note { margin: 0.45rem 0 0 !important; text-align: center; }
  body:has(.checkout-page) { padding-bottom: 7.5rem; }
}

/* ---- Phone: the dish full screen -------------------------------------------
 * A food app's detail screen is the dish and nothing else: no store header,
 * no footer. The photo's own bar already has back, share and save, and now
 * the bag — the one thing the header gave this page that it still needs. */
.pdp__cart { display: none; }
@media (max-width: 63.99rem) {
  body:has(.pdp) .topbar,
  body:has(.pdp) .site-header,
  body:has(.pdp) .subbar,
  body:has(.pdp) .site-footer { display: none; }

  .pdp__cart { display: inline-flex; position: relative; color: inherit; }
  .pdp__cart-count {
    position: absolute;
    top: -0.2rem;
    inset-inline-end: -0.2rem;
    min-width: 1.15rem;
    padding: 0 0.25rem;
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: var(--accent-contrast, #fff);
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1.15rem;
    text-align: center;
  }
}

/* The button refuses a press while something required is unanswered. */
.pdp__actions.is-incomplete .pdp__submit { opacity: 0.55; cursor: not-allowed; }

@media (max-width: 63.99rem) {
  /* On a phone the dish's own bar is the one that stays: the site header
   * scrolls away here, so the title bar pins to the very top instead of
   * stacking under it. theme.js reads the header as not stuck and --stuck-top
   * drops to 0, which everything below already follows. */
  body:has(.pdp) .site-header--sticky { position: relative; }
  .pdp .pdp__titlerow {
    position: sticky;
    top: var(--stuck-top, 0px);
    z-index: 5;
    align-items: center;
    margin-inline: calc(-1 * var(--gutter));
    padding: 0.7rem var(--gutter);
    background: var(--surface);
    border-bottom: 1px solid var(--line);
  }
  .pdp .cfg > .cfg__head { top: calc(var(--stuck-top, 0px) + var(--pdp-title-h, 0px)); }
  html { scroll-padding-top: calc(var(--stuck-top, 0px) + var(--pdp-title-h, 0px) + 1rem); }
}

/* ---- Phone: combo picks as rows ---------------------------------------------
 * One option per line — thumbnail at the start, name beside it, the tick at the
 * end — instead of photo tiles two to a row. On a phone the tiles were mostly
 * empty picture frames (many items carry no photo) and a three-slot combo ran
 * to several screens; as rows the whole slot fits in a glance, and the name
 * gets the full width instead of wrapping inside half of it. */
@media all {
  .pdp .combo-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.5rem;
  }
  .pdp .combo-tile {
    flex-direction: row;
    align-items: center;
    gap: 0.75rem;
    min-height: var(--tap-min, 3rem);
    padding: 0.4rem;
    padding-inline-end: 2.6rem;           /* room for the trailing tick */
    border-radius: 12px;
  }
  .pdp .combo-tile__media {
    flex: none;
    width: 3.25rem;
    aspect-ratio: 1 / 1;
    border-radius: 8px;
    overflow: hidden;
  }
  .pdp .combo-tile__ph svg { width: 18px; height: 18px; }
  .pdp .combo-tile__body { flex: 1; min-width: 0; padding: 0; }
  .pdp .combo-tile__name { font-size: 0.92rem; }
  /* The tick moves off the thumbnail — at 52px it covered most of the picture —
   * to the row's trailing edge, where a chosen line is marked. */
  .pdp .combo-tile:has(input:checked) .combo-tile__media::after { display: none; }
  .pdp .combo-tile:has(input:checked)::after {
    content: "";
    position: absolute;
    inset-inline-end: 0.8rem;
    top: 50%;
    width: 1.3rem;
    height: 1.3rem;
    margin-top: -0.65rem;
    border-radius: 50%;
    background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / 0.8rem no-repeat;
  }
}

/* ---- A pick's own questions, under the pick --------------------------------
 * One generic rule replaces the per-item <style> blocks: the questions sit in
 * the same cell as the tile they belong to, and open when that tile is picked. */
.combo-cell > .combo-sub { display: none; margin: 0.5rem 0 0.35rem; }
.combo-cell:has(> .combo-tile input:checked) > .combo-sub { display: block; }
/* A package's contents have no pick to wait for: their questions are open. */
.combo-cell > .combo-sub--open { display: block; }

/* Their options as rows — name, price, tick at the end, one per line — not the
 * size tiles, which inside a nested box folded "+ BHD 1" onto three lines. */
.pdp .cfg--nested .cfg__list--pills {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.pdp .cfg--nested .cfg__row--pill {
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: 0.6rem;
  min-height: var(--tap-min, 3rem);
  padding-block: 0.55rem;
  padding-inline: 0.8rem 2.6rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  text-align: start;
  box-shadow: none;
}
/* A nested multi-answer list too: one option per line. The two-column topping
 * chips, inside an indented nested box, left each chip ~110px — "no sauce
 * [en] + BHD 1" folded onto three lines beside its box. */
.pdp .cfg--nested .cfg__list:has(> li > .cfg__row > input[type="checkbox"]) {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding-bottom: 0.5rem;
}
.pdp .cfg--nested .cfg__row:has(> input[type="checkbox"]) {
  align-items: center;
  min-height: var(--tap-min, 3rem);
  padding: 0.55rem 0.8rem;
}
.pdp .cfg--nested .cfg__row:has(> input[type="checkbox"]) .cfg__name { flex: 1; font-size: 0.9rem; font-weight: 500; }
.pdp .cfg--nested .cfg__row:has(> input[type="checkbox"]) .cfg__price { white-space: nowrap; }
.pdp .cfg--nested .cfg__row--pill .cfg__thumb { width: 2rem; height: 2rem; border-radius: 6px; }
.pdp .cfg--nested .cfg__row--pill .cfg__name { flex: 1; font-size: 0.9rem; font-weight: 500; }
.pdp .cfg--nested .cfg__row--pill .cfg__price {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}
.pdp .cfg--nested .cfg__row--pill:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  color: var(--ink);
  box-shadow: none;
}
.pdp .cfg--nested .cfg__row--pill:has(input:checked) .cfg__price {
  background: none;
  color: var(--ink);
}
.pdp .cfg--nested .cfg__row--pill:has(input:checked)::after {
  content: "";
  position: absolute;
  inset-inline-end: 0.75rem;
  top: 50%;
  width: 1.2rem;
  height: 1.2rem;
  margin-top: -0.6rem;
  border-radius: 50%;
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / 0.75rem no-repeat;
}

/* ---- Combo slots, one at a time (after the PLUS app) ------------------------
 * The script adds `.is-stepped` to a multi-slot combo and `.is-away` to every
 * slot except the one being answered.
 *
 * `.is-away` hides VISUALLY, never with display:none. The running total, the
 * item count and the plate line only count controls that are rendered (they
 * test offsetParent, to skip the questions of items nobody picked), so a
 * display:none slot would silently drop an already-made pick from the price.
 * Clipped to nothing and taken out of flow, it stays counted and posted. */
.combo-steps { position: relative; }
.combo-steps.is-stepped > .combo-slot.is-away {
  position: absolute;
  top: 0;
  inset-inline-start: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  visibility: hidden;
  pointer-events: none;
}
.combo-slot__actions { display: flex; justify-content: flex-end; margin-top: 0.75rem; }
.combo-slot__add[disabled] { opacity: 0.45; cursor: not-allowed; }

/* The slot that just became current settles in rather than snapping into
 * place — a small cue that the step moved on, not just that the DOM changed.
 * Keyed to the class leaving `.is-away`, so it plays once per step and never
 * replays while the shopper is only answering something inside the slot
 * that's already on screen. */
.combo-steps.is-stepped > .combo-slot:not(.is-away) {
  animation: combo-slot-in 0.32s ease both;
}
@keyframes combo-slot-in {
  from { opacity: 0; transform: translateY(10px); }
}
@media (prefers-reduced-motion: reduce) {
  .combo-steps.is-stepped > .combo-slot:not(.is-away) { animation: none; }
}

/* The strip of picks already made — tap one to reopen its slot. Bottom
 * padding matches a slot's own (0.9rem): once every slot is answered, this
 * is the last thing in the card, and 0.3rem here — plenty while an open
 * slot followed right after — left the "Your choices" list sitting almost
 * flush against the card's edge. */
.combo-chosen { padding: 0.8rem 1rem 0.9rem; }
.combo-chosen__row {
  display: flex;
  gap: 0.6rem;
  overflow-x: auto;
  padding-bottom: 0.25rem;
  scrollbar-width: none;
}
.combo-chosen__row::-webkit-scrollbar { display: none; }
.combo-chip {
  position: relative;
  flex: none;
  width: 3.6rem;
  height: 3.6rem;
  padding: 0;
  border: 2px solid var(--line);
  border-radius: 12px;
  background: var(--surface-2);
  overflow: hidden;
  cursor: pointer;
}
.combo-chip.is-current { border-color: var(--accent); }
.combo-chip:focus-visible,
.combo-done__row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.combo-chip__thumb { position: absolute; inset: 0; }
.combo-chip__thumb .combo-tile__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  aspect-ratio: auto;
  margin: 0;
  border-radius: 0;
}
.combo-chip__thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.combo-chip__n {
  position: absolute;
  inset-block-start: 0.2rem;
  inset-inline-start: 0.2rem;
  min-width: 1.15rem;
  height: 1.15rem;
  padding: 0 0.25rem;
  border-radius: 999px;
  background: var(--dark);
  color: var(--on-dark);
  font-size: 0.65rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.combo-chosen__hint { margin: 0.35rem 0 0; font-size: 0.75rem; color: var(--muted); }
.combo-chosen__title {
  margin: 0 0 0.55rem;
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 600;
}

/* "Your choices" — every slot answered. Each row reopens its slot. */
.combo-done { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.combo-done__row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  min-height: var(--tap-min, 3rem);
  padding: 0.4rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}
.combo-done__row .combo-chip__thumb {
  position: relative;
  flex: none;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface-2);
}
.combo-done__text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.combo-done__name { font-weight: 600; font-size: 0.92rem; }
.combo-done__sub {
  font-size: 0.8rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.combo-done__row::after {
  content: "›";
  flex: none;
  margin-inline-end: 0.35rem;
  color: var(--muted);
  font-size: 1.3rem;
  line-height: 1;
}
[dir="rtl"] .combo-done__row::after { transform: scaleX(-1); }

@media (max-width: 63.99rem) {
  .pdp .combo-slot__add { width: 100%; min-height: var(--tap-min, 3rem); }
}

/* ---- Modify a cart line ------------------------------------------------------ */
.cart-line__modify {
  display: inline-block;
  margin: 0.2rem 0 0.35rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* Edit mode on the product page says so, above the questions it prefilled. */
.pdp__editing {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0 0 0.25rem;
  padding: 0.65rem 0.85rem;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line));
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  font-size: 0.88rem;
}
.pdp__editing a { font-weight: 600; color: var(--accent); white-space: nowrap; }

/* ---- Home: how would you like your order? -----------------------------------
 * The PLUS app's first screen as a row of large buttons — Delivery, Pick up,
 * Dine in, Table reservation (sections/service-buttons). An icon tile, the
 * name, one line of what it means, a chevron; the current service in the
 * accent. One column on a phone, as PLUS stacks them. */
.svc-home { padding-block: clamp(1.5rem, 4vw, 2.5rem); }
.svc-home__title {
  margin: 0 0 1rem;
  text-align: center;
  font-size: clamp(1.15rem, 2.4vw, 1.5rem);
}
.svc-home__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: 0.75rem;
  max-width: 60rem;
  margin-inline: auto;
}
.svc-home__form { display: contents; }
.svc-home__btn {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  width: 100%;
  min-height: 4.75rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  text-align: start;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 0.15s var(--ease, ease), box-shadow 0.15s var(--ease, ease);
}
.svc-home__btn:hover { color: var(--ink); border-color: var(--accent); box-shadow: 0 10px 24px -16px color-mix(in srgb, var(--accent) 65%, transparent); }
.svc-home__btn.is-active { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.svc-home__icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  color: var(--accent);
}
.svc-home__btn.is-active .svc-home__icon { background: var(--accent); color: var(--accent-contrast, #fff); }
.svc-home__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.svc-home__text strong { font-family: var(--font-display); font-size: 1rem; font-weight: 700; }
.svc-home__text small { font-size: 0.8rem; color: var(--muted); }
.svc-home__btn.is-active .svc-home__text small { color: var(--accent); font-weight: 600; }
.svc-home__btn > svg:last-child { flex: none; color: var(--muted); }
[dir="rtl"] .svc-home__btn > svg:last-child { transform: scaleX(-1); }
.svc-home__dinein p { margin: 0; line-height: 1.6; color: var(--ink-soft, var(--ink)); }

/* ---- Home: offer stories ------------------------------------------------------
 * The PLUS offers row as story circles (sections/offer-stories): a ringed
 * photo, the saving on a badge, the dish name under it. A tap opens the
 * viewer — dark, full screen on a phone, a tall card on a wide screen — with
 * progress bars, the saving in a white circle, the dish, and "Order now". */
.stories { padding-block: 0.25rem clamp(1.25rem, 3vw, 2rem); }
.stories__title { margin: 0 0 0.75rem; font-family: var(--font-display); font-size: 1rem; font-weight: 700; }
.stories__row {
  display: flex;
  gap: 0.9rem;
  margin: 0 calc(-1 * var(--gutter));
  padding: 0.25rem var(--gutter) 0.6rem;
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
}
.stories__row::-webkit-scrollbar { display: none; }
.story {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
  width: 5rem;
  color: var(--ink);
  text-decoration: none;
  scroll-snap-align: start;
}
.story:hover { color: var(--ink); }
.story__ring {
  position: relative;
  width: 4.5rem;
  height: 4.5rem;
  padding: 3px;
  border-radius: 50%;
  background: conic-gradient(from 210deg, var(--accent), color-mix(in srgb, var(--accent) 40%, #f2a900), var(--accent));
}
.story__pic {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  border: 3px solid var(--surface);
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface-3, #eee);
  color: var(--muted);
}
.story__pic img { width: 100%; height: 100%; object-fit: cover; }
.story__badge {
  position: absolute;
  bottom: -0.4rem;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.08rem 0.45rem;
  border: 2px solid var(--surface);
  border-radius: var(--radius-pill);
  background: var(--danger);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 700;
  white-space: nowrap;
}
.story__name {
  width: 100%;
  font-size: 0.75rem;
  font-weight: 600;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.story-view {
  width: 100%;
  max-width: 26rem;
  height: 100dvh;
  max-height: 100dvh;
  margin: auto;
  padding: 0;
  border: 0;
  background: #0d0d0d;
  color: #fff;
  overflow: hidden;
}
@media (min-width: 40rem) { .story-view { height: min(46rem, 92dvh); border-radius: 18px; } }
.story-view::backdrop { background: rgb(0 0 0 / 78%); }
.story-view[open] { display: flex; flex-direction: column; }
.story-view__bars { display: flex; gap: 0.3rem; padding: calc(0.75rem + env(safe-area-inset-top)) 0.9rem 0; }
.story-view__bars span { flex: 1; height: 3px; border-radius: 2px; background: rgb(255 255 255 / 30%); overflow: hidden; }
.story-view__bars i { display: block; width: 0; height: 100%; background: #fff; }
.story-view__bars .is-done i { width: 100%; }
.story-view__bars .is-now i { animation: story-fill 5s linear forwards; }
@keyframes story-fill { to { width: 100%; } }
@media (prefers-reduced-motion: reduce) { .story-view__bars .is-now i { animation: none; width: 100%; } }
.story-view__head { position: relative; z-index: 2; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.6rem 0.9rem; }
.story-view__who { font-size: 0.9rem; font-weight: 700; }
.story-view__x {
  width: 2.25rem;
  height: 2.25rem;
  border: 0;
  border-radius: 50%;
  background: rgb(255 255 255 / 14%);
  color: #fff;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
}
.story-view__stage {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 0 1.25rem;
  text-align: center;
}
.story-view__deal {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 8.5rem;
  height: 8.5rem;
  border-radius: 50%;
  background: #fff;
  color: #111;
  box-shadow: 0 10px 30px rgb(0 0 0 / 40%);
}
.story-view__deal strong { font-family: var(--font-display); font-size: 2.2rem; line-height: 1; }
.story-view__deal span { font-size: 1rem; font-weight: 700; }
.story-view__pic { width: 100%; border-radius: 16px; overflow: hidden; }
.story-view__pic img { display: block; width: 100%; max-height: 36vh; object-fit: cover; }
.story-view__title { margin: 0; font-family: var(--font-display); font-size: 1.35rem; font-weight: 700; }
.story-view__price { margin: 0; font-size: 0.95rem; color: rgb(255 255 255 / 85%); }
.story-view__price s { opacity: 0.6; }
.story-view__cta {
  position: relative;
  z-index: 2;
  margin: 0 1.25rem calc(1.1rem + env(safe-area-inset-bottom));
  min-height: 48px;
  border-radius: 12px;
  justify-content: center;
}
.story-view__nav { position: absolute; z-index: 1; top: 4.5rem; bottom: 5.5rem; width: 35%; padding: 0; border: 0; background: none; cursor: pointer; }
.story-view__nav--prev { inset-inline-start: 0; }
.story-view__nav--next { inset-inline-end: 0; }

/* ---- Dialogs: full screen on a phone, and they move ---------------------------
 * The delivery and pickup panels (and the dine-in note, which shares their
 * look) take the whole screen on a phone — the head pinned at the top, the
 * list scrolling under it, the foot at the bottom — rather than a card
 * floating over a dimmed page with the page still showing around it.
 *
 * Every dialog now arrives and leaves: a phone sheet rises from the bottom
 * and drops away; on a wider screen it fades in with a slight scale; the
 * story viewer fades. Done with the browser's own dialog transitions
 * (`@starting-style` + `allow-discrete` on display/overlay), so closing
 * animates too with no script, and a browser without them simply opens and
 * closes instantly, as before. None of it where less motion is asked for. */
@media (max-width: 40rem) {
  .delivery-modal {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    border-radius: 0;
    box-shadow: none;
  }
  .delivery-modal__form { height: 100%; max-height: 100dvh; }
  .delivery-modal__head { padding-top: calc(1.1rem + env(safe-area-inset-top)); }
  .delivery-modal__body { flex: 1; min-height: 0; }
  .delivery-modal__foot { padding-bottom: calc(1rem + env(safe-area-inset-bottom)); }
}

.sched-sheet[open] { animation: none; }         /* the shared transition below replaces it */

@media (prefers-reduced-motion: no-preference) {
  .delivery-modal,
  .sched-sheet,
  .story-view {
    transition:
      opacity 0.28s var(--ease, ease),
      transform 0.32s cubic-bezier(0.32, 0.72, 0, 1),
      overlay 0.32s allow-discrete,
      display 0.32s allow-discrete;
    opacity: 0;
  }
  .delivery-modal[open],
  .sched-sheet[open],
  .story-view[open] { opacity: 1; transform: none; }

  /* Where each one comes from, and goes back to. */
  .delivery-modal,
  .sched-sheet { transform: translateY(0.75rem) scale(0.98); }
  .story-view { transform: scale(0.96); }
  @media (max-width: 40rem) {
    .delivery-modal,
    .sched-sheet { transform: translateY(100%); }
  }
  @starting-style {
    .delivery-modal[open],
    .sched-sheet[open] { opacity: 0; transform: translateY(0.75rem) scale(0.98); }
    .story-view[open] { opacity: 0; transform: scale(0.96); }
  }
  @media (max-width: 40rem) {
    @starting-style {
      .delivery-modal[open],
      .sched-sheet[open] { opacity: 1; transform: translateY(100%); }
    }
  }

  /* The dimmed page fades with it. */
  .delivery-modal::backdrop,
  .sched-sheet::backdrop,
  .story-view::backdrop {
    transition: opacity 0.28s var(--ease, ease), overlay 0.32s allow-discrete, display 0.32s allow-discrete;
    opacity: 0;
  }
  .delivery-modal[open]::backdrop,
  .sched-sheet[open]::backdrop,
  .story-view[open]::backdrop { opacity: 1; }
  @starting-style {
    .delivery-modal[open]::backdrop,
    .sched-sheet[open]::backdrop,
    .story-view[open]::backdrop { opacity: 0; }
  }
}

/* ---- …and every other dialog too ----------------------------------------------
 * The date picker sheet and the service-selector section's panels take the
 * whole screen on a phone as well, and move like the rest. The language and
 * currency switchers are menus under their button, not dialogs — full screen
 * they would cover the very control that closes them — so they stay drop-
 * downs and only get the entrance. */
@media (max-width: 40rem) {
  .sched-sheet {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    border-radius: 0;
  }
  .sched-sheet[open] { display: flex; flex-direction: column; }
  .sched-sheet__head { padding-top: calc(1rem + env(safe-area-inset-top)); }
  .sched-times { flex: 1; min-height: 0; max-height: none; align-content: start; }

  /* The service-selector section (sections/service-widget) — its own inline
   * styles come after this file, hence the doubled class. */
  .service-widget.service-widget .svc-modal { padding: 0; align-items: stretch; }
  .service-widget.service-widget .svc-modal__card {
    max-width: 100%;
    height: 100dvh;
    max-height: 100dvh;
    border-radius: 0;
    box-shadow: none;
    padding-top: calc(1.25rem + env(safe-area-inset-top));
  }
}

@media (prefers-reduced-motion: no-preference) {
  /* The service-selector panels open on :target; `display` transitions
   * discretely, so leaving animates too. */
  .service-widget.service-widget .svc-modal {
    transition: opacity 0.28s var(--ease, ease), display 0.32s allow-discrete;
    opacity: 0;
  }
  .service-widget.service-widget .svc-modal:target { opacity: 1; }
  .service-widget.service-widget .svc-modal__card {
    transition: transform 0.32s cubic-bezier(0.32, 0.72, 0, 1);
    transform: translateY(0.75rem) scale(0.98);
  }
  .service-widget.service-widget .svc-modal:target .svc-modal__card { transform: none; }
  @starting-style {
    .service-widget.service-widget .svc-modal:target { opacity: 0; }
    .service-widget.service-widget .svc-modal:target .svc-modal__card { transform: translateY(0.75rem) scale(0.98); }
  }
  @media (max-width: 40rem) {
    .service-widget.service-widget .svc-modal__card { transform: translateY(100%); }
    @starting-style {
      .service-widget.service-widget .svc-modal:target .svc-modal__card { transform: translateY(100%); }
    }
  }

  /* Header menus: a short drop and fade as they open. */
  details[open] > .popover {
    transition: opacity 0.18s var(--ease, ease), transform 0.2s var(--ease, ease);
    opacity: 1;
    transform: none;
  }
  @starting-style {
    details[open] > .popover { opacity: 0; transform: translateY(-0.35rem); }
  }
}

/* ---- Cover hero (sections/hero-cover) -----------------------------------------
 * The page-builder cover: colour / gradient / image / video ground, an
 * optional tinted overlay and dot pattern, parallax for an image, the text in
 * the chosen colour. Everything the section sets arrives as custom properties
 * (--cover-ink, --cover-ground, --cover-overlay, --cover-overlay-o). */
.cover {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: clamp(22rem, 62vh, 40rem);
  padding-block: clamp(3rem, 8vw, 6rem);
  background: var(--cover-ground, #17190f);
  color: var(--cover-ink, #fff);
  overflow: hidden;
}
.cover--full { min-height: 100svh; }
.cover__media { position: absolute; inset: 0; z-index: -1; overflow: hidden; container-type: size; }
.cover__img { position: absolute; inset: 0; background-size: cover; background-position: center; }
.cover--parallax .cover__img { background-attachment: fixed; }
/* A 16:9 frame that always covers the box, whatever its shape — sized from
 * the media layer's own dimensions (container units). */
.cover__yt,
.cover__video {
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100cqw, 177.78cqh);
  height: max(56.25cqw, 100cqh);
  transform: translate(-50%, -50%);
  border: 0;
  pointer-events: none;
}
.cover__video { object-fit: cover; }
.cover__overlay { position: absolute; inset: 0; background: var(--cover-overlay, #000); opacity: var(--cover-overlay-o, 0.6); }
.cover__pattern {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgb(0 0 0 / 38%) 1px, transparent 1.3px);
  background-size: 4px 4px;
}
.cover__inner { position: relative; width: 100%; }
.cover--center .cover__inner { text-align: center; }
.cover__title {
  margin: 0;
  max-width: 20ch;
  color: inherit;
  font-size: clamp(2.1rem, 1.2rem + 3.6vw, 4rem);
  line-height: 1.05;
}
.cover--center .cover__title { margin-inline: auto; }
.cover__title em { font-style: normal; color: var(--accent); }
.cover__sub { max-width: 42ch; margin: 1rem 0 0; color: inherit; opacity: 0.9; font-size: clamp(1rem, 0.95rem + 0.3vw, 1.15rem); line-height: 1.6; }
.cover--center .cover__sub { margin-inline: auto; }
.cover__cta { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.75rem; }
.cover--center .cover__cta { justify-content: center; }
@media (prefers-reduced-motion: reduce) {
  .cover__yt { display: none; }
  .cover--parallax .cover__img { background-attachment: scroll; }
}

/* ---- Content cards (snippets/content-cards, sections/cards-*) -------------------
 * A titled grid of cards over an optional background — the Cover hero's
 * layers (.cover__media and friends) reused. Four card shapes:
 *   branches      photo on top, name, address, open/closed, contact footer
 *   team          round portrait, name, role, a line about them
 *   specials      photo beside the text, the price in the accent
 *   testimonials  round photo beside a quote, on the section's own ground */
.cards {
  position: relative;
  isolation: isolate;
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  background: var(--cover-ground, transparent);
  color: var(--cards-ink, var(--ink));
  overflow: hidden;
}
.cards--on-ground { --cards-ink-default: #fff; color: var(--cards-ink, var(--cards-ink-default)); }
.cards--full { display: flex; align-items: center; min-height: 100svh; }
.cards--full > .container { width: 100%; }
.cards .cover__media { z-index: -1; }
.cards__title { margin: 0; color: inherit; font-size: clamp(1.6rem, 1.2rem + 1.8vw, 2.4rem); }
.cards__sub { max-width: 48ch; margin: 0.6rem 0 0; opacity: 0.85; line-height: 1.6; }
.cards--center .cards__title,
.cards--center .cards__sub { text-align: center; margin-inline: auto; }
.cards__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin: clamp(1.5rem, 4vw, 2.5rem) 0 0;
  padding: 0;
  list-style: none;
}
.cards--cols-1 .cards__grid { grid-template-columns: minmax(0, 1fr); max-width: 44rem; margin-inline: auto; }
.cards--cols-2 .cards__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cards--cols-4 .cards__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 63.99rem) {
  .cards--cols-3 .cards__grid,
  .cards--cols-4 .cards__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 40rem) {
  .cards__grid,
  .cards--cols-2 .cards__grid,
  .cards--cols-3 .cards__grid,
  .cards--cols-4 .cards__grid { grid-template-columns: minmax(0, 1fr); }
}

.card-x {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface);
  color: var(--ink);
}
.card-x__media { display: block; aspect-ratio: 16 / 10; overflow: hidden; background: var(--surface-3, #eee); }
.card-x__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.card-x__media--ph { display: flex; align-items: center; justify-content: center; color: var(--muted); }
.card-x__body { flex: 1; padding: 1rem 1.1rem; text-align: center; }
.card-x__title { margin: 0; font-family: var(--font-display); font-size: 1.15rem; font-weight: 700; color: inherit; }
.card-x__title a { color: inherit; text-decoration: none; }
.card-x__subtitle { margin: 0.25rem 0 0; font-size: 0.85rem; font-weight: 600; color: var(--muted); }
.card-x__text { margin: 0.6rem 0 0; font-size: 0.9rem; line-height: 1.55; color: var(--ink-soft, var(--muted)); }
.card-x__chip {
  display: inline-block;
  margin-top: 0.5rem;
  padding: 0.12rem 0.55rem;
  border-radius: var(--radius-pill);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.card-x__chip--open { background: color-mix(in srgb, #1f9d55 14%, var(--surface)); color: #1f7a45; }
.card-x__chip--closed { background: color-mix(in srgb, var(--danger) 12%, var(--surface)); color: var(--danger); }
.card-x__foot {
  padding: 0.7rem 1rem;
  border-top: 1px solid var(--line);
  background: var(--surface-2, var(--surface));
  font-size: 0.85rem;
  text-align: center;
}
.card-x__foot p { margin: 0 0 0.2rem; }
.card-x__foot a { color: var(--accent); font-weight: 600; }
.card-x__link { display: inline-block; margin-top: 0.15rem; }

/* Team: a round portrait above the name. */
.card-x--team .card-x__media { width: 7.5rem; height: 7.5rem; aspect-ratio: 1; margin: 1.4rem auto 0; border-radius: 50%; }

/* Today's special: the photo beside the text. */
.card-x--specials { flex-direction: row; }
.card-x--specials .card-x__media { flex: 0 0 38%; aspect-ratio: auto; min-height: 8.5rem; }
.card-x--specials .card-x__body { text-align: start; }
.card-x--specials .card-x__subtitle { color: var(--accent); font-size: 0.95rem; font-weight: 700; }
.card-x--specials .card-x__text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Testimonial: a round photo beside the quote, on the section's own ground. */
.card-x--testimonials {
  flex-direction: row;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem;
  border: 0;
  background: transparent;
  color: inherit;
}
.card-x--testimonials .card-x__media { flex: 0 0 5.5rem; width: 5.5rem; height: 5.5rem; aspect-ratio: 1; border-radius: 50%; }
.card-x--testimonials .card-x__body { padding: 0; text-align: start; }
.card-x--testimonials .card-x__subtitle { color: inherit; opacity: 0.75; }
.card-x--testimonials .card-x__text { font-size: 1rem; font-style: italic; color: inherit; opacity: 0.92; }

/* ---- Home: order status (PLUS's "Following order") ----------------------------
 * First in the service buttons, full width, while there is an order to follow
 * (theme.js sets data-state). Each state has its own glyph and motion, as the
 * PLUS app's: waiting — three dots; preparing — steam over the dish; out for
 * delivery — the truck bumping with wind streaming past; ready / delivered —
 * a tick that pops in; cancelled — a red cross. The tile pulses while the
 * order is in progress. None of the motion where less is asked for. */
.svc-home__track { grid-column: 1 / -1; border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.svc-home__track[hidden] { display: none; }
.svc-track__icon { position: relative; overflow: visible; }
.svc-track__glyph { position: relative; display: none; align-items: center; justify-content: center; }
.svc-home__track[data-state="waiting"] .svc-track__glyph--waiting,
.svc-home__track[data-state="preparing"] .svc-track__glyph--preparing,
.svc-home__track[data-state="delivery"] .svc-track__glyph--delivery,
.svc-home__track[data-state="ready"] .svc-track__glyph--ready,
.svc-home__track[data-state="done"] .svc-track__glyph--ready,
.svc-home__track[data-state="cancelled"] .svc-track__glyph--cancelled { display: inline-flex; }

/* Waiting: three dots, one after another. */
.svc-track__glyph--waiting { gap: 3px; }
.svc-track__glyph--waiting i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: trk-dot 1.2s infinite ease-in-out; }
.svc-track__glyph--waiting i:nth-child(2) { animation-delay: 0.15s; }
.svc-track__glyph--waiting i:nth-child(3) { animation-delay: 0.3s; }
@keyframes trk-dot { 0%, 80%, 100% { transform: scale(0.5); opacity: 0.4; } 40% { transform: scale(1); opacity: 1; } }

/* Preparing: steam rising over the dish. */
.svc-track__steam { position: absolute; top: -9px; left: 50%; display: flex; gap: 3px; transform: translateX(-50%); }
.svc-track__steam i { width: 2px; height: 7px; border-radius: 2px; background: currentColor; opacity: 0; animation: trk-steam 1.6s infinite ease-out; }
.svc-track__steam i:nth-child(2) { animation-delay: 0.35s; }
.svc-track__steam i:nth-child(3) { animation-delay: 0.7s; }
@keyframes trk-steam { 0% { transform: translateY(4px); opacity: 0; } 40% { opacity: 0.8; } 100% { transform: translateY(-6px); opacity: 0; } }

/* Out for delivery: the truck bumps along, wind streaming past behind it. */
.svc-track__glyph--delivery svg { animation: trk-bump 0.45s infinite alternate ease-in-out; }
.svc-track__wind { position: absolute; top: 50%; inset-inline-start: -11px; display: grid; gap: 3px; transform: translateY(-50%); }
.svc-track__wind i { display: block; width: 8px; height: 2px; border-radius: 2px; background: currentColor; animation: trk-wind 0.8s infinite linear; }
.svc-track__wind i:nth-child(2) { width: 6px; animation-delay: 0.25s; }
.svc-track__wind i:nth-child(3) { animation-delay: 0.5s; }
[dir="rtl"] .svc-track__glyph--delivery { transform: scaleX(-1); }
@keyframes trk-bump { to { transform: translateY(-1.5px); } }
@keyframes trk-wind { from { transform: translateX(6px); opacity: 0; } 50% { opacity: 0.7; } to { transform: translateX(-6px); opacity: 0; } }

/* Ready / delivered: the tick pops in, the tile goes solid. */
.svc-track__glyph--ready svg { animation: trk-pop 0.5s cubic-bezier(0.3, 1.6, 0.5, 1) both; }
@keyframes trk-pop { from { transform: scale(0.3); opacity: 0; } }
.svc-home__track:is([data-state="ready"], [data-state="done"]) .svc-track__icon { background: var(--accent); color: var(--accent-contrast, #fff); }
.svc-home__track:is([data-state="ready"], [data-state="done"]) .svc-home__text small { color: var(--accent); font-weight: 600; }

/* Cancelled: in the danger colour. */
.svc-home__track[data-state="cancelled"] { border-color: color-mix(in srgb, var(--danger) 45%, var(--line)); }
.svc-home__track[data-state="cancelled"] .svc-track__icon { background: color-mix(in srgb, var(--danger) 12%, var(--surface)); color: var(--danger); }
.svc-home__track[data-state="cancelled"] .svc-home__text small { color: var(--danger); font-weight: 600; }

/* In progress: the tile breathes. */
.svc-home__track:is([data-state="waiting"], [data-state="preparing"], [data-state="delivery"]) .svc-track__icon { animation: trk-ring 2s infinite; }
.svc-home__track:is([data-state="waiting"], [data-state="preparing"], [data-state="delivery"]) .svc-home__text small { color: var(--accent); font-weight: 600; }
@keyframes trk-ring {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 45%, transparent); }
  70% { box-shadow: 0 0 0 10px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .svc-home__track *, .svc-home__track .svc-track__icon { animation: none !important; }
  .svc-track__steam, .svc-track__wind { display: none; }
}

/* ---- Content cards as a carousel ------------------------------------------------
 * Layout "Carousel" (sections/cards-*): the grid becomes one sideways track that
 * swipes and snaps — as many cards across as the Columns setting, one and a
 * peek of the next on a phone. Round arrows beside the title when it overflows
 * (theme.js / home-sections.js "Card carousels"). Branch cards carry a photo on
 * top in this layout like any other. */
.cards--carousel .container { position: relative; }
.cards--carousel .cards__grid {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 0;
  scrollbar-width: none;
  padding-bottom: 0.25rem;
  max-width: none;
}
.cards--carousel .cards__grid::-webkit-scrollbar { display: none; }
.cards--carousel .cards__grid > .card-x {
  flex: 0 0 calc((100% - (var(--cards-n, 3) - 1) * 1rem) / var(--cards-n, 3));
  scroll-snap-align: start;
}
.cards--carousel.cards--cols-1 { --cards-n: 1; }
.cards--carousel.cards--cols-2 { --cards-n: 2; }
.cards--carousel.cards--cols-3 { --cards-n: 3; }
.cards--carousel.cards--cols-4 { --cards-n: 4; }
@media (max-width: 63.99rem) {
  .cards--carousel.cards--cols-3,
  .cards--carousel.cards--cols-4 { --cards-n: 2; }
}
@media (max-width: 40rem) {
  .cards--carousel .cards__grid { gap: 0.75rem; }
  .cards--carousel .cards__grid > .card-x { flex-basis: 84%; }
}
.cards__nav {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin: 0.75rem 0 -0.5rem;
}
.cards__nav[hidden] { display: none; }
.cards__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 0.15s, opacity 0.15s;
}
.cards__btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.cards__btn:disabled { opacity: 0.35; cursor: default; }
[dir="rtl"] .cards__btn svg { transform: scaleX(-1); }
@media (max-width: 40rem) { .cards__nav { display: none; } }

/* Drag to scroll (theme.js / home-sections.js "Drag to scroll"): while a mouse
 * pulls a carousel or the stories row, snapping waits and text is not picked. */
:is([data-cards-track], .stories__row) { cursor: grab; }
:is([data-cards-track], .stories__row).is-dragging { cursor: grabbing; scroll-snap-type: none; user-select: none; }
:is([data-cards-track], .stories__row).is-dragging * { pointer-events: none; }

/* ---- Account: the profile page, organised like Fresha's -------------------------
 * templates/customers/account — a side menu (the customer's name over the
 * account's places) and the page as two cards: the profile (avatar with the
 * initial, the name, each detail as a label over its value) and the saved
 * addresses (icon rows, then "Add"). On a phone the menu becomes a row of tabs
 * and the cards stack. */
.account-page { padding: clamp(1.5rem, 4vw, 3rem) 0 clamp(2.5rem, 5vw, 4rem); background: var(--surface-2, transparent); }
.account-shell { display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: clamp(1.5rem, 4vw, 3.5rem); align-items: start; }

.account-nav { position: sticky; top: calc(var(--stuck-top, 0px) + 1rem); }
.account-nav__name { margin: 0 0 0.75rem; padding-inline: 0.75rem; font-family: var(--font-display); font-size: 1.15rem; font-weight: 700; }
.account-nav__list { display: grid; gap: 0.2rem; margin: 0; padding: 0; list-style: none; }
.account-nav__form { margin: 0; }
.account-nav__link {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  min-height: 2.75rem;
  padding: 0.55rem 0.75rem;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
  text-align: start;
  text-decoration: none;
  cursor: pointer;
}
.account-nav__link span { flex: 1; }
.account-nav__link em { font-style: normal; font-size: 0.75rem; font-weight: 700; padding: 0.05rem 0.5rem; border-radius: var(--radius-pill); background: color-mix(in srgb, var(--ink) 8%, var(--surface)); color: var(--muted); }
.account-nav__link:hover { background: color-mix(in srgb, var(--ink) 5%, var(--surface)); color: var(--ink); }
.account-nav__link[aria-current="page"] { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent); font-weight: 600; }
.account-nav__link--out { color: var(--muted); }
.account-nav__link--out:hover { color: var(--danger); }

.account-page__title { margin: 0 0 1.5rem; font-family: var(--font-display); font-size: clamp(1.6rem, 1.3rem + 1.2vw, 2.1rem); font-weight: 700; }
.account-cards { display: grid; grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); gap: 1.5rem; align-items: start; }
.account-card { padding: 1.5rem; border: 1px solid var(--line); border-radius: 16px; background: var(--surface); }
.account-card__title { margin: 0 0 1rem; font-family: var(--font-display); font-size: 1.15rem; font-weight: 700; }

.profile-card__head { display: grid; justify-items: center; gap: 0.5rem; padding-bottom: 1.25rem; border-bottom: 1px solid var(--line); text-align: center; }
.profile-card__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 6.5rem;
  height: 6.5rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-contrast, #fff);
  font-family: var(--font-display);
  font-size: 2.75rem;
  font-weight: 700;
}
.profile-card__name { margin: 0.25rem 0 0; font-family: var(--font-display); font-size: 1.35rem; font-weight: 700; overflow-wrap: anywhere; }
.profile-card__branch { margin: 0; font-size: 0.85rem; color: var(--muted); }
.profile-card__details { display: grid; gap: 1rem; margin: 1.25rem 0 0; }
.profile-card__details dt { font-size: 0.95rem; font-weight: 600; color: var(--ink); }
.profile-card__details dd { margin: 0.15rem 0 0; font-size: 0.9rem; color: var(--muted); overflow-wrap: anywhere; }

.address-card__list { display: grid; gap: 0.75rem; margin: 0 0 1rem; padding: 0; list-style: none; }
.address-row {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 1rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--ink);
  text-decoration: none;
  transition: border-color 0.15s;
}
.address-row:hover { border-color: var(--accent); color: var(--ink); }
.address-row__icon { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 2.4rem; height: 2.4rem; border-radius: 50%; background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent); }
.address-row__text { display: grid; gap: 0.15rem; min-width: 0; }
.address-row__text strong { font-size: 0.95rem; font-weight: 600; }
.address-row__text strong em { margin-inline-start: 0.35rem; padding: 0.05rem 0.45rem; border-radius: var(--radius-pill); background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent); font-size: 0.7rem; font-style: normal; font-weight: 700; }
.address-row__text span { font-size: 0.85rem; color: var(--muted); overflow-wrap: anywhere; }
.address-card__empty { margin: 0 0 1rem; color: var(--muted); font-size: 0.9rem; }
.address-card__add {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  min-height: 2.5rem;
  padding: 0.45rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
}
.address-card__add:hover { border-color: var(--accent); color: var(--accent); }

@media (max-width: 63.99rem) {
  .account-shell { grid-template-columns: minmax(0, 1fr); gap: 1.25rem; }
  .account-nav { position: static; }
  .account-nav__name { display: none; }
  .account-nav__list { display: flex; gap: 0.4rem; overflow-x: auto; scrollbar-width: none; padding-bottom: 0.25rem; }
  .account-nav__list::-webkit-scrollbar { display: none; }
  .account-nav__list > li { flex: none; }
  .account-nav__link { width: auto; min-height: 2.4rem; padding: 0.4rem 0.85rem; border: 1px solid var(--line); border-radius: var(--radius-pill); background: var(--surface); white-space: nowrap; font-size: 0.88rem; }
  .account-cards { grid-template-columns: minmax(0, 1fr); }
}

/* Phone: Fresha's mobile profile — the page's own bar (back + "My profile")
 * pinned at the top instead of the side menu, the profile card, the addresses
 * as white rows straight on the page, then the account's places as rows. */
.account-bar,
.account-more { display: none; }
@media (max-width: 63.99rem) {
  .account-page { padding-top: 0; }
  .account-bar {
    position: sticky;
    top: var(--stuck-top, 0px);
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-height: 3.5rem;
    margin-bottom: 1rem;
    padding: 0.5rem var(--gutter);
    background: var(--surface-2, var(--surface));
    border-bottom: 1px solid var(--line);
  }
  .account-bar__back { display: inline-flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; margin-inline-start: -0.5rem; color: var(--ink); }
  [dir="rtl"] .account-bar__back svg { transform: scaleX(-1); }
  .account-bar__title { margin: 0; font-family: var(--font-display); font-size: 1.05rem; font-weight: 700; }
  .account-nav { display: none; }
  .account-page__title { display: none; }
  .address-card { padding: 0; border: 0; background: none; }
  .address-row { background: var(--surface); }
  .account-more { display: block; margin-top: 2rem; }
  .account-more__title { margin: 0 0 0.5rem; font-family: var(--font-display); font-size: 1.15rem; font-weight: 700; }
  .account-more__list { margin: 0; padding: 0; list-style: none; }
  .account-more__list form { margin: 0; }
  .account-more__list a,
  .account-more__list button {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    min-height: 3.25rem;
    padding: 0.5rem 0;
    border: 0;
    border-bottom: 1px solid var(--line);
    background: none;
    color: var(--ink);
    font: inherit;
    font-size: 0.95rem;
    text-align: start;
    text-decoration: none;
    cursor: pointer;
  }
  .account-more__list svg { color: var(--muted); }
  [dir="rtl"] .account-more__list svg { transform: scaleX(-1); }
  .account-more__list button { color: var(--danger); }
}

/* ---- Account: the "Add address" sheet -------------------------------------------
 * The .delivery-modal panel (full screen on a phone, moving in and out) with a
 * plain form: label over a rounded field, building / block / flat three across,
 * and Save across the foot. */
.address-form__body { display: grid; gap: 1rem; }
.address-form__field { display: grid; gap: 0.35rem; margin: 0; }
.address-form__field span { font-size: 0.85rem; font-weight: 700; color: var(--ink); }
.address-form__field input {
  width: 100%;
  min-height: 3rem;
  padding: 0.65rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
}
.address-form__field input:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; border-color: var(--accent); }
.address-form__row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.6rem; }
.address-form__foot { justify-content: stretch; }
.address-form__save { width: 100%; min-height: 48px; border-radius: var(--radius-pill); justify-content: center; }

/* ---- Loyalty wallet (sections/main-wallet) — Fresha's loyalty page ---------------
 * A gradient header card over the balance and its two rows, a plain card of
 * rows below, and every row opening a rounded sheet. */
.wallet-page { padding: clamp(1.25rem, 3vw, 2.5rem) 0 clamp(2.5rem, 5vw, 4rem); background: var(--surface-2, transparent); }
.wallet-page__inner { display: grid; gap: 1.5rem; max-width: 40rem; margin-inline: auto; }
.wallet-page__back { justify-self: start; display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.45rem 1rem; border: 1px solid var(--line); border-radius: var(--radius-pill); background: var(--surface); color: var(--ink); font-size: 0.9rem; text-decoration: none; }
.wallet-page__back:hover { border-color: var(--ink); color: var(--ink); }
[dir="rtl"] .wallet-page__back svg, [dir="rtl"] .wallet-row > svg:last-child, [dir="rtl"] .wallet-item > svg:last-child, [dir="rtl"] .wallet-sheet__nav:not(.wallet-sheet__nav--end) svg { transform: scaleX(-1); }

.wallet-card { border: 1px solid var(--line); border-radius: 16px; background: var(--surface); overflow: hidden; }
.wallet-card--plain { padding: 0.75rem 2.5rem; }
.wallet-card__hero,
.wallet-sheet__hero {
  background:
    radial-gradient(120% 140% at 100% 100%, color-mix(in srgb, var(--wl-to) 90%, transparent), transparent 60%),
    linear-gradient(120deg, var(--wl-from), color-mix(in srgb, var(--wl-from) 55%, var(--wl-to)));
  color: #fff;
}
.wallet-card__hero { padding: 2.75rem 2.5rem 2rem; }
.wallet-card__name { margin: 0; font-family: var(--font-display); font-size: clamp(1.5rem, 1.2rem + 1vw, 1.9rem); font-weight: 700; color: #fff; }
.wallet-card__sub { margin: 0.4rem 0 0; font-size: 0.85rem; font-weight: 600; opacity: 0.92; }
.wallet-card__body { padding: 1.75rem 2.5rem 1.25rem; }
.wallet-card__title { margin: 0; font-family: var(--font-display); font-size: 1.3rem; font-weight: 700; }
.wallet-balance { display: flex; align-items: center; gap: 0.75rem; margin: 1rem 0 1.25rem; font-size: 1rem; }
.wallet-balance strong { font-size: 1.75rem; font-weight: 700; }
.wallet-balance__gem { display: inline-flex; color: var(--wl-from); }
.wallet-guest { margin: 0.75rem 0 1.25rem; color: var(--muted); }
.wallet-guest a { color: var(--accent); font-weight: 600; }

.wallet-rows { margin: 0; padding: 0; list-style: none; }
.wallet-row {
  display: flex; align-items: center; gap: 1rem; width: 100%;
  min-height: 3.25rem; padding: 0.5rem 0; border: 0; background: none;
  color: var(--ink); font: inherit; font-size: 1rem; text-align: start; text-decoration: none; cursor: pointer;
}
.wallet-row--sm { font-size: 0.92rem; }
.wallet-row span { flex: 1; }
.wallet-row:hover { color: var(--accent); }

/* Sheets */
.wallet-sheet {
  width: min(36rem, calc(100vw - 2rem)); max-height: calc(100dvh - 3rem);
  padding: 0; border: 0; border-radius: 28px; background: var(--surface); color: var(--ink);
  box-shadow: var(--shadow-lg, 0 20px 60px rgba(0,0,0,.25)); overflow: auto;
  opacity: 0; transform: translateY(1.5rem) scale(0.98);
  transition: opacity 0.25s, transform 0.25s, overlay 0.25s allow-discrete, display 0.25s allow-discrete;
}
.wallet-sheet[open] { opacity: 1; transform: none; }
@starting-style { .wallet-sheet[open] { opacity: 0; transform: translateY(1.5rem) scale(0.98); } }
.wallet-sheet::backdrop { background: rgba(20, 20, 20, 0.35); }
.wallet-sheet--tall { min-height: min(52rem, calc(100dvh - 3rem)); }
.wallet-sheet__x { position: absolute; top: 1.5rem; inset-inline-end: 1.5rem; display: inline-flex; padding: 0.4rem; border: 0; background: none; color: var(--ink); cursor: pointer; z-index: 1; }
.wallet-sheet__body { padding: 3.25rem 3rem 2.5rem; }
.wallet-sheet--detail .wallet-sheet__body { padding-top: 2rem; }
.wallet-sheet__title { margin: 0; font-family: var(--font-display); font-size: 1.75rem; font-weight: 700; }
.wallet-sheet__sub { margin: 0.6rem 0 0; font-size: 0.88rem; color: var(--muted); }
.wallet-sheet__h3 { margin: 0 0 0.6rem; font-family: var(--font-display); font-size: 1.3rem; font-weight: 700; }
.wallet-sheet__foot { display: flex; justify-content: flex-end; margin-top: 1.5rem; }
.wallet-sheet__hero { position: relative; display: grid; justify-items: center; gap: 0.35rem; padding: 3rem 3rem 2rem; text-align: center; }
.wallet-sheet__hero-icon { display: inline-flex; margin-bottom: 0.4rem; }
.wallet-sheet__hero-title { font-family: var(--font-display); font-size: 1.35rem; }
.wallet-sheet__hero-sub { font-size: 0.85rem; font-weight: 600; opacity: 0.92; }
.wallet-sheet__nav { position: absolute; top: 1.5rem; inset-inline-start: 2rem; display: inline-flex; padding: 0.3rem; border: 0; background: none; color: #fff; cursor: pointer; }
.wallet-sheet__nav--end { inset-inline-start: auto; inset-inline-end: 2rem; }

.wallet-list { display: grid; gap: 0.25rem; margin: 1.5rem 0 0; padding: 0; list-style: none; }
.wallet-item { display: flex; align-items: center; gap: 1rem; width: 100%; padding: 0.75rem 0; border: 0; background: none; color: var(--ink); font: inherit; text-align: start; cursor: pointer; }
.wallet-item:hover strong { color: var(--accent); }
.wallet-item__icon { flex: none; display: inline-flex; color: var(--wl-from); }
.wallet-item__icon--plain { color: var(--ink); }
.wallet-item__text { display: grid; gap: 0.15rem; flex: 1; min-width: 0; }
.wallet-item__text strong { font-size: 0.98rem; font-weight: 500; }
.wallet-item__text span { font-size: 0.85rem; color: var(--muted); }
.wallet-mini { display: flex; align-items: center; gap: 0.9rem; margin: 1.5rem 0 0; }
.wallet-mini > span:last-child { display: grid; }
.wallet-mini strong { font-size: 1.3rem; }
.wallet-mini span span { font-size: 0.85rem; color: var(--muted); }
.wallet-list--lined { gap: 0; margin-top: 1rem; }
.wallet-reward { display: flex; align-items: center; gap: 1rem; padding: 0.9rem 0; }
.wallet-reward + .wallet-reward { border-top: 1px solid var(--line); }
.wallet-reward__need { font-size: 0.85rem; color: var(--muted); white-space: nowrap; }
.wallet-reward__ready { font-size: 0.8rem; font-weight: 700; color: var(--wl-from); white-space: nowrap; }
.wallet-activity__pts { font-weight: 700; color: var(--success, #1a7f4b); }
.wallet-activity__pts.is-neg { color: var(--danger); }
.wallet-empty { display: grid; justify-items: center; gap: 0.35rem; margin-top: 4.5rem; text-align: center; }
.wallet-empty strong { margin-top: 0.75rem; font-size: 1.05rem; }
.wallet-empty span { font-size: 0.9rem; color: var(--muted); }

.wallet-rte { font-size: 0.92rem; line-height: 1.7; }
.wallet-rte p { margin: 0 0 0.35rem; }
.wallet-rte ul { margin: 0; padding-inline-start: 1.75rem; }
.wallet-rte a { color: var(--wl-to); }
.wallet-cta { display: flex; align-items: center; justify-content: center; min-height: 3rem; margin-top: 2.25rem; padding: 0.6rem 1.5rem; border: 0; border-radius: var(--radius-pill); background: var(--ink); color: var(--surface); font: inherit; font-weight: 700; text-decoration: none; cursor: pointer; }
.wallet-cta:hover { color: var(--surface); opacity: 0.9; }
.wallet-cta--sm { display: inline-flex; margin-top: 0; }

@media (max-width: 40rem) {
  .wallet-card__hero, .wallet-card__body { padding-inline: 1.5rem; }
  .wallet-card--plain { padding-inline: 1.5rem; }
  .wallet-sheet { width: 100vw; max-width: 100vw; max-height: 92dvh; margin: auto 0 0; border-radius: 24px 24px 0 0; }
  .wallet-sheet--tall { min-height: 80dvh; }
  .wallet-sheet__body { padding: 3rem 1.5rem 2rem; }
  .wallet-sheet__hero { padding-inline: 1.5rem; }
}

/* ---- Sign in / Create account (templates/customers/login, register) --------------
 * One rounded card on the page's tint: title and a line under it, label-over-
 * field inputs, the phone as dial-code select + number, a pill submit, then the
 * social buttons (snippets/social-login from the base theme) and the switch. */
.auth-page { padding: clamp(2rem, 5vw, 4rem) 0; background: var(--surface-2, transparent); }
.auth-card { max-width: 28rem; padding: clamp(1.5rem, 4vw, 2.5rem); border: 1px solid var(--line); border-radius: 20px; background: var(--surface); }
.auth-card__title { margin: 0; font-family: var(--font-display); font-size: clamp(1.6rem, 1.3rem + 1vw, 2rem); font-weight: 700; }
.auth-card__sub { margin: 0.4rem 0 1.5rem; color: var(--muted); font-size: 0.92rem; }
.auth-card__error { margin-bottom: 1rem; padding: 0.75rem 1rem; border-radius: 12px; background: color-mix(in srgb, var(--danger) 10%, var(--surface)); color: var(--danger); font-size: 0.9rem; }
.auth-form { display: grid; gap: 1rem; }
.auth-form__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem; }
.auth-field { display: grid; gap: 0.35rem; margin: 0; }
.auth-field > span,
.auth-field > label { font-size: 0.85rem; font-weight: 700; color: var(--ink); }
.auth-field small { font-weight: 400; color: var(--muted); }
.auth-field input,
.auth-phone__code {
  width: 100%;
  min-height: 3rem;
  padding: 0.65rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
}
.auth-field input:focus,
.auth-phone__code:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; border-color: var(--accent); }
.auth-phone { display: flex; gap: 0.5rem; }
.auth-phone__code { flex: 0 1 auto; width: auto; max-width: 9.5rem; padding-inline-end: 0.5rem; text-overflow: ellipsis; }
.auth-phone__number { flex: 1 1 auto; min-width: 0; }
.auth-card__forgot { justify-self: end; margin-top: -0.35rem; font-size: 0.85rem; color: var(--accent); }
.auth-form__submit { width: 100%; min-height: 48px; margin-top: 0.25rem; border-radius: var(--radius-pill); justify-content: center; }
.auth-card .social-login { margin-top: 1.25rem; }
.auth-card .social-login__button { min-height: 48px; border-radius: var(--radius-pill); }
.auth-card__switch { margin: 1.5rem 0 0; text-align: center; font-size: 0.9rem; color: var(--muted); }
.auth-card__switch a { color: var(--accent); font-weight: 700; }
@media (max-width: 30rem) {
  .auth-page { padding-top: 1rem; }
  .auth-card { padding: 1.25rem 0; border: 0; background: none; }
  .auth-form__row { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Full-width page tint -----------------------------------------------------------
 * The layout puts every template inside <main class="container">, so these
 * pages' tint stopped at the content column. A spread shadow in the same colour,
 * clipped to the page's own height, carries it edge to edge without widening the
 * page (no horizontal scroll). */
.account-page,
.wallet-page,
.auth-page {
  box-shadow: 0 0 0 100vmax var(--surface-2, transparent);
  clip-path: inset(0 -100vmax);
}

/* ---- Account: the saved-addresses page (templates/customers/addresses) ---------------
 * The profile page's shell; the addresses as cards (icon, name + default badge,
 * the lines, then Edit / Make default / Remove), and the add / edit sheet. */
.account-main__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1.5rem; }
.account-main__head .account-page__title { margin: 0; }
button.address-card__add { background: var(--surface); font: inherit; font-size: 0.9rem; font-weight: 600; cursor: pointer; }
.address-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr)); gap: 1rem; margin: 0; padding: 0; list-style: none; }
.address-item { display: flex; flex-direction: column; gap: 1rem; padding: 1.25rem; }
.address-item.is-default { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.address-item__top { display: flex; gap: 0.9rem; align-items: flex-start; }
.address-item__text { display: grid; gap: 0.2rem; min-width: 0; }
.address-item__text strong { font-size: 1rem; font-weight: 600; }
.address-item__text strong em { margin-inline-start: 0.35rem; padding: 0.05rem 0.45rem; border-radius: var(--radius-pill); background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent); font-size: 0.7rem; font-style: normal; font-weight: 700; vertical-align: middle; }
.address-item__text span { font-size: 0.88rem; color: var(--muted); overflow-wrap: anywhere; }
.address-item__note { font-style: italic; }
.address-item__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: auto; padding-top: 0.9rem; border-top: 1px solid var(--line); }
.address-item__actions form { margin: 0; }
.address-item__btn { min-height: 2.25rem; padding: 0.35rem 0.9rem; border: 1px solid var(--line); border-radius: var(--radius-pill); background: var(--surface); color: var(--ink); font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer; }
.address-item__btn:hover { border-color: var(--accent); color: var(--accent); }
.address-item__btn--danger { border-color: transparent; color: var(--danger); }
.address-item__btn--danger:hover { border-color: var(--danger); color: var(--danger); }
.address-empty { display: grid; justify-items: center; gap: 0.75rem; padding: 2.5rem 1.5rem; text-align: center; }
.address-empty p { margin: 0; color: var(--muted); }
.address-empty__add { width: auto; padding-inline: 1.75rem; }
.address-form__row--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.address-form__check { display: flex; align-items: center; gap: 0.6rem; font-size: 0.9rem; cursor: pointer; }
.address-form__check input { width: 1.1rem; height: 1.1rem; accent-color: var(--accent); }
.address-form__map .location-picker { margin-bottom: 0 !important; }
.address-form__map .location-picker > span { font-size: 0.85rem !important; font-weight: 700; color: var(--ink) !important; }
.address-form__map [id^="lp-map-"] { border-color: var(--line) !important; border-radius: 12px !important; }
.address-form__map [id^="lp-locate-"] { border-color: var(--line) !important; border-radius: var(--radius-pill) !important; background: var(--surface) !important; color: var(--ink); }
@media (max-width: 63.99rem) {
  .account-main__head .account-page__title { display: none; }
  .account-main__head { justify-content: flex-end; }
  .address-item { background: var(--surface); }
}

/* ---- Reservation form (sections/reservation-form) — the account sheets' look -------
 * The form sits in a white rounded card; labels are bold over 12px-rounded
 * fields with a soft focus ring; the submit is a full-width pill. The photo
 * keeps its side. */
.reserve__form { max-width: 32rem; }
.reserve__form > form {
  padding: clamp(1.25rem, 3vw, 2rem);
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--surface);
}
.reserve__form .field { margin-bottom: 1.1rem; }
.reserve__form .field__label { margin-bottom: 0.35rem; font-weight: 700; color: var(--ink); }
.reserve__form .input,
.reserve__form .select,
.reserve__form .textarea {
  min-height: 3rem;
  padding: 0.65rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
}
.reserve__form .textarea { min-height: 7rem; }
.reserve__form .input:focus,
.reserve__form .select:focus,
.reserve__form .textarea:focus {
  outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  outline-offset: 1px;
  border-color: var(--accent);
  box-shadow: none;
}
.reserve__form .form-grid { gap: 0 0.75rem; }
.reserve__form .field__hint { margin: -0.4rem 0 1.1rem !important; }
.reserve__form button[type="submit"] { width: 100%; min-height: 50px; margin-top: 0.25rem !important; border-radius: var(--radius-pill); justify-content: center; }
.reserve__media { border-radius: 20px; }
@media (max-width: 34rem) {
  .reserve__form > form { padding: 1.25rem 1rem; }
}

/* ---- The order (cart) page in the checkout's style (sections/main-cart) -------------
 * Mirrors themes/_checkout's look with Bistro's tokens: an italic centred
 * title with an accent word and a divider, white content cards with a round
 * icon badge, pill toggles, and a sticky summary card with an accent stripe. */
.cart-page { background: color-mix(in srgb, var(--accent) 3%, var(--surface-2, var(--surface))); box-shadow: 0 0 0 100vmax color-mix(in srgb, var(--accent) 3%, var(--surface-2, var(--surface))); clip-path: inset(0 -100vmax); }
.order-head { margin: 0 0 2.5rem; text-align: center; }
.order-head__title { margin: 0; font-family: var(--font-display); font-style: italic; font-weight: 600; font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.35rem); color: var(--ink); }
.order-head__title span { color: var(--accent); }
.order-head__divider { display: flex; align-items: center; justify-content: center; gap: 0.85rem; width: 220px; margin: 0.9rem auto 0; color: var(--accent); }
.order-head__divider span { flex: 1; height: 1px; background: var(--line); }
.order-head__sub { margin: 0.9rem 0 0; font-size: 0.9rem; color: var(--muted); }

.order-grid { display: grid; grid-template-columns: minmax(0, 1fr) 24rem; gap: 2.25rem; align-items: start; }
.order-main { display: flex; flex-direction: column; gap: 1.5rem; min-width: 0; }
:is(.cart-page, .thanks-page) .order-card { padding: 1.5rem; border: 1px solid var(--line); border-radius: 16px; background: var(--surface); }
:is(.cart-page, .thanks-page) .order-card__header { display: flex; align-items: center; gap: 0.65rem; margin-bottom: 1.25rem; }
:is(.cart-page, .thanks-page) .order-card__icon { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 38px; height: 38px; border-radius: 50%; background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent); }
:is(.cart-page, .thanks-page) .order-card__title { margin: 0; font-size: 1.05rem; font-weight: 700; color: var(--ink); }
:is(.cart-page, .thanks-page) .order-card__link { margin-inline-start: auto; font-size: 0.85rem; font-weight: 600; color: var(--accent); }
:is(.cart-page, .thanks-page) .order-card__note { margin: 1rem 0 0; font-size: 0.85rem; color: var(--muted); }
:is(.cart-page, .thanks-page) .order-card .cart__lines { margin: 0; }
:is(.cart-page, .thanks-page) .order-card .cart-line { border: 0; border-radius: 0; padding: 1rem 0; background: none; box-shadow: none; }
:is(.cart-page, .thanks-page) .order-card .cart-line + .cart-line { border-top: 1px solid var(--line); }
:is(.cart-page, .thanks-page) .order-card .cart-line:first-child { padding-top: 0; }
:is(.cart-page, .thanks-page) .order-card .cart-line:last-child { padding-bottom: 0; }

.order-toggle { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 0.6rem; margin: 0; }
.order-toggle__opt {
  display: flex; align-items: center; justify-content: center; gap: 0.55rem;
  min-height: 3rem; padding: 0.6rem 1rem;
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 0.92rem; font-weight: 600; cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.order-toggle__opt:hover { border-color: var(--accent); }
.order-toggle__opt.is-active,
.order-toggle__opt:has(input:checked) { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--surface)); color: var(--accent); }
.order-toggle__opt:disabled { cursor: default; }
.order-toggle__opt input { position: absolute; opacity: 0; pointer-events: none; }
.order-toggle__opt:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

.order-summary {
  position: sticky; top: calc(var(--stuck-top, 0px) + 1.5rem);
  padding: 1.75rem;
  border: 1px solid var(--line); border-radius: 16px;
  background: var(--surface);
}
.order-summary__title { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 1.15rem; font-size: 0.95rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.01em; color: var(--ink); }
.order-summary__row { display: flex; justify-content: space-between; align-items: center; padding: 0.35rem 0; font-size: 0.9rem; color: var(--ink); }
.order-summary__row--total { margin-top: 0.4rem; padding-top: 0.9rem; border-top: 1px solid var(--line); font-size: 1.15rem; font-weight: 800; }
.order-summary__row--total span:last-child { color: var(--accent); }
.order-pay { margin: 1.25rem 0 0; }
.order-pay__label { margin: 0 0 0.6rem; font-size: 0.85rem; font-weight: 700; color: var(--ink); }
.order-toggle--pay { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.order-toggle--pay .order-toggle__opt { position: relative; min-height: 2.75rem; font-size: 0.88rem; }
.order-summary__meta { margin: 0.8rem 0 0; font-size: 0.8rem; color: var(--muted); }
.order-summary__submit {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  width: 100%; min-height: 52px; margin-top: 1.25rem; padding: 0.9rem;
  border: 0; border-radius: var(--radius-pill);
  background: var(--accent); color: var(--accent-contrast, #fff);
  font: inherit; font-weight: 800; cursor: pointer;
}
.order-summary__submit:hover { filter: brightness(1.05); }
[dir="rtl"] .order-summary__submit svg { transform: scaleX(-1); }

@media (max-width: 63.99rem) {
  .order-grid { grid-template-columns: minmax(0, 1fr); gap: 1.75rem; }
  .order-summary { position: static; }
}
@media (max-width: 40rem) {
  .order-head { margin-bottom: 1.5rem; }
  :is(.cart-page, .thanks-page) .order-card, .order-summary { padding: 1.25rem; }
}

/* Phone: the checkout-style order page inside the order screen. The pinned bar
 * already names the page and the pinned foot carries the total and "Place
 * order", so the centred title, the summary's total row and its button stand
 * down; the payment choice stays, in its own card. The older aside-form card
 * rule (written for the previous layout) is undone for the summary's form. */
@media (max-width: 63.99rem) {
  .cart-page .order-head { display: none; }
  .cart-page .order-grid { gap: 1rem; }
  .cart-page .order-main { gap: 1rem; }
  .cart-page .order-summary { border-top-width: 1px; }
  .cart-page .order-summary__row--total,
  .cart-page .order-summary__submit { display: none; }
  .cart-page aside.order-summary form { padding: 0; border: 0; background: none; border-radius: 0; }
  .cart-page { padding-bottom: 9rem; }
}

/* ---- Checkout: the summary's total row ---------------------------------------------
 * The platform checkout (themes/_checkout) rounds the total row with the theme's
 * --radius; with only a top border drawn, Bistro's large radius bent that rule
 * into an arc. Straight, like the cart's summary. Extra class for specificity,
 * so it holds whichever stylesheet loads last. */
.checkout-page .chk-summary .chk-summary__row--total { border-radius: 0; }

/* Checkout: the page tint edge to edge, like the account pages. The platform
 * paints .checkout-page with this same mix; the spread shadow repeats it past
 * the layout's content column, clipped to the page's height (no sideways scroll). */
.checkout-page {
  box-shadow: 0 0 0 100vmax color-mix(in srgb, var(--checkout-accent, var(--accent, #bc906b)) 3%, var(--checkout-paper, var(--paper, #fff)));
  clip-path: inset(0 -100vmax);
}

/* ---- Order received (sections/main-thank-you) — the cart / checkout style -----------
 * Reuses the order page's pieces (.order-head__*, .order-card*, .order-summary__*)
 * in one centred column, with a success head, a status pill and pill actions. */
.thanks-page { padding: clamp(2rem, 5vw, 3.5rem) 0 clamp(2.5rem, 5vw, 4rem); background: color-mix(in srgb, var(--accent) 3%, var(--surface-2, var(--surface))); box-shadow: 0 0 0 100vmax color-mix(in srgb, var(--accent) 3%, var(--surface-2, var(--surface))); clip-path: inset(0 -100vmax); }
.thanks-page__inner { display: grid; gap: 1.25rem; max-width: 40rem; }
.thanks-hero { margin-bottom: 0.75rem; text-align: center; }
.thanks-hero__check {
  display: inline-flex; align-items: center; justify-content: center;
  width: 4.25rem; height: 4.25rem; margin-bottom: 1rem; border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 14%, var(--surface)); color: var(--accent);
  box-shadow: 0 0 0 8px color-mix(in srgb, var(--accent) 6%, transparent);
  animation: thanks-pop 0.45s cubic-bezier(.2,.9,.3,1.3) both;
}
@keyframes thanks-pop { from { transform: scale(0.6); opacity: 0; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .thanks-hero__check { animation: none; } }
.thanks-status { margin-inline-start: auto; padding: 0.2rem 0.75rem; border-radius: var(--radius-pill); background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent); font-size: 0.78rem; font-weight: 700; text-transform: capitalize; white-space: nowrap; }
.thanks-text { margin: 0; color: var(--ink); line-height: 1.6; }
.thanks-meta { margin: 0.35rem 0 0; font-size: 0.85rem; color: var(--muted); }
.thanks-pay { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.thanks-pay__form { display: grid; gap: 0.25rem; margin-top: 1rem; }
.thanks-pay__select { width: 100%; max-width: none; }
.thanks-pay .order-summary__submit { margin-top: 0.75rem; }
.thanks-lines { margin: 0 0 0.75rem; padding: 0; list-style: none; }
.thanks-lines > li { padding: 0.75rem 0; border-bottom: 1px solid var(--line); }
.thanks-lines > li:first-child { padding-top: 0; }
.thanks-lines__row { display: flex; align-items: baseline; gap: 0.6rem; }
.thanks-lines__qty { flex: none; min-width: 1.8rem; padding: 0.05rem 0.4rem; border-radius: 6px; background: color-mix(in srgb, var(--ink) 6%, var(--surface)); font-size: 0.8rem; font-weight: 700; text-align: center; }
.thanks-lines__title { flex: 1; min-width: 0; font-weight: 600; }
.thanks-lines__price { flex: none; font-weight: 600; color: var(--muted); }
.thanks-lines__sel { margin: 0.3rem 0 0; padding-inline-start: 2.4rem; list-style: none; font-size: 0.85rem; color: var(--muted); }
.thanks-lines__sel span { color: var(--ink-soft, var(--muted)); }
.thanks-free { color: var(--success, #0a7d3a); font-weight: 600; }
.thanks-actions { display: grid; justify-items: center; gap: 0.9rem; margin-top: 0.5rem; }
.thanks-actions__track { max-width: 22rem; margin-top: 0; text-decoration: none; }
.thanks-actions__track:hover { color: var(--accent-contrast, #fff); }
.thanks-actions__more { font-size: 0.9rem; font-weight: 600; color: var(--accent); }
[dir="rtl"] .thanks-actions__track svg, [dir="rtl"] .thanks-pay .order-summary__submit svg { transform: scaleX(-1); }

/* ---- Order tracking (sections/main-order-tracking) — the thank-you page's style -----
 * Shares .thanks-* and .order-*; adds the status ring (pulsing while the order
 * moves, red when cancelled), the notices, and the progress as a timeline:
 * dots joined by a line, done in the accent, the current one ringed. */
.track-hero__num { margin: 0 0 0.35rem; font-size: 0.85rem; font-weight: 600; color: var(--muted); letter-spacing: 0.02em; }
.track-hero__icon.is-live { animation: thanks-pop 0.45s cubic-bezier(.2,.9,.3,1.3) both, track-pulse 2.2s ease-out 0.5s infinite; }
.track-hero__icon.is-cancelled { background: color-mix(in srgb, var(--danger) 12%, var(--surface)); color: var(--danger); box-shadow: 0 0 0 8px color-mix(in srgb, var(--danger) 6%, transparent); }
@keyframes track-pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 35%, transparent); }
  70% { box-shadow: 0 0 0 16px color-mix(in srgb, var(--accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) { .track-hero__icon.is-live { animation: none; } }

.track-notice { padding: 0.9rem 1.1rem; border-radius: 14px; font-size: 0.92rem; line-height: 1.5; }
.track-notice--danger { background: color-mix(in srgb, var(--danger) 10%, var(--surface)); color: var(--danger); }
.track-notice--warn { background: #fff7e6; color: #8a5a00; }

.track-steps { margin: 0; padding: 0; list-style: none; }
.track-step { position: relative; display: flex; align-items: center; gap: 0.9rem; min-height: 2.9rem; }
.track-step + .track-step::before {
  content: ""; position: absolute; inset-inline-start: calc(0.9rem - 1px); bottom: calc(50% + 0.9rem); height: calc(2.9rem - 1.8rem);
  width: 2px; background: var(--line);
}
.track-step.is-done + .track-step::before { background: var(--accent); }
.track-step__dot {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 1.8rem; height: 1.8rem; border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 7%, var(--surface)); color: var(--muted);
  font-size: 0.8rem; font-weight: 700;
}
.track-step.is-done .track-step__dot { background: var(--accent); color: var(--accent-contrast, #fff); }
.track-step.is-current .track-step__dot { background: var(--surface); color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent), 0 0 0 4px color-mix(in srgb, var(--accent) 15%, transparent); }
.track-step__label { font-size: 0.95rem; color: var(--muted); }
.track-step.is-done .track-step__label { color: var(--ink); }
.track-step.is-current .track-step__label { color: var(--ink); font-weight: 700; }

/* ---- Product options as the selection rows ----------------------------------------
 * Every modifier group on the dish page — single-answer (the old pills / size
 * tiles) and multi-answer (the topping chips) — drawn the way a combo pick's own
 * options already are (.cfg--nested, above): one option per line, name then
 * price, and the chosen line tinted in the accent with a round tick at its end.
 * Quantity rows (.cfg__row--qty) keep their stepper layout. */
.pdp .cfg__list--pills,
.pdp .cfg__list:has(> li > .cfg__row > input[type="checkbox"]) {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  gap: 0.5rem;
}
.pdp .cfg__row:not(.cfg__row--qty) {
  position: relative;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: 0.6rem;
  min-height: var(--tap-min, 3rem);
  padding-block: 0.55rem;
  padding-inline: 0.8rem 2.6rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  text-align: start;
  box-shadow: none;
}
.pdp .cfg__row:not(.cfg__row--qty) > input { position: absolute; opacity: 0; pointer-events: none; }
.pdp .cfg__row:not(.cfg__row--qty)::before { display: none; }
.pdp .cfg__row:not(.cfg__row--qty) .cfg__thumb { display: block; width: 2rem; height: 2rem; border-radius: 6px; }
.pdp .cfg__row:not(.cfg__row--qty) .cfg__name { flex: 1; font-size: 0.9rem; font-weight: 500; line-height: 1.3; }
.pdp .cfg__row:not(.cfg__row--qty) .cfg__price {
  margin: 0; padding: 0; border: 0; background: none;
  color: var(--muted); font-size: 0.82rem; font-weight: 600; white-space: nowrap; opacity: 1;
}
.pdp .cfg__row:not(.cfg__row--qty):hover { border-color: var(--line-2, var(--accent)); }
.pdp .cfg__row:not(.cfg__row--qty):has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
  color: var(--ink);
  box-shadow: none;
}
.pdp .cfg__row:not(.cfg__row--qty):has(input:checked) .cfg__price { background: none; color: var(--ink); }
.pdp .cfg__row:not(.cfg__row--qty):has(input:checked)::after {
  content: "";
  position: absolute;
  inset-inline-end: 0.75rem;
  top: 50%;
  width: 1.2rem;
  height: 1.2rem;
  margin-top: -0.6rem;
  border-radius: 50%;
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / 0.75rem no-repeat;
}
.pdp .cfg__row:not(.cfg__row--qty):has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- Product option groups: a card each, closed or open, at every width -----------
 * The phone rules above made each top-level group a card; on a wider screen a
 * closed group was still bare text over a dashed rule and the open one a lifted
 * chit, with its first option flush against the header's rule. Now one card per
 * group everywhere: the header inside it (the rule under it only while open), the
 * options inset from every edge, and an even gap between the cards. Nested groups
 * (inside a pick) stay flat, as before. */
.pdp .cfg:not(.cfg--nested),
.pdp .cfg[open]:not(.cfg--nested) {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: none;
  padding: 0;
  margin: 0 0 0.75rem;
}
.pdp .cfg:not(.cfg--nested):last-of-type { margin-bottom: 0; }
.pdp .cfg:not(.cfg--nested) > .cfg__head {
  margin: 0;
  padding: 0.9rem 1rem;
  background: var(--surface);
  box-shadow: none;
  border-radius: var(--radius);
  align-items: center;
}
.pdp .cfg[open]:not(.cfg--nested) > .cfg__head {
  border-bottom: 1px solid var(--line);
  border-end-start-radius: 0;
  border-end-end-radius: 0;
}
.pdp .cfg:not(.cfg--nested) > .cfg__list { padding: 0.9rem 1rem 1rem; }
.pdp .cfg:not(.cfg--nested) > .combo-sub { padding: 0 1rem 0.75rem; }
/* A package's contents and a combo's slots take the same inset as the options
 * list, at every width (it was phone-only, so on a wide screen the tiles ran to
 * the card's edges). */
.pdp .cfg:not(.cfg--nested) > .combo-grid--fixed { padding: 0.75rem 1rem 0.9rem; }
.pdp .cfg:not(.cfg--nested) > .combo-slot,
.pdp .cfg:not(.cfg--nested) > .combo-steps { padding-inline: 1rem; }
.pdp .cfg:not(.cfg--nested) > .combo-steps .combo-slot { padding-inline: 0; }

/* Menu page, desktop: the "Your order" panel stays in view while the bands
 * scroll. It was position: sticky already, but inside a grid cell only as tall
 * as itself (the layout aligns its items to the start), so it had no room to
 * stick in and scrolled away with the page. Stretching the aside to the row
 * gives it the whole height of the menu to travel down. */
@media (min-width: 64rem) {
  .menu-layout__aside { align-self: stretch; }
}

/* The order-page cards are not the menu's order panel. That panel shares the
 * .order-card name and is made sticky on wide screens (Menu layout + order
 * panel, above), which pinned every card on the cart, thank-you and tracking
 * pages so each slid over the one before it. */
:is(.cart-page, .thanks-page) .order-card { position: static; top: auto; box-shadow: none; }
/* The branch the order goes out from, under the service details. */
.thanks-branch { display: flex; align-items: center; gap: 0.45rem; margin: 0.85rem 0 0; padding-top: 0.85rem; border-top: 1px solid var(--line); font-size: 0.88rem; color: var(--muted); }
.thanks-branch strong { color: var(--ink); }
.thanks-branch svg { flex: none; color: var(--accent); }

/* ---- Working… — a service or branch choice on its way (theme.js) -----------------
 * The chosen control shows a spinner; the rest of its form is held still and
 * faded so a second tap cannot post another choice. On a branch / area row the
 * spinner takes the place of the Open badge and the chevron. */
.busy-spin {
  display: inline-block;
  flex: none;
  width: 1.1rem;
  height: 1.1rem;
  border: 2px solid color-mix(in srgb, currentColor 25%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: busy-spin 0.7s linear infinite;
  vertical-align: -0.2em;
}
@keyframes busy-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .busy-spin { animation-duration: 1.6s; } }

form.is-submitting button:not(.is-loading):not(.delivery-modal__close),
form.is-submitting .area:not(.is-loading) { opacity: 0.5; pointer-events: none; }
form.is-submitting .is-loading { pointer-events: none; }

.btn.is-loading .busy-spin,
.order-toggle__opt.is-loading .busy-spin { margin-inline-start: 0.5rem; }

.area.is-loading { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 7%, var(--surface)); }
.area.is-loading .area__state,
.area.is-loading > svg:last-of-type { display: none; }
.area.is-loading .busy-spin { margin-inline-start: auto; color: var(--accent); }

/* ---- Listing pages (collection, category, brand, search, shop) ------------------
 * sections/main-collection & co.: the filter panel (snippets/product-filters)
 * beside the results on a wide screen and sticky under the header; on a tablet
 * or phone it sits above them. The sort pills (snippets/product-sort) wrap on a
 * wide screen and scroll sideways on a phone. The grid takes the editor's
 * column count (`--cols`) on a desktop, three on a tablet, two on a phone. */
.listing-page { padding: clamp(1.25rem, 3vw, 2.5rem) 0 clamp(2rem, 5vw, 3.5rem); }
/* Three children — the filters (aside), the page head, the results (main) —
 * placed by area: filters in their own column beside head and results on a
 * wide screen; head, filters, results top to bottom on a narrow one. */
.listing {
  display: grid;
  grid-template-columns: 16rem minmax(0, 1fr);
  grid-template-areas: "aside head" "aside main";
  grid-template-rows: auto 1fr;
  column-gap: clamp(1.25rem, 3vw, 2.25rem);
  align-items: start;
}
.listing__aside { grid-area: aside; position: sticky; top: calc(var(--stuck-top, 0px) + 1rem); min-width: 0; }
.listing__head { grid-area: head; margin-bottom: 1.25rem; min-width: 0; }
.listing__main { grid-area: main; min-width: 0; }
.listing--no-filters { grid-template-columns: minmax(0, 1fr); grid-template-areas: "head" "main"; }
.listing--no-filters .listing__aside { display: none; }
.listing__title { margin: 0; font-family: var(--font-display); font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.25rem); font-weight: 700; line-height: 1.15; overflow-wrap: anywhere; }
.listing__desc { margin: 0.6rem 0 0; max-width: 42rem; color: var(--ink-soft, var(--muted)); }
.listing__meta { margin: 0.5rem 0 0; font-size: 0.9rem; color: var(--muted); }
.listing__grid { display: grid; grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr)); gap: clamp(0.75rem, 2vw, 1.5rem); }
.listing__empty { color: var(--muted); }

/* Filter panel */
.product-filters { padding: 1rem 1.1rem 1.1rem; border: 1px solid var(--line); border-radius: 16px; background: var(--surface); }
.product-filters__head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; padding-bottom: 0.75rem; border-bottom: 1px solid var(--line); }
.product-filters__head strong { font-family: var(--font-display); font-size: 1rem; }
.product-filters__head span { font-size: 0.8rem; color: var(--muted); }
.product-filters__chips { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; padding-top: 0.75rem; }
.product-filters__chip { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.2rem 0.6rem; border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line)); border-radius: var(--radius-pill); background: color-mix(in srgb, var(--accent) 8%, var(--surface)); color: var(--ink); font-size: 0.78rem; text-decoration: none; }
.product-filters__chip span { color: var(--danger); font-weight: 700; }
.product-filters__clear { font-size: 0.78rem; color: var(--danger); }
.product-filters__group { padding: 0.75rem 0; border-bottom: 1px solid var(--line); }
.product-filters__group summary { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; font-size: 0.88rem; font-weight: 700; color: var(--ink); cursor: pointer; list-style: none; }
.product-filters__group summary::-webkit-details-marker { display: none; }
.product-filters__group summary svg { color: var(--muted); transition: transform 0.18s; }
.product-filters__group[open] summary svg { transform: rotate(180deg); }
.product-filters__values { display: grid; gap: 0.35rem; margin: 0.6rem 0 0; padding: 0; list-style: none; }
.product-filters__value { display: flex; align-items: center; gap: 0.55rem; min-height: 2rem; font-size: 0.88rem; color: var(--ink); cursor: pointer; }
.product-filters__value input { width: 1.05rem; height: 1.05rem; accent-color: var(--accent); }
.product-filters__value span { flex: 1; }
.product-filters__value em { font-style: normal; font-size: 0.75rem; color: var(--muted); }
.product-filters__value.is-empty { opacity: 0.45; }
.product-filters__price { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 0.5rem; margin-top: 0.6rem; }
.product-filters__price input { width: 100%; min-height: 2.5rem; padding: 0.4rem 0.7rem; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); color: var(--ink); font: inherit; font-size: 0.88rem; }
.product-filters__price input:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; border-color: var(--accent); }
.product-filters__price span { color: var(--muted); }
.product-filters__apply { width: 100%; min-height: 44px; margin-top: 1rem; border-radius: var(--radius-pill); justify-content: center; }

/* Sort pills */
.product-sort { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 1.25rem; }
.product-sort__label { flex: none; font-size: 0.82rem; color: var(--muted); white-space: nowrap; }
.product-sort__options { display: flex; flex-wrap: wrap; gap: 0.4rem; min-width: 0; }
.product-sort__opt { flex: none; padding: 0.35rem 0.8rem; border: 1px solid var(--line); border-radius: var(--radius-pill); background: var(--surface); color: var(--ink-soft, var(--ink)); font-size: 0.82rem; white-space: nowrap; text-decoration: none; }
.product-sort__opt:hover { border-color: var(--accent); color: var(--accent); }
.product-sort__opt.is-active { border-color: var(--accent); background: var(--accent); color: var(--accent-contrast, #fff); }

@media (max-width: 63.99rem) {
  .listing,
  .listing--no-filters { grid-template-columns: minmax(0, 1fr); grid-template-areas: "head" "aside" "main"; grid-template-rows: auto; row-gap: 1rem; }
  .listing--no-filters { grid-template-areas: "head" "main"; }
  .listing__aside { position: static; }
  .listing__head { margin-bottom: 0; }
  .listing__grid { grid-template-columns: repeat(min(var(--cols, 3), 3), minmax(0, 1fr)); }
}
@media (max-width: 40rem) {
  .listing__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* One row of pills that scrolls, not a column of words. */
  .product-sort { margin-inline: calc(var(--gutter, 1rem) * -1); padding-inline: var(--gutter, 1rem); }
  .product-sort__options { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-bottom: 0.15rem; }
  .product-sort__options::-webkit-scrollbar { display: none; }
}

/* Side column: its cards stack with a gap (shop: departments, filters, brands). */
.listing__aside { display: grid; gap: 1rem; align-content: start; }
/* Brand head: the logo beside the name. */
.listing__head--brand { display: flex; align-items: center; gap: 1rem; }
.listing__logo { flex: none; width: 4.5rem; height: 4.5rem; object-fit: cover; border: 1px solid var(--line); border-radius: 12px; background: var(--surface); }
.listing__eyebrow { margin: 0 0 0.2rem; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
/* Search head: the field and its button, then the result line. */
.listing__search { display: flex; gap: 0.6rem; max-width: 34rem; }
.listing__search .input { flex: 1; min-width: 0; min-height: 3rem; border-radius: var(--radius-pill); padding-inline: 1.1rem; }
.listing__search .btn { flex: none; min-height: 3rem; border-radius: var(--radius-pill); }
.listing__title--search { margin-top: 1.25rem; font-size: clamp(1.35rem, 1.1rem + 1vw, 1.8rem); }
.listing__empty--box { padding: 2rem 1.25rem; border: 1px dashed var(--line-2, var(--line)); border-radius: 16px; background: var(--surface); text-align: center; }
.listing__empty--box a { color: var(--accent); font-weight: 600; }
/* Shop side cards: departments → categories, brands. */
.listing-card { padding: 0.75rem; border: 1px solid var(--line); border-radius: 16px; background: var(--surface); }
.listing-card__title { display: block; padding: 0.25rem 0.5rem 0.5rem; font-family: var(--font-display); font-size: 0.95rem; }
.listing-card__list { display: grid; gap: 0.15rem; margin: 0; padding: 0; list-style: none; }
.listing-card__list--sub { margin: 0.2rem 0 0.35rem; padding-inline-start: 0.75rem; }
.listing-card__link { display: block; padding: 0.45rem 0.65rem; border-radius: 10px; color: var(--ink); font-size: 0.9rem; text-decoration: none; }
.listing-card__link:hover { background: color-mix(in srgb, var(--ink) 5%, var(--surface)); color: var(--ink); }
.listing-card__link.is-active { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); color: var(--accent); font-weight: 700; }
.listing-card__none { padding: 0.45rem 0.65rem; font-size: 0.88rem; color: var(--muted); }
.listing-card__dept summary { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.45rem 0.65rem; border-radius: 10px; font-size: 0.9rem; font-weight: 700; cursor: pointer; list-style: none; }
.listing-card__dept summary::-webkit-details-marker { display: none; }
.listing-card__dept summary em { font-style: normal; font-size: 0.78rem; font-weight: 600; color: var(--muted); }
@media (max-width: 40rem) {
  .listing__search .btn { padding-inline: 1rem; }
}

/* The filter panel's head is its fold (snippets/product-filters, a <details>):
 * on a wide screen it is always open and the head is only a heading; on a
 * tablet or phone it is a bar — "Filter · N results" with a caret — that opens
 * the panel, and theme.js starts it folded. */
.product-filters__head { list-style: none; cursor: default; }
.product-filters__head::-webkit-details-marker { display: none; }
.product-filters__head span { display: inline-flex; align-items: center; gap: 0.35rem; }
.product-filters__count { display: inline-flex; align-items: center; justify-content: center; min-width: 1.3rem; height: 1.3rem; margin-inline-start: 0.35rem; padding: 0 0.35rem; border-radius: var(--radius-pill); background: var(--accent); color: var(--accent-contrast, #fff); font-family: var(--font-body, inherit); font-size: 0.72rem; font-style: normal; vertical-align: 0.1em; }
.product-filters__caret { display: none; color: var(--muted); transition: transform 0.18s; }
@media (min-width: 64rem) {
  .product-filters__head { pointer-events: none; }
}
@media (max-width: 63.99rem) {
  .product-filters__head { cursor: pointer; }
  .product-filters__caret { display: inline-block; }
  .product-filters[open] .product-filters__caret { transform: rotate(180deg); }
  .product-filters:not([open]) .product-filters__head { padding-bottom: 0; border-bottom: 0; }
}

/* ---- No photo: a plain placeholder, never a stock picture ----------------------
 * A dish, a cart line, a product or a category without its own image shows this
 * — the slot's shape in a soft ground with a small picture icon — so the grid
 * keeps its rhythm without implying the dish looks like someone else's photo. */
.media-ph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background: linear-gradient(160deg, var(--surface-3, #eee), var(--line-2, #ddd));
  color: var(--muted);
}
.media-ph svg { opacity: 0.55; }
.dish__img.media-ph { position: absolute; inset: 0; }
.pdp__media > .media-ph { position: absolute; inset: 0; }
/* The plate, fork and knife (snippets/dish-placeholder), sized to the slot. */
.media-ph .dish-ph { width: min(46%, 6.5rem); height: auto; opacity: 0.45; }
.cart-line__media .media-ph .dish-ph, .cfg__thumb .media-ph .dish-ph { width: 70%; }

/* ---- Menu page head (sections/main-menu, editor: Menu → Page head) ----------------
 * Edge to edge, on its own ground: a colour (white by default, not the page's
 * cream), an image under a darkening overlay, or none. Three heights. Over an
 * image the text turns white unless the editor sets a text colour. */
.menu-page.section { padding-top: 0; }
.menu-hero {
  position: relative;
  isolation: isolate;
  padding-block: clamp(2.5rem, 5vw, 3.75rem);
  background: var(--mh-bg, transparent);
  color: var(--mh-fg, var(--ink));
  border-bottom: 1px solid var(--line);
}
.menu-hero--pad-small { padding-block: clamp(1.25rem, 3vw, 2rem); }
.menu-hero--pad-large { padding-block: clamp(4rem, 9vw, 6.5rem); }
.menu-hero--none { background: transparent; border-bottom: 0; }
.menu-hero--image { background: var(--ink) var(--mh-img, none) center / cover no-repeat; color: var(--mh-fg, #fff); border-bottom: 0; }
.menu-hero--image::before { content: ""; position: absolute; inset: 0; z-index: -1; background: rgb(0 0 0 / var(--mh-overlay, 0.4)); }
.menu-hero .section__head { margin-bottom: 0; }
.menu-hero .section__title { color: inherit; }
.menu-hero__sub { margin: 0.6rem 0 0; font-size: clamp(1rem, 0.9rem + 0.4vw, 1.15rem); color: inherit; opacity: 0.85; }
.menu-hero__meta { margin: 0.5rem 0 0; font-size: 0.95rem; color: inherit; opacity: 0.7; }
.section__head--center .menu-hero__sub { max-width: 40rem; margin-inline: auto; }
.menu-hero__search-only { padding-top: 1.5rem; }
/* The rail sits right under the head; the head's own rule is enough. */
.menu-hero + .menu-rail, .menu-hero ~ .menu-rail { border-top: 0; }

/* ---- Arabic faces for right-to-left pages -----------------------------------------
 * Loaded by layout/theme.liquid only on an RTL page. Cairo for headings and
 * Tajawal for body text; Poppins/Inter stay as fallbacks for any Latin run
 * (prices, product names typed in English). */
:root[dir="rtl"] {
  --font-display: "Cairo", "Poppins", "Segoe UI", system-ui, sans-serif;
  --font-body: "Tajawal", "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
/* Arabic sets taller than Latin at the same size; a touch more line height
 * keeps the dots and marks from crowding the line above. */
:root[dir="rtl"] body { line-height: 1.7; }

/* Delivery area rows: the chevron points the way the row leads, left in RTL.
 * Scoped to this row on purpose — other arrows in the theme carry their own
 * RTL flips, and a blanket rule would turn those back round. */
[dir="rtl"] .area > svg:last-child { transform: scaleX(-1); }

/* Cards are plain cards across the theme: no accent stripe along a card's top
 * edge and no accent rule over its total. The platform checkout's summary
 * draws both; flattened here so it matches the cart and the account pages. */
/* `body` first: the platform's own rule has the same two classes and its
 * stylesheet loads after this one, so an equal-weight rule here lost. */
body .checkout-page .chk-summary { border-top: 1px solid var(--checkout-line, var(--line)); }
body .checkout-page .chk-summary .chk-summary__row--total { border-top: 1px solid var(--checkout-line, var(--line)); }

/* ---- Searchable dropdown (theme.js, "Searchable dropdown") ------------------------
 * The country-code and country selects drawn as the theme's own control: a
 * field-shaped button, and a panel with a search field over the options. The
 * real <select> stays in the form, visually hidden. On a phone the panel is a
 * sheet from the bottom over a dimmed page. */
.sselect__native {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0 !important;
  opacity: 0 !important;
  pointer-events: none !important;
  clip-path: inset(50%) !important;
}
.sselect { position: relative; flex: 1 1 auto; min-width: 0; }
.sselect--dial { flex: 0 1 auto; width: 9.5rem; max-width: 45%; }
.sselect__btn {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  min-height: 3rem;
  padding: 0.55rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.92rem;
  text-align: start;
  cursor: pointer;
}
.sselect__btn:focus-visible,
.sselect.is-open .sselect__btn { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; border-color: var(--accent); }
.sselect__value { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.sselect--dial .sselect__value .sselect__name { display: none; }
.sselect--dial .sselect__value .sselect__code { font-weight: 600; }
.sselect__caret { flex: none; color: var(--muted); transition: transform 0.18s; }
.sselect.is-open .sselect__caret { transform: rotate(180deg); }

.sselect__panel {
  position: absolute;
  z-index: 60;
  top: calc(100% + 0.35rem);
  inset-inline-start: 0;
  width: max(100%, 17rem);
  max-height: 20rem;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  box-shadow: var(--shadow-lg, 0 18px 40px rgba(0, 0, 0, 0.14));
  overflow: hidden;
}
.sselect__panel[hidden] { display: none; }
.sselect__search { position: relative; flex: none; padding: 0.6rem; border-bottom: 1px solid var(--line); }
.sselect__search svg { position: absolute; top: 50%; inset-inline-start: 1.3rem; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.sselect__search input {
  width: 100%;
  min-height: 2.5rem;
  padding: 0.4rem 0.8rem;
  padding-inline-start: 2.2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface-2, var(--surface));
  color: var(--ink);
  font: inherit;
  font-size: 0.9rem;
}
.sselect__search input:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; border-color: var(--accent); }
.sselect__list { flex: 1; min-height: 0; margin: 0; padding: 0.35rem; list-style: none; overflow-y: auto; overscroll-behavior: contain; }
.sselect__opt {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 0.7rem;
  border-radius: 10px;
  font-size: 0.9rem;
  cursor: pointer;
}
.sselect__opt[hidden] { display: none; }
.sselect__opt .sselect__name { flex: 1; min-width: 0; }
.sselect__opt .sselect__code { flex: none; color: var(--muted); font-variant-numeric: tabular-nums; }
.sselect__opt.is-active { background: color-mix(in srgb, var(--ink) 6%, var(--surface)); }
.sselect__opt[aria-selected="true"] { color: var(--accent); font-weight: 700; }
.sselect__opt[aria-selected="true"] .sselect__code { color: inherit; }
.sselect__none { margin: 0; padding: 1rem; text-align: center; color: var(--muted); font-size: 0.88rem; }
.sselect__none[hidden] { display: none; }
.sselect__backdrop { position: fixed; inset: 0; z-index: 59; background: rgba(20, 20, 20, 0.35); }
.sselect__backdrop[hidden] { display: none; }

@media (max-width: 40rem) {
  .sselect__panel {
    position: fixed;
    top: auto;
    inset-inline: 0;
    bottom: 0;
    width: auto;
    max-height: 75dvh;
    border-radius: 20px 20px 0 0;
    border-bottom: 0;
  }
  .sselect__search { padding: 0.9rem; }
  .sselect__opt { padding-block: 0.75rem; }
}

/* Searchable dropdown inside checkout's fields. The dropdown sits in the
 * platform's <label class="chk-field">, whose rules restyle every span in the
 * label (uppercase, tracked, muted) and every input (its own padding) with a
 * heavier selector than the dropdown's — so the country names came out in
 * capitals and the search text ran under the icon. Reset at a weight that
 * holds whichever stylesheet loads last. */
.sselect .sselect__btn span.sselect__value,
.sselect .sselect__btn span.sselect__name,
.sselect .sselect__btn span.sselect__code,
.sselect .sselect__opt span.sselect__name,
.sselect .sselect__opt span.sselect__code {
  text-transform: none;
  letter-spacing: normal;
  font-size: inherit;
  line-height: inherit;
  margin: 0;
}
.sselect .sselect__btn span.sselect__value,
.sselect .sselect__opt span.sselect__name { color: inherit; font-weight: inherit; }
.sselect .sselect__opt span.sselect__code { color: var(--muted); font-weight: 600; }
.sselect .sselect__opt[aria-selected="true"] span.sselect__code { color: inherit; }
.sselect .sselect__search input[type="search"] {
  width: 100%;
  min-height: 2.5rem;
  margin: 0;
  padding-block: 0.4rem;
  padding-inline: 2.3rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface-2, var(--surface));
  font-size: 0.9rem;
  text-transform: none;
  letter-spacing: normal;
}
.sselect .sselect__search svg { inset-inline-start: 1.35rem; z-index: 1; }
/* The dial-code button is exactly as tall as the number field beside it: the
 * row (.auth-phone / .chk-phone) is a flex row, the dropdown stretches to it,
 * and the button fills that height instead of setting its own. */
.sselect--dial { align-self: stretch; display: flex; }
.sselect--dial .sselect__btn { height: auto; min-height: 0; align-self: stretch; padding-block: 0; }

/* Custom dropdown on every select: the button takes the height of the text
 * fields in its form (--sselect-h, measured by theme.js), a "choose…" option
 * reads as a placeholder, a disabled list looks it, and a short list has no
 * search field. */
.sselect__btn { min-height: var(--sselect-h, 3rem); }
.sselect.is-placeholder .sselect__value { color: var(--muted); }
.sselect--disabled .sselect__btn { opacity: 0.55; cursor: not-allowed; }
.sselect__search[hidden] { display: none; }
.sselect__panel:focus { outline: none; }
.sselect__opt.is-disabled { opacity: 0.45; cursor: default; }

/* ---- Full-width page grounds, without clipping ------------------------------------
 * The account, wallet, sign-in, cart, order and checkout pages ran their tint
 * edge to edge with a 100vmax box-shadow held in by `clip-path`. But clip-path
 * clips everything painted inside the element — position: fixed children
 * included — so the phone order screen's pinned foot ("Add item" / "Proceed"),
 * and the checkout's own pinned bar and pop-ups, were cut away as soon as the
 * page's bottom edge scrolled above the viewport's. A border-image outset
 * paints the same side bands and clips nothing; html's overflow-x: clip keeps
 * the page from scrolling sideways. */
.account-page,
.wallet-page,
.auth-page {
  clip-path: none;
  box-shadow: none;
  border-image: conic-gradient(var(--surface-2, transparent) 0 0) fill 0 / / 0 100vmax;
}
.cart-page,
.thanks-page {
  clip-path: none;
  box-shadow: none;
  border-image: conic-gradient(color-mix(in srgb, var(--accent) 3%, var(--surface-2, var(--surface))) 0 0) fill 0 / / 0 100vmax;
}
.checkout-page {
  clip-path: none;
  box-shadow: none;
  border-image: conic-gradient(color-mix(in srgb, var(--checkout-accent, var(--accent, #bc906b)) 3%, var(--checkout-paper, var(--paper, #fff))) 0 0) fill 0 / / 0 100vmax;
}

/* Room above the footer's brand badge. The footer sits directly under the page
 * (no margin), and its badge rises 2.75rem over the footer's edge — into the
 * last page's bottom padding. These pages ended with as little as 2rem, so the
 * badge sat on their last line ("Continue shopping"). 4rem at least leaves it
 * clear space. The cart is left alone: on a phone it hides the footer and pads
 * for its own pinned bar. */
.thanks-page,
.listing-page,
.account-page,
.wallet-page,
.auth-page {
  padding-bottom: clamp(4rem, 7vw, 5.5rem);
}

/* ---- Back link (order tracking) --------------------------------------------------
 * A small pill at the top of the page, the wallet's back link in shape. */
.page-back {
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
}
.page-back:hover { border-color: var(--ink); color: var(--ink); }
[dir="rtl"] .page-back svg { transform: scaleX(-1); }
