/* ==========================================================================
   King Food — tokens
   Inspired by "Selva" reference video: cinematic dark/cream rhythm,
   typographic wordmark instead of a logo mark, circular food photography.
   ========================================================================== */
:root {
  --ink: #0d0d0b;
  --ink-2: #17160f;
  --ink-3: #201f16;
  --cream: #efe7d8;
  --text-muted: #b7ad9c;
  --text-faint: #8a8171;
  --gold: #d9a66c;
  --gold-deep: #b97f49;
  --gold-soft: rgba(217, 166, 108, 0.16);
  --sage: #9ab356;
  --sage-deep: #5f6e39;
  --line: rgba(239, 231, 216, 0.12);

  --font-display: "Bodoni Moda", "Times New Roman", serif;
  --font-body: "Jost", "Segoe UI", sans-serif;

  --container: 1240px;
  --radius-pill: 999px;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --header-height: 68px;
}

@media (min-width: 768px) {
  :root { --header-height: 80px; }
}

/* ==========================================================================
   Reset / base
   ========================================================================== */
* { box-sizing: border-box; }

:root { color-scheme: dark; }

#menu, #histoire, #contact {
  scroll-margin-top: var(--header-height);
}

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--cream);
  font-family: var(--font-body);
  font-weight: 300;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, video, svg { max-width: 100%; }
img { display: block; }
a { color: inherit; text-decoration: none; }
p { margin: 0; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 500;
  margin: 0;
  color: var(--cream);
}

.italic-gold {
  font-style: italic;
  color: var(--gold);
}

/* Standard visually-hidden pattern: present in the DOM/raw text (for
   screen readers and plain-text extractors) but never rendered. Used on
   the menu to keep each dish's name and price together as one text unit
   for tools that read the name/price/description spans as unconnected
   fragments — the visible layout that already displays them separately
   is untouched. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 clamp(1.25rem, 4vw, 2.5rem);
}

.line { display: block; overflow: hidden; }
.line span { display: block; }

/* ==========================================================================
   Preloader
   ========================================================================== */
.preloader {
  position: fixed;
  inset: 0;
  z-index: 500;
  background: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.6s var(--ease-out), visibility 0.6s var(--ease-out);
}

.preloader.done {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.preloader-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.4rem;
}

.preloader-word {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 5vw, 2.6rem);
  color: var(--cream);
  letter-spacing: 0.01em;
}

.preloader-word em {
  font-style: italic;
  color: var(--sage);
}

.preloader-bar {
  width: 160px;
  height: 1px;
  background: var(--line);
  overflow: hidden;
}

.preloader-bar span {
  display: block;
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--sage), var(--gold));
}

/* ==========================================================================
   Custom cursor (hover-capable pointers only)
   ========================================================================== */
.cursor-dot, .cursor-ring {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 300;
  transform: translate3d(-50%, -50%, 0);
  will-change: transform;
  opacity: 0;
  transition: opacity 0.3s var(--ease-out);
}

.cursor-dot {
  width: 6px;
  height: 6px;
  background: var(--gold);
  border-radius: 50%;
}

.cursor-ring {
  width: 38px;
  height: 38px;
  border: 1px solid rgba(239, 231, 216, 0.55);
  border-radius: 50%;
  mix-blend-mode: difference;
  transition: opacity 0.3s var(--ease-out), width 0.4s var(--ease-out),
    height 0.4s var(--ease-out), background 0.4s var(--ease-out), border-color 0.4s var(--ease-out);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.cursor-ring span {
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.3s var(--ease-out), transform 0.3s var(--ease-out);
  white-space: nowrap;
}

body.cursor-ready .cursor-dot, body.cursor-ready .cursor-ring { opacity: 1; }

body.cursor-hover .cursor-ring {
  width: 62px;
  height: 62px;
  background: rgba(239, 231, 216, 0.14);
  border-color: rgba(239, 231, 216, 0.85);
}

body.cursor-label .cursor-ring {
  width: 96px;
  height: 96px;
  background: var(--cream);
  border-color: var(--cream);
  mix-blend-mode: normal;
}

body.cursor-label .cursor-ring span { opacity: 1; transform: translateY(0); }
body.cursor-label .cursor-dot { opacity: 0; }

@media (hover: none), (prefers-reduced-motion: reduce) {
  .cursor-dot, .cursor-ring { display: none; }
}

body.cursor-ready, body.cursor-ready * { cursor: none; }

/* ==========================================================================
   Word-split gilded reveal (plain section titles only — see main.js)
   ========================================================================== */
.word {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
}

.word span {
  display: inline-block;
  background: linear-gradient(90deg, var(--cream) 0%, var(--cream) 45%, var(--gold) 50%, var(--cream) 55%, var(--cream) 100%);
  background-size: 220% 100%;
  background-position: 100% 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  transition: background-position 1.2s var(--ease-out);
}

.word.gilded span { background-position: 0 0; }

/* ==========================================================================
   Progress bar + scroll track dot
   ========================================================================== */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  height: 2px;
  width: 100%;
  background: linear-gradient(90deg, var(--sage), var(--gold));
  transform: scaleX(0);
  transform-origin: left center;
  z-index: 200;
}

.scroll-track {
  position: fixed;
  top: 14vh;
  right: 1.6rem;
  height: 72vh;
  width: 1px;
  background: var(--line);
  z-index: 150;
  display: none;
}

.scroll-track-dot {
  position: absolute;
  top: 0;
  left: 50%;
  margin-left: -3.5px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 10px 2px rgba(217, 166, 108, 0.55);
  will-change: transform;
}

@media (min-width: 1080px) and (hover: hover) {
  .scroll-track { display: block; }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-track { display: none; }
}

.chapter-indicator {
  position: fixed;
  left: 1.6rem;
  bottom: 1.8rem;
  z-index: 150;
  display: none;
  flex-direction: column;
  gap: 0.55rem;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out);
  pointer-events: none;
}

.chapter-indicator.is-visible { opacity: 1; transform: translateY(0); }

.chapter-label {
  font-family: var(--font-body);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.55);
  white-space: nowrap;
}

.chapter-track {
  position: relative;
  display: block;
  width: 74px;
  height: 1px;
  background: var(--line);
}

.chapter-fill {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 20%;
  background: linear-gradient(90deg, var(--sage), var(--gold));
  transition: width 0.5s var(--ease-out);
}

@media (min-width: 900px) {
  .chapter-indicator { display: flex; }
}

@media (prefers-reduced-motion: reduce) {
  .chapter-indicator { display: none; }
}

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.95rem 1.9rem;
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
  font-size: 0.92rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
  touch-action: manipulation;
  /* transform deliberately excluded: every .btn carries [data-magnetic],
     which writes `transform` itself every pointermove via gsap.quickTo.
     A CSS transition on the same property would re-intercept each of
     those per-frame writes and re-ease them, fighting GSAP's own
     smoothing and reading as laggy/rubber-banded instead of magnetic. */
  transition: box-shadow 0.4s var(--ease-out), background 0.4s var(--ease-out);
}

