/* ==========================================================================
   TeamWorkOn3 — base, components, sections
   Depends on tokens.css. No framework: no Bootstrap, no UIkit, no jQuery.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Reset & base
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--s-4));
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--t-base);
  line-height: var(--lh-body);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Space for the mobile action bar so the footer is never covered.

   This MUST include the safe-area inset. The bar itself is
   `--bottombar-h` tall PLUS `env(safe-area-inset-bottom)` of padding to clear
   the home indicator — about 34px on a modern iPhone. Reserving only
   --bottombar-h left the bar covering the last ~34px of the footer. */
@media (max-width: 860px) {
  body { padding-bottom: calc(var(--bottombar-h) + env(safe-area-inset-bottom)); }
}

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

h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: 800; line-height: var(--lh-snug); }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; }
li { list-style: none; }

a { color: inherit; text-decoration: none; }

button,
input,
select,
textarea { font: inherit; color: inherit; }

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

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

@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;
  }
}

/* --------------------------------------------------------------------------
   2. Utilities
   -------------------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--max-w);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--wide { max-width: var(--max-w-wide); }
.wrap--narrow { max-width: 780px; }

.section { padding-block: var(--section-y); }
.section--dark { background: var(--night); color: var(--on-night); }
.section--warm { background: var(--paper-warm); }
.section--flush { padding-block: 0; }

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

.skip-link {
  position: absolute;
  top: -100px; left: var(--s-4);
  z-index: 999;
  padding: var(--s-3) var(--s-5);
  background: var(--accent);
  color: var(--night);
  font-weight: 700;
  border-radius: 0 0 var(--r-md) var(--r-md);
  transition: top var(--dur) var(--ease);
}
.skip-link:focus { top: 0; }

.measure { max-width: var(--measure); }
.center { text-align: center; margin-inline: auto; }

/* --------------------------------------------------------------------------
   3. Display type
   -------------------------------------------------------------------------- */

.eyebrow {
  display: block;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--s-3);
}
.section--dark .eyebrow { color: var(--accent); }

/* The signature look: oversized, wide-tracked, uppercase. */
.display {
  font-size: var(--t-3xl);
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  line-height: var(--lh-tight);
}
.display--hero { font-size: var(--t-4xl); }
.display--sm { font-size: var(--t-2xl); }

.subhead {
  font-size: var(--t-lg);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-top: var(--s-3);
}
.section--dark .subhead { color: var(--on-night-soft); }

.lede {
  font-size: var(--t-lg);
  color: var(--ink-soft);
  margin-top: var(--s-5);
}
.section--dark .lede { color: var(--on-night-soft); }

/* Short teal rule under a display heading.
   margin-inline:0 is required — the UA stylesheet gives <hr> `margin: auto`,
   which silently centered every rule sitting under a left-aligned heading. */
.rule {
  width: 76px; height: 4px;
  margin: var(--s-5) 0 0;
  background: var(--accent);
  border: 0;
  border-radius: var(--r-pill);
}
.center .rule, .rule--center { margin-inline: auto; }

.section-head { margin-bottom: var(--s-8); }

/* --------------------------------------------------------------------------
   4. Buttons
   -------------------------------------------------------------------------- */

.btn {
  --btn-bg: var(--accent);
  --btn-fg: var(--night);
  --btn-bd: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 48px;                       /* comfortable touch target */
  padding: var(--s-3) var(--s-6);
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 2px solid var(--btn-bd);
  border-radius: var(--r-pill);
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: var(--track-button);
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
    color var(--dur) var(--ease), transform var(--dur-fast) var(--ease);
}
.btn:hover { --btn-bg: var(--accent-strong); --btn-bd: var(--accent-strong); }
.btn:active { transform: translateY(1px); }

/* Secondary: outline. Used *beside* a filled primary, never instead of one —
   the reference site made its highest-value action the faintest thing on the
   page, which is the mistake this pairing exists to avoid. */
.btn--outline { --btn-bg: transparent; --btn-fg: var(--ink); --btn-bd: var(--ink); }
.btn--outline:hover { --btn-bg: var(--ink); --btn-fg: var(--night); --btn-bd: var(--ink); }

.btn--on-dark { --btn-bg: transparent; --btn-fg: #fff; --btn-bd: #fff; }
.btn--on-dark:hover { --btn-bg: #fff; --btn-fg: var(--night); --btn-bd: #fff; }

.btn--lg { min-height: 56px; padding-inline: var(--s-7); font-size: var(--t-base); }
.btn--block { width: 100%; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  margin-top: var(--s-6);
}
.center .btn-row, .btn-row--center { justify-content: center; }

/* --------------------------------------------------------------------------
   5. Announcement bar
   -------------------------------------------------------------------------- */

.announce {
  position: relative;
  z-index: calc(var(--z-header) + 1);
  background: var(--night-soft);
  color: var(--ink);
  font-size: var(--t-sm);
  font-weight: 500;
  border-bottom: 1px solid var(--rule);
}
.announce__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-4);
  min-height: 44px;
  padding: var(--s-2) calc(var(--gutter) + 28px) var(--s-2) var(--gutter);
  text-align: center;
}
.announce__text { margin: 0; }
.announce__link {
  flex: none;
  padding: var(--s-2) var(--s-5);
  background: var(--accent);
  color: var(--night);
  border-radius: var(--r-pill);
  font-size: var(--t-xs);
  font-weight: 700;
  white-space: nowrap;
  transition: background var(--dur) var(--ease);
}
.announce__link:hover { background: var(--accent-bright); }
.announce__close {
  position: absolute;
  right: var(--s-3);
  top: 50%;
  translate: 0 -50%;
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  background: transparent;
  border: 0;
  border-radius: var(--r-pill);
  color: inherit;
  cursor: pointer;
  opacity: 0.85;
}
.announce__close:hover { opacity: 1; background: rgb(255 255 255 / 0.10); }
.announce[hidden] { display: none; }

/* --------------------------------------------------------------------------
   6. Header & navigation
   -------------------------------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: var(--header-bar);
  border-bottom: 0;
  /* Compositor promotion, to stop iOS repainting the sticky bar a frame behind
     the content while Safari's toolbar animates.

     `backface-visibility` is used ON PURPOSE and must not be "simplified" to
     `transform: translateZ(0)` or `will-change: transform`. Those two BREAK
     THE MOBILE NAV: `.nav` is `position: fixed` and lives inside this element,
     and transform/will-change make an ancestor a containing block for fixed
     descendants — the full-screen panel collapsed to the height of the bar
     (measured 945x128 instead of 945x871 on 2026-09-10).

     `backface-visibility` is NOT one of the properties that establishes that
     containing block, so it buys the layer without the side effect. */
  backface-visibility: hidden;
}

/* The reference runs a hairline along the foot of the bar that starts to the
   right of the logo rather than spanning the full width — the badge breaks it.
   Worth copying: it's what stops the bar reading as a plain rectangle. */
.header::after {
  content: '';
  position: absolute;
  left: var(--header-rule-start);
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--accent-line);
}
.header__inner {
  display: flex;
  align-items: center;
  gap: var(--s-6);
  min-height: var(--header-h);
}

/* Lockup: the reference's circular badge, plus the wordmark beside it.
   The badge alone is the more faithful copy, but this brand's name sits as a
   small horizontal block inside a large disc — at 76px it is unreadable,
   where the reference's name curves around the full circumference. A header
   whose restaurant name can't be read is a usability fault, so the wordmark
   carries the name and the badge carries the shape. */
.brand { display: flex; align-items: center; gap: var(--s-4); flex: 0 0 auto; }
/* No border-radius here any more. The old badge was a filled black disc that
   needed clipping to a circle; the mark replacing it (2026-09-10) is a
   transparent PNG that draws its own gold ring, so a 50% radius would only
   risk clipping the artwork's corners while doing nothing visible. */
.brand__badge { width: auto; height: 76px; flex: none; }
.brand__logo { width: auto; height: 34px; }
@media (max-width: 1080px) {
  .brand__badge { height: 52px; }
  .brand__logo { height: 26px; }
}
@media (max-width: 560px) {
  .brand__logo { display: none; }   /* badge only once space is tight */
}

.nav { margin-left: auto; }
.nav__list { display: flex; align-items: center; gap: var(--s-6); }
.nav__link {
  position: relative;
  color: var(--accent);
  display: inline-block;
  padding: var(--s-2) 0;
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  transition: color var(--dur) var(--ease);
}

/* The active/hover underline is a pseudo-element, not a transparent border.
   Chrome paints a 0-alpha border as a faint grey hairline at some subpixel
   positions, which put a visible smudge under every nav item at rest. */
.nav__link::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--accent);
  border-radius: var(--r-pill);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur) var(--ease);
}
.nav__link:hover,
.nav__link[aria-current='page'] { color: var(--accent-bright); }
.nav__link:hover::after,
.nav__link[aria-current='page']::after { transform: scaleX(1); }

.header__actions { display: flex; align-items: center; gap: var(--s-4); }

/* The Reserve button inside the nav list belongs to the mobile panel only;
   above the breakpoint .header__actions carries its own. */
.nav__mobile-cta { display: none; }

