/* ============================================================================
   11TREE CAFE — "MELLO" REDESIGN
   ----------------------------------------------------------------------------
   Modelled on https://mello-coffee.webflow.io/ at the owner's request
   (2026-10-13), with ONE hard rule: the brand colour does not change.

   The reference is a sage-green cafe template. Everything structural, typo-
   graphic and spatial is ported; every colour is re-pointed at the 11Tree
   palette that already exists in css/style.css.

       reference                     here
       ---------------------------   --------------------------------------
       #284010  dark olive           --navy    #05144a   (the deep band)
       #E9EBDF  sage paper           --paper   #eef1f8   (the tinted paper)
       #78BF30  lime accent          --pop     #8fb4ff   on navy
                                     --blue    #0129a3   on paper
       Londrina Solid (display)      kept — self-hosted, OFL
       Gochi Hand (handwriting)      kept — self-hosted, OFL
       Inter 500 (body)              kept — already the body face here

   Six moves carry the reference. Do not "tidy" them into conventional
   components; they ARE the design:

     1. ROUNDED DISPLAY TYPE. Londrina Solid, weight 400, line-height exactly
        1.0, letter-spacing -0.01em. Headlines break onto two or three short
        lines and sit tight. This is the single most identifiable thing.
     2. HANDWRITING AS CONNECTIVE TISSUE. Gochi Hand carries every kicker,
        annotation and sticker — never body copy, never a price.
     3. SOFT GEOMETRY. 24px cards, 40px panels, 999px pills. Nothing on the
        page has a sharp corner except the page edge itself.
     4. BAND INVERSION. paper → navy → paper, with a curved seam between
        (.seam), not a straight rule.
     5. FLOATING ANNOTATIONS. Small cards and round stickers sit ON the
        photography rather than beside it, with hand-drawn arrows pointing.
     6. MARQUEE. A moving strip of short phrases, used as the join between
        two big sections.

   Accessibility notes are inline where a value was measured rather than
   chosen. Contrast pairs are recorded at the bottom of this file.
   ========================================================================= */


/* ───────────────────────── 1. FONTS ─────────────────────────
   Self-hosted, not linked: the owner deploys by drag-and-drop and the site
   has to survive with no network. Inter stays on the Google link in the
   document head because it is already cached from the live site.
   Both faces below are SIL Open Font Licence 1.1 — see fonts/OFL.txt. */

