/* Four Beans — homepage
   Two palettes, one brand. NIGHT is the film's own world and the approved default.
   DAY is the same shop at 10am: warm cream, espresso ink, the gold pulled deeper so
   it still reads as type on a light ground.

   Every themed rule uses the semantic tokens below, never a raw colour. Four scopes
   assign them:
     :root[data-theme]  → the visitor's chosen theme
     .reel              → always NIGHT. The film is watched in the dark, in both themes.
     .brandbar          → NIGHT while it floats over the film, themed once it goes solid.
     .foot              → always the OPPOSITE of the page. The inversion is the point.   */

:root{
  /* ── palette: night ── */
  --n-bg:        #080605;        /* page black, warmed */
  --n-surface:   #0d0707;        /* the mark's own background */
  --n-accent:    #d0b294;        /* sampled from the mark */
  --n-accent-lt: #d0b294;        /* gold where it needs to glow */
  --n-text:      #efdcc4;
  --n-text-2:    #a68e74;        /* quiet type — 6:1 on the page black */
  --n-hairline:  #6d5a48;
  --n-map: grayscale(1) invert(.92) contrast(.86) sepia(.35) hue-rotate(346deg) saturate(1.4) brightness(.92);
  --n-img-dim:   .88;            /* images sit under the page black */
  --n-line-rgb:  208,178,148;    /* borders are gold at low alpha */
  --n-bar-rgb:   9,7,6;

  /* ── palette: day ── */
  --d-bg:        #efe6d9;        /* warm cream, tinted toward the brand gold */
  --d-surface:   #e6dac7;
  --d-accent:    #7d5a2b;        /* deep antique gold — 5:1 on the cream */
  --d-accent-lt: #b4894e;        /* brighter gold, decoration only */
  --d-text:      #1c1310;        /* espresso, near-black */
  --d-text-2:    #6b5647;
  --d-hairline:  #b9a68e;
  --d-map: grayscale(.45) sepia(.28) contrast(.95) brightness(1.02) saturate(1.05);
  --d-img-dim:   .97;            /* on cream they need almost no holding back */
  --d-line-rgb:  60,42,30;       /* borders are espresso at low alpha */
  --d-bar-rgb:   243,237,228;

  --display: "Bodoni Moda", "Didot", "Bodoni MT", Georgia, serif;
  --util:    "Jost", "Futura", "Century Gothic", system-ui, sans-serif;

  --pad: clamp(1.25rem, 3.5vw, 3rem);
  --ease: cubic-bezier(.22,.61,.36,1);

  /* driven by main.js */
  --p: 0;        /* 0 → 1 across the whole scroll track */
  --open: 0;     /* 0 → 1 title curtain opening */
  --outro: 0;    /* 0 → 1 end card */
  --cue: 1;      /* 1 → 0 scroll prompt */
}

/* the eight tokens every themed rule reads */
.night, :root[data-theme="dark"]{
  --bg:var(--n-bg); --surface:var(--n-surface);
  --accent:var(--n-accent); --accent-lt:var(--n-accent-lt);
  --text:var(--n-text); --text-2:var(--n-text-2);
  --hairline:var(--n-hairline); --img-dim:var(--n-img-dim); --map-filter:var(--n-map);
  --line-rgb:var(--n-line-rgb); --bar-rgb:var(--n-bar-rgb);
  color-scheme:dark;
}
.day, :root[data-theme="light"]{
  --bg:var(--d-bg); --surface:var(--d-surface);
  --accent:var(--d-accent); --accent-lt:var(--d-accent-lt);
  --text:var(--d-text); --text-2:var(--d-text-2);
  --hairline:var(--d-hairline); --img-dim:var(--d-img-dim); --map-filter:var(--d-map);
  --line-rgb:var(--d-line-rgb); --bar-rgb:var(--d-bar-rgb);
  color-scheme:light;
}

/* The film keeps its own world. Nothing about the hero changes with the theme. */
.reel{
  --bg:var(--n-bg); --surface:var(--n-surface);
  --accent:var(--n-accent); --accent-lt:var(--n-accent-lt);
  --text:var(--n-text); --text-2:var(--n-text-2);
  --hairline:var(--n-hairline); --img-dim:var(--n-img-dim); --map-filter:var(--n-map);
  --line-rgb:var(--n-line-rgb); --bar-rgb:var(--n-bar-rgb);
}

/* The footer runs the opposite palette — cream under a black page, black under cream. */
:root[data-theme="dark"] .foot{
  --bg:var(--d-bg); --surface:var(--d-surface);
  --accent:var(--d-accent); --accent-lt:var(--d-accent-lt);
  --text:var(--d-text); --text-2:var(--d-text-2);
  --hairline:var(--d-hairline); --img-dim:var(--d-img-dim); --map-filter:var(--d-map);
  --line-rgb:var(--d-line-rgb); --bar-rgb:var(--d-bar-rgb);
}
:root[data-theme="light"] .foot{
  --bg:var(--n-bg); --surface:var(--n-surface);
  --accent:var(--n-accent); --accent-lt:var(--n-accent-lt);
  --text:var(--n-text); --text-2:var(--n-text-2);
  --hairline:var(--n-hairline); --img-dim:var(--n-img-dim); --map-filter:var(--n-map);
  --line-rgb:var(--n-line-rgb); --bar-rgb:var(--n-bar-rgb);
}

/* Crossfading colour is what makes the switch feel like a dimmer rather than a
   browser setting. Only applied while switching, so nothing pays for it at rest. */
:root.theme-shift,
:root.theme-shift *:not(.film){
  transition:background-color .55s var(--ease),
             border-color .55s var(--ease),
             color .55s var(--ease),
             fill .55s var(--ease);
}

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

/* No scroll-behavior:smooth — the page is ~17,000px tall and the hero is scrubbed
   by scroll position, so an animated jump drags the whole film past at speed. */
html{ background:var(--bg); }

body{
  margin:0;
  background:var(--bg);
  color:var(--text-2);
  font-family:var(--util);
  font-weight:300;
  -webkit-font-smoothing:antialiased;
  overscroll-behavior-y:none;
}

