/* ==========================================================================
   The Woods + Sidebar — "Dress Blues" visual system
   Navy / white / black only. Tailoring, not theme: sharp corners, hairline
   rules, disciplined uppercase labels, one 4px "piping" rule for emphasis.
   Three venue states on <body>: data-venue="overview" (no venue chosen, even
   hero, default navy ground), "woods" (navy ground, the static default) and
   "sidebar" (paper ground). Shared practical information is never hidden by the
   state. Ground rules keyed to the dark world use
   body:not([data-venue="sidebar"]) so overview inherits them.
   ========================================================================== */

/* The `hidden` attribute must actually hide. Several components here set an
   explicit display (.link-arrow is inline-flex, nav anchors are flex items),
   and a class selector outranks the UA stylesheet's `[hidden] { display:none }`
   — so a hidden element kept rendering. This is the one place !important is
   correct: `hidden` is a state, not a style, and nothing may override it. */
[hidden] { display: none !important; }

:root {
  /* Palette (design brief §F1) */
  --navy-ink: #0A111E;
  --navy-900: #111F38;
  --navy-700: #1C3355;
  --steel-500: #54708F;
  --steel-300: #9DB0C9;
  --black: #000000;
  --ink: #0D0F13;
  --paper: #F3F5F8;
  --white: #FFFFFF;
  --hair-dark: #24344E;
  --hair-light: #D4DAE3;

  /* Type */
  --font-display: "Barlow Condensed", "Arial Narrow", Impact, sans-serif;
  --font-body: "Public Sans", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "IBM Plex Mono", "Courier New", monospace;

  /* Layout */
  --container: 1200px;
  --gutter: clamp(16px, 4vw, 32px);
  --section-pad: clamp(64px, 10vw, 128px);
  --header-h: 72px;

  --ease: cubic-bezier(0.25, 0.1, 0.25, 1);
}

/* Mode-mapped surface roles. Default = Woods (navy). */
body {
  --surface: var(--navy-ink);
  --surface-panel: var(--navy-900);
  --surface-raised: var(--navy-700);
  --text: var(--white);
  --text-strong: var(--white);
  --meta: var(--steel-300);
  --hairline: var(--hair-dark);
  --piping: var(--white);
  --focus-ring: var(--white);
}
body[data-venue="sidebar"] {
  --surface: var(--paper);
  --surface-panel: var(--white);
  --surface-raised: var(--hair-light);
  --text: var(--ink);
  --text-strong: var(--navy-900);
  --meta: var(--steel-500);
  --hairline: var(--hair-light);
  --piping: var(--navy-900);
  --focus-ring: var(--navy-900);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  /* The header is sticky, so every in-page anchor — nav links, the skip link,
     hero CTAs, the footer nav — must stop clear of it. Without this the target
     section lands flush with the viewport top and its first 72px sit underneath
     the header. Keep this in step with --header-h. */
  scroll-padding-top: calc(var(--header-h) + 16px);
}
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  background: var(--surface);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  transition: background-color 320ms var(--ease), color 320ms var(--ease);
}
img { max-width: 100%; height: auto; display: block; }
h1, h2, h3, p, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
.site-header :focus-visible,
.mobile-menu :focus-visible,
.footer :focus-visible,
.action-bar :focus-visible,
.venue-section--woods :focus-visible,
.lightbox :focus-visible { outline-color: var(--white); }
.venue-section--sidebar :focus-visible,
.status-panel :focus-visible { outline-color: var(--navy-900); }

/* Available to screen readers, never painted. The mobile action bar uses it to
   say that its Instagram link opens in a new tab without printing that inside a
   64px-tall bar. */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: 8px;
  top: -48px;
  z-index: 200;
  padding: 12px 16px;
  background: var(--black);
  color: var(--white);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
}
.skip-link:focus { top: 8px; }

.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ---------- Type roles ---------- */
.display {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.015em;
  line-height: 0.95;
  font-size: clamp(32px, 5vw, 64px);
}
.mono, .section-head__meta {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* ---------- Announcement strip ---------- */
.announcement {
  background: var(--black);
  color: var(--white);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
  padding: 12px var(--gutter);
}
.announcement a { color: var(--white); }
.announcement__chip {
  border: 1px solid var(--white);
  padding: 2px 8px;
  margin-right: 12px;
}

/* ---------- Header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--navy-ink);
  color: var(--white);
  border-bottom: 1px solid var(--hair-dark);
}
.site-header__inner {
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 40px);
  height: var(--header-h);
  padding-inline: var(--gutter);
  max-width: 1440px;
  margin-inline: auto;
}
/* ---------- The venue lockup IS the venue control ----------
   Two independent logo links with a decorative plus between them. There is no
   text switch: the logos carry the whole interaction, so they need real hit
   targets (the group is 56px tall and each link is at least 44px wide) and a
   selected state that is not a button box.
   The marker is a 4px piping rule under the chosen logo — its PRESENCE, not its
   colour, carries the state, so it survives greyscale, forced colours and
   colour-blind rendering. The unselected logo stays bright and obviously
   clickable; it must never read as disabled. */
.site-lockup {
  display: flex;
  align-items: stretch;
  gap: 6px;
  flex-shrink: 0;
  height: 56px;
}
.site-lockup__venue {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  /* Padding, never a larger image, makes the target: the logo keeps its scale. */
  padding: 6px 10px 12px;
  text-decoration: none;
}
.site-lockup__venue::after {
  content: "";
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 2px;
  height: 0;
  background: var(--steel-300);
  transition: height 160ms var(--ease);
}
/* The links carry more bottom padding than top (the selection rule lives down
   there), so a plainly centred plus would sit 3px below the logos' optical
   centre. The margin cancels exactly that difference. */
.site-lockup .lockup__plus { align-self: center; margin-bottom: 6px; }
.lockup__mark { opacity: 0.8; transition: opacity 160ms var(--ease); }
.lockup__mark--woods { width: auto; height: 38px; }
.lockup__mark--sidebar { width: auto; height: 26px; }
/* Hover is gated on a real pointer: on touch, :hover sticks after a tap and the
   logo would keep a hover rule the visitor never asked for. */
@media (hover: hover) {
  .site-lockup__venue:hover .lockup__mark { opacity: 1; }
  .site-lockup__venue:hover::after { height: 2px; }
}
.site-lockup__venue:focus-visible .lockup__mark { opacity: 1; }
.site-lockup__venue:active::after { height: 2px; background: var(--white); }
.site-lockup__venue[aria-current="true"] .lockup__mark { opacity: 1; }
.site-lockup__venue[aria-current="true"]::after { height: 4px; background: var(--white); }
/* Overview: no venue is chosen, so there is nothing to step back — both marks
   come up to full strength and neither carries the rule. Three readable header
   states: overview (both bright, no rule), selected (bright + 4px rule), other
   (0.8, no rule). The rule is what carries selection, never colour alone. */
body[data-venue="overview"] .site-lockup__venue .lockup__mark { opacity: 1; }
.lockup__plus {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 22px;
  color: var(--white);
  line-height: 1;
}
.primary-nav {
  display: flex;
  gap: clamp(12px, 2vw, 28px);
  margin-left: auto;
}
.primary-nav a {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--white);
  padding: 8px 2px;
  position: relative;
  /* Two-word items ("This Week", "The Woods", "Find Us") must never break
     across lines inside a fixed-height header. */
  white-space: nowrap;
}

