/* Est Est Est Pizza — menu preview
   Premium but light: no scroll-jacking, no frame sequences, motion is
   micro-interaction only. Everything here is CSS; total page weight is a
   few KB so it stays fast on mobile data. */

/* Tokens now live in /tokens.css — see packages/design-tokens/tokens.css.
   These values were the canonical ones and became the shared scale, so this
   block is simply gone rather than aliased. Nothing below changes. */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 16px/1.5 ui-sans-serif, -apple-system, "Segoe UI", Inter, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

body { overflow-x: hidden; }
body.locked { overflow: hidden; }

/* ---------------------------------------------------------- bottom nav
   Installed PWA, three real destinations (Menu, Track, Account), and until
   now the only way between them was one "Account" text link in the topbar —
   Track wasn't reachable from chrome at all. A persistent tab bar is the
   standard PWA pattern for exactly this shape of app. Markup is duplicated
   per page (this repo has no templating), with the active tab hardcoded
   per file. --bottom-nav-h lets each page's own bottom padding clear it. */
:root { --bottom-nav-h: 64px; }
/* On a desktop the site header and the footer already carry every one of
   these destinations, and the tab bar was a phone pattern pinned over a
   1400px page. It appears where the ordering layout stacks (980px). */
@media (min-width: 981px) {
  :root { --bottom-nav-h: 0px; }
  .bottom-nav { display: none; }
}

.bottom-nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  display: flex;
  height: calc(var(--bottom-nav-h) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: rgba(251,247,240,.94);
  -webkit-backdrop-filter: blur(14px); /* Safari only took this unprefixed at 18 */
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--line-soft);
}
.bn-tab {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; min-height: 44px;
  color: var(--ink-faint); text-decoration: none;
  font-size: var(--text-xs); letter-spacing: .02em; font-weight: 600; /* 12px floor (audit 2026-09-25) */
}
.bn-tab svg { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 1.7; }
.bn-tab.is-active { color: var(--accent-text); }

/* Display face on headings and the brand mark. Until now every heading on
   the customer-facing site rendered in the system sans — the same face as a
   settings dialog — while the internal admin had a real serif. For a shop
   that has been on the same corner since 1973, the typography is most of
   what separates 'a form' from 'a restaurant'.

   Body copy stays on the system stack: it is faster, and a long menu is
   easier to scan in a sans. Operational apps (POS, driver) load no web font
   at all — see packages/design-tokens/tokens.css for why. */
h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-semi);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
}
button { font: inherit; color: inherit; cursor: pointer; }

/* ------------------------------------------------------------ site header
   The header markup and its look come from home.css (.home-header, .home-nav,
   .brand-mark) so it is pixel-identical to the homepage's. The homepage
   FIXES it over a full-bleed hero; these pages have no hero, so here it
   sits in the flow and sticks -- and below 900px, where it is two rows tall
   (nav wraps under the brand), it scrolls away with the page so a phone is
   not paying ~110px of every screen for links it can reach by scrolling up.
   The controls that must stay reachable on the ordering page move into
   .orderbar at that width (app.js, placeOrderControls).

   Offsets for everything that sticks beneath are measured, not guessed:
   app.js writes --hdr-h and --bar-h on <html> from the real rendered heights,
   so the category rail and the cart never sit under the header by a few px
   after a font loads or the nav wraps. */
.site-header { position: sticky; }
.header-actions { display: flex; align-items: center; gap: var(--space-10); }
/* Once app.js has moved the controls to the bar (it sets this class), the
   slot must not hold a header row open with nothing visible in it. */
.controls-in-bar .header-actions { display: none; }

.orderbar {
  position: sticky; top: 0; z-index: 36;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-8);
  padding: var(--space-10) var(--space-22);
  background: rgba(251,247,240,.94);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
}
.orderbar[hidden] { display: none; }

@media (max-width: 900px) {
  .site-header { position: static; }
  /* Account is in the bottom tab bar on this page; a second door in the
     header row would cost the space the Pickup/Delivery control needs. */
  .header-account { display: none; }
}

.seg { display: flex; padding: 3px; background: var(--bg-raised); border: 1px solid var(--line); border-radius: 999px; }
.seg-btn {
  border: 0; background: transparent; color: var(--ink-dim);
  padding: 7px 15px; border-radius: 999px; font-size: var(--text-sm); font-weight: 500;
  transition: color .18s var(--ease), background .18s var(--ease);
}
.seg-btn.is-active { background: var(--accent); color: var(--ink-onAccent); }