.sr-only{
  position:absolute; width:1px; height:1px; margin:-1px;
  padding:0; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

.skip{
  position:fixed; top:0; left:50%; transform:translate(-50%,-120%);
  z-index:60; padding:.7rem 1.2rem;
  background:var(--accent); color:var(--bg);
  font:400 .75rem/1 var(--util); letter-spacing:.12em; text-transform:uppercase;
  text-decoration:none; transition:transform .2s var(--ease);
}
.skip:focus-visible{ transform:translate(-50%,0); }

:where(a,button,video):focus-visible{
  outline:1px solid var(--text);
  outline-offset:4px;
}

/* ── the scroll track ──────────────────────────────────────────── */

.reel{
  /* The scroll track. Its height is the film's running time — 6.4 screens of scrolling
     for 14 seconds of footage, so roughly 400px of thumb per second of film. */
  height:640vh;
  position:relative;
}

.frame{
  position:sticky; top:0;
  height:100svh;
  overflow:hidden;
  background:var(--bg);
}

.film{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  /* Sits a touch under the brand's own black so the gold stays the brightest thing —
     but lifted while the title curtain is up, or the letterforms read as empty. */
  filter:saturate(.92) contrast(1.06) brightness(calc(.94 + (1 - var(--open)) * .7));
}

/* vignette + floor gradient, so type always has something to sit on */
.veil{
  position:absolute; inset:0; pointer-events:none;
  background:
    radial-gradient(120% 90% at 50% 45%, transparent 32%, rgba(8,6,5,.55) 78%, rgba(8,6,5,.9) 100%),
    linear-gradient(to bottom, rgba(8,6,5,.72) 0%, transparent 24%, transparent 58%, rgba(8,6,5,.88) 100%);
  opacity:calc(.7 + .3 * var(--outro));
}

/* ── title curtain: film visible only through the letterforms ──── */

.curtain{
  position:absolute; inset:0;
  width:100%; height:100%;
  pointer-events:none;
  opacity:calc(1 - var(--open));
}

.cut-word{
  font-family:var(--display);
  font-weight:500;
  /* "4 BEANS" sets about 4.7em wide, so 15vw lands it at roughly 70% of the window */
  font-size:15vw;
  letter-spacing:.06em;
  fill:#000;
}

/* ── brand bar ─────────────────────────────────────────────────────
   Over the film it is nothing but the lockup, fading in on the same
   --open the title curtain uses, so it arrives as part of the reveal
   rather than sitting on top of it. Once the hero is behind you it
   condenses into a glass bar and the links appear.                  */

/* Floating over the film it belongs to the film, so it borrows NIGHT until it lands. */
.brandbar:not(.is-solid){
  --accent:var(--n-accent); --text:var(--n-text); --text-2:var(--n-text-2);
  --line-rgb:var(--n-line-rgb);
}

.brandbar{
  position:fixed; inset:var(--pad) var(--pad) auto;
  z-index:40;
  display:flex; align-items:center; justify-content:space-between; gap:1.5rem;
  padding:.5rem .5rem;
  border:1px solid transparent;
  border-radius:999px;
  opacity:var(--open);
  transform:translateY(calc((1 - var(--open)) * -8px));
  transition:opacity .3s linear, transform .5s var(--ease),
             background-color .5s var(--ease), border-color .5s var(--ease),
             padding .5s var(--ease), backdrop-filter .5s var(--ease);
}
.brandbar.is-solid{
  background:rgba(var(--bar-rgb),.78);
  border-color:rgba(var(--line-rgb),.14);
  backdrop-filter:blur(14px) saturate(1.1);
  -webkit-backdrop-filter:blur(14px) saturate(1.1);
  padding:.5rem .5rem .5rem .75rem;
  /* The solid bar is always fully present. On the film homepage --open has
     already reached 1 by the time the bar goes solid, so this is a no-op there;
     on inner pages (menu, admin) --open is never driven, so without this the
     bar would sit permanently at opacity:0. */
  opacity:1;
  transform:none;
}

/* Pages that open on a hero instead of the title film. There is no curtain
   here to fade the bar in behind, and no title sequence to defer to, so the
   bar is present from the first paint and keeps its links while it rides over
   the picture — chrome-less until the hero scrolls away. Stated in CSS so it
   holds even if the script never runs. */
.brandbar.on-hero{ opacity:1; transform:none; }
.brandbar.on-hero .barnav{ opacity:1; transform:none; pointer-events:auto; }

.lockup{
  display:flex; align-items:center; gap:.8rem;
  text-decoration:none;
  flex:0 0 auto;
}
.lockup-mark{
  width:auto; height:clamp(34px,3.6vw,46px); display:block;
  transition:height .5s var(--ease);
}
.lockup-name{
  font-family:var(--display); font-weight:400;
  font-size:clamp(.9rem,1.2vw,1.1rem);
  letter-spacing:.34em;
  text-transform:uppercase;
  color:var(--accent);
  padding-top:.15em;
  transition:color .3s var(--ease);
}
.lockup:hover .lockup-name{ color:var(--text); }

.barnav{
  display:flex; gap:.35rem;
  opacity:0; transform:translateY(-4px);
  transition:opacity .55s var(--ease), transform .55s var(--ease);
  pointer-events:none;
}
.brandbar.is-solid .barnav{ opacity:1; transform:none; pointer-events:auto; }

.barnav a{
  position:relative;
  padding:.5rem .95rem;
  font-size:.72rem; letter-spacing:.2em; text-transform:uppercase;
  color:var(--text-2); text-decoration:none;
  border-radius:999px;
  transition:color .3s var(--ease), background-color .3s var(--ease);
}
.barnav a:hover{ color:var(--text); }
.barnav a[aria-current]{
  color:var(--text);
  background:rgba(var(--line-rgb),.09);
}

.barcta{
  flex:0 0 auto;
  padding:.6rem 1.3rem;
  border:1px solid rgba(var(--line-rgb),.35);
  border-radius:999px;
  font-size:.72rem; letter-spacing:.2em; text-transform:uppercase;
  color:var(--accent); text-decoration:none;
  transition:color .3s var(--ease), border-color .3s var(--ease), background-color .3s var(--ease);
}
.barcta:hover{ color:var(--bg); background:var(--accent); border-color:var(--accent); }

/* ── menu submenu ──────────────────────────────────────────────── */
.nav-has-sub{ position:relative; }

/* Invisible hover bridge — closes the gap between trigger and panel */
.nav-has-sub::after{
  content:'';
  position:absolute; top:100%;
  left:-16px; right:-16px;
  height:16px;
}

.nav-sub-chevron{
  display:inline-block;
  width:0; height:0;
  border-left:3px solid transparent;
  border-right:3px solid transparent;
  border-top:3px solid currentColor;
  margin-left:.4em;
  vertical-align:middle;
  opacity:.35;
  transition:transform .3s var(--ease), opacity .3s var(--ease);
}
.nav-has-sub:hover .nav-sub-chevron,
.nav-has-sub:focus-within .nav-sub-chevron{
  transform:rotate(180deg); opacity:.75;
}

.nav-sub{
  position:absolute;
  top:calc(100% + 16px); left:50%;
  transform:translateX(-50%) translateY(6px);
  min-width:190px;
  padding:.4rem 0 .55rem;
  background:rgba(var(--bar-rgb),.97);
  border:1px solid rgba(var(--line-rgb),.16);
  backdrop-filter:blur(18px) saturate(1.1);
  -webkit-backdrop-filter:blur(18px) saturate(1.1);
  opacity:0; pointer-events:none;
  transition:opacity .24s var(--ease), transform .24s var(--ease);
  z-index:1;
}
.nav-has-sub:hover .nav-sub,
.nav-has-sub:focus-within .nav-sub{
  opacity:1; transform:translateX(-50%) translateY(0);
  pointer-events:auto;
}
/* thin gold rule at the very top of the panel */
.nav-sub::before{
  content:'';
  display:block; height:1px;
  background:linear-gradient(to right, transparent, var(--accent), transparent);
  opacity:.45; margin-bottom:.38rem;
}

.nav-sub-all{
  display:block;
  padding:.42rem 1.1rem .48rem;
  font-family:var(--util); font-size:.64rem;
  letter-spacing:.22em; text-transform:uppercase;
  color:var(--accent); text-decoration:none;
  border-bottom:1px solid rgba(var(--line-rgb),.1);
  margin-bottom:.28rem;
  opacity:0; transform:translateY(4px);
  transition:opacity .2s var(--ease), transform .2s var(--ease), color .25s var(--ease);
}
.nav-has-sub:hover .nav-sub-all,
.nav-has-sub:focus-within .nav-sub-all{ opacity:1; transform:none; }
.nav-sub-all:hover{ color:var(--text); }

.nav-sub-item{
  display:flex; align-items:baseline; gap:.6rem;
  padding:.34rem 1.1rem;
  text-decoration:none; color:var(--text-2);
  opacity:0; transform:translateY(4px);
  transition:
    opacity .2s var(--ease) var(--sub-delay,0ms),
    transform .2s var(--ease) var(--sub-delay,0ms),
    color .25s var(--ease),
    background-color .25s var(--ease);
}
.nav-has-sub:hover .nav-sub-item,
.nav-has-sub:focus-within .nav-sub-item{ opacity:1; transform:none; }
.nav-sub-item:hover{ color:var(--text); background:rgba(var(--line-rgb),.06); }

.nav-sub-n{
  font-family:var(--util); font-size:.55rem;
  letter-spacing:.16em; color:var(--accent);
  flex:0 0 auto; line-height:1;
}
.nav-sub-name{
  font-family:var(--util); font-size:.68rem;
  letter-spacing:.14em; text-transform:uppercase; line-height:1.3;
}

/* ── drawer category sub-links ─────────────────────────────────── */
.drawer-cats{ padding:.05rem 0 .15rem; }

/* mobile toggle */
.barmenu{
  display:none;
  width:44px; height:44px; padding:0;
  background:none; border:0; cursor:pointer;
}
.barmenu span{
  display:block; width:22px; height:1px; margin:5px auto;
  background:var(--accent);
  transition:transform .35s var(--ease), opacity .35s var(--ease);
}
.barmenu[aria-expanded="true"] span:first-child{ transform:translateY(3px) rotate(45deg); }
.barmenu[aria-expanded="true"] span:last-child{ transform:translateY(-3px) rotate(-45deg); }

.drawer{
  position:fixed; inset:0; z-index:39;
  display:flex; flex-direction:column; justify-content:center; gap:.4rem;
  padding:calc(var(--pad) + 4rem) var(--pad) var(--pad);
  background:rgba(var(--bar-rgb),.97);
  backdrop-filter:blur(18px);
  -webkit-backdrop-filter:blur(18px);
  overflow-y:auto;
  opacity:0; transition:opacity .4s var(--ease);
}
.drawer[hidden]{ display:none; }
.drawer.is-open{ opacity:1; }
.drawer a{
  padding:.7rem 0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(1.6rem,7vw,2.2rem);
  letter-spacing:.02em;
  color:var(--accent); text-decoration:none;
  border-bottom:1px solid rgba(var(--line-rgb),.12);
  /* sequential entrance: each link starts hidden and slides up */
  opacity:0;
  transform:translateY(10px);
  transition:opacity .38s var(--ease), transform .38s var(--ease), color .3s var(--ease);
}
.drawer.is-open a{ opacity:1; transform:none; }
/* stagger each link by 60ms so they cascade down */
/* ── the Menu row: one line, two targets ──────────────────────────
   The word and the chevron are separate controls with separate jobs, so the
   rule that reads as "the Menu row" sits on the row, not on the link. */
.drawer-row{
  display:flex; align-items:center; gap:1rem;
  border-bottom:1px solid rgba(var(--line-rgb),.12);
  /* the row enters with the links around it */
  opacity:0; transform:translateY(10px);
  transition:opacity .38s var(--ease), transform .38s var(--ease);
}
.drawer.is-open .drawer-row{ opacity:1; transform:none; }
.drawer .drawer-row > a{
  flex:1 1 auto;
  border-bottom:0;
  opacity:1; transform:none;      /* the row owns the entrance now */
}

.drawer-toggle{
  flex:0 0 auto;
  /* a comfortable thumb target that still reads as a hairline mark */
  width:48px; height:48px;
  display:grid; place-items:center;
  margin:0; padding:0;
  background:none; border:0; cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.drawer-toggle i{
  display:block; width:8px; height:8px;
  border-right:1px solid var(--accent);
  border-top:1px solid var(--accent);
  transform:rotate(45deg);                 /* › closed */
  transform-origin:60% 40%;
  opacity:.7;
  transition:transform .4s var(--ease), opacity .3s var(--ease);
}
.drawer-toggle[aria-expanded="true"] i{
  transform:rotate(135deg);                /* ⌄ open */
  opacity:1;
}
.drawer-toggle:focus-visible{ outline:1px solid var(--accent); outline-offset:-6px; }

/* ── the categories, revealed ─────────────────────────────────────
   0fr → 1fr animates to the content's real height, so nothing has to guess a
   max-height that later breaks when a category is added in the admin. */
.drawer-sub{
  display:grid;
  grid-template-rows:0fr;
  transition:grid-template-rows .42s var(--ease);
}
.drawer-sub.is-open{ grid-template-rows:1fr; }
.drawer-sub-inner{
  overflow:hidden;
  /* keeps collapsed links out of the tab order until they are actually shown */
  visibility:hidden;
  transition:visibility 0s .42s;
}
.drawer-sub.is-open .drawer-sub-inner{ visibility:visible; transition-delay:0s; }

/* category links — must beat .drawer a specificity */
.drawer .drawer-sub a{
  display:block;
  padding:.5rem 0 .5rem 1.15rem;
  font-family:var(--util);
  font-size:clamp(.72rem,2.4vw,.8rem);
  letter-spacing:.16em; text-transform:uppercase;
  color:var(--accent); text-decoration:none;
  border-bottom:0;
  opacity:0; transform:translateY(6px);
  transition:opacity .3s var(--ease), transform .3s var(--ease), color .3s var(--ease);
}
/* they cascade in only once the row has opened */
.drawer-sub.is-open a{
  opacity:.62; transform:none;
  transition-delay:var(--dc-delay,0ms);
}
.drawer-sub.is-open a:hover,
.drawer-sub.is-open a:focus-visible{ opacity:1; color:var(--text); }
/* the first category sits under a short gold tick, tying it to the row above */
.drawer .drawer-sub a:first-child{ position:relative; }
.drawer .drawer-sub a:first-child::before{
  content:""; position:absolute; left:0; top:0; bottom:0;
  width:1px; background:linear-gradient(var(--accent), transparent);
  opacity:.4;
}

/* stagger the top-level rows; nth-child covers links and the Menu row alike */
.drawer.is-open > :nth-child(1){ transition-delay:.06s; }
.drawer.is-open > :nth-child(2){ transition-delay:.12s; }
.drawer.is-open > :nth-child(3){ transition-delay:.18s; }
.drawer.is-open > :nth-child(4){ transition-delay:.24s; }
.drawer.is-open > :nth-child(5){ transition-delay:.30s; }
.drawer.is-open > :nth-child(6){ transition-delay:.36s; }
.drawer.is-open > :nth-child(7){ transition-delay:.42s; }
.drawer.is-open > :nth-child(8){ transition-delay:.48s; }
/* the sub-panel is not part of that cascade — it opens on demand */
.drawer.is-open > .drawer-sub{ transition-delay:0s; }
.drawer > a:last-child{ border-bottom:0; }

/* ── stage rail ────────────────────────────────────────────────── */

.rail{
  position:absolute; right:var(--pad); top:50%;
  transform:translateY(-50%);
  display:flex; align-items:center; gap:1.1rem;
  opacity:calc(var(--open) * (1 - var(--outro)));
}
.rail ol{
  list-style:none; margin:0; padding:0;
  display:flex; flex-direction:column; gap:1.35rem;
  text-align:right;
}
.rail li span{
  display:block;
  font-size:.68rem; letter-spacing:.3em; text-transform:uppercase;
  color:var(--text-2);
  transition:color .35s var(--ease), opacity .35s var(--ease);
  opacity:.85;
}
.rail li[data-on] span{ color:var(--text); opacity:1; }

.rail-line{
  position:relative; width:1px; align-self:stretch;
  background:linear-gradient(to bottom, transparent, var(--hairline) 12%, var(--hairline) 88%, transparent);
}
.rail-line i{
  position:absolute; left:-1px; top:0; width:3px;
  background:var(--text);
  height:0%;
  box-shadow:0 0 12px rgba(var(--line-rgb),.7);
}

/* ── scroll cue ────────────────────────────────────────────────── */

.cue{
  position:absolute; left:50%; bottom:calc(var(--pad) + .4rem);
  transform:translateX(-50%);
  margin:0;
  font-size:.68rem; letter-spacing:.42em; text-transform:uppercase;
  color:var(--accent);
  /* present from the first frame — it is the only instruction on the page */
  opacity:calc(var(--cue) * .85);
}
.cue span{ display:inline-block; animation:breathe 2.6s var(--ease) infinite; }
.cue::after{
  content:""; display:block; width:1px; height:34px; margin:.7rem auto 0;
  background:linear-gradient(var(--accent), transparent);
}
@keyframes breathe{ 0%,100%{ opacity:.45; } 50%{ opacity:1; } }

/* ── end card ──────────────────────────────────────────────────── */

.end{
  position:absolute; inset:auto 0 0 0;
  padding:0 var(--pad) clamp(3rem,10vh,6.5rem);
  text-align:center;
  opacity:var(--outro);
  transform:translateY(calc((1 - var(--outro)) * 26px));
  pointer-events:none;
}
.end-line{
  margin:0;
  font-family:var(--display);
  font-size:clamp(1.35rem,3.4vw,2.6rem);
  font-weight:400;
  letter-spacing:.04em;
  color:var(--text);
}
.end-est{
  margin:1.15rem 0 0;
  font-size:.7rem; letter-spacing:.42em; text-transform:uppercase;
  color:var(--text-2);
}
.end-anchor{
  position:absolute; left:0; bottom:0; width:1px; height:1px;
}

.end-est::before{
  content:""; display:block; width:44px; height:1px; margin:0 auto 1.15rem;
  background:var(--hairline);
}

/* ════════════════════════════════════════════════════════════════
   BELOW THE FILM
   One reveal language for the whole page: everything with .reveal
   rises 18px and fades over 900ms, staggered by --i. Nothing else
   animates on scroll, so the page reads as one continuous take.
   ════════════════════════════════════════════════════════════════ */

/* Reveals hide themselves ONLY once JS has confirmed it is running and watching.
   `html.js-reveal` is set by the inline head script. Without it — script blocked,
   observer never fires, anything scrolled past before the callback lands — the
   content is simply visible. A reveal is decoration; legibility never waits on it.
   This is what left the footer wordmark at opacity 0. */
.js-reveal .reveal{
  opacity:0;
  transform:translateY(18px);
  transition:opacity .9s var(--ease), transform .9s var(--ease);
  transition-delay:calc(var(--i, 0) * 90ms);
}
.js-reveal .reveal.is-in{ opacity:1; transform:none; }

.chapter{
  position:relative;
  padding:clamp(6rem,14vh,11rem) var(--pad);
  max-width:1440px;
  margin-inline:auto;
  /* clears the fixed bar when a nav link jumps here */
  scroll-margin-top:clamp(84px,11vh,116px);
}
/* a hairline where each chapter starts — the only divider on the page */
.chapter + .chapter::before{
  content:""; position:absolute; top:0; left:var(--pad); right:var(--pad);
  height:1px; background:rgba(var(--line-rgb),.13);
}

.chead{ max-width:44rem; margin-bottom:clamp(3rem,7vh,5.5rem); }

.eyebrow{
  display:flex; align-items:center; gap:.9rem;
  margin:0 0 1.4rem;
  font-size:.68rem; letter-spacing:.4em; text-transform:uppercase;
  color:var(--text-2);
}
.eyebrow::before{
  content:""; width:clamp(24px,4vw,52px); height:1px;
  background:var(--accent); flex:0 0 auto;
}

/* ── section headings ──────────────────────────────────────────────
   Bodoni Moda, light, large. The shop's mark is a Didone and so are its
   headings; Jost stays on labels, prices and body copy. */

.chead-h{
  margin:0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(2.6rem,7vw,5.5rem);
  line-height:.98; letter-spacing:-.01em;
  color:var(--text);
  /* a long word breaks rather than pushing the page sideways */
  overflow-wrap:break-word;
}
.chead-sub{
  margin:1.5rem 0 0;
  max-width:34rem;
  font-size:clamp(.95rem,1.15vw,1.05rem); line-height:1.65;
  color:var(--text-2);
}
.stars{ color:var(--accent); letter-spacing:.14em; margin-right:.5rem; }

/* ── menu page ──────────────────────────────────────────────────── */

.menu-page .chead{ margin-bottom:clamp(2rem,5vh,3.5rem); }

/* card-link: invisible overlay that makes the whole card a keyboard/click target */
.card{ position:relative; }
.card-link{
  position:absolute; inset:0; display:block;
  border-radius:inherit; z-index:1;
  /* it is an <a> on the menu grid and a <button> on the landing page — both
     are invisible hit areas, so strip the button chrome */
  appearance:none; background:none; border:0; padding:0;
  cursor:pointer;
}
.card-link:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; }

/* category filter bar */
/* Category index. Capsules with a solid fill on the active one read as generic
   UI and put a heavy blob in the middle of a very quiet page. This is the same
   device the hero's frame index uses — a label with a gold rule drawn under
   the live one — so the two rows on this page speak the same language. */
.filter-bar{
  display:flex; flex-wrap:wrap;
  column-gap:clamp(1.1rem,3.5vw,2rem);
  row-gap:.15rem;
  margin-bottom:clamp(2.5rem,6vh,4rem);
}
.filter-btn{
  position:relative;
  appearance:none; background:none; border:0; cursor:pointer;
  display:inline-flex; align-items:center;
  min-height:44px;                 /* comfortable to tap without looking chunky */
  padding:0 0 .15rem;
  font-family:var(--util);
  font-size:.68rem; letter-spacing:.2em; text-transform:uppercase;
  color:var(--text-2);
  transition:color .3s var(--ease);
}
/* the track every label rests on */
.filter-btn::after{
  content:""; position:absolute; left:0; right:0; bottom:.35rem; height:1px;
  background:rgba(var(--line-rgb),.2);
}
/* and the gold rule that marks the live one */
.filter-btn::before{
  content:""; position:absolute; left:0; right:0; bottom:.35rem; height:1px;
  background:var(--accent); z-index:1;
  transform:scaleX(0); transform-origin:left center;
  transition:transform .4s var(--ease);
}
.filter-btn:hover{ color:var(--text); }
.filter-btn[aria-pressed="true"]{ color:var(--text); }
.filter-btn[aria-pressed="true"]::before{ transform:scaleX(1); }
.filter-btn:focus-visible{ outline:1px solid var(--accent); outline-offset:4px; }

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

/* product detail dialog */
#product-dialog{
  /* A modal <dialog> must be fixed to the viewport and centred there, so it
     appears in front of wherever the reader is — not anchored to the top of
     the document. inset:0 + margin:auto does the centring; position:fixed is
     also the containing block the absolutely-positioned close button needs. */
  position:fixed; inset:0; margin:auto;
  border:none; padding:0;
  background:var(--surface); color:var(--text);
  max-width:min(760px,96vw); width:100%;
  /* The card itself never scrolls. If it did, .detail-close — which is
     positioned against this box — would scroll away with the content and
     strand the reader in a modal with no visible way out. Overflow is the
     body's job instead, so the X stays put at every size and orientation. */
  max-height:90dvh; overflow:hidden;
  display:grid; grid-template-columns:1fr 1fr;
  border-radius:4px;
  box-shadow:0 24px 80px rgba(0,0,0,.5);
}
/* A native <dialog> is display:none until opened, but the ID rule above
   (display:grid) outranks the UA's dialog:not([open]){display:none}, so the
   CLOSED dialog was rendering in normal flow just above the footer — the
   "bottom card stuck to the footer". Restore the closed = hidden contract. */
