/* ============================================================
   ONYX — design tokens
   ============================================================ */

@font-face {
  font-family: 'Fraunces';
  src: local('Fraunces');
}

:root{
  --onyx-black: #0a0a0a;
  --onyx-ink: #111110;
  --onyx-charcoal: #1c1a18;
  --onyx-charcoal-2: #262320;
  --onyx-ivory: #f2ece1;
  --onyx-white: #f8f6f2;
  --onyx-smoke: #8f897f;
  --onyx-smoke-dim: #5c5852;
  --onyx-line: rgba(242,236,225,0.14);
  --onyx-line-strong: rgba(242,236,225,0.28);
  --accent: #b3603a;
  --accent-dim: #7c4a30;

  --font-serif: 'Fraunces', 'Iowan Old Style', 'Georgia', serif;
  --font-sans: 'Inter', -apple-system, 'Segoe UI', sans-serif;

  --ease-out: cubic-bezier(.16,.8,.24,1);
  --ease-soft: cubic-bezier(.4,0,.2,1);

  --nav-h: 96px;
  --nav-h-scrolled: 68px;
}

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

html{
  scroll-behavior: auto;
  background: var(--onyx-black);
  /* always reserve the scrollbar's gutter, whether or not one is currently
     needed — otherwise opening the nav overlay (which sets overflow:hidden
     on body to lock scrolling) removes the scrollbar, the viewport gets
     wider by its width, and the logo's left:50% centering shifts sideways
     by half that amount. Confirmed: htmlClientWidth measured 1425px before
     opening the overlay and 1440px while it was open. */
  scrollbar-gutter: stable;
}

body{
  margin: 0;
  background: var(--onyx-black);
  color: var(--onyx-ivory);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* NOTE: overflow-x:hidden must stay on body only, not html — putting it on
   both breaks position:sticky for any descendant (e.g. .day-stage), because
   html then becomes its own separate scrolling container instead of letting
   body's overflow propagate up to the viewport. Confirmed this the hard way:
   adding it to html broke the day-section's sticky pinning entirely. */
.site-nav,
.grain{
  transform: translateZ(0);
}

body.lock-scroll{ overflow: hidden; height: 100vh; }

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

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

button{
  font-family: inherit;
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
}

h1,h2,h3,h4,p{ margin: 0; }

::selection{ background: var(--accent); color: var(--onyx-white); }

/* film grain, sits above everything, never blocks input */
.grain{
  position: fixed;
  inset: 0;
  z-index: 9000;
  pointer-events: none;
  opacity: .05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 180px 180px;
}

.eyebrow{
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--onyx-smoke);
  font-weight: 500;
}

.serif-display{
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-weight: 340;
  letter-spacing: -0.01em;
}

.container{
  width: 100%;
  padding: 0 clamp(20px, 5vw, 64px);
}

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

.onyx-logo{
  display: block;
  width: auto;
  height: auto;
  /* belt-and-braces: height/width:auto already preserves the source
     file's ratio correctly on its own, but pinning the exact ratio here
     too means no other rule (a stray width, a flex stretch, anything)
     can ever squash or stretch it, on any page */
  aspect-ratio: 1502 / 414;
  flex: none;
  object-fit: contain;
}

/* ============================================================
   Navigation
   ============================================================ */

.site-nav{
  /* must be position:fixed, not sticky — sticky occupies real space in the
     document flow, which pushes the hero/video down and exposes the body's
     black background above it (confirmed: this was the actual cause of the
     "black bar behind the nav" complaint). Fixed takes the nav out of flow
     entirely so it overlays directly on top of the hero at all times. */
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 500;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 clamp(20px, 5vw, 56px);
  transition: height .6s var(--ease-soft), background-color .6s var(--ease-soft), border-color .6s var(--ease-soft);
  border-bottom: 1px solid transparent;
  background: transparent;
}

@media (min-width: 641px){
  .nav-mark{
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }
}

.site-nav.nav-scrolled{
  height: var(--nav-h-scrolled);
  background: transparent;
  backdrop-filter: none;
  border-bottom: 1px solid transparent;
}

.nav-mark{
  display: flex;
  align-items: center;
  gap: 12px;
  z-index: 2;
}

.nav-mark .onyx-logo{
  height: 32px;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.5));
}

.nav-links{
  display: flex;
  align-items: center;
  gap: clamp(20px, 3vw, 40px);
}

.nav-cta{
  background: var(--onyx-ivory);
  color: var(--onyx-black) !important;
  border: none;
  border-radius: 6px;
  padding: 10px 22px;
  transition: background-color .3s var(--ease-soft), transform .2s;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.5));
}
.nav-cta:hover{ background: var(--onyx-white); color: var(--onyx-black) !important; transform: translateY(-1px); }

.nav-toggle{
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  z-index: 2;
  background: var(--onyx-charcoal);
  border: 1px solid var(--onyx-line-strong);
  border-radius: 6px;
  padding: 12px;
  width: 44px;
  height: 44px;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.5));
}
.nav-toggle-label{
  display: none;
  font-size: 12px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--onyx-ivory);
  transition: color .3s var(--ease-soft);
}
.nav-toggle:hover .nav-toggle-label{ color: var(--onyx-ivory); }
.nav-toggle-icon{
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  width: 22px;
  height: 16px;
}
.nav-toggle-icon span{
  height: 1px; width: 100%;
  background: var(--onyx-ivory);
  transition: transform .45s var(--ease-soft), opacity .3s, width .3s;
}
.nav-toggle-icon span:last-child{ width: 70%; align-self: flex-end; }
.nav-toggle:hover .nav-toggle-icon span:last-child{ width: 100%; }

.toggle-open .nav-toggle-icon span:first-child{
  transform: translateY(3.5px) rotate(45deg);
}
.toggle-open .nav-toggle-icon span:last-child{
  transform: translateY(-3.5px) rotate(-45deg);
  width: 100%;
}

/* Fullscreen editorial menu overlay */
.nav-overlay{
  position: fixed;
  inset: 0;
  z-index: 400;
  background: var(--onyx-ink);
  display: flex;
  align-items: center;
  clip-path: inset(0 0 100% 0);
  transition: clip-path .8s var(--ease-out);
  pointer-events: none;
}
.nav-overlay.overlay-open{
  clip-path: inset(0 0 0% 0);
  pointer-events: auto;
}

.overlay-grid{
  width: 100%;
  padding: 0 clamp(24px, 8vw, 120px);
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 40px;
  align-items: center;
}

.overlay-links{
  display: flex;
  flex-direction: column;
}

.overlay-links a{
  font-family: var(--font-serif);
  font-weight: 320;
  font-size: clamp(40px, 7vw, 92px);
  line-height: 1.08;
  letter-spacing: -0.01em;
  color: var(--onyx-smoke);
  padding: .06em 0;
  transition: color .5s var(--ease-soft), padding-left .5s var(--ease-soft);
  border-top: 1px solid transparent;
}
.overlay-links a:hover,
.overlay-links a:focus-visible,
.overlay-links a.active{
  color: var(--onyx-ivory);
  padding-left: .18em;
}
.overlay-links a .num{
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: .1em;
  vertical-align: super;
  margin-right: 18px;
  color: var(--onyx-smoke-dim);
}

