/* ==========================================================================
   components.css
   Every storefront component. Token-driven: var() only, zero literal colors
   or font families. The order ticket is the signature; everything else is
   deliberately quiet so it carries the weight.
   ========================================================================== */

/* ==========================================================================
   1. Buttons
   Square-shouldered by house rule. Pills are reserved for genuine pill or
   sticker elements (the demo pill, count badges, tags).
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--tap-min);
  padding: var(--space-3) var(--space-5);
  border: var(--border-solid) solid transparent;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-weight: var(--weight-strong);
  font-size: var(--step-0);
  line-height: 1.1;
  text-align: center;
  text-decoration: none;
  transition: background-color var(--dur-base) var(--ease),
              border-color var(--dur-base) var(--ease),
              color var(--dur-base) var(--ease),
              transform var(--dur-fast) var(--ease);
}

.btn:active {
  transform: translateY(1px);
}

.btn[disabled],
.btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.btn--primary {
  background: var(--color-chile);
  border-color: var(--color-chile);
  color: var(--color-on-chile);
}

.btn--primary:hover:not([disabled]) {
  background: var(--color-chile-hover);
  border-color: var(--color-chile-hover);
}

.btn--secondary {
  background: transparent;
  border-color: var(--color-line-strong);
  color: var(--color-text);
}

.btn--secondary:hover:not([disabled]) {
  border-color: var(--color-ink);
  background: var(--color-surface-sunken);
}

.btn--ghost-ink {
  background: transparent;
  border-color: var(--color-line-on-ink);
  color: var(--color-on-ink);
}

.btn--ghost-ink:hover:not([disabled]) {
  background: color-mix(in srgb, var(--color-paper) 12%, transparent);
  border-color: var(--color-paper);
}

.btn--quiet {
  min-height: auto;
  padding: var(--space-2) var(--space-3);
  font-weight: var(--weight-medium);
  font-size: var(--step--1);
  color: var(--color-text-muted);
}

.btn--quiet:hover {
  color: var(--color-chile);
}

.btn--lg {
  min-height: 3.25rem;
  font-size: var(--step-1);
  padding-inline: var(--space-6);
}

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

.btn--icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--tap-min);
  block-size: var(--tap-min);
  padding: 0;
  border: var(--border-hair) solid transparent;
  border-radius: var(--radius-sm);
  color: inherit;
  transition: background-color var(--dur-base) var(--ease),
              border-color var(--dur-base) var(--ease);
}

.btn--icon:hover {
  background: var(--color-surface-sunken);
  border-color: var(--color-line);
}

.on-ink .btn--icon:hover {
  background: color-mix(in srgb, var(--color-paper) 12%, transparent);
  border-color: var(--color-line-on-ink);
}

/* ==========================================================================
   2. Site header
   ========================================================================== */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-header);
  background: var(--color-ink);
  border-block-end: var(--border-hair) solid var(--color-line-on-ink);
  /* Clears a notch when the page is displayed without browser chrome. */
  padding-block-start: env(safe-area-inset-top, 0px);
  transition: background-color var(--dur-base) var(--ease),
              border-color var(--dur-base) var(--ease);
}

/* --- Overlay mode ---------------------------------------------------------
   On the home page the header floats over the full-bleed hero and starts
   transparent. It carries its own top gradient so the brand, nav and cart
   button clear contrast over any photograph, then flips to the solid surface
   once the hero sentinel passes under it (see mountHeaderScrollState). The
   flip is driven by an IntersectionObserver boundary, which is monotonic with
   scroll and so cannot oscillate. */

.site-header--overlay {
  position: fixed;
  inset-inline: 0;
  background: transparent;
  border-block-end-color: transparent;
}

.site-header--overlay::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--color-ink) 82%, transparent),
    color-mix(in srgb, var(--color-ink) 38%, transparent) 62%,
    transparent
  );
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease);
}

/* Declared after the overlay rules so the solid state always wins. */
.site-header--solid {
  background: var(--color-ink);
  border-block-end-color: var(--color-line-on-ink);
}

.site-header--solid::before {
  opacity: 0;
}

.site-header__inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-block-size: var(--header-h);
}

.site-header__brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  flex: none;
  padding-block: var(--space-2);
  min-block-size: var(--tap-min);
}

/* A link that stands on its own, rather than sitting inside a sentence, is a
   control and gets a control-sized target. Links inline in prose keep their
   natural height, which is the correct exception. */
p > .link:only-child,
.infoline > .link,
.cluster > .link {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--tap-min);
}

/* Tenant logos arrive at wildly different aspect ratios: a 9:1 wordmark for one
   tenant, a 1:1 badge for another. Sizing by height alone shrinks a badge to
   nothing; sizing by width alone shrinks a wordmark. Capping BOTH axes and
   leaving the intrinsic size to resolve lets each shape hit whichever limit it
   reaches first, and because both are max constraints on a replaced element the
   aspect ratio is never distorted. */
.site-header__logo {
  inline-size: auto;
  block-size: auto;
  max-inline-size: 11rem;
  max-block-size: 2.25rem;
  object-fit: contain;
}

@media (min-width: 26rem) {
  .site-header__logo {
    max-inline-size: 13rem;
    max-block-size: 2.5rem;
  }
}

@media (min-width: 40rem) {
  .site-header__logo {
    max-inline-size: 15rem;
    max-block-size: 2.75rem;
  }
}

/* Tenant logos range from a light wordmark to a dark raster mark, so a soft
   drop scrim behind the brand block guarantees separation from the photograph
   in overlay mode whichever one is dropped in. It disappears with the flip. */
.site-header--overlay:not(.site-header--solid) .site-header__brand {
  padding-inline: var(--space-3);
  margin-inline-start: calc(-1 * var(--space-3));
  border-radius: var(--radius-sm);
  background: radial-gradient(
    ellipse at center,
    color-mix(in srgb, var(--color-ink) 66%, transparent),
    transparent 74%
  );
}

.site-nav {
  display: none;
  margin-inline-start: var(--space-4);
}

@media (min-width: 48rem) {
  .site-nav {
    display: flex;
    gap: var(--space-5);
  }
}

.site-nav__link {
  text-decoration: none;
  font-weight: var(--weight-medium);
  font-size: var(--step--1);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  padding-block: var(--space-2);
  border-block-end: var(--border-solid) solid transparent;
  color: var(--color-on-ink-muted);
  transition: color var(--dur-base) var(--ease),
              border-color var(--dur-base) var(--ease);
}

