/* Ravaya motion layer.
   Loaded after styles.css. Every rule below is gated by `.motion`, which the inline
   head script only sets when the visitor has NOT asked for reduced motion. Without the
   class (or without motion.js) the page is fully static and complete.

   Budget: one rehearsed entrance (the sign and the scene), depth while scrolling the hero,
   one signature reveal per world (the paddy fills), quick feedback elsewhere.
   Durations: feedback 150-250 ms, state 250-400 ms, entrances 600-1200 ms. Curves: exponential ease-out, no bounce.
   Ambient loops (sway, clouds, birds) run a limited number of cycles and then rest. */

:root {
  --ease-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-in: cubic-bezier(0.7, 0, 0.84, 0);
}

/* ================================================================
   1. Hero: the scene arrives, the sign swings in, the rest follows
   ================================================================ */
.motion:not(.ready) .hero .top > *,
.motion:not(.ready) .sign,
.motion:not(.ready) .hero .lead,
.motion:not(.ready) .hero .cta > * { visibility: hidden; }

/* The scene plays the moment app.js inserts it, over the plain sky colour of its container.
   It is not gated by `.ready`: that arrives only after fonts, and the drawing would show, vanish and fade in again.
   Opacity only: scaling or blurring the drawing would make the browser re-rasterise every sheet on every frame. */
.motion .hero__scene .scene { animation: scene-in 1.2s ease-out backwards; }
@keyframes scene-in { from { opacity: 0; } }
.motion.ready .hero .top > * { animation: fade-in 0.8s ease-out 0.2s backwards; }
.motion.ready .sign__beam { animation: fade-in 0.5s ease-out 0.2s backwards; }
.motion.ready .sign__board { animation: hang-in 1.2s var(--ease) 0.25s backwards, swing 7s ease-in-out 1.6s 6 alternate both; }
.motion.ready .hang { animation: tag-in 1s var(--ease) 0.7s backwards, tag-swing 5s ease-in-out 1.9s 6 alternate both; }
.motion.ready .hero .lead { animation: rise-in 0.8s var(--ease) 0.8s backwards; }
.motion.ready .hero .cta > :nth-child(1) { animation: rise-in 0.8s var(--ease) 0.95s backwards; }
.motion.ready .hero .cta > :nth-child(2) { animation: rise-in 0.8s var(--ease) 1.05s backwards; }
@keyframes hang-in { from { opacity: 0; rotate: -3deg; translate: 0 -1rem; } }
@keyframes swing { from { rotate: -0.3deg; } to { rotate: 0.3deg; } }
@keyframes tag-in { from { opacity: 0; rotate: 6deg; translate: 0 -0.6rem; } }
@keyframes tag-swing { from { rotate: 0.9deg; } to { rotate: 1.9deg; } }
@keyframes rise-in { from { opacity: 0; translate: 0 1rem; } }
@keyframes fade-in { from { opacity: 0; } }

/* Ambient: palms lean, clouds drift, egrets cross the sky, grain heads sway, the paddy water glints. */
.motion .scene .palm .crown { animation: sway-crown 8s ease-in-out 8 alternate both; }
.motion .scene .cloud { animation: drift var(--d, 90s) ease-in-out 4 alternate both; }
.motion .scene .egret { animation: glide var(--t, 90s) linear var(--d, 0s) 4 both; }
.motion .scene .egret .wing { transform-box: fill-box; transform-origin: 50% 100%; animation: flap 0.8s ease-in-out 500 alternate; }
.motion .scene .water.hi { animation: glint 5s ease-in-out 8 alternate both; }
.motion .stalk, .motion .sprig { animation: sway 6s ease-in-out 8 alternate both; }
@keyframes sway { from { rotate: -0.9deg; } to { rotate: 1.1deg; } }
@keyframes sway-crown { from { rotate: -0.9deg; } to { rotate: 1deg; } }
@keyframes drift { from { translate: -40px 0; } to { translate: 70px 0; } }
@keyframes glide { from { translate: -140px var(--y); } to { translate: 1740px var(--y); } }
@keyframes flap { from { scale: 1 1; } to { scale: 1 0.35; } }
@keyframes glint { from { opacity: 0.45; } to { opacity: 0.9; } }
.motion .scene .sun { transition: translate 1.2s var(--ease); }

/* ================================================================
   2. Depth while scrolling (progressive: Chromium, Safari 26+; static elsewhere)
   ================================================================ */
@supports (animation-timeline: scroll()) {
  .motion .progress {
    display: block; position: fixed; inset: 0 0 auto 0; height: 3px; z-index: 80; background: var(--orange);
    transform-origin: left; transform: scaleX(0); animation: progress linear both; animation-timeline: scroll(root);
  }
  @keyframes progress { to { transform: scaleX(1); } }

  /* Far layers follow the page a little, near layers move ahead of it. */
  .motion .scene .lyr { animation: par linear both; animation-timeline: scroll(root); animation-range: 0 100svh; }
  @keyframes par { to { translate: 0 var(--dy, 0px); } }
  .motion .hero__body { animation: body-out linear both; animation-timeline: scroll(root); animation-range: 0 75svh; }
  @keyframes body-out { to { opacity: 0.1; translate: 0 -2.5rem; } }
}