.btn-primary {
  background: linear-gradient(135deg, var(--gold) 0%, var(--gold-deep) 100%);
  color: #17160f;
  font-weight: 500;
}

.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 14px 30px -12px rgba(217, 166, 108, 0.55); }

.btn-ghost {
  background: rgba(13, 13, 11, 0.35);
  border: 1px solid rgba(239, 231, 216, 0.55);
  color: var(--cream);
  backdrop-filter: blur(6px);
}

.btn-ghost:hover { border-color: var(--gold); color: var(--gold); transform: translateY(-2px); }

.btn-lg { padding: 1.05rem 2.3rem; font-size: 1rem; }

.pill-btn {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0.6rem 1.3rem;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(239, 231, 216, 0.4);
  font-size: 0.82rem;
  letter-spacing: 0.03em;
  color: var(--cream);
  touch-action: manipulation;
  transition: border-color 0.3s var(--ease-out), color 0.3s var(--ease-out), background 0.3s var(--ease-out);
}

.pill-btn:hover { border-color: var(--gold); color: var(--ink); background: var(--gold); }

/* ==========================================================================
   Brand wordmark (replaces the logo image everywhere on the site)
   ========================================================================== */
.brand-word {
  font-family: var(--font-display);
  font-size: 1.3rem;
  letter-spacing: 0.01em;
  color: var(--cream);
  flex-shrink: 0;
  justify-self: start;
}

.brand-word em { font-style: italic; color: var(--sage); }

/* ==========================================================================
   Header
   ========================================================================== */
/* Always transparent, blending into whatever section sits behind it —
   no scrolled-state background/blur/border. Selva's own header never
   gains a bar; text legibility over light sections (e.g. the cream
   philosophy break) relies on each section's own scrim, same as the
   hero's ::after gradient. */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  padding: 1.1rem 0;
  padding-top: max(1.1rem, env(safe-area-inset-top));
  transition: padding 0.5s var(--ease-out);
}

.site-header.scrolled {
  padding: 0.8rem 0;
  padding-top: max(0.8rem, env(safe-area-inset-top));
}

/* The philosophy break is cream and so is the header ink — measured
   identical (rgb(239,231,216) on rgb(239,231,216), contrast 1:1), so while
   that band passes behind the fixed header the wordmark and the burger
   disappear completely. On mobile the burger is the only nav control, so
   this can't stand. Keeps the header transparent as designed — inverts its
   ink instead of adding the bar the design deliberately refuses. */
.site-header.over-light .brand-word { color: var(--ink); }
.site-header.over-light .brand-word em { color: var(--sage-deep); }
.site-header.over-light .nav-desktop a { color: rgba(13, 13, 11, 0.72); text-shadow: none; }
.site-header.over-light .nav-desktop a:hover { color: var(--gold-deep); }
.site-header.over-light .nav-toggle span { background: var(--ink); }
.site-header .brand-word,
.site-header .brand-word em { transition: color 0.35s var(--ease-out); }

.header-inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 clamp(1.25rem, 4vw, 2.5rem);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1.5rem;
}

.nav-desktop { display: flex; align-items: center; justify-self: center; gap: 2.4rem; }
.nav-desktop a { font-size: 0.9rem; letter-spacing: 0.03em; color: var(--text-muted); transition: color 0.3s var(--ease-out); text-shadow: 0 1px 10px rgba(0, 0, 0, 0.5); }
.nav-desktop a:hover { color: var(--gold); }
.nav-cta { justify-self: end; }

.nav-toggle {
  display: none;
  grid-column: 3;
  justify-self: end;
  width: 44px;
  height: 44px;
  border: none;
  background: transparent;
  cursor: pointer;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  flex-shrink: 0;
}

.nav-toggle span { width: 22px; height: 1.5px; background: var(--cream); transition: transform 0.35s var(--ease-out), opacity 0.35s var(--ease-out), background-color 0.35s var(--ease-out); }
.nav-toggle.open span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle.open span:nth-child(2) { opacity: 0; }
.nav-toggle.open span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* ==========================================================================
   Mobile menu
   ========================================================================== */
.mobile-menu {
  position: fixed;
  inset: 0;
  background: var(--ink);
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease-out), visibility 0.4s var(--ease-out);
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  overscroll-behavior: contain;
}

.mobile-menu.open { opacity: 1; visibility: visible; }
.mobile-menu nav { display: flex; flex-direction: column; align-items: center; gap: 1.9rem; }
.mobile-menu nav a:not(.btn) { font-family: var(--font-display); font-size: 1.8rem; color: var(--cream); }
.mobile-menu nav .btn { margin-top: 1rem; }

/* ==========================================================================
   Hero
   ========================================================================== */
/* Height is set/cleared entirely by js/hero-space.js + main.js — see the
   comment on the element in index.html. Zero by default so nothing shows
   without JS or with prefers-reduced-motion. */
#heroPinSpace { height: 0; overflow: hidden; }

.hero {
  position: relative;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  background: radial-gradient(120% 90% at 50% 12%, var(--ink-2) 0%, var(--ink) 62%);
}

/* ==========================================================================
   Hero background — a real King Food photo (1800x2700, plenty of headroom
   for a full-bleed crop at any screen size without softness), Ken-Burns
   zoomed by GSAP in lockstep with scroll; see js/main.js setupHeroKenBurns().
   Replaces an earlier real-video scrub: the source clip turned out to be
   another business's commercial footage (rights problem) and, separately,
   too low-resolution (464px wide) to fill a wide desktop hero without
   visible upscale softness — a still shot at this resolution has neither
   problem and still gets scroll-synced motion via the zoom. */
.hero-media-layer {
  /* top/left/right + height:100dvh, not inset:0 — .hero only sets
     min-height:100dvh and can end up taller than one viewport on short
     windows (hero-content's own text stacks past 100dvh there), and
     .hero-media-layer must not inherit that inflated height or the
     image sizes itself against a box bigger than what's actually
     visible, forcing it needlessly smaller within the real viewport. */
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 100dvh;
  z-index: 0;
  overflow: hidden;
  background: var(--ink);
}

.hero-media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* This shot is very tall (1800x2700) against a wide hero — cover only
     ever shows roughly the middle third of it, and that window barely
     moves as the Ken Burns scale changes (the scale range in js/main.js
     is deliberately mild for the same reason). Measured on the source
     photo: bun crown ~28-42%, cheese/patty ~42-58%, board/fries from
     ~60%. 48% centres the window on the cheese pull with bun above and
     the top of the fries just entering frame — reads as "burger", not
     "bread texture", at any crop severity. */
  object-position: center 48%;
}

