/* ==========================================================================
   Rosa Twelve — shared site stylesheet
   Warm, modern Mediterranean: cream base, brand red, terracotta + olive
   accents. Mobile-first; breakpoints at 640px, 900px, 1200px.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design tokens
   -------------------------------------------------------------------------- */
:root {
  /* Colour */
  --red: #dd131b;
  --red-dark: #b30f15;
  --terracotta: #c2603e;
  --terracotta-deep: #a3492a;
  --terracotta-soft: #eed9cd;
  --olive: #6e7245;
  --olive-soft: #d9dac2;
  --cream: #faf6ee;
  --cream-2: #f3ecdd;
  --cream-3: #f0e5d3;
  --white: #ffffff;
  --ink: #2e2823;
  --ink-soft: #6b6258;
  --line: #e5dbc8;
  --footer-bg: #2a211c;
  --footer-text: #efe7da;
  --footer-dim: #b8aa99;

  /* Scrim over photography so any text set on it stays legible.
     Warm near-black, weighted top and bottom for centred copy. */
  --scrim-hero: linear-gradient(
    180deg,
    rgba(28, 18, 14, 0.62) 0%,
    rgba(28, 18, 14, 0.34) 45%,
    rgba(28, 18, 14, 0.7) 100%
  );
  --scrim-band: linear-gradient(
    180deg,
    rgba(28, 18, 14, 0.55),
    rgba(28, 18, 14, 0.62)
  );

  /* Faint paper grain — felt, not seen. Tiled monochrome turbulence at ~5%
     alpha; reused on the body and on warm sections so they never read flat. */
  --paper: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.05'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)'/%3E%3C/svg%3E");

  /* Soft cream-to-terracotta wash for alternating sections */
  --wash-warm: linear-gradient(176deg, var(--cream-2) 0%, #f4e6d4 100%);

  /* Type */
  --serif: 'Fraunces', Georgia, 'Times New Roman', serif;
  --sans: 'Karla', 'Segoe UI', system-ui, -apple-system, sans-serif;
  --track-label: 0.14em;
  --track-btn: 0.1em;
  --track-display: -0.012em;

  /* Space */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 1rem;
  --space-4: 1.5rem;
  --space-5: 2.25rem;
  --space-6: 3.5rem;
  --space-7: 5rem;
  --space-8: 6.5rem;

  /* Layout */
  --container: 1160px;
  --container-narrow: 760px;
  --gutter: 1.25rem;
  --radius: 10px;
  --radius-sm: 6px;
  --shadow-soft: 0 2px 10px rgba(46, 40, 35, 0.07);
  --shadow-lift: 0 14px 30px rgba(46, 40, 35, 0.14);

  /* Nav */
  --nav-h: 76px;
  --nav-h-scrolled: 62px;

  /* Motion — one easing curve and a couple of durations shared across the
     site so hero entrance, reveals and menu transitions feel of a piece.
     --ease-out is a gentle decelerating curve (fast in, soft settle). */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-reveal: 640ms;
  --dur-menu: 240ms;

  /* The one canonical rose as a CSS mask — the actual Rosa rose lifted from the
     logo bloom (same geometry as the JS-injected roses in site.js roseMarkSvg
     and the inline .ornament / atmosphere roses). Used as a mask so any element
     can paint it in a brand colour via background-color. Single source for every
     CSS rose (the brand-dot bullets). Keep in sync with the JS builder and the
     inline SVGs. */
  --rose-svg: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='63.087%2082.743%2039.712%2031.416'%3E%3Cg%20transform='translate(91.279%2089.66)'%3E%3Cpath%20d='M89.388,104.924a12.347,12.347,0,0,1-.714,1.828,49.124,49.124,0,0,0,6.435-6.568c1.517-1.826.949-4.1.2-5.688a16.27,16.27,0,0,0-4.439-5.4,45.43,45.43,0,0,1-1.111,13.939,10.871,10.871,0,0,1-.374,1.892'%20transform='translate(-88.674%20-89.093)'/%3E%3C/g%3E%3Cg%20transform='translate(90.895%2085.27)'%3E%3Cpath%20d='M98.529,94.98A19.957,19.957,0,0,0,88.6,85.124a5.874,5.874,0,0,1,2.1,3.067,17.635,17.635,0,0,1,5.467,6.341c1.228,2.616,1.117,4.915-.325,6.651a46.976,46.976,0,0,1-7.515,7.448,40.161,40.161,0,0,0,9.7-7.472c1.787-1.775,1.256-4.341.5-6.18'%20transform='translate(-88.327%20-85.124)'/%3E%3C/g%3E%3Cg%20transform='translate(65.195%2085.285)'%3E%3Cpath%20d='M70.885,88.622a5.922,5.922,0,0,1,1.445-2.436A8.246,8.246,0,0,1,73.6,85.137a9.145,9.145,0,0,0-7.88,4.4,11.453,11.453,0,0,0-.633,1.1,7.3,7.3,0,0,1,5.4-2.029c.127,0,.261.011.394.015'%20transform='translate(-65.089%20-85.137)'/%3E%3C/g%3E%3Cg%20transform='translate(79.369%2086.162)'%3E%3Cpath%20d='M91.019,88.659a12.99,12.99,0,0,0-6.991-2.729,5.763,5.763,0,0,0-.745.067,4.683,4.683,0,0,0-.819.182,4.268,4.268,0,0,0-.857.379c-.092.055-.189.1-.276.161-.058.04-.117.077-.173.122a4.139,4.139,0,0,0-.364.348c-.09.09-.191.164-.275.264-.654.787-1.253,1.555-1.826,2.309-.27.357-.536.711-.787,1.058.133.061.263.116.4.177s.281.132.42.2a74.875,74.875,0,0,1,9.131,5.192,7.133,7.133,0,0,1,1.361,1.183c.121.133.252.257.361.4.124.16.223.334.331.5a6.572,6.572,0,0,1,.768,1.619,54.346,54.346,0,0,0,.435-10.683,4.95,4.95,0,0,0-.091-.749'%20transform='translate(-77.905%20-85.93)'/%3E%3C/g%3E%3Cg%20transform='translate(71.934%2083.744)'%3E%3Cpath%20d='M71.182,88.837a24.033,24.033,0,0,1,6.581,1.849c.826-1.148,1.741-2.337,2.773-3.578.02-.025.046-.049.069-.074.112-.127.223-.252.345-.366a4.032,4.032,0,0,1,.365-.31,5.142,5.142,0,0,1,2.264-1,6.375,6.375,0,0,1,.756-.086c.135-.009.269-.019.407-.019.1,0,.211.013.316.019A13.138,13.138,0,0,1,91.135,87.4a7.162,7.162,0,0,0-3.8-2.787c-.335-.121-.679-.233-1.034-.328-.294-.077-.593-.145-.9-.207a18.213,18.213,0,0,0-9.273.612c-.271.1-.535.2-.789.305s-.512.237-.759.363a8.421,8.421,0,0,0-2.243,1.6,5.084,5.084,0,0,0-1.157,1.879'%20transform='translate(-71.182%20-83.744)'/%3E%3C/g%3E%3Cg%20transform='translate(64.086%2089.66)'%3E%3Cpath%20d='M91.476,102.866a6.817,6.817,0,0,0-.488-3.535,8.952,8.952,0,0,0-.6-1.056,5.993,5.993,0,0,0-1.563-1.465A73.661,73.661,0,0,0,79.658,91.6c-.145-.067-.288-.131-.431-.194s-.26-.116-.388-.171l-.03-.014c-.28-.122-.553-.238-.825-.349a22.554,22.554,0,0,0-6.262-1.721c-.154-.014-.309-.029-.457-.038s-.305-.013-.455-.015c-.07,0-.143-.009-.212-.009a6.117,6.117,0,0,0-5.558,2.733,5.81,5.81,0,0,0-.867,2.2q-.615,3.484,3.161,7.906a44.675,44.675,0,0,0,7.394,6.607c1.008.745,2.1,1.506,3.253,2.278.262.177.519.352.789.53.134.087.253.173.387.261a5.786,5.786,0,0,0,3.2.988,7.462,7.462,0,0,0,4.478-1.672c.19-.145.376-.3.557-.456.056-.049.109-.1.164-.147q.259-.236.5-.487.327-.337.63-.7.269-.322.518-.662c.081-.112.163-.222.239-.335a12.638,12.638,0,0,0,1.678-3.469,9.921,9.921,0,0,0,.348-1.8'%20transform='translate(-64.086%20-89.093)'/%3E%3C/g%3E%3C/svg%3E");
}

@media (min-width: 900px) {
  :root {
    --gutter: 2rem;
  }
}

@media (min-width: 1100px) {
  :root {
    --nav-h: 92px;
    --nav-h-scrolled: 70px;
  }
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

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

body {
  margin: 0;
  font-family: var(--sans);
  font-size: 1.02rem;
  line-height: 1.65;
  color: var(--ink);
  background-color: var(--cream);
  background-image: var(--paper);
  font-optical-sizing: auto;
  font-variant-ligatures: common-ligatures contextual;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

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

a {
  color: var(--red);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover {
  color: var(--red-dark);
}

::selection {
  background: var(--terracotta-soft);
  color: var(--ink);
}

:focus-visible {
  outline: 3px solid var(--red);
  outline-offset: 2px;
  border-radius: 2px;
}

main {
  display: block;
}

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: var(--space-5) 0;
}

/* --------------------------------------------------------------------------
   3. Typography
   -------------------------------------------------------------------------- */
h1,
h2,
h3,
h4 {
  font-family: var(--serif);
  font-weight: 600;
  line-height: 1.12;
  color: var(--ink);
  margin: 0 0 var(--space-3);
  text-wrap: balance;
  font-optical-sizing: auto;
}

/* Larger headings read as display type: tighter tracking, generous line. The
   Fraunces opsz axis (requested in the font link) sharpens the serifs as the
   size grows, so big type feels crafted rather than merely scaled up. */
h1 {
  font-size: clamp(2.4rem, 6vw, 4.1rem);
  letter-spacing: var(--track-display);
  line-height: 1.04;
}

h2 {
  font-size: clamp(1.85rem, 4vw, 2.8rem);
  letter-spacing: -0.006em;
}

h3 {
  font-size: clamp(1.35rem, 2.4vw, 1.7rem);
}

h4 {
  font-size: 1.15rem;
  letter-spacing: 0.01em;
}

p {
  margin: 0 0 var(--space-3);
  text-wrap: pretty;
}

.lead {
  font-size: clamp(1.1rem, 2vw, 1.3rem);
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 46ch;
}

/* Drop cap for one key intro paragraph (used once, on the About story). The
   first letter rises into a brand-red serif initial. */
.dropcap::first-letter {
  float: left;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 3.5em;
  line-height: 0.74;
  margin: 0.06em 0.1em 0 0;
  color: var(--red);
}

/* Cursive/italic brand accent: warm italic serif, used in eyebrows and
   for emphasised words inside headings. */
.accent,
h1 em,
h2 em,
h3 em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  color: var(--terracotta);
}

.eyebrow {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(1.15rem, 2vw, 1.4rem);
  color: var(--terracotta);
  display: block;
  margin: 0 0 var(--space-2);
}

.kicker {
  font-family: var(--sans);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--olive);
  display: block;
  margin: 0 0 var(--space-2);
}

/* --------------------------------------------------------------------------
   4. Layout helpers
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container-narrow {
  max-width: var(--container-narrow);
}

/* Step 26 typography/spacing pass: considerably more breathing space between
   sections (was --space-6 / --space-7). One smooth ramp from phones to the
   full desktop rhythm. */
.section {
  padding-block: clamp(4.25rem, 3rem + 3.5vw, var(--space-8));
}

/* Alternating warm band: a soft cream-to-terracotta wash plus the paper grain
   and hairline edges, so it reads as a distinct surface rather than flat fill. */
.section-alt {
  background-color: var(--cream-2);
  background-image: var(--paper), var(--wash-warm);
  border-block: 1px solid var(--line);
}

.section-head {
  max-width: 640px;
  margin-bottom: var(--space-5);
}

.section-head-center {
  margin-inline: auto;
  text-align: center;
}

.section-head h2 {
  margin-bottom: var(--space-2);
}

.section-head p {
  color: var(--ink-soft);
  margin-bottom: 0;
}

.section-head::after {
  content: '';
  display: block;
  width: 56px;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--red), var(--terracotta));
  margin-top: var(--space-3);
}

