/* ==========================================================================
   The Whisper House — design system
   Mobile-first. Desktop enhancements live in min-width queries.
   Built by Gravity XL.
   ========================================================================== */

/* ---------- fonts (self-hosted: no third-party request, no FOUT) ----------
   Latin subset only — covers every character used on this site.
   Barlow Condensed is the display face: its condensed caps are the same species
   as the hand-lettered logo, which a high-contrast old-style serif never was.
   Yellowtail carries the small copper accents. Jost stays for body. */
@font-face{
  font-family:'Barlow Condensed';font-style:normal;font-weight:500;font-display:swap;
  src:url(../fonts/barlow-condensed-500.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Barlow Condensed';font-style:normal;font-weight:600;font-display:swap;
  src:url(../fonts/barlow-condensed-600.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Barlow Condensed';font-style:normal;font-weight:700;font-display:swap;
  src:url(../fonts/barlow-condensed-700.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Yellowtail';font-style:normal;font-weight:400;font-display:swap;
  src:url(../fonts/yellowtail-400.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Jost';font-style:normal;font-weight:300;font-display:swap;
  src:url(../fonts/jost-300.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Jost';font-style:normal;font-weight:400;font-display:swap;
  src:url(../fonts/jost-400.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Jost';font-style:normal;font-weight:500;font-display:swap;
  src:url(../fonts/jost-500.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root{
  /* ---- colour ---- */
  --bg:#0B0C0B;
  --bg-2:#151310;
  --surface:#211A14;
  --surface-2:#1A1511;
  --ivory:#F1E8D9;
  --muted:#C3B6A5;
  --copper:#AD7445;
  --copper-lt:#C89566;      /* copper that needs more presence as text */
  --copper-dk:#8A5A34;
  --line:#49372A;
  --line-soft:rgba(73,55,42,.55);
  --on-copper:#14100C;      /* 5:1 against --copper — never ivory on copper */

  /* ---- type ---- */
  --display:'Barlow Condensed', 'Oswald', 'Arial Narrow', sans-serif;
  --script:'Yellowtail', 'Brush Script MT', cursive;
  --body:'Jost', 'Avenir Next', 'Segoe UI', system-ui, sans-serif;

  --d1:clamp(2.7rem, 1.2rem + 5.8vw, 6.4rem);
  --d2:clamp(2.1rem, 1.15rem + 3.7vw, 4.1rem);
  --d3:clamp(1.6rem, 1.1rem + 2vw, 2.5rem);
  --lede:clamp(1.02rem, .96rem + .35vw, 1.2rem);
  --micro:clamp(.66rem, .62rem + .12vw, .74rem);

  /* ---- space ---- */
  --gut:clamp(20px, 5vw, 72px);
  --secpad:clamp(72px, 9vw, 152px);
  --nav-h:76px;
  --bar-h:62px;                /* mobile action bar */

  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);

  --grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.4'/%3E%3C/svg%3E");
}

/* ---------- reset ---------- */
*,*::before,*::after{box-sizing:border-box}
*{margin:0;padding:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  background:var(--bg);color:var(--ivory);
  font-family:var(--body);font-weight:300;font-size:1rem;line-height:1.72;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  /* clip, not hidden: overflow-x:hidden turns <body> into a scroll container,
     which breaks position:sticky and steals the scroll timeline the photo
     drift is measured against. clip cuts the overflow without doing either. */
  overflow-x:clip;
}
img,picture,svg,video{display:block;max-width:100%}
img{height:auto}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
ul,ol{list-style:none}
:focus-visible{outline:2px solid var(--copper-lt);outline-offset:3px;border-radius:2px}
::selection{background:var(--copper);color:var(--on-copper)}

.skip{
  position:absolute;left:-9999px;top:0;z-index:300;
  background:var(--copper);color:var(--on-copper);padding:14px 20px;font-weight:500;
}
.skip:focus{left:12px;top:12px}
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* ---------- type ---------- */
/* Lining figures everywhere the display face meets a number. */
h1,h2,h3,h4,.mitem__name,.namelist li,.drawer__link{
  font-variant-numeric:lining-nums;font-feature-settings:"lnum" 1,"onum" 0;
}
h1,h2,h3,h4{
  font-family:var(--display);font-weight:700;line-height:1.0;
  letter-spacing:.008em;text-transform:uppercase;
}
.d1{font-size:var(--d1)}
.d2{font-size:var(--d2)}
.d3{font-size:var(--d3)}
h2,h3{text-wrap:balance}
em{font-family:var(--script);font-style:normal;color:var(--copper-lt)}

/* the script accent from the reference — set larger than a label would be,
   because a script at micro size is illegible */
.eyebrow{
  font-family:var(--script);font-weight:400;
  /* 60% up on the original 1.2–1.75rem ramp */
  font-size:clamp(1.92rem,1.6rem + 1.28vw,2.8rem);
  letter-spacing:0;text-transform:none;color:var(--copper-lt);line-height:1.2;
  margin-bottom:clamp(14px,1.8vw,22px);
}
/* small structural labels stay a letterspaced sans — script does not work here */
.label-caps{
  font-family:var(--body);font-weight:400;font-size:var(--micro);
  letter-spacing:.3em;text-transform:uppercase;color:var(--copper-lt);
}
.lede{font-size:var(--lede);color:var(--muted);max-width:56ch}
.tc{text-align:center}
.tc :is(p,h1,h2,h3,.eyebrow,.lede),
.hero__in :is(p,.eyebrow),
.banner :is(p,.eyebrow),
.resv :is(p,.eyebrow),
.pending :is(p,.eyebrow){margin-inline:auto}
/* heading tag here varies by page depth (h2 when the block is the page's top
   section, h3 when it sits under one) — match them all, not one level */
.pending--left,.pending--left :is(p,h2,h3,h4,.eyebrow){text-align:left;margin-inline:0}
p{color:var(--muted);max-width:66ch}
p + p{margin-top:1.1em}
.ivory{color:var(--ivory)}
.nowrap{white-space:nowrap}

/* ---------- layout ---------- */
.wrap{width:100%;max-width:1280px;margin-inline:auto;padding-inline:var(--gut)}
.wrap-n{width:100%;max-width:880px;margin-inline:auto;padding-inline:var(--gut)}
.sec{position:relative;padding-block:var(--secpad)}
.sec--tight{padding-block:clamp(52px,6vw,96px)}
/* a section whose child runs edge to edge — no container, no side padding,
   just the vertical rhythm so bands still breathe against their neighbours */
.sec--bleed{position:relative}
.sec--bleed + .sec--bleed{border-top:1px solid var(--line-soft)}
.sec--alt{background:var(--bg-2)}
.sec--surface{background:var(--surface-2)}
.hair{height:1px;background:var(--line-soft);border:0}

.grain{
  position:absolute;inset:0;background-image:var(--grain);
  opacity:.045;pointer-events:none;mix-blend-mode:overlay;z-index:0;
}

/* ---------- ornament ---------- */
.orn{color:var(--copper);width:clamp(150px,18vw,220px);height:auto;opacity:.9}
.orn--center{margin-inline:auto}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:11px;
  min-height:52px;padding:0 clamp(22px,2.4vw,34px);
  font-family:var(--display);font-weight:600;font-size:.98rem;
  letter-spacing:.14em;text-transform:uppercase;text-align:center;
  border:1px solid var(--copper);background:var(--copper);color:var(--on-copper);
  transition:background .35s var(--ease),border-color .35s var(--ease),
             color .35s var(--ease),transform .35s var(--ease);
}
.btn:hover{background:var(--copper-lt);border-color:var(--copper-lt)}
.btn:active{transform:translateY(1px)}
.btn svg{width:15px;height:15px;flex:none;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}

.btn--ghost{background:transparent;color:var(--ivory);border-color:var(--line)}
.btn--ghost:hover{background:rgba(173,116,69,.10);border-color:var(--copper);color:var(--ivory)}
.btn--wide{width:100%}

/* underlined text link with a copper rule that draws in */
.tlink{
  position:relative;display:inline-flex;align-items:center;gap:9px;
  font-family:var(--display);font-size:.94rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--copper-lt);padding-block:13px;
}
.tlink::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--copper);transform:scaleX(.28);transform-origin:left;
  transition:transform .5s var(--ease-out);
}
.tlink:hover::after,.tlink:focus-visible::after{transform:scaleX(1)}
.tlink svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;transition:transform .35s var(--ease-out)}
.tlink:hover svg{transform:translateX(4px)}

/* ==========================================================================
   HEADER
   ========================================================================== */
.hdr{
  position:fixed;top:0;left:0;right:0;z-index:100;height:var(--nav-h);
  background:rgba(11,12,11,.96);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  border-bottom:1px solid var(--line-soft);
  transition:background .45s var(--ease),border-color .45s var(--ease);
}
/* homepage only: transparent until scrolled */
.hdr--overlay:not(.is-stuck){
  background:transparent;border-bottom-color:transparent;
  -webkit-backdrop-filter:none;backdrop-filter:none;
}
/* logo | nav | action — the nav sits in the middle column and centres itself
   there, so it stays optically centred on the page whatever the logo width. */
.hdr__in{height:100%;display:grid;grid-template-columns:auto 1fr auto;
  align-items:center;gap:clamp(12px,2vw,28px)}
.hdr__logo{display:flex;align-items:center;flex:none;padding-block:8px}
/* The logo is a stacked, three-line lockup — below ~46px the lower lines turn
   to mush. These values keep "WHISPER" legible inside both header heights. */
.hdr__logo img{height:clamp(46px,4.8vw,62px);width:auto}

.navwrap{display:none;grid-column:2;justify-self:center}
.hdr__cta{grid-column:3;display:flex;align-items:center;gap:clamp(10px,1.4vw,18px);
  justify-self:end;flex:none}
.hdr__cta > .btn{display:none}
/* the header action is a small button, not the full page-scale .btn */
.btn--sm{min-height:42px;padding:0 clamp(16px,1.6vw,24px);font-size:.7rem;letter-spacing:.2em}

.burger{
  position:relative;width:46px;height:46px;flex:none;
  border:1px solid var(--line);background:none;
}
.burger span{
  position:absolute;left:50%;top:50%;width:18px;height:1px;margin-left:-9px;background:var(--ivory);
  transition:transform .35s var(--ease),opacity .2s linear;
}
.burger span:nth-child(1){transform:translateY(-6px)}
.burger span:nth-child(3){transform:translateY(6px)}
.burger.is-open span:nth-child(1){transform:rotate(45deg)}
.burger.is-open span:nth-child(2){opacity:0}
.burger.is-open span:nth-child(3){transform:rotate(-45deg)}

/* ---------- mobile drawer ---------- */
.drawer{
  position:fixed;inset:0;z-index:98;background:var(--bg);
  opacity:0;visibility:hidden;transform:translateY(-10px);pointer-events:none;
  transition:opacity .35s var(--ease),transform .35s var(--ease),visibility .35s;
  display:flex;flex-direction:column;overflow-y:auto;
  padding:calc(var(--nav-h) + 26px) var(--gut) calc(var(--bar-h) + 40px + env(safe-area-inset-bottom));
}
.drawer.is-open{opacity:1;visibility:visible;transform:none;pointer-events:auto}
body.nav-open{overflow:hidden}
body.nav-open .hdr{background:rgba(11,12,11,.98);border-bottom-color:var(--line-soft)}
body.nav-open .mbar{transform:translateY(105%)}

.drawer__link{
  display:flex;align-items:baseline;justify-content:space-between;gap:16px;
  padding:16px 0;border-bottom:1px solid var(--line-soft);
  font-family:var(--display);font-size:1.6rem;font-weight:600;color:var(--ivory);
  text-transform:uppercase;letter-spacing:.02em;
}
.drawer__link .n{
  font-family:var(--body);font-size:.62rem;letter-spacing:.24em;color:var(--copper);
  display:inline-flex;align-items:center;gap:12px;
}
/* The Menus row opens a sub-list instead of navigating — it needs to look
   different from the rows that do navigate. */
.drawer__link--toggle{width:100%;text-align:left}
.drawer__caret{
  width:17px;height:17px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;
  transition:transform .3s var(--ease);
}
.drawer__link--toggle[aria-expanded="true"] .drawer__caret{transform:rotate(180deg)}
.drawer__sub{padding:4px 0 10px 0}
.drawer__sub a{
  display:block;padding:11px 0 11px 18px;border-left:1px solid var(--line);
  font-size:.82rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
}
.drawer__sub a:hover{color:var(--copper-lt)}
.drawer__foot{margin-top:auto;padding-top:32px;display:grid;gap:12px}
.drawer__meta{
  margin-top:24px;font-size:.78rem;letter-spacing:.06em;color:var(--muted);
}
.drawer__meta a{color:var(--copper-lt);display:inline-block;padding-block:12px}

/* ---------- mobile action bar ---------- */
.mbar{
  position:fixed;left:0;right:0;bottom:0;z-index:99;
  display:grid;grid-template-columns:repeat(3,1fr);
  background:rgba(11,12,11,.97);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  border-top:1px solid var(--line);
  padding-bottom:env(safe-area-inset-bottom);
  transition:transform .45s var(--ease-out);
}
/* the phone's action bar is navigation too, so it takes the same face */
.mbar a{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
  min-height:var(--bar-h);
  font-family:var(--display);font-weight:600;
  font-size:.76rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ivory);
}
.mbar a + a{border-left:1px solid var(--line-soft)}
.mbar a[data-primary]{background:var(--copper);color:var(--on-copper)}
.mbar svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}

