/* ============================================
   ENTROPY SHISHA BAR — style.css
   Dark lounge: near-black, emerald, soft neon
   ============================================ */

:root {
  /* ---------- Surfaces ----------
     Three tones, each a real step apart rather than a rounding error. */
  --ink: #070a08;    /* the page */
  --room: #0e1511;   /* lit surfaces / alternate sections */
  --raise: #131c17;  /* cards */

  /* ---------- Brand ----------
     Two accents, with one job each, so the page teaches itself:
     NEON is Entropy — the sign, the wordmark, the brand and nothing else.
     EMBER is information — prices, hours, anything live or actionable.
     Contrast against ink / room / raise, measured:
       neon  17.84 / 16.61 / 15.62
       ember  7.85 /  7.31 /  6.87
       smoke  9.35 /  8.70 /  8.18
       text  17.05 / 15.87 / 14.92                        (AA needs 4.5) */
  --leaf: #1b4d30;
  /* Near-white core, coloured halo — that's how a real tube photographs, and
     going greener in the core (#c8ffe0) just made it look like green text.
     The colour lives in --neon-glow. */
  --neon: #d8ffe9;
  --neon-glow: rgba(190, 255, 220, 0.55);
  --ember: #e0913c;
  --smoke: #a8b5ac;
  --text: #e9efea;

  /* ---------- Lines ----------
     Split by job. Decorative hairlines are exempt from contrast rules;
     anything bounding a control is not, and needs 3:1 (WCAG 1.4.11).
     --edge-control measures 3.60 / 3.35 / 3.15. */
  --edge: #1e3a2a;
  --edge-control: #457258;

  /* ---------- Type scale ----------
     1.25 minor third off a 16px base. Nothing outside this set. */
  --t-xs: 0.75rem;      /* 12px — labels, eyebrows */
  --t-sm: 0.875rem;     /* 14px — captions, footer */
  --t-base: 1rem;       /* 16px — body */
  --t-lg: 1.1875rem;    /* 19px — lead paragraphs */
  --t-2xl: clamp(1.75rem, 3vw, 2.25rem);  /* section titles */
  --t-4xl: clamp(3rem, 7vw, 5.5rem);      /* display */
  --measure: 62ch;

  --header-h: 76px;

  /* ---------- Legacy aliases ----------
     The rules below this block still reference the old names. Pointing
     them at the new tokens moves the whole site in one step; they can be
     inlined and deleted as each section is revisited. */
  --bg: var(--ink);
  --bg-2: var(--room);
  --bg-3: var(--raise);
  --emerald: var(--leaf);
  --emerald-deep: #14432f;
  --emerald-soft: #1e6b3f;
  --gold: var(--ember);
  --muted: var(--smoke);
  --line: var(--edge);
  /* fallbacks; the .hero-wall--v* variant classes set the real values */
  --leaf-tile: 460px;
  --leaf-dim: 0.4;
  --leaf-lit: 0.07;
  --gust: 1.3;
  --leaf-src: url("../img/leaf-wall-v2-back.svg");
  /* Mr Dafoe is the neon sign that actually hangs in the bar, so it earns
     its place — but only there. Logo and hero wordmark, nothing else; used
     a fourth time on a page it stops being a sign and becomes a font.
     Instrument Serif carries the headlines instead: high contrast enough to
     hold its own next to neon, without the hairlines a true didone would
     lose against near-black. Space Grotesk keeps the text and UI. */
  --font-script: "Mr Dafoe", cursive;
  --font-display: "Instrument Serif", Georgia, "Times New Roman", serif;
  --font-sans: "Space Grotesk", "Helvetica Neue", Arial, sans-serif;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

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

html { scroll-behavior: smooth; }

/* Weight 400, not 300. Space Grotesk Light loses too much stroke on
   near-black — the measured contrast stays high while the perceived
   contrast collapses. 1.55 rather than 1.65 for the same reason: tight
   enough to hold the line together. */
body {
  background: var(--ink);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--t-base);
  font-weight: 400;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

a { color: var(--neon); text-decoration: none; transition: color 0.3s var(--ease); }
a:hover { color: #fff; }

a:focus-visible, button:focus-visible {
  outline: 2px solid var(--neon);
  outline-offset: 3px;
  border-radius: 2px;
}

.container { width: min(1120px, 92%); margin-inline: auto; }

/* ---------- Labels / small caps ---------- */
.label {
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--smoke);
  display: inline-block;
}

.label--accent { color: var(--ember); }

/* ---------- Headings ---------- */
h1, h2, h3 { font-weight: 500; line-height: 1.2; }

/* Display serif, set big and tight — the disagreement between a
   high-contrast serif and a geometric sans is where the type contrast
   this page was missing actually comes from. */
.display, .section-title, .page-hero h1, .insta-banner h2, .menu-section h2 {
  font-family: var(--font-display);
  font-weight: 400;
}

.section-title {
  font-size: clamp(2rem, 3.4vw, 2.5rem);
  letter-spacing: -0.01em;
  line-height: 1.1;
  margin: 0.6rem 0 1rem;
}

.script { font-family: var(--font-script); font-weight: 400; }

/* One comfortable measure for running text. Applied per context rather than
   to every <p>: a bare max-width leaves a paragraph flush left inside its
   container, which silently knocks the centred blocks off centre. Centred
   contexts get the auto margins that go with it. */
.card p { max-width: var(--measure); }

.page-hero p,
.section-head p,
.insta-banner p,
.menu-section .menu-note { max-width: var(--measure); margin-inline: auto; }

/* ---------- Buttons ---------- */
/* The border is a control boundary, so it answers to WCAG 1.4.11 (3:1),
   not to taste. --edge-control is the dimmest green that clears it. */
.btn {
  display: inline-block;
  padding: 0.9rem 2.2rem;
  font-family: var(--font-sans);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  border: 2px solid var(--edge-control);
  color: var(--text);
  background: transparent;
  cursor: pointer;
  transition: all 0.45s var(--ease);
}

.btn:hover {
  border-color: var(--neon);
  color: var(--neon);
  box-shadow: 0 0 22px rgba(190, 255, 220, 0.18), inset 0 0 14px rgba(190, 255, 220, 0.05);
}

/* The fill sits at 1.55–1.77:1 against the page, so on its own it gives the
   button no discernible shape — only the label says a control is there.
   Keeping the deep fill and taking the shared control border puts the
   boundary at 3.6:1 while the two buttons still read as a pair: same edge,
   filled vs not. */
.btn--primary {
  background: var(--emerald-deep);
  border-color: var(--edge-control);
}

.btn--primary:hover {
  background: transparent;
  border-color: var(--neon);
  color: var(--neon);
  text-shadow: 0 0 8px rgba(190, 255, 220, 0.45);
  box-shadow: 0 0 28px rgba(190, 255, 220, 0.22), inset 0 0 16px rgba(190, 255, 220, 0.07);
}

/* ============================================
   HEADER
   ============================================ */
.site-header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  transition: background 0.5s var(--ease), box-shadow 0.5s var(--ease);
  background: transparent;
}

.site-header.scrolled {
  background: rgba(10, 13, 11, 0.92);
  backdrop-filter: blur(12px);
  box-shadow: 0 1px 0 var(--line);
}

