/* Template 2 — pizza. Four pages off one stylesheet.
   Spec: design/pizza/*.dc.html. Research behind it: design/pizza/RESEARCH.md.

   Structurally distinct from template 1 on purpose: split hero with the type
   panel BESIDE a macro crop (never text over the photograph, so a badly lit
   photo cannot make the page unreadable), a marquee band, a tilted card rail,
   pill controls, and a persistent order CTA.

   Container standard, from the page-build skill:
     stacked content  -> .wrap
     full-width band  -> the SECTION spans 100%, with a .wrap inside it
   --maxw is 1312 because the artboard is 1440 with 64px gutters. Never 100vw:
   it includes the scrollbar and pushes a horizontal scrollbar on every desktop
   with a classic one. */

:root {
  /* The measure the artboard was drawn at: 1440 - 2*64. It GROWS on large screens
     rather than stranding 300px of empty margin either side, and the gutter shrinks
     with the viewport on the way down. */
  --maxw: 1312px;
  --gutter: 64px;

  /* Overridden per business by {{CSS_VARS}} in the head. These are the
     fallbacks, and they are the artboard's values. */
  --bg: #f6f1e8;
  --surface: #ffffff;
  --ink: #17140f;
  --muted: #6e6558;
  --line: #e3dacb;
  --brand: #d6402a;
  --brand-dark: #a82e1d;
  --on-brand: #fff6f2;
  --accent: #2f6b4a;
  --foot-bg: #17140f;
  --foot-ink: #f6f1e8;
  --band-up: #fbfaf6;
  --band-down: #efe8da;

  --ink-dim: color-mix(in srgb, var(--ink) 72%, transparent);
  --on-dark: #b8b0a3;

  --font-display: "Bricolage Grotesque", "Helvetica Neue", Helvetica, sans-serif;
  --font-body: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;

  --r-card: 18px;
  --r-lg: 24px;
  --pill: 999px;
  --ease: cubic-bezier(.2, .7, .3, 1);
  /* Entrances only. Nearly all of the distance is covered in the first third,
     so a short travel still reads as deliberate instead of as a slow slide. */
  --ease-out: cubic-bezier(.22, 1, .36, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

.wrap {
  width: min(var(--maxw), 100% - calc(var(--gutter) * 2));
  margin-inline: auto;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* --- type ----------------------------------------------------------------- */

.dsp { font-family: var(--font-display); letter-spacing: -0.025em; font-weight: 800; }

.h1 { font-size: clamp(44px, 6.2vw, 88px); line-height: .94; letter-spacing: -0.03em; margin: 0; }
.h2 { font-size: clamp(34px, 4.2vw, 60px); line-height: 1; margin: 0; }
.h3 { font-size: clamp(26px, 3.75vw, 54px); line-height: 1.04; margin: 0; }
.h4 { font-size: clamp(20px, 2vw, 26px); line-height: 1.15; margin: 0; font-weight: 600; }

.eyebrow {
  font-size: 13px; letter-spacing: .16em; font-weight: 600;
  color: var(--muted); text-transform: uppercase; margin: 0;
}

.lede { font-size: 17px; line-height: 1.6; color: var(--ink-dim); margin: 0; }
.p { margin: 0; color: var(--muted); line-height: 1.6; }

/* --- controls ------------------------------------------------------------- */

/* outline, never border: a 1px border makes an outlined button 2px wider than
   a filled one, so the pair never lines up. outline draws inside and takes no
   space. */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  border-radius: var(--pill);
  padding: 17px 30px;
  font: inherit; font-size: 16px; font-weight: 600;
  border: 0; background: none; cursor: pointer;
  min-height: 48px;
  transition: transform .16s ease, background-color .16s ease, color .16s ease;
}
.btn--brand { background: var(--brand); color: var(--on-brand); }
.btn--brand:hover { background: var(--brand-dark); }
.btn--ghost { outline: 1px solid var(--ink); outline-offset: -1px; color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--bg); }
.btn--light { background: var(--bg); color: var(--ink); }
.btn--sm { padding: 12px 24px; font-size: 14px; min-height: 44px; }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

.pill {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--pill); padding: 13px 26px;
  font-size: 15px; font-weight: 500; min-height: 44px;
  outline: 1px solid color-mix(in srgb, var(--ink) 26%, transparent);
  outline-offset: -1px; cursor: pointer;
  transition: background-color .16s ease, color .16s ease;
}
.pill[aria-current="true"], .pill--on { background: var(--ink); color: var(--bg); outline-color: var(--ink); }
.pill:hover { outline-color: var(--ink); }
.pill:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

.icon { width: 18px; height: 18px; flex: none; }

/* --- promo strip + nav ---------------------------------------------------- */

.promo {
  background: var(--brand); color: var(--on-brand);
  font-size: 12px; letter-spacing: .14em; font-weight: 600;
  text-align: center; padding: 10px var(--gutter);
}