.cart-toggle {
  display: flex; align-items: center; gap: 9px;
  background: var(--bg-raised); border: 1px solid var(--line);
  padding: 9px 15px; border-radius: 999px; font-size: var(--text-sm); font-weight: 500;
  transition: border-color .18s var(--ease);
}
.cart-toggle:hover { border-color: var(--line-strong); }
.cart-count {
  min-width: 21px; height: 21px; padding: 0 var(--space-6);
  display: grid; place-items: center;
  background: var(--accent); color: var(--ink-onAccent);
  border-radius: 999px; font-size: var(--text-xs); font-weight: 600;
}

/* ------------------------------------------------------------- searchbar */
.searchbar { padding: var(--space-10) var(--space-22); background: var(--bg); }
.searchbar input {
  width: 100%; background: var(--bg-card); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  /* 40px before min-height: search is the fastest route to an item on a
     100-item menu, and it is tapped, not clicked. */
  min-height: 44px;
  padding: 11px var(--space-14); font-size: var(--text-ui);
}
.searchbar input::placeholder { color: var(--ink-faint); }
.searchbar input:focus { outline: none; border-color: var(--accent); }

/* A category jumped to from the rail must land below the sticky chrome, whose
   height is measured (see .site-header above). home.css sets a generic 84px
   scroll padding for the homepage's fixed header; the measured margin
   replaces it here. */
html { scroll-padding-top: 0; }
[data-cat-section] { scroll-margin-top: calc(var(--hdr-h, 0px) + var(--bar-h, 0px) + var(--cat-h, 0px) + var(--space-12)); }

/* --------------------------------------------------------------- catnav */
.catnav {
  position: sticky; top: calc(var(--hdr-h, 0px) + var(--bar-h, 0px)); z-index: 30;
  display: flex; gap: 7px; overflow-x: auto; scrollbar-width: none;
  padding: var(--space-12) var(--space-22);
  background: rgba(251,247,240,.94);
  -webkit-backdrop-filter: blur(14px); /* Safari only took this unprefixed at 18 */
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
}
.catnav::-webkit-scrollbar { display: none; }
/* Underline tabs in the display face, not a hard white-on-dark pill — a
   category is a heading you're browsing under, not a toggle you've pressed.
   The pill was the most generic control on the page, and it was the single
   most visible difference between this menu and the storefront's. Sizing
   comes off the type scale rather than a hardcoded 13px. */
.catnav button {
  flex: 0 0 auto; position: relative; border: 0; background: transparent;
  color: var(--ink-dim); padding: 7px var(--space-4); margin: 0 var(--space-8);
  font: var(--weight-semi) var(--text-md)/1 var(--font-display);
  white-space: nowrap;
  transition: color .18s var(--ease);
}
.catnav button::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -8px;
  height: 2px; background: var(--accent); border-radius: 999px;
  transform: scaleX(0); transition: transform .18s var(--ease);
}
.catnav button:hover { color: var(--ink); }
.catnav button.is-active { color: var(--ink); }
.catnav button.is-active::after { transform: scaleX(1); }

/* --------------------------------------------------------------- layout */
.layout {
  max-width: var(--maxw); margin: 0 auto;
  padding: 26px 22px calc(64px + var(--bottom-nav-h) + env(safe-area-inset-bottom, 0px));
  display: grid; grid-template-columns: 1fr 348px; gap: 26px; align-items: start;
}

.cat-title {
  grid-column: 1 / -1;
  margin: 26px 0 var(--space-4); font-size: var(--text-sm); letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-faint);
}
.cat-title:first-child { margin-top: 0; }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(252px, 1fr)); gap: var(--space-12); }

/* ---------------------------------------------------------------- cards */
.card {
  position: relative; text-align: left;
  background: var(--bg-card); border: 1px solid var(--line-soft);
  border-radius: var(--radius); padding: 0; overflow: hidden;
  display: flex; flex-direction: column; min-height: 116px;
  transition: transform .18s var(--ease), border-color .18s var(--ease), background .18s var(--ease);
}
.card:hover { transform: translateY(-2px); border-color: var(--line-strong); background: var(--bg-card-hi); }
.card:active { transform: translateY(0); }
.card:disabled { opacity: .45; cursor: not-allowed; transform: none; }

.card-body { display: flex; flex-direction: column; gap: 7px; padding: var(--space-16); flex: 1; }

/* Fixed aspect box so lazy-loaded photos cannot shift the grid. */
.thumb {
  display: block; position: relative; width: 100%; aspect-ratio: 3 / 2;
  background: var(--bg-card); overflow: hidden;
}
.thumb img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .3s var(--ease);
}
.card:hover .thumb img { transform: scale(1.035); }
/* Blend the photo into the card so it doesn't read as a pasted rectangle. */
.thumb::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to bottom, transparent 55%, rgba(27,23,20,.85) 100%);
}

