/* ============================================================
   The Bagel Lady - Design System
   Phase 1 foundation: tokens, @font-face, base, buttons.
   Later phases append sections below the Phase 2 marker.
   ============================================================ */
:root{
  /* palette: sampled from logo.png + food photography, 2026-08-04 */
  --cream:#F9F1E2;        /* dominant page background */
  --paper:#FFFCF5;        /* cards, raised surfaces */
  /* gold family: decorative or on-dark only, fails AA on cream (1.74:1) */
  --gold:#E9AF60;         /* bagel crust; badges, bands, curves */
  --gold-tint:#F0CE94;    /* soft fills, chip backgrounds */
  --gold-deep:#C77E2E;    /* toasted crust; borders, hover shifts */
  --brown-ink:#33241A;    /* primary text, footer background */
  --brown-soft:#6B543C;   /* secondary text */
  /* red family: reserved for order actions only; derived from the logo
     lettering red (--red-bright) deepened for AA contrast with white text */
  --red:#C9182B;          /* ORDER ACTIONS ONLY (AA with white text) */
  --red-bright:#ED2F45;   /* logo lettering red; decorative, non-interactive only */
  --red-deep:#B5121F;     /* accent text on cream, form errors */
  --line:rgba(51,36,26,.14);
  --line-strong:rgba(51,36,26,.26);
  --shadow-sm:0 2px 10px rgba(51,36,26,.08);
  --shadow-md:0 12px 32px rgba(51,36,26,.14);
  --shadow-lg:0 30px 70px rgba(51,36,26,.24);

  /* radii */
  --radius-sm:10px;
  --radius-md:18px;
  --radius-lg:28px;
  --radius-pill:999px;    /* all CTAs; locked hero direction */
  --radius-blob:42% 58% 56% 44% / 48% 42% 58% 52%; /* organic image masks */

  /* motion (mirrors Mahalic convention) */
  --ease-out:cubic-bezier(.16,1,.3,1);
  --dur-fast:.28s;
  --dur-med:.62s;

  /* type; the -fallback families are a CLS guard, metric-matched local
     fallbacks per 01-RESEARCH.md Pattern 2 (the only amendment to the
     approved UI-SPEC stacks) */
  --font-display:'Vollkorn','Vollkorn-fallback',Georgia,'Times New Roman',serif;
  --font-script:'Vollkorn','Vollkorn-fallback',Georgia,serif;
  /* the cursive is a true script face, used ONLY for single accent words */
  --font-cursive:'Parisienne','Snell Roundhand','Apple Chancery',cursive;
  --font-body:'Karla','Karla-fallback','Segoe UI',Arial,sans-serif;
  --fs-label:.875rem;
  --fs-body:1rem;
  --fs-heading:clamp(1.75rem, 1.4rem + 1.8vw, 2.5rem);
  --fs-display:clamp(2.75rem, 1.9rem + 4.2vw, 4.5rem);

  /* spacing */
  --space-xs:4px; --space-sm:8px; --space-md:16px; --space-lg:24px;
  --space-xl:32px; --space-2xl:48px; --space-3xl:64px; --space-4xl:96px;

  /* layout */
  --container:1240px;
  --gutter:clamp(20px, 5vw, 64px);
  --header-h:80px;
}

/* ============================================================
   Fonts: self-hosted variable woff2, zero external requests.
   Preload pattern for later page heads (research Pitfall 8):
   rel preload, as font, type font/woff2, on ../fonts/ Vollkorn
   and Karla (upright only), with the crossorigin attribute
   (required even same-origin or the font downloads twice). The
   Vollkorn italic face carries only the script flourish and is
   below the fold, so it is never preloaded.

   Vollkorn is a sturdy, warm, moderate-contrast serif with a
   genuine italic. It was picked over Fraunces deliberately:
   Fraunces is technically lovely but it has become one of the
   handful of faces the current wave of generated sites converges
   on, and this client's whole objection to the previous stack was
   that it looked machine-made. Vollkorn is far less worn, reads
   hearty rather than startup, and its name is German for whole
   grain, which is not nothing on a bakery.
   ============================================================ */