/* ================================================================
   3. World headers: the paddy fills with water, then the title arrives
   ================================================================ */
.motion .world__head.reveal .world__art { transition: clip-path 1.1s var(--ease); }
.motion .world__head.reveal:not(.is-in) .world__art { clip-path: inset(100% 0 0 0); }
.motion .world__head.reveal.is-in .world__art { clip-path: inset(0 0 0 0); }
.motion .b-t { transition: translate 1.1s var(--ease) calc(var(--k, 0) * 110ms + 0.3s); }
.motion .world__head:not(.is-in) .b-t { translate: 0 70px; }
.motion .world__title, .motion .world__desc { transition: opacity 0.6s ease-out 0.4s, translate 0.8s var(--ease) 0.4s; }
.motion .world__desc { transition-delay: 0.55s; }
.motion .world__head:not(.is-in) .world__title, .motion .world__head:not(.is-in) .world__desc { opacity: 0; translate: 0 0.8rem; }
.motion .world__head:not(.is-in) .lf { opacity: 0; }
.motion .world__head.is-in .lf { animation: leaf-in 0.9s var(--ease) calc(var(--i, 0) * 45ms + 0.5s) backwards; }
@keyframes leaf-in { from { opacity: 0; scale: 0.4; } }

/* ================================================================
   4. Sections and dishes
   ================================================================ */
.motion .sec__head:not(.in), .motion .item:not(.in) { opacity: 0; }
.motion .sec__head.in { animation: item-in 0.6s var(--ease) backwards; }
.motion .item.in { animation: item-in 0.6s var(--ease) var(--d, 0ms) backwards; }
.motion .item--pic.in .snap { animation: snap-in 0.85s var(--ease) calc(var(--d, 0ms) + 90ms) backwards; }
.motion .item.in > .price { animation: stick-on 0.55s var(--ease) calc(var(--d, 0ms) + 260ms) backwards; }
@keyframes item-in { from { opacity: 0; translate: 0 0.8rem; } }
/* Lazy photos develop in place once loaded instead of snapping in (motion.js marks them `.ok`). */
.motion .snap img { transition: opacity 0.4s ease-out; }
.motion .snap img:not(.ok) { opacity: 0; }
.motion .settled .snap img { transition: none; }
@keyframes snap-in { from { opacity: 0; scale: 0.92; rotate: -5deg; } }
@keyframes stick-on { from { opacity: 0; scale: 1.15; rotate: 3deg; } }
/* Filtering and searching rebuild the list; that should feel like a quick refresh, not a replay. */
.motion .settled .sec__head:not(.in), .motion .settled .item:not(.in) { opacity: 1; }
.motion .settled .sec__head.in, .motion .settled .item.in, .motion .settled .item--pic.in .snap, .motion .settled .item.in > .price, .motion .settled .world__head .lf { animation: none; }

/* ================================================================
   5. The rail and small state changes
   ================================================================ */
.motion .langpanel { transform-origin: top right; transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), display 0.22s allow-discrete; }
.motion .langpanel[hidden] { display: none; opacity: 0; transform: scale(0.94) translateY(-0.4rem); transition-duration: 0.15s; }
@starting-style { .motion .langpanel:not([hidden]) { opacity: 0; transform: scale(0.94) translateY(-0.4rem); } }
.motion .totop { display: inline-flex; opacity: 0; visibility: hidden; translate: 0 0.75rem; scale: 0.9; transition: opacity 0.25s ease, translate 0.3s var(--ease), scale 0.3s var(--ease), visibility 0s linear 0.3s; }
.motion .totop[data-show='true'] { opacity: 1; visibility: visible; translate: 0 0; scale: 1; transition-delay: 0s; }
.motion .totop:active { scale: 0.94; }

/* Theme and language changes run through the View Transitions API when available. */
::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
.vt-theme::view-transition-old(root) { z-index: 1; }
.vt-theme::view-transition-new(root) { z-index: 2; }
.vt-lang::view-transition-old(root) { animation: vt-out 0.16s ease both; }
.vt-lang::view-transition-new(root) { animation: vt-in 0.32s var(--ease) both; }
@keyframes vt-out { to { opacity: 0; } }
@keyframes vt-in { from { opacity: 0; filter: blur(4px); } }

/* ================================================================
   6. The gate sign, reviews and visit
   ================================================================ */
.motion .gate:not(.in) .gate__sign { opacity: 0; rotate: -3deg; translate: 0 0.8rem; }
.motion .gate__sign { transition: opacity 0.7s ease-out, rotate 1s var(--ease), translate 1s var(--ease); }
.motion .gate:not(.in) .gate__note { opacity: 0; translate: 0 1rem; }
.motion .gate__note { transition: opacity 0.7s ease-out 0.2s, translate 0.8s var(--ease) 0.2s; }

