/* ==========================================================================
   Ronald's Donuts — private owner-review concept
   Six-page sample. Visual system per DESIGN.md: deep red signature surfaces,
   clean white paper, Archivo 900 live display lettering, flat surfaces,
   outlined actions. Layout and motion vocabulary: Juice (bold counter), one
   signature motif. No raster lettering, no decorative shadow, no gradient,
   no second motion.

   Palette note (operator instruction, 2026-09-10): the main paper surfaces are
   clean white (--paper) instead of the earlier warm cream. Deep red #8c1d25
   stays the signature hero/header/footer/accent colour, type on it is white,
   and body reading text stays dark on white. The class name .section--cream is
   kept so no route or region markup has to change; it is the white surface.
   ========================================================================== */

/* 1. Tokens ---------------------------------------------------------------- */

:root {
  --red: #8c1d25;
  --red-deep: #6d151c;
  --paper: #fff;            /* the main canvas, per the operator's white call */
  --on-red: #fff;           /* type on the red surfaces */
  --on-red-soft: rgba(255, 255, 255, .84);   /* captions, notes and meta on red */
  --ink: #2b1715;
  --muted: #684b40;
  --line: #bda789;          /* decorative rules and row dividers on white */
  --line-strong: #8a6a55;   /* control boundaries on white: 4.9:1 */

  --reading: 1232px;
  --display: 1600px;
  --gutter: 32px;
  /* The approved hero's own inline gutter: 7.2vw where that is wider than the
     page gutter, which is what the 1440 mockup measured (103.68px at x104).
     The hero footer reuses it so the source caption lines up with the copy. */
  --hero-pad: max(7.2vw, 32px);

  --s1: 8px; --s2: 12px; --s3: 16px; --s4: 24px;
  --s5: 32px; --s6: 48px; --s7: 64px; --s8: 96px;

  --font: "Archivo", Arial, Helvetica, sans-serif;

  --fs-body: 18px;      --lh-body: 29px;
  --fs-caption: 22px;   --lh-caption: 28px;
  --fs-h2: 52px;        --lh-h2: 54px;
  --fs-h1: 88px;        --lh-h1: 84px;
  --fs-menu-name: 20px; --lh-menu-name: 27px;
  --fs-small: 14px;     --lh-small: 21px;

  /* The approved photographic hero schedules itself: one settled dwell, then
     one opacity fade. Both are named here because the script and the sheet have
     to agree on them, and both are disabled by .reduced and .noanim. */
  --hero-photo-min: 780px;
  --hero-dwell: 7000ms;
  --hero-fade: 1200ms;

  --track-display: -.055em;
  --track-h1: -.04em;
  --track-h2: -.03em;
}

/* 2. Base ------------------------------------------------------------------ */

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

[hidden] { display: none !important; }

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-weight: 400;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-synthesis-weight: none;
}

img { display: block; max-width: 100%; height: auto; }

figure { margin: 0; }

h1, h2, h3, h4, p, ul, ol, dl, figure, table, blockquote { margin: 0; }

ul, ol { padding: 0; list-style: none; }

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 3px; }

address { font-style: normal; }

button, input, summary { font: inherit; color: inherit; }

:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

[data-surface="red"] :focus-visible { outline-color: var(--on-red); }

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

/* 3. Layout helpers -------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: calc(var(--reading) + var(--gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--s8); }
.section--cream { background: var(--paper); color: var(--ink); }
.section--red { background: var(--red); color: var(--on-red); }

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

.skip-link {
  position: absolute;
  top: 0; left: 0;
  z-index: 40;
  padding: var(--s3) var(--s4);
  /* White on a white page needs its own boundary to stay visible. */
  background: var(--paper);
  border: 2px solid var(--ink);
  color: var(--ink);
  font-weight: 700;
  transform: translateY(-120%);
}
.skip-link:focus { transform: translateY(0); }

/* 4. Type ------------------------------------------------------------------ */

.display-1 {
  font-size: var(--fs-h1);
  line-height: var(--lh-h1);
  font-weight: 900;
  letter-spacing: var(--track-h1);
  text-transform: uppercase;
}

.display-2 {
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  font-weight: 900;
  letter-spacing: var(--track-h2);
}

.statement {
  font-size: var(--fs-h2);
  line-height: var(--lh-h2);
  font-weight: 700;
  letter-spacing: -.02em;
  max-width: 20ch;
}

.statement--center {
  margin-inline: auto;
  text-align: center;
  max-width: 22ch;
}

.lede { font-size: var(--fs-body); line-height: var(--lh-body); max-width: 60ch; }

.eyebrow {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}

.prose { max-width: 62ch; }
.prose p + p { margin-top: var(--s4); }
.prose--roomy p + p { margin-top: var(--s5); }

/* 5. Media, captions and credits ------------------------------------------ */

.crop { position: relative; overflow: hidden; background: var(--red-deep); }
.crop img { width: 100%; height: 100%; object-fit: cover; }

.crop--4x3 { aspect-ratio: 4 / 3; }
.crop--16x9 { aspect-ratio: 16 / 9; }
.crop--3x2 { aspect-ratio: 3 / 2; }

/* Licensed 2009 archival storefront. The static uniform 1.316 scale anchored
   to the top-right keeps the whole red sign and the "4600" door number while
   removing the pedestrian at the left edge of the original frame. */
.crop--storefront img {
  transform: scale(1.316);
  transform-origin: 100% 0;
}

/* The macro crop's object-position moved with its photograph into
   .gallery-image[data-variant="macro"] below, because the gallery swaps the
   framing per photograph instead of per fixed slot. The old single-image hero
   slot went the same way when the approved photographic hero replaced it. */
.food-sharing img { object-position: 50% 50%; }

.caption {
  margin-top: var(--s2);
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  font-weight: 500;
  letter-spacing: -.01em;
  color: var(--muted);
  max-width: 46ch;
}
[data-surface="red"] .caption { color: var(--on-red-soft); }

.caption--credit {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: 400;
}
.caption--credit a { text-decoration: underline; }

/* 6. Actions --------------------------------------------------------------- */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  align-items: center;
  margin-top: var(--s5);
}

.action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 20px;
  border: 2px solid currentColor;
  border-radius: 999px;
  font-weight: 700;
  font-size: var(--fs-body);
  line-height: 1.2;
  text-decoration: none;
  /* Restrained control transition: hover fills fade in instead of snapping.
     Background and border only — no lift, no shadow, per the flat surface
     vocabulary. The global reduced-motion block removes the duration. */
  transition: background-color 160ms ease, border-color 160ms ease;
}
.action:hover { background: rgba(43, 23, 21, .08); }
[data-surface="red"] .action:hover { background: rgba(255, 255, 255, .16); }

.action--primary { background: var(--red); border-color: var(--red); color: var(--on-red); }
.action--primary:hover { background: var(--red-deep); border-color: var(--red-deep); }

[data-surface="red"] .action--primary { background: var(--on-red); border-color: var(--on-red); color: var(--red); }
[data-surface="red"] .action--primary:hover { background: #f4e2e3; border-color: #f4e2e3; }

/* Real buttons that carry the outlined-action look (empty state, controls). */
button.action, .action[type="button"] { background: none; cursor: pointer; }
button.action--primary { background: var(--red); }

/* Stacking distances between a heading and the block that follows it. */
.stack-sm { margin-top: var(--s4); }
.stack-md { margin-top: var(--s5); }
.stack-lg { margin-top: var(--s6); }

.title-center { text-align: center; }

/* 7. Header ---------------------------------------------------------------- */

.site-header {
  background: var(--red);
  color: var(--on-red);
  position: relative;
  z-index: 30;
}
.header-inner {
  max-width: calc(var(--display) + var(--gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--gutter);
  min-height: 80px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3) var(--s5);
}

.header-mark {
  font-weight: 900;
  font-size: 22px;
  line-height: 1.1;
  letter-spacing: -.02em;
  text-decoration: none;
  white-space: nowrap;
}
.header-mark:hover { text-decoration: underline; }

.header-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
}
.header-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-weight: 700;
  font-size: 16px;
  line-height: 22px;
  text-decoration: none;
  border-bottom: 3px solid transparent;
  padding-bottom: 2px;
}
.header-nav a:hover { border-bottom-color: currentColor; }
.header-nav a[aria-current="page"] { border-bottom-color: currentColor; }