@font-face {
  font-family: "Vollkorn";
  src: url("../fonts/Vollkorn-Variable.woff2") format("woff2-variations"),
       url("../fonts/Vollkorn-Variable.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Vollkorn";
  src: url("../fonts/Vollkorn-Italic-Variable.woff2") format("woff2-variations"),
       url("../fonts/Vollkorn-Italic-Variable.woff2") format("woff2");
  font-weight: 400 900;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Parisienne";
  src: url("../fonts/Parisienne-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Karla";
  src: url("../fonts/Karla-Variable.woff2") format("woff2-variations"),
       url("../fonts/Karla-Variable.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

/* CLS guards. size-adjust only: these are eyeball-tuned against the real
   faces, not derived from the font tables, so no ascent/descent overrides
   are asserted. Georgia is already close to Vollkorn in x-height and Arial
   runs slightly wide against Karla, which is what the 96% corrects. */
@font-face {
  font-family: "Vollkorn-fallback";
  src: local("Georgia"), local("Times New Roman");
  size-adjust: 102%;
  font-display: swap;
}
@font-face {
  font-family: "Karla-fallback";
  src: local("Arial");
  size-adjust: 96%;
  font-display: swap;
}

/* ============================================================
   Base
   ============================================================ */
*,*::before,*::after{
  box-sizing:border-box;
  margin:0;
}
body{
  font-family:var(--font-body);
  font-size:var(--fs-body);
  line-height:1.5;
  color:var(--brown-ink);
  background:var(--cream);
}
h1{
  font-family:var(--font-display);
  font-size:var(--fs-display);
  line-height:1.02;
  font-weight:600;
  /* Vollkorn carries weight only, no optical-size or shape axes, so the
     display voice comes from weight, tight tracking and scale alone. */
  letter-spacing:-.02em;
}
h2,h3{
  font-family:var(--font-display);
  font-size:var(--fs-heading);
  line-height:1.18;
  font-weight:600;
  letter-spacing:-.012em;
}
.script-accent{
  /* The flourish is a true cursive.
     Single word or short phrase only, never a full sentence. */
  font-family:var(--font-script);
  font-style:italic;
  font-weight:400;
  font-size:var(--fs-heading);
  letter-spacing:.005em;
}
.prose{
  max-width:65ch;
}
img{
  max-width:100%;
  height:auto;
  display:block;
}
a{
  color:inherit;
  text-decoration:underline;
}
:focus-visible{
  /* two-layer ring so focus reads on both surfaces: the brown outline
     carries it on cream/paper, the paper halo in the offset gap carries
     it on --brown-ink bands (footer, dark sections) */
  outline:3px solid var(--brown-ink);
  outline-offset:2px;
  box-shadow:0 0 0 2px var(--paper);
}
.container{
  max-width:var(--container);
  margin-inline:auto;
  padding-inline:var(--gutter);
}
.section{
  padding-block:var(--space-3xl);
}
@media (min-width:768px){
  .section{
    padding-block:var(--space-4xl);
  }
}

/* ============================================================
   Buttons (UI-SPEC button contract; Phases 2+ consume)
   ============================================================ */
.btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:44px;
  padding-inline:var(--space-lg);
  border-radius:var(--radius-pill);
  font-family:var(--font-body);
  font-weight:600;
  font-size:1rem;
  text-decoration:none;
  /* UA resets so <button class="btn"> renders identically to <a class="btn">;
     modifiers re-add what they need (.btn-secondary its 2px border) */
  appearance:none;
  border:none;
  background:none;
  cursor:pointer;
  transition:background-color var(--dur-fast) var(--ease-out),
             color var(--dur-fast) var(--ease-out),
             border-color var(--dur-fast) var(--ease-out);
}
/* order actions only, per the UI-SPEC accent-reserved list */
.btn-primary{
  background:var(--red);
  color:#FFFFFF;
}
.btn-primary:hover{
  background:var(--red-deep);
}
.btn-secondary{
  background:transparent;
  color:var(--brown-ink);
  border:2px solid var(--brown-ink);
}
.btn-secondary:hover{
  background:var(--gold-tint);
}
.btn-soft{
  background:var(--gold-tint);
  color:var(--brown-ink);
}
.btn-soft:hover{
  /* brown-ink on gold passes AA at 7.65:1 */
  background:var(--gold);
}

/* ============================================================
   Phase 2 continues here: site chrome (header, nav, footer,
   order chooser modal, sticky mobile bar). Append below.
   ============================================================ */

/* ============================================================
   Phase 2: site chrome
   Styles the five sentinel-fenced blocks in tools/chrome-reference.html.
   Section order: 1 tokens, 2 utilities, 3 header, 4 drawer,
   5 order modal, 6 mobile bar, 7 footer, 8 motion guard.
   Nothing above this banner is ever modified (locked convention).
   ============================================================ */

/* ---- 1. Component tokens ---------------------------------- */
:root{
  /* sticky mobile bar height, excluding the safe-area inset */
  --bar-h:64px;
  /* tonal ground between cream and paper, so sections layer instead of
     reading as one flat cream slab. Verified against the AA contract:
     brown ink measures 12.17:1 on it and brown soft 5.79:1, both clear
     of AA, so it introduces no unvetted pair. */
  --cream-deep:#F2E7D2;
}
@media (max-width:767px){
  :root{
    /* desktop 80px is already tokenized in the Phase 1 block */
    --header-h:64px;
  }
}

/* ---- 2. Utilities ----------------------------------------- */
.sr-only{
  position:absolute;
  width:1px;
  height:1px;
  padding:0;
  margin:-1px;
  overflow:hidden;
  clip:rect(0 0 0 0);
  clip-path:inset(50%);
  white-space:nowrap;
  border:0;
}
.skip-link{
  position:fixed;
  top:var(--space-md);
  left:-9999px;
  z-index:100;
  display:inline-flex;
  align-items:center;
  min-height:44px;
  padding-inline:var(--space-lg);
  border-radius:var(--radius-pill);
  background:var(--gold-tint);
  color:var(--brown-ink);
  font-weight:600;
  text-decoration:none;
}
.skip-link:focus{
  /* lands clear of the sticky header instead of fighting it for paint
     order, so no extra z-index step is needed */
  left:var(--space-md);
  top:calc(var(--header-h) + var(--space-sm));
}
.script-flourish{
  /* the single-word script accent used sitewide. No color is declared on
     purpose: the word inherits its context, because gold only clears
     contrast on dark grounds. The footer supplies its color in section 7.
     Same cursive face as .flourish, one step larger again because the
     footer line around it is body scale rather than heading scale. */
  font-family:var(--font-cursive);
  font-style:normal;
  font-weight:400;
  font-size:1.85em;
  line-height:.85;
  padding-inline:.06em;
}
body:has(dialog[open]){
  /* CSS-only scroll lock covering both dialogs; also stops iOS from
     scrolling the page behind an open overlay */
  overflow:hidden;
}

/* ---- 3. Header -------------------------------------------- */
.site-header{
  position:sticky;
  top:0;
  z-index:100;
  background:var(--cream);
  border-bottom:1px solid var(--line);
  transition:box-shadow var(--dur-fast) var(--ease-out);
}
.site-header.is-scrolled{
  box-shadow:var(--shadow-sm);
}
.site-header__row{
  /* Three tracks rather than flex, so the nav sits on the true optical centre
     of the header instead of wherever the logo width happens to push it. The
     outer tracks are equal, so the centre track is centred no matter how wide
     the logo or the actions get. Below the nav breakpoint .main-nav is
     display:none, the middle track collapses to zero, and the logo and the
     order button simply sit at the two edges. */
  display:grid;
  grid-template-columns:1fr auto 1fr;
  align-items:center;
  height:var(--header-h);
}
.site-logo{
  display:inline-flex;
  text-decoration:none;
}
.site-logo img{
  height:64px;
  width:auto;
}
.main-nav{
  display:none;
  justify-self:center;
}
.main-nav ul{
  display:flex;
  align-items:center;
  gap:var(--space-lg);
  list-style:none;
  padding:0;
}
.main-nav a{
  font-family:var(--font-body);
  font-size:var(--fs-label);
  font-weight:600;
  color:var(--brown-ink);
  text-decoration:none;
  /* The hit area, not the look. A bare inline link is only as tall as its
     text (17px measured), which is under the WCAG 2.2 target-size minimum.
     The header row is flex-centred, so vertical padding costs no layout. */
  display:inline-block;
  padding-block:var(--space-sm);
}
.main-nav a:hover,
.main-nav a:focus-visible{
  /* transient decoration only; gold deep sits below the 3:1 non-text
     floor on cream, so it never carries the persistent active marker */
  text-decoration:underline;
  text-decoration-thickness:2px;
  text-underline-offset:6px;
  text-decoration-color:var(--gold-deep);
}
.main-nav a.is-active,
.main-nav a[aria-current="page"]{
  text-decoration:underline;
  text-decoration-thickness:2px;
  text-underline-offset:6px;
  text-decoration-color:var(--brown-ink);
}
.header-actions{
  justify-self:end;
  display:flex;
  align-items:center;
  gap:var(--space-sm);
  margin-left:auto;
}
.nav-toggle{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:44px;
  height:44px;
  padding:0;
  border:0;
  background:transparent;
  color:var(--brown-ink);
  cursor:pointer;
}
@media (max-width:767px){
  .site-logo img{
    height:48px;
  }
}
@media (min-width:1024px){
  .main-nav{
    display:inline-flex;
  }
  .header-actions{
    margin-left:var(--space-xl);
  }
  .nav-toggle{
    display:none;
  }
}

/* ---- 4. Mobile drawer ------------------------------------- */
.mobile-nav{
  /* zero padding and a transparent ground are load-bearing: the panel
     fills the dialog box exactly, so a click whose target is the dialog
     itself can only be a genuine backdrop click */
  padding:0;
  border:0;
  background:transparent;
  margin:0 0 0 auto;
  width:min(320px, 85vw);
  max-width:100vw;
  height:100dvh;
  max-height:100dvh;
  transform:translateX(100%);
  transition:transform var(--dur-med) var(--ease-out),
             display var(--dur-med) var(--ease-out) allow-discrete,
             overlay var(--dur-med) var(--ease-out) allow-discrete;
}
.mobile-nav[open]{
  transform:translateX(0);
}
/* progressive enhancement only: a browser without starting-style support
   renders the open drawer instantly, with no error and no broken state */
@starting-style{
  .mobile-nav[open]{
    transform:translateX(100%);
  }
}
.mobile-nav::backdrop,
.order-modal::backdrop{
  background:rgba(51,36,26,.55);
}
.mobile-nav__panel{
  display:flex;
  flex-direction:column;
  gap:var(--space-md);
  height:100%;
  padding:var(--space-lg);
  background:var(--paper);
  box-shadow:var(--shadow-lg);
  overflow-y:auto;
}
.mobile-nav__close{
  align-self:flex-end;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:44px;
  height:44px;
  padding:0;
  border:0;
  background:transparent;
  color:var(--brown-ink);
  cursor:pointer;
}
.mobile-nav__list{
  padding-bottom:var(--space-md);
  border-bottom:1px solid var(--line);
}
.mobile-nav__list ul{
  list-style:none;
  padding:0;
}
.mobile-nav__list a{
  display:flex;
  align-items:center;
  min-height:48px;
  font-family:var(--font-body);
  font-size:var(--fs-body);
  font-weight:600;
  color:var(--brown-ink);
  text-decoration:none;
}
.mobile-nav__list a:hover,
.mobile-nav__list a:focus-visible{
  text-decoration:underline;
  text-decoration-thickness:2px;
  text-underline-offset:6px;
  text-decoration-color:var(--gold-deep);
}
.mobile-nav__list a.is-active,
.mobile-nav__list a[aria-current="page"]{
  text-decoration:underline;
  text-decoration-thickness:2px;
  text-underline-offset:6px;
  text-decoration-color:var(--brown-ink);
}
.mobile-nav__panel .btn{
  width:100%;
  gap:var(--space-sm);
}

/* ---- 5. Order chooser modal ------------------------------- */
.order-modal{
  padding:0;
  border:0;
  background:transparent;
  width:min(440px, calc(100vw - 32px));
  /* margin:auto restores the UA dialog centering that the Phase 1 universal
     margin:0 reset overrides. Author declarations beat the UA sheet, so without
     this the dialog paints at the viewport top-left corner in every browser. */
  margin:auto;
}
.order-modal__card{
  position:relative;
  display:grid;
  gap:var(--space-md);
  padding:var(--space-xl);
  border-radius:var(--radius-lg);
  background:var(--paper);
  box-shadow:var(--shadow-lg);
}
.order-modal__card h2{
  /* fixed, not fluid: the card is width-capped so it never needs to scale.
     The inline end padding keeps the heading clear of the close button. */
  font-family:var(--font-display);
  font-size:28px;
  font-weight:600;
  line-height:1.2;
  padding-inline-end:44px;
}
.order-modal__close{
  position:absolute;
  top:var(--space-sm);
  right:var(--space-sm);
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:44px;
  height:44px;
  padding:0;
  border:0;
  background:transparent;
  color:var(--brown-ink);
  cursor:pointer;
}
.order-option{
  /* the quiet tonal card. Only the primary option carries fill, so the
     chooser has exactly one strong element pointing at pickup. */
  display:block;
  min-height:72px;
  padding:16px 24px;
  border:1px solid var(--line);
  border-radius:var(--radius-md);
  background:var(--cream-deep);
  color:var(--brown-ink);
  text-align:left;
  text-decoration:none;
  transition:border-color var(--dur-fast) var(--ease-out),
             background-color var(--dur-fast) var(--ease-out),
             box-shadow var(--dur-fast) var(--ease-out);
}
.order-option:hover{
  border-color:var(--line-strong);
  box-shadow:var(--shadow-sm);
}
.order-option--primary{
  background:var(--red);
  color:#FFFFFF;
  border-color:transparent;
}
.order-option--primary:hover{
  background:var(--red-deep);
  border-color:transparent;
}
.order-option__title{
  display:block;
  font-size:var(--fs-body);
  font-weight:600;
}
.order-option__sub{
  display:block;
  font-size:var(--fs-label);
  font-weight:400;
}
.order-modal__call{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:var(--space-sm);
  min-height:44px;
  font-size:var(--fs-body);
  font-weight:600;
  color:var(--brown-ink);
  text-decoration:underline;
}

/* ---- 6. Sticky mobile bar --------------------------------- */
.mobile-bar{
  /* Was phone-only. It is now the sitewide sticky order bar: the shop's one
     job on this site is taking orders, so the route to the ordering page is
     never more than one tap away at any width. It stays hidden until the
     reader has left the hero, where the same action is already the biggest
     thing on screen. */
  position:fixed;
  inset-inline:0;
  bottom:0;
  z-index:90;
  display:flex;
  align-items:center;
  /* nowrap is load-bearing: with three controls the bar wrapped to two lines
     at 390px, which broke the 64px height the page reserves for it. */
  flex-wrap:nowrap;
  gap:var(--space-sm);
  transform:translateY(110%);
  transition:transform .45s var(--ease-out);
  will-change:transform;
  background:var(--paper);
  border-top:1px solid var(--line);
  box-shadow:0 -2px 10px rgba(51,36,26,.08);
  padding:8px 16px;
  /* the bar keeps its own padding independent of the inset, so it stays
     usable when the inset reports zero with the toolbar hidden */
  padding-bottom:calc(8px + env(safe-area-inset-bottom, 0px));
}
@media (max-width:767px){
  .mobile-bar{
    display:grid;
    /* Three columns, not two. This was a 1fr 1fr grid from when the bar held
       two buttons; adding DoorDash pushed the call button onto a second row
       and made the bar 113px tall against a 64px reservation. The call column
       is auto so it takes only what the icon needs. */
    grid-template-columns:1fr 1fr auto;
    gap:8px;
  }
}

/* ---- 7. Footer -------------------------------------------- */
.site-footer{
  position:relative;
  overflow:hidden;
  padding-block:var(--space-3xl);
  background:var(--brown-ink);
  color:var(--paper);
}
.site-footer__curve{
  /* soft arch carved out of the page cream, so the footer's top edge
     reads as a shape rather than a hard slab cut */
  position:absolute;
  inset-inline:0;
  top:0;
  height:clamp(24px, 4vw, 40px);
  background:var(--cream);
  border-end-start-radius:50% 100%;
  border-end-end-radius:50% 100%;
  pointer-events:none;
}
.footer-grid{
  display:grid;
  gap:var(--space-xl);
  grid-template-columns:1fr;
}
.footer-col h2{
  font-family:var(--font-display);
  font-size:var(--fs-body);
  font-weight:600;
  color:var(--paper);
  margin-bottom:var(--space-xs);
}
.footer-col img{
  /* 48px read as a favicon against this much dark ground. The brand column
     is the one place the mark should have presence. */
  height:76px;
  width:auto;
}
.footer-col ul{
  list-style:none;
  padding:0;
}
.footer-col a{
  display:inline-flex;
  align-items:center;
  gap:var(--space-xs);
  min-height:44px;
  font-size:var(--fs-label);
  color:var(--paper);
  text-decoration:none;
}
.footer-col a:hover,
.footer-col a:focus-visible{
  text-decoration:underline;
  text-decoration-thickness:2px;
  text-underline-offset:4px;
  text-decoration-color:currentColor;
}
.footer-tagline{
  font-family:var(--font-body);
  font-weight:400;
  font-size:var(--fs-body);
  color:var(--paper);
  margin-block:var(--space-md) var(--space-lg);
  max-width:28ch;
}
.site-footer .script-flourish{
  /* the footer's single gold role: one designed second-read moment */
  color:var(--gold);
}
.footer-social{
  display:flex;
  align-items:center;
  gap:var(--space-sm);
}
/* The marks carry their own brand colour, which floats oddly on bare brown.
   A soft chip gives them a ground to sit on, matching the hero treatment. */
.footer-social a{
  justify-content:center;
  width:44px;
  height:44px;
  border-radius:var(--radius-pill);
  background:rgba(255,252,245,.07);
  border:1px solid rgba(255,252,245,.16);
  transition:background var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out),transform var(--dur-med) var(--ease-out);
}
.footer-social a:hover,
.footer-social a:focus-visible{
  background:rgba(255,252,245,.14);
  border-color:rgba(255,252,245,.34);
  transform:translateY(-2px);
}
@media (prefers-reduced-motion:reduce){
  .footer-social a{transition:none}
  .footer-social a:hover{transform:none}
}
/* Gives the marks a reason to exist rather than leaving two icons floating,
   and evens the brand column against the link columns beside it. */
.footer-social-note{
  margin-top:var(--space-md);
  max-width:30ch;
  font-size:var(--fs-label);
  color:rgba(255,252,245,.68);
  line-height:1.6;
}
.site-footer address{
  font-style:normal;
  font-size:var(--fs-label);
  line-height:1.9;
}
.footer-hours{
  font-size:var(--fs-label);
  margin-block:var(--space-sm);
}
.footer-bottom{
  margin-top:var(--space-xl);
  padding-top:var(--space-md);
  border-top:1px solid var(--line-strong);
  font-size:var(--fs-label);
}
@media (min-width:768px){
  .site-footer{
    padding-block:var(--space-4xl);
  }
  .footer-grid{
    grid-template-columns:1fr 1fr;
  }
}
@media (min-width:1024px){
  .footer-grid{
    grid-template-columns:1.4fr 1fr 1fr 1fr;
  }
}

/* ---- 8. Motion guard -------------------------------------- */
/* Authored last on purpose: these declarations share specificity with the
   chrome rules above, so the guard has to come after them to win the
   cascade and actually zero the drawer slide and the header shadow. */
@media (prefers-reduced-motion: reduce){
  .site-header,
  .mobile-nav,
  .order-option{
    transition:none;
  }
}

/* ============================================================
   Phase 2: order page
   Section styles for order.html, the durable no-JS order path.
   Four selectors, exhaustive: .order-page, .order-card,
   .order-eyebrow, .order-note. Everything else that page renders
   reuses the chrome region above and the Phase 1 utilities
   (.section, .container, .prose, .btn, .order-option,
   .script-flourish, .sr-only), which are deliberately NOT
   redefined here.
   ============================================================ */
.order-page{
  /* Grid rather than flow: the Phase 1 base zeroes every margin, so gap is
     what gives this page its vertical rhythm. justify-items centers each
     block inside the 640px column, which keeps the lede optically centered
     instead of hanging left of its own 65ch cap. */
  display:grid;
  justify-items:center;
  gap:var(--space-lg);
  max-width:640px;
  margin-inline:auto;
  text-align:center;
}
.order-card{
  width:100%;
  display:grid;
  gap:var(--space-md);
  padding:var(--space-xl);
  border-radius:var(--radius-lg);
  background:var(--paper);
  box-shadow:var(--shadow-sm);
  /* the three choices read as a list, so they stay left-aligned inside
     the centered page */
  text-align:left;
}
.order-eyebrow{
  /* A quiet Nunito line whose one flourish word inherits --brown-soft.
     DESIGN-DIRECTION D2: script is a single-word accent, never a full line.
     Colour matters here: Caveat in --gold on cream measures 1.74:1 and is
     illegible, while --brown-soft on cream is 6.32:1. This is exactly why
     the shared .script-flourish utility ships without a colour. */
  font-family:var(--font-body);
  font-weight:400;
  font-size:1rem;
  color:var(--brown-soft);
  margin-bottom:var(--space-sm);
}
.order-note{
  font-size:var(--fs-label);
  color:var(--brown-soft);
}

/* ============================================================
   Phase 3: homepage and menu
   The whole component vocabulary index.html and menu.html
   consume, authored once here so neither page plan writes CSS.
   Subsection order:
      1 token          the arch radius, the only new property
      2 tonal grounds  cream, cream-deep, paper, ink, gold-tint
      3 section heads  section-head, eyebrow, section-lede
      4 devices        arch, flourish, pull quote, link arrow, badge
      5 hero           grid, text column, photo, offset tile, curve
      6 signatures     the staggered no-box tile band
      7 story          arch portrait beside prose and a quote
      8 testimonials   the asymmetric quote field
      9 hours          three columns, each with a display anchor
     10 cta band       the one centered block per page
     11 menu hero
     12 menu category nav, sticky under the sticky header
     13 anchor offsets
     14 the menu item row
     15 category heads, the numbered build device, chips
     16 reveal motion
     17 reduced motion guard, authored last
   Nothing above this banner is ever modified (locked convention).
   ============================================================ */

/* ---- 1. Token --------------------------------------------- */
:root{
  /* The standardized arch. The percentage and slash form is load bearing:
     with a 50% horizontal radius on both top corners their sum equals the
     box width exactly, so the CSS radius reduction factor stays at 1 at
     every box size this phase uses. A large pixel arch such as
     600px 600px 12px 12px gets scaled down on a small box and degrades
     into a soft rectangle. --cream-deep is NOT redeclared here; it already
     ships in the Phase 2 token block and a duplicate fails contrast.mjs. */
  --radius-arch:50% 50% var(--radius-lg) var(--radius-lg) / 32% 32% var(--radius-lg) var(--radius-lg);
}

/* ---- 2. Tonal grounds ------------------------------------- */
/* A section is full bleed by nature: .section sets padding only and no
   width, so the tone spans the viewport and the .container inside keeps
   the content on the grid. No extra full bleed helper is needed. */
.on-cream{
  background:var(--cream);
}
.on-cream-deep{
  background:var(--cream-deep);
}
.on-paper{
  background:var(--paper);
}
.on-ink{
  background:var(--brown-ink);
  color:var(--paper);
}
.on-gold-tint{
  background:var(--gold-tint);
  color:var(--brown-ink);
}
/* The three flips the dark band locks. Gold clears 7.65:1 on ink, the
   warm white at .72 alpha clears 8.22:1, and the .16 alpha hairline is
   the ink band counterpart of --line. */
.on-ink .eyebrow{
  color:var(--gold);
}
.on-ink .section-lede,
.on-ink .hours-col__note,
.on-ink .menu-note,
.on-ink .menu-build__body,
.on-ink .menu-cat__head p,
.on-ink .area-block__body p,
.on-ink .event-row__body p,
.on-ink .package__body,
.on-ink .pull-quote__cite{
  color:rgba(255,252,245,.72);
}
.on-ink .menu-cat__head h2,
.on-ink .menu-build__step,
.on-ink .menu-item{
  border-color:rgba(255,252,245,.16);
}
/* Item names and chips carry an explicit ink colour for the cream grounds,
   so the dark ground has to take it back. */
.on-ink .menu-item__name{
  color:var(--paper);
}
.on-ink .chip{
  background:rgba(255,252,245,.08);
  border-color:rgba(255,252,245,.2);
  color:var(--paper);
}

/* ---- 3. Section heads ------------------------------------- */
/* Markup contract: .section-head holds .eyebrow, then the h2, then
   either .section-lede or .rating-badge. The eyebrow always spans, the
   heading takes the reading column, the third element pairs beside it. */
.section-head{
  display:grid;
  gap:var(--space-md);
  margin-bottom:var(--space-2xl);
}
.eyebrow{
  font:600 var(--fs-label)/1.4 var(--font-body);
  text-transform:uppercase;
  letter-spacing:.16em;
  color:var(--brown-soft);
  display:inline-flex;
  align-items:center;
  gap:var(--space-sm);
}
.eyebrow::before{
  content:"";
  flex:none;
  width:24px;
  height:2px;
  background:currentColor;
}
.section-lede{
  font-size:var(--fs-body);
  color:var(--brown-soft);
  max-width:60ch;
}
@media (min-width:768px){
  .section-head{
    grid-template-columns:minmax(0,1fr) auto;
    column-gap:clamp(var(--space-xl), 5vw, var(--space-4xl));
    row-gap:var(--space-md);
    align-items:end;
  }
  .section-head > .eyebrow{
    grid-column:1 / -1;
  }
  .section-head > h2{
    grid-column:1;
  }
  .section-head > .section-lede{
    grid-column:1 / -1;
  }
  .section-head > .rating-badge{
    grid-column:2;
    grid-row:2;
    justify-self:end;
  }
}
@media (min-width:1024px){
  .section-head{
    grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  }
  .section-head > .section-lede{
    grid-column:2;
    grid-row:2;
  }
}
/* The two-column head is an editorial device for FULL WIDTH sections: the
   heading takes the left, the lede pairs beside it. Two cases where that
   split is wrong, and both were shipping visibly broken headings:
   a head with nothing to pair (the heading kept only half the width for no
   reason), and a head nested inside an already narrow column, where half of
   half wraps a short heading into four lines. */
@media (min-width:768px){
  .section-head:not(:has(> .section-lede)):not(:has(> .rating-badge)),
  .contact-grid .section-head,
  .story__text .section-head,
  .area-block .section-head{
    grid-template-columns:minmax(0,1fr);
  }
  .contact-grid .section-head > .section-lede,
  .area-block .section-head > .section-lede{
    grid-column:1;
    grid-row:auto;
  }
}

/* ---- 4. Editorial devices --------------------------------- */
.arch{
  border-radius:var(--radius-arch);
  overflow:hidden;
  /* WebKit has a long standing bug where overflow plus border-radius
     fails to clip a child that carries a transform, and the photo hover
     here is a scale(1.03). Forcing this box into its own stacking
     context is the documented workaround, it costs nothing, and it does
     not disturb the z-index ladder below. */
  isolation:isolate;
}
.flourish{
  /* No colour on purpose: the single script word inherits its ground,
     because gold only clears contrast on dark. Same reasoning as the
     shipped .script-flourish utility.

     A true cursive, set well above its host line: script faces carry a much
     smaller apparent x-height, so at 1:1 they read as a mistake rather than
     an accent. Single word or short phrase only, never a full sentence, and
     never below heading scale, where a script stops being legible. */
  font-family:var(--font-cursive);
  font-style:normal;
  font-weight:400;
  font-size:1.5em;
  line-height:.9;
  letter-spacing:.01em;
  /* script descenders want room the roman line does not give them */
  padding-inline:.06em;
}
.on-ink .flourish{
  color:var(--gold);
}
.pull-quote{
  font-family:var(--font-display);
  font-weight:600;
  font-size:var(--fs-heading);
  line-height:1.25;
  letter-spacing:-.02em;
  max-width:20ch;
  position:relative;
}
.pull-quote::before{
  /* Ornament that hangs into the left margin. The quote text itself
     carries no typed quotation marks and reads complete without it. */
  content:"\201C";
  position:absolute;
  left:-.42em;
  top:-.12em;
  font-size:2.4em;
  line-height:1;
  color:var(--gold-deep);
}
.on-ink .pull-quote::before{
  color:var(--gold);
}
.pull-quote__cite{
  display:block;
  margin-top:var(--space-md);
  font-family:var(--font-body);
  font-weight:400;
  font-style:normal;
  font-size:var(--fs-label);
  letter-spacing:normal;
  color:var(--brown-soft);
}
.link-arrow{
  display:inline-flex;
  align-items:center;
  gap:var(--space-sm);
  min-height:44px;
  font-family:var(--font-body);
  font-weight:600;
  font-size:var(--fs-label);
  text-transform:uppercase;
  letter-spacing:.1em;
  color:var(--brown-ink);
  text-decoration:none;
  border-bottom:1px solid var(--line-strong);
  padding-bottom:2px;
  transition:border-color var(--dur-fast) var(--ease-out);
}
.link-arrow svg{
  flex:none;
  transition:transform var(--dur-fast) var(--ease-out);
}
.link-arrow:hover,
.link-arrow:focus-visible{
  /* transient decoration only, so gold-deep never carries a persistent
     marker on a light ground */
  border-bottom-color:var(--gold-deep);
}
.link-arrow:hover svg{
  transform:translateX(4px);
}
.rating-badge{
  display:inline-flex;
  align-items:center;
  gap:var(--space-sm);
  min-height:44px;
  padding-inline:var(--space-lg);
  border-radius:var(--radius-pill);
  background:var(--gold-tint);
  color:var(--brown-ink);
  font-family:var(--font-body);
  font-weight:600;
  font-size:var(--fs-label);
  text-decoration:none;
}
.rating-badge svg{
  flex:none;
}

/* ---- 5. Hero ---------------------------------------------- */
/* Markup contract, and the one structural refinement of the approved
   spec: the arch clip lives on an inner .hero__photo, never on
   .hero__media, so the absolutely positioned offset tile is a SIBLING of
   the clip and stays visible.
     .hero > svg.hero__curve
           > .container > .hero__grid > .hero__text
                                      > .hero__media > .hero__photo.arch
                                                     > img.hero__tile
   The hero never declares a viewport height, and nothing in this phase
   declares overflow-x on an ancestor of a sticky element, which would
   silently stop both the site header and the menu nav from docking. */
.hero{
  position:relative;
  padding-block:var(--space-2xl) var(--space-3xl);
}
.hero__grid{
  display:grid;
  gap:var(--space-2xl);
}
.hero__text{
  position:relative;
  z-index:3;
}
.hero__aside{
  /* The single most visible accent line on the site, so it carries the
     cursive rather than the roman italic. Sized off the heading role, not
     off .flourish, because it is a standalone line rather than a word
     sitting inside a heading. */
  font-family:var(--font-cursive);
  font-style:normal;
  font-size:calc(var(--fs-heading) * 1.15);
  line-height:1;
  color:var(--brown-soft);
  margin-bottom:var(--space-md);
}
.hero__word{
  /* Inherits the display role from the base h1 rule, so the size is
     stated here only as its declared em multiplier. */
  display:block;
  font-size:1.18em;
  letter-spacing:-.03em;
  color:var(--brown-soft);
  margin-bottom:var(--space-sm);
}
.hero__line{
  display:block;
  font-size:var(--fs-heading);
  line-height:1.15;
  letter-spacing:-.02em;
  max-width:18ch;
  color:var(--brown-ink);
}
.hero__lede{
  max-width:42ch;
  color:var(--brown-soft);
  margin-top:var(--space-lg);
}
.hero__actions{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-md);
  margin-top:var(--space-xl);
}
.hero__proof{
  display:inline-flex;
  align-items:center;
  gap:var(--space-sm);
  min-height:44px;
  margin-top:var(--space-lg);
  font-size:var(--fs-label);
  color:var(--brown-soft);
  text-decoration:none;
}
.hero__proof svg{
  flex:none;
}
.hero__proof:hover,
.hero__proof:focus-visible{
  text-decoration:underline;
  text-underline-offset:4px;
}
.hero__media{
  position:relative;
  z-index:1;
  order:-1;
  width:min(100%, 464px);
}
.hero__photo{
  aspect-ratio:3/4;
  max-height:620px;
}
.hero__photo picture,
.hero__photo img{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
}
.hero__photo img{
  transition:transform 1.2s var(--ease-out);
}
.hero__photo:hover img{
  transform:scale(1.03);
}
.hero__tile{
  position:absolute;
  left:-32px;
  bottom:-24px;
  z-index:2;
  display:none;
  aspect-ratio:1/1;
  object-fit:cover;
  border-radius:var(--radius-lg);
  /* the cream border reads as a cut-out against the hero ground, and
     this is the ONE shadow the entire Phase 3 vocabulary spends */
  border:8px solid var(--cream);
  box-shadow:var(--shadow-md);
}
.hero__curve{
  position:absolute;
  inset-block:0;
  right:0;
  z-index:0;
  display:block;
  width:min(58%, 820px);
  height:100%;
  color:var(--gold-tint);
  opacity:.55;
  transform:scaleX(-1);
  pointer-events:none;
}
@media (max-width:479px){
  .hero__actions > *{
    flex:1 1 100%;
  }
}
@media (max-width:767px){
  .hero__photo{
    max-height:46vh;
    max-height:46svh;
  }
  .hero__curve{
    inset-inline:0;
    width:100%;
    height:52%;
    opacity:.4;
  }
}
@media (min-width:768px) and (max-width:1023px){
  .hero__photo{
    max-height:52vh;
    max-height:52svh;
  }
  .hero__curve{
    /* The curve is shaped for the two-column hero, and that hero does not
       exist until 1024px. Left at its desktop geometry here it drops a hard
       vertical edge straight down the middle of a single-column layout,
       which reads as a rendering fault rather than a shape. Same banded
       treatment as the phone gets. */
    inset-inline:0;
    width:100%;
    /* full height, so the shape's only hard edge lands exactly on the
       hero's own boundary where the next section's ground takes over,
       instead of drawing a straight rule across the middle of the page */
    height:100%;
    opacity:.32;
    transform:none;
  }
}
@media (min-width:1024px){
  .hero{
    padding-block:var(--space-3xl) var(--space-4xl);
  }
  .hero__grid{
    grid-template-columns:1.05fr 0.95fr;
    align-items:center;
    gap:clamp(var(--space-xl), 5vw, var(--space-4xl));
  }
  .hero__media{
    order:0;
    justify-self:end;
  }
  .hero__tile{
    display:block;
    width:168px;
  }
}
@media (min-width:1280px){
  .hero__tile{
    width:200px;
  }
}

/* ---- 6. Signature tiles ----------------------------------- */
/* Anti card wall, and it is the single most effective rule here: a tile
   has no border, no fill, no padding box and no shadow. It is a photo
   plus text sitting on the section ground. The rhythm comes from two
   deliberate irregularities instead, the stagger and the alternating
   crop, so four items never read as four identical boxes. */
.signatures{
  display:grid;
  gap:var(--space-xl);
  grid-template-columns: minmax(0,1fr);
}
.signature-tile{
  display:block;
  color:inherit;
  text-decoration:none;
}
.signature-tile:nth-child(odd) .signature-tile__media{
  /* odd tiles carry .arch in markup and take the tall crop */
  aspect-ratio:3/4;
}
.signature-tile:nth-child(even) .signature-tile__media{
  aspect-ratio:1/1;
  border-radius:var(--radius-lg);
  overflow:hidden;
  /* own stacking context, the same WebKit clip guard .arch carries */
  position:relative;
  z-index:0;
}
.signature-tile__media img{
  width:100%;
  height:100%;
  object-fit:cover;
  transition:transform 1.2s var(--ease-out);
}
.signature-tile:hover .signature-tile__media img,
.signature-tile:focus-visible .signature-tile__media img{
  transform:scale(1.03);
}
.signature-tile__name{
  display:block;
  width:fit-content;
  margin-top:var(--space-md);
  font-family:var(--font-display);
  font-weight:600;
  font-size:var(--fs-body);
  letter-spacing:-.01em;
  color:var(--brown-ink);
  border-bottom:2px solid transparent;
  transition:border-color var(--dur-fast) var(--ease-out);
}
.signature-tile:hover .signature-tile__name,
.signature-tile:focus-visible .signature-tile__name{
  border-bottom-color:var(--brown-ink);
}
.signature-tile__price{
  display:block;
  margin-top:var(--space-xs);
  font-family:var(--font-body);
  font-weight:600;
  font-size:var(--fs-label);
  font-variant-numeric:tabular-nums;
  color:var(--brown-soft);
}
.signature-tile__desc{
  display:block;
  max-width:32ch;
  margin-top:var(--space-sm);
  font-family:var(--font-body);
  font-weight:400;
  font-size:var(--fs-label);
  line-height:1.5;
  color:var(--brown-soft);
}
@media (min-width:768px){
  .signatures{
    grid-template-columns: repeat(2, minmax(0,1fr));
  }
}
@media (min-width:1024px){
  .signatures{
    grid-template-columns: repeat(4, minmax(0,1fr));
    align-items:start;
  }
  .signature-tile:nth-child(2),
  .signature-tile:nth-child(4){
    margin-top:var(--space-3xl);
  }
}

/* ---- 7. Story teaser -------------------------------------- */
.story{
  display:grid;
  gap:var(--space-2xl);
  grid-template-columns: minmax(0,1fr);
}
.story__media{
  order:-1;
  aspect-ratio:4/5;
}
.story__media img{
  width:100%;
  height:100%;
  object-fit:cover;
  /* keeps Revi centred and the counter bagels in the bottom of the frame */
  object-position:58% center;
}
.story__text p{
  max-width:60ch;
  color:var(--brown-soft);
}
.story__text p + p{
  margin-top:var(--space-md);
}
.story__text .pull-quote{
  /* the quote device keeps its own measure and ink inside the column */
  max-width:20ch;
  margin-top:var(--space-xl);
  color:var(--brown-ink);
}
.story__text .link-arrow{
  margin-top:var(--space-xl);
}
@media (min-width:1024px){
  .story{
    grid-template-columns: 1fr 0.9fr;
    align-items:center;
    gap:clamp(var(--space-2xl), 5vw, var(--space-4xl));
  }
  .story__media{
    order:0;
  }
}

/* ---- 8. Testimonials -------------------------------------- */
/* Asymmetric on purpose: one quote promoted to display scale with the
   hanging gold mark, the rest quiet in a hairline field. No cards, no
   borders around cells, no shadows. */
.quote-grid{
  display:grid;
  gap:var(--space-2xl);
  grid-template-columns: minmax(0,1fr);
}
.quote-field{
  display:grid;
  grid-template-columns: minmax(0,1fr);
}
.quote-cell{
  padding:var(--space-lg);
  border-top:1px solid rgba(255,252,245,.16);
}
.quote-cell__text{
  font-family:var(--font-body);
  font-weight:400;
  font-size:var(--fs-body);
  color:var(--paper);
}
.quote-cell__cite{
  display:block;
  margin-top:var(--space-sm);
  font-family:var(--font-body);
  font-weight:400;
  font-style:normal;
  font-size:var(--fs-label);
  color:rgba(255,252,245,.72);
}
@media (min-width:768px){
  .quote-field{
    grid-template-columns: repeat(2, minmax(0,1fr));
  }
  .quote-cell:nth-child(2n){
    border-left:1px solid rgba(255,252,245,.16);
  }
}
@media (min-width:1024px){
  .quote-grid{
    grid-template-columns: repeat(12, minmax(0,1fr));
    column-gap:var(--space-xl);
    align-items:center;
  }
  .quote-grid > .pull-quote{
    grid-column:1 / 6;
  }
  .quote-field{
    grid-column:7 / -1;
  }
}

/* ---- 9. Hours and location -------------------------------- */
/* Three hairline separated columns is the exact shape a stock feature
   trio takes, so every column carries a display scale anchor: the street
   line, the hours line and the phone number. The numerals are what turn
   a utility block into a designed one. */
.hours{
  display:grid;
  gap:var(--space-xl);
  grid-template-columns: minmax(0,1fr);
}
.hours-col{
  display:grid;
  gap:var(--space-sm);
  align-content:start;
  justify-items:start;
}
.hours-col + .hours-col{
  padding-top:var(--space-xl);
  border-top:1px solid var(--line);
}
.hours-col__title{
  /* h3 override: the base rule would render this at heading scale */
  font-size:var(--fs-body);
  color:var(--brown-ink);
}
.hours-col__anchor{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-sm);
  font-family:var(--font-display);
  font-weight:600;
  /* A step down from the section heading. These are anchors within a column,
     not headings, and at full --fs-heading the hours line wraps to three
     ragged lines in a third-width column. */
  font-size:clamp(1.375rem, 1.15rem + 1vw, 1.75rem);
  line-height:1.2;
  letter-spacing:-.02em;
  color:var(--brown-ink);
  text-wrap:balance;
}
.hours-col__anchor svg{
  flex:none;
}
a.hours-col__anchor{
  display:inline-flex;
  min-height:44px;
  text-decoration:none;
}
a.hours-col__anchor:hover,
a.hours-col__anchor:focus-visible{
  text-decoration:underline;
  text-decoration-thickness:2px;
  text-underline-offset:6px;
  text-decoration-color:var(--gold-deep);
}
.hours address{
  font-style:normal;
}
.hours-col__note{
  max-width:40ch;
  font-size:var(--fs-label);
  color:var(--brown-soft);
}
.hours-col .btn{
  margin-top:var(--space-sm);
}
@media (min-width:768px){
  .hours{
    grid-template-columns: repeat(3, minmax(0,1fr));
  }
  .hours-col + .hours-col{
    padding-top:0;
    border-top:0;
    border-inline-start:1px solid var(--line);
    padding-inline-start:var(--space-xl);
  }
}