.nav {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--line);
  transition: padding .2s var(--ease), box-shadow .2s ease;
}
.nav__in { display: flex; align-items: center; gap: 40px; min-height: 84px; transition: min-height .2s var(--ease); }
.nav__mark { font-family: var(--font-display); font-weight: 800; font-size: 26px; letter-spacing: -0.02em; transition: font-size .2s var(--ease); }
.nav__links { display: flex; gap: 30px; flex: 1 1 auto; font-size: 15px; font-weight: 500; list-style: none; margin: 0; padding: 0; }
.nav__links a { padding: 4px 0; border-bottom: 2px solid transparent; }
.nav__links a:hover { border-bottom-color: color-mix(in srgb, var(--ink) 30%, transparent); }
.nav__links [aria-current="page"] { border-bottom-color: var(--brand); }
.nav__cta { display: flex; gap: 12px; align-items: center; flex: none; }
.nav__burger { display: none; }

/* condensed past the hero. Purely cosmetic — no content depends on it. */
.is-stuck .nav__in { min-height: 60px; }
.is-stuck .nav__mark { font-size: 20px; }
.is-stuck { box-shadow: 0 2px 14px color-mix(in srgb, var(--ink) 8%, transparent); }

/* --- hero ----------------------------------------------------------------- */

.hero { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; }
.hero__copy {
  display: flex; flex-direction: column; justify-content: center; gap: 28px;
  padding: 88px var(--gutter);
  padding-left: max(var(--gutter), calc((200% - var(--maxw)) / 2));
  min-height: 620px;
}
.hl { color: var(--brand); }
.hero__lede { max-width: 46ch; }
.hero__cta { display: flex; gap: 12px; flex-wrap: wrap; padding-top: 8px; }
.hero__facts { display: flex; gap: 24px; flex-wrap: wrap; font-size: 14px; color: var(--muted); padding-top: 8px; }
.hero__fact { display: inline-flex; align-items: center; gap: 8px; }
.dot { width: 8px; height: 8px; border-radius: var(--pill); background: #2f7d52; flex: none; }
.dot--shut { background: var(--muted); }
.hero__media { overflow: hidden; background: var(--band-down); }
.hero__img { width: 100%; height: 100%; object-fit: cover; min-height: 620px; }

/* --- marquee -------------------------------------------------------------- */

/* overflow hidden on the wrapper, always: a run of text wider than the viewport
   otherwise widens documentElement.scrollWidth and pushes a scrollbar. */
.tick { background: var(--ink); color: var(--bg); padding: 22px 0; overflow: hidden; }
.tick__row {
  display: flex; gap: 40px; white-space: nowrap; width: max-content;
  font-family: var(--font-display); font-weight: 600; font-size: 22px; letter-spacing: .04em;
  animation: tick 26s linear infinite;
}
.tick__sep { color: var(--brand); }
@keyframes tick { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* --- sections ------------------------------------------------------------- */

.sec { padding: 96px 0; }
.sec--tight { padding: 64px 0; }
.sec__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 32px; padding-bottom: 44px; flex-wrap: wrap; }
.sec__headings { display: flex; flex-direction: column; gap: 12px; }

.card {
  background: var(--surface);
  outline: 1px solid var(--line); outline-offset: -1px;
  border-radius: var(--r-card);
}

/* --- three ways ----------------------------------------------------------- */


/* --- menu rail ------------------------------------------------------------ */

.rail { display: flex; gap: 28px; overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 8px; scrollbar-width: none; }
.rail::-webkit-scrollbar { display: none; }
.rail__nav { display: flex; gap: 10px; align-items: center; }
.rail__btn {
  width: 46px; height: 46px; border-radius: var(--pill); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  outline: 1px solid color-mix(in srgb, var(--ink) 26%, transparent); outline-offset: -1px;
  background: none; color: var(--ink);
}
.rail__btn--on { background: var(--brand); color: var(--on-brand); outline-color: var(--brand); }
.rail__btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

/* the tilt. It has to correct on hover or it reads as a rendering fault. */
.item__tag { display: inline-flex; align-items: center; background: var(--band-down); border-radius: var(--pill); padding: 3px 9px; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }

/* --- this week ------------------------------------------------------------ */

.week { background: var(--brand); color: var(--on-brand); border-radius: var(--r-lg); overflow: hidden;
        display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.week__copy { padding: 56px; display: flex; flex-direction: column; justify-content: center; gap: 18px; }
.week__eyebrow { font-size: 13px; letter-spacing: .16em; font-weight: 600; opacity: .75; margin: 0; text-transform: uppercase; }
.week__body { margin: 0; font-size: 16px; line-height: 1.6; opacity: .92; max-width: 44ch; }
.week__cta { align-self: flex-start; margin-top: 6px; }
.week__img { width: 100%; height: 100%; object-fit: cover; min-height: 340px; }

/* --- craft / the oven ----------------------------------------------------- */

.craft { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); background: var(--ink); color: var(--bg); }
.craft__media { overflow: hidden; min-height: 520px; }
.craft__img { width: 100%; height: 100%; object-fit: cover; }
.craft__copy {
  display: flex; flex-direction: column; justify-content: center; gap: 26px;
  padding: 88px var(--gutter);
  padding-right: max(var(--gutter), calc((200% - var(--maxw)) / 2));
}
.craft__kicker { color: var(--brand); }
.craft__body { color: var(--on-dark); max-width: 48ch; margin: 0; line-height: 1.6; }
.stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; padding-top: 16px; }
.stat__n { font-family: var(--font-display); font-size: 46px; font-weight: 800; color: var(--brand); line-height: 1; }
.stat__l { font-size: 13px; color: var(--on-dark); padding-top: 6px; line-height: 1.4; }
.craft__cta { align-self: flex-start; margin-top: 10px; outline-color: color-mix(in srgb, var(--bg) 40%, transparent); color: var(--bg); }
.craft__cta:hover { background: var(--bg); color: var(--ink); }