.overlay-side{
  display: flex;
  flex-direction: column;
  gap: 28px;
  border-left: 1px solid var(--onyx-line);
  padding-left: 40px;
}
.overlay-side .eyebrow{ margin-bottom: 4px; }
.overlay-side address{
  font-style: normal;
  font-size: 14px;
  color: var(--onyx-smoke);
  line-height: 1.9;
}
.overlay-side address a:hover{ color: var(--onyx-ivory); }

/* qualified with the element (a.overlay-discount-link) so its specificity
   safely beats `.overlay-links a` — it now lives inside .overlay-links so
   it stays visible on mobile too (see the max-width:640px block below),
   and without this it would inherit that rule's huge serif nav-link size
   and smoke color instead of its own pill styling */
a.overlay-discount-link{
  display: inline-flex;
  align-items: center;
  /* .overlay-links is a flex column, whose default align-items:stretch
     would otherwise force this to the full column width like the other
     (plain-text, so it's invisible there) nav links — align-self keeps it
     a compact pill instead of a full-width bar */
  align-self: flex-start;
  margin-top: 22px;
  background: var(--accent);
  color: var(--onyx-white);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 10px 18px;
  border-radius: 6px;
  transition: background-color .3s var(--ease-soft), transform .2s;
}
a.overlay-discount-link:hover{
  background: var(--accent-dim);
  transform: translateY(-1px);
}

/* same reasoning/fix as the discount link above: lives inside
   .overlay-links so it stays visible on mobile, qualified with the
   element so it doesn't inherit the giant serif nav-link styling */
.overlay-legal-links{ display: flex; gap: 20px; margin-top: 20px; }
a.overlay-legal-links-link{
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--onyx-smoke-dim);
  padding: 0;
  border-top: none;
  transition: color .3s var(--ease-soft);
}
a.overlay-legal-links-link:hover{ color: var(--onyx-ivory); padding-left: 0; }

@media (max-width: 640px){
  .site-nav{ justify-content: space-between; }
  .nav-mark{
    position: static !important;
    left: auto; top: auto;
    transform: none !important;
  }
  .overlay-grid{ grid-template-columns: 1fr; }
  .overlay-side{ display: none; }
}

@media (max-width: 340px){
  /* logo + Reservieren + Menü fit with zero slack at 320px — a small safety buffer */
  .nav-cta{ padding: 10px 16px; }
  .nav-links{ gap: 12px; }
}

/* ============================================================
   Hero — video + one line
   Full-bleed looping video, a dark legibility overlay, and a
   single short German tagline. Nothing else.
   ============================================================ */

.hero{
  position: relative;
  height: 100vh;
  background: var(--onyx-black);
  overflow: visible;
}

.hero-frame{
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}

.hero-video{
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero-frame::after{
  content: '';
  position: absolute; inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(10,10,10,.6) 0%, rgba(10,10,10,.28) 45%, rgba(10,10,10,.6) 100%);
  pointer-events: none;
}

.hero-copy{
  position: relative;
  z-index: 2;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 24px;
}

.hero-tagline{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(6px, 2vw, 18px);
}
.hero-tagline span{
  font-family: var(--font-serif);
  font-weight: 650;
  text-transform: uppercase;
  font-size: clamp(40px, 8vw, 110px);
  line-height: .95;
  color: var(--onyx-ivory);
  opacity: 0;
  transform: translateY(20px);
  animation: hero-tagline-in .6s var(--ease-out) forwards;
}
.hero-tagline span:nth-child(1){ animation-delay: .15s; }
.hero-tagline span:nth-child(2){ animation-delay: .3s; }
.hero-tagline span:nth-child(3){ animation-delay: .45s; }

@keyframes hero-tagline-in{
  to{ opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce){
  .hero-tagline span{ animation: none; opacity: 1; transform: none; }
}

/* ============================================================
   Scroll badge — spinning "SCROLL" ring straddling the hero seam
   ============================================================ */

.scroll-badge{
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translate(-50%, 50%);
  width: clamp(110px, 12vw, 150px);
  height: clamp(110px, 12vw, 150px);
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
}
.scroll-badge::before{
  content: '';
  position: absolute; inset: 0;
  border-radius: 50%;
  background: transparent;
  border: none;
}
.scroll-badge-ring{
  position: relative;
  width: 100%;
  height: 100%;
  animation: scroll-badge-spin 12s linear infinite;
}
.scroll-badge-ring text{
  font-family: var(--font-serif);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: .14em;
  fill: var(--onyx-ivory);
  text-transform: uppercase;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.6));
}
.scroll-badge-arrow{
  position: absolute;
  font-size: 22px;
  color: var(--onyx-ivory);
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.6));
  animation: scroll-arrow-bob 1.8s ease-in-out infinite;
}
@keyframes scroll-badge-spin{
  from{ transform: rotate(0); }
  to{ transform: rotate(360deg); }
}
@keyframes scroll-arrow-bob{
  0%, 100%{ transform: translateY(-3px); }
  50%{ transform: translateY(3px); }
}
@media (prefers-reduced-motion: reduce){
  .scroll-badge-ring{ animation: none; }
  .scroll-badge-arrow{ animation: none; }
}

@media (max-width: 480px){
  .scroll-badge{ width: 84px; height: 84px; }
  /* the SVG's internal font-size scales down with the container (viewBox is
     fixed), so bump it here to keep the rendered text legible at 84px */
  .scroll-badge-ring text{ font-size: 24px; }
  .scroll-badge-arrow{ font-size: 16px; }
}

/* ============================================================
   Ein Tag im Onyx — day timeline
   ============================================================ */

.day{
  position: relative;
  background: var(--onyx-black);
}

.day-intro{
  padding: 180px clamp(20px, 6vw, 64px) 80px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  align-items: end;
}
.day-intro h2{
  font-family: var(--font-serif);
  font-weight: 340;
  font-size: clamp(44px, 6.5vw, 96px);
  line-height: .96;
  letter-spacing: -0.01em;
}
.day-intro p{
  font-size: 15px;
  color: var(--onyx-smoke);
  max-width: 440px;
  line-height: 1.75;
  justify-self: end;
  text-align: right;
}

.day-track{
  position: relative;
  height: 400vh; /* 4 chapters of runway */
  height: 400dvh;
}

.day-stage{
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: flex;
  align-items: center;
}

.day-bg{
  position: absolute; inset: 0;
  z-index: 0;
  transition: background-color 1s var(--ease-soft);
}
/* a soft cross-fade + gentle settle, instead of a hard clip-path wipe —
   opacity/transform are compositor-only properties (no layout, no repaint
   of the full-viewport image every frame), which is both the fix for the
   scroll jank this section had and a nicer, more "one moment dissolving
   into the next" transition than a geometric wipe ever looked like. */
.day-bg-frame{
  position: absolute; inset: 0;
  opacity: 0;
  transform: scale(1.045);
  transition: opacity 1.4s var(--ease-soft), transform 1.8s var(--ease-soft);
  overflow: hidden;
  will-change: opacity, transform;
}
.day-bg-frame.chapter-active{
  opacity: 1;
  transform: scale(1);
}
.day-bg-frame img{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  animation: day-kb 24s ease-in-out infinite alternate;
  animation-play-state: paused;
}
/* only the visible frame keeps animating — the other three would otherwise
   burn scale/translate recalculation every frame for nothing */
