/* Pink Owl Cafe — styles.css
   Mobile first. Base styles are for 320px; breakpoints add up from 390, 768, 1024, 1440. */

/* ---------- tokens ---------- */
:root {
  --ink: #2A1A1C;
  --pink: #E62988;
  --blush: #FDCEE5;
  --brick: #E8DCC4;
  /* a third of the way from white to --brick. The Meet Alex band needs to read as a
     warm panel against --marble without the weight --brick carries over a whole band. */
  --cream: #FAF5EA;
  --marble: #F7F5F3;
  --gold: #C9A227;
  --white: #FEFEFE;

  --ink-2: rgba(42, 26, 28, .72);
  --line: rgba(42, 26, 28, .14);
  --line-strong: rgba(42, 26, 28, .32);
  --pink-hover: #CF2079;
  --ink-hover: #3E2A2D;

  --radius: 8px;
  --header-h: 64px;
  --gutter: clamp(1rem, 4vw, 3rem);
  --wrap: 1280px;
  --sect: clamp(3.5rem, 6vw + 1rem, 7rem);

  --font-display: "Playfair Display", Georgia, "Times New Roman", serif;
  --font-body: Archivo, "Helvetica Neue", Arial, sans-serif;

  --fs-display: clamp(2.5rem, 1.75rem + 3vw, 4.5rem);
  --fs-status: clamp(1.75rem, 1.25rem + 2.2vw, 3rem);
  --fs-h3: clamp(1.625rem, 1.25rem + 1.4vw, 2.25rem);
  --fs-navlink: clamp(2.25rem, 1.5rem + 4vw, 3rem);
}
@media (min-width: 1024px) {
  :root { --header-h: 72px; }
}

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html {
  color-scheme: light;
  scroll-padding-top: var(--header-h);
  -webkit-text-size-adjust: 100%;
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
body {
  margin: 0;
  background: var(--marble);
  color: var(--ink);
  font: 400 1rem/1.55 var(--font-body);
  overflow-x: hidden;
}
body.nav-open {
  overflow: hidden;
  position: fixed;
  width: 100%;
}
img, video, svg { display: block; max-width: 100%; }
img { height: auto; }
h1, h2, h3, h4, p, ul, ol, dl, dd, figure, address { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: inherit; text-decoration-color: var(--pink); text-underline-offset: .15em; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
:focus-visible { outline: 3px solid var(--pink); outline-offset: 3px; }
.hero :focus-visible,
.site-footer :focus-visible { outline-color: var(--white); }
.btn--pink:focus-visible { outline-color: var(--ink); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: var(--gutter); top: -100px; z-index: 2000;
  background: var(--ink); color: var(--white); padding: .75rem 1rem;
  border-radius: var(--radius); text-decoration: none; font-weight: 700;
}
.skip:focus { top: .5rem; }

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.section { padding-block: var(--sect); }

.h-display {
  font: 900 var(--fs-display)/1.02 var(--font-display);
  letter-spacing: -.01em;
  color: var(--pink);
  padding-bottom: .75rem;
  border-bottom: 1px solid var(--gold);
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 48px; padding: .75rem 1.5rem;
  border-radius: var(--radius); border: 2px solid transparent;
  font-weight: 700; line-height: 1.2; text-decoration: none;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.btn--pink { background: var(--pink); color: var(--white); }
.btn--pink:hover { background: var(--pink-hover); }
.btn--ink { background: var(--ink); color: var(--white); }
.btn--ink:hover { background: var(--ink-hover); }
.btn--outline { border-color: var(--ink); color: var(--ink); }
.btn--outline:hover { background: var(--blush); }
.btn--ghost { border-color: var(--white); color: var(--white); background: transparent; }
.btn--ghost:hover { background: var(--white); color: var(--ink); }
.btn--icon { padding-right: 1.25rem; }
.btn__icon { width: 20px; height: 20px; flex: none; }

/* ---------- header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 1001;
  background: var(--marble);
  border-bottom: 1px solid var(--line);
}
.site-header__bar {
  display: flex; align-items: center; gap: .5rem;
  height: var(--header-h);
  max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter);
}
.brand {
  display: flex; align-items: center;
  margin-right: auto; min-height: 44px; min-width: 0; text-decoration: none;
}
/* two files, not one with a filter: the owner supplied a pink and a white logo, and a real
   white asset beats brightness(0) invert(1) on a mark with any internal detail */
.brand { position: relative; }
/* the images are decoration inside the link; the hidden one would otherwise still be the
   element under the cursor */
.brand__wordmark { display: block; width: min(48vw, 210px); max-width: 100%; height: auto; pointer-events: none; }
.brand__wordmark--white {
  position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  opacity: 0;
}
.brand__wordmark--pink, .brand__wordmark--white { transition: opacity .32s ease; }

.lang {
  display: flex; overflow: hidden;
  border: 1px solid var(--line-strong); border-radius: var(--radius);
}
.lang__btn {
  min-width: 44px; min-height: 44px; padding: 0 .75rem;
  font-weight: 700; font-size: .875rem;
  transition: background-color .15s ease, color .15s ease;
}
.lang__btn.is-active { background: var(--pink); color: var(--white); }
.lang__btn:not(.is-active):hover { background: var(--blush); }


/* One list, two homes: stacked in the drawer below 1024, inline in the bar above it. */
.social { display: flex; align-items: center; gap: .15rem; list-style: none; }
.social__link {
  width: 40px; height: 40px; display: grid; place-items: center;
  color: var(--ink); border-radius: 50%;
  transition: color .15s ease, background-color .15s ease;
}
.social__link svg { width: 20px; height: 20px; }
.social__link:hover { color: var(--pink); background: var(--blush); }

/* ---------- drawer nav: full-width pink rows, order button on top ---------- */
/* drawer: order button and socials sit under the links and above the address */
.nav__actions {
  margin-top: 1.5rem;
  display: flex; align-items: center; flex-wrap: wrap; gap: .75rem 1rem;
}
.nav__actions .social { gap: .25rem; }
/* the bar copy of the order button; below 1024 the drawer one above is what shows */
.hdr__order { display: none; }
.nav__order {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 1rem;
  border: 2px solid var(--pink); border-radius: var(--radius);
  color: var(--pink); text-decoration: none;
  font: 700 .8125rem/1 var(--font-body); letter-spacing: .08em; text-transform: uppercase;
  transition: background-color .15s ease, color .15s ease;
}
.nav__order:hover { background: var(--pink); color: var(--white); }

.nav .nav__list { display: block; margin-top: 0; gap: 0; }
.nav .nav__list li + li { border-top: 1px solid var(--line); }
/* the rows run the full width of the drawer, so they bleed back over the gutter padding */
.nav .nav__link {
  display: block; width: auto;
  margin-inline: calc(var(--gutter) * -1);
  padding: 1rem var(--gutter);
  font: 700 clamp(1.0625rem, 4.4vw, 1.3125rem)/1.25 var(--font-body);
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--pink); text-decoration: none;
}
.nav .nav__link:hover { background: var(--blush); color: var(--pink); }
.nav .nav__link[aria-current="page"] { background: var(--pink); color: var(--white); }
.nav__link--ext::after { content: ""; }

.nav__hrs { font-size: .9375rem; color: var(--ink-2); }
.nav__addr { margin-top: .5rem; font-size: .9375rem; line-height: 1.5; }

/* ---------- placeholder pages ---------- */
.page__lede { margin-top: 1.25rem; max-width: 52ch; font-size: 1.0625rem; line-height: 1.6; }
.page__back { margin-top: 1.75rem; }

.nav-toggle {
  width: 44px; height: 44px; display: grid; place-items: center; margin-right: -6px;
}
.nav-toggle svg { width: 26px; height: 26px; grid-area: 1 / 1; transition: opacity .2s ease; }
.nav-toggle .ico-close { opacity: 0; }
.nav-toggle[aria-expanded="true"] .ico-menu { opacity: 0; }
.nav-toggle[aria-expanded="true"] .ico-close { opacity: 1; }

/* nav: full-screen overlay below 1024, inline links above */
.nav {
  position: fixed; inset: var(--header-h) 0 0 0; z-index: 1000;
  background: var(--marble);
  padding: 1.5rem var(--gutter) 2rem;
  display: flex; flex-direction: column;
  overflow-y: auto;
  opacity: 0; visibility: hidden;
  transition: opacity .2s ease, visibility 0s linear .2s;
}
.nav.is-open { opacity: 1; visibility: visible; transition: opacity .2s ease, visibility 0s; }
.nav__list {
  display: flex; flex-direction: column;
  gap: clamp(.75rem, 3vh, 1.75rem);
  margin-top: clamp(.5rem, 4vh, 2.5rem);
}
.nav__link {
  display: inline-block; padding: .25rem 0;
  font: 900 var(--fs-navlink)/1.05 var(--font-display);
  letter-spacing: -.01em; text-decoration: none;
}
.nav__link:hover { color: var(--pink); }
.nav__link--ext::after {
  content: " ↗";
  font: 700 .45em/1 var(--font-body);
  vertical-align: .7em;
}
/* in the drawer the row sits under the links, before the hours block */
.nav .social { margin-top: 1.5rem; gap: .25rem; }
.nav .social__link { width: 44px; height: 44px; }

.nav__extra {
  margin-top: auto; padding-top: 1.5rem;
  border-top: 1px solid var(--gold);
  display: flex; flex-direction: column; gap: .25rem;
}
.nav__tel {
  display: inline-flex; align-items: center; min-height: 44px;
  font-weight: 700; font-size: 1.125rem; text-decoration: none;
}
.nav__today { color: var(--ink-2); font-size: .9375rem; }


/* ---------- home: the header starts over the video ----------
   Sticky, not fixed: the hero is pulled up under it by exactly the header's height, so
   nothing else on the page needs its offsets rethought (anchors, the drawer's inset, the
   sticky menu category headings all still measure from --header-h). */
.home .hero { margin-top: calc(-1 * var(--header-h)); height: 100svh; }
.home .site-header {
  background: transparent; border-bottom-color: transparent;
  transition: background-color .32s ease, border-color .32s ease;
}
.home .site-header.is-solid { background: var(--marble); border-bottom-color: var(--line); }

/* everything in the bar inverts while it is over the video, and eases back */
.home .brand__wordmark--pink,
.home .brand__wordmark--white,
.home .nav .nav__link,
.home .nav-toggle,
.home .hdr__order,
.home .lang,
.home .lang__btn { transition: color .32s ease, border-color .32s ease, filter .32s ease, background-color .15s ease; }

.home .site-header:not(.is-solid) .brand__wordmark--white { opacity: 1; }
.home .site-header:not(.is-solid) .brand__wordmark--pink { opacity: 0; }
/* NB: deliberately NOT applied to the drawer -- see the 1024 block. The drawer is an opaque
   panel, so white links there are invisible. */
.home .site-header:not(.is-solid) .nav-toggle { color: var(--white); }
.home .site-header:not(.is-solid) .hdr__order { color: var(--white); border-color: var(--white); }
.home .site-header:not(.is-solid) .hdr__order:hover { background: var(--white); color: var(--ink); }
.home .site-header:not(.is-solid) .lang { border-color: rgba(254, 254, 254, .7); }
.home .site-header:not(.is-solid) .lang__btn:not(.is-active) { color: var(--white); }

/* the drawer is opaque, so the bar above it has to be too */
.home .site-header.is-open { background: var(--marble); border-bottom-color: var(--line); }
.home .site-header.is-open .brand__wordmark--white { opacity: 0; }
.home .site-header.is-open .brand__wordmark--pink { opacity: 1; }
.home .site-header.is-open .nav-toggle,
.home .site-header.is-open .lang__btn:not(.is-active) { color: var(--ink); }
.home .site-header.is-open .lang { border-color: var(--line-strong); }

@media (prefers-reduced-motion: reduce) {
  .home .site-header, .home .brand__wordmark, .home .nav .nav__link,
  .home .nav-toggle, .home .hdr__order, .home .lang, .home .lang__btn { transition: none; }
}

/* ---------- hero: the counter on film, the mark, one quiet line ---------- */
.hero {
  position: relative;
  height: calc(100svh - var(--header-h));
  min-height: 520px; max-height: 820px;
  background: var(--ink); color: var(--white);
  overflow: hidden;
  display: grid; place-items: center;
}
.hero__video {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 50%;
  background: var(--ink);
  /* The clip is letterboxed: 2.37:1 picture inside a 16:9 frame, with 90px of black top and
     bottom (12.5% each). object-fit alone would show those bands on tall phone screens and
     thin slivers on desktop, so zoom past them — 1 / 0.75 = 1.333. .hero clips the overflow.
     The poster is the same 16:9 frame, so it lines up under identical treatment. */
  transform: scale(1.334);
}
/* flat scrim so the mark and the line read on the footage; a tint, not a gradient */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: rgba(42, 26, 28, .42);
}
.hero__content {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 1.25rem;
  padding: 0 var(--gutter) 96px;
  max-width: 40rem;
}
.hero__logo { width: clamp(150px, 42vw, 220px); height: auto; }
.hero__title {
  font: 900 clamp(1.125rem, 1rem + .8vw, 1.5rem)/1.3 var(--font-display);
  color: rgba(254, 254, 254, .9);
}
/* the two hero buttons stack on phones and sit side by side once there is room for both */
.hero__actions {
  margin-top: .25rem;
  display: flex; flex-wrap: wrap; justify-content: center; gap: .75rem;
}
.hero__cta { padding-inline: 1.75rem; }
.hero .ticker { z-index: 3; }

.ticker {
  position: absolute; bottom: 0; left: 50%;
  transform: translateX(-50%);
  width: max(100%, 1440px); height: auto;
  overflow: visible; pointer-events: none;
}
/* the SVG holds a fixed 1440-unit frame at every width, so on phones only a slice of the arc shows —
   step the type up there so it reads at the same visual size as on desktop (script.js re-measures on the flip) */
.ticker__text {
  font: 700 54px var(--font-body);
  letter-spacing: .2em; text-transform: uppercase;
  fill: var(--marble); fill-opacity: .85;
}
@media (min-width: 768px) {
  .ticker__text { font-size: 26px; }
}

/* ---------- hours: the status line is the heading; two plain columns, whitespace only ---------- */
.hours { padding: var(--sect) 0 0; }
.hours__status {
  font: 900 clamp(1.5rem, 1.1rem + 1.5vw, 2rem)/1.15 var(--font-display);
  letter-spacing: -.01em;
  color: var(--ink);
}
.hours__b { color: var(--pink); }
.hours__decks { display: grid; gap: 1.5rem 3rem; margin-top: 1.5rem; }
.hdeck__label {
  font: 700 .75rem/1 var(--font-body);
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--pink);
  margin-bottom: .5rem;
}
.hdeck__row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  padding: .3rem 0;
  font-size: .9375rem;
}
.hdeck__row dd { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.hdeck__note { color: var(--ink-2); font-size: .8125rem; }

/* ---------- menu ---------- */
.menu { padding-block: 2.5rem var(--sect); }

/* collapsed preview + Full Menu toggle. --menu-peek is how much shows before expanding;
   script.js reads it, so changing it here is enough. */
/* Tall enough for the whole seasonal category now that Drinks lead and its photo is square.
   Cutting a promotional block mid-item reads as broken rather than as a teaser. */
.menu__body { --menu-peek: 780px; }
@media (prefers-reduced-motion: no-preference) {
  .menu__body { transition: max-height .45s ease; }
}
.menu__body.is-collapsed { position: relative; }
/* fades the cut edge so the truncation reads as deliberate rather than clipped */
.menu__body.is-collapsed::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 160px;
  background: linear-gradient(to bottom, rgba(247, 245, 243, 0), var(--marble) 88%);
  pointer-events: none;
}
.menu__more { display: flex; justify-content: center; margin-top: 2rem; }
.menu__toggle[hidden] { display: none; }
.deck + .deck { margin-top: var(--sect); }
.deck__head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: .5rem 2rem;
  padding-bottom: .5rem; margin-bottom: 1.5rem;
  border-bottom: 3px solid var(--pink);
}
.deck__title {
  font: 900 var(--fs-display)/1 var(--font-display);
  color: var(--pink); letter-spacing: -.01em;
}
.deck__cols { display: grid; gap: 2.25rem; }
.deck__col { display: contents; }
.deck--tail { margin-top: var(--sect); }