/* Mobile-only frame-sequence scrub — replaces the Ken Burns photo below
   900px with the real King Food video, drawn frame-by-frame to canvas
   instead of a <video> element. Research before building this (GSAP's
   own forum, several 2026 sources) confirms video.currentTime scrubbing
   is a known source of stutter/unreliable seeking specifically on mobile
   Safari, independent of encoding — a canvas image sequence sidesteps
   the video decoder entirely, which is the actual bottleneck. See
   setupHeroKenBurns() in js/main.js for the draw loop; on ≥900px this
   canvas never loads a single frame and .hero-media (the photo) is what
   shows, unchanged. */
.hero-scrub-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: none;
  opacity: 0;
  transition: opacity 0.4s var(--ease-out);
}
.hero-scrub-canvas.is-ready { opacity: 1; }

@media (max-width: 899px) {
  .hero-scrub-canvas { display: block; }
}

.hero-media-layer::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(13, 13, 11, 0.55) 0%, rgba(13, 13, 11, 0.2) 28%, rgba(13, 13, 11, 0.32) 56%, rgba(13, 13, 11, 0.93) 100%);
}

/* Floating food accents — small real photos drifting gently in the
   hero's own empty right-hand space (the text stack caps at 46ch and
   never reaches that far), adding a cinematic layer of motion without
   competing with the headline or the main Ken Burns photo. Desktop
   only (≥900px): tried a small repositioned-corner version on mobile
   first, but with the text stack running full width there (no empty
   column to sit in), it read as clutter rather than a cinematic touch
   — dropped there entirely rather than kept as a compromise. Same
   edge-fade treatment as the menu photos (an inset box-shadow, not a
   mask-image or a hard circle — see the menu section for why) so they
   settle into the scene instead of reading as pasted-on cards. */
.hero-floating { position: absolute; inset: 0; z-index: 1; pointer-events: none; display: none; }

.hero-float-item {
  position: absolute;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 24px 50px -18px rgba(0, 0, 0, 0.7);
  animation: hero-float 6.5s ease-in-out infinite;
}

.hero-float-item img { width: 100%; height: 100%; object-fit: cover; display: block; filter: brightness(0.95) saturate(1.04); }

.hero-float-item::after { content: ""; position: absolute; inset: 0; box-shadow: inset 0 0 26px 10px var(--ink); }

.hero-float-1 { width: clamp(100px, 8vw, 140px); aspect-ratio: 1 / 1; top: 15%; right: 9%; animation-delay: 0s; }
.hero-float-2 { width: clamp(84px, 6.5vw, 116px); aspect-ratio: 1 / 1; top: 47%; right: 21%; animation-delay: -2.2s; }
.hero-float-3 { width: clamp(76px, 6vw, 104px); aspect-ratio: 1 / 1; bottom: 17%; right: 6%; animation-delay: -4.3s; }

@keyframes hero-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-16px); }
}

@media (min-width: 900px) {
  .hero-floating { display: block; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-float-item { animation: none; }
}

.hero-content {
  position: relative;
  z-index: 2;
  width: 100%;
  padding: calc(var(--header-height) + clamp(2rem, 6vw, 4rem)) clamp(1.25rem, 4vw, 2.5rem) clamp(3rem, 7vw, 5rem);
  max-width: var(--container);
  margin: 0 auto;
  display: flex;
  align-items: center;
}

.hero-text-stack { flex: 1 1 auto; min-width: 0; max-width: 46ch; position: relative; }

/* .hero-text-alt sits in normal flow by default (below the first block,
   both fully readable) so the page stays complete without JS/GSAP. Only
   js/main.js pulls it into an absolute overlay — see setupHeroKenBurns —
   once it's actually going to animate the crossfade between the two. */
.hero-text-alt { margin-top: clamp(2.5rem, 6vw, 3.5rem); }

.hero-eyebrow {
  display: inline-block;
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 1.2rem;
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
}

.hero-word {
  font-size: clamp(3.6rem, 11vw, 8.2rem);
  line-height: 0.94;
  font-weight: 500;
  text-shadow: 0 6px 40px rgba(0, 0, 0, 0.55);
}

.hero-sub {
  margin-top: 1.8rem;
  max-width: 40ch;
  font-size: clamp(1rem, 1.6vw, 1.15rem);
  color: var(--text-muted);
  text-shadow: 0 2px 20px rgba(0, 0, 0, 0.6);
}

.hero-actions { margin-top: 2.3rem; display: flex; flex-wrap: wrap; gap: 1rem; }

.hero-scroll-hint {
  position: absolute;
  z-index: 2;
  right: clamp(1.25rem, 4vw, 2.5rem);
  bottom: clamp(5.5rem, 11vw, 7.5rem);
  width: 2px;
  height: 64px;
  background: rgba(239, 231, 216, 0.16);
  display: none;
}

.hero-scroll-hint span {
  display: block;
  width: 100%;
  height: 0%;
  background: linear-gradient(180deg, var(--gold), var(--sage));
  transform-origin: top;
}

@media (min-width: 900px) {
  .hero-scroll-hint { display: block; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-scroll-hint { display: none; }
}

.hero-bottom {
  position: relative;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  max-width: var(--container);
  margin: 0 auto;
  width: 100%;
  padding: 0 clamp(1.25rem, 4vw, 2.5rem) clamp(1.5rem, 3vw, 2.2rem);
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  color: var(--text-faint);
}

.hero-bottom-item { display: flex; align-items: center; gap: 0.5rem; }
.hero-bottom-brand { display: none; }
.hero-sep { width: 4px; height: 4px; border-radius: 50%; background: var(--text-faint); }

@media (min-width: 700px) { .hero-bottom-brand { display: flex; } }

/* ==========================================================================
   Philosophy (cream breather) — giant statement, then a framed photo +
   copy split. Selva's own accent color inside this block is sage, not
   gold: gold (#d9a66c) reads muddy against this cream, sage-deep has
   real contrast — see .italic-sage below.
   ========================================================================== */
.philosophy { position: relative; background: var(--cream); color: var(--ink); padding: clamp(4rem, 9vw, 7rem) 0; overflow: hidden; }

.philosophy-ghost {
  position: absolute;
  top: -6vw;
  right: -2vw;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(14rem, 34vw, 30rem);
  line-height: 1;
  color: rgba(13, 13, 11, 0.05);
  pointer-events: none;
  user-select: none;
  z-index: 0;
}

.philosophy-statement { position: relative; z-index: 1; margin-bottom: clamp(3rem, 7vw, 5rem); }

.section-label-row { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.6rem; }
.section-label-row .rule { flex: 1 1 auto; height: 1px; background: rgba(13, 13, 11, 0.14); }
.section-label.section-label-dark { color: var(--sage-deep); margin-bottom: 0; }

.italic-sage { font-style: italic; color: var(--sage-deep); }

.philosophy-title {
  color: var(--ink);
  font-size: clamp(1.9rem, 4.6vw, 3.2rem);
  line-height: 1.24;
  max-width: 24ch;
}

.philosophy-split {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: center;
}

.framed-photo {
  margin: 0;
  padding: 0.6rem;
  border: 1px solid rgba(13, 13, 11, 0.14);
}

/* No colour filter: these are real King Food photos and they show in
   their own colours. An earlier grayscale(0.85) treatment came from the
   editorial reference look, back when the images here were stock. */
.framed-photo img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }

.framed-photo figcaption {
  margin-top: 0.7rem;
  padding: 0 0.2rem;
  font-size: 0.8rem;
  letter-spacing: 0.03em;
  color: rgba(13, 13, 11, 0.55);
}

.philosophy-icon { color: rgba(13, 13, 11, 0.4); margin-bottom: 1.4rem; }
.philosophy-copy p { max-width: 38ch; font-size: 1.05rem; line-height: 1.65; color: rgba(13, 13, 11, 0.78); }
.philosophy-copy .link-underline { margin-top: 1.2rem; color: var(--sage-deep); border-color: rgba(95, 110, 57, 0.4); }
.philosophy-copy .link-underline:hover { color: var(--gold-deep); border-color: var(--gold-deep); }

@media (min-width: 860px) {
  .philosophy-split { grid-template-columns: 1.1fr 0.9fr; }
}

/* ==========================================================================
   Section intro block (reused by menu / gallery / contact)
   ========================================================================== */
.section-label {
  display: inline-block;
  font-size: 0.76rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sage);
  margin-bottom: 0.9rem;
}