.social { display: flex; align-items: center; gap: var(--s-3); }
.social__link {
  display: grid;
  place-items: center;
  width: 36px; height: 36px;
  border-radius: var(--r-pill);
  color: var(--ink-soft);
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.social__link:hover { color: var(--accent); background: var(--accent-tint); }
.social__link svg { width: 18px; height: 18px; }

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  margin-left: auto;
  background: transparent;
  border: 0;
  cursor: pointer;
}
.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  content: '';
  display: block;
  width: 24px; height: 2px;
  background: var(--ink);
  border-radius: var(--r-pill);
  transition: transform var(--dur) var(--ease), opacity var(--dur-fast) var(--ease);
}
.nav-toggle__bars { position: relative; }
.nav-toggle__bars::before { position: absolute; top: -7px; }
.nav-toggle__bars::after { position: absolute; top: 7px; }
.nav-toggle[aria-expanded='true'] .nav-toggle__bars { background: transparent; }
.nav-toggle[aria-expanded='true'] .nav-toggle__bars::before { top: 0; transform: rotate(45deg); }
.nav-toggle[aria-expanded='true'] .nav-toggle__bars::after { top: 0; transform: rotate(-45deg); }

/* Dropdown (Order → pickup / delivery) */
.nav__item--has-menu { position: relative; }
.nav__submenu {
  position: absolute;
  top: 100%; left: 50%;
  translate: -50% 0;
  min-width: 220px;
  padding: var(--s-3);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  display: none;
}
.nav__item--has-menu:hover .nav__submenu,
.nav__submenu:has(a:focus-visible),
.nav__item--has-menu .nav__toggle[aria-expanded='true'] + .nav__submenu { display: block; }
.nav__submenu a {
  display: block;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-sm);
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.nav__submenu a:hover { background: var(--accent-tint); color: var(--accent-strong); }

@media (max-width: 1080px) {
  .nav-toggle { display: inline-flex; }
  .header::after { left: var(--header-rule-start-sm); }
  .header__actions { display: none; }
  .nav {
    position: fixed;
    /* --nav-top is the header's measured bottom edge, set by site.js when the
       panel opens. The constant is only the fallback for before JS runs — it
       is wrong whenever the announcement bar is showing, which is exactly the
       case that made this look broken. */
    inset: var(--nav-top, var(--header-h)) 0 0 0;
    margin: 0;
    padding: var(--s-6) var(--gutter) var(--s-9);
    background: var(--header-bar);
    overflow-y: auto;
    transform: translateX(100%);
    visibility: hidden;
    transition: transform var(--dur) var(--ease), visibility var(--dur) var(--ease);
  }
  .nav[data-open='true'] { transform: translateX(0); visibility: visible; }
  .nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav__link {
    padding: var(--s-4) 0;
    font-size: var(--t-lg);
    border-bottom: 1px solid var(--rule);
    color: var(--accent);
  }
  .nav__link::after { display: none; }
  .nav__submenu {
    position: static;
    translate: none;
    display: block;
    border: 0;
    box-shadow: none;
    padding: 0 0 var(--s-3) var(--s-4);
  }
  .nav__mobile-cta { display: block; margin-top: var(--s-6); }
}

/* --------------------------------------------------------------------------
   7. Hero — one still image, permanent scrim, one message, two actions.
   (Deliberately not a carousel: rotating headlines are read by nobody, and
   two of the five slides on the reference site carried no message at all.)
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  /* The reference hero is a full viewport tall with its header laid over the
     top of the photo. Our header is sticky but stays IN FLOW, so subtracting
     it here lands on the same visible proportion (the reference shows 870 of
     a 967px viewport) without restructuring the header across four pages.

     The announcement bar sits above the header and also eats viewport, so it
     is subtracted too — site.js measures it into --announce-h and updates that
     when the bar is dismissed or the bar rewraps. Without it the hero ran
     exactly that bar's height below the fold, taking its dots with it.
     The 0px fallback keeps this correct before JS runs and when there is no
     bar at all. */
  /* dvh, not vh. On iOS `100vh` is the viewport with the toolbars HIDDEN, so
     with them showing the hero is taller than anything you can actually see
     and it pushes the rest of the page down. `dvh` tracks the live viewport.
     The vh line stays first as the fallback for browsers without dvh. */
  min-height: calc(100vh - var(--header-h) - var(--announce-h, 0px));
  min-height: calc(100dvh - var(--header-h) - var(--announce-h, 0px));
  background: var(--night);
  color: #fff;
  isolation: isolate;
  overflow: hidden;
}
.hero .display--hero { text-shadow: 0 2px 24px rgb(0 0 0 / 0.4); }
.hero__lede {
  margin-top: var(--s-5);
  max-width: 46ch;
  font-size: var(--t-lg);
  color: #f0f1f2;
}
@media (max-width: 768px) {
  .hero {
    min-height: 78vh;
    min-height: 78dvh;
    align-items: center;
    text-align: center;
  }
  .hero__content { margin-inline: auto; }
  .hero .btn-row { justify-content: center; }
}

/* Fact strip directly under the hero: address, hours, phone. */
.factbar { background: var(--night-soft); color: #fff; border-block: 1px solid var(--rule); }
.factbar__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--s-4) var(--s-7);
  padding-block: var(--s-4);
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
}
.factbar__item { display: flex; align-items: center; gap: var(--s-2); }
.factbar__item svg { width: 16px; height: 16px; color: var(--accent); flex: none; }
.factbar a:hover { color: var(--accent); }

/* --------------------------------------------------------------------------
   8. Split section — text beside a blob-framed image
   -------------------------------------------------------------------------- */

.split {
  display: grid;
  gap: var(--s-8);
  align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; gap: var(--s-9); }
}

/* The signature oversized-radius image frame. Corners alternate so repeated
   use down the page doesn't read as a row of identical rounded rectangles. */
.blob {
  overflow: hidden;
  border-radius: var(--r-blob) var(--r-sm) var(--r-blob) var(--r-sm);
  box-shadow: var(--shadow-md);
}
.blob--alt { border-radius: var(--r-sm) var(--r-blob) var(--r-sm) var(--r-blob); }
.blob img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.blob--tall img { aspect-ratio: 3 / 4; }

/* --------------------------------------------------------------------------
   9. Game day board — the sports-bar section the reference design has no
   equivalent for. Today's fixtures, kickoff times, which screen.
   -------------------------------------------------------------------------- */

.gameday { background: var(--night); color: var(--on-night); }

.fixtures {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: 1fr;
}
@media (min-width: 720px) { .fixtures { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .fixtures { grid-template-columns: repeat(3, 1fr); } }

.fixture {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-5);
  background: var(--night-soft);
  border: 1px solid var(--rule-dark);
  border-radius: var(--r-lg);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.fixture:hover { border-color: var(--accent-line); background: var(--night-soft); }
.fixture__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--on-night-soft);
}
.fixture__league { color: var(--accent); }
.fixture__teams {
  font-size: var(--t-xl);
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: var(--lh-snug);
}
.fixture__time {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--on-night-soft);
}
.fixture__time svg { width: 15px; height: 15px; color: var(--accent); flex: none; }

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-1) var(--s-3);
  background: var(--accent);
  color: #fff;
  border-radius: var(--r-pill);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.badge--quiet { background: transparent; border: 1px solid var(--rule-dark); color: var(--on-night-soft); }

/* --------------------------------------------------------------------------
   10. Menu teaser cards
   -------------------------------------------------------------------------- */

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

.card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  position: relative;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

/* No lift, no glow. A gold rule wipes across the top edge — the way a foil
   line behaves on a printed card, and it stays where you put it. */
.card::before {
  content: '';
  position: absolute;
  inset: -1px auto auto -1px;
  width: calc(100% + 2px);
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-slow) var(--ease);
}
.card:hover { background: var(--night-soft); border-color: var(--rule-strong); }
.card:hover::before { transform: scaleX(1); }
.card__media { aspect-ratio: 3 / 2; width: 100%; object-fit: cover; }
/* Flex column, not grid: `.card__link { margin-top: auto }` only pushes the
   CTA to the bottom in a flex context, and without it the links sat at three
   different heights across a row of cards. */
.card__body {
  padding: var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  flex: 1;
}
.card__title {
  font-size: var(--t-xl);
  letter-spacing: var(--track-display);
  text-transform: uppercase;
}
.card__text { color: var(--ink-soft); font-size: var(--t-sm); }
.card__link {
  margin-top: auto;
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: var(--track-button);
  text-transform: uppercase;
  color: var(--accent);
}
.card__link:hover { color: var(--accent-strong); text-decoration: underline; text-underline-offset: 4px; }

/* --------------------------------------------------------------------------
   11. Gallery — dark grid, native-dialog lightbox
   -------------------------------------------------------------------------- */

.gallery {
  display: grid;
  gap: var(--s-3);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 720px) { .gallery { grid-template-columns: repeat(3, 1fr); gap: var(--s-4); } }
@media (min-width: 1080px) { .gallery { grid-template-columns: repeat(4, 1fr); } }

/* display:block + width:100% matter here. As an inline-block the button is
   shrink-to-fit, so before the lazy images load it measures zero and the whole
   grid collapses — the section jumped 447px -> 1065px on load. Filling the grid
   cell lets aspect-ratio reserve the height up front, so nothing shifts. */
