/* =========================================================
   DESIGN TOKENS
   ========================================================= */
:root{
  --bg:            #0d0d0c;
  --bg-panel:      #161513;
  --bg-panel-2:    #1c1a17;
  --line:          rgba(255,255,255,0.08);
  --line-strong:   rgba(255,255,255,0.16);

  --text:          #eee7da;
  --text-muted:    #9c9a91;
  --text-dim:      #6d6c66;

  --brass:         #d63a26;
  --brass-bright:  #eb5a3f;
  --jade:          #e0952f;
  --jade-bright:   #f0ac4d;
  --wood:          #8a5a34;

  --font-display:  "Fraunces", "Iowan Old Style", Georgia, serif;
  --font-body:     "Inter", -apple-system, "Segoe UI", sans-serif;
  --font-mono:     "IBM Plex Mono", "SFMono-Regular", Menlo, monospace;

  --radius-s: 3px;
  --radius-m: 6px;

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

  /* Shared seigaiha texture — a small seamless tile now, so it's repeated
     (not stretched). See body, .textured-bg below. */
  --noise-bg: url('../assets/img/textures/bg-texture.png');
}

/* =========================================================
   RESET
   ========================================================= */
*, *::before, *::after{ box-sizing:border-box; }
html{ scroll-behavior:smooth; }
body{
  margin:0;
  background-color:var(--bg);
  color:var(--text);
  font-family:var(--font-body);
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  cursor:url('../assets/img/cursors/fan-cursor.png') 18 2, auto;
}
/* Seigaiha texture, applied directly (no ::before layer) so there is only
   ONE texture layer on the page, not a fixed body layer plus a separate
   per-section layer scrolling at a different rate. background-attachment:
   fixed anchors the image to the viewport — every element that carries
   this (body + any .textured-bg section) samples the same continuous
   backdrop, so panel-colored sections (--bg-panel, --bg-panel-2) show the
   pattern lined up with the rest of the page instead of drifting out of
   sync while scrolling. Longhand background-* properties only (never the
   `background` shorthand) so this never gets reset by a section's own
   background-color rule, whichever one is declared later. */
body, .textured-bg{
  background-image:var(--noise-bg);
  background-repeat:repeat;
  background-size:150px;
  background-attachment:fixed;
}
img{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
ul{ list-style:none; margin:0; padding:0; }
h1,h2,h3,h4{ font-family:var(--font-display); font-weight:600; margin:0; }
button{ font-family:inherit; cursor:pointer; }
:focus-visible{ outline:2px solid var(--brass-bright); outline-offset:3px; }
@media (prefers-reduced-motion: reduce){
  *{ animation-duration:0.001ms !important; transition-duration:0.001ms !important; }
}

/* =========================================================
   SCROLL REVEAL — safe-by-default
   -----------------------------------------------------------
   IMPORTANT invariant: none of these classes hide anything on
   their own. The bare `.reveal` / `.reveal-group` / etc. rules
   below carry NO opacity/transform/clip-path — an element with
   only that class (i.e. before JS runs, or if JS throws anywhere
   on the page for any reason) renders fully visible, exactly like
   plain HTML/CSS with no JS at all.

   `.reveal-armed`, added ONLY by js/animations.js, and ONLY to an
   element it has just confirmed (via IntersectionObserver, which
   reports current state immediately on .observe()) is NOT yet in
   the viewport, is what actually hides it a moment before it
   scrolls into view. `.is-visible` then reveals it. If JS never
   runs, `.reveal-armed` never gets added, and the content was
   visible from the very first paint — there is no code path that
   can leave real content permanently invisible.
   ========================================================= */
.reveal{ transition:opacity .9s var(--ease), transform .9s var(--ease); }
.reveal.reveal-armed{ opacity:0; transform:translateY(28px); }
.reveal.is-visible{ opacity:1; transform:translateY(0); }

/* :not(.scroll-reveal) — cards opted into the paper-unroll treatment
   below (Services/Payment) get a completely different effect, not
   this fade+rise layered on top of it. Everything else inside any
   .reveal-group (pillars, dish cards, gallery tiles, Intro cards, ...)
   is untouched by that split. */
.reveal-group > *:not(.scroll-reveal){ transition:opacity .8s var(--ease), transform .8s var(--ease); }
.reveal-group.reveal-armed > *:not(.scroll-reveal){ opacity:0; transform:translateY(24px); }
.reveal-group.is-visible > *:not(.scroll-reveal){ opacity:1; transform:translateY(0); }

/* Paper/scroll unrolling open top-to-bottom — Services + Payment
   cards only (see .service-item.scroll-reveal in index.html). Intro
   cards deliberately keep the plain fade+rise above, unchanged.
   Stagger comes for free: js/animations.js already sets
   transitionDelay on every .reveal-group child regardless of which
   of these two treatments it uses.
   The actual clip-path/opacity durations live on .service-item's own
   `transition` shorthand below (search "clip-path .7s"), not here —
   .service-item is declared later in this file, so a `transition` set
   here would just get silently replaced wholesale (same specificity,
   later-wins) and clip-path/opacity would snap instead of animating. */
.scroll-reveal.reveal-armed{ clip-path:inset(0 0 100% 0); opacity:0; }
.scroll-reveal.is-visible{ clip-path:inset(0 0 0% 0); opacity:1; }

/* Whole-section "morph" entrance — separate from and layered on top of
   .reveal/.reveal-group above: this clips the ENTIRE section (an iris
   opening from the top edge) while .reveal/.reveal-group independently
   fade in that section's own children, both triggered by the same
   scroll moment. Much slower than button/hover-scale motion (1.2s,
   no bounce) so it reads as a single, unhurried scene change. */
.section-morph{ transition: clip-path 1.2s var(--ease), background-color 1.2s var(--ease); }
.section-morph.reveal-armed{ clip-path: circle(0 at 50% 0%); }
.section-morph.is-visible{ clip-path: circle(200vmax at 50% 0%); }

/* Section-seam divider: line draws left-to-right, then a small seal/stamp
   dot pops in at its center — replaces the plain border-top/bottom that
   used to sit between .dishes-strip / .payment-section / footer. Default
   (no JS) = line fully drawn and seal already stamped, so the seam always
   reads correctly even with no animation. */
/* z-index needed: the seal dot's halo (box-shadow rings) visually
   extends a few px above/below this 1px-tall element. Without an
   explicit z-index, the section that FOLLOWS in DOM order (same
   z-index:auto) paints its own background on top of that overflow,
   cutting the dot in half. z-index:5 keeps it above any normal
   section content while staying well under the fixed UI chrome
   (nav 200, section-dots 250, cookie-banner 350, legal panel 499/500). */
.section-divider{ position:relative; height:1px; z-index:5; pointer-events:none; }
.section-divider .divider-line{
  position:absolute; inset:0; background:var(--line);
  transform-origin:left;
  transition:transform .8s var(--ease);
}
.section-divider.reveal-armed .divider-line{ transform:scaleX(0); }
.section-divider.is-visible .divider-line{ transform:scaleX(1); }
.section-divider .divider-seal{
  position:absolute; top:50%; left:50%; width:8px; height:8px; border-radius:50%;
  background:var(--brass); box-shadow:0 0 0 4px var(--bg), 0 0 0 5px var(--line-strong);
  transform:translate(-50%, -50%) scale(1);
}
.section-divider.reveal-armed .divider-seal{ transform:translate(-50%, -50%) scale(0); }
.section-divider.is-visible .divider-seal{ animation:seal-stamp .5s var(--ease) 1.1s both; }
@keyframes seal-stamp{
  0%{ transform:translate(-50%, -50%) scale(0); }
  60%{ transform:translate(-50%, -50%) scale(1.15); }
  100%{ transform:translate(-50%, -50%) scale(1); }
}

/* fade used by the DE/EN language switcher, see js/main.js applyRealCopy() */
[data-de]{ transition:opacity .17s var(--ease); }

.container{ max-width:1180px; margin:0 auto; padding:0 32px; }
.eyebrow{
  font-family:var(--font-mono); font-size:12px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--brass-bright); margin-bottom:14px; display:block;
}
.section{ padding:120px 0; position:relative; }
.section-head{ max-width:640px; margin-bottom:64px; }
.section-head h2{ font-size:clamp(32px,4vw,46px); line-height:1.15; }
.section-head p{ color:var(--text-muted); margin-top:16px; font-size:17px; }
.divider{ height:1px; background:var(--line); border:0; margin:0; }