/* The phone number is an additional utility link and only appears in the
   header row when the six destinations still fit beside it. */
.header-util { display: none; margin-left: 0; }
.header-util a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-weight: 700;
  font-size: 16px;
  text-decoration: none;
  border-bottom: 3px solid transparent;
}
.header-util a:hover { border-bottom-color: currentColor; }
.header-call-short { display: none; }

@media (min-width: 1101px) {
  .header-util { display: block; }
}

/* The disclosure ships open so the six destinations are reachable with no
   JavaScript at all. Above 768px the summary is hidden, so the one navigation
   in the document simply sits in the header row. */
.nav-disclosure { display: block; margin-left: auto; }
.nav-disclosure > summary { display: none; }

.nav-disclosure > summary::-webkit-details-marker { display: none; }

@media (max-width: 768px) {
  :root { --gutter: 20px; }

  .header-inner {
    min-height: 72px;
    gap: var(--s2) var(--s3);
    flex-wrap: wrap;
  }
  .header-mark { font-size: 19px; }
  .header-util { display: block; margin-left: auto; }
  .header-util a { font-size: 15px; }
  .header-call-long { display: none; }
  .header-call-short { display: inline; }

  .nav-disclosure { display: block; order: 3; margin-left: 0; }

  .nav-disclosure > summary {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 16px;
    border: 2px solid currentColor;
    border-radius: 999px;
    font-weight: 700;
    font-size: 15px;
    cursor: pointer;
  }
  .nav-disclosure[open] > summary { background: rgba(255, 255, 255, .18); }

  /* Opened, the disclosure takes its own full-width row in normal flow: the
     six destinations never slide over the page and nothing is scroll-locked. */
  .nav-disclosure[open] {
    flex: 1 0 100%;
    margin-left: 0;
  }
  .nav-disclosure > .header-nav {
    width: 100%;
    margin-left: 0;
    padding-block: var(--s2) var(--s1);
    border-top: 1px solid rgba(255, 255, 255, .34);
  }
  .nav-disclosure > .header-nav ul { flex-direction: column; gap: 0; }
  .nav-disclosure > .header-nav a { min-height: 48px; border-bottom: 0; }
  .nav-disclosure > .header-nav a:hover { text-decoration: underline; }
  .nav-disclosure > .header-nav a[aria-current="page"] { text-decoration: underline; }
}

/* 8. Footer ---------------------------------------------------------------- */