.gallery__item {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: var(--night-soft);
  cursor: zoom-in;
  overflow: hidden;
  border-radius: var(--r-md);
  aspect-ratio: 1;
}
.gallery__item img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease), filter var(--dur) var(--ease);
}
.gallery__item:hover img { transform: scale(1.04); filter: brightness(1.08) saturate(1.05); }

/* Two-up square grid, matching the section the reference runs straight after
   its menu block. Measured there: 2 columns, 335x335 squares, 40px gutter,
   content 710 of 945px wide — so the grid is noticeably narrower than the page
   and the squares stay modest rather than filling the width.

   Declared after the base .gallery media queries on purpose: media blocks add
   no specificity, so source order is what lets this hold two columns where the
   base would go to three and then four.

   .gallery__item is already aspect-ratio 1 and display:block, so the square
   cells and the lazy-load height reservation both come for free. */
.gallery--pairs {
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-5);
  max-width: 46rem;
  margin-inline: auto;
}
@media (min-width: 720px) {
  .gallery--pairs { grid-template-columns: repeat(2, 1fr); gap: var(--s-6); }
}
@media (min-width: 1080px) {
  .gallery--pairs { grid-template-columns: repeat(2, 1fr); }
}

/* ==========================================================================
   Instagram strip

   Hand-placed tiles, not a live feed — see the note in index.html for why a
   real one is blocked by this site's own CSP. Each tile is a plain link to the
   profile, so it deliberately does NOT use .gallery__item: site.js binds the
   lightbox to that class and would swallow the navigation.
   ========================================================================== */
.iggrid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-3);
  margin-top: var(--s-7);
}
@media (min-width: 720px) { .iggrid { grid-template-columns: repeat(4, 1fr); gap: var(--s-4); } }

.igtile {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--r-md);
  background: var(--night);
}
.igtile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease);
}

/* The glyph only appears over the picture on hover or keyboard focus, so the
   tiles read as photographs first and as links second. */
.igtile__veil {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #fff;
  background: rgb(10 10 10 / 0.55);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.igtile__veil svg { width: 34px; height: 34px; }
.igtile:hover img, .igtile:focus-visible img { transform: scale(1.05); }
.igtile:hover .igtile__veil, .igtile:focus-visible .igtile__veil { opacity: 1; }

.ighandle { display: inline-flex; align-items: center; gap: var(--s-3); }
.ighandle svg { width: 20px; height: 20px; }

.lightbox {
  width: min(94vw, 1100px);
  max-width: none;
  padding: 0;
  background: transparent;
  border: 0;
}
.lightbox::backdrop { background: rgb(0 0 0 / 0.88); }
.lightbox img { width: 100%; height: auto; border-radius: var(--r-md); }
.lightbox__caption {
  margin-top: var(--s-3);
  color: #fff;
  font-size: var(--t-sm);
  text-align: center;
}
.lightbox__close {
  position: absolute;
  top: var(--s-3); right: var(--s-3);
  display: grid; place-items: center;
  width: 44px; height: 44px;
  background: rgb(0 0 0 / 0.6);
  color: #fff;
  border: 0;
  border-radius: var(--r-pill);
  cursor: pointer;
}
.lightbox__close:hover { background: rgb(0 0 0 / 0.85); }

/* --------------------------------------------------------------------------
   12. Reviews — three cards, all visible at once (no carousel)
   -------------------------------------------------------------------------- */

.reviews { background: var(--paper-warm); }
.review {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-6);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
}
.review__stars { display: flex; gap: 2px; color: var(--accent); }
.review__stars svg { width: 18px; height: 18px; }
.review__text { color: var(--ink-soft); font-size: var(--t-sm); }
.review__author { font-weight: 700; font-size: var(--t-sm); letter-spacing: 0.04em; }
.review__source { color: var(--ink-faint); font-weight: 500; }

/* --------------------------------------------------------------------------
   13. Newsletter + map
   -------------------------------------------------------------------------- */

.contact-split {
  display: grid;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) { .contact-split { grid-template-columns: 1fr 1fr; } }

.newsletter {
  display: grid;
  align-content: center;
  gap: var(--s-4);
  padding: var(--section-y) var(--gutter);
  background: var(--night);
  color: var(--on-night);
}
.newsletter__form { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-3); }
.field { flex: 1 1 240px; display: grid; gap: var(--s-2); }
.field__label { font-size: var(--t-xs); font-weight: 700; letter-spacing: var(--track-eyebrow); text-transform: uppercase; color: var(--on-night-soft); }
.field__input {
  width: 100%;
  min-height: 48px;
  padding: var(--s-3) var(--s-4);
  background: var(--night-soft);
  color: #fff;
  border: 1px solid var(--rule-dark);
  border-radius: var(--r-md);
}
.field__input::placeholder { color: #7d8085; }
.field__input:focus { border-color: var(--accent); }
.form__note { font-size: var(--t-xs); color: var(--on-night-soft); }
.form__status { font-size: var(--t-sm); font-weight: 600; min-height: 1.5em; }
.form__status[data-state='ok'] { color: #4ec9b0; }
.form__status[data-state='error'] { color: #ff8f8f; }


/* NOTE: there used to be a `.map img { width:100%; height:100%; ... }` rule
   here for the static map placeholder. Leaflet renders its TILES and its
   MARKER as <img> inside this same container, so that rule stretched every one
   of them — the marker came out as a blue bar the full height of the map.
   The placeholder is gone; the rule went with it. Do not reintroduce a bare
   `.map img` selector. */

/* Interactive map (Leaflet). The container must carry an explicit height —
   Leaflet measures its parent and renders nothing in a zero-height box, which
   is the classic "blank grey map" failure. */
.map { position: relative; min-height: 340px; background: var(--paper-warm); }
.map__canvas {
  width: 100%;
  height: 100%;
  min-height: 340px;
  background: var(--night-soft);
  z-index: 0;                 /* keep Leaflet's panes under the site header */
}
.leaflet-container { font: inherit; background: var(--night-soft); }
.leaflet-control-attribution { font-size: 11px; }

/* Always-visible directions link, so the address never depends on the map
   script having loaded. */
.map__directions,
.map__fallback {
  position: absolute;
  left: var(--s-4);
  bottom: var(--s-4);
  z-index: 500;               /* above Leaflet panes, below the header */
  padding: var(--s-3) var(--s-5);
  border-radius: var(--r-pill);
  background: rgb(10 10 10 / 0.82);
  color: #fff;
  font-size: var(--t-sm);
  font-weight: 600;
  backdrop-filter: blur(4px);
}
.map__directions:hover, .map__fallback:hover { background: var(--night); }

.footer__pin { display: inline-flex; align-items: center; gap: var(--s-2); }
.footer__pin svg { width: 16px; height: 16px; }
.social--footer { display: flex; gap: var(--s-4); margin-top: var(--s-3); }


/* --------------------------------------------------------------------------
   14. Footer
   -------------------------------------------------------------------------- */

.footer { background: var(--paper); border-top: 1px solid var(--rule); }
.footer__grid {
  display: grid;
  gap: var(--s-7);
  grid-template-columns: 1fr;
  padding-block: var(--section-y);
}
@media (min-width: 720px) { .footer__grid { grid-template-columns: repeat(2, 1fr); } }
/* Three columns, matching the reference's Location / Hours / Find us + Contact.
   Was four, back when the first cell held the logo — the client asked for that
   to come out, so the count came down with it. */
@media (min-width: 1000px) { .footer__grid { grid-template-columns: repeat(3, 1fr); } }

.footer__title {
  font-size: var(--t-sm);
  font-weight: 800;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  margin-bottom: var(--s-4);
}
.footer__list { display: grid; gap: var(--s-2); font-size: var(--t-sm); color: var(--ink-soft); }
.footer__list a:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }

.hours { display: grid; gap: var(--s-2); font-size: var(--t-sm); }
.hours__row { display: flex; justify-content: space-between; gap: var(--s-4); color: var(--ink-soft); }
.hours__day { font-weight: 600; color: var(--ink); }

.footer__bar {
  border-top: 1px solid var(--rule);
  padding-block: var(--s-5);
  font-size: var(--t-xs);
  color: var(--ink-faint);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-5);
  align-items: center;
  justify-content: space-between;
}

/* --------------------------------------------------------------------------
   15. Mobile sticky action bar — three actions, not five.
   -------------------------------------------------------------------------- */

.bottombar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--z-bottombar);
  display: none;
  background: var(--night-soft);
  border-top: 1px solid var(--rule);
  /* Clears the home indicator. */
  padding-bottom: env(safe-area-inset-bottom);
  /* Same problem as the header, worse: a fixed element is positioned against
     the LAYOUT viewport, so while Safari's toolbar collapses this bar drifted
     up the screen with page content visible underneath it. Its own layer keeps
     it pinned through the transition instead of being re-laid-out every frame.

     translate3d rather than translateZ so the tuck below can animate the Y of
     the SAME property — two transforms on one element would overwrite. */
  transform: translate3d(0, 0, 0);
  will-change: transform;
  transition: transform var(--dur) var(--ease);
}

/* Tucked away while reading. Two stacked bars — ours and Safari's own toolbar —
   eat about 90px of an already short phone screen, so this one gets out of the
   way on the way down and comes back the moment you scroll up. 110% clears the
   safe-area padding as well as the bar itself. */