.btn{
  display:inline-flex; align-items:center; gap:10px;
  padding:15px 30px; border-radius:2px; font-size:14px;
  letter-spacing:.04em; font-weight:600; border:1px solid transparent;
  transition:all .25s var(--ease);
}
.btn-brass{ background:var(--brass); color:#0c0805; }
.btn-brass:hover{ background:var(--brass-bright); box-shadow:0 16px 32px rgba(214,58,38,.28); animation:btn-stamp .5s var(--ease) forwards; }
.btn-outline{ border-color:var(--line-strong); color:var(--text); }
.btn-outline:hover{ border-color:var(--brass); color:var(--brass-bright); box-shadow:0 16px 32px rgba(0,0,0,.35); animation:btn-stamp .5s var(--ease) forwards; }
/* Hover feels like a seal stamping down, then lifting off the page,
   rather than a plain rise. */
@keyframes btn-stamp{
  0%{ transform:scale(1) translateY(0); }
  25%{ transform:scale(.97) translateY(0); }
  55%{ transform:scale(1.04) translateY(-1px); }
  100%{ transform:scale(1) translateY(-3px); }
}

/* =========================================================
   NAV
   ========================================================= */
.nav{
  position:fixed; top:0; left:0; right:0; z-index:200;
  background:linear-gradient(to bottom, rgba(11,14,18,.92), rgba(11,14,18,0));
  backdrop-filter:blur(6px);
  padding:22px 0;
  transition:background .3s var(--ease), padding .3s var(--ease), border-color .3s var(--ease);
  border-bottom:1px solid transparent;
}
.nav.is-scrolled{
  background:rgba(11,14,18,.9);
  padding:14px 0;
  border-color:var(--line);
}
.nav .container{ display:flex; align-items:center; justify-content:space-between; }
.brand{ font-family:var(--font-display); font-size:22px; letter-spacing:.03em; }
.brand span{ color:var(--brass); }
.nav-links{ display:flex; gap:34px; align-items:center; }
.nav-links a{
  font-size:14px; color:var(--text-muted); position:relative; padding:4px 0;
  transition:color .2s;
}
.nav-links a:hover{ color:var(--text); }
.nav-links a::after{
  content:""; position:absolute; left:0; bottom:0; height:1px; width:100%;
  background:var(--brass); transform:scaleX(0); transform-origin:left;
  transition:transform .4s var(--ease);
}
.nav-links a:hover::after{ transform:scaleX(1); }
.nav-cta{ display:flex; align-items:center; gap:22px; }

.nav-toggle{ display:none; background:none; border:0; color:var(--text); font-size:22px; }

/* language switcher */
.lang-switch{ position:relative; }
.lang-current{
  display:flex; align-items:center; gap:8px; font-size:13px;
  color:var(--text-muted); border:1px solid var(--line-strong);
  padding:8px 14px; border-radius:2px; background:transparent;
}
.lang-current:hover{ color:var(--text); border-color:var(--brass); }
.lang-panel{
  position:absolute; top:calc(100% + 10px); right:0;
  background:var(--bg-panel-2); border:1px solid var(--line-strong);
  padding:18px 20px; display:grid; grid-template-columns:repeat(3,minmax(110px,1fr));
  gap:8px 28px; opacity:0; visibility:hidden; transform:translateY(-6px);
  transition:all .2s var(--ease); box-shadow:0 20px 50px rgba(0,0,0,.5);
}
.lang-switch.is-open .lang-panel{ opacity:1; visibility:visible; transform:translateY(0); }
.lang-panel button{
  background:none; border:0; color:var(--text-muted); font-size:14px;
  text-align:left; padding:5px 0;
}
.lang-panel button:hover{ color:var(--brass-bright); }
.lang-panel button.is-active{ color:var(--text); font-weight:600; }

/* =========================================================
   HERO
   ========================================================= */
/* Drop a real photo at assets/img/hero/hero-bg.jpeg (min. 1920x800px) and
   it is picked up automatically — no code changes needed. Until then this
   layer just fails to load and the plain dark background shows instead. */
.hero{
  min-height:100vh; display:flex; align-items:flex-end;
  position:relative; overflow:hidden;
  padding:160px 0 120px;
  background-color:var(--bg);
}
.hero-bg{
  position:absolute; inset:0; z-index:0;
  background-image:url('../assets/img/hero/hero-bg.jpeg');
  background-size:cover; background-position:center; background-repeat:no-repeat;
  animation:hero-ken-burns 20s var(--ease) infinite alternate;
  will-change:transform;
}
@keyframes hero-ken-burns{
  from{ transform:scale(1); }
  to{ transform:scale(1.08); }
}
.hero::after{
  content:""; position:absolute; inset:0; z-index:1;
  background-image:
    linear-gradient(rgba(6,7,9,.45), rgba(6,7,9,.55)),
    radial-gradient(ellipse at 15% 0%, rgba(214,58,38,.10), transparent 55%),
    radial-gradient(ellipse at 85% 20%, rgba(224,149,47,.14), transparent 55%);
  pointer-events:none;
}
.hero::before{
  content:""; position:absolute; inset:0; z-index:1;
  background-image:
    repeating-linear-gradient(115deg, rgba(255,255,255,.025) 0 1px, transparent 1px 90px);
  pointer-events:none;
}
.hero-inner{ position:relative; z-index:2; display:grid; grid-template-columns:1.5fr 1fr; gap:60px; align-items:end; }
@keyframes hero-fade-up{
  from{ opacity:0; transform:translateY(24px); }
  to{ opacity:1; transform:translateY(0); }
}
/* Drop-in-and-settle for the brand mark + welcome line specifically —
   plain CSS animation on page load (no scroll, no JS at all), so the
   "no JS" state is simply the very last keyframe (translateY(0),
   opacity:1) with nothing in between ever having run: safe by
   construction, same guarantee as the .reveal system elsewhere but
   here it comes for free from how CSS animations degrade. */
@keyframes hero-drop-bounce{
  0%   { transform:translateY(-160%); opacity:0; }
  45%  { transform:translateY(0);      opacity:1; }
  58%  { transform:translateY(-9%); }
  70%  { transform:translateY(0); }
  80%  { transform:translateY(-4%); }
  89%  { transform:translateY(0); }
  95%  { transform:translateY(-1.5%); }
  100% { transform:translateY(0); }
}
.hero-brand{
  font-size:clamp(64px,10vw,140px); line-height:.9; letter-spacing:-.01em;
  color:var(--text); margin-bottom:18px;
  animation:hero-drop-bounce 1.3s ease-out .1s both;
}
.hero-welcome{
  font-family:var(--font-display); font-size:clamp(22px,2.6vw,30px);
  color:var(--brass-bright); margin:0 0 14px;
  animation:hero-drop-bounce 1.3s ease-out .38s both;
}
.hero-status{ color:var(--text-muted); font-size:16px; margin:0; animation:hero-fade-up 1s var(--ease) .45s both; }
.hero-actions{ margin-top:42px; display:flex; gap:18px; flex-wrap:wrap; animation:hero-fade-up 1s var(--ease) .6s both; }
.hero-aside{ border-left:1px solid var(--line); padding-left:32px; animation:hero-fade-up 1.1s var(--ease) .5s both; }
.hero-aside .stat{ margin-bottom:26px; }
.hero-aside .stat b{ font-family:var(--font-display); font-size:30px; color:var(--brass-bright); display:block; }
.hero-aside .stat b.stat-pulse{ animation:stat-pulse .28s var(--ease); }
@keyframes stat-pulse{
  0%{ transform:scale(1); }
  35%{ transform:scale(1.1); }
  65%{ transform:scale(.96); }
  100%{ transform:scale(1); }
}
.hero-aside .stat small{ color:var(--text-dim); font-size:13px; }

/* =========================================================
   ABOUT / STORY
   ========================================================= */
.about-grid{ display:grid; grid-template-columns:.9fr 1.1fr; gap:70px; align-items:center; }
.about-media{
  aspect-ratio:4/5; background:var(--bg-panel);
  border:1px solid var(--line); position:relative; overflow:hidden; z-index:2;
  display:flex; align-items:center; justify-content:center;
}
/* Base scale is a fixed buffer margin (not decorative) — js/animations.js
   drives --parallax-y on scroll, and this image needs slack outside its
   own box so a vertical shift never uncovers empty space at the top/
   bottom edge; combined into the same transform as the hover zoom
   (rather than each fighting over the `transform` property) via a
   custom property JS never has to know about. */
.about-media img{
  width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .4s var(--ease);
  transform:translateY(var(--parallax-y, 0px)) scale(1.12);
}
.about-media:hover img{ transform:translateY(var(--parallax-y, 0px)) scale(1.18); }
/* will-change only while js/animations.js has this layer actively
   updating each frame — added/removed with the layer's on/off-screen
   state, not left on permanently (that would ask the browser to keep
   a compositor layer around for images that aren't animating). */
.is-parallax-active{ will-change:transform; }
.about-media::after{
  content:attr(data-caption); position:absolute; inset:0; z-index:1;
  display:flex; align-items:flex-end; padding:20px;
  background:linear-gradient(to top, rgba(0,0,0,.6), transparent 55%);
  color:var(--text); font-family:var(--font-mono); font-size:13px; letter-spacing:.08em;
  opacity:0; transition:opacity .35s var(--ease); pointer-events:none;
}
.about-media:hover::after{ opacity:1; }
.about-media .frame-label{
  position:absolute; bottom:18px; left:18px; font-family:var(--font-mono);
  font-size:11px; color:var(--text-dim); letter-spacing:.1em;
}
.about-copy h2{
  font-size:clamp(34px,4.4vw,56px); line-height:.98; letter-spacing:-.01em;
  margin:10px 0 24px;
}
.about-copy h2 em{ font-style:italic; color:var(--brass-bright); }
.about-copy p{ color:var(--text-muted); margin:0 0 18px; font-size:16.5px; }
.about-copy p:first-of-type{ color:var(--text); font-size:20px; font-family:var(--font-display); line-height:1.5; }

/* Typewriter effect for the two About intro paragraphs is done via
   plain textContent typing in js/animations.js (typeText()) — no
   overlay, no clip, no CSS animation involved, so there is nothing to
   declare here. See that function for the safety contract. */
/* Staggered top-left-to-bottom-right cascade instead of 3 even
   columns — no dividing lines, each pillar just sits a bit lower
   and further right than the one before it. */
.pillars{ display:grid; grid-template-columns:repeat(3,1fr); gap:0 24px; margin-top:56px; }
.pillar{ padding-bottom:26px; }
.pillar:nth-child(2){ margin-top:40px; margin-left:14px; }
.pillar:nth-child(3){ margin-top:80px; margin-left:28px; }
.pillar .mark{ display:inline-flex; align-items:center; gap:6px; font-size:22px; }
.pillar .mark .fi{ border-radius:2px; box-shadow:0 0 0 1px var(--line-strong); }
.pillar h4{ font-size:17px; margin:10px 0 6px; }
.pillar p{ color:var(--text-dim); font-size:14px; margin:0; }

/* =========================================================
   SIGNATURE DISHES
   ========================================================= */
.dishes-strip{ background-color:var(--bg-panel); }
.dishes-strip.section-morph.reveal-armed{ background-color:var(--bg); }
.dishes-strip.section-morph.is-visible{ background-color:var(--bg-panel); }
.dish-row{ display:grid; grid-template-columns:repeat(3,1fr); }
.dish-card{
  padding:56px 40px; border-right:1px solid var(--line); position:relative;
  transition:background .3s;
}
.dish-card:last-child{ border-right:0; }
.dish-card:hover{ background:rgba(214,58,38,.05); }
.dish-num{ font-family:var(--font-mono); color:var(--wood); font-size:13px; }
.dish-card h3{ font-size:24px; margin:18px 0 10px; }
.dish-card p{ color:var(--text-muted); font-size:14.5px; margin:0 0 20px; }
.dish-price{ font-family:var(--font-mono); color:var(--brass-bright); font-size:15px; }
.dish-placeholder-icon{ width:34px; height:34px; color:var(--text-dim); margin-top:10px; }

/* =========================================================
   GLASS PANEL — shared frosted-glass card
   -----------------------------------------------------------
   Lifts a content block off the seigaiha texture behind it
   (service items, the payment block, intro cards, ...). Each
   instance is its own DOM node so .reveal/.reveal-group can be
   attached to it individually. Fallback background (no blur) for
   browsers without backdrop-filter, checked via @supports rather
   than assuming — the plain rgba is a bit more opaque there so text
   still reads without the blur helping it along.
   ========================================================= */
.glass-panel{
  background:rgba(23, 21, 19, 0.65);
  border:1px solid rgba(214, 58, 38, 0.3);
  border-top:1px solid rgba(235, 90, 63, 0.55);
  border-radius:4px;
  padding:28px;
}
@supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .glass-panel{
    background:rgba(23, 21, 19, 0.42);
    backdrop-filter:blur(6px);
    -webkit-backdrop-filter:blur(6px);
  }
}