/* --- gallery -------------------------------------------------------------- */

.gallery { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.shot { border-radius: 14px; overflow: hidden; height: 260px; background: var(--band-down); }
.shot img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s var(--ease); }
.shot:hover img { transform: scale(1.05); }

/* --- reviews -------------------------------------------------------------- */

.rating { display: flex; align-items: baseline; gap: 16px; padding-bottom: 40px; }
.rating__n { font-family: var(--font-display); font-size: 46px; font-weight: 800; letter-spacing: -0.025em; }
.reviews { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.quote { padding: 30px; }
.quote__text { margin: 0; font-size: 17px; line-height: 1.55; }
.quote__by { margin: 18px 0 0; font-size: 14px; color: var(--muted); }

/* --- press ---------------------------------------------------------------- */

.press { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
         padding: 34px 0; display: flex; align-items: center; justify-content: space-between; gap: 32px; flex-wrap: wrap; }
.press__list { display: flex; gap: 44px; align-items: center; flex-wrap: wrap; list-style: none; margin: 0; padding: 0; flex: 1 1 auto; justify-content: flex-end; }
.press__item { font-family: var(--font-display); font-size: 21px; font-weight: 600; color: color-mix(in srgb, var(--muted) 80%, var(--bg)); }

/* --- visit ---------------------------------------------------------------- */

.visit { padding: 56px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 56px; }
.visit__copy { display: flex; flex-direction: column; gap: 22px; }
.hours { display: flex; flex-direction: column; gap: 12px; margin: 0; }
.hours__row { display: flex; justify-content: space-between; gap: 20px; font-size: 16px; padding-bottom: 12px; border-bottom: 1px solid var(--band-down); }
.hours__row--on { font-weight: 600; }
.hours__d { color: var(--muted); }
.hours__t { font-weight: 500; }

/* --- faq ------------------------------------------------------------------ */

/* details/summary: the accordion works with no JavaScript at all. */
.faq { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 56px; }
.faq__item { border-top: 1px solid var(--line); padding: 22px 0; }
.faq__q {
  font-family: var(--font-display); font-size: 22px; font-weight: 600; letter-spacing: -0.01em;
  cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 20px;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after { content: "+"; color: var(--brand); font-size: 24px; line-height: 1; flex: none; }
.faq__item[open] .faq__q::after { content: "\2013"; }
.faq__q:hover { color: var(--brand-dark); }
.faq__q:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.faq__a { margin: 10px 0 0; font-size: 15px; line-height: 1.6; color: var(--muted); max-width: 60ch; }

/* --- footer --------------------------------------------------------------- */

.foot { background: var(--foot-bg); color: var(--foot-ink); padding: 72px 0 44px; }
.foot__grid { display: grid; grid-template-columns: 2fr repeat(3, minmax(0, 1fr)); gap: 48px;
              padding-bottom: 52px; border-bottom: 1px solid color-mix(in srgb, var(--foot-ink) 16%, transparent); }
.foot__about { display: flex; flex-direction: column; gap: 16px; }
.foot__mark { font-family: var(--font-display); font-size: 30px; font-weight: 800; letter-spacing: -0.02em; }
.foot__blurb { margin: 0; font-size: 15px; line-height: 1.6; color: color-mix(in srgb, var(--foot-ink) 72%, transparent); max-width: 34ch; }
.foot__col { display: flex; flex-direction: column; gap: 12px; font-size: 15px; list-style: none; margin: 0; padding: 0;
             color: color-mix(in srgb, var(--foot-ink) 72%, transparent); }
.foot__h { color: var(--foot-ink); font-weight: 600; padding-bottom: 4px; }
.foot__col a:hover { color: var(--foot-ink); }
.foot__base { display: flex; justify-content: space-between; gap: 24px; padding-top: 26px; font-size: 13px;
              color: color-mix(in srgb, var(--foot-ink) 52%, transparent); flex-wrap: wrap; }

/* the two lines the guards enforce. Never hide these. */
.disclaimer { font-size: 13px; line-height: 1.6; }

/* --- inner pages ---------------------------------------------------------- */

.phead { padding: 76px 0 52px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 56px; align-items: end; }
.phead__intro { font-size: 17px; line-height: 1.6; color: var(--ink-dim); padding-bottom: 10px; margin: 0; }

.grid3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px; }
.grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 64px; }

.list__row { display: flex; justify-content: space-between; gap: 24px; padding: 18px 0; border-bottom: 1px solid var(--line); }
.list__name { font-family: var(--font-display); font-size: 20px; font-weight: 600; margin: 0; }
.list__note { margin: 4px 0 0; font-size: 14px; color: var(--muted); }
.list__price { font-size: 17px; font-weight: 600; flex: none; }

.note {
  background: var(--band-down); border-radius: var(--r-card);
  padding: 34px 40px; display: flex; gap: 28px; align-items: center;
}
.note__icon { width: 26px; height: 26px; flex: none; color: var(--muted); }
.note__p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--ink-dim); }

.band {
  background: var(--ink); color: var(--bg); padding: 72px 0;
}
.band__in { display: flex; align-items: center; justify-content: space-between; gap: 48px; flex-wrap: wrap; }
.band__p { margin: 12px 0 0; font-size: 16px; color: var(--on-dark); }