.bottombar.is-tucked { transform: translate3d(0, 110%, 0); }

@media (prefers-reduced-motion: reduce) {
  .bottombar { transition: none; }
}
@media (max-width: 860px) { .bottombar { display: grid; grid-template-columns: repeat(3, 1fr); } }

.bottombar__link {
  display: grid;
  place-items: center;
  gap: 2px;
  min-height: var(--bottombar-h);
  padding: var(--s-2);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.bottombar__link + .bottombar__link { border-left: 1px solid var(--rule-dark); }
.bottombar__link svg { width: 18px; height: 18px; color: var(--accent); }
.bottombar__link:active { background: var(--night-soft); }

/* --------------------------------------------------------------------------
   17. Menu page — single column, sticky category nav, prices in a column.
   -------------------------------------------------------------------------- */

.page-head {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 320px;
  padding-block: var(--s-8);
  background: var(--night);
  color: #fff;
  text-align: center;
  isolation: isolate;
  overflow: hidden;
}
.page-head__media { position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; }
.page-head::after { content: ''; position: absolute; inset: 0; z-index: -1; background: var(--hero-scrim); }

/* Sticky category rail — the reference menu ran 7,500px with no way to jump. */
.menu-nav {
  position: sticky;
  top: var(--header-h);
  z-index: calc(var(--z-header) - 1);
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.menu-nav__scroll {
  display: flex;
  gap: var(--s-2);
  overflow-x: auto;
  scrollbar-width: none;
  padding-block: var(--s-3);
}
.menu-nav__scroll::-webkit-scrollbar { display: none; }
.menu-nav__link {
  flex: none;
  padding: var(--s-2) var(--s-4);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-soft);
  transition: all var(--dur) var(--ease);
}
.menu-nav__link:hover { border-color: var(--accent); color: var(--accent); }
.menu-nav__link[aria-current='true'] { background: var(--accent); border-color: var(--accent); color: var(--night); }

.menu-section { padding-block: var(--s-8); border-bottom: 1px solid var(--rule); }
.menu-section:last-of-type { border-bottom: 0; }
.menu-section__head { margin-bottom: var(--s-6); }
.menu-section__note { color: var(--ink-faint); font-size: var(--t-sm); margin-top: var(--s-2); }

.menu-list { display: grid; gap: var(--s-5); max-width: 760px; }

/* Name and price on one baseline joined by a dotted leader; description below.
   Prices are the thing people scan for, so they get their own column. */
.menu-item__head {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: var(--s-3);
}
.menu-item__name {
  font-size: var(--t-lg);
  font-weight: 700;
  letter-spacing: 0.01em;
}
.menu-item__leader {
  border-bottom: 1px dotted var(--rule);
  transform: translateY(-4px);
}
.menu-item__price {
  font-size: var(--t-lg);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  white-space: nowrap;
}
.menu-item__desc { margin-top: var(--s-2); color: var(--ink-soft); font-size: var(--t-sm); max-width: 60ch; }

/* A single line of copy that has to be READ, not skimmed past — used for the
   "every main comes with 2 side orders" promise, which is the selling point of
   that section and was previously a grey footnote nobody would notice. Gold
   rule on the left, brand tint behind, in the ink colour rather than the muted
   note colour. */
.menu-callout {
  margin: var(--s-4) 0 var(--s-5);
  padding: var(--s-3) var(--s-4);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: var(--accent-tint);
  color: var(--ink);
  font-size: var(--t-base);
  line-height: var(--lh-body);
}
.menu-callout strong { color: var(--accent-bright); }

.tag {
  display: inline-block;
  margin-left: var(--s-2);
  padding: 1px var(--s-2);
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  vertical-align: middle;
}

/* Menu photography is opt-in per item, at a scale that supports the text
   instead of burying it. */
.menu-item__photo {
  margin-top: var(--s-4);
  width: 100%;
  max-width: 380px;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--r-md);
}
/* Cocktails are shot as tall glasses with the garnish on top; a 3:2 crop cuts
   one end off. Square keeps the whole glass, and the old site's drink photos
   (2026-10-02) are square already, so they show uncropped. */
.menu-item__photo--drink {
  max-width: 300px;
  aspect-ratio: 1;
}




/* --------------------------------------------------------------------------
   19. House quote
   The restaurant's own line, set as a statement. Deliberately not styled as a
   review card — it isn't one, and there are no real reviews on the site yet.
   -------------------------------------------------------------------------- */

.housequote { margin: 0; display: grid; gap: var(--s-5); }
.housequote__text {
  font-size: var(--t-2xl);
  font-weight: 700;
  line-height: var(--lh-snug);
  text-wrap: balance;
  color: var(--ink);
}
.housequote__cite {
  display: block;
  font-style: normal;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
}
.housequote::before {
  content: '';
  display: block;
  width: 40px; height: 3px;
  margin: 0 auto;
  background: var(--accent);
  border-radius: var(--r-pill);
}

/* Gold hairline under the sticky header lifts it off a black page body. */
/* (header hairline is drawn by .header::after, above) */

/* --------------------------------------------------------------------------
   20. Menu page additions
   -------------------------------------------------------------------------- */

/* Sub-heading inside a menu section (Happy Hour splits into drinks / food /
   Tuesday / Thursday, which are one section but four lists). */
.menu-sub {
  margin-top: var(--s-7);
  margin-bottom: var(--s-4);
  font-size: var(--t-lg);
  font-weight: 800;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
}
.menu-sub:first-of-type { margin-top: 0; }
.menu-sub + .menu-section__note { margin-top: calc(var(--s-4) * -1); margin-bottom: var(--s-4); }


/* Brunch drink packages — the one place on the menu where a price is the
   headline rather than a figure at the end of a row. */
.deal-grid {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: 1fr;
  margin-top: var(--s-7);
  max-width: 760px;
}
@media (min-width: 640px) { .deal-grid { grid-template-columns: repeat(2, 1fr); } }

.deal {
  padding: var(--s-5);
  background: var(--surface);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-lg);
  text-align: center;
}
.deal__price {
  font-size: var(--t-3xl);
  font-weight: 800;
  line-height: 1;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.deal__price span {
  display: block;
  margin-top: var(--s-2);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--ink-soft);
}
.deal__title { margin-top: var(--s-4); font-weight: 700; }
.deal__detail { margin-top: var(--s-2); font-size: var(--t-sm); color: var(--ink-soft); }

/* ==========================================================================
   21. Texture and atmosphere
   A perfectly flat black ground is the thing that reads as screen-only. Grain
   plus a warm vignette gives the page a surface, the way a printed menu or a
   photograph has one.
   ========================================================================== */

body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9998;
  pointer-events: none;
  background-image: var(--grain);
  opacity: 0.055;
  mix-blend-mode: overlay;
}

/* MOBILE SCROLL FIX (2026-09-10). On touch devices the grain above is dropped
   entirely. A fixed, full-viewport mix-blend-mode layer forces iOS Safari to
   repaint and re-blend everything UNDER it on every scroll frame — including
   the sticky header, which is why the header visibly dragged/lagged while
   scrolling. Removing the blend layer lets the header composite smoothly.

   The loss is imperceptible: the grain is 5.5% opacity texture that does not
   read on a phone screen. Desktop keeps it — there the scroll is composited
   fine and the texture is worth having. Gated on a coarse pointer / no-hover,
   which is phones and tablets, not a narrow desktop window. */
@media (hover: none) and (pointer: coarse) {
  body::after { display: none; }
}
/* <dialog> renders in the top layer, so modals still sit above the grain. */

/* Warm falloff at the edges of full-bleed dark sections — light pools in the
   middle of a room, it doesn't fill it evenly. */
.page-head::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(120% 90% at 50% 35%,
    rgb(208 164 57 / 0.07) 0%,
    rgb(10 10 10 / 0) 55%),
    radial-gradient(100% 100% at 50% 100%,
    rgb(0 0 0 / 0.55) 0%,
    rgb(0 0 0 / 0) 60%);
}

/* ==========================================================================
   22. Script kicker
   Set from the client's own flyers, where the accent lines are handwritten.
   Large enough to read as a gesture; never used for anything functional.
   ========================================================================== */

.kicker {
  display: block;
  font-family: var(--font-script);
  font-size: clamp(1.75rem, 1.4rem + 1.4vw, 2.5rem);
  line-height: 1;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--accent);
  margin-bottom: var(--s-2);
}

/* A section head that sits left, with the rule running out to the left margin.
   Alternating this with centred heads breaks the every-section-identical
   rhythm that makes a page feel stamped out. */
.section-head--left { text-align: left; margin-bottom: var(--s-8); }
.section-head--left .rule { margin-inline: 0; }
.section-head--left .lede { max-width: var(--measure); }

/* ==========================================================================
   23. Schedule board
   The weekly lineup, set as a board rather than a row of cards: hairline
   rules, the day in gold, the night's name large. This is how a bar actually
   prints its week — and it removes six boxes from the page.
   ========================================================================== */

.schedule { border-top: 1px solid var(--rule); }

.schedule__row {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-2) var(--s-6);
  padding: var(--s-5) var(--s-4);
  border-bottom: 1px solid var(--rule);
  transition: background var(--dur) var(--ease);
}
@media (min-width: 760px) {
  .schedule__row {
    grid-template-columns: 190px 1fr auto;
    align-items: baseline;
    padding-inline: var(--s-5);
  }
}