/* =========================================================
   SERVICES CAROUSEL
   ========================================================= */
.services-section{ background-color:var(--bg-panel); padding-top:80px; padding-bottom:80px; }
.services-section.section-morph.reveal-armed{ background-color:var(--bg); }
.services-section.section-morph.is-visible{ background-color:var(--bg-panel); }
.services-section .section-head h2{ font-size:clamp(28px,3.4vw,38px); }
.services-carousel{ display:flex; align-items:center; gap:14px; max-width:1180px; margin:0 auto; padding:0 20px; }
.services-track{
  display:flex; gap:10px; overflow-x:auto; scroll-behavior:smooth;
  scroll-snap-type:x mandatory; scrollbar-width:none; padding:16px 2px 44px;
}
.services-track::-webkit-scrollbar{ display:none; }
.service-item{
  flex:0 0 auto; width:132px; scroll-snap-align:start;
  display:flex; flex-direction:column; align-items:center; text-align:center; gap:16px;
  padding:16px 6px; border-radius:8px;
  /* clip-path/opacity here (not on .scroll-reveal) are what actually drive
     the paper-unroll reveal — this rule comes later in the file than
     .scroll-reveal's, so listing them here is what makes them win. */
  transition:transform .3s var(--ease), box-shadow .3s var(--ease), background .3s var(--ease), border-color .3s var(--ease), clip-path .7s var(--ease), opacity .7s var(--ease);
}
.service-item:hover{ border-color:transparent; transform:translateY(-4px); background:var(--bg-panel-2); box-shadow:0 18px 36px rgba(0,0,0,.35); }
.service-item svg{ width:44px; height:44px; color:var(--text); transition:color .25s; }
.service-item:hover svg{ color:var(--brass-bright); }
.service-item span{ font-size:14.5px; color:var(--text); line-height:1.3; }
.carousel-arrow{
  flex:0 0 auto; width:38px; height:38px; border-radius:50%; border:1px solid var(--line-strong);
  background:transparent; color:var(--text-muted); font-size:20px; line-height:1;
  display:flex; align-items:center; justify-content:center; transition:all .2s var(--ease);
}
.carousel-arrow:hover,
.carousel-arrow.is-hover-zone{ color:var(--brass-bright); border-color:var(--brass); }
.carousel-arrow.is-disabled{ opacity:.25; pointer-events:none; }
.carousel-dots{ display:flex; justify-content:center; gap:8px; margin-top:30px; }
.carousel-dots .dot{ width:6px; height:6px; border-radius:50%; background:var(--line-strong); transition:background .2s; }
.carousel-dots .dot.is-active{ background:var(--brass); }