.primary-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 2px;
  height: 2px;
  width: 0;
  background: var(--white);
  transition: width 160ms var(--ease);
}
.primary-nav a:hover::after,
.primary-nav a:focus-visible::after { width: 100%; }
.site-header__actions {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-left: auto;
}
.primary-nav + .site-header__actions { margin-left: 0; }
.menu-toggle {
  display: none;
  width: 44px;
  height: 44px;
  position: relative;
}
.menu-toggle span,
.menu-toggle span::before,
.menu-toggle span::after {
  content: "";
  position: absolute;
  left: 10px;
  width: 24px;
  height: 2px;
  background: var(--white);
}
.menu-toggle span { top: 21px; }
.menu-toggle span::before { left: 0; top: -7px; }
.menu-toggle span::after { left: 0; top: 7px; }

/* ---------- Status dots (always paired with the state WORD) ----------
   Restrained, deliberately: a muted green and a muted red with a soft glow,
   never a saturated "gamer" green or a flashing alert red. There is no
   animation at all — a bar being open is not an emergency. Colour is never
   the only signal; every dot sits next to OPEN or CLOSED in text. */
:root {
  --status-open: #4E9A6B;
  --status-open-glow: rgba(78, 154, 107, 0.34);
  --status-closed: #B4564F;
  --status-closed-glow: rgba(180, 86, 79, 0.30);
}
.status-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}
.status-dot--open {
  background: var(--status-open);
  box-shadow: 0 0 0 3px var(--status-open-glow);
}
.status-dot--closed {
  background: var(--status-closed);
  box-shadow: 0 0 0 3px var(--status-closed-glow);
}
.status-dot--unknown { background: transparent; box-shadow: inset 0 0 0 1px currentColor; opacity: 0.6; }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  /* Breathing room under the status card, previously provided by the hero
     venue switch that used to sit here. */
  padding-bottom: clamp(20px, 2.5vw, 32px);
}
.hero__panels {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-bottom: 2px solid var(--black);
}
.hero-panel {
  position: relative;
  display: block;
  min-height: clamp(420px, 76vh, 820px);
  overflow: hidden;
  text-decoration: none;
  transition: opacity 320ms var(--ease);
}
.hero-panel--woods { background: var(--navy-ink); border-right: 2px solid var(--black); }
.hero-panel--sidebar { background: var(--paper); }
.hero-panel__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity 320ms var(--ease);
}
.hero-panel picture { display: contents; }
/* The shipped Sidebar derivatives are already cropped to the right of the
   original frame (see README → "Photography"), so this only fine-tunes the
   vertical framing: doorway and sky above, crowd below. */
.hero-panel--sidebar .hero-panel__art { object-position: 50% 45%; }
/* The room reads best from its centre; the foreground heads at the very bottom
   are the least useful part of the frame. */
.hero-panel--woods .hero-panel__art { object-position: 50% 38%; }
.hero-panel__content {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 16px;
  padding: clamp(24px, 4vw, 56px);
  /* keep the CTA clear of the status card overlapping the seam below */
  padding-bottom: 200px;
}
/* The scrim has to carry the logo AND the label. It was fading out by 60%,
   which was survivable only while the inactive panel was also washed out by an
   opacity veil; with the photographs at full strength the label needs a real
   field to sit on. */