.site-nav__link:hover {
  color: var(--color-on-ink);
}

.site-nav__link[aria-current="page"] {
  color: var(--color-on-ink);
  border-block-end-color: var(--color-chile);
}

.site-header__spacer {
  flex: 1 1 auto;
}

.cart-button,
.header-cta {
  flex: none;
  padding-inline: var(--space-4);
  gap: var(--space-2);
  font-size: var(--step--1);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  white-space: nowrap;
}

/* The header CTA is a filled control sitting on a dark bar, and over a dark
   region of the hero photograph a deep accent can fall under the 3:1 needed to
   read as a control boundary. A light hairline guarantees separation from the
   dark side while the fill guarantees it from the light side, so the button
   holds its shape whatever is behind it, in either header state. */
.on-ink .header-cta.btn--primary {
  border-color: color-mix(in srgb, var(--color-paper) 42%, transparent);
}

/* On the narrowest phones the logo yields width first, so the action never
   wraps or gets pushed off the bar. Above this there is room for both at full
   size. */
@media (max-width: 29.99rem) {
  .site-header__logo {
    max-inline-size: 9.5rem;
  }
}

.cart-button__label {
  display: none;
}

@media (min-width: 30rem) {
  .cart-button__label {
    display: inline;
  }
}

.cart-button__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 1.5rem;
  block-size: 1.5rem;
  padding-inline: var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--color-chile);
  color: var(--color-on-chile);
  font-size: var(--step--2);
  font-weight: var(--weight-strong);
  line-height: 1;
}

/* ==========================================================================
   3. Hero. The hero IS the menu.
   ========================================================================== */

.hero {
  position: relative;
  padding-block: var(--space-6) var(--space-8);
  overflow: hidden;
}

/* A quiet ruled texture so the ink slab is not a flat void. It is the whole
   treatment when the tenant has no hero photograph, and is suppressed once one
   loads so it never fights the image. */
.hero:not(.hero--photo)::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    -45deg,
    var(--color-line-on-ink) 0 1px,
    transparent 1px 14px
  );
  opacity: 0.35;
  pointer-events: none;
}

/* --- Full-bleed hero ------------------------------------------------------
   Runs to the very top of the viewport, under the overlay header. The picks
   panel below overlaps its bottom edge, so the hero reserves that much extra
   bottom padding and its copy is never covered. */

/* Height is deliberately well under a full viewport so the picks panel and the
   top of the first cards are on screen without scrolling. min-block-size is a
   floor, not a cap: if a tenant's headline wraps long the hero grows to fit
   rather than clipping. */
.hero--full {
  --picks-overlap: 3.5rem;
  display: grid;
  align-content: end;
  min-block-size: 62svh;
  padding-block-start: calc(var(--header-total) + var(--space-6));
  padding-block-end: calc(var(--space-6) + var(--picks-overlap));
}

@media (min-width: 62rem) {
  .hero--full {
    --picks-overlap: 5rem;
    min-block-size: 60svh;
    /* Trimmed relative to the mobile rhythm: at desktop the headline is large
       enough that the block reaches the target height on content alone, and
       every extra pixel of padding pushes the picks panel down. */
    padding-block-start: calc(var(--header-total) + var(--space-5));
    padding-block-end: calc(var(--space-6) + var(--picks-overlap));
    /* Consumed by .hero__lead and the hero copy spacing further down this file.
       Passing these as custom properties rather than re-declaring the rules
       keeps the override independent of source order. */
    --hero-measure: 46rem;
    --hero-copy-gap: var(--space-3);
    --hero-actions-gap: var(--space-5);
  }
}

/* Short landscape viewports: let content set the height entirely. */
@media (max-height: 34rem) {
  .hero--full {
    min-block-size: auto;
    padding-block-start: calc(var(--header-total) + var(--space-5));
  }
}

/* The display face runs very wide at hero sizes, and on a 375px screen the
   global --step-5 floor put the headline at nearly the full viewport width.
   The hero gets its own ramp with a lower floor. */
.hero__headline {
  font-size: clamp(2rem, 1.3rem + 3vw, 4rem);
}

/* The photo and the scrim are separate layers on purpose. Only the photo
   drifts; if the scrim moved with it, the gradient stops would slide relative
   to the copy and the measured contrast would change over the loop. */
.hero__media {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.hero--photo .hero__media::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--hero-image, none);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

/* --- Ambient drift --------------------------------------------------------
   A slow Ken Burns pass on the photo layer only. The type, the status chip and
   the scrim never move.

   `alternate` means the loop reverses instead of cutting back to the start, so
   there is no snap and no perceptible seam. Only transform is animated, so it
   stays on the compositor and never touches layout or paint. The scale floor of
   1.06 keeps the drift inside the frame: the translation is 1.2% each way
   against at least 3% of overflow per edge, so no edge of the photo can ever be
   pulled into view.

   will-change is scoped to this selector, which only exists while the photo is
   present and animating, and is dropped again under reduced motion. */
@keyframes hero-drift {
  from {
    transform: scale(1.06) translate3d(-1.2%, -0.7%, 0);
  }
  to {
    transform: scale(1.12) translate3d(1.2%, 0.7%, 0);
  }
}

.hero--photo .hero__media::before {
  animation: hero-drift 28s cubic-bezier(0.4, 0, 0.6, 1) infinite alternate;
  will-change: transform;
  backface-visibility: hidden;
}

/* The ink fallback has no photo layer to move, so it is static by construction
   and needs no separate treatment. */

@media (prefers-reduced-motion: reduce) {
  /* base.css collapses every animation to 0.001ms, which would leave the photo
     parked on the final keyframe rather than at rest. Cancel it outright so the
     image sits exactly where an unanimated one would. */
  .hero--photo .hero__media::before {
    animation: none !important;
    transform: none !important;
    will-change: auto;
  }
}

/* The scrim. House rule: text over a photograph must clear AA on its own and
   never rely on the picture. The bottom band where the copy actually sits is
   effectively solid ink, so the contrast is identical to the no-photo case;
   the image reads through the upper half where nothing but the header sits. */