#product-dialog:not([open]){ display:none; }
#product-dialog::backdrop{
  background:rgba(0,0,0,.65);
  backdrop-filter:blur(6px);
}
/* height:auto lets CSS aspect-ratio override the HTML height attribute on the img */
.detail-img-wrap img{ width:100%; height:auto; aspect-ratio:4/5; object-fit:cover; display:block; }
.detail-body{
  padding:clamp(1.5rem,4vw,3rem) clamp(1.5rem,3vw,2.5rem);
  display:flex; flex-direction:column; gap:1rem;
  /* "safe" centring: centred while the content fits, but falls back to the
     start once it overflows — plain centre alignment pushes the first line
     out of the scroll container's reachable area. Browsers without `safe`
     drop the declaration and land on flex-start, which is the same outcome. */
  justify-content:safe center;
  /* min-height:0 lets this grid child shrink below its content so the scroll
     actually engages here rather than pushing the card past its max-height. */
  min-height:0;
  overflow-y:auto;
  overscroll-behavior:contain;   /* a flick at the end must not scroll the page */
}
.detail-cat{
  font-size:.72rem; letter-spacing:.13em; text-transform:uppercase;
  color:var(--text-2); margin:0;
}
.detail-name{
  font-family:'Bodoni Moda',serif; font-size:clamp(1.5rem,2.8vw,2.2rem);
  font-weight:400; margin:0; line-height:1.15;
}
.detail-desc{ color:var(--text-2); line-height:1.75; margin:0; font-size:.95rem; }
.detail-price{ font-size:1.05rem; color:var(--accent); margin:0; }
/* When no discount, the direct text nodes use these rules */
.detail-price>span:first-child:only-of-type{ font-size:.78em; margin-right:.2em; }
.detail-close{
  position:absolute; top:.75rem; right:.75rem; z-index:2;
  background:rgba(var(--bar-rgb),.75); border:none; cursor:pointer; color:var(--text);
  font-size:1rem; line-height:1;
  /* 44×44px minimum touch target */
  min-width:44px; min-height:44px;
  display:flex; align-items:center; justify-content:center;
  border-radius:50%;
  opacity:.85; transition:opacity .15s;
}
.detail-close:hover{ opacity:1; }