.day-bg-frame.chapter-active img{ animation-play-state: running; }
@keyframes day-kb{
  from{ transform: scale(1) translateX(0); }
  to{ transform: scale(1.1) translateX(-1.5%); }
}
@media (prefers-reduced-motion: reduce){
  .day-bg-frame img{ animation: none; }
  .day-bg-frame{ transition: opacity .3s linear; }
}
.day-bg::after{
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(10,10,10,.94) 0%, rgba(10,10,10,.62) 42%, rgba(10,10,10,.2) 75%);
}

.day-chapters{
  position: relative;
  z-index: 2;
  width: 100%;
  padding: 0 clamp(20px, 6vw, 64px);
}

.day-chapter{
  position: absolute;
  top: 50%;
  left: clamp(20px, 6vw, 64px);
  transform: translateY(-50%) translateX(-14px);
  opacity: 0;
  transition: opacity .8s var(--ease-soft), transform .9s var(--ease-soft);
  pointer-events: none;
}
.day-chapter.chapter-active{
  opacity: 1;
  transform: translateY(-50%) translateX(0);
  pointer-events: auto;
}

.day-chapter h3{
  position: relative;
  display: inline-block;
  font-family: var(--font-serif);
  font-weight: 330;
  font-size: clamp(46px, 8vw, 108px);
  line-height: .96;
  max-width: 12ch;
}
.day-chapter h3::after{
  content: '';
  position: absolute;
  left: 0; bottom: -.08em;
  height: 2px;
  width: 0%;
  background: var(--accent);
  transition: width .4s var(--ease-soft) .35s;
}
.day-chapter.chapter-active h3::after{ width: 100%; }

.day-tags{
  margin-top: 22px;
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}
.day-tags span{
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--onyx-smoke);
  padding-bottom: 4px;
  border-bottom: 1px solid var(--onyx-line-strong);
}

/* dots: mobile fallback only — the clock arc takes over on desktop */
.day-progress{
  display: none;
  position: absolute;
  right: clamp(20px, 6vw, 64px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  flex-direction: column;
  gap: 22px;
}
.day-progress .dot{
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--onyx-line-strong);
  transition: background-color .4s, transform .4s;
}
.day-progress .dot.dot-active{
  background: var(--accent);
  transform: scale(1.6);
}

/* ---------------- the sun's path — a literal day-to-night arc, driven by
   the same scroll progress that switches chapters, plus a sky-wash overlay
   that darkens the whole stage as the day turns to night ---------------- */

.day-sky{
  position: absolute;
  top: clamp(40px, 9vh, 90px);
  right: clamp(24px, 7vw, 80px);
  width: clamp(300px, 30vw, 420px);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 14px;
  pointer-events: none;
}
/* no hard card — just a glow that shifts through the same day → sunset →
   night colors as the sun (set in main.js, right alongside the sun's own
   color) — but sized and saturated enough now to read as the section's
   main visual event, not a small corner accent */
.day-sky-panel{
  position: relative;
  width: 100%;
  height: clamp(150px, 14vw, 190px);
  border-radius: 24px;
  /* deliberately not clipped — the sun's path runs close enough to the
     rounded corners that overflow:hidden would shave its edge off right
     at the start/end of its journey. The rounded shape still reads fine
     purely from the gradient background's own border-radius. */
  background: linear-gradient(180deg, rgba(235,214,181,.08) 0%, rgba(235,214,181,.24) 100%);
  transition: background .5s linear;
}
.day-sky-arc{ position: absolute; inset: 0; display: block; width: 100%; height: 100%; overflow: visible; }
.day-sky-arc path{
  fill: none;
  stroke: rgba(242,236,225,.4);
  stroke-width: 1.75;
  stroke-dasharray: 2 5;
  stroke-linecap: round;
}
/* the line the sun rises from and sets behind — the clearest "this is a
   horizon" cue, now bright enough to actually register at a glance */
.day-horizon{
  position: absolute;
  left: 8%; right: 8%;
  bottom: 12.5%;
  height: 2px;
  background: linear-gradient(90deg, transparent 0%, var(--onyx-line-strong) 25%, var(--onyx-line-strong) 75%, transparent 100%);
}

/* the sun's actual position along the arc is written as a transform by
   main.js (dayTimeline()), computed from .day-sky-panel's real measured
   size every time it changes — NOT a CSS offset-path. offset-path only
   accepts a fixed path() in absolute units, which can't track a panel
   whose width is a fluid clamp(300px,30vw,420px): the drawn arc line (an
   SVG with preserveAspectRatio="none") stretched to fill the panel
   correctly, but the sun's motion stayed locked to a ~220-unit-wide path
   regardless of the panel's real width, so on most viewport widths it
   visibly travelled the wrong distance and ended up in the wrong place.
   A JS-computed transform is also strictly cheaper to update every scroll
   tick than offset-path, which several browsers still resolve off the
   compositor fast path. */
.day-sun{
  position: absolute;
  top: 0; left: 0;
  width: 27px;
  height: 27px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 30px 8px rgba(179,96,58,.6);
  z-index: 2;
  will-change: transform;
}

/* the caption that names the moment — grouped with the visual, not over on
   the chapter text, and its color is driven by main.js from the exact same
   day → sunset → night arc as the sun and the glow behind it. The text
   itself warms and cools with the sky instead of sitting next to it as a
   static label, so the two read as one continuous transition. */
.day-sky-caption{
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: clamp(18px, 2vw, 23px);
  letter-spacing: .01em;
  color: var(--onyx-ivory);
  text-align: right;
  transition: color .5s linear, text-shadow .5s linear;
}

@media (prefers-reduced-motion: reduce){
  .day-sun{ transition: none; }
  .day-sky-panel{ transition: none; }
  .day-sky-caption{ transition: none; }
}

.day-sky-wash{
  position: absolute; inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(5,5,6,0) 0%, rgba(5,5,6,.9) 100%);
  opacity: 0;
  pointer-events: none;
}

/* ---------------- day motto — persistent line, grouped with the sky
   widget (a flex child right under the caption) instead of floating alone
   at the bottom of the stage, so it reads as part of the same composition
   on every breakpoint ---------------- */

.day-motto{
  text-align: right;
  pointer-events: none;
}
.day-motto span{
  font-family: var(--font-sans);
  font-size: clamp(12px, 1.3vw, 15px);
  letter-spacing: .12em;
  line-height: 1.6;
  color: var(--onyx-smoke);
  text-transform: none;
}

/* on short viewports (landscape phones especially) the whole stacked group
   can run tall enough to collide with the vertically-centered chapter text
   — the motto is the least essential line, so it's the one that yields */
@media (max-height: 480px){
  .day-motto{ display: none; }
}

@media (max-width: 860px){
  .day-intro{ grid-template-columns: 1fr; }
  .day-intro p{ justify-self: start; text-align: left; }
  .day-progress{ display: flex; top: 56%; }
  /* nudge the whole composition down a little so nothing sits directly
     behind the fixed nav's buttons at the very top of the screen. Note:
     .day-chapter's own `top` percentage can't do this — it resolves against
     .day-chapters, which renders at 0 height (it only holds absolutely-
     positioned children), so any top:% value on .day-chapter is a no-op.
     The actual vertical centering comes from .day-stage's flex
     align-items:center acting on .day-chapters as a flex item, so a margin
     on that flex item is what actually shifts it. */
  .day-chapters{ margin-top: 48px; }
  /* the sun-arc sweep must stay on mobile too, matching desktop — shrunk,
     and moved well below the fixed nav's Reservieren/Menü buttons, which
     it was previously rendering directly behind (same top-right corner —
     nav floats over the pinned stage since the stage is sticky at top:0).
     Its motion (main.js) re-measures the panel on resize, so only the
     visual size needs a breakpoint override here, not a path. */
  .day-sky{
    top: 108px;
    right: 16px;
    width: 190px;
    gap: 8px;
  }
  .day-sky-panel{ height: 95px; border-radius: 18px; }
  .day-sky-caption{ font-size: 16px; }
  .day-sun{ width: 20px; height: 20px; }
  .day-motto span{ font-size: 11px; line-height: 1.5; }
  .day-chapter h3{ max-width: 12ch; }
}