.section-head-center::after {
  margin-inline: auto;
}

/* Ornamental divider — a hairline pair flanking a small rose mark derived from
   the logo. Used sparingly to punctuate a section break. Inline rosette SVG
   carries aria-hidden in the markup. */
.ornament {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  width: 100%;
  max-width: 360px;
  margin: var(--space-6) auto;
  color: var(--terracotta);
}

.ornament::before,
.ornament::after {
  content: '';
  flex: 1;
  height: 1px;
}

.ornament::before {
  background: linear-gradient(90deg, transparent, rgba(194, 96, 62, 0.45));
}

.ornament::after {
  background: linear-gradient(90deg, rgba(194, 96, 62, 0.45), transparent);
}

.ornament-mark {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  color: var(--red);
}

/* Rose accent — the one canonical rose (same six-petal rosette as the
   .ornament divider, the JS-injected programme cards and the nav marker) reused
   as a standalone decorative flourish. currentColor; size via a modifier so the
   single shape covers every accent tier. Replaces the former olive sprig. */
.rose-mark {
  display: block;
  width: 32px;
  height: 32px;
  color: var(--terracotta);
  flex-shrink: 0;
}

.rose-mark--xl {
  width: clamp(54px, 9vw, 84px);
  height: auto;
}

.rose-mark--center {
  margin-inline: auto;
}

/* On the dark atmosphere band the softer terracotta reads better over the
   photographic scrim, matching the band's eyebrow/em accents. */
.image-band .rose-mark {
  color: var(--terracotta-soft);
}

/* Full-bleed atmosphere band — a photographic break between stacked sections,
   for cadence. Background image set inline; scrim and copy handled here. */
.image-band {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 340px;
  padding: var(--space-7) var(--gutter);
  background-color: var(--footer-bg);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  color: var(--white);
  overflow: hidden;
}

@media (min-width: 900px) {
  .image-band {
    min-height: 420px;
  }
}

.image-band::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--scrim-band);
}

.image-band-inner {
  position: relative;
  z-index: 1;
  max-width: 640px;
}

.image-band .eyebrow {
  color: var(--terracotta-soft);
}

.image-band h2 {
  color: var(--white);
}

.image-band h2 em {
  color: var(--terracotta-soft);
}

.image-band p {
  color: rgba(255, 255, 255, 0.92);
  margin-inline: auto;
  margin-bottom: 0;
  max-width: 48ch;
}

/* Responsive grids: single column first, stepping up at 640/900/1200 */
.grid-2,
.grid-3,
.grid-4 {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .grid-2,
  .grid-3,
  .grid-4 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .grid-3 {
    grid-template-columns: repeat(3, 1fr);
  }
  .grid-2 {
    gap: var(--space-5);
  }
}

@media (min-width: 1200px) {
  .grid-4 {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* Split row: text beside an image, stacking on mobile */
.split {
  display: grid;
  gap: var(--space-4);
  align-items: center;
}

.split + .split {
  margin-top: var(--space-6);
}

.split .frame img {
  aspect-ratio: 4 / 3;
}

@media (min-width: 900px) {
  .split {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-6);
  }

  .split-flip > .split-media {
    order: 2;
  }
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
}

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-block;
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-btn);
  text-decoration: none;
  text-align: center;
  padding: 0.85em 1.9em;
  border-radius: 999px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: background-color 180ms ease, color 180ms ease,
    border-color 180ms ease, transform 180ms ease, box-shadow 180ms ease;
}

.btn:hover {
  transform: translateY(-2px);
}

.btn:active {
  transform: translateY(0);
}

.btn-primary {
  background: var(--red);
  color: var(--white);
}

.btn-primary:hover {
  background: var(--red-dark);
  color: var(--white);
  box-shadow: 0 10px 22px rgba(221, 19, 27, 0.28);
}

.btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
}

.btn-ghost:hover {
  color: var(--red);
  border-color: var(--red);
}

.btn-ghost-light {
  background: transparent;
  color: var(--white);
  border-color: var(--white);
}

.btn-ghost-light:hover {
  color: var(--white);
  background: rgba(255, 255, 255, 0.14);
}

/* --------------------------------------------------------------------------
   6. Cards
   -------------------------------------------------------------------------- */
.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: transform 200ms ease, box-shadow 200ms ease;
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift);
}

.card img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  /* Gentle zoom on card hover (the card clips overflow). Transform-only. */
  transition: transform 450ms var(--ease-out);
}

.card:hover img {
  transform: scale(1.045);
}

.card-body {
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1;
}

.card-body h3 {
  margin-bottom: 0;
}

.card-body p {
  color: var(--ink-soft);
  margin-bottom: 0;
  flex: 1;
}

.card-body .btn {
  align-self: flex-start;
  margin-top: var(--space-2);
}

/* --------------------------------------------------------------------------
   7. Image frame — photo with an offset terracotta keyline
   -------------------------------------------------------------------------- */
.frame {
  position: relative;
  display: inline-block;
  max-width: 100%;
  /* In a grid/flex row the keyline must hug the image, not stretch to the
     height of a taller sibling. */
  align-self: start;
}

.frame img {
  width: 100%;
  object-fit: cover;
}

.frame img {
  position: relative;
  z-index: 1;
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
}

.frame::before {
  content: '';
  position: absolute;
  inset: 0;
  transform: translate(12px, 12px);
  border: 2px solid var(--terracotta);
  border-radius: var(--radius);
  z-index: 0;
}

.frame-olive::before {
  border-color: var(--olive);
}

/* --------------------------------------------------------------------------
   8. Header / navigation (injected into #app-nav by site.js)
   -------------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  top: -48px;
  left: var(--space-3);
  z-index: 200;
  background: var(--ink);
  color: var(--white);
  padding: 0.6em 1.2em;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  text-decoration: none;
  transition: top 150ms ease;
}

.skip-link:focus {
  top: 0;
  color: var(--white);
}

/* Reserve the nav height on the empty placeholder so injecting the sticky
   bar (site.js sets class + innerHTML on #app-nav) does not push <main> down
   and cause layout shift. :empty only matches pre-injection, so it never
   fights the scroll-shrink once the bar is populated. */
#app-nav:empty {
  display: block;
  min-height: var(--nav-h);
}

.site-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(250, 246, 238, 0.92);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid transparent;
  transition: border-color 200ms ease, box-shadow 200ms ease;
}