.hero--photo .hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    /* Stops are absolute lengths measured up from the bottom edge, NOT
       percentages of the hero. The copy block is anchored to the bottom with
       fixed padding, so its distance from that edge barely changes, while its
       PERCENTAGE position swings with the hero's height. A percentage ramp was
       tuned for a full-viewport hero and silently dropped the status chip to
       2:1 when the hero was shortened. In rem, the same stops hold on a short
       phone hero, a tall desktop one, and any height content forces in between.
       Everything under 29rem stays at or above 72% ink, which clears AA for
       body text even if the photograph behind it were pure white.

       There is no stop for the top edge: the overlay header carries its own
       gradient, so this layer does not need to darken twice. */
    linear-gradient(
      to top,
      var(--color-ink) 0,
      var(--color-ink) 13rem,
      color-mix(in srgb, var(--color-ink) 90%, transparent) 21rem,
      color-mix(in srgb, var(--color-ink) 48%, transparent) 29rem,
      color-mix(in srgb, var(--color-ink) 20%, transparent) 38rem
    ),
    linear-gradient(
      to right,
      color-mix(in srgb, var(--color-ink) 62%, transparent),
      color-mix(in srgb, var(--color-ink) 12%, transparent) 62%,
      transparent
    );
}

/* Over a photograph the status chip carries its own near-opaque plate. The
   lime "ready by" time is a mid-tone and sits at the top of the copy block
   where the scrim is thinnest; on the scrim alone it measured 3.97:1 against a
   worst-case white photo. On this plate it clears AA with room to spare, and
   the chip reads as a deliberate live-status element rather than floating type. */
/* Written as .hero--photo.on-ink so it outranks the .on-ink .status rule
   further down the file rather than depending on source order. */
.hero--photo.on-ink .status {
  background: color-mix(in srgb, var(--color-ink) 88%, transparent);
  border-color: color-mix(in srgb, var(--color-paper) 26%, transparent);
}

.hero__sentinel {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  block-size: 1px;
  pointer-events: none;
}

.hero__inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--space-6);
}

.hero__lead {
  max-inline-size: var(--hero-measure, 34rem);
}

.hero__headline {
  margin-block-start: var(--hero-copy-gap, var(--space-4));
  color: var(--color-on-ink);
  text-wrap: balance;
}

.hero__sub {
  margin-block-start: var(--hero-copy-gap, var(--space-4));
  color: var(--color-on-ink-muted);
  max-inline-size: 44ch;
}

.hero__actions {
  margin-block-start: var(--hero-actions-gap, var(--space-6));
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* Live ordering status.
   Appears in two places on two different surfaces: inside the ink hero on the
   home page, and on the plain surface at the top of the menu page. The base
   styles are therefore the LIGHT-surface treatment, and the ink context opts in
   through .on-ink. Getting this backwards is how the chip ended up unreadable
   on the menu page, at 1.1:1. */
.status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  padding: var(--space-2) var(--space-3);
  border: var(--border-hair) solid var(--color-line);
  border-radius: var(--radius-sm);
  background: var(--color-surface-sunken);
}

.status__dot {
  inline-size: 0.5rem;
  block-size: 0.5rem;
  border-radius: var(--radius-pill);
  background: var(--color-ready-on-light);
  flex: none;
}

.status--closed .status__dot {
  background: var(--color-chile);
}

.status__label {
  color: var(--color-text);
}

.status__time {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--color-ready-on-light);
  font-variant-numeric: tabular-nums;
}

.status--closed .status__time {
  color: var(--color-text-muted);
}

/* Ink context: the raw lime is safe here and is the brighter, better signal. */
.on-ink .status {
  border-color: var(--color-line-on-ink);
  background: color-mix(in srgb, var(--color-paper) 8%, transparent);
}

.on-ink .status__dot {
  background: var(--color-lime);
}

.on-ink .status--closed .status__dot {
  background: var(--color-chile);
}

.on-ink .status__label {
  color: var(--color-on-ink);
}

.on-ink .status__time {
  color: var(--color-lime);
}

.on-ink .status--closed .status__time {
  color: var(--color-on-ink-muted);
}

/* --- Picks panel ----------------------------------------------------------
   Floats up over the hero's bottom edge so the three most-ordered items are
   already reachable at the fold. Sitting on the surface token rather than over
   the photo keeps its type on a known background, so contrast never depends on
   whichever image a tenant drops in. */

.picks-band {
  position: relative;
  z-index: 2;
  margin-block-start: calc(-1 * var(--picks-overlap, 3.5rem));
  padding-block-end: var(--space-8);
}

.picks-band__panel {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lift);
  padding: var(--space-5) var(--space-5) var(--space-6);
}

@media (min-width: 62rem) {
  .picks-band {
    --picks-overlap: 5rem;
  }

  .picks-band__panel {
    padding: var(--space-6) var(--space-6) var(--space-7);
  }
}

.picks-band__title {
  color: var(--color-text-muted);
  margin-block-end: var(--space-4);
}

.picks-band__more {
  margin-block-start: var(--space-5);
}

/* Inline ordering-state notice inside the hero, rather than a bar above it. */
.statebar--inline {
  max-inline-size: 34rem;
  margin-block-start: var(--space-5);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  border-inline-start: var(--space-1) solid var(--color-lime);
  background: color-mix(in srgb, var(--color-ink) 72%, transparent);
  color: var(--color-on-ink);
}

.statebar--inline .wrap {
  max-inline-size: none;
  margin-inline: 0;
  padding-inline: 0;
}

/* ==========================================================================
   4. Pick cards (hero) and item cards (menu). One tap into ordering.
   ========================================================================== */

.pick-grid {
  display: grid;
  gap: var(--space-3);
  margin: 0;
}

@media (min-width: 30rem) {
  .pick-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.pick__btn,
.item-card__btn {
  display: grid;
  inline-size: 100%;
  text-align: start;
  background: var(--color-surface);
  border: var(--border-hair) solid var(--color-line);
  border-radius: var(--radius-md);
  overflow: hidden;
  color: var(--color-text);
  transition: border-color var(--dur-base) var(--ease),
              box-shadow var(--dur-base) var(--ease),
              transform var(--dur-base) var(--ease);
}

.pick__btn:hover,
.item-card__btn:hover {
  border-color: var(--color-chile);
  box-shadow: var(--shadow-lift);
}

.pick__btn:active,
.item-card__btn:active {
  transform: translateY(1px);
}

/* Hero picks: horizontal on phones so three fit above the fold */
.pick__btn {
  grid-template-columns: 5.5rem minmax(0, 1fr);
  align-items: stretch;
}

@media (min-width: 30rem) {
  .pick__btn {
    grid-template-columns: minmax(0, 1fr);
    block-size: 100%;
  }
}

.pick__media,
.item-card__media {
  display: block;
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--tile-bg);
  overflow: hidden;
}