.card h3 { font-size: var(--text-base); line-height: 1.3; }
.card p {
  text-wrap: balance;
  margin: 0; font-size: var(--text-xs); color: var(--ink-faint); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.card .price { margin-top: auto; font-size: var(--text-ui); font-weight: 600; color: var(--accent-text); }
.card .from { font-size: var(--text-xs); color: var(--ink-faint); font-weight: 400; }
.card .leader { display: none; }

/* --------------------------------------------------- compact (no photo)
   A text-only item — a $2 Coke, a side of dressing — used to get the exact
   same 116px+ photo-card treatment as a full dish, with an empty box where
   the image would be. Twenty items on the live menu are in that state, so
   this was not a rare edge: whole runs of the drinks and sides categories
   rendered as blank tiles between photographed ones.

   This is a printed-menu row instead: name, dotted leader, price, on one
   line, full width instead of sharing the photo grid's 252px columns. It
   also happens to be the right answer for the brand — a leader row is how
   an Italian menu has set its drinks list for a century, so the fallback
   reads as deliberate typography rather than as a missing image.

   Ported from apps/menu-preview so both storefronts render one card system;
   keep the two in step until Phase 2 collapses them onto this app. */
.card:not(.has-img) {
  grid-column: 1 / -1;
  flex-direction: row;
  min-height: 44px;
}
.card:not(.has-img) .card-body {
  flex-direction: row; flex-wrap: wrap; align-items: baseline;
  gap: var(--space-2) 0; padding: 11px var(--space-16);
}
.card:not(.has-img) h3 { flex: 0 0 auto; order: 1; }
.card:not(.has-img) .leader {
  display: block; order: 2; flex: 1 1 20px; align-self: center;
  min-width: 16px; margin: 0 var(--space-10); height: 0;
  border-bottom: 1px dotted var(--line-strong);
}
.card:not(.has-img) .price { order: 3; margin-top: 0; white-space: nowrap; }
.card:not(.has-img) p,
.card:not(.has-img) .tag { order: 4; flex-basis: 100%; }
.card:not(.has-img) .badge { position: static; order: 0; flex-basis: 100%; margin-bottom: var(--space-2); }

.badge {
  position: absolute; top: 12px; right: 12px;
  font-size: var(--text-xs); letter-spacing: .08em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 5px;
  background: var(--danger-tint); color: var(--danger); border: 1px solid var(--danger-edge);
}
.tag {
  align-self: flex-start; font-size: var(--text-xs); letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-faint);
  border: 1px solid var(--line); border-radius: 5px; padding: var(--space-2) var(--space-6);
}

/* ----------------------------------------------------------------- cart */
.cart {
  position: sticky; top: calc(var(--hdr-h, 0px) + var(--cat-h, 0px) + var(--space-16));
  background: var(--bg-raised); border: 1px solid var(--line);
  border-radius: var(--radius); display: flex; flex-direction: column;
  max-height: calc(100vh - var(--hdr-h, 0px) - var(--cat-h, 0px) - var(--space-32));
  /* The whole panel scrolls, not just the list of lines. The foot (promo,
     totals, gift card, contact, payment, the Checkout button) is ~730px on
     its own, so on a 768px laptop screen it alone exceeded the panel: the
     lines flexed down to 16px and vanished, and the foot spilled out of the
     panel's bottom edge. Found in the 2026-09-18 audit with one item in the
     cart. */
  overflow-y: auto; overscroll-behavior: contain;
}
.cart-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-16) var(--space-18); border-bottom: 1px solid var(--line-soft);
  /* Stays put while the panel scrolls so the close control is always there
     on the phone, where the cart is full-screen. */
  position: sticky; top: 0; z-index: 1; background: var(--bg-raised);
}
.cart-head h2 { font-size: var(--text-ui); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-dim); }
.cart-head .icon-btn { display: none; }

.cart-body { padding: var(--space-8); flex: 1 0 auto; }
.cart-empty { padding: 34px var(--space-18); text-align: center; color: var(--ink-faint); font-size: var(--text-sm); }