.site-nav.scrolled {
  border-bottom-color: var(--line);
  box-shadow: var(--shadow-soft);
}

.nav-inner {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  transition: height 200ms ease;
}

.site-nav.scrolled .nav-inner {
  height: var(--nav-h-scrolled);
}

.brand {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}

.brand svg {
  height: calc(var(--nav-h) - 20px);
  width: auto;
  transition: height 200ms ease;
}

.site-nav.scrolled .brand svg {
  height: calc(var(--nav-h-scrolled) - 18px);
}

/* The harvested logo wordmark is white; over the cream header recolour it
   to ink so it stays legible. The rose keeps its brand red. */
.site-nav .brand svg path[fill='#fff'] {
  fill: var(--ink);
}

.nav-primary {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.nav-links {
  list-style: none;
  display: flex;
  align-items: center;
  gap: clamp(0.7rem, 1.4vw, 1.4rem);
  margin: 0;
  padding: 0;
}

.nav-links a {
  display: block;
  position: relative;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  text-decoration: none;
  color: var(--ink);
  padding: 0.4em 0.1em;
  /* Labels never break mid-phrase in the bar ("What's On", "Private Dining");
     the snug desktop gaps below are sized so nothing overflows instead. */
  white-space: nowrap;
  transition: color 150ms ease;
}

/* Animated underline: scales in from the left on hover/focus, and sits full
   for the current page. Transform-only, so it is cheap and reduced-motion
   simply makes it appear instantly. */
.nav-links a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--red);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 200ms var(--ease-out);
}

.nav-links a:hover,
.nav-links a:focus-visible {
  color: var(--red);
}

.nav-links a:hover::after,
.nav-links a:focus-visible::after,
.nav-links a.active::after {
  transform: scaleX(1);
}

/* Active-page marker — a small red rose on the current page's link. The link
   already has position:relative for its underline, so on the desktop bar the
   rose is absolutely positioned just ABOVE the label: it pins the current item
   between the rose (top) and the underline (bottom) and, crucially, adds zero
   horizontal width, so the full 10-link bar cannot be tipped into overflow at
   the step-20 breakpoints (the bar is already snug at 1100px). It is in the
   injected markup from first paint, so it never shifts the layout (CLS ~0).
   aria-current="page" stays the accessible signal; the rose is aria-hidden.
   The mobile overlay (<=1099px) has room to spare, so there the rose sits
   inline beside the label instead (see the hamburger block). */
.nav-links a.active {
  color: var(--red);
}

.nav-rose {
  position: absolute;
  left: 50%;
  bottom: 100%;
  transform: translateX(-50%);
  margin-bottom: -0.5em;
  width: 17px;
  height: auto;
  color: var(--red);
  pointer-events: none;
}

.nav-cta {
  white-space: nowrap;
}

/* "More" dropdown (step 23) — the secondary pages behind a disclosure so the
   bar stays uncluttered. The closed panel is absolutely positioned and in the
   injected markup from first paint, so opening it never reflows the bar and
   the CLS budget holds. */
.nav-more {
  position: relative;
}

.nav-more-toggle {
  display: flex;
  align-items: center;
  gap: 0.35em;
  position: relative;
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink);
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 0.4em 0.1em;
  transition: color 150ms ease;
}

.nav-more-toggle:hover,
.nav-more-toggle:focus-visible,
.nav-more.open .nav-more-toggle {
  color: var(--red);
}

/* When the current page lives inside the dropdown, the toggle carries the
   active colour so the bar still says "you are here". */
.nav-more-toggle.has-active {
  color: var(--red);
}

.nav-more-caret {
  flex: 0 0 auto;
  transition: transform 200ms var(--ease-out);
}

.nav-more.open .nav-more-caret {
  transform: rotate(180deg);
}

.nav-more-menu {
  list-style: none;
  margin: 0;
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  z-index: 120;
  min-width: 200px;
  padding: 6px;
  background: var(--cream);
  background-image: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lift);
  opacity: 0;
  visibility: hidden;
  transform: translateX(-50%) translateY(-6px);
  transition: opacity var(--dur-menu) var(--ease-out),
    transform var(--dur-menu) var(--ease-out),
    visibility 0s linear var(--dur-menu);
}

.nav-more.open .nav-more-menu {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%);
  transition: opacity var(--dur-menu) var(--ease-out),
    transform var(--dur-menu) var(--ease-out);
}

/* Dropdown items inherit the .nav-links a look but sit in a panel: give them
   room, drop the animated underline, and show the rose inline. */
.nav-more-menu a {
  padding: 0.55em 0.85em;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}

.nav-more-menu a::after {
  display: none;
}

.nav-more-menu a:hover,
.nav-more-menu a:focus-visible {
  background: var(--cream-2);
}

.nav-more-menu a.active {
  display: flex;
  align-items: center;
  gap: 0.4em;
}

.nav-more-menu .nav-rose {
  position: static;
  transform: none;
  margin: 0;
  width: auto;
  height: 1em;
  flex-shrink: 0;
}

/* Mobile-only Book a Table in the top bar (step 26) — hidden on the desktop
   bar, which carries the full Book a Table CTA instead. */
.nav-book-top {
  display: none;
}

/* Desktop bar spacing (step 26). The bar carries 7 links + More + Book a
   Table, and the Round 8 labels are longer (Private Dining & Events, Gift
   Vouchers), so the pre-23 gap defaults would overflow it. Snug gaps at
   every bar width keep the row inside its box. */
@media (min-width: 1100px) {
  .nav-primary {
    gap: var(--space-3);
  }

  .nav-links {
    gap: clamp(0.5rem, 0.85vw, 1.3rem);
  }
}

/* The tightest band of the bar (1100-1199px): with single-line labels the
   full row overflows the viewport, so the bar type steps down a notch
   here only (still comfortably legible; back to 0.8rem from 1200px). */
@media (min-width: 1100px) and (max-width: 1199px) {
  .nav-links a,
  .nav-more-toggle {
    font-size: 0.72rem;
    letter-spacing: 0.05em;
  }

  .nav-links {
    gap: 0.45rem;
  }
}

/* From 1320px the header row (only) gets a wider ceiling so the long Round 8
   labels breathe — the page sections stay on the 1160px container. */
@media (min-width: 1320px) {
  .nav-inner {
    max-width: 1320px;
  }
}

/* Hamburger — a labelled MENU control (step 26 target: LOGO | MENU), the
   word beside the three lines. The label is part of the accessible name
   (aria-label "Open menu" / "Close menu" keeps it in-name). */
.nav-toggle {
  display: none;
  align-items: center;
  gap: 0.55em;
  min-width: 44px;
  height: 44px;
  padding: 10px 12px;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.nav-toggle-label {
  font-family: inherit;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink);
}

.nav-toggle-lines {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 20px;
}

.nav-toggle-lines span {
  display: block;
  width: 100%;
  height: 2px;
  border-radius: 2px;
  background: var(--ink);
  transition: transform 200ms ease, opacity 200ms ease;
}

.site-nav.open .nav-toggle-lines span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.site-nav.open .nav-toggle-lines span:nth-child(2) {
  opacity: 0;
}

.site-nav.open .nav-toggle-lines span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* Hamburger overlay takes over up to 1099px. The full horizontal bar (10
   links + Book CTA) does not fit until ~1100px, so large tablets / small
   laptops get the roomier overlay instead of a cramped or overflowing bar
   (extends the step-13 decision; was 1023px before the Community link was
   added in step 17 pushed the bar over the edge at 1024px). */