@font-face {
  font-family: 'Londrina Solid';
  src: url('../fonts/londrina-solid-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Londrina Solid';
  src: url('../fonts/londrina-solid-900.woff2') format('woff2');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Gochi Hand';
  src: url('../fonts/gochi-hand.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}


/* ───────────────────────── 2. TOKENS ───────────────────────── */

:root {
  /* brand — unchanged, straight out of css/style.css */
  --blue:      #0129a3;
  --blue-lite: #2f5bd4;
  --navy:      #05144a;
  --navy-2:    #071b5e;
  --pop:       #8fb4ff;   /* the accent on navy; AA at 8.41:1 */
  --paper:     #eef1f8;
  --paper-2:   #f7f8fc;
  --white:     #fff;

  --ink:   #05144a;
  --ink-2: #35406b;
  --ink-3: #5c6478;   /* micro-labels; 5.2:1 on --paper */

  /* band-local tokens. Every component reads THESE, never the raw colours,
     so a block can be moved from a light band to a dark one untouched. */
  --bg:    var(--paper);
  --fg:    var(--ink);
  --fg-2:  var(--ink-2);
  --fg-3:  var(--ink-3);
  --accent: var(--blue);
  --card:  var(--white);
  --rule:  rgba(5, 20, 74, .14);

  /* The reference's type ladder, measured off it at 1280 and at 549.
     Display is ALWAYS Londrina 400, line-height exactly 1.0, tracking
     -0.01em. Body is Inter 500/1.44/-0.01em. Anything that acts like a
     control — a nav item, a button, a chip, an inline link — is Inter 700
     at line-height 1.0 and -0.02em; that pairing is what makes the small
     text on this reference feel set rather than default. */
  --fs-d1: clamp(3.25rem, 8.4vw, 6.5rem);    /*  52 → 104  hero          */
  --fs-d2: clamp(3rem,    6.2vw, 5rem);      /*  48 →  80  section head  */
  --fs-d3: clamp(2rem,    2.6vw, 2.5rem);    /*  32 →  40  card title    */
  --fs-d4: clamp(1.5rem,  2.2vw, 2.25rem);   /*  24 →  36  sub           */
  --fs-d5: 1.3125rem;                        /*  21        small display */
  --fs-body:  1.125rem;                      /*  18        prose, ledes  */
  --fs-small: .875rem;                       /*  14        the workhorse */
  --fs-micro: .75rem;

  --font-display: 'Londrina Solid', 'Arial Black', sans-serif;
  --font-hand:    'Gochi Hand', 'Comic Sans MS', cursive;
  --font-body:    Inter, system-ui, -apple-system, 'Segoe UI', sans-serif;

  --r-sm:   12px;
  --r-card: 24px;
  --r-lg:   40px;
  --r-pill: 999px;

  --wrap:   1240px;
  --gutter: clamp(1.1rem, 4.5vw, 3rem);
  --pad-y:  clamp(3.5rem, 8vw, 7rem);

  --ease: cubic-bezier(.22, 1, .36, 1);
}

/* The deep band. Note --card goes to navy-2 rather than white: a white card
   on a navy band is a hole, and the reference puts its cards in a lighter
   shade of the band colour instead. */
.band--deep {
  --bg:     var(--navy);
  --fg:     var(--paper);
  --fg-2:   rgba(238, 241, 248, .82);
  --fg-3:   rgba(238, 241, 248, .62);
  --accent: var(--pop);
  --card:   var(--navy-2);
  --rule:   rgba(238, 241, 248, .18);
}
.band--white { --bg: var(--white); --card: var(--paper); }


/* ───────────────────────── 3. BASE ───────────────────────── */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  /* Flat 18px, not a clamp. The reference does not scale its body copy
     down on a phone — the 14px workhorse size carries the dense material
     instead — and shrinking it here made the ledes feel like captions. */
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: 1.44;
  letter-spacing: -.01em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;   /* the marquee and the tilted stickers overhang */
}

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

a { color: inherit; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1;          /* the reference sets line-height === font-size */
  letter-spacing: -.01em;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; }

/* The control voice: nav items, buttons, chips, inline links. Inter 700,
   line-height 1, -0.02em. */
.em, .btn, .nav a, .chip, .way .foot a, .mood-out .go, .foot ul a {
  font-weight: 700;
  letter-spacing: -.02em;
}

::selection { background: var(--blue); color: #fff; }

:where(a, button, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 6px;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.visually-hidden:focus {
  position: fixed; top: .6rem; left: .6rem; width: auto; height: auto;
  clip: auto; z-index: 999; padding: .7rem 1rem; border-radius: var(--r-pill);
  background: var(--blue); color: #fff;
}


/* ───────────────────────── 4. LAYOUT ───────────────────────── */

.band {
  position: relative;
  background: var(--bg);
  color: var(--fg);
}
.section { padding-block: var(--pad-y); }
.section--tight { padding-block: clamp(2.25rem, 5vw, 3.75rem); }
.section--flush-top { padding-top: 0; }

.wrap {
  width: min(100%, var(--wrap));
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--wide { --wrap: 1480px; }

/* THE SEAM — reference move 4. Where a navy band meets a paper one the join
   is a shallow curve, not a line. Drawn as an SVG-free pseudo-element so it
   costs nothing: a very wide ellipse, clipped by the band's own overflow.
   `border-radius: 50%` on a box 160% wide and 120px tall gives the gentle
   arc the reference uses; a border-radius in % on a narrow box would get
   steeper as the screen narrows, which is the wrong way round. */
.seam { position: relative; overflow: hidden; }
.seam::before,
.seam::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 130%;
  height: 180px;
  transform: translateX(-50%);
  border-radius: 50%;
  pointer-events: none;
}
.seam--top::before    { top: -130px; background: var(--seam-from, var(--paper)); }
.seam--bottom::after  { bottom: -130px; background: var(--seam-to, var(--paper)); }


/* ── the section heading pattern ──
   Kicker (handwriting, with a dot) above a two- or three-line display
   headline on the left; the lede sits on the right, bottom-aligned with the
   last line of the headline. Collapses to one column under 860px. */

.head {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(1rem, 3vw, 2.5rem);
  align-items: end;
  margin-bottom: clamp(1.75rem, 4.5vw, 3.25rem);
}
.head--center {
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
}
.head h2 {
  font-size: var(--fs-d2);
  margin-top: .45rem;
}
.head .lede {
  color: var(--fg-2);
  font-size: var(--fs-body);
  max-width: 34ch;
  padding-bottom: .4rem;
}
.head--center .lede { margin-inline: auto; }

@media (max-width: 860px) {
  .head { grid-template-columns: 1fr; align-items: start; }
  .head .lede { padding-bottom: 0; margin-top: .25rem; max-width: 46ch; }
}

.kicker {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-family: var(--font-hand);
  font-size: clamp(1rem, 2.2vw, 1.125rem);
  /* Gochi Hand sits on a 1.04 line in the reference, not on the body's
     1.44 — at 1.44 the kicker floated away from the headline under it. */
  line-height: 1.04;
  letter-spacing: 0;
  color: var(--accent);
}
.kicker::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.head--center .kicker { justify-content: center; }

/* A word or line of a headline lifted into the accent colour. The reference
   uses this once per section at most. */
.hl { color: var(--accent); }


/* ───────────────────────── 5. BUTTONS & PILLS ───────────────────────── */

/* THE BUTTON — three layers, exactly as the reference builds it:

     1. a 3px RING, drawn as ::before at radius 20px, always visible
     2. a PANEL, ::after at radius 18px (inset by the ring), which sits at
        scale(0) with its origin at the bottom centre and grows to fill on
        hover
     3. the LABEL, Inter 700 / 1.0 / -0.02em, painted above both

   The move is an inversion, not a tint: a solid button goes solid → paper
   as the panel wipes up, and the ring stays put so the shape never moves.

   ⚠️ These are NOT capsules. The reference runs 20px on a 66px box — a
   rounded rectangle. Setting border-radius to 999px here is the single
   fastest way to stop looking like the reference. Same ratio on the nav
   pills (12px on 36px).

   ⚠️ `isolation: isolate` is load-bearing. The panel is at z-index -1 so
   the button's own text (a bare text node, which cannot take a z-index)
   still paints above it. Without the isolate, -1 escapes the button and
   the panel disappears behind the band. */
.btn {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  min-height: clamp(53px, 5vw, 66px);
  padding: 1.1rem 1.75rem;
  border: 0;
  border-radius: 20px;
  background: var(--blue);
  color: #fff;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: color .4s var(--ease);
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 3px solid var(--blue);
  border-radius: 20px;
  z-index: 2;
  pointer-events: none;
}
.btn::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 18px;
  background: var(--paper);
  z-index: -1;
  transform: scale(0);
  transform-origin: 50% 100%;
  transition: transform .5s var(--ease);
}
.btn:hover::after,
.btn:focus-visible::after { transform: scale(1); }
.btn:hover, .btn:focus-visible { color: var(--ink); }

/* The outline variant: no fill, a dark ring, and the panel is a wash of
   the ink colour rather than paper — so the label never has to change. */
.btn--ghost {
  background: transparent;
  color: var(--fg);
}
.btn--ghost::before { border-color: var(--fg); }
.btn--ghost::after  { background: color-mix(in srgb, var(--fg) 12%, transparent); }
.btn--ghost:hover, .btn--ghost:focus-visible { color: var(--fg); }

/* On navy a solid brand-blue button disappears into the band, so the fill
   flips to the pale accent with dark text — the same rule the live
   stylesheet uses — and the panel goes to white. */
.band--deep .btn {
  background: var(--pop);
  color: var(--navy);
}
.band--deep .btn::before { border-color: var(--pop); }
.band--deep .btn::after  { background: #fff; }
.band--deep .btn:hover   { color: var(--navy); }
.band--deep .btn--ghost  { background: transparent; color: var(--fg); }
.band--deep .btn--ghost::before { border-color: var(--fg); }
.band--deep .btn--ghost::after  { background: rgba(238, 241, 248, .16); }

@media (prefers-reduced-motion: reduce) {
  .btn::after { transition: none; }
}

.btn .ico { width: 1.1em; height: 1.1em; flex: none; position: relative; z-index: 1; }

/* Chips — the small outlined tags above a dish name ("Cheese · Chicken"). */
.chips { display: flex; flex-wrap: wrap; gap: .4rem; }
.chip {
  display: inline-block;
  padding: .3rem .7rem;
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--fg-2);
  white-space: nowrap;
}

/* The price + size pair that closes every dish card. */
.price {
  display: flex;
  align-items: baseline;
  gap: .55rem;
}
.price b {
  font-size: 1.15rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.price span {
  font-size: .75rem;
  font-weight: 600;
  padding: .22rem .55rem;
  border-radius: var(--r-pill);
  background: var(--rule);
  color: var(--fg-2);
}


/* ───────────────────────── 6. TOP BAR + NAV ───────────────────────── */

.topbar {
  background: var(--navy);
  color: var(--paper);
  font-size: .8125rem;
  font-weight: 500;
}
.topbar .wrap {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: .4rem 1rem;
  padding-block: .1rem;
}
.topbar span { display: inline-flex; align-items: center; gap: .5rem; }
/* A tel: link in a 19px-tall strip is not a tap target. The link gets the
   44px, not the bar, so the bar only grows to ~46 — and on a phone the
   address drops out so the remaining two facts stay on one line instead of
   costing 80px of the first screen. */
.topbar a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: .2rem;
  color: inherit;
  text-decoration: none;
}
.topbar a:hover { text-decoration: underline; text-underline-offset: 3px; }
.topbar .leaf { width: 14px; height: 14px; color: var(--pop); flex: none; }
@media (max-width: 560px) {
  .topbar .addr, .topbar .addr + .leaf { display: none; }
}

/* The masthead: wordmark centred, pill nav beneath it. Sticky, and it keeps
   the paper ground so the hero reads as one block with it. */
/* Static, not sticky — the reference's header is position:absolute and
   scrolls away with the page. The phone number is reachable from the top
   strip, the clock panel, all three service cards and the footer, so
   nothing is lost by letting the bar go. */
.masthead {
  position: relative;
  z-index: 60;
  background: var(--paper);
  padding-block: clamp(.8rem, 2vw, 1.4rem);
}
.masthead .wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .7rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  gap: .55rem;
  text-decoration: none;
  color: var(--ink);
}
.brand img { width: 34px; height: 34px; }
.brand b {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.6rem, 4vw, 2.1rem);
  letter-spacing: -.01em;
  line-height: 1;
}

/* The nav, as the reference builds it: the link has no fill at rest, and
   a rounded rect grows behind the label from scale(0) on hover. 6px gap,
   36px tall, 12px radius, Inter 700. */
.nav { display: flex; align-items: center; gap: 6px; }
.nav a {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: .5rem .7rem;
  border: 0;
  border-radius: 12px;
  font-size: var(--fs-body);
  line-height: 1;
  text-decoration: none;
  color: var(--ink);
  transition: color .3s var(--ease);
}
.nav a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 12px;
  background: var(--pop);
  z-index: -1;
  transform: scale(0);
  transition: transform .4s var(--ease);
}
.nav a:hover::after,
.nav a:focus-visible::after,
.nav a[aria-current="page"]::after { transform: scale(1); }