@media (max-width: 340px){
  /* at the narrowest stress-test width the chapter heading's bounding box
     genuinely reaches far enough right to intersect the sky widget. Shrink
     the widget a little further AND give the chapter text more headroom
     (rather than shrinking the widget down to nothing, which would undercut
     the whole point of this round's change) to clear it properly. */
  .day-sky{ top: 100px; width: 148px; gap: 6px; }
  .day-sky-panel{ height: 72px; border-radius: 14px; }
  .day-sky-caption{ font-size: 13px; }
  .day-sun{ width: 16px; height: 16px; }
  .day-chapters{ margin-top: 150px; }
  /* at this width every right-anchored element (widget, dots) and the
     chapter text are all fighting for the same tight vertical space — the
     dots are the least essential piece (a supplementary progress cue; the
     chapter text + sky widget are the real story), so they're the one that
     yields here rather than chasing an ever-shifting gap between the rest */
  .day-progress{ display: none; }
}

/* ============================================================
   Discover Onyx — a slowly self-scrolling gallery
   The rail drifts sideways on its own (main.js: discoverRail(), a
   requestAnimationFrame loop nudging native scrollLeft), and instantly
   pauses on hover/touch/drag. Because it's driven through real scrollLeft
   on a plain overflow-x:auto element (not a scroll-jacked pin), it's also
   just a normal draggable/swipeable strip the rest of the time — on both
   desktop and mobile — with no dependency on the page's own scroll
   position at all.
   ============================================================ */

.discover{
  position: relative;
  background: var(--onyx-ink);
  padding: 140px 0 120px;
}

.discover-head{
  margin: 0 clamp(20px, 6vw, 64px) 60px;
}
.discover-head h2{
  font-family: var(--font-serif);
  font-weight: 340;
  font-size: clamp(38px, 5vw, 64px);
}

.discover-rail-wrap{
  position: relative;
}

.discover-rail{
  display: flex;
  align-items: center;
  gap: clamp(16px, 2vw, 32px);
  padding: 0 clamp(20px, 6vw, 64px);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  cursor: grab;
  user-select: none;
}
.discover-rail::-webkit-scrollbar{ display: none; }
.discover-rail.is-dragging{ cursor: grabbing; scroll-snap-type: none; }

.discover-panel{
  position: relative;
  display: block;
  flex: 0 0 auto;
  width: min(46vw, 560px);
  height: 62vh;
  min-height: 360px;
  max-height: 560px;
  border-radius: 6px;
  overflow: hidden;
  background: var(--onyx-charcoal);
  box-shadow: 0 30px 60px rgba(0,0,0,.35);
}

.discover-panel-media{
  position: absolute;
  top: -8%; left: 0;
  width: 100%; height: 116%;
  overflow: hidden;
}
.discover-panel-media img{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.08);
  filter: saturate(.85) brightness(.68);
  transition: transform 1s var(--ease-out), filter .6s var(--ease-soft);
  animation: discover-kb 20s ease-in-out infinite alternate;
}
.discover-panel:nth-child(2n) .discover-panel-media img{ animation-duration: 24s; animation-delay: -6s; }
.discover-panel:nth-child(3n) .discover-panel-media img{ animation-duration: 17s; animation-delay: -3s; }
@keyframes discover-kb{
  from{ transform: scale(1.08) translate(0, 0); }
  to{ transform: scale(1.2) translate(-2%, -1.5%); }
}
.discover-panel:hover .discover-panel-media img{
  transform: scale(1.14);
  filter: saturate(1) brightness(.8);
  animation-play-state: paused;
}

.discover-panel::after{
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10,10,10,0) 32%, rgba(10,10,10,.9) 100%);
}

.discover-panel-info{
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 2;
  padding: clamp(24px, 3vw, 44px);
}
.discover-panel-count{
  display: block;
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: .2em;
  color: var(--onyx-smoke-dim);
  margin-bottom: 16px;
}
.discover-panel-info .eyebrow{ display: block; margin-bottom: 10px; }
.discover-panel-info h3{
  font-weight: 330;
  font-size: clamp(32px, 4vw, 60px);
  line-height: 1;
  color: var(--onyx-white);
}
.discover-panel-info p{
  margin-top: 14px;
  font-size: 14px;
  color: var(--onyx-smoke);
  max-width: 34ch;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .4s var(--ease-soft), transform .4s var(--ease-soft);
}
.discover-panel:hover .discover-panel-info p{ opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce){
  .discover-panel-media img{ transition: none; animation: none; }
  .discover-panel-info p{ transition: none; }
}

@media (max-width: 860px){
  .discover{ padding: 100px 0 100px; }
  .discover-head{ margin: 0 clamp(20px, 6vw, 64px) 36px; }

  .discover-rail{
    gap: 14px;
    padding: 0 20px;
    -webkit-overflow-scrolling: touch;
  }
  .discover-panel{
    width: 82vw;
    height: 58vh;
    min-height: 340px;
    max-height: none;
  }
  /* on touch there's no hover — keep the description visible at rest */
  .discover-panel-info p{ opacity: 1; transform: none; }
}

/* ============================================================
   Footer / reserve strip
   ============================================================ */

.reserve-strip{
  position: relative;
  padding: 200px clamp(20px, 6vw, 64px) 160px;
  background: var(--onyx-black);
  overflow: hidden;
  text-align: center;
}
.reserve-strip::before{
  content:'';
  position: absolute;
  inset: 0;
  background: radial-gradient(60% 60% at 50% 30%, rgba(179,96,58,.08), transparent 70%);
}
.reserve-strip .eyebrow{ display:block; margin-bottom: 26px; }
.reserve-strip h2{
  font-family: var(--font-serif);
  font-weight: 320;
  font-size: clamp(48px, 9vw, 140px);
  line-height: .92;
  letter-spacing: -0.01em;
}
.reserve-strip .reserve-cta{
  display: inline-flex;
  align-items: center;
  gap: 16px;
  margin-top: 46px;
  padding: 18px 40px;
  border: 1px solid var(--onyx-line-strong);
  font-size: 12px;
  letter-spacing: .22em;
  text-transform: uppercase;
  transition: background-color .35s, color .35s, border-color .35s;
}
.reserve-strip .reserve-cta:hover{
  background: var(--onyx-ivory);
  color: var(--onyx-black);
}

/* ============================================================
   LEGAL PAGES — Impressum / Datenschutz
   ============================================================ */

.legal-page{
  max-width: 780px;
  margin: 0 auto;
  padding: calc(var(--nav-h) + 64px) clamp(20px, 5vw, 40px) 100px;
}
.legal-page > .eyebrow{ display: block; margin-bottom: 18px; }
.legal-page h1{
  font-family: var(--font-serif);
  font-weight: 320;
  font-size: clamp(40px, 7vw, 64px);
  line-height: .98;
  letter-spacing: -0.01em;
}
.legal-page .legal-updated{
  margin-top: 16px;
  font-size: 12px;
  letter-spacing: .06em;
  color: var(--onyx-smoke-dim);
}