.section-head-title { font-size: clamp(2rem, 3.8vw, 3.1rem); line-height: 1.12; }

/* ==========================================================================
   Menu — one dish at a time. Info block far left, a single modestly
   sized dish photo centered well clear of it, and a small dim preview
   of the next dish floating further right — three widely-spaced points
   rather than a tight text+photo pair, matching the reference's use of
   negative space. Controls are a full-width bar below (progress far
   left, arrows dead-center via a 3-column grid, CTA far right), not a
   side column next to the dish.
   ========================================================================== */
.menu { padding: clamp(4rem, 9vw, 6.5rem) 0; background: var(--ink); }

.menu-head-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem 3rem;
  margin-bottom: clamp(2.5rem, 6vw, 4rem);
}

.menu-head { max-width: 46ch; }
.menu-head .section-head-title { margin-top: 0.6rem; }
.menu-note { max-width: 30ch; margin-top: 0.3rem; color: var(--text-muted); font-size: 0.96rem; }

.menu-carousel { position: relative; }

/* Mobile: horizontal swipe carousel, one dish per snap-slide — the same
   "one dish at a time" experience the desktop click-through gives, just
   driven by touch scroll instead of buttons. .menu-progress below tracks
   the centered slide via IntersectionObserver (see setupMenuCarousel in
   js/main.js) instead of a click handler. Desktop (≥900px) replaces this
   with the absolute-stack crossfade further down. */
.menu-dishes {
  display: flex;
  flex-direction: row;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  gap: clamp(1.5rem, 5vw, 2.5rem);
}
.menu-dishes::-webkit-scrollbar { display: none; }

.menu-dish {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.6rem;
  text-align: center;
  flex: 0 0 100%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

/* Mobile "stories" peek: real neighbor dishes (not a decorative ghost)
   partially visible on both sides of the centered one, dimmed/scaled
   down — the ::before/::after spacers give the first/last dish the same
   room to reach dead-center as an interior one (a percentage flex-basis
   alone can't do this: it can narrow every dish, but nothing physically
   extends past the track's own edges to let dish 1 center itself with
   empty space on its left). scroll-snap-stop:normal (not "always") lets
   a fast flick glide past more than one dish in a single motion instead
   of hard-stopping at each — the actual mechanic behind a fluid
   Instagram/TikTok-stories-style swipe, requested explicitly over the
   previous one-hop-per-swipe feel. */
@media (max-width: 899px) {
  .menu-dishes { --menu-peek: clamp(34px, 11vw, 52px); }
  .menu-dishes::before,
  .menu-dishes::after {
    content: "";
    flex: 0 0 var(--menu-peek);
  }
  .menu-dish {
    flex: 0 0 calc(100% - (var(--menu-peek) * 2));
    scroll-snap-align: center;
    scroll-snap-stop: normal;
    /* Kept subtle on purpose: every dish photo already fades to near-black
       at its own edges (baked into the file, see .menu-dish-media img
       comment below) — stacking a heavy opacity/scale drop on top of that
       built-in fade left the peek all but invisible (measured: visible
       photo content only starts well past the peek width once both fades
       compound). A light touch here still reads as "dimmed" without
       erasing the sliver the wider peek above now gives it room to show. */
    opacity: 0.72;
    transform: scale(0.95);
    transition: opacity 0.4s var(--ease-out), transform 0.4s var(--ease-out);
  }
  .menu-dish.is-centered { opacity: 1; transform: scale(1); }
}

.menu-dish-media {
  width: clamp(230px, 60vw, 340px);
  aspect-ratio: 1 / 1;
  flex-shrink: 0;
}

/* The photo's own width above is tuned as a fraction of the VIEWPORT
   (60vw), sized back when each dish filled the full viewport — vw
   doesn't know the dish box above got narrower for the peek effect, so
   it kept rendering at its old size, sitting inset with empty margin on
   both sides. That margin is exactly what got exposed as the "peek"
   instead of actual neighbor photo. Filling the dish's own (now
   narrower) box makes the peek show real image content immediately.
   Declared after the rule above (same specificity) so it wins the
   cascade at these widths instead of being overridden back. */
@media (max-width: 899px) {
  .menu-dish-media { width: 100%; }
}

/* No frame at all: the fade into the section's dark background is
   baked into the image files themselves (images/menu-retouched/,
   regenerated from the originals with ffmpeg — alphamerge against a
   blurred edge mask, composited onto solid var(--ink)), not layered on
   with CSS. Three earlier CSS-only attempts (mask-image, a radial
   overlay, an inset box-shadow) each either failed to render or fought
   a given photo's own off-center composition (a circular fade cropped
   a skewer sticking up out of frame on one dish, sharp below). Baking
   the fade into the file lets it be judged per photo instead of forcing
   one geometric shape onto every composition. */
.menu-dish-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.menu-dish-info { max-width: 34ch; }
.menu-dish-eyebrow { display: block; font-size: 0.76rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--sage); margin-bottom: 0.8rem; }
.menu-dish-info h3 { font-size: clamp(1.7rem, 4vw, 2.4rem); line-height: 1.1; }
.menu-dish-info p { margin-top: 0.9rem; color: var(--text-muted); font-size: 0.98rem; }
.menu-dish-price { display: inline-block; margin-top: 1.1rem; font-family: var(--font-display); font-size: 1.15rem; color: var(--cream); }