/* The one real action in the shop: there is no cart, you order at the counter.
   Same retracting rule as .row-cta so it is the brand's button, not a button. */
.detail-cta{
  align-self:start;
  position:relative;
  margin-top:.35rem;
  padding-bottom:.45rem;
  font-family:var(--util);
  font-size:.7rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--text); text-decoration:none;
  transition:color .3s var(--ease);
}
.detail-cta::after{
  content:""; position:absolute; inset:auto 0 0 0; height:1px;
  background:var(--accent);
  transform:scaleX(1); transform-origin:left center;
  transition:transform .45s var(--ease);
}
.detail-cta:hover{ color:var(--accent); }
.detail-cta:hover::after{ transform:scaleX(.4); }
.detail-cta[hidden]{ display:none; }

.detail-actions{ display:flex; align-items:center; gap:1.1rem; flex-wrap:wrap; }

/* A real button, not the text-link treatment .detail-cta uses — this opens a
   full-screen viewer rather than navigating, so it reads as an action. */
.detail-ar-btn{
  align-self:start;
  margin-top:.35rem;
  padding:.55rem 1.1rem;
  font-family:var(--util);
  font-size:.7rem; letter-spacing:.2em; text-transform:uppercase;
  color:var(--bg); background:var(--accent);
  border:1px solid var(--accent); border-radius:2px;
  cursor:pointer;
  transition:opacity .2s var(--ease);
}
.detail-ar-btn:hover{ opacity:.85; }
.detail-ar-btn[hidden]{ display:none; }

/* ── AR / 3D viewer overlay ── */
#ar-overlay{
  position:fixed; inset:0; z-index:100;
  background:var(--bg);
  display:flex; align-items:center; justify-content:center;
}
#ar-overlay model-viewer{ width:100%; height:100%; --poster-color:transparent; }
.ar-close{
  position:absolute; top:1rem; right:1rem; z-index:2;
  background:rgba(var(--bar-rgb),.75); border:none; cursor:pointer; color:var(--text);
  font-size:1rem; line-height:1;
  min-width:44px; min-height:44px;
  display:flex; align-items:center; justify-content:center;
  border-radius:50%;
  opacity:.85; transition:opacity .15s;
}
.ar-close:hover{ opacity:1; }
.ar-status{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  color:var(--text-2); font-family:var(--util); font-size:.8rem;
  letter-spacing:.08em; text-align:center;
}
.ar-status[hidden]{ display:none; }

/* Only shown once a tier is resolved — tells Tier 1 apart from Tier 3 at a
   glance, since both render as an identical orbiting model until the
   customer actually taps the AR button. */
.ar-hint{
  position:absolute; left:50%; bottom:4.5rem; transform:translateX(-50%);
  color:var(--text); font-family:var(--util); font-size:.75rem;
  letter-spacing:.04em; text-align:center; padding:.5rem 1rem;
  background:rgba(var(--bar-rgb),.65); border-radius:999px; white-space:nowrap;
  pointer-events:none;
}
.ar-hint[hidden]{ display:none; }

body.ar-open{ overflow:hidden; }

@media(max-width:600px){
  /* Same centred, viewport-fixed overlay as desktop — position:fixed, inset:0
     and margin:auto are inherited from the base rule. Only the dimensions and
     the single-column stack adapt to the narrow screen; this is NOT a bottom
     sheet, so mobile and desktop share one interaction model. */
  #product-dialog{
    grid-template-columns:1fr;
    /* The picture keeps its natural height; the body takes what is left and
       scrolls inside it, so the card is bounded but never crops the content. */
    grid-template-rows:auto minmax(0,1fr);
    width:min(90vw,370px);
    max-height:min(84dvh,640px);
    /* 4px, as on desktop — the sharp corner is the brand's language, and a
       16px radius made this read as a generic rounded card. */
    border-radius:4px;
  }
  /* A 5:4 crop rather than a 16:10 strip: the drink is the point of this card,
     and the dvh cap keeps it from crowding out the name and price. */
  .detail-img-wrap img{ aspect-ratio:5/4; max-height:min(32dvh,230px); }
  .detail-body{
    gap:.6rem;
    padding:1.15rem 1.15rem calc(1.3rem + env(safe-area-inset-bottom,0px));
  }
  .detail-name{ font-size:clamp(1.35rem,6vw,1.7rem); }
  .detail-desc{ font-size:.88rem; line-height:1.6; }
  .detail-close{ top:.5rem; right:.5rem; }
  /* Grows the action to a 44px target with padding rather than type size, and
     the extra room above it doubles as the break between reading and acting. */
  .detail-cta{ margin-top:0; padding-top:1.3rem; padding-bottom:.65rem; }
}

/* ── signatures ────────────────────────────────────────────────── */

.cards{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:clamp(1.5rem,3vw,3rem) clamp(1.5rem,2.5vw,2.5rem);
}

.card{ position:relative; }
.card-shot{
  position:relative;
  overflow:hidden;
  background:var(--surface);
  aspect-ratio:4/5;
}
.card-shot img{
  width:100%; height:100%; object-fit:cover; display:block;
  transform:scale(1.001);
  filter:brightness(var(--img-dim)) saturate(.95);
  transition:transform 1.1s var(--ease), filter .7s var(--ease);
}
/* the gold line that draws across the top of the card on hover */
.card-shot::after{
  content:""; position:absolute; inset:auto 0 0 0; height:1px;
  background:var(--accent);
  transform:scaleX(0); transform-origin:left;
  transition:transform .7s var(--ease);
}
.card:hover .card-shot img,
.card:focus-within .card-shot img{ transform:scale(1.05); filter:brightness(1) saturate(1); }
.card:hover .card-shot::after,
.card:focus-within .card-shot::after{ transform:scaleX(1); }

.card-body{ padding-top:1.4rem; }
.card-tag{
  margin:0 0 .7rem;
  font-size:.63rem; letter-spacing:.32em; text-transform:uppercase;
  color:var(--text-2);
}
.card-name{
  margin:0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(1.5rem,2.1vw,1.95rem); line-height:1;
  color:var(--text);
  transition:color .4s var(--ease);
}
.card-note{
  margin:.85rem 0 0; max-width:26rem;
  font-size:.92rem; line-height:1.62;
  color:var(--text-2);
}
.card-price{
  margin:1.1rem 0 0;
  font-size:1.05rem; letter-spacing:.06em;
  color:var(--accent);
  transition:color .4s var(--ease);
}
.card-price span{
  font-size:.68rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--text-2); margin-right:.45em;
}
.card:hover .card-price{ color:var(--text); }

/* ── discount badge & price hierarchy ──────────────────────────── */

/* Inline badge: thin gold-bordered tag, no red-sticker aggression */
.discount-badge{
  display:block;
  font-family:var(--util); font-size:.58rem; font-weight:600;
  letter-spacing:.18em; text-transform:uppercase;
  color:var(--accent); border:1px solid var(--accent);
  padding:.18em .55em;
  width:max-content;
  margin-bottom:.35rem;
  line-height:1.4;
}

/* Discounted (final) price — dominant */
.price-final{
  display:block;
  font-size:1.05rem; letter-spacing:.06em;
  color:var(--accent);
  transition:color .4s var(--ease);
}
.price-final span{ /* "Rs" label */
  font-size:.68rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--text-2); margin-right:.45em;
}
.card:hover .price-final{ color:var(--text); }

/* Original price — muted strikethrough */
.price-original{
  display:block;
  font-size:.78rem; letter-spacing:.04em;
  color:var(--text-2);
  text-decoration:line-through;
  text-decoration-color:var(--hairline);
  margin-top:.18rem;
  line-height:1.3;
}
.price-original span{
  font-size:.6rem; letter-spacing:.2em; text-transform:uppercase;
  margin-right:.3em;
}

/* Detail dialog — same tokens, slightly larger */
.detail-price .discount-badge{ font-size:.62rem; margin-bottom:.4rem; }
.detail-price .price-final{
  font-size:1.1rem; display:block;
}
.detail-price .price-final span{ font-size:.78em; margin-right:.2em; }
.detail-price .price-original{ font-size:.85rem; margin-top:.22rem; }

/* ── best selling: editorial rows, alternating ─────────────────── */

.rows{ display:flex; flex-direction:column; gap:clamp(4rem,10vh,8rem); }

.sect-msg{ grid-column:1/-1; padding:2rem 0; color:var(--text-2); font-size:.95rem; }

.row{
  position:relative;              /* containing block for the detail hit area */
  display:grid; grid-template-columns:1.15fr .85fr;
  gap:clamp(2rem,5vw,5rem);
  align-items:center;
}
.row.is-flip .row-shot{ order:2; }

.row-shot{
  overflow:hidden; background:var(--surface);
  aspect-ratio:3/2;
}
.row-shot img{
  width:100%; height:100%; object-fit:cover; display:block;
  filter:brightness(var(--img-dim)) saturate(.96);
  transform:scale(1.001);
  transition:transform 1.2s var(--ease), filter .8s var(--ease);
}
.row:hover .row-shot img{ transform:scale(1.04); filter:brightness(1) saturate(1); }

.row-rank{
  margin:0 0 1.2rem;
  font-size:.66rem; letter-spacing:.34em; text-transform:uppercase;
  color:var(--accent);
}
.row-name{
  margin:0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(2.1rem,4.2vw,3.4rem); line-height:1;
  color:var(--text);
}
.row-note{
  margin:1.4rem 0 0; max-width:32rem;
  font-size:clamp(.95rem,1.1vw,1.05rem); line-height:1.7;
  color:var(--text-2);
}
.row-meta{
  margin:2.2rem 0 0;
  display:flex; align-items:center; gap:2rem; flex-wrap:wrap;
  /* Sits above the row's detail hit area but stays transparent to clicks, so
     only .row-cta inside it actually catches one — the price still opens the
     card like the rest of the row. */
  position:relative; z-index:2;
  pointer-events:none;
}
.row-price{ font-size:1.35rem; letter-spacing:.05em; color:var(--accent); }
.row-price span{
  font-size:.7rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--text-2); margin-right:.45em;
}
.row-cta{
  position:relative;
  /* Raised clear of the full-row hit area — but only this link takes clicks.
     A z-index on the link alone would not do it: .row-body is unpositioned, so
     the whole text subtree resolves below the overlay no matter what the link
     asks for. The lift has to happen on an ancestor, and the pointer-events
     pair lets the rest of the meta row fall through and open the card. */
  pointer-events:auto;
  font-size:.72rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--text); text-decoration:none;
  padding-bottom:.4rem;
}
.row-cta::after{
  content:""; position:absolute; inset:auto 0 0 0; height:1px;
  background:var(--accent);
  transform:scaleX(1); transform-origin:right;
  transition:transform .5s var(--ease);
}
.row-cta:hover::after{ transform:scaleX(0); }

