/* ============================================================================
   illos.css — design tokens + the animation system
   ----------------------------------------------------------------------------
   Tailwind (loaded from the CDN) handles layout and spacing. This file owns
   the two things utility classes cannot express well: the brand's visual
   identity, and motion.

   Motion here is treated as a feature, not decoration:
     • Scroll reveals driven by IntersectionObserver (see assets/js/illos.js),
       so nothing animates until it is actually on screen.
     • Every effect is GPU-friendly — transform and opacity only, never
       width/top/left, which cause layout thrash on mid-range Android.
     • Every animation is disabled under prefers-reduced-motion. This is not
       optional politeness: motion sickness is real, and iOS/Android expose
       the setting prominently.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   1. TOKENS
   ------------------------------------------------------------------------- */
:root {
  --gold:          #D4AF37;
  --gold-soft:     #E8CD70;
  --gold-deep:     #A8862A;
  --ink:           #0A0A0A;
  --ink-2:         #141414;
  --ink-3:         #1E1E1E;
  --line:          rgba(212, 175, 55, 0.18);
  --paper:         #FAF8F3;
  --muted:         #9A9A9A;

  --font-display:  'Cormorant Garamond', 'Playfair Display', Georgia, serif;
  --font-body:     'Poppins', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --ease-out:      cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out:   cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring:   cubic-bezier(0.34, 1.56, 0.64, 1);

  --nav-h:         76px;
}

/* ---------------------------------------------------------------------------
   2. BASE
   ------------------------------------------------------------------------- */
* { -webkit-tap-highlight-color: transparent; }

html { scroll-behavior: smooth; }
/* An in-page jump must not hide the target under the fixed navbar. */
html { scroll-padding-top: var(--nav-h); }

body {
  font-family: var(--font-body);
  background-color: var(--ink);
  color: #EDEDED;
  overflow-x: hidden;
  /* Stops iOS Safari inflating font sizes in landscape. */
  -webkit-text-size-adjust: 100%;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, .display { font-family: var(--font-display); font-weight: 600; }

::selection { background: var(--gold); color: #000; }

/* Scrollbar — Chromium/WebKit, then Firefox. */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--ink-2); }
::-webkit-scrollbar-thumb {
  background: linear-gradient(var(--gold-deep), var(--gold));
  border-radius: 99px;
  border: 2px solid var(--ink-2);
}
::-webkit-scrollbar-thumb:hover { background: var(--gold-soft); }
* { scrollbar-width: thin; scrollbar-color: var(--gold-deep) var(--ink-2); }

/* Used by the category rail and mini-cart, which scroll but must look clean. */
.hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
.hide-scrollbar::-webkit-scrollbar { display: none; }

/* Visible keyboard focus. Removing outlines without a replacement makes a
   site unusable by keyboard, so this restores an on-brand one. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---------------------------------------------------------------------------
   3. ANIMATED BACKGROUND  —  "Golden Ember Drift"
   ---------------------------------------------------------------------------
   The site is dark-only, so the background is doing real work: on a flat black
   page every section boundary looks like a seam. These layers keep the black
   alive without ever competing with the food photography.

   Seven layers, all pure CSS — no canvas, no JS, no image requests:

     .bg-stage    the fixed container; owns the base ink gradient, which is
                  warmer at the top so the page is never a dead flat black
     .bg-orbs     three large gold light pools, each on its OWN path and its
                  own duration. Three separate loops of different lengths never
                  line back up, so the motion never looks like a short GIF
     .bg-beams    a very slow conic sweep — a light turning across the room
     .bg-aurora   the original drifting pools, kept as the mid-tone wash
     .bg-mesh     a faint grid, panning, that gives the black some depth
     .bg-embers   slow rising sparks — the movement the eye actually catches
     .bg-grain    a film-grain veil that stops the gradients banding
     .bg-vignette darkened edges so content in the middle stays the focus

   Everything animates on transform / opacity / background-position only, so
   the compositor handles it on the GPU and the main thread stays free for
   scrolling. Nothing here paints above z-index -1 and nothing takes pointer
   events, so no layer can ever intercept a tap on a button.
   ------------------------------------------------------------------------- */