/* category titles stick under the sticky header at every width, so you always know where you are */
.cat__title {
  position: sticky; top: var(--header-h); z-index: 2;
  background: var(--marble);
  padding: .6rem 0 .4rem;
  font: 900 var(--fs-h3)/1.1 var(--font-display);
  border-bottom: 1px solid var(--line-strong);
}
.cat__list { margin-top: .25rem; }
.item { padding: .8rem 0; border-top: 1px solid var(--line); }
.item:first-child { border-top: 0; }
.item__row { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
/* the auto margin keeps the price hard right once a glass joins the row as a third child;
   rows without a glass are unaffected */
.item__name { margin-right: auto; }
.item__name {
  font-weight: 700; font-size: .9375rem;
  text-transform: uppercase; letter-spacing: -.01em;
}
.item__price { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---------- loading screen ----------
   Hidden unless the inline head script adds .is-loading, so: no JS, reduced motion, or a
   second page view in the same session all get no overlay at all rather than one that has
   to be dismissed.

   z-index clears the sticky header (1001) and the newsletter popup (1500) so the ground is
   genuinely blank; it stays under the skip link (2000), which a keyboard user should still
   be able to reach. */
.ld {
  position: fixed; inset: 0; z-index: 1900;
  display: none; place-items: center;
  background: var(--marble);
  pointer-events: none;   /* never blocks a click, even mid-animation */
}
.is-loading .ld { display: grid; }
.ld__mark { position: relative; width: 264px; height: 264px; display: grid; place-items: center; }

.ld__arc { position: absolute; inset: 0; width: 264px; height: 264px; }
/* r=92 in a 200 box -> circumference 578.05. Rotated so the trace starts at the top. */
.ld__arc circle {
  fill: none; stroke: var(--pink); stroke-width: 4; stroke-linecap: round;
  shape-rendering: geometricPrecision;   /* keep the curve smooth rather than speed-rasterised */
  stroke-dasharray: 578.05; stroke-dashoffset: 578.05;
  transform: rotate(-90deg); transform-origin: 50% 50%;
}
.ld.is-arcing .ld__arc circle {
  /* the arc traces for the whole hold rather than finishing early and leaving dead time */
  transition: stroke-dashoffset 2900ms ease-in-out;
  stroke-dashoffset: 0;
  /* stroke-dashoffset cannot be composited -- every frame is a main-thread repaint -- so
     this only hints the raster. The real work for smoothness is done in script.js, which
     holds the hero video and the ticker until the overlay is gone. */
  will-change: stroke-dashoffset;
}

.ld__badge { position: relative; width: 200px; height: 200px; }
.ld__logo { display: block; width: 200px; height: 200px; }

/* fades and lifts. Plain ease both ways -- no bounce, no spring. */
.ld.is-exiting {
  opacity: 0; transform: translateY(-12px);
  transition: opacity 400ms ease, transform 400ms ease;
}

/* belt and braces: even if the class somehow survives, motion-averse users see nothing */
@media (prefers-reduced-motion: reduce) {
  .ld { display: none !important; }
}

/* ---------- the strata: hover a signature drink and its glass fills ----------
   The layers are the drink's own build, bottom to top, straight from its description.
   Hover-only motion, so it is not a fourth ambient moving thing -- and because hover does
   not exist on a phone, touch devices get the glass already filled: the point is seeing
   the strata, not the animation. */
.glass {
  flex: none; align-self: center;
  width: 18px; height: 25px; margin-right: .6rem;
  border: 1.5px solid var(--ink);
  border-radius: 2px 2px 6px 6px;
  overflow: hidden; background: var(--white);
}
.glass__fill { display: flex; flex-direction: column-reverse; height: 100%; }
/* column-reverse puts the FIRST layer at the bottom of the glass, which is the order the
   data is written in. Keep them in sync. */
.glass__fill i {
  display: block; height: var(--h); background: var(--c);
  transform: scaleY(0); transform-origin: bottom;
  transition: transform .34s cubic-bezier(.2, .75, .3, 1);
}
.item:hover .glass__fill i { transform: scaleY(1); }
.item:hover .glass__fill i:nth-child(2) { transition-delay: .11s; }
.item:hover .glass__fill i:nth-child(3) { transition-delay: .22s; }
/* no hover to trigger it, and nobody who opted out of motion should need it: show it poured */
@media (hover: none) {
  .glass__fill i { transform: scaleY(1); transition: none; }
}
@media (prefers-reduced-motion: reduce) {
  .glass__fill i { transform: scaleY(1); transition: none; }
}
.item__desc { margin-top: .2rem; font-size: .875rem; line-height: 1.45; color: var(--ink-2); }
.item__note { margin-top: .2rem; font-size: .8125rem; font-weight: 700; }
/* a photo for the whole category, sitting between the heading and the list */
.cat__photo {
  display: block; margin-top: .9rem;
  aspect-ratio: 3 / 2;
  border-radius: var(--radius); overflow: hidden;
  background: var(--brick);
}
.cat__photo img { width: 100%; height: 100%; object-fit: cover; }
.cat__photo--sq { aspect-ratio: 1; }
.item__photo {
  display: block; margin-top: .75rem;
  aspect-ratio: 3 / 2;
  border-radius: var(--radius); overflow: hidden;
  background: var(--brick);
}
.item__photo img { width: 100%; height: 100%; object-fit: cover; }
.item__photo--sq { aspect-ratio: 1; }
.cat__note {
  margin-top: 1rem; padding: .75rem .5rem;
  border-top: 2px solid var(--pink); border-bottom: 2px solid var(--pink);
  font-size: .875rem; text-align: center;
}

/* build your own: a blush panel inside the Drinks deck, photo leading */
.build__panel {
  background: var(--blush);
  border-radius: var(--radius);
  padding: 1.25rem;
  margin-top: .5rem;
}
.cat--build .cat__title {
  position: static;
  background: none;
  border-bottom: 0;
  padding: 0;
}
.build__photo {
  display: block; margin-top: .9rem;
  aspect-ratio: 3 / 2;
  border-radius: var(--radius); overflow: hidden; background: var(--marble);
}
.build__photo img { width: 100%; height: 100%; object-fit: cover; }
.build__lede { margin-top: .9rem; font-size: .875rem; line-height: 1.45; color: var(--ink-2); }
.build__rows { margin-top: .75rem; }
.build__row {
  display: grid; grid-template-columns: 4rem 1fr; gap: .75rem;
  padding: .6rem 0; border-top: 1px solid rgba(42, 26, 28, .18);
  font-size: .875rem; line-height: 1.45;
}
.build__row dt {
  font-weight: 700; font-size: .75rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--pink); padding-top: .2em;
}
.build__addons {
  margin-top: .9rem; padding-top: .75rem;
  border-top: 1px solid rgba(42, 26, 28, .18);
  font-size: .8125rem; font-weight: 700;
}

/* ---------- newsletter popup ----------
   Replaces the seasonal fall popup. Site theme, not the sample's: marble ground, Playfair
   heading in pink, Archivo body, the shared --pink button. Fade only, 250ms, no transform,
   and script.js fades it in, or simply shows it under prefers-reduced-motion. */
.nl {
  position: fixed; inset: 0; z-index: 1500;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
  opacity: 0;
  transition: opacity .25s ease;
}
/* .nl sets display:flex, which would otherwise win over the hidden attribute */
.nl[hidden] { display: none; }
.nl.is-open { opacity: 1; }
/* it appears rather than fades for anyone who asked for less motion -- it still APPEARS */
@media (prefers-reduced-motion: reduce) { .nl { transition: none; } }
.nl__scrim { position: absolute; inset: 0; background: rgba(42, 26, 28, .66); }

.nl__box {
  position: relative;
  width: 100%; max-width: 30rem;
  max-height: calc(100svh - 2rem); overflow: hidden auto;
  padding: 2rem 1.5rem 1.75rem;
  background: var(--marble); color: var(--ink);
  border-radius: var(--radius);
  box-shadow: 0 18px 50px rgba(42, 26, 28, .35);
}
.nl__box:focus { outline: none; }

.nl__x {
  position: absolute; top: .35rem; right: .35rem;
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  border-radius: var(--radius); color: var(--ink);
}
.nl__x svg { width: 22px; height: 22px; }
.nl__x:hover { background: var(--blush); }

.nl__title {
  font: 900 clamp(2rem, 1.5rem + 2.4vw, 2.75rem)/1.02 var(--font-display);
  letter-spacing: -.01em; color: var(--pink); text-align: center;
  padding-right: 2.5rem; padding-left: 2.5rem;
}
.nl__sub { margin-top: .6rem; text-align: center; color: var(--ink-2); line-height: 1.45; }

.nl__form { margin-top: 1.5rem; }
.nl__field + .nl__field { margin-top: 1rem; }
/* same tracked label as the hours columns and Build your own, so the form reads as part of
   the site rather than a bolted-on widget */
.nl__field label {
  display: block; margin-bottom: .35rem;
  font-weight: 700; font-size: .75rem;
  text-transform: uppercase; letter-spacing: .06em; color: var(--pink);
}
.nl__input {
  width: 100%; min-height: 52px; padding: .75rem 1rem;
  border: 2px solid var(--line-strong); border-radius: var(--radius);
  background: var(--white); color: var(--ink);
  font: 400 1rem var(--font-body);
}
.nl__input::placeholder { color: var(--ink-2); }
.nl__input:focus-visible { outline: 3px solid var(--pink); outline-offset: 2px; }

.nl__consent { display: flex; align-items: flex-start; gap: .75rem; margin-top: 1.25rem; }
.nl__check {
  flex: none; width: 22px; height: 22px; margin: .1rem 0 0;
  accent-color: var(--pink);
}
/* the label is the whole sentence, so the effective tap target is far larger than the box */
.nl__consent-text label { display: block; font-size: .875rem; line-height: 1.45; cursor: pointer; }
.nl__policies { display: block; margin-top: .3rem; font-size: .875rem; }
.nl__policies a { font-weight: 700; text-decoration: underline; text-decoration-color: var(--pink); }
.nl__policies a + a { margin-left: .9rem; }

/* base CSS strips list styling site-wide; the fine print is the one place that wants it back */
.nl__fine {
  margin: .6rem 0 0; padding-left: 1.1rem; margin-left: 1.9rem;
  list-style: disc;
  font-size: .8125rem; line-height: 1.5; color: var(--ink-2);
}
.nl__submit { margin-top: 1.5rem; width: 100%; min-height: 54px; font-size: 1.0625rem; }

/* ---------- seasonal category ----------
   TEMPORARY, and deliberately the one category that does not match the others: a gold heading
   over a warm tint, and real maple leaves falling behind it.
   Colours are scoped to .cat--seasonal so none of it can reach the rest of the site.
   Delete this whole block when the season changes (and drop `cls`, `leaves` and `fall`
   from MENU.seasonal). */
.cat--seasonal {
  --amber: #C97B2E;
  --rust: #A8501E;
  --tint: #FBF3E9;
  /* Deeper than --gold #C9A227, which measures about 2.2:1 on this cream ground and is simply
     not readable. This one clears the bar while still reading as gold rather than brown. */
  --gold-deep: #8C6A11;
  position: relative;
  background: var(--tint);
  border-radius: var(--radius);
  padding: 1.25rem 1.125rem 1.5rem;
}
.cat--seasonal .cat__title {
  color: var(--gold-deep);
  border-bottom-color: var(--gold-deep);
  /* bolder than a normal category heading: bigger, tighter, and it already carries Playfair 900 */
  font-size: clamp(1.875rem, 1.35rem + 2.2vw, 2.75rem);
  letter-spacing: -.025em;
  /* the heading is sticky, so it needs the tint too — on --marble it reads as a grey
     bar sliding over the warm ground */
  background: var(--tint);
}
.cat__sub {
  margin-top: .45rem;
  font-weight: 700; font-size: .9375rem;
  color: var(--rust);
}
.cat--seasonal .item__name { color: var(--amber); }
/* the heading is already sticky at z-index 2; these just need to clear the leaf layer */
.cat--seasonal .cat__sub,
.cat--seasonal .cat__photo,
.cat--seasonal .cat__list,
.cat--seasonal .cat__note { position: relative; z-index: 1; }

/* falling maple leaves. The layer carries its own overflow so the section does not need
   `overflow: hidden`, which would break the sticky category heading inside it. */
.cat__fall {
  position: absolute; inset: 0; z-index: 0;
  overflow: hidden; pointer-events: none;
  border-radius: var(--radius);
}
.mleaf {
  position: absolute; top: 0; display: block;
  opacity: 0;
  animation: maple-fall var(--t, 14s) linear var(--d, 0s) infinite;
  will-change: transform;
}
.mleaf img { display: block; width: 100%; height: auto; }
/* --fall-h is measured from the section in script.js so a leaf always clears the bottom edge */
@keyframes maple-fall {
  0%   { transform: translate3d(0, -90px, 0) rotate(0deg); opacity: 0; }
  8%   { opacity: .9; }
  88%  { opacity: .9; }
  100% { transform: translate3d(var(--dx, 0), var(--fall-h, 700px), 0) rotate(var(--r, 300deg)); opacity: 0; }
}

/* heading sprigs — the same photographed leaf as the falling ones */
.leaf { display: inline-block; vertical-align: baseline; }
.leaf img { display: block; width: 100%; height: auto; }
/* the trailing pair travels together, so a narrow column cannot strand one on its own line */
.leaves { display: inline-block; white-space: nowrap; }
/* uneven on purpose — sizes, rotations, gaps and heights all differ */
.leaf--1 { width: 26px; margin-right: .45rem; transform: rotate(-24deg) translateY(-.16em); }
.leaf--2 { width: 21px; margin-left: .5rem;   transform: rotate(16deg) translateY(.2em); }
.leaf--3 { width: 31px; margin-left: .2rem;   transform: rotate(-8deg) translateY(-.26em); }

/* ---------- menu page: the printed menu's header band ---------- */
.menu--page { padding-top: clamp(1.5rem, 4vw, 2.5rem); }
.mband {
  display: grid;
  /* Back to equal side columns, which centres the mark: the hours are a compact two-column
     table now rather than one long run-on line, so they no longer need the extra room they
     were being given at the title's expense. */
  grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: .75rem; padding-bottom: .6rem;
  border-bottom: 4px solid var(--pink);
  margin-bottom: 1.75rem;
}
.deck + .mband { margin-top: 3rem; }
.mband__title { font: 900 var(--fs-display)/1 var(--font-display); color: var(--pink); letter-spacing: -.01em; }
.mband__mark { width: clamp(56px, 11vw, 96px); height: auto; }
/* Coffee and Kitchen side by side, each a day column and a time column. */
.mband__hours {
  display: grid; grid-auto-flow: column; justify-content: end;
  gap: clamp(1rem, 2.5vw, 2rem);
  font-size: clamp(.6875rem, 1.25vw, .8125rem);
}
/* the category label is the only pink here -- the band title is already pink and should stay
   the loudest thing in the header */
.mhrs__h {
  margin-bottom: .35rem;
  font: 700 .6875rem/1 var(--font-body);
  letter-spacing: .14em; text-transform: uppercase; color: var(--pink);
}
.mhrs__dl { display: grid; grid-template-columns: auto auto; gap: .18rem .7rem; margin: 0; }
.mhrs__dl dt { font-weight: 700; color: var(--ink-2); white-space: nowrap; }
/* the times right-align against each other so the figures stack in a column */
.mhrs__dl dd { margin: 0; font-weight: 700; color: var(--ink); text-align: right; white-space: nowrap; }
/* on a phone the three columns collapse to title + mark, hours underneath */
@media (max-width: 599px) {
  .mband { grid-template-columns: 1fr auto; }
  .mband__hours { grid-column: 1 / -1; justify-content: start; }
}

/* ---------- home: eat and drink ----------
   The label sits ON the photograph, over a gradient, rather than under it in a panel. */
.hl__title {
  font: 900 var(--fs-display)/1.05 var(--font-display);
  color: var(--ink); letter-spacing: -.01em;
}
.hl__grid {
  list-style: none; margin-top: clamp(1.5rem, 4vw, 2.25rem);
  display: grid; gap: clamp(.75rem, 2vw, 1.1rem);
  grid-template-columns: 1fr;
}
.hl__card a {
  display: block; text-decoration: none; color: inherit;
  /* same corner the site's buttons and panels use, rather than a softer one of its own */
  border-radius: var(--radius);
  transition: transform .28s ease, box-shadow .28s ease;
}
.hl__card a:hover, .hl__card a:focus-visible {
  transform: translateY(-4px);
  box-shadow: 0 16px 32px rgba(42, 26, 28, .18);
}
.hl__shot {
  position: relative; display: block;
  border-radius: var(--radius); overflow: hidden;
  background: var(--brick);
}
.hl__card img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 1 / 1; object-fit: cover;
  transition: transform .55s ease;
}
.hl__card a:hover img, .hl__card a:focus-visible img { transform: scale(1.07); }
/* the label has to stay readable over whatever the photograph happens to be doing */
.hl__shot::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 58%;
  background: linear-gradient(to top, rgba(26, 14, 16, .82), rgba(26, 14, 16, .35) 45%, transparent);
  z-index: 1; pointer-events: none;
}
.hl__name {
  position: absolute; left: .95rem; right: .95rem; bottom: .8rem; z-index: 3;
  color: var(--white);
  font: 700 .8125rem/1.25 var(--font-body);
  letter-spacing: .07em; text-transform: uppercase;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .35);
}
.hl__flag {
  position: absolute; left: .7rem; top: .7rem; z-index: 3;
  padding: .28rem .6rem; border-radius: 4px;
  background: var(--pink); color: var(--white);
  font: 700 .6875rem/1 var(--font-body);
  letter-spacing: .07em; text-transform: uppercase;
}
/* leaves fall over the photograph, under the gradient so the label stays legible */
.hl__card--seasonal { --fall-h: 320px; }
.hl__leaves { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.hl__leaves .cat__fall { border-radius: inherit; }

.hl__more { margin-top: clamp(1.5rem, 4vw, 2.25rem); display: flex; justify-content: center; }
.hl__cta {
  display: inline-flex; align-items: center; gap: .6rem;
  min-height: 52px; padding: 0 1.6rem;
  border-radius: var(--radius);   /* matches .btn, not a pill */
  background: var(--pink); color: var(--white);
  font: 700 .9375rem/1 var(--font-body); letter-spacing: .06em; text-transform: uppercase;
  text-decoration: none;
  box-shadow: 0 0 0 1px var(--pink), 0 0 0 4px rgba(201, 162, 39, .5);
  transition: background-color .2s ease, box-shadow .2s ease;
}
.hl__cta svg { width: 18px; height: 18px; transition: transform .2s ease; }
.hl__cta:hover { background: var(--ink); box-shadow: 0 0 0 1px var(--ink), 0 0 0 4px var(--gold); }
.hl__cta:hover svg { transform: translateX(4px); }

@media (min-width: 600px) { .hl__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .hl__grid { grid-template-columns: repeat(4, 1fr); } }

/* ---------- scroll reveal ----------
   The hidden half is gated on .reveal-ready, which JS adds, so no-JS or a thrown error
   leaves everything plainly visible rather than blank. */
/* The transition belongs to the REVEALED state, never the hidden one. The hidden state is
   applied by a class JS adds after parse, so if the transition sat on the base rule the
   element would be painted visible, fade OUT to hidden, then fade back in -- a flicker on
   every load. Declared here, it only runs on the way in. */
.reveal-ready [data-reveal]:not(.is-in) { opacity: 0; transform: translateY(18px); }
.reveal-ready [data-reveal].is-in {
  opacity: 1; transform: none;
  transition: opacity .55s ease, transform .55s ease;
}
.hl__grid [data-reveal]:nth-child(2) { transition-delay: .08s; }
.hl__grid [data-reveal]:nth-child(3) { transition-delay: .16s; }
.hl__grid [data-reveal]:nth-child(4) { transition-delay: .24s; }
@media (prefers-reduced-motion: reduce) {
  .reveal-ready [data-reveal]:not(.is-in),
  .reveal-ready [data-reveal].is-in { opacity: 1; transform: none; transition: none; }
}

/* ---------- home: meet Alex ----------
   Replaced the long Our story band. That copy is on about.html now; this is the doorway.
   The photograph is square at source and circled here -- a 4:5 original in a round mask
   loses the sides of the frame, which on this shot is the counter and the stacked cups. */
.meet { background: var(--cream); padding-block: clamp(2.75rem, 6vw, 5rem); }
/* Phone: photograph over copy, both centred. From 760 the two sit side by side and the
   PAIR is centred on the page -- content-sized tracks plus justify-content: center, not a
   1fr column, which would pin the circle to the left gutter and leave the slack on the
   right. justify-items keeps each item centred in the stacked case. */
.meet__grid {
  display: grid; justify-items: center;
  gap: clamp(1.25rem, 3vw, 2rem);
  text-align: center;
}
.meet__photo { width: clamp(210px, 58vw, 330px); }
.meet__photo img { width: 100%; height: auto; aspect-ratio: 1; border-radius: 50%; object-fit: cover; }
.meet__body { max-width: 44ch; }
.meet__eyebrow {
  font: 700 .75rem/1 var(--font-body);
  letter-spacing: .14em; text-transform: uppercase; color: var(--gold);
}
.meet__title {
  margin-top: .75rem;
  font: 900 clamp(2rem, 1.5rem + 2.2vw, 3.25rem)/1.02 var(--font-display);
  letter-spacing: -.01em; color: var(--ink);
}
.meet__lede { margin-top: .9rem; font-size: 1.0625rem; line-height: 1.65; }
/* the rule is the link's own underline, 2px and pink, so the arrow sits over it too */
.meet__cta {
  display: inline-flex; align-items: center; gap: .6rem;
  margin-top: 1.4rem; padding-bottom: .5rem;
  border-bottom: 2px solid var(--pink);
  color: var(--pink); text-decoration: none;
  font: 700 .8125rem/1 var(--font-body);
  letter-spacing: .12em; text-transform: uppercase;
}
.meet__cta:hover { color: var(--pink-hover); border-bottom-color: var(--pink-hover); }
.meet__arrow { width: 18px; height: 18px; transition: transform .15s ease; }
.meet__cta:hover .meet__arrow { transform: translateX(3px); }

@media (min-width: 760px) {
  .meet__grid {
    grid-template-columns: auto auto;
    justify-content: center; align-items: center; justify-items: start;
    text-align: left;
    gap: clamp(2.5rem, 6vw, 5rem);
  }
}


/* ---------- page hero: a photo band torn off along the bottom ----------
   Shared by the inner pages, so the modifier carries the photograph and nothing else.
   The tear is a seamless 600px SVG tile repeated along x, NOT one stretched path: a
   single path with preserveAspectRatio="none" is drawn ~5x denser at 320 than at 1440,
   and the jag stops reading as paper and starts reading as noise. A repeated tile keeps
   every nick the same physical size at every width.
   The tile is filled --marble because that is what sits under it on every page. It hangs
   1px past the bottom so sub-pixel rounding cannot open a hairline of photo beneath it --
   which is also why .phero must NOT be overflow: hidden. */
.phero {
  position: relative;
  display: grid; place-items: center;
  min-height: clamp(260px, 36vw, 440px);
  padding: clamp(2.5rem, 6vw, 4rem) var(--gutter) clamp(3.5rem, 7vw, 5rem);
  color: var(--white); text-align: center;
  background-color: var(--ink);
  background-size: cover; background-repeat: no-repeat;
}
/* NOT the flat scrim the home hero and the newsletter band use. The brightest thing in this
   photograph -- the lit ring of the sign -- sits dead centre, which is exactly where the
   title goes, and the band is wider than the source is tall so background-position has no
   horizontal slack to push it aside with. A pool of shade over the middle lets the type read
   while the marquee still glows out at the edges. */
.phero::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(ellipse 88% 130% at 50% 48%, rgba(42, 26, 28, .68) 0%, rgba(42, 26, 28, .64) 34%, rgba(42, 26, 28, .34) 100%);
}
.phero__inner { position: relative; z-index: 1; max-width: 46rem; }
.phero__eyebrow {
  font: 700 .75rem/1 var(--font-body);
  letter-spacing: .14em; text-transform: uppercase; color: var(--blush);
}
.phero__title {
  margin-top: .8rem;
  font: 900 var(--fs-display)/1.02 var(--font-display);
  letter-spacing: -.01em;
}
.phero__sub {
  margin-top: .9rem; margin-inline: auto; max-width: 34ch;
  font-size: 1.0625rem; line-height: 1.55; color: rgba(254, 254, 254, .88);
}
.phero__tear {
  position: absolute; left: 0; right: 0; bottom: -1px; z-index: 2;
  height: clamp(16px, 2.6vw, 34px);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='40' viewBox='0 0 600 40' preserveAspectRatio='none'%3E%3Cpath d='M0 40 L0 18 L13.9 18.3 L28 33.3 L45.9 24.9 L58.2 12.2 L70.2 3.5 L80 2.3 L95.4 14 L114.1 25 L133.4 2.5 L141.4 24.6 L151.3 3.1 L172.9 24.2 L192.1 13.3 L205.5 28.5 L215.3 24.9 L230.4 16.7 L242.7 19.3 L259 33.9 L276.6 25 L292.8 20.4 L304.2 17.8 L325 14.3 L346.8 12.3 L368.4 30.1 L376.3 3.4 L388.4 21.6 L402.8 23.2 L417.2 19.7 L434.9 9.8 L453.8 24.1 L461 18.8 L478.8 21.7 L489.3 2.5 L501.2 11.4 L522.1 24.4 L537 9.3 L545 20.6 L553.1 10.7 L569.8 12.7 L587.8 18.6 L600 18 L600 40 Z' fill='%23F7F5F3'/%3E%3C/svg%3E") repeat-x left bottom;
  background-size: 600px 100%;
}
/* the lit marquee at night. 56%/46% holds the sign right of the title block on phones and
   keeps the whole ring inside the band on desktop. */