/* ── story ─────────────────────────────────────────────────────── */

.story{
  display:grid; grid-template-columns:1fr 1fr;
  gap:clamp(2.5rem,6vw,6rem);
  align-items:center;
}
.story-shot{
  overflow:hidden; background:var(--surface);
  aspect-ratio:4/5;
  /* the container must keep its box: an element clipped to zero area never
     registers as intersecting, so the mask lives on the image instead */
  opacity:1; transform:none; transition:none;
}
.story-shot img{
  width:100%; height:100%; object-fit:cover; display:block;
}
/* Same rule as every other reveal: the mask only exists once JS is watching.
   Ungated, a blocked script left the café photograph permanently invisible. */
.js-reveal .story-shot img{
  clip-path:inset(0 0 100% 0);
  transform:scale(1.08);
  transition:clip-path 1.4s var(--ease), transform 1.8s var(--ease);
}
.js-reveal .story-shot.is-in img{ clip-path:inset(0 0 0 0); transform:scale(1); }

.story-h{
  margin:0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(2.3rem,4.6vw,3.9rem);
  line-height:1.06; letter-spacing:-.01em;
  color:var(--text);
}
/* The origin is two moments: where it began, and where it landed. One hairline
   runs beside both and fades out at the foot — the passage of time as a mark,
   not an ornament. It is the only thing added to this section. */
.story-arc{
  position:relative;
  margin-top:1.9rem;
  padding-left:clamp(1.05rem,2.2vw,1.5rem);
}
.story-arc::before{
  content:""; position:absolute;
  left:0; top:.6em; bottom:0; width:1px;
  background:linear-gradient(var(--accent), rgba(var(--line-rgb),0));
  opacity:.55;
}
.story-p{
  margin:1.9rem 0 0; max-width:30rem;
  font-size:clamp(1rem,1.2vw,1.12rem); line-height:1.75;
  color:var(--text-2);
}
/* the arc already supplies the gap under the title */
.story-arc .story-p:first-child{ margin-top:0; }
.story-cta{
  display:inline-block; margin-top:2.6rem;
  padding:.9rem 2rem;
  border:1px solid rgba(var(--line-rgb),.4);
  font-size:.72rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--accent); text-decoration:none;
  transition:color .4s var(--ease), background-color .4s var(--ease), border-color .4s var(--ease);
}
.story-cta:hover{ color:var(--bg); background:var(--accent); border-color:var(--accent); }

/* ── testimonials ──────────────────────────────────────────────── */

.quotes{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:clamp(1.25rem,2.5vw,2rem);
}
.quote{
  display:flex; flex-direction:column;
  padding:clamp(1.75rem,2.6vw,2.6rem);
  border:1px solid rgba(var(--line-rgb),.14);
  background:linear-gradient(180deg, rgba(var(--line-rgb),.035), transparent);
  transition:border-color .5s var(--ease), background-color .5s var(--ease),
             opacity .9s var(--ease), transform .9s var(--ease);
}
.quote:hover{ border-color:rgba(var(--line-rgb),.34); }
.quote-mark{
  margin:0 0 1.4rem; height:.42em;
  font-family:var(--display); font-weight:500;
  font-size:5.5rem; line-height:1;
  color:var(--accent); opacity:.5;
}
.quote-text{
  margin:0; flex:1;
  font-family:var(--display); font-weight:400;
  font-size:clamp(1.05rem,1.35vw,1.25rem); line-height:1.55;
  color:var(--text);
}
.quote-by{
  margin:2rem 0 0;
  font-size:.8rem; letter-spacing:.08em;
  color:var(--accent);
}
.quote-by span{
  display:block; margin-top:.4rem;
  font-size:.64rem; letter-spacing:.28em; text-transform:uppercase;
  color:var(--text-2);
}

/* ── find us ───────────────────────────────────────────────────── */

.find{
  display:grid; grid-template-columns:.85fr 1.15fr;
  gap:clamp(2.5rem,5vw,5rem);
  align-items:start;
}
.find-facts{ display:flex; flex-direction:column; }
.fact{ padding:1.6rem 0; border-top:1px solid rgba(var(--line-rgb),.14); }
.fact:first-child{ border-top:0; padding-top:0; }
.fact h3{
  margin:0 0 .9rem;
  font-size:.66rem; letter-spacing:.34em; text-transform:uppercase;
  font-weight:400; color:var(--text-2);
}
.fact p{
  margin:0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(1.05rem,1.5vw,1.3rem); line-height:1.55;
  color:var(--text);
}
.fact a{ color:var(--text); text-decoration:none; border-bottom:1px solid rgba(var(--line-rgb),.3); }
.fact a:hover{ color:var(--accent); border-bottom-color:var(--accent); }

.find-cta{
  align-self:flex-start; margin-top:2.2rem;
  padding:.9rem 2rem;
  border:1px solid rgba(var(--line-rgb),.4);
  font-size:.72rem; letter-spacing:.24em; text-transform:uppercase;
  color:var(--accent); text-decoration:none;
  transition:color .4s var(--ease), background-color .4s var(--ease), border-color .4s var(--ease);
}
.find-cta:hover{ color:var(--bg); background:var(--accent); border-color:var(--accent); }

/* The whole card is the link to Maps — one target, one step. */
/* Same box as before — size, ratio, border and surface are unchanged. It is an
   <a> now so the visible map is the click target, with no layer over it. */
.find-map{
  position:relative;
  aspect-ratio:4/3;
  border:1px solid rgba(var(--line-rgb),.16);
  background:
    radial-gradient(70% 60% at 50% 45%, rgba(var(--line-rgb),.07), transparent 70%),
    var(--surface);
  overflow:hidden;
  display:block;
  text-decoration:none;
  transition:border-color .4s var(--ease);
}
.find-map:hover{ border-color:rgba(var(--line-rgb),.34); }
.find-map:focus-visible{ outline:1px solid var(--accent); outline-offset:3px; }

.find-map iframe{
  width:100%; height:100%; border:0; display:block;
  /* The embed is the picture, not a control: without this it would swallow the
     click and pan itself instead of letting the card open Maps. */
  pointer-events:none;
  /* toned down to sit in the room; returns to normal when you reach for it */
  filter:var(--map-filter);
  transition:filter .6s var(--ease);
}
.find-map:hover iframe,
.find-map:focus-visible iframe{ filter:none; }

/* ── faq ───────────────────────────────────────────────────────── */

.faq{ max-width:60rem; }

.q{ border-top:1px solid rgba(var(--line-rgb),.14); }
.q:last-child{ border-bottom:1px solid rgba(var(--line-rgb),.14); }

/* One gutter width drives the row and the answer's indent, so the number, the
   question and the answer all hang off the same line at every size. */
.faq{ --q-gutter:clamp(2rem,4.5vw,3.4rem); }

.q summary{
  display:grid;
  grid-template-columns:var(--q-gutter) 1fr auto;
  align-items:baseline;
  column-gap:clamp(.6rem,2vw,1.25rem);
  padding:clamp(1.4rem,2.6vh,2rem) 0;
  cursor:pointer;
  list-style:none;
  font-family:var(--display); font-weight:400;
  font-size:clamp(1.15rem,2.1vw,1.7rem); line-height:1.3;
  color:var(--accent);
  transition:color .35s var(--ease);
}
/* The index is a label, not part of the question — utility face, quiet, and it
   keeps its own baseline beside a question that may wrap to three lines. */
.q-n{
  font-family:var(--util);
  font-size:.66rem; letter-spacing:.18em;
  color:var(--text-2);
  transition:color .35s var(--ease);
}
.q[open] .q-n,
.q summary:hover .q-n{ color:var(--accent); }
.q-t{ min-width:0; }        /* lets a long question wrap instead of pushing the + out */
.q summary::-webkit-details-marker{ display:none; }
.q summary:hover,
.q[open] summary{ color:var(--text); }

/* a plus that becomes a minus — the only icon on the page */
.q summary i{
  position:relative; flex:0 0 auto; width:16px; height:16px;
  align-self:center;          /* stays centred beside a question that wraps */
}
.q summary i::before,
.q summary i::after{
  content:""; position:absolute; left:0; top:50%;
  width:16px; height:1px; background:currentColor;
  transition:transform .45s var(--ease);
}
.q summary i::after{ transform:rotate(90deg); }
.q[open] summary i::after{ transform:rotate(0deg); }

.q-body{
  display:grid; grid-template-rows:0fr;
  transition:grid-template-rows .5s var(--ease);
}
.q[open] .q-body{ grid-template-rows:1fr; }
.q-body > p{
  overflow:hidden;
  margin:0;
  /* aligned under the question, clear of the number's gutter */
  padding-left:calc(var(--q-gutter) + clamp(.6rem,2vw,1.25rem));
  max-width:48rem;
  font-size:clamp(.95rem,1.1vw,1.05rem); line-height:1.75;
  color:var(--text-2);
  opacity:0;
  transition:opacity .45s var(--ease), padding-bottom .5s var(--ease);
}
.q[open] .q-body > p{ opacity:1; padding-bottom:clamp(1.5rem,3vh,2.2rem); }
.q-body a{ color:var(--accent); text-decoration:none; border-bottom:1px solid rgba(var(--line-rgb),.35); }
.q-body a:hover{ color:var(--text); }

/* ── theme switch ──────────────────────────────────────────────────
   A lamp, not a checkbox: a small orb that grows rays in the dark and
   pulls them in when the lights are already on.                      */

.barend{ display:flex; align-items:center; gap:.6rem; flex:0 0 auto; }

.lamp{
  width:42px; height:42px; padding:0; flex:0 0 auto;
  display:grid; place-items:center;
  background:none; border:1px solid transparent; border-radius:999px;
  cursor:pointer;
  transition:border-color .4s var(--ease), background-color .4s var(--ease);
}
.lamp:hover{ border-color:rgba(var(--line-rgb),.3); }