.hero-panel--woods .hero-panel__content {
  background: linear-gradient(180deg, rgba(10, 17, 30, 0.72) 0%, rgba(10, 17, 30, 0.22) 42%, rgba(10, 17, 30, 0) 64%);
}
.hero-panel--sidebar .hero-panel__content {
  background: linear-gradient(180deg, rgba(243, 245, 248, 0.86) 0%, rgba(243, 245, 248, 0.3) 42%, rgba(243, 245, 248, 0) 64%);
}
.hero-panel__mark { width: clamp(150px, 16vw, 230px); height: auto; }
.hero-panel--sidebar .hero-panel__mark { width: clamp(140px, 15vw, 215px); }
.hero-panel__meta {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.hero-panel--woods .hero-panel__meta { color: var(--steel-300); }
/* Navy rather than steel: this label sits on sunlit brick past the strong part
   of the scrim, and the mid-tone steel did not hold up against it. */
.hero-panel--sidebar .hero-panel__meta { color: var(--navy-900); }
.hero-panel__cta {
  margin-top: auto;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 12px 18px;
  border: 2px solid;
}
/* The CTA sits low in the panel, past the end of the scrim, directly on the
   photograph — an outlined label there was legible only by luck of whatever
   crowd happened to be behind it. Filling it makes contrast independent of the
   picture, and reads as the button it already behaved like. */
.hero-panel--woods .hero-panel__cta {
  background: var(--white); color: var(--navy-900); border-color: var(--white);
}
.hero-panel--sidebar .hero-panel__cta {
  background: var(--navy-900); color: var(--white); border-color: var(--navy-900);
}
.hero-panel--woods:hover .hero-panel__cta,
.hero-panel--woods:focus-visible .hero-panel__cta { background: var(--steel-300); border-color: var(--steel-300); }
.hero-panel--sidebar:hover .hero-panel__cta,
.hero-panel--sidebar:focus-visible .hero-panel__cta { background: var(--navy-700); border-color: var(--navy-700); }
.hero-panel:hover .hero-panel__cta,
.hero-panel:focus-visible .hero-panel__cta { text-decoration: underline; text-underline-offset: 4px; }

/* ---------- What the switch actually does ----------
   The old build changed a background colour and a filter chip, so pressing it
   read as doing nothing. The selected venue now takes real estate: its hero
   panel widens to 60% and comes up to full strength, while the other panel
   holds 40% and steps back. Both stay visible, linked and keyboard-reachable —
   nothing is hidden, so nothing is lost by choosing a side.
   The grid animates on grid-template-columns rather than transforms, so the
   panels stay in flow and the status card below them never jumps. */
/* The panel weighting only animates once the initial mode has been applied.
   Transitioning on first paint would animate the split open on every load and
   re-run responsive-image selection mid-animation. */
body.mode-ready .hero__panels {
  transition: grid-template-columns 420ms var(--ease);
}
/* Overview is a real third state, not "Woods with the marker hidden": the split
   is exactly even and every de-emphasis rule below is keyed to the two venue
   states, so overview simply never matches one. Both photographs stay at full
   strength, both marks stay full size, and neither panel carries the edge rule.
   Overview keeps the site's default navy ground — the neutral signal is the
   balanced hero and the unmarked logos, not a third colour world. */
body[data-venue="overview"] .hero__panels { grid-template-columns: 1fr 1fr; }
body[data-venue="woods"] .hero__panels { grid-template-columns: 60fr 40fr; }
body[data-venue="sidebar"] .hero__panels { grid-template-columns: 40fr 60fr; }

/* The unselected side steps back with brightness and saturation, not opacity
   alone, so it still reads as a photograph rather than a faded layer. */
.hero-panel__art { transition: opacity 320ms var(--ease), filter 420ms var(--ease); }
/* De-emphasis is done with FILTER ONLY — never opacity.
   Opacity blends the photograph into whatever is behind it, and the Sidebar
   panel sits on paper: at 0.55 the picture turned milky, faces and brickwork
   washed out, and the panel read as a disabled control rather than the other
   half of the venue. Filter keeps the image fully opaque and still clearly
   secondary. The 60/40 width, the edge rule and the logo scale carry most of
   the state anyway, so this can stay gentle enough to keep detail. */
body[data-venue="woods"] .hero-panel--sidebar .hero-panel__art,
body[data-venue="sidebar"] .hero-panel--woods .hero-panel__art {
  filter: saturate(0.6) brightness(0.9) contrast(1.02);
}
/* A rule of colour along the selected panel's edge — a second, non-colour cue
   that survives greyscale and high-contrast rendering. */
.hero-panel::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 0;
  background: currentColor;
  transition: height 300ms var(--ease);
}
body[data-venue="woods"] .hero-panel--woods::after,
body[data-venue="sidebar"] .hero-panel--sidebar::after { height: 6px; }
.hero-panel--woods::after { color: var(--white); }
.hero-panel--sidebar::after { color: var(--navy-900); }

/* The unselected panel's label recedes; its CTA stays legible and clickable. */
body[data-venue="woods"] .hero-panel--sidebar .hero-panel__mark,
body[data-venue="sidebar"] .hero-panel--woods .hero-panel__mark {
  opacity: 0.72;
  transform: scale(0.92);
  transform-origin: left center;
}
.hero-panel__mark { transition: opacity 320ms var(--ease), transform 320ms var(--ease); }

/* Venue photography follows the mode: the other venue's section imagery steps
   back a little so the page reads as focused, but it is never hidden — the
   section stays fully readable and the pictures stay meaningful. */
.venue-media img { transition: filter 420ms var(--ease); }
body[data-venue="woods"] .venue-section--sidebar .venue-media img,
body[data-venue="sidebar"] .venue-section--woods .venue-media img {
  filter: saturate(0.7) brightness(0.94);
}

@media (prefers-reduced-motion: reduce) {
  .hero__panels,
  .hero-panel__art,
  .hero-panel__mark,
  .hero-panel::after,
  .venue-media img { transition: none; }
}