.phero--about {
  background-image: url("Images/web/cafesignoutdoors.jpg");
  background-image: image-set(url("Images/web/cafesignoutdoors.webp") type("image/webp"),
                              url("Images/web/cafesignoutdoors.jpg") type("image/jpeg"));
  background-position: 56% 46%;
}

/* ---------- about: how Pink Owl started ----------
   Mirror of the home page's Our story -- copy left, photograph right, cream instead of
   blush -- so the two pages do not read as the same band twice. */
.origin { display: grid; background: var(--brick); }
.origin__panel { padding: clamp(2rem, 5.5vw, 3.25rem) var(--gutter); }
.origin__inner { max-width: 60ch; margin-inline: auto; }
/* "How Pink Owl started" is three words longer than "Our story". At the full --fs-display
   it broke to two lines in the panel and the gold rule was left trailing an empty half-line. */
.origin__inner .h-display { font: 900 clamp(2rem, 1.4rem + 2vw, 3rem)/1.05 var(--font-display); }
.origin__inner p { margin-top: 1.2rem; font-size: 1.0625rem; line-height: 1.65; }
.origin__inner p:first-of-type { font-size: 1.1875rem; line-height: 1.55; }
/* 125vw is the 4:5 of the source: show the whole frame on a phone, but never taller than
   600px. object-position 50% 36% is what keeps BOTH the sign over his shoulder and his
   face in the window once the box goes wider than 4:5 -- the sign is the reason this
   photograph is on the page at all. */