/* The phone is this cafe's primary action and the reference has no
   equivalent, so it keeps a permanent fill. Its panel wipes to paper on
   hover, the same inversion the buttons use. */
.nav a.is-call {
  background: var(--blue);
  color: #fff;
}
.nav a.is-call::after { background: var(--paper); }
.nav a.is-call:hover { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .nav a::after { transition: none; }
}

.nav-toggle { display: none; }


/* ───────────────────────── 7. HERO ─────────────────────────
   Measured off the reference at an 1100px viewport, where its container is
   972px wide:

     .hero-content   flex column, gap 80px
     .hero-text      306 tall — headline, then buttons
     doodles         167px (left) and 195px (right), absolutely placed
     .hero-image     972 x 729  →  4:3
     .product        164 wide, flex COLUMN, gap 12, padding-left 16,
                     border-left 3px accent, NO background
     .divider        a 3px dot
     .volume         rgba(ink,.1), radius 6px, padding 1px 4px

   Those proportions are the section. Scaling the doodles down to
   "tasteful" flourishes, or putting the annotation in a white card, is
   what made the first attempt read as a different site.                 */

.hero { padding-top: clamp(1.25rem, 3.5vw, 2.5rem); }
.hero-content {
  display: flex;
  flex-direction: column;
  gap: clamp(2.5rem, 7vw, 5rem);
}

.hero-text { position: relative; text-align: center; }
.hero h1 {
  font-size: var(--fs-d1);
  margin-inline: auto;
  max-width: 14ch;
}
.hero .actions {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: .75rem;
  margin-top: clamp(1.75rem, 4vw, 2.5rem);
}

/* The two marks. Big — a sixth of the container each — and allowed to
   overhang the text block, which is why .hero-text is the positioning
   context and not .wrap. */
.hero-doodle {
  position: absolute;
  color: var(--blue);
  pointer-events: none;
}
.hero-doodle--l { left: 1%;  top: -14%; width: clamp(96px, 15.5vw, 170px); }
.hero-doodle--r { right: 0;  top:  -2%; width: clamp(96px, 18vw, 195px); }

/* Below 900 there is no room beside the headline. The reference keeps the
   left mark and drops the right one, moving the survivor above the type —
   so that is what happens here. */
@media (max-width: 900px) {
  .hero-doodle--r { display: none; }
  .hero-doodle--l {
    position: static;
    width: 86px;
    margin: 0 auto .5rem;
  }
}

/* THE STAGE. No frame, no card, no aspect-ratio box — the product is a
   cut-out standing on the paper, exactly as the reference does it, and it
   runs off the bottom edge behind the marquee.

   The bleed is produced by the MARQUEE pulling itself up with a negative
   margin, not by this clipping its own overflow. That way it works for a
   tall glass or a wide box without anyone having to retune a stage
   height when the owner's photo arrives. */
.hero-stage { position: relative; }

/* ⚠️ The cut-out ships as a JPEG plus a separate alpha MASK, not as an
   RGBA PNG — the same split the six menu tiles use, and for the same
   reason. Measured on this image: 1,277 KB as RGBA PNG against 254 KB of
   JPEG plus a 4 KB mask. PNG is the wrong codec for a photograph.

   Four things here are load-bearing; every one of them broke when the
   tiles were built (see CLAUDE.md):

   1. The mask carries its shape in ALPHA, not luminance — CSS masking
      defaults to alpha and `mask-mode: luminance` needs WebKit's
      barely-supported -webkit-mask-source-type. tools-mask.py writes PNG
      colour type 4 for exactly this.
   2. The URL is ROOT-relative. A relative url() resolves against the
      stylesheet, so images/... silently becomes /css/images/... .
   3. The element box must equal the rendered image box or
      `mask-size: 100% 100%` drifts off the picture. Here height is auto
      and there is no object-fit, so they are the same box.
   4. Without masking support the JPEG would show its flattened
      background as a rectangle, so @supports gives it a soft card and it
      reads as deliberate.

   The JPEG is flattened onto --paper rather than white, so even the
   anti-aliased rim of the mask blends into the band instead of showing a
   pale fringe. */
.hero-cutout {
  display: block;
  width: min(86%, 680px);
  height: auto;
  margin-inline: auto;
  -webkit-mask-image: url(/images/photos/hero-mask.png);
          mask-image: url(/images/photos/hero-mask.png);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  /* a cut-out has no edges of its own, so a little shadow keeps it from
     looking pasted on. drop-shadow runs AFTER the mask, so it follows the
     silhouette rather than boxing the image. */
  filter: drop-shadow(0 28px 34px rgba(5, 20, 74, .22));
}