.site-footer {
  background: var(--red);
  color: var(--on-red);
  padding-block: var(--s7) var(--s6);
}
.footer-inner {
  width: 100%;
  max-width: calc(var(--display) + var(--gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.footer-identity {
  font-weight: 900;
  font-size: 72px;
  line-height: .9;
  letter-spacing: var(--track-display);
  text-transform: uppercase;
}
.footer-invite {
  margin-top: var(--s4);
  font-size: var(--fs-h2);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.05;
  max-width: 24ch;
}
.footer-grid {
  margin-top: var(--s6);
  display: grid;
  grid-template-columns: 1.1fr 1fr 1.2fr;
  gap: var(--s5) var(--s6);
  padding-top: var(--s5);
  border-top: 1px solid rgba(255, 255, 255, .36);
}
.footer-head {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--on-red-soft);
}
.footer-col > * + * { margin-top: var(--s2); }
.footer-col { font-size: 16px; line-height: 24px; }
.footer-col a { text-decoration: none; }
.footer-col a:hover { text-decoration: underline; }
.footer-col ul { display: flex; flex-direction: column; gap: 2px; }
.footer-col li a { display: inline-block; padding-block: 5px; }
.footer-address { font-weight: 700; }
.footer-status {
  margin-top: var(--s6);
  padding-top: var(--s4);
  border-top: 1px solid rgba(255, 255, 255, .36);
  font-weight: 700;
}
.footer-status a { text-decoration: underline; }
.footer-top { margin-top: var(--s5); }
.footer-top a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-weight: 700;
  font-size: var(--fs-small);
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* 9. Home — approved photographic hero (OP-HERO) --------------------------- */

/* The header sits on white above the photograph, which is what the approved
   mockup shows. Declared here, after the shared header rules, so it wins at
   equal specificity without an !important. */
.site-header--photo {
  background: var(--paper);
  color: var(--red);
}
.site-header--photo .header-inner { min-height: 94px; }

/* Full-bleed stage. Everything except the crossfade is a still: no translation,
   no zoom, no rotation, no scroll-linked movement. With no JavaScript the box
   photograph is simply present in the HTML and the whole hero reads normally.
   The clip lives on the stage rather than here, because the opening chapter
   pins this section and a clip on the pinned ancestor would cut the pinned
   layer off; DESIGN.md allows a local photo mask, never a sticky ancestor. */
.photo-hero {
  position: relative;
  isolation: isolate;
  min-height: var(--hero-photo-min);
  display: flex;
  background: #291710;
  color: var(--on-red);
}
.photo-hero :focus-visible { outline-color: var(--on-red); }

.photo-stage {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* One slide per photograph, stacked. Visibility is driven entirely by
   [data-active], which ships on the display-case slide in the HTML, so the
   poster is never revealed by script. Only opacity changes; the photos are
   inert. The rules below are written by slide name, never by position, so the
   authored frame order is independent of this sheet. */
.photo-slide {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--hero-fade) ease-in-out;
}
.photo-slide[data-active] { opacity: 1; }

.photo-backdrop {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Approved cover positions, one per photograph. The last of the three original
   crops is the one frame the table leaves at the same place at every width. */
.photo-slide[data-slide="box"] .photo-backdrop { object-position: 78% 50%; }
.photo-slide[data-slide="rings"] .photo-backdrop { object-position: 50% 50%; }
.photo-slide[data-slide="macro"] .photo-backdrop { object-position: 63% 50%; }
.photo-slide[data-slide="case"] .photo-backdrop { object-position: 60% 56%; }

/* The two frames whose subject is narrower than the frame. They are composed
   at their own size on the right against the approved deep-ink field, so the
   storefront sign is never cut to fit a portrait and no source pixel is ever
   enlarged. The field is intentional negative space, not a blurred duplicate. */
.photo-slide[data-fit="contain"] { background: #2b1715; }

.photo-plates {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  display: grid;
  align-content: center;
  justify-items: end;
  padding-inline: var(--hero-pad);
}
.photo-plate {
  grid-area: 1 / 1;
  display: block;
  height: auto;
  object-fit: contain;
  opacity: 0;
  transition: opacity var(--hero-fade) ease-in-out;
}
.photo-plate[hidden] { display: none; }
.photo-plate[data-active] { opacity: 1; }
/* Widths are the approved measures and the height follows the file's own
   ratio, so the rendered box is never taller or wider than the source. */
.photo-plate[data-hero-plate="storefront"] { width: min(52vw, 720px); }
.photo-plate[data-hero-plate="variety"] {
  width: min(42vw, 600px);
  max-height: 640px;
}

/* The dark layer that keeps the copy readable, at the approved values and
   unchanged. Composited over the real pixels of all three photographs at their
   approved cover positions, the block the sentence occupies never drops below
   6.67:1 and the soft caption line never below 7.94:1, so the sentence and the
   source note hold on every frame. The display name is the weak one: its box is
   760px wide, the horizontal gradient has faded by its right-hand end, and a
   background pixel out there measures as low as 1.77:1. The letters are
   left-aligned and stop well short of that; measured glyph by glyph on the
   approved mockup the two lines read 3.06:1 and 2.78:1 against the 3.0:1
   large-text floor. That is a measurement of the mockup, not of a render of
   this build, so the name over each photograph stays an open finding. */
.photo-shade {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(90deg,
      rgba(30, 8, 5, .87) 0%,
      rgba(43, 14, 7, .64) 31%,
      rgba(31, 9, 3, .14) 66%,
      rgba(31, 9, 3, .03) 100%),
    linear-gradient(0deg, rgba(25, 8, 3, .60), transparent 32%);
}

/* Stationary copy. The stacking level is what keeps the name, the sentence and
   the two actions above every photograph and above the shade. */
.photo-copy {
  position: relative;
  z-index: 2;
  padding: 85px var(--hero-pad) 145px;
}
.photo-eyebrow {
  font-size: 12px;
  line-height: 1.2;
  font-weight: 650;
  letter-spacing: .2em;
  text-transform: uppercase;
  margin-bottom: 33px;
}
.photo-copy .hero-wordmark {
  font-size: clamp(72px, 8.6vw, 138px);
  line-height: .91;
  font-weight: 900;
  text-transform: uppercase;
  margin: 0 0 27px;
  max-width: 760px;
  /* tracking has to resolve at each line's own size, so it is deliberately
     neutral here and set on the spans below. */
  letter-spacing: normal;
}
.photo-copy .hero-wordmark span {
  display: block;
  letter-spacing: var(--track-display);
}
.photo-tag {
  font-size: 28px;
  line-height: 1.15;
  font-weight: 800;
  letter-spacing: -.03em;
  margin-bottom: 8px;
}
.photo-description {
  font-size: var(--fs-body);
  line-height: 1.6;
  max-width: 46ch;
}
.photo-copy .actions { margin-top: 28px; }
.photo-call {
  margin-top: 8px;
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: 700;
}
.photo-call a {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  color: var(--on-red);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.photo-call a:hover { color: #f4e2e3; }
.photo-primary {
  background: var(--on-red);
  border-color: var(--on-red);
  color: var(--red);
  min-width: 219px;
  justify-content: space-between;
  gap: 24px;
}
.photo-primary:hover { background: #f4e2e3; border-color: #f4e2e3; }
.photo-secondary { border-color: var(--on-red); color: var(--on-red); }
.photo-arrow { font-size: 20px; line-height: 1; }

/* The caption and the photo controls sit on one line at the bottom of the
   stage. The caption text is raised above the prototype's 12px because it is
   the honest source statement for the photography, and the control row is
   given the space it needs rather than overlapping the copy. */
.photo-footer {
  position: absolute;
  z-index: 3;
  left: var(--hero-pad);
  right: 5vw;
  bottom: 32px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s5);
}
.photo-caption {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  max-width: 52ch;
}
.photo-caption small {
  display: block;
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--on-red-soft);
}

.photo-film {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
  justify-content: flex-end;
}
.photo-thumb {
  display: block;
  flex: none;
  width: 88px;
  height: 65px;
  padding: 4px;
  background: none;
  border: 1px solid rgba(255, 255, 255, .4);
  cursor: pointer;
}
.photo-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.photo-thumb[aria-pressed="true"] { border-color: var(--on-red); border-width: 3px; }
.photo-count {
  margin-left: 6px;
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  letter-spacing: .13em;
  font-variant-numeric: tabular-nums;
}
/* The one live label in the hero sits with the caption, on the dark left of
   every approved cover position, rather than in the bright bottom-right
   corner where the approved mockup's own index label measures its weakest
   contrast. It is a small line of text and it belongs where it is readable. */
.photo-state {
  margin-top: 4px;
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--on-red-soft);
}
.photo-pause {
  min-width: 104px;
  margin-left: 8px;
  border-color: var(--on-red);
  color: var(--on-red);
}

/* The six credits, in one compact source area beside the caption. It ships
   closed and needs no script, so with no JavaScript every frame still has a
   reachable source link; the script moves the matching entry into the caption
   when the frame changes and puts it back when it does not, so no line of copy
   is ever in two places at once. */
.photo-credits {
  margin-top: 6px;
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--on-red-soft);
}
.photo-credits > summary {
  display: flex;
  align-items: center;
  min-height: 44px;
  cursor: pointer;
  color: var(--on-red);
}
.photo-credits-list {
  margin: 0 0 6px 14px;
  padding: 0;
  max-width: 44ch;
}
.photo-credits-list li { margin-bottom: 4px; }
/* The same line is the caption's credit once the script moves it there, so it
   has to read as a caption line in both places and never as a stray list. */
.photo-credit {
  display: block;
  list-style: none;
  font-size: 13px;
  line-height: 19px;
}
.photo-caption .photo-credit { color: var(--on-red-soft); }
/* A source link has to be distinguishable from the words around it by more
   than its colour. */
.photo-credit a { color: inherit; text-decoration: underline; }

/* Until the script that drives them is ready, the selectors, the index, the
   state label and Pause are simply absent; the hero is complete without them. */

/* 9b. Home — the two approved LiveNow chapters ----------------------------- */

/* One mechanism, two instances: the opening photo chapter and the later story
   chapter. The chapter element stays in normal flow and keeps its own height;
   the pin layer is what the script holds against the top of the viewport and
   the surface inside it is what shrinks, from its own bottom edge. Nothing here
   is a still and nothing here is timing: every transform is written by script,
   so a browser with no script, a visitor who asked for less motion, and the
   ?noanim sample all get the plain unscaled sections in ordinary flow. */
.chapter {
  position: relative;
  background: var(--ink);
}
.chapter-pin {
  position: relative;
  z-index: 1;
  display: flex;
  /* The opening chapter is the photo hero, which is itself a row flex
     container; an auto-width pin there would shrink to its content and leave
     the chapter's own backing exposed down one side. flex:1 makes the pin
     claim the full row and min-width:0 stops anything inside it from holding
     that width back. Both are inert on the block-level story chapter, so one
     rule serves the two instances. */
  flex: 1;
  min-width: 0;
}
.chapter-surface {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  transform-origin: 50% 100%;
}
/* The story chapter keeps the white surface it was approved with; it is now the
   layer that shrinks, so the ink that shows around it while it shrinks is the
   chapter's own backing rather than the page. */
[data-chapter="story"] > .chapter-pin > .chapter-surface { background: var(--paper); }

/* A cover is the next opaque section in existing document order. It is full
   width, it paints above the pin, and it stays in normal flow, so it simply
   slides up over the shrinking surface and the two never open a gap. */
.chapter-cover {
  position: relative;
  z-index: 2;
}

/* 9a. Home — approved Google review rail (OP-REVIEWS) ---------------------- */

.review-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s4) var(--s6);
  margin-bottom: var(--s6);
}
.review-aggregate {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}
.review-source-label {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
}
.review-aggregate-link {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  text-decoration: none;
  border-bottom: 3px solid var(--red);
  padding-bottom: 4px;
}
.review-aggregate-link:hover { border-bottom-color: var(--red-deep); }
.review-score {
  font-size: 40px;
  line-height: 1;
  font-weight: 900;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.review-score-of { font-size: 20px; font-weight: 700; }
.review-count { font-size: var(--fs-body); font-weight: 700; }

/* The rail is a native horizontal scroller first: all ten records are in the
   HTML, in capture order, reachable by touch, by wheel and by Tab with no
   script at all. Snap points are a convenience, never a requirement. */
.review-rail {
  display: block;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  /* Room for the focus outline on the cards at both ends. */
  padding: 4px;
  margin: -4px;
}
.review-rail:focus-visible { outline-offset: 6px; }
.review-track {
  display: flex;
  gap: 22px;
  align-items: stretch;
}
.review-card {
  flex: 0 0 calc((100% - 44px) / 3);
  min-width: 0;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  padding: 28px;
  min-height: 245px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-top: 3px solid var(--red);
}
.review-author {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 900;
}
.review-author a { text-decoration: none; }
.review-author a:hover { text-decoration: underline; }
/* A typographic badge, never a copied avatar. */
.review-initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 36px;
  height: 36px;
  background: var(--red);
  color: var(--on-red);
  font-size: 17px;
  font-weight: 900;
  text-transform: uppercase;
}
.review-text { font-size: var(--fs-body); line-height: var(--lh-body); }
/* The source link is the smallest type in the card and is still 14px. */
.review-source {
  margin-top: auto;
  padding-top: var(--s3);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
}
.review-source a { font-weight: 700; }

.review-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3) var(--s5);
  margin-top: var(--s6);
}
.review-range { font-size: var(--fs-small); line-height: var(--lh-small); font-weight: 700; }
.review-arrows { display: flex; gap: var(--s3); }
.review-arrows .action { min-height: 44px; min-width: 120px; }
.review-arrows .action[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }

.review-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3) var(--s5);
  margin-top: var(--s6);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
}
.review-foot .note { margin-top: 0; }
.review-community { font-size: var(--fs-body); line-height: var(--lh-body); font-weight: 700; }

/* 9b. Home — the real map above the footer (OP-MAP) ------------------------ */

/* The Home map reuses the shared .map-frame drawn for Location and Contact, so
   there is one map style across the site; only the height and the two-line
   invitation are particular to this region. */
.home-map { padding-block: 80px; }
.home-map .map-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s4) var(--s6);
  margin-bottom: var(--s6);
}
.home-map .display-2 { max-width: 18ch; }
.map-contact { text-align: right; }
.map-contact .map-address {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 700;
}
.home-map .map-frame iframe { height: 460px; }
.home-map .map-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3) var(--s5);
  margin-top: var(--s5);
}
.home-map .map-foot .note { margin-top: 0; }
.home-map .map-foot .actions { margin-top: 0; }

/* 9c. Home — the bounded counter corridor (WOW-CORRIDOR-CRAIG-20260920) ---
   A single scroll-led depth moment, kept inside the existing Juice counter
   language. The stage is decorative; the adjacent step articles are the
   semantic content and remain in normal document flow in every mode. */
.corridor-section {
  position: relative;
  z-index: 2;
  /* No overflow clip here: a hidden overflow on this ancestor would become
     the sticky stage's scrolling ancestor, so the stage could never dock to
     the viewport on any width. The stage clips its own planes, so nothing
     inside the section can escape anyway. */
  padding-block: clamp(72px, 10vw, 152px);
}
.corridor-intro {
  display: grid;
  grid-template-columns: minmax(0, 56fr) minmax(0, 44fr);
  gap: var(--s5) var(--s7);
  align-items: end;
  margin-bottom: var(--s7);
}
.corridor-intro .display-2 { max-width: 13ch; }
.corridor-intro .lede {
  max-width: 37ch;
  justify-self: end;
  padding-bottom: 4px;
}
.corridor-track {
  display: grid;
  grid-template-columns: minmax(0, 56fr) minmax(0, 44fr);
  gap: clamp(28px, 5vw, 96px);
  align-items: start;
  min-height: 168vh;
}
.corridor-stage {
  position: sticky;
  top: clamp(92px, 13vh, 136px);
  height: min(67vh, 680px);
  min-height: 460px;
  overflow: hidden;
  isolation: isolate;
  background: var(--ink);
  border: 2px solid var(--ink);
  color: var(--on-red);
  perspective: 1200px;
}
.corridor-stage::before,
.corridor-stage::after {
  content: "";
  position: absolute;
  z-index: 0;
  pointer-events: none;
  border: 1px solid rgba(255, 255, 255, .22);
}
.corridor-stage::before { inset: 18px; }
.corridor-stage::after { inset: 32px; border-color: rgba(255, 255, 255, .1); }
.corridor-stage-grid {
  position: absolute;
  inset: 50% 0 auto;
  z-index: 0;
  height: 1px;
  background: rgba(255, 255, 255, .18);
}
.corridor-stage-label,
.corridor-stage-depth {
  position: absolute;
  z-index: 6;
  font-size: 12px;
  line-height: 18px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .8);
}
.corridor-stage-label { top: 20px; left: 24px; }
.corridor-stage-depth { right: 24px; bottom: 20px; font-variant-numeric: tabular-nums; }
.corridor-plane {
  position: absolute;
  z-index: 1;
  overflow: hidden;
  margin: 0;
  background: var(--red-deep);
  border: 2px solid var(--paper);
  transform-style: preserve-3d;
  will-change: transform;
  transition: transform 180ms cubic-bezier(.22, .61, .21, 1);
}
.corridor-plane img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.corridor-plane--case {
  top: 15%;
  left: 8%;
  width: 62%;
  height: 56%;
  transform: translate3d(-8px, 20px, -120px) rotateY(-8deg) rotateZ(-4deg);
}
.corridor-plane--case img { object-position: 58% 56%; }
.corridor-plane--box {
  top: 29%;
  right: 8%;
  width: 31%;
  height: 45%;
  z-index: 2;
  transform: translate3d(16px, 12px, -260px) rotateY(8deg) rotateZ(6deg);
}
.corridor-plane--box img { object-position: 50% 50%; }
.corridor-plane--storefront {
  bottom: 8%;
  left: 27%;
  width: 46%;
  height: 31%;
  z-index: 3;
  transform: translate3d(-4px, 30px, -380px) rotateY(-4deg) rotateZ(-2deg);
}
.corridor-plane--storefront img { object-position: 50% 50%; }
.corridor-arrival-mark {
  position: absolute;
  right: 22px;
  top: 28%;
  z-index: 5;
  display: block;
  font-size: clamp(22px, 3vw, 48px);
  line-height: .86;
  font-weight: 900;
  letter-spacing: -.05em;
  text-align: right;
  text-transform: uppercase;
  color: var(--on-red);
  opacity: .9;
}
.corridor-copy {
  display: grid;
  align-content: start;
  gap: 0;
}
.corridor-step {
  min-height: 56vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(28px, 4vw, 64px) 0;
  border-top: 3px solid var(--ink);
  scroll-margin-top: 120px;
}
.corridor-step + .corridor-step { border-top-width: 1px; }
.corridor-step.is-current:not(.corridor-step--arrival) { border-top-color: var(--red); }
.corridor-index {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--red);
}
.corridor-step h3 {
  max-width: 13ch;
  margin-top: var(--s3);
  font-size: clamp(30px, 3vw, 48px);
  line-height: .98;
  font-weight: 900;
  letter-spacing: -.04em;
}
.corridor-step > p:not(.corridor-index):not(.caption) {
  max-width: 38ch;
  margin-top: var(--s4);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}
.corridor-step .caption {
  max-width: 42ch;
  margin-top: var(--s4);
}
.corridor-step .actions { margin-top: var(--s5); }
.corridor-step--arrival {
  padding-inline: clamp(24px, 3vw, 48px);
  background: var(--red);
  border-top-color: var(--red);
  color: var(--on-red);
}
.corridor-step--arrival .corridor-index { color: var(--on-red-soft); }
.corridor-step--arrival .caption { color: var(--on-red-soft); }
.corridor-step--arrival .action { color: var(--on-red); }
.corridor-step--arrival .action--primary { color: var(--red); }

/* 10. Home — remaining sections ------------------------------------------- */

.split {
  display: grid;
  gap: var(--s6);
  align-items: start;
}
.split--58-42 { grid-template-columns: minmax(0, 42fr) minmax(0, 58fr); }
.split--40-60 { grid-template-columns: minmax(0, 40fr) minmax(0, 60fr); }
.split--55-45 { grid-template-columns: minmax(0, 55fr) minmax(0, 45fr); }