/* ==========================================================================
   HERO
   ========================================================================== */
.hero{
  position:relative;display:flex;align-items:center;
  /* fills the screen on landing. svh is the *small* viewport height, so on a
     phone the hero does not jump when the browser chrome hides on scroll. */
  min-height:100vh;min-height:100svh;
  padding-top:calc(var(--nav-h) + clamp(28px,4vw,56px));
  padding-bottom:clamp(64px,8vw,110px);
  overflow:hidden;isolation:isolate;
}
.hero__media{position:absolute;inset:0;z-index:-3;overflow:hidden}
.hero__media picture{display:block;width:100%;height:100%}
/* The hero photograph runs black and white. The room is warm and busy in
   colour and the logo had to fight it; desaturated, the mark sits on top of
   the room instead of in it, and the copper in the buttons below becomes the
   only colour on the first screen. Everything further down the page stays in
   colour — this is the hero only. */
.hero__media img,.hero__media video{
  width:100%;height:100%;object-fit:cover;
  filter:grayscale(1) contrast(1.06) brightness(.92);
}

/* ---------- slow push-in on landing ----------
   Two knobs: how far it travels and how long it takes. The image starts at
   rest and eases in, so it is still moving when the page settles but has
   nearly stopped by the time anyone scrolls. `forwards` holds the end state
   rather than snapping back. */
.hero{--hero-zoom:1.13;--hero-zoom-time:18s}
.hero__media img{
  transform-origin:52% 58%;   /* the lit back bar, not the dead centre */
  animation:heroZoom var(--hero-zoom-time) cubic-bezier(.22,.35,.24,1) forwards;
}
@keyframes heroZoom{
  from{transform:scale(1)}
  to{transform:scale(var(--hero-zoom))}
}
/* On a short screen (laptops at 720p, landscape phones) the stack of logo,
   place, ornament and buttons is taller than the padding allows, and the hero
   would push past the fold — defeating the point of a full-screen hero.
   Tighten the vertical rhythm rather than let it spill. */
@media (max-height:820px) and (min-width:760px){
  .hero{
    padding-top:calc(var(--nav-h) + clamp(14px,2.4vh,34px));
    padding-bottom:clamp(48px,7vh,78px);
  }
  .hero__logo{width:min(clamp(330px,48vw,585px),100%)}
  .hero__place{margin-top:clamp(14px,2vh,24px)}
  .hero__orn{margin-top:clamp(12px,1.6vh,20px)}
  .hero__ctas{margin-top:clamp(18px,2.6vh,32px)}
}
@media (max-height:700px){
  .hero__orn{display:none}
}
/* Deeper than it was. The room still reads behind the mark, but it sits well
   back — a dark ground the logo lands on rather than a photograph competing
   with it. The radial keeps a little lift right behind the mark so the shot
   does not go flat; the linear holds the nav at the top and the CTAs at the
   foot. Adjust these two numbers together, not one at a time. */
