@keyframes fade-up {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.reveal {
  animation: fade-up 460ms ease both;
}

.reveal--delay-1 {
  animation-delay: 90ms;
}

.reveal--delay-2 {
  animation-delay: 170ms;
}

/* ── Entrance on mount ──────────────────────────────────────────
   For content the router paints in one go. Staggered so a page
   assembles itself rather than snapping into place.             */
@keyframes rise-in {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}

.reveal-up {
  animation: rise-in 620ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

.reveal-up--1 { animation-delay: 90ms; }
.reveal-up--2 { animation-delay: 180ms; }
.reveal-up--3 { animation-delay: 270ms; }
.reveal-up--4 { animation-delay: 360ms; }

/* Children of a staggered container, without a class per item */
.stagger > * {
  animation: rise-in 560ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
.stagger > *:nth-child(1) { animation-delay: 60ms; }
.stagger > *:nth-child(2) { animation-delay: 130ms; }
.stagger > *:nth-child(3) { animation-delay: 200ms; }
.stagger > *:nth-child(4) { animation-delay: 270ms; }
.stagger > *:nth-child(5) { animation-delay: 340ms; }
.stagger > *:nth-child(6) { animation-delay: 410ms; }

/* ── Page transitions ───────────────────────────────────────────
   A focus pull, not a slide: the outgoing page drifts out of focus and
   the incoming one resolves from soft to sharp. The router swaps the
   content while it is invisible, so a slow page never flashes empty.  */
#app-main {
  transition:
    opacity 720ms cubic-bezier(0.16, 1, 0.3, 1),
    transform 720ms cubic-bezier(0.16, 1, 0.3, 1),
    filter 720ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* Focus pulls away — accelerating, the way a lens racks off a subject */
#app-main.is-leaving {
  opacity: 0;
  filter: blur(16px);
  transform: scale(0.972);
  transition-duration: 360ms;
  transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
}

/* Arrives soft and slightly forward, then settles into focus */
#app-main.is-entering {
  opacity: 0;
  filter: blur(20px);
  transform: scale(1.04);
  transition: none;
}

/* Warmth blooms through the swap. Opacity only — nothing moves. */
.page-glow {
  position: fixed;
  inset: 0;
  /* Under the header, so the chrome stays crisp while the content shifts */
  z-index: 90;
  pointer-events: none;
  opacity: 0;
  background:
    radial-gradient(circle at 50% 42%, rgba(197, 164, 106, 0.12), transparent 58%),
    radial-gradient(circle at 50% 100%, rgba(154, 122, 69, 0.1), transparent 45%);
  transition: opacity 620ms cubic-bezier(0.16, 1, 0.3, 1);
}

.page-glow.is-on {
  opacity: 1;
  transition-duration: 340ms;
}

/* Motion is decoration; never let it stand between a user and the shop */
@media (prefers-reduced-motion: reduce) {
  .reveal,
  .reveal-up,
  .stagger > * {
    animation: none;
    opacity: 1;
    transform: none;
  }

  #app-main,
  #app-main.is-leaving,
  #app-main.is-entering {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }

  .page-glow { display: none; }
}