.map {
  height: 340px; border-radius: 20px; background: var(--band-down);
  outline: 1px solid var(--line); outline-offset: -1px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  color: var(--muted);
}
.map__label { font-size: 15px; font-weight: 600; letter-spacing: .06em; }

.getting { display: flex; flex-direction: column; gap: 20px; }
.get { padding: 30px 34px; display: flex; gap: 20px; align-items: flex-start; }
.get__icon { width: 42px; height: 42px; border-radius: var(--pill); background: var(--band-down);
             display: flex; align-items: center; justify-content: center; flex: none; color: var(--brand); }
.get__h { font-family: var(--font-display); font-size: 21px; font-weight: 600; margin: 0 0 6px; }
.get__p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--muted); }

.hire { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); background: var(--ink); color: var(--bg); }
.hire__copy { padding: 80px var(--gutter); display: flex; flex-direction: column; justify-content: center; gap: 22px;
              padding-left: max(var(--gutter), calc((200% - var(--maxw)) / 2)); }
.hire__img { width: 100%; height: 100%; object-fit: cover; min-height: 460px; }

.contact { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px; }
.contact__v { font-family: var(--font-display); font-size: 26px; font-weight: 600; letter-spacing: -0.01em; }

.tl { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.tl__item { padding: 34px; display: flex; flex-direction: column; gap: 12px; }
.tl__when { color: var(--brand); }
.tl__h { font-family: var(--font-display); font-size: 26px; font-weight: 600; margin: 0; }
.tl__p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--muted); }

.pull { font-family: var(--font-display); font-size: clamp(28px, 3vw, 44px); font-weight: 600;
        line-height: 1.22; letter-spacing: -0.02em; max-width: 22ch; margin: 0; }
.pull--wide { max-width: 1000px; }

.cols2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 64px; }
.cols2 p { margin: 0 0 1.1em; font-size: 17px; line-height: 1.7; color: color-mix(in srgb, var(--ink) 88%, transparent); }
.cols2 p:last-child { margin-bottom: 0; }

.statband { background: var(--ink); color: var(--bg); padding: 72px 0; }
.statband__grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 32px; }
.statband .stat__n { font-size: 60px; }
.statband .stat__l { font-size: 14px; padding-top: 10px; line-height: 1.5; }

/* --- the promo card ------------------------------------------------------- */

/* Hours-aware, not timed: it says something true about right now, off the same
   data the open/closed pill reads. Hidden until the script decides to show it,
   so it can never appear in an export capture. */
.promocard {
  position: fixed; left: 24px; bottom: 24px; z-index: 60; width: min(400px, calc(100% - 48px));
  padding: 24px 26px; border-radius: var(--r-card);
  background: var(--surface); color: var(--ink);
  outline: 1px solid var(--line); outline-offset: -1px;
  box-shadow: 0 20px 46px color-mix(in srgb, var(--ink) 18%, transparent);
  display: none;
}
.promocard.is-on { display: block; animation: rise .34s var(--ease) both; }
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.promocard__x {
  position: absolute; top: 10px; right: 10px; width: 44px; height: 44px;
  border: 0; background: none; color: var(--muted); font-size: 20px; cursor: pointer; border-radius: var(--pill);
}
.promocard__x:hover { color: var(--ink); }
.promocard__x:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; }
.promocard__kicker { display: flex; align-items: center; gap: 9px; padding-bottom: 10px; }
.promocard__h { font-family: var(--font-display); font-size: 25px; font-weight: 600; line-height: 1.15; margin: 0 0 8px; letter-spacing: -0.01em; }
.promocard__p { margin: 0 0 16px; font-size: 14.5px; line-height: 1.55; color: var(--muted); }

/* --- motion --------------------------------------------------------------- */

/* The hidden state only ever applies when the script has set .js on <html>.
   No JS -> no hidden state -> the page renders complete. The failure mode is
   "no animation", never "no content". */
.js .reveal { opacity: 0; transform: translateY(10px); }
.js .reveal.is-in { opacity: 1; transform: none; transition: opacity .4s var(--ease-out), transform .4s var(--ease-out); }

/* --- the hero -------------------------------------------------------------
   CSS ANIMATION, NOT THE JS REVEAL. Everything else on the page is hidden by a
   `.js` class and un-hidden when the observer says the visitor has reached it -
   correct for content below the fold, and wrong here. site.js is deferred, so
   gating the hero on it means the headline - the LCP element - is invisible
   until the script has downloaded and run. An entrance is not worth delaying
   the first thing anyone reads.

   A keyframe animation off the render-blocking stylesheet has no such gap: it
   starts at first paint, and it still plays with JS broken, blocked or slow.
   Kept under a third of a second from first line to last. */
@media (prefers-reduced-motion: no-preference) {
  [data-reveal="hero"] > * { animation: hero-in .45s var(--ease-out) both; }
  [data-reveal="hero"] > *:nth-child(1) { animation-delay: .04s; }
  [data-reveal="hero"] > *:nth-child(2) { animation-delay: .09s; }
  [data-reveal="hero"] > *:nth-child(3) { animation-delay: .14s; }
  [data-reveal="hero"] > *:nth-child(4) { animation-delay: .19s; }
  [data-reveal="hero"] > *:nth-child(5) { animation-delay: .24s; }

  /* The photograph comes up under the type rather than beside it, so the eye
     gets the headline first. No travel: a full-bleed panel has nowhere to slide
     from, and a crop shifting on load reads as a layout bug. */
  [data-reveal="hero-media"] { animation: hero-fade .6s var(--ease-out) .1s both; }
}