.menu-ghost { display: none; }

/* Arrows only mean something as a click target (≥900px) — on mobile the
   swipe itself steps through dishes, so only the progress readout (now
   driven by IntersectionObserver instead of a click handler, see
   setupMenuCarousel in js/main.js) and the "see the whole menu" link
   carry over. */
.menu-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 1rem 1.5rem;
  max-width: var(--container);
  margin: clamp(2.5rem, 6vw, 4rem) auto 0;
  padding: clamp(1.5rem, 4vw, 2.2rem) clamp(1.25rem, 4vw, 2.5rem) 0;
  border-top: 1px solid var(--line);
}

.menu-progress { display: flex; align-items: center; gap: 0.7rem; font-family: var(--font-display); font-size: 0.9rem; color: var(--text-faint); }
.menu-arrows { display: flex; gap: 0.7rem; }
.menu-progress-index { color: var(--gold); }
.menu-progress-track { width: 72px; height: 1px; background: var(--line); position: relative; display: block; }
.menu-progress-fill { position: absolute; inset: 0 auto 0 0; width: 25%; background: linear-gradient(90deg, var(--sage), var(--gold)); transition: width 0.5s var(--ease-out); }
.menu-arrow {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--cream);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  touch-action: manipulation;
  transition: border-color 0.3s var(--ease-out), color 0.3s var(--ease-out), background 0.3s var(--ease-out), transform 0.15s var(--ease-out);
}
.menu-arrow svg { transition: transform 0.2s var(--ease-out); }
.menu-arrow:hover { border-color: var(--gold); color: var(--ink); background: var(--gold); }
/* :active (not just :hover) so tapping gets the same feedback touch
   devices never get from hover — a quick press-in plus the icon
   nudging a step further in its own direction, the same "subtle,
   carousel-appropriate motion" a morphing arrow button uses, built
   from tokens already on this site rather than a new import. */
.menu-arrow:active { border-color: var(--gold); color: var(--ink); background: var(--gold); transform: scale(0.88); }
#menuPrev:active svg { transform: translateX(-2px); }
#menuNext:active svg { transform: translateX(2px); }
.menu-arrow:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.menu-arrow:disabled { opacity: 0.35; cursor: default; pointer-events: none; }

@media (min-width: 900px) {
  .menu-head-row { flex-wrap: nowrap; }
  .menu-note { text-align: right; padding-top: 0.4rem; }

  .menu-dishes {
    position: relative;
    height: clamp(280px, 32vw, 400px);
    /* Reset the mobile swipe-track properties — dishes become
       position:absolute;inset:0 below, so there's nothing left to
       scroll/snap and leaving these active is inert-but-messy. */
    overflow-x: visible;
    scroll-snap-type: none;
  }

  /* No CSS transition here on purpose: opacity/filter/scale are set by
     a GSAP tween on step (see setupMenuCarousel in js/main.js), triggered
     by the arrow buttons rather than scroll. A parallel CSS transition
     would re-intercept those writes and lag behind the click — same
     reasoning documented for the buttons' own transition list below.
     The scale is the reference video's own dish-to-dish mechanic (outgoing
     shrinks+blurs, incoming grows from reduced size while sharpening),
     not a plain opacity crossfade. */
  /* Three columns, not two: info | photo | an empty spacer the same
     width as info. With only info+photo, "centering" the photo in the
     leftover space actually lands it right of the box's true center
     (the info column eats into that space unevenly) — the matching
     empty third column balances it back to the real midpoint. */
  .menu-dish {
    position: absolute;
    inset: 0;
    display: grid;
    grid-template-columns: minmax(160px, 24%) 1fr minmax(0, 24%);
    align-items: center;
    column-gap: clamp(2rem, 6vw, 4rem);
    text-align: left;
    opacity: 0;
    pointer-events: none;
    will-change: opacity, filter, transform;
  }

  .menu-dish-info { grid-column: 1; }
  .menu-dish-media { grid-column: 2; }

  .menu-dish.is-active { opacity: 1; pointer-events: auto; z-index: 2; }

  @media (prefers-reduced-motion: reduce) {
    /* JS never wires up the button-driven crossfade for reduced-motion
       users (see setupMenuCarousel), so fall back to the same static
       stacked flow mobile uses instead of leaving every dish invisible. */
    .menu-dishes { position: static; height: auto; display: flex; flex-direction: column; gap: clamp(2.5rem, 8vw, 5rem); }
    .menu-dish { position: static; opacity: 1; filter: none; pointer-events: auto; display: flex; flex-direction: row; text-align: left; }
    .menu-ghost { display: none; }
  }

  .menu-dish-media { width: clamp(210px, 19vw, 300px); justify-self: center; flex-shrink: 0; }
  .menu-dish-info { text-align: left; min-width: 0; }

  /* Reference-checked against the source video frame-by-frame (see
     project memory): both ghosts sit there, one is even partly behind
     the title/paragraph text — but at an opacity so low (measured a
     few RGB points above pure black, nowhere near a "visible photo")
     that it never fights legibility. An earlier attempt at a left ghost
     used a much higher opacity and did visibly compete with the text;
     the fix here is dimming it enough to match the source, not avoiding
     the left side altogether. */
  .menu-ghost {
    display: block;
    position: absolute;
    top: 50%;
    width: clamp(84px, 9vw, 128px);
    aspect-ratio: 1 / 1;
    border-radius: 50%;
    overflow: hidden;
    transform: translateY(-50%);
    opacity: 0.1;
    pointer-events: none;
    z-index: 1;
  }
  .menu-ghost-prev { left: clamp(4%, 8vw, 11%); }
  .menu-ghost-next { right: clamp(4%, 8vw, 11%); }

  .menu-ghost img { width: 100%; height: 100%; object-fit: cover; }

  /* Click-and-drag swipe for mouse users — mobile already gets a real
     swipe for free via native touch scroll; desktop's crossfade was
     button/keyboard-only until now. */
  #menuCarousel { cursor: grab; }
  #menuCarousel.is-dragging { cursor: grabbing; }

  /* Grid, not flex+space-between: with a flex row the arrows would only
     land at the true visual center if the progress text and CTA pill
     happened to be the same width — a 1fr/auto/1fr grid guarantees
     dead-center arrows regardless of how those two labels wrap. */
  .menu-controls { display: grid; grid-template-columns: 1fr auto 1fr; }
  .menu-progress { justify-self: start; }
  .menu-arrows { justify-self: center; }
  .menu-controls .pill-btn { justify-self: end; }
}