.hero__scrim{
  position:absolute;inset:0;z-index:-1;
  background:
    radial-gradient(ellipse at 50% 46%, rgba(11,12,11,.22) 0%, rgba(11,12,11,.56) 58%, rgba(11,12,11,.88) 100%),
    linear-gradient(180deg, rgba(11,12,11,.86) 0%, rgba(11,12,11,.40) 34%, rgba(11,12,11,.48) 62%, rgba(11,12,11,.94) 100%);
}
.hero__in{position:relative;width:100%;text-align:center}
.hero__logo{
  /* 50% up on the original 240–470px ramp */
  width:min(clamp(360px,63vw,705px),100%);height:auto;margin-inline:auto;
  filter:drop-shadow(0 10px 40px rgba(0,0,0,.85));
}
.hero__place{
  margin-top:clamp(22px,3vw,34px);
  font-size:var(--micro);letter-spacing:.42em;text-transform:uppercase;color:var(--ivory);
}
.hero__orn{margin-top:clamp(18px,2.4vw,28px)}
.hero__ctas{
  margin-top:clamp(26px,3.4vw,42px);
  display:flex;flex-wrap:wrap;gap:14px;justify-content:center;
}
.hero__cue{
  position:absolute;left:50%;bottom:clamp(14px,3vw,30px);transform:translateX(-50%);
  z-index:2;display:flex;flex-direction:column;align-items:center;gap:9px;
  font-size:.58rem;letter-spacing:.3em;text-transform:uppercase;color:var(--muted);
}
.hero__cue i{display:block;width:1px;height:34px;background:linear-gradient(var(--copper),transparent)}
/* Under ~768px of viewport height (a 1280x720 laptop is the common case) the
   cue starts colliding with the CTA row. The cue is decorative, the buttons are
   not, so the cue goes first. Declared after the base rule, not up with the
   other height queries, or the base `display:flex` would win on source order. */
@media (max-height:768px){ .hero__cue{display:none} }

/* ==========================================================================
   INTRO — the welcome block that sits directly under the hero
   ========================================================================== */
.intro{background:var(--bg)}
.intro .eyebrow{margin-top:clamp(16px,2vw,24px)}
.intro__text{
  margin-top:clamp(18px,2.4vw,28px);max-width:52ch;
  color:var(--muted);text-wrap:pretty;
}
.intro__kicker{
  margin-top:clamp(20px,2.6vw,30px);max-width:none;
  font-size:var(--micro);letter-spacing:.28em;text-transform:uppercase;
  color:var(--copper);
}

/* ==========================================================================
   MARQUEE — house facts ticking under the hero
   Two identical runs sit side by side and the track slides exactly one run
   width, so the loop is seamless. Duration scales with content length rather
   than being a fixed number, which keeps the speed steady if lines are added.
   ========================================================================== */
.mq{
  position:relative;overflow:hidden;
  border-block:1px solid var(--line-soft);background:var(--bg-2);
  padding-block:clamp(16px,1.8vw,26px);
  /* One full run width per cycle, so the duration has to track the type size
     or the ticker changes pace. At the 4.32rem desktop cap the run is ~2.7x
     the width it was at 1.62rem, hence 180s — same pixels per second. */
  --mq-time:180s;
}
/* fade the ends so items enter and leave rather than being chopped */
.mq::before,.mq::after{
  /* wide enough to swallow a whole word at the 4.32rem size — a narrow fade
     just clips a letter in half, which reads as a bug rather than a fade */
  content:"";position:absolute;top:0;bottom:0;width:clamp(56px,13vw,240px);z-index:2;
  pointer-events:none;
}
.mq::before{left:0;background:linear-gradient(90deg,var(--bg-2),transparent)}
.mq::after{right:0;background:linear-gradient(270deg,var(--bg-2),transparent)}

.mq__track{display:flex;width:max-content;animation:mqScroll var(--mq-time,46s) linear infinite}
.mq__run{display:flex;align-items:center}
.mq__run li{
  display:flex;align-items:center;flex:none;
  font-family:var(--display);font-weight:500;
  /* Big-type ticker: 4.32rem on desktop, reaching the cap by ~1440. Set on
     one line (line-height:1) so the band stays a band and does not become a
     stripe the height of a paragraph. */
  font-size:clamp(1.5rem,.5rem + 4.6vw,4.32rem);
  line-height:1;
  letter-spacing:.08em;text-transform:uppercase;color:var(--muted);
  white-space:nowrap;padding-inline:clamp(22px,3.2vw,56px);
}
/* copper lozenge between items, drawn rather than typed so it never wraps */
.mq__run li::after{
  content:"";width:clamp(10px,1.4vw,22px);height:clamp(10px,1.4vw,22px);
  flex:none;margin-left:clamp(22px,3.2vw,56px);
  border:1px solid var(--copper);transform:rotate(45deg);
}
.mq:hover .mq__track{animation-play-state:paused}
@keyframes mqScroll{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}
}

/* ==========================================================================
   EDITORIAL BAND — full bleed, image runs to the viewport edge
   The band is NOT inside .wrap. The picture fills its half of the screen and
   the copy sits in the other half with its own padding, which is what gives
   the mockups their cinematic width.
   ========================================================================== */
.band{display:grid;align-items:stretch;background:var(--bg)}
.band__media{position:relative;overflow:clip;background:var(--bg-2)}
.band__media img{width:100%;height:100%;object-fit:cover;aspect-ratio:3/2}
.band__media::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(11,12,11,.32) 0%,rgba(11,12,11,0) 26%,rgba(11,12,11,.30) 100%);
}
.band__body{
  padding:clamp(40px,7vw,86px) var(--gut);
  display:flex;flex-direction:column;justify-content:center;
}
.band__body > *{max-width:42ch}
.band__body > .eyebrow{max-width:none}
.band__body .lede{max-width:34ch;text-wrap:pretty}
.band__body p{text-wrap:pretty}
.band__body h2{margin-bottom:clamp(14px,1.8vw,22px)}
.band__body .lede{margin-bottom:.4em}
.band__body .btn,.band__body .tlink{margin-top:clamp(20px,2.6vw,32px);align-self:flex-start}
/* a row of buttons must not be squeezed by the band's reading measure */
.btnrow{max-width:none;display:flex;flex-wrap:wrap;gap:14px;margin-top:clamp(20px,2.6vw,32px)}
.btnrow .btn{margin-top:0}
.band--alt{background:var(--bg-2)}

/* eyebrow with a copper rule trailing off it, as in the mockups */
.eyebrow--rule{display:flex;align-items:center;gap:16px}
.eyebrow--rule::after{
  content:"";flex:1;height:1px;background:var(--line);max-width:120px;
}

/* ==========================================================================
   ORNAMENTAL SECTION HEADING — fleuron between two hairlines
   ========================================================================== */
.rulehd{display:flex;align-items:center;justify-content:center;gap:clamp(14px,2vw,24px)}
.rulehd::before,.rulehd::after{
  content:"";height:1px;background:var(--line);flex:1;max-width:clamp(40px,10vw,150px);
}
.rulehd__mark{color:var(--copper);flex:none;width:11px;height:11px;transform:rotate(45deg);
  border:1px solid currentColor}
.rulehd--wide{margin-bottom:clamp(18px,2.4vw,30px)}
/* the same treatment wrapped around a word, as on the menu pages */
.rulehd--word{gap:clamp(18px,3vw,38px)}
.rulehd--word::before,.rulehd--word::after{max-width:clamp(50px,16vw,260px)}
.rulehd--word h2,.rulehd--word .d3{flex:none}

/* ==========================================================================
   MENU CATEGORY PANELS — full-bleed 4:5 portraits, caption over the photo

   Edge to edge with no gap: the section that holds .cats closes its .wrap
   first, so this grid spans the viewport. The 4:5 box is declared in CSS, so
   the panels hold their shape at every width and the page never reflows as
   the photos arrive.
   ========================================================================== */
.cats{
  display:grid;grid-template-columns:1fr;gap:0;
  margin-top:clamp(34px,4.4vw,58px);
  background:var(--bg-2);
}
.cat{
  /* clip, not hidden: `hidden` makes this a scroll container, which steals the
     view() timeline the panel's scroll drift is measured against */
  position:relative;display:block;text-align:center;overflow:clip;
  aspect-ratio:4/5;isolation:isolate;
}
/* Once the panels sit three across they become tall portraits. 4:5 is right
   when one panel spans the whole phone; at a third of a desktop it reads as a
   stub. The max-height stops a 1920 screen producing a panel taller than the
   window — the ratio gives way rather than the photo, which object-fit covers. */
@media (min-width:600px){
  /* width:100% makes the width definite, so aspect-ratio only drives the
     height. Without it the max-height clamps the height and the ratio pulls
     the width in with it, leaving the panel narrower than its column — which
     shows up as gaps between panels that are meant to touch. */
  .cat{width:100%;aspect-ratio:1/1.9;max-height:min(86vh,1040px)}
}
.cat__img{position:absolute;inset:0;overflow:clip;background:var(--bg-2)}
.cat__img img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 1.2s var(--ease-out);
}
/* Hover overlay. The photographs stay in colour — they are the whole reason
   someone stops here — and hovering lays a warm wash over the one you are
   pointing at instead: copper at the top fading to near-black at the foot,
   which both marks the panel and pushes the caption forward. It sits above
   the photo and below the caption and the wordmark, which both carry z-index,
   and it is pointer-events:none so it never eats the click. */