/* =========================================================
   PAYMENT OPTIONS
   ========================================================= */
.payment-section{ background-color:var(--bg); padding:90px 0; }
.payment-section .section-head h2{ font-size:clamp(26px,3.2vw,34px); }
/* Reuses .service-item + .glass-panel directly (same card size/style/
   gap as Services) instead of its own payment-item styling — 4 cards
   fit one centered row without needing the carousel-scroll mechanics
   Services needs for 9. */
.payment-grid{ display:flex; flex-wrap:wrap; justify-content:center; gap:10px; max-width:820px; margin:0 auto; }

/* =========================================================
   MENU SECTION
   ========================================================= */
.menu-section{ text-align:center; }
.menu-preview{ margin:0 auto; max-width:760px; }
.menu-preview h3{ font-size:26px; margin-bottom:14px; }
.menu-preview p{ color:var(--text-muted); margin-bottom:0; }

/* menu flipbook, embedded inline in the page */
.menu-flip-wrap{
  position:relative; z-index:2; margin:56px auto 0; max-width:1080px; min-height:380px;
}
/* Full-bleed on mobile: breaks .menu-flip-wrap out of .container's side
   padding (20-32px per side, see .container rules above) so the page
   image renders at the phone's true full width instead of losing ~15%
   of it to padding it doesn't need here. Classic "break out of a
   centered container" trick (100vw + negative margin pulls both edges
   back to the viewport edge) rather than hardcoding the padding value,
   so it stays correct even if .container's padding changes later. */