.bg-stage {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  /* Static on purpose. Animating a gradient on a full-viewport element means
     repainting the entire screen every frame; the orbs and beams below give
     the same impression using transforms, which the GPU handles for free. */
  background:
    radial-gradient(120% 90% at 50% -10%, #16130B 0%, transparent 58%),
    linear-gradient(175deg, #0C0B08 0%, #0A0A0A 46%, #08070A 100%);
}

/* --- Orbs: the main sense of movement -------------------------------------- */
.bg-orbs { position: absolute; inset: 0; }

.bg-orbs i {
  position: absolute;
  display: block;
  border-radius: 50%;
  filter: blur(70px);
  will-change: transform;
  opacity: 0.55;
}

.bg-orbs i:nth-child(1) {
  width: 46vw; height: 46vw;
  top: -8%; left: -6%;
  background: radial-gradient(circle, rgba(212,175,55,0.30), transparent 68%);
  animation: orb-a 38s var(--ease-in-out) infinite alternate;
}
.bg-orbs i:nth-child(2) {
  width: 40vw; height: 40vw;
  top: 34%; right: -10%; left: auto;
  background: radial-gradient(circle, rgba(168,134,42,0.26), transparent 68%);
  animation: orb-b 47s var(--ease-in-out) infinite alternate;
}
.bg-orbs i:nth-child(3) {
  width: 52vw; height: 52vw;
  bottom: -18%; left: 22%;
  background: radial-gradient(circle, rgba(232,205,112,0.18), transparent 70%);
  animation: orb-c 59s var(--ease-in-out) infinite alternate;
}

/* Different distances AND different durations — the three never resynchronise. */
@keyframes orb-a {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(14vw, 9vh, 0) scale(1.16); }
  100% { transform: translate3d(5vw, 20vh, 0) scale(0.94); }
}
@keyframes orb-b {
  0%   { transform: translate3d(0, 0, 0) scale(1.04); }
  50%  { transform: translate3d(-16vw, -11vh, 0) scale(0.9); }
  100% { transform: translate3d(-6vw, 12vh, 0) scale(1.2); }
}
@keyframes orb-c {
  0%   { transform: translate3d(0, 0, 0) scale(0.96); }
  50%  { transform: translate3d(11vw, -14vh, 0) scale(1.18); }
  100% { transform: translate3d(-9vw, -5vh, 0) scale(1.02); }
}

/* --- Beams: a slow turning light ------------------------------------------- */
.bg-beams {
  position: absolute;
  top: 50%; left: 50%;
  width: 165vmax; height: 165vmax;
  margin: -82.5vmax 0 0 -82.5vmax;
  background: conic-gradient(
    from 0deg,
    transparent 0deg,
    rgba(212,175,55,0.075) 18deg,
    transparent 46deg,
    transparent 150deg,
    rgba(232,205,112,0.055) 176deg,
    transparent 210deg,
    transparent 300deg,
    rgba(168,134,42,0.06) 326deg,
    transparent 356deg
  );
  /* Softened at the centre, faded at the rim — otherwise it reads as a pie chart. */
  mask-image: radial-gradient(circle, transparent 4%, #000 34%, transparent 76%);
  -webkit-mask-image: radial-gradient(circle, transparent 4%, #000 34%, transparent 76%);
  filter: blur(26px);
  animation: beams-turn 120s linear infinite;
  will-change: transform;
}

@keyframes beams-turn {
  to { transform: rotate(360deg); }
}

/* --- Aurora: the original mid-tone wash, kept ------------------------------ */
.bg-aurora {
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(38% 44% at 18% 22%, rgba(212, 175, 55, 0.13), transparent 62%),
    radial-gradient(32% 38% at 82% 30%, rgba(168, 134, 42, 0.11), transparent 60%),
    radial-gradient(44% 46% at 50% 88%, rgba(232, 205, 112, 0.08), transparent 66%);
  filter: blur(18px);
  animation: aurora-drift 34s var(--ease-in-out) infinite alternate;
  will-change: transform;
}

@keyframes aurora-drift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(-3%, 2.5%, 0) scale(1.09); }
  100% { transform: translate3d(2.5%, -2%, 0) scale(1.04); }
}

/* --- Mesh: panning grid ---------------------------------------------------- */
.bg-mesh {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(212, 175, 55, 0.042) 1px, transparent 1px),
    linear-gradient(90deg, rgba(212, 175, 55, 0.042) 1px, transparent 1px);
  background-size: 68px 68px;
  /* Fades the grid out toward the edges so it never looks like a table. */
  mask-image: radial-gradient(circle at 50% 40%, #000 10%, transparent 76%);
  -webkit-mask-image: radial-gradient(circle at 50% 40%, #000 10%, transparent 76%);
  animation: mesh-pan 60s linear infinite;
}

@keyframes mesh-pan {
  to { background-position: 68px 68px, 68px 68px; }
}

/* --- Embers: slow rising sparks -------------------------------------------- */
/* Each <i> carries its own --x (start column), --dur, --delay, --size and
   --drift from the markup, so eighteen spans give eighteen distinct paths from
   one keyframe. Writing them as one animation keeps the CSS short and lets the
   compositor run every one of them off the main thread. */
.bg-embers { position: absolute; inset: 0; overflow: hidden; }

.bg-embers i {
  position: absolute;
  bottom: -6vh;
  left: var(--x, 50%);
  width: var(--size, 3px);
  height: var(--size, 3px);
  border-radius: 50%;
  background: var(--gold-soft);
  box-shadow: 0 0 6px rgba(212, 175, 55, 0.85);
  opacity: 0;
  animation: ember-rise var(--dur, 22s) linear var(--delay, 0s) infinite;
  will-change: transform, opacity;
}

@keyframes ember-rise {
  0%   { transform: translate3d(0, 0, 0) scale(0.6);                  opacity: 0; }
  8%   {                                                              opacity: 0.85; }
  50%  { transform: translate3d(var(--drift, 3vw), -55vh, 0) scale(1); opacity: 0.6; }
  85%  {                                                              opacity: 0.25; }
  100% { transform: translate3d(calc(var(--drift, 3vw) * -0.6), -112vh, 0) scale(0.5); opacity: 0; }
}

/* --- Grain + vignette ------------------------------------------------------ */
.bg-grain {
  position: absolute;
  inset: -150%;
  opacity: 0.032;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/></filter><rect width='180' height='180' filter='url(%23n)'/></svg>");
  animation: grain-shift 700ms steps(4) infinite;
}

@keyframes grain-shift {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(-2%, 1.5%); }
  50%  { transform: translate(1.5%, -1%); }
  75%  { transform: translate(-1%, -1.5%); }
  100% { transform: translate(0, 0); }
}

.bg-vignette {
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 80% at 50% 40%, transparent 42%, rgba(0,0,0,0.55) 100%);
}