@media (max-width: 1099px) {
  .nav-toggle {
    display: flex;
  }

  /* Keep the logo, the Book a Table pill and the hamburger/X above the
     overlay and tappable. */
  .brand,
  .nav-book-top,
  .nav-toggle {
    position: relative;
    z-index: 110;
  }

  /* Discreet, persistent Book a Table in the top bar, between the logo and
     the MENU toggle (step 26). A quiet outlined pill rather than the loud
     primary fill — visible at all times (the header is sticky) without
     shouting. margin-left: auto packs it against the toggle; a >=40px hit
     area keeps it comfortable. */
  .nav-book-top {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    margin-left: auto;
    padding: 0 0.95em;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    white-space: nowrap;
    color: var(--red);
    border: 1px solid currentColor;
    border-radius: 999px;
    text-decoration: none;
    transition: color 150ms ease, background-color 150ms ease;
  }

  .nav-book-top:hover,
  .nav-book-top:focus-visible {
    color: var(--white);
    background: var(--red);
  }

  /* The overlay below is position:fixed and must size to the viewport. The
     header's backdrop-filter would otherwise become its containing block, so
     it is dropped while the menu is open (the overlay is opaque, no blur is
     needed then). */
  .site-nav.open {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  /* Full-screen menu overlay */
  .nav-primary {
    position: fixed;
    inset: 0;
    z-index: 95;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    /* `safe center` keeps a tall menu scrollable from the top on short
       screens instead of clipping above the viewport. */
    justify-content: safe center;
    gap: var(--space-2);
    padding: calc(var(--nav-h) + var(--space-4)) var(--gutter) var(--space-6);
    background: var(--cream);
    background-image: var(--paper);
    overflow-y: auto;
    overscroll-behavior: contain;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-10px);
    transition: opacity var(--dur-menu) var(--ease-out),
      transform var(--dur-menu) var(--ease-out),
      visibility 0s linear var(--dur-menu);
  }

  .site-nav.open .nav-primary {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: opacity var(--dur-menu) var(--ease-out),
      transform var(--dur-menu) var(--ease-out);
  }

  .nav-links {
    flex-direction: column;
    align-items: center;
    gap: var(--space-1);
    padding: 0;
  }

  .nav-links a {
    display: block;
    font-size: 1.3rem;
    letter-spacing: 0.05em;
    text-align: center;
    padding: 0.5em var(--gutter);
  }

  /* The animated bottom underline doesn't suit the centred overlay list. */
  .nav-links a::after {
    display: none;
  }

  /* Overlay has room to spare, so the rose sits inline beside the label here
     (em-sized so it scales with the larger overlay type). */
  .nav-links a.active {
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    color: var(--red);
  }

  .nav-rose {
    position: static;
    transform: none;
    margin: 0;
    width: auto;
    height: 1.05em;
    flex-shrink: 0;
  }

  /* The overlay carries no phone entry (steps 23/26): phone numbers stay
     tappable in page content and the footer, never as a header control. */

  /* "More" group expands inline inside the overlay: the same disclosure
     control, restyled as a list heading with its items indented beneath. */
  .nav-more {
    position: static;
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .nav-more-toggle {
    font-size: 1.3rem;
    letter-spacing: 0.05em;
    padding: 0.5em var(--gutter);
  }

  .nav-more-menu {
    position: static;
    display: none;
    min-width: 0;
    padding: 0;
    margin: 0;
    background: transparent;
    background-image: none;
    border: 0;
    box-shadow: none;
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: none;
    text-align: center;
  }

  .nav-more.open .nav-more-menu {
    display: block;
    transform: none;
  }

  .nav-more-menu a {
    font-size: 1.05rem;
    padding: 0.45em var(--gutter);
    border-radius: 0;
    white-space: normal;
  }

  .nav-more-menu a:hover,
  .nav-more-menu a:focus-visible {
    background: transparent;
  }

  .nav-more-menu a.active {
    display: inline-flex;
  }

  .nav-cta {
    margin-top: var(--space-3);
  }
}

/* Narrow screens: tighten the Book a Table pill first, and only on the very
   narrowest (~320px) drop the MENU word (the lines + aria-label still carry
   the control's meaning). */
@media (max-width: 419px) {
  .nav-book-top {
    padding: 0 0.7em;
    font-size: 0.62rem;
    letter-spacing: 0.05em;
  }
}

@media (max-width: 359px) {
  .nav-toggle-label {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   9. Footer (injected into #app-footer by site.js)
   -------------------------------------------------------------------------- */
.site-footer {
  background: var(--footer-bg);
  color: var(--footer-text);
  margin-top: var(--space-6);
  font-size: 0.95rem;
}

.footer-grid {
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--space-6) var(--gutter) var(--space-5);
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .footer-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .footer-grid {
    grid-template-columns: 1.3fr 1fr 1fr 1.1fr;
  }
}

.footer-brand svg {
  height: 84px;
  width: auto;
  margin-bottom: var(--space-3);
}

.footer-blurb {
  color: var(--footer-dim);
  max-width: 30ch;
}

.site-footer h4 {
  color: var(--white);
  font-size: 1.05rem;
  margin-bottom: var(--space-3);
}

.site-footer h4 .accent {
  color: var(--terracotta-soft);
}

.site-footer address {
  font-style: normal;
  color: var(--footer-dim);
}

.site-footer a {
  color: var(--footer-text);
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--white);
  text-decoration: underline;
}

.footer-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.footer-hours {
  list-style: none;
  margin: 0;
  padding: 0;
  color: var(--footer-dim);
}

.footer-hours li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: 2px;
}

.footer-hours .today {
  color: var(--white);
  font-weight: 700;
}

.footer-hours-note {
  display: block;
  margin-top: var(--space-3);
  color: var(--footer-dim);
  font-size: 0.85rem;
}

.footer-bottom {
  border-top: 1px solid rgba(239, 231, 218, 0.15);
}

.footer-bottom-inner {
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--space-3) var(--gutter);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  color: var(--footer-dim);
  font-size: 0.85rem;
}

.footer-bottom-inner a {
  color: var(--footer-dim);
  text-decoration: underline;
}

.footer-bottom-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
}

/* --------------------------------------------------------------------------
   10. Scroll reveal
   -------------------------------------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur-reveal) var(--ease-out),
    transform var(--dur-reveal) var(--ease-out);
}

.reveal.visible {
  opacity: 1;
  transform: none;
}

.reveal-stagger > * {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur-reveal) var(--ease-out),
    transform var(--dur-reveal) var(--ease-out);
}

.reveal-stagger.visible > * {
  opacity: 1;
  transform: none;
}

.reveal-stagger.visible > :nth-child(2) {
  transition-delay: 100ms;
}

.reveal-stagger.visible > :nth-child(3) {
  transition-delay: 200ms;
}

.reveal-stagger.visible > :nth-child(4) {
  transition-delay: 300ms;
}

.reveal-stagger.visible > :nth-child(5) {
  transition-delay: 400ms;
}

.reveal-stagger.visible > :nth-child(n + 6) {
  transition-delay: 500ms;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
  }

  .reveal,
  .reveal-stagger > * {
    opacity: 1;
    transform: none;
  }

  /* Hero: no Ken Burns drift, no entrance, no scroll-settle. Content present.
     !important is needed because the hero rules are defined later in the file
     (and on inline styles set by the scroll handler), so without it they would
     win on source order. */
  .hero-slide {
    animation: none !important;
    transform: none !important;
  }

  .home-hero-logo,
  .home-hero h1,
  .home-hero .hero-experiences,
  .home-hero .cluster {
    animation: none !important;
  }

  .home-hero-inner {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* --------------------------------------------------------------------------
   11. Misc utilities
   -------------------------------------------------------------------------- */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

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

.text-center .lead {
  margin-inline: auto;
}

.cluster-center {
  justify-content: center;
}

.noscript-note {
  display: block;
  background: var(--terracotta-soft);
  color: var(--ink);
  padding: var(--space-3) var(--gutter);
  text-align: center;
}

/* --------------------------------------------------------------------------
   12. Home hero
   -------------------------------------------------------------------------- */
.home-hero {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: min(86vh, 720px);
  min-height: min(86svh, 720px);
  padding: var(--space-7) var(--gutter);
  background: var(--footer-bg);
  overflow: hidden;
}

/* Rotating hero (step 18): a crossfading stack of experience-led slides. Each
   slide fills the hero (object-fit: cover), so the fixed min-height means the
   image ratio never causes layout shift. Only opacity animates between slides.
   The first slide carries .is-active in the HTML, so it paints immediately with
   no fade-in on load and is the LCP image (eager + fetchpriority=high). */
.hero-slides {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero-slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.04);
  transition: opacity 1500ms var(--ease-out), transform 1500ms var(--ease-out);
}

/* The active slide fades up and gets a slow Ken Burns drift. Adding .is-active
   (in JS, or in the HTML for the first slide) restarts the keyframes, so each
   slide drifts afresh while it is shown. Stays above scale 1 throughout so the
   scrim-covered image always fills the frame (no edge gap). The outgoing slide
   eases transform back to the base scale as it fades, so there is no snap. */
.hero-slide.is-active {
  opacity: 1;
  animation: hero-kenburns 9s var(--ease-out) forwards;
  will-change: opacity, transform;
}

@keyframes hero-kenburns {
  from { transform: scale(1.04) translateY(0); }
  /* Small upward drift; at scale 1.1 there is ~5% overflow each edge, so a
     1.2% lift never uncovers the frame. */
  to   { transform: scale(1.1) translateY(-1.2%); }
}

/* Three-experience teaser beneath the headline (step 23: label-only cards —
   the grey description lines and the step-22 supporting strapline were removed
   at the 2026-07-22 owner review, so each card is just its linked name). */
.hero-experiences {
  list-style: none;
  margin: var(--space-4) auto 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
  max-width: 600px;
  text-align: left;
}

.hero-experiences a {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  height: 100%;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm, 8px);
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(20, 12, 10, 0.28);
  color: var(--white);
  text-decoration: none;
  transition: background 0.25s var(--ease-out), border-color 0.25s var(--ease-out), transform 0.25s var(--ease-out);
}

.hero-experiences a:hover,
.hero-experiences a:focus-visible {
  background: rgba(221, 19, 27, 0.55);
  border-color: rgba(255, 255, 255, 0.6);
  transform: translateY(-2px);
}

.hero-exp-label {
  display: block;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.05rem;
  line-height: 1.2;
}

@media (min-width: 760px) {
  .hero-experiences {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-3);
    max-width: 880px;
    text-align: center;
  }
}

@media (max-width: 759px) {
  /* Keep headline + experience labels + CTAs above the fold on phones:
     tighten the logo and hero padding. */
  .home-hero {
    padding-block: var(--space-6);
  }

  .home-hero-logo {
    width: clamp(104px, 22vw, 150px);
    margin-bottom: var(--space-3);
  }

  .hero-experiences {
    margin-top: var(--space-3);
  }
}

/* Slide dots — manual controls for the rotation. Built by initHero(); none are
   rendered under reduced motion (a single static slide is shown instead). */
.hero-dots {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: var(--space-3);
  display: flex;
  justify-content: center;
  gap: 10px;
}

.hero-dots:empty {
  display: none;
}

