/* ============================================================================
   Belly Bytes — site stylesheet (v2)
   The values here are the ones in docs/DESIGN.md. If one is not in that file,
   either the file is out of date or the value is a mistake.

   THREE RULES THAT BREAK THE PAGE SILENTLY IF VIOLATED

   1. NEVER write `html, body { overflow-x: hidden }`. Both together make <body>
      a scroll container, and the sticky nav and the sticky menu chips stop
      sticking. Contain the overflowing element itself, or use `overflow: clip`,
      which clips without creating a scroll container.

   2. `.nav` is a DIRECT CHILD of <body>. An ancestor that gains transform,
      filter, backdrop-filter, will-change or perspective becomes the containing
      block for position:fixed and detaches the phone's tab bar from the bottom
      of the screen.

   3. THE MAP'S 3D CHAIN. `.map__stage` sets the perspective; from `.map__plane`
      down to every `.sign__body` the elements share one 3D space. None of them
      may get opacity below 1, a filter, a mask, clip-path, overflow or
      isolation: any of these flattens the map without an error. Put such
      effects on the stage (above the chain) or on a leaf (below it).
   ========================================================================= */

/* Typefaces: self-hosted, latin subset only, all OFL. See site/fonts/README.txt. */
@font-face {
  font-family: "Abril Fatface";
  src: url("../fonts/abril-fatface-latin.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
/* Karla is variable, so one file covers 400-700 and bold is real. */
@font-face {
  font-family: "Karla";
  src: url("../fonts/karla-latin.woff2") format("woff2");
  font-weight: 400 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Instrument Serif";
  src: url("../fonts/instrument-serif-italic-latin.woff2") format("woff2");
  font-weight: 400; font-style: italic; font-display: swap;
}

/* The map animates these, and a custom property only animates once it has a type. */
@property --tilt { syntax: "<angle>"; inherits: true; initial-value: 0deg; }
@property --spin { syntax: "<angle>"; inherits: true; initial-value: 0deg; }
@property --zoom { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --rise { syntax: "<number>"; inherits: true; initial-value: 1; }

:root {
  /* ── Colour ── */
  --roast:        #21140D;   /* charcoal of the pit: the scenes' scrims, nav, footer */
  --roast-line:   #4B3324;
  --rust:         #C4491B;   /* the brand colour, used as a ground */
  --rust-deep:    #9E3812;
  --rust-text:    #B23F14;   /* rust for TEXT on rice or paper (5.5:1 and 5:1) */
  --gold:         #E8A33D;   /* the pig's gold */
  --gold-hover:   #F3B658;
  --gold-soft:    #FFE2AE;   /* gold for large type on rust; --gold is 2.3:1 there */
  --rice:         #FFF8EC;   /* paper for the menu */
  --paper:        #F7ECD8;
  --line:         #E6D5B8;
  --line-strong:  #C9B594;
  --ink:          #2A170E;
  --ink-soft:     #6A5145;
  --leaf:         #2F6B45;   /* banana leaf, the venue's green floor: "open now" */
  --on-dark:      #FFF3DF;
  --on-dark-soft: #D9C3A6;

  /* ── Type ── */
  --font-display: "Abril Fatface", Didot, "Bodoni MT", Georgia, serif;
  --font-accent:  "Instrument Serif", Georgia, "Times New Roman", serif;
  --font-text:    Karla, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* The one stack that must NOT be a webfont - see .peso at the end. */
  --font-system:  system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* ── Layout ── */
  --wrap: 72rem;
  --gutter: 1.25rem;
  --radius: 5px;
  --ease: cubic-bezier(.2, .7, .2, 1);

  /* ── Chrome that covers the scrollport. Drives scroll-padding. ──
     Phone: the nav is at the BOTTOM, so nothing covers the top. */
  --nav-top: 0px;
  --nav-bottom: 60px;
  --strip-h: 4.75rem;

  /* ── Stacking ── */
  --z-chipbar: 50;
  --z-nav: 100;
  --z-skip: 200;
}

@media (min-width: 768px) {
  :root { --nav-top: 68px; --nav-bottom: 0px; --strip-h: 3.5rem; --gutter: 2rem; }
}

/* ============================================================================
   Base
   ========================================================================= */

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

html {
  -webkit-text-size-adjust: 100%;
  /* scroll-padding, not per-element scroll-margin: it covers fragment links,
     :target, keyboard focus and find-in-page. The bottom half keeps a focused
     link from landing underneath the phone's tab bar. */
  scroll-padding-top: calc(var(--nav-top) + .75rem);
  scroll-padding-bottom: calc(var(--nav-bottom) + env(safe-area-inset-bottom, 0px) + .5rem);
}

body {
  margin: 0;
  background: var(--roast);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: 1rem;
  line-height: 1.6;
  /* Abril Fatface has ONE weight. Without this a stray bold is synthesised:
     smeared strokes on a face whose point is its fine hairlines. */
  font-synthesis: none;
  overflow-x: clip;
  /* Reserve the tab bar's height or it covers the end of the footer. */
  padding-bottom: calc(var(--nav-bottom) + env(safe-area-inset-bottom, 0px));
}

img { max-width: 100%; display: block; }
h1, h2, h3, h4, p, figure, dl, dd, ul { margin: 0; }
ul { padding: 0; list-style: none; }
address { font-style: normal; }

a { color: var(--link, var(--rust-text)); text-underline-offset: .18em; }

:focus-visible { outline: 2px solid var(--focus, var(--rust)); outline-offset: 3px; }

.skip {
  position: absolute; left: var(--gutter); top: -100px; z-index: var(--z-skip);
  background: var(--gold); color: var(--roast);
  padding: .75rem 1rem; border-radius: var(--radius);
  font-weight: 700; text-decoration: none;
}
.skip:focus { top: 1rem; }

.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }

/* ── Type roles ── */
.title {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(2.2rem, 7.6vw, 3.6rem);
  line-height: 1.02; letter-spacing: -.01em;
  text-wrap: balance;
}
/* The fixed brand lines. 1.5rem minimum on purpose: at 24px the type counts as
   large, and --gold-soft on rust (3.9:1) is only allowed at that size. */
.kicker {
  font-family: var(--font-accent); font-style: italic; font-weight: 400;
  font-size: clamp(1.5rem, 5vw, 1.9rem);
  line-height: 1.1;
  color: var(--accent, var(--rust-text));
}
.lead { font-size: clamp(1.0625rem, 3.6vw, 1.25rem); line-height: 1.5; }

/* ── Sections: each sets its ground and the colours that ride on it ── */
.sect { padding-block: clamp(3.75rem, 9vw, 6.5rem); }
.sect--rice  { background: var(--rice); }
.sect--paper { background: var(--paper); }
.sect--rust {
  color: var(--rice); --accent: var(--gold-soft); --focus: var(--rice); --link: var(--rice);
  /* The scored diamond crosshatch of the pig's back, kept quiet. */
  background:
    repeating-linear-gradient(56deg, transparent 0 33px, rgba(255, 248, 236, .075) 33px 34px),
    repeating-linear-gradient(-56deg, transparent 0 33px, rgba(255, 248, 236, .075) 33px 34px),
    var(--rust);
}

/* ── Buttons ── */
.btns { display: flex; flex-wrap: wrap; gap: .6rem; }
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 0 clamp(1rem, 4.6vw, 1.4rem);
  border: 1.5px solid transparent; border-radius: 999px;
  font-weight: 700; font-size: 1rem; line-height: 1.2; text-decoration: none;
  transition: background-color .15s var(--ease), border-color .15s var(--ease);
}
.btn--gold  { background: var(--gold); color: var(--roast); }
.btn--gold:hover  { background: var(--gold-hover); }
.btn--line  { border-color: currentColor; color: inherit; }
.btn--line:hover  { background: rgba(255, 243, 223, .14); }
.btn--rust  { background: var(--rust); color: #fff; }
.btn--rust:hover  { background: var(--rust-deep); }
.btn--plain { border-color: var(--line-strong); color: var(--ink); }
.btn--plain:hover { background: var(--rice); border-color: var(--ink-soft); }

/* ============================================================================
   Nav — one element, two positions
   ========================================================================= */

.nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-nav);   /* longhands, not `inset`: iOS 14.0-14.4 lacks it */
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  background: var(--roast);
  border-top: 1px solid var(--roast-line);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  --focus: var(--gold);
}
.nav__brand { display: none; }
.nav__item {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-height: var(--nav-bottom);
  color: var(--on-dark); text-decoration: none;
  font-size: .6875rem; font-weight: 700;
}
.nav__icon {
  width: 20px; height: 20px;
  fill: none; stroke: var(--gold); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

@media (min-width: 768px) {
  .nav {
    position: sticky;
    left: auto; right: auto; bottom: auto;   /* undo the phone's offsets */
    top: 0;
    height: var(--nav-top);
    display: flex; align-items: center; gap: .25rem;
    padding: 0 var(--gutter);
    border-top: 0;
  }
  .nav__brand {
    display: flex; align-items: center; gap: .7rem; margin-right: auto;
    color: var(--on-dark); text-decoration: none;
  }
  /* The owners' logo: the pig in its own colours, the wordmark in cream. */
  .nav__logo { width: 62px; height: auto; }
  .nav__wordmark { width: 132px; height: auto; }
  .nav__item { flex-direction: row; gap: .5rem; min-height: 44px; padding: 0 1rem; font-size: .9375rem; border-radius: 999px; }
  .nav__item:hover { background: rgba(255, 243, 223, .1); }
  .nav__item--message { background: var(--gold); color: var(--roast); margin-left: .5rem; }
  .nav__item--message:hover { background: var(--gold-hover); }
  .nav__item--message .nav__icon { stroke: var(--roast); }
}

/* ============================================================================
   The opening — three scenes: the food, the place, the nights
   Sticky parallax: each scene is taller than the screen, its photo sticks to
   the top while the scene scrolls, and the copy at the top of the scene rides
   up over it. No JavaScript: the browser composites it, so it behaves the same
   on iOS, Android and desktop.

   NEVER background-attachment: fixed (it silently does nothing in iOS WKWebView,
   which is the Facebook in-app browser on every iPhone).
   NEVER a scroll listener that sets transform (always a frame behind the finger).
   ========================================================================= */

.scene {
  position: relative;
  min-height: 150vh;       /* for browsers without svh: iOS 14-15.3, old Android WebView */
  min-height: 150svh;      /* svh, NOT dvh: svh is constant; dvh changes as the browser's
                              bars slide away and would resize the page mid-scroll,
                              moving every deep link's target */
  background: #5A200D;     /* each scene carries its photo's dominant colour, so a
                              photo that is still loading is never a pale hole */
  color: var(--on-dark);
  --accent: var(--gold); --focus: var(--gold);
}
.scene--place  { background: #2A1B10; }
.scene--nights { background: #241609; }

.scene__media {
  position: sticky; top: 0;
  height: 100vh; height: 100svh;
  overflow: hidden;        /* safe HERE: an element clipping its own children keeps its
                              own stickiness. NEVER move this to .scene. */
}
.scene__media img { width: 100%; height: 100%; object-fit: cover; }
.scene--food .scene__media img { object-position: 50% 42%; }

/* Two scrims. This one is sized to the PHOTO and is strongest at the top,
   because all scene copy is top-anchored. */
.scene__media::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  background: linear-gradient(180deg,
    rgba(33, 20, 13, .6) 0%, rgba(33, 20, 13, .2) 34%, rgba(33, 20, 13, .14) 70%, rgba(33, 20, 13, .6) 100%);
}

/* Copy sits at the TOP of the scene and scrolls away while the photo stays.
   Nothing is bottom-anchored: on the vh fallback the bottom of the pinned
   photo is cut off by the browser's bars, and anything anchored there would
   be invisible on first paint. */
.scene__body {
  /* The copy starts where the rest of the page's content starts: the gutter,
     or the edge of the centred column on a wide screen. */
  --pad: max(var(--gutter), calc((100% - var(--wrap)) / 2 + var(--gutter)));
  position: absolute; top: 0; left: 0; right: 0;
  max-width: calc(var(--pad) + 38rem);
  display: flex; flex-direction: column; align-items: flex-start; gap: .75rem;
  padding: calc(var(--nav-top) + 1.75rem) var(--gutter) 2rem var(--pad);
}
/* position:relative puts the copy above the ::before scrim below: both are
   positioned with z-index auto, so they paint in DOM order, scrim first.
   32rem, not the body's 38: the last 6rem of the body is where its scrim fades
   out sideways, and no line may run into the fade. */
.scene__body > * { position: relative; max-width: 32rem; }

/* The second scrim is sized to the COPY, and it is the one that guarantees the
   contrast. A scrim tied to the photo protects whatever text happened to be
   there when it was tuned; a longer line or a different phone outruns it. This
   one is as tall as the copy, so it grows with it, and it fades out over a
   5rem tail hung BELOW the last line, never across it.
   Measured on the photos' brightest spots: titles 3:1 or better (large type),
   everything else 4.5:1 or better. Re-measure after changing copy or photo. */
.scene__body::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0;
  height: calc(100% + 5rem);
  background: linear-gradient(180deg,
    rgba(33, 20, 13, .66) 0%, rgba(33, 20, 13, .62) calc(100% - 5rem), rgba(33, 20, 13, 0) 100%);
  pointer-events: none;
}
/* From this width the body is narrower than the photo, and its scrim would end
   in a hard vertical seam. Fade its right edge away. Narrower than this the
   body is the full width, there is no seam, and the fade would only eat the
   scrim under the ends of the lines. */
@media (min-width: 38rem) {
  .scene__body::before {
    -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 calc(100% - 6rem), transparent 100%);
            mask-image: linear-gradient(90deg, #000 0%, #000 calc(100% - 6rem), transparent 100%);
  }
}

.scene__logo { width: 104px; height: auto; margin-bottom: .25rem; }
@media (min-width: 768px) { .scene__logo { display: none; } }   /* the nav carries the logo from here up */

.scene__title {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(2.7rem, 11vw, 4.75rem);
  line-height: .98; letter-spacing: -.01em;
  text-wrap: balance;
}
/* The name, on two lines. "Bytes" is the wider word: 2.7em. 27vw keeps it
   inside a 320px screen. */
.scene__title--name { font-size: clamp(4.5rem, 27vw, 8.5rem); line-height: .88; letter-spacing: -.02em; }
.scene__title--name span { display: block; }
.scene__tag {
  font-family: var(--font-accent); font-style: italic;
  font-size: clamp(1.7rem, 7.4vw, 2.5rem); line-height: 1;
  color: var(--gold);
}
.scene__lead { max-width: 34ch; font-size: clamp(1rem, 3.8vw, 1.125rem); }
.scene .btns { margin-top: .35rem; }

/* Open or closed. The dot is decoration: the words beside it say which. */
.status {
  display: inline-flex; align-items: center; min-height: 2.25rem;
  padding: .25rem .95rem;
  border: 1px solid rgba(255, 243, 223, .5); border-radius: 999px;
  font-size: .9375rem; font-weight: 700; line-height: 1.3;
}
.status::before {
  content: ""; flex: none; width: .6em; height: .6em; margin-right: .55em;
  border-radius: 50%; background: var(--on-dark); opacity: .5;
}
.status.is-open::before   { background: #8FD6A3; opacity: 1; }
.status.is-closed::before { background: var(--gold); opacity: 1; }

/* ============================================================================
   Today strip
   ========================================================================= */

.strip {
  display: grid; align-content: center; gap: .1rem;
  min-height: var(--strip-h);
  padding: .6rem var(--gutter);
  background: var(--gold); color: var(--roast);
  font-weight: 700; line-height: 1.35;
  --focus: var(--roast);
}
.strip a { color: inherit; }
.strip__where { font-weight: 400; }
.strip__where span { display: none; }      /* the street name needs the room a wide screen has */
.strip__call { display: none; }
/* The dot is decoration: the words beside it say open or closed. */
.strip__status::before {
  content: ""; display: inline-block; width: .62em; height: .62em; margin-right: .5em;
  border-radius: 50%; background: var(--roast); opacity: .4;
}
.strip__status.is-open::before   { background: var(--leaf); opacity: 1; }
.strip__status.is-closed::before { background: var(--rust-deep); opacity: 1; }

@media (min-width: 768px) {
  .strip { display: flex; align-items: center; justify-content: center; gap: clamp(1.5rem, 4vw, 3.5rem); white-space: nowrap; }
  .strip__call { display: block; }
}
@media (min-width: 900px) {
  .strip__where span { display: inline; }
}

/* ============================================================================
   What we do
   ========================================================================= */

.pillars__title { margin-bottom: 1.5rem; }
.pillars__list { display: grid; }
.pillars__list li { padding-block: 1.5rem; border-top: 1px solid rgba(255, 248, 236, .4); }
.pillars__list h3 {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(2.1rem, 8.4vw, 2.9rem); line-height: 1; letter-spacing: -.01em;
  margin-bottom: .6rem;
}
.pillars__list p { max-width: 36ch; }

@media (min-width: 900px) {
  .pillars__list { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 3rem; }
  .pillars__list li { padding-bottom: 0; }
}

/* ============================================================================
   Find us
   ========================================================================= */

.find__intro { display: grid; gap: .7rem; max-width: 40rem; margin-bottom: 2rem; }
/* On a phone the map runs edge to edge. */
.find__map { margin-inline: calc(var(--gutter) * -1); container-type: inline-size; }
.find__credit { margin: .7rem var(--gutter) 0; font-size: .8125rem; color: var(--ink-soft); }
.find__below { display: grid; gap: 2.5rem; margin-top: 2rem; }
.find__facts { display: grid; gap: 1.5rem; align-content: start; }
.find__front img { width: 100%; height: auto; border-radius: var(--radius); }
.find__front figcaption { margin-top: .6rem; font-size: .875rem; color: var(--ink-soft); }

@media (min-width: 640px) {
  .find__map { margin-inline: 0; }
  .find__credit { margin-inline: 0; }
}
@media (min-width: 1000px) {
  .find__below { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); gap: 4.5rem; align-items: center; }
}

/* A plain list of facts: label, value, hairline. Used here and in the footer. */
.facts__row { display: grid; grid-template-columns: 5.25rem minmax(0, 1fr); gap: .75rem; padding-block: .8rem; border-top: 1px solid var(--line-strong); }
.facts__row:last-child { border-bottom: 1px solid var(--line-strong); }
.facts dt { font-size: .8125rem; font-weight: 700; color: var(--ink-soft); padding-top: .2em; }
.facts dd { overflow-wrap: anywhere; }
.facts--dark .facts__row { border-color: var(--roast-line); }
.facts--dark dt { color: var(--on-dark-soft); }

/* ============================================================================
   The map
   A flat map on a tilted table. .map__ground is the drawing (an SVG shown as an
   image), .map__ink the street names, each .sign a board standing upright.

   Upright: every sign is a 0x0 anchor at its place on the plane. Its body
   undoes the plane's two rotations in reverse order, so it faces the viewer
   with its foot on the point. Shadows and the pin's glow are children of the
   anchor with no transform, so they lie flat on the ground.

   Without the 3D rules everything still works: the plane lies flat and the
   signs stand "up" the page from their points.
   ========================================================================= */

.map { display: block; text-decoration: none; color: inherit; border-radius: var(--radius); }

.map__stage {
  /* Phone: the plane is wider than the stage and turns around the pin, so the
     streets run off the edges like ground under your feet. */
  --fit: 1.8;
  --tilt-final: 52deg;
  --spin-final: 0deg;
  --zoom-start: .8;
  --tilt: var(--tilt-final);
  --spin: var(--spin-final);
  --zoom: 1;
  --rise: 1;
  position: relative;
  height: min(108vw, 30rem);
  overflow: hidden;
  background: #B8421A;      /* the ground's colour: the far edge of the plane melts into it */
  perspective: 900px;
  perspective-origin: 50% 12%;
  /* The far distance fades out instead of ending in a hard line. The stage is
     above the 3D chain, so a mask is safe here. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 24%);
          mask-image: linear-gradient(180deg, transparent 0, #000 24%);
}

.map__slab { display: none; }

.map__plane, .map__slab {
  --ox: var(--pin-x);
  --oy: var(--pin-y);
  position: absolute; left: 50%; top: 66%;
  width: calc(100% * var(--fit));
  transform-style: preserve-3d;
  transform-origin: var(--ox) var(--oy);
  /* Read right to left: turn and tilt around the origin, then move the origin
     to the element's left/top. On a phone the origin is the pin. */
  transform: translate(calc(var(--ox) * -1), calc(var(--oy) * -1)) scale(var(--zoom)) rotateX(var(--tilt)) rotateZ(var(--spin));
}

.map__ground { width: 100%; height: auto; transform: translateZ(0); }
.map__ink { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform: translateZ(0); }

.map__street {
  font-family: var(--font-text); font-weight: 700; font-size: 17px;
  letter-spacing: .14em; text-transform: uppercase;
  text-anchor: middle; fill: var(--rust-deep);
}
.map__sea { font-family: var(--font-accent); font-style: italic; font-size: 30px; text-anchor: middle; fill: #3F6B72; }
.map__trail { fill: none; stroke: var(--gold-soft); stroke-width: 5.5; stroke-linecap: round; stroke-dasharray: 0 14; }
.map__compass path, .map__scale path { fill: none; stroke: #FFF1DC; stroke-opacity: .8; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.map__compass text, .map__scale text { font-family: var(--font-text); font-weight: 700; font-size: 17px; text-anchor: middle; fill: #FFF1DC; fill-opacity: .85; }

/* ── Signs ── */
.sign {
  --bw: 340px;      /* wide on purpose: Chrome paints only the box of an element turned in 3D, and the boards hang sideways */
  position: absolute; left: calc(var(--x) * 1%); top: calc(var(--y) * 1%);
  width: 0; height: 0;
  transform-style: preserve-3d;
}
.sign__body {
  position: absolute; bottom: 0; left: calc(var(--bw) / -2); width: var(--bw);
  display: flex; flex-direction: column; align-items: center;
  transform-origin: 50% 100%;
  --pop: calc(.35 + .65 * var(--rise));
  transform: rotateZ(calc(var(--spin) * -1)) rotateX(calc(var(--tilt) * -1)) scale3d(var(--pop), var(--pop), var(--pop));
}
.sign__board {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: 3px 8px 2px 6px;
  background: var(--rice); color: var(--ink);
  border-radius: 3px;
  font-size: .6875rem; font-weight: 700; line-height: 1.35; white-space: nowrap;
  box-shadow: 0 1px 0 rgba(33, 20, 13, .35);
}
.sign__icon { width: 14px; height: 14px; flex: none; fill: none; stroke: var(--rust-text); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.sign__pole { width: 2px; height: var(--pole); background: var(--rice); }
/* A board hangs to one side of its post, like a flag, so it clears the pin. */
.sign--left .sign__board  { transform: translateX(calc(-50% + 9px - var(--hang, 0px))); }
.sign--right .sign__board { transform: translateX(calc(50% - 9px + var(--hang, 0px))); }
.sign__shadow, .sign__glow, .sign__ring { position: absolute; border-radius: 50%; pointer-events: none; }
.sign__shadow { width: 30px; height: 14px; left: -11px; top: -7px; background: radial-gradient(closest-side, rgba(33, 20, 13, .5), rgba(33, 20, 13, 0)); }

/* The pin: a medal on a gold post, bigger than every other sign. */
.sign--pin .sign__board {
  padding: 4px 11px 3px;
  background: var(--roast); color: var(--gold);
  font-family: var(--font-display); font-size: .9375rem; font-weight: 400; line-height: 1.2;
  border-radius: 999px;
}
.sign__medal {
  display: grid; place-items: center;
  width: 60px; height: 60px; margin-top: 4px;
  border: 3px solid var(--gold); border-radius: 50%;
  background: var(--rice);
  box-shadow: 0 2px 0 rgba(33, 20, 13, .4);
}
.sign__medal img { width: 46px; height: auto; }
.sign--pin .sign__pole { width: 3px; background: var(--gold); }
.sign__glow { width: 150px; height: 150px; left: -75px; top: -75px; background: radial-gradient(closest-side, rgba(255, 214, 140, .8), rgba(255, 214, 140, 0)); transition: opacity .4s var(--ease); }
.sign__ring { width: 58px; height: 58px; left: -29px; top: -29px; border: 2px solid var(--gold-soft); }

/* Closed: the lights go down. js/main.js sets data-open on <html>. */
[data-open="false"] .sign__glow { opacity: 0; }
/* `animation: none` as well: a running animation would override the opacity. */
[data-open="false"] .sign .sign__ring { animation: none; opacity: 0; }

/* ── From 640px: the whole table is in view, slab and all ── */
@media (min-width: 640px) {
  .map__stage {
    --fit: .76;
    --tilt-final: 54deg;
    --spin-final: 8deg;
    --zoom-start: .74;
    height: 30rem;                       /* for browsers without container units */
    height: calc(50cqw + 7rem);
    overflow: visible;
    background: none;
    perspective: 1700px;
    perspective-origin: 50% 30%;
    -webkit-mask-image: none; mask-image: none;
  }
  .map__plane, .map__slab { --ox: 50%; --oy: 50%; top: 50%; }
  .map__street, .map__compass text, .map__scale text { font-size: 15px; }
  .sign__board { font-size: .75rem; }

  /* The table's underside: three faces and a soft shadow on the floor, in a
     box of their own with the plane's transform. Kept out of .map__plane on
     purpose: faces at right angles inside it make Firefox sort the map in
     front of the signs. */
  .map__slab { display: block; pointer-events: none; --thick: 16px; }
  /* The slab has no picture inside to give it height, so this does: 80% is the
     map's height over its width. Not `aspect-ratio`, which iOS 14 lacks. */
  .map__slab::before { content: ""; display: block; padding-top: 80%; }
  .map__face { position: absolute; background: linear-gradient(#7C2C0F, #5E2109); -webkit-backface-visibility: hidden; backface-visibility: hidden; }
  .map__face--s { left: 0; right: 0; top: 100%; height: var(--thick); transform-origin: top; transform: rotateX(-90deg); }
  .map__face--e { top: 0; bottom: 0; left: 100%; width: var(--thick); transform-origin: left; transform: rotateY(90deg); }
  .map__face--w { top: 0; bottom: 0; right: 100%; width: var(--thick); transform-origin: right; transform: rotateY(-90deg); }
  .map__floor { position: absolute; top: 3%; right: 3%; bottom: 3%; left: 3%; transform: translateZ(calc(var(--thick) * -1 - 1px)); background: rgba(33, 20, 13, .3); filter: blur(22px); }
}

/* ── Motion: the one orchestrated moment on the page ──
   The flat map tilts up into the table as it scrolls into view, and the signs
   rise. Longhands only: a minifier that folds animation-timeline into the
   animation shorthand produces a rule browsers drop. */
@keyframes map-tilt-in { from { --tilt: 0deg; --spin: 0deg; --zoom: var(--zoom-start); --rise: 0; } }
@keyframes map-march  { to { stroke-dashoffset: -28; } }
@keyframes map-ring   { from { transform: scale(.7); opacity: 1; } to { transform: scale(1.9); opacity: 0; } }

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .map__stage {
      animation-name: map-tilt-in;
      animation-timing-function: linear;
      animation-fill-mode: both;
      animation-timeline: view();
      animation-range: entry 0% cover 42%;
    }
  }
  @supports not (animation-timeline: view()) {
    /* js/main.js holds the map flat (pending) until it scrolls into view, then lets it tilt (done). */
    .map__stage[data-entrance] {
      transition-property: --tilt, --spin, --zoom, --rise;
      transition-duration: 1.2s, 1.2s, 1.2s, 1s;
      transition-timing-function: var(--ease);
      transition-delay: 0s, 0s, 0s, .25s;
    }
    .map__stage[data-entrance="pending"] { --tilt: 0deg; --spin: 0deg; --zoom: var(--zoom-start); --rise: 0; }
  }
  .map__trail { animation: map-march 2.6s steps(14) infinite; }
  .sign__ring { animation: map-ring 2.4s var(--ease) infinite; }
}

/* ============================================================================
   Menu
   ========================================================================= */

.menu .lead { margin-top: .9rem; color: var(--ink-soft); max-width: 40ch; }

/* Popular picks: three dishes on dark cards. A horizontal swipe on phones, a
   3-up grid once there is room. Contained here: this strip scrolls, the
   document never does. */
.picks__title { font-family: var(--font-display); font-weight: 400; font-size: 1.6rem; line-height: 1.1; margin: 2.5rem 0 .6rem; }
.picks {
  display: flex; gap: 1rem;
  /* The padding all round is room for the focus ring: a strip that scrolls
     sideways clips whatever sticks out of it, top and bottom included. */
  margin: 0 calc(var(--gutter) * -1) 3rem; padding: .4rem var(--gutter) .5rem;
  overflow-x: auto; overscroll-behavior-inline: contain;
  scroll-snap-type: x proximity; scroll-padding-inline: var(--gutter);
  scrollbar-width: none;
}
.picks::-webkit-scrollbar { display: none; }
.pick { flex: 0 0 68%; min-width: 0; scroll-snap-align: start; }
.pick__link {
  display: flex; flex-direction: column; height: 100%;
  background: var(--roast); color: var(--on-dark);
  border-radius: var(--radius); overflow: hidden;
  text-decoration: none; --focus: var(--rust);
}
.pick__shot img { width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; transition: transform .5s var(--ease); }
.pick__link:hover .pick__shot img { transform: scale(1.04); }
.pick__shot { display: block; overflow: hidden; }
.pick__body { display: flex; flex-direction: column; gap: .2rem; padding: 1rem 1.1rem 1.2rem; flex: 1 1 auto; }
.pick__note { font-family: var(--font-accent); font-style: italic; font-size: 1.2rem; line-height: 1.1; color: var(--gold); }
.pick__name { font-family: var(--font-display); font-size: 1.5rem; line-height: 1.1; }
.pick__desc { font-size: .9375rem; line-height: 1.45; color: var(--on-dark-soft); flex: 1 1 auto; margin-top: .2rem; }
.pick__price { font-family: var(--font-display); font-size: 1.6rem; line-height: 1; color: var(--gold); margin-top: .6rem; }

@media (min-width: 760px) {
  .picks { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.5rem; margin-inline: 0; padding-inline: 0; overflow: visible; }
  .pick { flex: none; }
}

/* The chip bar is the likeliest source of sideways overflow on this page, and
   the reflex fix for that (root overflow-x: hidden) kills every sticky element.
   So it is contained HERE: the strip scrolls, the document never does. */
.chipbar {
  position: sticky; top: var(--nav-top); z-index: var(--z-chipbar);
  display: flex; gap: .5rem;
  margin: 0 calc(var(--gutter) * -1) 2rem; padding: .7rem var(--gutter);
  overflow-x: auto; overscroll-behavior-inline: contain;   /* an edge swipe must not navigate back */
  scrollbar-width: none;
  background: var(--rice); border-bottom: 1px solid var(--line);
}
.chipbar::-webkit-scrollbar { display: none; }
.chipbar__chip {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: .45rem;
  min-height: 44px; padding: 0 .9rem;
  border: 1px solid var(--line-strong); border-radius: 999px;
  color: var(--ink); font-size: .875rem; font-weight: 700; text-decoration: none; white-space: nowrap;
  transition: background-color .15s var(--ease), border-color .15s var(--ease);
}
.chipbar__chip[aria-current] { background: var(--roast); border-color: var(--roast); color: var(--on-dark); }

/* One sprite, referenced by <use>. The sprite's shapes carry no stroke of their
   own, so they inherit these: that is what turns a chip's icon gold when the
   chip goes dark, with no second icon set. */
.chipbar__icon, .mcat__icon { flex: none; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; color: var(--rust-text); }
.chipbar__icon { width: 17px; height: 17px; stroke-width: 1.7; }
.mcat__icon { width: 24px; height: 24px; stroke-width: 1.5; }
.chipbar__chip[aria-current] .chipbar__icon { color: var(--gold); }

@media (min-width: 1000px) {
  /* With a mouse a hidden sideways scroll is not discoverable: wrap instead. */
  .chipbar { position: static; flex-wrap: wrap; margin-inline: 0; padding-inline: 0; overflow: visible; border-bottom: 0; }
  .mcats { columns: 2; column-gap: 5rem; }
}

/* A category link must land BELOW the sticky chips. html's scroll-padding
   already clears the top bar, so this adds only the chips' own height. */
.mcat { break-inside: avoid; margin-bottom: 3rem; scroll-margin-top: 4.25rem; }
@media (min-width: 1000px) { .mcat { scroll-margin-top: 1rem; } }   /* the chips do not stick here */
.mcat__title {
  display: flex; align-items: center; gap: .6rem;
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(1.55rem, 5.6vw, 1.8rem); line-height: 1.1;
  padding-bottom: .65rem; border-bottom: 2px solid var(--ink);
}
.mcat__note { margin-top: .7rem; font-size: .875rem; font-weight: 700; color: var(--ink-soft); }
.mcat__sub { font-family: var(--font-accent); font-style: italic; font-weight: 400; font-size: 1.4rem; line-height: 1.1; color: var(--rust-text); margin: 1.5rem 0 0; }

.mlist { display: grid; gap: .9rem; margin-top: 1rem; }

/* Grid, not a flex spacer: below 480px a name can wrap to two lines, and a
   flex-spacer leader would then float at the vertical centre of the row. */
.mrow { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .15rem .75rem; align-items: baseline; }
.mrow__head { min-width: 0; }
.mrow__lead { display: none; }
.mrow__name { font-weight: 700; }
.mrow__meta { font-size: .8125rem; color: var(--ink-soft); margin-left: .4rem; white-space: nowrap; }
/* The description is a row of its own, under the name and the price, so the
   leader's length depends on the name alone and is the same for every row. */
.mrow__desc { grid-column: 1 / -1; font-size: .875rem; line-height: 1.45; color: var(--ink-soft); max-width: 46ch; }
.mrow__price {
  font-family: var(--font-display); font-size: 1.1875rem; line-height: 1.2;
  color: var(--rust-text);
  font-variant-numeric: lining-nums tabular-nums;
  white-space: nowrap;          /* a price must never wrap */
  justify-self: end;
}
.mrow__from { font-family: var(--font-text); font-size: .75rem; font-weight: 700; color: var(--ink-soft); }
.mrow__price--off { font-family: var(--font-text); font-size: .8125rem; font-weight: 700; color: var(--ink-soft); }
.mrow--unavailable .mrow__name { color: var(--ink-soft); }

/* Dotted leaders only where names reliably fit on one line. */
@media (min-width: 480px) {
  .mrow { grid-template-columns: auto minmax(1.5rem, 1fr) auto; }
  .mrow__lead { display: block; border-bottom: 1.5px dotted var(--line-strong); transform: translateY(-.3em); }
}

.tag {
  display: inline-block; margin-left: .4rem; padding: 0 .5rem;
  border: 1px solid currentColor; border-radius: 999px;
  font-size: .6875rem; font-weight: 700; line-height: 1.5; text-transform: capitalize;
  color: var(--ink-soft); vertical-align: middle;
}
.tag--bestseller { color: #8A5A00; }
.tag--spicy, .tag--new { color: var(--rust-text); }

.menu__foot { margin-top: 1rem; text-align: center; }

/* ============================================================================
   Story
   ========================================================================= */

.story__grid { display: grid; gap: 2.5rem; }
.story__name { font-family: var(--font-display); line-height: .95; }
.story__was { font-size: clamp(2rem, 8.5vw, 3.2rem); color: rgba(255, 248, 236, .6); }
.story__was s { text-decoration-line: line-through; text-decoration-thickness: .07em; text-decoration-color: var(--gold-soft); }
.story__is { font-size: clamp(3.4rem, 15vw, 6.4rem); letter-spacing: -.02em; margin-top: .12em; }
.story__is b { font-weight: 400; color: var(--gold-soft); }
.story__text { display: grid; gap: 1rem; max-width: 36rem; }
.story__sig { margin-top: .5rem; }

@media (min-width: 900px) {
  .story__grid { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: 5rem; align-items: center; }
}

/* ============================================================================
   Quick facts and footer
   ========================================================================= */

.foot {
  position: relative;
  background: var(--roast); color: var(--on-dark);
  padding-block: clamp(7rem, 17vw, 10.5rem) 2rem;      /* room for the string lights */
  --focus: var(--gold); --link: var(--gold-soft);
}
.foot .wrap { display: grid; gap: 2.5rem; }
.foot__logo { width: 120px; height: auto; }
.foot__wordmark { width: min(230px, 62vw); height: auto; margin: .9rem 0 .7rem; }
.foot .kicker { color: var(--gold); }
.foot__title { font-family: var(--font-display); font-weight: 400; font-size: 1.6rem; line-height: 1.1; margin-bottom: .9rem; }
.foot__legal { font-size: .8125rem; color: var(--on-dark-soft); }

/* String lights across the top of the footer. The wire is an SVG stretched to
   the footer's width; the bulbs are HTML, because a stretched SVG would squash
   a circle. Their left/top are points on the wire's curve (viewBox 1200 x 100).
   They glow; they do not twinkle. */
.garland { position: absolute; top: 0; left: 0; width: 100%; height: clamp(64px, 10vw, 104px); }
.garland__wire { fill: none; stroke: #6B4A33; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.garland--bulbs i {
  position: absolute; width: 8px; height: 11px; margin-left: -4px;
  border-radius: 45% 45% 50% 50%;
  background: #FFDA8E;
  box-shadow: 0 0 16px 6px rgba(255, 194, 107, .38);
}
.garland--bulbs i:nth-child(1) { left: 7.1%;  top: 44%; }
.garland--bulbs i:nth-child(2) { left: 15.8%; top: 56%; }
.garland--bulbs i:nth-child(3) { left: 24.6%; top: 46%; }
.garland--bulbs i:nth-child(4) { left: 42.1%; top: 45%; }
.garland--bulbs i:nth-child(5) { left: 50.8%; top: 55%; }
.garland--bulbs i:nth-child(6) { left: 59.6%; top: 45%; }
.garland--bulbs i:nth-child(7) { left: 76.4%; top: 43%; }
.garland--bulbs i:nth-child(8) { left: 84.6%; top: 51.5%; }
.garland--bulbs i:nth-child(9) { left: 93%;   top: 40%; }

@media (min-width: 900px) {
  .foot .wrap { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); column-gap: 5rem; }
  .foot__legal { grid-column: 1 / -1; }
}

/* ============================================================================
   Reduced motion — a commonly enabled iOS setting, not an edge case.
   The map simply stands tilted; nothing on the page moves by itself.
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .map__trail, .sign__ring { animation: none; }

  /* The scenes become three ordinary blocks: photo, then copy on roast. The
     image rules are REQUIRED: without them height:100% resolves against an
     auto-height parent and the photos collapse to nothing. */
  .scene { min-height: 0; }
  .scene__media { position: static; height: auto; }
  .scene__media img { height: auto; aspect-ratio: 16 / 10; }
  .scene__body { position: static; max-width: none; background: var(--roast); padding-top: 1.75rem; }
  .scene__body::before { display: none; }
}

@media print {
  .nav, .garland { display: none; }
  .map__stage { --tilt: 0deg; --spin: 0deg; }
}

/* ============================================================================
   The peso sign
   U+20B1 is NOT in the "latin" subset of any webfont here; it lives in
   "latin-ext". Leaving it to a webfont would pull a whole second font file to
   draw one glyph, 73 times. So the peso is drawn from the system stack on
   purpose: it costs nothing and keeps every webfont on the latin subset alone.
   Sized down a little so it sits level with the display face's digits.
   ========================================================================= */

.peso { font-family: var(--font-system); font-size: .8em; font-weight: 700; margin-right: .05em; }