@supports not ((-webkit-mask-image: url(a.png)) or (mask-image: url(a.png))) {
  .hero-cutout {
    border-radius: var(--r-lg);
    filter: none;
    box-shadow: 0 24px 50px -30px rgba(5, 20, 74, .55);
  }
}

/* The placeholder is an SVG with its own transparency — masking it with a
   silhouette of a different picture would shred it. */
.hero-cutout.is-fallback {
  -webkit-mask-image: none;
          mask-image: none;
  filter: none;
}

/* The annotation row sits across the top of the stage: product note at the
   left, arrow, quality note at the right, with the cut-out centred between
   them. Absolute on desktop so the product can rise behind it. */
.hero-notes {
  display: flex;
  align-items: flex-start;
  gap: clamp(.75rem, 3vw, 2rem);
  text-align: left;
}
.quality { margin-left: auto; }

@media (min-width: 861px) {
  .hero-notes {
    position: absolute;
    left: 0; right: 0; top: 3%;
    z-index: 2;
    pointer-events: none;      /* never sit in front of the product */
  }
  .hero-notes a { pointer-events: auto; }
}
@media (max-width: 860px) {
  /* stacked: the notes go above the cut-out and the arrow has nothing left
     to point at, so it goes */
  .hero-notes { margin-bottom: clamp(.75rem, 3vw, 1.25rem); }
  .hero-arrow { display: none; }
  .hero-cutout { width: min(100%, 420px); }
}

.product {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-left: 16px;
  border-left: 3px solid var(--accent);
}
.product .nm {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-d5);
  line-height: 1;
  margin-bottom: .3rem;
}
.product .details {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: var(--fs-small);
  color: var(--fg-2);
}
.product .dot {
  width: 3px; height: 3px;
  border-radius: 100px;
  background: currentColor;
  flex: none;
}
.product b {
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--fg);
}
.product .vol {
  font-size: .625rem;
  font-weight: 500;
  padding: 1px 4px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--fg) 10%, transparent);
  color: var(--fg-2);
}

.hero-arrow {
  width: clamp(64px, 8vw, 110px);
  flex: none;
  color: var(--accent);
  margin-top: .75rem;
}

/* The reference's "100% pure green energy": a 40px mark and two lines of
   handwriting, set at a slight angle. Ours says the thing no other place
   in Veliyancode can. */
.quality {
  display: flex;
  align-items: center;
  gap: .6rem;
  font-family: var(--font-hand);
  font-size: clamp(.95rem, 2vw, 1.125rem);
  line-height: 1.15;
  color: var(--fg-2);
  text-align: left;
  transform: rotate(-4deg);
  transform-origin: left center;
}
.quality svg { width: 40px; height: 40px; flex: none; color: var(--accent); }

@media (max-width: 720px) {
  .quality { font-size: .9rem; gap: .45rem; transform: none; }
  .quality svg { width: 28px; height: 28px; }
}
@media (max-width: 520px) {
  .hero-notes { flex-wrap: wrap; }
  .quality { margin-left: 0; }
}


/* ───────────────────────── 8. MARQUEE ───────────────────────── */

/* ⚠️ The negative margin is what makes the hero cut-out bleed. The band
   is opaque and later in the flow, so it paints over the last of the
   product — the same join the reference has between its matcha glass and
   its ticker. z-index keeps it above the drop-shadow. */
.marquee {
  position: relative;
  z-index: 3;
  margin-top: clamp(-5rem, -6vw, -2.5rem);
  background: var(--blue);
  color: #fff;
  padding-block: .85rem;
  overflow: hidden;
  white-space: nowrap;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.marquee-track {
  display: inline-flex;
  align-items: center;
  gap: 2.25rem;
  animation: slide 38s linear infinite;
  will-change: transform;
}
/* The track holds the phrase list TWICE (the second copy is cloned by
   mello.js) and travels exactly -50%, so the loop is seamless whatever the
   phrases are. Hard-coding a pixel distance breaks the moment copy changes. */
@keyframes slide { to { transform: translateX(-50%); } }
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee span {
  display: inline-flex;
  align-items: center;
  gap: 2.25rem;
  font-size: clamp(.9rem, 2vw, 1.0625rem);
  font-weight: 600;
  letter-spacing: -.005em;
}
.marquee .leaf { width: 15px; height: 15px; color: var(--pop); flex: none; }
@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; }
  .marquee { white-space: normal; }
}


/* ───────────────────────── 9. DISH CARDS ───────────────────────── */

/* A 12-column bed so the bento can be stated in spans rather than in a pile
   of grid-template-areas. First card is 7 wide and tall; the rest are 5. */
.dishes {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(.75rem, 1.8vw, 1.25rem);
}
.dish {
  grid-column: span 6;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: clamp(300px, 36vw, 440px);
  border-radius: var(--r-card);
  overflow: hidden;
  background: var(--white);
  text-decoration: none;
  color: inherit;
  isolation: isolate;
}
.dish:nth-child(1) { grid-column: span 7; min-height: clamp(340px, 44vw, 560px); }
.dish:nth-child(2) { grid-column: span 5; min-height: clamp(340px, 44vw, 560px); }
.dish:nth-child(3),
.dish:nth-child(4) { grid-column: span 6; }

.dish-img {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--ease);
}
.dish:hover .dish-img { transform: scale(1.045); }

/* The info panel. Navy, inset from the card edge, with its own radius — the
   reference floats it rather than running it to the card's edges. */