.status-panel {
  position: relative;
  z-index: 2;
  width: min(400px, calc(100% - 2 * var(--gutter)));
  margin: -140px auto 0;
  background: var(--white);
  color: var(--ink);
  border: 2px solid var(--black);
  padding: clamp(24px, 3vw, 36px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: center;
  align-items: center;
}
.status-panel__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(34px, 4.4vw, 46px);
  line-height: 0.95;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--navy-900);
}
.status-panel__plus { font-weight: 600; }
.status-panel__support {
  font-size: 15px;
  color: var(--ink);
}
.status-panel__address {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--steel-500);
}
.status-panel__hours-link {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.status-panel__hours-link a { color: var(--navy-900); }

/* ---------- Status rail (one live pill per venue, above the hero) ----------
   The rail mirrors the hero's own column proportions so each pill stays
   locked to the panel it describes — even, then weighted when a venue is
   selected. It transitions on the same curve as .hero__panels, so the pill and
   its photograph move together rather than sliding apart. */
.status-rail {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-bottom: 2px solid var(--black);
  background: var(--navy-ink);
}
body.mode-ready .status-rail {
  transition: grid-template-columns 420ms var(--ease);
}
body[data-venue="overview"] .status-rail { grid-template-columns: 1fr 1fr; }
body[data-venue="woods"] .status-rail { grid-template-columns: 60fr 40fr; }
body[data-venue="sidebar"] .status-rail { grid-template-columns: 40fr 60fr; }

.status-pill {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 14px;
  min-height: 44px;
  padding: 12px clamp(16px, 3vw, 32px);
  text-decoration: none;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.4;
}
.status-pill--woods {
  background: var(--navy-ink);
  color: var(--steel-300);
  border-right: 2px solid var(--black);
}
.status-pill--sidebar {
  background: var(--paper);
  color: var(--steel-500);
}
.status-pill__venue {
  font-weight: 500;
  letter-spacing: 0.16em;
}
.status-pill--woods .status-pill__venue { color: var(--white); }
.status-pill--sidebar .status-pill__venue { color: var(--navy-900); }

.status-pill__state {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
  letter-spacing: 0.14em;
}
.status-pill[data-state="open"] .status-pill__state { color: var(--status-open); }
.status-pill[data-state="closed"] .status-pill__state { color: var(--status-closed); }
.status-pill--woods[data-state="open"] .status-pill__state { color: #7FC79B; }
.status-pill--woods[data-state="closed"] .status-pill__state { color: #E08A82; }

.status-pill__detail {
  letter-spacing: 0.06em;
  text-transform: none;
  font-size: 12px;
}
.status-pill:hover .status-pill__detail,
.status-pill:focus-visible .status-pill__detail { text-decoration: underline; }
.status-pill--sidebar:focus-visible { outline-color: var(--navy-900); }

@media (prefers-reduced-motion: reduce) {
  body.mode-ready .status-rail { transition: none; }
}

/* ---------- Buttons & links ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 10px 22px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  border: 2px solid var(--navy-900);
}
.btn--primary { background: var(--navy-900); color: var(--white); }
.btn--primary:hover, .btn--primary:focus-visible { background: var(--navy-700); }
.btn--ghost { background: transparent; color: inherit; border-color: currentColor; }
.link-arrow {
  display: inline-block;
  margin-top: 24px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* ---------- Sections ---------- */
.section { padding-block: var(--section-pad); }
.section--tonight, .section--week { border-bottom: 1px solid var(--hairline); }
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: clamp(32px, 5vw, 56px);
  padding-bottom: 16px;
  border-bottom: 1px solid var(--hairline);
}
.section-head__meta { color: var(--meta); }

/* ---------- Tonight ---------- */
.tonight-grid {
  display: grid;
  grid-template-columns: 7fr 5fr;
  gap: clamp(24px, 4vw, 48px);
  align-items: start;
}
.tonight-grid__events { display: flex; flex-direction: column; gap: 16px; }
.event-row {
  display: grid;
  grid-template-columns: 110px 1fr auto;
  gap: 16px;
  align-items: baseline;
  padding: 20px;
  border: 1px solid var(--hairline);
  background: var(--surface-panel);
}
.event-row--featured { border-left: 4px solid var(--piping); }
.event-row__time {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.12em;
}
.event-row__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 28px;
  line-height: 1;
  text-transform: uppercase;
}
.event-row__title--cancelled { text-decoration: line-through; }
.event-row__meta {
  grid-column: 2 / -1;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 14px;
  color: var(--meta);
}
.venue-chip {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border: 1px solid currentColor;
  padding: 3px 8px;
  align-self: center;
}
.tonight-grid__aside { display: flex; flex-direction: column; gap: 16px; }
.aside-card {
  border: 1px solid var(--hairline);
  background: var(--surface-panel);
  padding: 20px 22px;
}
.aside-card__label {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--meta);
  margin-bottom: 10px;
}
.aside-card p { font-size: 15px; }
.aside-card__meta { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em; color: var(--meta); margin-top: 8px; }
.aside-card__meta:empty { display: none; }
.aside-card__links { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.aside-card__links a, .aside-card a { color: inherit; }
.aside-card--onlight {
  background: var(--white);
  border: 2px solid var(--black);
  color: var(--ink);
  margin-top: 24px;
}
.aside-card--onlight .aside-card__label { color: var(--steel-500); }

/* ---------- Empty states ---------- */
.empty-state {
  border: 1px dashed var(--hairline);
  padding: clamp(24px, 4vw, 40px);
}
.empty-state__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 26px;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.empty-state p { font-size: 15px; color: var(--meta); max-width: 48ch; }
.empty-state a { color: inherit; }

/* ---------- This Week ledger ---------- */
.week-ledger { display: flex; flex-direction: column; }
.week-row {
  display: grid;
  grid-template-columns: 64px 120px 1fr auto;
  gap: 16px;
  align-items: baseline;
  padding: 18px 12px;
  border-bottom: 1px solid var(--hairline);
  transition: background-color 160ms var(--ease), opacity 320ms var(--ease);
}
.week-row:first-child { border-top: 1px solid var(--hairline); }
.week-row:hover { background: var(--surface-panel); }
.week-row--dimmed { opacity: 0.4; }
.week-row--featured { border-left: 4px solid var(--piping); padding-left: 16px; }
.week-row__day, .week-row__time {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.week-row__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 24px;
  line-height: 1;
  text-transform: uppercase;
}
.week-row__desc { grid-column: 3 / 4; font-size: 14px; color: var(--meta); }

/* ---------- Venue sections (fixed color worlds) ---------- */
.venue-section { padding-block: var(--section-pad); }
.venue-section--woods {
  background: var(--navy-ink);
  color: var(--white);
  border-block: 2px solid var(--black);
}
.venue-section--sidebar {
  background: var(--paper);
  color: var(--ink);
  border-bottom: 2px solid var(--black);
}
.venue-section__grid {
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: clamp(32px, 5vw, 64px);
  align-items: start;
}
.venue-section__grid--mirrored { grid-template-columns: 7fr 5fr; }
.venue-section__mark { width: clamp(180px, 20vw, 260px); height: auto; margin-bottom: 28px; }
.venue-section--sidebar .venue-section__mark { width: clamp(160px, 18vw, 235px); }
.venue-section .display { margin-bottom: 20px; }
.venue-section--woods .display { color: var(--white); }
.venue-section--sidebar .display { color: var(--navy-900); }
.venue-section__text p { margin-bottom: 14px; max-width: 52ch; }
.venue-section--woods .venue-section__text p { color: var(--steel-300); }
.venue-section--sidebar .venue-section__text p { color: var(--ink); }
.venue-section__text p a { color: inherit; }
.venue-meta { margin-top: 28px; border-top: 1px solid var(--hair-dark); }
.venue-meta--onlight { border-color: var(--hair-light); }
.venue-meta li {
  display: flex;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--hair-dark);
  font-size: 14px;
  align-items: baseline;
}
.venue-meta--onlight li { border-color: var(--hair-light); }
.venue-meta__key {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  flex: 0 0 96px;
}
.venue-section--woods .venue-meta__key { color: var(--steel-300); }
.venue-section--sidebar .venue-meta__key { color: var(--steel-500); }
.venue-meta a { color: inherit; }
/* ---------- Venue media ----------
   The two venues do NOT share a media layout, and that is the point. The Woods
   runs a dense four-frame block; Sidebar runs one frame with air around it. The
   asset libraries are genuinely unequal and the composition states that rather
   than padding one side out to match the other. */
.venue-section__media { display: grid; }
.venue-media { margin: 0; }
.venue-media picture { display: block; }
.venue-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border: 1px solid var(--hairline);
}
.venue-section--woods .venue-media img { border-color: var(--hair-dark); }
.venue-section--sidebar .venue-media img { border-color: var(--hair-light); }