.price-list { margin-top: var(--s5); border-top: 1px solid var(--line); }
.price-row {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  padding-block: var(--s3);
  border-bottom: 1px solid var(--line);
}
.price-row-name { font-size: var(--fs-menu-name); line-height: var(--lh-menu-name); font-weight: 700; }
.price-row-note { display: block; font-size: 15px; line-height: 22px; font-weight: 400; color: var(--muted); }
.price-row-amount {
  margin-left: auto;
  font-size: var(--fs-menu-name);
  line-height: var(--lh-menu-name);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.note {
  margin-top: var(--s4);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--muted);
  max-width: 62ch;
}
[data-surface="red"] .note { color: var(--on-red-soft); }

.community-cols {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: var(--s5) var(--s7);
  margin-top: var(--s6);
}
.comment-block { border-top: 3px solid var(--ink); padding-top: var(--s3); }
.comment-name { font-size: 22px; line-height: 28px; font-weight: 900; }
.comment-text { margin-top: var(--s2); font-size: var(--fs-body); line-height: var(--lh-body); max-width: 42ch; }
.comment-source { margin-top: var(--s2); font-size: var(--fs-small); line-height: var(--lh-small); }
/* The provenance note and the section CTA drop into the second column, under
   the shorter quote, so the right column carries its share of the block
   instead of emptying out below it. The single-column phone layout resets the
   placement, which puts the note and CTA back after both quotes — the reading
   order they already had. */
.community-foot { grid-column: 2; }

.visit-copy .visit-address { font-size: 40px; line-height: 1.05; font-weight: 900; letter-spacing: -.03em; }
.visit-copy .visit-phone { margin-top: var(--s3); font-size: 26px; font-weight: 700; }

/* 11. Menu ----------------------------------------------------------------- */

/* The page band already contributes the red field above the content, so the
   open block below it only needs a short lead-in: together they used to add
   112px of dead red before the first useful sentence. */
.page-band { background: var(--red); color: var(--on-red); padding-block: var(--s6) var(--s5); }
.page-band .display-1 { margin-bottom: var(--s4); }

.page-open { padding-block: var(--s5) var(--s6); }

.menu-intro-grid {
  display: grid;
  grid-template-columns: minmax(0, 54fr) minmax(0, 42fr);
  gap: var(--s5) var(--s6);
  align-items: start;
}
.menu-intro-grid .caption { font-size: var(--fs-small); line-height: var(--lh-small); }
.menu-intro-grid .actions { margin-top: var(--s4); }

.menu-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--s4) var(--s5);
  padding-bottom: var(--s4);
  border-bottom: 2px solid var(--ink);
}
.menu-tabs { display: flex; flex-wrap: wrap; gap: var(--s2); }
.menu-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
  min-height: 48px;
  padding: 0 18px;
  background: none;
  border: 2px solid var(--ink);
  border-radius: 999px;
  font-weight: 700;
  font-size: 17px;
  cursor: pointer;
}
.menu-tab[aria-selected="true"] {
  background: var(--ink);
  color: var(--paper);
}
.menu-tab-count { font-variant-numeric: tabular-nums; opacity: .72; }
.menu-tab[aria-selected="true"] .menu-tab-count { opacity: .82; }

.menu-search { margin-left: auto; }
.menu-search label { display: block; font-size: var(--fs-small); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.menu-search-row { display: flex; gap: var(--s2); margin-top: var(--s1); }
.menu-search input {
  min-height: 48px;
  width: 260px;
  max-width: 100%;
  padding: 0 16px;
  background: var(--paper);
  border: 2px solid var(--line-strong);
  border-radius: 999px;
  font-size: 17px;
}
.menu-search button {
  min-height: 48px;
  padding: 0 16px;
  background: none;
  border: 2px solid var(--ink);
  border-radius: 999px;
  font-weight: 700;
  font-size: 15px;
  cursor: pointer;
}

.menu-body {
  display: grid;
  grid-template-columns: 224px minmax(0, 1fr);
  gap: var(--s6);
  margin-top: var(--s4);
  align-items: start;
}

/* The rail follows the visitor down the list, so the category filter stays
   reachable while browsing instead of scrolling away above the first rows.
   The provenance note closes the list column, under the last row, where a
   footnote belongs. Solo mode (Drinks) keeps the same order in its one
   column: list first, then the note. Nothing spans two rows here, so no
   item's height can leak into the other column's track sizing. */
@media (min-width: 1024px) {
  .menu-rail { position: sticky; top: var(--s4); }
  .menu-body > .menu-list { grid-column: 2; grid-row: 1; }
  .menu-body > .menu-source-note { grid-column: 2; grid-row: 2; }
  .menu-body--solo > .menu-list { grid-column: 1; grid-row: 1; }
  .menu-body--solo > .menu-source-note { grid-column: 1; grid-row: 2; }
}
/* Applied while the Drinks tab is selected. The food-category rail is hidden
   then, and without this the grid would keep its 224px first column and
   squeeze the whole list into it. */
.menu-body--solo { grid-template-columns: minmax(0, 1fr); }
.menu-rail { display: flex; flex-direction: column; gap: var(--s2); }
.menu-rail-title {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.menu-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
  min-height: 44px;
  padding: 0 16px;
  background: none;
  border: 2px solid var(--line-strong);
  border-radius: 999px;
  font-weight: 700;
  font-size: 16px;
  text-align: left;
  cursor: pointer;
}
.menu-chip[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.menu-chip--link { text-decoration: none; }

.menu-list { max-width: 800px; }
.menu-source-note {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--muted);
  max-width: 70ch;
  padding-bottom: var(--s3);
}
.menu-group + .menu-group { margin-top: var(--s4); }
.menu-group-title {
  font-size: 26px;
  line-height: 32px;
  font-weight: 900;
  letter-spacing: -.02em;
  text-transform: uppercase;
  padding-bottom: var(--s2);
  border-bottom: 3px solid var(--ink);
}
.menu-rows { border-bottom: 1px solid var(--line); }
.menu-row {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  min-height: 64px;
  padding-block: var(--s2);
  border-top: 1px solid var(--line);
}
.menu-rows .menu-row:first-child { border-top: 0; }
.menu-row-name {
  font-size: var(--fs-menu-name);
  line-height: var(--lh-menu-name);
  font-weight: 700;
  overflow-wrap: anywhere;
}
.menu-row-note { display: block; font-size: 15px; line-height: 22px; font-weight: 400; color: var(--muted); }
.menu-row-price {
  margin-left: auto;
  flex: 0 0 auto;
  font-size: var(--fs-menu-name);
  line-height: var(--lh-menu-name);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.menu-empty {
  margin-top: var(--s4);
  padding: var(--s5);
  border: 2px solid var(--line-strong);
  border-radius: 4px;
}
.menu-empty p { font-weight: 700; }
.menu-empty .actions { margin-top: var(--s3); }

.menu-count {
  margin-top: var(--s4);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: 700;
  color: var(--muted);
}

/* 12. Location / Contact map ---------------------------------------------- */

.map-frame {
  border: 2px solid var(--line-strong);
  border-radius: 4px;
  overflow: hidden;
  background: var(--paper);
}
.map-frame iframe {
  display: block;
  width: 100%;
  height: 440px;
  border: 0;
}
.map-fallback {
  padding: var(--s3) var(--s4);
  border-top: 1px solid var(--line);
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  color: var(--muted);
}
.contact-map .map-frame iframe { height: 360px; }

.map-detail { margin-top: var(--s5); }
.map-address { font-size: 26px; line-height: 1.15; font-weight: 900; letter-spacing: -.02em; }

/* 12b. Photo gallery and lightbox -----------------------------------------
   The same four permitted photographs, browsable. This is a functional
   image-browser inside the approved Juice image region: the large photograph
   keeps the composition the single-image version had, the four thumbnails
   swap it, and opening any photograph shows it larger in a native <dialog>.
   The markup ships as ordinary links, so with no JavaScript every thumbnail
   and the large photograph still open their own file. */

.gallery { display: grid; gap: var(--s3); }
.gallery-head { display: grid; gap: var(--s1); }
.gallery-label {
  font-size: 26px;
  line-height: 32px;
  font-weight: 900;
  letter-spacing: -.02em;
  text-transform: uppercase;
}
.gallery-lede { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--muted); max-width: 54ch; }

.gallery-stage { display: grid; gap: var(--s2); }
.gallery-open { display: block; text-decoration: none; }
.gallery-crop { aspect-ratio: 4 / 3; }
.gallery-image { object-position: 50% 50%; }
/* The approved framing of each photograph, carried over from the single-image
   regions these pictures sat in before. */
.gallery-image[data-variant="ring"]  { object-position: 45% 55%; }
.gallery-image[data-variant="macro"] { object-position: 63% 50%; }
.gallery-image[data-variant="box"]   { object-position: 50% 50%; }
.gallery-image[data-variant="store"] { transform: scale(1.316); transform-origin: 100% 0; }

.gallery-caption { display: grid; gap: var(--s1); }
.gallery-caption .caption { margin-top: 0; font-size: var(--fs-small); line-height: var(--lh-small); }

.gallery-thumbs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s2);
}
.gallery-thumb {
  display: block;
  padding: 0;
  border: 3px solid transparent;
  border-radius: 4px;
  overflow: hidden;
  background: none;
  cursor: pointer;
}
.gallery-thumb img { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; }
.gallery-thumb:hover { border-color: var(--line-strong); }
.gallery-thumb[aria-current="true"],
.gallery-thumb[aria-pressed="true"] { border-color: var(--ink); }