.dish-info {
  margin: clamp(.6rem, 1.4vw, .9rem);
  padding: clamp(.9rem, 2vw, 1.15rem);
  border-radius: var(--r-sm);
  background: var(--navy);
  color: var(--paper);
  --fg-2: rgba(238, 241, 248, .82);
  --fg-3: rgba(238, 241, 248, .62);
  --rule: rgba(238, 241, 248, .2);
}
.dish-info h3 {
  font-size: var(--fs-d3);
  margin: .5rem 0 .3rem;
}
.dish-info p {
  font-size: .875rem;
  color: var(--fg-2);
  margin-bottom: .75rem;
}
.dish-info .price b { color: #fff; }
.dish-info .price span { background: rgba(238,241,248,.16); color: rgba(238,241,248,.85); }

/* A "Favourite" flag in the top corner of one card. */
.flag {
  position: absolute;
  top: clamp(.6rem, 1.4vw, .9rem);
  left: clamp(.6rem, 1.4vw, .9rem);
  z-index: 2;
  padding: .35rem .8rem;
  border-radius: var(--r-pill);
  background: var(--pop);
  color: var(--navy);
  font-size: .75rem;
  font-weight: 700;
}

/* The handwritten aside that sits above two of the cards in the reference. */
.aside-hand {
  grid-column: span 12;
  font-family: var(--font-hand);
  font-size: clamp(1.1rem, 2.6vw, 1.5rem);
  color: var(--accent);
  text-align: right;
  line-height: 1.15;
}

@media (max-width: 860px) {
  .dish,
  .dish:nth-child(1),
  .dish:nth-child(2),
  .dish:nth-child(3),
  .dish:nth-child(4) { grid-column: span 12; min-height: clamp(280px, 70vw, 420px); }
  .aside-hand { text-align: left; }
}


/* ───────────────────── 10. CATEGORY STRIP (menu teaser) ───────────────── */

.cats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 165px), 1fr));
  gap: clamp(.6rem, 1.6vw, 1rem);
}
.cat {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: 1rem;
  flex-wrap: wrap;
  border: 1.5px solid var(--rule);
  border-radius: var(--r-card);
  background: var(--card);
  text-decoration: none;
  color: inherit;
  min-height: 72px;
  transition: border-color .25s var(--ease), transform .25s var(--ease);
}
.cat:hover { border-color: var(--accent); transform: translateY(-3px); }
.cat .n {
  font-family: var(--font-hand);
  font-size: 1.1rem;
  color: var(--accent);
  flex: none;
}
.cat .nm {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 1.6vw, 1.3rem);
  line-height: 1;
  flex: 1;
}
.cat .from {
  font-size: .75rem;
  font-weight: 600;
  color: var(--fg-3);
  white-space: nowrap;
}

.center-cta {
  display: flex;
  justify-content: center;
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
}


/* ───────────────────────── 11. MOOD MATCHER ───────────────────────── */

.mood {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, .8fr);
  gap: clamp(1.5rem, 5vw, 4rem);
  align-items: center;
}

/* The wheel: four quadrants of one circle. Each quadrant is a square with
   three sharp corners and one 100% corner, so together they close a disc
   with no SVG and no clip-path. */
.wheel {
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: min(100%, 420px);
  aspect-ratio: 1;
  margin-inline: auto;
  position: relative;
}
.wheel button {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .2rem;
  padding: 18% 12% 12%;
  border: 1.5px solid var(--rule);
  background: var(--card);
  color: var(--fg);
  font: inherit;
  cursor: pointer;
  text-align: center;
  transition: background .3s var(--ease), color .3s var(--ease);
}
.wheel button:nth-child(1) { border-radius: 100% 0 0 0; }
.wheel button:nth-child(2) { border-radius: 0 100% 0 0; }
.wheel button:nth-child(3) { border-radius: 0 0 0 100%; }
.wheel button:nth-child(4) { border-radius: 0 0 100% 0; }
.wheel button em {
  font-family: var(--font-hand);
  font-style: normal;
  font-size: .9rem;
  color: var(--fg-3);
}
.wheel button b {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.05rem, 2.6vw, 1.5rem);
  line-height: 1.05;
}
.wheel button[aria-pressed="true"] {
  background: var(--pop);
  color: var(--navy);
  border-color: var(--pop);
}
.wheel button[aria-pressed="true"] em { color: rgba(5, 20, 74, .7); }

/* The leaf pinned at the hub, covering the four corners where the quadrants
   meet. Pointer-events off so it never eats a click meant for a quadrant. */
.wheel .hub {
  position: absolute;
  inset: 50% auto auto 50%;
  transform: translate(-50%, -50%);
  width: 15%;
  color: var(--accent);
  pointer-events: none;
}

.mood-out {
  border-radius: var(--r-card);
  background: var(--card);
  padding: clamp(.65rem, 1.6vw, .9rem);
  max-width: 360px;
  margin-inline: auto;
}
.mood-out .shot {
  /* positioned, because the empty-slot pseudo-element is `inset: 0` and
     without this it anchors to whatever ancestor happens to be positioned
     — which put the drop-zone label over the mood wheel. */
  position: relative;
  border-radius: var(--r-sm);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--navy);
}
.mood-out .shot img { width: 100%; height: 100%; object-fit: cover; }
.mood-out .body { padding: .9rem .4rem .35rem; }
.mood-out h3 { font-size: var(--fs-d4); margin: .45rem 0 .3rem; }
.mood-out p { font-size: .875rem; color: var(--fg-2); margin-bottom: .75rem; }
.mood-out .go {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  min-height: 44px;
  font-size: .875rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
}
.mood-out .go:hover { text-decoration: underline; text-underline-offset: 4px; }

@media (max-width: 860px) {
  .mood { grid-template-columns: 1fr; }
}


/* ───────────────────────── 12. THE LATE CLOCK ───────────────────────── */

.clockbox {
  border-radius: var(--r-lg);
  background: var(--navy-2);
  padding: clamp(1.25rem, 3.5vw, 2.5rem);
}
.clockbox .tag {
  font-family: var(--font-hand);
  font-size: 1.05rem;
  color: var(--pop);
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-bottom: clamp(.75rem, 2vw, 1.25rem);
}
.clockbox .tag i { font-style: normal; opacity: .6; }

.clock-row {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: clamp(1rem, 4vw, 3rem);
  align-items: center;
}
/* The number. Londrina's digits are tabular enough to not jitter on the
   minute, but font-variant-numeric is set anyway — the fallback face
   (Arial Black) is not. */
.clock-big {
  font-family: var(--font-display);
  font-size: clamp(3.6rem, 15vw, 11rem);
  line-height: .86;
  color: var(--pop);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}
.clock-big small {
  display: block;
  margin-top: .3em;
  font-family: var(--font-body);
  font-size: .105em;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: rgba(238, 241, 248, .7);
  white-space: nowrap;
}
.clock-note h3 { font-size: var(--fs-d4); color: var(--paper); }
.clock-note p  { color: rgba(238,241,248,.75); font-size: .9375rem; margin-top: .5rem; max-width: 40ch; }

/* Progress through the night. */
.nightbar {
  position: relative;
  height: 10px;
  border-radius: var(--r-pill);
  background: rgba(238, 241, 248, .16);
  margin-top: clamp(1.25rem, 3vw, 2rem);
  overflow: hidden;
}
.nightbar i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  border-radius: inherit;
  background: var(--pop);
  transition: width .6s var(--ease);
}
.nightscale {
  display: flex;
  justify-content: space-between;
  margin-top: .5rem;
  font-size: .75rem;
  font-weight: 600;
  color: rgba(238, 241, 248, .6);
}