.origin__photo { height: min(125vw, 600px); background: var(--brick); }
.origin__photo img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 36%; }

/* ---------- about: the press card ---------- */
.press { padding-block: var(--sect); }
.press__card {
  max-width: 940px; margin-inline: auto;
  display: grid;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.press__thumb { background: var(--brick); }
/* phone: a letterbox off the top of the square so his face is not cut at the chin */
.press__thumb img { width: 100%; height: 100%; aspect-ratio: 16 / 10; object-fit: cover; object-position: 50% 24%; }
.press__body { padding: clamp(1.5rem, 4vw, 2.25rem); }
.press__eyebrow {
  font: 700 .75rem/1 var(--font-body);
  letter-spacing: .14em; text-transform: uppercase; color: var(--pink);
}
/* capped well under --fs-display: the headline is the article's own, 70 characters of it,
   and at display size it ran to five lines inside the card */
.press__title {
  margin-top: .7rem;
  font: 900 clamp(1.25rem, 1rem + 1.1vw, 1.75rem)/1.18 var(--font-display);
  letter-spacing: -.01em;
}
.press__blurb { margin-top: .9rem; font-size: 1.0625rem; line-height: 1.6; color: var(--ink-2); }
.press__cta { margin-top: 1.5rem; }
.press__cta .btn__icon { width: 16px; height: 16px; }
.press__meta { margin-top: .9rem; font-size: .8125rem; line-height: 1.45; color: var(--ink-2); }

/* ---------- about: hours and the two ways out ---------- */
.abvisit { background: var(--blush); padding-block: clamp(2rem, 5vw, 3rem); }
.abvisit__grid { display: grid; gap: 1.5rem; }
.abvisit__hours { display: grid; gap: .3rem; font-size: 1.0625rem; line-height: 1.5; }
.abvisit__actions { display: flex; flex-wrap: wrap; gap: .75rem; }
.abvisit__actions .btn { flex: 1 1 auto; }

@media (min-width: 560px) {
  .abvisit__actions .btn { flex: 0 0 auto; }
}

@media (min-width: 720px) {
  .press__card { grid-template-columns: minmax(0, 240px) minmax(0, 1fr); }
  .press__thumb img { aspect-ratio: auto; object-position: 50% 22%; }

  .abvisit__grid { grid-template-columns: 1fr auto; align-items: center; gap: 2rem; }
}

/* 900, not 1024: unlike Our story this panel holds three paragraphs, not four, so the
   column is short enough to sit beside a portrait without squeezing it to a sliver. */
@media (min-width: 900px) {
  .origin { grid-template-columns: 1.05fr .95fr; }
  .origin__panel {
    display: flex; align-items: center; justify-content: center;
    padding: clamp(2.5rem, 4.5vw, 4.5rem) clamp(1.5rem, 3vw, 3.5rem);
  }
  .origin__photo { position: relative; height: auto; min-height: 560px; }
  .origin__photo img { position: absolute; }
}

/* same reasoning as Our story at 1500: the measure is capped, so past here the extra
   width would only grow the cream margins. Give it to the photograph. */
@media (min-width: 1500px) {
  .origin { grid-template-columns: .95fr 1.05fr; }
}

/* ---------- events: page head ----------
   The one page where the title is NOT .h-display. Events is a listing, and a 4.5rem pink
   headline over a gold rule above a single card looked like a section that had lost its
   section. Small gold eyebrow, ink title, one line of lede, then straight into the list. */
.evhead { padding-block: clamp(2rem, 5vw, 3.25rem) clamp(1.25rem, 3vw, 2rem); text-align: center; }
.evhead__eyebrow {
  font: 700 .75rem/1 var(--font-body);
  letter-spacing: .14em; text-transform: uppercase; color: var(--gold);
}
.evhead__title {
  margin-top: .65rem;
  font: 900 clamp(2.25rem, 1.6rem + 2.6vw, 3.75rem)/1.02 var(--font-display);
  letter-spacing: -.01em; color: var(--ink);
}
.evhead__lede {
  margin: .9rem auto 0; max-width: 46ch;
  font-size: 1.0625rem; line-height: 1.6; color: var(--ink-2);
}
.evhead__lede a,
.evhead__ask a { color: var(--pink); font-weight: 700; text-decoration-color: currentColor; }
.evhead__lede a:hover,
.evhead__ask a:hover { color: var(--pink-hover); }
.evhead__ask { margin-top: .6rem; font-size: .9375rem; line-height: 1.6; color: var(--ink-2); }

/* ---------- events: the list ---------- */
.evlist { padding-bottom: var(--sect); }
.evlist__inner { border-top: 1px solid var(--line); padding-top: clamp(1.75rem, 4vw, 2.75rem); }

.ev { display: grid; gap: clamp(1rem, 3vw, 1.75rem); align-items: start; }
.ev + .ev {
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
  padding-top: clamp(1.75rem, 4vw, 2.75rem);
  border-top: 1px solid var(--line);
}
.ev__media { position: relative; border-radius: var(--radius); overflow: hidden; background: var(--brick); }
.ev__media img { width: 100%; height: auto; }
/* the date tab, top right of the flyer. aria-hidden: the full date is in the <time> below
   it, and a screen reader does not need "Oct 4" read twice. */
.ev__chip {
  position: absolute; top: .5rem; right: .5rem;
  display: grid; justify-items: center; gap: .05rem;
  min-width: 46px; padding: .35rem .45rem .4rem;
  border-radius: 6px;
  background: var(--white); color: var(--ink);
  box-shadow: 0 2px 10px rgba(42, 26, 28, .22);
}
.ev__chip-m {
  font: 700 .625rem/1 var(--font-body);
  letter-spacing: .1em; text-transform: uppercase; color: var(--pink);
}
.ev__chip-d { font: 900 1.25rem/1 var(--font-display); }
/* 4 October is behind us. The tab is crossed out rather than pulled: the listing stays up,
   the date still reads straight through a light grey rule, and nothing in the copy has to
   say "this already happened". Both lines get their own strike -- one rule across the
   middle of a two-line chip reads as a divider, not a cancellation. */
.ev__chip--past .ev__chip-m,
.ev__chip--past .ev__chip-d {
  text-decoration: line-through;
  text-decoration-color: rgba(42, 26, 28, .45);
}
.ev__chip--past .ev__chip-m { text-decoration-thickness: 1.5px; }
.ev__chip--past .ev__chip-d { text-decoration-thickness: 2px; }

.ev__title {
  font: 700 1.0625rem/1.25 var(--font-body);
  letter-spacing: .04em; text-transform: uppercase;
}
.ev__meta { margin-top: .6rem; display: grid; gap: .2rem; font-size: .9375rem; color: var(--ink-2); }
.ev__meta dd { margin: 0; }
.ev__meta a { color: var(--pink); text-decoration-color: currentColor; }
.ev__meta a:hover { color: var(--pink-hover); }
.ev__add { margin-top: .15rem; }
.ev__p { margin-top: .9rem; font-size: 1rem; line-height: 1.6; }
.ev__p strong { color: var(--ink); }
.ev__by { margin-top: .9rem; font-size: .875rem; color: var(--ink-2); }
.ev__cta {
  margin-top: 1.1rem;
  font-size: .8125rem; letter-spacing: .08em; text-transform: uppercase;
}

/* ---------- events: private bookings ---------- */
.pev { padding-bottom: var(--sect); }
.pev__grid { display: grid; gap: clamp(1.75rem, 4vw, 3rem); align-items: start; }
.pev__eyebrow {
  font: 700 .75rem/1 var(--font-body);
  letter-spacing: .14em; text-transform: uppercase; color: var(--gold);
}
.pev__title {
  margin-top: .65rem;
  font: 900 clamp(1.75rem, 1.3rem + 1.8vw, 2.5rem)/1.08 var(--font-display);
  letter-spacing: -.01em; color: var(--ink);
}
.pev__sub { margin-top: .85rem; max-width: 40ch; font-size: 1rem; line-height: 1.6; }
/* ruled rows, not bullets: four one-line facts read as a spec sheet, which is what they are */
.pev__list { margin-top: 1.5rem; display: grid; }
.pev__list li {
  display: flex; gap: .65rem; align-items: baseline;
  padding: .7rem 0;
  font-size: .9375rem; line-height: 1.5;
}
.pev__list li + li { border-top: 1px solid var(--line); }
.pev__list li::before { content: "\2605"; color: var(--pink); flex: none; }

.pevform {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 4vw, 1.75rem);
}
.pevform__h { font: 700 1.0625rem/1.3 var(--font-body); }
.pevform__row { display: grid; gap: 1rem; }
.pevform__field { display: grid; gap: .35rem; }
.pevform__h + .pevform__row,
.pevform__h + .pevform__field { margin-top: 1.25rem; }
.pevform__row + .pevform__field,
.pevform__field + .pevform__field,
.pevform__field + .pevform__row { margin-top: 1rem; }
.pevform__label {
  font: 700 .6875rem/1 var(--font-body);
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-2);
}
.pevform__input {
  width: 100%; min-height: 48px; padding: .7rem .85rem;
  border: 1px solid var(--line-strong); border-radius: 6px;
  background: var(--white); color: var(--ink);
  font: 400 1rem var(--font-body);
}
.pevform__input::placeholder { color: var(--ink-2); opacity: .75; }
.pevform__input:focus-visible { outline: 3px solid var(--pink); outline-offset: 1px; }
.pevform__select { padding-right: .5rem; }
.pevform__area { min-height: 128px; resize: vertical; line-height: 1.55; }
.pevform__submit {
  margin-top: 1.5rem;
  font-size: .8125rem; letter-spacing: .08em; text-transform: uppercase;
}
.pevform__fine { margin-top: .85rem; font-size: .8125rem; line-height: 1.5; color: var(--ink-2); }