.lamp-icon{ position:relative; display:block; width:20px; height:20px; }

.lamp-orb{
  position:absolute; inset:5px;
  border-radius:50%;
  border:1px solid var(--accent);
  background:transparent;
  transition:inset .5s var(--ease), background-color .5s var(--ease),
             box-shadow .5s var(--ease), border-color .4s var(--ease);
}
/* eight rays, drawn once, scaled out of the orb */
.lamp-rays{
  position:absolute; inset:0;
  transition:transform .6s var(--ease), opacity .45s var(--ease);
}
.lamp-rays::before,
.lamp-rays::after{
  content:""; position:absolute; left:50%; top:50%;
  width:1px; height:20px; margin:-10px 0 0 -.5px;
  background:
    linear-gradient(var(--accent) 0 3px, transparent 3px 17px, var(--accent) 17px 20px);
}
.lamp-rays::after{ transform:rotate(90deg); }

/* daylight: the orb fills in and the rays fan out */
:root[data-theme="light"] .lamp-orb{
  inset:6px;
  background:var(--accent);
  box-shadow:0 0 10px rgba(var(--line-rgb),.45);
}
:root[data-theme="light"] .lamp-rays{ transform:rotate(45deg) scale(1); opacity:1; }
:root[data-theme="dark"]  .lamp-rays{ transform:rotate(0deg) scale(.45); opacity:0; }
/* night: the orb becomes a crescent */
:root[data-theme="dark"] .lamp-orb{
  box-shadow:inset -4px 1px 0 0 var(--accent);
  border-color:transparent;
}

/* ── footer ────────────────────────────────────────────────────────
   Colours are inverted against the page by the token scopes at the top
   of this file. Everything here just reads --bg / --text / --accent.  */

.foot{
  background:var(--bg);
  color:var(--text-2);
}
.foot-inner{
  max-width:1440px; margin-inline:auto;
  padding:clamp(4.5rem,11vh,8rem) var(--pad) clamp(2rem,4vh,3rem);
}

.foot-head{ max-width:56rem; }

.foot-eyebrow{
  margin:0 0 1.6rem;
  font-size:.66rem; letter-spacing:.4em; text-transform:uppercase;
  color:var(--accent);
}

/* The wordmark is the footer's only loud element, and it was the one place
   Bodoni actively worked against us: a Didone's hairlines are its whole
   character, and at display size they thin to almost nothing, so the mark read
   as faint no matter how much contrast sat behind it. The geometric sans
   already in the system carries an even stroke at any size, which is what a
   wordmark needs — the same face the rest of the site uses for its labels,
   here at full scale. Set slightly smaller than before, because a sans at
   equal size carries far more mass. */
.foot-mark{
  margin:0;
  font-family:var(--util); font-weight:600;
  font-size:clamp(3.3rem,12vw,8.5rem);
  line-height:.94;
  /* geometric caps need air to stop reading as a single block */
  letter-spacing:.08em;
  color:var(--text);
}
.foot-line{
  margin:1.8rem 0 0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(1.05rem,2vw,1.5rem);
  color:var(--text-2);
}

.foot-cols{
  margin-top:clamp(3.5rem,8vh,6rem);
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(2rem,4vw,4rem);
}
/* The footer's micro-labels all sat at slightly different sizes and weights
   (.64/.66rem, 300/400) which is what made it read as assembled rather than
   designed. One size and one weight; gold and tracking carry the hierarchy. */
.foot-col h2{
  margin:0 0 1.4rem;
  font-size:.66rem; letter-spacing:.34em; text-transform:uppercase;
  font-weight:300; color:var(--accent);
}
.foot-col ul{ list-style:none; margin:0; padding:0; }
.foot-col li{ margin:0 0 .55rem; }
.foot-col a{
  display:inline-block;
  /* matches the address it sits beside — the .02em here was arbitrary, and the
     default line-height left the links cramped next to 1.75 body copy */
  font-size:.95rem; line-height:1.75;
  color:var(--text-2); text-decoration:none;
  transition:color .3s var(--ease);
}
.foot-col a:hover{ color:var(--text); }
.foot-col address{
  font-style:normal;
  font-size:.95rem; line-height:1.75;
  color:var(--text-2);
}
.foot-hours{
  margin:1.1rem 0 0;
  font-size:.66rem; letter-spacing:.22em; text-transform:uppercase;
  color:var(--accent);
}

.foot-rule{
  margin:clamp(3.5rem,8vh,6rem) 0 0;
  padding-top:1.6rem;
  border-top:1px solid rgba(var(--line-rgb),.18);
  display:flex; justify-content:space-between; flex-wrap:wrap; gap:.5rem 2rem;
  font-size:.66rem; letter-spacing:.22em; text-transform:uppercase;
  color:var(--text-2);
}

/* ── narrow screens: the film plays itself, nothing is scroll-bound ── */

/* ── reduced motion: the hero collapses to one held frame ────────── */

body.is-still .reel{ height:100svh; }

/* The reel's 640vh only exists to give the scrub something to scrub. When the
   film runs on its own clock that track is dead scroll, so the hero collapses
   to the one screen it actually occupies — same as the held-frame mode above. */
body.is-auto .reel{ height:100svh; }
body.is-still .rail,
body.is-still .cue{ display:none; }
body.is-still .veil{ opacity:1; }

@media (max-width:1080px){
  .cards{ grid-template-columns:repeat(2,1fr); }
  .row,.story,.find{ grid-template-columns:1fr; }
  .row.is-flip .row-shot{ order:0; }
  .row-shot,.story-shot{ aspect-ratio:16/10; }
  .quotes{ grid-template-columns:1fr; }
  /* no room for inline links — hand over to the drawer */
  .barnav{ display:none; }
  .barmenu{ display:block; }
}

@media (max-width:760px){
  .lockup-name{ letter-spacing:.28em; }
  .cut-word{ font-size:18vw; }

  .brandbar{ padding:.4rem; }
  .barcta{ display:none; }
  .barmenu{ display:block; }

  /* Signatures: two per row. minmax(0,1fr) rather than 1fr so a long word in a
     card can never widen its own column and push the grid past the viewport. */
  .cards{
    display:grid;
    grid-template-columns:repeat(2,minmax(0,1fr));
    gap:clamp(2rem,6vw,2.75rem) clamp(.85rem,3.5vw,1.35rem);
  }
  .card{ min-width:0; }
  /* squarer than the desktop 4:5 — two columns of tall images makes for tall cards */
  .card-shot{ aspect-ratio:1/1; }
  .card-body{ padding-top:.9rem; }
  .card-tag{ font-size:.56rem; letter-spacing:.24em; margin-bottom:.45rem; }
  .card-name{ font-size:clamp(1.15rem,5.2vw,1.45rem); }
  .card-note{
    max-width:none;
    margin-top:.5rem;
    font-size:clamp(.78rem,3.2vw,.88rem); line-height:1.5;
  }
  .card-price{ margin-top:.7rem; font-size:.95rem; }
  .card-price span{ font-size:.6rem; letter-spacing:.18em; }

  /* Testimonials stay a swipe rail — three quotes read better one at a time than
     stacked — but the rail is what scrolls, never the page. */
  .quotes{
    display:flex; gap:1rem;
    overflow-x:auto;
    overscroll-behavior-x:contain;
    -webkit-overflow-scrolling:touch;
    scroll-snap-type:x mandatory;
    margin-inline:calc(var(--pad) * -1);
    padding-inline:var(--pad);
    scrollbar-width:none;
  }
  .quotes::-webkit-scrollbar{ display:none; }
  .quote{
    flex:0 0 calc(100% - var(--pad) - 1rem);
    min-width:0;
    scroll-snap-align:center;
  }
  .quote-text{ overflow-wrap:break-word; }

  /* Best selling: the same two-column grid, so the two product sections read as one
     system on a phone. Each editorial row becomes a card — image over text. */
  .rows{
    display:grid;
    grid-template-columns:repeat(2,minmax(0,1fr));
    gap:clamp(2rem,6vw,2.75rem) clamp(.85rem,3.5vw,1.35rem);
  }
  .row{ display:block; min-width:0; }
  .row.is-flip .row-shot{ order:0; }
  /* matches the Signatures image ratio exactly */
  .row-shot{ aspect-ratio:1/1; }
  .row-body{ padding-top:.9rem; }
  .row-rank{
    font-size:.56rem; letter-spacing:.24em; margin-bottom:.45rem;
  }
  .row-name{ font-size:clamp(1.15rem,5.2vw,1.45rem); line-height:1.05; }
  .row-note{
    max-width:none; margin-top:.5rem;
    font-size:clamp(.78rem,3.2vw,.88rem); line-height:1.5;
  }
  .row-meta{
    margin-top:.85rem;
    flex-direction:column; align-items:flex-start; gap:.5rem;
  }
  .row-price{ font-size:.95rem; }
  .row-price span{ font-size:.6rem; letter-spacing:.18em; }
  .row-cta{ font-size:.6rem; letter-spacing:.18em; }

  .find-map{ aspect-ratio:1/1; }

  /* footer: one column, and links get a thumb-sized target */
  .foot-cols{ grid-template-columns:1fr; gap:2.75rem; }
  .foot-col li{ margin-bottom:.2rem; }
  .foot-col a{ padding:.4rem 0; }
  .foot-rule{ flex-direction:column; gap:.5rem; }
}

/* ── phones ────────────────────────────────────────────────────────
   The portrait cut sits the cup smaller and higher than the old centre-
   cropped 16:9 did, which leaves the lower third dark and empty — so the
   closing tagline goes back where it belongs, in the film, not just the
   footer. Nothing in the hero is hidden on a phone any more.            */