.line { padding: var(--space-12); border-radius: var(--radius-sm); display: grid; gap: 5px; }
.line + .line { border-top: 1px solid var(--line-soft); }
.line-top { display: flex; justify-content: space-between; gap: var(--space-12); align-items: baseline; }
.line-name { font-size: var(--text-ui); font-weight: 500; }
.line-name em { font-style: normal; color: var(--ink-faint); font-weight: 400; }
.line-price { font-size: var(--text-ui); font-weight: 600; white-space: nowrap; }
.line-mods { font-size: var(--text-xs); color: var(--ink-faint); line-height: 1.6; }
.line-mods span { display: block; }
.line-actions { display: flex; gap: var(--space-12); margin-top: 3px; }
.line-actions button {
  background: none; border: 0; padding: 0; font-size: var(--text-xs);
  color: var(--ink-faint); text-decoration: underline; text-underline-offset: 3px;
}
.line-actions button:hover { color: var(--accent); }

.cart-foot { border-top: 1px solid var(--line-soft); padding: var(--space-16) var(--space-18); display: grid; gap: 9px; }
.row { display: flex; justify-content: space-between; font-size: var(--text-sm); color: var(--ink-dim); }
.row.total { font-size: var(--text-lead); font-weight: 700; color: var(--ink); padding-top: 9px; border-top: 1px solid var(--line-soft); }
.warn { font-size: var(--text-xs); color: var(--accent-2); background: var(--warn-tint); border: 1px solid var(--warn-edge); padding: 9px 11px; border-radius: var(--radius-sm); }
.row.discount span:last-child { color: var(--good); }
.row s { color: var(--ink-faint); margin-right: 5px; }

/* ---- promo codes */
.promo { display: flex; gap: var(--space-6); }
.promo input {
  flex: 1; min-width: 0; background: var(--bg-card); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 9px 11px; font-size: var(--text-sm); text-transform: uppercase;
}
.promo input::placeholder { color: var(--ink-faint); text-transform: none; }
.promo input:focus { outline: none; border-color: var(--accent); }
.promo button {
  background: var(--bg-card); border: 1px solid var(--line); color: var(--ink-dim);
  border-radius: var(--radius-sm); padding: 9px var(--space-14); font-size: var(--text-sm); font-weight: 500;
  transition: color .16s var(--ease), border-color .16s var(--ease);
}
.promo button:hover { color: var(--ink); border-color: var(--line-strong); }

.promo-on, .promo-bad {
  display: flex; align-items: center; gap: var(--space-8);
  font-size: var(--text-xs); padding: var(--space-8) 11px; border-radius: var(--radius-sm);
}
.promo-on {
  background: var(--ok-tint); border: 1px solid var(--ok-edge); color: var(--ink-dim);
}
.promo-on strong { color: var(--ok); letter-spacing: .04em; }
.promo-val { margin-left: auto; color: var(--ok); font-weight: 600; font-variant-numeric: tabular-nums; }
.promo-bad { background: var(--warn-tint); border: 1px solid var(--warn-edge); color: var(--accent-2); }
.promo-x {
  margin-left: auto; flex: 0 0 auto; background: none; border: 0;
  color: inherit; opacity: .6; font-size: var(--text-md); line-height: 1; padding: 0 var(--space-2);
}
.promo-x:hover { opacity: 1; }

/* ---- contact & loyalty */
.contact-form { display: grid; gap: 7px; padding: var(--space-12) 0 var(--space-4); }
.contact-form input {
  width: 100%; min-width: 0; background: var(--bg-card); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: var(--space-10) var(--space-12); font-size: var(--text-ui);
}
.contact-form input:focus { outline: none; border-color: var(--accent); }
.contact-form input::placeholder { color: var(--ink-faint); }

.ck { display: flex; gap: 9px; align-items: flex-start; font-size: var(--text-xs); color: var(--ink-faint); line-height: 1.45; }
.ck input { width: 16px; height: 16px; flex: 0 0 auto; margin-top: 1px; accent-color: var(--accent); }