/* The gold rule grows from the left edge on hover — a pointer moving along a
   printed list, not a card taking off. */
.schedule__row::before {
  content: '';
  position: absolute;
  left: 0; bottom: -1px;
  width: 100%; height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-slow) var(--ease);
}
.schedule__row:hover { background: rgb(255 255 255 / 0.02); }
.schedule__row:hover::before { transform: scaleX(1); }

.schedule__day {
  font-size: var(--t-sm);
  font-weight: 800;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
}
.schedule__time {
  display: block;
  margin-top: var(--s-1);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
}
.schedule__name {
  font-size: var(--t-xl);
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: var(--lh-snug);
}
.schedule__detail {
  margin-top: var(--s-2);
  font-size: var(--t-sm);
  color: var(--ink-soft);
  max-width: 54ch;
}
.schedule__link {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--track-button);
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
.schedule__row:hover .schedule__link { color: var(--accent); }

/* ==========================================================================
   24. Index columns
   Three menus presented as columns of type divided by hairlines, instead of
   three more bordered boxes.
   ========================================================================== */

.index-cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-7);
}
@media (min-width: 820px) {
  .index-cols { grid-template-columns: repeat(3, 1fr); gap: 0; }
  .index-cols > * + * { border-left: 1px solid var(--rule); }
  .index-cols > * { padding-inline: var(--s-6); }
  .index-cols > *:first-child { padding-left: 0; }
  .index-cols > *:last-child { padding-right: 0; }
}

.index-item__name {
  font-size: var(--t-xl);
  font-weight: 800;
  letter-spacing: var(--track-display);
  text-transform: uppercase;
}
.index-item__when {
  margin-top: var(--s-2);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
}
.index-item__text { margin-top: var(--s-4); color: var(--ink-soft); font-size: var(--t-sm); }
.index-item__link {
  display: inline-block;
  margin-top: var(--s-4);
  padding-bottom: 2px;
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: var(--track-button);
  text-transform: uppercase;
  border-bottom: 1px solid var(--accent-line);
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.index-item__link:hover { color: var(--accent); border-bottom-color: var(--accent); }

/* ==========================================================================
   25. Light sections
   Bird in Hand alternates white and black; going dark-everywhere lost half of
   that rhythm. A light section re-points the token set locally, so every
   component inside it flips without a single component rule changing.

   The one thing that cannot carry over is gold *text*: the brand gold reads
   2.19:1 on this ground. --accent-ink is the brand gold darkened to 4.81:1
   for type; full-strength gold stays for rules, fills and frames.
   ========================================================================== */

.section--light {
  --paper: #faf8f4;
  --paper-warm: #f2eee6;
  --surface: #ffffff;
  --night-soft: #f2eee6;
  --ink: #14110c;
  --ink-soft: #4a453c;
  --ink-faint: #7a7469;
  --rule: #e2ddd2;
  --rule-strong: #cfc8b9;
  --accent-ink: #8f6714;

  background: var(--paper);
  color: var(--ink);
}
.section--light .kicker,
.section--light .eyebrow,
.section--light .index-item__when,
.section--light .schedule__day,
.section--light .menu-sub { color: var(--accent-ink); }
.section--light .lede { color: var(--ink-soft); }

/* On light, the button reads as Bird in Hand's does: a black hairline pill. */
.section--light .btn--outline { --btn-bg: transparent; --btn-fg: var(--ink); --btn-bd: var(--ink); }
.section--light .btn--outline:hover { --btn-bg: var(--ink); --btn-fg: var(--paper); }

/* ==========================================================================
   26. Underlined display heading
   The reference sets its accent rule hard under the word, spanning the text —
   not as a detached stub floating below it. inline-block + border-bottom makes
   the rule measure itself against the heading, which is exactly that.
   ========================================================================== */

.display--underlined {
  display: inline-block;
  padding-bottom: 0.1em;
  border-bottom: 5px solid var(--accent);
  text-wrap: balance;
}
.display--underlined.display--sm { border-bottom-width: 4px; }

/* The formal, centred section head the reference uses for its full-width
   blocks: word, rule, uppercase subhead, one outline button. */
.formal { text-align: center; }
.formal__sub {
  margin-top: var(--s-5);
  font-size: var(--t-lg);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  text-wrap: balance;
}
.formal .btn-row { justify-content: center; }


/* ==========================================================================
   28. Bleed section
   Text centred in one half, photography filling the other and running off the
   edge of the page behind one oversized corner. The section is the grid, so
   the media column reaches the viewport edge without any negative-margin
   arithmetic.
   ========================================================================== */

/* About us — the photograph bleeds off the LEFT page edge, copy to its right.
   The mirror of .bleedsec below, which bleeds right and wedges into a corner;
   run together on the same ground they read as a matched pair.

   This does not live inside .wrap, because .wrap centres and pads and the
   photograph has to actually reach the page edge. .section carries no inline
   padding, so a direct child of the section starts at x=0. */
.splitbleed {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-8);
  align-items: center;
}
.splitbleed__media {
  /* <figure> carries the UA's own `margin: 1em 40px`, which quietly held the
     photograph 40px clear of the page edge — the one thing this component
     exists to do. */
  margin: 0;
  overflow: hidden;
  /* Square against the page edge it touches, oversized on the side that faces
     into the page. */
  border-radius: 0 var(--r-blob) var(--r-blob) 0;
  /* The reference sets its section photography in a black mat rather than
     letting it meet the cream ground directly. Padding + a night background
     is the mat; the image gets the same radius less the mat width so the two
     curves stay concentric. Only the three edges that are ON the page get a
     mat — the left edge is flush to the page edge and must stay flush. */
  background: var(--night);
  padding: var(--mat) var(--mat) var(--mat) 0;
  /* Lifts the panel off the cream so the mat reads as a mounted frame rather
     than a flat block. Offset to the right and down, away from the page edge
     it is flush against, so nothing shows outside the viewport. */
  box-shadow: 14px 18px 44px rgb(10 10 10 / 0.30);
}
.splitbleed__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 0 calc(var(--r-blob) - var(--mat)) calc(var(--r-blob) - var(--mat)) 0;
}
.splitbleed__text { padding-inline: var(--gutter); }

@media (min-width: 920px) {
  .splitbleed { grid-template-columns: 48% 1fr; gap: var(--s-9); }
  .splitbleed__media { aspect-ratio: 4 / 3; }
  .splitbleed__text { padding-inline: var(--s-6) var(--gutter); }
}

.bleedsec {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  align-items: stretch;
  overflow: hidden;
}

.bleedsec__text {
  padding: var(--section-y) var(--gutter);
  display: grid;
  justify-items: center;
  align-content: center;
  text-align: center;
}
.bleedsec__text > * { max-width: 46ch; }

/* Below the breakpoint the corner treatment cannot work — there is no spare
   corner to cram anything into — so it stacks: copy, then the photograph full
   width with its top corners rounded. */
.bleedsec__media {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-blob) var(--r-blob) 0 0;
}
.bleedsec__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The reference's menu section, measured: the photo panel is 331 of 945px wide
   (35%) and 400 of a 1200px section tall, sitting FLUSH to the page's right
   edge and to the section's bottom edge — genuinely wedged into the corner,
   not a half-width panel filling one side. One oversized radius on the corner
   that faces into the page; the other three are square because they are all
   against an edge. It carries no frame or border: the photograph meets the
   cream ground directly.

   Ours is proportioned a little wider and shorter than the reference's,
   because our photograph is 4:3 landscape where theirs is portrait-ish — a
   331x400 box would have cropped the room out of it.

   The panel is absolutely positioned, so it does NOT contribute to the
   section's height; min-height below is what guarantees there is a corner for
   it to sit in. The copy is capped at half the width so the two never meet. */
@media (min-width: 920px) {
  .bleedsec { min-height: 640px; }
  .bleedsec__text {
    max-width: 52%;
    padding-inline: var(--gutter);
  }
  .bleedsec__media {
    position: absolute;
    right: 0;
    bottom: 0;
    width: min(38%, 480px);
    aspect-ratio: 4 / 3;
    border-radius: var(--r-blob) 0 0 0;
    /* Same black mat as About. Only the two edges facing into the page carry
       it; right and bottom stay flush to the corner they are wedged into. */
    background: var(--night);
    padding: var(--mat) 0 0 var(--mat);
    /* Shadow thrown up and to the left — the two edges that face into the
       page. Right and bottom sit in the corner, so a shadow there would only
       fall off the page. */
    box-shadow: -14px -18px 44px rgb(10 10 10 / 0.30);
  }
  .bleedsec__media img {
    border-radius: calc(var(--r-blob) - var(--mat)) 0 0 0;
  }
}