@media (min-width: 560px) {
  .pevform__row { grid-template-columns: 1fr 1fr; }
}

/* 900: copy beside the form. The form is the heavier half and holds two-up fields of its
   own, so it takes the wider track. */
@media (min-width: 900px) {
  .pev__grid {
    grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
    gap: clamp(2.5rem, 5vw, 4.5rem);
  }
}

/* 560: the flyer beside the detail. Earlier than the About page's split because the card
   body is short lines, not paragraphs of measure -- it survives a narrow column. */
@media (min-width: 560px) {
  .ev { grid-template-columns: minmax(0, 200px) minmax(0, 1fr); }
}
@media (min-width: 1024px) {
  .ev { grid-template-columns: minmax(0, 300px) minmax(0, 1fr); gap: 2.25rem; }
  .ev__title { font-size: 1.1875rem; }
  /* the detail column is 900px wide at 1280 and the two paragraphs were running to ~95
     characters a line. Cap the measure and let the slack sit to the right of it. */
  .ev__body { max-width: 62ch; }
}

/* ---------- contact: the ask ---------- */
.chead { padding-block: clamp(2.25rem, 5vw, 3.5rem) 0; }
.chead__inner { max-width: 44rem; margin-inline: auto; text-align: center; }
.chead__title {
  font: 900 clamp(2rem, 1.4rem + 2.6vw, 3.25rem)/1.06 var(--font-display);
  letter-spacing: -.01em; color: var(--ink);
  /* centred, so an unbalanced break leaves one word alone on the second line. Browsers
     without it fall back to the ordinary greedy break, which is what we had. */
  text-wrap: balance;
}
.chead__sub {
  margin: .9rem auto 0; max-width: 40ch;
  font-size: 1.0625rem; line-height: 1.6; color: var(--ink-2);
}

.cbody { padding-block: clamp(1.75rem, 4vw, 2.75rem) var(--sect); }