/* In the horizontal row layout the media is a grid item that stretches to the
   row height. Combined with aspect-ratio that made the square track the length
   of each item's description, so thumbnails came out between 124 and 128px and
   spilled past their column. Dropping the ratio and filling the fixed track
   instead keeps the left column identical on every card, photo or tile. */
@media (max-width: 33.99rem) {
  .pick__media,
  .item-card__media {
    aspect-ratio: auto;
    inline-size: 100%;
    block-size: 100%;
    min-block-size: 5.5rem;
  }
}

@media (min-width: 30rem) {
  .pick__media {
    aspect-ratio: 4 / 3;
  }
}

.pick__media img,
.item-card__media img,
.modal__media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.pick__body,
.item-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-4) var(--space-4);
  min-inline-size: 0;
}

.pick__name,
.item-card__name {
  font-family: var(--font-display);
  font-size: var(--step-1);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-display);
}

.pick__desc,
.item-card__desc {
  font-size: var(--step--1);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.pick__foot,
.item-card__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-block-start: auto;
  padding-block-start: var(--space-3);
}

.pick__add {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--step--1);
  font-weight: var(--weight-strong);
  color: var(--color-chile);
}

/* Menu grid */
.item-grid {
  display: grid;
  gap: var(--space-4);
  margin: 0;
}

@media (min-width: 34rem) {
  .item-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 62rem) {
  .item-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 78rem) {
  .item-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.item-card {
  display: flex;
}

.item-card__btn {
  grid-template-columns: 6.5rem minmax(0, 1fr);
  align-items: stretch;
}

@media (min-width: 34rem) {
  .item-card__btn {
    grid-template-columns: minmax(0, 1fr);
  }

  .item-card__media {
    aspect-ratio: 4 / 3;
  }
}

.item-card--out .item-card__btn {
  cursor: not-allowed;
  opacity: 0.62;
}

.item-card--out .item-card__btn:hover {
  border-color: var(--color-line);
  box-shadow: none;
}

.item-card__soldout {
  display: inline-block;
  font-size: var(--step--2);
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-chile);
}

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

/* Tags are genuine stickers, so the pill radius is earned here. */
.tag {
  display: inline-block;
  padding: 0.1rem var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--step--2);
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  background: var(--color-surface-sunken);
  color: var(--color-on-paper-muted);
  border: var(--border-hair) solid var(--color-line);
}

.tag--popular {
  background: var(--color-chile-wash);
  color: var(--color-chile);
  border-color: color-mix(in srgb, var(--color-chile) 30%, transparent);
}

.tag--new {
  background: var(--color-lime-wash);
  color: color-mix(in srgb, var(--color-lime) 55%, var(--color-ink));
  border-color: color-mix(in srgb, var(--color-lime) 40%, transparent);
}

/* ==========================================================================
   5. Typographic tile fallback for missing menu photography
   ========================================================================== */

/* Two rows: the name centres in whatever space is left, the ribbon takes its
   natural height at the bottom. Laying it out rather than absolutely
   positioning it means the name can never collide with the ribbon and the
   ribbon can never inflate the card, whatever the tile size or how the
   translated string wraps. */
.tile {
  position: relative;
  display: grid;
  grid-template-rows: 1fr auto;
  justify-items: center;
  align-items: center;
  inline-size: 100%;
  block-size: 100%;
  padding-block-start: var(--space-3);
  padding-inline: var(--space-2);
  text-align: center;
  background-color: var(--tile-bg);
  background-image: repeating-linear-gradient(
    -45deg,
    var(--tile-rule) 0 1px,
    transparent 1px 9px
  );
  color: var(--tile-ink);
  font-family: var(--font-display);
  font-size: var(--step-0);
  line-height: 1.1;
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  overflow: hidden;
}

.tile--alt {
  background-color: var(--tile-bg-alt);
}

.tile__text {
  display: block;
  overflow-wrap: anywhere;
  hyphens: auto;
}

.tile--lg {
  font-size: var(--step-2);
}

/* --- "Waiting for image" ribbon -------------------------------------------
   Sits on the tile, never on a real photograph. Deliberately quiet: body face,
   not the display face, so it reads as a caption on a placeholder rather than
   as part of the design. Sized in its own absolute units rather than em, so it
   stays legible on a 104px card thumbnail and does not inflate on the large
   modal tile. */
.tile__ribbon {
  grid-row: 2;
  inline-size: calc(100% + 2 * var(--space-2));
  margin-inline: calc(-1 * var(--space-2));
  padding: var(--space-1) var(--space-2);
  background: color-mix(in srgb, var(--color-ink) 84%, transparent);
  color: var(--color-paper);
  font-family: var(--font-body);
  /* Sized off the tile rather than the viewport: a wide tile in the item modal
     on a narrow phone still gets a proportionate ribbon, which a media query
     keyed to screen width could not do. */
  font-size: 0.55em;
  font-weight: var(--weight-strong);
  letter-spacing: 0.04em;
  line-height: 1.35;
  text-transform: uppercase;
  text-align: center;
  text-wrap: balance;
}

/* ==========================================================================
   6. Category rail
   ========================================================================== */

.catnav {
  position: sticky;
  inset-block-start: var(--header-total);
  z-index: var(--z-sticky);
  background: var(--color-surface);
  border-block-end: var(--border-hair) solid var(--color-line);
}

.catnav__inner {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.catnav__rail {
  display: flex;
  gap: var(--space-1);
  flex: 1 1 auto;
  padding-block: var(--space-2);
  min-inline-size: 0;
}

.catnav__link {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-block-size: var(--tap-min);
  padding-inline: var(--space-3);
  text-decoration: none;
  white-space: nowrap;
  font-size: var(--step--1);
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-text-muted);
  border-block-end: var(--border-solid) solid transparent;
  transition: color var(--dur-base) var(--ease),
              border-color var(--dur-base) var(--ease);
}

.catnav__link:hover {
  color: var(--color-text);
}