.loy {
  background: var(--accent-tint); border: 1px solid var(--accent-edge); border-radius: var(--radius-sm);
  padding: 11px 13px; display: grid; gap: 7px;
}
.loy-top { display: flex; justify-content: space-between; align-items: baseline; }
.loy-tier {
  font-size: var(--text-xs); letter-spacing: .1em; text-transform: uppercase;
  font-weight: 700; color: var(--gold);
}
.loy-bal { font-size: var(--text-base); font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.loy-bar { height: 5px; border-radius: 999px; background: var(--data-track); overflow: hidden; }
.loy-bar i { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.loy-next { font-size: var(--text-xs); color: var(--ink-faint); }
.loy-redeem {
  display: flex; gap: 9px; align-items: center; font-size: var(--text-sm); color: var(--ink-dim);
  padding-top: 3px; cursor: pointer;
}
.loy-redeem input { width: 17px; height: 17px; accent-color: var(--accent); }

/* ---- address form */
.addr-form { display: grid; gap: 7px; padding: var(--space-12) 0 var(--space-4); }
.addr-title {
  font-size: var(--text-xs); letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-faint); margin-bottom: var(--space-2);
}
.addr-form input {
  width: 100%; min-width: 0; background: var(--bg-card); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: var(--space-10) var(--space-12); font-size: var(--text-ui);
}
.addr-form input:focus { outline: none; border-color: var(--accent); }
.addr-form input::placeholder { color: var(--ink-faint); }
.addr-row { display: grid; grid-template-columns: 1fr 62px 88px; gap: var(--space-6); }
.addr-row input:nth-child(2) { text-transform: uppercase; text-align: center; }
.fe { font-size: var(--text-xs); color: var(--danger-on-tint); }

.saved-addrs { display: grid; gap: var(--space-6); margin-bottom: var(--space-4); }
.saved-addr-row { display: flex; gap: var(--space-6); align-items: stretch; }
.saved-addr {
  flex: 1; min-width: 0; text-align: left; background: var(--bg-card);
  border: 1px solid var(--line); color: var(--ink-dim); border-radius: var(--radius-sm);
  padding: var(--space-10) var(--space-12); font-size: var(--text-sm); line-height: 1.4;
  transition: color .16s var(--ease), border-color .16s var(--ease);
}
.saved-addr:hover { color: var(--ink); border-color: var(--line-strong); }
.saved-addr-remove {
  flex: 0 0 auto; width: 36px; background: var(--bg-card); border: 1px solid var(--line);
  color: var(--ink-faint); border-radius: var(--radius-sm); font-size: var(--text-md); line-height: 1;
  transition: color .16s var(--ease), border-color .16s var(--ease);
}
.saved-addr-remove:hover { color: var(--danger); border-color: var(--danger-edge); }
.saved-addr-remove:disabled { opacity: .5; pointer-events: none; }

.addr-check {
  background: var(--bg-card); border: 1px solid var(--line); color: var(--ink-dim);
  border-radius: var(--radius-sm); padding: var(--space-10); font-size: var(--text-sm); font-weight: 600;
  transition: color .16s var(--ease), border-color .16s var(--ease);
}
.addr-check:hover { color: var(--ink); border-color: var(--line-strong); }
.addr-check:disabled { opacity: .6; pointer-events: none; }

.addr-ok, .addr-bad { font-size: var(--text-xs); padding: 9px 11px; border-radius: var(--radius-sm); }
.addr-ok {
  background: var(--ok-tint); border: 1px solid var(--ok-edge); color: var(--ink-dim);
}
.addr-ok span { display: block; color: var(--ok); font-size: var(--text-xs); margin-top: var(--space-2); }
.addr-bad { background: var(--warn-tint); border: 1px solid var(--warn-edge); color: var(--accent-2); }

/* ---- checkout */
.primary.checkout { margin-top: var(--space-4); width: 100%; }
.pay-mode {
  margin: 0; text-align: center; font-size: var(--text-xs); color: var(--ink-faint);
  letter-spacing: .03em;
}
.pay-mode.is-live { color: var(--accent-2); font-weight: 600; }

.result { text-align: center; padding: 26px var(--space-6) var(--space-12); }
.result-mark {
  width: 54px; height: 54px; margin: 0 auto var(--space-16); border-radius: 999px;
  display: grid; place-items: center; font-size: var(--text-2xl); font-weight: 700;
}
.result.is-ok .result-mark  { background: var(--ok-tint); color: var(--ok);       border: 1px solid var(--ok-edge); }
.result.is-bad .result-mark { background: var(--danger-tint); color: var(--danger); border: 1px solid var(--danger-edge); }
.result p { margin: var(--space-6) 0; font-size: var(--text-ui); color: var(--ink-dim); line-height: 1.5; }
.result.is-ok p:first-of-type { color: var(--ink); font-weight: 500; }
.track-link {
  display: inline-block; margin-top: var(--space-16); padding: var(--space-12) var(--space-22);
  border: 1px solid var(--line); border-radius: 999px;
  color: var(--accent-text); text-decoration: none; font-size: var(--text-ui); font-weight: 600;
  transition: border-color .16s var(--ease);
}
.track-link:hover { border-color: var(--accent); }

/* ---------------------------------------------------------------- sheet */
.scrim {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(6,5,4,.72);
  -webkit-backdrop-filter: blur(3px); /* Safari only took this unprefixed at 18 */
  backdrop-filter: blur(3px);
  animation: fade .18s var(--ease);
}
@keyframes fade { from { opacity: 0 } }

.sheet {
  position: fixed; z-index: 60;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(620px, calc(100vw - 32px)); max-height: min(86vh, 860px);
  background: var(--bg-raised); border: 1px solid var(--line);
  border-radius: 18px; display: flex; flex-direction: column; overflow: hidden;
  box-shadow: var(--shadow-pop);
  animation: pop .22s var(--ease);
}
/* `.sheet[hidden]` ties the browser's built-in `[hidden]{display:none}` on
   specificity, and being later in the cascade the class rule above was
   winning outright — the panel rendered `display:flex` even with the
   `hidden` attribute set, permanently covering the menu. An
   attribute-selector override has higher specificity than either, so it
   wins regardless of source order. */
.sheet[hidden] { display: none; }
@keyframes pop {
  from { opacity: 0; transform: translate(-50%, calc(-50% + 12px)) scale(.985); }
}

.sheet-head {
  display: flex; justify-content: space-between; gap: var(--space-16); align-items: flex-start;
  padding: var(--space-20) var(--space-22) var(--space-16); border-bottom: 1px solid var(--line-soft);
}
.sheet-head h2 { font-size: var(--text-lg); }
.sheet-head p { margin: var(--space-6) 0 0; font-size: var(--text-sm); color: var(--ink-faint); line-height: 1.5; }

.icon-btn {
  flex: 0 0 auto; width: 32px; height: 32px; display: grid; place-items: center;
  background: transparent; border: 1px solid var(--line); border-radius: 8px;
  font-size: var(--text-lg); line-height: 1; color: var(--ink-dim);
  transition: border-color .18s var(--ease), color .18s var(--ease);
}
.icon-btn:hover { color: var(--ink); border-color: var(--line-strong); }

.sheet-body { overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: var(--space-6) var(--space-22) var(--space-18); }

/* .sheet-photo, not .hero: order.html also loads home.css, whose .hero is
   the full-screen homepage banner (100svh, 150px top padding on phones) --
   the shared name blew the dish photo up to fill the screen. */
/* 12 of the 84 photos are portrait. A cover-crop hero guillotines them, so
   the image is CONTAINED over a blurred copy of itself — nothing is cropped,
   and the frame still fills. The blurred layer reuses the same cached file,
   so it costs no extra request. */
.sheet-photo {
  position: relative; margin: var(--space-10) calc(-1 * var(--space-22)) 0; height: min(36vh, 300px); overflow: hidden;
  background: var(--bg-raised);
}
.sheet-photo::before {
  content: ''; position: absolute; inset: 0;
  background-image: var(--img); background-size: cover; background-position: center;
  filter: blur(30px) saturate(1.25) brightness(.55);
  transform: scale(1.2);
}
/* Phones: the photo must never push the choices off the first screen. */
@media (max-width: 560px) { .sheet-photo { height: min(30vh, 220px); } }
.sheet-photo img {
  position: relative; width: 100%; height: 100%; object-fit: contain; display: block;
}
/* Settle the still into the sheet rather than sitting it on top. */
.sheet-photo::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to bottom, rgba(22,19,15,.3) 0%, transparent 26%, rgba(22,19,15,.92) 100%);
}