/* ---- 10. Closing CTA band --------------------------------- */
.cta-band{
  position:relative;
  /* The ONE centred block per page. It earns the exception with the
     arch behind it, which also closes the page shape language. */
  text-align:center;
}
.cta-band__arch{
  position:absolute;
  left:50%;
  top:50%;
  transform:translate(-50%,-50%);
  width:min(560px, 70%);
  aspect-ratio:1/1.15;
  /* Never raise this opacity. The red pill sits over this arch, gold at
     .45 over gold-tint computes to #EDC07D and the pill measures 3.41:1
     against it, which clears the 3:1 non-text floor only below .93. A
     later make-the-arch-pop tweak would silently break that. */
  opacity:.45;
  border-radius:var(--radius-arch);
  background:var(--gold);
  z-index:0;
  pointer-events:none;
  /* keeps a purely decorative shape from escaping its own band and
     painting over the neighbouring section */
  max-height:calc(100% - var(--space-xl));
}
.cta-band .container{
  position:relative;
  z-index:1;
}
.cta-band .eyebrow{
  margin-bottom:var(--space-md);
}
.cta-band__title{
  /* the one display scale rule in this section, the deliberate echo of
     the hero word that closes the page */
  font-size:var(--fs-display);
  line-height:1.05;
  letter-spacing:-.02em;
}
.cta-band__body{
  max-width:46ch;
  margin-inline:auto;
  margin-top:var(--space-md);
  font-size:var(--fs-body);
  color:var(--brown-ink);
}
.cta-band__actions{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:var(--space-md);
  margin-top:var(--space-xl);
}
.cta-band__note{
  margin-top:var(--space-lg);
  font-size:var(--fs-label);
  color:var(--brown-soft);
}