@keyframes hero-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
@keyframes hero-fade { from { opacity: 0; } to { opacity: 1; } }

/* The drift script writes scale(1.06) on its very first frame. Declaring that
   as the resting scale here is what stops the image jumping 6% the moment JS
   runs - the inline transform it sets at scroll 0 is now identical to this. */
.js .hero__img { transform: translate3d(0, 0, 0) scale(1.06); }
/* on screen at load: no fade, it is already there */
.js .reveal.is-now { transition: none; }

/* Capture: screenshot.js and export-assets.js set this so a half-revealed page
   never lands in an exported carousel slide. */
html[data-capture] .reveal,
html[data-capture] .reveal.is-in { opacity: 1 !important; transform: none !important; }
html[data-capture] [data-reveal="hero"] > *,
html[data-capture] [data-reveal="hero-media"] { animation: none !important; opacity: 1 !important; transform: none !important; }
html[data-capture] .promocard { display: none !important; }
html[data-capture] .tick__row { animation: none !important; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .js .reveal { opacity: 1; transform: none; }
  .fcard:nth-child(n) { transform: none; }
}

/* --- responsive ----------------------------------------------------------- */

@media (max-width: 1100px) {
  :root { --gutter: 40px; }
  .ways, .reviews, .grid3, .tl, .contact { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .statband__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  :root { --gutter: 24px; }
  body { font-size: 16px; }

  .nav__in { gap: 16px; min-height: 64px; }
  .nav__mark { font-size: 20px; }
  .nav__cta .btn span.nav__num { display: none; }

  .hero, .craft, .week, .hire, .visit, .phead, .grid2, .cols2, .faq { grid-template-columns: minmax(0, 1fr); }
  .hero__copy { padding: 32px var(--gutter) 28px; min-height: 0; gap: 18px; }
  .hero__img, .craft__media { min-height: 0; height: 240px; }
  .hero__cta { flex-direction: column; align-items: stretch; }
  .hero__cta .btn { justify-content: center; }

  .craft { display: flex; flex-direction: column-reverse; }
  .craft__copy { padding: 36px var(--gutter) 44px; }
  .stats { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
  .stat__n { font-size: 32px; }

  .week__copy { padding: 32px 26px; }
  .week__img { min-height: 200px; }

  .sec { padding: 44px 0; }
  .sec__head { padding-bottom: 24px; }
  .ways, .reviews, .grid3, .tl, .contact, .gallery, .statband__grid { grid-template-columns: minmax(0, 1fr); }
  .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .shot { height: 160px; }

  .fcard { width: 244px; }
  .fcard__img { height: 148px; }

  .visit { padding: 28px; gap: 28px; }
  .hire__copy { padding: 36px var(--gutter) 44px; }
  .hire__img { min-height: 220px; }
  .foot__grid { grid-template-columns: minmax(0, 1fr); gap: 28px; padding-bottom: 28px; }
  .foot { padding: 40px 0 28px; }
  .press__list { justify-content: flex-start; gap: 24px; }
  .press__item { font-size: 17px; }
  .promocard { left: 12px; right: 12px; bottom: 12px; width: auto; }
}

/* --- builder-emitted markup ------------------------------------------------
   These class names come from build-mockup.js, not from this template, so they
   are its contract and not ours to rename. Kept together so it is obvious which
   half of the stylesheet has to move if the builder's markup ever changes. */

.mark__stack { display: inline-flex; flex-direction: column; line-height: .92; }
.mark__text { font-family: var(--font-display); font-weight: 800; letter-spacing: -0.02em; }
.mark__sub { font-size: .46em; letter-spacing: .12em; font-weight: 600; color: var(--brand); }

.muted { color: var(--muted); }

/* trust badges in the hero fact row */
.fact--icon { display: inline-flex; align-items: center; gap: 8px; }
.fact__icon { width: 16px; height: 16px; flex: none; color: var(--muted); }

/* featured cards on the rail */

/* the three ways cards are numbered by the builder */

.stat { display: block; }

/* an hours row for a day they are shut */
.closed { color: var(--muted); }
.hero__title { max-width: 14ch; }
.quote__stars { color: var(--brand); font-size: 14px; letter-spacing: .1em; display: block; padding-bottom: 10px; }

/* --- fixes found by the audit ---------------------------------------------
   Every one of these came out of `audit-page.js` across seven widths, not out
   of looking at the page. */

/* 44px hit targets. A footer link at 29px is a link most thumbs miss. */
.foot__col a, .nav__mark { display: inline-flex; align-items: center; min-height: 44px; }
.foot__col { gap: 0; }

@media (max-width: 860px) {
  /* The nav CTA pair is 317px of buttons and will not shrink, which pushed a
     41px horizontal scroll at 390 and 71px at 360. On a phone the number and
     the call button say the same thing, so keep one. */
  .nav__cta .btn--ghost { display: none; }
  .nav__cta .btn { padding: 11px 18px; }
}
.nav__links a { min-height: 44px; display: inline-flex; align-items: center; }

/* --- menu page -------------------------------------------------------------
   .cat/.item/.menu__* are the builder's names again. .cat is sized to 44px
   deliberately: it is 22-24px in template 1, which is the one real tap-target
   failure that template carries, and there is no reason to inherit it. */

/* MENU_CATS emits bare <li>s, which render a marker outside a list. */
.cats { display: flex; gap: 10px; flex-wrap: wrap; padding: 0 0 48px; list-style: none; }
.cats li { list-style: none; display: block; }
.cat { border: 0; background: none; font: inherit; cursor: pointer; }
.cat {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 12px 26px; border-radius: var(--pill);
  font-size: 15px; font-weight: 500;
  outline: 1px solid color-mix(in srgb, var(--ink) 26%, transparent); outline-offset: -1px;
}
.cat:hover { outline-color: var(--ink); }
.cat--on { background: var(--ink); color: var(--bg); outline-color: var(--ink); }
.cat:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

.menu__section { padding-bottom: 64px; }
.menu__h { font-family: var(--font-display); font-size: clamp(28px, 3vw, 42px); font-weight: 800;
           letter-spacing: -0.025em; margin: 0 0 26px; display: flex; align-items: center; gap: 14px; }
.menu__items { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 56px; list-style: none; margin: 0; padding: 0; }

.item { display: block; padding: 18px 0; border-bottom: 1px solid var(--line); }
.item__top { display: flex; align-items: baseline; gap: 10px; margin: 0; }
/* the dotted leader between name and price. The builder emits an empty span for it. */
.item__lead { flex: 1 1 auto; min-width: 18px; border-bottom: 1px dotted color-mix(in srgb, var(--muted) 55%, transparent); transform: translateY(-4px); }
.item__name { flex: none; font-family: var(--font-display); font-size: 20px; font-weight: 600; margin: 0; letter-spacing: -0.01em; }
.item__desc { margin: 5px 0 0; max-width: 52ch; font-size: 14px; line-height: 1.5; color: var(--muted); }
.item__price { font-size: 17px; font-weight: 600; flex: none; color: var(--brand); }
.item__tags { display: inline-flex; gap: 6px; flex: none; list-style: none; margin: 0; padding: 0; }

/* --- visit page ------------------------------------------------------------ */

.grid2--tight { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; align-items: start; }
.visit__hours { padding: 44px; }
.visit__hours .h4 { padding-bottom: 26px; }

@media (max-width: 860px) {
  .menu__items { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .grid2--tight { grid-template-columns: minmax(0, 1fr); }
  .visit__hours { padding: 28px; }
  .menu__section { padding-bottom: 40px; }
}
.contact__v { display: inline-flex; align-items: center; min-height: 44px; }

/* --- wide screens ----------------------------------------------------------
   Above the artboard width the container grows rather than leaving the page
   marooned in the middle of a 1920 monitor. */
@media (min-width: 1600px) { :root { --maxw: 1440px; --gutter: 72px; } }
@media (min-width: 1800px) { :root { --maxw: 1560px; --gutter: 80px; } }
@media (min-width: 2100px) { :root { --maxw: 1720px; } }

/* --- the two card components, rewritten against the builder's real markup ----
   Both are <li>/<div> the builder emits, and neither carries a .card class, so
   the card treatment has to be applied here or they render as loose images and
   text floating on the page background.

   fcard markup is:
     li.fcard > img.fcard__img
              > div.fcard__body > span.fcard__dot, h3.fcard__name,
                                  p.fcard__price, a.fcard__cta
   There is no __top wrapper: name and price are stacked siblings. */

.ways { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; list-style: none; margin: 0; padding: 0; }

.util {
  background: var(--surface); outline: 1px solid var(--line); outline-offset: -1px;
  border-radius: var(--r-card); overflow: hidden; list-style: none;
  display: flex; flex-direction: column;
}
.util__img { width: 100%; height: 190px; object-fit: cover; }
.util > div { padding: 28px 30px 32px; }
.util__h { font-family: var(--font-display); font-size: 24px; font-weight: 600; letter-spacing: -0.01em; margin: 0 0 8px; }
.util__p { margin: 0; font-size: 15px; line-height: 1.55; color: var(--muted); }

.rail { list-style: none; margin: 0; padding: 0 0 8px; }

.fcard {
  width: 300px; flex: none; list-style: none; overflow: hidden;
  background: var(--surface); outline: 1px solid var(--line); outline-offset: -1px;
  border-radius: var(--r-card); scroll-snap-align: start;
  display: flex; flex-direction: column;
  transition: transform .28s var(--ease), box-shadow .28s ease;
}
.fcard:nth-child(4n+1) { transform: rotate(-1.6deg); }
.fcard:nth-child(4n+2) { transform: rotate(1.1deg); }
.fcard:nth-child(4n+3) { transform: rotate(-0.8deg); }
.fcard:nth-child(4n+4) { transform: rotate(1.7deg); }
.fcard:hover, .fcard:focus-within {
  transform: rotate(0deg) translateY(-6px);
  box-shadow: 0 18px 40px color-mix(in srgb, var(--ink) 14%, transparent);
}
.fcard__img { width: 100%; height: 190px; object-fit: cover; flex: none; }
/* An item with no photo still has to be the same card, not a collapsed one. */
.fcard__img--none { display: block; height: 190px; background: var(--band-down); }
.fcard__body { padding: 22px; display: flex; flex-direction: column; gap: 6px; flex: 1 1 auto; }
.fcard__dot { width: 8px; height: 8px; border-radius: var(--pill); background: var(--muted); display: block; }
.fcard__dot--veg { background: var(--accent); }
.fcard__name { font-family: var(--font-display); font-size: 23px; font-weight: 600; letter-spacing: -0.01em; margin: 0; }
.fcard__price { margin: 0; font-size: 17px; font-weight: 600; color: var(--brand); }
.fcard__cta { margin-top: auto; padding-top: 12px; font-size: 14px; font-weight: 600; display: inline-flex; align-items: center; min-height: 44px; }
.fcard__cta:hover { color: var(--brand); }

@media (max-width: 1100px) { .ways { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 860px)  { .ways { grid-template-columns: minmax(0, 1fr); } .fcard { width: 244px; } .fcard__img, .fcard__img--none { height: 148px; } }

/* --- spec alignment --------------------------------------------------------
   Found by comparing the built page against design/pizza/spec section by section. */

/* The spec's "how it works" cards are numbered 01/02/03 with no photograph.
   The builder always emits a photo slot, so the count is a CSS counter and the
   image is dropped in this context only - the story page still uses the photos. */
.ways { counter-reset: way; }
.ways .util { counter-increment: way; padding: 34px 30px 32px; }
.ways .util__img { display: none; }
.ways .util::before {
  content: "0" counter(way);
  font-family: var(--font-display); font-size: 40px; font-weight: 800;
  color: var(--brand); line-height: 1; display: block; padding-bottom: 14px;
}
.ways .util > div { padding: 0; }

/* name and price share a row, description beneath */
.fcard__body { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: 4px 12px; }
.fcard__name { grid-column: 1; }
.fcard__price { grid-column: 2; grid-row: 1; }
.fcard__note { grid-column: 1 / -1; margin: 4px 0 0; font-size: 14px; line-height: 1.5; color: var(--muted); }

/* the note beside a section heading, right-aligned on the spec */
.sec__note { margin: 0; font-size: 15px; line-height: 1.55; color: var(--muted); max-width: 34ch; text-align: right; align-self: flex-end; }

/* the spec's FAQ has no +/- marker: the question is the affordance */
.faq__q::after { content: none; }
.faq__q { display: block; }
@media (max-width: 860px) { .sec__note { text-align: left; } }

/* --- reviews, rating and hours, against the builder's real markup ------------
   REVIEWS emits <li class="quote"> with .quote__stars/.quote__text/.quote__by.
   HOURS_ROWS emits <dt>/<dd> pairs, NOT rows - the .hours__row rules above never
   matched anything. RATING_SUMMARY is one string with the number in <strong>. */

.reviews { list-style: none; margin: 0; padding: 0; }
.quote {
  background: var(--surface); outline: 1px solid var(--line); outline-offset: -1px;
  border-radius: var(--r-card); padding: 30px; list-style: none;
  display: flex; flex-direction: column; gap: 14px;
}
.quote__stars { display: none; }              /* the spec's cards carry no stars */
.quote__text { margin: 0; font-size: 17px; line-height: 1.55; quotes: "“" "”"; }
.quote__text::before { content: open-quote; }
.quote__text::after  { content: close-quote; }
.quote__by { margin: 0; font-size: 14px; color: var(--muted); }

/* "4.7" large, the rest small and grey, from one string */
.rating { align-items: baseline; gap: 12px; }
.rating__n { font-family: var(--font-body); font-size: 16px; font-weight: 400; color: var(--muted); letter-spacing: 0; }
.rating__n strong {
  font-family: var(--font-display); font-size: 46px; font-weight: 800;
  letter-spacing: -0.025em; color: var(--ink); margin-right: 8px;
}

.hours { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0; margin: 0; }
.hours dt, .hours dd {
  margin: 0; font-size: 16px; padding: 12px 0;
  border-bottom: 1px solid var(--band-down);
}
.hours dt { color: var(--muted); }
.hours dd { font-weight: 500; text-align: right; }
.hours dd.closed { color: var(--muted); font-weight: 400; }

/* GALLERY and CRAFT_STATS emit bare <li>. The <li> IS the tile - there is no
   .shot class to hang the treatment on. */
.gallery { list-style: none; margin: 0; padding: 0; }
.gallery li { border-radius: 14px; overflow: hidden; height: 260px; background: var(--band-down); list-style: none; }
.gallery img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s var(--ease); }
.gallery li:hover img { transform: scale(1.05); }

.stats, .statband__grid { list-style: none; margin: 0; padding: 0; }
.stat { list-style: none; }
.stat__n { margin: 0; }
.stat__l { margin: 6px 0 0; }
@media (max-width: 860px) { .gallery li { height: 160px; } }
.hero__facts { list-style: none; margin: 0; padding-top: 8px; }
.hero__facts > * { list-style: none; }
.rail { display: flex; gap: 28px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; }
.rail::-webkit-scrollbar { display: none; }

/* --- mobile navigation -----------------------------------------------------
   The links were hidden at 860 with a .nav__burger that does not exist in the
   markup, so a phone had no way to reach Menu, The oven or Visit at all.

   A scrollable row instead of a drawer: nothing is hidden, there is no toggle
   state to get wrong, and it needs no JavaScript. */
@media (max-width: 860px) {
  .nav__in { flex-wrap: wrap; row-gap: 0; padding-bottom: 6px; }
  .nav__mark { order: 1; }
  .nav__cta { order: 2; margin-left: auto; }
  .nav__links {
    order: 3; flex: 1 0 100%; gap: 20px; overflow-x: auto;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
    margin: 0 calc(var(--gutter) * -1); padding: 0 var(--gutter) 4px;
  }
  .nav__links::-webkit-scrollbar { display: none; }
  .nav__links li { flex: none; }
  .nav__links a { min-height: 44px; white-space: nowrap; font-size: 14px; }
}

/* ===========================================================================
   MOTION
   Transform and opacity only - the two things the compositor can animate
   without re-laying out the page. Everything is off under
   prefers-reduced-motion and under [data-capture].
   =========================================================================== */

/* --- staggered children ---------------------------------------------------
   The section fades up as a whole; its cards follow one after another. --i is
   written by site.js; the rhythm stays here.

   ONE FADE PER ELEMENT. The children slide, they do not fade: a card inside a
   section that is itself fading gets both opacities multiplied together, so it
   sits under 20% for most of the transition and the whole band reads as washed
   out rather than as arriving. The section owns the fade; the stagger owns the
   travel, and the cascade is legible because it is the only thing moving. */
.js .reveal [data-stagger] > * {
  transform: translateY(16px);
}
.js .reveal.is-in [data-stagger] > * {
  transform: none;
  transition: transform .42s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 45ms);
}
/* on screen at load: no fade, it is already there */
.js .reveal.is-now,
.js .reveal.is-now [data-stagger] > * { transition: none; }

/* images wipe up from their frame rather than fading */
.js .reveal [data-stagger] > * > img,
.js .reveal .hero__img { will-change: transform; }
.js .reveal.is-in .gallery li { overflow: hidden; }

/* --- hover ----------------------------------------------------------------
   Every interactive thing answers the pointer. */

/* nav: the underline sweeps in from the left rather than appearing */
.nav__links a { position: relative; border-bottom: 0; }
.nav__links a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 2px; height: 2px;
  background: var(--brand); transform: scaleX(0); transform-origin: left;
  transition: transform .3s var(--ease);
}
.nav__links a:hover::after { transform: scaleX(1); }
.nav__links [aria-current="page"]::after { transform: scaleX(1); }

/* buttons lean toward the pointer (--mx/--my come from site.js) and lift */
.btn { transform: translate(var(--mx, 0), var(--my, 0)); }
.btn:hover { transform: translate(var(--mx, 0), calc(var(--my, 0px) - 2px)); }
.btn--brand { position: relative; overflow: hidden; z-index: 0; }
.btn--brand::before {
  content: ""; position: absolute; inset: 0; z-index: -1; background: var(--brand-dark);
  transform: translateY(101%); transition: transform .34s var(--ease);
}
.btn--brand:hover::before { transform: translateY(0); }

.rail__btn { transform: translate(var(--mx, 0), var(--my, 0)); transition: transform .18s ease, background-color .2s ease; }

/* menu rows: the leader fills toward the price */
.item { transition: background-color .25s ease; }
.item:hover { background: color-mix(in srgb, var(--band-down) 55%, transparent); }
.item:hover .item__lead { border-bottom-color: var(--brand); }
.item:hover .item__price { color: var(--brand-dark); }

/* gallery tiles */
.gallery li { transition: transform .4s var(--ease); }
.gallery li:hover { transform: translateY(-4px); }

/* press names come forward */
.press__item { transition: color .25s ease; }
.press__item:hover { color: var(--ink); }

/* the marquee slows when you look at it */
.tick:hover .tick__row { animation-play-state: paused; }

/* --- custom cursor --------------------------------------------------------
   Built by site.js and only on a real mouse: (hover: hover) and
   (pointer: fine). The native cursor is hidden by .has-cursor, which the same
   code adds, so if any of it fails the visitor still has a pointer. */
.cur {
  position: fixed; top: 0; left: 0; z-index: 90; pointer-events: none;
  border-radius: var(--pill); mix-blend-mode: difference;
  transition: width .25s var(--ease), height .25s var(--ease), opacity .2s ease;
}
.cur--dot { width: 7px; height: 7px; background: #fff; }
.cur--ring { width: 34px; height: 34px; border: 1.5px solid #fff; }
.cur--ring.is-hot { width: 62px; height: 62px; border-width: 1px; }
.cur--dot.is-hot { opacity: 0; }
.cur--ring.is-down { width: 26px; height: 26px; }
.has-cursor.cur-out .cur { opacity: 0; }

/* Hide the native cursor only where the custom one is live, and never on a
   text field - typing without a caret cursor is hostile. */
.has-cursor, .has-cursor a, .has-cursor button, .has-cursor summary { cursor: none; }
.has-cursor input, .has-cursor textarea, .has-cursor select { cursor: auto; }

@media (prefers-reduced-motion: reduce) {
  .cur { display: none; }
  .has-cursor, .has-cursor a, .has-cursor button, .has-cursor summary { cursor: auto; }
  .js .reveal [data-stagger] > * { opacity: 1; transform: none; }
  .nav__links a::after { transition: none; }
  .btn { transform: none; }
}
html[data-capture] .cur { display: none !important; }
html[data-capture] .reveal [data-stagger] > * { opacity: 1 !important; transform: none !important; }