/* backdrop-filter establishes a containing block for fixed-position
   descendants, which collapses the full-screen mobile nav (position:
   fixed; inset:0) down to just the header's own box. Drop the filter
   while the nav is open so it keeps sizing itself off the viewport. */
.site-header.nav-open {
  backdrop-filter: none;
}

.header-inner {
  width: min(1200px, 94%);
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

/* Mr Dafoe's x-height is roughly half its point size, so at 1.9rem the
   wordmark was optically smaller than the tracked-out label beneath it —
   the brand was the least prominent thing in its own lockup. A script face
   needs about 1.6x the size of a sans to carry equal weight. */
/* Glow radius has to scale with the type or the tube stops reading as lit —
   a single 12px shadow that looked right at 1.9rem is a thin outline at this
   size. Three layers: tight core, mid bloom, wide haze, same structure as the
   hero wordmark. */
.logo {
  font-family: var(--font-script);
  font-size: 2.35rem;
  color: var(--neon);
  text-shadow:
    0 0 7px var(--neon-glow),
    0 0 20px rgba(190, 255, 220, 0.4),
    0 0 46px rgba(120, 220, 170, 0.25);
  line-height: 0.9;
  white-space: nowrap;
}

.logo small {
  display: block;
  font-family: var(--font-sans);
  font-size: 0.58rem;
  font-weight: 500;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--smoke);
  text-shadow: none;
  margin-top: 4px;
}

.main-nav { display: flex; align-items: center; gap: 2.2rem; }

.main-nav a {
  font-size: 0.78rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text);
  position: relative;
  padding: 0.3rem 0;
}

.main-nav a::after {
  content: "";
  position: absolute;
  left: 0; bottom: -2px;
  width: 100%;
  height: 1px;
  background: var(--neon);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s var(--ease);
  box-shadow: 0 0 8px var(--neon-glow);
}

.main-nav a:hover::after,
.main-nav a[aria-current="page"]::after { transform: scaleX(1); }

.main-nav a:hover, .main-nav a[aria-current="page"] { color: var(--neon); }

/* Language toggle */
.lang-toggle {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.75rem;
  letter-spacing: 0.15em;
}

.lang-toggle button {
  background: none;
  border: none;
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: 0.75rem;
  letter-spacing: 0.15em;
  cursor: pointer;
  padding: 0.3rem 0.15rem;
  transition: color 0.3s;
}

.lang-toggle button.active {
  color: var(--neon);
  text-shadow: 0 0 8px var(--neon-glow);
}

/* Was --emerald-soft at 3.06:1. Decorative and aria-hidden, so technically
   exempt, but matching the inactive language reads better anyway: both
   languages sit at one weight and neon marks the active one. */
.lang-toggle .sep { color: var(--smoke); }

/* Hamburger */
.nav-toggle {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  width: 42px;
  height: 42px;
  position: relative;
  z-index: 210;
  transition: transform 0.6s var(--ease);
}

.nav-toggle span {
  display: block;
  width: 24px;
  height: 1.5px;
  border-radius: 2px;
  background: var(--text);
  margin: 6px auto;
  transition:
    transform 0.5s var(--ease),
    opacity 0.3s var(--ease),
    width 0.4s var(--ease),
    background 0.3s var(--ease),
    box-shadow 0.3s var(--ease);
}

/* Asymmetric middle line, left-aligned; expands on hover
   (mouse pointers only — on touch, :hover sticks after a tap) */
.nav-toggle span:nth-child(2) { width: 15px; margin-left: 9px; }

@media (hover: hover) and (pointer: fine) {
  .nav-toggle:hover span:nth-child(2) { width: 24px; }
}

/* Open: button spins while lines morph into a glowing neon X */
.nav-toggle[aria-expanded="true"] { transform: rotate(180deg); }

.nav-toggle[aria-expanded="true"] span {
  background: var(--neon);
  box-shadow: 0 0 8px var(--neon-glow);
}

.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; transform: scaleX(0); }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }

/* Mobile overlay nav */
@media (max-width: 820px) {
  .nav-toggle { display: block; }

  .main-nav {
    position: fixed;
    inset: 0;
    z-index: 200;
    flex-direction: column;
    justify-content: center;
    gap: 2.4rem;
    background: radial-gradient(
      ellipse at 50% 30%,
      rgba(14, 23, 18, 0.88) 0%,
      rgba(10, 13, 11, 0.94) 70%
    );
    -webkit-backdrop-filter: blur(18px) saturate(1.2);
    backdrop-filter: blur(18px) saturate(1.2);
    /* Circle grows out of the hamburger button (top-right of header) */
    clip-path: circle(0px at calc(100% - 45px) calc(var(--header-h) / 2));
    visibility: hidden;
    transition:
      clip-path 0.55s var(--ease),
      visibility 0s 0.55s;
  }

  .main-nav.open {
    clip-path: circle(150% at calc(100% - 45px) calc(var(--header-h) / 2));
    visibility: visible;
    transition: clip-path 0.7s var(--ease), visibility 0s;
  }

  .main-nav a { font-size: 1.25rem; letter-spacing: 0.3em; }

  /* Staggered entrance: links rise in from a blur */
  .main-nav a,
  .main-nav .lang-toggle {
    opacity: 0;
    transform: translateY(1.8rem);
    filter: blur(6px);
    transition:
      opacity 0.3s var(--ease),
      transform 0.3s var(--ease),
      filter 0.3s var(--ease),
      color 0.3s var(--ease);
  }

  .main-nav.open a,
  .main-nav.open .lang-toggle {
    opacity: 1;
    transform: none;
    filter: blur(0);
    transition:
      opacity 0.55s var(--ease),
      transform 0.55s var(--ease),
      filter 0.55s var(--ease),
      color 0.3s var(--ease);
  }

  .main-nav.open a:nth-child(1) { transition-delay: 0.18s; }
  .main-nav.open a:nth-child(2) { transition-delay: 0.26s; }
  .main-nav.open a:nth-child(3) { transition-delay: 0.34s; }
  .main-nav.open a:nth-child(4) { transition-delay: 0.42s; }
  .main-nav.open .lang-toggle   { transition-delay: 0.5s; }
}

/* Reduced motion: plain fade, no stagger, no spin */
@media (max-width: 820px) and (prefers-reduced-motion: reduce) {
  .main-nav {
    clip-path: none;
    opacity: 0;
    transition: opacity 0.25s ease, visibility 0s 0.25s;
  }

  .main-nav.open {
    clip-path: none;
    opacity: 1;
    transition: opacity 0.25s ease, visibility 0s;
  }

  .main-nav a,
  .main-nav .lang-toggle {
    transform: none;
    filter: none;
    transition-delay: 0s !important;
  }

  .nav-toggle,
  .nav-toggle[aria-expanded="true"] { transform: none; }
}

/* ============================================
   HERO
   ============================================ */
.hero {
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(ellipse 90% 60% at 50% 110%, rgba(15, 61, 46, 0.55) 0%, transparent 60%),
    radial-gradient(ellipse 60% 45% at 50% 0%, rgba(20, 83, 45, 0.25) 0%, transparent 65%),
    var(--bg);
}