@media (max-width:767px){
  .menu-flip-wrap{
    width:100vw; max-width:100vw;
    margin-left:calc(50% - 50vw); margin-right:calc(50% - 50vw);
  }
}
/* !important beats the inline min-width StPageFlip sets on this exact
   element from MOBILE_FLIP_OPTIONS.minWidth (js/flipbook.js) — on
   mobile that value is pushed up on purpose (to force single-page
   "portrait" mode below the 768px breakpoint, see
   flipOptionsForViewport()), which would otherwise force this element
   wider than a narrow phone and cause horizontal page overflow. */
#menu-flip{ width:100%; min-width:0 !important; box-shadow:0 40px 100px rgba(0,0,0,.6); }
/* StPageFlip (desktop only now — see js/flipbook.js's useSimpleViewer)
   captures single-finger horizontal drags itself to power the
   page-turn animation, which as a side effect also swallows the
   browser's native two-finger pinch-to-zoom gesture over the whole
   book. Explicitly allowing pinch-zoom (and vertical panning) hands
   two-finger gestures back to the browser, while leaving single-finger
   horizontal panning unclaimed so the library can still intercept it
   for swipe-to-flip. Harmless to also apply on mobile even though that
   path no longer uses StPageFlip at all. */
#menu-flip, #menu-flip *{ touch-action:pan-y pinch-zoom; }
/* Plain full-width viewer (js/flipbook.js's mountFallbackViewer) — the
   default on mobile, and the fallback everywhere if the page-flip
   library fails to load. No JS touch handling sits on the <img> here,
   so pinch-zoom and double-tap-zoom both work with zero extra markup. */
.menu-fallback-viewer{ text-align:center; }
.menu-fallback-viewer img{
  display:block; width:100%; height:auto; max-width:100%;
}
.menu-fallback-nav{
  margin-top:16px; display:flex; gap:14px; justify-content:center;
  padding:0 20px 20px;
}
/* Second hint line — only relevant on mobile, where the simple
   full-width viewer (and its native pinch-zoom) is actually used;
   desktop keeps the page-flip book at a comfortable size already. */
.flipbook-hint-zoom{ display:none; margin-top:6px; }
@media (max-width:767px){
  .flipbook-hint-zoom{ display:block; }
}
/* First-view "opening" reveal: two cover panels sit over the book and
   swing outward like double doors. Simplified from a true 3D/rotateY
   page-fold — the page-flip library measures and builds its own DOM
   inside #menu-flip on init, so a real fold would have to rotate that
   library-owned element in 3D, risking its internal size/click math.
   Overlaying two plain panels that slide away gets the same "opening"
   read without ever touching the library's own box.
   Safe by default: with no JS, the curtains are already swung open
   (translateX away, opacity 0) so the book is visible. Only
   `.reveal-armed` (added by JS, only once it's confirmed the wrap is
   not yet in view) pulls them back over the book just before the
   real open animation runs. */
.flip-curtain{
  position:absolute; top:0; bottom:0; width:50%; z-index:3;
  background:var(--bg-panel-2); pointer-events:none; opacity:0;
  transition:transform 1s var(--ease), opacity 1s var(--ease);
}
.flip-curtain-left{ left:0; transform:translateX(-100%); }
.flip-curtain-right{ right:0; transform:translateX(100%); }
.menu-flip-wrap.reveal-armed .flip-curtain-left,
.menu-flip-wrap.reveal-armed .flip-curtain-right{ transform:translateX(0); opacity:1; }
.menu-flip-wrap.is-visible .flip-curtain-left{ transform:translateX(-100%); opacity:0; }
.menu-flip-wrap.is-visible .flip-curtain-right{ transform:translateX(100%); opacity:0; }
.flipbook-loading{
  position:absolute; inset:0; z-index:2; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:16px;
  background:var(--bg-panel); border:1px solid var(--line);
  color:var(--text-muted); font-family:var(--font-mono); font-size:13.5px;
}
/* An author-stylesheet display:flex always beats the browser's own
   [hidden]{display:none} rule (different cascade origin, not just
   specificity) — so this override is required for the JS-toggled
   `hidden` attribute to actually hide the spinner. */
.flipbook-loading[hidden]{ display:none; }
.flipbook-loading::before{
  content:""; width:28px; height:28px; border-radius:50%;
  border:2px solid var(--line-strong); border-top-color:var(--brass);
  animation:flipbook-spin .8s linear infinite;
}
@keyframes flipbook-spin{ to{ transform:rotate(360deg); } }
.flipbook-hint{ margin-top:18px; color:var(--text-dim); font-size:13px; font-family:var(--font-mono); }
.flip-page{
  background:#efe9dd; color:#1c1b18; display:flex; align-items:center; justify-content:center;
  font-family:var(--font-display); font-size:15px; text-align:center; padding:24px;
}

/* =========================================================
   IMAGE CAROUSEL (Gallery "Ambiente" + Intro — shared component)
   -----------------------------------------------------------
   Items are injected by js/carousel.js from a plain filename list
   in config.js. How many show at once is pure CSS (.carousel-item
   flex-basis below).
   .img-carousel-track is a fixed, non-scrolling viewport
   (overflow:hidden, no scroll-snap, no touch-action override needed —
   there's nothing left for touch/trackpad/wheel input to scroll).
   .img-carousel-rail is the actual flex row of items, moved only via
   transform:translateX() from js/carousel.js on an arrow click — never
   from a scroll/drag/swipe gesture, since the viewport can't scroll at
   all. Was previously overflow-x:auto + scroll-snap-x (matching the
   services carousel below): that meant ANY horizontal drag/swipe/
   trackpad gesture over the track — including one that just happens to
   land near the arrows on the way to clicking — paged it via native
   browser scrolling, with no JS involved to gate it. Rebuilt as a
   transform rail specifically so clicking the arrow buttons is the
   *only* possible way to move it.
   ========================================================= */