.group { padding: 17px 0; border-bottom: 1px solid var(--line-soft); }
.group:last-child { border-bottom: 0; }
.group-head { display: flex; align-items: baseline; gap: 9px; margin-bottom: 11px; flex-wrap: wrap; }
.group-head h3 { font-size: var(--text-ui); }
.rule { font-size: var(--text-xs); color: var(--ink-faint); letter-spacing: .04em; }
.rule.req { color: var(--accent-2); }

.opts { display: grid; gap: var(--space-6); }
.opt {
  display: flex; align-items: center; gap: 11px;
  padding: var(--space-10) var(--space-12); border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--bg); cursor: pointer;
  transition: border-color .16s var(--ease), background .16s var(--ease);
}
.opt:hover { border-color: var(--line-strong); }
.opt.is-on { border-color: var(--accent); background: var(--accent-tint); }
.opt.is-off { opacity: .4; cursor: not-allowed; }
.opt input { accent-color: var(--accent); width: 16px; height: 16px; flex: 0 0 auto; cursor: pointer; }
.opt-name { flex: 1; font-size: var(--text-sm); }
.opt-price { font-size: var(--text-xs); color: var(--ink-dim); font-variant-numeric: tabular-nums; }

/* Kitchen instructions, straight under the photo. */
.kitchen-note { padding: var(--space-14, 14px) 0 var(--space-4); }
.note-label { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; font-size: var(--text-ui); font-weight: 600; color: var(--ink); }
.note-label .rule { font-weight: 400; margin-left: auto; }
.note-pencil { flex: 0 0 auto; color: var(--accent-2); }
.kitchen-note textarea {
  display: block; width: 100%; min-height: 76px; resize: vertical; box-sizing: border-box;
  padding: var(--space-10) var(--space-12); border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg); color: var(--ink); font: inherit; font-size: var(--text-sm); line-height: 1.45;
}
.kitchen-note textarea::placeholder { color: var(--ink-faint); }
.kitchen-note textarea:focus { outline: none; border-color: var(--accent); }
.line-note { display: flex; gap: 7px; align-items: flex-start; margin-top: 4px; font-size: var(--text-xs); color: var(--ink-dim); line-height: 1.5; overflow-wrap: anywhere; }
.line-note .note-pencil { margin-top: 2px; width: 13px; height: 13px; }