.catnav__link[aria-current="true"] {
  color: var(--color-chile);
  border-block-end-color: var(--color-chile);
}

/* Chevrons are permitted here: this is a genuine carousel control. */
.catnav__chev {
  display: none;
  flex: none;
}

@media (min-width: 48rem) {
  .catnav__chev {
    display: inline-flex;
  }
}

.catnav__chev--prev .icon {
  transform: rotate(180deg);
}

/* ==========================================================================
   7. Menu page layout
   ========================================================================== */

.order-layout {
  display: grid;
  gap: var(--space-6);
  padding-block: var(--space-6) calc(var(--space-8) + var(--viewbar-h));
  align-items: start;
}

@media (min-width: 62rem) {
  .order-layout {
    grid-template-columns: minmax(0, 1fr) var(--ticket-w);
    gap: var(--space-7);
  }
}

.menu-cat + .menu-cat {
  margin-block-start: var(--space-7);
}

.menu-cat__head {
  margin-block-end: var(--space-4);
  padding-block-end: var(--space-3);
  border-block-end: var(--border-solid) solid var(--color-ink);
}

.menu-cat__desc {
  margin-block-start: var(--space-1);
  font-size: var(--step--1);
  max-inline-size: var(--measure);
}

/* ==========================================================================
   8. The ticket. The signature element.
   ========================================================================== */

.ticket {
  position: relative;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.10))
          drop-shadow(0 10px 26px rgba(0, 0, 0, 0.14));
}

.ticket__edge {
  display: block;
  inline-size: 100%;
  block-size: 0.5rem;
  fill: var(--color-paper);
}

.ticket__edge--bottom {
  block-size: 0.85rem;
  transition: transform var(--dur-print) var(--ease);
}

.ticket__paper {
  background: var(--color-paper);
  color: var(--color-on-paper);
  padding: var(--space-4) var(--space-4) var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
}

/* Everything inside the ticket is mono. Nothing else on the site is. */
.ticket__paper * {
  font-family: var(--font-mono);
}

.ticket__head {
  text-align: center;
  padding-block-end: var(--space-3);
  border-block-end: var(--border-hair) dashed var(--color-line-ticket);
}

.ticket__brand {
  font-weight: var(--weight-strong);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: var(--step-0);
}

.ticket__meta {
  margin-block-start: var(--space-1);
  font-size: var(--step--2);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-on-paper-muted);
}

.ticket__number {
  display: block;
  margin-block-start: var(--space-2);
  font-size: var(--step-2);
  font-weight: var(--weight-strong);
  letter-spacing: 0.06em;
}

.ticket__lines {
  list-style: none;
  margin: 0;
  padding: 0;
}

.ticket__line {
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 1fr) auto;
  column-gap: var(--space-2);
  padding-block: var(--space-2);
  border-block-end: var(--border-hair) dashed var(--color-line-ticket);
}

.ticket__line:last-child {
  border-block-end: 0;
}

.ticket__qty {
  font-weight: var(--weight-strong);
}

.ticket__name {
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.ticket__amt {
  text-align: end;
  font-weight: var(--weight-strong);
  white-space: nowrap;
}

.ticket__mods,
.ticket__note {
  grid-column: 2 / -1;
  margin-block-start: var(--space-1);
  font-size: var(--step--2);
  color: var(--color-on-paper-muted);
  list-style: none;
  padding: 0;
}

.ticket__mods li::before {
  content: "+ ";
}

.ticket__note {
  color: var(--color-chile);
}

.ticket__line-actions {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-block-start: var(--space-2);
}

.ticket-step {
  display: inline-flex;
  align-items: center;
  border: var(--border-hair) solid var(--color-line-ticket);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--color-paper) 70%, var(--color-surface));
}

.ticket-step__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 2rem;
  block-size: 2rem;
  color: var(--color-on-paper);
}

.ticket-step__btn:hover {
  background: var(--color-paper-shade);
}

.ticket-step__value {
  min-inline-size: 1.75rem;
  text-align: center;
  font-weight: var(--weight-strong);
}

.ticket__remove {
  margin-inline-start: auto;
  font-size: var(--step--2);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-on-paper-muted);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  min-block-size: 2rem;
  padding-inline: var(--space-1);
}

.ticket__remove:hover {
  color: var(--color-chile);
}

.ticket__totals {
  margin-block-start: var(--space-2);
  padding-block-start: var(--space-3);
  border-block-start: var(--border-solid) solid var(--color-line-ticket);
}

.ticket__row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: 0.1rem;
  color: var(--color-on-paper-muted);
}

.ticket__row--total {
  margin-block-start: var(--space-2);
  padding-block-start: var(--space-2);
  border-block-start: var(--border-hair) dashed var(--color-line-ticket);
  color: var(--color-on-paper);
  font-size: var(--step-0);
  font-weight: var(--weight-strong);
  text-transform: uppercase;
}

.ticket__foot {
  margin-block-start: var(--space-3);
  padding-block-start: var(--space-3);
  border-block-start: var(--border-hair) dashed var(--color-line-ticket);
  text-align: center;
  font-size: var(--step--2);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-on-paper-muted);
}

.ticket__empty {
  padding-block: var(--space-5);
  text-align: center;
  color: var(--color-on-paper-muted);
}

.ticket--lg .ticket__paper {
  padding: var(--space-5) var(--space-5) var(--space-4);
  font-size: var(--step-0);
}

.ticket--lg .ticket__edge {
  block-size: 0.7rem;
}

.ticket--lg .ticket__edge--bottom {
  block-size: 1.1rem;
}

/* --- The one orchestrated moment -----------------------------------------
   A new line prints in with a short stagger and the torn edge shifts down. */

@keyframes ticket-print {
  from {
    opacity: 0;
    transform: translateY(-0.4rem);
    clip-path: inset(0 0 100% 0);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    clip-path: inset(0 0 0 0);
  }
}

.ticket__line--printing {
  animation: ticket-print var(--dur-print) var(--ease) backwards;
  animation-delay: calc(var(--i, 0) * var(--print-stagger));
}

.ticket--printing .ticket__edge--bottom {
  transform: translateY(0.35rem);
}

@media (prefers-reduced-motion: reduce) {
  .ticket__line--printing {
    animation: none;
  }

  .ticket--printing .ticket__edge--bottom {
    transform: none;
  }
}