/* ---------- legal pages ---------- */
/* privacy.html and terms.html. One column of prose and nothing else, so the only real
   decision is the measure: ~70 characters, set in ch so it tracks the font rather than
   guessing in rem, and the loosest line height on the site. */
.legal { padding-block: clamp(1.5rem, 3.5vw, 2.25rem) var(--sect); }
.legal__doc { max-width: 70ch; margin-inline: auto; }
.legal__h2 {
  margin-top: clamp(2rem, 4vw, 2.75rem);
  font: 900 clamp(1.375rem, 1.1rem + 1vw, 1.75rem)/1.2 var(--font-display);
  letter-spacing: -.01em; color: var(--ink);
}
.legal__p { margin-top: 1rem; font-size: 1.0625rem; line-height: 1.75; color: var(--ink); }
.legal__p strong { font-weight: 700; }
.legal__contact {
  margin-top: 1.25rem; font-style: normal;
  font-size: 1.0625rem; line-height: 1.75; color: var(--ink);
}
.legal__mail { font-weight: 700; text-decoration: underline;
  text-decoration-color: var(--pink); text-underline-offset: 3px; }

/* ---------- footer: the quiet legal row ---------- */
/* Deliberately below the copyright line and dimmer than it: these are links people go
   looking for, not links we are selling. */
.footer__fine {
  max-width: var(--wrap); margin: .6rem auto 0; padding-inline: var(--gutter);
  font-size: .8125rem; color: rgba(254, 254, 254, .55);
}
.footer__fine a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.footer__fine a + a { margin-left: 1.25rem; }
.cbody__grid { display: grid; gap: clamp(2rem, 5vw, 3.5rem); align-items: start; }

/* ---------- contact: the form ---------- */
/* No fill. The page ground runs straight through both boxes and a hairline is the only
   thing holding them -- which is why the inputs keep their white: on a transparent panel
   they are the only edge telling you where to type. */
.cform {
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 4vw, 2rem);
}
.cform__row { display: grid; gap: 1rem; }
.cform__field { display: grid; gap: .35rem; }
.cform__row + .cform__field,
.cform__field + .cform__field { margin-top: 1rem; }
.cform__label {
  font: 700 .6875rem/1 var(--font-body);
  letter-spacing: .12em; text-transform: uppercase; color: var(--ink-2);
}
.cform__input {
  width: 100%; min-height: 48px; padding: .7rem .85rem;
  border: 1px solid var(--line-strong); border-radius: 6px;
  background: var(--white); color: var(--ink);
  font: 400 1rem var(--font-body);
}
.cform__input::placeholder { color: var(--ink-2); opacity: .75; }
.cform__input:focus-visible { outline: 3px solid var(--pink); outline-offset: 1px; }
/* the UA arrow is the only affordance a <select> has; keep appearance alone */
.cform__select { padding-right: .5rem; }
.cform__area { min-height: 150px; resize: vertical; line-height: 1.55; }
.cform__submit {
  margin-top: 1.5rem;
  font-size: .8125rem; letter-spacing: .08em; text-transform: uppercase;
}
.cform__fine { margin-top: .85rem; font-size: .8125rem; line-height: 1.5; color: var(--ink-2); }

/* ---------- form messages ---------- */
/* What Netlify's answer looks like, shown in place of the fields. Deliberately has no colour
   of its own: the newsletter band sets --white over a photo while the two request cards and
   the popup sit on light ground, so inheriting is the only way one rule reads correctly in
   all four places. */
.fmsg { margin: 0; font: 700 1.0625rem/1.5 var(--font-body); color: inherit; }
/* focused programmatically so the confirmation is announced -- it is a <p>, not a control, so
   a focus ring on it would read as a glitch */
.fmsg:focus { outline: none; }
/* the popup's own title and sub are centred, so the confirmation that replaces its fields
   should be too -- the error keeps its left rule and stays ranged left */
.nl__form .fmsg--ok { text-align: center; }

/* ---------- field errors ---------- */
.ferr {
  display: block; margin-top: .35rem;
  font: 400 .8125rem/1.4 var(--font-body);
  color: var(--pink);
}
/* .ferr sets display, so it has to beat it back for the hidden attribute */
.ferr[hidden] { display: none; }

/* the did-you-mean hint. Quieter than .ferr on purpose -- it is advice about a valid
   address, not a refusal, so it must not read as an error. */
.ehint {
  display: block; margin-top: .35rem;
  font: 400 .8125rem/1.4 var(--font-body); color: var(--ink-2);
}
.ehint[hidden] { display: none; }
.ehint__fix {
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-weight: 700; color: var(--pink);
  text-decoration: underline; text-underline-offset: 2px;
}
.ehint__fix:hover { color: var(--pink-hover); }
/* on the scrimmed photo the band needs light text, like .ferr there */
.news .ehint { color: rgba(254, 254, 254, .85); }
.news .ehint__fix { color: var(--white); }
/* the band is white copy over a scrimmed photo, where --pink does not read as text --
   same pink rule the submit error uses there */
.news .ferr {
  color: var(--white);
  padding-left: .6rem; border-left: 3px solid var(--pink);
}
/* an inset ring rather than a border: these four inputs have different borders (the
   band's has none at all) and a ring shifts nothing */
.cform [aria-invalid="true"], .pevform [aria-invalid="true"],
.news__form [aria-invalid="true"], .nl__form [aria-invalid="true"] {
  box-shadow: inset 0 0 0 2px var(--pink);
}
.fmsg--err {
  margin-top: .85rem;
  font-weight: 400; font-size: .9375rem;
  /* a pink rule rather than pink text: --pink does not clear contrast as body copy against
     the newsletter band's scrimmed photo */
  padding-left: .7rem; border-left: 3px solid var(--pink);
}
/* .cform__field, .pevform__row, .nl__consent and .btn all set display, which would otherwise
   win over the hidden attribute when the success message takes the fields' place -- the same
   problem the popup root has at .nl[hidden]. Two classes' worth of specificity beats all of
   them, so no !important. */
.cform > [hidden], .pevform > [hidden],
.news__form > [hidden], .nl__form > [hidden] { display: none; }

/* ---------- contact: the rail ---------- */
.crail {
  display: grid; gap: clamp(1.5rem, 3vw, 2rem);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 4vw, 1.75rem);
  align-content: start;
}
.crail__h {
  font: 700 .6875rem/1 var(--font-body);
  letter-spacing: .14em; text-transform: uppercase; color: var(--gold);
}
.crail__addr { margin-top: .6rem; font-style: normal; font-size: 1.0625rem; line-height: 1.5; }
.crail__link { margin-top: .5rem; }
.crail__a { color: var(--pink); font-weight: 700; text-decoration-color: currentColor; }
.crail__a:hover { color: var(--pink-hover); }
.crail__a--arrow {
  font-size: .8125rem; letter-spacing: .08em; text-transform: uppercase; text-decoration: none;
}
.crail__a--arrow::after { content: " \2197"; }

.crail__hours { margin-top: .7rem; display: grid; gap: .1rem .6rem; font-size: .9375rem; }
.crail__hours dt { font-weight: 700; }
.crail__hours dd { margin: 0 0 .45rem; color: var(--ink-2); }

.crail__social { margin-top: .5rem; display: grid; }
.crail__social li + li { border-top: 1px solid var(--line); }
.crail__social a {
  display: grid; grid-template-columns: 20px minmax(0, 1fr) auto;
  align-items: center; gap: .65rem;
  min-height: 48px; padding: .35rem 0;
  text-decoration: none;
}
.crail__social svg { width: 20px; height: 20px; color: var(--pink); }
.crail__handle { font-weight: 700; font-size: .9375rem; }
.crail__net { font-size: .8125rem; color: var(--ink-2); }
.crail__social a:hover .crail__handle { color: var(--pink); }

@media (min-width: 560px) {
  .cform__row { grid-template-columns: 1fr 1fr; }
}

/* 900: the rail beside the form. Below that the rail would be a 260px column of 14px type
   next to a 300px form, and both lose. */
@media (min-width: 900px) {
  .cbody__grid {
    grid-template-columns: minmax(0, 1.35fr) minmax(0, .65fr);
    gap: clamp(2.5rem, 5vw, 4.5rem);
  }
  .crail { gap: 2rem; }
}

/* The hours stay stacked at every width. They were set inline above 1200 while the rail was
   open to the page, but the rail is a bordered box now and its padding costs ~56px: the
   inline form needs 367px of content ("Saturday and Sunday" sets the label column, "9AM to
   3PM, Tuesday to Sunday" sets the value column) and the rail only offers 310 at 1280 and
   357 at 1440. Every value wrapped and the rows fell out of step with each other. */

/* ---------- instagram coverflow ---------- */
.cf {
  --cf-size: min(72vw, 420px);
  --cf-gap: calc(var(--cf-size) * .78);
  --cf-rot: 38deg;
  margin-top: 2rem;
  display: grid; align-items: center; gap: 1rem .5rem;
  /* phone: arrows sit on their own row under the dots. Eight 44px dots plus two arrows do not
     fit on one row at 390 (let alone 320) — that overflow is what pushed the stage off-centre. */
  grid-template-columns: 1fr 1fr;
  grid-template-areas:
    "stage stage"
    "dots  dots"
    "prev  next";
  column-gap: .75rem;
}
.cf__stage {
  grid-area: stage;
  position: relative; height: var(--cf-size);
  perspective: 1200px; overflow: hidden;
  touch-action: pan-y;
}
.cf__item {
  position: absolute; top: 0; left: 50%;
  width: var(--cf-size); height: var(--cf-size);
  margin-left: calc(var(--cf-size) / -2);
  border-radius: var(--radius); overflow: hidden;
  background: var(--brick);
  transform-style: preserve-3d; backface-visibility: hidden;
  -webkit-user-drag: none; user-select: none;
  transition: transform .5s ease, opacity .5s ease;
  will-change: transform;
}
.cf__item picture, .cf__item img { width: 100%; height: 100%; object-fit: cover; }
.cf__item::after {
  content: ""; position: absolute; inset: 0;
  background: var(--ink); opacity: 0;
  transition: opacity .5s ease;
}
.cf__item[data-pos="0"]  { transform: translateX(0) rotateY(0) scale(1); z-index: 5; opacity: 1; }
.cf__item[data-pos="1"]  { transform: translateX(var(--cf-gap)) rotateY(calc(-1 * var(--cf-rot))) scale(.84); z-index: 4; }
.cf__item[data-pos="-1"] { transform: translateX(calc(-1 * var(--cf-gap))) rotateY(var(--cf-rot)) scale(.84); z-index: 4; }
.cf__item[data-pos="2"]  { transform: translateX(calc(1.75 * var(--cf-gap))) rotateY(calc(-1 * var(--cf-rot))) scale(.7); z-index: 3; }
.cf__item[data-pos="-2"] { transform: translateX(calc(-1.75 * var(--cf-gap))) rotateY(var(--cf-rot)) scale(.7); z-index: 3; }
.cf__item[data-pos="x"]  { transform: translateX(0) scale(.5); opacity: 0; pointer-events: none; z-index: 0; }
.cf__item[data-pos="1"]::after, .cf__item[data-pos="-1"]::after { opacity: .35; }
.cf__item[data-pos="2"]::after, .cf__item[data-pos="-2"]::after { opacity: .55; }
.cf__item:focus-visible { outline-offset: -3px; }