/* ---------------------------------------------------------------------------
   4. SCROLL REVEALS
   ---------------------------------------------------------------------------
   Add data-reveal to any element. illos.js adds .is-visible when it scrolls
   into view. data-reveal-delay="200" staggers it by 200ms.

   The starting state is only applied when JS is present (html.js), so if a
   script fails to load the content is visible rather than permanently blank —
   this is why the old AOS-based About page went empty for some users.
   ------------------------------------------------------------------------- */
.js [data-reveal] {
  opacity: 0;
  transition:
    opacity 800ms var(--ease-out),
    transform 800ms var(--ease-out),
    filter 800ms var(--ease-out);
  will-change: opacity, transform;
}

.js [data-reveal="up"]      { transform: translate3d(0, 38px, 0); }
.js [data-reveal="down"]    { transform: translate3d(0, -30px, 0); }
.js [data-reveal="left"]    { transform: translate3d(-48px, 0, 0); }
.js [data-reveal="right"]   { transform: translate3d(48px, 0, 0); }
.js [data-reveal="zoom"]    { transform: scale(0.9); }
.js [data-reveal="fade"]    { transform: none; }
.js [data-reveal="blur"]    { filter: blur(10px); transform: scale(1.03); }
.js [data-reveal="tilt"]    { transform: perspective(1000px) rotateX(-11deg) translate3d(0, 34px, 0); }

.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
  filter: none;
}

/* Reveal every direct child in sequence: <div data-reveal-group> */
.js [data-reveal-group] > * {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition: opacity 640ms var(--ease-out), transform 640ms var(--ease-out);
}
.js [data-reveal-group].is-visible > * { opacity: 1; transform: none; }
.js [data-reveal-group].is-visible > *:nth-child(1)  { transition-delay:  40ms; }
.js [data-reveal-group].is-visible > *:nth-child(2)  { transition-delay: 100ms; }
.js [data-reveal-group].is-visible > *:nth-child(3)  { transition-delay: 160ms; }
.js [data-reveal-group].is-visible > *:nth-child(4)  { transition-delay: 220ms; }
.js [data-reveal-group].is-visible > *:nth-child(5)  { transition-delay: 280ms; }
.js [data-reveal-group].is-visible > *:nth-child(6)  { transition-delay: 340ms; }
.js [data-reveal-group].is-visible > *:nth-child(7)  { transition-delay: 400ms; }
.js [data-reveal-group].is-visible > *:nth-child(8)  { transition-delay: 460ms; }
.js [data-reveal-group].is-visible > *:nth-child(n+9){ transition-delay: 520ms; }

/* ---------------------------------------------------------------------------
   5. TEXT EFFECTS
   ------------------------------------------------------------------------- */

/* Gold gradient text with a slow shimmer sweep. */
.text-gold-shimmer {
  background: linear-gradient(
    100deg,
    var(--gold-deep) 0%, var(--gold) 22%, #FFF6D8 42%,
    var(--gold) 60%, var(--gold-deep) 100%
  );
  background-size: 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: shimmer-sweep 7s linear infinite;
}

@keyframes shimmer-sweep {
  0%   { background-position: 180% 0; }
  100% { background-position: -80% 0; }
}

/* A gold hairline that grows out from the centre under a heading. */
.rule-gold {
  position: relative;
  display: inline-block;
  padding-bottom: 16px;
}
.rule-gold::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
  transform: translateX(-50%);
  transition: width 900ms var(--ease-out) 200ms;
}
.rule-gold.is-visible::after,
.is-visible .rule-gold::after { width: 128px; }

/* Letters rise into place one after another. Spans are built by illos.js. */
.split-lift > span {
  display: inline-block;
  opacity: 0;
  transform: translate3d(0, 0.7em, 0) rotate(4deg);
  transition: opacity 620ms var(--ease-out), transform 620ms var(--ease-spring);
}
.split-lift.is-visible > span { opacity: 1; transform: none; }

/* ---------------------------------------------------------------------------
   6. INTERACTIVE PIECES
   ------------------------------------------------------------------------- */