/* The Woods — layered. A tall frame holds the left field, two smaller frames
   stack beside it, and the daylight storefront runs as a wide strip underneath
   so the block reads arrival-last rather than as four equal tiles. */
.venue-section__media--dense {
  grid-template-columns: 3fr 2fr;
  grid-template-areas:
    "crowd band"
    "crowd dj"
    "strip strip";
  gap: 8px;
  align-items: stretch;
}
.venue-media--tall    { grid-area: crowd; }
.venue-media--wide    { grid-area: band; }
.venue-media--upright { grid-area: dj; }
.venue-media--strip   { grid-area: strip; }
/* Fixed ratios keep the block stable while images load and stop any frame from
   dictating the height of the others. */
.venue-media--tall picture,
.venue-media--tall img { aspect-ratio: 3 / 4; }
.venue-media--wide picture,
.venue-media--wide img { aspect-ratio: 4 / 3; }
.venue-media--upright picture,
.venue-media--upright img { aspect-ratio: 3 / 4; }
/* The storefront is the smallest source on the page (640px). Held to a letterbox
   strip it never renders wider than its own pixels can carry. */
.venue-media--strip picture,
.venue-media--strip img { aspect-ratio: 21 / 9; }
.venue-media--strip img { object-position: 50% 42%; }

/* Sidebar — one frame, deliberately large, with light space around it. */
.venue-section__media--single {
  grid-template-columns: minmax(0, 1fr);
  justify-items: start;
}
.venue-media--feature { width: min(100%, 30rem); }
.venue-media--feature picture,
.venue-media--feature img { aspect-ratio: 4 / 5; }

/* ---------- Traditions ---------- */
.traditions-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
}
.tradition-card {
  border: 1px solid var(--hairline);
  background: var(--surface-panel);
  padding: 24px;
}
.tradition-card h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 28px;
  text-transform: uppercase;
  margin-bottom: 10px;
}
.tradition-card__schedule {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--meta);
  margin-top: 12px;
}

/* ---------- Gallery ---------- */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 8px;
}
.gallery-item { padding: 0; border: 1px solid var(--hairline); }
.gallery-item[data-orientation="landscape"] { grid-column: span 6; }
.gallery-item[data-orientation="portrait"] { grid-column: span 3; }
.gallery-item img { width: 100%; height: 100%; object-fit: cover; }

.lightbox {
  border: 2px solid var(--black);
  padding: 0;
  background: var(--white);
  max-width: min(1080px, 92vw);
}
.lightbox::backdrop { background: rgba(10, 17, 30, 0.92); }
.lightbox figure { margin: 0; }
.lightbox img { max-height: 74vh; width: auto; max-width: 100%; margin-inline: auto; }
.lightbox figcaption {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 18px;
  font-size: 14px;
  border-top: 1px solid var(--hair-light);
}
.lightbox__venue {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel-500);
}
.lightbox__close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 44px;
  height: 44px;
  font-size: 24px;
  line-height: 1;
  background: var(--white);
  border: 2px solid var(--black);
  z-index: 1;
}
.lightbox__nav {
  display: flex;
  justify-content: space-between;
  border-top: 1px solid var(--hair-light);
}
.lightbox__nav button {
  min-width: 64px;
  min-height: 48px;
  font-size: 18px;
}

/* ---------- Find Us ---------- */
.find-grid {
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: clamp(24px, 4vw, 48px);
  align-items: start;
}
.find-card {
  background: var(--surface-panel);
  border: 1px solid var(--hairline);
  padding: clamp(24px, 3vw, 36px);
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-start;
}
body[data-venue="sidebar"] .find-card { border: 2px solid var(--black); }
.find-card__address {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(24px, 3vw, 32px);
  line-height: 1.1;
  text-transform: uppercase;
}
.find-card__phone a { font-size: 17px; font-weight: 500; color: inherit; }
.find-card__label {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--meta);
  margin-top: 18px;
}
.find-card p { font-size: 15px; }
.find-card__dora {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--hairline);
  font-size: 13px;
  color: var(--meta);
}
.find-card .btn { margin-top: 20px; align-self: stretch; }
/* Keyed to "not the paper ground" rather than to Woods: overview uses the same
   navy ground, where a navy primary button would vanish. */
body:not([data-venue="sidebar"]) .find-card .btn--primary { background: var(--white); color: var(--navy-900); border-color: var(--white); }
body:not([data-venue="sidebar"]) .find-card .btn--primary:hover,
body:not([data-venue="sidebar"]) .find-card .btn--primary:focus-visible { background: var(--steel-300); border-color: var(--steel-300); }

.hours-block { width: 100%; }
.hours-block p { font-size: 15px; }
.hours-table { width: 100%; border-collapse: collapse; }
.hours-table th, .hours-table td {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-align: left;
  padding: 8px 4px;
  border-bottom: 1px solid var(--hairline);
}
.hours-table tr.is-today th, .hours-table tr.is-today td { border-left: 4px solid var(--piping); padding-left: 10px; }
.hours-table caption { text-align: left; font-size: 12px; color: var(--meta); padding-bottom: 8px; }

.find-map { display: flex; flex-direction: column; gap: 12px; }
.find-map__frame {
  height: clamp(320px, 44vw, 460px);
  border: 2px solid var(--black);
  background: var(--surface-panel);
}
.find-map__frame.is-fallback { display: grid; place-items: center; }
.find-map__fallback { font-size: 15px; color: var(--meta); }
.find-map__link a { color: inherit; font-weight: 500; font-size: 15px; }
/* Leaflet tiles stay naturally colorized; keep controls legible */
.leaflet-container { font: 12px/1.4 var(--font-body); }

/* ---------- Contact ---------- */
/* ---------- Rentals ----------
   Shared practical content, so it runs on the mode surface like Tonight and
   Find Us rather than adopting either venue's fixed palette — the form serves
   both bars equally and should not look like it belongs to one of them. */
.section--rentals { border-top: 1px solid var(--hairline); }
.rentals-grid {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: clamp(24px, 4vw, 56px);
  align-items: start;
}
.rentals-intro { max-width: 34ch; }
.rentals-lede { font-size: 19px; line-height: 1.5; margin: 0 0 16px; }
.rentals-boundary { color: var(--meta); margin: 0 0 16px; }
.rentals-contact { color: var(--meta); margin: 0; }
.rentals-contact a { color: inherit; }

/* Venue choice — visible and editable, never a hidden field. The visitor must
   always be able to see which bar they are about to ask about. The two venue
   options carry equal weight; neither is styled as the default. */