.cf__arrow {
  width: 48px; height: 48px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--ink); color: var(--white);
  transition: background-color .15s ease;
}
/* the pair reads as one control centred under the dots */
.cf__arrow--prev { justify-self: end; }
.cf__arrow--next { justify-self: start; }
.cf__arrow:hover { background: var(--pink); }
.cf__arrow svg { width: 22px; height: 22px; }
.cf__arrow--prev { grid-area: prev; }
.cf__arrow--next { grid-area: next; }
/* Not dots. A gold rule broken into one segment per photo, with the current one in pink --
   the same gold hairline that sits under every section heading, doing a second job.
   The segment widths stay >=24px so they remain real touch targets at 320. */
.cf__dots { grid-area: dots; display: flex; align-items: center; justify-content: center; gap: 2px; }
.cf__count {
  margin: 0 .65rem 0 0;
  font: 900 .875rem/1 var(--font-display);
  color: var(--ink); opacity: .7;
  letter-spacing: .06em; font-variant-numeric: tabular-nums;
}
/* Flexible rather than a fixed clamp: with eleven photos a fixed width overflows 320, and
   hand-tuning the clamp every time a photo is added is how it silently breaks. They grow to
   34px where there is room and never go under the 24px touch target. */
.cf__dot { flex: 1 1 auto; min-width: 24px; max-width: 34px; height: 44px; display: grid; place-items: center; }
.cf__dot::before {
  content: ""; width: 100%; height: 2px; border-radius: 2px;
  background: var(--gold); opacity: .5;
  transition: opacity .15s ease, height .15s ease, background-color .15s ease;
}
.cf__dot:hover::before { opacity: .9; }
.cf__dot[aria-current="true"]::before { background: var(--pink); opacity: 1; height: 5px; }
/* Eleven segments plus the counter do not share a line on any phone: the segments alone
   need 284px at their 24px minimum, and the counter wants another 61. So on phones the
   counter sits above the track, which also lets the segments grow into the full width
   instead of huddling at the minimum. */
@media (max-width: 599px) {
  .cf__dots { flex-wrap: wrap; }
  .cf__count { flex: 0 0 100%; margin: 0 0 .45rem; text-align: center; }
}

/* Affordances for the ways in that are not the arrows: the stage is draggable, and an
   off-centre photo is clickable and says so by lifting out of its dim as you point at it. */
.cf:not(.cf--flat) .cf__stage { cursor: grab; }
.cf:not(.cf--flat) .cf__stage:active { cursor: grabbing; }
.cf:not(.cf--flat) .cf__item:not([data-pos="0"]) { cursor: pointer; }
.cf:not(.cf--flat) .cf__item[data-pos="1"]:hover::after,
.cf:not(.cf--flat) .cf__item[data-pos="-1"]:hover::after { opacity: .12; }
.cf:not(.cf--flat) .cf__item[data-pos="2"]:hover::after,
.cf:not(.cf--flat) .cf__item[data-pos="-2"]:hover::after { opacity: .3; }
/* the centred photo is the one you can actually open, so it gets the gold frame */
.cf:not(.cf--flat) .cf__item[data-pos="0"] {
  box-shadow: 0 0 0 1px var(--gold), 0 18px 38px rgba(42, 26, 28, .18);
}
.cf__follow { margin-top: 1.5rem; display: flex; justify-content: center; }

/* flat strip: phones and reduced motion. The current card sits centred with its neighbours peeking in;
   swipe is native scroll, arrows and dots scroll the strip, auto-advance scrolls it too. */
.cf--flat .cf__stage {
  display: flex; gap: .75rem; height: auto;
  overflow-x: auto; scroll-snap-type: x mandatory;
  padding-inline: calc((100% - var(--cf-size)) / 2);
  scrollbar-width: none; perspective: none;
  /* MUST override the base pan-y. The coverflow sets touch-action: pan-y because JS handles
     the horizontal gesture there and the page still has to scroll vertically -- but the flat
     strip scrolls horizontally by NATIVE scroll, and pan-y tells the browser not to pan
     horizontally at all. With pan-y inherited here the strip simply does not swipe on a
     touch device, which is invisible on a desktop mouse. */
  touch-action: pan-x pan-y;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}
.cf--flat .cf__stage::-webkit-scrollbar { display: none; }
.cf--flat .cf__item {
  position: static; margin: 0;
  flex: 0 0 var(--cf-size); aspect-ratio: 1; height: auto;
  transform: none !important; opacity: 1 !important; pointer-events: auto !important;
  scroll-snap-align: center; transition: none;
}
.cf--flat .cf__item::after { display: none; }

/* ---------- reviews ----------
   Presentational only. No Review/AggregateRating JSON-LD anywhere -- CLAUDE.md forbids it,
   and the penalty for self-serving review markup lands on the whole domain. */
/* tighter than the default section rhythm: the stage is sized to the LONGEST review, so
   this section runs tall on a phone and every saving compounds */
.rev.section { padding-block: clamp(2rem, 5vw, 3rem); }
.rev { background: var(--blush); text-align: center; }
.rev .h-display { display: inline-block; }
.rev__src {
  margin-top: .9rem;
  display: flex; align-items: center; justify-content: center; gap: .45rem;
  font-weight: 700; letter-spacing: .04em; text-transform: uppercase; font-size: .9375rem;
}
.rev__badge { display: inline-flex; align-items: center; gap: .3rem; color: var(--pink); }
.rev__check { width: 1.05em; height: 1.05em; flex: none; }

/* all six occupy one grid cell, so the section is as tall as the LONGEST review and the
   page does not jump as you step through them. visibility:hidden also keeps the inactive
   ones out of the accessibility tree. */
.rev__stage { display: grid; margin-top: 1.1rem; touch-action: pan-y; }
.rev__item {
  grid-area: 1 / 1; margin: 0;
  visibility: hidden; opacity: 0;
  transition: opacity .42s ease, transform .42s ease, visibility 0s linear .42s;
}
.rev__item[data-on] {
  visibility: visible; opacity: 1; transform: none;
  transition: opacity .42s ease, transform .42s ease, visibility 0s;
}
/* the incoming quote arrives from the side you swiped from */
.rev__stage[data-dir="next"] .rev__item:not([data-on]) { transform: translateX(22px); }
.rev__stage[data-dir="prev"] .rev__item:not([data-on]) { transform: translateX(-22px); }
/* while a finger is on it the card tracks 1:1 -- a transition here would lag the drag */
.rev__stage.is-dragging { cursor: grabbing; }
.rev__stage.is-dragging .rev__item[data-on] { transition: none; }

.rev__play { width: 44px; height: 44px; display: grid; place-items: center; flex: none; color: var(--ink); }
.rev__play svg { width: 17px; height: 17px; grid-area: 1 / 1; }
.rev__play:hover { color: var(--pink); }
.rev__ico-play { opacity: 0; }
.rev.is-paused .rev__ico-pause { opacity: 0; }
.rev.is-paused .rev__ico-play { opacity: 1; }

/* Entrance, one shot when the section first comes into view: the gold rule draws across the
   heading the way the loader's arc draws round the badge, and the card rises under it. */
.rev .h-display { position: relative; }
/* only hide the rule once JS has promised to draw it */
.rev--anim .h-display { border-bottom-color: transparent; }
.rev .h-display::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--gold); transform: scaleX(0); transform-origin: left;
  transition: transform .85s cubic-bezier(.22, .7, .3, 1);
}
.rev.is-in .h-display::after { transform: scaleX(1); }
/* scoped to .rev--anim: without it the content is simply visible, which is what a browser
   with no JS, no IntersectionObserver, or a thrown error must get */
/* same rule as the highlight cards: the transition is on the way IN only, or the section
   is painted, faded out, then faded back in */
.rev--anim .rev__src, .rev--anim .rev__stage, .rev--anim .rev__nav {
  opacity: 0; transform: translateY(14px);
}
.rev.is-in .rev__src, .rev.is-in .rev__stage, .rev.is-in .rev__nav {
  transition: opacity .6s ease, transform .6s ease;
}
.rev.is-in .rev__src,
.rev.is-in .rev__stage,
.rev.is-in .rev__nav { opacity: 1; transform: none; }
.rev.is-in .rev__src   { transition-delay: .18s; }
.rev.is-in .rev__stage { transition-delay: .3s; }
.rev.is-in .rev__nav   { transition-delay: .42s; }

@media (prefers-reduced-motion: reduce) {
  /* nothing moves: no slide, no entrance. Autoplay is already refused in script.js. */
  .rev__item, .rev__src, .rev__stage, .rev__nav, .rev .h-display::after { transition: none; }
  .rev__src, .rev__stage, .rev__nav { opacity: 1; transform: none; }
  .rev .h-display::after { transform: scaleX(1); }
  .rev__stage .rev__item:not([data-on]) { transform: none; }
}
.rev__who {
  display: flex; align-items: center; justify-content: center;
  gap: .6rem; flex-wrap: wrap;
}
/* lettered avatar -- no profile photographs, see the note on REVIEWS in script.js */
.rev__avatar {
  position: relative; flex: none;
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--tint); color: var(--white);
  font: 700 1.125rem/1 var(--font-body);
}
.rev__guidemark {
  position: absolute; right: -2px; bottom: -2px;
  width: 17px; height: 17px; color: var(--gold);
}
.rev__id { display: grid; justify-items: start; text-align: start; }
.rev__name { font-weight: 700; font-size: 1.0625rem; }
.rev__guide { font-size: .8125rem; color: var(--ink-2); }
.rev__stars { display: inline-flex; gap: 2px; }
.rev__star { width: 16px; height: 16px; fill: var(--gold); }
.rev__star[data-off] { fill: var(--line); }
.rev__quote { margin: .8rem auto 0; max-width: 54ch; }
/* smaller than a pull quote: these run to a full paragraph, and Playfair italic at pull-quote
   size turns a real review into a wall */
.rev__quote p {
  font: 400 1rem/1.5 var(--font-display);
  font-style: italic; color: var(--ink);
}
/* the quote marks are decoration, so they are drawn rather than typed -- no stray
   characters for a screen reader to read out */
.rev__quote p::before { content: "\201C"; }
.rev__quote p::after  { content: "\201D"; }

.rev__nav {
  margin-top: 1.1rem;
  display: flex; align-items: center; justify-content: center; gap: .5rem;
}
.rev__arrow {
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center; flex: none;
  background: var(--ink); color: var(--white);
  transition: background-color .15s ease;
}
.rev__arrow:hover { background: var(--pink); }
.rev__arrow svg { width: 20px; height: 20px; }
.rev__dots { display: flex; align-items: center; justify-content: center; gap: 2px; }
.rev__dot { width: clamp(26px, 8vw, 34px); height: 44px; display: grid; place-items: center; }
.rev__dot::before {
  content: ""; width: 100%; height: 2px; border-radius: 2px;
  background: var(--gold); opacity: .5;
  transition: opacity .15s ease, height .15s ease, background-color .15s ease;
}
.rev__dot:hover::before { opacity: .9; }
.rev__dot[aria-current="true"]::before { background: var(--pink); opacity: 1; height: 5px; }