/* ==========================================================================
   Place — full-bleed photo carrying eyebrow, two-line heading and a
   closing caption/labels/link all at once (merges what used to be two
   separate breaks: "ambiance" full-bleed moment + "story" two-line
   heading section — Selva's own reference has just the one).
   ========================================================================== */
.place {
  position: relative;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: hidden;
  padding: clamp(2.5rem, 6vw, 4rem) 0;
}

.place-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.place-overlay { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(13, 13, 11, 0.5) 0%, rgba(13, 13, 11, 0.28) 26%, rgba(13, 13, 11, 0.4) 60%, rgba(13, 13, 11, 0.92) 100%); }

.place-top, .place-inner, .place-bottom { position: relative; z-index: 2; }

.place-eyebrow {
  display: inline-block;
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
}

.place-inner { flex: 1 1 auto; display: flex; align-items: center; }
.place-title { font-size: clamp(2.4rem, 6.4vw, 4.4rem); line-height: 1.04; max-width: 14ch; }

.place-bottom { display: flex; flex-direction: column; gap: 1.2rem; }
.place-caption { max-width: 44ch; color: var(--text-muted); font-size: 1rem; }

.place-labels { display: flex; flex-wrap: wrap; gap: 0.6rem 1.6rem; }
.place-labels span {
  font-size: 0.76rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.place-bottom .link-underline { align-self: flex-start; }

.link-underline {
  display: inline-block;
  margin-top: 0.4rem;
  font-size: 0.92rem;
  color: var(--sage);
  border-bottom: 1px solid var(--sage-deep);
  padding-bottom: 2px;
  transition: color 0.3s var(--ease-out), border-color 0.3s var(--ease-out);
}

.link-underline:hover { color: var(--gold); border-color: var(--gold); }

/* ==========================================================================
   Testimonial — framed photo + oversized italic pull-quote
   ========================================================================== */
.testimonial { padding: clamp(4.5rem, 10vw, 7.5rem) 0; background: var(--ink-2); }

.testimonial-inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2.5rem, 6vw, 4rem);
  align-items: center;
}

.testimonial-photo { max-width: 420px; margin: 0 auto; border-color: var(--line); }

.testimonial-content .section-label { color: var(--text-faint); }
.testimonial-quote {
  margin-top: 0.6rem;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.6rem, 4vw, 2.6rem);
  line-height: 1.28;
  max-width: 20ch;
}

.testimonial-source { display: block; margin-top: 1.4rem; font-size: 0.85rem; letter-spacing: 0.04em; color: var(--text-muted); }

@media (min-width: 860px) {
  .testimonial-inner { grid-template-columns: 1.05fr 0.95fr; }
  .testimonial-photo { max-width: none; margin: 0; }
}

/* ==========================================================================
   FAQ — native <details> accordion, no JS needed. Answers the questions
   people actually type into Google/ChatGPT/Perplexity about King Food
   (location, hours, menu, ordering, prices) as short self-contained
   answers, which helps both human visitors and AI-search citation.
   ========================================================================== */
.faq { padding: clamp(4.5rem, 10vw, 7.5rem) 0; background: var(--ink-2); }

.faq-head { max-width: 46ch; margin-bottom: clamp(2.2rem, 6vw, 3.2rem); }

.faq-list { border-top: 1px solid var(--line); }

.faq-item { border-bottom: 1px solid var(--line); padding: 1.3rem 0; }

.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: clamp(1.02rem, 2vw, 1.3rem);
  color: var(--cream);
  transition: color 0.3s var(--ease-out);
}

.faq-item summary::-webkit-details-marker { display: none; }

.faq-item summary::after {
  content: "+";
  flex: none;
  font-family: var(--font-body);
  font-size: 1.4rem;
  color: var(--sage);
  transition: color 0.3s var(--ease-out);
}

.faq-item:hover summary { color: var(--gold); }
.faq-item[open] summary::after { content: "\2212"; color: var(--gold); }

.faq-item p {
  margin-top: 0.9rem;
  max-width: 62ch;
  color: var(--text-muted);
  font-size: 0.98rem;
  line-height: 1.6;
}

/* ==========================================================================
   Final CTA — full-bleed atmospheric close, with the footer folded
   directly into the same section instead of a separate block below it.
   ========================================================================== */
.cta-final {
  position: relative;
  overflow: hidden;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: clamp(2.5rem, 6vw, 4rem) 0 clamp(1.5rem, 4vw, 2.2rem);
}

.cta-final-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cta-final-overlay { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(13, 13, 11, 0.75) 0%, rgba(13, 13, 11, 0.55) 40%, rgba(13, 13, 11, 0.8) 78%, var(--ink) 100%); }

.cta-final-top, .cta-final-inner, .cta-final-footer { position: relative; z-index: 2; }

.cta-final-top {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.cta-final-inner {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 1.6rem;
  padding-top: clamp(3rem, 8vw, 5rem);
  padding-bottom: clamp(3rem, 8vw, 5rem);
}

.cta-final-title { font-size: clamp(2.6rem, 7vw, 5rem); line-height: 1; }
.cta-final-note { max-width: 42ch; color: var(--text-muted); font-size: 1rem; }

.cta-final-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.2rem 2rem;
  padding-top: clamp(1.5rem, 4vw, 2rem);
  border-top: 1px solid var(--line);
  font-size: 0.85rem;
  color: var(--text-muted);
}

.cta-final-footer-info { display: flex; flex-direction: column; gap: 0.35rem; }
.cta-final-footer-info .link-underline { margin-top: 0.3rem; align-self: flex-start; font-size: 0.85rem; }

.cta-final-footer-links { display: flex; gap: 0.9rem; }
.cta-final-footer-links a {
  width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  transition: border-color 0.3s var(--ease-out), transform 0.3s var(--ease-out);
}
.cta-final-footer-links a:hover { border-color: var(--gold); transform: translateY(-3px); }

.cta-final-copyright { font-size: 0.78rem; color: var(--text-faint); flex-basis: 100%; text-align: center; order: 3; }

@media (min-width: 640px) {
  .cta-final-copyright { flex-basis: auto; text-align: right; order: 0; }
}

/* ==========================================================================
   Responsive — structural shifts
   ========================================================================== */
@media (max-width: 899px) {
  .nav-desktop, .nav-cta { display: none; }
  .nav-toggle { display: flex; }

  /* Touch targets. Measured at 390px: quicknav pills 40px tall, the
     wordmark 33px, inline CTA links 25-27px — all under the 44px minimum.
     The pills can just grow; the other two must not move a pixel, so they
     get an invisible pseudo-element hit area instead of padding. */
  .menu-quicknav-inner a { display: inline-flex; align-items: center; min-height: 44px; }

  .brand-word,
  .link-underline { position: relative; }

  .brand-word::after,
  .link-underline::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }
}

