/* ============================================================
   LÜDI GARDENS — shared motion
   entrance · scroll reveals · hover
   - transform/opacity only (GPU, 60fps, no layout shift)
   - gated by html.anim-ready  (no flash of content, no-JS safe)
   - reveal/entrance motion wrapped in (no-preference) so it is
     fully disabled for users who prefer reduced motion
   - HIDE happens only while :not(.is-visible) — so adding the
     .is-visible class always wins, regardless of selector depth
   TUNE MOVEMENT: change the two values below.
   ============================================================ */
:root {
  --reveal-shift: 14px;   /* how far blocks rise on scroll reveal */
  --hero-shift: 12px;     /* how far hero elements rise on load   */
  --reveal-ease: cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes ludiRise { from { opacity: 0; transform: translateY(var(--hero-shift)); } to { opacity: 1; transform: none; } }
@keyframes ludiFade { from { opacity: 0; } to { opacity: 1; } }
/* Hero ken-burns — a barely-there continuous zoom + drift (homepage hero) */
@keyframes ludiKenBurns {
  from { transform: scale(1.02) translate(0, 0); }
  to   { transform: scale(1.09) translate(-1.5%, -1.2%); }
}

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

  /* ---- Hero entrance on load (homepage) ---- */
  html.anim-ready .hero-text > * { opacity: 0; animation: ludiRise 0.7s var(--reveal-ease) both; }
  html.anim-ready .hero-text > *:nth-child(1) { animation-delay: 0.08s; }
  html.anim-ready .hero-text > *:nth-child(2) { animation-delay: 0.18s; }
  html.anim-ready .hero-text > *:nth-child(3) { animation-delay: 0.28s; }
  html.anim-ready .hero-text > *:nth-child(4) { animation-delay: 0.38s; }
  html.anim-ready .hero-text > *:nth-child(5) { animation-delay: 0.48s; }
  html.anim-ready .hero-image { opacity: 0; animation: ludiFade 0.9s var(--reveal-ease) 0.15s both; }
  html.anim-ready .hero-image > img { animation: ludiKenBurns 28s ease-in-out 0.6s infinite alternate; transform-origin: center; will-change: transform; }

  /* ---- Scroll reveals ----
     Every target keeps a transition; it is hidden ONLY while it has
     not yet received .is-visible. JS adds .is-visible on enter. */
  html.anim-ready :is(
    .section-head, .page-header > *, .post-header > *, .pull-quote-frame,
    .service-row, .faq-row, .timeline-step, .area-inner > *, .ig-item, .review,
    .ig-foot, .reviews-foot, .final-grid > *, .feature-image,
    .approach .article-body, .journal-card-featured, .journal-card-upcoming,
    .post-hero, .article-body > h2, .article-body > ol, .article-body > ul,
    .post-cta, .post-foot-nav
  ) {
    transition: opacity 0.6s var(--reveal-ease), transform 0.6s var(--reveal-ease);
  }
  html.anim-ready :is(
    .section-head, .page-header > *, .post-header > *, .pull-quote-frame,
    .service-row, .faq-row, .timeline-step, .area-inner > *, .ig-item, .review,
    .ig-foot, .reviews-foot, .final-grid > *, .feature-image,
    .approach .article-body, .journal-card-featured, .journal-card-upcoming,
    .post-hero, .article-body > h2, .article-body > ol, .article-body > ul,
    .post-cta, .post-foot-nav
  ):not(.is-visible) {
    opacity: 0; transform: translateY(var(--reveal-shift));
  }

  /* ---- Section-heading underline draws itself in after the head reveals ---- */
  html.anim-ready :is(.section-head, .page-header) .divider {
    transform: scaleX(0); transform-origin: center;
    transition: transform 0.6s var(--reveal-ease) 0.2s;
  }
  html.anim-ready :is(.section-head, .page-header) .divider-left { transform-origin: left; }
  html.anim-ready .section-head.is-visible .divider,
  html.anim-ready .page-header .is-visible .divider { transform: scaleX(1); }
}

/* ---- Hover micro-interactions (subtle, intentional) ---- */
.btn {
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
              transform 0.15s ease-out, box-shadow 0.15s ease-out;
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(44, 62, 45, 0.16); }
.btn:active { transform: translateY(0); box-shadow: none; transition-duration: 80ms; }

.review:hover,
.journal-card-upcoming:hover { transform: translateY(-3px); }

/* ---- Condensing sticky nav — shrinks + lifts off the page on scroll ---- */
.nav { transition: transform 0.35s ease, box-shadow 0.3s ease, background 0.3s ease, border-color 0.3s ease; }
html.is-nav-hidden .nav { transform: translateY(-100%); }
.nav-inner { transition: height 0.3s ease; }
.nav-logo-img { transition: height 0.3s ease; }
html.is-scrolled .nav {
  box-shadow: 0 6px 24px rgba(26, 26, 26, 0.07);
  border-bottom-color: transparent;
  background: rgba(250, 247, 242, 0.82);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
html.is-scrolled .nav-inner { height: 68px; }
html.is-scrolled .nav-logo-img { height: 50px; }
@media (max-width: 640px) { html.is-scrolled .nav-logo-img { height: 42px; } }

/* ---- Smooth page transitions — native cross-document View Transitions.
   The browser keeps the current page visible until the next is ready, then
   cross-fades — so there is NO white/blank flash. Browsers without support
   just navigate normally (graceful, no JS, no interception). ---- */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.35s; }
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  .btn, .nav, .nav-inner, .nav-logo-img { transition: none; }
}