/* ---------- The leaf wall (the real one behind the neon sign in the bar) ----------
   Three passes over one seamless tile: a dark base wall, the same leaves lit by the
   sign's glow (revealed through a radial mask), and a vignette that sinks the edges.

   Two textures exist. Swap the variant class on .hero-wall in index.html to switch:
     .hero-wall--v2  fronds in tufts, serrated leaflets, depth of field  (current)
     .hero-wall--v1  the first pass: scattered simple sprigs, flatter
   v2 ships as five files — the still wall (back) plus four patches of the top
   leaf layer, which the wind moves independently — all cut from one generated
   wall so they line up exactly. Rebuild:
     node tools/gen-leaf-wall-v2.js img/leaf-wall-v2-back.svg 20260731 back
     for k in 0 1 2 3; do
       node tools/gen-leaf-wall-v2.js img/leaf-wall-v2-front$k.svg 20260731 "front:$k/4"
     done */
.hero-wall {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(rgba(4, 10, 7, var(--leaf-dim)), rgba(4, 10, 7, var(--leaf-dim))),
    var(--leaf-src) repeat;
  background-size: auto, var(--leaf-tile) var(--leaf-tile);
}

.hero-wall--v2 {
  --leaf-src: url("../img/leaf-wall-v2-back.svg");
  --leaf-tile: 460px;
  --leaf-dim: 0.4;
  --gust: 1.3;
}

.hero-wall--v1 {
  --leaf-src: url("../img/leaf-wall-v1.svg");
  --leaf-tile: 480px;
  --leaf-dim: 0.74;
  --leaf-lit: 0.07;
}

/* The wall strikes on with the neon: light spreads from the sign outwards.
   The mask only exists while the animation runs (fill-mode: backwards), so the
   finished hero carries no mask and no compositing cost. */
.hero-wall {
  animation: wall-strike 2.6s cubic-bezier(0.25, 0.6, 0.3, 1) 0.15s backwards;
}

@keyframes wall-strike {
  0% {
    opacity: 0;
    -webkit-mask-size: 24% 24%;
    mask-size: 24% 24%;
  }
  12% { opacity: 1; }
  70% {
    -webkit-mask-size: 230% 230%;
    mask-size: 230% 230%;
  }
  0%, 99% {
    -webkit-mask-image: radial-gradient(closest-side, #000 55%, rgba(0, 0, 0, 0.4) 80%, transparent 100%);
    mask-image: radial-gradient(closest-side, #000 55%, rgba(0, 0, 0, 0.4) 80%, transparent 100%);
    -webkit-mask-position: 50% 41%;
    mask-position: 50% 41%;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
  }
  99% {
    -webkit-mask-size: 600% 600%;
    mask-size: 600% 600%;
  }
}

/* Pool of light the neon throws onto the leaves. It brightens whatever is behind
   it, so it lights the moving leaves as they pass through without needing a lit
   copy of every wind layer. The mask is written as size + position so it can be
   animated: the pool slowly swells and wanders, like light shifting. */
.leaf-glow {
  position: absolute;
  inset: 0;
  -webkit-backdrop-filter: brightness(1.85) saturate(1.06);
  backdrop-filter: brightness(1.85) saturate(1.06);
  -webkit-mask-image: radial-gradient(closest-side, #000 0%, rgba(0, 0, 0, 0.45) 45%, transparent 75%);
  mask-image: radial-gradient(closest-side, #000 0%, rgba(0, 0, 0, 0.45) 45%, transparent 75%);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 80% 52%;
  mask-size: 80% 52%;
  -webkit-mask-position: 50% 39%;
  mask-position: 50% 39%;
  animation: leaf-swell 34s ease-in-out infinite;
}

/* Without backdrop-filter (older Firefox), fall back to a plain glow so the sign
   still sits in a pool of light rather than on a flat wall */
@supports not (backdrop-filter: brightness(1)) {
  .leaf-glow {
    background: radial-gradient(closest-side, rgba(190, 255, 220, 0.16) 0%, transparent 100%);
    mix-blend-mode: screen;
  }
}

@keyframes leaf-swell {
  0%, 100% {
    -webkit-mask-size: 80% 52%; mask-size: 80% 52%;
    -webkit-mask-position: 49% 39%; mask-position: 49% 39%;
  }
  35% {
    -webkit-mask-size: 92% 60%; mask-size: 92% 60%;
    -webkit-mask-position: 53% 41%; mask-position: 53% 41%;
  }
  68% {
    -webkit-mask-size: 74% 47%; mask-size: 74% 47%;
    -webkit-mask-position: 47% 37%; mask-position: 47% 37%;
  }
}

/* Wind: only the front-most leaves move, and they move in patches rather than as
   one sheet. The top leaf layer of the wall is cut into four interlocking areas
   (see tools/gen-leaf-wall-v2.js); each is its own layer drifting on its own
   rhythm, so different parts of the wall are always leaning different ways. Each
   patch sits exactly on its twin in the base texture when its transform is zero,
   so nothing doubles up. Transform-only, so they composite without repainting. */
.leaf-wind {
  position: absolute;
  inset: -2%;
  background-repeat: repeat;
  background-size: var(--leaf-tile) var(--leaf-tile);
  /* the base wall dims itself with an overlay; a transparent layer can't, so it
     darkens by the same factor with a filter instead */
  filter: brightness(calc(1 - var(--leaf-dim)));
  transform-origin: 50% 100%;
  will-change: transform;
}

/* Durations share no common factor, so the four patches drift out of step and
   the wall never repeats a pattern of movement. The negative delays start each
   patch mid-drift, so nothing is ever caught sitting still. */
.leaf-wind--1 {
  background-image: url("../img/leaf-wall-v2-front0.svg");
  animation: leaf-drift 9s ease-in-out -3s infinite;
}
.leaf-wind--2 {
  background-image: url("../img/leaf-wall-v2-front1.svg");
  animation: leaf-drift-b 11s ease-in-out -7s infinite;
}
.leaf-wind--3 {
  background-image: url("../img/leaf-wall-v2-front2.svg");
  animation: leaf-drift 13s ease-in-out -5s infinite;
}
.leaf-wind--4 {
  background-image: url("../img/leaf-wall-v2-front3.svg");
  animation: leaf-drift-b 17s ease-in-out -11s infinite;
}

.hero-wall--v1 .leaf-wind { display: none; }

/* A gust: a shove, an overshoot back, then the leaves settling — followed by a
   long calm. Real wind arrives in pulses, it doesn't oscillate like a metronome. */
/* A constant, barely-there drift rather than gusts: the leaves never stop moving
   and never travel far. Every waypoint is under two pixels, and the loop closes
   where it opened so there is no seam when it repeats. */
@keyframes leaf-drift {
  0%   { transform: none; }
  22%  { transform: translate3d(calc(-1.8px * var(--gust)), calc(0.4px * var(--gust)), 0) skewX(calc(0.22deg * var(--gust))); }
  44%  { transform: translate3d(calc(0.9px * var(--gust)), calc(-0.3px * var(--gust)), 0) skewX(calc(-0.12deg * var(--gust))); }
  63%  { transform: translate3d(calc(-1.1px * var(--gust)), calc(0.2px * var(--gust)), 0) skewX(calc(0.14deg * var(--gust))); }
  82%  { transform: translate3d(calc(1.6px * var(--gust)), calc(-0.4px * var(--gust)), 0) skewX(calc(-0.2deg * var(--gust))); }
  100% { transform: none; }
}

/* The mirrored drift: leans the other way first, on its own rhythm */
@keyframes leaf-drift-b {
  0%   { transform: none; }
  18%  { transform: translate3d(calc(1.5px * var(--gust)), calc(-0.35px * var(--gust)), 0) skewX(calc(-0.18deg * var(--gust))); }
  39%  { transform: translate3d(calc(-1.2px * var(--gust)), calc(0.3px * var(--gust)), 0) skewX(calc(0.16deg * var(--gust))); }
  58%  { transform: translate3d(calc(1.9px * var(--gust)), calc(-0.2px * var(--gust)), 0) skewX(calc(-0.24deg * var(--gust))); }
  79%  { transform: translate3d(calc(-0.8px * var(--gust)), calc(0.35px * var(--gust)), 0) skewX(calc(0.1deg * var(--gust))); }
  100% { transform: none; }
}

/* Vignette: the wall falls off into the dark room at the edges, and the lower
   half sinks so the tagline and buttons keep their contrast */
.hero-wall::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 80% 70% at 50% 40%, transparent 24%, rgba(3, 9, 6, 0.34) 70%, rgba(3, 9, 6, 0.72) 100%),
    linear-gradient(180deg, rgba(3, 9, 6, 0.55) 0%, transparent 22%),
    linear-gradient(180deg, transparent 48%, rgba(3, 9, 6, 0.34) 72%, rgba(3, 9, 6, 0.6) 100%);
}

/* Soft bloom around the sign, sitting on top of the leaves */
.hero::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 43%;
  transform: translate(-50%, -50%);
  width: min(94vw, 940px);
  height: min(60vh, 520px);
  background: radial-gradient(ellipse at center, rgba(190, 255, 220, 0.16) 0%, rgba(120, 220, 170, 0.07) 38%, transparent 70%);
  mix-blend-mode: screen;
  pointer-events: none;
  z-index: 1;
}

/* Keep the leaves at roughly the size they read at in the bar, whatever the screen */
@media (max-width: 900px) { .hero-wall { --leaf-tile: 370px; } }
@media (max-width: 560px) {
  /* narrower screen: tighter pool of light — keeps the tagline off the lit
     leaves — and a shorter throw on the gusts, to match the smaller leaves */
  .hero-wall { --leaf-tile: 300px; --leaf-dim: 0.42; --gust: 0.91; }
  .leaf-glow {
    -webkit-mask-size: 92% 38%;
    mask-size: 92% 38%;
    -webkit-mask-position: 50% 36%;
    mask-position: 50% 36%;
    animation-name: leaf-swell-sm;
  }

  /* Tall, narrow viewports leave a lot of empty hero space below the CTAs —
     the vignette and the dissolve-into-about gradient used to stack there
     and crush it to solid black. Ease off both on mobile. */
  .hero-wall::after {
    background:
      radial-gradient(ellipse 80% 70% at 50% 40%, transparent 30%, rgba(3, 9, 6, 0.24) 72%, rgba(3, 9, 6, 0.5) 100%),
      linear-gradient(180deg, rgba(3, 9, 6, 0.45) 0%, transparent 20%),
      linear-gradient(180deg, transparent 58%, rgba(3, 9, 6, 0.2) 80%, rgba(3, 9, 6, 0.4) 100%);
  }
  .hero::after { height: 18vh; }
}

@keyframes leaf-swell-sm {
  0%, 100% {
    -webkit-mask-size: 92% 38%; mask-size: 92% 38%;
    -webkit-mask-position: 49% 36%; mask-position: 49% 36%;
  }
  35% {
    -webkit-mask-size: 106% 45%; mask-size: 106% 45%;
    -webkit-mask-position: 53% 38%; mask-position: 53% 38%;
  }
  68% {
    -webkit-mask-size: 85% 34%; mask-size: 85% 34%;
    -webkit-mask-position: 47% 34%; mask-position: 47% 34%;
  }
}

/* bounded below, so it can't override the smaller drift set at 560px */
@media (max-width: 700px) and (min-width: 561px) { .hero-wall { --gust: 1.04; } }

/* Dissolve the hero (glow + smoke) into the about section's base tone */
.hero::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 34vh;
  background: linear-gradient(180deg, transparent 0%, var(--bg) 100%);
  pointer-events: none;
  z-index: 1;
}