@media (min-width: 900px) {
  .nav-toggle { display: none; }
}

@media (max-width: 560px) {
  .hero-actions { flex-direction: column; align-items: flex-start; }
  .cta-final-footer { flex-direction: column; align-items: flex-start; }
}

@media print {
  * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ==========================================================================
   Menu page (menu.html) — dedicated full-carte page. Reuses every token,
   button, framed-photo and cta-final/footer pattern from the single-page
   site rather than inventing a second visual language. Real content (all
   names/prices/descriptions below) comes directly from the client's own
   PDF menu, not placeholders.
   ========================================================================== */
.menu-hero {
  position: relative;
  min-height: 62dvh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  padding: calc(var(--header-height) + 2rem) 0 clamp(3rem, 6vw, 4.5rem);
}
.menu-hero-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.menu-hero-overlay { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(13, 13, 11, 0.78) 0%, rgba(13, 13, 11, 0.32) 45%, rgba(13, 13, 11, 0.94) 100%); }
.menu-hero-inner { position: relative; z-index: 2; }
.menu-hero-eyebrow {
  display: inline-block;
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 1.1rem;
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
}
.menu-hero-title { font-size: clamp(2.2rem, 5.4vw, 3.6rem); line-height: 1.08; margin-bottom: 1.2rem; text-shadow: 0 6px 30px rgba(0, 0, 0, 0.5); }
.menu-hero-sub { color: var(--text-muted); font-size: 1.05rem; max-width: 38ch; margin-bottom: 1.8rem; text-shadow: 0 2px 16px rgba(0, 0, 0, 0.5); }

/* Sticky under the (always-transparent, fixed) header rather than inside
   it — a long multi-category menu benefits from jump links in a way nothing
   else on the site needs, so this is deliberately unique to this page. */
.menu-quicknav {
  position: sticky;
  top: var(--header-height);
  z-index: 90;
  background: rgba(13, 13, 11, 0.86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.menu-quicknav-inner {
  display: flex;
  gap: 0.6rem;
  overflow-x: auto;
  padding-top: 0.9rem;
  padding-bottom: 0.9rem;
  scrollbar-width: none;
}
.menu-quicknav-inner::-webkit-scrollbar { display: none; }
.menu-quicknav-inner a {
  flex: 0 0 auto;
  padding: 0.5rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  font-size: 0.85rem;
  color: var(--text-muted);
  white-space: nowrap;
  transition: border-color 0.3s var(--ease-out), color 0.3s var(--ease-out), background 0.3s var(--ease-out);
}
.menu-quicknav-inner a:hover { color: var(--ink); background: var(--gold); border-color: var(--gold); }

/* Quick-nav jump targets need more scroll-margin than the site-wide
   #menu/#histoire/#contact rule near the top of this file accounts for —
   this page also has the sticky quicknav bar sitting right under the
   fixed header, which would otherwise cover each category's own heading
   right after a jump. */
#pizzas, #burgers, #poulets, #tacos, #sandwichs, #salades, #formules, #boissons {
  scroll-margin-top: calc(var(--header-height) + 56px);
}

.menu-cat { padding: clamp(4rem, 8vw, 6rem) 0; border-bottom: 1px solid var(--line); }
.menu-cat-head { margin-bottom: clamp(2rem, 4vw, 3rem); }
.menu-cat-title { font-size: clamp(2rem, 4.2vw, 3rem); }

.menu-subgroups { display: grid; grid-template-columns: 1fr; gap: clamp(2.2rem, 5vw, 3.5rem); }
@media (min-width: 860px) {
  .menu-subgroups { grid-template-columns: 1fr 1fr; }
  .menu-subgroups-two { grid-template-columns: 1.4fr 1fr; }
  .menu-subgroups-three { grid-template-columns: repeat(3, 1fr); }
}
.menu-subgroup-title { font-family: var(--font-display); font-style: italic; color: var(--sage); font-size: 1.1rem; margin-bottom: 1.2rem; }

/* Single-item subgroups (Buffalo, Pimento) don't need the full grid-cell
   width — a lone dotted-leader row stretched that wide looked unbalanced
   next to the 5-item subgroups sharing the same row. */
.menu-subgroup-narrow { max-width: 320px; }

/* Dotted price leader — the one thing worth borrowing wholesale from the
   Zigzag reference: it is simply the correct, legible convention for a
   name-then-price menu row, independent of any other stylistic choice. */
.menu-list { display: flex; flex-direction: column; gap: 1.3rem; }
.menu-list-row { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 0.6rem; }
.menu-list-name { font-family: var(--font-display); font-size: 1.05rem; color: var(--cream); white-space: nowrap; }
.menu-list-leader { flex: 1 1 40px; min-width: 20px; border-bottom: 1px dotted var(--line); margin-bottom: 0.35em; }
.menu-list-price { font-size: 0.92rem; color: var(--gold); white-space: nowrap; }
.menu-list-desc { flex-basis: 100%; margin-top: 0.3rem; font-size: 0.88rem; color: var(--text-muted); max-width: 52ch; }

/* Dual pricing (Seul / Menu) reads better as two stacked figures at the
   row's end than crammed into one dotted-leader line. */
.menu-list-row-dual { justify-content: space-between; align-items: flex-start; gap: 1.2rem; flex-wrap: nowrap; }
.menu-list-main { flex: 1 1 auto; min-width: 0; }
.menu-list-main .menu-list-desc { flex-basis: auto; max-width: 48ch; }
.menu-list-prices { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; gap: 0.15rem; font-size: 0.85rem; color: var(--text-muted); text-align: right; white-space: nowrap; }
.menu-list-prices b { color: var(--gold); font-weight: 500; font-family: var(--font-display); font-size: 0.98rem; }

@media (max-width: 640px) {
  .menu-list-row-dual { flex-wrap: wrap; }
  .menu-list-prices { flex-direction: row; gap: 1rem; align-items: baseline; }
}

/* Small real-photo thumbnail on the handful of list rows that have one —
   most rows stay plain text, so this only affects the specific items it's
   added to, never a whole section. */
.menu-list-thumb { width: 44px; height: 44px; border-radius: 8px; object-fit: cover; flex: none; }
.menu-list-main-inner { display: flex; align-items: center; gap: 0.7rem; }

.menu-atmosphere { position: relative; min-height: 46vh; display: flex; align-items: center; justify-content: center; overflow: hidden; }
/* This band is extremely wide and short relative to the tall source
   photo (only ~9% of its height is ever visible), so object-position is
   really "which thin slice", not a framing nudge — checked live: 50%
   (default) landed mid-wall, mostly repetitive slat texture. 60% brings
   the table/napkin/banquette into view instead. */
.menu-atmosphere-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center 60%; }
.menu-atmosphere-overlay { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(13, 13, 11, 0.55) 0%, rgba(13, 13, 11, 0.22) 50%, rgba(13, 13, 11, 0.68) 100%); }
.menu-atmosphere-line {
  position: relative;
  z-index: 2;
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.4rem, 3.2vw, 2.2rem);
  color: var(--cream);
  text-align: center;
  max-width: 26ch;
  padding: 0 1.5rem;
  text-shadow: 0 4px 24px rgba(0, 0, 0, 0.6);
}