/* The viewer itself. Native <dialog> + showModal() supplies the focus trap,
   the Escape key and the inert page behind it; this only sets the frame. */
.lightbox {
  width: min(100% - var(--s4), 1080px);
  max-width: none;
  max-height: calc(100vh - var(--s4));
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: var(--paper);
  color: var(--ink);
  overflow: auto;
}
/* An engine without <dialog> support must never spill the viewer into the page. */
dialog.lightbox:not([open]) { display: none; }
.lightbox::backdrop { background: rgba(43, 23, 21, .76); }

.lightbox-box { padding: var(--s4); display: grid; gap: var(--s3); }
.lightbox-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s2) var(--s4); }
.lightbox-label {
  font-size: 20px;
  line-height: 27px;
  font-weight: 900;
  letter-spacing: -.01em;
  text-transform: uppercase;
}
.lightbox-count {
  font-size: var(--fs-small);
  line-height: var(--lh-small);
  font-weight: 700;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.lightbox-close { margin-left: auto; }

.lightbox-stage { display: grid; }
.lightbox-item { display: grid; gap: var(--s2); }
/* The frame keeps each photograph's own proportion and is bounded by height as
   well as width, so nothing is stretched and nothing is cropped to fit a box
   the picture was not taken for. */
.lightbox-frame { margin-inline: auto; overflow: hidden; background: rgba(43, 23, 21, .06); }
.lightbox-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
.lightbox-frame--16x9 { aspect-ratio: 16 / 9; width: min(100%, calc(58vh * 16 / 9)); }
.lightbox-frame--4x3 { aspect-ratio: 4 / 3; width: min(100%, calc(58vh * 4 / 3)); }

.lightbox-meta { display: grid; gap: var(--s1); }
.lightbox-meta .caption { margin-top: 0; max-width: 72ch; font-size: var(--fs-small); line-height: var(--lh-small); }

.lightbox-nav { display: flex; flex-wrap: wrap; gap: var(--s3); }

/* 12c. The real-shop gallery ------------------------------------------------
   Five photographs of the shop itself, each one shared on Google Maps by a
   contributor. Nothing here is illustrative and nothing is stretched: every
   figure keeps its own aspect ratio, is never shown wider than the width it is
   composed at (all of which sit below the file's own pixel width), and carries
   the contributor and a link to the source it came from. The paired stagger is
   the approved composition; the ordinary markup underneath it means all five
   photographs are visible in the page with no JavaScript at all. */

.business-gallery { display: grid; gap: var(--s3); }

/* The five real photographs are the full-measure band of this section, not a
   column of the split above them: the gallery spans both of the split's
   columns so the staggered composition reads at the whole width instead of
   being squeezed into the 42% column and leaving the rest of the row empty.
   The composition itself is unchanged — the same asymmetric 12-column grid,
   the same per-figure ceilings and the same credits. Below 1024px the split
   is a single column and this spans that one column unchanged. */
#story-food .split > .business-gallery { grid-column: 1 / -1; }

.business-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: start;
  gap: 44px 28px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.business-cell { min-width: 0; }
.business-cell--storefront { grid-column: 1 / span 6; }
.business-cell--interior   { grid-column: 8 / span 5; justify-self: end; padding-top: 32px; }
.business-cell--plate      { grid-column: 1 / span 4; }
.business-cell--variety    { grid-column: 5 / span 4; }
.business-cell--case       { grid-column: 9 / span 4; justify-self: end; }

.business-figure { display: grid; gap: var(--s2); margin: 0; width: 100%; }
.business-cell--storefront .business-figure { max-width: 480px; }
.business-cell--interior   .business-figure { max-width: 440px; }
.business-cell--plate      .business-figure { max-width: 300px; }
.business-cell--variety    .business-figure { max-width: 340px; }
.business-cell--case       .business-figure { max-width: 380px; }

.business-open { display: block; text-decoration: none; }
.business-image {
  display: block;
  width: 100%;
  height: auto;
  background: rgba(43, 23, 21, .06);
}

.business-caption { display: grid; gap: var(--s1); }
.business-caption .caption { margin-top: 0; font-size: var(--fs-small); line-height: var(--lh-small); }
.business-caption .caption--credit { color: var(--muted); }

/* The viewer reuses the dialog frame above. Its own frame holds each
   photograph at its natural ratio instead of cropping it to a fixed box, and
   is bounded by the viewport height, so the one portrait picture is shown
   whole and nothing is ever blown up past the pixels that exist. The
   caption sits under the image and scrolls with the dialog if it needs to. */
.business-item { display: grid; gap: var(--s2); }
.business-frame {
  display: grid;
  place-items: center;
  overflow: hidden;
  background: rgba(43, 23, 21, .06);
}
.business-frame img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 58vh;
  object-fit: contain;
}

/* 13. Customers ------------------------------------------------------------ */

.customers-intro-grid {
  display: grid;
  grid-template-columns: minmax(0, 60fr) minmax(0, 34fr);
  gap: var(--s5) var(--s6);
  align-items: end;
}
.customers-intro-grid .caption { font-size: var(--fs-small); line-height: var(--lh-small); }

.comment-pairs { display: grid; gap: var(--s6) var(--s7); }
.comment-pair { display: grid; gap: var(--s6) var(--s7); }
.comment-pair--wide-left { grid-template-columns: minmax(0, 55fr) minmax(0, 37fr); }
.comment-pair--wide-right { grid-template-columns: minmax(0, 37fr) minmax(0, 55fr); }
.comment-trio { display: grid; gap: var(--s6); }