/* Smoke: blurred wisps rise from the bottom, sway and dissolve */
.smoke {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

.smoke span {
  position: absolute;
  bottom: -55vmin;
  border-radius: 50%;
  filter: blur(60px);
  opacity: 0;
  transform: translateY(0);
  will-change: transform, opacity;
}

/* Two sway paths so neighbouring wisps don't move in sync */
@keyframes smoke-rise-a {
  0%   { transform: translate(0, 0) scale(0.7); opacity: 0; }
  18%  { opacity: 1; }
  50%  { transform: translate(9vw, -55vh) scale(1.05) rotate(8deg); }
  78%  { opacity: 0.55; }
  100% { transform: translate(-4vw, -115vh) scale(1.45) rotate(-6deg); opacity: 0; }
}

@keyframes smoke-rise-b {
  0%   { transform: translate(0, 0) scale(0.8); opacity: 0; }
  20%  { opacity: 1; }
  50%  { transform: translate(-8vw, -50vh) scale(1.15) rotate(-9deg); }
  75%  { opacity: 0.5; }
  100% { transform: translate(5vw, -110vh) scale(1.5) rotate(7deg); opacity: 0; }
}

/* Each wisp: own size, tint, path, tempo; negative delays
   keep the scene mid-motion from the first frame */
.smoke span:nth-child(1) {
  left: 8%;
  width: 34vmax; height: 46vmax;
  background: radial-gradient(ellipse 45% 50% at 50% 55%, rgba(190, 255, 220, 0.10) 0%, transparent 70%);
  animation: smoke-rise-a 30s ease-in-out -6s infinite;
}

.smoke span:nth-child(2) {
  left: 38%;
  width: 40vmax; height: 54vmax;
  background: radial-gradient(ellipse 45% 50% at 50% 55%, rgba(20, 83, 45, 0.30) 0%, transparent 70%);
  animation: smoke-rise-b 38s ease-in-out -19s infinite;
}

.smoke span:nth-child(3) {
  left: 64%;
  width: 30vmax; height: 44vmax;
  background: radial-gradient(ellipse 45% 50% at 50% 55%, rgba(170, 240, 205, 0.08) 0%, transparent 70%);
  animation: smoke-rise-a 26s ease-in-out -14s infinite;
}

.smoke span:nth-child(4) {
  left: -6%;
  width: 44vmax; height: 50vmax;
  background: radial-gradient(ellipse 45% 50% at 50% 55%, rgba(15, 61, 46, 0.34) 0%, transparent 70%);
  animation: smoke-rise-b 44s ease-in-out -30s infinite;
}

.smoke span:nth-child(5) {
  left: 78%;
  width: 26vmax; height: 38vmax;
  background: radial-gradient(ellipse 45% 50% at 50% 55%, rgba(190, 255, 220, 0.06) 0%, transparent 70%);
  animation: smoke-rise-a 34s ease-in-out -25s infinite;
}

.hero-content { position: relative; z-index: 2; padding: 6rem 1rem 4rem; }

.hero-wordmark {
  font-family: var(--font-script);
  font-size: clamp(4rem, 14vw, 8.5rem);
  color: var(--neon);
  line-height: 1.1;
  text-shadow:
    0 0 10px var(--neon-glow),
    0 0 34px rgba(190, 255, 220, 0.35),
    0 0 90px rgba(120, 220, 170, 0.25);
  animation: neon-on 12s var(--ease) infinite;
}

/* Flicker plays in the first ~2.4s of each 12s cycle, then holds lit */
@keyframes neon-on {
  0%    { opacity: 0; text-shadow: none; }
  1.6%  { opacity: 0.6; }
  2.4%  { opacity: 0.1; }
  4%    { opacity: 0.8; text-shadow: 0 0 8px var(--neon-glow); }
  5.2%  { opacity: 0.35; }
  7.6%  { opacity: 1; }
  100%  {
    opacity: 1;
    text-shadow:
      0 0 10px var(--neon-glow),
      0 0 34px rgba(190, 255, 220, 0.35),
      0 0 90px rgba(120, 220, 170, 0.25);
  }
}

/* This sits on the brightest part of the lit wall. At --smoke it measured
   3.21:1 against a mid-tone lit leaf and worse against the bright ones —
   below the 4.5:1 AA needs at this size, which made the bar's own category
   and town the least readable words on the page. Full --text plus a tight
   shadow puts it at 6.70:1 on the same leaf. */
.hero-sub {
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--text);
  margin-top: 0.7rem;
  /* It sits dead centre of the light pool, where the leaves are brightest
     and the wordmark's own glow spills onto it, so the background behind it
     is the one thing here that can't be pinned to a hex value. Stacked
     short-radius shadows give the glyphs their own dark halo, which holds
     the ratio wherever the light lands. */
  text-shadow:
    0 0 2px rgba(3, 9, 6, 0.95),
    0 1px 3px rgba(3, 9, 6, 0.95),
    0 2px 14px rgba(3, 9, 6, 0.9);
}