.venue-choice { border: 0; margin: 0 0 28px; padding: 0; }
.venue-choice legend {
  padding: 0;
  margin-bottom: 12px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--meta);
}
.venue-choice__options {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
.venue-choice__option {
  position: relative;
  display: grid;
  gap: 4px;
  padding: 14px 16px;
  border: 2px solid var(--hairline);
  background: var(--surface);
  cursor: pointer;
}
.venue-choice__option input {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.venue-choice__title { font-weight: 600; }
.venue-choice__hint { font-size: 13px; color: var(--meta); }
.venue-choice__option:hover { border-color: var(--text); }
/* Selected state uses a border weight change AND an inset rule, not colour
   alone, so it survives greyscale and forced-colours rendering. */
.venue-choice__option:has(input:checked) {
  border-color: var(--text);
  box-shadow: inset 4px 0 0 0 var(--text);
}
.venue-choice__option:has(input:focus-visible) {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

.rental-form__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px clamp(12px, 2vw, 24px);
}
.form-field { display: grid; gap: 6px; }
.form-field--full { grid-column: 1 / -1; }
.form-field label {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.form-field__optional { color: var(--meta); letter-spacing: 0.06em; text-transform: none; }
.form-field input,
.form-field textarea {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  border: 2px solid var(--hairline);
  border-radius: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px; /* 16px avoids the iOS zoom-on-focus jump */
}
.form-field textarea { min-height: 132px; resize: vertical; }
.form-field input:focus-visible,
.form-field textarea:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-color: var(--text);
}
.form-field ::placeholder { color: #5C6675; opacity: 1; }
/* Only flag invalid fields after a submit attempt — never while the visitor is
   still working through an empty form. */
.rental-form.is-submitted :invalid { border-color: #A6303B; }

.honeypot {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.rental-form__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 24px;
  margin-top: 24px;
}
.form-privacy { margin: 0; max-width: 42ch; font-size: 14px; color: var(--meta); }
.form-privacy a { color: inherit; }
.form-local-status {
  flex-basis: 100%;
  margin: 0;
  padding: 12px 14px;
  border-left: 4px solid var(--focus-ring);
  background: var(--surface-raised);
  font-size: 14px;
}
.js .form-local-status[hidden] { display: none; }

/* On the navy ground (Woods and overview) the navy primary button would vanish —
   same inversion the Find Us card already uses. */
body:not([data-venue="sidebar"]) .section--rentals .btn--primary {
  background: var(--white); color: var(--navy-900); border-color: var(--white);
}
body:not([data-venue="sidebar"]) .section--rentals .btn--primary:hover,
body:not([data-venue="sidebar"]) .section--rentals .btn--primary:focus-visible {
  background: var(--steel-300); border-color: var(--steel-300);
}

/* Two link-arrows per venue section sit on one row. */
.venue-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 28px;
  margin: 0;
}

.footer__nav { margin: 0 0 4px; }
.footer__nav a { color: inherit; }

@media (max-width: 860px) {
  .rentals-grid { grid-template-columns: minmax(0, 1fr); }
  .rentals-intro { max-width: none; }
}
@media (max-width: 560px) {
  /* One field per row: a date picker and a number spinner both need room. */
  .rental-form__grid { grid-template-columns: minmax(0, 1fr); }
  .venue-choice__options { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Utility pages (thanks, privacy, 404) ----------
   Same system at a smaller scale — these are rooms off the main page, not a
   second design. They set data-venue on <body> to pick a ground. */
.utility-page {
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-block: clamp(48px, 8vw, 96px);
  background: var(--surface);
  color: var(--text);
}
.utility-page__inner { max-width: 60ch; }
.utility-page__lockup {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: clamp(32px, 6vw, 56px);
  text-decoration: none;
}
.utility-page__lockup img:first-child { width: auto; height: 44px; }
.utility-page__lockup img:last-child { width: auto; height: 30px; }
.utility-page__eyebrow { color: var(--meta); margin-bottom: 12px; }
.utility-page__lede { margin-top: 20px; font-size: 19px; max-width: 52ch; }
.utility-page__updated { color: var(--meta); margin-top: 8px; }
.utility-page__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: clamp(28px, 5vw, 44px);
}
.utility-page--legal { align-items: flex-start; }
.legal-body { margin-top: clamp(28px, 5vw, 44px); }
.legal-body h2 {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--meta);
  margin: 28px 0 8px;
  padding-left: 12px;
  border-left: 4px solid var(--piping);
}
.legal-body p { max-width: 62ch; }
.legal-body a { color: inherit; }

.section--contact { border-top: 1px solid var(--hairline); text-align: center; }
.section--contact .display { margin-bottom: 20px; }
.contact-line { font-size: 17px; margin-bottom: 24px; }
.contact-line a { color: inherit; font-weight: 600; }
.contact-social { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* ---------- Footer ---------- */
.footer {
  background: var(--black);
  color: var(--white);
  padding-block: clamp(48px, 6vw, 80px);
}
.footer__inner { display: flex; flex-direction: column; gap: 14px; align-items: flex-start; }
.footer__lockup { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.footer__lockup img:first-child { height: 34px; width: auto; }
.footer__lockup img:last-child { height: 23px; width: auto; }
.footer p { font-size: 14px; color: var(--steel-300); }
.footer a { color: var(--white); }
.footer__meta { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em; }

/* ---------- Mobile menu ---------- */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 150;
  background: var(--navy-ink);
  color: var(--white);
  display: none;
}
.mobile-menu[data-open="true"] { display: block; }
.mobile-menu__panel {
  height: 100%;
  overflow-y: auto;
  padding: 16px var(--gutter) 40px;
  display: flex;
  flex-direction: column;
}
.mobile-menu__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 56px;
  border-bottom: 1px solid var(--hair-dark);
}
/* The venue control inside the menu runs larger than the header instance —
   there is room here, and it is the first thing the menu should offer. */
.site-lockup--menu { height: 56px; gap: 8px; }
.site-lockup--menu .site-lockup__venue { padding: 8px 10px 14px; }
.site-lockup--menu .lockup__mark--woods { height: 32px; }
.site-lockup--menu .lockup__mark--sidebar { height: 22px; }
.menu-close { width: 44px; height: 44px; font-size: 28px; color: var(--white); }
.mobile-menu nav { display: flex; flex-direction: column; margin-top: 12px; }
.mobile-menu nav a {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 30px;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--white);
  padding: 14px 0;
  min-height: 56px;
  border-bottom: 1px solid var(--hair-dark);
}
.mobile-menu__sub {
  margin-top: auto;
  padding-top: 32px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-size: 15px;
  color: var(--steel-300);
}
.mobile-menu__sub a { color: var(--white); text-decoration: none; }
body.menu-open { overflow: hidden; }

/* ---------- Mobile action bar ---------- */
.action-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
  display: none;
  grid-template-columns: repeat(3, 1fr);
  background: var(--navy-ink);
  border-top: 1px solid var(--hair-dark);
  padding-bottom: env(safe-area-inset-bottom);
  transform: translateY(100%);
  transition: transform 240ms var(--ease);
}
.action-bar a {
  display: grid;
  place-items: center;
  min-height: 56px;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--white);
  text-decoration: none;
  border-left: 1px solid var(--hair-dark);
}
.action-bar a:first-child { border-left: 0; }
.action-bar.is-visible { transform: translateY(0); }
body.menu-open .action-bar, body.dialog-open .action-bar { display: none; }

