:root {
    --brand-red: #E21B22;
    --brand-red-dark: #c8161d;
    --brand-red-soft: #FDECEE;
    --brand-green: #16a34a;
    --brand-green-dark: #15803d;
    --text: #1a1a1a;
    --muted: #6b6b6b;
    --border: #E5E7EB;
    --bg-soft: #F4F4F5;
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.04);
    --shadow-md: 0 4px 12px rgba(0,0,0,0.06);
    --header-h: 64px;   /* single-row header: logo + store name + slider + nav on one line */
    --sidebar-w: 130px;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

/* Minimal scrollbars on desktop — hairline rounded thumb, no track, no arrow
   buttons. Universal so the page and every inner pane match; components that
   declare their own ::-webkit-scrollbar / scrollbar-* (the 4px panes, and the
   carousels that hide theirs) keep winning on class specificity. Desktop-only:
   touch scrollbars are already overlay/invisible and mobile hides html/body. */
@media (min-width: 992px) {
    /* Firefox has no ::-webkit-scrollbar, so the standard properties are all it gets. */
    @supports not selector(::-webkit-scrollbar) {
        * {
            scrollbar-width: thin;
            scrollbar-color: rgba(0, 0, 0, 0.18) transparent;
        }
    }
    /* Chromium/WebKit must keep scrollbar-width at `auto`: any non-auto value
       (site.css sets `thin` globally on the non-menu layouts) makes Chromium 121+
       discard the pseudo-element rules below and paint its stock thin bar instead.
       Components that declare their own scrollbar-width still opt out, by design. */
    @supports selector(::-webkit-scrollbar) {
        * { scrollbar-width: auto; }
    }
    *::-webkit-scrollbar { width: 8px; height: 8px; }
    *::-webkit-scrollbar-track { background: transparent; }
    *::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.18); border-radius: 999px; }
    *::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.32); }
    *::-webkit-scrollbar-button,
    *::-webkit-scrollbar-corner { display: none; background: transparent; }
}

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
    color: var(--text);
    background: #fff;
}

button { font-family: inherit; cursor: pointer; }

/* Prices, totals and offer amounts use tabular figures so digits line up in columns
   and a total doesn't change width as it recalculates. Inter ships true tabular
   numerals; this one rule covers every .*price* / .*total* / .*amount* class on the
   ordering pages (menu.css is loaded document-wide by _MenuLayout). */
[class*="price"], [class*="total"], [class*="amount"] {
    font-variant-numeric: tabular-nums;
}

/* ============ Page shell ============ */
.menu-page { min-height: 100vh; display: flex; flex-direction: column; }

/* ============ Header ============ */
.menu-header {
    height: var(--header-h);
    /* Single row: [logo] [store name] … [order-type slider] [nav]. (Desktop; mobile refines
       this in the ≤720 block and moves the slider below the header via JS.) */
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 0 28px;
    border-bottom: 1px solid var(--border);
    background: #fff;
    position: sticky;
    top: 0;
    z-index: 30;
}
.menu-header > .menu-nav { margin-left: auto; }   /* nav (and anything after it) hugs the right */

/* Back button — first child of .menu-header, injected by _MenuLayout (it only exists when
   there is somewhere to go back TO, so there is no markup for it in the page views). Walks
   the real navigation stack, so it is a plain icon with no destination label. */
.pt-back-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    margin-left: -6px;          /* optically align the arrow with the page gutter */
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text);
    cursor: pointer;
}
.pt-back-btn:hover { background: var(--bg-soft); }
.pt-back-btn:focus-visible { outline: 2px solid var(--brand-red); outline-offset: 1px; }
.pt-back-btn svg { width: 22px; height: 22px; }

/* Logo + store selector, grouped so they can read as one tappable unit. Plain (no border/
   background) on desktop — that look is mobile-only, added in the ≤720 block below. */
.menu-store-pill {
    display: inline-flex;
    align-items: center;
    gap: 16px;
    min-width: 0;
}

/* Logo is a link back to the store home — keep it underline-free and tidy. Now the circular
   badge (logo-badge.png), sat above the store-locator link. */
.menu-brand { grid-area: brand; justify-self: start; display: inline-flex; align-items: center; text-decoration: none; }
.menu-brand img { height: 48px; width: auto; display: block; }

/* Container for the two header anchors (Home + address). Now a flex row
   with no underline of its own; underline + cursor styles live on the
   inner <a> tags so each link feels clickable in isolation. */
.menu-store-link {
    grid-area: store;
    justify-self: start;        /* sit under the badge, left-aligned */
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--text);
    font-size: 0.875rem;
    max-width: 380px;
    /* The flexible middle of the header. min-width:0 lets it shrink below the
       address's intrinsic (no-wrap) width so the address ellipsizes instead of
       pushing the brand + nav past the viewport on tablet widths. */
    min-width: 0;
}

.menu-store-home {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    padding: 2px 0;
}
.menu-store-home:hover .menu-store-label { text-decoration: underline; }

/* Address button — a clickable pill matching the order-type button; opens the
   Stores (store-selection) page. The leading location pin is a CSS-only SVG
   background, so no markup change is needed. */
.menu-store-addr-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    padding: 5px 12px;
    border: 1px solid var(--border);
    background: #fff;
    border-radius: 999px;
    color: var(--text);
    text-decoration: none;
    cursor: pointer;
    line-height: 1;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.menu-store-addr-link::before {
    content: "";
    flex-shrink: 0;
    width: 15px;
    height: 15px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 21s-7-6.2-7-11a7 7 0 1 1 14 0c0 4.8-7 11-7 11z' fill='none' stroke='%23E21B22' stroke-width='2' stroke-linejoin='round'/%3E%3Ccircle cx='12' cy='10' r='2.5' fill='%23E21B22'/%3E%3C/svg%3E") center / contain no-repeat;
}
.menu-store-addr-link:hover {
    background: var(--brand-red-soft);
    border-color: var(--brand-red);
}
.menu-store-addr-link:focus-visible {
    outline: 2px solid var(--brand-red);
    outline-offset: 1px;
}

.menu-store-label { font-weight: 700; text-decoration: underline; }
/* Store name in black. Wraps (up to whatever it needs, normally 2 lines) instead of
   ellipsising — the full outlet name must always be readable; the max-width still caps
   how wide it can push the header. */
.menu-store-addr { color: #111; white-space: normal; overflow-wrap: anywhere; line-height: 1.15; font-size: 0.8125rem; max-width: 260px; min-width: 0; }
.menu-store-chev { width: 14px; height: 14px; color: var(--muted); margin-left: 2px; }

.menu-nav {
    grid-area: nav;
    justify-self: end;          /* right edge, spanning both stacked rows */
    display: flex;
    align-items: center;
    gap: 8px;
}

.menu-nav-item {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border: 0;
    background: transparent;
    border-radius: 8px;
    color: var(--text);
    font-size: 0.875rem;
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
}

.menu-nav-item:hover { background: var(--bg-soft); }
/* Selected page. Was weight-only (500 → 600) in the same --text colour, which read as
   "nothing is selected" — brand red + a tab underline so the current page is obvious.
   The bar rides the item's existing position:relative; icons inherit currentColor. */
.menu-nav-item.is-active { color: var(--brand-red); font-weight: 600; }
.menu-nav-item.is-active::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: -2px;
    height: 3px;
    border-radius: 2px;
    background: var(--brand-red);
}
.menu-nav-item svg { width: 18px; height: 18px; }

/* ── Header order-type indicator (icon only) ──────────────────────────────
   An inline <span> inside the address link (.menu-store-addr-link), between
   the address text and the chevron. Purely a visual indicator — not a button,
   not separately clickable. Shows the selected order type's red icon. The
   parent link's `gap` handles spacing. Desktop-only because .menu-store-link
   is hidden on mobile. */
.menu-store-ot-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: #b32222;
    line-height: 1;
}
.menu-store-ot-ico .pt-mi { font-size: 1.125rem; color: #b32222; line-height: 1; }
.menu-store-ot-ico svg { width: 18px; height: 18px; color: #b32222; }

/* Order-type button — sits beside the address link in the header and opens the
   order-type picker. Styled as a distinct, clearly-clickable pill (border + white
   fill) so it reads as a button, with a brand-red hover/active tint and focus ring. */
.menu-store-ot-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 10px;
    border: 1px solid var(--border);
    background: #fff;
    color: var(--text);
    cursor: pointer;
    border-radius: 999px;
    line-height: 1;
    transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.menu-store-ot-btn:hover {
    background: var(--brand-red-soft);
    border-color: var(--brand-red);
}
.menu-store-ot-btn:active {
    background: var(--brand-red-soft);
    border-color: var(--brand-red);
    transform: translateY(0.5px);
}
.menu-store-ot-btn:focus-visible {
    outline: 2px solid var(--brand-red);
    outline-offset: 1px;
}
/* Chevron lives inside the pill — drop the legacy left margin (gap handles spacing)
   and give a small downward nudge on hover as an "opens a menu" affordance. */
.menu-store-ot-btn .menu-store-chev {
    margin-left: 0;
    transition: transform 0.15s ease;
}
.menu-store-ot-btn:hover .menu-store-chev { transform: translateY(1px); }

/* Order-type text label inside the header pill (e.g. "Delivery"). Painted by JS
   (syncDrawerEntry) with the current type's localized label. Shown on desktop and
   mobile. */
.menu-store-ot-label {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text);
    line-height: 1;
    white-space: nowrap;
}
/* Compact store NAME — shown only on mobile (desktop shows the full address). */
.menu-store-name-m { display: none; }

.menu-nav-new {
    position: absolute;
    top: -4px;
    left: 50%;
    transform: translateX(-50%);
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--brand-red);
    color: #fff;
    font-size: 0.5625rem;
    font-weight: 700;
    letter-spacing: 0.04em;
}

/* ── Cart trigger: red pill, white icon disc, live count (per design ref) ──
   Not a plain nav item — it's the primary action in the header. The "Cart"
   label is a bare text node with no element to hide, so font-size:0 on the
   button drops it and the count re-declares its own size. `order` puts the
   disc first: in the DOM the count span still comes before the icon, from
   when it was an absolutely-positioned corner badge. These rules sit after
   `.menu-nav-item svg` and `.menu-nav-item:hover`, which they tie on
   specificity and must win.

   The `.menu-nav .menu-nav-item` prefix is load-bearing: the ≤1024 rule
   `.menu-nav .menu-nav-item { padding: 6px 8px; font-size: 0.8125rem }` outranks a
   bare `.menu-cart-trigger`, which flattened the pill's padding AND un-hid the "Cart"
   label between 721px and 1024px. */
.menu-nav .menu-nav-item.menu-cart-trigger {
    gap: 8px;
    padding: 4px 14px 4px 4px;
    border-radius: 999px;
    background: var(--brand-red);
    color: #fff;
    font-size: 0;
}

.menu-nav .menu-nav-item.menu-cart-trigger:hover { background: var(--brand-red-dark); }

.menu-nav .menu-nav-item.menu-cart-trigger svg {
    order: 1;
    width: 28px;
    height: 28px;
    padding: 6px;                    /* box-sizing:border-box is global → 16px glyph */
    border-radius: 50%;
    background: #fff;
    color: var(--brand-red);
}

.menu-nav .menu-nav-item.menu-cart-trigger .menu-cart-count {
    order: 2;
    color: #fff;
    font-size: 0.9375rem;
    font-weight: 700;
}

/* ============ Breadcrumbs ============
   Rendered by Views/Shared/_Breadcrumbs.cshtml directly under the page header. Only ever
   shown with 2+ hops. The separator is a ::before on every item after the first, so it is
   presentational and never read out. On narrow screens the trail scrolls sideways rather
   than wrapping into two lines — standard mobile breadcrumb behaviour. */
.pt-crumbs {
    display: none;                                /* hidden for now (per request) — delete this line to restore */
    padding: 12px 28px 0;
    overflow-x: auto;
    scrollbar-width: none;                        /* Firefox: no bar for a 1-line strip */
}

.pt-crumbs::-webkit-scrollbar { display: none; }

.pt-crumbs ol {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 0;
    list-style: none;
    white-space: nowrap;
    font-size: 0.8125rem;
}

.pt-crumbs li { display: inline-flex; align-items: center; gap: 6px; }

.pt-crumbs li + li::before {
    content: '›';
    color: var(--muted);
    font-size: 0.9375rem;
    line-height: 1;
}

.pt-crumbs a {
    color: var(--muted);
    text-decoration: none;
    border-radius: 4px;
}

.pt-crumbs a:hover { color: var(--brand-red); text-decoration: underline; }
.pt-crumbs a:focus-visible { outline: 2px solid var(--brand-red); outline-offset: 2px; }

/* Current page — not a link, so it needs the weight to read as "you are here". */
.pt-crumbs-current { color: var(--text); font-weight: 600; }

@media (max-width: 1024px) {
    .pt-crumbs { padding: 10px 16px 0; }
}

@media (max-width: 720px) {
    .pt-crumbs { padding: 8px 12px 0; }
    .pt-crumbs ol { font-size: 0.75rem; }
}

@media print { .pt-crumbs { display: none; } }

/* ============ Shell layout: sidebar + main ============ */
.menu-shell {
    flex: 1;
    display: grid;
    grid-template-columns: var(--sidebar-w) 1fr;
    min-height: 0;
}

/* Desktop gutters, matching .store-home so both pages are framed identically — same outer box,
   same gutters, no shift when you navigate between them. The category rail sits inside the cap
   rather than pinned to the glass edge: a full-height rail against the viewport edge while the
   page it belongs to is centred reads as two different layouts.

   1096 is NOT an independent choice here — it is .store-home's cap, which is itself derived from
   the two-banner rail width (see the note there). These two values must move together; changing
   one alone makes the pages jump on navigation. The cost is real and was accepted deliberately:
   the menu grid loses the width the sidebar takes, so cards are narrower here than on the home
   page. Widen both if that bites. */
@media (min-width: 1025px) {
    .menu-shell {
        max-width: 1096px;
        margin-left: auto;
        margin-right: auto;
        width: 100%;
    }
}