/* ============================================================
   Site build: page-level components
   Everything the remaining pages need. Written as one vocabulary
   so the pages stay diverse in LAYOUT while staying one design
   system in TREATMENT.

   Structural note the markup depends on: .story, .hours and
   .quote-grid are the grid elements themselves and are authored as
   INNER divs inside .container, never on the section element.
   Putting them on the section would make .container the grid's
   only child and collapse the layout into one column.
   ============================================================ */

/* ---- Reveal ------------------------------------------------ */
/* The gate is set in the head before first paint, so nothing ever
   flashes visible then hides. No-JS keeps everything visible. */
html.js [data-reveal]{
  opacity:0;
  /* a shorter lift than before: less travel reads as settling rather than
     sliding in from off-screen */
  transform:translateY(12px);
}
html.js [data-reveal].is-revealed{
  opacity:1;
  transform:none;
  transition:opacity var(--dur-med) var(--ease-out),transform var(--dur-med) var(--ease-out);
}
html.js [data-reveal][data-reveal-delay="1"].is-revealed{transition-delay:.08s}
html.js [data-reveal][data-reveal-delay="2"].is-revealed{transition-delay:.16s}
html.js [data-reveal][data-reveal-delay="3"].is-revealed{transition-delay:.24s}

/* ---- Page hero (every page except the homepage) ------------ */
/* Deliberately NOT the homepage hero. Short, wide, one arch, so the
   interior pages read as chapters rather than repeated landings. */
.page-hero{
  position:relative;
  padding-block:clamp(var(--space-3xl),9vw,var(--space-4xl)) var(--space-3xl);
  overflow:hidden;
}
.page-hero__grid{
  display:grid;
  gap:var(--space-2xl);
  grid-template-columns:minmax(0,1fr);
  align-items:end;
}
.page-hero h1{
  max-width:16ch;
}
.page-hero__lede{
  max-width:52ch;
  margin-top:var(--space-lg);
  font-size:1.0625rem;
  color:var(--brown-soft);
}
.page-hero__aside{
  display:grid;
  gap:var(--space-md);
  align-content:end;
}
.page-hero__figure{
  position:relative;
  border-radius:var(--radius-lg);
  overflow:hidden;
  aspect-ratio:16/10;
  box-shadow:var(--shadow-md);
}
.page-hero__figure img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}
@media (min-width:900px){
  .page-hero__grid{
    grid-template-columns:1.15fr .85fr;
    gap:clamp(var(--space-2xl),5vw,var(--space-4xl));
  }
}

/* ---- Breadcrumb -------------------------------------------- */
.crumbs{
  font-size:var(--fs-label);
  color:var(--brown-soft);
  margin-bottom:var(--space-lg);
}
.crumbs a{
  color:inherit;
  /* text-decoration rather than border-bottom: the underline has to track the
     TEXT, and a border tracks the padded box, which would strand the rule
     22px below the word once the target is padded out to 44px. */
  text-decoration:underline;
  text-decoration-color:var(--line-strong);
  text-underline-offset:3px;
  display:inline-flex;
  align-items:center;
  min-height:44px;
}
.crumbs a:hover,.crumbs a:focus-visible{
  color:var(--brown-ink);
  text-decoration-color:var(--gold-deep);
}
.crumbs span{
  padding-inline:var(--space-sm);
  opacity:.5;
}

/* ============================================================
   Menu page
   The single biggest upgrade over the current site: the menu is
   real selectable indexable text, not a photographed board.
   ============================================================ */

/* ---- Sticky category rail ---------------------------------- */
.menu-nav{
  position:sticky;
  top:var(--header-h);
  z-index:60;
  background:color-mix(in srgb,var(--cream) 92%,transparent);
  backdrop-filter:blur(10px);
  border-bottom:1px solid var(--line);
}
.menu-nav__rail{
  display:flex;
  gap:var(--space-xs);
  overflow-x:auto;
  scrollbar-width:none;
  padding-block:var(--space-md);
  scroll-snap-type:x proximity;
}
.menu-nav__rail::-webkit-scrollbar{display:none}
.menu-nav__rail a{
  flex:0 0 auto;
  scroll-snap-align:start;
  /* min-height rather than padding maths: the rail is the primary way a
     phone navigates this menu, so it gets the full 44px touch target */
  padding:.7rem .95rem;
  display:inline-flex;
  align-items:center;
  min-height:44px;
  border-radius:var(--radius-pill);
  font-size:var(--fs-label);
  font-weight:600;
  letter-spacing:.01em;
  color:var(--brown-soft);
  text-decoration:none;
  white-space:nowrap;
  transition:background var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out);
}
.menu-nav__rail a:hover,
.menu-nav__rail a:focus-visible{
  background:var(--gold-tint);
  color:var(--brown-ink);
}
.menu-nav__rail a.is-current{
  background:var(--brown-ink);
  color:var(--paper);
}

/* ---- Category block ---------------------------------------- */
.menu-cat{
  padding-block:clamp(var(--space-3xl),7vw,var(--space-4xl));
  scroll-margin-top:calc(var(--header-h) + 64px);
}
.menu-cat + .menu-cat{
  border-top:1px solid var(--line);
}
.menu-cat__head{
  display:grid;
  gap:var(--space-sm);
  margin-bottom:var(--space-2xl);
  max-width:60ch;
}
.menu-cat__head p{
  color:var(--brown-soft);
}

/* ---- Item rows --------------------------------------------- */
/* Rows with a dotted leader, not cards. A grid of bordered boxes is
   the most recognisable stock-menu tell; a printed deli board sets a
   name, a leader and a price, so that is what this does. */
.menu-list{
  list-style:none;
  display:grid;
  gap:var(--space-lg);
  padding:0;
}
@media (min-width:820px){
  .menu-list{
    grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:clamp(var(--space-2xl),5vw,var(--space-4xl));
  }
  .menu-list--single{
    grid-template-columns:minmax(0,1fr);
    max-width:64ch;
  }
}
.menu-item{
  /* Three tracks, not two: the name takes its own width, the leader eats the
     slack, the price sits hard right. With two tracks the price is a third
     child and wraps to its own row, which is what a stock menu looks like. */
  display:grid;
  grid-template-columns:auto 1fr auto;
  align-items:baseline;
  gap:var(--space-sm) var(--space-xs);
}
.menu-item__name{
  font-weight:600;
  color:var(--brown-ink);
  letter-spacing:-.005em;
}
.menu-item__lead{
  border-bottom:1px dotted var(--line-strong);
  transform:translateY(-.28em);
  min-width:var(--space-lg);
}
.menu-item__price{
  font-family:var(--font-display);
  font-weight:600;
  font-variant-numeric:tabular-nums;
  color:var(--gold-deep);
  white-space:nowrap;
}
.menu-item__desc{
  grid-column:1 / -1;
  font-size:.9375rem;
  line-height:1.5;
  color:var(--brown-soft);
  max-width:46ch;
}
.menu-note{
  margin-top:var(--space-2xl);
  font-size:var(--fs-label);
  color:var(--brown-soft);
  max-width:62ch;
}

/* ---- Chips (bagel and schmear varieties) ------------------- */
.chip-row{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-sm);
  list-style:none;
  padding:0;
}
.chip{
  padding:.45rem .85rem;
  border-radius:var(--radius-pill);
  background:var(--paper);
  border:1px solid var(--line);
  font-size:var(--fs-label);
  color:var(--brown-ink);
}
.chip--star{
  background:var(--gold-tint);
  border-color:transparent;
  font-weight:600;
}

/* ---- How a bagel gets made (numbered steps) ---------------- */
.menu-build{
  display:grid;
  gap:var(--space-2xl);
}
.menu-build__step{
  display:grid;
  grid-template-columns:var(--space-4xl) 1fr;
  align-items:start;
  /* align-content too, not just align-items: when a short step shares a row
     with a tall one, the default stretch hands the leftover height to BOTH
     auto rows, which drops the body away from its own heading. */
  align-content:start;
  gap:0 var(--space-lg);
}
.menu-build__num{
  grid-column:1;
  grid-row:1 / span 2;
  font-family:var(--font-display);
  font-size:3rem;
  line-height:.9;
  font-weight:400;
  color:var(--gold);
}
.menu-build__step h3{
  grid-column:2;
  margin-bottom:var(--space-sm);
}
.menu-build__body{
  grid-column:2;
  color:var(--brown-soft);
  max-width:56ch;
}
@media (min-width:820px){
  .menu-build{
    grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:clamp(var(--space-2xl),5vw,var(--space-4xl));
  }
}

