/* ==========================================================================
   ANIMATIONS — scroll entrances, parallax, ambient motion, page load
   Every animation here is transform/opacity only, and every one collapses
   under prefers-reduced-motion at the bottom of this file.
   ========================================================================== */

/* --------------------------------------------------------------------------
   SCROLL-TRIGGERED ENTRANCES
   JS adds .is-in via IntersectionObserver, then unobserves (fires once).
   -------------------------------------------------------------------------- */
[data-rise] {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity var(--d-rise) var(--ease-out),
              transform var(--d-rise) var(--ease-out);
  transition-delay: var(--delay, 0ms);
}
[data-rise].is-in { opacity: 1; transform: none; }

[data-rise="left"]  { transform: translateX(-38px); }
[data-rise="right"] { transform: translateX(38px); }
[data-rise="scale"] { transform: scale(.93); }
[data-rise="left"].is-in,
[data-rise="right"].is-in,
[data-rise="scale"].is-in { transform: none; }

/* Clip-path reveal for images.
   The clip goes on the CHILD, never on [data-reveal] itself: a clip-path of
   inset(0 0 100% 0) collapses the element's box to zero height, and
   IntersectionObserver then reports it as permanently non-intersecting — so
   .is-in would never be added and the image would stay hidden forever.
   Keeping the observed element unclipped keeps its geometry real. */
[data-reveal] > * {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1s var(--ease-out);
  transition-delay: var(--delay, 0ms);
}
[data-reveal].is-in > * { clip-path: inset(0 0 0 0); }

/* Line-by-line display text unmasking */
.reveal-lines { display: block; }
.reveal-lines__line { display: block; overflow: hidden; }
.reveal-lines__inner {
  display: block;
  transform: translateY(105%);
  transition: transform 900ms var(--ease-out);
  transition-delay: var(--delay, 0ms);
}
.reveal-lines.is-in .reveal-lines__inner { transform: none; }

/* --------------------------------------------------------------------------
   PARALLAX — JS writes --py (px). Transform-driven, rAF-throttled.
   -------------------------------------------------------------------------- */
[data-parallax] {
  will-change: transform;
  transform: translate3d(0, var(--py, 0px), 0);
}
[data-parallax-scale] {
  will-change: transform;
  transform: translate3d(0, var(--py, 0px), 0) scale(var(--ps, 1));
}

/* --------------------------------------------------------------------------
   AMBIENT — smoke drift, ember float, glow pulse
   -------------------------------------------------------------------------- */
@keyframes drift {
  0%   { transform: translate3d(0, 0, 0) scale(1); opacity: .16; }
  50%  { transform: translate3d(2.5vw, -3vh, 0) scale(1.14); opacity: .3; }
  100% { transform: translate3d(0, 0, 0) scale(1); opacity: .16; }
}
.smoke {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(circle, rgba(226, 103, 58, .5), transparent 68%);
  filter: blur(70px);
  animation: drift 22s var(--ease-io) infinite;
  animation-delay: var(--delay, 0s);
  z-index: var(--z-base);
}

@keyframes float-y {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  50%      { transform: translate3d(0, -16px, 0) rotate(4deg); }
}
.floaty {
  animation: float-y 7s var(--ease-io) infinite;
  animation-delay: var(--delay, 0s);
  will-change: transform;
}

@keyframes glow-pulse {
  0%, 100% { opacity: var(--glow-o, .3); transform: scale(1); }
  50%      { opacity: calc(var(--glow-o, .3) * 1.5); transform: scale(1.1); }
}
.glow--pulse { animation: glow-pulse 8s var(--ease-io) infinite; }

/* Ember sparks rising from the hero */
@keyframes spark {
  0%   { transform: translate3d(0, 0, 0) scale(.5); opacity: 0; }
  12%  { opacity: .85; }
  100% { transform: translate3d(var(--dx, 12px), -160px, 0) scale(0); opacity: 0; }
}
.spark {
  position: absolute;
  width: 3px; height: 3px;
  border-radius: 50%;
  background: var(--clr-ember-hot);
  box-shadow: 0 0 7px 2px rgba(247, 160, 114, .65);
  animation: spark var(--dur, 5s) linear infinite;
  animation-delay: var(--delay, 0s);
  pointer-events: none;
  will-change: transform, opacity;
}

/* Cursor-follow ember (desktop pointer only) */
.cursor-ember {
  position: fixed;
  top: 0; left: 0;
  width: 320px; height: 320px;
  margin: -160px 0 0 -160px;
  border-radius: 50%;
  pointer-events: none;
  z-index: var(--z-base);
  background: radial-gradient(circle, rgba(226, 103, 58, .16), transparent 62%);
  filter: blur(30px);
  opacity: 0;
  transform: translate3d(var(--mx, 0), var(--my, 0), 0);
  transition: opacity var(--d-slow) var(--ease-out);
  will-change: transform;
}
.cursor-ember.is-on { opacity: 1; }
@media (hover: none), (pointer: coarse) {
  .cursor-ember { display: none; }
}

/* --------------------------------------------------------------------------
   PAGE LOAD CHOREOGRAPHY
   -------------------------------------------------------------------------- */
@keyframes curtain {
  0%   { transform: scaleY(1); }
  100% { transform: scaleY(0); }
}
.curtain {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  background: var(--clr-ink);
  transform-origin: top;
  animation: curtain 800ms var(--ease-io) 260ms forwards;
  pointer-events: none;
}
.curtain__mark {
  position: absolute;
  top: 50%; left: 50%;
  width: 76px; height: 76px;
  margin: -38px 0 0 -38px;
  animation: mark-out 620ms var(--ease-out) forwards;
}
@keyframes mark-out {
  0%   { opacity: 0; transform: scale(.82); }
  40%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.08); }
}

/* --------------------------------------------------------------------------
   MICRO-INTERACTIONS
   -------------------------------------------------------------------------- */
.magnetic { transition: transform var(--d-base) var(--ease-soft); will-change: transform; }

/* Counter roll-up: JS animates the number; this just fades the unit in */
.counter { font-variant-numeric: tabular-nums; }

/* Horizontal scroll-snap rail (mobile review/dish rails) */
.rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(min(84vw, 340px), 1fr);
  gap: var(--sp-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--gutter);
  padding-inline: var(--gutter);
  margin-inline: calc(var(--gutter) * -1);
  padding-bottom: var(--sp-4);
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail > * { scroll-snap-align: start; }

/* ==========================================================================
   REDUCED MOTION — hard stop. Everything above collapses to a static state.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  [data-rise], [data-rise="left"], [data-rise="right"], [data-rise="scale"] {
    opacity: 1 !important;
    transform: none !important;
  }
  [data-reveal] > * { clip-path: none !important; }
  .reveal-lines__inner { transform: none !important; }
  [data-parallax], [data-parallax-scale] { transform: none !important; }
  .smoke, .floaty, .glow--pulse, .spark { animation: none !important; }
  .spark { display: none !important; }
  .cursor-ember { display: none !important; }
  .curtain { display: none !important; }
  .tilt__inner { transform: none !important; }
}