.opt-extra { display: flex; gap: var(--space-6); align-items: center; padding: 0 var(--space-12) var(--space-10) 39px; margin-top: calc(-1 * var(--space-4)); }
.pill {
  border: 1px solid var(--line); background: transparent; color: var(--ink-faint);
  font-size: var(--text-xs); padding: var(--space-4) 9px; border-radius: 999px;
  transition: all .16s var(--ease);
}
.pill:hover { color: var(--ink); }
.pill.is-on { background: var(--accent); border-color: var(--accent); color: var(--ink-onAccent); }
.mini-qty { display: flex; align-items: center; gap: 7px; margin-left: auto; font-size: var(--text-xs); color: var(--ink-dim); }
.mini-qty button {
  width: 22px; height: 22px; border-radius: 6px; border: 1px solid var(--line);
  background: transparent; display: grid; place-items: center; line-height: 1;
}
.mini-qty button:hover { border-color: var(--line-strong); }
/* The +1 / -1 on salad extras, dressings and wings is used a lot: finger-sized on touch screens. */
@media (pointer: coarse), (max-width: 700px) {
  .mini-qty { gap: 10px; font-size: var(--text-sm); }
  .mini-qty button { width: 40px; height: 40px; border-radius: 10px; font-size: 20px; }
}

/* ----------------------------------------------------------- sheet foot */
.sheet-foot {
  display: flex; gap: var(--space-12); align-items: center;
  padding: 15px var(--space-22); border-top: 1px solid var(--line-soft); background: var(--bg-raised);
}
/* Same specificity trap as .sheet[hidden] above — the order-confirmation
   view hides this bar, and without this it would not hide. */