@media (max-width:700px){
  /* narrower gutters buy ~10px of content on each side without crowding */
  :root{ --pad:clamp(1.05rem,4.5vw,1.35rem); }

  .end{ padding-bottom:clamp(2rem,6vh,3.2rem); }
  .end-line{
    font-size:clamp(1.05rem,4.6vw,1.4rem);
    line-height:1.35;
    max-width:19ch;
    margin-inline:auto;   /* two balanced lines rather than one long thin one */
  }
  .end-est{
    margin-top:.9rem;
    font-size:.6rem; letter-spacing:.3em;
  }
  .end-est::before{ margin-bottom:.9rem; }

  /* All five stage names would crowd the frame, so the rail shows the one
     that is actually true right now. The information survives; the clutter
     does not. */
  .rail{ right:calc(var(--pad) * .7); height:30vh; gap:.7rem; }
  .rail ol{ display:flex; gap:0; }
  .rail li{ display:none; }
  .rail li[data-on]{ display:block; }
  .rail li span{ font-size:.58rem; letter-spacing:.26em; }
  .rail-line{ align-self:stretch; }

  /* ── vertical rhythm ──
     The desktop scale is built for a 900px-tall window. On a phone the same
     values read as dead air between sections, which is most of why the page
     felt endless. */
  .chapter{ padding:clamp(3.75rem,8.5vh,5.5rem) var(--pad); }
  .chead{ margin-bottom:clamp(1.9rem,4.5vh,2.75rem); }
  .chead-sub{ margin-top:1rem; font-size:.92rem; line-height:1.6; }
  .eyebrow{ margin-bottom:1rem; }

  /* ── headings ──
     Bodoni is a variable face with an optical-size axis. Left to itself it
     picks a text cut at 44px and the hairlines thicken; pinning opsz to the
     display end keeps the fine strokes the desktop headings have. */
  .chead-h,
  .story-h{
    font-size:clamp(2.7rem,10.5vw,3.5rem);
    line-height:.94;
    letter-spacing:-.018em;
    font-variation-settings:'opsz' 92,'wght' 400;
  }

  .rows{ gap:clamp(2rem,5vw,2.6rem) clamp(.7rem,2.8vw,1.1rem); }
  .cards{ gap:clamp(1.9rem,5vw,2.5rem) clamp(.7rem,2.8vw,1.1rem); }

  /* The rows still crop landscape — one full-width band per drink, where a tall
     frame would push everything else off the screen. */
  .row-shot{ aspect-ratio:5/4; }

  /* The cards do not. A landscape crop here assumed the grid collapsed to a
     single column, and it never does — it stays two-up, so each card is only
     about half the screen wide. A 5:4 box on a 166px card left a 133px-tall
     image, and the product photography is portrait (about 4:5), so every cup
     lost its top and bottom to the crop and read as a thumbnail. Matching the
     frame to the pictures' own proportion fills the same width with a much
     taller image and almost no crop at all. */
  .card-shot{ aspect-ratio:4/5; }

  /* The paging controls are trimmed at this width too, but those rules sit
     with the rest of .shot-nav further down: declared here they would come
     before the base rule and lose the cascade to it. */

  .story-shot{ aspect-ratio:4/3; }
  .story-body{ margin-top:1.75rem; }
  .story-p{ margin-top:1.1rem; font-size:.95rem; line-height:1.65; }
  .story-cta{ margin-top:1.75rem; }

  .foot-inner{ padding-top:clamp(3rem,8vh,4.5rem); }
  .foot-cols{ margin-top:clamp(2.5rem,6vh,3.5rem); }
  .foot-rule{ margin-top:clamp(2.5rem,6vh,3.5rem); }
}

/* ── the smallest phones ───────────────────────────────────────────
   Below 380 the bar genuinely cannot hold the wordmark, the lamp and the
   menu at once, so the monogram carries the brand on its own. Above it,
   the wordmark stays. */

@media (max-width:430px){
  .brandbar{ gap:.4rem; }
  .lockup{ min-width:0; }
  .barend{ gap:.15rem; }
  .lamp{ width:40px; height:40px; }
}

@media (max-width:380px){
  .lockup-name{ display:none; }
}

/* ── menu hero ────────────────────────────────────────────────────
   Full-viewport cinematic still. The still lives inside a frame that
   crops to 100svh so mobile browser chrome never leaves a strip of
   bg. A slow Ken Burns crawl runs on the still image itself, so the
   crop is stable and only the picture moves. */

.menu-hero{
  position:relative;
  margin:0; padding:0;
  background:#080605;
  color:var(--n-text);
}

/* Two panels, not a photo with words on it. The left is true black and holds
   every piece of type; the right is the still. Nothing is ever set over the
   photograph, so contrast is fixed by construction rather than by scrim. */
.menu-hero-frame{
  position:relative;
  display:grid;
  grid-template-columns:minmax(0,46fr) minmax(0,54fr);
  /* Controlled band: tall enough to carry the still and a two-line headline,
     short enough that the filter bar is already in view when the page lands. */
  height:clamp(460px,62vh,600px);
  isolation:isolate;
  /* The gold rule is allowed to run past the type and fade out; clipping it
     here means it can never widen the document, stacked or split. */
  overflow:clip;
  /* One source of truth for the frame dwell — the strip, the image drift and
     the index countdown all read it, and so does the script. The travel is
     deliberately a separate value: shortening the pause makes the reel feel
     more alive, shortening the movement would just make it snap. */
  --dwell:3600ms;
  --travel:950ms;
}

/* ── left panel: the type ──────────────────────────────────────── */
.menu-hero-copy{
  position:relative;
  z-index:2;
  display:flex; flex-direction:column; justify-content:center;
  /* top inset clears the floating brandbar; the foot leaves room for the rail */
  padding:clamp(4rem,8vh,6rem) clamp(1.5rem,4vw,4.5rem) 4.75rem clamp(1.5rem,5vw,5.5rem);
  background:#080605;
  color:var(--n-text);
}

.menu-hero-eyebrow{
  position:relative;
  display:flex; align-items:center; gap:.8rem;
  margin:0 0 1.4rem;
  font-family:var(--util);
  font-size:.68rem; letter-spacing:.3em; text-transform:uppercase;
  color:var(--n-accent);
  animation:menuHeroRise .8s var(--ease) .15s both;
}
.menu-hero-eyebrow b{
  width:3px; height:3px; flex:0 0 auto;
  background:var(--n-accent); opacity:.6;
}
/* The signature: one hairline leaves the eyebrow, crosses the seam and
   dissolves into the photograph. Absolute, so it never affects layout. */
.menu-hero-eyebrow i{
  position:absolute; left:100%; top:50%;
  margin-left:1.1rem;
  width:44vw; height:1px;
  background:linear-gradient(to right, var(--n-accent), rgba(208,178,148,0));
  transform-origin:left center;
  animation:menuHeroRule 1.5s var(--ease) .5s both;
}
@keyframes menuHeroRule{
  from{ transform:scaleX(0); opacity:0; }
  to  { transform:scaleX(1); opacity:.75; }
}

.menu-hero-h{
  margin:0;
  font-family:var(--display); font-weight:400;
  font-size:clamp(2.5rem,5vw,4.6rem);
  line-height:.94;
  letter-spacing:-.01em;
  color:var(--n-text);
  animation:menuHeroRise .9s var(--ease) .3s both;
}
.menu-hero-h em{
  font-style:italic;
  color:var(--n-accent);
}
.menu-hero-sub{
  margin:1.35rem 0 0;
  max-width:26rem;
  font-size:clamp(.92rem,1.05vw,1.02rem);
  line-height:1.62;
  color:var(--n-text-2);
  animation:menuHeroRise .9s var(--ease) .45s both;
}

/* CTA: a word and a rule that finishes drawing on hover. No box, no pill. */
.menu-hero-cta{
  align-self:start;
  position:relative;
  margin-top:2.1rem;
  padding-bottom:.55rem;
  font-family:var(--util);
  font-size:.7rem; letter-spacing:.26em; text-transform:uppercase;
  color:var(--n-text); text-decoration:none;
  animation:menuHeroRise .9s var(--ease) .6s both;
  transition:color .35s var(--ease);
}
.menu-hero-cta i{
  position:absolute; left:0; bottom:0;
  width:100%; height:1px;
  background:var(--n-accent);
  transform:scaleX(.34); transform-origin:left center;
  opacity:.5;
  transition:transform .5s var(--ease), opacity .5s var(--ease);
}
.menu-hero-cta:hover{ color:var(--n-accent); }
.menu-hero-cta:hover i,
.menu-hero-cta:focus-visible i{ transform:scaleX(1); opacity:1; }

@keyframes menuHeroRise{
  from{ opacity:0; transform:translateY(12px); }
  to  { opacity:1; transform:none; }
}

/* ── right panel: the strip ────────────────────────────────────—
   Not a slideshow of separate pictures — one continuous film strip that
   travels past a gate. A sliver of the next frame always waits at the right
   edge behind a fine gold seam, so the panel reads as a reel in motion even
   when it is parked. */
.menu-hero-plate{
  position:relative;
  overflow:hidden;
  background:#080605;
  /* how much of the gate the live frame fills; the remainder is the next one */
  --fw:87%;
  --seam:2px;
  --step:calc(var(--fw) + var(--seam));
}
.strip{
  display:flex;
  gap:var(--seam);
  width:100%; height:100%;
  /* the gap is the only place this shows — a hairline of gold between frames */
  background:rgba(var(--n-line-rgb),.34);
  transform:translate3d(calc(-1 * var(--i,0) * var(--step)),0,0);
  transition:transform var(--travel) cubic-bezier(.72,0,.22,1);
  will-change:transform;
}
.strip-frame{
  position:relative;
  flex:0 0 var(--fw);
  margin:0;
  overflow:hidden;
  background:#080605;
}
.strip-frame img{
  width:100%; height:100%;
  object-fit:cover;
  /* every frame is cropped to its own focal point, set per frame in the markup */
  object-position:var(--focal,50% 55%);
  transform:scale(1.05);
  transition:transform var(--dwell) linear;
}
/* the live frame breathes for the length of its dwell */
.strip-frame.is-on img{ transform:scale(1.12); }
/* frames waiting their turn sit back in shadow */
.strip-frame::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:rgba(8,6,5,.62);
  transition:opacity var(--travel) var(--ease);
}
.strip-frame.is-on::after{ opacity:0; }

/* Softens the seam so the strip emerges from the black panel rather than
   butting against it, and keeps the brandbar legible over the picture. */