.cat::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(173,116,69,.26) 0%,rgba(11,12,11,.42) 55%,rgba(11,12,11,.62) 100%);
  opacity:0;transition:opacity .55s var(--ease);
}
.cat:hover::after,.cat:focus-visible::after{opacity:1}
/* Two stops rather than one: a light wash over the whole panel so the photos
   read as a set, then a deeper foot so the caption clears 4.5:1 whatever the
   plate underneath happens to be. */
.cat__img::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(180deg,rgba(11,12,11,.34) 0%,rgba(11,12,11,.12) 30%,rgba(11,12,11,.14) 48%,rgba(11,12,11,.62) 74%,rgba(11,12,11,.86) 90%,rgba(11,12,11,.92) 100%);
}
.cat__body{
  position:absolute;left:0;right:0;bottom:clamp(26px,4vw,56px);
  padding:0 clamp(16px,3vw,34px);z-index:1;
  transition:transform .7s var(--ease-out);
}
.cat:hover .cat__body,.cat:focus-visible .cat__body{transform:translateY(-14px)}
.cat__t{
  font-size:clamp(1.5rem,2.5vw,2.3rem);color:var(--ivory);
  text-shadow:0 2px 18px rgba(0,0,0,.55);
}
/* Desktop only. Each panel is a third of the viewport, so 3.3rem needs real
   width behind it — measured: "Weekend Brunch" wraps to two lines below
   1280px, so that is where the size steps up. Narrower screens keep the ramp. */
@media (min-width:1280px){
  .cat__t{font-size:3.3rem}
}
.cat__more{
  display:inline-block;margin-top:clamp(10px,1.2vw,15px);padding-bottom:6px;
  font-size:.62rem;letter-spacing:.24em;text-transform:uppercase;color:var(--ivory);
  border-bottom:1px solid var(--copper);
  transition:color .4s var(--ease),border-color .4s var(--ease);
}
/* The word set vertically up the panel. It is a watermark, not a label — the
   caption already names the panel — so it takes its colour from the photo
   underneath via mix-blend-mode rather than sitting on top of it as flat
   type. `overlay` darkens where the plate is dark and lightens where it is
   bright, which is what stops it reading as a sticker. Sized in cqh so it
   always fills the panel's height whatever the viewport does. */
.cat__ghost{
  position:absolute;right:-.3em;bottom:-.1em;z-index:1;pointer-events:none;
  writing-mode:vertical-rl;
  font-family:var(--display);font-weight:700;text-transform:uppercase;
  /* sized against the panel, not the viewport, so the word fills the height
     of a 4:5 box at any width and bleeds a little off both ends */
  font-size:24cqh;line-height:.76;letter-spacing:.01em;
  /* Ink, not light. A pale word over a photograph disappears wherever the
     plate is bright — which is most of these. A dark word at low alpha
     darkens consistently over both a lit waffle and a dark bar, which is what
     makes it read as part of the picture rather than a sticker on it. */
  color:rgba(9,10,9,.46);
  transition:transform .9s var(--ease-out),color .55s var(--ease);
  transform:translateY(0);
}
.cat{container-type:size}

.cat:hover .cat__img img,.cat:focus-visible .cat__img img{transform:scale(1.06)}
.cat:hover .cat__more,.cat:focus-visible .cat__more{color:var(--copper-lt)}
/* On hover the word rises and firms up while the photo pushes in behind it —
   two things moving at different rates, which is what gives the panel depth.
   Everything here is decoration, so a device with no hover simply sees the
   resting state, which is the state the panel is designed in. */
.cat:hover .cat__ghost,.cat:focus-visible .cat__ghost{
  transform:translateY(-3.2%);color:rgba(9,10,9,.62);
}
.cat__more{position:relative}
/* the rule under "Discover more" draws itself out from the centre on hover */
.cat__more::after{
  content:"";position:absolute;left:50%;right:50%;bottom:-1px;height:1px;
  background:var(--copper-lt);transition:left .55s var(--ease-out),right .55s var(--ease-out);
}
.cat:hover .cat__more::after,.cat:focus-visible .cat__more::after{left:0;right:0}
/* No border to hang focus on any more, so give the panel its own ring */
.cat:focus-visible{outline:2px solid var(--copper);outline-offset:-4px}

/* ==========================================================================
   WEEKEND BRUNCH — off-grid collage, headline laid across the seam
   Single column and plain stacking order below 900px; the overlap only
   happens where there is room for it.
   ========================================================================== */
.brunch{background:var(--bg);overflow:clip}
.brunch__in{position:relative}
.brunch__art{display:grid;gap:clamp(14px,2vw,26px)}
.brunch figure{margin:0;background:var(--bg-2);overflow:clip}
.brunch figure img{width:100%;height:100%;object-fit:cover;display:block}
.brunch__sq{aspect-ratio:1/1}
.brunch__lead{aspect-ratio:7/8}
/* Title first in the source so the heading reads before the photos it labels;
   on a wide screen it is lifted out of flow and laid across the collage. */
.brunch__title{margin-bottom:clamp(26px,3.4vw,40px)}
.brunch__h{
  margin-top:clamp(10px,1.4vw,18px);
  font-size:clamp(2.1rem,6vw,4.2rem);line-height:.98;color:var(--ivory);
}
.brunch__note{margin-top:clamp(20px,2.6vw,32px);max-width:46ch}
.brunch__note::before{
  content:"";display:block;width:100%;height:1px;background:var(--line-soft);
  margin-bottom:clamp(16px,2vw,24px);
}
.brunch__text{color:var(--muted);text-wrap:pretty}
.brunch__when{
  margin-top:clamp(10px,1.2vw,14px);
  font-size:.66rem;letter-spacing:.2em;text-transform:uppercase;color:var(--copper-lt);
}
.brunch__note .btn{margin-top:clamp(18px,2.2vw,26px)}

/* ==========================================================================
   RESERVATIONS BAND
   ========================================================================== */
.resv{position:relative;overflow:clip;isolation:isolate;text-align:center}
.resv__bg{position:absolute;inset:0;z-index:-2;overflow:clip}
.resv__bg img{width:100%;height:100%;object-fit:cover}
.resv__bg::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(11,12,11,.93),rgba(11,12,11,.80) 45%,rgba(11,12,11,.95));
}
.resv h2{margin-block:clamp(14px,1.8vw,22px)}
/* The headline is the reservation link — the whole line is the tap target,
   not a word inside it, and the copper rule under it grows on hover so it
   reads as a link without being underlined at rest. */
.resv__h a{
  display:inline-block;position:relative;color:inherit;
  transition:color .4s var(--ease);
}
.resv__h a::after{
  content:"";position:absolute;left:0;right:0;bottom:-.1em;
  height:2px;background:var(--copper);
  transform:scaleX(0);transform-origin:50%;
  transition:transform .55s var(--ease-out);
}
.resv__h a:hover,.resv__h a:focus-visible{color:var(--ivory)}
.resv__h a:hover::after,.resv__h a:focus-visible::after{transform:scaleX(1)}
.resv .lede{margin-inline:auto}
.resv__note{
  margin-top:clamp(20px,2.4vw,28px);font-size:.82rem;color:var(--muted);
  margin-inline:auto;
}
.resv__actions{margin-top:clamp(26px,3vw,38px);display:flex;flex-wrap:wrap;gap:14px;justify-content:center}

/* ==========================================================================
   LOCATION + MAP
   ========================================================================== */
.loc__grid{display:grid;gap:clamp(28px,3.6vw,56px);align-items:start}
.loc__map{
  position:relative;border:1px solid var(--line);background:var(--bg-2);
  aspect-ratio:4/3;overflow:hidden;
}
/* map as a full-bleed band panel */
.band__media--map{
  /* the map follows the copy column's height; this floor only matters when the
     copy is short, so it stays well under what the column actually needs */
  background:var(--bg-2);min-height:clamp(280px,30vw,440px);
  display:grid;place-items:center;
}
/* sits behind the iframe, so a blocked or offline embed degrades to this
   instead of an empty rectangle */
.band__media--map .mapfall{
  grid-area:1/1;text-align:center;padding:var(--gut);color:var(--muted);
  font-size:.86rem;line-height:1.9;
}
.band__media--map .mapfall svg{
  width:30px;height:30px;margin:0 auto 12px;fill:none;stroke:var(--copper);
  stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round;
}
.band__media--map iframe{grid-area:1/1;position:relative;z-index:2}
.band__media--map iframe{width:100%;height:100%;min-height:inherit;border:0;display:block}
.band__media--map::after{display:none}
/* The location band runs taller than the editorial ones because its copy
   column carries an address, a phone number, five lines of hours and two
   buttons. Left on the shared rhythm it filled a whole 1440x900 screen on its
   own, so this column keeps its own tighter one — the band is a reference
   panel, not a spread. */