/* Gold button with a light sweep on hover. */
.btn-gold {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: linear-gradient(135deg, var(--gold) 0%, var(--gold-soft) 52%, var(--gold-deep) 100%);
  color: #100D04;
  font-weight: 600;
  letter-spacing: 0.02em;
  transition: transform 320ms var(--ease-spring), box-shadow 320ms var(--ease-out);
}
.btn-gold::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(115deg, transparent 32%, rgba(255,255,255,0.6) 50%, transparent 68%);
  transform: translateX(-110%);
  transition: transform 720ms var(--ease-out);
}
.btn-gold:hover { transform: translateY(-2px); box-shadow: 0 14px 34px -10px rgba(212,175,55,0.6); }
.btn-gold:hover::before { transform: translateX(110%); }
.btn-gold:active { transform: translateY(0) scale(0.985); }

/* Outline button that fills from the bottom. */
.btn-outline-gold {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border: 1px solid var(--gold);
  color: var(--gold);
  font-weight: 500;
  transition: color 300ms var(--ease-out), transform 300ms var(--ease-spring);
}
.btn-outline-gold::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--gold);
  transform: translateY(101%);
  transition: transform 380ms var(--ease-out);
}
.btn-outline-gold:hover { color: #100D04; transform: translateY(-2px); }
.btn-outline-gold:hover::before { transform: translateY(0); }

/* Dish / content card: lifts, gains a gold edge, image pushes in slightly. */
.card-lift {
  transition:
    transform 480ms var(--ease-out),
    box-shadow 480ms var(--ease-out),
    border-color 480ms var(--ease-out);
  will-change: transform;
}
.card-lift:hover {
  transform: translateY(-8px);
  border-color: rgba(212, 175, 55, 0.55);
  box-shadow: 0 26px 52px -18px rgba(0,0,0,0.85), 0 0 0 1px rgba(212,175,55,0.22);
}
.card-lift .card-media { overflow: hidden; }
.card-lift .card-media img {
  transition: transform 760ms var(--ease-out), filter 500ms var(--ease-out);
  will-change: transform;
}
.card-lift:hover .card-media img { transform: scale(1.08); filter: brightness(1.06); }

/* A gold sheen that travels across a card on hover. */
.sheen { position: relative; overflow: hidden; }
.sheen::after {
  content: '';
  position: absolute;
  top: 0;
  left: -75%;
  width: 50%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(212,175,55,0.18), transparent);
  transform: skewX(-22deg);
  transition: left 780ms var(--ease-out);
  pointer-events: none;
}
.sheen:hover::after { left: 125%; }

/* Category pill for the menu rail. */
.pill {
  position: relative;
  white-space: nowrap;
  border: 1px solid rgba(212, 175, 55, 0.3);
  color: #D8D8D8;
  background: rgba(255, 255, 255, 0.03);
  transition:
    color 260ms var(--ease-out),
    border-color 260ms var(--ease-out),
    background-color 260ms var(--ease-out),
    transform 260ms var(--ease-spring);
}
.pill:hover { color: var(--gold); border-color: var(--gold); transform: translateY(-2px); }
.pill.active {
  color: #100D04;
  background: linear-gradient(135deg, var(--gold), var(--gold-soft));
  border-color: var(--gold);
  font-weight: 600;
  box-shadow: 0 8px 22px -8px rgba(212,175,55,0.65);
}

/* Underline that grows in from the left — navbar links. */
.link-underline { position: relative; }
.link-underline::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -5px;
  width: 100%;
  height: 1.5px;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 360ms var(--ease-out);
}
.link-underline:hover::after,
.link-underline[aria-current="page"]::after { transform: scaleX(1); }

/* ---------------------------------------------------------------------------
   7. HERO
   ------------------------------------------------------------------------- */
.hero-stage {
  position: relative;
  width: 100%;
  height: 100vh;
  /* Dynamic viewport height, so mobile browser chrome does not crop the hero. */
  height: 100dvh;
  overflow: hidden;
  background: #000;
}

.hero-stage video,
.hero-stage .hero-fallback {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Slow push-in gives a still-ish video some life. */
  animation: hero-push 26s var(--ease-in-out) infinite alternate;
}

@keyframes hero-push {
  from { transform: scale(1); }
  to   { transform: scale(1.07); }
}

.hero-veil {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(0,0,0,0.62) 0%, rgba(0,0,0,0.34) 42%, rgba(10,10,10,0.96) 100%),
    radial-gradient(70% 60% at 50% 45%, transparent 30%, rgba(0,0,0,0.5) 100%);
}

.hero-body {
  position: relative;
  z-index: 2;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 1.25rem;
}

/* The little bobbing scroll cue. */
.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 30px;
  transform: translateX(-50%);
  z-index: 3;
  animation: cue-bob 2.3s var(--ease-in-out) infinite;
}
@keyframes cue-bob {
  0%, 100% { transform: translateX(-50%) translateY(0);    opacity: 0.85; }
  50%      { transform: translateX(-50%) translateY(11px); opacity: 0.35; }
}

@media (max-width: 768px) {
  .hero-stage { height: 68vh; height: 68dvh; }
}