.hero__controls {
  position: absolute;
  left: var(--gutter);
  bottom: var(--s-5);
  z-index: 3;
  display: flex;
  gap: var(--s-3);
}
.hero__ctrl {
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  background: rgb(10 10 10 / 0.45);
  color: #fff;
  border: 1px solid rgb(255 255 255 / 0.35);
  border-radius: var(--r-pill);
  cursor: pointer;
  backdrop-filter: blur(4px);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.hero__ctrl:hover { background: rgb(10 10 10 / 0.75); border-color: var(--accent); }
.hero__ctrl svg { width: 16px; height: 16px; }

@media (max-width: 768px) {
  .hero__controls { bottom: var(--s-4); left: var(--s-4); }
  .hero__ctrl { width: 36px; height: 36px; }
}

/* ==========================================================================
   31. Age gate

   Shown before anything else, dismissed by an explicit confirmation that is
   then remembered in localStorage. The class that hides it is set by a small
   script in <head> (hashed in the CSP), so a returning visitor never sees the
   gate flash between paint and script execution.

   This is a declaration, not a security control. The <noscript> block in the
   markup removes it entirely when scripting is off — nobody should be unable
   to reach a restaurant's address because a script failed to run.
   ========================================================================== */

.agegate {
  position: fixed;
  inset: 0;
  z-index: 1000;                 /* above --z-modal (600) */
  display: grid;
  place-items: center;
  padding: var(--gutter);

  /* A POPUP OVER THE SITE, not a page that replaces it — the site stays
     visible and recognisable behind the card, which is what tells a first-time
     visitor they have arrived somewhere rather than hit a door.

     The scrim is heavy (0.78) on purpose: the hero photograph behind this is
     bright neon on black and the card's own copy has to stay legible over
     whatever slide happens to be up. The blur is what stops the photograph
     competing for attention through the scrim.

     `backdrop-filter` on a fixed element is the thing that caused the mobile
     scroll drag in 10q — but nothing scrolls while this is up (body overflow
     is locked below) and the element is REMOVED on Enter, so it never composites
     against a moving page. Do not copy this pattern onto anything that survives
     the scroll. */
  background: rgb(4 3 2 / 0.78);
  backdrop-filter: blur(14px) saturate(0.9);
  -webkit-backdrop-filter: blur(14px) saturate(0.9);
}

/* No blur available (older Safari, Firefox with the flag off): fall back to a
   near-solid scrim so the copy never lands on a busy photograph. */
@supports not (backdrop-filter: blur(2px)) {
  .agegate { background: rgb(4 3 2 / 0.94); }
}

.age-ok .agegate { display: none; }

/* Hold the page still behind the gate; the same class releases it. */
html:not(.age-ok) body { overflow: hidden; }

/* The card. A menu-card device: an outer hairline in the brand gold and a
   second, fainter rule inset from it. The doubled rule is what makes this read
   as printed stationery rather than as a cookie banner — it is the one piece
   of ornament here, so it is allowed to be the only one. */
.agegate__panel {
  position: relative;
  width: min(100%, 33rem);
  padding: clamp(2.25rem, 6vw, 3.5rem) clamp(1.5rem, 5vw, 3rem);
  text-align: center;
  background: linear-gradient(180deg, #17150f 0%, #0e0d0a 100%);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-md);
  /* Deeper than --shadow-lg: this is lifted off a photograph now, not off a
     flat ground, and it needs the separation to read as a floating panel. */
  box-shadow: 0 30px 80px rgb(0 0 0 / 0.75), 0 0 0 1px rgb(0 0 0 / 0.5);
  animation: agegate-rise var(--dur-slow) var(--ease) both;
}

.agegate__panel::before {
  content: '';
  position: absolute;
  inset: 9px;
  border: 1px solid rgb(208 164 57 / 0.17);
  border-radius: calc(var(--r-md) - 4px);
  pointer-events: none;
}

@keyframes agegate-rise {
  from { opacity: 0; transform: translate3d(0, 14px, 0) scale(0.985); }
  to   { opacity: 1; transform: none; }
}

/* The TB monogram, not the wordmark: the wordmark is 900px of horizontal type
   and would set the width of the whole card. */
.agegate__mark {
  display: block;
  width: clamp(62px, 16vw, 84px);
  height: auto;
  margin: 0 auto var(--s-4);
}

.agegate__kicker {
  margin: 0;
  font-family: var(--font-script);
  font-size: var(--t-xl);
  line-height: 1;
  color: var(--accent);
}

.agegate__name {
  margin: var(--s-2) 0 0;
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: 0.22em;        /* wider than --track-display; this is a mark,
                                    not a heading, and it sits under script */
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Hairline, diamond, hairline. The rules fade OUT towards the card edges so
   they never quite touch the inner border. */
.agegate__orn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  margin: var(--s-5) 0;
}
.agegate__orn span {
  width: clamp(38px, 16%, 74px);
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent-line));
}
.agegate__orn span:last-child {
  background: linear-gradient(90deg, var(--accent-line), transparent);
}
.agegate__orn i {
  width: 7px;
  height: 7px;
  background: var(--accent);
  transform: rotate(45deg);
}

/* The legal sentence, and the reason the card exists, so it carries the
   display treatment. <br> in the markup breaks it in the same place at every
   width rather than letting a narrow card orphan "to drink" on its own line. */
.agegate__title {
  margin: 0;
  font-size: var(--t-2xl);
  font-weight: 800;
  line-height: var(--lh-snug);
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  color: var(--ink);
  text-wrap: balance;
}

/* Not .btn. The gate has one control and it should read as the way in, so it
   runs full width of the card's measure rather than sitting as a pill in the
   middle of it. */
.agegate__enter {
  display: block;
  width: 100%;
  min-height: 52px;
  margin: var(--s-6) 0 0;
  padding: var(--s-3) var(--s-6);
  background: var(--accent);
  color: var(--night);
  border: 2px solid var(--accent);
  border-radius: var(--r-pill);
  font: inherit;
  font-size: var(--t-sm);
  font-weight: 800;
  letter-spacing: var(--track-button);
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease), transform var(--dur-fast) var(--ease);
}
.agegate__enter:hover {
  background: var(--accent-bright);
  border-color: var(--accent-bright);
  box-shadow: 0 8px 26px rgb(208 164 57 / 0.22);
}
.agegate__enter:active { transform: translateY(1px); }
.agegate__enter:focus-visible {
  outline: 3px solid var(--accent-bright);
  outline-offset: 3px;
}

.agegate__fine {
  margin: var(--s-4) 0 0;
  font-size: var(--t-xs);
  letter-spacing: 0.04em;
  color: var(--ink-faint);
}

@media (prefers-reduced-motion: reduce) {
  .agegate__panel { animation: none; }
  .agegate__enter { transition: none; }
}
}

/* ==========================================================================
   32. Hero slideshow — photographs, swiped horizontally

   Rebuilt 2026-09-10 against MEASURED values from the Bird in Hand hero the
   client keeps pointing at. It runs UIkit 2.26.3, and its own slideshow
   options read:

       animation: swipe · autoplayInterval: 4000 · duration: 500
       kenburns: false · pauseOnHover: false · 5 slides

   So the transition is a 500ms HORIZONTAL SLIDE on a 4s hold — not the slow
   crossfade built earlier the same day. If this ever looks too quick, that is
   the reference's cadence and changing it is a decision to take with the
   client, not a bug to fix.

   Structure per slide, mirroring the reference's markup: the photograph, a
   flat overlay above it, then that slide's caption above that. The overlay is
   per-slide rather than one scrim over the whole hero specifically so the
   caption rides above its own darkening and swipes with it.

   THE CONTAIN/COVER REVERSAL — do not "fix" this back.
   Older notes in this file say never use `cover` here. That rule existed
   because the client's footage was VERTICAL, so cover on a wide stage threw
   two thirds of every frame away. These are landscape HD photographs shot for
   this slot. The reference itself cover-crops 800x1200 portrait sources into a
   full-width stage without apology. If vertical media ever returns, so does
   `contain` — and with it the blurred backdrop and portrait stacking that used
   to prop it up, both deleted.
   ========================================================================== */

.herofilm {
  position: absolute;
  inset: 0;
  z-index: 0;            /* holds the captions now, so no longer behind the page */
  overflow: hidden;
}

/* Position is driven entirely by --x, set inline by site.js, so the resting
   place of an off-stage slide is one stage-width to the right. Nothing here
   animates opacity: the reference slides, it does not dissolve. */
.herofilm__slide {
  position: absolute;
  inset: 0;
  overflow: hidden;
  transform: translate3d(var(--x, 100%), 0, 0);
  /* 500ms, matching the reference's `duration`. Paired with SLIDE in site.js
     section 7 — change both together. */
  transition: transform 500ms cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform;
}

/* Set by JS for one frame while a slide is snapped back to its resting place
   off stage, so the reset never animates across the viewport. */
.herofilm__slide.is-instant { transition: none; }

.herofilm__media {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Each slide sets its own focal point inline as --focus, because the photos
     are not one shape: three are square and one is landscape, and where the
     crop should hold differs per picture. The fallback is a slight upward bias,
     which suits a room shot. */
  object-position: var(--focus, center 40%);
}