.legal-notice{
  margin-top: 40px;
  padding: 18px 22px;
  border: 1px solid var(--accent-dim);
  border-radius: 10px;
  background: linear-gradient(160deg, rgba(179,96,58,.12) 0%, rgba(179,96,58,.02) 100%);
  font-size: 13.5px;
  line-height: 1.7;
  color: var(--onyx-smoke);
}
.legal-notice strong{ color: var(--accent); }

.legal-body{ margin-top: 48px; }
.legal-body section{ margin-top: 40px; }
.legal-body section:first-child{ margin-top: 0; }
.legal-body h2{
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(20px, 2.6vw, 26px);
  color: var(--onyx-ivory);
  margin-bottom: 14px;
}
.legal-body h3{
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--onyx-ivory);
  margin: 20px 0 8px;
}
.legal-body p, .legal-body li{
  font-family: var(--font-sans);
  font-size: 14.5px;
  line-height: 1.8;
  color: var(--onyx-smoke);
  max-width: 68ch;
}
.legal-body p + p{ margin-top: 12px; }
.legal-body ul{ margin: 10px 0; padding-left: 20px; }
.legal-body li{ margin: 6px 0; }
.legal-body a{ color: var(--onyx-ivory); text-decoration: underline; text-underline-offset: 2px; }
.legal-body a:hover{ color: var(--accent); }

/* every business-specific fact the owner still needs to fill in is
   wrapped in this — impossible to miss, and greppable (search the html
   for "placeholder") before the site goes live */
.legal-placeholder{
  display: inline;
  background: rgba(179,96,58,.16);
  color: var(--accent);
  border: 1px solid var(--accent-dim);
  border-radius: 4px;
  padding: 1px 6px;
  font-weight: 600;
}

@media (max-width: 640px){
  .legal-page{ padding-top: calc(var(--nav-h-scrolled) + 40px); }
}

/* ============================================================
   SITE FOOTER — one shared component (js/footer.js) injected into
   every page's <div id="siteFooter">, so it is byte-for-byte identical
   everywhere. Three quiet groups on a single top line (brand+address,
   page links, legal links), a hairline rule, then a small copyright
   line — nothing louder than that.
   ============================================================ */

.site-footer{
  border-top: 1px solid var(--onyx-line);
  background: var(--onyx-black);
}

.footer-top{
  max-width: 1400px;
  margin: 0 auto;
  padding: 56px clamp(20px, 6vw, 64px) 32px;
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 32px;
  align-items: start;
}
/* Coming Soon page: no .footer-nav group, so only 2 columns are needed —
   without this the 3-column grid leaves a visibly empty gap */
.footer-top.is-simple{
  grid-template-columns: 1.4fr 1fr;
}

/* align-items:flex-start — without it, the flex column's default
   (stretch) forces the logo <img> to fill the full column width, which
   fights its own aspect ratio and reads as a stretched/squashed wordmark */
.footer-brand{ display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.footer-logo{ height: 26px; width: auto; flex: none; opacity: .92; }
.footer-brand address{
  font-style: normal;
  font-size: 12.5px;
  line-height: 1.6;
  letter-spacing: .02em;
  color: var(--onyx-smoke-dim);
}

.footer-hours{ display: flex; flex-direction: column; gap: 3px; }
.footer-hours-label{
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--onyx-smoke-dim);
}
.footer-hours-value{
  font-size: 12.5px;
  letter-spacing: .02em;
  color: var(--onyx-smoke-dim);
}

.footer-social{ display: flex; align-items: center; gap: 10px; }
.footer-social a{
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--onyx-line-strong);
  color: var(--onyx-smoke);
  transition: color .3s var(--ease-soft), border-color .3s var(--ease-soft);
}
.footer-social a:hover{ color: var(--onyx-ivory); border-color: var(--onyx-ivory); }
.footer-social svg{ width: 16px; height: 16px; display: block; fill: currentColor; }

.footer-nav,
.footer-legal{ display: flex; flex-direction: column; gap: 13px; }
.footer-nav a,
.footer-legal a,
.footer-legal button{
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--onyx-smoke);
  text-align: left;
  transition: color .3s var(--ease-soft);
}
/* .footer-legal button (the "Cookie-Einstellungen" trigger) inherits the
   shared rule above for font/color/spacing, but a <button> still carries
   the browser's own native padding/margin/line-height on top of that —
   unlike the <a> tags beside it, which have none — so without zeroing
   those out here it renders visibly fatter and misaligned against its
   siblings even though the text styling matches exactly. */
.footer-legal button{
  padding: 0;
  margin: 0;
  border: none;
  line-height: inherit;
  display: inline;
}
.footer-nav a:hover,
.footer-legal a:hover,
.footer-legal button:hover{ color: var(--onyx-ivory); }

.footer-bottom{
  max-width: 1400px;
  margin: 0 auto;
  padding: 20px clamp(20px, 6vw, 64px) 28px;
  border-top: 1px solid var(--onyx-line);
}
.footer-bottom span{
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: .06em;
  color: var(--onyx-smoke-dim);
}

@media (max-width: 720px){
  .footer-top{
    grid-template-columns: 1fr;
    gap: 36px;
    padding: 48px clamp(20px, 6vw, 40px) 28px;
    text-align: center;
  }
  .footer-brand{ align-items: center; }
  .footer-nav,
  .footer-legal{ align-items: center; gap: 16px; }
  .footer-bottom{ text-align: center; padding-left: 20px; padding-right: 20px; }
}

/* ============================================================
   Menu page
   ============================================================ */

.menu-hero{
  position: relative;
  min-height: 62vh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 0 clamp(20px, 6vw, 64px) 90px;
  overflow: hidden;
}
.menu-hero-bg{
  position: absolute; inset: 0;
  z-index: 0;
}
.menu-hero-bg img{
  width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(.25) brightness(.55);
  transform: scale(1.05);
}
.menu-hero-bg::after{
  content:'';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10,10,10,.55) 0%, rgba(10,10,10,.35) 40%, var(--onyx-black) 100%);
}
.menu-hero-copy{ position: relative; z-index: 2; }
.menu-hero-copy .eyebrow{ display: block; margin-bottom: 20px; }
.menu-hero-copy h1{
  font-family: var(--font-serif);
  font-weight: 320;
  font-size: clamp(60px, 13vw, 180px);
  line-height: .86;
}

.menu-shell{
  position: relative;
  display: grid;
  grid-template-columns: 84px 1fr;
  background: var(--onyx-black);
}

.menu-rail{
  position: sticky;
  top: var(--nav-h);
  align-self: start;
  height: calc(100vh - var(--nav-h));
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 30px;
  padding: 20px 0;
  border-right: 1px solid var(--onyx-line);
}
.menu-rail button{
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 11px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--onyx-smoke-dim);
  text-align: left;
  transition: color .4s var(--ease-soft);
  padding: 4px 0;
}
.menu-rail button:hover{ color: var(--onyx-smoke); }
.menu-rail button.rail-active{ color: var(--onyx-ivory); }

.menu-content{ min-width: 0; }