.sheet-foot[hidden] { display: none; }
.qty { display: flex; align-items: center; gap: 3px; border: 1px solid var(--line); border-radius: 999px; padding: 3px; }
.qty button {
  width: 32px; height: 32px; border-radius: 999px; border: 0; background: transparent;
  display: grid; place-items: center; color: var(--ink-dim);
}
.qty button:hover { background: var(--bg-card); color: var(--ink); }
.qty span { min-width: 26px; text-align: center; font-size: var(--text-ui); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Deltas from the shared .ui-btn base only. This is a CTA with a running
   total pinned to its right edge, so it opts out of centred content and
   fills its row; everything else (radius, touch floor, transition, hover
   and active feedback) comes from components.css. */
.primary {
  flex: 1; justify-content: space-between; gap: var(--space-12);
  background: var(--accent); color: var(--ink-onAccent); border: 0;
  padding: var(--space-14) var(--space-20); font-size: var(--text-ui);
}
.primary:disabled { background: var(--bg-card-hi); color: var(--ink-faint); cursor: not-allowed; filter: none; }
.primary strong { font-variant-numeric: tabular-nums; }

.sheet-note {
  margin: 0; padding: 0 var(--space-22) 13px; background: var(--bg-raised);
  font-size: var(--text-xs); color: var(--ink-faint); text-align: center; letter-spacing: .02em;
}

.errors { margin: 0 0 var(--space-4); padding: var(--space-10) var(--space-12); border-radius: var(--radius-sm);
  background: var(--danger-tint); border: 1px solid var(--danger-edge); color: var(--danger); font-size: var(--text-xs); }
.errors span { display: block; }

/* --------------------------------------------------------------- mobile */
@media (max-width: 980px) {
  .layout { grid-template-columns: 1fr; }
  .cart {
    position: fixed; inset: 0; z-index: 70; max-height: none;
    border-radius: 0; border: 0; transform: translateX(100%);
    transition: transform .26s var(--ease);
  }
  .cart.is-open { transform: none; }
  .cart-head .icon-btn { display: grid; }
}

/* Below ~430px the header ran off the screen: brand (146px) + fulfilment
   toggle (~153px) + cart (87px) + gaps exceeded a 375px viewport, so the
   ordering page scrolled sideways on a phone. Pre-existing, and on the
   money path, so worth fixing properly rather than hiding the overflow.

   The brand shrinks to its mark and the controls keep full touch targets —
   the header is the last thing that should be hard to hit. */
@media (max-width: 430px) {
  .orderbar { padding: var(--space-8) var(--space-14); }
  /* Account moves out of the header on phones. It is NOT lost: the bottom
     nav on this page carries Menu / Track / Account, so at this width the
     header link was a second door to the same room, costing 75px in the one
     row that could not afford it.
     Measured at 390px: brand 118 + controls 291 + gaps and padding overran
     the viewport by 40px, so /order.html -- the ordering page, at the width
     most orders come from -- scrolled sideways. The earlier pass at this
     breakpoint tightened padding and type but never removed anything, and
     tightening alone could not close a 40px gap without pushing the
     Pickup/Delivery toggle back under the touch floor it was raised to. */
  .seg-btn { padding: 7px var(--space-10); font-size: var(--text-xs); }
  .cart-toggle { padding: 9px var(--space-10); gap: var(--space-6); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ---------------------------------------------------------- table mode */
/* The fulfillment toggle becomes a label when the customer scanned a table
   QR: there is nothing to choose. The pay note sits above the button so the
   "Send to the kitchen" wording is never a surprise. */
.table-badge {
  display: inline-flex; align-items: center; padding: 8px 14px;
  font-size: var(--text-sm); font-weight: 600; color: var(--ink);
  background: var(--accent-tint); border-color: var(--accent-edge);
}
.table-badge.is-off { color: var(--ink-dim); background: var(--warn-tint); border-color: var(--warn-edge); font-weight: 500; }
.table-pay {
  margin: 12px 0 4px; padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--accent-tint); border: 1px solid var(--accent-edge);
  color: var(--ink-dim); font-size: var(--text-sm); line-height: 1.45;
}
.table-pay strong { color: var(--ink); }

/* --------------------------------------------------------- pay choice */
/* Two equal options, the chosen one lit. Radios stay real (keyboard,
   screen readers) and are visually replaced by the card border. */
.pay-choice { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 12px 0 4px; }
.pay-opt {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; cursor: pointer;
  background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.pay-opt.is-on { border-color: var(--accent); background: var(--accent-tint); }
.pay-opt input { accent-color: var(--accent); margin: 0; flex: none; }
.pay-opt span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pay-opt strong { color: var(--ink); font-size: var(--text-sm); }
.pay-opt small { color: var(--ink-faint); font-size: var(--text-xs); line-height: 1.3; }
@media (max-width: 380px) { .pay-choice { grid-template-columns: 1fr; } }

/* A button that reads as a link (the menu's "Try again"). */
.link-btn { background: none; border: 0; padding: 0; font: inherit; color: var(--accent-text); text-decoration: underline; cursor: pointer; }
.cart-empty a { color: var(--accent-text); }

/* Ordering app on phones: 12px floor for text (all --text-2xs/3xs above now
   use --text-xs) and 44px tap targets for the controls a thumb uses most
   (audit 2026-09-25: qty 32px, Remove 42x18, contact inputs 38px). */
@media (max-width: 700px) {
  .qty button { width: 44px; height: 44px; }
  .seg-btn { min-height: 44px; }
  .icon-btn { width: 44px; height: 44px; }
  [data-remove] { min-height: 44px; min-width: 44px; padding: 0 var(--space-8); }
  .cart input:not([type=checkbox]):not([type=radio]), .cart select, .cart textarea,
  .sheet input:not([type=checkbox]):not([type=radio]) { min-height: 44px; }
}


/* Which place am I ordering from (restaurant or Lunch Cart): always said, never guessed. */
.placebar {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; gap: var(--space-4) var(--space-16);
  margin: 0; padding: var(--space-10) var(--space-16); text-align: center; text-wrap: balance;
  background: var(--bg-band, rgba(255,255,255,.04)); border-bottom: 1px solid var(--line, rgba(255,255,255,.12));
  color: var(--ink-dim); font-size: var(--text-sm); line-height: 1.45;
}
.placebar strong { color: var(--ink); }
.placebar a { color: var(--accent-text, var(--accent)); font-weight: var(--weight-semi); text-decoration: underline; text-underline-offset: 3px; }