.img-carousel{ display:flex; align-items:center; gap:14px; }
.img-carousel-track{ overflow:hidden; flex:1; padding:4px 2px; }
.img-carousel-rail{
  display:flex; gap:12px;
  transition:transform .45s var(--ease); /* only ever runs from a click — see js/carousel.js */
}
.carousel-item{
  position:relative; z-index:2; flex:0 0 calc((100% - 3*12px)/4);
  aspect-ratio:1; background:var(--bg-panel); border:1px solid var(--line); overflow:hidden;
  cursor:zoom-in;
}
/* Intro cards only (Gallery photos stay plain) — compound selector so
   this reliably wins over the plain background/border above regardless
   of source order. Padding wide enough (16px, vs. glass-panel's default
   28px) that the frosted ring around the photo reads clearly instead of
   being a barely-there sliver. */
.carousel-item.glass-panel{
  background:rgba(23, 21, 19, 0.65);
  border:1px solid rgba(214, 58, 38, 0.3);
  border-top:1px solid rgba(235, 90, 63, 0.55);
  padding:16px;
}
@supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .carousel-item.glass-panel{
    background:rgba(23, 21, 19, 0.42);
    backdrop-filter:blur(6px);
    -webkit-backdrop-filter:blur(6px);
  }
}
/* Same --parallax-y composition trick as .about-media img above — a
   much smaller buffer here since Gallery/Intro's parallax factor is
   far subtler (0.95x vs About's 0.85x). */
.carousel-item img{
  width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .4s var(--ease);
  transform:translateY(var(--parallax-y, 0px)) scale(1.06);
}
.carousel-item:hover img{ transform:translateY(var(--parallax-y, 0px)) scale(1.11); }
.carousel-item::after{
  content:attr(data-caption); position:absolute; inset:0; z-index:1;
  display:flex; align-items:flex-end; padding:16px;
  background:linear-gradient(to top, rgba(0,0,0,.6), transparent 55%);
  color:var(--text); font-family:var(--font-mono); font-size:12.5px; letter-spacing:.08em;
  opacity:0; transition:opacity .35s var(--ease); pointer-events:none;
}
.carousel-item:hover::after{ opacity:1; }

/* =========================================================
   CAROUSEL LIGHTBOX
   -----------------------------------------------------------
   Same overlay pattern as .legal-overlay/.legal-panel: opacity +
   visibility transition toggled by .is-open, closable via ×, backdrop
   click, or Escape (see js/carousel.js). z-index:600 — higher than
   everything else on the page (legal panel tops out at 500) since this
   can be opened from anywhere a carousel appears.
   ========================================================= */
.lightbox-overlay{
  position:fixed; inset:0; z-index:600;
  background:rgba(0,0,0,.85);
  display:flex; align-items:center; justify-content:center; padding:40px;
  opacity:0; visibility:hidden; transition:opacity .3s var(--ease), visibility .3s var(--ease);
}
.lightbox-overlay.is-open{ opacity:1; visibility:visible; }
/* width/height (not just max-width/max-height) are what make
   object-fit:contain actually scale the photo UP to fill this box —
   with only max-* set, an <img> with no explicit size renders at its
   own natural pixel size and object-fit has nothing to contain into,
   which is why this looked small before regardless of the max-* value. */
.lightbox-img{
  width:90vw; height:90vh; max-width:90vw; max-height:90vh; object-fit:contain;
  border-radius:4px; box-shadow:0 30px 90px rgba(0,0,0,.6);
}
.lightbox-close{
  position:absolute; top:16px; right:20px; width:44px; height:44px; border-radius:50%;
  border:1px solid var(--line-strong); background:rgba(0,0,0,.4); color:var(--text);
  font-size:26px; line-height:1; cursor:pointer; transition:color .2s, border-color .2s;
}
.lightbox-close:hover{ color:var(--brass-bright); border-color:var(--brass); }

/* =========================================================
   CONTACT
   ========================================================= */
.contact-grid{ display:grid; grid-template-columns:.85fr 1.15fr; gap:70px; align-items:stretch; }
.contact-card{ background:var(--bg-panel); border:1px solid var(--line); padding:48px 42px; }
.contact-row{ display:flex; gap:16px; padding:18px 0; border-bottom:1px solid var(--line); }
.contact-row:last-of-type{ border-bottom:0; }
.contact-row .icon{ color:var(--brass); flex-shrink:0; width:20px; padding-top:2px; }
.contact-row a, .contact-row div{ color:var(--text); font-size:15.5px; }
.contact-row a{ text-decoration:underline; text-decoration-color:var(--line-strong); }
.contact-row a:hover{ color:var(--brass-bright); text-decoration-color:var(--brass); }
.map-column{ display:flex; flex-direction:column; gap:14px; }
.map-column .btn{ width:100%; justify-content:center; }
.map-wrap{ position:relative; border:1px solid var(--line); overflow:hidden; min-height:340px; flex:1; }
.map-wrap iframe{ width:100%; height:100%; min-height:340px; border:0; filter:grayscale(.4) invert(.92) contrast(.9); }
.map-open-link{
  position:absolute; bottom:14px; right:14px; background:var(--bg-panel-2);
  border:1px solid var(--line-strong); color:var(--text); font-size:12.5px;
  padding:8px 14px; border-radius:2px; transition:border-color .2s, color .2s;
}
.map-open-link:hover{ border-color:var(--brass); color:var(--brass-bright); }
.hours-list{ margin-top:28px; }
.hours-list li{
  display:flex; justify-content:space-between; flex-wrap:wrap; gap:4px 12px;
  padding:8px 0; border-bottom:1px dashed var(--line); font-size:14.5px;
}
.hours-list li span:first-child{ color:var(--text-muted); }
.hours-list li span:last-child{ font-family:var(--font-mono); }

/* =========================================================
   FOOTER
   ========================================================= */
footer{ padding:60px 0 40px; }
.footer-grid{ display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:20px; }
.footer-grid .brand{ font-size:19px; }
.footer-links{ display:flex; gap:26px; flex-wrap:wrap; }
.footer-links a, .footer-legal-link{
  background:none; border:0; padding:0; font:inherit; cursor:pointer;
  color:var(--text-dim); font-size:13.5px; transition:color .2s;
}
.footer-links a:hover, .footer-legal-link:hover{ color:var(--brass-bright); }
.footer-note{ margin-top:30px; color:var(--text-dim); font-size:12.5px; text-align:center; }