/* ==========================================================================
   HERO CROP — three square photographs and one landscape

   The stage is the viewport less the header and announcement bar, so on a
   maximized desktop it is about 2.3:1 — wide and short. `cover` fills it by
   scaling until the WIDTH fits and discarding the rest.

   For the three SQUARE food photos (1254x1254) that discards the top and
   bottom, which crops into empty plate and table rather than into the dish.
   The client looked at it and said those three were fine as they were, so they
   are plain <img>s cropped by `cover`, each with its own focal point below.
   THAT IS DELIBERATE — do not "improve" them into the treatment slide 4 uses.

   Slide 4 USED TO BE the hard case. Its subjects — the Lexington Avenue sign,
   the neon, and the payphone under them — ran almost the full height of a
   PORTRAIT frame, so a 2.3:1 stage showed about a quarter of it and no choice
   of `object-position` fitted the rest. It was carried by a 2400x1000
   derivative (hero-4-wide.jpg) served through a <picture>: the photo at full
   height, centred, with the gap either side filled by a heavily blurred,
   darkened, desaturated copy of itself. Edge-stretch and mirroring were tried
   instead and were worse — stretching smeared the wall's warm glow into
   streaks, mirroring produced three payphones. The client never liked any of
   it: "i dont like the empty spaces".

   RESOLVED 2026-09-12 — the fill is GONE. The client supplied a genuine
   landscape frame, 3840x1800, subject centred with the scene extended outward:
   exactly the spec in ~/TeamworkOn3-hero-photos/README.md. It ships downsampled
   to 2560x1200 (2.13:1), so the source ratio matches the stage. `cover` now
   trims 0.4%-11% on normal screens and there is never a gap.

   THE <picture>, THE -wide DERIVATIVE AND THE LANDSCAPE MEDIA QUERY THAT RESET
   THIS SLIDE'S FOCAL POINT ARE ALL DELETED. Do not reintroduce them — a second
   photograph for this slide is no longer needed and would go stale silently.
   Previous files are in archive/hero-2026-09-12/.

   The lit subject spans 36.7%-63.3% of the frame's width, so even the tightest
   portrait-phone crop — about the middle 30% — keeps the sign, the neon and the
   payphone together. Keep that true if this photograph is ever replaced.
   ========================================================================== */

/* Focal points live HERE, not inline on the <img>, because an inline custom
   property cannot be overridden by a media query — and slide 4's has to be. */
/* Slide 1 since 2026-09-12. Square source, subject high in the frame — 25%
   is what keeps the portrait in the foam intact on a wide stage. See the
   comment on the slide in index.html before changing it. */
.herofilm__media--cup  { --focus: center 25%; }   /* tribute cappuccino */
.herofilm__media--s1   { --focus: center 55%; }   /* sliders */
.herofilm__media--s2   { --focus: center 30%; }   /* cocktail — keeps the
                                                     headline off the cup's
                                                     own gold lettering */
.herofilm__media--s3   { --focus: center 50%; }   /* tacos */
.herofilm__media--s4   { --focus: center 50%; }   /* neon wall — landscape
                                                     since 2026-09-12, framed
                                                     to the stage, so dead
                                                     centre is right at every
                                                     width. It was --tall, and
                                                     needed a media query to
                                                     re-centre it; neither is
                                                     needed now. */

/* The reference's overlay panel, measured: a flat rgba(0,0,0,0.6) across the
   whole photograph. Flat, not directional — the caption is centred now, so
   there is no one edge that needs protecting. */
.herofilm__slide::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgb(0 0 0 / 0.6);
}

.herofilm__caption {
  position: absolute;
  inset: 0;
  z-index: 1;                    /* above this slide's own overlay */
  display: grid;
  place-items: center;
  text-align: center;
  /* Clear of the dots along the bottom. */
  padding-block: var(--s-7) var(--s-9);
}
.herofilm__caption .hero__lede { margin-inline: auto; }

/* Centred headlines orphan their last word badly — "Pull up. Dig in. Vibe
   out." was dropping OUT. onto a line of its own. Balance evens the lines out;
   browsers without it just wrap as before. */
.herofilm__caption .display {
  text-wrap: balance;
  max-width: 18ch;
  margin-inline: auto;
}
.btn-row--center { justify-content: center; }

/* Dot indicators, as in the reference — five there, four here. Built by JS, so
   a no-JS visitor gets a single still photograph and no dead controls. They
   are real buttons: the reference's are decorative, but a control that shows
   position and cannot be used is worse than none. */
.herodots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--s-5);
  z-index: 3;
  display: flex;
  justify-content: center;
  gap: 12px;
}
.dot {
  width: 12px;
  height: 12px;
  padding: 0;
  border: 1px solid rgb(255 255 255 / 0.55);
  border-radius: 50%;
  background: rgb(255 255 255 / 0.28);
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.dot:hover { background: rgb(255 255 255 / 0.6); }
.dot[aria-current="true"] {
  background: var(--accent);
  border-color: var(--accent);
}

@media (max-width: 768px) {
  .herodots { bottom: var(--s-4); }
  .dot { width: 10px; height: 10px; }
}

/* Reduced motion: nothing slides and nothing advances on its own. The swap is
   instant and the dots still move it by hand. */
@media (prefers-reduced-motion: reduce) {
  .herofilm__slide { transition: none; }
}


/* Newsletter: optional-field hint, consent checkbox, honeypot. */
.field__opt { color: var(--ink-faint); font-weight: 400; text-transform: none; letter-spacing: normal; }

.check {
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
  margin-top: var(--s-4);
  font-size: var(--t-sm);
  line-height: var(--lh-snug);
  color: var(--ink-soft);
  cursor: pointer;
}
.check input {
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  accent-color: var(--accent);
}

/* Honeypot. Off-screen rather than display:none — some bots skip hidden
   fields, and this must still be fillable by them to be worth anything. It is
   aria-hidden and out of the tab order in the markup, so nobody else meets it. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}


/* ==========================================================================
   Cocktail slideshow

   Same engine as the hero (createSlideshow in site.js), so the slide mechanics
   are identical: position comes from --x, and .is-instant kills the transition
   for one frame while a slide is parked off stage.
   ========================================================================== */
.drinkshow {
  position: relative;
  width: min(100%, 560px);
  margin: var(--s-7) auto 0;
}
.drinkshow__stage {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--r-lg, 20px);
  background: var(--night-soft);
}
.drinkshow__slide {
  position: absolute;
  inset: 0;
  overflow: hidden;
  transform: translate3d(var(--x, 100%), 0, 0);
  transition: transform 500ms cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform;
}
.drinkshow__slide.is-instant { transition: none; }
.drinkshow__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* These photographs are not one shape — two portrait, one landscape — so
     each slide sets where the square crop should hold, the same way the hero
     slides do. */
  object-position: var(--focus, center);
}

/* Name and price sit ON the photograph, over a scrim that only darkens the
   bottom — the drinks are lit from above, so a full overlay would flatten the
   glass for no benefit. */
.drinkshow__caption {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--s-7) var(--s-5) var(--s-5);
  background: linear-gradient(to top, rgb(10 10 10 / 0.88) 0%, rgb(10 10 10 / 0.55) 55%, rgb(10 10 10 / 0) 100%);
  color: #fff;
}
.drinkshow__name {
  display: flex;
  align-items: baseline;
  gap: var(--s-4);
  margin: 0;
  font-size: var(--t-lg);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.drinkshow__price { margin-left: auto; color: var(--accent-bright); }
.drinkshow__desc {
  margin: var(--s-2) 0 0;
  font-size: var(--t-sm);
  color: #e6e2da;
}

.drinkshow__dots {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: var(--s-5);
}
.drinkshow__controls { position: absolute; left: var(--s-4); bottom: var(--s-4); z-index: 3; }

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

/* The menu, kept under the photograph. Hairline rows with a leader, matching
   the menu page rather than inventing a third way of setting a price list. */
.drinklist-wrap { width: min(100%, 560px); margin: var(--s-8) auto 0; }
.drinklist__title {
  margin: var(--s-7) 0 var(--s-4);
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
.drinklist-wrap > .drinklist__title:first-child { margin-top: 0; }
.drinklist__note {
  margin: calc(var(--s-3) * -1) 0 var(--s-4);
  font-size: var(--t-sm);
  color: var(--ink-faint);
}
.drinklist { list-style: none; margin: 0; padding: 0; }
.drinklist__row {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--rule);
}
.drinklist__name { font-weight: 600; }
.drinklist__leader {
  flex: 1;
  border-bottom: 1px dotted var(--rule-strong);
  transform: translateY(-4px);
}
.drinklist__price { font-weight: 700; color: var(--accent); }

/* ==========================================================================
   Specials, typeset

   The client's four promotional cards, rebuilt as real text rather than shown
   as images of text. Styled in the same gold-on-black language: a hairline
   gold frame with bracket corners standing in for the printed cards' ornate
   border. Deliberately NOT an attempt to fake gold foil — a flat gold hairline
   reads as intentional where a fake foil gradient reads as a bad copy.
   ========================================================================== */
.specgrid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-6);
  margin-top: var(--s-8);
}
@media (min-width: 900px) { .specgrid { grid-template-columns: repeat(2, 1fr); } }

