/* ==========================================================================
   Pasta Pot — design system
   Brand: yellow #fccf0f · dark green #015833 · light green #e4ede5 ·
          light yellow #ffe9b3
   Type: Quache Heavy Condensed for display, Quache Regular and Medium for
         text — all self-hosted from /fonts, no webfont from Google
   ========================================================================== */

/* --------------------------------------------------------------------------
   BRAND FONT — Quache (Måns Grebäck)

   Three static cuts, self-hosted from /fonts and converted from the licensed
   OTFs. The pages preload the .woff2 files that set type above the fold, so it
   paints in the brand face rather than swapping.

   Heavy Condensed sets the headings. Everything else on the site is Quache
   Text: Regular for running copy, Medium wherever the old Inter type asked for
   600 or 700. Inter is gone — the site fetches no font from Google.

   Display and text are declared as two families on purpose. Under one family
   name, weight matching decides between them, so a paragraph asking for 700
   would land on Heavy Condensed. Separate families keep that from happening.

   Both families claim wider weight ranges than the single cut behind them.
   That is deliberate: it stops the browser reaching for a synthesised weight it
   would render worse, and with font-synthesis-weight also off on body, every
   bold in the stylesheet resolves to real Medium rather than a smeared 400.

   See fonts/README.md for the conversion and the licence.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Quache";
  src: url("../fonts/Quache-HeavyCon.woff2") format("woff2"),
       url("../fonts/Quache-HeavyCon.woff") format("woff");
  font-weight: 400 900;
  font-stretch: 50% 100%;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Quache Text";
  src: url("../fonts/Quache-Regular.woff2") format("woff2"),
       url("../fonts/Quache-Regular.woff") format("woff");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Quache Text";
  src: url("../fonts/Quache-Medium.woff2") format("woff2"),
       url("../fonts/Quache-Medium.woff") format("woff");
  font-weight: 500 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Brand ----------------------------------------------------------------- */
  --yellow:      #fccf0f;
  --yellow-lt:   #ffe9b3;
  --green:       #015833;
  --green-lt:    #e4ede5;

  --green-dk:    #013f24;   /* hover / pressed */
  --yellow-dk:   #e0b800;   /* hover / pressed */

  /* Semantic -------------------------------------------------------------- */
  --bg:        #ffffff;
  --surface:   var(--green-lt);
  --surface-2: var(--yellow-lt);
  --ink:       #0f2418;
  --ink-soft:  #3d5648;
  --muted:     #6b7f72;
  --line:      rgba(1, 88, 51, 0.18);
  --line-soft: rgba(1, 88, 51, 0.10);
  --accent:    var(--green);

  /* Type ------------------------------------------------------------------ */
  --font-display: "Quache", "Archivo", "Anton", "Arial Narrow", "Helvetica Neue", sans-serif;
  /* The site's text face: everything that is not a heading. Which cut you get
     is the weight's job — 400 is Regular, 500 and up is Medium. The system
     stack behind it is only a fallback for a failed font load. */
  --font: "Quache Text", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          Helvetica, Arial, sans-serif;
  /* Kept as names for the two surfaces that were Quache before the rest of the
     site was — the hero copy, and the dish name and description wherever a dish
     is listed. Same family as body type now; they read better at the call site
     than a bare var(--font) would. */
  --font-hero: var(--font);
  --font-dish: var(--font);

  --step--1: clamp(0.82rem, 0.79rem + 0.15vw, 0.9rem);
  --step-0:  clamp(1rem, 0.96rem + 0.2vw, 1.09rem);
  --step-1:  clamp(1.2rem, 1.12rem + 0.4vw, 1.4rem);
  --step-2:  clamp(1.75rem, 1.45rem + 1.4vw, 2.75rem);
  --step-3:  clamp(2.25rem, 1.7rem + 2.6vw, 4rem);
  --step-4:  clamp(3rem, 1.9rem + 5.4vw, 6.5rem);

  /* Space ----------------------------------------------------------------- */
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --section: clamp(4rem, 9vw, 7.5rem);
  --maxw: 1220px;
  --header-h: 76px;   /* sticky header; anchors and the menu bar offset by it */

  --radius: 6px;
  --radius-lg: 14px;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

/* Reset -------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

/* scrollbar-gutter keeps the page from jumping sideways when the cart drawer
   locks body scrolling. */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scrollbar-gutter: stable; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