.band__body--loc{padding-block:clamp(28px,3.6vw,48px)}
/* the display sizes step down here too — at the shared scale the heading and
   the script eyebrow alone accounted for a fifth of the band's height */
.band__body--loc .d2{font-size:clamp(1.75rem,1.1rem + 2.4vw,2.8rem)}
.band__body--loc .eyebrow{font-size:clamp(1.35rem,1.1rem + .7vw,1.85rem);margin-bottom:clamp(8px,1vw,13px)}
.band__body--loc > *{max-width:none}
.band__body--loc .loc__rows{margin-top:clamp(18px,2vw,26px)}
.band__body--loc .loc__rows{gap:clamp(14px,1.7vw,22px)}
.band__body--loc .loc__row{padding-bottom:clamp(13px,1.6vw,19px)}
.band__body--loc .hours li{padding-block:2px}
.band__body--loc .hours__note{margin-top:7px}
.band__body--loc .loc__actions{margin-top:clamp(14px,1.7vw,20px)}
.loc__map iframe{width:100%;height:100%;border:0;display:block}
.loc__rows{display:grid;gap:clamp(20px,2.4vw,30px)}
.loc__row{display:grid;gap:6px;padding-bottom:clamp(18px,2.2vw,26px);border-bottom:1px solid var(--line-soft)}
.loc__row:last-child{border-bottom:0;padding-bottom:0}
.loc__row :is(h2,h3),.loc__row-hd{
  font-family:var(--body);font-size:var(--micro);font-weight:400;
  letter-spacing:.28em;text-transform:uppercase;color:var(--copper-lt);
  line-height:1.4;
}
.loc__row p,.loc__row li{color:var(--ivory);font-size:1rem}
.loc__row a{color:var(--ivory);border-bottom:1px solid var(--line)}
.loc__row a:hover{color:var(--copper-lt);border-bottom-color:var(--copper)}
.hours li{display:flex;justify-content:space-between;gap:20px;padding-block:5px;flex-wrap:wrap}
.hours li span:last-child{color:var(--muted);font-variant-numeric:tabular-nums}
.hours__note{margin-top:10px;font-size:.84rem;color:var(--copper-lt)}
.loc__actions{margin-top:clamp(18px,2.2vw,26px);display:flex;flex-wrap:wrap;gap:12px}

/* ==========================================================================
   FOOTER
   ========================================================================== */
.ft{background:var(--bg-2);border-top:1px solid var(--line-soft);position:relative}
.ft__in{padding-block:clamp(40px,4.6vw,64px)}
/* One compact row: mark left, links centre, social right. */
.ft__top{
  display:grid;gap:clamp(26px,3vw,40px);justify-items:center;text-align:center;
  padding-bottom:clamp(28px,3.4vw,44px);
}
.ft__brand img{height:clamp(58px,6vw,80px);width:auto}
.ft__links{
  display:flex;flex-wrap:wrap;justify-content:center;
  gap:4px clamp(20px,3vw,44px);
}
.ft__links a{
  display:block;padding-block:10px;font-size:.7rem;letter-spacing:.2em;
  text-transform:uppercase;color:var(--muted);transition:color .3s var(--ease);
}
.ft__links a:hover{color:var(--copper-lt)}
/* house saying + place, split across the hairline bar */
.ft__saying{
  max-width:none;
  border-top:1px solid var(--line-soft);
  padding-top:clamp(18px,2.2vw,26px);padding-bottom:clamp(9px,1.1vw,13px);
  display:flex;flex-wrap:wrap;gap:10px 24px;justify-content:space-between;align-items:center;
  font-size:var(--micro);letter-spacing:.26em;text-transform:uppercase;color:var(--copper);
}
/* The address line used to be centred while the two rows around it ran edge
   to edge, so it read as floating rather than placed. All three footer rows
   now share one pair of edges: something on the left, something on the right,
   the same gutters top to bottom. */
.ft__nap{
  max-width:none;
  display:flex;flex-wrap:wrap;gap:4px 24px;
  justify-content:space-between;align-items:baseline;
  padding-top:clamp(9px,1.1vw,13px);font-size:.84rem;color:var(--muted);
}
.ft__nap a{color:var(--muted);padding-block:8px}
.ft__nap a:hover{color:var(--copper-lt)}
@media (min-width:880px){
  .ft__top{grid-template-columns:auto 1fr auto;align-items:center;justify-items:stretch}
  .ft__brand{justify-self:start}
  .ft__social{justify-self:end;margin-top:0}
}
.ft__social{display:flex;gap:10px;margin-top:4px}
.ft__social a{
  display:grid;place-items:center;width:44px;height:44px;
  border:1px solid var(--line);color:var(--muted);
  transition:border-color .35s var(--ease),color .35s var(--ease);
}
.ft__social a:hover{border-color:var(--copper);color:var(--copper-lt)}
.ft__social svg{width:17px;height:17px;fill:currentColor}
.ft__social-word span{font-size:.62rem;letter-spacing:.12em;text-transform:uppercase}
.ft__bar{
  border-top:1px solid var(--line-soft);padding-block:clamp(15px,1.7vw,19px);
  margin-top:clamp(16px,2vw,24px);
  display:flex;flex-wrap:wrap;gap:10px 24px;justify-content:space-between;
  font-size:.74rem;letter-spacing:.08em;color:var(--muted);
}
.ft__bar a{color:var(--muted)}
.ft__bar a:hover{color:var(--copper-lt)}

/* ==========================================================================
   PAGE BANNER (internal pages)
   ========================================================================== */
.banner{
  position:relative;overflow:clip;isolation:isolate;text-align:center;
  padding-top:calc(var(--nav-h) + clamp(46px,6vw,86px));
  padding-bottom:clamp(46px,6vw,86px);
}
.banner__bg{position:absolute;inset:0;z-index:-2;overflow:clip}
.banner__bg img{width:100%;height:100%;object-fit:cover}
.banner__bg::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(11,12,11,.92),rgba(11,12,11,.72) 50%,rgba(11,12,11,.96));
}
.banner h1{margin-bottom:clamp(12px,1.6vw,18px)}
.banner .lede{margin-inline:auto}
.banner__orn{margin-top:clamp(18px,2.2vw,26px)}

/* ==========================================================================
   MENU PAGES
   ========================================================================== */
.menunav{
  position:sticky;top:var(--nav-h);z-index:60;
  background:rgba(11,12,11,.97);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  border-bottom:1px solid var(--line-soft);
}
.menunav__scroll{
  display:flex;gap:4px;overflow-x:auto;scrollbar-width:none;
  -webkit-overflow-scrolling:touch;scroll-snap-type:x proximity;
  padding-block:6px;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 18px,#000 calc(100% - 18px),transparent);
  mask-image:linear-gradient(90deg,transparent,#000 18px,#000 calc(100% - 18px),transparent);
}
.menunav__scroll::-webkit-scrollbar{display:none}
.menunav a{
  flex:none;scroll-snap-align:center;
  display:inline-flex;align-items:center;min-height:48px;padding:0 16px;
  font-size:.74rem;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);
  border-bottom:1px solid transparent;white-space:nowrap;
  transition:color .3s var(--ease),border-color .3s var(--ease);
}
.menunav a:hover{color:var(--ivory)}
.menunav a.is-active{color:var(--copper-lt);border-bottom-color:var(--copper)}
.menunav__hint{
  display:flex;align-items:center;gap:7px;padding:0 0 8px;
  font-size:.58rem;letter-spacing:.2em;text-transform:uppercase;color:var(--copper);
}
.menunav__hint svg{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;animation:nudge 2.6s var(--ease-out) infinite}
@keyframes nudge{0%,70%,100%{transform:translateX(0)}82%{transform:translateX(4px)}}

.mgroup{padding-block:clamp(36px,4.4vw,66px)}
.mgroup__hd{
  display:flex;align-items:baseline;gap:18px;margin-bottom:clamp(24px,3vw,40px);
}
.mgroup__hd h2{font-size:clamp(1.9rem,3.2vw,3rem);flex:none}
.mgroup__hd i{display:block;flex:1;height:1px;background:var(--line);min-width:20px}
/* house saying beside the heading — two short lines, copper, hard right */
.mgroup__tag{
  flex:none;max-width:24ch;text-align:right;
  font-size:var(--micro);letter-spacing:.16em;text-transform:uppercase;
  color:var(--copper);line-height:1.8;text-wrap:balance;
}
/* below this the heading, rule and saying cannot share a line comfortably —
   let the saying drop underneath rather than crushing a longer course name */