/* ============================================================
   Gallery
   ============================================================ */
.reel-rail{
  display:grid;
  grid-auto-flow:column;
  grid-auto-columns:minmax(240px,74vw);
  gap:var(--space-lg);
  overflow-x:auto;
  scroll-snap-type:x mandatory;
  scrollbar-width:none;
  padding-block:var(--space-sm) var(--space-lg);
  margin-inline:calc(var(--gutter) * -1);
  padding-inline:var(--gutter);
}
.reel-rail::-webkit-scrollbar{display:none}
@media (min-width:700px){
  .reel-rail{grid-auto-columns:minmax(260px,32%)}
}
.reel-card{
  scroll-snap-align:start;
  position:relative;
  display:block;
  border-radius:var(--radius-md);
  overflow:hidden;
  aspect-ratio:9/16;
  background:var(--brown-ink);
  text-decoration:none;
  box-shadow:var(--shadow-sm);
}
.reel-card img,
.reel-card video{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
  transition:transform var(--dur-med) var(--ease-out);
}
.reel-card:hover img,
.reel-card:focus-visible img,
.reel-card:hover video{
  transform:scale(1.04);
}
.reel-card__scrim{
  position:absolute;
  inset:auto 0 0 0;
  padding:var(--space-lg) var(--space-md) var(--space-md);
  background:linear-gradient(to top,rgba(51,36,26,.86),transparent);
  color:var(--paper);
  font-size:var(--fs-label);
  font-weight:600;
}
.reel-card__play{
  position:absolute;
  top:var(--space-md);
  right:var(--space-md);
  width:34px;
  height:34px;
  display:grid;
  place-items:center;
  border-radius:var(--radius-pill);
  background:color-mix(in srgb,var(--paper) 88%,transparent);
  color:var(--brown-ink);
}

/* ---- Photo mosaic ------------------------------------------ */
/* Deliberately uneven: two tiles span, the rest do not. An even grid
   of identical squares is the stock gallery shape. */
.photo-grid{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--space-md);
}
.photo-grid figure{
  position:relative;
  border-radius:var(--radius-md);
  overflow:hidden;
  background:var(--gold-tint);
  aspect-ratio:1;
}
.photo-grid img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
  transition:transform var(--dur-med) var(--ease-out);
}
.photo-grid figure:hover img{transform:scale(1.05)}
.photo-grid figcaption{
  position:absolute;
  inset:auto 0 0 0;
  padding:var(--space-xl) var(--space-md) var(--space-md);
  background:linear-gradient(to top,rgba(51,36,26,.8),transparent);
  color:var(--paper);
  font-size:var(--fs-label);
}
@media (min-width:760px){
  .photo-grid{grid-template-columns:repeat(4,minmax(0,1fr))}
  .photo-grid figure:nth-child(1){grid-column:span 2;grid-row:span 2;aspect-ratio:auto}
  .photo-grid figure:nth-child(6){grid-column:span 2;aspect-ratio:2}
}

/* ---- Ambient video frame ----------------------------------- */
.video-frame{
  position:relative;
  border-radius:var(--radius-lg);
  overflow:hidden;
  background:var(--brown-ink);
  aspect-ratio:16/9;
  box-shadow:var(--shadow-md);
}
.video-frame video{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}
.video-frame__cap{
  position:absolute;
  left:var(--space-lg);
  bottom:var(--space-lg);
  color:var(--paper);
  font-family:var(--font-display);
  font-style:italic;
  font-size:1.25rem;
  text-shadow:0 2px 12px rgba(51,36,26,.6);
}

/* ============================================================
   Catering and wholesale
   ============================================================ */
.package-grid{
  display:grid;
  gap:var(--space-xl);
  grid-template-columns:minmax(0,1fr);
}
/* auto-fit rather than a hard 3-up: forced into three tracks at 820px each
   card is ~215px and every heading breaks to three lines. This gives two
   columns on a tablet and three once there is room for them. */
.package-grid{
  grid-template-columns:repeat(auto-fit,minmax(min(100%,290px),1fr));
}
.package{
  display:grid;
  align-content:start;
  gap:var(--space-sm);
  padding:var(--space-xl);
  border-radius:var(--radius-md);
  background:var(--paper);
  border:1px solid var(--line);
}
.package--feature{
  background:var(--brown-ink);
  color:var(--paper);
  border-color:transparent;
}
.package--feature h3,
.package--feature .package__serves{color:var(--paper)}
.package--feature .package__body{color:color-mix(in srgb,var(--paper) 78%,var(--brown-ink))}
.package__serves{
  font-family:var(--font-display);
  font-size:1.5rem;
  color:var(--gold-deep);
}
.package--feature .package__serves{color:var(--gold)}
.package__body{
  color:var(--brown-soft);
  font-size:.9375rem;
  line-height:1.55;
}
.package__list{
  list-style:none;
  padding:0;
  display:grid;
  gap:var(--space-xs);
  margin-top:var(--space-sm);
  font-size:.9375rem;
}
.package__list li{
  padding-left:1.15rem;
  position:relative;
}
.package__list li::before{
  content:"";
  position:absolute;
  left:0;
  top:.55em;
  width:6px;
  height:6px;
  border-radius:var(--radius-pill);
  background:var(--gold);
}

/* ---- Ordered process --------------------------------------- */
.step-list{
  counter-reset:step;
  list-style:none;
  padding:0;
  display:grid;
  gap:var(--space-xl);
}
/* same reasoning as .package-grid */
@media (min-width:640px){
  .step-list{
    grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));
    gap:var(--space-2xl);
  }
}
.step-list li{
  counter-increment:step;
  padding-top:var(--space-lg);
  border-top:2px solid var(--gold);
}
.step-list li::before{
  content:counter(step,decimal-leading-zero);
  display:block;
  font-family:var(--font-display);
  font-size:1.75rem;
  color:var(--gold-deep);
  margin-bottom:var(--space-sm);
}
.step-list h3{margin-bottom:var(--space-xs)}
.step-list p{color:var(--brown-soft);font-size:.9375rem}

/* ============================================================
   Contact
   ============================================================ */
.contact-grid{
  display:grid;
  gap:var(--space-2xl);
  grid-template-columns:minmax(0,1fr);
}
@media (min-width:900px){
  .contact-grid{
    grid-template-columns:1fr .85fr;
    gap:clamp(var(--space-2xl),5vw,var(--space-4xl));
    align-items:start;
  }
}
.field{
  display:grid;
  gap:var(--space-xs);
  margin-bottom:var(--space-lg);
}
.field label{
  font-size:var(--fs-label);
  font-weight:600;
  color:var(--brown-ink);
}
.field input,
.field select,
.field textarea{
  font-family:var(--font-body);
  font-size:1rem;
  color:var(--brown-ink);
  background:var(--paper);
  border:1px solid var(--line-strong);
  border-radius:var(--radius-sm);
  padding:.8rem .9rem;
  width:100%;
  min-height:44px;
}
.field textarea{min-height:140px;resize:vertical}
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible{
  outline:2px solid var(--gold-deep);
  outline-offset:1px;
  border-color:var(--gold-deep);
}
.field__hint{
  font-size:var(--fs-label);
  color:var(--brown-soft);
}
.form-note{
  font-size:var(--fs-label);
  color:var(--brown-soft);
  margin-top:var(--space-md);
}
.info-card{
  display:grid;
  gap:var(--space-lg);
  padding:var(--space-xl);
  border-radius:var(--radius-md);
  background:var(--paper);
  border:1px solid var(--line);
}
.info-card h2{font-size:1.25rem}
.info-row{
  display:grid;
  gap:var(--space-xs);
}
.info-row__label{
  font-size:var(--fs-label);
  text-transform:uppercase;
  letter-spacing:.08em;
  color:var(--brown-soft);
}
.info-row a{
  color:var(--brown-ink);
  text-decoration:none;
  border-bottom:1px solid var(--line-strong);
  /* justify-self keeps the underline tight to the text while the padded
     box still gives the link a real touch target */
  justify-self:start;
  padding-block:.4rem;
}
.info-row a:hover,.info-row a:focus-visible{border-bottom-color:var(--gold-deep)}
.map-card{
  border-radius:var(--radius-md);
  overflow:hidden;
  border:1px solid var(--line);
  background:var(--gold-tint);
  aspect-ratio:4/3;
}
.map-card img{width:100%;height:100%;object-fit:cover;display:block}

/* ============================================================
   Events
   ============================================================ */
.event-list{
  list-style:none;
  padding:0;
  display:grid;
  gap:0;
}
.event-row{
  display:grid;
  grid-template-columns:minmax(0,1fr);
  gap:var(--space-sm);
  padding-block:var(--space-xl);
  border-top:1px solid var(--line);
}
.event-row:last-child{border-bottom:1px solid var(--line)}
@media (min-width:760px){
  .event-row{
    grid-template-columns:auto 1fr auto;
    gap:var(--space-2xl);
    align-items:baseline;
  }
}
.event-row__when{
  font-family:var(--font-display);
  font-size:1.125rem;
  color:var(--gold-deep);
  white-space:nowrap;
}
.event-row__body h3{font-size:1.25rem;margin-bottom:var(--space-xs)}
.event-row__body p{color:var(--brown-soft);font-size:.9375rem;max-width:56ch}

/* ============================================================
   Service area
   ============================================================ */
.area-block{
  padding-block:clamp(var(--space-2xl),6vw,var(--space-3xl));
  scroll-margin-top:calc(var(--header-h) + 24px);
}
.area-block + .area-block{border-top:1px solid var(--line)}
.area-block__grid{
  display:grid;
  gap:var(--space-lg);
  grid-template-columns:minmax(0,1fr);
}
@media (min-width:860px){
  .area-block__grid{
    grid-template-columns:.8fr 1.2fr;
    gap:clamp(var(--space-2xl),5vw,var(--space-4xl));
  }
}
.area-block__drive{
  font-family:var(--font-display);
  font-size:1.125rem;
  color:var(--gold-deep);
  margin-top:var(--space-sm);
}
.area-block__body p + p{margin-top:var(--space-md)}

/* ============================================================
   Chatbot
   Self-contained: a scripted concierge, zero network calls, so it
   works over file:// and cannot leak or invent business facts.
   ============================================================ */
.chatbot{
  position:fixed;
  /* Hidden until the hero is behind you, same as the sticky order bar. On a
     375x667 phone this corner sits directly on the hero headline, and a chat
     bubble over the first thing anyone reads is not a trade worth making.
     JS adds .is-up; without JS the no-JS rule below keeps it visible. */
  opacity:0;
  visibility:hidden;
  transform:translateY(10px);
  transition:opacity var(--dur-med) var(--ease-out),transform var(--dur-med) var(--ease-out),visibility var(--dur-med);
  /* bottom LEFT. The order dock owns the right corner, and two fixed
     controls sharing one corner is a collision waiting to happen at every
     future copy length. Opposite corners is the arrangement that cannot
     break. */
  left:var(--space-lg);
  bottom:var(--space-lg);
  z-index:120;
  display:grid;
  justify-items:start;
  gap:var(--space-sm);
}
.chatbot.is-up{opacity:1;visibility:visible;transform:none}
/* No JS means no observer, so the launcher must not be stranded hidden. */
html:not(.js) .chatbot{opacity:1;visibility:visible;transform:none}
@media (prefers-reduced-motion:reduce){
  .chatbot{transition:none}
}
@media (max-width:860px){
  .chatbot{bottom:calc(64px + var(--space-md))}
}
.chatbot__toggle{
  display:inline-flex;
  align-items:center;
  gap:var(--space-sm);
  min-height:44px;
  padding:.7rem 1.1rem;
  border:0;
  border-radius:var(--radius-pill);
  background:var(--brown-ink);
  color:var(--paper);
  font-family:var(--font-body);
  font-size:var(--fs-label);
  font-weight:600;
  cursor:pointer;
  box-shadow:var(--shadow-md);
  transition:transform var(--dur-fast) var(--ease-out);
}
.chatbot__toggle:hover{transform:translateY(-2px)}
.chatbot__panel{
  width:min(340px,calc(100vw - var(--space-xl)));
  max-height:min(460px,70vh);
  display:none;
  grid-template-rows:auto 1fr auto;
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--radius-md);
  box-shadow:var(--shadow-lg);
  overflow:hidden;
}
.chatbot.is-open .chatbot__panel{display:grid}
.chatbot__head{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--space-sm);
  padding:var(--space-md);
  background:var(--brown-ink);
  color:var(--paper);
}
.chatbot__head p{font-weight:600;font-size:.9375rem}
.chatbot__head span{display:block;font-size:.75rem;opacity:.75;font-weight:400}
.chatbot__close{
  border:0;
  background:transparent;
  color:inherit;
  cursor:pointer;
  padding:var(--space-xs);
  line-height:0;
}
.chatbot__log{
  padding:var(--space-md);
  overflow-y:auto;
  display:grid;
  gap:var(--space-sm);
  align-content:start;
}
.chatbot__msg{
  max-width:88%;
  padding:.6rem .8rem;
  border-radius:var(--radius-md);
  font-size:.9375rem;
  line-height:1.45;
}
.chatbot__msg--bot{
  background:var(--gold-tint);
  color:var(--brown-ink);
  border-bottom-left-radius:var(--radius-sm);
}
.chatbot__msg--me{
  background:var(--brown-ink);
  color:var(--paper);
  justify-self:end;
  border-bottom-right-radius:var(--radius-sm);
}
.chatbot__msg a{color:inherit;font-weight:600}
.chatbot__chips{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-xs);
  padding:var(--space-md);
  border-top:1px solid var(--line);
  background:var(--cream);
}
.chatbot__chips button{
  padding:.4rem .75rem;
  border-radius:var(--radius-pill);
  border:1px solid var(--line-strong);
  background:var(--paper);
  color:var(--brown-ink);
  font-family:var(--font-body);
  font-size:.8125rem;
  cursor:pointer;
  transition:background var(--dur-fast) var(--ease-out);
}
.chatbot__chips button:hover{background:var(--gold-tint)}