.hero-dot {
  width: 11px;
  height: 11px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.75);
  background: rgba(255, 255, 255, 0.28);
  cursor: pointer;
  transition: background 0.3s var(--ease-out), transform 0.3s var(--ease-out);
}

.hero-dot.is-active {
  background: var(--white);
  transform: scale(1.2);
}

.hero-dot:focus-visible {
  outline: 2px solid var(--white);
  outline-offset: 3px;
}

.home-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--scrim-hero);
}

.home-hero-inner {
  position: relative;
  z-index: 1;
  max-width: 720px;
  color: var(--white);
}

/* Framed-corner motif around the hero copy — picks up the offset keyline used
   on photos elsewhere. Desktop only (the hero clips overflow, so no scroll);
   on phones the copy fills the width and the brackets would crowd it. */
.home-hero-inner::before,
.home-hero-inner::after {
  content: '';
  position: absolute;
  display: none;
  width: 28px;
  height: 28px;
  border: 0 solid rgba(255, 255, 255, 0.5);
}

.home-hero-inner::before {
  top: -22px;
  left: -22px;
  border-top-width: 2px;
  border-left-width: 2px;
}

.home-hero-inner::after {
  bottom: -22px;
  right: -22px;
  border-bottom-width: 2px;
  border-right-width: 2px;
}

@media (min-width: 900px) {
  .home-hero-inner::before,
  .home-hero-inner::after {
    display: block;
  }
}

.home-hero-logo {
  width: clamp(140px, 24vw, 200px);
  height: auto;
  margin-inline: auto;
  margin-bottom: var(--space-4);
  filter: drop-shadow(0 4px 14px rgba(0, 0, 0, 0.35));
}

.home-hero h1 {
  color: var(--white);
}

.home-hero h1 em {
  color: var(--terracotta-soft);
}

.home-hero .lead {
  color: rgba(255, 255, 255, 0.92);
  margin-inline: auto;
}

.home-hero .cluster {
  justify-content: center;
  margin-top: var(--space-4);
}

/* Refined entrance: logo, headline, strapline and CTAs fade-and-rise in a
   short stagger on load. Pure CSS (runs without waiting on JS); animating
   only opacity + transform, so it adds no layout shift. `both` fill keeps each
   element hidden until its turn, avoiding a flash of unstyled content.
   The whole sequence is neutralised under prefers-reduced-motion. */
.home-hero-logo,
.home-hero h1,
.home-hero .hero-experiences,
.home-hero .cluster {
  animation: hero-rise 760ms var(--ease-out) both;
}

.home-hero-logo  { animation-delay: 80ms; }
.home-hero h1    { animation-delay: 200ms; }
.home-hero .hero-experiences { animation-delay: 320ms; }
.home-hero .cluster { animation-delay: 440ms; }

@keyframes hero-rise {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   13. Promo ticker — duplicated list scrolls by -50% for a seamless loop
   -------------------------------------------------------------------------- */
.ticker {
  background: var(--red);
  color: var(--white);
  overflow: hidden;
  padding-block: 0.75em;
}

.ticker-track {
  display: flex;
  width: max-content;
  animation: ticker-scroll 42s linear infinite;
}

.ticker:hover .ticker-track,
.ticker:focus-within .ticker-track {
  animation-play-state: paused;
}

.ticker-items {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  white-space: nowrap;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
}

.ticker-items li {
  display: flex;
  align-items: center;
}

.ticker-items li::after {
  content: '\2726';
  margin-inline: 1.6rem;
  color: rgba(255, 255, 255, 0.55);
  font-size: 0.7em;
}

/* Ribbon items link to their destinations (step 26) — quiet inline links
   that pick up an underline on hover/focus; the ticker already pauses on
   hover and focus-within. */
.ticker-items a {
  color: inherit;
  text-decoration: none;
}

.ticker-items a:hover,
.ticker-items a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

@keyframes ticker-scroll {
  to {
    transform: translateX(-50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .ticker {
    overflow-x: auto;
  }

  .ticker-track {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   14. Gift voucher denominations
   -------------------------------------------------------------------------- */
.voucher-amounts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-block: var(--space-4);
}

.voucher-amount {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(1.5rem, 3.5vw, 2rem);
  color: var(--red);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  padding: 0.3em 0.75em;
}

/* Occasion chips above the denominations (single-sourced from vouchers.json) */
.voucher-occasions {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.voucher-occasions li {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--ink);
  background: var(--olive-soft);
  border-radius: 999px;
  padding: 0.4em 0.95em;
}

.voucher-note {
  color: var(--ink-soft);
  margin: 0 0 var(--space-4);
}

/* Centred variant for standalone voucher bands (functions / food) */
.voucher-feature--center {
  text-align: center;
}

.voucher-feature--center .voucher-occasions,
.voucher-feature--center .voucher-amounts {
  justify-content: center;
}

.voucher-feature--center .voucher-note {
  margin-inline: auto;
  max-width: 56ch;
}

/* --------------------------------------------------------------------------
   15. Instagram grid
   -------------------------------------------------------------------------- */
.insta-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-2);
}

@media (min-width: 640px) {
  .insta-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.insta-grid a {
  display: block;
  overflow: hidden;
  border-radius: var(--radius-sm);
}

.insta-grid img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  transition: transform 250ms ease;
}

.insta-grid a:hover img,
.insta-grid a:focus-visible img {
  transform: scale(1.04);
}

.insta-grid + .text-center {
  margin-top: var(--space-4);
}

/* --------------------------------------------------------------------------
   16. Page hero — banner used by every page except home
   -------------------------------------------------------------------------- */
.page-hero {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 340px;
  padding: var(--space-6) var(--gutter);
  background: var(--footer-bg);
  overflow: hidden;
}

@media (min-width: 900px) {
  .page-hero {
    min-height: 420px;
  }
}

.page-hero-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.page-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(28, 18, 14, 0.46),
    rgba(28, 18, 14, 0.62)
  );
}

.page-hero-inner {
  position: relative;
  z-index: 1;
  max-width: 680px;
  color: var(--white);
}

.page-hero h1 {
  color: var(--white);
  margin-bottom: var(--space-2);
}

.page-hero h1 em {
  color: var(--terracotta-soft);
}

.page-hero .lead {
  color: rgba(255, 255, 255, 0.92);
  margin-inline: auto;
}

.page-hero .btn {
  margin-top: var(--space-3);
}

/* --------------------------------------------------------------------------
   17. Menu pages — sticky jump nav, menu blocks, item rows
   -------------------------------------------------------------------------- */
.menu-jump {
  position: sticky;
  top: var(--nav-h-scrolled);
  z-index: 50;
  background: rgba(250, 246, 238, 0.95);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.menu-jump:empty {
  display: none;
}

.menu-jump-inner {
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--space-2) var(--gutter);
  display: flex;
  gap: var(--space-2);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.menu-jump-inner::-webkit-scrollbar {
  display: none;
}

.menu-jump a {
  flex-shrink: 0;
  font-size: 0.76rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  text-decoration: none;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.5em 1.1em;
  transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease;
}

.menu-jump a:hover {
  color: var(--red);
  border-color: var(--red);
}

.menu-jump a.active {
  background: var(--red);
  border-color: var(--red);
  color: var(--white);
}

.menu-block {
  padding-block: var(--space-5);
  scroll-margin-top: calc(var(--nav-h-scrolled) + 72px);
}

.menu-block + .menu-block {
  border-top: 1px solid var(--line);
}

.menu-head {
  max-width: 640px;
}

.menu-head h2 {
  margin-bottom: var(--space-1);
}

.menu-sub {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(1.1rem, 2vw, 1.3rem);
  color: var(--terracotta);
}

.menu-intro {
  background: var(--cream-2);
  border-left: 3px solid var(--terracotta);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  margin-block: var(--space-3) var(--space-4);
  color: var(--ink-soft);
}

.menu-intro p:last-child {
  margin-bottom: 0;
}

.menu-section {
  margin-top: var(--space-5);
}

.menu-section h3 {
  margin-bottom: var(--space-1);
}

.menu-section-intro {
  font-style: italic;
  color: var(--ink-soft);
}

.menu-items {
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}

@media (min-width: 900px) {
  .menu-items {
    grid-template-columns: 1fr 1fr;
    column-gap: var(--space-6);
  }
}

.mi-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.mi-name {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.08rem;
}

.mi-origin {
  display: block;
  font-family: var(--sans);
  font-weight: 700;
  font-size: 0.68rem;
  letter-spacing: var(--track-label);
  color: var(--ink-soft);
}

.badge-v {
  display: inline-block;
  font-family: var(--sans);
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.05em;
  padding: 0.3em 0.5em;
  border-radius: 4px;
  background: var(--olive-soft);
  color: var(--olive);
  vertical-align: 0.15em;
}

.mi-leader {
  flex: 1;
  min-width: 1.5rem;
  border-bottom: 2px dotted var(--line);
  transform: translateY(-0.25em);
}

.mi-price {
  font-weight: 700;
  white-space: nowrap;
}

.serve-note {
  font-weight: 400;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.mi-serves {
  list-style: none;
  margin: 0;
  padding: 0;
  text-align: right;
}

.mi-serves li {
  white-space: nowrap;
}

.serve-size {
  font-size: 0.75rem;
  color: var(--ink-soft);
  margin-right: 0.5em;
}

.serve-price {
  font-weight: 700;
}

.mi-desc {
  color: var(--ink-soft);
  font-size: 0.95rem;
  margin: var(--space-1) 0 0;
  max-width: 56ch;
}

.mi-note {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--terracotta);
  margin: var(--space-1) 0 0;
}

.menu-fallback {
  background: var(--terracotta-soft);
  border-radius: var(--radius);
  padding: var(--space-5) var(--space-4);
  text-align: center;
  margin-block: var(--space-5);
}

.menu-fallback p {
  margin: 0;
  max-width: 46ch;
  margin-inline: auto;
}

/* Delivery platform tiles (food.html takeaway section) */
.delivery-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
}