@media (max-width:620px){
  .mgroup__hd{flex-wrap:wrap}
  .mgroup__hd i{order:3;width:100%;flex:0 0 100%}
  .mgroup__tag{order:2;text-align:left;max-width:none;margin-left:auto}
}
.mgroup__note{
  margin:-10px 0 clamp(22px,2.6vw,34px);font-size:.86rem;color:var(--copper-lt);
}
.mlist{display:grid;gap:clamp(24px,2.6vw,36px)}
.mitem{break-inside:avoid;-webkit-column-break-inside:avoid}
.mitem{
  display:grid;grid-template-columns:1fr auto;gap:5px clamp(14px,2vw,26px);
  align-items:baseline;
}
.mitem__name{
  font-family:var(--display);font-size:clamp(1.2rem,1.6vw,1.44rem);font-weight:500;
  line-height:1.22;color:var(--ivory);text-transform:none;letter-spacing:.01em;
}
.mitem__price{
  font-family:var(--body);font-weight:400;font-size:.98rem;letter-spacing:.04em;
  color:var(--copper-lt);white-space:nowrap;font-variant-numeric:tabular-nums;
  justify-self:end;
}
.mitem__desc{
  grid-column:1/-1;font-size:.92rem;line-height:1.66;color:var(--muted);max-width:60ch;
}
.mitem__tags{grid-column:1/-1;display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
.mitem__tags span{
  font-size:.58rem;letter-spacing:.18em;text-transform:uppercase;color:var(--copper);
  border:1px solid var(--line);padding:4px 9px;
}

/* A list of names with no prices and no descriptions — the cocktails. Without
   a second column of figures to anchor the eye, the names have to carry the
   rhythm themselves: a little larger than a dish name, a hairline under each
   one so the row still reads as an entry rather than a paragraph of nouns,
   and tighter spacing than the food menu because there is nothing under the
   name to separate. */
.mlist--names{gap:0}
.mlist--names .mitem{
  padding-block:clamp(13px,1.5vw,17px);
  border-bottom:1px solid var(--line-soft);
}
.mlist--names .mitem__name{
  font-size:clamp(1.3rem,1.75vw,1.6rem);font-weight:500;
}

/* fleuron centred on the column rule. Hidden below the two-column breakpoint,
   where there is no rule to sit on. */
.mlist__wrap{position:relative}
.mlist__mark{
  display:none;position:absolute;left:50%;top:50%;z-index:2;
  width:34px;height:34px;margin:-17px 0 0 -17px;
  background:var(--sec-bg,var(--bg));
  color:var(--copper);
}
.mlist__mark::before{
  content:"";position:absolute;inset:11px;border:1px solid currentColor;transform:rotate(45deg);
}
.sec--alt{--sec-bg:var(--bg-2)}
.sec--surface{--sec-bg:var(--surface-2)}

/* ---------- continue to the next course ---------- */
.contlink{
  display:flex;flex-direction:column;align-items:center;gap:9px;
  margin-top:clamp(22px,2.6vw,34px);padding-block:12px;
  font-size:.66rem;letter-spacing:.26em;text-transform:uppercase;color:var(--muted);
  transition:color .3s var(--ease);
}
.contlink:hover{color:var(--copper-lt)}
.contlink svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;transition:transform .35s var(--ease-out)}
.contlink:hover svg{transform:translateY(3px)}

/* ---------- full-bleed photo interlude between courses ---------- */
/* clip, not hidden — the two photos are scaled up for the scroll drift and
   would otherwise spill past the page edge, and `hidden` here would make this
   a scroll container and stall the drift's timeline */
.interlude{position:relative;display:grid;grid-template-columns:1fr 1fr;background:var(--bg-2);overflow:clip}
.interlude img{width:100%;height:100%;object-fit:cover;
  aspect-ratio:1/1;min-height:clamp(220px,30vw,430px)}
.interlude__cap{
  position:absolute;right:clamp(12px,2vw,30px);top:50%;z-index:2;
  transform:translateY(-50%) rotate(180deg);writing-mode:vertical-rl;
  font-size:.6rem;letter-spacing:.24em;text-transform:uppercase;color:var(--copper-lt);
  text-shadow:0 2px 14px rgba(11,12,11,.9);
  max-height:88%;overflow:hidden;white-space:nowrap;
}
.interlude::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,rgba(11,12,11,.2),rgba(11,12,11,0) 22%,rgba(11,12,11,0) 72%,rgba(11,12,11,.6));
}

/* ---------- "taking it to go?" panel ---------- */
.togo{
  display:grid;gap:clamp(22px,3vw,44px);align-items:center;
  border:1px solid var(--line);background:var(--surface-2);
  padding:clamp(26px,3.4vw,46px);margin-top:clamp(40px,5vw,72px);
}
.togo__art{display:none;color:var(--copper);opacity:.85}
.togo__art svg{width:100%;height:auto;max-width:190px;fill:none;stroke:currentColor;
  stroke-width:1.15;stroke-linecap:round;stroke-linejoin:round}
.togo__body h2,.togo__body h3{font-size:clamp(1.5rem,2.4vw,2.2rem);margin-bottom:12px}
.togo__body p{font-size:.95rem;margin-bottom:clamp(18px,2.2vw,26px)}
@media (min-width:760px){
  .togo{grid-template-columns:auto 1px 1fr;padding-inline:clamp(34px,4vw,60px)}
  .togo__art{display:block}
  .togo__rule{background:var(--line);align-self:stretch;min-height:150px}
}

.msource{
  margin-top:clamp(34px,4vw,56px);padding:clamp(20px,2.4vw,30px);
  border:1px solid var(--line-soft);background:var(--surface-2);
  font-size:.82rem;color:var(--muted);
}
.msource strong{color:var(--copper-lt);font-weight:400;letter-spacing:.06em}
.msource p{font-size:.82rem;max-width:80ch}
.msource p + p{margin-top:.7em}

/* honest preview state for unverified menus */
.pending{
  border:1px solid var(--line);background:var(--surface-2);
  padding:clamp(26px,3.4vw,48px);text-align:center;
}
.pending .eyebrow{margin-bottom:12px}
.pending h3{font-size:clamp(1.4rem,2.4vw,2rem);margin-bottom:14px}
.pending p{margin-inline:auto;font-size:.95rem}
.pending__actions{margin-top:clamp(22px,2.6vw,32px);display:flex;flex-wrap:wrap;gap:12px;justify-content:center}
.pending__known{
  margin-top:clamp(26px,3vw,38px);padding-top:clamp(22px,2.6vw,30px);
  border-top:1px solid var(--line-soft);
}
.pending__subhd{
  font-family:var(--body);font-size:var(--micro);font-weight:400;letter-spacing:.26em;
  text-transform:uppercase;color:var(--copper-lt);margin-bottom:16px;
}
.namelist{display:grid;gap:0}
.namelist li{
  padding-block:13px;border-bottom:1px solid rgba(73,55,42,.3);
  font-family:var(--display);font-size:clamp(1.1rem,1.45vw,1.3rem);color:var(--ivory);
  text-align:left;text-transform:none;font-weight:500;
}
.namelist li:last-child{border-bottom:0}

/* ==========================================================================
   LOADING SCREEN
   The client's shield mark on a black gradient, shown while the page arrives.

   Three rules govern it, in this order of importance:
   1. It NEVER shows without JavaScript. The default is display:none and only
      the .js class — set by an inline script in <head>, before first paint —
      turns it on. If the script never runs, there is no black screen to be
      stuck behind.
   2. It removes itself even if the JavaScript that dismisses it fails. The
      failsafe keyframe below fires on a 4s delay and hides it regardless. A
      visitor must never be trapped by a decoration.
   3. It shows once per session. The head script reads sessionStorage and adds
      .wh-seen, so moving between pages does not replay it — the loader is a
      front door, not a toll booth.
   ========================================================================== */
/* The element also carries the `hidden` attribute in the markup, so if this
   stylesheet ever fails to arrive the browser keeps the loader hidden instead
   of rendering a page-wide inline logo. An author rule beats the UA rule for
   [hidden], so the line below still shows it when the CSS is present. */