/* ============================================================
   Paper grain
   A 16KB tile at 5% over the dark bands only. Flat #33241A across a
   full-bleed band reads like a CSS colour; a trace of grain reads like
   stock. It sits in a pseudo-element behind the content, is pointer
   and screen-reader inert, and never touches the cream grounds, where
   it would fight the photography.
   ============================================================ */
.on-ink{
  position:relative;
  isolation:isolate;
}
.on-ink::after{
  content:"";
  position:absolute;
  inset:0;
  z-index:-1;
  background-image:url("../images/branding/grain.webp");
  background-size:256px 256px;
  background-repeat:repeat;
  opacity:.05;
  mix-blend-mode:overlay;
  pointer-events:none;
}


/* ============================================================
   Motion layer and the components it drives
   Everything here degrades: no-JS gets the static, readable version,
   and the reduced-motion block at the very end of this file switches
   every one of these back off.
   ============================================================ */

/* ---- Kinetic headline -------------------------------------- */
/* The split spans are aria-hidden and the heading carries an aria-label,
   so assistive tech reads the original sentence, not 9 fragments. */
/* A heading arrives whole: one slow fade, one short rise, no rotation and
   no per-word stagger. Longer and softer than the generic reveal because a
   heading is the thing you want to feel settled rather than announced. */
.settle-ready{
  opacity:0;
  transform:translateY(14px);
  transition:opacity 1s var(--ease-out),transform 1s var(--ease-out);
  will-change:opacity,transform;
}
.settle-in{
  opacity:1;
  transform:none;
}

/* ---- Parallax ---------------------------------------------- */
[data-parallax]{
  transform:translate3d(0,var(--parallax,0px),0);
  will-change:transform;
}

/* ---- Magnetic ---------------------------------------------- */
[data-magnetic]{
  transition:transform .7s var(--ease-out);
}
[data-magnetic]:active{
  transition:transform .1s var(--ease-out);
}

/* ---- Stat counters ----------------------------------------- */
.stat-row{
  display:grid;
  gap:var(--space-xl);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,180px),1fr));
}
.stat{
  display:grid;
  gap:var(--space-xs);
  padding-top:var(--space-lg);
  border-top:2px solid var(--gold);
}
.stat__num{
  font-family:var(--font-display);
  font-weight:600;
  font-size:clamp(2.25rem,1.6rem + 2.6vw,3.5rem);
  line-height:1;
  letter-spacing:-.03em;
  color:var(--brown-ink);
  font-variant-numeric:lining-nums tabular-nums;
}
.on-ink .stat__num{color:var(--paper)}
.on-ink .stat{border-top-color:var(--gold)}
.stat__label{
  font-size:var(--fs-label);
  color:var(--brown-soft);
  max-width:22ch;
}
.on-ink .stat__label{color:rgba(255,252,245,.72)}


/* ---- Menu items with a photo -------------------------------- */
/* A photographed row keeps the same three-track price line, but gains a
   leading thumbnail column. The thumbnail spans both text rows so the name,
   leader, price and description all sit in one block beside it. */
.menu-list--photo .menu-item{
  grid-template-columns:72px auto 1fr auto;
  column-gap:var(--space-md);
  align-items:baseline;
}
.menu-item__img{
  grid-row:1 / span 2;
  align-self:start;
  width:72px;
  height:72px;
  object-fit:cover;
  border-radius:var(--radius-sm);
  background:var(--gold-tint);
  /* nudge down so the image optically centres on the name's cap height
     rather than hanging off its baseline */
  margin-top:-.25em;
}
.menu-list--photo .menu-item__desc{
  grid-column:2 / -1;
}
/* rows without a photo keep their alignment with the photographed ones */
.menu-list--photo .menu-item:not(:has(.menu-item__img)){
  grid-template-columns:72px auto 1fr auto;
}
.menu-list--photo .menu-item:not(:has(.menu-item__img)) .menu-item__name{
  grid-column:2;
}
@media (max-width:560px){
  .menu-list--photo .menu-item{
    grid-template-columns:56px auto 1fr auto;
    column-gap:var(--space-sm);
  }
  .menu-item__img{width:56px;height:56px}
  .menu-list--photo .menu-item:not(:has(.menu-item__img)){
    grid-template-columns:56px auto 1fr auto;
  }
}

/* ---- Pick lists (sub builder) ------------------------------- */
/* These read as ingredient lists, not tappable choices, so they are set as
   text rather than as pills. Two or three columns so a dozen toppings do not
   become a dozen lines. */
.pick-list{
  list-style:none;
  padding:0;
  margin-top:var(--space-sm);
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(min(100%,150px),1fr));
  gap:var(--space-xs) var(--space-lg);
}
.pick-list li{
  position:relative;
  padding-left:var(--space-md);
  color:var(--brown-soft);
  font-size:.9375rem;
  line-height:1.5;
}
.pick-list + .menu-list{margin-top:var(--space-lg)}
.pick-list li::before{
  content:"";
  position:absolute;
  left:0;
  top:.62em;
  width:5px;
  height:5px;
  border-radius:var(--radius-pill);
  background:var(--gold);
}



/* the bar rides in once the hero is behind you */
.mobile-bar.is-up{transform:none}
.mobile-bar .btn{
  /* 1 1 0 not 1 1 auto: basis auto keeps each button at its content width and
     is what forced the wrap. min-width:0 lets them actually shrink. */
  flex:1 1 0;
  min-width:0;
  justify-content:center;
  white-space:nowrap;
  padding-inline:clamp(.5rem,3vw,1.4rem);
}
/* Three controls have to fit at 375px. The call button carries the phone icon
   and shrinks to it alone on the narrowest screens, where 'Call' costs more
   width than it earns. The aria-label keeps the full number for screen
   readers either way. */
.mobile-bar .mobile-bar__call{flex:0 1 auto;gap:.4rem;min-width:48px}
@media (max-width:420px){
  .mobile-bar__call-text{
    position:absolute;
    width:1px;height:1px;
    padding:0;margin:-1px;
    overflow:hidden;
    clip-path:inset(50%);
    white-space:nowrap;
  }
  /* specificity has to match .mobile-bar .btn{min-width:0}, which was winning
     and squeezing this to 43px, one pixel under the 44px target minimum */
  .mobile-bar .mobile-bar__call{flex:0 0 auto;min-width:52px}
}
@media (min-width:900px){
  .mobile-bar{
    /* on desktop it becomes a slim right-aligned dock rather than a full
       width bar, so it never covers a column of text.
       It sits ABOVE the chatbot toggle, which is pinned to the same corner at
       bottom:var(--space-lg) and is roughly 44px tall. Stacking them is the
       only arrangement where neither covers the other and the two persistent
       actions still read as one group. */
    inset-inline:auto 0;
    bottom:var(--space-lg);
    right:var(--space-lg);
    width:auto;
    border-radius:var(--radius-pill);
    border:1px solid var(--line);
    box-shadow:var(--shadow-lg);
    padding:10px 12px 10px var(--space-lg);
  }
  .mobile-bar .btn{flex:0 0 auto}
  /* The mobile bar hides by sliding off the bottom edge, which works only
     because it is docked at bottom:0. The desktop dock is inset ~76px, so
     translateY(110%) moves it 73px and leaves it sitting squarely on the
     chatbot toggle. Fade it instead, and take it out of the hit-testing
     tree so it cannot swallow clicks meant for the chatbot. */
  .mobile-bar{
    transform:translateY(14px);
    opacity:0;
    visibility:hidden;
    transition:transform .45s var(--ease-out),opacity .3s var(--ease-out),visibility 0s linear .3s;
  }
  .mobile-bar.is-up{
    transform:none;
    opacity:1;
    visibility:visible;
    transition:transform .45s var(--ease-out),opacity .3s var(--ease-out),visibility 0s;
  }
}
@media (prefers-reduced-motion:reduce){
  .mobile-bar{transition:none}
}


/* ---- Interactive typography --------------------------------- */
/* The weight itself is the interaction. Vollkorn carries a real 400..900
   axis, so a character can thicken under the pointer rather than merely
   shifting position. Only the transition is declared here; the weight is set
   per character from JS. */
/* The word wrapper is what preserves line breaking: every inline-block is a
   break opportunity, so without it the browser breaks between letters. */
.flex-ready .fx-word{
  display:inline-block;
  white-space:nowrap;
}
.flex-ready .fx{
  display:inline-block;
  font-variation-settings:"wght" 400;
  /* inline-block characters would otherwise sit on their own line boxes and
     open up the leading */
  vertical-align:baseline;
}
.flex-ready{
  /* character spans break the normal white-space collapse, so hold the words
     together explicitly */
  word-spacing:.02em;
}
@media (prefers-reduced-motion:reduce){
  .flex-ready .fx{
    transition:none;
    font-variation-settings:"wght" 600;
  }
}



/* The hero now runs kicker, then the shop's name in cursive, then the line.
   Three steps down in scale, each with its own job: when, who, why. The old
   arrangement had the cursive doing the kicker's job and a headline carrying
   a second full sentence, which is what made the spacing read as loose. */
.hero__kicker{
  font-family:var(--font-body);
  font-size:var(--fs-label);
  font-weight:700;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--gold-deep);
  margin-bottom:var(--space-xs);
}
.hero__text .hero__aside{
  /* tucked up under the kicker: the two read as one stacked lockup rather
     than two separate lines */
  margin-bottom:var(--space-sm);
  line-height:.95;
}
.hero__text h1{
  margin-top:var(--space-xs);
}





/* ---- Hero social ------------------------------------------- */
/* Sits under the hero CTAs. Deliberately quieter than the buttons: the marks
   carry their own brand colour, so they draw the eye without competing with
   the ordering action, which is still the point of the page. */
.hero__social{
  display:flex;
  align-items:center;
  gap:var(--space-sm);
  margin-top:var(--space-lg);
  flex-wrap:wrap;
}
.hero__social-label{
  font-size:var(--fs-label);
  color:var(--brown-soft);
  margin-right:.25rem;
}
.hero__social-link{
  display:grid;
  place-items:center;
  width:44px;
  height:44px;
  border-radius:var(--radius-pill);
  background:var(--paper);
  border:1px solid var(--line);
  transition:transform var(--dur-med) var(--ease-out),border-color var(--dur-fast) var(--ease-out),box-shadow var(--dur-med) var(--ease-out);
}
.hero__social-link:hover,
.hero__social-link:focus-visible{
  transform:translateY(-2px);
  border-color:var(--line-strong);
  box-shadow:0 10px 22px -14px rgba(51,36,26,.5);
}
@media (prefers-reduced-motion:reduce){
  .hero__social-link{transition:none}
  .hero__social-link:hover{transform:none}
}

/* ---- Order choices ------------------------------------------ */
/* Three ways to order, rendered as ONE component. They were previously a solid
   red block, a flat tan block and a gold pill, which made parallel choices
   look like unrelated things and made the gold one read as disabled. Emphasis
   now comes from a border and a tag, not from three different fills. */
.order-picks{
  display:grid;
  gap:var(--space-md);
  list-style:none;
  padding:0;
  margin:var(--space-2xl) 0 var(--space-xl);
  text-align:left;
}
.order-pick{
  display:grid;
  grid-template-columns:auto 1fr auto;
  align-items:center;
  gap:var(--space-lg);
  padding:var(--space-lg) var(--space-xl);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--radius-md);
  text-decoration:none;
  color:var(--brown-ink);
  transition:border-color var(--dur-fast) var(--ease-out),transform var(--dur-med) var(--ease-out),box-shadow var(--dur-med) var(--ease-out);
}
.order-pick:hover,
.order-pick:focus-visible{
  border-color:var(--gold-deep);
  transform:translateY(-2px);
  box-shadow:0 14px 32px -20px rgba(51,36,26,.5);
}
.order-pick--primary{
  border-color:var(--red);
  border-width:2px;
  background:linear-gradient(180deg,var(--gold-tint),var(--paper));
}
.order-pick__icon{
  display:grid;
  place-items:center;
  width:48px;
  height:48px;
  flex:none;
  border-radius:var(--radius-pill);
  background:var(--gold-tint);
  color:var(--gold-deep);
}
.order-pick--primary .order-pick__icon{
  background:var(--red);
  color:#FFFFFF;
}
.order-pick__text{display:grid;gap:.25rem;min-width:0}
.order-pick__title{
  font-family:var(--font-display);
  font-weight:600;
  font-size:1.0625rem;
  line-height:1.3;
  display:flex;
  align-items:center;
  flex-wrap:wrap;
  gap:.5rem;
}
.order-pick__tag{
  font-family:var(--font-body);
  /* 12px is the floor tools/check-pages.mjs enforces sitewide. 11px tripped it. */
  font-size:.75rem;
  font-weight:700;
  letter-spacing:.06em;
  text-transform:uppercase;
  padding:.2rem .5rem;
  border-radius:var(--radius-pill);
  background:var(--red);
  color:#FFFFFF;
}
.order-pick__sub{
  font-size:var(--fs-label);
  color:var(--brown-soft);
  line-height:1.5;
}
.order-pick__go{
  flex:none;
  color:var(--gold-deep);
  transition:transform var(--dur-med) var(--ease-out);
}
.order-pick:hover .order-pick__go{transform:translateX(4px)}
@media (max-width:560px){
  .order-pick{
    grid-template-columns:auto 1fr;
    padding:var(--space-lg);
    gap:var(--space-md);
  }
  .order-pick__go{display:none}
}
@media (prefers-reduced-motion:reduce){
  .order-pick,.order-pick__go{transition:none}
  .order-pick:hover{transform:none}
  .order-pick:hover .order-pick__go{transform:none}
}

/* ---- Contact form status --------------------------------- */
/* No coloured left bar. A thick accent border down one edge of a notice is the
   Bootstrap alert pattern and reads as generated UI, which is the exact thing
   this build has been pulling away from. The tonal panel does the work on its
   own: gold-tint against the paper the form sits on is already a clear enough
   step, and it is the same tonal layering the rest of the site uses instead of
   drawing lines around things. */
.form-status{
  margin-top:var(--space-lg);
  padding:var(--space-lg) var(--space-xl);
  border-radius:var(--radius-md);
  background:var(--gold-tint);
  color:var(--brown-ink);
  font-size:var(--fs-label);
  line-height:1.55;
  max-width:52ch;
}
.form-status:focus-visible{outline:2px solid var(--gold-deep);outline-offset:3px}