.delivery-link {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  min-width: 10rem;
  padding: var(--space-4) var(--space-3);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  text-decoration: none;
  color: var(--ink);
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-btn);
  transition: transform 200ms ease, box-shadow 200ms ease;
}

.delivery-link img {
  height: 44px;
  width: auto;
}

.delivery-link:hover,
.delivery-link:focus-visible {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
  color: var(--red);
}

/* Reserve space while async JSON containers are empty, preventing a large
   layout shift when the fetch resolves on a slow connection. */
[data-offers-source]:empty,
#events-root:empty,
#menu-root:empty {
  min-height: 220px;
}

/* --------------------------------------------------------------------------
   18. Floating book button — shown by site.js once the hero is scrolled past
   -------------------------------------------------------------------------- */
.floating-book {
  position: fixed;
  right: var(--space-3);
  bottom: var(--space-3);
  z-index: 90;
  box-shadow: var(--shadow-lift);
  opacity: 0;
  transform: translateY(14px);
  pointer-events: none;
  transition: opacity 220ms ease, transform 220ms ease;
}

.floating-book.visible {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* --------------------------------------------------------------------------
   19. Venue hire & events pages (functions / events / christmas)
   -------------------------------------------------------------------------- */

/* Capacity strapline under a hire-space heading */
.hire-capacity {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.2rem;
  line-height: 1.3;
  color: var(--terracotta);
  margin: 0 0 var(--space-3);
}

/* Verbatim hire small print (minimum spend, time-slot terms) */
.small-print {
  font-size: 0.85rem;
  color: var(--ink-soft);
  border-left: 3px solid var(--olive-soft);
  padding-left: var(--space-3);
  margin-top: var(--space-4);
}

/* Recurring "what's on" weekly cards */
.whatson-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  height: 100%;
  overflow: hidden;
}

.whatson-card-fig {
  margin: calc(-1 * var(--space-4)) calc(-1 * var(--space-4)) 0;
  flex-shrink: 0;
}

.whatson-card-fig img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.whatson-card h3 {
  margin: 0;
}

.whatson-card p {
  color: var(--ink-soft);
  margin: 0;
  flex: 1;
}

.day-badge {
  align-self: flex-start;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--white);
  background: var(--olive);
  border-radius: 999px;
  padding: 0.35em 0.95em;
}

.whatson-link {
  align-self: flex-start;
  margin-top: var(--space-1);
  font-weight: 700;
  font-size: 0.9rem;
  text-decoration: none;
}

.whatson-link:hover {
  text-decoration: underline;
}

/* One-off / dated events and the Christmas "coming soon" blocks */
.events-list {
  display: grid;
  gap: var(--space-4);
}

.event-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-left: 4px solid var(--red);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
}

.event-card-body {
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.event-card h3 {
  margin: 0;
}

.event-when {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.1rem;
  color: var(--terracotta);
  margin: 0;
}

.event-price {
  align-self: flex-start;
  font-weight: 700;
  color: var(--red);
  background: var(--terracotta-soft);
  border-radius: 999px;
  padding: 0.35em 1.1em;
  margin: 0;
}

.event-desc {
  color: var(--ink-soft);
  margin: 0;
}

.event-notes {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin: 0;
}

.event-card .btn {
  align-self: flex-start;
}

/* Event card with a promo image (e.g. a poster supplied by the venue).
   Step 24 (owner request): the poster sits full width ABOVE the copy at
   every breakpoint, at its natural aspect ratio. Posters carry dates,
   times and booking details, so never crop, letterbox or fix a height on
   them. overflow: hidden keeps the poster's top corners rounded with the
   card while the red left border still reads. */
.event-card-has-media {
  overflow: hidden;
}

.event-card-media {
  margin: 0;
}

.event-card-media img {
  display: block;
  width: 100%;
  height: auto;
}

/* Empty state when no events match (e.g. no one-off events listed) */
.empty-state {
  text-align: center;
  background: var(--cream-2);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: var(--space-6) var(--space-4);
}

.empty-state p {
  color: var(--ink-soft);
  margin: 0 auto var(--space-4);
  max-width: 36ch;
}

/* Supper Club feature — owner-approved evergreen message (events.html) */
.supper-club {
  position: relative;
  background: var(--terracotta-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  padding: var(--space-6) var(--space-5);
  text-align: center;
  overflow: hidden;
}

@media (min-width: 720px) {
  .supper-club {
    padding: var(--space-7) var(--space-6);
  }
}

.supper-club h2,
.supper-club h3 {
  margin: 0 0 var(--space-2);
  font-size: clamp(1.5rem, 1.1rem + 1.8vw, 2.1rem);
}

.supper-club-tagline {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.25rem;
  color: var(--terracotta);
  margin: 0 0 var(--space-4);
}

.supper-club-lead {
  color: var(--ink-soft);
  max-width: 62ch;
  margin: 0 auto;
}

.supper-club-note {
  font-weight: 700;
  color: var(--ink);
  margin: var(--space-3) 0 0;
}

.supper-club .cluster {
  justify-content: center;
  margin-top: var(--space-4);
}

/* The Lugano's evolving events programme — strand cards (events.html) */
.programme-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .programme-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 980px) {
  .programme-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.programme-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  height: 100%;
}

.programme-mark {
  width: 26px;
  height: 26px;
  color: var(--red);
  opacity: 0.85;
}

.programme-card h3 {
  margin: 0;
  font-size: 1.15rem;
}

.programme-card p {
  color: var(--ink-soft);
  margin: 0;
  flex: 1;
}

.programme-when {
  flex: 0 0 auto;
  font-family: var(--serif);
  font-style: italic;
  color: var(--terracotta);
}

.programme-card .whatson-link {
  flex: 0 0 auto;
}

/* VIP Guest List — register-interest feature (events.html) */
.vip-card {
  background: linear-gradient(160deg, var(--cream-2) 0%, var(--terracotta-soft) 100%);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  padding: var(--space-6) var(--space-5);
  text-align: center;
}

@media (min-width: 720px) {
  .vip-card {
    padding: var(--space-7) var(--space-6);
  }
}

.vip-card h2 {
  margin: 0 0 var(--space-2);
}

.vip-card .lead {
  margin: 0 auto var(--space-4);
  max-width: 52ch;
}

.vip-perks {
  list-style: none;
  padding: 0;
  margin: 0 auto var(--space-5);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  max-width: 42ch;
}

.vip-perks li {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.4em 1em;
}

.vip-note {
  margin: 0 auto var(--space-4);
  max-width: 48ch;
  color: var(--ink-soft);
}

.vip-consent-note {
  margin: var(--space-3) auto 0;
  max-width: 54ch;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

/* VIP MailChimp embedded form (step 23). Ready-styled for the wiring template
   in the events.html comment — unused until the owner supplies their MailChimp
   embed code (audience-specific u/id values; do NOT invent them). Matches the
   site system: Karla fields, red primary button, soft cream card tones. */
.vip-form {
  margin: 0 auto;
  max-width: 420px;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  text-align: left;
}

.vip-field label {
  display: block;
  margin-bottom: var(--space-1);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--ink);
}

.vip-field input {
  width: 100%;
  min-height: 48px;
  padding: 0.6em 0.9em;
  font: inherit;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.vip-field input:focus-visible {
  outline: 3px solid var(--red);
  outline-offset: 1px;
}

.vip-consent {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.vip-consent input {
  flex: 0 0 auto;
  width: 1.15em;
  height: 1.15em;
  margin-top: 0.15em;
  accent-color: var(--red);
}

.vip-form .btn {
  align-self: center;
}

/* --------------------------------------------------------------------------
   20. Info pages (contact / about / gallery / privacy / 404)
   -------------------------------------------------------------------------- */

/* Text-only hero for pages with no banner photo */
.page-hero-text {
  min-height: 240px;
  background: linear-gradient(155deg, var(--cream-2) 0%, var(--terracotta-soft) 100%);
}

.page-hero-text::after {
  display: none;
}

.page-hero-text .page-hero-inner {
  color: var(--ink);
}

.page-hero-text h1 {
  color: var(--ink);
}

.page-hero-text h1 em {
  color: var(--terracotta);
}

.page-hero-text .lead {
  color: var(--ink-soft);
}

@media (min-width: 900px) {
  .page-hero-text {
    min-height: 300px;
  }
}

/* Contact — info cards, address, map */
.info-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  padding: var(--space-5);
  height: 100%;
}

.info-card h2 {
  margin-top: 0;
}

.info-card h3 {
  margin: 0 0 var(--space-3);
}

/* Guest information / accessibility (contact.html) — warm, practical lists */
.guest-info-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.guest-info-list li {
  position: relative;
  padding-left: 1.7em;
  color: var(--ink-soft);
  line-height: 1.55;
}

/* Rose bullet — the canonical rose, painted in terracotta via --rose-svg as a
   mask (see :root). border-radius keeps a tidy round dot as the fallback where
   CSS masks are unsupported. Same treatment on .spaces-bullets and .prose ul. */
.guest-info-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.4em;
  width: 15px;
  height: 13px;
  background-color: var(--terracotta);
  border-radius: 50%;
  -webkit-mask: var(--rose-svg) center / contain no-repeat;
  mask: var(--rose-svg) center / contain no-repeat;
}

.guest-info-cta {
  margin-top: var(--space-5);
  color: var(--ink-soft);
}

/* Community page — organisation-type chips + ways-to-help cards */
.community-chips {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-5);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
}