.clock-chips {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
  gap: .6rem;
  margin-top: clamp(1.25rem, 3vw, 1.75rem);
}
.clock-chips div {
  border-radius: var(--r-sm);
  background: rgba(238, 241, 248, .08);
  padding: .8rem .9rem;
}
.clock-chips div:has(a) { padding-block: .55rem; }
.clock-chips dt { font-size: .75rem; font-weight: 600; color: rgba(238,241,248,.6); }
.clock-chips dd {
  margin: .2rem 0 0;
  font-family: var(--font-display);
  font-size: 1.25rem;
  color: var(--paper);
}
.clock-chips a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--pop);
  text-decoration: none;
}
.clock-chips a:hover { text-decoration: underline; text-underline-offset: 3px; }

.live {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin-top: clamp(1rem, 2.5vw, 1.5rem);
  font-size: .9375rem;
  font-weight: 600;
  color: var(--paper);
}
.live .dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: rgba(238,241,248,.4);
  flex: none;
}
.live[data-open="1"] .dot {
  background: var(--pop);
  box-shadow: 0 0 0 0 rgba(143, 180, 255, .55);
  animation: pulse 2.4s ease-out infinite;
}
@keyframes pulse {
  70%  { box-shadow: 0 0 0 10px rgba(143, 180, 255, 0); }
  100% { box-shadow: 0 0 0 0 rgba(143, 180, 255, 0); }
}
@media (prefers-reduced-motion: reduce) { .live .dot { animation: none !important; } }
.live .sub { color: rgba(238,241,248,.7); font-weight: 500; }

@media (max-width: 760px) {
  .clock-row { grid-template-columns: 1fr; }
}


/* ───────────────────────── 13. WAYS (three services) ───────────────────── */

.ways {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(.75rem, 2vw, 1.25rem);
}
.way {
  display: flex;
  flex-direction: column;
  border-radius: var(--r-card);
  background: var(--card);
  padding: clamp(1.1rem, 2.6vw, 1.6rem);
  border: 1.5px solid var(--rule);
}
.way .num {
  font-family: var(--font-hand);
  font-size: 1.1rem;
  color: var(--accent);
}
.way h3 { font-size: var(--fs-d4); margin: .4rem 0 .5rem; }
.way p { color: var(--fg-2); font-size: .9375rem; }
/* margin-top:auto keeps the three footers on one line whatever the copy
   length — the same trick the live .svc-meta uses. */
.way .foot {
  margin-top: auto;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
}
.way .foot a {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  min-height: 44px;            /* measured: .7rem padding gives 43px */
  padding-block: .75rem;
  font-size: .875rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
}
.way .foot a:hover { text-decoration: underline; text-underline-offset: 4px; }
.way .status { font-size: .8125rem; font-weight: 600; color: var(--fg-3); display: inline-flex; align-items: center; gap: .45rem; }
.way .status .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }


/* ───────────────────────── 14. WHAT MATTERS + RECEIPT ───────────────────── */

.matters {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: clamp(1.75rem, 6vw, 5rem);
  align-items: center;
}
.matters h2 { font-size: var(--fs-d2); }
.matters p { color: var(--fg-2); margin-top: 1rem; max-width: 42ch; }
.matters .actions { display: flex; gap: .65rem; flex-wrap: wrap; margin-top: clamp(1.25rem, 3vw, 1.75rem); }

/* The receipt. Two things make it read as paper rather than as a card: the
   torn edges (a repeating conic gradient masked at top and bottom) and the
   dotted leaders between label and value. */