/* ---------------------------------------------------------------------------
   8. TIMELINE  (the Our Story page)
   ---------------------------------------------------------------------------
   Same left/right alternating shape as the original, but the spine now draws
   itself as you scroll (--spine is set by illos.js) instead of just sitting
   there, and each card animates in from its own side.
   ------------------------------------------------------------------------- */
.timeline { position: relative; padding: 12px 0 40px; }

/* The dim full-length track. */
.timeline::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 2px;
  margin-left: -1px;
  background: rgba(212, 175, 55, 0.16);
}

/* The bright section that fills as you scroll. */
.timeline::after {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 2px;
  margin-left: -1px;
  height: var(--spine, 0%);
  background: linear-gradient(180deg, var(--gold-soft), var(--gold), var(--gold-deep));
  box-shadow: 0 0 16px rgba(212, 175, 55, 0.7);
  transition: height 180ms linear;
}

.tl-item {
  position: relative;
  width: 50%;
  padding: 0 42px 56px;
  box-sizing: border-box;
}
.tl-item.left  { left: 0; text-align: right; }
.tl-item.right { left: 50%; text-align: left; }

/* The node on the spine. */
.tl-item::after {
  content: '';
  position: absolute;
  top: 26px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--ink);
  border: 2px solid var(--gold);
  z-index: 2;
  transition: transform 460ms var(--ease-spring), box-shadow 460ms var(--ease-out), background-color 460ms;
}
.tl-item.left::after  { right: -8.5px; }
.tl-item.right::after { left: -8.5px; }

.tl-item.is-visible::after {
  background: var(--gold);
  transform: scale(1.42);
  box-shadow: 0 0 0 6px rgba(212, 175, 55, 0.16), 0 0 20px rgba(212, 175, 55, 0.85);
}

.tl-card {
  background: linear-gradient(155deg, rgba(30,30,30,0.94), rgba(14,14,14,0.94));
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 24px 26px;
  backdrop-filter: blur(6px);
  transition: transform 520ms var(--ease-out), border-color 420ms, box-shadow 420ms;
}
.tl-card:hover {
  transform: translateY(-6px);
  border-color: rgba(212, 175, 55, 0.5);
  box-shadow: 0 24px 48px -20px rgba(0,0,0,0.9);
}

.tl-year {
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: 600;
  line-height: 1.1;
  color: var(--gold);
}
.tl-title {
  font-size: 0.94rem;
  font-weight: 500;
  color: #C9C9C9;
  margin-top: 3px;
}
.tl-copy {
  font-size: 0.9rem;
  line-height: 1.72;
  color: #A8A8A8;
  margin-top: 12px;
}

.tl-media {
  margin-top: 16px;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(212, 175, 55, 0.14);
  aspect-ratio: 16 / 10;
  background: var(--ink-3);
}
.tl-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 900ms var(--ease-out);
}
.tl-card:hover .tl-media img { transform: scale(1.07); }

/* Single column on tablet and phone, spine moved to the left edge. */
@media (max-width: 860px) {
  .timeline::before,
  .timeline::after { left: 21px; }

  .tl-item {
    width: 100%;
    left: 0 !important;
    text-align: left !important;
    padding: 0 0 40px 54px;
  }
  .tl-item::after {
    left: 14px !important;
    right: auto !important;
    top: 22px;
  }
  .tl-year { font-size: 1.45rem; }
}

/* ---------------------------------------------------------------------------
   9. MINI CART
   ------------------------------------------------------------------------- */
.cart-drawer {
  position: fixed;
  top: 0;
  right: 0;
  height: 100%;
  height: 100dvh;
  width: 100%;
  max-width: 400px;
  z-index: 1200;
  background: linear-gradient(180deg, var(--ink-2), var(--ink));
  border-left: 1px solid var(--line);
  box-shadow: -24px 0 60px -20px rgba(0,0,0,0.9);
  transform: translateX(100%);
  transition: transform 440ms var(--ease-out);
  display: flex;
  flex-direction: column;
}
.cart-drawer.open { transform: translateX(0); }

.cart-scrim {
  position: fixed;
  inset: 0;
  z-index: 1150;
  background: rgba(0,0,0,0.66);
  backdrop-filter: blur(3px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 380ms var(--ease-out), visibility 380ms;
}
.cart-scrim.open { opacity: 1; visibility: visible; }

/* Rows slide in one after another when the drawer opens. */
.cart-drawer.open .cart-row {
  animation: row-in 420ms var(--ease-out) backwards;
}
.cart-drawer.open .cart-row:nth-child(1) { animation-delay:  60ms; }
.cart-drawer.open .cart-row:nth-child(2) { animation-delay: 110ms; }
.cart-drawer.open .cart-row:nth-child(3) { animation-delay: 160ms; }
.cart-drawer.open .cart-row:nth-child(4) { animation-delay: 210ms; }
.cart-drawer.open .cart-row:nth-child(n+5) { animation-delay: 260ms; }

@keyframes row-in {
  from { opacity: 0; transform: translateX(26px); }
  to   { opacity: 1; transform: none; }
}

/* The badge pops when the count changes. */
.badge-pop { animation: badge-pop 520ms var(--ease-spring); }
@keyframes badge-pop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.55); }
  100% { transform: scale(1); }
}