/* ---- Reviews ------------------------------------------------ */
/* A horizontal rail you can scroll, drag, or step through with the arrows.
   Scroll-snap does the paging so the whole thing still works with JS off;
   the arrows and the counter are enhancement on top. */
.testi-block{
  position:relative;
}
.testi-track{
  display:flex;
  gap:var(--space-lg);
  list-style:none;
  padding:var(--space-sm) 0 var(--space-lg);
  margin:0;
  overflow-x:auto;
  scroll-snap-type:x mandatory;
  scroll-padding-inline-start:0;
  scrollbar-width:none;
  /* room for the lifted card shadow so it is not clipped by the scroller */
  padding-inline:2px;
}
.testi-track::-webkit-scrollbar{display:none}
.testi-track:focus-visible{
  outline:2px solid var(--gold-deep);
  outline-offset:4px;
  border-radius:var(--radius-md);
}
.testi-card{
  flex:0 0 min(100%, 380px);
  scroll-snap-align:start;
  display:flex;
  flex-direction:column;
  gap:var(--space-lg);
  padding:var(--space-xl);
  background:var(--paper);
  border-radius:var(--radius-md);
  box-shadow:0 10px 30px -20px rgba(51,36,26,.5);
  /* a hair off square, alternating, so a row reads hand-placed */
  transform:rotate(-.35deg);
  transition:transform .6s var(--ease-out),box-shadow .6s var(--ease-out);
}
.testi-card:nth-child(even){transform:rotate(.4deg)}
.testi-card:hover{
  transform:rotate(0deg) translateY(-3px);
  box-shadow:0 18px 40px -22px rgba(51,36,26,.55);
}
.testi-card__quote{
  margin:0;
  font-family:var(--font-display);
  font-size:1.0625rem;
  line-height:1.55;
  color:var(--brown-ink);
  quotes:none;
}
.testi-card__quote::before{
  content:"\201C";
  display:block;
  font-size:2.5rem;
  line-height:.6;
  color:var(--gold);
  margin-bottom:.25rem;
}
.testi-card__by{
  margin-top:auto;
  display:flex;
  align-items:center;
  gap:var(--space-md);
}
/* Monograms, not photographs. We hold no rights to these people's profile
   pictures, and a stock or generated face beside a real name and a real quote
   would be inventing someone's likeness. */
.testi-avatar{
  position:relative;
  flex:none;
  width:44px;
  height:44px;
  border-radius:var(--radius-pill);
  display:grid;
  place-items:center;
  background:var(--brown-ink);
  color:var(--paper);
  font-family:var(--font-display);
  font-weight:600;
  font-size:.9375rem;
  letter-spacing:.02em;
}
/* deterministic colour rotation so a rail of them never looks like a template */
.testi-card:nth-child(5n+2) .testi-avatar{background:var(--gold-deep);color:var(--paper)}
.testi-card:nth-child(5n+3) .testi-avatar{background:var(--brown-soft);color:var(--paper)}
.testi-card:nth-child(5n+4) .testi-avatar{background:var(--gold);color:var(--brown-ink)}
.testi-card:nth-child(5n+5) .testi-avatar{background:var(--cream-deep);color:var(--brown-ink)}
.testi-avatar__badge{
  position:absolute;
  right:-3px;
  bottom:-3px;
  width:19px;
  height:19px;
  border-radius:var(--radius-pill);
  background:var(--paper);
  color:var(--gold-deep);
  display:grid;
  place-items:center;
  box-shadow:0 1px 4px rgba(51,36,26,.25);
}
.testi-card__id{
  display:grid;
  gap:1px;
  font-size:var(--fs-label);
  min-width:0;
}
.testi-card__id b{color:var(--brown-ink)}
.testi-card__id a{
  color:var(--brown-soft);
  text-underline-offset:3px;
  display:inline-flex;
  align-items:center;
  min-height:24px;
}
.testi-card__id a:hover{color:var(--gold-deep)}
.testi-nav{
  display:flex;
  align-items:center;
  gap:var(--space-md);
  margin-top:var(--space-md);
}
.testi-btn{
  width:44px;
  height:44px;
  display:grid;
  place-items:center;
  border-radius:var(--radius-pill);
  border:1px solid var(--line-strong);
  background:var(--paper);
  color:var(--brown-ink);
  cursor:pointer;
  transition:background var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),opacity var(--dur-fast) var(--ease-out);
}
.testi-btn:hover{background:var(--gold-tint)}
.testi-btn:focus-visible{outline:2px solid var(--gold-deep);outline-offset:3px}
.testi-btn[disabled]{opacity:.35;cursor:default}
.testi-btn[disabled]:hover{background:var(--paper)}
.testi-count{
  margin:0;
  font-size:var(--fs-label);
  color:var(--brown-soft);
  font-variant-numeric:tabular-nums;
}
@media (prefers-reduced-motion:reduce){
  .testi-card,
  .testi-card:nth-child(even),
  .testi-card:hover{transform:none;transition:none}
  .testi-track{scroll-behavior:auto}
}


/* ---- Shop map ----------------------------------------------- */
/* Ships as an image. The interactive Google embed only loads if a visitor
   asks for it, so the page carries no third-party iframe or cookies by
   default, and the map is still visible with no network at all. */
.shopmap{
  margin:var(--space-2xl) 0 var(--space-lg);
  position:relative;
}
.shopmap__frame{
  display:block;
  position:relative;
  width:100%;
  padding:0;
  border:0;
  border-radius:var(--radius-md);
  overflow:hidden;
  background:var(--cream);
  cursor:pointer;
  box-shadow:0 14px 36px -24px rgba(51,36,26,.55);
  isolation:isolate;
}
.shopmap__frame img{
  display:block;
  width:100%;
  height:auto;
  transition:transform .9s var(--ease-out);
}
.shopmap__frame:hover img{transform:scale(1.02)}
.shopmap__frame:focus-visible{
  outline:2px solid var(--gold-deep);
  outline-offset:3px;
}
.shopmap__pin{
  position:absolute;
  z-index:2;
  /* the anchor point is the tip of the pin, not its centre */
  transform:translate(-50%,-100%);
  filter:drop-shadow(0 4px 6px rgba(51,36,26,.45));
  pointer-events:none;
}
.shopmap__hint{
  position:absolute;
  z-index:2;
  right:var(--space-md);
  bottom:var(--space-md);
  display:inline-flex;
  align-items:center;
  min-height:36px;
  padding:.4rem .9rem;
  border-radius:var(--radius-pill);
  background:color-mix(in srgb,var(--paper) 94%,transparent);
  color:var(--brown-ink);
  font-size:var(--fs-label);
  font-weight:600;
  box-shadow:0 2px 10px rgba(51,36,26,.18);
}
.shopmap iframe{
  display:block;
  width:100%;
  aspect-ratio:2/1;
  border:0;
  border-radius:var(--radius-md);
}
.shopmap__credit{
  margin-top:var(--space-sm);
  font-size:.8125rem;
  color:var(--brown-soft);
}
.on-ink .shopmap__credit{color:rgba(255,252,245,.65)}
.shopmap__actions{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-md);
  margin-bottom:var(--space-3xl);
}
@media (prefers-reduced-motion:reduce){
  .shopmap__frame img,
  .shopmap__frame:hover img{transition:none;transform:none}
}

/* ---- Bagel care intro --------------------------------------- */
/* Text left, the shop's own do-not-microwave sign to its right. The sign was
   previously nested inside the section head, which stacked it under the copy
   and left it reading as an afterthought rather than as the warning it is. */
.care-intro{
  display:grid;
  gap:var(--space-xl);
  align-items:center;
  margin-bottom:var(--space-3xl);
}
@media (min-width:900px){
  .care-intro{
    grid-template-columns:minmax(0,1fr) auto;
    gap:var(--space-4xl);
  }
}
.care-intro__text{display:grid;gap:var(--space-md)}
.care-intro__text h2{color:var(--paper)}
.care-intro__text p:not(.eyebrow){color:rgba(255,252,245,.76);max-width:46ch}
.care-intro__sign{
  width:min(260px,60%);
  height:auto;
  border-radius:var(--radius-md);
  justify-self:start;
  box-shadow:0 16px 40px -14px rgba(0,0,0,.55);
  /* a slight tilt so a flat graphic reads as a sign taped to the case */
  transform:rotate(-2.5deg);
}
@media (min-width:900px){
  .care-intro__sign{justify-self:end;width:260px}
}
@media (prefers-reduced-motion:reduce){
  .care-intro__sign{transform:none}
}

/* ---- Hero lockup -------------------------------------------- */
/* Order of size: the shop's name first and largest, the promise under it,
   the time-of-day kicker above both as the smallest thing.

   line-height:1 on the h1 is load bearing. Its children are block level, and
   the character splitter can leave collapsible whitespace between them; at a
   72px font that whitespace was rendering as an anonymous line box 73px tall
   and opening a hole in the middle of the lockup. With line-height:1 any
   stray box is a single ineffective line rather than a visible gap, and each
   child states its own leading. */
.hero__title{
  line-height:1;
  margin:0;
}
.hero__name{
  display:block;
  font-family:var(--font-cursive);
  font-weight:400;
  font-style:normal;
  font-size:clamp(3rem, 1.6rem + 5.4vw, 5.9rem);
  line-height:.9;
  text-wrap:balance;
  letter-spacing:.005em;
  color:var(--brown-ink);
  /* script descenders need room the roman line does not */
  padding-block:.06em;
  text-shadow:0 0 34px rgba(217, 160, 61, .3);
}
.hero__tag{
  display:block;
  font-family:var(--font-display);
  font-weight:600;
  font-size:clamp(1.5rem, 1.1rem + 1.5vw, 2.35rem);
  line-height:1.18;
  letter-spacing:-.02em;
  max-width:17ch;
  color:var(--brown-soft);
  margin-top:var(--space-sm);
}


/* Her logo, sat on the right shoulder of the hero photograph. It overlaps the
   arch deliberately so the mark reads as applied to the photo, like a stamp
   on a bakery box, rather than as another floating element. */
.hero__seal{
  position:absolute;
  z-index:3;
  top:8%;
  right:-6%;
  width:clamp(84px, 11vw, 148px);
  height:auto;
  filter:drop-shadow(0 10px 22px rgba(51,36,26,.34));
  animation:seal-float 7s ease-in-out infinite;
}
@keyframes seal-float{
  0%,100%{transform:translateY(0) rotate(-4deg)}
  50%{transform:translateY(-9px) rotate(-1deg)}
}
@media (max-width:1023px){
  .hero__seal{top:4%;right:2%}
}
@media (prefers-reduced-motion:reduce){
  .hero__seal{animation:none;transform:rotate(-4deg)}
}

/* ---- Glow and contrast -------------------------------------- */
/* The palette was cream on cream almost everywhere, which reads calm at a
   glance and bland after three seconds. Two changes fix it without repainting
   the brand:
     1. a warm glow on display type, tied to the same pointer proximity that
        drives the weight, so the light follows your hand
     2. genuinely dark ground under the hero and the section heads, so the
        cream sections have something to be light AGAINST */

/* The glow sits behind the glyph, never on it, so it can never muddy the
   letterform's edge the way a text-shadow on body copy does. */
.flex-ready .fx{
  position:relative;
  /* --glow is written per character from JS, 0 at rest */
  text-shadow:
    0 0 calc(var(--glow, 0) * 18px) rgba(217, 160, 61, calc(var(--glow, 0) * .55)),
    0 0 calc(var(--glow, 0) * 44px) rgba(217, 160, 61, calc(var(--glow, 0) * .28));
  transition:font-variation-settings .28s var(--ease-out), text-shadow .28s var(--ease-out);
}
/* On ink the glow is the point, so it runs hotter and cooler-white at the core. */
.on-ink .flex-ready .fx{
  text-shadow:
    0 0 calc(var(--glow, 0) * 14px) rgba(255, 233, 187, calc(var(--glow, 0) * .75)),
    0 0 calc(var(--glow, 0) * 40px) rgba(217, 160, 61, calc(var(--glow, 0) * .45));
}

/* The cursive accents carry a permanent, very soft glow. They are the one
   place on the site where a little theatre is appropriate. */
.hero__aside,
.script-flourish{
  text-shadow:0 0 26px rgba(217, 160, 61, .32);
}
.on-ink .script-flourish{
  text-shadow:0 0 30px rgba(255, 233, 187, .38);
}

/* Gold rules under section eyebrows gain a faint bloom so the accent colour
   actually registers as light rather than as a printed line. */
.on-ink .eyebrow::before{
  box-shadow:0 0 12px rgba(217, 160, 61, .8);
}

/* ---- Contrast ------------------------------------------------ */
/* A deep band that can sit between two cream sections and give the page a
   real dark/light rhythm. Uses the existing ink token, so no new colour
   enters the palette. */
.section.on-ink{
  position:relative;
  isolation:isolate;
}
/* a slow warm wash across ink sections so they are not flat black-brown */
.section.on-ink::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:-1;
  background:
    radial-gradient(120% 90% at 15% 0%, rgba(217, 160, 61, .16), transparent 60%),
    radial-gradient(90% 80% at 100% 100%, rgba(196, 30, 58, .12), transparent 65%);
  pointer-events:none;
}

/* Photographs on cream were floating; a real shadow anchors them and adds the
   tonal depth the flat layout was missing. */
.story__media,
.page-hero__figure,
.signature-tile__media,
.video-frame{
  box-shadow:0 18px 44px -18px rgba(51, 36, 26, .45);
}

/* The gold accent was doing almost nothing at small sizes. Give the eyebrow
   rule real presence. */
.eyebrow::before{
  height:2px;
}

/* Primary buttons get a warm lift so the single most important action on the
   page stops reading as flat fill. */
.btn-primary{
  box-shadow:0 10px 24px -10px rgba(196, 30, 58, .65);
}
.btn-primary:hover{
  box-shadow:0 14px 30px -10px rgba(196, 30, 58, .8);
}

@media (prefers-reduced-motion:reduce){
  .flex-ready .fx{transition:none}
}