/* ==========================================================================
   9. Order panel, mobile view bar, bottom sheet
   ========================================================================== */

.order-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

@media (min-width: 62rem) {
  .order-panel {
    position: sticky;
    inset-block-start: calc(var(--header-total) + 3.5rem);
  }
}

.order-panel__title {
  color: var(--color-text-muted);
}

.tipper {
  border: var(--border-hair) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: var(--space-3);
}

.tipper__legend {
  font-size: var(--step--1);
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-text-muted);
  padding: 0;
  margin-block-end: var(--space-2);
}

.tipper__row {
  display: flex;
  gap: var(--space-1);
  flex-wrap: wrap;
}

.tipchip {
  position: relative;
  flex: 1 1 3.5rem;
}

.tipchip input {
  position: absolute;
  inset: 0;
  opacity: 0;
  inline-size: 100%;
  block-size: 100%;
  margin: 0;
  cursor: pointer;
}

.tipchip span {
  display: flex;
  align-items: center;
  justify-content: center;
  min-block-size: var(--tap-min);
  padding-inline: var(--space-2);
  border: var(--border-hair) solid var(--color-line-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  transition: background-color var(--dur-base) var(--ease),
              border-color var(--dur-base) var(--ease),
              color var(--dur-base) var(--ease);
}

.tipchip input:checked + span {
  background: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-on-ink);
}

.tipchip input:focus-visible + span {
  outline: var(--focus-width) solid var(--color-focus);
  outline-offset: var(--focus-offset);
}

/* Persistent mobile order bar */
.viewbar {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: var(--z-viewbar);
  padding: var(--space-2) var(--wrap-gutter)
           calc(var(--space-2) + env(safe-area-inset-bottom, 0px));
  background: var(--color-ink);
  border-block-start: var(--border-hair) solid var(--color-line-on-ink);
}

@media (min-width: 62rem) {
  .viewbar {
    display: none;
  }
}

.viewbar__btn {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  inline-size: 100%;
  min-block-size: 3rem;
  padding-inline: var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--color-chile);
  color: var(--color-on-chile);
  font-weight: var(--weight-strong);
}

.viewbar__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 1.75rem;
  block-size: 1.75rem;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--color-ink) 45%, transparent);
  font-size: var(--step--1);
}

.viewbar__label {
  flex: 1 1 auto;
  text-align: start;
}

.viewbar__total {
  font-variant-numeric: tabular-nums;
}

/* Bottom sheet holding the ticket on small screens */
.sheet {
  inline-size: 100%;
  max-inline-size: 100%;
  margin: 0;
  margin-block-start: auto;
  inset-block-end: 0;
  inset-inline: 0;
  background: transparent;
}

.sheet__panel {
  background: var(--color-surface);
  border-start-start-radius: var(--radius-lg);
  border-start-end-radius: var(--radius-lg);
  box-shadow: var(--shadow-sheet);
  padding: var(--space-3) var(--wrap-gutter)
           calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
  max-block-size: 88svh;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.sheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-block-end: var(--space-3);
}

.sheet__grab {
  inline-size: 2.5rem;
  block-size: 0.25rem;
  border-radius: var(--radius-pill);
  background: var(--color-line-strong);
  margin: 0 auto var(--space-3);
}

.sheet[open] {
  animation: sheet-rise var(--dur-print) var(--ease);
}

@keyframes sheet-rise {
  from { transform: translateY(2rem); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

/* ==========================================================================
   10. Modal (item detail, generic)
   ========================================================================== */

.modal {
  inline-size: min(34rem, 100vw);
  max-block-size: 100svh;
  margin: auto;
}

.modal__panel {
  display: flex;
  flex-direction: column;
  max-block-size: 100svh;
  background: var(--color-surface);
  border-radius: var(--radius-md);
  overflow: hidden;
}

@media (max-width: 39.99rem) {
  .modal {
    margin: 0;
    margin-block-start: auto;
    inline-size: 100%;
    max-inline-size: 100%;
  }

  .modal__panel {
    border-end-end-radius: 0;
    border-end-start-radius: 0;
    max-block-size: 94svh;
  }
}

.modal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-4) var(--space-3);
  border-block-end: var(--border-hair) solid var(--color-line);
}

.modal__body {
  padding: var(--space-4);
  overflow-y: auto;
  overscroll-behavior: contain;
  flex: 1 1 auto;
}

.modal__media {
  aspect-ratio: 16 / 7;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: var(--tile-bg);
  margin-block-end: var(--space-4);
}

.modal__desc {
  font-size: var(--step-0);
  max-inline-size: var(--measure);
}

.modal__price {
  margin-block-start: var(--space-2);
}

.modal__foot {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4)
           calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
  border-block-start: var(--border-hair) solid var(--color-line);
  background: var(--color-surface);
}

.modal__foot .btn {
  flex: 1 1 auto;
}

/* Modifier groups: real fieldset and legend */
.modgroup {
  margin-block-start: var(--space-5);
  border: 0;
  padding: 0;
}

.modgroup__legend {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  flex-wrap: wrap;
  inline-size: 100%;
  padding: 0 0 var(--space-2);
  margin-block-end: var(--space-2);
  border-block-end: var(--border-hair) solid var(--color-line);
  font-family: var(--font-display);
  font-size: var(--step-1);
  letter-spacing: var(--tracking-display);
}

.modgroup__rule {
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  color: var(--color-text-muted);
}

.modgroup__rule--required {
  color: var(--color-chile);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  font-weight: var(--weight-strong);
  font-size: var(--step--2);
}

.modgroup__options {
  list-style: none;
  margin: 0;
  padding: 0;
}

.option {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-block-size: var(--tap-min);
  padding: var(--space-2) var(--space-2);
  border-block-end: var(--border-hair) solid var(--color-line);
  cursor: pointer;
}

.option:last-child {
  border-block-end: 0;
}

.option input {
  inline-size: 1.25rem;
  block-size: 1.25rem;
  flex: none;
  accent-color: var(--color-chile);
  margin: 0;
}

.option__name {
  flex: 1 1 auto;
}

.option__price {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--color-text-muted);
  white-space: nowrap;
}

.option:has(input:checked) .option__name {
  font-weight: var(--weight-strong);
}

.option:has(input:disabled) {
  opacity: 0.5;
  cursor: not-allowed;
}