.hero-tagline {
  max-width: 46ch;
  margin: 1.6rem auto 2rem;
  color: var(--text);
  font-size: var(--t-lg);
  text-shadow: 0 2px 16px rgba(3, 9, 6, 0.9);
}

.hero-ctas { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }

.hero-scroll {
  position: absolute;
  bottom: 2.2rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
}

.hero-scroll__mouse {
  display: block;
  width: 26px;
  height: 42px;
  border: 2px solid var(--text);
  border-radius: 14px;
  box-shadow: 0 2px 10px rgba(3, 9, 6, 0.9);
  opacity: 0.85;
}

.hero-scroll__wheel {
  display: block;
  width: 4px;
  height: 8px;
  margin: 21px auto 0;
  background: var(--neon);
  box-shadow: 0 0 6px var(--neon-glow);
  border-radius: 2px;
  animation: hero-scroll-wheel 2s ease-in-out infinite;
}

@keyframes hero-scroll-wheel {
  0%   { transform: translateY(0); opacity: 1; }
  55%  { transform: translateY(-14px); opacity: 0; }
  56%  { transform: translateY(0); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}

/* ============================================
   SECTIONS
   ============================================ */
.section { padding: clamp(4rem, 9vw, 7rem) 0; }

.section--alt { background: var(--bg-2); }

.section-head { text-align: center; max-width: 40rem; margin: 0 auto 3rem; }

.section-head p { color: var(--muted); }

.divider {
  width: 64px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
  margin: 1.4rem auto 0;
  border: none;
}

/* About — eases from the hero into the darker team section. Photo and
   copy side by side, editorial rather than another centred block. */
.about {
  background:
    radial-gradient(ellipse 55% 60% at 22% 52%, rgba(20, 83, 45, 0.22) 0%, transparent 62%),
    radial-gradient(ellipse 45% 45% at 85% 55%, rgba(190, 255, 220, 0.04) 0%, transparent 60%),
    linear-gradient(180deg, var(--bg) 0%, var(--bg-2) 100%);
}

.about-grid {
  display: grid;
  grid-template-columns: 0.95fr 1fr;
  gap: clamp(3rem, 6vw, 6rem);
  align-items: center;
}

@media (max-width: 860px) {
  .about-grid { grid-template-columns: 1fr; gap: 4.5rem; }
}

/* The photo sits on its own layer so an offset rule can float behind it —
   the one asymmetric gesture in an otherwise centred page, and enough on
   its own to stop this reading as another bordered rectangle. */
.about-media {
  position: relative;
  max-width: 26rem;
  margin-inline: auto;
}

@media (min-width: 861px) {
  .about-media { margin-inline: 0 auto; }
}

.about-media::before {
  content: "";
  position: absolute;
  inset: 1.5rem -1.5rem -1.5rem 1.5rem;
  border: 1px solid var(--edge-control);
  z-index: 0;
}

.about-photo {
  position: relative;
  z-index: 1;
  overflow: hidden;
  aspect-ratio: 4 / 5;
  border: 1px solid var(--edge);
  background: linear-gradient(160deg, var(--raise) 0%, var(--room) 100%);
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.8);
}

.about-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid rgba(200, 255, 224, 0.12);
  pointer-events: none;
}

.about-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(0.35) contrast(1.05) brightness(0.82);
  transform: scale(1.01);
  transition: filter 0.8s var(--ease), transform 1s var(--ease);
}

@media (hover: hover) {
  .about-media:hover .about-photo img {
    filter: grayscale(0) contrast(1.02) brightness(0.95);
    transform: scale(1.04);
  }
}

/* A small stamped plaque, doing the job a caption usually does but reading
   like a detail of the room rather than a label stuck on top of it. */
.about-badge {
  position: absolute;
  z-index: 2;
  left: -1.1rem;
  bottom: -1.1rem;
  width: 6.5rem;
  height: 6.5rem;
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  background: radial-gradient(circle at 35% 30%, var(--raise) 0%, var(--room) 100%);
  border: 1px solid var(--edge-control);
  box-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.8), 0 0 22px rgba(190, 255, 220, 0.1);
}

.about-badge__num {
  font-family: var(--font-display);
  font-size: 1.4rem;
  line-height: 1;
  color: var(--neon);
  text-shadow: 0 0 10px var(--neon-glow), 0 0 30px rgba(190, 255, 220, 0.3);
}

.about-badge__label {
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--smoke);
}

@media (max-width: 560px) {
  .about-badge { width: 5.5rem; height: 5.5rem; left: -0.75rem; bottom: -0.75rem; }
  .about-badge__num { font-size: 1.2rem; }
}

.about-content .label { margin-bottom: 0.2rem; }

.about-lead {
  color: var(--text);
  font-size: var(--t-lg);
  margin-top: 0.2rem;
}

.about-content p {
  color: var(--muted);
  max-width: var(--measure);
}

.about-content p + p { margin-top: 1rem; }

/* Stats — three quick facts standing in for the "about the founders"
   paragraph a bar doesn't really need. Ember numbers echo the hours
   table and menu prices, so it reads as information rather than decor. */