/* ---- Order paths -------------------------------------------- */
/* The old site made pickup and delivery two separate nav destinations. That
   distinction matters to somebody sitting in a car park, so it gets two real
   cards here rather than living only behind the header modal. */
.order-paths{
  display:grid;
  gap:var(--space-xl);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));
  list-style:none;
  padding:0;
}
.order-path{
  display:grid;
  align-content:start;
  gap:var(--space-sm);
  padding:var(--space-xl);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:var(--radius-lg);
}
.order-path__kicker{
  font-size:var(--fs-label);
  letter-spacing:.09em;
  text-transform:uppercase;
  color:var(--gold-deep);
  font-weight:700;
}
.order-path__name{
  font-family:var(--font-display);
  font-size:1.3125rem;
  line-height:1.25;
  color:var(--brown-ink);
}
.order-path__body{color:var(--brown-soft);max-width:44ch}
.order-path .btn{justify-self:start;margin-top:var(--space-sm)}
.order-path__note{
  font-size:.8125rem;
  color:var(--brown-soft);
}

/* ---- Jax Comedy House --------------------------------------- */
/* Its own section, on ink, with more air than anything around it. The room is
   a memorial as much as a venue, so the layout is deliberately quiet: one
   photograph, one column of text, nothing ornamental competing with it. */
.jax__grid{
  display:grid;
  gap:var(--space-2xl);
  align-items:center;
}
@media (min-width:900px){
  .jax__grid{grid-template-columns:420px 1fr;gap:var(--space-4xl)}
}
.jax__poster{
  width:100%;
  height:auto;
  border-radius:var(--radius-lg);
  box-shadow:var(--shadow-lg);
}
.jax__text{display:grid;gap:var(--space-md)}
.jax__text .eyebrow{color:var(--gold)}
.jax__text h2{color:var(--paper)}
.jax__lede{
  font-size:1.125rem;
  color:rgba(255,252,245,.9);
  max-width:52ch;
}
.jax__text p{color:rgba(255,252,245,.74);max-width:58ch}
.jax__meta{
  font-size:.9375rem;
  padding-top:var(--space-md);
  border-top:1px solid rgba(255,252,245,.16);
}
.jax__actions{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-sm);
  margin-top:var(--space-sm);
}

/* ---- Filter bar -------------------------------------------- */
.filter-bar{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-sm);
  margin-bottom:var(--space-2xl);
}
.filter-bar button{
  min-height:44px;
  padding:.55rem 1rem;
  border-radius:var(--radius-pill);
  border:1px solid var(--line-strong);
  background:var(--paper);
  color:var(--brown-ink);
  font-family:var(--font-body);
  font-size:var(--fs-label);
  font-weight:600;
  cursor:pointer;
  transition:background var(--dur-fast) var(--ease-out),color var(--dur-fast) var(--ease-out),border-color var(--dur-fast) var(--ease-out);
}
.filter-bar button:hover{background:var(--gold-tint);border-color:transparent}
.filter-bar button.is-current{
  background:var(--brown-ink);
  border-color:var(--brown-ink);
  color:var(--paper);
}
.filter-count{
  font-size:var(--fs-label);
  color:var(--brown-soft);
  margin-bottom:var(--space-lg);
}

/* ---- Lightbox ---------------------------------------------- */
.lightbox{
  padding:0;
  border:0;
  background:transparent;
  width:100%;
  max-width:100%;
  height:100%;
  max-height:100%;
  margin:auto;
  overflow:hidden;
}
.lightbox::backdrop{
  background:rgba(28,19,13,.92);
  backdrop-filter:blur(3px);
}
.lightbox__inner{
  position:absolute;
  inset:0;
  display:grid;
  grid-template-rows:1fr auto;
  place-items:center;
  padding:clamp(12px,3vw,40px);
  gap:var(--space-md);
  pointer-events:none;
}
.lightbox__inner > *{pointer-events:auto}
.lightbox img{
  max-width:min(1100px,92vw);
  max-height:76vh;
  width:auto;
  height:auto;
  object-fit:contain;
  border-radius:var(--radius-md);
  box-shadow:var(--shadow-lg);
  background:var(--brown-ink);
}
.lightbox__bar{
  display:flex;
  align-items:center;
  gap:var(--space-md);
  color:var(--paper);
  font-size:var(--fs-label);
}
.lightbox__cap{
  max-width:56ch;
  text-align:center;
  color:rgba(255,252,245,.82);
}
.lightbox__btn{
  width:44px;
  height:44px;
  display:grid;
  place-items:center;
  border-radius:var(--radius-pill);
  border:1px solid rgba(255,252,245,.28);
  background:rgba(255,252,245,.08);
  color:var(--paper);
  cursor:pointer;
  transition:background var(--dur-fast) var(--ease-out);
}
.lightbox__btn:hover{background:rgba(255,252,245,.2)}
.lightbox__close{
  position:absolute;
  top:clamp(12px,3vw,28px);
  right:clamp(12px,3vw,28px);
}

/* ---- Marquee ----------------------------------------------- */
.marquee{
  display:flex;
  gap:var(--space-2xl);
  overflow:hidden;
  padding-block:var(--space-xl);
  /* full-bleed band: it follows a .container, so it supplies its own top
     separation rather than inheriting the container bottom padding */
  margin-top:var(--space-4xl);
  border-block:1px solid var(--line);
  /* fade the ends so the loop never visibly pops */
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
}
.marquee__track{
  display:flex;
  align-items:center;
  gap:var(--space-2xl);
  flex:none;
  /* slow on purpose: a fast logo band reads as a conference sponsor reel */
  animation:marquee 72s linear infinite;
}
.marquee:hover .marquee__track{animation-play-state:paused}
.marquee__item{
  display:inline-flex;
  align-items:center;
  gap:var(--space-md);
  white-space:nowrap;
  font-family:var(--font-display);
  font-size:1.125rem;
  color:var(--brown-soft);
}
.marquee__item::after{
  content:"";
  width:7px;
  height:7px;
  border-radius:var(--radius-pill);
  background:var(--gold);
}
@keyframes marquee{
  from{transform:translateX(0)}
  to{transform:translateX(calc(-100% - var(--space-2xl)))}
}

/* ---- Flavor tiles (replaces the naked pill wall) ------------ */
/* The old chip row put 12 unlabelled pills in a ragged two-line block with
   no hierarchy and no photography, which is exactly the "unorganized
   buttons" complaint. Same information, as a photographed grid. */
.flavor-grid{
  display:grid;
  gap:var(--space-lg);
  grid-template-columns:repeat(auto-fill,minmax(min(100%,150px),1fr));
  list-style:none;
  padding:0;
}
.flavor{
  display:grid;
  gap:var(--space-sm);
  text-align:center;
}
.flavor__media{
  aspect-ratio:1;
  border-radius:var(--radius-md);
  overflow:hidden;
  background:var(--gold-tint);
  position:relative;
  isolation:isolate;
}
.flavor__media img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
  transition:transform .7s var(--ease-out);
}
.flavor:hover .flavor__media img{transform:scale(1.04)}
.flavor__name{
  font-family:var(--font-display);
  font-weight:600;
  font-size:.9375rem;
  color:var(--brown-ink);
  line-height:1.3;
}
.on-ink .flavor__name{color:var(--paper)}
/* Flavors we have no photograph of get a drawn bagel rather than the name
   printed twice. The caption below every tile is the single source of the
   name, so the grid keeps one rhythm whether a tile has a photo or not. */
.flavor--text .flavor__media{
  display:grid;
  place-items:center;
  background:var(--paper);
  border:1px solid var(--line);
}
/* The shop's own mark stands in until each flavour is photographed.
   object-fit is contain, not the cover the photo tiles use, so the logo is
   never cropped, and it is held well inside the tile so it reads as a
   placeholder mark rather than a badly cropped photo. */
.flavor--text .flavor__media img{
  width:64%;
  height:auto;
  object-fit:contain;
  opacity:.82;
  transition:opacity var(--dur-med) var(--ease-out),transform var(--dur-med) var(--ease-out);
}
.flavor--text:hover .flavor__media img{
  opacity:1;
  transform:scale(1.05);
}

/* ---- Poster wall (real event flyers) ----------------------- */
.poster-grid{
  display:grid;
  gap:var(--space-lg);
  grid-template-columns:repeat(auto-fill,minmax(min(100%,210px),1fr));
  list-style:none;
  padding:0;
}
.poster{
  display:block;
  /* form controls shrink-wrap in Chrome even at display:block, which
     collapsed these to 14x4 inside their grid cells */
  width:100%;
  padding:0;
  border-radius:var(--radius-md);
  overflow:hidden;
  background:var(--paper);
  border:1px solid var(--line);
  box-shadow:var(--shadow-sm);
  transition:transform var(--dur-med) var(--ease-out),box-shadow var(--dur-med) var(--ease-out);
  cursor:zoom-in;
}
.poster:hover,
.poster:focus-visible{
  transform:translateY(-4px);
  box-shadow:var(--shadow-md);
}
.poster img{
  width:100%;
  height:auto;
  display:block;
}

/* ---- Community partner strip ------------------------------- */
.partner{
  display:inline-flex;
  align-items:center;
  height:72px;
}
.partner img{
  max-height:72px;
  width:auto;
  /* partner marks are every colour under the sun; a light knock-back keeps
     the strip calm without erasing brands entirely */
  opacity:.88;
  filter:saturate(.92);
  transition:opacity var(--dur-fast) var(--ease-out),filter var(--dur-fast) var(--ease-out);
}
.marquee:hover .partner img,
.partner:hover img{
  opacity:1;
  filter:none;
}

/* ---- Gallery tile (filterable, lightboxed) ----------------- */
.tile-grid{
  display:grid;
  gap:var(--space-md);
  grid-template-columns:repeat(auto-fill,minmax(min(100%,220px),1fr));
  list-style:none;
  padding:0;
}
.tile{
  position:relative;
  display:block;
  width:100%;
  padding:0;
  border:0;
  border-radius:var(--radius-md);
  overflow:hidden;
  background:var(--gold-tint);
  aspect-ratio:1;
  cursor:zoom-in;
  isolation:isolate;
}
.tile img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
  transition:transform .8s var(--ease-out),filter .5s var(--ease-out);
}
.tile:hover img,
.tile:focus-visible img{transform:scale(1.035)}
.tile::after{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(to top,rgba(51,36,26,.5),transparent 55%);
  opacity:0;
  transition:opacity var(--dur-med) var(--ease-out);
}
.tile:hover::after,
.tile:focus-visible::after{opacity:1}
.tile__zoom{
  position:absolute;
  right:var(--space-sm);
  bottom:var(--space-sm);
  z-index:2;
  width:34px;
  height:34px;
  display:grid;
  place-items:center;
  border-radius:var(--radius-pill);
  background:color-mix(in srgb,var(--paper) 90%,transparent);
  color:var(--brown-ink);
  opacity:0;
  transform:translateY(6px);
  transition:opacity var(--dur-med) var(--ease-out),transform var(--dur-med) var(--ease-out);
}
.tile:hover .tile__zoom,
.tile:focus-visible .tile__zoom{opacity:1;transform:none}
.tile--wide{grid-column:span 2;aspect-ratio:2}
@media (max-width:520px){
  .tile--wide{grid-column:span 1;aspect-ratio:1}
}

/* ============================================================
   Print
   Aimed squarely at menu.html: a shop gets asked to print the menu,
   and a customer prints it to stick on a fridge. Everything that is
   navigation, decoration or interaction comes out; the type stays.
   Backgrounds are dropped so it does not drink a colour cartridge.
   ============================================================ */
@media print{
  .site-header,
  .mobile-bar,
  .mobile-nav,
  .order-modal,
  .chatbot,
  .menu-nav,
  .skip-link,
  .site-footer__curve,
  .hero__curve,
  .cta-band,
  .page-hero__aside,
  .crumbs,
  .reel-rail,
  .video-frame{
    display:none !important;
  }
  .on-ink::after{
    display:none;
  }
  body{
    background:#fff;
    color:#000;
    padding-bottom:0;
  }
  .on-cream,.on-cream-deep,.on-paper,.on-ink,.on-gold-tint{
    background:#fff !important;
    color:#000 !important;
  }
  .on-ink h1,.on-ink h2,.on-ink h3,.on-ink p,
  .on-ink .menu-item__name,.on-ink .menu-build__body{
    color:#000 !important;
  }
  .section,.menu-cat,.page-hero{
    padding-block:12pt;
  }
  .menu-cat{
    break-inside:avoid;
  }
  .menu-item,.menu-build__step{
    break-inside:avoid;
  }
  .menu-item__price{
    color:#000;
  }
  .menu-list{
    grid-template-columns:repeat(2,minmax(0,1fr));
  }
  a[href^="http"]::after{
    /* a printed page cannot be clicked, so spell the destination out */
    content:" (" attr(href) ")";
    font-size:9pt;
    word-break:break-all;
  }
  a[href^="tel:"]::after,
  a[href^="#"]::after{
    content:"";
  }
  .site-footer{
    background:#fff !important;
    color:#000 !important;
    border-top:1pt solid #000;
  }
  .footer-grid{
    display:block;
  }
}

/* ============================================================
   Reduced motion. Stays last in the file so it always wins.
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  /* the motion layer, switched off wholesale */
  .settle-ready,
  .settle-in{
    opacity:1;
    transform:none;
    transition:none;
  }
  [data-parallax]{transform:none}
  [data-magnetic]{transition:none}
  .marquee__track{animation:none}
  .tile img,
  .flavor__media img,
  .poster{transition:none}
  .tile:hover img,
  .flavor:hover .flavor__media img{transform:none}
  .poster:hover{transform:none}
  html.js [data-reveal],
  html.js [data-reveal].is-revealed{
    opacity:1;
    transform:none;
    transition:none;
  }
  .reel-card img,
  .reel-card video,
  .photo-grid img,
  .chatbot__toggle{
    transition:none;
  }
  .reel-card:hover img,
  .reel-card:focus-visible img,
  .reel-card:hover video,
  .photo-grid figure:hover img,
  .chatbot__toggle:hover{
    transform:none;
  }
}
