/* ==========================================================================
   Do Sushi Haus – Motion system
   Driven by js/motion.js. Everything here only applies when <html> has
   .js-motion (JS loaded + no reduced-motion), so content is never hidden
   without JavaScript.
   Rules:  · only transform / opacity / clip-path / filter are animated
           · entering = slow & soft (expo-out), leaving = quicker & quiet
           · --dir = 1 when an element enters from below, -1 from above
   ========================================================================== */

:root {
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);
}

/* ---------- Scroll progress (thin gold thread under the header) ---------- */
.scroll-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 60; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--gold) 20%, var(--gold-soft) 80%, var(--koi));
  transform-origin: 0 50%; transform: scaleX(var(--progress, 0));
}

/* ---------- Smart header: hides going down, returns going up ---------- */
.site-header { transition: transform .5s var(--ease-out), background-color .4s, border-color .4s, backdrop-filter .4s; }
.header-hidden .site-header { transform: translateY(-100%); }
.menu-nav { transition: top .5s var(--ease-out); }
.header-hidden .menu-nav { top: 0; }
.header-hidden .site-header { transform: translateY(-100%); }

/* ---------- Back to top (koi-gold progress ring) ---------- */
.to-top {
  position: fixed; right: 1rem; bottom: calc(1rem + env(safe-area-inset-bottom)); z-index: 49;
  width: 52px; height: 52px; border-radius: 50%; border: 0; padding: 0; cursor: pointer;
  background: rgba(17,17,17,.85); backdrop-filter: blur(6px); color: var(--gold);
  display: grid; place-items: center;
  opacity: 0; transform: translateY(16px) scale(.9); pointer-events: none;
  transition: opacity .4s, transform .5s var(--ease-out);
}
.to-top.is-shown { opacity: 1; transform: none; pointer-events: auto; }
.to-top svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.to-top circle { fill: none; stroke-width: 1.5; }
.to-top .track { stroke: var(--line); }
.to-top .bar { stroke: var(--gold); stroke-dasharray: 1; stroke-dashoffset: calc(1 - var(--progress, 0)); }
.to-top span { font-size: 1.1rem; line-height: 1; transition: transform .3s var(--ease-out); }
.to-top:hover span { transform: translateY(-3px); }
@media (max-width: 1023px) { .to-top { bottom: calc(5.25rem + env(safe-area-inset-bottom)); width: 44px; height: 44px; } }