.comment-entry { border-top: 3px solid var(--ink); padding-top: var(--s3); }
.comment-index {
  display: block;
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: .1em;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.comment-entry .comment-name { margin-top: var(--s1); font-size: 24px; line-height: 28px; }
.comment-entry .comment-text { font-size: var(--fs-body); line-height: var(--lh-body); max-width: 44ch; }
.comment-link { display: inline-flex; align-items: center; min-height: 44px; font-size: var(--fs-small); font-weight: 700; }

/* 14. Story ---------------------------------------------------------------- */

.story-intro-grid {
  display: grid;
  grid-template-columns: minmax(0, 40fr) minmax(0, 54fr);
  gap: var(--s5) var(--s6);
  align-items: start;
}

.food-chapters { display: grid; gap: var(--s6); }
.food-chapter { border-top: 1px solid var(--line); padding-top: var(--s3); }
.food-chapter h3 { font-size: 26px; line-height: 32px; font-weight: 900; letter-spacing: -.02em; }
.food-chapter p { margin-top: var(--s2); font-size: var(--fs-body); line-height: var(--lh-body); max-width: 52ch; }
.food-chapter .food-chapter-link { display: inline-flex; align-items: center; min-height: 44px; margin-top: var(--s1); font-size: var(--fs-small); font-weight: 700; }

.vegan-cols {
  display: grid;
  grid-template-columns: minmax(0, 48fr) minmax(0, 44fr);
  gap: var(--s5) var(--s7);
  margin-top: var(--s5);
}

/* 15. Contact -------------------------------------------------------------- */

.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 46fr) minmax(0, 54fr);
  gap: var(--s5) var(--s7);
  align-items: start;
}
.contact-phone { font-size: 32px; line-height: 1.1; font-weight: 900; letter-spacing: -.02em; }
.contact-phone a { text-decoration: none; }
.contact-phone a:hover { text-decoration: underline; }

.hours-table { width: 100%; border-collapse: collapse; }
.hours-table caption { text-align: left; }
.hours-table th, .hours-table td {
  text-align: left;
  padding-block: var(--s2);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}
.hours-table td { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.hours-heading { font-size: 26px; line-height: 32px; font-weight: 900; letter-spacing: -.02em; }

.questions { border-top: 3px solid var(--ink); }
.questions details { border-bottom: 1px solid var(--line); }
.questions summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  min-height: 48px;
  padding-block: var(--s3);
  font-size: 20px;
  line-height: 27px;
  font-weight: 700;
  cursor: pointer;
  list-style: none;
}
.questions summary::-webkit-details-marker { display: none; }
.questions summary::after { content: "+"; font-weight: 700; font-size: 24px; line-height: 1; }
.questions details[open] summary::after { content: "\2013"; }
.questions .question-body { padding-bottom: var(--s4); max-width: 74ch; }
.questions .question-body > * + * { margin-top: var(--s3); }
.questions .question-body ul { display: flex; flex-direction: column; gap: var(--s1); }
.questions .question-body li { padding-left: var(--s4); position: relative; }
.questions .question-body li::before { content: "\2014"; position: absolute; left: 0; color: var(--muted); }
.question-confirm { font-weight: 700; }

/* The full provenance lives behind one native disclosure on Contact, so the
   booking-and-hours help above stays prominent while every source, status note
   and credit remains one keystroke away. */
.source-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  min-height: 56px;
  padding-block: var(--s3);
  border-block: 2px solid var(--ink);
  font-size: 20px;
  line-height: 27px;
  font-weight: 900;
  cursor: pointer;
  list-style: none;
}
.source-summary::-webkit-details-marker { display: none; }
.source-summary::after { content: "+"; font-size: 24px; line-height: 1; }
.source-notes[open] .source-summary::after { content: "\2013"; }

.source-notes { font-size: var(--fs-small); line-height: var(--lh-small); }
.source-notes .source-cols { margin-top: var(--s5); }
.source-notes h3 { font-size: 17px; line-height: 24px; font-weight: 900; margin-top: var(--s5); }
.source-notes h3:first-child { margin-top: 0; }
.source-notes > div > div > * + *:not(h3) { margin-top: var(--s2); }
.source-notes ul { display: flex; flex-direction: column; gap: 2px; }
.source-notes li a { overflow-wrap: anywhere; }
.source-notes a { text-decoration: underline; }
.source-email { overflow-wrap: anywhere; font-weight: 700; }
.source-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s5) var(--s7); }

/* 16. Responsive ----------------------------------------------------------- */

@media (max-width: 1279px) {
  :root {
    --gutter: 24px;
    --fs-h1: 76px; --lh-h1: 74px;
    --fs-h2: 46px; --lh-h2: 48px;
  }
  .footer-identity { font-size: 62px; }
}