.about-stats {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 4vw, 3rem);
  margin-top: 2rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--edge);
}

.about-stats li {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.about-stats strong {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.4rem, 2.6vw, 1.75rem);
  line-height: 1;
  color: var(--ember);
}

.about-stats span {
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Ambient glow section — blends into the footer tone */
.section--glow {
  background:
    radial-gradient(ellipse 45% 70% at 80% 55%, rgba(20, 83, 45, 0.24) 0%, transparent 65%),
    radial-gradient(ellipse 40% 55% at 10% 20%, rgba(190, 255, 220, 0.05) 0%, transparent 60%),
    linear-gradient(180deg, var(--bg) 0%, var(--bg-2) 100%);
}

/* ============================================
   TEAM — PEEK SLIDER
   One member at a time, snapped full-width in the viewport, with the next
   member's edge left showing so the eye knows to keep going. That sliver
   is the entire affordance — no "swipe" hint copy needed once it's there.
   Native scroll-snap does the paging; JS only drives the active state
   and the optional arrow/dot controls.
   ============================================ */
.team-peek-section { background: var(--bg-2); }

.team-peek { position: relative; }

.team-peek__track {
  display: flex;
  gap: 4vw;
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  /* The gutter the track scrolls within — same on both ends, so the
     first slide's left edge lines up with the heading above it. */
  padding-inline: 6vw;
  scroll-padding-inline: 6vw;
}

.team-peek__track::-webkit-scrollbar { display: none; }

.team-peek__slide {
  flex: 0 0 auto;
  /* 76% + the gutter + the gap leaves ~14% of viewport width showing the
     next card — enough to read as "more," not enough to look cropped. */
  width: 76%;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

@media (min-width: 561px) {
  .team-peek__track { gap: 3vw; padding-inline: 5vw; scroll-padding-inline: 5vw; }
  .team-peek__slide { width: 80%; }
}

@media (min-width: 861px) {
  /* 34% looked right on paper but three of them can land flush against
     the viewport edge at common widths (1280px among them) and erase the
     peek entirely — the one thing this layout exists to show. 30% keeps
     a ~90px/quarter-card sliver showing at any width in this tier. */
  .team-peek__track {
    gap: clamp(1.5rem, 2vw, 2.25rem);
    padding-inline: clamp(2rem, 4vw, 4rem);
    scroll-padding-inline: clamp(2rem, 4vw, 4rem);
    /* Full-bleed is the point up to a normal desktop width — past it the
       vw-based gutters would keep inflating and the three portraits would
       just get larger and larger with nothing to stop them. Capping the
       track and centring it turns that runaway growth into letterboxing,
       same trick the rest of the page uses via .container. */
    max-width: 1720px;
    margin-inline: auto;
  }
  .team-peek__slide { width: 30%; }
}

.team-peek__frame {
  position: relative;
  overflow: hidden;
  aspect-ratio: 3 / 4;
  border: 1px solid var(--edge);
  background: linear-gradient(160deg, var(--raise) 0%, var(--room) 100%);
}

.team-peek__frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Peeking cards read as background, not a second choice — full colour
     throughout, just dimmed until scroll brings them forward. */
  filter: brightness(0.62) saturate(0.85);
  transform: scale(1.02);
  transition: filter 0.5s var(--ease), transform 0.5s var(--ease);
}

.team-peek__slide.is-active .team-peek__frame img {
  filter: brightness(1) saturate(1);
  transform: scale(1);
}

.team-peek__frame::after {
  content: "";
  position: absolute;
  inset: 40% 0 0;
  background: linear-gradient(180deg, transparent 0%, rgba(7, 10, 8, 0.55) 45%, rgba(7, 10, 8, 0.92) 100%);
  pointer-events: none;
}

.team-peek__caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  padding: 1.5rem 1.25rem 1.25rem;
  opacity: 0.55;
  transition: opacity 0.5s var(--ease);
}

.team-peek__slide.is-active .team-peek__caption { opacity: 1; }

.team-peek__name {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 5vw, 1.9rem);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: 0.01em;
  color: var(--neon);
  text-shadow:
    0 0 10px var(--neon-glow),
    0 0 34px rgba(190, 255, 220, 0.3);
}

.team-peek__role {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.4rem;
  font-size: var(--t-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ember);
}

.team-peek__role::after {
  content: "";
  height: 1px;
  width: 0;
  flex: 0 0 auto;
  background: linear-gradient(90deg, var(--ember), transparent);
  transition: width 0.5s var(--ease);
}

.team-peek__slide.is-active .team-peek__role::after { width: 2.25rem; }

.team-peek__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.25rem;
  margin-top: 1.75rem;
}

.team-peek__arrow {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--edge-control);
  color: var(--text);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color 0.4s var(--ease), color 0.4s var(--ease);
}

.team-peek__arrow:hover {
  border-color: rgba(200, 255, 224, 0.45);
  color: var(--neon);
}

.team-peek__dots {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.team-peek__dots button {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--edge-control);
  cursor: pointer;
  transition: width 0.4s var(--ease), background 0.4s var(--ease), border-radius 0.4s var(--ease);
}

.team-peek__dots button[aria-selected="true"] {
  width: 22px;
  border-radius: 4px;
  background: var(--neon);
  box-shadow: 0 0 8px var(--neon-glow);
}

@media (max-width: 640px) {
  .team-peek__arrow { display: none; }
}

/* Highlight cards */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.4rem;
}

/* Interactive surface, so the boundary needs 3:1 like any other control. */
.card {
  position: relative;
  display: block;
  color: inherit;
  padding: 2.6rem 2rem;
  background: linear-gradient(160deg, var(--raise) 0%, var(--room) 100%);
  border: 1px solid var(--edge-control);
  overflow: hidden;
  transition: border-color 0.5s var(--ease), transform 0.5s var(--ease), box-shadow 0.5s var(--ease);
}

/* The whole tile is clickable, but the accessible name is just the heading —
   a stretched link rather than an <a> wrapped round three sentences of prose,
   which is what a screen reader used to have to read out as the link text. */
.card h3 a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.card h3 a { color: inherit; }

.card::before {
  content: "";
  position: absolute;
  top: -40%; right: -30%;
  width: 70%;
  height: 90%;
  background: radial-gradient(circle, rgba(20, 83, 45, 0.28) 0%, transparent 70%);
  transition: opacity 0.5s;
  opacity: 0.6;
}

.card:hover {
  border-color: rgba(200, 255, 224, 0.45);
  transform: translateY(-4px);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
}

.card:hover { color: inherit; }

/* Keyboard focus lands on the inner link, so the ring has to be drawn
   round the tile it actually activates. */
.card:has(a:focus-visible) {
  outline: 2px solid var(--neon);
  outline-offset: 3px;
  border-color: rgba(200, 255, 224, 0.45);
}

.card h3 a:focus-visible { outline: none; }

.card .card-icon { margin-bottom: 1.4rem; color: var(--neon); }

.card .card-icon svg {
  width: 42px;
  height: 42px;
  filter: drop-shadow(0 0 7px rgba(190, 255, 220, 0.4));
  transition: filter 0.5s var(--ease);
}