/* ---------- Reveal animation ---------- */
.reveal { opacity: 0; transform: translateY(12px); transition: opacity 400ms var(--ease), transform 400ms var(--ease); }
.reveal.is-revealed { opacity: 1; transform: none; }

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1280px) {
  .primary-nav { gap: 12px; }
  .site-header__inner { gap: 16px; }
}
@media (max-width: 1023px) {
  .primary-nav { display: none; }
  .menu-toggle { display: block; }
  .site-header__actions { margin-left: auto; }
}

@media (max-width: 900px) {
  .tonight-grid, .find-grid { grid-template-columns: 1fr; }
  .venue-section__grid, .venue-section__grid--mirrored { grid-template-columns: 1fr; }
  .venue-section__grid--mirrored .venue-section__media { order: 2; }
  .venue-section__grid--mirrored .venue-section__text { order: 1; }
}

@media (max-width: 767px) {
  :root { --header-h: 56px; }
  body { font-size: 16px; }
  /* 44px group height inside a 56px header — still a full touch target. */
  .site-lockup { height: 44px; gap: 4px; }
  .site-lockup__venue { padding: 4px 8px 10px; }
  .site-lockup__venue::after { left: 8px; right: 8px; }
  .lockup__mark--woods { height: 28px; }
  .lockup__mark--sidebar { height: 19px; }
  .lockup__plus { font-size: 16px; }

  /* Hero on a phone: practical information first, then the two venues STACKED.
     Side by side they were two ~150px slivers, which is why the photography
     used to be switched off here entirely — there was no room for it. Stacked,
     each panel is full width, so the real picture can carry the panel the way
     it does on desktop. The selected venue takes the taller band and leads. */
  .hero { padding-bottom: 0; }
  /* Scoped with body[data-venue] so it outranks the desktop 60fr/40fr rule —
     a media query adds no specificity of its own. */
  body[data-venue] .hero__panels,
  .hero__panels {
    order: 2;
    grid-template-columns: minmax(0, 1fr);
    grid-auto-rows: auto;
    gap: 2px;
    border-top: 2px solid var(--black);
    margin-top: 24px;
  }
  /* Selected panel first and taller; the other stays directly beneath it,
     full width and still obviously tappable. */
  /* The panel content stays absolutely positioned so the type sits over the
     photograph, which means the panel cannot grow to fit it — these heights
     have to clear logo + label + CTA on their own. The px floors keep the CTA
     from clipping on the narrowest phones. */
  body[data-venue="woods"] .hero-panel--woods,
  body[data-venue="sidebar"] .hero-panel--sidebar { order: 1; min-height: max(60vw, 230px); }
  body[data-venue="woods"] .hero-panel--sidebar,
  body[data-venue="sidebar"] .hero-panel--woods { order: 2; min-height: max(46vw, 178px); }
  .hero-panel { min-height: max(46vw, 178px); border-right: 0; }
  .hero-panel__art { display: block; }
  /* Text sits over the photograph again, so it needs its scrim back. */
  .hero-panel__content {
    padding: 18px 16px;
    padding-bottom: 18px;
    justify-content: space-between;
  }
  .hero-panel--woods .hero-panel__content {
    background: linear-gradient(180deg, rgba(10,17,30,0.72) 0%, rgba(10,17,30,0.15) 55%, rgba(10,17,30,0.62) 100%);
  }
  .hero-panel--sidebar .hero-panel__content {
    background: linear-gradient(180deg, rgba(243,245,248,0.80) 0%, rgba(243,245,248,0.25) 55%, rgba(243,245,248,0.72) 100%);
  }
  /* The status card no longer overlaps the panels on this layout. */
  .hero-panel__content { padding-bottom: 18px; }
  .hero-panel__mark { width: min(52vw, 170px); }
  .hero-panel--sidebar .hero-panel__mark { width: min(48vw, 158px); }
  .hero-panel__cta { font-size: 12px; padding: 10px 12px; }
  .status-panel { order: 1; margin: 24px auto 0; width: calc(100% - 2 * var(--gutter)); }

  .event-row { grid-template-columns: 1fr auto; }
  .event-row__time { grid-column: 1 / -1; }
  .week-row { grid-template-columns: 48px 1fr auto; }
  .week-row__time { grid-column: 2; }
  .week-row__title { grid-column: 2; }
  .week-row__desc { grid-column: 2; }
  /* Narrow screens: the Woods block folds to two columns rather than one, so
     four photographs stay large enough to read without turning the section into
     a very long single file. The tall frame keeps the full width above them. */
  .venue-section__media--dense {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "crowd crowd"
      "band  dj"
      "strip strip";
  }
  .venue-media--tall picture,
  .venue-media--tall img { aspect-ratio: 4 / 3; }
  .venue-media--tall img { object-position: 50% 38%; }
  .venue-media--feature { width: 100%; }
  .action-bar { display: grid; }
  .footer { padding-bottom: calc(clamp(48px, 6vw, 80px) + 64px); }
}

@media (max-width: 400px) {
  .status-panel__title { font-size: 30px; }
  .hero-panel__cta { font-size: 11px; }
}

/* ==========================================================================
   Reduced motion: instant state changes, nothing removed
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* ==========================================================================
   Hours — both schedules, side by side
   Two panels that stay easy to compare (same rows, same order) while keeping
   each venue's own ground: The Woods on navy, Sidebar on paper. Deliberately
   two editorial ledgers, not fourteen cards.
   ========================================================================== */