.menu-cat{
  position: relative;
  padding: 120px clamp(20px, 5vw, 64px) 40px;
  background: var(--onyx-black);
  transition: background-color .6s var(--ease-soft);
}
.menu-cat[data-cat="matcha"]{ background: linear-gradient(180deg, #12160e 0%, var(--onyx-black) 70%); }
.menu-cat[data-cat="acai"]{ background: linear-gradient(180deg, #150f17 0%, var(--onyx-black) 70%); }
.menu-cat[data-cat="coffee"]{ background: linear-gradient(180deg, #18120b 0%, var(--onyx-black) 70%); }
.menu-cat[data-cat="tea"]{ background: linear-gradient(180deg, #141310 0%, var(--onyx-black) 70%); }
.menu-cat[data-cat="desserts"]{ background: linear-gradient(180deg, #1a140c 0%, var(--onyx-black) 70%); }
.menu-cat[data-cat="cocktails"]{ background: linear-gradient(180deg, #180c10 0%, var(--onyx-black) 70%); }
.menu-cat[data-cat="shisha"]{ background: linear-gradient(180deg, #0d0d0d 0%, #050505 70%); }

.menu-cat-grid{
  display: grid;
  grid-template-columns: minmax(220px, 400px) 1fr;
  gap: clamp(24px, 4vw, 64px);
  align-items: start;
}

.menu-cat-label{
  position: sticky;
  top: calc(var(--nav-h) + 60px);
  min-width: 0;
}
.menu-cat-label .eyebrow{ display: block; margin-bottom: 18px; }
.menu-cat-label h2{
  font-family: var(--font-serif);
  font-weight: 320;
  font-size: clamp(38px, 5vw, 72px);
  line-height: .96;
  overflow-wrap: break-word;
  hyphens: auto;
}
.menu-cat-label p{
  margin-top: 20px;
  font-size: 14px;
  color: var(--onyx-smoke);
  max-width: 26ch;
  line-height: 1.7;
}

.menu-cat-products{ display: flex; flex-direction: column; }

.menu-item{
  display: grid;
  grid-template-columns: minmax(180px, 40%) 1fr;
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
  padding: 56px 0;
  border-top: 1px solid var(--onyx-line);
  cursor: pointer;
}
.menu-cat-products .menu-item:first-child{ border-top: none; }

.menu-item-media{
  position: relative;
  aspect-ratio: 4/5;
  overflow: hidden;
  background: var(--onyx-charcoal);
}
.menu-item-media img{
  width: 100%; height: 100%; object-fit: cover;
  transform: scale(1.08);
  transition: transform 1.1s var(--ease-out), filter .6s;
  filter: saturate(.92) brightness(.92);
}
.menu-item:hover .menu-item-media img{ transform: scale(1); filter: saturate(1) brightness(1); }

/* a product image that fails to load (missing file, typo'd path in
   menu-data.js) falls back to this quiet mark instead of a broken-image
   icon — the box itself already has a fixed aspect-ratio, so nothing
   shifts either way */
.menu-item-media.img-missing::after,
.product-overlay-media.img-missing::after{
  content: 'ONYX';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-serif);
  font-size: 13px;
  letter-spacing: .3em;
  color: var(--onyx-smoke-dim);
}

.menu-error{
  padding: 120px clamp(20px, 5vw, 64px);
  text-align: center;
  color: var(--onyx-smoke);
  font-size: 15px;
  line-height: 1.8;
}
.menu-error-hint{ margin-top: 8px; font-size: 13px; color: var(--onyx-smoke-dim); }

.menu-item-index{
  font-size: 11px;
  letter-spacing: .16em;
  color: var(--onyx-smoke-dim);
  display: block;
  margin-bottom: 14px;
}
.menu-item-info h3{
  font-family: var(--font-serif);
  font-weight: 340;
  font-size: clamp(28px, 3.4vw, 44px);
  line-height: 1.08;
}
.menu-item-info .featured-mark{
  display: inline-block;
  margin-left: 12px;
  font-size: 10px;
  letter-spacing: .18em;
  color: var(--accent);
  vertical-align: middle;
  border: 1px solid var(--accent-dim);
  padding: 3px 8px;
  border-radius: 2px;
}
.menu-item-info p{
  margin-top: 16px;
  font-size: 14px;
  line-height: 1.7;
  color: var(--onyx-smoke);
  max-width: 46ch;
}
/* a generic list of option labels on a product — Shisha flavors shown
   under one photo instead of one product per flavor, a drink/dessert's
   size or topping choice, whatever the admin panel's "Optionen" field on
   that product is set to. Hidden entirely (not just empty) when a
   product has none, same pattern as .allergens below. */
.menu-item-options{
  margin-top: 10px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--onyx-smoke);
  max-width: 46ch;
}
.menu-item-options span{
  color: var(--onyx-smoke-dim);
  letter-spacing: .06em;
  text-transform: uppercase;
  font-size: 10.5px;
  margin-right: 4px;
}
.menu-item-options:empty{ display: none; }

.menu-item-bottom{
  margin-top: 24px;
  display: flex;
  align-items: center;
  gap: 20px;
}
.menu-item-price{
  font-family: var(--font-serif);
  font-size: 20px;
  color: var(--onyx-ivory);
}
.menu-item-tags{ display: flex; gap: 12px; flex-wrap: wrap; }
.menu-item-tags span{
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--onyx-smoke-dim);
}

@media (max-width: 860px){
  .menu-shell{ grid-template-columns: 1fr; }
  /* a slim, editorial text-tab bar instead of app-style pill chips — all
     seven categories at once, anchored to the bottom of the screen */
  .menu-rail{
    position: fixed;
    top: auto; bottom: 0; left: 0; right: 0;
    height: auto;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    row-gap: 2px;
    column-gap: clamp(18px, 5vw, 30px);
    padding: 8px clamp(20px, 6vw, 40px);
    background: rgba(10,10,10,.97);
    backdrop-filter: blur(14px);
    border-right: none;
    border-top: 1px solid var(--onyx-line);
    z-index: 250;
    overflow: visible;
  }
  .menu-rail button{
    writing-mode: horizontal-tb;
    transform: none;
    white-space: nowrap;
    flex: none;
    position: relative;
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 11px 1px;
    font-size: 11px;
    letter-spacing: .16em;
    color: var(--onyx-smoke-dim);
    transition: color .3s var(--ease-soft);
  }
  .menu-rail button::after{
    content: '';
    position: absolute;
    left: 1px; right: 1px; bottom: 7px;
    height: 1px;
    background: var(--accent);
    transform: scaleX(0);
    transition: transform .35s var(--ease-soft);
  }
  .menu-rail button.rail-active{ color: var(--onyx-ivory); }
  .menu-rail button.rail-active::after{ transform: scaleX(1); }

  /* the rail is fixed at the bottom again — give the product list room so
     the last cards in each category aren't hidden behind it */
  .menu-content{ padding-bottom: 130px; }
  .menu-cat{ scroll-margin-top: 84px; }
  .menu-cat-grid{ grid-template-columns: 1fr; }
  .menu-cat-label{ position: static; margin-bottom: 30px; }
  .menu-item{ grid-template-columns: 1fr; }
}

@media (max-width: 640px){
  /* compact horizontal image+text cards — target ~4 visible per screen */
  .menu-item{
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 14px;
    padding: 14px 0;
  }
  .menu-item-media{
    width: 92px;
    height: 92px;
    aspect-ratio: auto;
    flex: 0 0 92px;
    border-radius: 4px;
    overflow: hidden;
  }
  .menu-item-info{
    flex: 1;
    min-width: 0;
  }
  .menu-item-index{ display: none; }
  .menu-item-info h3{
    font-size: 15px;
    line-height: 1.25;
  }
  .menu-item-info .featured-mark{
    margin-left: 8px;
    font-size: 9px;
    padding: 2px 6px;
  }
  .menu-item-info p{
    margin-top: 4px;
    font-size: 12px;
    line-height: 1.4;
    max-width: none;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .menu-item-bottom{
    margin-top: 6px;
    gap: 10px;
    flex-wrap: wrap;
  }
  .menu-item-price{ font-size: 13px; }
  .menu-item-tags{ gap: 8px; }
  .menu-item-tags span{ font-size: 9px; }
}

/* ---------------- product overlay ---------------- */
.product-overlay{
  position: fixed;
  inset: 0;
  z-index: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 64px);
  opacity: 0;
  pointer-events: none;
  transition: opacity .4s var(--ease-soft);
}
.product-overlay.overlay-active{ opacity: 1; pointer-events: auto; }
.product-overlay-backdrop{
  position: absolute; inset: 0;
  background: rgba(6,6,6,.88);
  backdrop-filter: blur(6px);
}
.product-overlay-panel{
  position: relative;
  z-index: 2;
  width: min(1000px, 100%);
  max-height: 88vh;
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  background: var(--onyx-ink);
  border: 1px solid var(--onyx-line);
  overflow: hidden;
  transform: translateY(24px);
  opacity: 0;
  transition: transform .5s var(--ease-out), opacity .5s var(--ease-out);
}
.overlay-active .product-overlay-panel{ transform: translateY(0); opacity: 1; }

.product-overlay-media{ position: relative; overflow: hidden; background: var(--onyx-charcoal); }
.product-overlay-media img{
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.product-overlay-info{
  padding: clamp(28px, 4vw, 56px);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}
.product-overlay-info .eyebrow{ display: block; margin-bottom: 20px; }
.product-overlay-info h3{
  font-family: var(--font-serif);
  font-weight: 320;
  font-size: clamp(28px, 3.6vw, 42px);
  line-height: 1.08;
}
.product-overlay-info p.desc{
  margin-top: 20px;
  font-size: 15px;
  line-height: 1.8;
  color: var(--onyx-smoke);
}
.product-overlay-info .price-row{
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid var(--onyx-line);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.product-overlay-info .price{
  font-family: var(--font-serif);
  font-size: 26px;
}
.product-overlay-info .allergens{
  margin-top: 18px;
  font-size: 12px;
  color: var(--onyx-smoke-dim);
  letter-spacing: .02em;
}
.product-overlay-close{
  position: absolute;
  top: 20px; right: 20px;
  z-index: 3;
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 1px solid var(--onyx-line-strong);
  display: flex; align-items: center; justify-content: center;
  color: var(--onyx-ivory);
  transition: background-color .3s;
}
.product-overlay-close:hover{ background: rgba(255,255,255,.08); }

@media (max-width: 720px){
  .product-overlay-panel{ grid-template-columns: 1fr; max-height: 92vh; }
  .product-overlay-media{ height: 40vh; }
}

/* ============================================================
   Coming soon — standalone teaser page
   ============================================================ */

.coming-soon{
  position: relative;
  min-height: 100vh;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  background: var(--onyx-black);
}
.coming-soon-video{
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.coming-soon-overlay{
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(10,10,10,.6) 0%, rgba(10,10,10,.28) 45%, rgba(10,10,10,.6) 100%);
  pointer-events: none;
}
.coming-soon-content{
  position: relative;
  z-index: 2;
  padding: 0 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.coming-soon-logo{
  height: clamp(40px, 5vw, 60px);
  width: auto;
  margin-bottom: 32px;
  opacity: .92;
}
.coming-soon-eyebrow{ display: block; margin-bottom: 14px; }
.coming-soon-content h1{
  font-family: var(--font-serif);
  font-weight: 340;
  font-size: clamp(40px, 6vw, 80px);
  line-height: 1.05;
  color: var(--onyx-ivory);
}
.coming-soon-content p{
  margin-top: 22px;
  max-width: 46ch;
  font-size: 15px;
  line-height: 1.75;
  color: var(--onyx-smoke);
}
/* the "this is when it starts, not when it closes" statement — deliberately
   its own line right under the headline (not folded into the paragraph
   below), in the accent color and uppercase like the site's eyebrow labels
   but bolder and larger, so the date reads as the headline's payoff, not
   a footnote */
/* qualified as .coming-soon-content p.coming-soon-date (not just
   .coming-soon-date) so it safely outweighs .coming-soon-content p's
   own specificity — otherwise that rule's smoke-gray/15px/22px-margin
   would win over this one for every property they share */
.coming-soon-content p.coming-soon-date{
  margin-top: 18px;
  max-width: 32ch;
  font-family: var(--font-sans);
  font-size: clamp(15px, 1.8vw, 18px);
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--accent);
}
.coming-soon-content address{
  margin-top: 36px;
  font-style: normal;
  font-size: 13px;
  letter-spacing: .04em;
  line-height: 1.9;
  color: var(--onyx-smoke);
}
.coming-soon-content address a:hover{ color: var(--onyx-ivory); }

.coming-soon-cta{
  display: inline-block;
  margin-top: 28px;
  background: var(--accent);
  color: var(--onyx-white);
  border-radius: 6px;
  padding: 12px 26px;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  transition: background-color .3s var(--ease-soft), transform .2s;
}
.coming-soon-cta:hover{ background: var(--accent-dim); transform: translateY(-1px); }

/* ============================================================
   CHALLENGE — online practice game vs. the physical Fun4Four
   competition at ONYX. Two distinct cards up top spell out which is
   which; the board below is read-only and pulled live from
   api/leaderboard.php (js/challenge.js) — it only ever reflects scores
   the admin panel entered by hand, never anything the practice game does.
   ============================================================ */

.challenge{
  position: relative;
  background: var(--onyx-ink);
  padding: 140px clamp(20px, 6vw, 64px) 120px;
}

.challenge-head{
  max-width: 640px;
  margin: 0 auto 64px;
  text-align: center;
}
.challenge-head .eyebrow{ display: block; margin-bottom: 18px; }
.challenge-head h2{
  font-size: clamp(38px, 5vw, 64px);
  line-height: 1.02;
}
.challenge-head p{
  margin-top: 22px;
  font-size: 15px;
  line-height: 1.75;
  color: var(--onyx-smoke);
}

.challenge-grid{
  max-width: 1080px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(16px, 2.4vw, 28px);
}

.challenge-card{
  padding: clamp(28px, 3vw, 40px);
  border: 1px solid var(--onyx-line);
  border-radius: 14px;
  background: var(--onyx-charcoal);
  display: flex;
  flex-direction: column;
}
.challenge-card.is-live{
  background: linear-gradient(160deg, rgba(179,96,58,.14) 0%, var(--onyx-charcoal) 60%);
  border-color: var(--accent-dim);
}
.challenge-card .eyebrow{ display: block; margin-bottom: 16px; }
.challenge-card h3{
  font-size: clamp(24px, 2.6vw, 32px);
  line-height: 1.08;
}
.challenge-card p{
  margin-top: 16px;
  font-size: 14px;
  line-height: 1.7;
  color: var(--onyx-smoke);
  flex-grow: 1;
}

.challenge-cta{
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 24px;
  align-self: flex-start;
  background: var(--accent);
  color: var(--onyx-white);
  border-radius: 6px;
  padding: 13px 24px;
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  transition: background-color .3s var(--ease-soft), transform .2s;
}
.challenge-cta:hover{ background: var(--accent-dim); transform: translateY(-1px); }
.challenge-cta.challenge-cta-ghost{
  background: transparent;
  color: var(--onyx-ivory);
  border: 1px solid var(--onyx-line-strong);
}
.challenge-cta.challenge-cta-ghost:hover{ background: rgba(255,255,255,.06); border-color: var(--onyx-ivory); }

.challenge-footnote{
  display: block;
  margin-top: 14px;
  font-size: 11.5px;
  letter-spacing: .02em;
  line-height: 1.6;
  color: var(--onyx-smoke-dim);
}

/* ---------------- leaderboard + prize ----------------
   .challenge-board carries the admin-uploaded background image (inline
   style, set by js/challenge.js) at full bleed; .board-overlay sits on top
   with a dark gradient wash for text contrast, and lays out the prize
   badge beside the leaderboard so the two read as one composition instead
   of two separate widgets bolted together. */

.challenge-board{
  position: relative;
  max-width: 1080px;
  margin: clamp(56px, 6vw, 84px) auto 0;
  border-radius: 18px;
  overflow: hidden;
  background-color: var(--onyx-black);
  background-size: cover;
  background-position: center;
  border: 1px solid var(--onyx-line);
}

.board-loading, .board-empty{
  text-align: center;
  color: var(--onyx-smoke-dim);
  font-size: 13.5px;
  padding: 40px 20px;
}

.board-overlay{
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: clamp(28px, 4vw, 52px);
  align-items: center;
  padding: clamp(32px, 4vw, 52px);
  /* subtle, elegant wash rather than a flat scrim — keeps a bright uploaded
     photo readable underneath without flattening it to a black box */
  background: linear-gradient(115deg, rgba(8,7,6,.85) 0%, rgba(10,9,8,.72) 45%, rgba(10,9,8,.6) 100%);
}
.challenge-board:not(.has-bg) .board-overlay{
  background: none;
}

/* ---- prize badge: a rotating circular seal with the prize image at its
   core — the "COMPETITION → TOP SCORE → iPhone" read happens by tracing
   the ring text around the image itself, the same circular-text technique
   as .scroll-badge-ring elsewhere on the page. ---- */

.board-prize{
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
}

.prize-badge{
  position: relative;
  width: 100%;
  max-width: 220px;
  aspect-ratio: 1 / 1;
}
.prize-badge::before{
  content: '';
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 42%, rgba(179,96,58,.55), rgba(179,96,58,0) 72%);
  filter: blur(6px);
}
.prize-badge-ring{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  animation: prize-badge-spin 26s linear infinite;
}
.prize-badge-ring text{
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .16em;
  fill: var(--onyx-ivory);
}
.prize-badge-core{
  position: absolute;
  inset: 16%;
  border-radius: 50%;
  background: radial-gradient(140% 140% at 50% 20%, #2a221b 0%, var(--onyx-black) 68%);
  border: 1px solid var(--onyx-line-strong);
  box-shadow: 0 0 0 1px rgba(179,96,58,.25), 0 18px 40px rgba(0,0,0,.55);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
/* fills the circle edge-to-edge (cover + no padding) rather than sitting
   as a small, letterboxed image inside it — cropping is expected/fine
   here since the frame is round and the upload is whatever shape it is */
.prize-badge-core img{ width: 100%; height: 100%; object-fit: cover; object-position: center; }
.prize-badge-fallback{
  font-family: var(--font-serif);
  font-size: 13px;
  letter-spacing: .1em;
  color: var(--onyx-smoke);
  text-align: center;
}

.prize-badge-flag{
  display: inline-block;
  background: var(--accent);
  color: var(--onyx-white);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: 7px 16px;
  border-radius: 999px;
}
.prize-badge-title{
  font-family: var(--font-serif);
  font-size: clamp(19px, 2vw, 23px);
  font-weight: 500;
  color: var(--onyx-white);
}

/* ---- 2nd/3rd place: quieter supporting circles beside the main badge —
   no rotating ring, smaller, so the podium reads at a glance without
   competing with the 1st-place seal for attention. Either or both are
   absent whenever the admin hasn't set that prize (see challenge.js). ---- */

.prize-podium{
  display: flex;
  gap: clamp(16px, 3vw, 28px);
  margin-top: 8px;
}
.prize-podium-item{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  max-width: 92px;
}
.prize-podium-circle{
  width: 56px;
  height: 56px;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  background: radial-gradient(140% 140% at 50% 20%, #241d17 0%, var(--onyx-black) 68%);
  border: 1px solid var(--onyx-line-strong);
  box-shadow: 0 10px 22px rgba(0,0,0,.4);
  display: flex;
  align-items: center;
  justify-content: center;
}
.prize-podium-circle img{ width: 100%; height: 100%; object-fit: cover; object-position: center; }
.prize-podium-fallback{
  font-family: var(--font-serif);
  font-size: 9px;
  letter-spacing: .06em;
  color: var(--onyx-smoke-dim);
  text-align: center;
  padding: 0 4px;
}
.prize-podium-label{
  font-family: var(--font-sans);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--onyx-smoke);
}
.prize-podium-title{
  font-family: var(--font-sans);
  font-size: 11.5px;
  line-height: 1.3;
  color: var(--onyx-ivory);
  text-align: center;
}

@keyframes prize-badge-spin{
  from{ transform: rotate(0); }
  to{ transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce){
  .prize-badge-ring{ animation: none; }
}

/* ---- leaderboard content, beside the badge ---- */

.board-content{ min-width: 0; }

.board-head{
  padding-bottom: 24px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--onyx-line);
}
.board-head .eyebrow{ display: block; margin-bottom: 12px; }
.board-head h3{
  font-size: clamp(22px, 2.8vw, 32px);
  line-height: 1.08;
  letter-spacing: .01em;
  color: var(--onyx-white);
}
.board-dates{
  display: inline-block;
  margin-top: 10px;
  font-size: 12px;
  letter-spacing: .08em;
  color: var(--accent);
  font-weight: 600;
}

.board-list{
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
}
.board-list li{
  display: grid;
  grid-template-columns: 32px 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 13px 4px;
  border-bottom: 1px solid var(--onyx-line);
  font-size: 14px;
}
.board-list li:last-child{ border-bottom: none; }
.board-list li.is-first .board-rank{ color: var(--accent); }
.board-list li.is-first .board-name{ color: var(--onyx-white); font-weight: 600; }
.board-rank{
  font-family: var(--font-serif);
  font-size: 17px;
  color: var(--onyx-smoke-dim);
}
.board-name{ color: var(--onyx-ivory); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-score{ font-variant-numeric: tabular-nums; font-weight: 600; color: var(--onyx-ivory); }

@media (max-width: 860px){
  .challenge{ padding: 100px clamp(20px, 6vw, 64px) 90px; }
  .challenge-head{ margin-bottom: 44px; }
  .challenge-grid{ grid-template-columns: 1fr; }
  .board-overlay{ grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .prize-badge{ max-width: 180px; }
}