.card:hover .card-icon svg {
  filter: drop-shadow(0 0 12px rgba(190, 255, 220, 0.65));
}

.card h3 { font-size: 1.25rem; margin-bottom: 0.7rem; letter-spacing: 0.04em; }

.card p { color: var(--muted); font-size: 0.95rem; margin-bottom: 1.4rem; }

.card .card-link {
  font-size: 0.74rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--neon);
  transition: color 0.4s var(--ease);
}

.card .card-link::after {
  content: "→";
  margin-left: 0.5em;
  display: inline-block;
  transition: transform 0.4s var(--ease);
}

.card:hover .card-link::after { transform: translateX(4px); }

/* Instagram / reservation banner */
.insta-banner {
  text-align: center;
  padding: clamp(4rem, 8vw, 6rem) 1.5rem;
  background:
    radial-gradient(ellipse 70% 100% at 50% 100%, rgba(15, 61, 46, 0.5) 0%, transparent 70%),
    var(--bg-3);
  border-block: 1px solid var(--line);
}

.insta-banner h2 { font-size: clamp(1.5rem, 3.5vw, 2.2rem); margin: 0.6rem 0 1rem; }

.insta-banner p { color: var(--muted); max-width: 34rem; margin: 0 auto 2rem; }

/* Hours + map teaser */
.hours-map {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3rem;
  align-items: center;
}

@media (max-width: 720px) { .hours-map { grid-template-columns: 1fr; } }

/* Hours table */
.hours-table { width: 100%; border-collapse: collapse; }

.hours-table th, .hours-table td {
  padding: 0.85rem 0.4rem;
  text-align: left;
  border-bottom: 1px solid var(--line);
}

.hours-table th { color: var(--text); font-weight: 400; }

.hours-table td { text-align: right; color: var(--muted); }

.hours-table tr.today th, .hours-table tr.today td {
  color: var(--neon);
  text-shadow: 0 0 10px rgba(200, 255, 224, 0.25);
}

.hours-table .closed { color: var(--ember); }

/* `.hours-table tr.today td` (0,2,2) outranks `.hours-table .closed` (0,2,0),
   so on a Monday the site used to highlight "closed" in the same celebratory
   neon it uses for open. The one row that should warn was reassuring. */
.hours-table tr.today td.closed {
  color: var(--ember);
  text-shadow: none;
}

/* Place card — replaces the drawn-on grid that pretended to be a map.
   A fake map reads as a broken one: people try to pan it. This says the
   same thing honestly, and takes a different surface treatment from every
   other block on the page — a rule down one side instead of a box — so the
   page stops being five variations of the same bordered rectangle. */
.place-card {
  display: block;
  color: inherit;
  padding: 0.4rem 0 0.4rem 2rem;
  border-left: 2px solid var(--edge-control);
  transition: border-color 0.4s var(--ease);
}

.place-card:hover, .place-card:focus-visible { border-left-color: var(--neon); }

.place-card address {
  font-style: normal;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  line-height: 1.15;
  color: var(--text);
  margin: 0.6rem 0 1.6rem;
}

.map-embed {
  width: 100%;
  min-height: 340px;
  border: 1px solid var(--line);
  filter: grayscale(1) invert(0.92) hue-rotate(120deg) saturate(0.5);
}

/* ============================================
   PAGE HERO (subpages)
   ============================================ */
.page-hero {
  padding: calc(var(--header-h) + clamp(3rem, 8vw, 5.5rem)) 0 clamp(2.5rem, 6vw, 4rem);
  text-align: center;
  background:
    radial-gradient(ellipse 70% 90% at 50% -20%, rgba(20, 83, 45, 0.35) 0%, transparent 65%),
    var(--bg);
}

.page-hero h1 {
  font-size: clamp(2.5rem, 6vw, 3.75rem);
  letter-spacing: -0.015em;
  line-height: 1.05;
  color: var(--text);
}

.page-hero p { color: var(--muted); margin-top: 0.8rem; }

/* ============================================
   MENU PAGE
   ============================================ */