.section--hours { background: var(--surface); }
.hours-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px;
  border: 2px solid var(--black);
  background: var(--black);
}
.hours-panel { padding: clamp(20px, 2.6vw, 34px); }
.hours-panel--woods { background: var(--navy-ink); color: var(--steel-300); }
.hours-panel--sidebar { background: var(--paper); color: var(--steel-500); }

.hours-panel__head {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-bottom: 14px;
  margin-bottom: 8px;
  border-bottom: 1px solid currentColor;
}
.hours-panel__mark { width: clamp(120px, 15vw, 168px); height: auto; }
.hours-panel--sidebar .hours-panel__mark { width: clamp(112px, 14vw, 150px); }
.hours-panel__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(22px, 2.4vw, 30px);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.hours-panel--woods .hours-panel__title { color: var(--white); }
.hours-panel--sidebar .hours-panel__title { color: var(--navy-900); }

.hours-panel__live {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.hours-panel__live[data-state="open"] { color: var(--status-open); }
.hours-panel__live[data-state="closed"] { color: var(--status-closed); }
.hours-panel--woods .hours-panel__live[data-state="open"] { color: #7FC79B; }
.hours-panel--woods .hours-panel__live[data-state="closed"] { color: #E08A82; }

.hours-table { width: 100%; border-collapse: collapse; }
.hours-table th,
.hours-table td {
  padding: 11px 0;
  border-bottom: 1px solid currentColor;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.06em;
  text-align: left;
  vertical-align: baseline;
}
.hours-table tr:last-child th,
.hours-table tr:last-child td { border-bottom: 0; }
.hours-table th { text-transform: uppercase; width: 40%; }
.hours-table td { text-align: right; }
.hours-table td.is-closed { opacity: 0.62; }
/* Today is marked with a WORD and a weight change, never colour alone. */
.hours-table tr.is-today th,
.hours-table tr.is-today td { font-weight: 700; }
.hours-panel--woods tr.is-today th,
.hours-panel--woods tr.is-today td { color: var(--white); }
.hours-panel--sidebar tr.is-today th,
.hours-panel--sidebar tr.is-today td { color: var(--navy-900); }
.hours-table__today {
  display: inline-block;
  margin-left: 8px;
  font-size: 10px;
  letter-spacing: 0.14em;
  opacity: 0.8;
}
.hours-panel__note {
  margin-top: 14px;
  font-size: 13px;
  line-height: 1.5;
}
.find-card__hours-link { font-size: 15px; line-height: 1.6; }

@media (max-width: 780px) {
  .hours-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   One address — the paired frontage frame
   Full-bleed, because it is the only place both buildings appear together and
   the whole point is the width of the two storefronts side by side.
   ========================================================================== */
.section--frontage { background: var(--surface); }
.frontage { margin: clamp(20px, 3vw, 36px) 0 0; }
.frontage img {
  display: block;
  width: 100%;
  height: auto;
  border-block: 2px solid var(--black);
}
.frontage__caption {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 28px;
  justify-content: center;
  padding: 14px var(--gutter) 0;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--meta);
}

/* ==========================================================================
   Mobile: keep each status pill locked to its own hero panel
   The rail and the panel grid both become display:contents so the hero itself
   lays out four children, letting each pill sit immediately above the panel it
   describes — including when the selected venue reorders to the top. Without
   this the two pills would stack together and separate from their imagery.
   ========================================================================== */
@media (max-width: 900px) {
  .hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 2px;
  }
  .status-rail,
  body[data-venue] .status-rail,
  .hero__panels,
  body[data-venue] .hero__panels {
    display: contents;
  }
  .status-pill {
    border-right: 0;
    border-top: 2px solid var(--black);
    padding: 12px var(--gutter);
  }
  .status-panel { order: 1; }

  /* These must outrank the earlier `body[data-venue="woods"] .hero-panel--woods`
     ordering rules, which are (0,2,1); a bare class selector loses to them and
     the pills detach from their panels. Same specificity + later in the file. */

  /* Overview and Woods-selected: Woods pill, Woods panel, then Sidebar. */
  body[data-venue] .status-pill--woods { order: 2; }
  body[data-venue] .hero-panel--woods { order: 3; }
  body[data-venue] .status-pill--sidebar { order: 4; }
  body[data-venue] .hero-panel--sidebar { order: 5; }

  /* Sidebar selected: its pill and panel lead, Woods follows. */
  body[data-venue="sidebar"] .status-pill--sidebar { order: 2; }
  body[data-venue="sidebar"] .hero-panel--sidebar { order: 3; }
  body[data-venue="sidebar"] .status-pill--woods { order: 4; }
  body[data-venue="sidebar"] .hero-panel--woods { order: 5; }
}

/* ==========================================================================
   Creator credit â€” "Site created by Bibelhausen Digital"
   The quietest thing in the footer. It credits who built the site and must
   never compete with the venue's own branding, so it sits last, runs small,
   and borrows the surrounding footer's colour rather than introducing one.
   The mark is decorative (alt="") â€” the adjacent text is the link's accessible
   name. Readability comes from real colour contrast, not from opacity alone:
   the name renders at full currentColor and only the smaller label is muted.
   Every deploy root carries its own local copy of the image; nothing here
   reaches outside the folder that gets uploaded.
   ========================================================================== */
.creator-credit {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: inherit;
  padding: 6px 4px;
  border-radius: 2px;
}
.creator-credit__mark {
  width: 28px;
  height: 28px;
  flex: none;
  display: block;
}
.creator-credit__text {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
  text-align: left;
}
.creator-credit__label {
  font-size: 10px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  opacity: 0.78;
}
.creator-credit__name {
  font-size: 11.5px;
  letter-spacing: 0.03em;
  font-weight: 600;
}
.creator-credit:hover .creator-credit__name,
.creator-credit:focus-visible .creator-credit__name { text-decoration: underline; }
.creator-credit:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}
/* Standalone bar for utility pages (privacy / thanks / 404) that carry no
   site footer of their own. Never fixed, never floating â€” it is simply the
   last thing on the page. */
.creator-credit-bar {
  display: flex;
  justify-content: center;
  padding: 28px 16px 34px;
  margin-top: auto;
}
@media (prefers-reduced-motion: reduce) {
  .creator-credit { transition: none; }
}