.receipt {
  position: relative;
  background: var(--paper-2);
  color: var(--ink);
  padding: clamp(1.4rem, 3vw, 2rem) clamp(1.2rem, 3vw, 1.9rem);
  max-width: 380px;
  margin-inline: auto;
  width: 100%;
  transform: rotate(1.2deg);
}
.receipt::before,
.receipt::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 10px;
  background: var(--paper-2);
  -webkit-mask-image: repeating-conic-gradient(from -45deg at 50% 0,
            #000 0 25%, transparent 0 50%);
          mask-image: repeating-conic-gradient(from -45deg at 50% 0,
            #000 0 25%, transparent 0 50%);
  -webkit-mask-size: 18px 20px;
          mask-size: 18px 20px;
}
.receipt::before { top: -10px; transform: scaleY(-1); }
.receipt::after  { bottom: -10px; }

.receipt .top { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.receipt .top b {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.9rem;
  line-height: 1;
}
.receipt .top em {
  display: block;
  font-family: var(--font-hand);
  font-style: normal;
  font-size: .9rem;
  color: var(--ink-3);
  margin-top: .15rem;
}
.receipt .top .leaf { width: 26px; height: 26px; color: var(--blue); flex: none; }

.receipt dl { margin: 1.4rem 0 0; }
.receipt dl div {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  padding: .42rem 0;
  font-size: .9375rem;
}
.receipt dt { color: var(--ink-2); }
.receipt dd { margin: 0; font-weight: 600; white-space: nowrap; }
/* the dotted leader */
.receipt dl div::before {
  content: "";
  order: 1;
  flex: 1;
  height: 0;
  border-bottom: 1px dotted rgba(5, 20, 74, .3);
  transform: translateY(-.25em);
}
.receipt dd { order: 2; }

.receipt .total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1rem;
  padding-top: .9rem;
  border-top: 1.5px dashed rgba(5, 20, 74, .3);
}
.receipt .total span { font-size: .8125rem; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: .08em; }
.receipt .total b { font-family: var(--font-display); font-weight: 400; font-size: 1.5rem; line-height: 1; }

.receipt .barcode {
  display: flex;
  gap: 2px;
  height: 42px;
  margin-top: 1.25rem;
  align-items: stretch;
}
.receipt .barcode i { flex: 1; background: var(--ink); border-radius: 1px; }
.receipt .barcode i:nth-child(3n)   { flex: 2.2; }
.receipt .barcode i:nth-child(4n)   { opacity: .25; }
.receipt .barcode i:nth-child(5n)   { flex: .6; }
.receipt .thanks {
  text-align: center;
  font-family: var(--font-hand);
  font-size: 1rem;
  color: var(--ink-3);
  margin-top: .6rem;
}

@media (max-width: 860px) {
  .matters { grid-template-columns: 1fr; }
  .receipt { transform: none; }
}


/* ───────────────────────── 15. THE SPACE ───────────────────────── */

.space {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: clamp(.75rem, 2vw, 1.25rem);
  align-items: stretch;
}
.space-shot {
  border-radius: var(--r-lg);
  overflow: hidden;
  min-height: clamp(280px, 42vw, 520px);
  background: var(--navy);
}
.space-shot img { width: 100%; height: 100%; object-fit: cover; }
.space-panel {
  border-radius: var(--r-lg);
  background: var(--blue);
  color: #fff;
  padding: clamp(1.25rem, 3vw, 2rem);
  display: flex;
  flex-direction: column;
}
.space-panel .n { font-family: var(--font-hand); font-size: 1rem; opacity: .75; }
.space-panel h3 { font-size: var(--fs-d3); margin: auto 0 .6rem; }
.space-panel p { color: rgba(255,255,255,.85); font-size: .9375rem; }
.space-tags { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: 1rem; }
.space-tags span {
  font-family: var(--font-hand);
  font-size: .95rem;
  color: rgba(255,255,255,.8);
}
.space-panel .sun { width: 44px; height: 44px; color: var(--pop); margin-bottom: 1rem; }

@media (max-width: 860px) { .space { grid-template-columns: 1fr; } }


/* ───────────────────────── 16. BENTO (gallery + visit) ───────────────── */

.bento {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: clamp(120px, 15vw, 190px);
  gap: clamp(.6rem, 1.6vw, 1rem);
}
.bento > * {
  border-radius: var(--r-card);
  overflow: hidden;
  position: relative;
}
.bento img { width: 100%; height: 100%; object-fit: cover; }

/* Eight tiles on a 12-column bed, two rows deep each time a photograph is
   involved, so nothing is left as a one-row letterbox.

     row 1-2   front-night 3 │ yard 5 │ hours 4
                             │        │ front-day 4   (row 2)
     row 3-4   yard-table 5 │ address 6 │ say 1

   Both rows sum to exactly 12. The DOM order below is also the phone
   order, which is why the address and the "Say hello" strip are last and
   adjacent — they are the only pair that has to share a row at every
   width. */
.b-a { grid-column: span 3; grid-row: span 2; }   /* front, after dark */
.b-b { grid-column: span 5; grid-row: span 2; }   /* the yard */
.b-c { grid-column: span 4; grid-row: span 1; }   /* hours card */
.b-d { grid-column: span 4; grid-row: span 1; }   /* front, daytime */
.b-e { grid-column: span 5; grid-row: span 2; }   /* under the roof */
.b-addr { grid-column: span 6; grid-row: span 2; }
.b-say  { grid-column: span 1; grid-row: span 2; }

/* the caption that sits in the bottom-left of a photo tile */
.b-cap {
  position: absolute;
  left: .75rem; bottom: .75rem;
  padding: .35rem .75rem;
  border-radius: var(--r-pill);
  background: rgba(5, 20, 74, .72);
  color: var(--paper);
  font-size: .8125rem;
  font-weight: 600;
}
@supports (backdrop-filter: blur(6px)) {
  .b-cap { background: rgba(5, 20, 74, .45); backdrop-filter: blur(8px); }
}

.b-hours {
  background: var(--paper-2);
  color: var(--ink);
  padding: clamp(.9rem, 2vw, 1.25rem);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.b-hours .k { font-family: var(--font-hand); font-size: .95rem; color: var(--ink-3); }
.b-hours b { font-family: var(--font-display); font-weight: 400; font-size: clamp(1.3rem, 2.6vw, 1.8rem); line-height: 1.05; }

.b-addr {
  background: var(--blue);
  color: #fff;
  padding: clamp(.9rem, 2vw, 1.25rem);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  text-decoration: none;
}
.b-addr b { font-family: var(--font-display); font-weight: 400; font-size: clamp(1.2rem, 2.4vw, 1.6rem); line-height: 1.1; }
.b-addr .pin { width: 34px; height: 34px; color: var(--pop); flex: none; }

/* the vertical "Say hello" strip */
.b-say {
  background: var(--navy-2);
  color: var(--paper);
  display: grid;
  place-items: center;
  text-decoration: none;
}
.b-say span {
  writing-mode: vertical-rl;
  font-family: var(--font-display);
  font-size: clamp(.95rem, 2.2vw, 1.5rem);
  letter-spacing: .02em;
  max-block-size: 100%;
  overflow: hidden;
}

@media (max-width: 960px) {
  .bento { grid-auto-rows: clamp(110px, 24vw, 170px); }
  /* Two up, and every tile the same two rows deep — a one-row tile beside
     a two-row photograph leaves a hole that auto-placement will not fill. */
  .b-a, .b-b, .b-c, .b-d, .b-e { grid-column: span 6; grid-row: span 2; }
  .b-addr { grid-column: span 9; grid-row: span 2; }
  .b-say  { grid-column: span 3; grid-row: span 2; }
}
@media (max-width: 560px) {
  .b-a, .b-b, .b-c, .b-d, .b-e { grid-column: span 12; }
  /* One per row, so the hours card no longer has a photograph beside it to
     match heights with — two rows of it is a card of empty paper. */
  .b-c { grid-row: span 1; }
  .b-addr { grid-column: span 9; }
  .b-say  { grid-column: span 3; }
  .b-say span { font-size: .9rem; }
}

/* the ⚠ line that still has to be shown until the street address lands */
.todo {
  margin-top: 1rem;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--fg-3);
}


/* ───────────────────────── 17. FOOTER ───────────────────────── */

.foot { background: var(--paper); color: var(--ink); padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(1.5rem, 3vw, 2.5rem); }
.foot-top {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
}
.foot-mark {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  gap: .6rem;
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 6vw, 3.4rem);
  line-height: 1;
  text-decoration: none;
  color: var(--ink);
}
.foot-mark .leaf { width: 30px; height: 30px; color: var(--blue); }
.foot-hours { font-family: var(--font-hand); font-size: 1.05rem; color: var(--ink-2); margin-top: .5rem; }
.foot h4 {
  font-family: var(--font-hand);
  font-weight: 400;
  font-size: 1rem;
  color: var(--ink-3);
  margin: 0 0 .75rem;
}
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .1rem; }
.foot ul a {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  min-height: 44px;
  padding-block: .6rem;
  font-size: .9375rem;
  font-weight: 600;
  text-decoration: none;
}
.foot ul a:hover { color: var(--blue); text-decoration: underline; text-underline-offset: 4px; }
.foot ul .ico { width: 15px; height: 15px; color: var(--blue); flex: none; }
.foot-base {
  margin-top: clamp(2rem, 5vw, 3.5rem);
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 1.25rem;
  justify-content: space-between;
  font-size: .8125rem;
  color: var(--ink-3);
}
@media (max-width: 760px) {
  .foot-top { grid-template-columns: 1fr 1fr; }
  .foot-mark { font-size: 2.4rem; }
  .foot-top > :first-child { grid-column: span 2; }
}


/* ───────────────────────── 18. MOBILE NAV ───────────────────────── */