.spec {
  position: relative;
  padding: clamp(1.5rem, 1rem + 2vw, 2.5rem);
  background: linear-gradient(180deg, #16130d 0%, var(--night) 70%);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-md);
  color: #f2eee6;
}

/* Bracket corners, echoing the printed cards' frame. Two pseudo-elements each
   drawing an L, which is enough to read as an ornamental border without any
   images. */
.spec::before,
.spec::after {
  content: '';
  position: absolute;
  width: 26px;
  height: 26px;
  border: 2px solid var(--accent);
  opacity: 0.75;
  pointer-events: none;
}
.spec::before { top: 10px; left: 10px; border-width: 2px 0 0 2px; border-radius: 6px 0 0 0; }
.spec::after  { bottom: 10px; right: 10px; border-width: 0 2px 2px 0; border-radius: 0 0 6px 0; }

.spec__kicker {
  margin: 0 0 var(--s-2);
  font-size: var(--t-xs, 0.75rem);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.spec__title {
  margin: 0;
  font-size: var(--t-2xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  color: #fff;
}
.spec__when {
  margin: var(--s-2) 0 var(--s-5);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--accent-line);
  font-size: var(--t-sm);
  color: var(--accent-bright);
}
.spec__body { margin: 0 0 var(--s-5); color: #d9d4ca; }
.spec__sub {
  margin: var(--s-6) 0 var(--s-3);
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
.spec__sub:first-of-type { margin-top: 0; }

.spec__list { list-style: none; margin: 0; padding: 0; }
.spec__row {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  padding: 7px 0;
}
.spec__item { font-weight: 600; }
.spec__leader {
  flex: 1;
  border-bottom: 1px dotted rgb(208 164 57 / 0.4);
  transform: translateY(-4px);
}
.spec__price { font-weight: 700; color: var(--accent-bright); }

.spec__note {
  margin: var(--s-5) 0 0;
  font-size: var(--t-sm);
  font-style: italic;
  color: #a9a293;
}

.spec__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4);
  margin-top: var(--s-6);
}

/* The printed card, kept one tap away: a thumbnail that opens the original
   graphic in the lightbox. It is a .gallery__item so site.js wires it up with
   no extra code, but it needs its own look — a small chip, not a grid tile. */
.spec__card-link {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  width: auto;
  aspect-ratio: auto;
  padding: 6px 14px 6px 6px;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--accent);
  font-size: var(--t-sm);
  font-weight: 600;
  cursor: zoom-in;
}
.spec__card-link img {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  object-fit: cover;
}
.spec__card-link:hover { border-color: var(--accent); background: var(--accent-tint); }
.spec__card-link:hover img { transform: none; filter: none; }

.btn--sm { min-height: 40px; padding-inline: var(--s-5); font-size: var(--t-sm); }

/* ==========================================================================
   40. THE TEAM — cut-out figures on the ground (2026-09-12)

   The photographs are transparent PNG/WebP cut-outs, so there is no frame to
   crop and no background to darken. The figure IS the artwork. Everything here
   exists to give it a place to stand:

     * a gold radial glow behind each figure, echoing the neon in the hero and
       the bar photograph in #about — this is what stops a cut-out reading as
       "pasted on";
     * a soft elliptical contact shadow at the feet, so the figure is standing
       on the section rather than hovering over it;
     * `object-fit: contain` and a fixed block size, so the WHOLE figure is
       always visible. Never change this to `cover` — it would behead them.

   Two columns hold at every width. These are tall, narrow figures; forcing
   them to one column on a phone makes each one enormous and pushes the rest
   of the page a full screen down.
   ========================================================================== */

.team {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-6);
  max-width: 62rem;
  margin-inline: auto;
}

.team__member { text-align: center; }

/* The stage. `isolation` keeps the glow's blend inside this element. */
.team__figure {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-height: 0;
}

/* The glow — an ellipse behind the figure, widest at chest height. Sized in %
   so it tracks the column rather than needing a breakpoint of its own. */
.team__figure::before {
  content: '';
  position: absolute;
  z-index: -2;
  left: 50%;
  top: 8%;
  width: 92%;
  aspect-ratio: 1 / 1.25;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at 50% 45%,
                rgb(208 164 57 / 0.30) 0%,
                rgb(208 164 57 / 0.13) 38%,
                rgb(208 164 57 / 0.04) 62%,
                transparent 78%);
  pointer-events: none;
}

/* Contact shadow, so the figure has weight on the ground. */
.team__figure::after {
  content: '';
  position: absolute;
  z-index: -1;
  left: 50%;
  bottom: 2%;
  width: 58%;
  height: 5%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at 50% 50%,
                rgb(0 0 0 / 0.55) 0%, transparent 72%);
  pointer-events: none;
}

.team__img {
  position: relative;
  display: block;
  width: 100%;
  height: clamp(20rem, 42vw, 32rem);
  object-fit: contain;      /* NEVER cover — see the block comment above */
  object-position: center bottom;
}

.team__name {
  margin: var(--s-5) 0 0;
  font-weight: 800;
  font-size: var(--t-lg);
  letter-spacing: 0.02em;
  color: var(--ink);
}

.team__role {
  margin: var(--s-1) 0 0;
  font-size: var(--t-sm);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

@media (max-width: 30rem) {
  .team { gap: var(--s-4); }
  .team__name { font-size: var(--t-base); }
  .team__role { font-size: 0.7rem; letter-spacing: 0.12em; }
}

/* The role line standing alone. Without a name above it, it needs the gap the
   name used to open up, or it crowds the figure's feet. Client's instruction
   2026-09-12: role only, no names. */
.team__role--solo { margin-top: var(--s-5); }

/* The tribute slide's quote. NOT `.display`, which the hero caption clamps to
   `max-width: 18ch` for short headlines — this line is ~64 characters and that
   measure would break it into four narrow lines. Sized between the hero lede
   and the hero display so it reads as a quotation rather than a headline, with
   the same gold rule the house quote in #quote uses. */
.hero__quote {
  position: relative;
  margin: 0 auto;
  padding-top: var(--s-6);
  max-width: 24ch;
  font-size: var(--t-2xl);
  font-weight: 700;
  font-style: italic;
  line-height: var(--lh-snug);
  text-wrap: balance;
  color: var(--ink);
  text-shadow: 0 2px 18px rgb(0 0 0 / 0.55);
}
.hero__quote::before {
  content: '';
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  width: 40px; height: 3px;
  background: var(--accent);
  border-radius: var(--r-pill);
}

/* Each host's own Instagram, under the role. Gold like every other link on the
   dark ground, with the same glyph the footer and #instagram use so it reads as
   one family. The handle is `word-break: break-word` because these are long and
   underscore-heavy — on a narrow phone column one will otherwise push its card
   wider than its neighbour and break the two-column grid. */
.team__handle {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-2);
  max-width: 100%;
  font-size: var(--t-sm);
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--accent);
  text-decoration: none;
  word-break: break-word;
}
.team__handle svg { width: 1em; height: 1em; flex: none; }
.team__handle:hover,
.team__handle:focus-visible { color: var(--accent-bright); text-decoration: underline; }

@media (max-width: 30rem) {
  .team__handle { font-size: 0.72rem; gap: var(--s-1); }
}

/* ==========================================================================
   41. THE STOREFRONT behind The Team (2026-09-12)

   The photograph is 1672x941 — 16:9, the shape specified in
   ~/TeamworkOn3-storefront/DIMENSIONS.txt. This section's box measures about
   1.95 on a 1920 stage, so `cover` trims very little and the sign, the
   entrance and the lit windows all survive. The figures are transparent
   cut-outs, so they read as standing outside the venue.

   *** RE-MEASURE BEFORE MOVING THIS ANYWHERE ELSE. *** It was first wrapped
   around Cocktails AND The Team together. That box is 0.384 and `cover`
   discarded 32% of the image's width — "too zoomed in cant see nothing", and
   correct. A box shows a whole picture only when their ratios match; `cover`
   crops and `contain` letterboxes, and there is no third option.

   A blurred wordmark was also tried behind Cocktails on 2026-09-12 and
   REMOVED at the client's request — the section is back to the flat ground.
   Do not reinstate it without asking; the logo files are still in
   from-client/photos/2026-09-12-team/ if it is ever wanted again.

   *** THIS IMAGE IS NOT CACHE-STAMPED. *** bump.py rewrites href/src/srcset in
   the PAGES; a url() inside a stylesheet is invisible to it, and this file is
   served under /assets/images/* (max-age=300, stale-while-revalidate=86400).
   If it is ever replaced, RENAME IT and change the url() here — overwriting in
   place looks unchanged for up to a day. That already bit once: storefront.jpg
   became storefront-wide.jpg and the old name had to be chased out of here.
   ========================================================================== */

.section--storefront { position: relative; isolation: isolate; }

.section--storefront::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -2;
  background: url('/assets/images/room/storefront-wide.jpg') center center / cover no-repeat;
  filter: blur(2px) saturate(0.95);
  pointer-events: none;
}

/* NOT DECORATION. The brand gold is 8.53:1 on the flat ground and drops far
   below that over lit brick and signage. This holds the effective ground near
   --night so the contrast ratios in this section still stand. Lightening it is
   a legibility change — check the Instagram handles if you touch it. */
.section--storefront::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to bottom,
      rgb(11 10 8 / 0.94) 0%,
      rgb(11 10 8 / 0.84) 18%,
      rgb(11 10 8 / 0.82) 50%,
      rgb(11 10 8 / 0.88) 82%,
      rgb(11 10 8 / 0.95) 100%);
  pointer-events: none;
}

/* On a phone the box turns tall and narrow, so a centred crop shows pavement.
   Hold it to the top, where the sign is. */
@media (max-width: 48rem) {
  .section--storefront::before { background-position: center top; }
  .section--storefront::after  { background: rgb(11 10 8 / 0.88); }
}