/* ---------------------------------------------------------------------------
   10. MODAL
   ------------------------------------------------------------------------- */
.modal-shell {
  position: fixed;
  inset: 0;
  z-index: 1300;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.modal-shell.open { display: flex; }

.modal-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.78);
  backdrop-filter: blur(5px);
  animation: fade-in 280ms var(--ease-out);
}

.modal-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-height: 90vh;
  max-height: 90dvh;
  overflow-y: auto;
  background: linear-gradient(160deg, var(--ink-3), var(--ink));
  border: 1px solid var(--line);
  border-radius: 20px;
  animation: modal-in 420ms var(--ease-spring);
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-in {
  from { opacity: 0; transform: translateY(26px) scale(0.955); }
  to   { opacity: 1; transform: none; }
}

/* Size chips inside the dish modal. */
.size-chip {
  cursor: pointer;
  border: 1px solid rgba(212,175,55,0.3);
  color: #DADADA;
  transition: all 240ms var(--ease-out);
}
.size-chip:hover { border-color: var(--gold); color: var(--gold); transform: translateY(-2px); }
.size-chip.selected {
  background: linear-gradient(135deg, var(--gold), var(--gold-soft));
  border-color: var(--gold);
  color: #100D04;
  font-weight: 600;
  box-shadow: 0 8px 20px -8px rgba(212,175,55,0.65);
}

/* ---------------------------------------------------------------------------
   11. MARQUEE  (Features + Our Brands rails)
   ---------------------------------------------------------------------------
   Replaces the Swiper dependency. The track holds the list twice, and the
   animation moves it exactly -50%, so the loop is seamless with no JS.
   ------------------------------------------------------------------------- */
.marquee { overflow: hidden; position: relative; }
.marquee::before,
.marquee::after {
  content: '';
  position: absolute;
  top: 0;
  width: 90px;
  height: 100%;
  z-index: 2;
  pointer-events: none;
}
.marquee::before { left: 0;  background: linear-gradient(90deg, var(--ink), transparent); }
.marquee::after  { right: 0; background: linear-gradient(270deg, var(--ink), transparent); }