@media (prefers-reduced-motion: no-preference) {

  /* ---------- 1. Basic reveal: fade + rise ---------- */
  .js-motion .reveal,
  .js-motion [data-stagger] > :not([data-split]) {
    opacity: 0;
    transform: translate3d(0, calc(var(--dir, 1) * 36px), 0) rotate(calc(var(--dir, 1) * var(--rot, 0deg)));
    transition: opacity .45s ease, transform .6s var(--ease-in-out);
  }
  .js-motion .reveal.is-in,
  .js-motion [data-stagger].is-in > :not([data-split]) {
    opacity: 1; transform: none;
    transition: opacity 1s var(--ease-out) var(--d, 0ms), transform 1.25s var(--ease-out) var(--d, 0ms);
  }

  /* ---------- 2. Split headline: words rise out of a mask ---------- */
  .split-word { display: inline-block; overflow: hidden; vertical-align: top; padding: .08em .02em .14em; margin: -.08em -.02em -.14em; }
  .split-word > span { display: inline-block; }
  .js-motion .split-word > span {
    transform: translate3d(0, calc(var(--dir, 1) * 110%), 0) rotate(calc(var(--dir, 1) * 6deg));
    transform-origin: 0 100%;
    transition: transform .5s var(--ease-in-out);
  }
  .js-motion .is-in .split-word > span {
    transform: none;
    transition: transform 1.3s var(--ease-out) var(--d, 0ms);
  }

  /* ---------- 3. Title frame: opens from the centre like a noren ---------- */
  .js-motion [data-frame] .title-frame__box {
    clip-path: inset(-30px 50% -30px 50%);
    transition: clip-path .6s var(--ease-in-out);
  }
  .js-motion [data-frame] .title-frame__sub,
  .js-motion [data-frame] .title-frame__desc { opacity: 0; transition: opacity .4s, transform .5s var(--ease-in-out); }
  .js-motion [data-frame] .title-frame__sub { transform: translate(-50%, 50%) translateY(8px); }
  .js-motion [data-frame] .title-frame__desc { transform: translateY(14px); }
  .js-motion [data-frame].is-in .title-frame__box { clip-path: inset(-30px -30px -30px -30px); transition: clip-path 1.3s var(--ease-out); }
  .js-motion [data-frame].is-in .title-frame__sub { opacity: 1; transform: translate(-50%, 50%); transition: opacity .8s .55s, transform 1s var(--ease-out) .55s; }
  .js-motion [data-frame].is-in .title-frame__desc { opacity: 1; transform: none; transition: opacity 1s .75s, transform 1.2s var(--ease-out) .75s; }

  /* ---------- 4. Ink reveal for round dishes + ensō ring drawing ---------- */
  .js-motion .hero__visual.reveal-ink img { clip-path: inset(0 50% 0 50%); }
  .js-motion .hero__visual.reveal-ink.is-in img { clip-path: inset(0 0 0 0); }
  .js-motion .reveal-ink img {
    clip-path: circle(0% at 50% 55%); transform: scale(1.25);
    transition: clip-path .6s var(--ease-in-out), transform .8s var(--ease-in-out);
  }
  .js-motion .reveal-ink.is-in img {
    clip-path: circle(71% at 50% 50%); transform: none;
    transition: clip-path 1.6s var(--ease-out) var(--d, 0ms), transform 2.2s var(--ease-out) var(--d, 0ms);
  }
  .js-motion .reveal-ink .ring-draw path { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset .5s; }
  .js-motion .reveal-ink.is-in .ring-draw path { stroke-dashoffset: 0; transition: stroke-dashoffset 2s var(--ease-out) calc(var(--d, 0ms) + .35s); }
  .js-motion .reveal-ink.is-in .ring-draw path + path { transition-delay: calc(var(--d, 0ms) + 1.1s); transition-duration: .9s; }

  /* ---------- 5. Brush wipe for wide photos ---------- */
  .js-motion .reveal-wipe { clip-path: inset(0 100% 0 0 round 6px); transition: clip-path .6s var(--ease-in-out); }
  .js-motion .reveal-wipe img { transform: scale(1.18); transition: transform .8s var(--ease-in-out); }
  .js-motion .reveal-wipe::after { opacity: 0; transform: scale(1.04); transition: opacity .4s, transform .6s; }
  .js-motion .reveal-wipe.is-in { clip-path: inset(0 0 0 0 round 6px); transition: clip-path 1.5s var(--ease-out); }
  .js-motion .reveal-wipe.is-in img { transform: none; transition: transform 2.4s var(--ease-out); }
  .js-motion .reveal-wipe.is-in::after { opacity: 1; transform: none; transition: opacity 1s 1s, transform 1.4s var(--ease-out) 1s; }

  /* ---------- 6. Lanterns drop on their string, then keep swaying ---------- */
  .js-motion [data-drop] > * {
    translate: 0 -220px; opacity: 0;
    transition: translate .6s var(--ease-in-out), opacity .4s;
  }
  .js-motion [data-drop].is-in > * {
    translate: 0 0; opacity: 1;
    transition: translate 1.6s var(--ease-spring) var(--d, 0ms), opacity .6s var(--d, 0ms);
  }

  /* ---------- 7. Scroll velocity: lanterns & plates lean with momentum ---------- */
  .lantern { rotate: calc(var(--vel, 0) * 1.3deg); transition: rotate .9s var(--ease-spring); }
  /* page scroll (--vel) and belt drag (--bvel) both tilt the plates */
  .plate__dish { rotate: calc((var(--vel, 0) + var(--bvel, 0)) * -.7deg); transition: translate .45s var(--ease-out), box-shadow .45s; }

  /* ---------- 8. Parallax targets get headroom so edges never show ---------- */
  .world__img img[data-speed], .alley__bg img[data-speed], .cat__banner img[data-speed] { scale: 1.18; }
  [data-speed], [data-rotate], [data-hero-out] { will-change: translate, rotate; }

  /* ---------- 9. Hero dish: breathes in after the intro ---------- */
  .js-motion .hero__visual .hero__ring { opacity: 0; transition: opacity 1s; }
  .js-motion .hero__visual.is-in .hero__ring { opacity: 1; transition: opacity 1.4s .5s; }

  /* ---------- 10. Set cards: hover uses translate so it never fights the reveal ---------- */
  .set-card:hover { transform: none; translate: 0 -6px; }
  .set-card { transition: translate .4s var(--ease-out), border-color .4s; }
  .sets > :nth-child(3n+1) { --rot: -1.5deg; }
  .sets > :nth-child(3n) { --rot: 1.5deg; }

  /* ---------- 11. Dish rows: price dots draw after the row lands ---------- */
  .js-motion [data-stagger] .dish__head::after { transform-origin: left; transform: translateY(-.3em) scaleX(0); transition: transform .4s; }
  .js-motion [data-stagger].is-in .dish__head::after { transform: translateY(-.3em) scaleX(1); transition: transform 1.2s var(--ease-out) calc(var(--d, 0ms) + .3s); }

  /* ---------- 12. Footer: pond surfaces gently ---------- */
  .js-motion .pond .footer__grid > * { opacity: 0; transform: translateY(24px); transition: opacity .5s, transform .6s; }
  .js-motion .pond.is-in .footer__grid > * { opacity: 1; transform: none; transition: opacity 1.2s var(--ease-out) var(--d, 0ms), transform 1.4s var(--ease-out) var(--d, 0ms); }
}

/* ---------- 13. Lantern alley glows brighter as it scrolls into view ---------- */
@media (prefers-reduced-motion: no-preference) {
  .alley[data-glow] .alley__string { filter: brightness(calc(.45 + var(--p, 1) * .9)) saturate(calc(.7 + var(--p, 1) * .5)); }
  .alley[data-glow]::before { opacity: calc(1.15 - var(--p, 1) * .35); }
}

/* ---------- 14. Scrubbed text (driven by scroll position, reversible) ---------- */
.scrub-word { color: rgba(242,237,227,.16); transition: color .35s ease, text-shadow .5s; }
.scrub-word.is-lit { color: var(--ink); }
[data-scrub-text] em .scrub-word.is-lit, [data-scrub-text] .gold .scrub-word.is-lit { color: var(--gold); text-shadow: 0 0 24px rgba(212,167,44,.25); }

/* ---------- 15. Fixed-background window: content scrolls over a still photo ---------- */
.window { position: relative; clip-path: inset(0); isolation: isolate; }
.window__bg { position: fixed; inset: 0; z-index: -1; pointer-events: none; }
.window__bg img { width: 100%; height: 100%; object-fit: cover; filter: brightness(.42) saturate(1.1) blur(1.5px); transform: scale(1.04); }
.window__bg::after { content: ""; position: absolute; inset: 0; background: radial-gradient(ellipse at center, transparent 30%, rgba(10,10,10,.75) 100%), linear-gradient(rgba(17,17,17,.6), transparent 25%, transparent 75%, rgba(17,17,17,.7)); }