.community-chips li {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--white);
  background: var(--olive);
  border-radius: 999px;
  padding: 0.45em 1.1em;
}

.community-ways {
  margin-top: var(--space-5);
  text-align: left;
}

.contact-address {
  font-style: normal;
  font-size: 1.1rem;
  line-height: 1.7;
  margin-bottom: var(--space-3);
}

.contact-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-4);
  font-size: 1.15rem;
}

.contact-list li {
  margin-bottom: var(--space-1);
}

.map-frame {
  margin-top: var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  overflow: hidden;
  aspect-ratio: 16 / 10;
}

@media (min-width: 900px) {
  .map-frame {
    aspect-ratio: 21 / 9;
  }
}

.map-frame iframe,
.map-frame #rosa-map {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* Contact — marker InfoWindow content (initRosaMap in contact.html). The
   popup lives inside Google's .gm-style container, which sets its own
   Roboto font stack, so the site fonts must be restated here rather than
   inherited. */
.map-pop {
  font-family: var(--sans);
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--ink);
}

.map-pop strong {
  font-family: var(--serif);
  font-size: 1rem;
}

.map-pop a {
  color: var(--red);
  font-weight: 700;
  text-decoration: none;
}

.map-pop a:hover,
.map-pop a:focus {
  color: var(--red-dark);
  text-decoration: underline;
}

/* Contact — opening-hours cards rendered from hours.json */
.hours-grid {
  display: grid;
  gap: var(--space-3);
}

@media (min-width: 640px) {
  .hours-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1200px) {
  .hours-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.hours-day {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  padding: var(--space-4);
}

.hours-day.today {
  border-color: var(--red);
  box-shadow: 0 0 0 2px rgba(221, 19, 27, 0.16), var(--shadow-soft);
}

.hours-day h3 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
}

.today-tag {
  font-family: var(--sans);
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--white);
  background: var(--red);
  border-radius: 999px;
  padding: 0.25em 0.7em;
}

.hours-rows {
  margin: 0;
}

.hours-rows > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 0.4rem 0;
  border-top: 1px solid var(--line);
}

.hours-rows > div:first-child {
  border-top: 0;
}

.hours-rows dt {
  margin: 0;
  color: var(--ink-soft);
}

.hours-rows dd {
  margin: 0;
  font-weight: 700;
  text-align: right;
  white-space: nowrap;
}

.hours-notes {
  list-style: none;
  padding: 0;
  margin: var(--space-5) auto 0;
  max-width: var(--container-narrow);
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.hours-notes li {
  margin-bottom: var(--space-2);
}

/* About — long-form prose and pull-quote */
.prose > p {
  margin-bottom: var(--space-4);
}

/* Brand-dot bullets for prose lists (cookies & privacy policy) — replaces the
   browser-default disc bullets, the one place these remained, with the same
   terracotta brand marker used on the guest-info and spaces lists. */
.prose ul {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.prose ul li {
  position: relative;
  padding-left: 1.6em;
  line-height: 1.6;
}

.prose ul li::before {
  content: '';
  position: absolute;
  left: 0.1em;
  top: 0.5em;
  width: 15px;
  height: 13px;
  background-color: var(--terracotta);
  border-radius: 50%;
  -webkit-mask: var(--rose-svg) center / contain no-repeat;
  mask: var(--rose-svg) center / contain no-repeat;
}

.pull-quote {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(1.4rem, 1rem + 2.4vw, 2rem);
  line-height: 1.3;
  color: var(--terracotta);
  border-left: 4px solid var(--red);
  padding-left: var(--space-4);
  margin: var(--space-6) 0;
}

.pull-quote cite {
  display: block;
  margin-top: var(--space-3);
  font-family: var(--sans);
  font-style: normal;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--ink-soft);
}

/* Privacy / policy text column */
.policy h2 {
  margin-top: var(--space-6);
}

.policy h2:first-of-type {
  margin-top: var(--space-4);
}

.policy ul {
  padding-left: 1.2em;
  margin-bottom: var(--space-4);
}

.policy li {
  margin-bottom: var(--space-1);
}

.policy-updated {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin-bottom: var(--space-5);
}

/* Gallery — CSS-columns masonry + dependency-free lightbox */
.gallery {
  column-count: 2;
  column-gap: var(--space-3);
}

@media (min-width: 640px) {
  .gallery {
    column-count: 3;
  }
}

@media (min-width: 900px) {
  .gallery {
    column-count: 4;
  }
}

/* Full-bleed dual-row photo marquee — decorative ambience above the grid.
   site.js clones each row for a seamless loop and adds .is-looping; margins
   (not flex gap) keep two copies exactly 2x one copy so -50% never jumps. The
   edge mask dissolves the photos into the page. */
.gallery-marquee {
  margin: 0 0 var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  overflow: hidden;
}

.marquee-row {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
}

.marquee-track {
  display: flex;
  width: max-content;
}

.marquee-track.is-looping {
  animation: marquee-left 64s linear infinite;
}

.marquee-row--rev .marquee-track.is-looping {
  animation-name: marquee-right;
}

.marquee-row:hover .marquee-track.is-looping,
.marquee-row:focus-within .marquee-track.is-looping {
  animation-play-state: paused;
}

.marquee-track img {
  flex: none;
  width: 240px;
  height: 160px;
  margin-right: var(--space-3);
  object-fit: cover;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-soft);
}

@media (max-width: 640px) {
  .marquee-track img {
    width: 180px;
    height: 120px;
  }
}

@keyframes marquee-left {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@keyframes marquee-right {
  from { transform: translateX(-50%); }
  to { transform: translateX(0); }
}

.gallery-item {
  position: relative;
  display: block;
  margin-bottom: var(--space-3);
  break-inside: avoid;
  border-radius: var(--radius-sm);
  overflow: hidden;
  box-shadow: var(--shadow-soft);
}

.gallery-item img {
  width: 100%;
  transition: transform 450ms var(--ease-out);
}

.gallery-item:hover img,
.gallery-item:focus-visible img {
  transform: scale(1.06);
}

/* Hover/focus: a warm gradient veil and the caption sliding up. The caption
   duplicates the image alt, so it is aria-hidden (the alt already announces). */
.gallery-item::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    rgba(20, 13, 10, 0.66) 0%, rgba(20, 13, 10, 0.1) 44%, transparent 72%);
  opacity: 0;
  transition: opacity 320ms ease;
  pointer-events: none;
}

.gallery-item:hover::after,
.gallery-item:focus-visible::after {
  opacity: 1;
}

.gallery-cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  margin: 0;
  padding: var(--space-3);
  color: var(--white);
  font-size: 0.82rem;
  line-height: 1.35;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 320ms ease, transform 360ms var(--ease-out);
  pointer-events: none;
}

.gallery-item:hover .gallery-cap,
.gallery-item:focus-visible .gallery-cap {
  opacity: 1;
  transform: none;
}

/* Staggered entrance — added by site.js only when motion is allowed, so no-JS
   and reduced-motion users always see the tiles immediately. */
.gallery--ready .gallery-item {
  opacity: 0;
  transform: translateY(28px) scale(0.96);
  transition: opacity 620ms var(--ease-out), transform 620ms var(--ease-out);
  transition-delay: calc(var(--i, 0) * 42ms);
}

.gallery--ready .gallery-item.is-in {
  opacity: 1;
  transform: none;
}

/* Filtering: outgoing tiles dim out before the survivors glide (FLIP) into
   their new column positions and incoming tiles fade up. */
.gallery-item.is-leaving {
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 200ms ease, transform 200ms ease;
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: rgba(20, 13, 10, 0.93);
  opacity: 0;
  transition: opacity 240ms ease;
}

/* Fade the backdrop in on open (site.js adds .is-open one frame after
   un-hiding). The image itself flies from the clicked tile to centre via an
   inline transform set in site.js (shared-element zoom). Closing is synchronous
   (hidden=true) so it stays instant and keeps the lightbox QA contract. */
.lightbox.is-open {
  opacity: 1;
}

.lightbox[hidden] {
  display: none;
}

.lightbox-media {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  max-width: min(1100px, 92vw);
}

.lightbox-img {
  max-height: 78vh;
  width: auto;
  height: auto;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lift);
}

.lightbox-caption {
  font-size: 0.85rem;
  color: rgba(255, 255, 255, 0.72);
  text-align: center;
  max-width: 60ch;
  margin: 0;
  padding: 0 var(--space-3);
  min-height: 1.4em;
  line-height: 1.4;
}

.lightbox-btn {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  font-size: 2rem;
  line-height: 1;
  color: var(--ink);
  background: var(--cream);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  box-shadow: var(--shadow-soft);
  transition: transform 150ms ease, background-color 150ms ease;
}

.lightbox-btn:hover {
  background: var(--white);
  transform: scale(1.06);
}

.lightbox-close {
  top: var(--space-4);
  right: var(--space-4);
}

.lightbox-prev {
  left: var(--space-3);
}