.menu-hero-plate::after{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:2;
  background:
    linear-gradient(90deg, #080605 0%, rgba(8,6,5,.5) 7%, rgba(8,6,5,0) 22%),
    linear-gradient(180deg, rgba(8,6,5,.6) 0%, rgba(8,6,5,0) 28%);
}

/* ── the index: four stages, doubling as the dwell timer ───────── */
.strip-rail{
  display:flex; flex-wrap:wrap;
  gap:clamp(.85rem,2.2vw,1.7rem);
  animation:menuHeroRise .9s var(--ease) .75s both;
  /* Anchored to the foot of the band rather than stacked under the type: it
     belongs to the strip, and keeping it out of the centred column leaves the
     headline room to sit clear of the floating brandbar. */
  position:absolute;
  left:clamp(1.5rem,5vw,5.5rem);
  bottom:clamp(1.4rem,3.4vh,2.2rem);
  z-index:3;
}
.strip-tab{
  position:relative;
  padding:0 0 .55rem; margin:0;
  background:none; border:0; cursor:pointer;
  font-family:var(--util);
  font-size:.62rem; letter-spacing:.22em; text-transform:uppercase;
  color:var(--n-text-2);
  transition:color .4s var(--ease);
}
.strip-tab:hover{ color:var(--n-text); }
.strip-tab[aria-current="true"]{ color:var(--n-text); }
.strip-tab:focus-visible{ outline:1px solid var(--n-accent); outline-offset:4px; }
.strip-tab i{
  position:absolute; left:0; bottom:0;
  width:100%; height:1px;
  background:rgba(var(--n-line-rgb),.24);
  overflow:hidden;
}
.strip-tab i::after{
  content:""; position:absolute; inset:0;
  background:var(--n-accent);
  transform:scaleX(0); transform-origin:left center;
}
/* the fill is the countdown to the next frame; JS restarts it on each change */
.strip-tab[aria-current="true"] i::after{
  animation:stripFill var(--dwell,3600ms) linear forwards;
}
@keyframes stripFill{ from{ transform:scaleX(0); } to{ transform:scaleX(1); } }

/* Menu page spacing: the hero replaces the chead, so the filter bar needs
   its own comfortable inset. */
.menu-page{ padding-top:clamp(2.5rem,6vh,4rem); }

/* ── menu-hero: stacked below 900px ─────────────────────────────── */

@media (max-width:900px){
  /* Panels stack: still on top as a controlled band, type beneath it on black.
     The photograph keeps its own space instead of being cropped into a sliver. */
  .menu-hero-frame{
    grid-template-columns:1fr;
    grid-template-rows:auto auto;
    height:auto;
  }
  .menu-hero-plate{
    order:-1;
    height:clamp(230px,34vh,330px);
  }
  /* Less width to spend, so the waiting frame narrows to a hint rather than
     a panel — the strip still reads as a strip without starving the live frame. */
  .menu-hero-plate{ --fw:91%; }
  .menu-hero-plate::after{
    background:
      linear-gradient(180deg, rgba(8,6,5,.66) 0%, rgba(8,6,5,0) 34%),
      linear-gradient(180deg, rgba(8,6,5,0) 68%, #080605 100%);
  }
  .menu-hero-copy{
    padding:1.9rem clamp(1.25rem,5vw,2.5rem) 2.6rem;
  }
  /* Stacked, there is no band foot to pin to — the index simply follows the CTA. */
  .strip-rail{
    position:static;
    margin-top:1.9rem;
  }
  .menu-hero-h{ font-size:clamp(2.4rem,8.4vw,3.6rem); }
  .menu-hero-sub{ max-width:32rem; }
  /* nothing to cross once the panels stack — let it run to the edge and fade */
  .menu-hero-eyebrow i{ width:36vw; }
}

@media (max-width:600px){
  /* Tightened so the band plus its type still leaves the first cards showing
     on a short phone rather than filling the whole opening screen. */
  .menu-hero-plate{ height:clamp(180px,28vh,260px); }
  .menu-hero-copy{ padding:1.5rem 1.25rem 1.8rem; }
  .menu-hero-h{ font-size:clamp(2.15rem,9.6vw,3rem); }
  .menu-hero-sub{ font-size:.9rem; line-height:1.55; margin-top:1rem; }
  .menu-hero-eyebrow{ margin-bottom:1rem; font-size:.63rem; letter-spacing:.26em; }
  .menu-hero-cta{ margin-top:1.35rem; }
  .strip-rail{ margin-top:1.35rem; gap:.8rem; }
  .strip-tab{ font-size:.6rem; letter-spacing:.18em; }
}

/* ── menu cards: sharper editorial motion ─────────────────────────
   The existing card system is retained. These rules layer a slower zoom,
   a nameplate slide, and a "gold rule" that draws under the name. */

.menu-page .card-shot{
  /* The image lives behind a fine hairline that stays until hover */
  box-shadow:inset 0 0 0 1px rgba(var(--line-rgb),.08);
}
.menu-page .card-shot img{
  transition:transform 1.4s var(--ease), filter .9s var(--ease);
}
.menu-page .card:hover .card-shot img,
.menu-page .card:focus-within .card-shot img{
  transform:scale(1.06);
}
/* replace the base underline behaviour with an editorial full-width draw */
.menu-page .card-shot::after{
  height:1px;
  transition:transform 1s var(--ease);
}

.menu-page .card-body{
  padding-top:1.25rem;
  position:relative;
}
.menu-page .card-tag{
  transform:translateY(0);
  transition:transform .5s var(--ease), color .3s var(--ease);
}
.menu-page .card:hover .card-tag,
.menu-page .card:focus-within .card-tag{
  color:var(--accent);
  transform:translateY(-2px);
}
.menu-page .card-name{
  position:relative;
  display:inline-block;
  padding-bottom:.15em;
}
.menu-page .card-name::after{
  content:""; position:absolute; left:0; right:0; bottom:0;
  height:1px; background:var(--accent);
  transform:scaleX(0); transform-origin:left;
  transition:transform .55s var(--ease);
}
.menu-page .card:hover .card-name::after,
.menu-page .card:focus-within .card-name::after{
  transform:scaleX(1);
}
.menu-page .card-note{ transition:color .35s var(--ease); }
.menu-page .card:hover .card-note{ color:var(--text); }

/* ── product dialog: tablet range ─────────────────────────────────
   Existing rules cover ≤600 (bottom sheet) and desktop (two-column).
   Between them the dialog was a two-column card that felt cramped on
   768. Reflow to a stacked card with a controlled image height. */

@media (min-width:601px) and (max-width:900px){
  #product-dialog{
    grid-template-columns:1fr;
    grid-template-rows:auto minmax(0,1fr);
    max-width:min(560px,92vw);
    max-height:88dvh;
  }
  /* dvh, not vh: a phone held sideways lands in this range with very little
     height to spend, and vh would let the picture eat all of it. */
  .detail-img-wrap img{
    aspect-ratio:16/10;
    max-height:min(40dvh,300px);
  }
  .detail-body{
    padding:clamp(1.75rem,3.5vw,2.25rem);
  }
}

/* ── reduced motion: one held frame, everything legible at once ─── */

@media (prefers-reduced-motion:reduce){
  .cue span{ animation:none; opacity:.8; }
  .reel{ height:100svh; }
  .curtain{ opacity:0; }
  .brandbar{ opacity:1; transform:none; }
  .rail,.cue{ display:none; }
  .end{ opacity:1; transform:none; }
  .veil{ opacity:1; }

  .reveal{ opacity:1; transform:none; transition:none; }
  .story-shot img{ clip-path:none; transform:none; transition:none; }
  .card-shot img,.row-shot img{ transition:none; }
  .q-body{ transition:none; }
  .q-body > p{ transition:none; }

  .menu-hero-eyebrow,
  .menu-hero-h,
  .menu-hero-sub,
  .menu-hero-cta,
  .strip-rail{ animation:none; opacity:1; transform:none; }
  .menu-hero-eyebrow i{ animation:none; opacity:.75; transform:none; }
  .menu-hero-cta i{ transition:none; }
  /* The strip still moves when a frame is chosen — it just moves at once,
     and never advances on its own. The script skips autoplay to match. */
  .strip{ transition:none; }
  .strip-frame img{ transform:none; transition:none; }
  .strip-frame::after{ transition:none; }
  .strip-tab[aria-current="true"] i::after{ animation:none; transform:scaleX(1); }
}

/* ── product card gallery ─────────────────────────────────────────
   Frames are stacked and cross-faded in place. The card keeps its exact
   4:5 box, so paging never reflows the grid. */
.card-shot .shot-frame{
  position:absolute; inset:0;
  width:100%; height:100%; object-fit:cover;
  opacity:0;
  /* keeps the card's existing hover zoom and dim — a bare opacity transition
     here would override the one .card-shot img declares */
  transition:opacity .35s var(--ease),
             transform 1.1s var(--ease),
             filter .7s var(--ease);
}
.card-shot .shot-frame.is-on{ opacity:1; }

/* A hairline chevron, not a carousel button. The visible mark stays small;
   the tappable box around it is a full 44px. */
.shot-nav{
  position:absolute; top:50%; transform:translateY(-50%);
  z-index:2;
  width:44px; height:44px;
  display:grid; place-items:center;
  padding:0; border:0; background:none; cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  opacity:0;
  transition:opacity .3s var(--ease);
}
.shot-nav--prev{ left:0; }
.shot-nav--next{ right:0; }
.shot-nav i{
  display:grid; place-items:center;
  width:26px; height:26px;
  font-style:normal; font-size:1.15rem; line-height:1;
  color:var(--n-text);
  background:rgba(8,6,5,.55);
  backdrop-filter:blur(6px);
  -webkit-backdrop-filter:blur(6px);
  border:1px solid rgba(var(--n-line-rgb),.28);
  transition:color .3s var(--ease), border-color .3s var(--ease),
             background-color .3s var(--ease);
}
.shot-nav:hover i{ color:var(--n-accent); border-color:var(--n-accent); }
.shot-nav:focus-visible{ opacity:1; }
.shot-nav:focus-visible i{ outline:1px solid var(--n-accent); outline-offset:2px; }

.shot-count{
  position:absolute; right:.55rem; bottom:.55rem; z-index:2;
  font-family:var(--util);
  font-size:.58rem; letter-spacing:.16em;
  color:var(--n-text);
  background:rgba(8,6,5,.55);
  backdrop-filter:blur(6px);
  -webkit-backdrop-filter:blur(6px);
  padding:.2em .5em;
  opacity:0;
  transition:opacity .3s var(--ease);
}

/* On a mouse, the controls stay out of the way until the card is approached. */
.card:hover .shot-nav,
.card:focus-within .shot-nav,
.card:hover .shot-count,
.card:focus-within .shot-count{ opacity:1; }

/* Touch has no hover, so nothing may depend on it — show them always. */
@media (hover:none){
  .shot-nav, .shot-count{ opacity:1; }
  .shot-nav--prev{ left:.15rem; }
  .shot-nav--next{ right:.15rem; }
}

/* Phone widths: back to the hairline chevron this was always meant to be. On a
   card only ~165px wide, a 26px filled square with its own border reads as a
   carousel button bolted onto the photograph. Only the visible mark shrinks —
   .shot-nav keeps its full 44px tap target, which is the part a thumb needs. */
@media (max-width:700px){
  .shot-nav i{
    width:20px; height:20px;
    font-size:.9rem;
    border-color:transparent;
    background:rgba(8,6,5,.4);
  }
  /* the frame counter is a footnote, not a label */
  .shot-count{
    right:.4rem; bottom:.4rem;
    font-size:.54rem;
    background:rgba(8,6,5,.4);
  }
}

@media (prefers-reduced-motion:reduce){
  .card-shot .shot-frame{ transition:none; }
  .shot-nav, .shot-count{ transition:none; }
}