/* ============ Sidebar ============ */
.menu-sidebar {
    border-right: 1px solid var(--border);
    overflow-y: auto;
    overflow-x: hidden;
    /* Vertical padding trimmed 18 → 10; the 12px sides are load-bearing — the active
       category's indicator bar sits at right:-12px and this element clips overflow-x. */
    padding: 10px 12px;
    height: calc(100vh - var(--header-h));
    /* Hide scrollbar visually but keep scrolling */
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.menu-sidebar::-webkit-scrollbar { display: none; width: 0; height: 0; }

.menu-cats {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.menu-cat {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 5px 4px 2px;
    border-radius: 10px;
    cursor: pointer;
    text-align: center;
    transition: background 0.15s ease;
}

.menu-cat:hover { background: var(--bg-soft); }

.menu-cat.is-active {
    color: var(--brand-green);
}

.menu-cat.is-active .menu-cat-thumb {
    box-shadow: 0 0 0 2px var(--brand-green);
}

/* Active category — right-side indicator bar (per design ref) */
.menu-cat.is-active::after {
    content: '';
    position: absolute;
    right: -12px;
    top: 8px;
    bottom: 8px;
    width: 3px;
    border-radius: 2px;
    background: var(--brand-green);
}

.menu-cat-thumb {
    width: 56px;
    height: 56px;
    border-radius: 8px;         /* square tile (was a 50% circle) */
    background-color: #fef3c7;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    box-shadow: var(--shadow-sm);
}

.menu-cat-thumb--new      { background-image: linear-gradient(135deg, #fee2e2, #fecaca); }
/* Deals rail entry — the store home's red coupon badge (.store-promo--deals), not a food
   photo/tint: same white tag glyph on the same red so both surfaces share one "deals" mark. */
.menu-cat-thumb--deals    { display: grid; place-items: center; background: #e11d2a; color: #fff; }
.menu-cat-thumb--deals svg { width: 55%; height: 55%; }
.menu-cat-thumb--create   { background-image: linear-gradient(135deg, #fde68a, #f59e0b); }
.menu-cat-thumb--deep-pan { background-image: linear-gradient(135deg, #fca5a5, #ef4444); }
.menu-cat-thumb--halal    { background-image: linear-gradient(135deg, #bbf7d0, #16a34a); }
.menu-cat-thumb--sides    { background-image: linear-gradient(135deg, #a7f3d0, #22c55e); }
.menu-cat-thumb--plant    { background-image: linear-gradient(135deg, #bef264, #65a30d); }
.menu-cat-thumb--bread    { background-image: linear-gradient(135deg, #fde68a, #d97706); }
.menu-cat-thumb--wings    { background-image: linear-gradient(135deg, #fdba74, #ea580c); }

.menu-cat-label {
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.25;
    color: var(--text);
}

.menu-cat.is-active .menu-cat-label { color: var(--brand-green); }

/* ============ Main panel ============ */
.menu-main {
    /* Lock the main panel to the viewport so only the inner grid scrolls.
       Filters / sub-nav / section title stay pinned at the top.
       Side padding is 8px, not 28: the card grid runs edge-to-edge so the first/last card in
       each row reach the screen sides. 8 (not 0) is the card box-shadow's breathing room —
       this element is overflow:hidden and would clip it. */
    padding: 20px 8px 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    height: calc(100vh - var(--header-h));
    min-height: 0;
}

.menu-filters {
    display: none;
    gap: 8px;
    margin-bottom: 18px;
    flex-wrap: wrap;
    flex-shrink: 0;
}

.menu-filter {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: #fff;
    color: var(--text);
    font-size: 0.8125rem;
    font-weight: 500;
}

.menu-filter:hover { background: var(--bg-soft); }
.menu-filter.is-active { border-color: var(--brand-green); background: #f0fdf4; color: var(--brand-green); font-weight: 600; }
.menu-filter.is-active[data-filter="halal"]  { border-color: #16a34a; }
.menu-filter.is-active[data-filter="vegan"]  { border-color: #65a30d; color: #65a30d; background: #f7fee7; }
.menu-filter.is-active[data-filter="all"]    { border-color: var(--text); color: var(--text); background: #fff; }

.menu-filter-dot {
    width: 14px;
    height: 14px;
    border-radius: 3px;
    border: 1.5px solid currentColor;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: relative;
}

.menu-filter-dot::after {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
}

.menu-filter-dot--all { color: var(--text); border-radius: 999px; }
.menu-filter-dot--all::after { background: var(--text); }
.menu-filter-dot--veg { color: var(--brand-green); }
.menu-filter-dot--halal { color: #16a34a; border-radius: 999px; }
.menu-filter-dot--vegan { color: #65a30d; }
.menu-filter-dot--vegan::after { background: #65a30d; }

/* ============ Sub-category nav (e.g. Pizza → Veg / Non-Veg / Specialty) ============ */
.menu-sub-nav {
    display: flex;
    gap: 8px;
    align-items: center;
    overflow-x: auto;
    padding: 4px 2px 10px;
    margin: -4px 0 14px;
    border-bottom: 1px solid var(--border);
    scrollbar-width: thin;
    scrollbar-color: #d4d4d8 transparent;
    flex-shrink: 0;
}

.menu-sub-nav::-webkit-scrollbar { height: 4px; }
.menu-sub-nav::-webkit-scrollbar-track { background: transparent; }
.menu-sub-nav::-webkit-scrollbar-thumb { background: #d4d4d8; border-radius: 2px; }

.menu-sub-nav-item {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    padding: 8px 16px;
    border: 1px solid var(--border);
    background: #fff;
    color: var(--text);
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.menu-sub-nav-item:hover { background: var(--bg-soft); }

.menu-sub-nav-item.is-active {
    background: var(--brand-red);
    border-color: var(--brand-red);
    color: #fff;
}

.menu-section-title {
    margin: 0 0 16px 0;
    font-size: 1.375rem;
    font-weight: 700;
    flex-shrink: 0;
}

/* ============ Sectioned grid (category groups + sticky headers) ============
   The grid is no longer a single CSS-grid of cards — it's a flex column of
   per-category sections, each with its own sticky header and an inner card
   grid. This is what lets the category name "stick" while you scroll its
   items, and slides up out of view exactly when the next category's header
   takes its place. */
.menu-grid {
    display: flex;
    flex-direction: column;
    gap: 18px;
    /* The grid remains the only scroll surface inside .menu-main on desktop.
       Hide the scrollbar visually while keeping wheel/touch scrolling. */
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    /* `position: relative` makes the grid the offsetParent for every section
       inside, so scrollTo can use `sec.offsetTop` directly. Without this the
       descendants fall through to `<body>` as offsetParent (display:flex
       doesn't establish positioning), breaking sidebar-click → scroll. */
    position: relative;
    padding-bottom: 40px;
    scroll-behavior: smooth;
    scrollbar-width: none;       /* Firefox */
    -ms-overflow-style: none;    /* old Edge / IE */
}

.menu-grid::-webkit-scrollbar { display: none; width: 0; height: 0; }

.menu-cat-section {
    /* Each top-level category renders one of these. Borders + paddings sit on
       the head/body children so the sticky header can run edge-to-edge. */
    display: flex;
    flex-direction: column;
    /* `min-width: 0` lets the section shrink below its content's intrinsic
       size; without it, a long sub-nav pill would inflate the section width
       and push the page horizontally. */
    min-width: 0;
    max-width: 100%;
}

.menu-cat-section-head {
    /* Sticky to the top of the scroll container — see media queries below for
       the mobile `top` override when the whole page becomes the scroll context. */
    position: sticky;
    top: 0;
    z-index: 5;
    background: #fff;
    /* Left inset only on the CONTENT: .menu-main now hugs the screen edge (8px) so the card
       grid runs full-width, which left the sticky title flush against the viewport. Padding
       here (not margin) keeps the white background + bottom border edge-to-edge. */
    padding: 4px 0 6px 12px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--border);
    box-shadow: 0 2px 6px -2px #54525224;
}

.menu-cat-section-head h3 {
    /* Category name removed from the sticky bar (user request) — the bar itself (and any
       sub-category filter pills inside it) stays as the visual divider between sections. */
    display: none;
}

/* Per-section sub-nav (e.g. Pizza → All Pizza / Traditional / Fusion / …).
   Sits inside the sticky header so it stays pinned together with the title.
   Width is locked to the parent so pills overflowing the right edge are
   scrolled INSIDE the nav rather than pushing the whole page horizontally. */
.menu-cat-section-subnav {
    display: flex;
    gap: 8px;
    align-items: center;
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 10px 2px 4px;
    margin-top: 8px;
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
}

.menu-cat-section-subnav::-webkit-scrollbar { display: none; width: 0; height: 0; }

.menu-cat-section-subnav .menu-sub-nav-item {
    /* Don't let flex shrink the pills — keep their pill shape; sub-nav scrolls
       instead. */
    flex-shrink: 0;
}

/* Body wraps the inner card grids — for Pizza this contains multiple
   .menu-subcat-section blocks, one per sub-category anchor. For everything
   else it's a single block.  */
.menu-cat-section-body {
    display: flex;
    flex-direction: column;
    gap: 24px;
    min-width: 0;
    max-width: 100%;
}

.menu-subcat-section {
    display: grid;
    /* 4 cards per row across all categories on desktop. Smaller breakpoints below step down to
       3 / 2 columns so cards stay legible.

       Was 5, chosen when .menu-shell was full-bleed and this grid had ~1764px to spend (345px
       cards). The shell is now capped at 1096px to frame the page, which leaves the grid 950px —
       and 5 columns of that is a 182px card, well under the legibility floor this very rule exists
       to defend. 4 gives ~228px, in line with the 256px cards on the store home.

       Note the breakpoints below are VIEWPORT-based while this container is now a FIXED 950px
       above 1096px viewport, so they no longer describe how much room the grid actually has. They
       still work for the widths that matter (a narrower viewport does mean a narrower grid once
       the cap stops binding), but do not read them as container queries. */
    grid-template-columns: repeat(4, minmax(0, 1fr));
    /* `auto` (not max-content) so each implicit row track sizes to its TALLEST card and the
       cards stretch to fill it — equal-height cards per row. Paired with the align-self:stretch
       override below (the base .menu-card opts out with align-self:start for other grids). */
    grid-auto-rows: auto;
    align-content: start;
    /* Tightened from 18/32. The FAB straddles the photo but stays INSIDE the card box, so
       nothing bleeds into these gutters and they can be this small. */
    column-gap: 10px;
    row-gap: 16px;
    width: 100%;
    max-width: 100%;
    scroll-margin-top: 90px;     /* used by scrollIntoView for sub-nav clicks */
}

/* ── 2G card: warm cream card, inset rounded photo, floating red cart FAB ──
   The three --card-* values are the whole palette — tweak them to restyle every card. */
.menu-card {
    --card-bg: #FBF3E3;         /* warm cream */
    --card-ink: #5C2E1E;        /* name + price (dark warm brown) */
    --card-ink-soft: #8A6D52;   /* description (muted warm brown) */
    border: 0;
    /* Keep in step with the photo's top corners below (and the <img>/canvas rule) — the photo
       is flush to the card edge, so any mismatch shows as a sliver of cream in the corner. */
    border-radius: 12px;
    overflow: visible;          /* let the FAB straddle the photo's bottom edge */
    background: var(--card-bg);
    padding: 0;                 /* photo sits FLUSH to the card edges — the old 3px inset
                                   showed as a thin uneven cream sliver down the left. The
                                   text gutter now lives on .menu-card-body instead. */
    display: flex;
    flex-direction: column;
    align-self: start;          /* don't stretch to fill a tall grid row */
    box-shadow: 0 6px 20px rgba(70, 40, 20, 0.10);
    transition: box-shadow 0.18s ease, transform 0.18s ease;
}

.menu-card:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
}

/* Equal-height cards per row on the menu grid: override the base `align-self: start` so cards
   stretch to the row's tallest. Scoped to .menu-subcat-section ONLY — .store-grid and
   .store-carousel keep the base start-alignment on purpose. The card body already flexes
   (flex:1) and .menu-card-actions has margin-top:auto, so the buttons stay pinned to the
   bottom of every stretched card. Higher specificity than the base rule, so it always wins. */
.menu-subcat-section > .menu-card {
    align-self: stretch;
}

.menu-card-image {
    height: 180px;
    flex-shrink: 0;                 /* never collapse the image area */
    background-color: #ededed;   /* neutral placeholder (no golden); the real photo covers it */
    background-size: cover;
    background-position: center;
    position: relative;
    /* Flush with the card: the top corners take the card's own 18px, the bottom edge is
       square because the cream body butts straight up against it. Radius has to be repeated
       on the <img>/canvas below — the photo is a child, not a background, at that point. */
    border-radius: 12px 12px 0 0;
    /* overflow stays VISIBLE so the FAB can straddle the bottom edge. */
}

/* ── Recommended / Best Seller tag ────────────────────────────────────────────────
   Top-RIGHT of the photo; the quick-add FAB owns the bottom-right, so the two never meet.
   z-index 2 keeps it over the <img> but under the FAB (3). max-width + ellipsis so a
   translated label can't run off a narrow 2-up card. */
.menu-card-tag {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 2;
    max-width: calc(100% - 12px);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 3px 8px;
    border-radius: 999px;
    font-size: 0.625rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: #fff;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.22);
    pointer-events: none;       /* the whole card is clickable — never swallow that tap */
}
.menu-card-tag--rec  { background: var(--brand-red, #e11d2a); }
.menu-card-tag--best { background: #b45309; }   /* amber-700: reads as distinct from the red */

/* Floating cart FAB — built by menu.js buildCard(); straddles the photo's bottom-right
   corner and performs quick-add. Replaces the old CUSTOMIZE / ADD TO CART button row. */
.menu-card-fab {
    position: absolute;
    right: 14px;
    bottom: -24px;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--brand-red);
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    /* White ring: the control straddles the photo's bottom edge, and without a break the red
       disc reads as a blob sitting on the pizza. box-sizing is border-box globally, so the ring
       eats INWARD — the box stays 48px (same 24px dip into the body, same tap target) and the
       red disc becomes 42px. */
    border: 3px solid #fff;
    box-shadow: 0 6px 14px rgba(226, 27, 34, 0.35);
    transition: background 0.15s ease, transform 0.12s ease;
    z-index: 3;
}
.menu-card-fab svg { width: 22px; height: 22px; }
.menu-card-fab:hover { background: var(--brand-red-dark); }
.menu-card-fab:active { transform: scale(0.92); }
/* [hidden] alone wouldn't win against the FAB's display:inline-flex, so make it explicit. */
.menu-card-fab[hidden] { display: none; }

/* −/qty/+ stepper shown IN PLACE of the add FAB once the item is in the cart (qty >= 1).
   Same anchor as the FAB — a pill straddling the photo's bottom-right edge. */
.menu-card-stepper {
    position: absolute;
    right: 14px;
    bottom: -24px;
    height: 48px;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 0 5px;
    border-radius: 999px;
    /* Two-tone red capsule: darker brick under the − , brighter warm red under the + . */
    background: linear-gradient(90deg, #9d3327 0%, #c93d2f 50%, #e9513b 100%);
    color: #fff;
    border: 3px solid #fff;        /* same ring as the FAB it replaces */
    box-shadow: 0 6px 16px rgba(157, 51, 39, 0.42);
    z-index: 3;
}
.menu-card-stepper[hidden] { display: none; }
.menu-card-step {
    width: 30px;
    /* 42px, not the pill's 48: the white ring eats 3px off each end (border-box), so a 44px
       child would push out through the rounded cap. */
    height: 42px;
    border: 0;
    background: transparent;
    color: #fff;
    font-size: 1.35rem;
    line-height: 1;
    font-weight: 700;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.menu-card-step:active { transform: scale(0.88); }
/* White circular "knob" holding the quantity — the visual centrepiece of the pill.
   min-width keeps a perfect circle for 1–2 digits and lets it grow to a pill for 3+. */
.menu-card-step-qty {
    flex: 0 0 auto;
    min-width: 34px;
    height: 34px;
    padding: 0 6px;
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    color: #2a2a2a;
    border-radius: 999px;
    font-size: 0.95rem;
    font-weight: 800;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

/* Mobile: the straddling controls dip into the card body and cover the item name on
   narrow 2-up cards. Sit BOTH the add-FAB and the stepper fully on the photo (positive
   bottom) at the same spot, so neither reaches the name and there's no jump when the FAB
   swaps to the stepper. The stepper is also slimmed so it isn't oversized on a phone. */
@media (max-width: 600px) {
    /* Control sits fully ON the photo here (positive `bottom`, no dip into the body), so the
       name needs no clearance — just enough not to touch the photo.
       Child selector for SPECIFICITY, not style: the base .menu-card-body sets `padding` as a
       shorthand LATER in this file at equal single-class weight, so a bare `.menu-card-body
       { padding-top }` here silently lost and mobile kept paying the desktop's full FAB
       clearance. (0,2,0) beats it regardless of order. */
    .menu-card > .menu-card-body { padding-top: 4px; }
    .menu-card-fab {
        right: 10px;
        bottom: 8px;
        width: 40px;
        height: 40px;
    }
    .menu-card-fab svg { width: 18px; height: 18px; }
    .menu-card-stepper {
        right: 10px;
        bottom: 8px;
        height: 40px;
        padding: 0 4px;
    }
    .menu-card-step {
        width: 26px;
        height: 36px;
        font-size: 1.2rem;
    }
    .menu-card-step-qty {
        min-width: 28px;
        height: 28px;
        font-size: 0.85rem;
    }
}

/* Veg / non-veg badge — top-left of the card image. Default = veg (green
   square + green dot inside a white circle); data-veg="false" swaps in the
   red square + white triangle non-veg icon. Both are inline SVG so they
   scale crisply at any size and require no extra image files. */
.menu-card-image::after { content: none; }   /* retired — single ::before now does the whole badge */

.menu-card-image::before {
    content: none;
    position: absolute;
    top: 8px;
    left: 8px;
    width: 20px;
    height: 20px;
    border-radius: 0;
    background: transparent;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect width='24' height='24' rx='4' fill='%2316a34a'/><circle cx='12' cy='12' r='6' fill='%23fff'/><circle cx='12' cy='12' r='3.5' fill='%2316a34a'/></svg>");
    background-size: contain;
    background-repeat: no-repeat;
    z-index: 1;
}

.menu-card-image[data-veg="false"]::before {
    content: none;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect width='24' height='24' rx='4' fill='%23E21B22'/><path d='M12 6.5 L17.2 16.8 H6.8 Z' fill='%23fff'/></svg>");
}

.menu-card-body {
    /* Name on one row, description below. Cards carry no price, so this is a single column —
       with the old `1fr auto` the name would keep an empty right-hand gutter reserved for a
       child that no longer exists.
       Top padding is NOT decoration: the FAB dips 24px into the body (48px at bottom:-24px),
       so the name has to start below that — 30px clears it and its white ring. Sides and
       bottom are the card's whole text gutter now that the card itself has no padding:
       16px left/right, 18px bottom, even against the photo edge. */
    padding: 30px 16px 18px;
    display: grid;
    grid-template-columns: 1fr;
    grid-template-areas:
        "name"
        "desc";
    align-items: baseline;
    flex: 1;
}

.menu-card-name {
    grid-area: name;
    margin: 0;
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--card-ink);
    /* Full item name ALWAYS shown — never clamped or truncated; wraps to as many lines as it
       needs. The name shares the first row with the price (reference layout); the body's top
       padding drops that whole row below the straddling control so nothing is covered.
       overflow-wrap keeps a single very long word from spilling past a narrow 2-up card. */
    overflow-wrap: anywhere;
}
    
.menu-card-desc {
    grid-area: desc;
    margin: 8px 0 0 0;
    font-size: 0.8125rem;
    /* Own colour, not --card-ink-soft: that warm brown at 13px sat too close to the title and
       the truncated line took a second read. */
    color: #7d7168;
    line-height: 1.55;
    /* FIXED height so every card in a row is the SAME height regardless of description length —
       short descriptions reserve the slot, long ones clamp to an ellipsis. That uniformity is the
       point; it's also why this is the ONLY lever on card height. A one-line description ("10pcs
       wings choose your options") still reserved the full slot, which is where the dead space
       under the short cards came from — and since the row stretches to its tallest card, nothing
       shrinks until this number does.
       Now 3 lines (4.5em). It went 4 -> 2 to claw back card height; the size <select> that used to
       sit below (40px + 8px) is gone, so the third line is paid for and the card is still shorter.
       Dial: 2 lines = 3em, 4 lines = 6em. Keep the clamp and the height in step — the clamp
       truncates the text, the height reserves the box, and they must agree or short cards drift
       out of alignment with tall ones. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    height: 3.1em;              /* 2 lines x 1.55 */
}

/* Variation size picker — "soft warm pill": warm-white fill, soft brown hairline, rounded,
   a faint shadow for depth, and a clean brown chevron, instead of the browser-default select.
   No longer on menu cards (they show one price and defer size to the Customize popup) — the
   only remaining user is the offer builder's item picker (offers-select.js), where choosing
   the eligible variation IS the interaction. Kept for that. */

/* ── Sticky "Proceed to Cart" bar ─────────────────────────────────────────────
   Replaces the navbar cart pill + mini-cart popover. Full-width, pinned to the
   bottom of the viewport; shown only when the cart has items (JS toggles [hidden]).
   z-index 100: above page content and the sticky category/filter bars (30–45), but
   BELOW every modal overlay (deal builder 150, search 180, customize 200, banner 250,
   toppings 300). It used to be 1200, which put this bar on top of all of them — the
   customize popup's footer ("Add to Cart") rendered behind it on mobile. */
.pt-proceed-bar {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom));
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 10px;
    background: #fff;
    border-radius: 16px;
    box-shadow: 0 8px 24px rgba(70, 40, 20, 0.16);
    cursor: pointer;   /* whole bar navigates to cart — see menu.js */
}
.pt-proceed-bar[hidden] { display: none; }

/* The "some items are unavailable" notice, when it lands INSIDE this bar.
   menu.js / store-home.js create it with insertBefore(el, checkoutBtn) — written when the
   button lived in the mini-cart popover, a vertical stack where "before the button" meant
   above it. The Proceed-to-Cart redesign kept the .cart-popup-checkout class on the new bar's
   button so the existing handlers would bind with no JS change, and that quietly re-homed the
   notice into THIS flex row: it became a middle column, crushed between the total and Proceed
   (three words per line, overlapping both).
   Fixed here rather than in the two JS files because the insertion point is correct — the
   notice does belong with the button — and this is the only layout in which it needed to
   behave differently. flex-basis:100% + order:-1 gives it its own full-width line above the
   row; the bar's own gap provides the spacing, so the popover's bottom margin is dropped. */
.pt-proceed-bar { flex-wrap: wrap; }
.pt-proceed-bar > .cart-popup-warn {
    order: -1;
    flex: 1 0 100%;
    margin: 0;
    cursor: default;   /* the rest of the bar navigates to the cart; this is a message, not a control */
}

.pt-proceed-summary {
    display: flex;
    align-items: center;
    gap: 8px;
}
.pt-proceed-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    background: var(--bg-soft, #F4F4F5);
    color: var(--card-ink-soft, #8A6D52);
}
.pt-proceed-icon svg { width: 16px; height: 16px; }
/* Empty-cart trash button — same tile as .pt-proceed-icon (whose slot it took), but interactive. */
.pt-proceed-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: 8px;
    background: var(--bg-soft, #F4F4F5);
    color: var(--card-ink-soft, #8A6D52);
    cursor: pointer;
}
.pt-proceed-clear:hover { background: #fdeced; color: #e11d2a; }
.pt-proceed-clear svg { width: 16px; height: 16px; }
/* Empty-cart confirm chip — floats above the bar's left edge (bar is position:fixed, so it's
   the containing block). Small, in-context, light-dismissed — deliberately not a modal. */
.pt-proceed-confirm {
    position: absolute;
    left: 0;
    bottom: calc(100% + 10px);
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(70, 40, 20, 0.2);
    cursor: default;              /* not part of the bar's click-to-checkout surface */
    animation: pt-proceed-confirm-in .16s ease-out;
}
.pt-proceed-confirm[hidden] { display: none; }
@keyframes pt-proceed-confirm-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
.pt-proceed-confirm-text {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text, #1f1f1f);
    white-space: nowrap;
}
.pt-proceed-confirm-btn {
    height: 30px;
    padding: 0 12px;
    border: 0;
    border-radius: 9px;
    font-size: 0.8rem;
    font-weight: 700;
    background: var(--bg-soft, #F4F4F5);
    color: var(--text, #1f1f1f);
    cursor: pointer;
}
.pt-proceed-confirm-btn--empty { background: #e11d2a; color: #fff; }
.pt-proceed-confirm-btn--empty:hover { background: #c41320; }
.pt-proceed-text {
    display: flex;
    flex-direction: column;
    gap: 1px;
    line-height: 1.1;
}
.pt-proceed-count-label {
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--card-ink-soft, #8A6D52);
}
.pt-proceed-total { font-size: 1rem; font-weight: 800; color: var(--card-ink, #5C2E1E); }
.pt-proceed-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 38px;
    padding: 0 16px;
    border: 0;
    border-radius: 12px;
    background: var(--brand-red, #e11d2a);
    color: #fff;
    font-size: 0.85rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.12s ease;
}
.pt-proceed-btn svg { width: 16px; height: 16px; }
.pt-proceed-btn:hover { background: var(--brand-red-dark, #b3121d); }
.pt-proceed-btn:active { transform: scale(0.98); }
/* This button also carries .cart-popup-checkout so the existing checkout handler binds to
   it with no JS change (see _ProceedToCartBar.cshtml). But that class is the MINI-CART
   POPOVER's full-width button: it sits later in this file at the same single-class
   specificity, so it was winning — width:100% stretched the button across the entire bar,
   and its ≤720px rule added a stray 52px left indent. Scoping to the parent outranks it on
   specificity (not order), so the JS contract stays untouched and the reset can't be
   undone by a later same-specificity rule. Re-asserts the four properties it overrode. */
.pt-proceed-bar .pt-proceed-btn {
    flex: 0 0 auto;
    width: auto;
    height: 38px;
    margin-left: 0;
    border-radius: 12px;
    font-size: 0.85rem;
}
/* The rule that lifted the bottom-right FABs above this bar is gone with the FABs themselves:
   .a11y-fab was replaced by the top accessibility bar, and .pt-app-fab never existed (the
   app-download promo has always been .pt-app-promo). Nothing floats in that corner now. */

.menu-card-size {
    width: 100%;
    height: 40px;
    padding: 0 40px 0 14px;                     /* room for the caret on the right */
    border: 1px solid rgba(92, 46, 22, 0.14);   /* soft warm hairline (derived from --card-ink) */
    border-radius: 12px;
    background-color: #fffdf9;                  /* warm white — sits nicely on the cream card */
    color: var(--card-ink);
    font-size: 0.84rem;
    font-weight: 600;
    margin-bottom: 8px;
    font-family: inherit;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    box-shadow: 0 1px 2px rgba(70, 40, 20, 0.05);
    /* Warm-brown chevron caret — same data-URI pattern as the veg badge above. */
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235C2E1E' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 13px 13px;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}
.menu-card-size:hover { border-color: rgba(92, 46, 22, 0.26); background-color: #fff; }
.menu-card-size:focus { outline: none; border-color: var(--brand-red); box-shadow: 0 0 0 3px rgba(226, 27, 34, 0.12); }

.menu-card-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-top: auto;
}

.menu-card-actions--solo { grid-template-columns: 1fr; }

.menu-btn {
    height: 36px;
    border: 0;
    border-radius: 6px;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    cursor: pointer;
    font-family: inherit;
    color: #fff;
    transition: filter 0.15s ease;
}

.menu-btn:hover { filter: brightness(0.95); }
.menu-btn-customize { background: var(--brand-green); }
.menu-btn-add       { background: var(--brand-red); }

/* ============ Customize modal ============ */
.cust-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.cust-card {
    width: 100%;
    max-width: 460px;
    max-height: 92vh;
    /* dvh partner: on mobile, vh is the LARGE viewport (toolbar hidden) while this fixed
       overlay is the visible one, so a vh-capped card can be taller than the screen and
       overflow where nothing scrolls. Same fallback pair the full-screen .cust-card block
       already documents: vh first, dvh last so modern browsers track the visible viewport. */
    max-height: 92dvh;
    background: #fff;
    border-radius: 14px;
    overflow: hidden;                          /* outer card no longer scrolls */
    box-shadow: 0 30px 60px rgba(0,0,0,0.25);
    position: relative;
    display: flex;
    flex-direction: column;                    /* hero + body + footer column */
}

/* WORKAROUND for a Chrome/Blink paint-invalidation defect — this is NOT fixing an app bug.
   Symptom: after scrolling .cust-body up and down repeatedly, a stale "ghost" copy of the
   Select Size row keeps painting over .cust-fixed-head, and stays until the popup is
   reopened. Verified on Live that the DOM is correct while the ghost is on screen (4 size
   cards, zero geometric overlap) — the layout is right and the pixels are stale.
   Ruled out by probing the broken popup: border-radius:0, overflow:visible on the card,
   contain:paint on the body, forced reflow, and disabling GPU acceleration all changed
   nothing; only promoting .cust-card to its own compositing layer (translateZ(0)) cleared
   it, every time. will-change:transform is the declarative form of that promotion, applied
   up-front so the layer never goes stale in the first place.
   SCOPED to ≥426px on purpose: below that, .cust-card is itself the scroll region and
   .cust-close is position:fixed INSIDE it (see the ≤1080px block). Promoting the card would
   make it the containing block for that fixed child, so the close button would scroll away
   with the content. Phones keep the un-promoted card. */
@media (min-width: 426px) {
    .cust-card { will-change: transform; }
}

.cust-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 0;
    background: rgba(255,255,255,0.92);
    color: var(--brand-red);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.cust-close svg { width: 16px; height: 16px; }

.cust-hero {
    height: 260px;
    flex-shrink: 0;
    background-image: linear-gradient(135deg, #fde68a, #f59e0b);
    position: relative;
}

.cust-hero-image {
    position: absolute;
    inset: 0;
    /* Default fallback — JS overrides this with the actual item image via
       openCustomize() so the modal reflects whichever item the user picked. */
    background-image: url('/images/pizza-hero.jpg');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    background-color: #fef3c7;
}

.cust-hero-tag {
    position: absolute;
    left: 14px;
    bottom: 14px;
    padding: 6px 10px;
    background: rgba(0,0,0,0.65);
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 600;
    border-radius: 6px;
    display: none;
}

/* Sub-header: item name + description. Sits between the hero and .cust-body, and is
   PINNED (position:sticky) to the top of the scrolling card so the item name stays visible
   while the modifier groups scroll past. The hero image is a separate sibling ABOVE this and
   is not sticky, so it scrolls away — only this name/description header pins. The card is the
   scroll region at every width, so top:0 sticks to the card; z-index sits under .cust-close
   (6 / 99999) and above the scrolling body. Exception: the 721–1080px two-column tier keeps
   its floated hero-left / head-right row and opts back out (position:static there), because a
   pinned full-width name bar cannot share a row with the image. */
.cust-fixed-head {
    padding: 16px 18px 12px;
    background: #fff;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
    position: sticky;
    top: 0;
    z-index: 4;
}

.cust-fixed-head .cust-title { margin: 0 0 6px 0; }
.cust-fixed-head .cust-desc  { margin: 0; }

.cust-body {
    padding: 14px 18px 8px;
    overflow-y: auto;
    flex: 1;
    min-height: 0;
    scrollbar-width: thin;                     /* Firefox */
    scrollbar-color: #d4d4d8 transparent;
    scroll-behavior: smooth;                   /* for validation-driven scrollTo */
}

/* Webkit thin scrollbar */
.cust-body::-webkit-scrollbar { width: 4px; }
.cust-body::-webkit-scrollbar-track { background: transparent; }
.cust-body::-webkit-scrollbar-thumb { background: #d4d4d8; border-radius: 2px; }
.cust-body::-webkit-scrollbar-thumb:hover { background: #a1a1aa; }

/* ── Desktop (>1080px): scroll EVERYTHING together ────────────────────────────
   Same mechanism the ≤425px phone tier already uses: the CARD becomes the single
   scroll region (display:block so the hero and sub-header stack at natural height
   instead of being pinned as flex-shrink:0 flex items), the footer sticks to the
   bottom, and the close button sticks to the top-right.
   Deliberately NOT done by wrapping the three blocks in a scroll div: 721–1080px
   lays .cust-hero / .cust-fixed-head / .cust-body out as named GRID AREAS of
   .cust-card, and grid-area only works on direct children — a wrapper silently
   collapses that tier's two-column header.
   The close button is sticky+float, not absolute: an absolutely-positioned child of
   a scroll container scrolls away with the content, and `fixed` would anchor to the
   card anyway (the will-change:transform above makes it the containing block).
   float keeps it out of the block flow so the hero still starts at the very top. */
@media (min-width: 1081px) {
    .cust-card {
        display: block;
        overflow-y: auto;
        scrollbar-width: thin;
        scrollbar-color: #d4d4d8 transparent;
    }
    .cust-card::-webkit-scrollbar { width: 4px; }
    .cust-card::-webkit-scrollbar-track { background: transparent; }
    .cust-card::-webkit-scrollbar-thumb { background: #d4d4d8; border-radius: 2px; }
    .cust-card::-webkit-scrollbar-thumb:hover { background: #a1a1aa; }

    /* The card scrolls now — the body must not add a nested scrollbar of its own. */
    .cust-body { overflow-y: visible; flex: none; }

    .cust-close {
        position: sticky;
        top: 12px;
        right: auto; /* `right` does nothing on a sticky float */
        float: right;
        margin-right: 12px;
        z-index: 6;
        box-shadow: 0 0 3px 0px var(--brand-red-dark);
    }

    .cust-footer {
        position: sticky;
        bottom: 0;
        z-index: 5;
        background: #fff;
    }
}

/* Validation: pulse a group when required option not selected */
.cust-group.is-invalid h4 { color: var(--brand-red); }
.cust-group.is-invalid .cust-options {
    border-color: var(--brand-red);
    box-shadow: 0 0 0 3px rgba(226, 27, 34, 0.12);
}

.cust-title {
    margin: 0 0 6px 0;
    font-size: 1.125rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Veg / non-veg badge next to the customize-modal item title.
   Inherits the same inline-SVG icon set as the card badge. */
.cust-veg-mark {
    display: none;
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect width='24' height='24' rx='4' fill='%2316a34a'/><circle cx='12' cy='12' r='6' fill='%23fff'/><circle cx='12' cy='12' r='3.5' fill='%2316a34a'/></svg>");
    background-size: contain;
    background-repeat: no-repeat;
}

.cust-veg-mark.is-nonveg {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect width='24' height='24' rx='4' fill='%23E21B22'/><path d='M12 6.5 L17.2 16.8 H6.8 Z' fill='%23fff'/></svg>");
}

.cust-veg-mark::after { content: none; }

.cust-desc {
    margin: 0 0 14px 0;
    font-size: 0.8125rem;
    color: var(--muted);
    line-height: 1.5;
}

/* 2-line clamp for the item description — applied on every viewport so the
   description in the customize popover never exceeds two lines unless the
   user explicitly expands it. customize.js attaches .cust-desc-clamped on
   every render and only injects the toggle when the text actually overflows
   (scrollHeight > clientHeight + 2). */
.cust-desc-clamped {
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.cust-desc-toggle {
    display: inline-block;
    background: none; border: 0; padding: 2px 0 0; margin: 0;
    font-size: 0.75rem; font-weight: 600;
    color: var(--brand-red, #E21B22);
    cursor: pointer; font-family: inherit;
}

/* Positioning context for the sub-modifier popover — mounted on .cust-group
   (not .cust-option) so it can extend past the .cust-options overflow:hidden
   clipper without being cut off when neighbouring groups sit below. */
.cust-group { margin-bottom: 18px; position: relative; }
.cust-group h4 {
    margin: 0 0 4px 0;
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--brand-red);
}

.cust-group p.cust-hint {
    margin: 0 0 8px 0;
    font-size: 0.75rem;
    color: var(--muted);
}

/* Required pill on the group title (customize.js modifierOptionGroup). Three states:
   red-tinted "Required" → green "✓ Required" once satisfied → solid red when the
   add-to-cart guard flags the group (.is-invalid). */
.cust-req-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    background: #fdeced;
    color: var(--brand-red);
    vertical-align: 1px;
}
.cust-req-badge.is-done { background: #e8f7ee; color: #15803d; }
.cust-group.is-invalid .cust-req-badge { background: var(--brand-red); color: #fff; }
.cust-group.is-invalid p.cust-hint { color: var(--brand-red); font-weight: 600; }

/* Dietary pill row */
.cust-diet {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
    margin-bottom: 14px;
}

.cust-diet-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    justify-content: center;
    height: 38px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: #fff;
    font-size: 0.75rem;
    font-weight: 600;
}

.cust-diet-btn.is-active {
    border-color: var(--brand-red);
    background: var(--brand-red);
    color: #fff;
}

/* Size selector */
.cust-sizes {
    display: grid;
    /* auto-fit + minmax keeps 4 cards across on desktop/tablet/most phones, but
       lets them WRAP onto a new row on ultra-narrow screens instead of squishing
       or overflowing — so the size cards can never spill over / overlap the
       "Choose Your Crust" section below. The min track (64px) is small enough
       that a 320px full-screen card still fits all four on one row. */
    grid-template-columns: repeat(auto-fit, minmax(64px, 1fr));
    gap: 6px;
    align-items: stretch;                  /* equal-height cards per row */
    align-content: start;                  /* rows pack from the top — no stretch gaps */
}

.cust-size {
    /* Column flex keeps label · price · serves stacked and vertically centred at
       a stable height regardless of size label length (prevents the content from
       bleeding outside the card box). */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 0;                          /* allow the grid track to shrink — no overflow */
    overflow-wrap: anywhere;               /* long labels wrap instead of forcing width */
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 10px 6px;
    text-align: center;
    background: #fff;
    font-family: inherit;
    font-size: 0.75rem;
    color: var(--text);
    font-weight: 500;
    line-height: 1.3;
}

.cust-size strong { display: block; font-size: 1rem; font-weight: 700; }

.cust-size.is-active {
    border-color: var(--brand-red);
    background: var(--brand-red);
    color: #fff;
}

.cust-size.is-active strong { color: #fff; }

.cust-size span { font-size: 0.625rem; color: var(--muted); display: block; margin-top: 2px; }
.cust-size.is-active span { color: #fff; opacity: 0.85; }

/* Option list (crust/sauce/cheese) */
.cust-options {
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
}

.cust-option {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
    background: #fff;
    cursor: pointer;
    position: relative;                  /* positioning context for .cust-submenu */
}

.cust-option:last-child { border-bottom: 0; }
.cust-option:hover { background: #fafafa; }

.cust-option.is-active { background: var(--brand-red-soft); }

.cust-option-thumb {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background-image: linear-gradient(135deg, #fde68a, #f59e0b);
    background-size: cover;
    background-position: center;
    flex-shrink: 0;
    overflow: hidden;
    position: relative;
}

.cust-option-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.cust-option-name { flex: 1; font-size: 0.8125rem; font-weight: 500; }
.cust-option-price { font-size: 0.75rem; color: var(--muted); margin-right: 6px; }

.cust-option-radio {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 2px solid var(--brand-red);
    flex-shrink: 0;
    position: relative;
}

.cust-option.is-active .cust-option-radio::after {
    content: '';
    position: absolute;
    inset: 3px;
    border-radius: 50%;
    background: var(--brand-red);
}

/* Spice level row */
.cust-spice {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 6px;
}

.cust-spice-btn {
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px 6px;
    text-align: center;
    background: #fff;
    font-family: inherit;
    font-size: 0.75rem;
    line-height: 1.3;
}

.cust-spice-btn strong { display: block; font-weight: 700; }
.cust-spice-btn span { display: block; font-size: 0.625rem; color: var(--muted); margin-top: 2px; }

.cust-spice-btn.is-active {
    background: var(--brand-red);
    border-color: var(--brand-red);
    color: #fff;
}

.cust-spice-btn.is-active span { color: rgba(255,255,255,0.85); }

/* Customize toppings (full-width green CTA) */
.cust-toppings-btn {
    width: 100%;
    height: 44px;
    border-radius: 8px;
    background: var(--brand-green);
    color: #fff;
    border: 0;
    font-weight: 700;
    font-size: 0.8125rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    margin-top: 4px;
}

.cust-toppings-btn:hover { background: var(--brand-green-dark); }

/* Footer */
.cust-footer {
    padding: 12px 18px 18px;
    border-top: 1px solid var(--border);
    background: #fff;
    flex-shrink: 0;                            /* stays pinned below the scroll area */
}

.cust-footer-name {
    font-size: 0.875rem;
    font-weight: 700;
    margin-bottom: 2px;
}

.cust-footer-added {
    font-size: 0.6875rem;
    color: var(--muted);
    margin-bottom: 10px;
    line-height: 1.45;
}

/* Each segment ("Added: ...", "Toppings: ...", "Remove Toppings: ...") gets
   its OWN line — display:block stacks them vertically so the three labels
   read as a tidy summary column instead of a comma-run paragraph. Segments
   with no selections aren't rendered by customize.js at all, so a 1-modifier
   item just shows the single "Added:" line. */
.cust-footer-added .cust-footer-seg {
    display: block;
}

/* Per-segment 1-line clamp — used by Toppings: and Remove Toppings:.
   customize.js adds this class on render; the JS measurement leaves it on
   (segment fits in one line) or strips it via a per-segment Show more toggle
   (segment wraps). The .cust-footer-seg-clamped class wins over the base
   display:block by using -webkit-box so the line-clamp engages. */
.cust-footer-added .cust-footer-seg.cust-footer-seg-clamped {
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Per-segment 1.5-line clamp — used by the Added: line, which packs more
   tokens (size + crust + sauce + cheese + spice) and benefits from a bit
   more breathing room before the toggle appears. -webkit-line-clamp only
   takes integers, so 1.5 lines is expressed as a max-height: each line is
   line-height(1.45) × font-size, so 1.5 lines == 2.175em. The block display
   lets the value wrap naturally inside the height cap. */
.cust-footer-added .cust-footer-seg.cust-footer-seg-clamped-1_5 {
    display: block;
    max-height: calc(1.45em * 2);
    overflow: hidden;
}

/* Label color — the user-visible "Added:" / "Toppings:" / "Remove Toppings:"
   words sit at full text color + bold, while their values inherit the parent
   muted footer color so the labels read as headings. */
.cust-footer-added .cust-footer-label {
    color: var(--text);
    font-weight: 700;
}

/* Per-segment Show more / Show less toggle — injected by customize.js as a
   sibling AFTER any segment that wraps past one line. There can be up to
   three of these in the footer (one per overflowing segment), each toggling
   only its own preceding segment via the .cust-footer-seg-clamped class. */
.cust-footer-seg-toggle {
    display: inline-block;
    background: none; border: 0; padding: 0 0 4px 0; margin: 0;
    font-size: 0.6875rem; font-weight: 600;
    color: var(--brand-red, #E21B22);
    cursor: pointer; font-family: inherit;
}

/* "Show / Hide Selected Item Details" — mobile-only control that collapses the
   item name + modifier summary above the Add-to-Cart row. Hidden on desktop,
   where the summary always shows inline (see the ≤720px media block). */
.cust-footer-summary-toggle {
    display: none;
    align-items: center;
    gap: 4px;
    background: none; border: 0; margin: 0; padding: 0 0 6px 0;
    font-family: inherit; font-size: 0.75rem; font-weight: 700;
    color: var(--brand-red, #E21B22);
    cursor: pointer;
}
.cust-footer-summary-toggle-chev svg {
    width: 16px; height: 16px; display: block;
    transition: transform 0.15s ease;
}
.cust-footer-summary-toggle[aria-expanded="true"] .cust-footer-summary-toggle-chev svg {
    transform: rotate(180deg);
}

.cust-footer-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.cust-qty {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 4px;
}

.cust-qty button {
    width: 28px;
    height: 28px;
    border: 0;
    border-radius: 5px;
    background: #fff;
    font-size: 1rem;
    font-weight: 700;
    color: var(--brand-red);
    line-height: 1;
}

.cust-qty button:hover { background: var(--brand-red-soft); }
.cust-qty span { min-width: 18px; text-align: center; font-weight: 700; font-size: 0.875rem; }
/* Deal-slot customizer (opened from a banner deal / offer builder): the deal owns the
   quantity, so hide the qty stepper — the Add-to-Cart button then fills the footer row. */
.cust-overlay--no-qty .cust-qty { display: none; }

.cust-add {
    flex: 1;
    height: 44px;
    border-radius: 8px;
    background: var(--brand-red);
    color: #fff;
    border: 0;
    font-weight: 700;
    font-size: 0.875rem;
}

.cust-add:hover { background: var(--brand-red-dark); }

/* Required modifiers not yet satisfied — looks disabled but stays tappable so the
   click guard can highlight + scroll to the first missing group (customize.js). */
.cust-add.is-disabled,
.cust-add.is-disabled:hover {
    background: #d4d4d8;
    color: #fafafa;
    cursor: not-allowed;
}

/* Nested sub-group dropdown chip (e.g. Mozzarella Cheese → Lite/Regular/Extra) */
.cust-subchip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 28px;
    padding: 0 8px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: #f5f5f5;
    font-size: 0.75rem;
    color: var(--text);
    cursor: pointer;
    font-family: inherit;
}

.cust-subchip svg {
    width: 12px;
    height: 12px;
}

.cust-subchip:hover { background: #eaeaea; }

/* Pop-over surface that opens from a sub-chip. Positioned absolutely inside the
   .cust-option row so it scrolls with the row when the modal body scrolls.
   Capped at 240px tall with an internal scroll so it never overflows past the
   modal — combined with the smart flip-up logic in customize.js, the popover
   stays inside the modal body regardless of where the chip sits vertically. */
.cust-submenu {
    position: absolute;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 12px 24px rgba(0,0,0,0.18);
    padding: 6px;
    z-index: 500;
    display: flex;
    flex-direction: column;
    gap: 4px;
    max-height: 240px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: #d4d4d8 transparent;
}

.cust-submenu::-webkit-scrollbar { width: 4px; }
.cust-submenu::-webkit-scrollbar-track { background: transparent; }
.cust-submenu::-webkit-scrollbar-thumb { background: #d4d4d8; border-radius: 2px; }

/* When the popover flips to OPEN UP (because there's no room below), shift the
   drop-shadow direction so it visually still feels like it comes from the chip. */
.cust-submenu--up {
    box-shadow: 0 -12px 24px rgba(0,0,0,0.18);
}

.cust-submenu-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 10px;
    border-radius: 6px;
    border: 1px solid transparent;
    background: #fff;
    font-size: 0.8125rem;
    color: var(--text);
    text-align: left;
    cursor: pointer;
    font-family: inherit;
}

.cust-submenu-item:hover { background: #fafafa; }

.cust-submenu-item.is-active {
    border-color: var(--brand-red, #E21B22);
    color: var(--brand-red, #E21B22);
}

.cust-submenu-radio {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid var(--border);
    flex-shrink: 0;
}

.cust-submenu-item.is-active .cust-submenu-radio {
    border-color: var(--brand-red, #E21B22);
    background: radial-gradient(circle, var(--brand-red, #E21B22) 0 35%, #fff 40% 100%);
}

.cust-submenu-price {
    font-size: 0.75rem;
    color: var(--muted);
}

/* ============ Toppings popup (Add or Remove Toppings) ============ */
.toppings-overlay {
    z-index: 300;                              /* above the customize modal */
}   

.toppings-card {
    width: 100%;
    max-width: 420px;
    max-height: 92vh;
    max-height: 92dvh;
    background: #fff;
    border-radius: 18px;
    overflow: hidden;
    box-shadow: 0 30px 60px rgba(0,0,0,0.25);
    display: flex;
    flex-direction: column;
}

.toppings-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
    background: #fff;
}

.toppings-back {
    width: 28px;
    height: 28px;
    border: 0;
    background: transparent;
    color: var(--text);
    cursor: pointer;
    padding: 2px;
}

.toppings-back svg {
    width: 22px;
    height: 22px;
}

.toppings-title {
    margin: 0;
    font-size: 1rem;
    font-weight: 700;
    color: var(--text);
    flex: 1;
    text-align: center;
    padding-right: 28px;                       /* visually centre after the back button */
}

.toppings-body {
    padding: 14px 16px;
    overflow-y: auto;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* Wrapper around every minQty=0 subgroup shown in the shared topping popup.
   Each block carries its own subgroup heading + Default/Add New sections + cap caption. */
.toppings-block {
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.toppings-block-head {
    margin: 0;
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--text);
}

.toppings-section {
    border-top: 1px solid #f1f1f1;
    padding-top: 8px;
}

.toppings-section:first-of-type { border-top: 0; padding-top: 0; }

.toppings-section-head {
    margin: 0 0 10px 0;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--brand-green, #0a8a3a);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.toppings-list {
    display: flex;
    flex-direction: column;
}

.toppings-row {
    display: grid;
    grid-template-columns: 28px 1fr auto auto;
    gap: 10px;
    align-items: center;
    padding: 8px 0;
    border-bottom: 1px solid #f4f4f4;
}

.toppings-row:last-child { border-bottom: 0; }

.toppings-thumb {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    overflow: hidden;
    background: #fafafa;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #aaa;
    font-size: 0.875rem;
}

.toppings-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.toppings-name {
    font-size: 0.8125rem;
    color: var(--text);
}

.toppings-price {
    font-size: 0.75rem;
    color: var(--muted);
    min-width: 22px;
    text-align: right;
}

.toppings-stepper {
    display: inline-flex;
    align-items: stretch;
    border: 1px solid var(--brand-green, #0a8a3a);
    border-radius: 6px;
    overflow: hidden;
    height: 26px;
}

.toppings-step {
    width: 24px;
    border: 0;
    background: #fff;
    color: var(--brand-green, #0a8a3a);
    font-size: 0.875rem;
    font-weight: 700;
    cursor: pointer;
}

.toppings-qty {
    min-width: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--brand-green, #0a8a3a);
    color: #fff;
    font-size: 0.75rem;
    font-weight: 700;
    padding: 0 6px;
}

.toppings-foot {
    padding: 12px 16px 16px;
    border-top: 1px solid var(--border);
    background: #fff;
}

.toppings-save {
    width: 100%;
    height: 44px;
    background: var(--brand-green, #0a8a3a);
    color: #fff;
    border: 0;
    border-radius: 10px;
    font-weight: 700;
    font-size: 0.875rem;
    cursor: pointer;
}

.toppings-save:hover { background: var(--brand-green-dark, #097030); }

/* Disabled stepper buttons when caps are reached — visually muted, no pointer. */
.toppings-step[disabled] {
    color: #c4c4c4;
    cursor: not-allowed;
    background: #fafafa;
}

/* Per-group cap caption shown under the topping list (e.g. "5/7 selected"). */
.toppings-cap-note {
    margin: 4px 0 0 0;
    font-size: 0.6875rem;
    color: var(--muted);
    text-align: right;
}

/* Inline option row that's blocked because the group has hit its maxQuantity. */
.cust-option.is-disabled {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

/* The full-page .pt-loader (animated logo over every navigation) was removed along with its
   markup in _Layout / _MenuLayout. Page loading is covered by the skeleton flow in skeleton.css. */

/* ============ Shared cart-line chrome (.ptl-*) ============
   Modifier chips and the Edit / ♡ / Remove row, built by pt-cart-line.js and
   used by BOTH the sidebar (.cart-item) and the checkout page (.chk-line). Defined here
   rather than in cart.css because _MenuLayout loads menu.css on every page that has a
   cart — checkout included — so one copy covers both. */
.ptl-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }

/* One chip per modifier VALUE — replaces the old "Added: a, b, c" prose row. */
.ptl-chip {
    padding: 2px 7px;
    border-radius: 999px;
    background: var(--bg-soft);
    color: #4b5563;
    font-size: 0.6875rem;
    line-height: 1.5;
    white-space: nowrap;
}

.ptl-acts { display: flex; align-items: center; gap: 12px; margin-top: 7px; }

.ptl-act {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--muted);
    font: inherit;
    font-size: 0.6875rem;
    font-weight: 500;
    cursor: pointer;
    border-radius: 4px;
}

.ptl-act svg { width: 13px; height: 13px; }
.ptl-act:hover { color: var(--text); }
.ptl-act:focus-visible { outline: 2px solid var(--brand-red); outline-offset: 2px; }
.ptl-act--danger:hover { color: var(--brand-red); }
/* Favourited — the heart fills (pt-cart-line.js swaps the svg fill to match). */
/* .ptl-act.is-on removed with the ♡ Save button — nothing sets is-on on an action any more. */

/* ============ Cart popup ============ */
.cart-popup {
    position: fixed;
    top: calc(var(--header-h) + 8px);
    right: 18px;
    width: 320px;
    max-height: calc(100vh - var(--header-h) - 30px);
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 20px 50px rgba(0,0,0,0.18);
    z-index: 60;
    display: flex;
    flex-direction: column;
}

.cart-popup[hidden] { display: none; }

/* ── Desktop: cart becomes a full-height right-side slide-in panel ──────────
   (mobile keeps the popover styles above). Inner cart UI is unchanged — only
   the container position / size / slide animation differ. */
.cart-scrim {
    display: none;                       /* enabled per-viewport by the media blocks below */
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.45);
    z-index: 9250;
    opacity: 0;
    transition: opacity 0.28s ease;
}
.cart-scrim[hidden] { display: none; }

/* ── Mobile: backdrop over the page CONTENT only — starts under the sticky
   header so the top bar stays fully visible/undimmed (desktop-like dim; the
   page stays readable through it — NOT a full-screen blackout). z-index sits
   above the sticky category bar (40) and filter row (38) but below the cart
   popover (60), so neither the header nor the panel is ever covered. */
@media (max-width: 720px) {
    .cart-scrim {
        display: block;
        top: var(--header-h);
        z-index: 45;
    }
    .cart-scrim.is-open { opacity: 1; }
}

/* Close (✕) button — injected into the panel; hidden by default, shown on the
   desktop drawer (the @media rule below comes later in source so it wins). */
.cart-popup-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.06);
    color: #333;
    cursor: pointer;
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 2;
}
.cart-popup-close:hover { background: rgba(0, 0, 0, 0.12); }
.cart-popup-close svg { width: 16px; height: 16px; }

@media (min-width: 721px) {
    .cart-popup {
        top: 0;
        right: 0;
        bottom: 0;
        left: auto;
        /* 400 → 520: long item names, modifier lines and the bill rows were wrapping.
           max-width keeps it from swallowing a small laptop screen. */
        width: 520px;
        max-width: 92vw;
        height: 100vh;
        height: 100dvh;
        max-height: none;
        border-radius: 0;
        box-shadow: -10px 0 36px rgba(0, 0, 0, 0.20);
        z-index: 9300;
        transform: translateX(100%);
        transition: transform 0.28s ease;
    }
    .cart-popup.is-open { transform: translateX(0); }

    .cart-scrim { display: block; }      /* desktop: dim click-catcher behind the panel */
    .cart-scrim.is-open { opacity: 1; }

    /* Close (✕) — top-right of the panel; keep the head text clear of it. */
    .cart-popup-close { display: inline-flex; }
    .cart-popup-head { padding-right: 50px; }
}

.cart-popup-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
}

.cart-popup-brand {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--brand-red);
    color: #fff;
}
.cart-popup-brand svg { width: 20px; height: 20px; }

.cart-popup-store-name { font-size: 0.875rem; font-weight: 700; }
.cart-popup-store-addr { font-size: 0.6875rem; color: var(--muted); margin-top: 1px; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.cart-popup-items {
    flex: 1;
    overflow-y: auto;
    padding: 8px 0;
}

.cart-popup-empty {
    padding: 30px 16px;
    text-align: center;
    color: var(--muted);
}

.cart-popup-empty p { margin: 0; font-size: 0.875rem; font-weight: 500; }
.cart-popup-empty-sub { font-size: 0.75rem; margin-top: 6px; opacity: 0.8; }

.cart-item {
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
    position: relative;
}

.cart-item:last-child { border-bottom: 0; }

/* Plain item lines only: [thumb] [name+price / chips / actions] [qty stepper].
   Deal cards (.cart-deal) skip this wrapper and keep their own header layout — a
   multi-item deal has no single image or item to edit. */
.cart-item-body { display: flex; align-items: flex-start; gap: 10px; }
.cart-item-main { flex: 1; min-width: 0; }

.cart-item-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
}

.cart-item-name {
    font-size: 0.8125rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Veg / non-veg badge next to each line item in the cart popup. */
.cart-item-veg {
    width: 14px;
    height: 14px;
    display: none;
    flex-shrink: 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect width='24' height='24' rx='4' fill='%2316a34a'/><circle cx='12' cy='12' r='6' fill='%23fff'/><circle cx='12' cy='12' r='3.5' fill='%2316a34a'/></svg>");
    background-size: contain;
    background-repeat: no-repeat;
}

.cart-item-veg.is-nonveg {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect width='24' height='24' rx='4' fill='%23E21B22'/><path d='M12 6.5 L17.2 16.8 H6.8 Z' fill='%23fff'/></svg>");
}

.cart-item-veg::after { content: none; }

.cart-item-qty {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: var(--brand-green);
    border-radius: 6px;
    padding: 2px;
    flex-shrink: 0;
}

.cart-item-qty button {
    width: 22px;
    height: 22px;
    border: 0;
    border-radius: 4px;
    background: var(--brand-green);
    color: #fff;
    font-size: 0.875rem;
    font-weight: 700;
    line-height: 1;
}

.cart-item-qty button:hover { background: var(--brand-green-dark); }
.cart-item-qty span { min-width: 14px; text-align: center; color: #fff; font-size: 0.75rem; font-weight: 700; }

/* Added / Topping / Remove Topping lines — value text dark; leading label darker still. */
.cart-item-meta { font-size: 0.75rem; color: #333; margin: 4px 0 0; }
.cart-item-added { font-size: 0.75rem; color: #333; margin: 2px 0 0; line-height: 1.35; }
.cart-item-label { color: #1a1a1a; font-weight: 600; }
.cart-item-price { font-size: 0.8125rem; font-weight: 700; margin-top: 4px; }
/* Inside the new line layout the price shares the name's row and sits hard right,
   so it drops the top margin the standalone (deal-card) price still needs. */
.cart-item-row .cart-item-price { margin-top: 0; white-space: nowrap; }

/* ── Unavailable cart line (per-outlet DisabledMenuItems) ────────
   Mirrors the cart page's .chk-line.is-unavailable treatment: the line stays visible so the
   customer can see what became unavailable, but shows no price and no quantity stepper —
   just the badge and a single Remove button. */
/* The popover is a WHITE surface (and stays white in high-contrast mode), so these use the
   same dark-red-on-pale-red palette as the cart page. Each carries its own explicit colour,
   which is exactly what a11y.css's container re-pin leaves alone. */
.cart-item.is-unavailable { opacity: .72; }
.cart-item.is-unavailable .cart-item-name { text-decoration: line-through; text-decoration-color: #b00020; }

.cart-item-unavail {
    display: inline-block;
    flex: none;
    font-size: 0.5625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    line-height: 1;
    color: #b00020;
    background: #fff4f4;
    border: 1px solid #f5c6c6;
    border-radius: 4px;
    padding: 3px 5px;
    vertical-align: middle;
    white-space: nowrap;
}

.cart-item-remove-btn {
    flex: none;
    align-self: center;
    border: 1px solid #f5c6c6;
    background: #fff4f4;
    border-radius: 8px;
    padding: 5px 12px;
    font-size: 0.6875rem;
    font-weight: 700;
    color: #b00020;
    cursor: pointer;
    white-space: nowrap;
}
.cart-item-remove-btn:hover { background: #ffe9e9; }

/* "Some items are no longer available" notice above the popover's CHECKOUT button. */
.cart-popup-warn {
    margin: 0 0 8px;
    padding: 8px 10px;
    background: #fff4f4;
    border: 1px solid #f5c6c6;
    border-radius: 8px;
    color: #b00020;
    font-size: 0.75rem;
    line-height: 1.35;
}

.cart-popup-checkout:disabled { background: #c7c7cc; cursor: not-allowed; }

/* ── Deal / offer card in the cart popover (3-card spec) ─────────── */
.cart-deal-name { font-weight: 700; }
.cart-deal-badge {
    display: inline-block;
    font-size: 0.5625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    line-height: 1;
    color: #fff;
    background: var(--brand-green);
    border-radius: 4px;
    padding: 3px 5px;
    vertical-align: middle;
}
.cart-deal-remove {
    border: 0;
    background: none;
    padding: 0;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--brand-red);
    text-decoration: underline;
    cursor: pointer;
}
.cart-deal-remove:hover { color: var(--brand-red-dark, #c8161d); }
.cart-deal-items {
    margin: 6px 0 0;
    padding-left: 10px;
    border-left: 2px solid var(--border);
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.cart-deal-included-label {
    margin: 0;
    font-size: 0.625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--muted);
}
.cart-deal-item .cart-item-name { font-size: 0.78125rem; }
/* Constituent name + price on one row, price right-aligned. */
.cart-deal-item-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
}
.cart-deal-item-val { font-size: 0.78125rem; font-weight: 700; color: var(--text); flex-shrink: 0; }
/* "Show / Hide Included Items" toggle — shares the deal price row (left-aligned). */
.cart-deal-toggle {
    display: inline-block;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--brand-red);
    text-decoration: underline;
    cursor: pointer;
}

/* Deal toggle (left) + price (right) on one vertically-centered row. The price is
   pushed right with margin-left:auto so it stays right-aligned even when the deal has
   no toggle (single-item); the toggle sits alone on the left for a free deal (no price). */
.cart-deal-pricerow {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 6px;
}
.cart-deal-pricerow .cart-item-price { margin-top: 0; margin-left: auto; }

.cart-popup-foot {
    padding: 12px 14px 14px;
    border-top: 1px solid var(--border);
}

.cart-popup-total {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.875rem;
    font-weight: 700;
    margin-bottom: 10px;
}

.cart-popup-checkout {
    width: 100%;
    height: 42px;
    border: 0;
    border-radius: 8px;
    background: var(--brand-red);
    color: #fff;
    font-weight: 700;
    font-size: 0.875rem;
    letter-spacing: 0.05em;
}

.cart-popup-checkout:hover { background: var(--brand-red-dark); }

/* Gated state — shown when the user isn't logged in. Stays clickable (it
   redirects to login) but reads as disabled. */
.cart-popup-checkout.is-disabled {
    background: #c7c7cc;
    cursor: not-allowed;
}
.cart-popup-checkout.is-disabled:hover { background: #c7c7cc; }

/* ── Mobile: the ✕ moves onto the checkout row (thumb zone) ─────────────────
   Mobile had NO close affordance at all — the panel only dismissed on an
   outside tap. Same injected button, repositioned: it stays a child of
   .cart-popup (position:fixed, so the containing block) rather than of the
   footer, which is deliberate — #cartFoot is hidden on an empty cart, and a
   footer child would disappear exactly when the user most wants to close.
   bottom/left/height mirror .cart-popup-foot's padding + the button height so
   the two line up as one row.
   MUST stay below the .cart-popup-checkout block above: same specificity, so
   an earlier position loses `width` to it and the button overflows the panel. */
@media (max-width: 720px) {
    .cart-popup-close {
        display: inline-flex;
        top: auto;
        bottom: 14px;
        left: 14px;
        right: auto;
        width: 42px;
        height: 42px;
        border-radius: 8px;
    }
    .cart-popup-close svg { width: 18px; height: 18px; }
    /* Yield the ✕'s width so the two never overlap. */
    .cart-popup-checkout { width: calc(100% - 52px); margin-left: 52px; }
}

/* ============ Store home (landing) ============ */
.store-home {
    flex: 1;
    /* Edge-to-edge on phones and tablets: 8px sides are shadow clearance only, so cards use the
       full width where width is scarce. Desktop caps and centres this instead — see below. */
    padding: 4px 8px 40px;
    margin: 0 auto;
    width: 100%;
}

/* Desktop: gutters instead of full bleed.
   This REVERSES the earlier "no 1280px cap" decision, deliberately. Uncapped, the content grew with
   the monitor — at 1920px the promo cards were ~620px wide each and the whole page ran from glass
   edge to glass edge with nothing to frame it. margin:0 auto is already set above, so a max-width
   is all it takes to centre.

   1096 = 1048 of content + the 24px padding each side, and 1048 is exactly two banners plus the
   16px gap between them. THAT is where the number comes from: the banner rail sets the page width,
   not the other way round. Banner height is not independently settable (the slide is 50% of the
   rail and 16/9 turns that into height), so this cap is the height control — 1096 yields 516 x 290
   banners. Widen it and the banners grow with it; at the earlier 1440 they were 688 x 387 and
   dominated the fold.

   Everything else is fr-based or auto-fit and simply reflows, so this one number governs the whole
   desktop layout. Kept above 1024px so tablets keep the full width they actually need. */
@media (min-width: 1025px) {
    .store-home {
        max-width: 1096px;
        padding-left: 24px;
        padding-right: 24px;
    }
}

/* Hero banners — horizontally scrollable carousel.
   Desktop / tablet: 2 banners visible per "page"; mobile: 1.
   Auto-scrolls every few seconds via store-home.js; scrollbar is hidden
   but wheel / touch / programmatic scroll all still work. */
.store-banners-wrap {
    position: relative;
    margin-bottom: 22px;
}

/* Rail width is the ONLY height lever (see .store-banner: aspect-ratio ties the two, and
   capping height instead crops the baked-in artwork typography). This 880px cap makes the two
   slides ~432 x 243 instead of the 516 x 290 they'd take at the full 1048px content width.
   The trade-off it buys back is the one the page cap was meant to remove: the rail is again
   narrower than the categories below it. Centred, so it reads as a deliberate inset rather
   than a misalignment. Raise this number to make the banners taller; there is no other knob.
   Under ~880px viewport it never binds, so phones are untouched by it. */

.store-banners {
    display: flex;
    max-width: 880px;
    margin-inline: auto;
    gap: 16px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    padding-bottom: 2px;
    padding-top: 4px;
    /* Hide the scrollbar but keep scrolling */
    scrollbar-width: none;
    -ms-overflow-style: none;
    /* Prevent iOS rubber-banding from breaking the auto-scroll loop */
    -webkit-overflow-scrolling: touch;
}

.store-banners::-webkit-scrollbar { display: none; width: 0; height: 0; }

.store-banner {
    /* Exactly TWO banners per view: 50% of the rail minus half the 16px gap, so two slides plus the
       gap between them consume the rail exactly and no third banner peeks in.

       This is sized off the RAIL, not the viewport, and that only works because .store-home is
       capped at 1440px on desktop. It was briefly a clamp(280px, 50%, 520px) while the page was
       still full-bleed — back then a bare 50% grew with the monitor and the 16/9 ratio turned that
       into height (531px tall at 1920px, 711px at 2560px). The cap solves that at the source, so
       the clamp is gone rather than left stacked on top of it. Height is now a flat ~387px on any
       screen at or above the cap.

       Do NOT cap the height instead: that keeps the box wide and lets object-fit:cover crop the
       artwork top and bottom, and these banners carry baked-in typography, so cropping eats the
       words. If they ever need to be shorter, lower .store-home's max-width — width and height are
       tied together by the aspect ratio, so the rail is the only honest lever.

       store-home.js perPage() derives paging from the measured slide width, so it follows this
       automatically. The ≤720px rule below still wins for one-per-view on phones. */
    flex: 0 0 calc(50% - 8px);
    aspect-ratio: 16 / 9;
    border-radius: 12px;
    overflow: hidden;
    background-color: #fee2e2;
    position: relative;
    scroll-snap-align: start;
    cursor: pointer;
    border: 0;
    padding: 0;
    font: inherit;
    color: inherit;
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}

button.store-banner { background: #fee2e2; }
.store-banner:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.store-banner:focus-visible { outline: 2px solid var(--brand-red); outline-offset: 2px; }

.store-banner img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    pointer-events: none;
}

/* Condition chip — "Available 10:00 AM - 2:00 PM", "Valid on your first order".
   store-home.js fills it from the banner's linked deal and keeps it hidden when the deal has no
   conditions, so an unconditional banner is exactly as it was.
   Deliberately a thin strip pinned to the bottom edge rather than a floating pill: this artwork
   carries baked-in typography (see the note on .store-banner about never cropping it), and the
   bottom edge is the one band that is reliably background rather than words. One line only,
   ellipsised — the full set lives in the popover, which is why the chip shows just the first. */
.store-banner-cond {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 5px 10px;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.72), rgba(0, 0, 0, 0));
    color: #fff;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1.3;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;   /* the whole tile is the button */
}

.store-banner-cond[hidden] { display: none; }

/* Conditions + terms in the banner popover and in the offer builder. Same voice in both, because
   a customer can reach the same deal either way (banner -> builder when the deal is live in the
   builder payload, else the legacy popover). */
.banner-modal-conds[hidden], .offer-deal-conds[hidden], .offer-deal-terms[hidden] { display: none; }

.banner-modal-cond,
.offer-deal-conds li {
    margin: 4px 0 0;
    padding-left: 14px;
    position: relative;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--brand-red);
    list-style: none;
}

.banner-modal-cond::before,
.offer-deal-conds li::before {
    content: "•";
    position: absolute;
    left: 2px;
}

.offer-deal-conds { margin: 6px 0 0; padding: 0; }

.banner-modal-terms,
.offer-deal-terms {
    margin: 8px 0 0;
    font-size: 0.6875rem;
    line-height: 1.4;
    color: var(--card-ink-soft, #8A6D52);
}

.store-banner--placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background-image: linear-gradient(135deg, #ef4444 0%, #b91c1c 100%);
    color: #fff;
    font-weight: 800;
    font-size: 1.75rem;
    letter-spacing: 0.04em;
}

.store-banners-dots {
    display: flex;
    justify-content: center;
    gap: 6px;
    margin-top: 8px;
}

.store-banners-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #d4d4d8;
    border: 0;
    padding: 0;
    cursor: pointer;
    transition: background 0.18s ease, width 0.18s ease;
}

.store-banners-dot.is-active {
    background: var(--brand-red);
    width: 18px;
    border-radius: 999px;
}

.store-section { margin-bottom: 26px; }

.store-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;                     /* two action pills + h2 can't share 375px */
    margin-bottom: 14px;
    gap: 12px;
}

.store-section-head h2 {
    margin: 0 auto 0 0;                  /* right-auto: actions cluster right even with 3 children */
    font-size: 1.125rem;
    font-weight: 800;
    letter-spacing: 0.04em;
}

.store-search-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: var(--brand-red);
    color: #fff;
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 600;
    text-decoration: none;
}

.store-search-btn:hover { background: var(--brand-red-dark); }
.store-search-btn svg   { width: 14px; height: 14px; }

/* Optical nudge for "View All". The row is flex-centred, so the pill is already
   geometrically centred against the h2 — but the heading is all-caps (no descenders), which
   reads as sitting lower than it measures and leaves the pill looking high. The nudge scales
   with the row: largest on phones, where the pill is closest to the heading.
   Desktop is the base; the two overrides below step it up for tablet and phone. */
.store-search-btn { margin-top: 2px; }

@media (max-width: 1024px) {
    .store-search-btn { margin-top: 3px; }
}

@media (max-width: 720px) {
    .store-search-btn { margin-top: 4px; }
}

.store-arrows {
    display: flex;
    gap: 6px;
}

.store-arrow {
    width: 28px;
    height: 28px;
    border: 1px solid var(--border);
    border-radius: 50%;
    background: #fff;
    font-size: 1rem;
    font-weight: 700;
    color: var(--text);
    line-height: 1;
}

.store-arrow:hover { background: var(--bg-soft); }

/* Explore Menu categories — two rows, horizontal scroll, desktop paging arrows. */
.store-cats-wrap { position: relative; }

.store-cats {
    /* TWO rows, filled column-by-column, scrolling sideways. grid-auto-flow: column with
       exactly 2 explicit rows is what caps the height — no JS measures anything, so there is
       no clamp to re-run on resize/late images. minmax(76px, 1fr) does double duty: a short
       category list stretches to fill the row (no dead space), and a long one bottoms out at
       the 76px floor, which is what makes the track overflow and become scrollable.
       NOTE: set grid-auto-columns, never grid-template-columns — an explicit column template
       would fight the column auto-flow and force everything back into one row. */
    display: grid;
    grid-template-rows: repeat(2, auto);
    grid-auto-flow: column;
    grid-auto-columns: minmax(76px, 1fr);
    gap: 6px 4px;
    padding: 2px 2px 4px 2px;
    overflow-x: auto;
    overscroll-behavior-x: contain;   /* a swipe past the end doesn't page the browser back */
    /* Scrollbar hidden, scrolling kept — same treatment as the banner rail above. The
       half-tile peek at the right edge (phone rule below) and the desktop arrows are the
       affordances now. */
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.store-cats::-webkit-scrollbar { display: none; width: 0; height: 0; }

.store-cat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 5px;
    width: 100%;
    text-decoration: none;
    color: var(--text);
    text-align: center;
    border-radius: 12px;
    transition: background 0.15s ease, transform 0.15s ease;
}

.store-cat:hover { background: var(--bg-soft); transform: translateY(-1px); }

.store-cat-thumb {
    /* Fluid: fills the grid cell but never grows past 64px (compact strip), so it can't
       overflow a narrower column. aspect-ratio keeps it a perfect circle at any size. */
    width: 100%;
    max-width: 64px;
    aspect-ratio: 1 / 1;
    border-radius: 50%;
    overflow: hidden;
    background-color: #fef3c7;
    background-image: linear-gradient(135deg, #fde68a, #fcd34d);
    background-size: cover;
    background-position: center;
    box-shadow: var(--shadow-sm);
    display: block;
    position: relative;
    transition: max-width 0.2s ease;
}

.store-cat-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.store-cat-label {
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.2;
    /* Cap at 2 lines so a long name can't add a whole extra row of height. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}

/* ── Explore-menu category slider: desktop prev/next arrows ──────────────────
   Desktop (≥992px) hides the scrollbar and pages the category row ~2 cards per
   click via these circular arrows (injected + wired by store-home.js). Mobile /
   tablet keep native touch-swipe, so the arrows stay hidden there. */
.store-cats-nav {
    display: none;                  /* shown only on desktop (media query below) */
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: #fff;
    border: 1px solid var(--border);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
    align-items: center;
    justify-content: center;
    color: var(--text);
    cursor: pointer;
    padding: 0;
    z-index: 10;
    transition: background 0.15s ease, box-shadow 0.15s ease;
}
.store-cats-nav:hover { background: var(--bg-soft); box-shadow: 0 4px 14px rgba(0, 0, 0, 0.16); }
.store-cats-nav svg { width: 18px; height: 18px; display: block; }
.store-cats-prev { left: -32px; }
.store-cats-next { right: -32px; }

/* The row scrolls again, so the paging arrows are useful again on desktop. store-home.js
   toggles .is-hidden at each edge (and when nothing overflows), so an outlet whose categories
   already fit shows no arrows at all. Mobile/tablet keep native swipe. */
@media (min-width: 992px) {
    .store-cats-nav { display: flex; }
    .store-cats-nav.is-hidden { display: none; }
}

/* Promo blocks: 3 responsive red cards (Deals / Party Order / Trending).
   Columns are 1fr so the block size tracks the display width; the card height
   follows via aspect-ratio, and icon/label scale with clamp(). */
/* ── Promo strip (Deals / Party Order / Trending) ─────────────────────────────
   Horizontal cards: accent disc, title + subtitle, chevron.

   ALWAYS one row of three. An earlier pass used auto-fit so the browser could reflow to 2 then
   1 column, but three equal-weight shortcuts reading as a single row is the point of the strip —
   reflowing produced a 2+1 orphan on tablets and a three-deep stack on phones that pushed the
   menu below the fold. The card CONTENT changes shape at ≤720px instead (see that media query):
   horizontal with a subtitle where there is room, compact icon-over-label where there isn't. */
.store-promo-strip {
    display: grid;
    /* Auto COLUMNS, not a fixed repeat(3): the cards are gated per outlet by
       BusinessDetails.HomePageSections, so the strip can hold 1, 2 or 3 of them. A fixed 3-column
       track left the hidden card's column standing, shrinking the survivors to a third of the row
       with dead space beside them. Identical to the old rule when all three show. */
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: clamp(8px, 1.6vw, 18px);
    margin: 4px 0 26px;
    padding: 0;
    background: transparent;
}

/* Trending promo scroll target — keep the section clear of the sticky header. */
#ptTrending { scroll-margin-top: calc(var(--header-h) + 12px); }

.store-promo {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    background: var(--promo-bg);
    border-radius: 14px;
    color: #111827;
    text-decoration: none;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

/* The only per-card difference: an accent and the tint derived from it. */
.store-promo--deals    { --promo: #e11d2a; --promo-bg: #fdeced; }
.store-promo--party    { --promo: #16a34a; --promo-bg: #e8f7ee; }
.store-promo--trending { --promo: #a855f7; --promo-bg: #f5ebfe; }

.store-promo:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08); }

.store-promo-ico {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: clamp(38px, 4.4vw, 46px);
    height: clamp(38px, 4.4vw, 46px);
    border-radius: 50%;
    background: var(--promo);
    color: #fff;
}
.store-promo-ico svg { width: 55%; height: 55%; }

/* min-width:0 so a long subtitle wraps inside the card instead of forcing the grid wider —
   without it the flex item takes its max-content width and the chevron gets pushed out. */
.store-promo-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.store-promo-title {
    font-weight: 700;
    font-size: clamp(0.9rem, 1.2vw, 1.02rem);
    line-height: 1.2;
}
.store-promo-sub {
    font-size: clamp(0.72rem, 0.95vw, 0.8rem);
    line-height: 1.25;
    color: #6b7280;
}

.store-promo-go {
    flex: 0 0 auto;
    margin-left: auto;
    display: grid;
    place-items: center;
    width: clamp(24px, 2.6vw, 28px);
    height: clamp(24px, 2.6vw, 28px);
    border-radius: 50%;
    background: #fff;
    color: var(--promo);
}
.store-promo-go svg { width: 60%; height: 60%; }

/* Rank badge for Top 10 cards */
.menu-card-image { position: relative; }
.topten-rank {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 2;
    min-width: 24px;
    height: 24px;
    padding: 0 7px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--brand-red);
    color: #fff;
    font-weight: 800;
    font-size: 0.8125rem;
    border-radius: 999px;
    box-shadow: 0 2px 6px rgba(0,0,0,0.22);
}

.store-carousel {
    display: flex;
    gap: 18px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding-bottom: 6px;
    scrollbar-width: none;
}

.store-carousel .menu-card {
    flex: 0 0 290px;
    scroll-snap-align: start;
}

.store-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px;
    align-items: start;
}
/* Equal-width columns → every card is the same width no matter how many are in
   the row. A short last row (e.g. 2 items) keeps the SAME width as the full
   rows above instead of stretching to fill the leftover space. */
    .store-grid > .menu-card {
        min-width: 0; /* allow the grid item to shrink; avoids text overflow */
        max-width: none;
    }

/* =====================================================================
   End-of-page "View Full Menu" button (Stores/Menu.cshtml)
   The last thing on the store home page, filling what used to be dead
   space between Best Sellers and the footer. Just the button — no card,
   no icon badge, no heading: the page has already said everything it
   needs to by this point, and one control reads faster than a panel.
   ===================================================================== */
.store-fullmenu {
    display: flex;
    justify-content: center;
    margin: 10px 0 30px;
}

.store-fullmenu-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 13px 30px;
    border-radius: 999px;
    background: var(--brand-red);
    color: #fff;
    font-size: 0.95rem;
    font-weight: 800;
    white-space: nowrap;
    text-decoration: none;
    transition: background 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.store-fullmenu-btn svg { width: 16px; height: 16px; }
.store-fullmenu-btn:hover {
    background: var(--brand-red-dark);
    transform: translateY(-1px);
    box-shadow: 0 8px 20px rgba(226, 27, 34, 0.28);
}
.store-fullmenu-btn:focus-visible { outline: 2px solid var(--brand-red); outline-offset: 3px; }

/* Phones: full-width tap target rather than a small pill adrift in the middle. */
@media (max-width: 620px) {
    .store-fullmenu     { margin: 6px 0 26px; }
    .store-fullmenu-btn { width: 100%; justify-content: center; }
}

/* The transform/lift is decoration; honour a reduced-motion preference. */
@media (prefers-reduced-motion: reduce) {
    .store-fullmenu-btn { transition: background 0.15s ease; }
    .store-fullmenu-btn:hover { transform: none; }
}

.store-foot {
    border-top: 1px solid var(--border);
    padding: 20px 28px;
    text-align: center;
}

.store-foot img { height: 30px; margin-bottom: 12px; }

.store-foot-row {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 0.75rem;
    color: var(--muted);
    max-width: 1280px;
    margin: 0 auto;
}

.store-foot-links { display: inline-flex; gap: 14px; }
.store-foot-links a { color: var(--muted); text-decoration: none; }
.store-foot-links a:hover { color: var(--text); }

/* Image inside menu-card */
.menu-card-image img,
.menu-card-image canvas {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    border-radius: 12px 12px 0 0;   /* match the flush photo frame above */
}

/* ── Deal tiles: show the whole banner ────────────────────────────────────────────
   Deal artwork is PROMOTIONAL - the price and the offer name are baked into the pixels
   ("$37.99", "FAMILY DEAL"). Cropping it is not a cosmetic trim, it deletes the thing the
   image exists to say. Item photos are just food and crop harmlessly, which is why this is
   scoped to .menu-card--deal and the rest of the grid is untouched.
   MEASURED, not guessed: the tile box is 174x143 (ratio 1.21) while the deal art is a MIX of
   1920x1080 / 1280x720 (1.78) and 896x672 (1.33). At 1.21 the 16:9 banners lost ~32% of their
   width - which is precisely the set that was showing a sliced-off price.
   Two changes, and both are needed:
     aspect-ratio 16/9 - retargets the box at the dominant artwork ratio, so those banners now
       fit exactly rather than being squeezed into a near-square. Overrides the fixed heights
       (180/160/143/140px) at every breakpoint on specificity alone, so no media queries here.
     object-fit: contain - the 4:3 banners still do not match a 16:9 box, and for THIS content
       a band is better than a crop. The band is the card's own cream, so it reads as padding.
   Result: 16:9 deals fill edge to edge, 4:3 deals sit centred with cream at the sides, every
   tile is the same height, and no price is ever cut. */
.menu-card--deal .menu-card-image {
    height: auto;
    aspect-ratio: 16 / 9;
    background-color: var(--card-bg);
}
.menu-card--deal .menu-card-image img,
.menu-card--deal .menu-card-image canvas {
    object-fit: contain;
    background: var(--card-bg);
}

/* ============ Offers page ============ */
/* Grey ground with white cards floating on it — the app's screen. The grey lives on the PAGE
   root, not on .offers-main: the reference runs it edge to edge, and a centered 860px grey band
   read as a stripe with white margins on desktop. */
.offers-page { background: #F2F2F2; }

/* Centered white strip under the site header — the web stand-in for the app's own top bar
   (which is a nav title, not page copy). */
.offers-titlebar {
    background: #fff;
    border-bottom: 1px solid var(--border);
    padding: 14px 16px;
}
.offers-titlebar h1 {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 800;
    text-align: center;
}

/* Card column only. Narrower than the 1200px it was: the cards are one-per-row, and stretched
   that wide a deal banner turns into a letterbox strip with white space beside it. */
.offers-main {
    flex: 1;
    padding: 20px 16px 28px;
    max-width: 860px;
    margin: 0 auto;
    width: 100%;
}

/* Vouchers/item-offers and deals are still two sections (offers.js collapses each one when all
   its cards fall out of their date window), but they read as ONE flat list like the app's — no
   headings, and the same gap between sections as between cards. */
.offers-section { margin-bottom: 16px; }

/* One card per row, matching the app's Deals & Offers screen. It was an auto-fill grid of
   narrow portrait cards; the deal artwork is a wide banner with its own baked-in typography,
   which a 260px column cropped into illegibility. */
.offers-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
}

/* ── Deal cards in the menu grid ──────────────────────────────────────────────
   The "Deals" rail entry renders .menu-card like every other section, so it inherits the whole
   card design. Only the deal-specific bits are added: the price line (menu items deliberately
   show no price — the number lives in Customize — but a deal's price IS the offer), and the
   unlock line offers.js writes when the deal is outside its hours or otherwise gated. */

/* .menu-card-body is a GRID with exactly two named areas ("name" / "desc"). The price and
   unlock lines have no area, so they were auto-placed into implicit rows — which is what threw
   the deal card's layout out. Flex column just stacks children in DOM order (price, name, desc,
   unlock), which is all this card needs, and leaves the item cards' grid untouched. */
.menu-card--deal .menu-card-body {
    display: flex;
    flex-direction: column;
}
/* The 3-line fixed height exists so item cards in a row stay level. A deal's blurb is short and
   often absent, so reserving three empty lines is just dead space — size to content, clamp at
   two. Row heights still level up via `align-self: stretch` on the grid children. */
.menu-card--deal .menu-card-desc {
    height: auto;
    -webkit-line-clamp: 2;
}
.menu-card--deal .menu-card-desc:empty { display: none; }

.menu-card-price {
    margin: 0 0 2px;
    font-size: 0.95rem;
    font-weight: 800;
    color: var(--brand-red, #e11d2a);
}

/* "Was" price on a deal card — what its contents cost bought separately. Muted and lighter so
   the deal price stays the number that reads first; the <s> element supplies the strike itself,
   so there is no text-decoration here to drift out of step with the markup. */
.menu-card-price-was {
    margin-right: 4px;
    font-weight: 600;
    font-size: 0.85em;
    color: #9ca3af;
}
.menu-card-unlock {
    margin: 6px 0 0;
    font-size: 0.72rem;
    line-height: 1.3;
    color: var(--muted, #8A6D52);
    white-space: pre-line;   /* offers.js joins "Available today" + the window with \n */
}
.menu-card-unlock.is-locked { color: var(--brand-red, #e11d2a); }
/* Gated deal: offers.js only ever touches the CTA and the unlock line, so the card greys itself
   off the CTA's state rather than needing a second class pushed onto it. menu.js's own click
   handler bails on the same flag, so the greyed card isn't merely cosmetic. */
.menu-card--deal:has(.menu-card-fab.is-locked) { opacity: 0.55; }
/* .menu-card sets display:flex, which beats the UA's [hidden]{display:none} — without this a
   deal outside its DATE window would stay visible after offers.js hid it. */
.menu-card[hidden] { display: none; }
/* …and once every deal is date-hidden, drop the section so a bare "Deals" heading isn't left
   sitting above the menu.
   ponytail: the rail entry stays (it lives in a different subtree, so no single selector
   reaches it) — clicking it just scrolls nowhere. Hide it from menu.js if that shows up. */
.menu-cat-section[data-cat="deals-virtual"]:not(:has(.menu-card:not([hidden]))) { display: none; }

/* Banner left, copy right — the app's card. No border: the shadow and the white fill separate
   it from the page, and a hairline around a full-bleed image reads as a seam. */
.offer-card {
    border: 0;
    border-radius: 16px;
    overflow: hidden;
    background: #fff;
    display: grid;
    grid-template-columns: minmax(0, 54fr) minmax(0, 46fr);
    box-shadow: 0 2px 10px rgba(70, 40, 20, 0.10);
    transition: box-shadow 0.18s ease, transform 0.18s ease;
}

.offer-card:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.offer-card--item, .offer-card--deal { cursor: pointer; }

/* 16:9 banner, held at 16:9 — the merchant art is a pre-baked banner drawn at 16:9 (logo, deal
   name, price all inside that frame), so a 16:9 box + cover shows the WHOLE thing with no crop
   and no letterbox. The trap was `height: 100%`: on phone widths the copy column is taller than
   the banner, and stretching the image to match turned the box PORTRAIT — cover then cropped the
   sides off ("WINGS", "$29.99"). align-self:center instead keeps the banner at its own 16:9
   height and lets the (rare) extra height sit as thin blurhash margin above/below, never a crop. */
.offer-card-image {
    position: relative;
    align-self: center;
    aspect-ratio: 16 / 9;
    width: 100%;
    background-color: #fef3c7;
    background-size: cover;
    background-position: center;
}

.offer-card-image img { width: 100%; height: 100%; object-fit: cover; display: block; }

.offer-card-body {
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.offer-card-body h3 {
    margin: 0;
    font-size: 1.375rem;
    font-weight: 800;
    line-height: 1.22;
    color: #111827;
}
/* Clamp to 2 lines like the app — an unbounded description is what pushes the copy column past
   the banner's height and re-opens the blurhash margins. */
.offer-card-body p {
    margin: 0; font-size: 1rem; color: #6b7280; line-height: 1.4;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* "More details" + the CTA on one row at the foot of the copy column. margin-top:auto pins it
   to the bottom so the CTAs line up across cards of different copy lengths; margin-left:auto on
   the button keeps it right-aligned when there are no terms to link. */
.offer-card-foot {
    margin-top: auto;
    padding-top: 6px;
    display: flex;
    align-items: center;
    gap: 12px;
}
.offer-card-foot .offer-card-btn { margin-left: auto; }

/* Solid red, sentence case, min-width so it stays a wide pill even for a short label — the
   app's "Get Now". Was a full-width uppercase bar, which the two-column card has no room for. */
.offer-card-btn {
    flex: 0 0 auto;
    height: 48px;
    min-width: 150px;
    padding: 0 22px;
    border: 0;
    border-radius: 10px;
    background: var(--brand-red);
    color: #fff;
    font-weight: 700;
    font-size: 1.0625rem;
    cursor: pointer;
}

.offer-card-btn:hover { background: var(--brand-red-dark); }

/* CTA rendered as an anchor (item/deal "Select items") needs flex centering. */
a.offer-card-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
}

/* The .offer-card-badge rules went with the badge markup — the redesigned card shows the
   artwork unobstructed, and the deal's own banner already names what it is. */

/* The headline-amount line (.offer-amount), the min-order / one-time / item-count chips
   (.offer-meta) and the .offer-card-price / .offer-card-type rules went with their markup —
   the card is title + description + More details + CTA, as in the app. The min-order figure
   still reaches the customer via .offer-unlock, which offers.js fills when it actually bites. */

/* "More details" — a red underlined link that opens the dialog below. A plain <button> rather
   than an <a>: it goes nowhere, and the card around it is itself clickable. */
.offer-terms-btn {
    border: 0;
    background: transparent;
    padding: 0;
    font: inherit;
    font-size: 1rem;
    font-weight: 600;
    color: var(--brand-red);
    text-decoration: underline;
    cursor: pointer;
}
.offer-terms-btn:hover { color: var(--brand-red-dark); }

/* Phones keep banner-left / copy-right (the app's layout). Here the copy column wraps taller than
   the banner's own 16:9 height, so the banner is STRETCHED to the card height and cover crops its
   left/right edges to fill — a deliberate trade (chosen over stacking): the card matches the app,
   at the cost of trimming the banner's side margins. The 2-line description clamp above keeps the
   card short, which keeps that crop shallow. `aspect-ratio: auto` is what lets height:100% win over
   the base 16:9 box; align-self:stretch pins the box to the full card height.
   This block must sit AFTER every base .offer-card-* rule above: it overrides them at the SAME
   specificity, so only source order makes it win — placed earlier it silently loses. */
@media (max-width: 700px) {
    .offers-titlebar h1 { font-size: 1.25rem; }
    /* 50/50 on phones, not the desktop 54/46. The copy column has to seat "More details" and
       "Get Now" on ONE row: measured at 375px they need 144px, and a 46% column offers 136px
       inner - an 8px overflow, which is what pushed the link onto a second line. 50% gives 153px,
       so the row fits with headroom rather than exactly. The image only loses 14px of width and
       is still the larger visual element. */
    .offer-card { border-radius: 12px; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }

    /* The banner fills its half EXACTLY - no crop, no letterbox - and that is a consequence of
       the body being compact, not of anything set on the image.
       The artwork is 16:9. The image column is ~54% of a ~343px card, so ~185px wide, which wants
       to be ~104px tall. `cover` on a box taller than that scales the art up and slices its sides
       off; `contain` on the same box leaves bands. Both are symptoms of ONE cause: a body taller
       than 16:9. Previously the title was unclamped, so a long offer name ran to five lines, the
       card hit 202px, and over half the artwork - the price, the offer name - was cropped away.
       Everything below exists to keep the body near that 104px so `cover` has nothing to crop. */
    .offer-card-image { align-self: stretch; aspect-ratio: auto; height: 100%; }
    .offer-card-image img { object-fit: cover; }

    .offer-card-body { padding: 9px 11px; gap: 3px; justify-content: center; }
    /* Clamped, where it used to be unbounded - the single change that made the crop possible. */
    .offer-card-body h3 {
        font-size: 0.8125rem;
        line-height: 1.24;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
    .offer-card-body p { font-size: 0.6875rem; line-height: 1.32; }
    /* white-space:nowrap, not just flex-wrap on the row: nowrap on the FLEX CONTAINER stops the
       two children stacking, but does nothing about the text inside "More details" breaking
       across two lines, which is what was actually happening. Both are needed. */
    .offer-terms-btn { font-size: 0.6875rem; white-space: nowrap; flex: 0 0 auto; }
    /* One row, never wrapping: a wrapped foot adds a whole line and is what tips the card back
       over 16:9. margin-top:0 because the body is centred rather than pinned to the bottom. */
    .offer-card-foot { flex-wrap: nowrap; gap: 8px; margin-top: 4px; align-items: center; }
    /* flex:0 0 auto so the pill keeps its shape instead of being squeezed by the link beside it. */
    .offer-card-btn {
        height: 30px; min-width: 0; padding: 0 11px;
        font-size: 0.71875rem; border-radius: 6px;
        white-space: nowrap; flex: 0 0 auto;
    }
}
}

/* ── "More details" dialog ─────────────────────────────────────────────────────
   Native <dialog>, so the backdrop, Escape, focus containment and page inertness are the
   element's job, not ours. Only the box is styled. */
.offer-details {
    width: min(520px, calc(100vw - 32px));
    padding: 22px 24px 26px;
    border: 0;
    border-radius: 16px;
    background: #fff;
    color: #111827;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.28);
}
.offer-details::backdrop { background: rgba(17, 24, 39, 0.45); }
.offer-details h2 { margin: 0 0 8px; font-size: 1.25rem; font-weight: 800; padding-right: 28px; }
.offer-details p  { margin: 0; font-size: 1rem; line-height: 1.5; color: #4b5563; }
.offer-details h3 {
    margin: 20px 0 6px;
    font-size: 0.9375rem;
    font-weight: 700;
    color: #111827;
}
.offer-details h3 + p { font-size: 0.875rem; color: var(--muted); white-space: pre-line; }
.offer-details [hidden] { display: none; }

/* Floated out of the flow so the title starts at the top of the box, not below the button. */
.offer-details-close {
    float: right;
    width: 30px;
    height: 30px;
    margin: -6px -6px 0 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    font-size: 22px;
    line-height: 1;
    color: #6b7280;
    cursor: pointer;
}
.offer-details-close:hover { background: var(--bg-soft); color: #111827; }

/* Inline apply feedback + applied state. */
.offer-apply-msg { margin: 0 !important; font-size: 0.75rem !important; }
.offer-apply-msg.is-ok { color: var(--brand-green) !important; }
.offer-apply-msg.is-err { color: var(--brand-red) !important; }

.offer-apply-btn.is-applied { background: var(--brand-green); }
.offer-apply-btn.is-applied:hover { background: var(--brand-green); }
.offer-apply-btn:disabled { cursor: not-allowed; }
/* Applied buttons are hard-disabled (no re-apply clicks) but read as a state badge,
   not a blocked action — neutral cursor instead of not-allowed. */
.offer-apply-btn.is-applied:disabled { cursor: default; }

/* A card locked ONLY by the cart minimum is tappable — it routes to the menu so the customer can
   add the items its own message is asking for (offers.js). Two parts make that work:
     • the card advertises itself as a target (cursor + hover lift), and
     • the greyed CTA stops swallowing the tap. A disabled <button> fires no click event and
       blocks it from reaching anything underneath, so the most natural place to press was the
       one dead spot on the card. pointer-events:none lets it through to the card handler.
   Scoped to [data-lock-reason="minimum"]: every other lock (time window, spent one-time offer,
   combination clash) is one the menu page cannot fix, so those cards stay inert. */
.offer-card[data-lock-reason="minimum"] { cursor: pointer; }

.offer-card[data-lock-reason="minimum"] .offer-card-btn:disabled,
.offer-card[data-lock-reason="minimum"] .offer-apply-btn:disabled {
    pointer-events: none;
}

/* Live unlock hint (red italic) — mirrors the app's "Add items worth $X to unlock". */
.offer-unlock {
    margin: 0 !important;
    font-size: 0.71875rem !important;
    font-weight: 600;
    font-style: italic;
    color: var(--brand-red) !important;
}

/* Locked CTA = solid grey + not-allowed (matches the app's disabled Get Now / Apply Now). */
.offer-card-btn.is-locked,
a.offer-card-btn.is-locked {
    background: #c4c8cf !important;
    color: #fff !important;
    opacity: 1 !important;
    cursor: not-allowed;
}
.offer-card-btn.is-locked:hover,
a.offer-card-btn.is-locked:hover { background: #c4c8cf !important; }

/* Applied item-offer CTA ("✓ Applied") — same green as the applied voucher button.
   Declared AFTER the .is-locked rules: an applied card carries BOTH classes (is-locked
   keeps the click-guards inert), and this later rule wins the background. */
.offer-card-btn.is-applied,
a.offer-card-btn.is-applied {
    background: var(--brand-green) !important;
    color: #fff !important;
    cursor: default;
}
.offer-card-btn.is-applied:hover,
a.offer-card-btn.is-applied:hover { background: var(--brand-green) !important; }

/* Applied-voucher banner at the top of the offers page. */
.offer-voucher-banner {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    margin-bottom: 20px;
    border: 1px solid var(--brand-green);
    border-radius: 10px;
    background: rgba(22, 163, 74, 0.08);
    color: var(--brand-green);
}
.offer-voucher-banner-ico { width: 22px; height: 22px; flex: none; }
.offer-voucher-banner-text { display: flex; flex-wrap: wrap; gap: 2px; align-items: baseline; }
.offer-voucher-banner-text strong { font-size: 0.875rem; }
.offer-voucher-banner-text span { font-size: 0.8125rem; }
.offer-voucher-banner-remove {
    margin-left: auto;
    border: 0;
    background: transparent;
    color: var(--brand-green);
    font-weight: 700;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    cursor: pointer;
}
.offer-voucher-banner-remove:hover { text-decoration: underline; }

/* ── Item-offer selection sheet ───────────────────────────────────── */
.offer-select-overlay {
    position: fixed;
    inset: 0;
    z-index: 1200;
    background: rgba(15, 23, 42, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.offer-select-sheet {
    background: #fff;
    width: 100%;
    max-width: 460px;
    max-height: 92vh;
    max-height: 92dvh;
    border-radius: 14px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    box-shadow: 0 30px 60px rgba(0, 0, 0, 0.25);
}
@media (max-width: 520px) {
    .offer-select-overlay { padding: 0; align-items: stretch; }
    .offer-select-sheet { max-width: none; max-height: 100vh; border-radius: 0; }
}
.offer-select-head {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 14px 44px;
    border-bottom: 1px solid var(--border);
}
.offer-select-title { margin: 0; font-size: 0.9375rem; font-weight: 800; text-align: center; }
.offer-select-close {
    border: 0; background: transparent; font-size: 1.125rem; line-height: 1;
    color: var(--muted); cursor: pointer; padding: 4px 6px;
}
.offer-select-sub { margin: 8px 18px 0; font-size: 0.75rem; color: var(--muted); }
.offer-select-list {
    padding: 8px 12px 16px;
    overflow-y: auto;
    scroll-behavior: smooth;
    scrollbar-width: thin;
}
.offer-select-empty { padding: 28px 18px; text-align: center; color: var(--muted); }

.offer-select-item {
    display: flex;
    gap: 12px;
    align-items: center;
    width: 100%;
    text-align: left;
    padding: 10px 6px;
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--border);
    font: inherit;
    color: inherit;
    cursor: pointer;
}
.offer-select-item:hover { background: #faf7f2; }
.offer-select-item:last-child { border-bottom: 0; }
.offer-select-cta { margin: 2px 0 0; font-size: 0.6875rem; font-weight: 700; color: var(--brand-green); }
.offer-select-thumb {
    width: 56px; height: 56px; flex: none;
    border-radius: 8px; overflow: hidden; background: #fef3c7;
}
.offer-select-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.offer-select-body { flex: 1; min-width: 0; }
.offer-select-body h3 { margin: 0; font-size: 0.875rem; font-weight: 700; }
.offer-select-price { margin: 2px 0 0; font-size: 0.8125rem; font-weight: 700; color: var(--brand-red); }
.offer-select-actions { display: flex; gap: 8px; flex: none; }
.offer-select-btn {
    height: 32px; padding: 0 14px; border: 0; border-radius: 6px;
    background: var(--brand-red); color: #fff; font-weight: 700; font-size: 0.75rem; cursor: pointer;
}
.offer-select-btn:hover { background: var(--brand-red-dark); }
.offer-select-btn.ghost { background: transparent; color: var(--brand-green); border: 1px solid var(--brand-green); }
.offer-select-btn.ghost:hover { background: rgba(22, 163, 74, 0.08); }

/* Add-to-cart confirmation toast. */
.offer-toast {
    position: fixed;
    left: 50%;
    bottom: 24px;
    transform: translate(-50%, 20px);
    background: var(--brand-green);
    color: #fff;
    font-weight: 600;
    font-size: 0.8125rem;
    padding: 10px 18px;
    border-radius: 999px;
    box-shadow: var(--shadow-md);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease, transform 0.2s ease;
    z-index: 1300;
}
.offer-toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ── Multi-group deal builder (image 1) ───────────────────────────── */
/* z-index 150 keeps it BELOW the customize popup (.cust-overlay = 200) so customize
   layers on top when picking a group's item. */
.offer-deal-overlay {
    position: fixed;
    inset: 0;
    z-index: 150;
    background: rgba(15, 23, 42, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.offer-deal-sheet {
    position: relative;
    background: #fff;
    width: 100%;
    max-width: 460px;
    max-height: 92vh;
    max-height: 92dvh;
    border-radius: 14px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    box-shadow: 0 30px 60px rgba(0, 0, 0, 0.25);
}
@media (max-width: 520px) {
    .offer-deal-overlay { padding: 0; align-items: stretch; }
    .offer-deal-sheet { max-width: none; max-height: 100vh; border-radius: 0; }
}
.offer-deal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 2;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.9);
    color: var(--text);
    font-size: 0.9375rem;
    cursor: pointer;
}
.offer-deal-hero {
    height: 168px;
    flex: none;
    background-color: #b91c1c;
    background-size: cover;
    background-position: center;
}
.offer-deal-head { padding: 14px 18px 4px; }
.offer-deal-title { margin: 0; font-size: 1.125rem; font-weight: 800; }
.offer-deal-desc { margin: 4px 0 0; font-size: 0.75rem; color: var(--muted); }

/* flex:1 + min-height:0 lets this region grow to fill the sheet (pushing the foot to
   the bottom on the full-height mobile sheet) and scroll instead of pushing the foot
   off-screen when groups overflow. */
.offer-deal-groups {
    padding: 10px 16px 12px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 12px;
    flex: 1 1 auto;
    min-height: 0;
    scrollbar-width: thin;
}
.offer-deal-group {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: #fbfbfc;
}
.offer-deal-group.is-filled { background: rgba(22, 163, 74, 0.06); border-color: rgba(22, 163, 74, 0.4); }
.offer-deal-group-main { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.offer-deal-group-label { font-size: 0.875rem; font-weight: 700; }
.offer-deal-group-action {
    align-self: flex-start;
    min-width: 90px;
    height: 34px;
    padding: 0 16px;
    border: 0;
    border-radius: 6px;
    background: #d1d5db;
    color: #fff;
    font-weight: 700;
    font-size: 0.8125rem;
    cursor: pointer;
}
.offer-deal-group-action.is-added { background: var(--brand-green); }
.offer-deal-group-chosen { font-size: 0.6875rem; color: var(--muted); }
.offer-deal-group-icon {
    flex: none;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: #fff;
    color: var(--muted);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}
.offer-deal-group-icon svg { width: 22px; height: 22px; }
.offer-deal-group-icon.is-added { color: var(--brand-green); border-color: var(--brand-green); }

/* "Add Now": grey by default, green for the next slot to fill. */
.offer-deal-group-action.is-next { background: var(--brand-green); }

/* Right-side circle holds the slice icon (empty) or the chosen item image (filled). */
.offer-deal-group-aside {
    flex: none;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.offer-deal-group-aside img { width: 100%; height: 100%; object-fit: cover; }
.offer-deal-group.is-filled .offer-deal-group-aside { border: 2px solid var(--brand-green); }

/* Filled-slot summary text (green card): item + price, then "+ modifier" lines. */
.offer-deal-group-filled-head { font-size: 0.875rem; font-weight: 800; color: var(--brand-green); }
.offer-deal-mod { font-size: 0.75rem; color: #15803d; }
.offer-deal-change {
    align-self: flex-start;
    margin-top: 4px;
    height: 30px;
    padding: 0 12px;
    border: 1px solid var(--brand-green);
    border-radius: 6px;
    background: #fff;
    color: var(--brand-green);
    font-weight: 700;
    font-size: 0.75rem;
    cursor: pointer;
}
.offer-deal-change:hover { background: rgba(22, 163, 74, 0.08); }

/* ── Candidate list (image 2): back-arrow header + item cards ──────── */
.offer-select-back {
    position: absolute;
    left: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 34px;
    height: 34px;
    border: 0;
    background: transparent;
    color: var(--text);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}
.offer-select-back svg { width: 22px; height: 22px; }

/* Veg marker in the candidate card's name. The .menu-card veg badge is currently switched
   off (.menu-card-image::before { content: none }), so this popup carries its own. */
.offer-veg-dot { width: 11px; height: 11px; border: 1.5px solid var(--brand-green); border-radius: 2px; position: relative; flex: none; display: inline-block; margin-right: 6px; vertical-align: middle; }
.offer-veg-dot::after { content: ''; position: absolute; inset: 2px; background: var(--brand-green); border-radius: 50%; }

/* Deal/offer candidates are .menu-card (see offers-select.js buildCandidateCard) — the same
   2G card as the menu grid. Only the stacking gap is popup-specific; the FAB hangs 24px below
   the photo, so the gap has to clear the NEXT card's shadow, not just its border. */
.offer-select-list > .menu-card { margin-bottom: 18px; }
.offer-select-list > .menu-card:last-child { margin-bottom: 0; }

.offer-deal-foot { border-top: 1px solid var(--border); padding: 10px 16px 14px; background: #fff; flex: none; }
.offer-deal-foot-name { font-size: 0.8125rem; font-weight: 700; margin-bottom: 8px; }
.offer-deal-foot-row { display: flex; align-items: center; gap: 12px; }
.offer-deal-qty {
    display: flex;
    align-items: center;
    border: 1px solid var(--brand-red);
    border-radius: 8px;
    overflow: hidden;
    flex: none;
}
.offer-deal-qty button {
    width: 34px;
    height: 38px;
    border: 0;
    background: #fff;
    color: var(--brand-red);
    font-size: 1.125rem;
    font-weight: 700;
    cursor: pointer;
}
.offer-deal-qty span { min-width: 28px; text-align: center; font-weight: 700; }
.offer-deal-qty button:disabled { color: #c4c8cf; cursor: not-allowed; }
.offer-deal-add {
    flex: 1;
    height: 44px;
    border: 0;
    border-radius: 8px;
    background: var(--brand-red);
    color: #fff;
    font-weight: 800;
    font-size: 0.875rem;
    letter-spacing: 0.03em;
    cursor: pointer;
}
.offer-deal-add:hover:not(:disabled) { background: var(--brand-red-dark); }
.offer-deal-add:disabled { background: #c4c8cf; cursor: not-allowed; }

/* "Offer valid at participating stores only." — centred under the list, like the app. */
.offers-note {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    margin: 4px 0 0;
    color: var(--muted);
    font-size: 0.8125rem;
}
.offers-note svg { width: 16px; height: 16px; flex-shrink: 0; }

.offers-empty {
    padding: 60px 20px;
    text-align: center;
    color: var(--muted);
    border: 2px dashed var(--border);
    border-radius: 12px;
}

/* ============ Responsive ============ */
@media (max-width: 1200px) {
    .menu-subcat-section { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .store-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    /* Slightly smaller category thumbs on narrower desktops (width is grid-governed). */
    .store-cat-thumb { max-width: 60px; }
}

@media (max-width: 1024px) {
    :root { --sidebar-w: 110px; }
    .menu-main { padding: 16px 8px 0; }
    .menu-grid { padding-bottom: 28px; }
    .menu-subcat-section { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 16px; }
    .menu-card-image { height: 160px; }
    .menu-nav .menu-nav-item { padding: 6px 8px; font-size: 0.8125rem; }
    /* Tablet header fit: trim the outer padding + inter-section gap and the nav gap
       so the brand + address + full nav row stays within the viewport (was 28px/28px). */
    .menu-header { padding: 0 16px; column-gap: 16px; row-gap: 3px; }
    .menu-nav { gap: 4px; }
    /* Tablet: keep the address + order-type buttons visible (only mobile ≤720px
       hides them — the side drawer covers it there), but compact so both pills
       fit the tighter header. */
    .menu-store-link { max-width: 380px; gap: 4px; }
    .menu-store-addr-link { padding: 4px 9px; min-width: 0; }
    .menu-store-ot-btn { padding: 4px 8px; }
    /* Wider than the old 110px: the name wraps now instead of ellipsising, and 110px
       shredded a normal outlet name into 3-4 lines. */
    .menu-store-addr { max-width: 150px; font-size: 0.75rem; }
    .menu-store-ot-label { font-size: 0.8125rem; }
    /* Home page categories shrink further (width is grid-governed). */
    .store-cat-thumb { max-width: 58px; }
    .store-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    /* .store-promo-strip needs nothing here: its columns are auto-generated from the number of
       cards that survive the per-outlet gate, at every width. (The old flex-wrap declaration did
       nothing on a grid anyway.) */
}

@media (max-width: 720px) {
    /* Defensive: clip the X axis at the page level so a long sub-nav pill or
       any wide child can never push the page horizontally. We use
       `overflow-x: clip` instead of `hidden` because `hidden` establishes a
       new scrolling container — that would break `position: sticky` on the
       header / sidebar / filters (they'd stick relative to .menu-page
       instead of the body, and slide up out of view as the page scrolls). */
    :root {
        --header-h: 56px;   /* single-row header (redesign): badge + store name on one line */
    }
    /* Tighten the top header on mobile so the sticky stack is shorter. Column 1 (badge +
       locator) is flexible+shrinkable so the store name ellipsises; column 2 keeps the cart
       pill at its natural width. */
    /* Single-row header (redesign): [badge] [store name ▾], avatar floats right, cart moves
       to the bottom Proceed bar, and the order type becomes the slider below the header. */
    /* Plain flex row so the badge + store name sit on ONE vertically-centred line (the base
       grid's two-row template kept the content top-aligned, misaligned vs the fixed burger). */
    .menu-header {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 0 10px;
        height: var(--header-h);
        min-height: 0;
    }
    .menu-nav { display: none; }                 /* cart is in the bottom Proceed-to-Cart bar */
    .menu-store-ot-btn { display: none; }         /* order type is the Pickup/Delivery slider now */
    /* Logo + store name as ONE bordered pill, like the outlet switcher on the design
       reference — badge on the left, name + red caret on the right, no gap for daylight
       between them. Replaces the old "badge, then plain name" look. */
    .menu-store-pill {
        flex: 0 1 auto;
        min-width: 0;
        /* Capped (not just 100%) so a long store name can't out-shrink the search field next
           to it — flexbox shrinks both proportionally to content size, and the pill's content
           (a whole store name) is much bigger than the search field's ("Search"), so without
           a cap the pill would win nearly all the available room and crush the search field
           down to a sliver. The name still ellipsizes inside this cap. */
        max-width: 170px;
        gap: 6px;
        height: 40px;        /* same height as the search field next to it */
        padding: 0 10px 0 4px;
        border: 1px solid var(--border);
        border-radius: 999px;
        background: #fff;
    }
    .menu-store-pill .menu-brand img {
        height: 30px;
        width: 30px;
        border-radius: 50%;
    }
    .menu-store-addr-link {
        border: 0;
        background: transparent;
        padding: 2px 0;
        font-weight: 700;
        flex: 0 1 auto;
    }
    .menu-store-addr-link:hover { background: transparent; }
    .menu-store-addr-link::before { display: none; }   /* drop the location pin */
    .menu-store-addr-link::after {                       /* red dropdown caret */
        content: "";
        flex-shrink: 0;
        width: 0; height: 0;
        border-left: 4px solid transparent;
        border-right: 4px solid transparent;
        border-top: 5px solid var(--brand-red);
        margin-left: 3px;
    }
    /* Mobile: surface a COMPACT store + order-type control inline in the top bar
       (still also available in the side drawer). The address text is swapped for
       the store NAME; both pills carry min-width:0 + ellipsis so they shrink and
       the cart icon on the right always stays reachable. */
    .menu-store-link {
        display: inline-flex;
        justify-self: stretch;   /* fill column 1 under the badge so the name ellipsises */
        flex: 0 1 auto;
        min-width: 0;
        max-width: none;
        gap: 6px;
    }
    .menu-store-addr { display: none; }              /* hide the long address on mobile */
    .menu-store-name-m {
        display: inline-block;
        min-width: 0;
        max-width: 100%;
        /* Wraps to a second line rather than truncating — the full outlet name must always be
           readable. The pill's max-width caps how wide it gets; min-height lets it grow. */
        white-space: normal;
        overflow-wrap: anywhere;
        vertical-align: middle;
        /* 11px/1.15 keeps two wrapped lines (~26px) inside the pill's 40px height. */
        line-height: 1.15;
        font-weight: 700;
        font-size: 0.6875rem;
        color: #111;                 /* store name in black */
    }
    .menu-store-addr-link {
        flex: 1 1 auto;          /* store name truncates first when space is tight */
        min-width: 0;
        padding: 5px 9px;
        gap: 4px;
    }
    .menu-store-ot-btn {
        flex: 0 1 auto;          /* order type keeps its label longer */
        min-width: 0;
        padding: 5px 9px;
        gap: 4px;
    }
    .menu-store-ot-label {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: 0.8125rem;
    }
    .menu-brand img { height: 42px; }   /* circular badge — a bit bigger */
    .menu-page {
        overflow-x: clip;
        max-width: 100%;
    }
    .menu-shell {
        grid-template-columns: 1fr;
        max-width: 100%;
        min-width: 0;
    }
    .menu-main {
        padding-top: 0px;
        max-width: 100%;
        min-width: 0;
    }
    /* The ONLY mobile sticky bar is the category icons row. The dietary
       filter (All / Veg / Halal / Vegan) sits below in normal flow and
       scrolls away with the cards — keeps the sticky stack short so cat
       section heads don't have to compete for the top edge with the
       filter row (which used to overlap visually on small screens). */
    .menu-sidebar {
        position: sticky;
        top: var(--header-h);
        z-index: 40;
        background: #fff;
        border-right: 0;
        border-bottom: 1px solid var(--border);
        overflow-x: auto;
        overflow-y: hidden;
        height: auto;
        padding: 4px 8px 2px;   /* nothing hangs below the chips any more */
        scrollbar-width: none;       /* Firefox */
        -ms-overflow-style: none;    /* old Edge / IE */
    }
    .menu-sidebar::-webkit-scrollbar { display: none; width: 0; height: 0; }
    .menu-cats {
        flex-direction: row;
        gap: 4px;
        /* Belt + suspenders: the wrapper-level scrollbar hiding above covers
           webkit; this hides any scrollbar that browsers paint on the inner
           track when the row overflows horizontally. */
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    .menu-cats::-webkit-scrollbar { display: none; width: 0; height: 0; }
    /* min-width: 0 — without it a flex item's `auto` minimum is its min-content width, and
       the nowrap label below makes that the whole name, blowing the 60px basis out to ~94px. */
    .menu-cat { flex: 0 0 60px; min-width: 0; padding: 3px 2px; gap: 2px; }
    /* One line only. The chip is a fixed 60px, so names like "Sourdough Twist" wrapped to
       two lines — and since .menu-cats is a flex row, ALL chips stretched to that height,
       leaving a blank band under every short name. Ellipsis costs less than that band. */
    .menu-cat-label { font-size: 0.6875rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
    /* On mobile the active indicator slides under instead of to the side. bottom:0 (was -4px)
       so it hugs the chip — the 4px it used to hang below forced the strip to reserve dead
       height for it. The old duplicate ::before rule here never rendered (no `content`). */
    .menu-cat.is-active::after { right: 50%; left: auto; top: auto; bottom: 0; transform: translateX(50%); width: 24px; height: 2px; }
    .menu-cat-thumb { width: 48px; height: 48px; }
    /* Sidebar now sits on top of main — let the main panel grow naturally so
       the whole page scrolls together instead of competing for viewport height. */
    .menu-main { height: auto; overflow: visible; }
    .menu-grid { overflow: visible; padding-bottom: 24px; }
    .menu-subcat-section { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* Dietary filter row: STICKY on mobile, same treatment as the category
       icons bar. Its `top` is the bottom of that bar (--menu-stack-top), and
       JS keeps that var in sync with the bar's real measured height so the
       two never overlap (the bug that motivated this fix). */
    .menu-filters {
        position: sticky;
        top: var(--menu-stack-top, 168px);
        z-index: 38;
        background: #fff;
        margin: 0 -18px 12px;
        padding: 10px 18px;
        border-bottom: 1px solid var(--border);
    }
    /* Category section heads stick directly below the header + cat-icons bar.
       menu.js (syncMobileStickyTop) measures that stack into --menu-stack-top-h;
       the 137px fallback below is what it used to be hard-pinned to and only
       applies for the pre-JS paint. */
    .menu-cat-section-head {
        top: var(--menu-stack-top-h, 137px);
        /* Negative margins cancel .menu-main's side padding so the white bar bleeds to the
           screen edge; the padding then sets where the TITLE sits (14px in). Was -29/18 back
           when .menu-main had 28px sides — that now overshoots and pushed the title off-screen
           left. Keep the margin equal to .menu-main's padding whenever that changes. */
        margin-left: -8px;
        margin-right: -8px;
        padding-left: 22px;
        padding-right: 22px;
        padding-top: 2px;
        padding-bottom: 2px;
        margin-bottom: 6px;
    }
    /* Category name hidden here too (see the base .menu-cat-section-head h3 rule) — the
       sticky bar still doubles as the divider between one category's cards and the next. */
    .menu-cat-section-head h3 { display: none; }
    /* Hide the body's vertical scrollbar across browsers. The card list still
       scrolls normally with touch / wheel; we just suppress the visible track
       so the menu page feels app-like (matches the user's mockup). */
    html, body {
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    html::-webkit-scrollbar,
    body::-webkit-scrollbar { display: none; width: 0; height: 0; }
    /* Pizza sub-nav (All Pizza / Traditional / Halal / …) — horizontal scroll,
       no visible scrollbar across browsers. */
    .menu-cat-section-subnav {
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    .menu-cat-section-subnav::-webkit-scrollbar { display: none; width: 0; height: 0; }
    .cart-popup { width: calc(100vw - 24px); right: 12px; }
    .menu-nav-item span,
    .menu-nav-item:not(.menu-cart-trigger):not(#menuSearchTrigger) { /* no-op */ }
    /* Home page mobile */
    .store-home { padding: 0 8px 24px; }
    /* One banner per view on mobile, with a tiny peek of the next slide */
    .store-banners { gap: 10px; }
    .store-banner { flex: 0 0 100%; }
    /* Categories wrap to a responsive grid (base rule); tighten gap + thumb here. */
    .store-cats { gap: 8px 8px; }
    .store-cat-thumb { max-width: 56px; }
    .store-cat-label { font-size: 0.75rem; }
    .store-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }   /* 2 per row */
    .store-carousel { gap: 12px; }
    .store-carousel .menu-card { min-width: 60vw; }
    /* ── Promo strip on phones: still one row of three, but the card turns compact ──────────
       Three across on a 390px screen is ~115px per card, which cannot hold a disc, two lines of
       text and a chevron side by side. So the card stacks: disc over title, centred. The
       subtitle and the chevron are DISPLAY:NONE rather than shrunk — "Most loved by our
       customers" at 115px wide is four lines of unreadable text, and the whole card is the tap
       target so the chevron was never the affordance. The tint and accent disc carry the
       identity, and the result matches the category row directly above it. */
    .store-promo {
        flex-direction: column;
        align-items: center;
        text-align: center;
        gap: 6px;
        padding: 12px 6px;
        border-radius: 12px;
    }
    .store-promo-text { align-items: center; }
    .store-promo-title { font-size: clamp(0.68rem, 3vw, 0.82rem); }
    .store-promo-sub,
    .store-promo-go { display: none; }
    .store-promo-ico { width: 34px; height: 34px; }
    /* ── Customize modal: true full-screen on mobile ──────────────────────── */
    .cust-overlay { padding: 0; align-items: stretch; }
    .cust-card {
        max-width: 100vw;
        width: 100vw;
        /* 100vh first as the fallback; 100dvh LAST so modern browsers override it and
           track the *visible* viewport — without this the card is taller than the
           screen and the footer hides behind the iOS Safari / Android toolbar. */
        height: 100vh;
        height: 100dvh;
        max-height: 100vh;
        max-height: 100dvh;
        margin: 0;
        border-radius: 0;
        /* Mobile: the CARD is the single scroll region — image, item name, description
           and modifier groups scroll together. Overrides the base overflow:hidden; the
           footer (sticky) and close button (fixed) stay pinned. */
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    /* Close button stays pinned to the viewport corner while the card scrolls — an
       absolute button would scroll away with the content. No transformed ancestor, so
       `fixed` resolves to the full-screen card area. */
    .cust-close { position: fixed; z-index: 6; }
    /* Footer pinned above the browser chrome (safe-area aware) so the Add-to-Cart
       button, quantity selector and price stay visible while the body scrolls. */
    .cust-footer {
        position: sticky;
        bottom: 0;
        z-index: 5;
        background: #fff;
        padding-bottom: calc(18px + env(safe-area-inset-bottom));
    }
    /* Mobile: collapse the item name + modifier summary by default; the explicit
       red "Show Selected Item Details" toggle reveals them on demand. */
    .cust-footer-summary-toggle { display: inline-flex; }
    .cust-footer--summary-hidden .cust-footer-name,
    .cust-footer--summary-hidden .cust-footer-added { display: none; }
    /* Smaller hero image — more room for options */
    .cust-hero { height: 160px; }
    /* Compact fixed header */
    .cust-fixed-head { padding: 10px 14px 8px; }
    .cust-title { font-size: 0.9375rem; }
    /* .cust-desc-clamped + .cust-desc-toggle now live at top-level so the
       2-line clamp + Show more toggle apply on desktop too (mobile inherits). */

    /* Per-segment clamp is identical on mobile and desktop now — the policy
       moved from "group-level 2-line clamp on mobile" to "each individual
       segment clamps to 1 line and gets its own Show more toggle when it
       wraps". The mobile-specific group rules used to live here; left this
       block in place for future mobile-only tweaks. */

    /* Body flows into the card's single scroll instead of scrolling on its own;
       flex-grow keeps the footer pinned to the bottom even when content is short. */
    .cust-body { padding: 10px 14px 6px; overflow: visible; flex: 1 0 auto; min-height: 0; }
    .cust-group { margin-bottom: 14px; }
    .cust-group h4 { font-size: 0.8125rem; margin-bottom: 6px; }
    .cust-group p.cust-hint { font-size: 0.6875rem; }
    /* Toppings popup full-width */
    .toppings-overlay { padding: 0; align-items: flex-end; }
    .toppings-card {
        max-width: 100%;
        max-height: 100vh;
        max-height: 100dvh;
        border-radius: 14px 14px 0 0;
    }

    .cust-desc-clamped {
        -webkit-line-clamp: 1;
    }
    .cust-desc {
        font-size: 0.75rem; line-height: 1.3;
    }
}

/* Phones < 420 — drop sizes one more notch */
@media (max-width: 420px) {
    .cart-item {
        padding: 9px 10px;
    }
    .cart-item-meta {
        font-size: 0.6875rem;
    }
    .store-cat-thumb { max-width: 52px; }   /* smallest phones: compact category circles */
    .store-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }   /* 2 per row on phones */
    .menu-subcat-section { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .menu-card-image { height: 140px; }
}

/* Phones ≤ 425px — home "EXPLORE MENU" categories: same two scrolling rows, sized so a
   half tile peeks past the right edge; circles size themselves to the column via aspect-ratio. */
@media (max-width: 425px) {
    .store-cats {
        /* 4.5 tiles per screen: the half-tile peek at the right edge is the only affordance
           telling a phone user the row scrolls. Gaps are subtracted so the maths holds at any
           viewport width. */
        grid-auto-columns: calc((100% - 4 * 4px) / 4.5);
        gap: 6px 4px;                             /* row-gap col-gap */
        padding: 2px 2px 4px 2px;
    }
    /* Tiles fill their column instead of carrying a fixed card width. */
    .store-cat {
        min-width: 0;            /* let the column govern width; allow labels to wrap */
        padding: 4px;
        gap: 6px;
    }
    .store-cat-thumb {
        width: 100%;
        height: auto;
        aspect-ratio: 1 / 1;     /* stays circular, sized to the column */
    }
    /* overflow-wrap: a long single word can't overflow the now-narrow cell. */
    .store-cat-label { font-size: 0.6875rem; text-align: center; overflow-wrap: anywhere; }
    .menu-card-desc {
        /* Smaller + tighter + more lines, so the space the name no longer reserves is filled
           with actual description rather than left blank. 12px/1.45 over 13px/1.55 buys two
           extra lines inside a box only ~27px taller, and most item descriptions fit whole at
           this size in a 2-up column (~22 chars a line) instead of ending in an ellipsis.
           Height and clamp MUST stay in step - the clamp truncates the text, the height reserves
           the box, and if they disagree short cards drift out of line with tall ones.
           Dial: 4 lines = 5.8em, 5 lines = 7.25em, 6 lines = 8.7em. */
        font-size: 0.75rem;
        line-height: 1.45;
        margin-top: 4px;
        -webkit-line-clamp: 5;
        height: 7.25em;             /* 5 lines x 1.45 */
    }
}

/* ============ Mobile drawer (account panel) ============ */
.pt-burger {
    display: none; /* visible only on mobile via media query (set to flex there) */
    position: fixed;
    top: 12px;             /* centred in the 56px mobile header ((56-32)/2) */
    left: 14px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: #fff;
    border: 0;
    z-index: 90;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.14);
    cursor: pointer;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
}

/* Three thick, fully-rounded brand-red bars (was two 2px --text hairlines, which read as
   low-contrast furniture on the white circle and got missed). Drawn in CSS rather than
   shipping the PNG — same mark, no extra request, scales on any DPI. */
.pt-burger span {
    display: block;
    width: 17px;
    height: 3px;
    border-radius: 999px;
    background: var(--brand-red);
}

/* Profile/avatar trigger — mirrors the burger but floats top-RIGHT; mobile-only (shown via
   the ≤720px media query, hidden on desktop where the header account item opens the panel). */
/* Mobile avatar — a HEADER-ROW child, not a fixed float. It used to pin to the viewport's
   top-right corner, which put it on top of whatever else claims that corner — latest casualty
   was the accessibility bar's Options button, which sits exactly there at page top. A fixed
   button can't track a bar that scrolls away, so instead _MenuLayout appends this button into
   .menu-header at runtime (same six-views-one-header trick as the back button) and it rides
   the row, aligned with the search field and cart pill. Shown by the ≤720px block below ONLY
   once inside the header, so with JS off it stays hidden — the drawer it opens is JS-driven
   anyway. */
.pt-profile-btn {
    display: none;
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 50%;
    background: #fff;
    color: var(--brand-red);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    cursor: pointer;
}
.pt-profile-btn { border: 1px solid var(--border); }   /* thin ring around the avatar */
.pt-profile-btn svg { width: 24px; height: 24px; }
.pt-profile-initials {
    font-size: 0.82rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    color: var(--brand-red);
    line-height: 1;
}
.pt-profile-initials[hidden] { display: none; }

/* Pickup / Delivery order-type slider — the ONLY order-type control site-wide (the popup,
   the header button and the drawer picker are all gone). Shown on every viewport. */
.pt-ot-slider {
    display: flex;
    max-width: 520px;                    /* full width on phones, capped on wide screens */
    gap: 4px;
    margin: 6px 10px 2px;
    padding: 3px;
    background: #f1ece3;                 /* light cream track (matches the header card) */
    border-radius: 999px;
}
.pt-ot-seg {
    flex: 1 1 0;
    padding: 6px 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--muted, #8a6d52);
    font-size: 0.85rem;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}
.pt-ot-seg.is-active {
    background: #fff;
    color: var(--text);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
}
/* Muted "Unavailable" side of the pill — still tappable (the tap opens the explainer
   popover, so no disabled attr), hence the pointer cursor. */
.pt-ot-seg.is-disabled,
.pt-ot-seg:disabled { opacity: 0.4; cursor: pointer; }
.pt-ot-seg-sub {
    display: block;
    font-size: 0.55rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    line-height: 1;
    margin-top: 2px;
}

/* The order-type popup + the header order-type button are removed site-wide — the slider
   above is the only control. */
.pt-ordertype-modal { display: none !important; }
.menu-store-ot-btn { display: none !important; }

/* Explainer popover for the muted segment — body-level position:fixed card, so it
   overlays the page and never takes layout space; JS anchors it under the tapped segment. */
.pt-ot-pop {
    position: fixed;
    z-index: 9600;                       /* above the sticky header and the drawer scrim (9000) */
    width: min(300px, calc(100vw - 24px));
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 10px 32px rgba(0, 0, 0, 0.2);
    padding: 14px 16px;
}
.pt-ot-pop[hidden] { display: none; }
.pt-ot-pop-title { margin: 0 0 4px; font-size: 0.95rem; font-weight: 800; color: var(--text); }
.pt-ot-pop-body { margin: 0 0 10px; font-size: 0.82rem; line-height: 1.45; color: var(--muted, #8a6d52); }
.pt-ot-pop-link { color: var(--brand-red, #E21B22); font-weight: 700; font-size: 0.85rem; text-decoration: none; }

/* Desktop: the slider is relocated INTO the header row (JS adds this class).
   Shrinkwrapped there — the header row has no width to give; full-width stays
   a below-the-header (mobile) behavior. */
.pt-ot-slider--nav { margin: 0; flex: 0 0 auto; }
.pt-ot-slider--nav .pt-ot-seg { flex: 0 0 auto; padding: 6px 16px; }

.pt-drawer-scrim {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.45);
    z-index: 9000;
    opacity: 0;
    transition: opacity 0.25s ease;
}

.pt-drawer-scrim.is-open { opacity: 1; }
.pt-drawer-scrim[hidden] { display: none; }

.pt-drawer {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    width: 86vw;
    max-width: 340px;
    background: #fff;
    z-index: 9100;
    transform: translateX(-100%);
    transition: transform 0.25s ease;
    display: flex;
    flex-direction: column;
    overflow: hidden;                 /* the panel itself never scrolls — only .pt-drawer-nav does */
    box-shadow: 4px 0 18px rgba(0,0,0,0.18);
}

/* Top block (logo / user / default store) stays fixed above the scroll area */
.pt-drawer-head,
.pt-drawer-user,
.pt-drawer-store { flex-shrink: 0; }

.pt-drawer.is-open { transform: translateX(0); }
.pt-drawer[hidden] { display: none; }

/* Right-side variant — the user-profile panel slides in from the RIGHT instead of the left.
   (.pt-drawer.is-open above still wins to bring it to translateX(0) when open.) */
.pt-drawer--right {
    left: auto;
    right: 0;
    transform: translateX(100%);
    box-shadow: -4px 0 18px rgba(0, 0, 0, 0.18);
}
/* Explicit open state for the right variant — same specificity as (and declared after) the
   base .pt-drawer.is-open, so it wins and slides the panel fully on-screen. */
.pt-drawer--right.is-open { transform: translateX(0); }

/* Close (X) button — top-right of the mobile drawer. */
.pt-drawer-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.06);
    color: var(--text);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    z-index: 6;
    transition: background 0.15s ease;
}
.pt-drawer-close svg { width: 18px; height: 18px; }
.pt-drawer-close:hover { background: rgba(0, 0, 0, 0.12); }

.pt-drawer-head {
    padding: 14px 16px 4px;
    border-bottom: 2px solid var(--brand-green, #0a8a3a);
}

.pt-drawer-logo { width: 130px; height: auto; display: block; }

.pt-drawer-user {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px 12px;
}

.pt-drawer-avatar {
    width: 44px;
    height: 44px;
    border-radius: 8px;
    background: var(--brand-red, #E21B22);
    flex-shrink: 0;
}

.pt-drawer-id { flex: 1; min-width: 0; }

.pt-drawer-name {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.9375rem;
    font-weight: 700;
    color: var(--text);
}

.pt-drawer-name svg { width: 14px; height: 14px; color: var(--brand-red, #E21B22); }
.pt-drawer-phone { font-size: 0.8125rem; color: var(--muted); margin-top: 2px; }

.pt-drawer-store {
    padding: 0 16px 14px;
}

.pt-drawer-label {
    font-size: 0.8125rem;
    color: var(--text);
    margin-bottom: 6px;
}

.pt-drawer-store-row {
    display: flex;
    flex-direction: column;
/*    gap: 10px;*/
    padding: 10px 12px;
    border-radius: 10px;
    background: var(--brand-red-soft, #fff1f1);
    color: var(--text);
    text-decoration: none;
    border: 1px solid transparent;
}

.pt-drawer-store-icon svg,
.pt-drawer-store-pin svg { width: 18px; height: 18px; color: var(--text); }
.pt-drawer-store-pin { margin-left: auto; color: var(--brand-red, #E21B22); }
.pt-drawer-store-pin svg { color: var(--brand-red, #E21B22); }
.pt-drawer-store-name {
    font-size: 0.875rem;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pt-drawer-nav {
    flex: 1 1 auto;                    /* grow to fill the gap between top + bottom blocks */
    min-height: 0;                    /* allow the flex child to shrink so overflow kicks in */
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    padding: 2px 4px;
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    /* thin, smooth scrollbar */
    scrollbar-width: thin;                        /* Firefox */
    scrollbar-color: #d4d4d8 transparent;
    scroll-behavior: smooth;
}
.pt-drawer-nav::-webkit-scrollbar { width: 4px; }
.pt-drawer-nav::-webkit-scrollbar-track { background: transparent; }
.pt-drawer-nav::-webkit-scrollbar-thumb { background: #d4d4d8; border-radius: 2px; }
.pt-drawer-nav::-webkit-scrollbar-thumb:hover { background: #a1a1aa; }

/* "My Account" profile group at the top of the drawer nav — a labelled, divided section
   holding Orders / Rewards / Addresses + the account-settings actions. */
.pt-drawer-section { display: flex; flex-direction: column; }
.pt-drawer-section[hidden] { display: none; }
.pt-drawer-account {
    padding-bottom: 8px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--border, #ececec);
}
.pt-drawer-section-label {
    padding: 4px 20px 6px;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted, #8a6d52);
}

.pt-drawer-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 14px;
    color: var(--text);
    text-decoration: none;
    font-size: 0.8125rem;
    border-radius: 8px;
}

.pt-drawer-link:hover { background: var(--bg-soft); }

.pt-drawer-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 19px; height: 19px;
    color: var(--text);
    flex-shrink: 0;
}

.pt-drawer-ico svg { width: 19px; height: 19px; }

.pt-drawer-link--danger { color: var(--brand-red, #E21B22); }
.pt-drawer-link--danger .pt-drawer-ico { color: var(--brand-red, #E21B22); }

/* Language picker row — fixed below the scroll area, above the footer */
.pt-drawer-lang-row {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 14px;
    margin: 4px 8px 0;
    border-radius: 8px;
    color: var(--text);
    font-size: 0.8125rem;
    font-weight: 500;
    text-decoration: none;
    transition: background 0.15s;
}
.pt-drawer-lang-row:hover { background: var(--bg-soft); }
.pt-drawer-lang-sel {
    flex: 1 1 auto;
    border: 0;
    background: transparent;
    font: inherit;
    color: inherit;
    cursor: pointer;
    padding: 0;
    appearance: auto;
}
.pt-drawer-lang-sel:focus-visible {
    outline: 2px solid var(--brand-red, #E21B22);
    outline-offset: 2px;
    border-radius: 4px;
}

.pt-drawer-foot {
    flex-shrink: 0;
    padding: 10px 16px;
    display: flex;
    flex-direction: column;          /* "Our Presence" link stacks above the version/credit */
    align-items: flex-start;
    font-size: 0.625rem;
    color: var(--muted);
    gap: 6px;
}

.pt-drawer-credit strong { color: var(--text); font-weight: 600; }
/* The version NUMBER carries the information, not the "App Version" label — darken and
   bold it out of the muted 10px footer text. 700 (vs the credit's 600) so it reads as the
   footer's one piece of data rather than another byline. */
.pt-drawer-version strong { color: var(--text); font-weight: 700; }

/* "Our Presence" link, moved into the drawer footer. */
.pt-drawer-foot-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--brand-red, #E21B22);
    font-size: 0.85rem;
    font-weight: 700;
    text-decoration: none;
}
.pt-drawer-foot-link:hover { text-decoration: underline; }
.pt-drawer-foot-link .pt-mi { font-size: 18px; }

/* ===== Account panel profile header (replaces the old logo header) ===== */
.pt-drawer-profile {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px;
    background: #efb9bd;                  /* soft pink from the mock (desktop only) */
    border-bottom: 0;
}

/* On mobile the brand bar above already gives the panel a white header, so
   drop the pink background from the profile row and tighten its padding. */
@media (max-width: 720px) {
    .pt-drawer-profile {
        padding: 0 16px 16px;
        background: none;
    }
}
/* The right profile panel has no brand bar above the header, so give it top margin
   (clears the close button + breathing room from the top edge). */
.pt-drawer--right .pt-drawer-profile { padding-top: 44px; }
.pt-profile-avatar {
    width: 46px;
    height: 46px;
    border-radius: 8px;
    background: var(--brand-red, #E21B22);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    overflow: hidden;
    background-size: cover;
    background-position: center;
}
/* Placeholder person icon is hidden by default so the avatar reads as a flat
   red tile, matching the reference design. When the user uploads a photo, the
   `.has-img` class swaps in a background-image. */
.pt-profile-avatar svg { display: none; }
.pt-profile-avatar.has-img svg { display: none; }
.pt-profile-name {
    flex: 1;
    min-width: 0;
    font-size: 1.0625rem;
    font-weight: 700;
    color: #1f1f1f;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.pt-profile-edit {
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
    color: var(--brand-red, #E21B22);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
}
.pt-profile-edit:hover { background: rgba(255,255,255,0.45); }
.pt-profile-edit svg { width: 20px; height: 20px; }

/* Mobile-only centered brand bar at the very top of the drawer. */
.pt-drawer-brand {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 5px 16px 12px;
    background: #fff;
}
.pt-drawer-brand img {
    height: 45px;
    width: auto;
    display: block;
}

/* Two-line name + phone stack (mobile design — name + pencil on the same row,
   phone on the row below). .pt-profile-text takes the flex slot the name used
   to occupy directly. */
.pt-profile-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.pt-profile-name-row {
    display: flex;
    align-items: center;
    gap: 6px;
}
.pt-profile-text .pt-profile-name {
    flex: initial;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.pt-profile-phone {
    font-size: 0.8125rem;
    color: #5b5b5b;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ===== Default Store row (mobile-only quick-pick card) =====
   Sits below the profile header. "Default Store" is a plain left-aligned
   label above a soft-pink card with the store name and a red location pin. */
.pt-drawer-store-row {
    padding: 0 16px 8px;
    background: #fff;
}
.pt-drawer-store-label {
    font-size: 0.8125rem;
    color: #1f1f1f;
    margin-bottom: 2px;
}
.pt-drawer-store-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 12px;
    background: transparent;
    border: 1px solid #f5d4cf;
    border-radius: 8px;
    text-decoration: none;
    color: #1f1f1f;
}
.pt-drawer-store-card:hover,
.pt-drawer-store-card:focus { background: #ffece9; }
.pt-drawer-store-ico,
.pt-drawer-store-pin {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    color: #1f1f1f;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.pt-drawer-store-pin { color: var(--brand-red, #E21B22); }
.pt-drawer-store-ico svg,
.pt-drawer-store-pin svg { width: 100%; height: 100%; }
.pt-drawer-store-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.875rem;
    color: #6b6b6b;
    font-style: italic;
}

/* ===== Desktop: open the account panel as a top-right dropdown card ===== */
@media (min-width: 721px) {
    .pt-drawer {
        top: calc(var(--header-h) + 10px);
        bottom: auto;
        left: auto;
        right: 18px;
        width: 320px;
        max-width: 320px;
        max-height: calc(100vh - var(--header-h) - 28px);
        border-radius: 14px;
        transform: translateY(-10px);
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.18s ease, transform 0.18s ease;
        box-shadow: 0 12px 32px rgba(0,0,0,0.18);
    }
    .pt-drawer.is-open { transform: translateY(0); opacity: 1; pointer-events: auto; }
    .pt-drawer-profile { border-radius: 14px 14px 0 0; }
    /* No dark overlay on desktop — the scrim is just an invisible click-catcher. */
    .pt-drawer-scrim { background: transparent; }

    /* Mobile-only extras: hide brand bar, phone sub-line, and Default Store row
       on desktop. (Edit profile from the pencil → phone is still saved; just
       not surfaced in the desktop dropdown.) */
    .pt-drawer-brand,
    .pt-profile-phone,
    .pt-drawer-store-row { display: none; }
}

/* =====================================================================
   Google Material Symbols — utility classes + brand-red color (#b32222)
   ===================================================================== */
.material-symbols-outlined,
.material-symbols-rounded {
    font-weight: normal;
    font-style: normal;
    font-size: 1.375rem;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    -webkit-font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
    vertical-align: middle;
    user-select: none;
}

/* Variant filtering: only the "Outlined" stylesheet ships with the
   Material Symbols Outlined family; the "Rounded" stylesheet ships with
   the Rounded family. We hand-bind the family names for clarity. */
.material-symbols-outlined { font-family: 'Material Symbols Outlined'; }
.material-symbols-rounded  { font-family: 'Material Symbols Rounded'; }

/* Material icons inherit their parent's color (default text/dark grey) — no
   forced brand-red so the icons sit alongside neighbouring nav links visually. */
.pt-mi {
    color: inherit;
    font-variation-settings: 'opsz' 24, 'wght' 400, 'FILL' 0, 'GRAD' 0;
}

/* Filled variant — used by directions_car for the In-Car option.
   `!important` + the qualified selectors keep FILL=1 from being clobbered
   by downstream rules (e.g. the modal-button color/size restatement). */
.pt-mi--filled,
.material-symbols-outlined.pt-mi--filled,
.material-symbols-rounded.pt-mi--filled {
    font-variation-settings: 'opsz' 24, 'wght' 400, 'FILL' 1, 'GRAD' 0 !important;
}

/* Larger icon in the order-type grid (modal). */
.pt-mi--lg { font-size: 2rem; }

/* Wrapper that keeps the material icon centred where a 19×19 SVG used to
   sit (drawer store-card icon, "Our Presence" link icon, etc). */
.pt-mi-wrap {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    flex-shrink: 0;
}
.pt-mi-wrap .pt-mi { font-size: 1.375rem; line-height: 1; }

/* Store-card icon: slightly larger to read against the soft-pink card. */
.pt-drawer-store-card .pt-mi-wrap { width: 24px; height: 24px; }
.pt-drawer-store-card .pt-mi-wrap .pt-mi { font-size: 1.5rem; }

/* Inside drawer nav links, match the 19px SVG sizing the other links use. */
.pt-drawer-link .pt-mi-wrap { width: 19px; height: 19px; }
.pt-drawer-link .pt-mi-wrap .pt-mi { font-size: 1.25rem; }

/* =====================================================================
   Drawer — Order Type trigger + inline dropdown
   ===================================================================== */
.pt-drawer-ot-trigger {
    /* Override default link layout so we can host an icon + 2-line label
       + chevron in one row. */
    align-items: center;
}
.pt-drawer-ot-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}
.pt-drawer-ot-name {
    font-size: 0.8125rem;
    color: var(--text);
}
.pt-drawer-ot-current {
    font-size: 0.75rem;
    color: #b32222;
    font-weight: 600;
}

/* Trigger entry — paint the currently-selected order-type icon brand-red so
   it matches the value label beside it. Other material icons in the drawer
   (store, Our Presence, etc.) keep their inherited dark-grey text colour. */
.pt-drawer-ot-trigger .pt-mi { color: #b32222; }
.pt-drawer-ot-chev {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #6b6b6b;
    transition: transform 0.2s ease;
}
.pt-drawer-ot-chev svg { width: 100%; height: 100%; }
.pt-drawer-ot-trigger.is-open .pt-drawer-ot-chev { transform: rotate(180deg); }

.pt-drawer-ot-dropdown {
    margin: 2px 14px 6px 36px;       /* indent under the icon column */
    padding: 4px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 6px 14px rgba(0,0,0,0.08);
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.pt-drawer-ot-dropdown[hidden] { display: none; }

.pt-drawer-ot-opt {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border: 0;
    background: transparent;
    border-radius: 6px;
    font-size: 0.8125rem;
    color: var(--text);
    cursor: pointer;
    text-align: left;
}
.pt-drawer-ot-opt:hover { background: var(--bg-soft); }
.pt-drawer-ot-opt.is-active {
    background: var(--bg-soft);
    color: var(--text);
    font-weight: 600;
}
.pt-drawer-ot-opt .material-symbols-outlined,
.pt-drawer-ot-opt .material-symbols-rounded {
    color: inherit;
    font-size: 1.25rem;
}

/* Mobile (≤720px): the modal handles the picker, so hide the inline
   dropdown entirely. The trigger still shows the current selection. */
@media (max-width: 720px) {
    .pt-drawer-ot-dropdown { display: none !important; }
    .pt-drawer-ot-chev     { display: none; }
}

/* Large desktop (>1024px): hide the drawer "Order Type" entry — on wide screens
   the order type is changed via the address "Change Order Type" popover instead.
   It stays visible at ≤1024px. */
@media (min-width: 721px) {
    #ptLinkOrderType,
    #ptOrderTypeDropdown,
    #ptLinkMenu,
    #ptLinkOffers {
        display: none !important;
    }
}
@media (max-width: 735px){
    #ptStoreOrderTypeBtn .menu-store-ot-label {
        display: none !important;
    }
}

/* ===== QR table mode (_MenuLayout adds .pt-table-locked when the ?table= cookie is live) =====
   The diner scanned a code stuck to a table in THIS restaurant: the outlet and the order type
   are facts, not choices. Hide every control that offers to change either — the Pickup/Delivery
   slider, the drawer's order-type entry and its dropdown, the store-picker rows, and the chevron
   that makes the header order-type badge look tappable. The badge itself stays: it reads
   "Dine-In", which is exactly what the diner should see. */
.pt-table-locked #ptOtSlider,
.pt-table-locked #ptLinkOrderType,
.pt-table-locked #ptOrderTypeDropdown,
.pt-table-locked #ptDrawerStoreLink,
.pt-table-locked .pt-drawer-store-row,
.pt-table-locked .pt-drawer-store-card,
.pt-table-locked .pt-loc-item[href*="stores"],
.pt-table-locked #ptStoreOrderTypeBtn .menu-store-chev {
    display: none !important;
}
/* No href in table mode — kill the affordance too. */
.pt-table-locked #ptStoreAddr { cursor: default; }

/* ===== Edit-profile popover ===== */
.profile-modal {
    position: fixed;
    inset: 0;
    z-index: 9500;
    background: rgba(15,23,42,0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.profile-modal[hidden] { display: none; }
.profile-modal-card {
    width: 100%;
    max-width: 460px;
    background: #fff;
    border-radius: 16px;
    padding: 26px;
    position: relative;
    box-shadow: 0 30px 60px rgba(0,0,0,0.25);
    max-height: 92vh;
    max-height: 92dvh;
    overflow-y: auto;
}
.profile-modal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 50%;
    background: #f1f1f1;
    color: #333;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.profile-modal-close svg { width: 15px; height: 15px; }
.profile-upload-row {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 8px;
}
.profile-pic {
    width: 78px;
    height: 78px;
    border-radius: 10px;
    background: #4a4a4a;
    color: #cfcfcf;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    overflow: hidden;
    background-size: cover;
    background-position: center;
}
.profile-pic svg { width: 42px; height: 42px; }
.profile-pic.has-img svg { display: none; }
.profile-upload-btn {
    border: 0;
    border-radius: 8px;
    background: var(--brand-red, #E21B22);
    color: #fff;
    font-weight: 600;
    font-size: 0.875rem;
    padding: 11px 18px;
    cursor: pointer;
    font-family: inherit;
}
.profile-upload-btn:hover { filter: brightness(0.96); }
.profile-label {
    display: block;
    font-size: 0.875rem;
    font-weight: 700;
    color: #1f1f1f;
    margin: 14px 0 6px;
}
.profile-input {
    width: 100%;
    height: 46px;
    border: 1px solid #d6d6d6;
    border-radius: 8px;
    padding: 0 14px;
    font-size: 0.875rem;
    font-family: inherit;
    color: #1f1f1f;
    background: #fff;
}
.profile-input::placeholder { color: #b0b0b0; }
.profile-input:focus { outline: 2px solid var(--brand-red, #E21B22); border-color: transparent; }
.profile-phone {
    display: flex;
    align-items: center;
    border: 1px solid #d6d6d6;
    border-radius: 8px;
    height: 46px;
    overflow: hidden;
}
.profile-phone:focus-within { outline: 2px solid var(--brand-red, #E21B22); }
.profile-phone-cc {
    padding: 0 10px;
    font-size: 0.875rem;
    color: #1f1f1f;
    border-right: 1px solid #e5e5e5;
    white-space: nowrap;
    display: none;
    align-items: center;
    height: 100%;
}
.profile-phone-input {
    flex: 1;
    min-width: 0;
    border: 0;
    height: 100%;
    padding: 0 14px;
    font-size: 0.875rem;
    font-family: inherit;
    background: transparent;
}
.profile-phone-input:focus { outline: none; }
.profile-save {
    width: 100%;
    height: 48px;
    margin-top: 22px;
    border: 0;
    border-radius: 10px;
    background: var(--brand-red, #E21B22);
    color: #fff;
    font-weight: 700;
    font-size: 0.9375rem;
    cursor: pointer;
    font-family: inherit;
}
.profile-save:hover { filter: brightness(0.96); }
@media (max-width: 480px) {
    .profile-modal { padding: 0; align-items: flex-end; }
    .profile-modal-card { max-width: 100%; border-radius: 16px 16px 0 0; max-height: 94vh; }
}

/* ===== Outlet-details popover (Call Outlet) ===== */
.outlet-modal {
    position: fixed;
    inset: 0;
    z-index: 9500;
    background: rgba(15,23,42,0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.outlet-modal[hidden] { display: none; }
.outlet-modal-card {
    width: 100%;
    max-width: 380px;
    background: #fff;
    border-radius: 16px;
    padding: 22px;
    position: relative;
    box-shadow: 0 30px 60px rgba(0,0,0,0.25);
}
.outlet-modal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 50%;
    background: #f1f1f1;
    color: #333;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.outlet-modal-close svg { width: 15px; height: 15px; }
.outlet-modal-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
    padding-right: 28px;
}
.outlet-modal-badge {
    width: 42px;
    height: 42px;
    flex-shrink: 0;
    border-radius: 10px;
    background: var(--brand-red-soft, #fff1f1);
    color: var(--brand-red, #E21B22);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.outlet-modal-badge svg { width: 24px; height: 24px; }
.outlet-modal-title {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--text);
}
.outlet-modal-row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 9px 0;
    font-size: 0.875rem;
    color: var(--text);
    border-top: 1px solid var(--border);
}
.outlet-modal-row[hidden] { display: none; }
.outlet-modal-ico {
    flex-shrink: 0;
    color: #6a6a6a;
    display: inline-flex;
    align-items: center;
}
.outlet-modal-ico svg { width: 18px; height: 18px; }
.outlet-modal-row a { color: var(--brand-red, #E21B22); text-decoration: none; word-break: break-word; }
.outlet-modal-row a:hover { text-decoration: underline; }
.outlet-modal-call {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    height: 46px;
    margin-top: 18px;
    border-radius: 10px;
    background: var(--brand-red, #E21B22);
    color: #fff;
    font-weight: 700;
    font-size: 0.9375rem;
    text-decoration: none;
}
.outlet-modal-call[hidden] { display: none; }
.outlet-modal-call:hover { filter: brightness(0.96); }
.outlet-modal-call svg { width: 18px; height: 18px; }
@media (max-width: 480px) {
    .outlet-modal { padding: 0; align-items: flex-end; }
    .outlet-modal-card { max-width: 100%; border-radius: 16px 16px 0 0; }
}

/* Mobile header: profile avatar + the full nav strip (the hamburger is gone) */
@media (max-width: 720px) {
    /* Profile avatar — last item in the header row (relocated there by _MenuLayout's script),
       so it sits in the same row as the search field and cart pill. Scoped to .menu-header on
       purpose: still at body level (JS off / not yet run) it must stay hidden, not paint in
       page flow. */
    .menu-header .pt-profile-btn { display: inline-flex; }
    /* Nothing floats over the header's right edge any more, so no clearing inset either side. */
    .menu-header { padding-left: 12px; padding-right: 12px; }
    /* The nav strip used to be hidden here down to just the cart, because the rest of the
       navigation lived in the hamburger drawer. That drawer is gone, so the nav carries the
       navigation now — Search / Cart on mobile.
       Icon-only (labels off) so they fit a 375px header without wrapping. */
    /* flex:1 (not the old margin-left:auto hug-right) so the search field inside can grow
       to fill the row like a real field — cart stays fixed-width via its own flex:0 0 auto. */
    .menu-nav { display: inline-flex; flex: 1 1 auto; margin-left: 0; gap: 8px; min-width: 0; }
    /* Home is desktop-only. On mobile the header back button (.pt-back-btn, injected by
       _MenuLayout) owns backwards navigation, and the brand badge is still the one-tap link
       to the store landing page — a third way home just ate 34px of a 375px header. */
    .menu-nav .menu-nav-home { display: none; }
    /* Menu, Offers and Account are desktop-only. Matched on what each link IS rather than by
       position — every one of the five store pages renders this nav in the same order today,
       but nth-child would silently retarget the moment an item is added or reordered.
         Home   → /locations/{slug}        (no "/menu", so untouched)
         Menu   → /locations/{slug}/menu   — hidden
         Search → /locations/{slug}/menu?search=1, or a <button> on MenuList — kept, hence :not()
         Offers → /locations/{slug}/offers — hidden
         Account→ #account                 — hidden (the avatar in the header row,
                                             .pt-profile-btn, is the mobile way into the
                                             same panel) */
    .menu-nav .menu-nav-item[href*="/menu"]:not([href*="search"]),
    .menu-nav .menu-nav-item[href*="/offers"],
    .menu-nav .menu-nav-item[href="#account"] { display: none; }
    .menu-nav .menu-nav-item {
        flex: 0 0 auto;
        padding: 6px;
        font-size: 0;                /* drop the text label, keep the icon */
        gap: 0;
    }
    .menu-nav .menu-nav-item svg { width: 22px; height: 22px; }
    /* The NEW badge on Offers is a text pill — pointless once labels are off, and it
       overlaps the neighbouring icons at this size. */
    .menu-nav .menu-nav-new { display: none; }

    /* Search is styled as a field further down (search for "Search: a field, not a third
       icon") — that block already owned #menuSearchTrigger on mobile, so it stays the single
       owner rather than competing with a second rule here. */
    /* Same red pill as desktop, a touch more compact. (Was a 40×40 icon-only
       square with the count as an absolute corner badge.) Selector matches the base
       pill rules' specificity and wins on order. */
    .menu-nav .menu-nav-item.menu-cart-trigger {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        padding: 3px 12px 3px 3px;
        font-size: 0;                               /* hide the "Cart" label, leave icon */
    }
    .menu-nav .menu-nav-item.menu-cart-trigger svg {
        width: 26px;
        height: 26px;
        padding: 5px;
        color: var(--brand-red);
    }
    .menu-nav .menu-nav-item.menu-cart-trigger .menu-cart-count { font-size: 0.875rem; }
}

/* ============ Banner popover modal ============
   Mirrors the Flutter Flow mock: image header, title + subtitle, deal
   selection groups, footer with qty + Add to Cart. */
.banner-modal {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    z-index: 250;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.banner-modal[hidden] { display: none; }

.banner-modal-card {
    width: 100%;
    max-width: 380px;
    max-height: 92vh;
    max-height: 92dvh;
    background: #fff;
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 30px 60px rgba(0,0,0,0.28);
    position: relative;
    display: flex;
    flex-direction: column;
}

.banner-modal-close {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 0;
    background: rgba(255,255,255,0.92);
    color: var(--text);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.banner-modal-close svg { width: 16px; height: 16px; }

.banner-modal-image {
    width: 100%;
    aspect-ratio: 16 / 8;
    background-color: #fee2e2;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    flex-shrink: 0;
    overflow: hidden;
    position: relative;
}

.banner-modal-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.banner-modal-head {
    padding: 14px 18px 4px;
    flex-shrink: 0;
}

.banner-modal-title {
    margin: 0 0 4px 0;
    font-size: 1rem;
    font-weight: 700;
    color: var(--text);
}

.banner-modal-desc {
    margin: 0;
    font-size: 0.75rem;
    color: var(--muted);
    line-height: 1.4;
}

.banner-modal-body {
    padding: 10px 18px 0;
    overflow-y: auto;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.banner-modal-group {
    border-radius: 12px;
    padding: 12px 14px;
    background: #f0fdf4;
    border: 1px solid #bbf7d0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    position: relative;
}

.banner-modal-group--locked {
    background: #fafafa;
    border-color: var(--border);
}

.banner-modal-group-title {
    margin: 0;
    font-size: 0.8125rem;
    font-weight: 700;
    color: var(--text);
}

.banner-modal-group-cta {
    align-self: flex-start;
    border: 0;
    background: var(--brand-green);
    color: #fff;
    font-weight: 700;
    font-size: 0.75rem;
    padding: 6px 14px;
    border-radius: 6px;
    cursor: pointer;
    text-transform: capitalize;
}

.banner-modal-group--locked .banner-modal-group-cta {
    background: #d4d4d8;
    color: #fff;
    cursor: not-allowed;
}

.banner-modal-group-cta:hover:not(:disabled) { background: var(--brand-green-dark); }

.banner-modal-group-pizza {
    position: absolute;
    right: 12px;
    bottom: 10px;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: var(--shadow-sm);
}

.banner-modal-group-pizza svg { width: 26px; height: 26px; color: var(--brand-green); }
.banner-modal-group--locked .banner-modal-group-pizza svg { color: #c4c4c4; }

.banner-modal-foot {
    padding: 12px 18px 16px;
    border-top: 1px solid var(--border);
    background: #fff;
    flex-shrink: 0;
}

.banner-modal-name {
    font-size: 0.8125rem;
    font-weight: 700;
    margin-bottom: 8px;
    color: var(--text);
}

.banner-modal-row {
    display: flex;
    align-items: center;
    gap: 10px;
}

.banner-modal-qty {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border: 1px solid var(--brand-red);
    border-radius: 6px;
    padding: 2px;
}

.banner-modal-qty button {
    width: 24px;
    height: 24px;
    border: 0;
    border-radius: 4px;
    background: var(--brand-red);
    color: #fff;
    font-size: 0.875rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
}

.banner-modal-qty span {
    min-width: 18px;
    text-align: center;
    font-weight: 700;
    font-size: 0.8125rem;
    color: var(--text);
}

.banner-modal-add {
    flex: 1;
    height: 40px;
    border: 0;
    border-radius: 8px;
    background: #e5e7eb;
    color: #6b6b6b;
    font-weight: 700;
    font-size: 0.8125rem;
    cursor: not-allowed;
    transition: background 0.15s ease, color 0.15s ease;
}

.banner-modal-add:not(:disabled) {
    background: var(--brand-red);
    color: #fff;
    cursor: pointer;
}

.banner-modal-add:not(:disabled):hover { background: var(--brand-red-dark); }

@media (max-width: 720px) {
    .banner-modal { padding: 0; align-items: flex-end; }
    .banner-modal-card { max-width: 100%; max-height: 95vh; border-radius: 16px 16px 0 0; }
}

/* ============ Menu search overlay ============ */
.menu-search-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    z-index: 180;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: calc(var(--header-h) + 16px) 16px 16px;
}

.menu-search-card {
    width: 100%;
    max-width: 580px;
    background: #fff;
    border-radius: 14px;
    overflow: hidden;
    box-shadow: 0 24px 64px rgba(0,0,0,0.22);
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - var(--header-h) - 48px);
    animation: search-card-in 0.18s ease;
}

@keyframes search-card-in {
    from { opacity: 0; transform: translateY(-10px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0)    scale(1); }
}

/* ── Search bar ── */
.menu-search-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
    background: #fff;
}

.menu-search-icon {
    width: 18px;
    height: 18px;
    color: var(--muted);
    flex-shrink: 0;
    pointer-events: none;
}

.menu-search-input {
    flex: 1;
    border: 0;
    outline: 0;
    font-family: inherit;
    font-size: 0.9375rem;
    color: var(--text);
    background: transparent;
    min-width: 0;
    /* Remove browser default search-input decorations */
    -webkit-appearance: none;
}

.menu-search-input::placeholder { color: var(--muted); }
/* Chrome × button */
.menu-search-input::-webkit-search-cancel-button { display: none; }

.menu-search-clear-btn {
    width: 22px;
    height: 22px;
    border: 0;
    background: var(--bg-soft);
    border-radius: 50%;
    color: var(--muted);
    cursor: pointer;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.12s;
}
.menu-search-clear-btn svg { width: 12px; height: 12px; }
.menu-search-clear-btn:hover { background: #e4e4e7; }

.menu-search-close-btn {
    border: 0;
    background: transparent;
    font-family: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--brand-red);
    cursor: pointer;
    padding: 0 2px;
    flex-shrink: 0;
    white-space: nowrap;
}
.menu-search-close-btn:hover { color: var(--brand-red-dark); }

/* ── Results panel ── */
.menu-search-results {
    overflow-y: auto;
    flex: 1;
    min-height: 120px;
    scrollbar-width: thin;
    scrollbar-color: #d4d4d8 transparent;
}

.menu-search-results::-webkit-scrollbar { width: 4px; }
.menu-search-results::-webkit-scrollbar-track { background: transparent; }
.menu-search-results::-webkit-scrollbar-thumb { background: #d4d4d8; border-radius: 2px; }

.menu-search-hint,
.menu-search-empty {
    padding: 36px 20px;
    text-align: center;
    font-size: 0.8125rem;
    color: var(--muted);
    margin: 0;
}

.menu-search-empty::before {
    content: '🔍';
    display: block;
    font-size: 1.75rem;
    margin-bottom: 10px;
}

/* ── Group sections ── */
.menu-search-group + .menu-search-group {
    border-top: 1px solid var(--border);
}

.menu-search-group-label {
    padding: 10px 14px 4px;
    font-size: 0.625rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted);
    background: var(--bg-soft);
}

/* ── Result rows ── */
.menu-search-row {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border: 0;
    background: #fff;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    transition: background 0.1s;
    border-bottom: 1px solid var(--border);
}

.menu-search-row:last-child { border-bottom: 0; }
.menu-search-row:hover  { background: var(--bg-soft); }
.menu-search-row:active { background: #f0f0f0; }

.menu-search-row-thumb {
    width: 46px;
    height: 46px;
    border-radius: 10px;
    background: var(--bg-soft);
    background-image: linear-gradient(135deg, #fde68a, #fcd34d);
    background-size: cover;
    background-position: center;
    flex-shrink: 0;
    overflow: hidden;
}

.menu-search-row-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Category rows get a tinted icon background */
.menu-search-row--cat .menu-search-row-thumb {
    background-image: linear-gradient(135deg, #bbf7d0, #16a34a22);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--brand-green);
    font-size: 1.25rem;
}

.menu-search-row-info {
    flex: 1;
    min-width: 0;
}

.menu-search-row-name {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.3;
}

.menu-search-row-sub {
    font-size: 0.6875rem;
    color: var(--muted);
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.menu-search-row-chev {
    width: 16px;
    height: 16px;
    color: #c4c4c8;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.menu-search-row-chev svg { width: 16px; height: 16px; }

/* ── Card flash on scroll-to ── */
@keyframes menu-card-flash {
    0%   { box-shadow: var(--shadow-sm); outline: 2px solid transparent; }
    25%  { box-shadow: 0 0 0 4px rgba(226, 27, 34, 0.35); outline: 2px solid var(--brand-red); }
    75%  { box-shadow: 0 0 0 4px rgba(226, 27, 34, 0.15); outline: 2px solid rgba(226, 27, 34, 0.5); }
    100% { box-shadow: var(--shadow-sm); outline: 2px solid transparent; }
}

.menu-card.is-search-flash {
    animation: menu-card-flash 1.4s ease forwards;
    border-radius: 12px;
}

/* ── Search trigger visible on mobile nav ── */
#menuSearchTrigger { border: 0; background: transparent; }

@media (max-width: 720px) {
    /* ── Search: a real field, not a pill button ────────────────────────────────────────
       Mobile nav is down to Home + Search. Instead of a small grey "Search" pill that read
       as a button, this looks like the actual bordered input it opens: flex:1 to fill the
       row (see .menu-nav flex:1 above), left-inset icon, left-aligned label text.
       Two selectors because Search is two different elements: <button id="menuSearchTrigger">
       on the menu page, <a href="…?search=1"> on the store home / offers / top-ten / cart.
       This block is the SINGLE owner of the mobile search look — it sits after the
       `.menu-nav .menu-nav-item { font-size: 0 }` rule that switches every other label off,
       so it wins on order without needing !important on the type. */
    .menu-nav > #menuSearchTrigger,
    .menu-nav .menu-nav-item[href*="search"] {
        display: inline-flex !important;
        flex: 1 1 auto;
        align-items: center;
        justify-content: flex-start;
        /* Floor so a long store name (capped but still sizable) can't crush this down to a
           sliver — see .menu-store-pill's max-width cap for the other half of this fix. */
        min-width: 88px;
        height: 40px;
        padding: 0 10px 0 32px;
        gap: 0;
        font-size: 0.8125rem;
        font-weight: 400;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        border: 1.5px solid var(--border);
        border-radius: 12px;
        background: #fff;
        color: var(--muted);
        position: relative;
        transition: border-color 0.12s ease, box-shadow 0.12s ease;
    }
    .menu-nav > #menuSearchTrigger:active,
    .menu-nav .menu-nav-item[href*="search"]:active {
        border-color: var(--brand-red);
        box-shadow: 0 0 0 4px rgba(226, 27, 34, 0.12);
    }
    .menu-nav > #menuSearchTrigger svg,
    .menu-nav .menu-nav-item[href*="search"] svg {
        position: absolute;
        left: 9px;
        top: 50%;
        transform: translateY(-50%);
        width: 16px;
        height: 16px;
        color: var(--muted);
    }
}

/* Smallest phones: the labelled pill costs ~88px against a ~120px budget once the store name
   has its share, so drop back to a bare icon like Home. 360px (the common small-Android width)
   deliberately KEEPS the pill — measured, it still leaves the store name ~112px there. */
@media (max-width: 359px) {
    .menu-nav > #menuSearchTrigger,
    .menu-nav .menu-nav-item[href*="search"] {
        flex: 0 0 auto;          /* stop growing to fill the row — back to an icon circle */
        justify-content: center;
        min-width: 0;            /* drop the ≤720 field's 88px floor so this can go to 34px */
        width: 34px;
        height: 34px;
        padding: 0;
        gap: 0;
        font-size: 0;
        border: 0;
        background: transparent;
        border-radius: 50%;
    }
    .menu-nav > #menuSearchTrigger svg,
    .menu-nav .menu-nav-item[href*="search"] svg {
        position: static;        /* undo the ≤720 field's left-inset absolute icon */
        transform: none;
        width: 22px;
        height: 22px;
    }

    /* Overlay fills from just below the sticky header */
    .menu-search-overlay {
        padding-top: calc(var(--header-h) + 8px);
        padding-left: 10px;
        padding-right: 10px;
    }
    .menu-search-card {
        border-radius: 12px;
        max-height: calc(100vh - var(--header-h) - 28px);
    }
}

/* ============================================================
   Location popover (header Home / address) + Order Type modal
   ============================================================ */

.pt-loc-popover {
    position: absolute;
    z-index: 1100;
    min-width: 220px;
    background: #fff;
    border-radius: 10px;
    box-shadow: 0 12px 32px rgba(0,0,0,0.18);
    padding: 6px;
    border: 1px solid #ececec;
}
.pt-loc-popover[hidden] { display: none !important; }

.pt-loc-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    border: 0;
    background: transparent;
    color: var(--text, #1f1f1f);
    font-size: 0.8125rem;
    font-weight: 500;
    cursor: pointer;
    border-radius: 6px;
    text-decoration: none;
    text-align: left;
    font-family: inherit;
}
.pt-loc-item:hover { background: #f8f9fb; }
.pt-loc-ico {
    width: 26px;
    height: 26px;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #B32222;
    background: #fff5f4;
    flex-shrink: 0;
}
.pt-loc-ico svg { width: 16px; height: 16px; }
/* Material icon inside the popover chip — sized to match the 16px SVGs.
   The icon inherits the chip's brand-red colour from .pt-loc-ico. */
.pt-loc-ico .pt-mi { font-size: 1.125rem; color: #b32222; }

/* Two-line label for the "Change Order Type" item — main label on top,
   currently-selected order type as a smaller brand-red sub-label. */
.pt-loc-ot-text {
    display: inline-flex;
    flex-direction: column;
    line-height: 1.2;
}
.pt-loc-ot-current {
    font-size: 0.6875rem;
    color: #b32222;
    font-weight: 600;
    margin-top: 2px;
}

/* ── Order Type modal ──────────────────────────────────────── */
.pt-ordertype-modal {
    position: fixed;
    inset: 0;
    z-index: 1200;
    background: rgba(15, 23, 42, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.pt-ordertype-modal[hidden] { display: none !important; }

.pt-ordertype-card {
    position: relative;
    width: 100%;
    max-width: 420px;
    background: #fff;
    border-radius: 14px;
    padding: 24px 22px 22px;
    box-shadow: 0 24px 60px rgba(0,0,0,0.3);
}
.pt-ordertype-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: #6b7280;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.pt-ordertype-close:hover { background: #f1f5f9; color: #1f1f1f; }
.pt-ordertype-close svg { width: 18px; height: 18px; }
.pt-ordertype-title {
    margin: 0 0 18px;
    font-size: 1.25rem;
    font-weight: 700;
    color: #1f1f1f;
    text-align: center;
}
/* Shown when the outlet doesn't offer the user's saved order type. Their choice is
   preserved for other outlets — this just explains why it isn't selectable here. */
.pt-ordertype-note {
    margin: -8px 0 16px;
    padding: 10px 12px;
    border-radius: 8px;
    background: #fdf1f1;
    border: 1px solid #f3c7c7;
    color: #9b2222;
    font-size: 0.875rem;
    line-height: 1.4;
    text-align: center;
}
.pt-ordertype-note[hidden] { display: none; }
.pt-ordertype-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}
.pt-ordertype-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 12px;
    border: 1.5px solid var(--brand-red, #B32222);
    background: #fff;
    color: var(--brand-red, #B32222);
    border-radius: 8px;
    font-size: 0.9375rem;
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
    transition: filter 0.15s, transform 0.15s;
}

.pt-ordertype-btn:hover {
filter: brightness(0.93);
}

.pt-ordertype-btn svg {
width: 22px;
height: 22px;
color: var(--brand-red, #B32222);
flex-shrink: 0;
}
/* Material icons inside the red modal buttons render white (overrides .pt-mi). */
.pt-ordertype-btn .material-symbols-outlined,
.pt-ordertype-btn .material-symbols-rounded {
color: var(--brand-red, #B32222);
font-size: 1.625rem;
}
/* Selected order type — inverted look. White background with red text + red
icon makes the active choice clearly readable against the unselected red
tiles. Applies to all four buttons (Delivery / Pickup / Dine-In / InCar). */
.pt-ordertype-btn.is-active {
background: var(--brand-red, #B32222);
color: #fff;
box-shadow: 0 0 0 3px rgba(179,34,34,0.18);
transform: translateY(-1px);
}

.pt-ordertype-btn.is-active svg {
    color: #fff;
}

.pt-ordertype-btn.is-active .material-symbols-outlined,
.pt-ordertype-btn.is-active .material-symbols-rounded {
    color: #fff;
}

/* Order types not in the outlet's OrderTypesEnabled — greyed out + unclickable.
   Applies to both the modal buttons and the drawer dropdown options. */
.pt-ordertype-btn:disabled,
.pt-ordertype-btn.is-disabled,
.pt-drawer-ot-opt:disabled,
.pt-drawer-ot-opt.is-disabled {
    opacity: 0.4;
    filter: grayscale(1);
    cursor: not-allowed;
    pointer-events: none;
}

/* Bottom-sheet style on phones — slide up from the bottom edge. */
@media (max-width: 720px) {
    .pt-ordertype-modal {
        align-items: flex-end;
        padding: 0;
    }
    .pt-ordertype-card {
        max-width: 100%;
        border-radius: 16px 16px 0 0;
        padding: 22px 18px 28px;
    }
    .pt-ordertype-title { font-size: 1.375rem; }
    .pt-ordertype-btn { font-size: 1rem; padding: 12px; }
}
@media (max-width:1080px ) {
    .menu-main {
        padding: 0px 8px;   /* edge-to-edge card grid; 8px is shadow clearance, see base rule */
    }

    .menu-cat-section-subnav {
        padding: 0px 2px 4px;
    }

    .menu-subcat-section {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .menu-card-image {
        height: 143px;
    }

    .menu-card-desc {
        /* Smaller + tighter + more lines, so the space the name no longer reserves is filled
           with actual description rather than left blank. 12px/1.45 over 13px/1.55 buys two
           extra lines inside a box only ~27px taller, and most item descriptions fit whole at
           this size in a 2-up column (~22 chars a line) instead of ending in an ellipsis.
           Height and clamp MUST stay in step - the clamp truncates the text, the height reserves
           the box, and if they disagree short cards drift out of line with tall ones.
           Dial: 4 lines = 5.8em, 5 lines = 7.25em, 6 lines = 8.7em. */
        font-size: 0.75rem;
        line-height: 1.45;
        margin-top: 4px;
        -webkit-line-clamp: 5;
        height: 7.25em;             /* 5 lines x 1.45 */
    }

    .menu-card-name {
        font-size: 0.875rem;
        /* min-height REMOVED. It reserved two lines so cards stayed level, but a one-line name
           ("Cheese Pizza") then sat in a 35px box only ~17px of which was text - a visible hole
           between the name and its description, which is the gap this fixes. Card levelling is
           unaffected in practice: the grid row still stretches every card to the tallest, so the
           slack lands at the BOTTOM of a short card, reading as padding instead of as a gap in
           the middle of the copy. */
    }

    .menu-card-size {
        height: 40px;               /* keep equal to the flat-price row so all cards match */
    }
    
    /* ≤1080px: full-screen, mobile-style popup. The card fills the viewport and is the single
       scroll region — .cust-hero + .cust-fixed-head + .cust-body scroll together — while the
       close (fixed, top-right) and footer (sticky, bottom) stay pinned to the viewport. The page
       behind is already locked via JS (body overflow:hidden in PTCustomize.open). */
    .cust-overlay { padding: 0; align-items: stretch; }
    .cust-card {
        width: 100vw;
        max-width: 100vw;
        /* 100vh fallback first, 100dvh last so modern browsers track the *visible* viewport
           (footer not hidden behind mobile browser chrome). The base max-height:92vh is removed. */
        height: 100vh;
        height: 100dvh;
        max-height: none;
        margin: 0;
        border-radius: 0;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        /* block (not flex): all children stack at natural height so .cust-hero + .cust-fixed-head
           + .cust-body scroll together as the card scrolls. Flex would pin the flex-shrink:0 hero
           and head, breaking the "scroll together" requirement. */
        display: block;
    }
    /* The card is the single scroll region — the body must NOT add its own nested scrollbar. */
    .cust-body { overflow-y: visible; }
    /* Footer pinned to the viewport bottom while the content scrolls (safe-area aware). It stays
       in the flow (sticky), so it never overlaps the last form field. */
    .cust-footer {
        position: sticky;
        bottom: 0;
        z-index: 5;
        background: #fff;
        padding-bottom: calc(18px + env(safe-area-inset-bottom));
    }
    /* Close pinned to the viewport's top-right corner (full-screen card → its own corner). */
    .cust-close {
        position: fixed;
        top: 16px;
        right: 16px;
        z-index: 99999;
        box-shadow: 0 0 3px 0px var(--brand-red-dark);
        background: rgb(255 255 255);
    }
}

@media (max-width:1024px) {
    .menu-main {
        padding: 0px 8px;   /* edge-to-edge card grid; 8px is shadow clearance, see base rule */
    }

    .menu-cat-section-subnav {
        padding: 0px 2px 4px;
    }
     
    .menu-card-name {
        font-size: 0.875rem;
        /* min-height REMOVED. It reserved two lines so cards stayed level, but a one-line name
           ("Cheese Pizza") then sat in a 35px box only ~17px of which was text - a visible hole
           between the name and its description, which is the gap this fixes. Card levelling is
           unaffected in practice: the grid row still stretches every card to the tallest, so the
           slack lands at the BOTTOM of a short card, reading as padding instead of as a gap in
           the middle of the copy. */
    }

    /* .cust-card stays full-screen ≤1080px (see the 1080px block) — no max-width cap here. */
    .cust-hero {
        height: 215px;
    }
}
@media(max-width:858px) {
    .menu-btn {
        height: 31px;
        font-size: 0.6875rem;
    }
}

@media(max-width:820px) {
    .menu-btn {
        letter-spacing: 0.02em;
    }

}

@media (max-width:768px) {
    .menu-main {
        padding: 0px 8px;   /* edge-to-edge card grid; 8px is shadow clearance, see base rule */
    }

    .menu-cat-section-subnav {
        padding: 0px 2px 4px;
    }

    .menu-subcat-section {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* Home page (Recommended / Best Sellers) uses .store-grid — keep it 2-up too so the whole
       mobile range shows exactly 2 cards. Placed last so it wins over the ≤1024 (3-col) rule. */
    .store-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* .cust-card stays full-screen ≤1080px (see the 1080px block) — no max-width cap here. */
    .cust-hero {
        height: 200px;
    }
    .cust-close{

    }
}

@media (max-width: 720px) {
    .cust-card {
        max-width: 100vw;
    }
}

/* Full-screen is reserved for phones (≤425px). For 426–1080px, override the full-screen rules
   (set in the ≤1080px and ≤720px blocks above) back to the NORMAL CENTERED card, so tablets and
   small desktops get the standard popup — not an edge-to-edge sheet. This block is placed AFTER
   every full-screen source so it wins for 426–1080px; ≤425px is excluded by min-width:426. */
@media (min-width: 426px) and (max-width: 1080px) {
    .cust-overlay { padding: 24px; align-items: center; }
    .cust-card {
        width: 100%;
        max-width: 460px;
        height: auto;
        max-height: 92vh;
        max-height: 92dvh;
        margin: 0;
        border-radius: 17px;
        /* block (not flex) + overflow-y:auto → the CARD is the scroll region, so the hero
           and .cust-fixed-head stack at natural height and scroll away with the modifier
           groups instead of being pinned as flex-shrink:0 items. overflow-x computes to
           auto alongside it, so the rounded corners still clip the hero image. */
        display: block;
        overflow-y: auto;
    }
    .cust-body { overflow-y: visible; flex: none; }             /* card scrolls; no nested scrollbar */
    .cust-footer { position: sticky; bottom: 0; z-index: 5; background: #fff; }
    /* sticky + float, not absolute: an absolute child of a scroll container scrolls away.
       float keeps it out of block flow so the hero still starts at the very top. */
    .cust-close {
        position: sticky;
        top: 12px;
        right: auto;
        float: right;
        margin-right: 12px;
        z-index: 6;
    }
}

/* 721–1080px (tablet / small desktop): inside the centered card, lay the TOP section out as a
   2-column row — .cust-hero on the LEFT, .cust-fixed-head (title + description + show-more) on the
   RIGHT — with .cust-body full width below and .cust-footer pinned at the card bottom.
   FLOATS, not CSS Grid, and that choice is load-bearing: the card is a block scroll container in
   every tier (so the header scrolls away with the content), and a grid item's sticky containing
   block is its own grid area — a grid-placed footer or close button therefore cannot stay pinned,
   it scrolls off with its row. Working around that needs the footer to span every row plus a
   hardcoded body padding-bottom equal to its height. Floats reproduce the same two-column visual
   with the card as a plain block, so sticky just works. No DOM change either way. */
@media (min-width: 721px) and (max-width: 1080px) {
    .cust-card {
        width: min(85vw, 422px);
        max-width: 422px;
        height: 92vh;
        height: 92dvh;
    }
    /* Hero — fixed 142px left column; a rounded image inset 16px on all sides (equal spacing).
       The gap shows the card behind it; background-size:cover already behaves like object-fit. */
    .cust-hero {
        float: left;
        width: 142px;
        height: 136px;
        background: transparent;
    }
    .cust-hero-image { inset: 16px; border-radius: 12px; }
    .cust-hero-tag { left: 28px; bottom: 28px; }
    /* Header — the right column. margin-left clears the hero float (a flex container is its own
       formatting context, so it will not overlap the float); min-height matches the hero so the
       vertical centring has the full row to work with. */
    .cust-fixed-head {
        margin-left: 142px;
        min-height: 136px;
        display: flex;
        flex-direction: column;
        justify-content: center;
        padding: 18px 35px 18px 0;
        border-bottom: 0;
        /* Two-column header (hero LEFT / text RIGHT) can't host a pinned full-width top bar,
           so this tier opts out of the sticky name — the header scrolls with the content. */
        position: static;
    }
    /* No padding-right for the close button any more: the head is a flex container, so it is
       its own formatting context and shrinks away from the floated close instead of running
       under it. The button can no longer overlap the title, so the reserved 36px is dead space. */
    .cust-fixed-head .cust-title { margin: 0 0 8px; font-size: 1.1875rem; }
    .cust-fixed-head .cust-desc  { margin: 0 0 12px; font-size: 0.75rem; line-height: 1.5; }
    .cust-fixed-head .cust-desc-toggle { margin-top: 4px; align-self:flex-start; }
    /* Body — full width below the header row; `clear` drops it past the hero float. */
    .cust-body { clear: both; border-top: 1px solid var(--border); }
    .cust-footer { padding: 16px; }
}

@media (max-width:425px) {
    .menu-subcat-section {
        grid-template-columns: repeat(2, minmax(0, 1fr));   /* 2 cards per row on phones */
        column-gap: 12px;
    }

    .menu-cat-section-subnav {
        padding: 10px 2px 4px;
    }

    /* Store name stays visible as TEXT at every mobile width now (the old icon-only ≤425
       mode is gone — the redesigned header shows the selected store name + a red caret). */
    .menu-store-name-m {
        display: inline;
    }
    .menu-store-addr-link,
    .menu-store-ot-btn {
        /* 0 1 auto, not 0 0 auto. flex-shrink:0 stopped this pill shrinking, so a long store
           name ("Sacramento CA (Gateway Park)") rendered at its full intrinsic width and
           painted straight over the nav — the ellipsis on .menu-store-name-m could never
           fire, defeating the min-width:0 that .menu-store-link sets for exactly this. */
        flex: 0 1 auto;
        min-width: 0;
        padding: 5px 8px;
        gap: 0;
    }
    /* Claw back the ~20px the two pills need on a 320px screen. The 54px padding-left here
       was clearance for the hamburger, which is gone — reclaiming it gives the nav strip the
       room it needs to fit six icons at 320px. */
    .menu-header { column-gap: 6px; padding-left: 10px; }
    .menu-brand img { height: 38px; }   /* circular badge — the primary logo, a bit bigger */

    .cust-body {
        min-height: 47vh;
    }

}
/* ── Delete-account confirmation ─────────────────────────────────────────────────
   Sits above the account drawer (which is z-index 1200 territory), because it is opened FROM
   that drawer and must not appear behind it. Styling stays deliberately plain and text-heavy:
   this dialog exists to be read, not to look inviting. */
.pt-del-overlay {
    position: fixed;
    inset: 0;
    z-index: 100000;
    background: rgba(0, 0, 0, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.pt-del-overlay[hidden] { display: none; }

.pt-del-card {
    width: 100%;
    max-width: 440px;
    max-height: 90vh;
    max-height: 90dvh;
    overflow-y: auto;
    background: #fff;
    border-radius: 16px;
    padding: 24px;
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.3);
}

.pt-del-title { margin: 0 0 12px; font-size: 1.35rem; font-weight: 800; color: var(--text); }

/* The irreversibility warning is the most important line in the dialog — given the brand red
   and its own tinted block so it can't be skimmed past. */
.pt-del-warn {
    margin: 0 0 14px;
    padding: 12px 14px;
    border-radius: 10px;
    background: var(--brand-red-soft);
    border: 1px solid var(--brand-red);
    color: #7f1218;
    font-size: 0.9rem;
    line-height: 1.5;
}
.pt-del-warn strong { display: block; margin-bottom: 2px; color: var(--brand-red); }

.pt-del-list { margin: 0 0 14px; padding-left: 20px; color: var(--muted); font-size: 0.875rem; line-height: 1.7; }
.pt-del-note { margin: 0 0 18px; font-size: 0.8125rem; color: var(--muted); line-height: 1.5; }

.pt-del-label { display: block; margin-bottom: 6px; font-size: 0.8125rem; font-weight: 700; color: var(--text); }
.pt-del-input {
    width: 100%;
    padding: 11px 13px;
    border: 1.5px solid var(--border);
    border-radius: 10px;
    font-family: inherit;
    font-size: 0.95rem;
    letter-spacing: 1px;
}
.pt-del-input:focus { outline: none; border-color: var(--brand-red); }

.pt-del-error { margin: 10px 0 0; font-size: 0.8125rem; color: var(--brand-red); }
.pt-del-error[hidden] { display: none; }

.pt-del-actions { display: flex; gap: 10px; margin-top: 20px; }
.pt-del-btn {
    flex: 1;
    padding: 12px 14px;
    border-radius: 10px;
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 700;
    cursor: pointer;
    border: 1.5px solid transparent;
}
/* "Keep my account" is the safe path, so it gets the visual weight. */
.pt-del-btn--ghost  { background: var(--text); color: #fff; }
.pt-del-btn--danger { background: #fff; color: var(--brand-red); border-color: var(--brand-red); }
.pt-del-btn--danger:hover:not(:disabled) { background: var(--brand-red); color: #fff; }
.pt-del-btn:disabled { opacity: 0.45; cursor: not-allowed; }

@media (max-width: 425px) {
    .pt-del-card { padding: 20px 16px; }
    .pt-del-actions { flex-direction: column-reverse; }   /* safe option ends up on top */
}

/* The "Save as your default store?" prompt bar was removed from _MenuLayout; its
   rules went with it. The .pt-drawer-link--btn rule below styled the drawer's
   "Make this my default store" button, which this layout no longer renders — it is
   kept because the button is the obvious place to restore the feature. */

/* "Make this my default store" is a <button> in a list of <a>s — strip the UA
   button chrome so it sits flush with its neighbours. */
.pt-drawer-link--btn {
    width: 100%;
    background: none;
    border: 0;
    font: inherit;
    font-size: 0.8125rem;
    text-align: left;
    cursor: pointer;
}

/* ── Free-item nudge (offer-autofree.js) ──────────────────────────────────────
   Shown when an offer has unlocked but still needs a choice from the customer —
   several candidate items, or a required option group with no default. Green
   rather than the red of .offer-unlock: that one says "you cannot have this
   yet", this one says "you can, come and get it".

   Lives in menu.css because _MenuLayout loads this file on every page that can
   raise the banner (Cart, Menu, MenuList, Offers); cart.css would cover only one.
   The element is created by JS, so there is nothing to style until it appears. */
.pt-free-nudge {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 12px 0;
    padding: 10px 14px;
    border: 1px solid var(--brand-green);
    border-radius: 10px;
    background: #f0fdf4;
}

.pt-free-nudge[hidden] { display: none; }

.pt-free-nudge-text {
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--brand-green-dark);
}

.pt-free-nudge-btn {
    flex: 0 0 auto;
    border: 0;
    border-radius: 8px;
    padding: 8px 14px;
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 700;
    color: #fff;
    background: var(--brand-green);
    cursor: pointer;
}

.pt-free-nudge-btn:hover { background: var(--brand-green-dark); }