.lightbox-next {
  right: var(--space-3);
}

@media (min-width: 640px) {
  .lightbox-prev {
    left: var(--space-5);
  }
  .lightbox-next {
    right: var(--space-5);
  }
}

/* 404 */
.error-code {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(4.5rem, 2rem + 18vw, 9rem);
  line-height: 1;
  color: var(--red);
  margin: 0 0 var(--space-2);
}

/* --------------------------------------------------------------------------
   21. Fixed-price offers feature block (home + food.html)
   Reusable cards rendered by site.js from assets/data/offers.json. The accent
   modifier (terracotta / olive / red) differentiates each offer at a glance.
   -------------------------------------------------------------------------- */
.offers-feature {
  scroll-margin-top: calc(var(--nav-h-scrolled) + 16px);
}

/* Second group on a page (the weekly experiences) sits closer to the pair */
.offers-subhead {
  margin-top: var(--space-6);
}

.offers-grid {
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 760px) {
  .offers-grid--pair,
  .offers-grid--trio {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1000px) {
  .offers-grid--trio {
    grid-template-columns: repeat(3, 1fr);
  }
}

.offer-card {
  --offer-accent: var(--terracotta);
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--line);
  border-top: 4px solid var(--offer-accent);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
  padding: var(--space-5);
  transition: transform 200ms ease, box-shadow 200ms ease;
}

.offer-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift);
}

.offer-card--terracotta { --offer-accent: var(--terracotta); }
.offer-card--olive { --offer-accent: var(--olive); }
.offer-card--red { --offer-accent: var(--red); }

.offer-kicker {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--offer-accent);
}

.offer-name {
  font-family: var(--serif);
  font-size: clamp(1.5rem, 1.2rem + 1.6vw, 1.9rem);
  margin: var(--space-1) 0 var(--space-3);
}

.offer-courses {
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: var(--space-3) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  display: grid;
  gap: var(--space-2);
}

.offer-courses li {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.offer-course-label {
  font-weight: 700;
}

.offer-course-dots {
  flex: 1;
  min-width: 1rem;
  align-self: center;
  border-bottom: 2px dotted var(--line);
}

.offer-course-price {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 1.3rem;
  color: var(--offer-accent);
  white-space: nowrap;
}

.offer-available {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--ink);
  margin-bottom: var(--space-2);
}

.offer-icon {
  flex-shrink: 0;
  color: var(--offer-accent);
}

.offer-choose {
  color: var(--ink-soft);
  margin-bottom: var(--space-4);
}

.offer-cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: auto;
}

.offer-cta .btn {
  flex: 1 1 140px;
}

/* Lead pill that the food.html jump nav uses to return to the offers block */
.menu-jump a.menu-jump-lead {
  background: var(--red);
  border-color: var(--red);
  color: var(--white);
}

.menu-jump a.menu-jump-lead:hover {
  background: var(--red-dark);
  border-color: var(--red-dark);
  color: var(--white);
}

/* --------------------------------------------------------------------------
   22. Three-spaces showcase — immersive tabbed section (index.html)
   -------------------------------------------------------------------------- */
.spaces-showcase {
  padding-bottom: 0;
}

.spaces-tablist {
  display: flex;
  gap: 0;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px;
  margin-block: var(--space-5) 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.spaces-tablist::-webkit-scrollbar {
  display: none;
}

/* Step 23 fix: at phone widths the three pills used to shrink (flex: 1 +
   min-width: 0) under their nowrap labels, so the text overlapped (owner
   screenshot, 2026-07-22). Below 600px the tabs stack full-width instead:
   every label stays readable, each tab is a >=44px tap target, and there is
   room to keep the floor sub-lines visible. Tab semantics and the roving
   tabindex are untouched — this is presentation only. */
@media (max-width: 599px) {
  .spaces-tablist {
    flex-direction: column;
    gap: 4px;
    border-radius: calc(var(--radius) + 4px);
  }

  .spaces-tab {
    flex: none;
    width: 100%;
    min-height: 48px;
    white-space: normal;
    padding: 0.6em 1em;
  }

  /* Extra specificity: the base .spaces-tab-sub { display: none } rule sits
     later in this section and would win on source order otherwise. */
  .spaces-tab .spaces-tab-sub {
    display: block;
  }
}

.spaces-tab {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 0.7em 1.1em;
  background: transparent;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  font-family: var(--sans);
  transition: background-color 200ms ease, color 200ms ease;
  text-align: center;
  white-space: nowrap;
}

.spaces-tab:focus-visible {
  outline: 3px solid var(--red);
  outline-offset: -2px;
}

.spaces-tab-label {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  line-height: 1.2;
  color: var(--ink);
  transition: color 200ms ease;
}

.spaces-tab-sub {
  display: none;
  font-size: 0.68rem;
  color: var(--ink-soft);
  line-height: 1.2;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  transition: color 200ms ease;
}

@media (min-width: 480px) {
  .spaces-tab-sub {
    display: block;
  }
}

.spaces-tab[aria-selected="true"] {
  background: var(--red);
}

.spaces-tab[aria-selected="true"] .spaces-tab-label {
  color: var(--white);
}

.spaces-tab[aria-selected="true"] .spaces-tab-sub {
  color: rgba(255, 255, 255, 0.78);
}

.spaces-tab:hover:not([aria-selected="true"]) {
  background: var(--cream-2);
}

.spaces-panel {
  padding-block: var(--space-6) var(--space-7);
}

.spaces-panel.is-entering {
  animation: spaces-enter 340ms var(--ease-out) both;
}

@keyframes spaces-enter {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.spaces-panel-inner {
  display: grid;
  gap: var(--space-4);
  align-items: center;
}

@media (min-width: 900px) {
  .spaces-panel-inner {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-6);
  }

  .spaces-panel-inner.flip > .spaces-panel-img {
    order: 2;
  }
}

.spaces-panel-img {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-lift);
}

.spaces-panel-img img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  transition: transform 600ms var(--ease-out);
}

.spaces-panel-img:hover img,
.spaces-panel-img:focus-within img {
  transform: scale(1.03);
}

@media (min-width: 900px) {
  .spaces-panel-img img {
    aspect-ratio: 3 / 2;
  }
}

/* Terracotta keyline offset — mirrors the .frame motif */
.spaces-panel-img::before {
  content: '';
  position: absolute;
  inset: 0;
  transform: translate(10px, 10px);
  border: 2px solid var(--terracotta);
  border-radius: var(--radius);
  z-index: -1;
}

.spaces-panel-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.spaces-panel-body h3 {
  margin: 0;
}

.spaces-panel-body > p:not(.lead) {
  color: var(--ink-soft);
  margin: 0;
}

.spaces-bullets {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.spaces-bullets li {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.95rem;
  color: var(--ink);
}

.spaces-bullets li::before {
  content: '';
  width: 15px;
  height: 13px;
  background-color: var(--terracotta);
  border-radius: 50%;
  -webkit-mask: var(--rose-svg) center / contain no-repeat;
  mask: var(--rose-svg) center / contain no-repeat;
  flex-shrink: 0;
}

/* --------------------------------------------------------------------------
   23. Reviews / testimonials carousel (index.html)
   -------------------------------------------------------------------------- */
.reviews-section {
  /* inherits .section-alt */
}

.reviews-carousel {
  max-width: 780px;
  margin-inline: auto;
  position: relative;
}

.reviews-stage {
  min-height: 280px;
  display: flex;
  align-items: center;
  padding-block: var(--space-4);
}

@media (min-width: 640px) {
  .reviews-stage {
    min-height: 240px;
  }
}

.review-slide {
  margin: 0;
  padding: 0;
  width: 100%;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
}

.review-slide.is-entering {
  animation: review-enter 360ms var(--ease-out) both;
}

@keyframes review-enter {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.review-mark {
  font-family: var(--serif);
  font-size: 5rem;
  line-height: 0.6;
  color: var(--red);
  opacity: 0.18;
  font-style: normal;
  font-weight: 600;
  user-select: none;
  pointer-events: none;
}

.review-text {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(1.2rem, 2.4vw, 1.6rem);
  line-height: 1.45;
  color: var(--ink);
  max-width: 52ch;
  margin: 0;
  text-wrap: balance;
}

.review-stars {
  color: var(--terracotta);
  font-size: 1rem;
  letter-spacing: 0.1em;
  line-height: 1;
}

.review-source {
  font-family: var(--sans);
  font-style: normal;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--ink-soft);
  display: block;
  margin-top: var(--space-1);
}

.reviews-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-3);
}

.reviews-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  font-size: 1.6rem;
  line-height: 1;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 150ms ease, border-color 150ms ease,
    color 150ms ease, transform 150ms ease;
  box-shadow: var(--shadow-soft);
  padding: 0;
}

.reviews-btn:hover {
  background: var(--red);
  border-color: var(--red);
  color: var(--white);
  transform: scale(1.06);
}

.reviews-dots {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}

.reviews-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid var(--terracotta);
  background: transparent;
  padding: 0;
  cursor: pointer;
  transition: background-color 200ms ease, transform 200ms ease;
}

.reviews-dot.active {
  background: var(--terracotta);
  transform: scale(1.3);
}

.reviews-ta-link {
  text-align: center;
  margin-top: var(--space-4);
  margin-bottom: 0;
}

.reviews-ta-link a {
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--ink-soft);
  text-decoration: none;
}

.reviews-ta-link a:hover {
  color: var(--red);
  text-decoration: underline;
}