.motion .reviews:not(.in) .reviews__sprig { opacity: 0; }
.motion .reviews.in .reviews__sprig { animation: fade-in 0.8s ease-out backwards; }
.motion .reviews:not(.in) .lf { opacity: 0; }
.motion .reviews.in .lf { animation: leaf-in 0.9s var(--ease) calc(var(--i, 0) * 12ms + 0.3s) backwards; }
.motion .reviews:not(.in) .score__num { opacity: 0; rotate: -6deg; scale: 0.9; }
.motion .score__num { transition: opacity 0.5s ease-out, rotate 0.9s var(--ease), scale 0.9s var(--ease); }
.motion .rating .ears svg { transition: opacity 0.4s ease-out, scale 0.6s var(--ease); }
.motion .reviews:not(.in) .rating .ears svg { opacity: 0; scale: 0.5; }
.motion .rating .ears svg:nth-child(2) { transition-delay: 80ms; }
.motion .rating .ears svg:nth-child(3) { transition-delay: 160ms; }
.motion .rating .ears svg:nth-child(4) { transition-delay: 240ms; }
.motion .rating .ears svg:nth-child(5) { transition-delay: 320ms; }
.motion .dist .bar i { transform-origin: left; transition: transform 1.1s var(--ease); }
.motion .reviews:not(.in) .dist .bar i { transform: scaleX(0); }
.motion .dist div:nth-child(2) .bar i { transition-delay: 90ms; }
.motion .dist div:nth-child(3) .bar i { transition-delay: 180ms; }
.motion .dist div:nth-child(4) .bar i { transition-delay: 270ms; }
.motion .dist div:nth-child(5) .bar i { transition-delay: 360ms; }
.motion .topics li { transition: opacity 0.5s ease-out, translate 0.6s var(--ease); }
.motion .reviews:not(.in) .topics li { opacity: 0; translate: 0 0.7rem; }
.motion .topics li:nth-child(2) { transition-delay: 70ms; }
.motion .topics li:nth-child(3) { transition-delay: 140ms; }
.motion .topics li:nth-child(4) { transition-delay: 210ms; }
.motion .quote { transition: opacity 0.7s ease-out var(--d, 0ms), translate 0.7s var(--ease) var(--d, 0ms); }
.motion .quote:not(.in) { opacity: 0; translate: 0 1rem; }
.motion .quote .ears svg { transition: opacity 0.4s ease-out, scale 0.6s var(--ease); }
.motion .quote:not(.in) .ears svg { opacity: 0; scale: 0.5; }

.motion .visit:not(.in) .fact { opacity: 0; translate: 0 1rem; }
.motion .fact { transition: opacity 0.6s ease-out, translate 0.7s var(--ease); }
.motion .fact:nth-child(2) { transition-delay: 70ms; }
.motion .fact:nth-child(3) { transition-delay: 140ms; }
.motion .fact:nth-child(4) { transition-delay: 210ms; }
.motion .map { transition: opacity 0.6s ease-out 0.2s, translate 1s var(--ease) 0.2s, rotate 0.4s var(--ease), scale 0.4s var(--ease); }
.motion .visit:not(.in) .map { opacity: 0; translate: 0 2.5rem; }
.motion .m-river, .motion .m-road { stroke-dasharray: 1; transition: stroke-dashoffset 1.6s var(--ease) 0.5s; }
.motion .visit:not(.in) .m-river, .motion .visit:not(.in) .m-road { stroke-dashoffset: 1; }
.motion .m-plot, .motion .m-sh { transition: opacity 0.8s ease-out 0.7s; }
.motion .visit:not(.in) .m-plot, .motion .visit:not(.in) .m-sh { opacity: 0; }
.motion .m-pin { transition: translate 0.8s cubic-bezier(0.22, 1, 0.36, 1) 1.1s, opacity 0.25s ease-out 1.1s; }
.motion .visit:not(.in) .m-pin { opacity: 0; translate: 0 -4rem; }
.motion .m-ripple { opacity: 0; transform-box: fill-box; transform-origin: center; }
.motion .visit.in .m-ripple { animation: ripple 2.8s var(--ease) 2s 6; }
.motion .visit.in .m-ripple + .m-ripple { animation-delay: 3.2s; }
@keyframes ripple { from { opacity: 0.7; scale: 0.3; } to { opacity: 0; scale: 2.8; } }

/* ---------------- Print: never hide content behind an animation ---------------- */
@media print {
  .item, .quote, .fact, .sec__head, .gate__sign, .gate__note { opacity: 1 !important; translate: none !important; scale: none !important; animation: none !important; }
  .world__head .world__art { clip-path: none !important; }
  .snap img { opacity: 1 !important; }
  .progress { display: none !important; }
}