.marquee-track {
  display: flex;
  align-items: center;
  gap: 2.6rem;
  width: max-content;
  animation: marquee-run var(--marquee-speed, 42s) linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-track.reverse { animation-direction: reverse; }

@keyframes marquee-run {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* Logo colour and hover are defined once in section 20 ("FEATURES — in
   colour"). The greyscale treatment that used to live here has been removed
   rather than left to be overridden further down, so there is only one place
   that decides how these look. */

/* ---------------------------------------------------------------------------
   12. LOADING STATES
   ------------------------------------------------------------------------- */
.skeleton {
  background: linear-gradient(90deg, var(--ink-3) 25%, #2A2A2A 50%, var(--ink-3) 75%);
  background-size: 200% 100%;
  animation: skeleton-run 1.4s ease-in-out infinite;
  border-radius: 8px;
}
@keyframes skeleton-run {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

.spinner {
  width: 42px;
  height: 42px;
  border: 3px solid rgba(212, 175, 55, 0.2);
  border-top-color: var(--gold);
  border-radius: 50%;
  animation: spin 800ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Full-screen veil while a payment redirect is in flight. */
.busy-veil {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.2rem;
  background: rgba(6, 6, 6, 0.9);
  backdrop-filter: blur(6px);
}
.busy-veil.open { display: flex; animation: fade-in 240ms var(--ease-out); }

/* ---------------------------------------------------------------------------
   13. TOASTS
   ------------------------------------------------------------------------- */
.toast-stack {
  position: fixed;
  bottom: 22px;
  right: 22px;
  z-index: 2100;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: min(360px, calc(100vw - 44px));
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 14px 16px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: linear-gradient(140deg, var(--ink-3), var(--ink-2));
  box-shadow: 0 18px 40px -14px rgba(0,0,0,0.9);
  font-size: 0.875rem;
  color: #E8E8E8;
  animation: toast-in 420ms var(--ease-spring);
}
.toast.leaving { animation: toast-out 300ms var(--ease-out) forwards; }
.toast.ok    { border-left: 3px solid #34D399; }
.toast.error { border-left: 3px solid #F87171; }
.toast.info  { border-left: 3px solid var(--gold); }

@keyframes toast-in  { from { opacity: 0; transform: translateX(60px) scale(0.94); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to   { opacity: 0; transform: translateX(60px) scale(0.94); } }

/* ---------------------------------------------------------------------------
   14. AD POPUP
   ------------------------------------------------------------------------- */
.ad-shell {
  position: fixed;
  inset: 0;
  z-index: 1400;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background: rgba(0,0,0,0.82);
  backdrop-filter: blur(5px);
}
.ad-shell.open { display: flex; animation: fade-in 400ms var(--ease-out); }
.ad-frame {
  position: relative;
  max-width: 560px;
  width: 100%;
  animation: ad-in 620ms var(--ease-spring);
}
@keyframes ad-in {
  from { opacity: 0; transform: translateY(40px) scale(0.9); }
  to   { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------------------
   15. UTILITIES
   ------------------------------------------------------------------------- */
.glass {
  background: rgba(20, 20, 20, 0.72);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  border: 1px solid var(--line);
}

.hairline { border-top: 1px solid var(--line); }

.float-slow { animation: float-slow 6.5s var(--ease-in-out) infinite; }
@keyframes float-slow {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-13px); }
}

.pulse-ring { position: relative; }
.pulse-ring::before {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: inherit;
  border: 1.5px solid var(--gold);
  animation: pulse-ring 2.1s var(--ease-out) infinite;
}
@keyframes pulse-ring {
  0%   { opacity: 0.85; transform: scale(0.94); }
  100% { opacity: 0;    transform: scale(1.28); }
}

/* Screen-reader-only text that stays keyboard reachable. */
.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;
}

/* ---------------------------------------------------------------------------
   16. PRINT  (admin uses this for order slips)
   ------------------------------------------------------------------------- */
@media print {
  body { background: #fff !important; color: #000 !important; }
  .bg-stage, .no-print, nav, footer, .cart-drawer, .cart-scrim { display: none !important; }
  * { animation: none !important; transition: none !important; box-shadow: none !important; }
  a[href]::after { content: ''; }
}

/* ---------------------------------------------------------------------------
   17. REDUCED MOTION
   ---------------------------------------------------------------------------
   One block that neutralises everything above for anyone who has asked their
   OS for less movement. Content still appears — only the motion stops.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  html { scroll-behavior: auto; }

  .js [data-reveal],
  .js [data-reveal-group] > *,
  .split-lift > span {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
  }

  .bg-aurora, .bg-grain, .bg-mesh, .bg-beams { animation: none !important; }
  .bg-orbs i { animation: none !important; }
  .bg-embers { display: none !important; }
  .hero-stage video, .hero-stage .hero-fallback { animation: none !important; transform: none !important; }
  .marquee-track { animation: none !important; }
  .rule-gold::after { width: 128px !important; }
  .scroll-cue { display: none; }
}

/* ============================================================================
   18. MENU CARD — whole photo, and every size priced
   ----------------------------------------------------------------------------
   Two corrections to match the live site:

   1. The photo is no longer cropped. object-fit:cover filled the frame by
      slicing the edges off, which cut the ends off wide party trays — the
      worst possible thing to crop on a food menu. object-fit:contain shows the
      entire image; the tinted panel behind it absorbs the leftover space so
      the grid still lines up.

   2. Every size and its price is listed (Lite / Half / Full), rather than a
      single "from ₱840".
   ========================================================================== */

.dish-photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  display: block;
  object-fit: contain;          /* whole picture, never cropped */
  object-position: center;
  background: var(--ink-3);
  padding: 6px;
  transition: transform 620ms var(--ease-out);
}

/* A blurred copy of the same photo fills the empty space beside a tall or
   narrow image, so the card never shows bare grey bars. */
.dish-media {
  position: relative;
  overflow: hidden;
  background: var(--ink-3);
}
.dish-media::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: var(--dish-bg);
  background-size: cover;
  background-position: center;
  filter: blur(22px) saturate(1.25) brightness(0.55);
  transform: scale(1.25);
  opacity: 0.5;
  z-index: 0;
}
.dish-media .dish-photo { position: relative; z-index: 1; background: transparent; }

.card-lift:hover .dish-photo { transform: scale(1.045); }

/* Size + price rows on the card. */
.size-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 3px 0;
  font-size: 0.8rem;
}
.size-line + .size-line { border-top: 1px dashed rgba(212, 175, 55, 0.16); }
.size-line .size-name  { color: var(--muted); letter-spacing: 0.02em; }
.size-line .size-price { color: var(--gold); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Allergen line vs package line — visually distinct so they are not confused. */
.dish-allergens {
  display: inline-block;
  font-size: 0.65rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 600;
  color: #C98A2E;
  background: rgba(201, 138, 46, 0.12);
  border: 1px solid rgba(201, 138, 46, 0.28);
  border-radius: 999px;
  padding: 3px 9px;
}

.dish-package {
  font-size: 0.76rem;
  line-height: 1.6;
  color: var(--muted);
  display: -webkit-box;
  -webkit-line-clamp: 4;        /* keeps every card the same height */
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.dish-package .pkg-item { display: block; }
.dish-package .pkg-item::before { content: '· '; color: var(--gold); }

/* ============================================================================
   19. FEATURES — in colour
   ----------------------------------------------------------------------------
   The press logos were forced to greyscale. They are brand marks and read far
   better in their real colours, so the filter is gone; only a slight
   transparency remains, lifting to full on hover.
   ========================================================================== */

.marquee img {
  filter: none;
  opacity: 0.92;
  transition: transform 380ms var(--ease-spring), opacity 380ms var(--ease-out);
}
.marquee a:hover img { transform: scale(1.1); opacity: 1; filter: none; }

/* A few press logos are black-on-transparent and vanish against the ink. A soft
   white plate behind each one keeps them readable without washing out the
   colour. (This used to be forked per theme; the site is dark-only now.) */
.marquee a {
  background: rgba(255, 255, 255, 0.94);
  border-radius: 12px;
  padding: 10px 14px;
  display: block;
  transition: background-color 320ms var(--ease-out), transform 320ms var(--ease-spring);
}
.marquee a:hover {
  background: #FFFFFF;
  transform: translateY(-3px);
}

/* ============================================================================
   20. MOBILE & LOW-END DEVICE PERFORMANCE
   ----------------------------------------------------------------------------
   The animated background is the expensive part: three stacked layers, one of
   them a large blur, repainting continuously. On a mid-range Android that is
   the difference between smooth scrolling and visible stutter.

   Below 1024px the blur is reduced and the grain layer — the most costly and
   least noticeable of the three — is dropped entirely. Below 768px the aurora
   stops animating at all and becomes a static gradient, which looks nearly
   identical on a small screen and costs nothing to maintain.
   ========================================================================== */

@media (max-width: 1023px) {
  .bg-grain { display: none; }
  .bg-aurora { filter: blur(10px); animation-duration: 48s; }
  /* A 70px blur on a 46vw circle is the single most expensive thing on the
     page. Halving it is invisible at this size and costs a fraction to paint. */
  .bg-orbs i { filter: blur(44px); }
  .bg-beams  { filter: blur(16px); animation-duration: 160s; }
  .bg-embers i:nth-child(n+11) { display: none; }   /* 18 sparks -> 10 */
  .glass { backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
}

@media (max-width: 767px) {
  /* Static background: no continuous repaint while the user scrolls. The orbs
     and embers stay — they are the movement worth keeping — but the layers
     that repaint the WHOLE viewport every frame are frozen. */
  .bg-aurora { animation: none; filter: blur(8px); }
  .bg-mesh   { animation: none; background-size: 54px 54px; }
  .bg-beams  { display: none; }
  .bg-orbs i { filter: blur(34px); opacity: 0.45; }
  .bg-embers i:nth-child(n+7) { display: none; }    /* 10 sparks -> 6 */

  /* The hero's slow zoom forces the compositor to re-rasterise a video frame
     every tick. Not worth it on a phone. */
  .hero-stage video,
  .hero-stage .hero-fallback { animation: none; transform: none; }

  /* Shorter, simpler reveals — long transforms feel sluggish on a small screen. */
  .js [data-reveal] { transition-duration: 480ms; }
  .js [data-reveal="up"]    { transform: translate3d(0, 22px, 0); }
  .js [data-reveal="left"],
  .js [data-reveal="right"] { transform: translate3d(0, 22px, 0); }
  .js [data-reveal="blur"]  { filter: none; transform: translate3d(0, 22px, 0); }
  .js [data-reveal="tilt"]  { transform: translate3d(0, 22px, 0); }

  /* Hover effects do nothing on touch and only cost paint time. */
  .card-lift:hover { transform: none; box-shadow: none; }
  .sheen::after    { display: none; }

  .marquee-track { animation-duration: 30s; }
}

/* Touch devices: give every control a finger-sized target.
   44px is Apple's minimum and Google's recommendation; below that people
   mis-tap, which on a checkout page means a lost order. */
@media (hover: none) and (pointer: coarse) {
  .a-btn,
  .btn-gold,
  .btn-outline-gold,
  .pill,
  .size-chip,
  .admin-link,
  button:not(.expand-btn),
  select,
  [role="tab"] {
    min-height: 44px;
  }

  .a-btn-sm { min-height: 38px; }

  /* iOS zooms the page in when a focused field's font is under 16px. Setting
     every input to 16px stops that jarring auto-zoom on the checkout form. */
  input, select, textarea { font-size: 16px !important; }

  /* Nothing should depend on hover being available. */
  .card-lift:hover,
  .a-card:hover,
  .a-btn:hover { transform: none; }
}

/* Very small phones: the reCAPTCHA box is a fixed 304px and cannot be resized
   with CSS, so it is scaled down instead. Without this it overflows the card
   and pushes the submit button off the screen. */
.recaptcha-wrap {
  display: flex;
  justify-content: center;
  min-height: 78px;
}
@media (max-width: 360px) {
  .recaptcha-wrap { transform: scale(0.86); transform-origin: center; min-height: 68px; }
}

/* Respect a data-saver setting: drop the decorative layers entirely. */
@media (prefers-reduced-data: reduce) {
  .bg-aurora, .bg-grain, .bg-mesh, .bg-beams, .bg-embers, .bg-orbs { display: none; }
}

/* Tablets: the dish grid reads better at three columns than four. */
@media (min-width: 768px) and (max-width: 1279px) {
  .dish-package { -webkit-line-clamp: 3; }
}