@media (min-width: 768px) {
  .rev__quote p { font-size: 1.125rem; line-height: 1.55; }
  .rev__quote { max-width: 62ch; }
}

/* ---------- newsletter ---------- */
.news {
  position: relative;
  padding-block: var(--sect);
  color: var(--white);
  background-image: url("Images/web/cafesignoutdoors.jpg");
  background-image: image-set(url("Images/web/cafesignoutdoors.webp") type("image/webp"),
                              url("Images/web/cafesignoutdoors.jpg") type("image/jpeg"));
  /* Keeps the lit sign right of centre so it clears the copy. A background percentage aligns that
     point of the image with the same point of the box, so on a narrow phone a LOWER number pushes
     the sign rightward; wide screens have no horizontal slack and ignore it. */
  background-size: cover; background-position: 30% center; background-color: var(--ink);
}
/* flat scrim, not a gradient */
.news::before { content: ""; position: absolute; inset: 0; background: rgba(42, 26, 28, .63); }
.news .wrap { position: relative; }
.news__inner { max-width: 34rem; }
/* phone: copy centred over the sign, form stacked full width beneath it */
.news__text { text-align: center; }
.news__title { font: 900 var(--fs-display)/1.02 var(--font-display); letter-spacing: -.01em; }
.news__sub { margin-top: .75rem; color: rgba(254, 254, 254, .85); font-size: 1.0625rem; }
.news__form { margin-top: 1.75rem; display: flex; flex-direction: column; gap: .75rem; }
.news__input {
  width: 100%; min-height: 52px; padding: .8rem 1rem;
  border: 0; border-radius: var(--radius);
  background: var(--white); color: var(--ink);
  font: 400 1rem var(--font-body);
}
.news__input::placeholder { color: var(--ink-2); }
.news__submit { min-height: 52px; }

/* ---------- visit ---------- */
/* No band of its own. --marble is the page ground, so Visit now reads as the page simply
   continuing under the newsletter photo rather than as a third coloured stripe stacked
   between that band and the ink footer. */
.visit { background: var(--marble); }
.visit__grid { display: grid; gap: 2rem; }
.visit__address { margin-top: 1.25rem; font-size: 1.125rem; line-height: 1.5; }
/* The address is a real <button> so it is reachable by keyboard and announces itself,
   but it has to go on looking like an address -- font: inherit also carries the italic
   that the UA stylesheet puts on <address>. */
.visit__copy {
  display: inline-flex; align-items: flex-start; gap: .55rem;
  margin: 0; padding: 0;
  font: inherit; color: inherit; text-align: start;
  background: none; border: 0; cursor: pointer;
}
.visit__copyicon {
  width: 1.05em; height: 1.05em; flex: none; margin-top: .25em;
  opacity: .7; transition: opacity .15s ease;
}
.visit__copy:hover .visit__copyicon,
.visit__copy:focus-visible .visit__copyicon { opacity: 1; }
.visit__copy:hover .visit__addr { text-decoration: underline; text-underline-offset: 3px; }
/* role="status" announces this to a screen reader; the pill is the same news for everyone else */
.visit__copied {
  display: inline-block; margin-top: .65rem;
  padding: .2rem .7rem; border-radius: 999px;
  background: var(--pink); color: var(--white);
  font-size: .9375rem; font-weight: 700; font-style: normal;
  opacity: 0; transform: translateY(-3px);
  transition: opacity .18s ease, transform .18s ease;
}
.visit__copied[data-on] { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .visit__copied, .visit__copyicon { transition: none; }
}
.visit__actions {
  display: flex; flex-direction: column; gap: .75rem;
  margin-top: 1.5rem; max-width: 360px;
}
.visit__map {
  aspect-ratio: 4 / 3;
  border-radius: var(--radius); overflow: hidden; background: var(--marble);
}
.visit__map iframe { width: 100%; height: 100%; border: 0; display: block; }

/* ---------- footer ---------- */
.site-footer {
  background: var(--ink); color: var(--white);
  padding-block: var(--sect) 1.5rem;
}
.footer__grid { display: grid; gap: 2.25rem; }
.footer__mark { width: 120px; height: 120px; filter: invert(1); }
.site-footer h2 { font: 900 var(--fs-h3)/1.1 var(--font-display); color: var(--pink); margin-bottom: .75rem; }
.footer__list { display: grid; gap: .35rem; font-size: .9375rem; }
.footer__list a { text-decoration-color: var(--gold); }
.site-footer a:hover { color: var(--blush); }
/* five links now, so a tighter gap -- they wrap inside the contact column */
.footer__social { display: flex; flex-wrap: wrap; gap: .4rem 1rem; margin-top: .75rem; }
.footer__social a {
  display: inline-flex; align-items: center; gap: .5rem;
  min-height: 44px; font-weight: 700; text-decoration: none;
}
.footer__social svg { width: 24px; height: 24px; }
.footer__legal {
  max-width: var(--wrap); margin: 2.5rem auto 0; padding-inline: var(--gutter);
  padding-top: 1.25rem; border-top: 1px solid rgba(254, 254, 254, .18);
  font-size: .8125rem; color: rgba(254, 254, 254, .7);
}

/* ======================================================
   768+ : tablet
   ====================================================== */
@media (min-width: 768px) {
  .brand__wordmark { width: 230px; }

  .hero__content { gap: 1.5rem; padding-bottom: 110px; }
  .hero__logo { width: 240px; }

  .hours__decks { grid-template-columns: repeat(2, minmax(0, 22rem)); }

  .menu__body { --menu-peek: 980px; }


  /* tablet and up: copy on the left, form beside it on the right */
  .news__inner {
    max-width: none;
    display: grid; align-items: center;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    gap: 1.5rem clamp(2rem, 5vw, 4rem);
  }
  .news__text { text-align: left; }
  .news__sub { max-width: 42ch; }
  .news__form { margin-top: 0; flex-direction: row; align-items: stretch; }
  .news__input { flex: 1 1 auto; min-width: 0; }
  .news__submit { flex: 0 0 auto; }

  .deck__cols { padding-inline: 6%; }

  .cf {
    --cf-size: min(48vw, 420px); --cf-gap: calc(var(--cf-size) * .66);
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
      "stage stage stage"
      "prev  dots  next";
  }

  .visit__actions { flex-direction: row; flex-wrap: wrap; max-width: none; }

  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }
}

/* ======================================================
   1024+ : desktop
   ====================================================== */
@media (min-width: 1024px) {
  .nav {
    position: static; inset: auto; z-index: auto;
    background: none; padding: 0;
    flex-direction: row; align-items: center;
    margin-left: auto; margin-right: 1.5rem;
    overflow: visible; opacity: 1; visibility: visible; transition: none;
  }
  .nav__list { flex-direction: row; gap: 1.75rem; margin: 0; }
  .nav__link {
    padding: .75rem 0;
    font: 700 1rem/1 var(--font-body); letter-spacing: 0;
  }
  .nav__link--ext::after { font-size: .75em; vertical-align: .25em; }
  .nav__extra, .nav-toggle { display: none; }
  /* the drawer's full-width pink rows are a phone treatment only */
  .nav .nav__list { display: flex; gap: 1.6rem; }
  .nav .nav__list li + li { border-top: 0; }
  .nav .nav__link {
    display: inline-block; margin-inline: 0; width: auto; background: none;
    padding: .75rem 0;
    font: 700 1rem/1 var(--font-body);
    text-transform: none; letter-spacing: 0; color: var(--ink);
  }
  .nav .nav__link:hover { background: none; color: var(--pink); }
  /* only the inline bar sits over the hero video */
  .home .site-header:not(.is-solid) .nav .nav__link,
  .home .site-header:not(.is-solid) .nav .nav__link[aria-current="page"] { color: var(--white); }
  .home .site-header:not(.is-solid) .nav .nav__link:hover { color: var(--white); text-decoration: underline; text-underline-offset: 6px; }
  .nav .nav__link[aria-current="page"] { background: none; color: var(--pink); text-decoration: underline; text-underline-offset: 6px; }
  /* on the bar the button sits beside the language toggle, so the drawer block goes away */
  .nav__actions { display: none; }
  .hdr__order {
    display: inline-flex; align-items: center; flex: none;
    min-height: 38px; padding: 0 .9rem; margin-left: .25rem;
    border: 2px solid var(--pink); border-radius: var(--radius);
    color: var(--pink); text-decoration: none;
    font: 700 .75rem/1 var(--font-body); letter-spacing: .08em; text-transform: uppercase;
    white-space: nowrap;
    transition: background-color .15s ease, color .15s ease, border-color .25s ease;
  }
  .hdr__order:hover { background: var(--pink); color: var(--white); }
  /* brand keeps its auto margin and .nav keeps its own, so the free space splits either
     side of the phone and it lands centred between them -- without absolute positioning,
     which would let it collide with the links once Spanish makes them wider. */
  .nav .social { margin-top: 0; margin-left: 1.25rem; }
  .nav .social__link { width: 36px; height: 36px; }
  .brand__wordmark { width: 250px; }

  /* the clip is 720x320; keep the hero near its shape on desktop so it is not stretched past ~2x */
  .hero { height: min(calc(100svh - var(--header-h)), 46vw); }
  .home .hero { height: min(100svh, 52vw); }
  .hero__logo { width: 260px; }

  .menu__body { --menu-peek: 1080px; }

  .deck__cols { grid-template-columns: 1fr 1fr; column-gap: clamp(2.5rem, 5vw, 5rem); padding-inline: 0; }
  .deck__cols--3 { grid-template-columns: repeat(3, 1fr); }
  .deck__col { display: block; }
  .deck__col > .cat + .cat { margin-top: 2.5rem; }
  .build__panel { padding: 1.5rem; }

  /* the box itself has no padding any more — the photo is full bleed and the copy block
     carries its own. Taller here too: at 56px the headline block would otherwise crowd out
     the photograph it sits on. */
  /* must stay ABOVE the base min-height, not below it — the copy block is a fixed height,
     so every pixel added here goes straight to the photograph */
  .nl__box { padding: 2.25rem 2rem 2rem; }

  .cf { --cf-gap: calc(var(--cf-size) * .62); --cf-rot: 40deg; margin-top: 2.5rem;
    grid-template-columns: auto 1fr auto;
    grid-template-areas:
      "prev stage next"
      "dots dots dots";
    column-gap: 1.25rem;
  }
  .cf__arrow { width: 52px; height: 52px; }

  .visit__grid { grid-template-columns: 1fr 1.2fr; align-items: start; gap: clamp(2.5rem, 5vw, 5rem); }
  .visit__map { aspect-ratio: 16 / 11; }

  .footer__grid { grid-template-columns: minmax(160px, .9fr) 1fr 1fr; align-items: start; }
  .footer__brand { grid-column: auto; }
  .footer__mark { width: 150px; height: 150px; }
}

/* ======================================================
   1440+ : wide
   ====================================================== */
/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0s !important; }
  /* the seasonal leaves are decoration only, so they go entirely rather than piling up */
  .cat__fall { display: none; }

}