.modgroup--invalid .modgroup__legend {
  border-block-end-color: var(--color-chile);
}

/* Quantity stepper */
.qty {
  display: inline-flex;
  align-items: center;
  border: var(--border-hair) solid var(--color-line-strong);
  border-radius: var(--radius-sm);
  flex: none;
}

.qty__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--tap-min);
  block-size: var(--tap-min);
  color: var(--color-text);
}

.qty__btn:hover:not([disabled]) {
  background: var(--color-surface-sunken);
}

.qty__btn[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
}

.qty__value {
  min-inline-size: 2.25rem;
  text-align: center;
  font-family: var(--font-mono);
  font-weight: var(--weight-strong);
}

/* ==========================================================================
   11. Forms
   ========================================================================== */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field__label {
  font-size: var(--step--1);
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.field__control {
  min-block-size: var(--tap-min);
  padding: var(--space-3);
  border: var(--border-hair) solid var(--color-line-strong);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  font-size: var(--step-0);
  transition: border-color var(--dur-base) var(--ease);
}

.field__control:hover {
  border-color: var(--color-ink);
}

textarea.field__control {
  min-block-size: 4.5rem;
  resize: vertical;
}

.field__control--mono {
  font-family: var(--font-mono);
  letter-spacing: 0.08em;
}

.field__hint {
  font-size: var(--step--1);
  color: var(--color-text-muted);
}

.field__error {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--step--1);
  font-weight: var(--weight-medium);
  color: var(--color-chile);
}

.field--invalid .field__control {
  border-color: var(--color-chile);
  border-width: var(--border-solid);
}

.field-row {
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 30rem) {
  .field-row--split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.formcard {
  border: var(--border-hair) solid var(--color-line);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  background: var(--color-surface);
}

.formcard__title {
  font-family: var(--font-display);
  font-size: var(--step-2);
  letter-spacing: var(--tracking-display);
  margin-block-end: var(--space-4);
}

/* ==========================================================================
   12. Checkout
   ========================================================================== */

.checkout-layout {
  display: grid;
  gap: var(--space-6);
  padding-block: var(--space-6) var(--space-8);
  align-items: start;
}

@media (min-width: 62rem) {
  .checkout-layout {
    grid-template-columns: minmax(0, 1fr) var(--ticket-w);
    gap: var(--space-7);
  }
}

.checkout-aside {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

@media (min-width: 62rem) {
  .checkout-aside {
    position: sticky;
    inset-block-start: calc(var(--header-total) + var(--space-4));
  }
}

.slotpicker {
  border: 0;
  padding: 0;
  margin: 0;
}

.slotpicker__legend {
  padding: 0;
  font-family: var(--font-display);
  font-size: var(--step-2);
  letter-spacing: var(--tracking-display);
  margin-block-end: var(--space-4);
}

.slot-asap {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-block-size: 4rem;
  padding: var(--space-3) var(--space-4);
  border: var(--border-solid) solid var(--color-line-strong);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color var(--dur-base) var(--ease),
              background-color var(--dur-base) var(--ease);
}

.slot-asap:hover {
  border-color: var(--color-ink);
}

.slot-asap input {
  inline-size: 1.25rem;
  block-size: 1.25rem;
  accent-color: var(--color-chile);
  flex: none;
  margin: 0;
}

.slot-asap:has(input:checked) {
  border-color: var(--color-chile);
  background: var(--color-chile-wash);
}

.slot-asap:has(input:focus-visible) {
  outline: var(--focus-width) solid var(--color-focus);
  outline-offset: var(--focus-offset);
}

.slot-asap__body {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.slot-asap__label {
  font-weight: var(--weight-strong);
}

.slot-asap__time {
  font-family: var(--font-mono);
  font-size: var(--step-1);
  color: var(--color-chile);
  font-variant-numeric: tabular-nums;
}

.daytabs {
  display: flex;
  gap: var(--space-1);
  margin-block: var(--space-5) var(--space-3);
  border-block-end: var(--border-hair) solid var(--color-line);
}

.daytab {
  min-block-size: var(--tap-min);
  padding-inline: var(--space-4);
  font-size: var(--step--1);
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-text-muted);
  border-block-end: var(--border-solid) solid transparent;
  margin-block-end: -1px;
}

.daytab[aria-pressed="true"] {
  color: var(--color-text);
  border-block-end-color: var(--color-chile);
}

.slot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.slot {
  position: relative;
  display: block;
}

.slot input {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}

.slot__face {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.1rem;
  min-block-size: 3.25rem;
  padding: var(--space-2);
  border: var(--border-hair) solid var(--color-line-strong);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  text-align: center;
  transition: background-color var(--dur-base) var(--ease),
              border-color var(--dur-base) var(--ease),
              color var(--dur-base) var(--ease);
}

.slot input:not(:disabled):hover + .slot__face {
  border-color: var(--color-ink);
}

.slot input:checked + .slot__face {
  background: var(--color-ink);
  border-color: var(--color-ink);
  color: var(--color-on-ink);
}

.slot input:focus-visible + .slot__face {
  outline: var(--focus-width) solid var(--color-focus);
  outline-offset: var(--focus-offset);
}

.slot--full .slot__face {
  border-style: dashed;
  color: var(--color-on-paper-muted);
  background: var(--color-surface-sunken);
  cursor: not-allowed;
}

.slot__flag {
  font-size: var(--step--2);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-chile);
  font-weight: var(--weight-strong);
}

.slot input:disabled {
  cursor: not-allowed;
}

.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  border-inline-start: var(--space-1) solid var(--color-chile);
  background: var(--color-chile-wash);
  font-size: var(--step--1);
}

.notice--info {
  border-inline-start-color: var(--color-smoke);
  background: var(--color-surface-sunken);
}

.notice--good {
  border-inline-start-color: var(--color-lime);
  background: var(--color-lime-wash);
}

.notice .icon {
  margin-block-start: 0.15rem;
  color: var(--color-chile);
}

.notice--info .icon { color: var(--color-smoke); }
.notice--good .icon { color: color-mix(in srgb, var(--color-lime) 60%, var(--color-ink)); }

.paybar {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-block-start: var(--space-5);
}

.paybar__note {
  font-size: var(--step--1);
  color: var(--color-text-muted);
  text-align: center;
}

.btn--busy {
  pointer-events: none;
  opacity: 0.72;
}