.menu-cat-zigzag { padding: clamp(4rem, 8vw, 6rem) 0; border-bottom: 1px solid var(--line); }
.menu-zigzag-inner { display: grid; grid-template-columns: 1fr; gap: clamp(2.2rem, 6vw, 4rem); align-items: center; }
.menu-zigzag-list .section-label { display: block; }
.menu-zigzag-list .menu-cat-title { margin-bottom: clamp(1.8rem, 3vw, 2.4rem); }
.menu-zigzag-photos { position: relative; }
.menu-zigzag-photo-a { width: 72%; }
.menu-zigzag-photo-b { width: 60%; margin-left: auto; margin-top: -18%; position: relative; z-index: 2; }
.menu-zigzag-photo-single { width: 88%; margin: 0 auto; }

@media (min-width: 860px) {
  .menu-zigzag-inner { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 859px) {
  /* Photo first on mobile regardless of source order, so the dish reads
     before its price list — desktop keeps true left/right zigzag via DOM
     order instead (see menu.html), no CSS override needed there. */
  .menu-cat-zigzag-rev .menu-zigzag-photos { order: -1; margin-bottom: 1rem; }
}

.menu-formules { padding: clamp(4rem, 8vw, 6rem) 0; background: var(--ink-2); border-bottom: 1px solid var(--line); }
.menu-formules-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; margin-top: clamp(2rem, 4vw, 2.5rem); }
@media (min-width: 700px) { .menu-formules-grid { grid-template-columns: 1fr 1fr; } }
.menu-formule-card { border: 1px solid var(--gold-soft); padding: clamp(1.6rem, 3vw, 2.2rem); background: rgba(217, 166, 108, 0.04); }
.menu-formule-card h3 { font-family: var(--font-display); font-style: italic; color: var(--gold); font-size: 1.3rem; margin-bottom: 1.3rem; }
/* Formula names are full sentences ("Burger, frites & boisson"), not the
   short dish names the nowrap rule was written for. Inside these padded
   cards the row can't shrink below ~297px, so at 320px it forced the page
   into horizontal scroll. Letting these names wrap is the only part of the
   row that can give. */
.menu-formule-card .menu-list-name { white-space: normal; }

@media (prefers-reduced-motion: reduce) {
  .menu-quicknav { position: static; }
}

/* ==========================================================================
   Contact page (contact.html) — compact photo title-band, then a two-column
   "get in touch" split (info + socials | form). Reuses every token, button,
   .menu-head reveal and .cta-final-footer-links icon style from the rest of
   the site rather than inventing a second visual language.
   ========================================================================== */
.contact-hero {
  position: relative;
  min-height: 42dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: calc(var(--header-height) + 2rem) 0 2.5rem;
  border-bottom: 1px solid var(--line);
}
.contact-hero-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center 70%; }
.contact-hero-overlay { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(13, 13, 11, 0.35) 0%, rgba(13, 13, 11, 0.55) 55%, rgba(13, 13, 11, 0.88) 100%); }
.contact-hero-inner { position: relative; z-index: 2; text-align: center; }
.contact-hero-title { margin: 0; font-size: clamp(2.6rem, 6.5vw, 4.4rem); line-height: 1.08; text-shadow: 0 6px 30px rgba(0, 0, 0, 0.6); }

.get-in-touch { padding: clamp(4rem, 8vw, 6rem) 0; }
.get-in-touch-grid { display: grid; grid-template-columns: 1fr; gap: clamp(3rem, 6vw, 5rem); }
@media (min-width: 900px) {
  .get-in-touch-grid { grid-template-columns: 0.95fr 1.05fr; }
}

.get-in-touch-copy .menu-head p { color: var(--text-muted); max-width: 42ch; margin-top: 1rem; }

.contact-info-grid { display: grid; grid-template-columns: 1fr; gap: 1.6rem 2rem; margin: 2.4rem 0; }
@media (min-width: 480px) {
  .contact-info-grid { grid-template-columns: 1fr 1fr; }
}
.contact-info-item { display: flex; gap: 0.9rem; align-items: flex-start; }
.contact-info-item svg { flex-shrink: 0; margin-top: 0.15rem; color: var(--gold); }
.contact-info-item div { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.contact-info-item span { font-size: 0.9rem; line-height: 1.5; color: var(--text-muted); overflow-wrap: break-word; }
.contact-info-item span:first-child { font-family: var(--font-display); font-size: 1rem; color: var(--cream); }

.tel-link { color: inherit; font: inherit; text-decoration: none; transition: color 0.3s var(--ease-out); }
.tel-link:hover { color: var(--gold); }

.contact-social { display: flex; align-items: center; gap: 1.1rem; padding-top: 1.8rem; border-top: 1px solid var(--line); }
.contact-social-label { font-size: 0.76rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-faint); }

.get-in-touch-form-note { color: var(--text-muted); font-size: 0.96rem; max-width: 38ch; margin: 0.6rem 0 2rem; }

.contact-form { display: flex; flex-direction: column; gap: 1.4rem; }
.contact-form-row { display: grid; grid-template-columns: 1fr; gap: 1.4rem; }
@media (min-width: 560px) {
  .contact-form-row { grid-template-columns: 1fr 1fr; }
}
.form-field { display: flex; flex-direction: column; gap: 0.55rem; }
.form-field label { font-size: 0.76rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); }
.form-field label em { color: var(--gold); font-style: normal; }
.form-field input, .form-field textarea {
  background: var(--ink-2);
  border: 1px solid var(--line);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: max(16px, 1rem); /* below 16px, iOS Safari auto-zooms on focus */
  padding: 0.85rem 1rem;
  border-radius: 2px;
  transition: border-color 0.3s var(--ease-out), background 0.3s var(--ease-out);
}
.form-field input::placeholder, .form-field textarea::placeholder { color: var(--text-faint); }
.form-field input:focus, .form-field textarea:focus { outline: none; border-color: var(--gold); background: var(--ink-3); }
.form-field textarea { resize: vertical; min-height: 140px; }
.contact-form .btn { align-self: flex-start; margin-top: 0.4rem; }