body {
  font-family: var(--font);
  font-size: var(--step-0);
  line-height: 1.65;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  font-synthesis-weight: none;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
button, input, textarea, select { font: inherit; color: inherit; }
a { color: inherit; }

/* Display type — headings use the brand condensed face, uppercase.
   `.display-face` carries the axis settings so every display element (headings,
   the brand wordmark, the Life Style cards) resolves to the same weight and
   width. */
.display-face,
h1, h2, h3.display, .brand, .diet-card h3 {
  font-family: var(--font-display);
  font-weight: 900;
  font-stretch: 75%;             /* condensed; ignored by single-width faces */
}

h1, h2, h3.display {
  text-transform: uppercase;
  letter-spacing: 0.005em;
  line-height: 0.95;
  color: var(--green);
  text-wrap: balance;
}
/* Default display sizes. Every h1/h2 on the site wants one of these two, so
   they live here instead of being re-declared per component. */
h1 { font-size: var(--step-3); }
h2 { font-size: var(--step-2); }
h3, h4 { font-weight: 600; line-height: 1.25; letter-spacing: -0.01em; }
/* Brand yellow for a heading that would otherwise be green. Note this is used on
   the white home-page story section, where it measures 1.49:1 against the 3:1
   large text wants — a deliberate call by Zain, not an oversight. Don't "fix" it. */
.is-yellow { color: var(--yellow); }
/* The site's way of accenting one word inside a display heading: <em> in the
   markup, yellow and upright here. Started on the hero and is now the general
   rule, so any h1/h2 can reach for it. Same contrast caveat as .is-yellow — on
   the light-green page header it is lower still. */
h1 em, h2 em { font-style: normal; color: var(--yellow); }
p { text-wrap: pretty; }

:focus-visible { outline: 3px solid var(--yellow); outline-offset: 2px; border-radius: 2px; }

.skip-link {
  position: absolute; left: 0; top: 0; padding: 0.75rem 1.25rem;
  background: var(--green); color: #fff; z-index: 200; text-decoration: none;
  transform: translateY(-120%);
}
.skip-link:focus { transform: none; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Layout ------------------------------------------------------------------- */
.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.wrap--narrow { max-width: 760px; }
/* Extra room at the page edges, phones only. The default gutter is about 20px
   there, which runs the text almost edge to edge; stepping it in is what makes a
   section read as a set piece on a small screen. Deliberately does nothing on
   desktop — the wide-screen version of this was tried and pulled. */
@media (max-width: 640px) {
  .wrap--inset { padding-inline: calc(var(--gutter) + 1rem); }
}
.section { padding-block: var(--section); }
/* Anything an in-page link can target has to clear the sticky header. */
.section[id], .page-header[id] { scroll-margin-top: calc(var(--header-h) + 1.25rem); }
/* Used where one section runs straight into the next (a callout under its own
   section, say) and the doubled padding would leave a hole. */
.section--flush-top { padding-top: 0; }
/* A band of facts rather than a full section; full --section padding around it
   reads as a gap in the page. */
.section--compact { padding-block: clamp(2.5rem, 5vw, 3.75rem); }
.section--tint { background: var(--surface); }
.section--yellow { background: var(--surface-2); }
.section--green { background: var(--green); color: #fff; }
.section--green h1, .section--green h2 { color: var(--yellow); }
.section--green p { color: rgba(255,255,255,0.82); }

.eyebrow {
  font-size: var(--step--1);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 0.9rem;
}
.section--green .eyebrow { color: rgba(255,255,255,0.6); }

.lede { font-size: var(--step-1); color: var(--ink-soft); }

/* Buttons ------------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  padding: 0.95rem 1.9rem;
  border: 2px solid transparent;
  border-radius: 999px;
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease),
              border-color 0.2s var(--ease), transform 0.12s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--yellow); color: var(--green); border-color: var(--yellow); }
.btn--primary:hover { background: var(--yellow-dk); border-color: var(--yellow-dk); }
.btn--green { background: var(--green); color: #fff; border-color: var(--green); }
.btn--green:hover { background: var(--green-dk); border-color: var(--green-dk); }
.btn--ghost { background: transparent; color: var(--green); border-color: var(--green); }
.btn--ghost:hover { background: var(--green); color: #fff; }
.btn--ghost-light { background: transparent; color: #fff; border-color: rgba(255,255,255,0.6); }
.btn--ghost-light:hover { background: #fff; color: var(--green); border-color: #fff; }
.btn--sm { padding: 0.55rem 1.2rem; }
/* Add-to-order confirmation, for the .btn-sized button on a dish page. The
   small pill version of the same state is on .add-btn further down. */
.btn--green.is-added { background: var(--yellow); border-color: var(--yellow); color: var(--green); }
.btn[disabled] { opacity: 0.45; cursor: not-allowed; }
.btn[disabled]:active { transform: none; }

/* Header ------------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line-soft);
}
.site-header__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; min-height: var(--header-h);
}
/* Brand lockup: the full circular badge plus a Quache wordmark. The badge's own
   arced type does not survive header size, so the wordmark is what actually
   reads the name — the badge is the mark. Sized as large as the 76px header
   allows, since a round badge reads smaller than a shape that fills its box. */
.brand {
  display: inline-flex; align-items: center; gap: 0.55rem;
  text-decoration: none; color: var(--green);
}
/* Pulled back out of the page gutter, header only — the footer chip is centred
   in its own column and must not move. The badge is a circle with transparent
   corners, so aligning its bounding box to the gutter leaves it looking inset
   next to the square-edged content below. The shift is capped at a fraction of
   the gutter, not the whole of it: phones only have a 20px gutter to give back,
   and eating all of it puts the badge against the edge of the screen. */
.site-header .brand {
  margin-inline-start: calc(-1 * min(0.9rem, var(--gutter) * 0.4));
}
/* 60px is the ceiling: the sticky header is 76px and --header-h is what every
   anchor offset and the mobile drawer position measure against, so the lockup
   has to stay inside it. */
.brand img { height: clamp(50px, 4.4vw, 60px); width: auto; }
.brand span {
  font-family: var(--font-display);
  font-weight: 900;
  font-stretch: 75%;
  font-size: clamp(1rem, 0.85rem + 0.65vw, 1.4rem);
  text-transform: uppercase;
  line-height: 1;
  letter-spacing: 0.01em;
  /* Two words with a space in them, in a flex row that runs out of width on a
     phone once the badge, the Order button and the menu toggle have taken
     theirs. Without this it breaks after "PASTA" and stacks. */
  white-space: nowrap;
}

/* Footer sits on dark green, and the badge is drawn for a light ground, so it
   gets a white circular chip rather than being recoloured. */
.brand--chip {
  width: 104px; height: 104px;
  background: #fff;
  border-radius: 50%;
  display: inline-grid; place-items: center;
  padding: 14px;
}
.brand--chip img { height: 100%; }

.nav { display: flex; align-items: center; gap: clamp(1rem, 2.4vw, 2.25rem); }
.nav a {
  text-decoration: none; font-size: var(--step--1); font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-soft);
  padding-block: 0.3rem;
  border-bottom: 2px solid transparent;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.nav a:hover { color: var(--green); }
.nav a[aria-current="page"] { color: var(--green); border-bottom-color: var(--yellow); }

.header-actions { display: flex; align-items: center; gap: 0.6rem; }

.cart-btn {
  position: relative; display: inline-flex; align-items: center; gap: 0.5rem;
  background: var(--yellow); border: 2px solid var(--yellow); border-radius: 999px;
  padding: 0.55rem 1.1rem; cursor: pointer; color: var(--green);
  font-size: var(--step--1); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  transition: background-color 0.2s var(--ease);
}
.cart-btn:hover { background: var(--yellow-dk); border-color: var(--yellow-dk); }
.cart-btn__count {
  min-width: 1.4rem; height: 1.4rem; padding-inline: 0.35rem;
  display: inline-grid; place-items: center;
  background: var(--green); color: #fff;
  border-radius: 999px; font-size: 0.72rem; font-weight: 700; line-height: 1;
}
.cart-btn__count[hidden] { display: none; }

.nav-toggle {
  display: none; background: none; border: 2px solid var(--line);
  border-radius: 999px; padding: 0.5rem 0.65rem; cursor: pointer; color: var(--green);
}
.nav-toggle svg { width: 20px; height: 20px; }

@media (max-width: 900px) {
  .nav-toggle { display: block; }
  /* visibility (not just opacity) is what actually takes the closed panel out
     of the tab order — without it, keyboard users tab through invisible links. */
  .nav {
    position: fixed; inset: var(--header-h) 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--bg);
    border-bottom: 2px solid var(--yellow);
    padding: 0.5rem var(--gutter) 1.5rem;
    transform: translateY(-105%);
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: transform 0.28s var(--ease), opacity 0.2s var(--ease),
                visibility 0s linear 0.28s;
  }
  .nav[data-open="true"] {
    transform: none; opacity: 1; visibility: visible; pointer-events: auto;
    transition: transform 0.28s var(--ease), opacity 0.2s var(--ease),
                visibility 0s;
  }
  .nav a { padding-block: 0.95rem; border-bottom: 1px solid var(--line-soft); font-size: var(--step-0); }
  /* The underline indicator reads as a divider in a stacked list, so the
     current page is marked with a yellow rail on the leading edge instead. */
  .nav a[aria-current="page"] {
    border-bottom-color: var(--line-soft);
    box-shadow: inset 3px 0 0 var(--yellow);
    padding-inline-start: 0.75rem;
    margin-inline-start: -0.75rem;
  }
}

/* Hero --------------------------------------------------------------------- */
/* Media and content share one grid cell, so the row is as tall as whichever
   needs more room. On a short, wide viewport the copy grows the hero instead of
   overflowing up behind the sticky header.

   The height is set here, on the section, and NOT on the image. Left on the
   image, `height: 100%` had no resolved parent height to measure against, so it
   fell back to auto and the picture's own aspect ratio drove the hero: a 16:9
   source made the hero 900px tall at 1600px wide and 1080px on a 1920px
   monitor, and object-fit: cover never cropped anything because the box already
   matched the source. Absolutely positioning the image inside the media cell
   makes it fill whatever height the row settles on instead of setting it. */
.hero {
  display: grid;
  background: var(--green);
  /* Sized off the viewport, not the copy. At 68vh the section was shorter than
     the fold once the headline came down, so a band of the white section under
     it showed on a laptop before any scrolling. Taking the sticky header out
     lands the bottom edge of the hero on the bottom edge of the window. */
  min-height: clamp(420px, calc(100vh - var(--header-h)), 820px);
  min-height: clamp(420px, calc(100svh - var(--header-h)), 820px);
}
.hero__media { grid-area: 1 / 1; position: relative; overflow: hidden; }
.hero__media img,
.hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
/* The file ships pre-cropped to 16:9 around the pot line, so cover only has the
   little that separates 16:9 from the banner's ratio left to trim and plain
   centring is right. Framing changes belong in the encode, not here. */
.hero__video { object-position: center center; }
/* Default 1 so the frame still shows if the script never runs; main.js drops it
   to 0 on init and back to 1 once the clip actually paints, which keeps a black
   first frame from flashing over the green. */
.hero__video[data-playing="false"] { opacity: 0; }
.hero__video { opacity: 1; transition: opacity 700ms ease; }
/* Two scrims rather than one flat wash. A single heavy green gradient made the
   footage read as a green block instead of a kitchen, so the vertical layer
   stays light across the picture and only gets dense at the very bottom, and a
   second left-weighted layer buys back contrast under the copy — which all sits
   bottom-left — leaving the right side of the frame legible as video. */
.hero__overlay {
  position: absolute; inset: 0;
  background:
    linear-gradient(90deg, rgba(1,42,25,0.62) 0%, rgba(1,42,25,0.28) 42%, rgba(1,42,25,0) 72%),
    linear-gradient(180deg, rgba(1,63,36,0.22) 0%, rgba(1,63,36,0.3) 45%, rgba(1,63,36,0.72) 100%);
}
.hero__content {
  grid-area: 1 / 1;
  align-self: end;
  position: relative;
  padding-block: clamp(2rem, 6vw, 4.5rem);
  color: #fff;
}
/* The brand text face, here and nowhere else. Not on .hero__cta: the buttons are
   a site-wide component and one pair set in a different face than every other
   button on the site reads as a mistake rather than a choice. */
/* Weight 500 is pinned rather than left at the inherited 400. "Quache Text" now
   carries both cuts, so a bare 400 would quietly drop the hero from Medium to
   Regular — this keeps it on the cut it was designed with. */
.hero p { font-family: var(--font-hero); font-weight: 500; }
/* No max-width: the <br> in the markup controls where the line breaks. A ch
   limit fights it, because Quache's wide glyphs make 1ch much narrower than
   the average character it actually sets. */
/* Its own scale rather than --step-4: that token tops out at 6.5rem, which on a
   laptop put the headline at ~100px and left the copy shouting over the video. */
/* Looser than the 0.95 the other headings run: two lines of Quache this size sat
   almost touching, and the yellow line needs air to read as its own line. */
.hero h1 { font-size: clamp(2.4rem, 1.6rem + 3.1vw, 4.25rem); line-height: 1.1; color: #fff; }
@media (max-width: 620px) {
  /* Exactly two lines, on every phone. The <br> gives the first break; this size
     is what stops the second line finding a third.

     "DIFFERENT LEVEL." measures 11.63em of advance width in Quache Heavy
     Condensed, 11.75em once the 0.005em tracking is counted, so it fits only
     while font-size stays under (100vw - both gutters) / 11.75. The gutter is
     pinned at 20px below a 400px viewport, which gives (100vw - 40px) / 11.75,
     or 8.5vw - 3.4px. The 8.3 below keeps ~2.5% in hand for rounding. It is a
     hard width budget rather than a taste call: at the old 1.9rem floor the
     line needed 358px of a 320px screen and broke into three.

     No `white-space: nowrap` to enforce it. If the webfont is slow and Archivo
     paints first, the wider fallback should wrap to a third line for a moment,
     not run off the side of the screen. */
  .hero h1 { font-size: clamp(1.4rem, calc(8.3vw - 3.4px), 2.6rem); }
}
/* White, at 0.9 alpha so it sits a step under the headline rather than
   competing with it. Green was tried here — both the brand's #015833 and a mint
   tint of it — and neither held up over moving footage: the dark green measured
   about 1.2:1 against the video, and the light --green-lt read as plain white
   anyway. On a picture this busy, white is the colour that works. */
.hero p { margin-top: 1.25rem; max-width: 48ch; color: rgba(255,255,255,0.9); font-size: var(--step-1); }
.hero__cta { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 2rem; }

/* Every override below has to sit after the .hero p and .hero__cta rules above,
   not before them. Same specificity, so source order decides, and while they
   were higher up the file the unconditional `font-size: var(--step-1)` and
   `margin-top: 2rem` simply won and the blocks did nothing. */

/* Split composition, phones only: headline and paragraph at the top of the hero,
   the two buttons pinned to its bottom edge, video filling the gap between them.
   The content stretches across the whole hero rather than sitting at one end of
   it, and `margin-top: auto` on the CTA row eats whatever height is left over.

   The bottom padding sets how far the buttons ride above the bottom edge. It is
   in vh so it scales with the screen, and the 2.5rem floor matters: the hero is
   sized in svh, so this padding is all that separates the buttons from a phone
   browser's toolbar. */
@media (max-width: 620px) {
  .hero__content {
    align-self: stretch;
    display: flex;
    padding-block: clamp(2rem, 7vh, 4rem) clamp(2.5rem, 9vh, 5rem);
  }
  .hero__content > .wrap { display: flex; flex-direction: column; }
  .hero__cta { margin-top: auto; padding-top: 2rem; }
}

/* Small phones — an SE, a mini, anything around 568–667px of viewport height.
   Keeps the paragraph from running the copy block down past the fold on the
   shortest screens, where the hero has ~490px to work with. */
@media (max-width: 620px) and (max-height: 700px) {
  .hero p { font-size: var(--step-0); margin-top: 0.9rem; }
  /* padding, not margin: `margin-top: auto` above is what pins the buttons to
     the bottom of the hero, and a margin here would cancel it. */
  .hero__cta { padding-top: 1.5rem; }
}
/* Wide but short: a laptop with devtools open, or a phone turned sideways.
   There is width to spare, so the fluid display size goes large while there is
   no height to put it in. Size the type off the viewport height instead, which
   keeps the copy inside the hero rather than pushing it past the fold. */
@media (min-width: 640px) and (max-height: 720px) {
  .hero__content { padding-block: clamp(1.25rem, 4vh, 2.5rem); }
  .hero h1 { font-size: clamp(2rem, 7vh, 3.25rem); }
  .hero p { font-size: var(--step-0); margin-top: 0.85rem; }
  .hero__cta { margin-top: 1.35rem; }
}

/* Page header (inner pages) ------------------------------------------------ */
.page-header {
  padding-block: clamp(3rem, 8vw, 5.5rem) clamp(2rem, 5vw, 3.5rem);
  background: var(--surface);
  border-bottom: 3px solid var(--yellow);
}
/* Looser than the 0.95 headings run elsewhere, for the same reason the hero is:
   two lines of Quache at this size sat almost touching. Every page header here
   is a two-line headline, so they all want the air. */
.page-header h1 { font-size: var(--step-3); line-height: 1.1; }
/* Body size, not the --step-1 this ran at first — Zain wanted it smaller under
   the headline. Medium rather than the Regular the rest of the site's copy runs,
   which is what keeps it reading as an intro at this size rather than as body
   copy that wandered up the page. Both his calls, picked off side-by-sides. */
.page-header p { margin-top: 1rem; max-width: 62ch; color: var(--ink-soft); font-size: var(--step-0); font-weight: 500; }

/* Grids -------------------------------------------------------------------- */
.grid { --grid-gap: clamp(1.5rem, 3vw, 2.5rem); display: grid; gap: var(--grid-gap); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }

/* The five signature dishes, all on one line once there is room for it, and any
   part-row centred rather than hanging off the left edge on the way down.

   Flex rather than grid on both counts: grid's justify-content moves the whole
   track set, not the leftovers inside a last row, and auto-fit picks its own
   column count from a minimum width, which is what capped this at three. Here
   the count is stated outright — basis and cap are the same fraction at every
   step, so a row holds exactly 1, 2, 3 then 5 and nothing in between. */
.grid--center { display: flex; flex-wrap: wrap; justify-content: center; }
.grid--center > * { flex: 1 1 100%; max-width: 100%; }
@media (min-width: 37.5em) {
  .grid--center > * { flex-basis: calc((100% - var(--grid-gap)) / 2); max-width: calc((100% - var(--grid-gap)) / 2); }
}
@media (min-width: 60em) {
  .grid--center > * { flex-basis: calc((100% - 2 * var(--grid-gap)) / 3); max-width: calc((100% - 2 * var(--grid-gap)) / 3); }
}
/* Five up. The wrap caps at 1220px however wide the screen gets, so a card here
   is always about 190px — too narrow for the dish name at its usual size, hence
   the tighter gap and the step down to --step-0 below. */
@media (min-width: 75em) {
  .grid--center { --grid-gap: 1.5rem; }
  .grid--center > * { flex-basis: calc((100% - 4 * var(--grid-gap)) / 5); max-width: calc((100% - 4 * var(--grid-gap)) / 5); }
  .grid--center .dish-card h3 { font-size: var(--step-0); }
  .grid--center .dish-card__price { font-size: var(--step--1); }
}

.section-head { display: flex; flex-wrap: wrap; align-items: end; justify-content: space-between; gap: 1.5rem; margin-bottom: clamp(2rem, 5vw, 3.5rem); }
.section-head h2 { max-width: 18ch; line-height: 1.32; }
/* :where() so this contributes no specificity beyond .section-head itself,
   which is what lets a utility class on the paragraph override the colour.
   Without it this rule is two selectors and outranks any single class. */
.section-head :where(p) { color: var(--ink-soft); max-width: 46ch; }

/* Dish cards --------------------------------------------------------------- */
/* Fixed column counts so four featured dishes never wrap to an orphan 3 + 1. */
#featured-dishes { grid-template-columns: 1fr; }
@media (min-width: 620px)  { #featured-dishes { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { #featured-dishes { grid-template-columns: repeat(5, 1fr); } }

/* Each card is a link to that dish's page. The whole card, rather than the
   name alone: it holds nothing else clickable, and a card-sized target beats a
   two-word one on a phone. */
.dish-card { display: flex; flex-direction: column; text-decoration: none; color: inherit; }
.dish-card img, .dish-card__pending { transition: transform 0.25s var(--ease); }
.dish-card:hover img, .dish-card:hover .dish-card__pending { transform: translateY(-4px); }
.dish-card:hover h3 { text-decoration: underline; text-decoration-color: var(--yellow); text-decoration-thickness: 3px; text-underline-offset: 3px; }
.dish-card img { aspect-ratio: 4 / 3; object-fit: cover; width: 100%; border-radius: var(--radius-lg); }
/* Stands in for a dish that has no photo yet: the badge on the tile, so the
   row of cards keeps its rhythm instead of going ragged. */
.dish-card__pending {
  aspect-ratio: 4 / 3; width: 100%; border-radius: var(--radius-lg);
  background: var(--green-lt); display: grid; place-items: center;
}
/* Sized in px, not a percentage: the tile's own height comes from its aspect
   ratio, so a percentage height inside it has nothing definite to resolve
   against and collapses to the logo's intrinsic size. */
.dish-card__pending img { width: auto; height: clamp(64px, 9vw, 104px); aspect-ratio: auto; object-fit: contain; opacity: 0.4; border-radius: 0; }
/* Real photography is a cut-out of the cup on transparent ground, so it is
   contained on a tint. `cover` would crop a portrait shot's lid off. */
.dish-card img.is-cutout { object-fit: contain; background: var(--green-lt); padding: 10px; }
.dish-card__head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-top: 1.25rem; }
.dish-card h3 { font-family: var(--font-dish); font-weight: 500; font-size: var(--step-1); color: var(--green); }
.dish-card__price { font-weight: 700; white-space: nowrap; color: var(--green); }
.dish-card p { margin-top: 0.5rem; font-family: var(--font-dish); font-weight: 400; color: var(--ink-soft); font-size: calc(var(--step--1) - 2pt); }
.dish-card .tags { margin-top: 0.75rem; }

/* Split feature ------------------------------------------------------------ */
.split { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center; grid-template-columns: 1fr; }
@media (min-width: 900px) { .split { grid-template-columns: 1fr 1fr; } }
.split img { border-radius: var(--radius-lg); aspect-ratio: 4 / 3; object-fit: cover; width: 100%; }
/* The kitchen photo is cropped to 3:2 at the source, so it gets a 3:2 box. In the
   default 4/3 box, cover would crop the sides back off and undo that framing. */
.split img.is-wide { aspect-ratio: 3 / 2; }
/* Headings here are section titles like the ones in .section-head, so they take
   the same line-height. The base 0.95 is set for one-line display type and reads
   cramped once a title wraps, which these always do in a half-width column. */
.split h2 { line-height: 1.32; }
.split p { color: var(--ink-soft); margin-top: 1rem; }
.split .btn { margin-top: 2rem; }

/* Diet badges -------------------------------------------------------------- */
.diet-card {
  background: #fff; border: 2px solid var(--line-soft); border-radius: var(--radius-lg);
  padding: 1.75rem 1.5rem; text-align: center;
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.diet-card:hover { border-color: var(--yellow); transform: translateY(-3px); }
.diet-card h3 { text-transform: uppercase; font-size: var(--step-1); color: var(--green); letter-spacing: 0.01em; }
.diet-card p { margin-top: 0.5rem; font-size: var(--step--1); color: var(--muted); }
.diet-card a { display: inline-block; margin-top: 0.9rem; font-size: var(--step--1); font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--green); text-decoration: none; border-bottom: 2px solid var(--yellow); }

/* Info strip --------------------------------------------------------------- */
.info-strip { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.info-strip h3 { font-size: var(--step--1); letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.info-strip p, .info-strip a { margin-top: 0.6rem; font-size: var(--step-0); }
.info-strip a { color: var(--green); font-weight: 600; text-decoration: none; border-bottom: 2px solid var(--yellow); }
.info-strip a:hover { background: var(--yellow-lt); }
/* Phone rows: a mark, then the number. Each number gets one — the WhatsApp mark
   on the line that takes WhatsApp, a handset on the line that is voice only —
   which says the same thing the old "calls only" label did without the words.
   The WhatsApp mark is itself a link to the chat; the handset is decorative,
   since the number beside it already dials. */
.phone-row { display: flex; align-items: center; gap: 0.55rem; }
.wa-icon, .tel-icon { width: 1.15em; height: 1.15em; flex: none; }
.wa-icon { fill: #25d366; }
.tel-icon { fill: var(--muted); }
/* `a.wa-link`, not `.wa-link`: `.info-strip a` is a class+element selector and
   outranks a bare class, so a plain .wa-link rule lost and the yellow underline
   stayed on. */
a.wa-link { display: inline-flex; border-bottom: 0; line-height: 0; }
a.wa-link:hover { background: none; }
a.wa-link:hover .wa-icon { fill: #128c4a; }
/* On the button the mark sits on the button's own colour, so it inherits. */
.btn--wa .wa-icon { width: 1.05em; height: 1.05em; fill: currentColor; }
/* A phone number that wraps mid-digits is unreadable, and the contact page puts
   these in a narrow two-column block where it happened. */
.info-strip a[href^="tel:"] { white-space: nowrap; }

/* Open / closed right now, filled in by js/main.js against Erbil time.
   Element selector included so it outranks `.info-strip p` on the homepage. */
p.status {
  display: inline-flex; align-items: center; gap: 0.5rem;
  margin-top: 0.4rem;
  font-size: var(--step--1); font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--muted);
}
p.status::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }
p.status[data-open="true"]  { color: #1c6b34; }
p.status[data-open="false"] { color: #a5341a; }

/* Menu --------------------------------------------------------------------- */
.menu-nav {
  position: sticky; top: var(--header-h); z-index: 50;
  background: rgba(255,255,255,0.95); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line-soft);
}
.menu-nav ul {
  display: flex; gap: 0.5rem; list-style: none; padding: 0; margin: 0;
  overflow-x: auto; scrollbar-width: none; padding-block: 0.85rem;
}
.menu-nav ul::-webkit-scrollbar { display: none; }
.menu-nav a {
  display: block; text-decoration: none; white-space: nowrap;
  padding: 0.4rem 0.9rem; border-radius: 999px;
  font-size: var(--step--1); letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 700; color: var(--muted);
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}
.menu-nav a:hover { color: var(--green); background: var(--green-lt); }
.menu-nav a.is-active { color: var(--green); background: var(--yellow); }

/* Jump links have to clear both sticky bars: the site header and the menu bar. */
.menu-section { padding-block: clamp(2.5rem, 6vw, 4.5rem); border-bottom: 1px solid var(--line-soft); scroll-margin-top: calc(var(--header-h) + 4.3rem); }
.menu-section:last-of-type { border-bottom: 0; }
.menu-section > header { margin-bottom: 2.25rem; }
.menu-section > header p { margin-top: 0.5rem; color: var(--ink-soft); max-width: 58ch; }

.menu-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); column-gap: clamp(2rem, 5vw, 4rem); }

/* A menu row is [optional photo] + the text block. The text block keeps the
   two-column name/price grid, so every rule below it is unaffected by whether
   the dish has a photo yet. Most don't, and won't for a while. */
.menu-item {
  position: relative;        /* the name link stretches over this box */
  display: flex;
  align-items: flex-start;
  gap: clamp(0.9rem, 2vw, 1.25rem);
  padding-block: 1.6rem;
  border-top: 1px solid var(--line-soft);
}
/* Hover highlight. Drawn on a pseudo-element rather than as a background on the
   row itself so it can bleed sideways into the column gap without dragging the
   divider line out with it, and tuck in vertically so it never touches one. */
.menu-item::before {
  content: "";
  position: absolute; z-index: -1; inset: 0.5rem -0.9rem;
  border-radius: var(--radius-lg);
  background: transparent;
  transition: background-color 0.2s var(--ease);
}
.menu-item:hover::before, .menu-item:focus-within::before { background: var(--green-lt); }
.menu-item__body {
  flex: 1;
  min-width: 0;              /* lets long descriptions wrap inside the flex row */
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.4rem 1.5rem;
  align-items: start;
  /* Pack rows to the top so a short item beside a tall one doesn't get its
     Add button pushed down by the shared grid row height. */
  align-content: start;
}

/* Dish photos are transparent cutouts of the product in its cup, not
   rectangular plates. So they are contained on a tinted pad rather than cropped
   to fill: `cover` would slice the lid off a portrait shot, and the cut-out
   edge needs something behind it other than the page white. */
.menu-item__photo {
  flex: none;
  width: clamp(84px, 20vw, 112px);
  aspect-ratio: 1;
  object-fit: contain;
  background: var(--green-lt);
  border-radius: var(--radius-lg);
  padding: 7px;
  transition: background-color 0.2s var(--ease);
}
/* The tile is the same green as the row's hover highlight, so it would dissolve
   into it. Inverted on hover to keep the dish framed. */
.menu-item:hover .menu-item__photo { background: #fff; }
/* An un-photographed dish in a part-photographed section. It holds the slot and
   nothing else: an empty tinted tile would read as a broken image. */
.menu-item__photo--pending, .menu-item:hover .menu-item__photo--pending { background: none; }
.menu-item__name { font-family: var(--font-dish); font-size: var(--step-1); font-weight: 500; color: var(--green); line-height: 1.25; }
/* The link to the dish's own page. Left undecorated until the row is hovered:
   28 underlined names down a menu reads as a link farm rather than a menu. */
.menu-item__link { text-decoration: none; color: inherit; }
.menu-item:hover .menu-item__link, .menu-item__link:focus-visible {
  text-decoration: underline; text-decoration-color: var(--yellow);
  text-decoration-thickness: 3px; text-underline-offset: 3px;
}
/* Stretched link: the whole row is the click target, photo and description
   included, while the row stays a plain container with one link in it. The
   cost is that the row's text can no longer be selected with the mouse. */
.menu-item__link::after { content: ""; position: absolute; inset: 0; }
.menu-item__price { font-weight: 700; color: var(--green); white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Two points off the small step. Subtracted rather than written as a new clamp
   so the description keeps tracking --step--1 as the viewport scales. */
.menu-item__desc { grid-column: 1 / -1; font-family: var(--font-dish); font-weight: 400; color: var(--ink-soft); font-size: calc(var(--step--1) - 2pt); max-width: 56ch; }
.menu-item__nutrition {
  grid-column: 1 / -1; margin-top: 0.5rem;
  font-size: var(--step--1); font-weight: 600; color: var(--green);
}
.menu-item__actions { grid-column: 1 / -1; margin-top: 0.9rem; display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }

.tags { display: flex; flex-wrap: wrap; gap: 0.4rem; grid-column: 1 / -1; margin-top: 0.5rem; }
.tag {
  font-size: 0.68rem; letter-spacing: 0.09em; text-transform: uppercase;
  font-weight: 700; padding: 0.2rem 0.55rem; border-radius: 999px;
  background: var(--green-lt); color: var(--green);
  white-space: nowrap;
}
.tag--popular { background: var(--yellow); color: var(--green); }
.tag--hot     { background: #fde4dd; color: #a5341a; }
.tag--hp      { background: var(--green); color: var(--yellow); }
.tag--vg,
.tag--v       { background: #d9ecdd; color: #1c6b34; }
.tag--gf      { background: var(--yellow-lt); color: #7a5b00; }
.tag--keto    { background: #e6e9f5; color: #35427a; }

.add-btn {
  /* Lifted above the stretched name link, or the row-wide overlay would take
     the click and navigate instead of adding to the order. */
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; gap: 0.4rem;
  background: none; border: 2px solid var(--green); border-radius: 999px;
  padding: 0.45rem 1.1rem; cursor: pointer; color: var(--green);
  font-size: var(--step--1); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.add-btn:hover { background: var(--green); color: #fff; }
.add-btn.is-added { background: var(--yellow); border-color: var(--yellow); color: var(--green); }

/* Cart drawer -------------------------------------------------------------- */
.cart-backdrop {
  position: fixed; inset: 0; z-index: 150;
  background: rgba(1, 63, 36, 0.5);
  opacity: 0; pointer-events: none;
  transition: opacity 0.25s var(--ease);
}
.cart-backdrop[data-open="true"] { opacity: 1; pointer-events: auto; }

.cart {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 160;
  width: min(430px, 100%);
  background: var(--bg);
  display: flex; flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.3s var(--ease);
  box-shadow: -8px 0 40px rgba(1, 63, 36, 0.18);
}
.cart[data-open="true"] { transform: none; }
/* The drawer stays in the DOM when closed, so it is marked `inert` in the
   markup and by js/main.js. That, not the off-screen transform, is what keeps
   its buttons out of the tab order. */

.cart__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.35rem var(--gutter);
  background: var(--green); color: #fff;
}
.cart__head h2 { font-size: var(--step-1); color: var(--yellow); }
.cart__close { background: none; border: 0; cursor: pointer; padding: 0.35rem; line-height: 0; color: #fff; }
.cart__close svg { width: 22px; height: 22px; }

.cart__body { flex: 1; overflow-y: auto; padding: 0 var(--gutter); }
.cart__empty { padding-block: 4rem; text-align: center; color: var(--muted); }

.cart-line { display: grid; grid-template-columns: 1fr auto; gap: 0.35rem 1rem; padding-block: 1.25rem; border-bottom: 1px solid var(--line-soft); }
.cart-line__name { font-weight: 700; font-size: var(--step-0); color: var(--green); }
.cart-line__price { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cart-line__qty { grid-column: 1 / -1; display: flex; align-items: center; gap: 0.5rem; margin-top: 0.4rem; }
.qty-btn {
  width: 32px; height: 32px; display: grid; place-items: center;
  border: 2px solid var(--line); border-radius: 999px;
  background: none; cursor: pointer; font-size: 1rem; line-height: 1; color: var(--green);
}
.qty-btn:hover { border-color: var(--green); background: var(--green-lt); }
.cart-line__count { min-width: 2ch; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }
.cart-line__remove { margin-left: auto; background: none; border: 0; cursor: pointer; color: var(--muted); font-size: var(--step--1); text-decoration: underline; text-underline-offset: 3px; }
.cart-line__remove:hover { color: #a5341a; }

.cart__foot { padding: 1.35rem var(--gutter); border-top: 2px solid var(--yellow); background: var(--green-lt); }
.cart__row { display: flex; justify-content: space-between; gap: 1rem; }
.cart__row--total { font-size: var(--step-1); font-weight: 700; color: var(--green); }
.cart__foot > .btn { width: 100%; margin-top: 1.1rem; }
.cart__note { margin-top: 0.85rem; font-size: var(--step--1); color: var(--muted); text-align: center; }

/* Order summary — what "checkout" produces until payments are switched on.
   Built by js/main.js so it isn't duplicated across four pages. */
.cart__summary {
  margin-top: 1.1rem; padding: 1rem 1.1rem;
  background: #fff; border: 2px solid var(--line-soft); border-radius: var(--radius-lg);
}
.cart__summary[hidden] { display: none; }
.cart__summary h3 { font-size: var(--step--1); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.cart__summary-text {
  margin-top: 0.6rem; white-space: pre-line;
  font-size: var(--step--1); line-height: 1.7; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.cart__summary .btn { margin-top: 0.9rem; width: 100%; }

/* Forms -------------------------------------------------------------------- */
.form { display: grid; gap: 1.25rem; }
.field { display: grid; gap: 0.5rem; }
.field label { font-size: var(--step--1); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-soft); }
.field input, .field textarea, .field select {
  padding: 0.85rem 1rem;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
  transition: border-color 0.2s var(--ease);
}
.field input:focus, .field textarea:focus, .field select:focus { border-color: var(--green); }
.field textarea { min-height: 140px; resize: vertical; }
.form__row { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); }
.form-note { font-size: var(--step--1); color: var(--muted); }

/* Hours -------------------------------------------------------------------- */
.hours { list-style: none; padding: 0; margin: 0; }
.status + .hours { margin-top: 1.25rem; }
.hours li { display: flex; justify-content: space-between; gap: 1.5rem; padding-block: 0.75rem; border-bottom: 1px solid var(--line-soft); }
.hours li:last-child { border-bottom: 0; }
.hours li[data-today="true"] { font-weight: 700; color: var(--green); }
.hours li[data-today="true"] span:first-child::after {
  content: "Today"; margin-left: 0.6rem; font-size: 0.68rem; letter-spacing: 0.09em;
  background: var(--yellow); color: var(--green); padding: 0.15rem 0.5rem; border-radius: 999px;
  vertical-align: middle;
}
.hours span:last-child { font-variant-numeric: tabular-nums; }

/* Map ---------------------------------------------------------------------- */
.map { border-radius: var(--radius-lg); overflow: hidden; border: 2px solid var(--line-soft); background: var(--green-lt); }
.map iframe { width: 100%; height: clamp(320px, 48vh, 480px); border: 0; display: block; }

/* Callout ------------------------------------------------------------------ */
.callout {
  background: var(--green); color: #fff;
  padding: clamp(2.5rem, 6vw, 4.5rem);
  border-radius: var(--radius-lg);
  text-align: center;
}
.callout h2 { max-width: 20ch; margin-inline: auto; color: var(--yellow); }
.callout p { margin-top: 1rem; color: rgba(255,255,255,0.8); max-width: 52ch; margin-inline: auto; }
.callout .btn { margin-top: 2rem; }

/* Dish page ---------------------------------------------------------------- */
/* One page per menu item, generated into menu/ by tools/build-menu-pages.js.
   Everything below is only ever used there. */

.breadcrumb { padding-block: 1.25rem 0; }
.breadcrumb ol {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  font-size: var(--step--1); color: var(--muted);
}
.breadcrumb li { display: flex; align-items: center; gap: 0.5rem; }
/* Separators are drawn rather than typed, so a screen reader doesn't read a
   slash between every crumb. */
.breadcrumb li + li::before { content: "/"; color: var(--line); }
.breadcrumb a { color: var(--muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--green); text-decoration: underline; }
.breadcrumb [aria-current="page"] { color: var(--green); font-weight: 600; }

.dish { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
@media (min-width: 900px) {
  .dish { grid-template-columns: minmax(0, 0.95fr) minmax(0, 1fr); }
  /* The photo is the tallest thing on the page and the info column is the one
     people read, so the photo sticks while the specs scroll past it. */
  .dish__media { position: sticky; top: calc(var(--header-h) + 1.5rem); }
}

/* Same reasoning as the menu thumbnails: cut-outs get contained on a tint, not
   cropped to fill. Square, because the shots are a mix of portrait and
   landscape and a square tile suits both. */
.dish__media {
  background: var(--green-lt); border-radius: var(--radius-lg);
  aspect-ratio: 1;
  /* minmax(0, 1fr) is what actually holds the square. With a plain `grid`, a
     portrait photo's own height wins over aspect-ratio and stretches the tile:
     Orzo Salad came out 516x574 and the drinks cup 516x1035. Capping the row at
     the tile's height stops the image driving it. */
  display: grid; grid-template-rows: minmax(0, 1fr); place-items: center;
  padding: clamp(1rem, 3vw, 2.25rem);
}
/* Sized by max, not by 100%, so a tall photo shrinks to fit the square instead
   of overflowing it. */
.dish__media img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
/* No photo of this dish yet. Says so, rather than showing an empty tile that
   reads as a failed image. */
/* Two stacked children rather than one image, so it needs its rows back. */
.dish__media--pending { grid-template-rows: auto auto; gap: 1rem; align-content: center; }
.dish__media--pending img { width: auto; height: clamp(90px, 22vw, 150px); opacity: 0.38; }
.dish__media--pending p {
  font-size: var(--step--1); letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 700; color: var(--muted);
}

.dish__info > .eyebrow { margin-bottom: 0.75rem; }
.dish__price {
  margin-top: 1rem;
  font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem); font-weight: 700;
  color: var(--green); font-variant-numeric: tabular-nums;
}
.dish__info .tags { margin-top: 1rem; }
.dish__desc { margin-top: 1.5rem; font-family: var(--font-dish); font-weight: 400; font-size: var(--step-1); color: var(--ink-soft); max-width: 54ch; }
.dish__options { margin-top: 1rem; color: var(--ink-soft); max-width: 54ch; }
.dish__nutrition {
  margin-top: 1rem; display: inline-block;
  padding: 0.35rem 0.85rem; border-radius: 999px;
  background: var(--green-lt); color: var(--green);
  font-size: var(--step--1); font-weight: 700;
}
.dish__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 2rem; }
.dish__note { margin-top: 1.5rem; font-size: var(--step--1); color: var(--muted); max-width: 54ch; }

/* More from this section. Fixed column counts rather than the auto-fit of
   .grid--3: Oven Baked holds two dishes, so a page there has exactly one card
   to show, and auto-fit would collapse the empty tracks and stretch that one
   card across the whole row. */
/* A hairline instead of a background tint, since the cards need white behind
   them to keep their own tiles visible. */
.section--related { border-top: 1px solid var(--line-soft); }
.related { grid-template-columns: 1fr; }
@media (min-width: 560px) { .related { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .related { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* The facts, every one of them read off the item in js/menu-data.js. */
.spec { margin-top: 2.5rem; border-top: 1px solid var(--line-soft); }
.spec > div {
  display: grid; gap: 0.25rem 1.5rem; padding-block: 0.9rem;
  border-bottom: 1px solid var(--line-soft);
}
@media (min-width: 480px) { .spec > div { grid-template-columns: 10rem 1fr; align-items: baseline; } }
.spec dt {
  font-size: var(--step--1); letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 700; color: var(--muted);
}
.spec dd { margin: 0; color: var(--ink); }
.spec a { color: var(--green); font-weight: 600; text-decoration: none; border-bottom: 2px solid var(--yellow); }
.spec a:hover { background: var(--yellow-lt); }

/* Footer ------------------------------------------------------------------- */
.site-footer { background: var(--green); color: #fff; padding-block: clamp(3rem, 7vw, 5rem) 2rem; }
.footer-grid { display: grid; gap: 2.5rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.footer-grid h3 { font-size: var(--step--1); letter-spacing: 0.16em; text-transform: uppercase; color: var(--yellow); font-weight: 700; margin-bottom: 1rem; }
.footer-grid ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.6rem; }
.footer-grid a { text-decoration: none; color: rgba(255,255,255,0.85); }
.footer-grid a:hover { color: var(--yellow); }
.footer-grid p { color: rgba(255,255,255,0.85); font-size: var(--step-0); }
.footer-bottom {
  margin-top: clamp(2.5rem, 6vw, 4rem); padding-top: 1.5rem;
  border-top: 1px solid rgba(255,255,255,0.2);
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  font-size: var(--step--1); color: rgba(255,255,255,0.6);
}
.socials { display: flex; gap: 0.75rem; }
.socials a {
  width: 40px; height: 40px; display: grid; place-items: center;
  border: 2px solid rgba(255,255,255,0.3); border-radius: 999px; color: #fff;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.socials a:hover { background: var(--yellow); border-color: var(--yellow); color: var(--green); }
.socials svg { width: 19px; height: 19px; }

/* Small helpers ------------------------------------------------------------ */
/* These replace the inline style attributes the pages used to carry, so every
   spacing decision stays in one file. */
.contact-address { font-size: var(--step-1); font-weight: 600; color: var(--green); line-height: 1.4; }
.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.footer-tagline { margin-top: 1.25rem; }
.stack-sm { margin-top: 1rem; }
.stack-md { margin-top: 1.5rem; }
.stack-lg { margin-top: 2.5rem; }

/* Placeholder marker — remove once real photography is in ------------------- */
[data-placeholder] { outline: 2px dashed rgba(1, 88, 51, 0.3); outline-offset: -2px; }

/* Utilities ---------------------------------------------------------------- */
/* Last on purpose. A component rule like `.section-head p` is two selectors and
   outranks a single utility class, so these only win from down here. Anything
   added later that has to override a component belongs in this block, not up
   with .is-yellow. */

/* Tighter set than the 1.65 body copy runs. Not true condensed type — Quache
   Text has only the one width and browsers will not synthesise a narrower one —
   so this closes the leading and the tracking instead, which is what reads as
   condensed at this size. */
.is-condensed { line-height: 1.4; letter-spacing: -0.02em; }
/* Flush on both edges. hyphens comes with it rather than as a separate choice:
   these columns are half-width, and justifying that measure without breaking
   words opens rivers of white space between them. */
.is-justified { text-align: justify; hyphens: auto; }
/* 700 lands on Quache Medium, the heaviest text cut installed — there is no
   Quache Bold, so this is as heavy as text on this site goes. See
   fonts/README.md if a real bold is ever wanted. */
.is-bold { font-weight: 700; }

/* Print -------------------------------------------------------------------- */
/* Mostly for the menu page: staff and customers do print these. */
@media print {
  .site-header, .menu-nav, .site-footer, .cart, .cart-backdrop,
  .add-btn, .btn, .skip-link, .callout, .hero__cta,
  .breadcrumb, .dish__actions,
  /* Images are dropped below, and an empty photo tile would print as half a
     page of nothing. */
  .dish__media, .dish-card__pending { display: none !important; }

  /* With the photo gone there is no second column to fill. */
  .dish { display: block; }

  body { font-size: 10.5pt; line-height: 1.4; color: #000; background: #fff; }
  h1, h2, h3 { color: #000; }
  .section, .menu-section { padding-block: 0.75rem; page-break-inside: avoid; }
  .page-header { padding-block: 0 1rem; background: none; border-bottom: 2px solid #000; }
  .menu-list { grid-template-columns: 1fr 1fr; column-gap: 2rem; }
  .menu-item { padding-block: 0.5rem; page-break-inside: avoid; }
  .menu-item__actions { display: none; }
  .tag { border: 1px solid #666; background: none !important; color: #000 !important; }
  a { text-decoration: none; color: #000; }
  img { display: none; }
}