@media (max-width: 1023px) {
  :root {
    --fs-h1: 64px; --lh-h1: 62px;
    --fs-h2: 40px; --lh-h2: 44px;
  }
  /* The photographic hero keeps the desktop proportions down to here, then
     hands the footer back to normal flow so the caption and the selectors can
     never collide with the copy or run off the stage. The stage is allowed to
     grow past its minimum rather than clip. */
  .photo-hero { min-height: 740px; }
  .photo-copy { padding: 62px 24px var(--s5); }
  .photo-copy .hero-wordmark { font-size: min(80px, 10.4vw); }
  .photo-footer {
    position: static;
    margin-top: auto;
    padding: 0 24px var(--s5);
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s4);
  }
  .photo-film { justify-content: flex-start; }
  /* The two contained frames leave the desktop overlap and take a band of their
     own in normal flow, above the caption, so nothing can land on them. The
     band is a grid, so the taller of the two sets its height whichever frame is
     showing and the stage never jumps between them. */
  .photo-plates {
    position: relative;
    inset: auto;
    padding: 0 24px var(--s5);
  }
  .photo-plate[data-hero-plate="storefront"] { width: min(46vw, 480px); }
  .photo-plate[data-hero-plate="variety"] { width: min(46vw, 460px); }
  /* Reserved for the tallest caption and its credit, so a longer source line on
     a real frame never shifts the section under it. */
  .photo-caption { min-height: 88px; }
  .photo-slide[data-slide="box"] .photo-backdrop { object-position: 70% 50%; }
  .photo-slide[data-slide="rings"] .photo-backdrop { object-position: 45% 50%; }
  .review-card { flex-basis: calc((100% - 22px) / 2); }
  .review-head { margin-bottom: var(--s5); }
  .home-map { padding-block: 56px; }
  .home-map .display-2 { font-size: 40px; line-height: 44px; max-width: none; }
  .home-map .map-head { align-items: flex-start; }
  .map-contact { text-align: left; }
  .home-map .map-frame iframe { height: 400px; }
  .section { padding-block: var(--s7); }
  .corridor-track { gap: var(--s5); min-height: 162vh; }
  .corridor-stage { top: 88px; min-height: 380px; height: min(62vh, 560px); }
  .corridor-step { min-height: 54vh; }
  .split--58-42, .split--40-60, .split--55-45,
  .menu-intro-grid, .customers-intro-grid, .story-intro-grid,
  .contact-grid, .vegan-cols, .source-cols {
    grid-template-columns: minmax(0, 1fr);
  }
  .menu-body { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .menu-rail { flex-direction: row; flex-wrap: wrap; align-items: center; }
  .menu-rail-title { flex: 1 0 100%; }
  .comment-pair--wide-left, .comment-pair--wide-right { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  /* Two columns at the approved 44% / 48% measure, with the case kept on the
     right so the stagger still reads. Every figure keeps its own ceiling, so
     nothing is stretched past the width it was composed at. */
  .business-grid {
    grid-template-columns: 44% 48%;
    justify-content: space-between;
    gap: 32px 24px;
  }
  .business-cell { grid-column: auto; justify-self: start; }
  .business-cell--case { grid-column: 2; justify-self: end; }
  /* At this width the two columns are the composition, so a figure fills its
     column and only the source photograph's own pixels cap it. The plate is
     the one picture whose file is narrower than a column here. */
  .business-cell--storefront .business-figure,
  .business-cell--interior .business-figure,
  .business-cell--case .business-figure { max-width: 680px; }
  .business-cell--plate .business-figure { max-width: 382px; }
  .business-cell--variety .business-figure { max-width: 477px; }
}

@media (max-width: 768px) {
  /* The name is the display element, so it keeps the left margin of the copy
     above it and is never allowed past the gutter. 15vw is the phone cap the
     approval names; the 80px ceiling keeps 700–768px on the tablet measure. */
  .photo-copy .hero-wordmark { font-size: min(80px, 15vw); }
  .photo-tag { font-size: 25px; }
  /* Six selectors in the approved two rows of three, with the index and Pause
     on the row under them. */
  .photo-film {
    display: grid;
    grid-template-columns: repeat(3, auto);
    justify-content: start;
    gap: var(--s2) var(--s3);
  }
  .photo-count { margin-left: 0; }
  .photo-pause { margin-left: 0; }
  .photo-description { font-size: 16px; line-height: 26px; }
  .corridor-section { padding-block: var(--s7); }
  .corridor-intro { grid-template-columns: minmax(0, 1fr); gap: var(--s3); margin-bottom: var(--s5); }
  .corridor-intro .lede { justify-self: start; padding-bottom: 0; }
  .corridor-track { display: block; min-height: 0; }
  /* The stage docks just under the top edge while its three steps scroll past
     beneath it, so the moving photographs and the active step's copy share
     the phone screen for the whole sequence. It paints above the copy (its
     own solid ink surface and z-index), clips its own planes, and adds no
     scroll height: the corridor is still the stage plus the three steps. */
  .corridor-stage {
    position: sticky;
    top: 10px;
    z-index: 6;
    height: min(50vh, 340px);
    min-height: 280px;
    margin-bottom: var(--s4);
  }
  .corridor-stage-label { top: 16px; left: 18px; }
  .corridor-stage-depth { right: 18px; bottom: 16px; }
  .corridor-stage::before { inset: 12px; }
  .corridor-stage::after { inset: 22px; }
  .corridor-plane--case { left: 7%; width: 65%; }
  .corridor-plane--box { right: 7%; width: 34%; }
  .corridor-plane--storefront { left: 24%; width: 52%; }
  .corridor-copy { gap: var(--s3); }
  .corridor-step { min-height: 0; padding: var(--s6) 0; }
  .corridor-step--arrival { padding-inline: var(--s4); }
  .corridor-step h3 { max-width: 16ch; font-size: 34px; line-height: 1; }
  .review-card { flex-basis: 86%; }
  .footer-grid { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
}

@media (max-width: 599px) {
  :root {
    --gutter: 20px;
    --fs-h1: 44px; --lh-h1: 44px;
    --fs-h2: 32px; --lh-h2: 35px;
    --fs-body: 17px; --lh-body: 27px;
    --fs-caption: 20px; --lh-caption: 26px;
    --fs-menu-name: 17px; --lh-menu-name: 24px;
  }
  .section { padding-block: var(--s6); }
  .page-band, .page-open { padding-block: var(--s5); }
  .footer-identity { font-size: 38px; }
  .footer-invite { font-size: 28px; }
  .footer-inner { padding-bottom: 0; }
  .site-footer { padding-block: var(--s6) var(--s5); }
  .corridor-stage { height: min(46vh, 320px); min-height: 230px; }
  .photo-copy { padding: 40px 20px var(--s4); }
  .photo-eyebrow { margin-bottom: 18px; }
  .photo-copy .hero-wordmark { margin-bottom: 18px; }
  .photo-copy .actions { margin-top: 20px; }
  .photo-call { margin-top: 4px; }
  .corridor-plane--case { top: 16%; height: 55%; }
  .corridor-plane--box { top: 31%; height: 42%; }
  .corridor-plane--storefront { bottom: 9%; height: 30%; }
  .corridor-arrival-mark { right: 16px; top: 27%; font-size: 25px; }
  .corridor-step { padding-block: var(--s5); }
  .corridor-step h3 { font-size: 30px; }
  .statement { max-width: none; }
  .menu-search { margin-left: 0; width: 100%; }
  .menu-search input { width: 100%; }
  .menu-row { gap: var(--s3); }
  .menu-row-name { flex: 1 1 auto; }
  .menu-row-price { flex: 0 0 76px; text-align: right; }
  .map-frame iframe { height: 300px; }
  .contact-map .map-frame iframe { height: 280px; }
  .home-map .map-frame iframe { height: 350px; }
  .photo-thumb { width: 64px; height: 48px; }
  .photo-pause { min-width: 0; margin-left: 0; }
  .photo-slide[data-slide="box"] .photo-backdrop { object-position: 66% 50%; }
  .photo-slide[data-slide="rings"] .photo-backdrop { object-position: 40% 50%; }
  .photo-slide[data-slide="case"] .photo-backdrop { object-position: 50% 58%; }
  /* The storefront is 4:3, so 350 wide is its approved 263 high; the mixed box
     keeps its own portrait ratio at the same 350 measure. */
  .photo-plate[data-hero-plate="storefront"],
  .photo-plate[data-hero-plate="variety"] { width: min(350px, 100%); }
  .review-card { padding: 22px; }
  .review-controls { flex-direction: column; align-items: flex-start; }
  .review-arrows { width: 100%; }
  .review-arrows .action { flex: 1 1 0; min-width: 0; }
  .review-foot { flex-direction: column; align-items: flex-start; }
  .visit-copy .visit-address { font-size: 30px; }
  .contact-phone { font-size: 27px; }
  .community-cols { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
  .community-foot { grid-column: auto; }
  .hours-table th, .hours-table td { padding-block: 11px; }
  .menu-intro-grid .crop { max-height: 160px; }
  .menu-intro-grid .crop img { object-position: 50% 50%; }
  /* Keep the viewer's own chrome small enough that the photograph still leads
     on a 320-wide phone, and give the two step controls full-width targets. */
  .lightbox-box { padding: var(--s3); gap: var(--s2); }
  .lightbox-label { font-size: 17px; line-height: 24px; }
  .lightbox-nav { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); }
  .lightbox-nav .action { width: 100%; }
  /* One ordered column: the five photographs keep the order they are read in,
     alternating 88% and 100% of the measure. The page gutter supplies the
     20px, and the gaps between figures are 24px. */
  .business-grid { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .business-cell,
  .business-cell--storefront,
  .business-cell--interior,
  .business-cell--plate,
  .business-cell--variety,
  .business-cell--case {
    grid-column: 1;
    padding-top: 0;
    width: 100%;
    justify-self: start;
  }
  .business-cell .business-figure { max-width: none; }
  .business-cell--storefront,
  .business-cell--case { width: 88%; }
  .business-cell--plate { width: 88%; justify-self: end; }
}

/* 17. Reduced motion, no-animation and no-JS ------------------------------- */

/* The hero's one timed focus is disabled in both forced-static states: no
   automatic advance (the script checks the same two classes) and no fade, so a
   manual selection lands instantly instead of dissolving. */
.reduced .photo-slide,
.noanim .photo-slide,
.reduced .photo-plate,
.noanim .photo-plate { transition: none; }

/* Both chapters keep full scale in ordinary static flow. The script writes no
   transform and no pin in these states, so these rules only have to cover the
   case where a transform was written and the preference changed mid-visit. */
.reduced .chapter-pin,
.noanim .chapter-pin { transform: none; }
.reduced .chapter-surface,
.noanim .chapter-surface { transform: none; }

/* The corridor remains a readable stack when motion is reduced or explicitly
   disabled. Its semantic step copy never waits on the enhancement, and these
   rules clear any scroll-linked plane state if the preference changes during a
   visit. */
.reduced .corridor-plane,
.noanim .corridor-plane {
  transform: none !important;
  opacity: 1 !important;
  transition: none;
}
.reduced .corridor-step.is-current,
.noanim .corridor-step.is-current { border-top-color: var(--ink); }

/* Static modes keep the documented plain stack at every width: the stage
   returns to normal flow with its planes at their authored positions, so the
   reduced/no-JS corridor is the readable stack, not a docked panel. */
.reduced .corridor-stage,
.noanim .corridor-stage { position: relative; top: auto; }

@media (prefers-reduced-motion: reduce) {
  .corridor-stage { position: relative; top: auto; }
}