@media (max-width: 760px) {
  .masthead .wrap { flex-direction: row; justify-content: space-between; }
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 46px; height: 46px;
    border: 1.5px solid var(--ink);
    border-radius: var(--r-pill);
    background: transparent;
    cursor: pointer;
    color: var(--ink);
  }
  .nav-toggle span, .nav-toggle span::before, .nav-toggle span::after {
    content: "";
    display: block;
    width: 18px; height: 2px;
    background: currentColor;
    border-radius: 2px;
    transition: transform .3s var(--ease), opacity .2s linear;
  }
  .nav-toggle span { position: relative; }
  .nav-toggle span::before { position: absolute; top: -6px; }
  .nav-toggle span::after  { position: absolute; top: 6px; }
  .nav-toggle[aria-expanded="true"] span { background: transparent; }
  .nav-toggle[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] span::after  { transform: translateY(-6px) rotate(-45deg); }

  .nav {
    position: absolute;
    top: 100%; left: var(--gutter); right: var(--gutter);
    flex-direction: column;
    align-items: stretch;
    gap: .25rem;
    padding: .6rem;
    border-radius: var(--r-card);
    background: var(--white);
    box-shadow: 0 24px 50px -30px rgba(5, 20, 74, .8);
    /* visibility, not display:none — a display toggle cannot be transitioned
       and the menu snapped open hard enough to read as a bug */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity .22s var(--ease), transform .22s var(--ease), visibility .22s;
  }
  .nav.is-open { opacity: 1; visibility: visible; transform: none; }
  .nav a { justify-content: center; min-height: 48px; }
}


/* ───────────────────── 18b. EMPTY PHOTO SLOTS ─────────────────────
   Every food photograph on this page is a slot waiting for the owner's
   own picture. Until the file exists the <img> 404s, its onerror puts
   .is-empty on the container, and this draws the drop-zone instead.

   Done in CSS rather than as N placeholder SVGs because each slot has to
   name its OWN file — `content: attr(data-slot)` does that with one rule
   and no extra assets. Drop the file in and the slot disappears; there is
   nothing to edit.

   ⚠️ The container needs `position: relative` (or better) and the slot
   name on data-slot. `.dish` is already `isolation: isolate` with its
   image at z-index -1, so the pseudo-element matches that depth and stays
   behind the navy info panel — the dish name and price keep showing over
   an empty slot, which is the point. */
[data-slot].is-empty > img { display: none; }

[data-slot].is-empty::after {
  content: "Add a photo\A" attr(data-slot);
  white-space: pre-line;
  text-align: center;
  position: absolute;
  inset: 0;
  z-index: -1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  padding: 1rem;
  border: 2px dashed color-mix(in srgb, var(--fg) 28%, transparent);
  border-radius: inherit;
  background: color-mix(in srgb, var(--fg) 5%, transparent);
  color: color-mix(in srgb, var(--fg) 62%, transparent);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .75rem;
  font-weight: 600;
  line-height: 1.7;
  letter-spacing: 0;
}

/* On a dish card the slot sits under the info panel, so its text has to
   clear the panel rather than sit behind it. */
.dish[data-slot].is-empty::after { padding-bottom: 42%; }

/* The mood card's slot is a plain box, not an isolated stack. */
.mood-out .shot[data-slot].is-empty::after { z-index: 0; }


/* ───────────────────────── 19. REVEAL ───────────────────────── */

/* Deliberately NOT GSAP. This page is a standalone preview and the whole
   point of the reference is calm, so one short fade-and-rise is the entire
   motion vocabulary. js/mello.js adds .in with an IntersectionObserver and
   falls back to showing everything if the API is missing. */
[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .7s var(--ease), transform .7s var(--ease);
  transition-delay: var(--d, 0ms);
}
[data-reveal].in { opacity: 1; transform: none; }
.no-js [data-reveal] { opacity: 1; transform: none; }

/* WORD-BY-WORD HEADINGS — the reference's one piece of real choreography.
   Every heading there is split into inline-block words (its markup is
   littered with `gsap_split_word` spans) which rise and fade in sequence
   rather than the block moving as one.

   Split here by mello.js §5a, with no GSAP: each word carries its index
   as --i and the delay is arithmetic. A heading that has been split stops
   animating as a block — .is-split cancels the container's own transform
   so the two do not compound into a double move. */
.is-split { opacity: 1 !important; transform: none !important; }
.is-split .w {
  display: inline-block;
  opacity: 0;
  transform: translateY(.5em);
  transition: opacity .7s var(--ease), transform .7s var(--ease);
  transition-delay: calc(var(--d, 0ms) + var(--i) * 45ms);
  /* the descenders of a Londrina 104px line get clipped by the inline box
     without this, because inline-block shrink-wraps to the content box */
  padding-bottom: .04em;
}
.is-split.in .w { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .is-split .w { opacity: 1 !important; transform: none !important; transition: none; }
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1 !important; transform: none !important; transition: none; }
  .dish-img, .btn, .cat { transition: none !important; }
}


/* ───────────────────────── 20. PRINT ───────────────────────── */

@media print {
  .topbar, .masthead, .marquee, .plate, .bento, .wheel, .sticker, .arrow { display: none !important; }
  body { background: #fff; color: #000; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}


/* ============================================================================
   CONTRAST — measured, not estimated (WCAG 2.1 ratios, alpha composited)

   on --paper #eef1f8
     --ink      #05144a   15.90:1   body, headlines
     --ink-2    #35406b    8.27:1   lede
     --ink-3    #5c6478    5.20:1   micro-labels            AA
     --blue     #0129a3   10.71:1   kickers, links, accents

   on --navy #05144a
     --paper    #eef1f8   15.90:1   headlines, body
     82% paper            12.1 :1   lede
     62% paper             7.1 :1   micro-labels            AA
     --pop      #8fb4ff    8.41:1   accents, clock, chips

   on --blue #0129a3 (the space panel, the address tile)
     #ffffff              10.71:1
     85% white             8.0 :1
     --pop      #8fb4ff    3.4 :1   decorative only — never text

   Tap targets: nav 40px in the bar / 48px in the drawer, .btn 48px,
   .way .foot a 44px (at .75rem padding-block; .7rem measures 43 and misses).
   ========================================================================= */


/* ───────────────── 21. ADDENDA ─────────────────
   A studio shot on a white ground is not a photograph of a table, and
   `cover` crops it into its own background. `contain` on paper turns it
   into a deliberate product card instead. */
.dish--prod { background: var(--paper-2); }
.dish--prod .dish-img {
  object-fit: contain;
  padding: clamp(1rem, 4vw, 2.5rem) clamp(1rem, 4vw, 2.5rem) 42%;
}

/* The receipt's leaf sits in a flex row with the wordmark; without an
   explicit size it inherits the 100% width of a bare <svg>. */
.receipt .top .leaf { width: 26px; height: 26px; }

/* The mood card's image carries its own object-fit, set per dish in
   mello.js §4, so nothing here may override it. */
.mood-out .shot img { background: var(--navy); }