/* =========================================================
   RESERVATION TAB + DRAWER  (signature element)
   ========================================================= */
.res-tab{
  position:fixed; left:0; top:50%; transform:translateY(-50%) translateX(0);
  z-index:300; background:var(--brass); color:#161207;
  writing-mode:vertical-rl; text-orientation:mixed;
  padding:26px 12px; font-family:var(--font-mono); font-size:13px;
  letter-spacing:.14em; font-weight:600; border:0;
  border-radius:0 6px 6px 0;
  box-shadow:6px 0 24px rgba(0,0,0,.35);
  display:flex; align-items:center; gap:10px;
  transition:background .2s, padding-left .2s var(--ease);
}
.res-tab::before{ content:"—"; opacity:.6; }
.res-tab:hover{ background:var(--brass-bright); padding-left:16px; }

.res-drawer{
  position:fixed; top:0; left:0; height:100vh; width:min(440px,92vw);
  background:var(--bg-panel-2); border-right:1px solid var(--line-strong);
  z-index:400; transform:translateX(-100%);
  transition:transform .45s var(--ease);
  box-shadow:40px 0 80px rgba(0,0,0,.5);
  display:flex; flex-direction:column;
}
.res-drawer.is-open{ transform:translateX(0); }
.res-drawer-head{
  padding:34px 34px 22px; border-bottom:1px dashed var(--line-strong);
  display:flex; align-items:flex-start; justify-content:space-between;
}
.res-drawer-head h3{ font-size:24px; }
.res-drawer-head p{ color:var(--text-muted); font-size:14px; margin-top:8px; }
.res-drawer-close{ background:none; border:0; color:var(--text-muted); font-size:22px; }
.res-drawer-close:hover{ color:var(--brass-bright); }
.res-form{ padding:28px 34px; overflow-y:auto; flex:1; }
.res-field{ margin-bottom:20px; }
.res-field label{ display:block; font-size:12.5px; letter-spacing:.05em; text-transform:uppercase; color:var(--text-dim); margin-bottom:8px; font-family:var(--font-mono); }
.res-field input, .res-field textarea, .res-field select{
  width:100%; background:var(--bg); border:1px solid var(--line-strong); color:var(--text);
  padding:13px 14px; font-family:var(--font-body); font-size:14.5px; border-radius:2px;
}
.res-field input:focus, .res-field textarea:focus, .res-field select:focus{ border-color:var(--brass); }
.res-row{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
.res-submit{ width:100%; justify-content:center; margin-top:6px; }
.res-status{ margin-top:14px; font-size:13.5px; text-align:center; min-height:18px; }
.res-status.ok{ color:var(--jade-bright); }
.res-status.err{ color:#d67878; }
.res-overlay{
  position:fixed; inset:0; background:rgba(0,0,0,.55); z-index:399;
  opacity:0; visibility:hidden; transition:opacity .35s var(--ease);
}
.res-overlay.is-open{ opacity:1; visibility:visible; }

/* =========================================================
   IMPRESSUM / DATENSCHUTZ SLIDE-UP PANEL
   -----------------------------------------------------------
   Same overlay + open/close pattern as the reservation drawer
   above, but the panel slides up from the bottom instead of in
   from the left, and is shared by both buttons (content swapped
   per click, see js/legal.js).
   ========================================================= */
.legal-overlay{
  position:fixed; inset:0; background:rgba(0,0,0,.55); z-index:499;
  opacity:0; visibility:hidden; transition:opacity .35s var(--ease), visibility .35s var(--ease);
}
.legal-overlay.is-open{ opacity:1; visibility:visible; }

.legal-panel{
  position:fixed; left:0; right:0; bottom:0; z-index:500;
  height:85vh; max-height:85vh;
  background:var(--bg-panel-2); border-top:1px solid var(--line-strong);
  border-radius:16px 16px 0 0;
  transform:translateY(100%);
  visibility:hidden;
  transition:transform .45s var(--ease), visibility .45s var(--ease);
  box-shadow:0 -40px 80px rgba(0,0,0,.5);
  display:flex; flex-direction:column;
}
.legal-panel.is-open{ transform:translateY(0); visibility:visible; }
/* Desktop: shrink into a centered floating card instead of a full-width
   sheet. Mobile keeps the full-width bottom sheet above unchanged. */
@media (min-width:768px){
  .legal-panel{
    left:50%; right:auto; bottom:6vh;
    width:30vw; min-width:480px; max-width:640px;
    height:auto; max-height:80vh;
    border-radius:16px;
    border-top:0;
    /* closed position must clear the box's own height (100%) PLUS the
       6vh resting offset from the viewport bottom — translateY(100%)
       alone only covers the box's height and left a permanent ~6vh
       sliver stuck on screen at all times. */
    transform:translate(-50%, calc(100% + 6vh + 40px));
  }
  .legal-panel.is-open{ transform:translate(-50%, 0); }
}
.legal-panel-head{
  padding:26px 34px 20px; border-bottom:1px dashed var(--line-strong);
  display:flex; align-items:flex-start; justify-content:space-between; flex-shrink:0;
}
.legal-panel-head h3{ font-size:23px; }
.legal-panel-close{ background:none; border:0; color:var(--text-muted); font-size:22px; }
.legal-panel-close:hover{ color:var(--brass-bright); }
.legal-panel-body{ padding:28px 34px 44px; overflow-y:auto; flex:1; color:var(--text-muted); font-size:15px; line-height:1.7; }
.legal-text p{ white-space:pre-line; margin:0 0 16px; }
.legal-text p:last-child{ margin-bottom:0; }
.legal-subtitle{ color:var(--brass-bright); font-weight:600; font-size:15.5px; margin:22px 0 8px; }
.legal-subtitle:first-child{ margin-top:0; }
.legal-table{ width:100%; border-collapse:collapse; }
.legal-table tr{ border-bottom:1px dashed var(--line); }
.legal-table tr:last-child{ border-bottom:0; }
.legal-table td{ padding:11px 0; font-size:14.5px; vertical-align:top; }
.legal-table td:first-child{ color:var(--text-dim); width:42%; padding-right:20px; }
.legal-table td:last-child{ color:var(--text); }

/* =========================================================
   COOKIE BANNER
   ========================================================= */
.cookie-banner{
  position:fixed; left:0; right:0; bottom:0; z-index:350;
  background:var(--bg-panel-2); border-top:1px solid var(--line);
  padding:20px 32px; display:flex; align-items:center; justify-content:space-between;
  gap:16px 28px; flex-wrap:wrap; box-shadow:0 -10px 30px rgba(0,0,0,.35);
}
.cookie-banner[hidden]{ display:none; }
.cookie-banner p{ margin:0; color:var(--text-muted); font-size:14px; max-width:640px; }
.cookie-actions{ display:flex; align-items:center; gap:20px; flex-shrink:0; }

/* =========================================================
   AMBIENT DRIFT LAYERS (purely decorative — aria-hidden, never
   carries information, so unlike text/images these are allowed to
   simply not appear at all with no JS; nothing is ever hidden FROM
   a visitor, there's just no ambient motion added on top). Both use
   plain CSS @keyframes with animation-play-state toggled by JS via
   the shared initDriftLayer() helper in animations.js — no
   per-frame JS math, so this never competes with the parallax rAF
   loop for the same work, and running on the compositor via
   transform/opacity alone keeps it cheap even while active.
   ========================================================= */
.drift-dots, .menu-petals{
  position:fixed; inset:0; z-index:1; overflow:hidden; pointer-events:none;
  opacity:0; transition:opacity .6s var(--ease);
}
.drift-dots.is-active, .menu-petals.is-active{ opacity:1; }

.drift-dot{
  position:absolute; top:-20px; width:3px; height:3px; border-radius:50%;
  background:var(--brass);
  box-shadow:0 0 6px 1px var(--brass);
  animation:drift var(--drift-duration, 7s) linear infinite;
  animation-delay:var(--drift-delay, 0s);
  animation-play-state:paused;
}
.drift-dots.is-active .drift-dot{ animation-play-state:running; }
.drift-dot:nth-child(even){ background:var(--brass-bright); box-shadow:0 0 6px 1px var(--brass-bright); }
@keyframes drift{
  0%{ transform:translate(0, -20px); opacity:0; }
  10%{ opacity:.8; }
  90%{ opacity:.5; }
  100%{ transform:translate(var(--drift-x, 0px), 100vh); opacity:0; }
}

.petal{
  position:absolute; top:-24px; width:9px; height:14px;
  border-radius:0 100% 0 100%; /* asymmetric corners read as a petal, not a dot */
  animation:petal-fall var(--fall-duration, 8s) linear infinite;
  animation-delay:var(--fall-delay, 0s);
  animation-play-state:paused;
}
.menu-petals.is-active .petal{ animation-play-state:running; }
.petal-left{ left:4%; }
.petal-right{ right:4%; }
.petal:nth-child(3n+1){ background:#f2b8c6; }
.petal:nth-child(3n+2){ background:#e89aad; }
.petal:nth-child(3n){ background:#f7cdd8; }
@keyframes petal-fall{
  0%{ transform:translateY(-24px) rotate(0deg); opacity:0; }
  10%{ opacity:.9; }
  90%{ opacity:.6; }
  100%{ transform:translateY(100vh) rotate(var(--rotate-end, 320deg)); opacity:0; }
}

/* =========================================================
   SIDE SECTION-DOT NAV (compass — desktop only)
   ========================================================= */
.section-dots{
  position:fixed; right:28px; top:50%; transform:translateY(-50%); z-index:250;
  display:flex; flex-direction:column; align-items:center; gap:16px;
}
.section-dot{
  width:8px; height:8px; border-radius:50%; background:var(--text-dim);
  border:0; padding:0; opacity:.6;
  transition:transform .3s var(--ease), background .3s var(--ease), opacity .3s var(--ease);
}
.section-dot:hover{ opacity:1; }
.section-dot.is-active{ background:var(--brass); opacity:1; transform:scale(1.6); }

/* =========================================================
   RESPONSIVE
   ========================================================= */
@media (max-width:960px){
  .section-dots{ display:none; }
  .hero-inner{ grid-template-columns:1fr; }
  .hero-aside{ border-left:0; border-top:1px solid var(--line); padding-left:0; padding-top:26px; display:flex; gap:40px; }
  .about-grid, .contact-grid{ grid-template-columns:1fr; }
  .dish-row{ grid-template-columns:1fr; }
  .dish-card{ border-right:0; border-bottom:1px solid var(--line); }
  .pillars{ grid-template-columns:1fr; gap:20px 0; }
  .pillar{ padding-bottom:0; }
  .pillar:nth-child(2), .pillar:nth-child(3){ margin-top:0; margin-left:0; }
  .carousel-item{ flex-basis:calc((100% - 12px)/2); }
  .nav-links{ display:none; }
  .nav-toggle{ display:block; }
}
@media (max-width:560px){
  .container{ padding:0 20px; }
  .section{ padding:80px 0; }
  .lang-panel{ grid-template-columns:repeat(2,minmax(100px,1fr)); right:-20px; }
  .services-carousel{ padding:0 6px; gap:6px; }
  .service-item{ width:104px; }
  .service-item svg{ width:36px; height:36px; }
  .carousel-item{ flex-basis:100%; }
  .img-carousel{ gap:6px; }
  .legal-panel-head{ padding:22px 20px 16px; }
  .legal-panel-body{ padding:22px 20px 34px; }
  .legal-table td:first-child{ width:auto; padding-right:14px; }
  .cookie-banner{ flex-direction:column; align-items:stretch; text-align:center; padding:18px 20px; }
  .cookie-actions{ justify-content:center; }
  .hours-list li{ font-size:13px; }
  /* Near-fullscreen on phones — the 40px overlay padding would eat too
     much of an already-small viewport, so it shrinks along with it. */
  .lightbox-overlay{ padding:14px; }
  .lightbox-img{ width:95vw; height:95vh; max-width:95vw; max-height:95vh; }
  .lightbox-close{ top:8px; right:10px; }
}

/* =========================================================
   MENU FLIPBOOK CURSOR
   -----------------------------------------------------------
   Overrides the site-wide fan cursor (see body{cursor} above) while
   hovering the book itself. Declared after body{} and with an ID
   selector (higher specificity than the type selector on body) so it
   always wins here regardless of source order.
   ========================================================= */
#menu-flip, #menu-flip *{
  cursor:url('../assets/img/cursors/katana-cursor.png') 1 0, pointer;
}