.menu-tabs {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  position: sticky;
  top: var(--header-h);
  z-index: 50;
  padding: 0.8rem 0;
  background: rgba(10, 13, 11, 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.menu-tabs a {
  padding: 0.5rem 1.1rem;
  font-size: 0.74rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid transparent;
  transition: all 0.35s var(--ease);
}

.menu-tabs a:hover, .menu-tabs a.active {
  color: var(--neon);
  border-color: var(--line);
}

.menu-section { padding: clamp(3rem, 6vw, 4.5rem) 0; scroll-margin-top: calc(var(--header-h) + 64px); }

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

.menu-section h2 {
  text-align: center;
  font-size: clamp(1.6rem, 3.5vw, 2.2rem);
  margin-bottom: 0.4rem;
}

.menu-section .menu-note {
  text-align: center;
  color: var(--muted);
  font-size: 0.9rem;
  max-width: 32rem;
  margin: 0 auto 2.5rem;
}

.menu-list { max-width: 680px; margin: 0 auto; list-style: none; }

.menu-item {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.3rem 1.5rem;
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--line);
  align-items: baseline;
}

.menu-item:last-child { border-bottom: none; }

.menu-item .name { font-size: 1.05rem; letter-spacing: 0.02em; }

.menu-item .price {
  color: var(--gold);
  font-size: 0.95rem;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.menu-item .desc {
  grid-column: 1 / -1;
  color: var(--muted);
  font-size: 0.88rem;
}

.menu-footnote {
  text-align: center;
  color: var(--muted);
  font-size: 0.8rem;
  padding: 2rem 1rem 0;
  opacity: 0.75;
}

/* ============================================
   GALLERY
   ============================================ */
.gallery-grid {
  columns: 3;
  column-gap: 1rem;
}

@media (max-width: 900px) { .gallery-grid { columns: 2; } }
@media (max-width: 520px) { .gallery-grid { columns: 2; column-gap: 0.6rem; } }

.gallery-item {
  break-inside: avoid;
  margin-bottom: 1rem;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  cursor: pointer;
  background: var(--bg-2);
  transition: border-color 0.4s, box-shadow 0.4s;
  padding: 0;
  width: 100%;
  display: block;
}

.gallery-item:hover {
  border-color: rgba(190, 255, 220, 0.4);
  box-shadow: 0 0 24px rgba(190, 255, 220, 0.12);
}

.gallery-item .ph {
  width: 100%;
  display: flex;
  align-items: flex-end;
  padding: 1rem;
  transition: transform 0.7s var(--ease);
}

.gallery-item:hover .ph { transform: scale(1.05); }

.gallery-item .ph span {
  font-size: 0.68rem;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: rgba(232, 237, 233, 0.55);
}

/* Placeholder art — swap for real <img> later */
.ph--tall { aspect-ratio: 3 / 4; }
.ph--wide { aspect-ratio: 4 / 3; }
.ph--square { aspect-ratio: 1; }

.ph--1 { background: radial-gradient(circle at 30% 25%, rgba(190,255,220,0.13) 0%, transparent 45%), linear-gradient(160deg, #11201a, #0a0d0b); }
.ph--2 { background: radial-gradient(circle at 70% 70%, rgba(201,164,92,0.16) 0%, transparent 50%), linear-gradient(200deg, #131a15, #0a0d0b); }
.ph--3 { background: radial-gradient(ellipse at 50% 100%, rgba(20,83,45,0.5) 0%, transparent 60%), #0c110e; }
.ph--4 { background: radial-gradient(circle at 20% 80%, rgba(190,255,220,0.09) 0%, transparent 55%), linear-gradient(120deg, #0f1712, #0a0d0b); }
.ph--5 { background: radial-gradient(circle at 80% 20%, rgba(201,164,92,0.13) 0%, transparent 45%), #0e1410; }
.ph--6 { background: radial-gradient(ellipse at 50% 0%, rgba(20,83,45,0.45) 0%, transparent 65%), #0b0f0c; }

/* Lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(6, 8, 7, 0.94);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease), visibility 0.4s;
}

.lightbox.open { opacity: 1; visibility: visible; }

.lightbox-content {
  width: min(760px, 90vw);
  max-height: 84vh;
  border: 1px solid var(--line);
  box-shadow: 0 0 60px rgba(190, 255, 220, 0.1);
}

.lightbox-content .ph { height: min(70vh, 560px); padding: 1.4rem; align-items: flex-end; display: flex; }

.lightbox-close {
  position: absolute;
  top: 1.4rem;
  right: 1.8rem;
  background: none;
  border: none;
  color: var(--text);
  font-size: 2rem;
  cursor: pointer;
  line-height: 1;
  transition: color 0.3s, text-shadow 0.3s;
}

.lightbox-close:hover { color: var(--neon); text-shadow: 0 0 12px var(--neon-glow); }

/* ============================================
   CONTACT
   ============================================ */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3rem;
}

@media (max-width: 780px) { .contact-grid { grid-template-columns: 1fr; } }

.contact-card {
  padding: 2.4rem 2rem;
  background: var(--bg-2);
  border: 1px solid var(--line);
}

.contact-card h2 { font-size: 1.3rem; margin: 0.4rem 0 1.4rem; }

.contact-card address { font-style: normal; color: var(--muted); line-height: 2; }

.contact-card address a { color: var(--text); }
.contact-card address a:hover { color: var(--neon); }

/* ============================================
   FOOTER
   ============================================ */
.site-footer {
  border-top: 1px solid var(--line);
  padding: 3.5rem 0 2rem;
  background: var(--bg-2);
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 2.5rem;
  margin-bottom: 2.5rem;
}

@media (max-width: 720px) {
  .footer-grid { grid-template-columns: 1fr; text-align: center; }
}

.footer-logo {
  font-family: var(--font-script);
  font-size: 3.25rem;
  line-height: 0.9;
  color: var(--neon);
  text-shadow:
    0 0 9px var(--neon-glow),
    0 0 26px rgba(190, 255, 220, 0.35),
    0 0 60px rgba(120, 220, 170, 0.2);
}

.footer-logo small {
  display: block;
  font-family: var(--font-sans);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--smoke);
  text-shadow: none;
  margin-top: 6px;
}

/* :not(.footer-logo) matters — this selector is (0,1,1) and .footer-logo is
   (0,1,0), so without it the wordmark loses and renders at 14px however
   large its own rule sets it. */
.site-footer p:not(.footer-logo), .site-footer address {
  color: var(--smoke);
  font-size: var(--t-sm);
  font-style: normal;
}

.footer-grid h4 {
  font-size: 0.72rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--text);
  font-weight: 500;
  margin-bottom: 1rem;
}

.footer-grid ul { list-style: none; }
.footer-grid li { margin-bottom: 0.45rem; color: var(--muted); font-size: 0.88rem; }

.footer-bottom {
  border-top: 1px solid var(--line);
  padding-top: 1.6rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

@media (max-width: 720px) { .footer-bottom { justify-content: center; text-align: center; } }

.footer-bottom p { font-size: 0.75rem; }

.badge-18 {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--gold);
  border-radius: 50%;
  color: var(--gold);
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  flex-shrink: 0;
}

/* ============================================
   LIVE STATUS — "the sign is on when the bar is on"

   Reservations run through Instagram and there is no phone number, so
   "can I go tonight?" is the one question this site has to answer before
   anything else. It used to be answered in row one of a table 2,500px
   down the page.

   Two renderings of one state: a chip in the header on every page, and a
   line under the hero wordmark on the home page. Both filled by main.js
   from the same HOURS object.
   ============================================ */
/* An author `display` beats the UA stylesheet's [hidden] rule, so the
   attribute needs honouring explicitly or the empty chip renders anyway. */
.status[hidden] { display: none; }

.status {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--neon);
  white-space: nowrap;
}

/* The dot is the tell you read before the words. */
.status::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 8px currentColor;
  flex-shrink: 0;
}

.status[data-open="false"] {
  color: var(--ember);
  letter-spacing: 0.12em;
}

.status[data-open="false"]::before { box-shadow: none; opacity: 0.75; }

/* Below the wordmark, where the eye already is. */
.hero-status {
  margin-top: 1.2rem;
  margin-bottom: 1.2rem;
  justify-content: center;
  text-shadow: 0 1px 3px rgba(3, 9, 6, 0.95);
}

/* The header chip is the middle item in a three-item flex row, so revealing
   it moves neither the logo nor the nav — no layout shift when JS fills it. */
.header-inner .status { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }

/* Two lengths of the same message, both always in the DOM; CSS decides.
   The full line is the default everywhere. */
.status .s-short { display: none; }

/* A 390px header holds the wordmark and the hamburger and not much else,
   so the chip there drops to one word and the dot carries the state. The
   full sentence still runs under the hero wordmark on the home page and
   under the page title everywhere else, so nothing is actually lost. */
@media (max-width: 700px) {
  .header-inner .status .s-long { display: none; }
  .header-inner .status .s-short { display: inline; }
  .header-inner .status { font-size: 0.6875rem; letter-spacing: 0.14em; }
  .header-inner .status::before { width: 6px; height: 6px; }
  .logo { font-size: 2.15rem; }
  .logo small { font-size: 0.5rem; letter-spacing: 0.3em; }
}

/* Under the page title on the subpages. */
.page-status { margin-top: 1.1rem; }

/* ---------- Closed ----------
   The sign stays on. A bar leaves its neon lit in the window when it's shut,
   so the honest version of "closed" is not a dead tube — it's a lit sign over
   a quiet room. Earlier passes here dimmed the wordmark to a dead grey-green
   and had it gutter out; both were the concept pushing past what's actually
   true, and both made the hero look broken rather than shut.

   So the sign, its glow pool and the strike-on entrance are identical in both
   states. What changes is the room behind it: nobody is smoking, and fewer
   lights are on. The ember status chip does the actual telling. */
body.is-closed .smoke { display: none; }

body.is-closed .hero-wall { --leaf-dim: 0.5; }

@media (prefers-reduced-motion: reduce) {
  .status::before { box-shadow: none; }
  /* Durations are already forced to 0.01ms globally, which lands both fail
     animations on their final frame: sign unlit, pool dark. Correct end
     state, no stutter. */
}

/* ============================================
   SCROLL REVEAL
   ============================================ */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 1s var(--ease), transform 1s var(--ease);
}

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

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .reveal { opacity: 1; transform: none; }
  html { scroll-behavior: auto; }
}