/* ==========================================================================
   13. Confirmation
   ========================================================================== */

.confirm {
  padding-block: var(--space-7) var(--space-8);
}

.confirm__inner {
  display: grid;
  gap: var(--space-6);
  justify-items: center;
  text-align: center;
}

.confirm__headline {
  color: var(--color-on-ink);
}

.confirm__sub {
  max-inline-size: 34rem;
}

.confirm__ticket {
  inline-size: min(24rem, 100%);
}

.statuschip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--color-lime);
  color: var(--color-on-lime);
  font-size: var(--step--1);
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.statuschip--new {
  background: var(--color-chile);
  color: var(--color-on-chile);
}

.statuschip--making {
  background: var(--color-paper);
  color: var(--color-on-paper);
}

.statuschip--done {
  background: color-mix(in srgb, var(--color-paper) 35%, transparent);
  color: var(--color-on-ink);
}

.wherecard {
  inline-size: min(24rem, 100%);
  text-align: start;
  padding: var(--space-5);
  border: var(--border-hair) solid var(--color-line-on-ink);
  border-radius: var(--radius-md);
}

.wherecard__title {
  color: var(--color-on-ink-muted);
  margin-block-end: var(--space-3);
}

.wherecard address {
  font-style: normal;
  line-height: var(--leading-body);
}

.infoline {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-block-size: var(--tap-min);
  text-decoration: none;
}

.infoline .icon {
  color: var(--color-on-ink-muted);
}

.on-paper .infoline .icon,
.section .infoline .icon {
  color: var(--color-text-muted);
}

/* ==========================================================================
   14. About band and footer
   ========================================================================== */

.about {
  padding-block: var(--space-8) var(--space-9);
}

.about__inner {
  display: grid;
  gap: var(--space-5);
}

@media (min-width: 56rem) {
  .about__inner {
    grid-template-columns: minmax(0, 4fr) minmax(0, 6fr);
    gap: var(--space-8);
    align-items: start;
  }
}

/* A short accent rule above the section title. Cheap, token-driven, and it
   stops the band reading as a default two-column text block. */
.about__head::before {
  content: "";
  display: block;
  inline-size: 3.5rem;
  block-size: 3px;
  background: var(--color-chile);
  margin-block-end: var(--space-4);
}

.about__body .prose {
  font-size: var(--step-1);
}

.about__findus {
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-5);
  border-block-start: var(--border-hair) solid var(--color-line);
}

.site-footer {
  border-block-start: var(--border-hair) solid var(--color-line-on-ink);
  padding-block: var(--space-7) var(--space-5);
  margin-block-start: auto;
}

.site-footer__inner {
  display: grid;
  gap: var(--space-6);
}

@media (min-width: 48rem) {
  .site-footer__inner {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-7);
  }
}

.site-footer__title {
  color: var(--color-on-ink-muted);
  margin-block-end: var(--space-3);
}

.hours {
  margin: 0;
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-4);
  row-gap: var(--space-1);
  font-size: var(--step--1);
}

.hours dt {
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  font-size: var(--step--2);
  align-self: center;
  color: var(--color-on-ink-muted);
}

.hours dd {
  margin: 0;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--step--1);
}

.hours__row--today dt,
.hours__row--today dd {
  color: var(--color-lime);
}

.site-footer__legal {
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-4);
  border-block-start: var(--border-hair) solid var(--color-line-on-ink);
  font-size: var(--step--2);
}

.findus {
  font-style: normal;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--step--1);
}

/* ==========================================================================
   15. Demo dock. A pitch remote, not a debug tool.
   ========================================================================== */

.demo-dock {
  position: fixed;
  inset-inline-end: var(--space-4);
  inset-block-end: calc(var(--space-4) + var(--viewbar-h) + env(safe-area-inset-bottom, 0px));
  z-index: var(--z-demo);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-2);
}

/* A genuine pill. */
.demo-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: var(--tap-min);
  padding-inline: var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--color-ink);
  color: var(--color-on-ink);
  border: var(--border-hair) solid var(--color-line-on-ink);
  box-shadow: var(--shadow-lift);
  font-size: var(--step--1);
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  transition: background-color var(--dur-base) var(--ease);
}

.demo-pill:hover {
  background: var(--color-ink-raised);
}

.demo-pill__dot {
  inline-size: 0.45rem;
  block-size: 0.45rem;
  border-radius: var(--radius-pill);
  background: var(--color-lime);
}

.demo-pill--closed .demo-pill__dot {
  background: var(--color-chile);
}

.demo-panel {
  inline-size: min(17rem, calc(100vw - var(--space-6)));
  background: var(--color-ink);
  color: var(--color-on-ink);
  border: var(--border-hair) solid var(--color-line-on-ink);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lift);
  overflow: hidden;
}

.demo-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-3) var(--space-2) var(--space-4);
  border-block-end: var(--border-hair) solid var(--color-line-on-ink);
}

.demo-panel__title {
  font-size: var(--step--1);
  font-weight: var(--weight-strong);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.demo-panel__list {
  list-style: none;
  margin: 0;
  padding: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.demo-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  inline-size: 100%;
  min-block-size: var(--tap-min);
  padding-inline: var(--space-3);
  border-radius: var(--radius-sm);
  text-align: start;
  text-decoration: none;
  font-size: var(--step--1);
  color: var(--color-on-ink);
  transition: background-color var(--dur-base) var(--ease);
}

.demo-item:hover {
  background: color-mix(in srgb, var(--color-paper) 12%, transparent);
}

.demo-item .icon {
  color: var(--color-on-ink-muted);
}

.demo-item__state {
  margin-inline-start: auto;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-lime);
}

.demo-panel__foot {
  padding: var(--space-2) var(--space-4) var(--space-3);
  border-block-start: var(--border-hair) solid var(--color-line-on-ink);
  font-size: var(--step--2);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-on-ink-muted);
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
}

.demo-panel__mode {
  font-family: var(--font-mono);
  color: var(--color-lime);
}

/* ==========================================================================
   16. Page-level state banners
   ========================================================================== */

.statebar {
  padding-block: var(--space-3);
  background: var(--color-chile);
  color: var(--color-on-chile);
  font-size: var(--step--1);
  font-weight: var(--weight-medium);
}

.statebar__inner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.emptystate {
  padding-block: var(--space-8);
  text-align: center;
  color: var(--color-text-muted);
}