.wh-load{display:none}
.js .wh-load{
  display:grid;place-items:center;
  position:fixed;inset:0;z-index:400;
  background:radial-gradient(ellipse at 50% 42%,#1B1713 0%,#0B0C0B 58%,#050605 100%);
  animation:whFailsafe 0s linear 6s forwards;
}
.wh-seen .wh-load{display:none !important}
@keyframes whFailsafe{to{opacity:0;visibility:hidden;pointer-events:none}}

.wh-load__in{display:grid;justify-items:center;gap:clamp(22px,3vw,34px)}
.wh-load__mark{
  width:clamp(112px,15vw,196px);color:var(--ivory);
  /* slow: the mark is the whole point of the screen, so it gets time to be
     read. Paired with MIN in main.js — if you shorten one, shorten both or
     the arc gets cut off mid-rise. */
  animation:whMark 1.5s var(--ease-out) both;
}
.wh-load__mark svg{width:100%;height:auto;display:block}
@keyframes whMark{
  from{opacity:0;transform:translateY(16px) scale(.9)}
  60% {opacity:1}
  to  {opacity:1;transform:none}
}
/* a copper hairline that fills once, left to right, under the mark */
.wh-load__bar{
  width:clamp(104px,13vw,170px);height:1px;background:var(--line);overflow:hidden;
}
.wh-load__bar i{
  display:block;height:100%;background:var(--copper);
  transform:scaleX(0);transform-origin:left;
  animation:whBar 2.2s var(--ease) .45s forwards;
}
@keyframes whBar{to{transform:scaleX(1)}}

/* dismissed by main.js once the page is ready */
.wh-load.is-done{
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .7s var(--ease),visibility 0s .7s;
}

/* ==========================================================================
   CURSOR
   A copper reticle: a hairline crosshair with the house diamond pinned at its
   centre — the same rotated square as the marquee separators, the menu
   fleuron and the hero ornament, so the pointer belongs to the same set of
   marks as everything else on the page.

   Two parts moving at two speeds: the small diamond sits exactly on the
   pointer, and the crosshair eases in behind it. Over anything clickable the
   sight opens from 26px to 58px, which is the whole affordance the system
   cursor was providing.

   The native cursor is hidden by `.crs-on`, a class JAVASCRIPT adds. That is
   deliberate: if the script never runs, the class is never set and the normal
   cursor stays exactly where it was. Hiding it in plain CSS would risk leaving
   somebody with no pointer at all.
   ========================================================================== */
.crs{
  position:fixed;left:0;top:0;z-index:500;pointer-events:none;
  opacity:0;transition:opacity .3s var(--ease);
  mix-blend-mode:screen;
}
.crs.is-live{opacity:1}
.crs i{position:absolute;left:0;top:0;display:block;transform:translate(-50%,-50%) rotate(45deg)}
/* A reticle: two hairlines crossing, with a small open square pinned to the
   exact pointer position. Drawn as two gradients rather than four elements —
   one box, no extra nodes to keep in sync. */
.crs__ring{
  width:26px;height:26px;
  background:
    linear-gradient(var(--copper),var(--copper)) center/1px 100% no-repeat,
    linear-gradient(var(--copper),var(--copper)) center/100% 1px no-repeat;
  transition:width .35s var(--ease-out),height .35s var(--ease-out),
             opacity .35s var(--ease),filter .35s var(--ease);
}
.crs__dot{width:7px;height:7px;border:1px solid var(--copper-lt)}
.crs.is-over .crs__ring{width:58px;height:58px}
.crs.is-over .crs__dot{border-color:var(--ivory)}
.crs.is-down .crs__ring{width:18px;height:18px}


/* only once the script is running, and only for a real pointer */
@media (hover:hover) and (pointer:fine){
  html.crs-on,html.crs-on *{cursor:none}
}
@media (hover:none),(pointer:coarse){
  .crs{display:none}
}

/* ---------- reveal ----------
   Scoped to .js, which the inline snippet in <head> sets before first paint.
   If main.js never loads — blocked, cached wrong, a syntax error — the page
   renders fully visible instead of blank. */
.js [data-rv]{opacity:0;transform:translateY(clamp(26px,3.4vw,46px));
  transition:opacity 1.15s var(--ease-out),transform 1.15s var(--ease-out)}
.js [data-rv].rv-in{opacity:1;transform:none}
.js [data-rv="fade"]{transform:none}
/* Set by the <head> failsafe when main.js never ran. Without it the .js gate
   above would leave a scriptless page blank. */
.rv-off [data-rv]{opacity:1 !important;transform:none !important;clip-path:none !important}

/* The stagger is what makes a section read as a sequence rather than a
   single block arriving. Under ~120ms the eye reads it as one movement, so
   these steps are deliberately wide. Order within a section is the reading
   order: eyebrow, heading, lede, body, button. */
[data-rv-d="0"]{transition-delay:0s}
[data-rv-d="1"]{transition-delay:.13s}
[data-rv-d="2"]{transition-delay:.26s}
[data-rv-d="3"]{transition-delay:.39s}
[data-rv-d="4"]{transition-delay:.52s}
[data-rv-d="5"]{transition-delay:.65s}

/* Text in an editorial band drifts in from the side its photograph is NOT
   on, so the two halves close toward each other. The direction is taken from
   the layout modifier rather than tagged per element, so a band that gets
   flipped in the template picks up the right direction on its own.
   Travel is small and .band is x-clipped below, so nothing can widen the
   page mid-reveal. */
.js .band:not(.band--flip) .band__body [data-rv]:not([data-rv="fade"]){
  transform:translate(clamp(16px,2.2vw,32px),clamp(12px,1.6vw,22px));
}
.js .band--flip .band__body [data-rv]:not([data-rv="fade"]){
  transform:translate(calc(-1 * clamp(16px,2.2vw,32px)),clamp(12px,1.6vw,22px));
}
.js .band .band__body [data-rv].rv-in{transform:none}
.band{overflow-x:clip}

/* Photographs don't slide — they uncover, bottom edge upward, like a curtain
   going up. Deliberately clip-path ONLY: these same images carry the
   scroll-drift animation below, and an animation out-ranks a transition, so
   touching transform here would silently kill the drift. */
.js .band__media[data-rv],
.js .banner__bg[data-rv],
.js .brunch figure[data-rv],
.js .cat[data-rv]{
  opacity:1;transform:none;
  clip-path:inset(0 0 100% 0);
  transition:clip-path 1.3s var(--ease-out);
}
.js .band__media[data-rv].rv-in,
.js .banner__bg[data-rv].rv-in,
.js .brunch figure[data-rv].rv-in,
.js .cat[data-rv].rv-in{clip-path:inset(0 0 0 0)}

/* ---------- scroll drift on the photographs ----------
   The large photographs move a little against the page as they pass through
   the viewport — the same push-in idea as the hero, but tied to scroll
   position instead of a clock, so the picture is always at the same point in
   its travel for a given scroll position and there is nothing to "catch up"
   when you scroll back.

   Done with a scroll-driven animation rather than a scroll listener: it runs
   on the compositor, so it cannot jank the main thread, and there is no JS to
   load or fail. Browsers without `animation-timeline` simply get a still
   photograph, which is why the whole thing sits inside @supports and nothing
   else depends on it.

   scale() is the headroom: the image is blown up 12% so a ±2.2% travel never
   exposes an edge. Keep those two numbers in that ratio if you change them.

   Deliberately NOT applied to:
   - .hero__media img, which has its own one-shot push-in on landing
   - .cat__img img, where an animation would out-rank the hover zoom */
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .band__media img,
    .banner__bg img,
    .interlude img,
    .brunch figure img,
    .resv__bg img{
      animation:photoDrift linear both;
      animation-timeline:view();
      animation-range:entry 0% exit 100%;
      will-change:transform;
    }
    /* --drift is the travel each photo takes; --lift is the headroom that
       stops it exposing an edge. Keep lift comfortably above drift. */
    @keyframes photoDrift{
      from{transform:scale(var(--lift,1.12)) translateY(calc(var(--drift,4%) * -1))}
      to{transform:scale(var(--lift,1.12)) translateY(var(--drift,4%))}
    }

    /* The brunch collage is where this earns its keep: three photographs at
       three speeds, the small squares travelling further and in the opposite
       direction to the tall plate, so they visibly move against each other
       instead of sliding as one sheet. */
    .brunch__sq--a img{--drift:7%;--lift:1.2}
    .brunch__sq--b img{--drift:-6.5%;--lift:1.2}
    .brunch__lead img{--drift:2.5%}

    /* The menu panels drift too, but the movement goes on the WRAPPER, not the
       image — the image already owns transform for its hover zoom, and an
       animation would out-rank it. The wrapper is inset past the panel on both
       edges so its travel never shows a gap; .cat clips the result. */
    .cat__img{
      animation:panelDrift linear both;
      animation-timeline:view();
      animation-range:entry 0% exit 100%;
      inset:-7% 0;
    }
    @keyframes panelDrift{
      from{transform:translateY(-3.4%)}
      to{transform:translateY(3.4%)}
    }
  }
}

/* anchor offset so sticky headers never cover a heading */
[id]{scroll-margin-top:calc(var(--nav-h) + 62px)}

/* ==========================================================================
   RESPONSIVE — min-width enhancements only
   ========================================================================== */
@media (min-width:600px){
  /* minmax(0,1fr), not 1fr: a tall aspect-ratio box reports a min-content
     width, and plain 1fr lets that shrink the column — which opened gaps
     between panels that are supposed to run edge to edge. */
  .cats{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* Brunch collage: the stepped, overlapping arrangement only once there is
   room for it. Below this the section is a plain stack, which is why every
   rule that moves something lives in here and nothing above needs undoing. */
@media (min-width:900px){
  .brunch__art{
    grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);
    grid-template-areas:"a lead" "b lead";
    column-gap:clamp(20px,3vw,48px);
    row-gap:clamp(40px,6vw,104px);
    align-items:start;
  }
  .brunch__art{
    grid-template-areas:"a lead" "b lead" "b note";
    grid-template-rows:auto auto auto;
  }
  .brunch__sq--a{grid-area:a;width:70%;margin-left:3%}
  .brunch__sq--b{grid-area:b;width:58%;margin-left:28%;align-self:end}
  .brunch__lead{grid-area:lead;aspect-ratio:6/7}
  .brunch__note{grid-area:note;width:min(100%,520px);max-width:none}
  .brunch__title{
    position:absolute;z-index:2;left:7%;top:33%;
    width:min(56%,640px);text-align:center;margin:0;
  }
  /* The headline crosses a photo edge, so it carries its own shadow rather
     than a scrim box, which reads as a grey rectangle over the plate. */
  .brunch__title .eyebrow,.brunch__h{text-shadow:0 2px 16px rgba(11,12,11,.92),0 0 40px rgba(11,12,11,.8)}
}

@media (min-width:860px){
  .band{grid-template-columns:1fr 1fr}
  .band--flip .band__media{order:2}
  .band__media img{aspect-ratio:auto;height:100%;min-height:clamp(420px,46vw,620px)}
  /* the copy column keeps a page-edge gutter on its outer side so the text
     lines up with the rest of the site rather than floating mid-screen */
  .band:not(.band--flip) .band__body{
    padding-right:max(var(--gut),calc((100vw - 1280px) / 2 + var(--gut)));
    padding-left:clamp(32px,4.4vw,72px);
  }
  .band--flip .band__body{
    padding-left:max(var(--gut),calc((100vw - 1280px) / 2 + var(--gut)));
    padding-right:clamp(32px,4.4vw,72px);
  }
  .loc__grid{grid-template-columns:1.05fr .95fr}
  /* two columns split by a hairline with a fleuron sitting on it */
  .mlist{
    display:block;columns:2;column-gap:clamp(44px,6vw,96px);
    column-rule:1px solid var(--line-soft);
  }
  .mlist > .mitem{margin-bottom:clamp(24px,2.6vw,36px)}
  .mlist__mark{display:block}
  .menunav__hint{display:none}
}

@media (min-width:1000px){
  :root{--nav-h:88px}
  .navwrap{display:block}
  .nav{display:flex;align-items:center;gap:clamp(18px,2.4vw,42px)}
  .nav > li{position:relative}
  /* Barlow Condensed, same face and weight as the buttons — the nav was the
     one place still set in the body sans, which read as a different system.
     Condensed caps are narrower, so the size goes up and the tracking comes
     in slightly to hold the same optical weight across the bar. */
  .nav > li > a,.nav > li > button{
    display:inline-flex;align-items:center;gap:7px;padding:10px 2px;
    font-family:var(--display);font-weight:600;
    font-size:1.5rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);
    transition:color .3s var(--ease);
  }
  .nav > li > a:hover,.nav > li > button:hover,
  .nav > li > a[aria-current="page"]{color:var(--ivory)}
  .nav > li > a::after{
    content:"";position:absolute;left:0;right:0;bottom:4px;height:1px;background:var(--copper);
    transform:scaleX(0);transform-origin:left;transition:transform .4s var(--ease-out);
  }
  .nav > li > a:hover::after,.nav > li > a[aria-current="page"]::after{transform:scaleX(1)}
  .nav__caret{width:13px;height:13px;fill:none;stroke:currentColor;stroke-width:1.8;
    transition:transform .3s var(--ease)}
  .nav > li > button[aria-expanded="true"] .nav__caret{transform:rotate(180deg)}

  .dropdown{
    position:absolute;top:calc(100% + 10px);left:-18px;min-width:216px;
    background:var(--bg-2);border:1px solid var(--line);
    padding:8px;opacity:0;visibility:hidden;transform:translateY(-8px);
    /* visibility is a discrete property: transitioned plainly it flips halfway
       through, so the first link was still unfocusable when the ArrowDown
       handler tried to focus it. Flip it instantly open, delay it on close. */
    transition:opacity .3s var(--ease),transform .3s var(--ease),visibility 0s linear .3s;
    box-shadow:0 30px 60px -30px #000;
  }
  .nav > li > button[aria-expanded="true"] + .dropdown,
  .dropdown:hover,.dropdown:focus-within{
    opacity:1;visibility:visible;transform:none;
    transition:opacity .3s var(--ease),transform .3s var(--ease),visibility 0s;
  }
  .dropdown a{
    display:block;padding:12px 14px;
    font-family:var(--display);font-weight:500;
    font-size:.92rem;letter-spacing:.14em;
    text-transform:uppercase;color:var(--muted);transition:background .3s var(--ease),color .3s var(--ease);
  }
  .dropdown a:hover,.dropdown a:focus-visible{background:rgba(173,116,69,.12);color:var(--ivory)}

  .burger{display:none}
  .mbar{display:none}
  .hdr__cta > .btn{display:inline-flex}
  .drawer{display:none}
  body{padding-bottom:0}
  .mgroup__hd{gap:26px}
}

/* space for the fixed mobile bar so it never covers page content */
@media (max-width:999px){
  body{padding-bottom:calc(var(--bar-h) + env(safe-area-inset-bottom))}
  .menunav{top:calc(var(--nav-h) - 1px)}
  /* lift the scroll cue clear of the fixed action bar, which owns the bottom
     of the screen on phones */
  .hero__cue{bottom:calc(var(--bar-h) + env(safe-area-inset-bottom) + clamp(14px,2.4vh,26px))}
}

@media (pointer:coarse),(max-width:999px){
  .loc__row a,.msource a,.hours a{display:inline-block;padding-block:10px}
  .ft__links a{padding-block:12px}
}

/* ---------- motion ---------- */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important;
  }
  /* clip-path is listed because the photo reveals uncover with it rather than
     move — without this they would sit permanently clipped to nothing. */
  .js [data-rv],[data-rv]{opacity:1;transform:none;clip-path:none !important}
  /* The blanket rule above would collapse the hero push-in to 0.001ms and snap
     it straight to the zoomed crop. Hold it still instead. */
  .hero__media img{animation:none !important;transform:none !important}
  /* A marquee is motion by definition — stop it and let the row scroll by hand
     rather than flickering through the whole loop in a millisecond. */
  .mq__track{animation:none !important;transform:none !important}
  .mq{overflow-x:auto}
  .mq__run[aria-hidden="true"]{display:none}
  .cat:hover .cat__img img{transform:none}
  /* A loading screen is motion by definition, and it delays content. With
     reduced motion asked for, skip it entirely rather than animate it faster. */
  .js .wh-load{display:none !important}
  /* a cursor that lags behind the pointer is motion; give the system one back */
  .crs{display:none !important}
  html.crs-on,html.crs-on *{cursor:auto !important}
  /* the colour change is not motion, so it stays; the movement does not */
  .cat:hover .cat__body,.cat:focus-visible .cat__body{transform:none}
  .cat:hover .cat__ghost,.cat:focus-visible .cat__ghost{transform:none}
  /* belt and braces — the drift is already gated on no-preference */
  .band__media img,.banner__bg img,.interlude img,
  .brunch figure img,.resv__bg img,
  .cat__img{animation:none !important;transform:none !important}
  .cat__img{inset:0 !important}
}

@media print{
  .hdr,.mbar,.drawer,.hero__cue,.menunav,.loc__map{display:none !important}
  body{background:#fff;color:#111}
  .mitem__name,.loc__row p{color:#111}
  .mitem__desc,p{color:#333}
}
