/* Painter's Theme 3.0 — unified direction-safe motion lifecycle.
   Scroll reveals, navigation transitions and interface motion are intentionally
   kept separate so each system has one source of truth. */
/* The same document-to-document fade is used on mobile and desktop.
   Cross-document View Transitions are intentionally not opted in here: a
   browser's support does not guarantee an actual transition on every link. */
:root {
  --lf-motion-distance: 48px;
  --lf-motion-duration: 1280ms;
  --lf-motion-fade-duration: 1020ms;
  --lf-motion-ease: cubic-bezier(.16,1,.3,1);
  /* Separate easing keeps header, navigation and lightbox behavior unchanged. */
  --lf-reveal-ease: cubic-bezier(.38,0,.4,1);
  --lf-lightbox-swap-duration: 800ms;
  --lf-lightbox-overlay-duration: 620ms;
  --lf-header-duration: 860ms;
  --lf-header-ease: cubic-bezier(.42,0,.28,1);
  --lf-page-exit-duration: 300ms;
  --lf-page-arrival-duration: 520ms;
  --lf-page-transition-duration: 520ms;
  --lf-page-transition-ease: cubic-bezier(.16,1,.3,1);
}

/* Non-View-Transition fallback. The arrival class is applied early in <head>
   for same-origin navigations/back-forward restores, so content does not flash
   visible before the reveal observer is initialized. */
html.lf-page-fallback.lf-page-arriving body {
  opacity:0;
}
html.lf-page-fallback.lf-page-arrived body {
  opacity:1;
  transition:opacity var(--lf-page-arrival-duration) var(--lf-page-transition-ease);
}
html.lf-page-fallback.lf-page-leaving body {
  opacity:0;
  transition:opacity var(--lf-page-exit-duration) var(--lf-page-transition-ease);
}
/* A real entry animation, not a transition that may be skipped before first paint.
   Activated only for a same-site navigation or restored history entry. */
@keyframes lf-page-fade-in {
  from { opacity:0; }
  to { opacity:1; }
}
html.lf-page-fallback.lf-page-arrive-animate body {
  animation:lf-page-fade-in var(--lf-page-arrival-duration) var(--lf-page-transition-ease) both;
}

/* First-paint state: targeted content is hidden before initial paint. JS then
   upgrades every selected target to .lf-motion-item before releasing this state. */
html.lf-motion-pending .works-grid > .work-card:not(.lf-motion-item),
html.lf-motion-pending .work-single > .work-hero-link:not(.lf-motion-item),
html.lf-motion-pending .work-single > .work-details > div:not(.lf-motion-item),
html.lf-motion-pending .work-single > .work-gallery .work-gallery-item:not(.lf-motion-item),
html.lf-motion-pending .work-single > .work-navigation:not(.lf-motion-item),
html.lf-motion-pending .journal-orientation-entry .journal-orientation-copy:not(.lf-motion-item),
html.lf-motion-pending .journal-orientation-entry .journal-orientation-media:not(.lf-motion-item),
html.lf-motion-pending .journal-entry .entry-lead:not(.lf-motion-item),
html.lf-motion-pending .journal-entry .entry-main > div:first-child > .journal-meta:not(.lf-motion-item),
html.lf-motion-pending .journal-entry .entry-main > div:first-child > .entry-title:not(.lf-motion-item),
html.lf-motion-pending .journal-entry .entry-main > .journal-post-summary:not(.lf-motion-item),
html.lf-motion-pending .archive-wrap > .page-header:not(.lf-motion-item),
html.lf-motion-pending .archive-wrap > .journal-entry > .entry-date:not(.lf-motion-item),
html.lf-motion-pending .fallback-entry > .entry-header:not(.lf-motion-item),
html.lf-motion-pending .fallback-entry > .entry-content:not(.lf-motion-item),
html.lf-motion-pending .editorial-layout > .editorial-heading:not(.lf-motion-item),
html.lf-motion-pending .editorial-layout > .editorial-text:not(.lf-motion-item),
html.lf-motion-pending .editorial-layout > .editorial-hero:not(.lf-motion-item),
html.lf-motion-pending .exhibition-layout > .exhibition-text:not(.lf-motion-item),
html.lf-motion-pending .exhibition-layout > .exhibition-hero:not(.lf-motion-item),
html.lf-motion-pending .exhibition-left > .exhibition-heading:not(.lf-motion-item),
html.lf-motion-pending .exhibition-events > .exhibition-event:not(.lf-motion-item),
html.lf-motion-pending .exhibition-events > .exhibition-event-credit:not(.lf-motion-item),
html.lf-motion-pending .post-single > .post-header:not(.lf-motion-item),
html.lf-motion-pending .post-single > .post-content > .post-featured-image:not(.lf-motion-item),
html.lf-motion-pending .post-single > .post-content > *:not(.post-featured-image):not(.lf-motion-item),
html.lf-motion-pending .post-single > .post-pagination:not(.lf-motion-item),
html.lf-motion-pending .exhibition-single > .post-pagination:not(.lf-motion-item),
html.lf-motion-pending .editorial-single > .post-pagination:not(.lf-motion-item),
html.lf-motion-pending .page-wrap > .page-header:not(.lf-motion-item),
html.lf-motion-pending .page-wrap > .page-content:not(.vita-content):not(.info-layout) > *:not(.lf-motion-item),
html.lf-motion-pending .page-wrap > p:not(.lf-motion-item),
html.lf-motion-pending .info-layout > .info-intro > *:not(.lf-motion-item),
html.lf-motion-pending .info-layout > .info-image:not(.lf-motion-item),
html.lf-motion-pending .info-layout > .info-contact-block > .info-contact-items > .info-item:not(.lf-motion-item),
html.lf-motion-pending .vita-content > .vita-intro > .vita-row:not(.lf-motion-item),
html.lf-motion-pending .vita-content > .vita-section > .lf-managed-section-heading:not(.lf-motion-item),
html.lf-motion-pending .vita-content > .vita-section > .vita-row:not(.lf-motion-item),
html.lf-motion-pending .site-footer:not(.lf-motion-item) {
  opacity:0;
  transform:translate3d(0,var(--lf-motion-distance),0);
}

/* The hidden/armed state never animates. Once completely outside the
   viewport an element is reset instantly, not dragged back across the screen.
   An entering item gets exactly one transition from its correct side. */
.lf-motion-enabled .lf-motion-item {
  opacity:0;
  transform:translate3d(0,var(--lf-motion-distance),0);
  transition:none;
}
.lf-motion-enabled .lf-motion-item.lf-reveal-reverse {
  transform:translate3d(0,calc(-1 * var(--lf-motion-distance)),0);
}
.lf-motion-enabled .lf-motion-item.lf-reveal-visible {
  opacity:1;
  transform:translate3d(0,0,0);
  transition:opacity var(--lf-motion-fade-duration) var(--lf-reveal-ease),
             transform var(--lf-motion-duration) var(--lf-reveal-ease);
  transition-delay:var(--lf-motion-delay,0ms);
}
/* Initial viewport belongs to the page entrance, not to scroll reveal. */
.lf-motion-enabled .lf-motion-item.lf-reveal-visible.lf-reveal-instant {
  transition:none;
  transition-delay:0ms;
}
.lf-motion-enabled .lf-motion-item.lf-motion-active {
  will-change:opacity,transform;
}

/* Footer inherits the same reveal transitions; no parallel implementation. */

/* Lightbox: one buffered image slides/fades against the other; no src swapping
   on the visible image during an animation. */
.lf-lightbox {
  opacity:0;
  transition:opacity var(--lf-lightbox-overlay-duration) var(--lf-motion-ease);
}
.lf-lightbox.is-open { opacity:1; }
.lf-lightbox.is-closing { opacity:0; }
.lf-lightbox-stage { overflow:hidden; }
.lf-lightbox-stage .lf-lightbox-image {
  transition:opacity var(--lf-lightbox-swap-duration) var(--lf-motion-ease), transform var(--lf-lightbox-swap-duration) var(--lf-motion-ease);
}
.lf-lightbox-stage .lf-lightbox-image.lf-motion-active {
  will-change:opacity,transform;
}
.lf-lightbox-stage .lf-lightbox-image-current {
  position:relative;
  z-index:2;
  opacity:1;
  transform:translate3d(0,0,0);
}
.lf-lightbox-stage .lf-lightbox-image-next {
  position:absolute;
  inset:0;
  z-index:1;
  width:100%;
  height:100%;
  opacity:0;
  transform:translate3d(clamp(48px,6vw,92px),0,0);
  object-fit:contain;
  object-position:center;
  pointer-events:none;
}
.lf-lightbox-stage.is-sliding-next .lf-lightbox-image-current,
.lf-lightbox-stage.is-sliding-prev .lf-lightbox-image-current { opacity:0; }
.lf-lightbox-stage.is-sliding-next .lf-lightbox-image-current { transform:translate3d(clamp(-92px,-6vw,-48px),0,0); }
.lf-lightbox-stage.is-sliding-next .lf-lightbox-image-next { opacity:1; transform:translate3d(0,0,0); }
.lf-lightbox-stage.is-sliding-prev .lf-lightbox-image-current { transform:translate3d(clamp(48px,6vw,92px),0,0); }
.lf-lightbox-stage.is-sliding-prev .lf-lightbox-image-next { opacity:1; transform:translate3d(0,0,0); }
.lf-lightbox-caption { transition:opacity 420ms var(--lf-motion-ease), transform 420ms var(--lf-motion-ease); }
.lf-lightbox-caption.is-changing { opacity:0; transform:translate3d(0,4px,0); }

/* Scroll-reactive header. will-change is enabled only while the header is moving. */
.site-header {
  position:sticky;
  top:0;
  z-index:2000;
  background:#fff;
  transition:transform var(--lf-header-duration) var(--lf-header-ease);
}
.site-header.lf-header-moving { will-change:transform; }
html.lf-header-hidden .site-header {
  transform:translate3d(0,-105%,0);
}
html.lf-menu-open .site-header {
  transform:translate3d(0,0,0) !important;
}

@media (prefers-reduced-motion:reduce) {
  html.lf-page-fallback.lf-page-arriving body,
  html.lf-page-fallback.lf-page-arrived body,
  html.lf-page-fallback.lf-page-leaving body { opacity:1 !important; transition:none !important; }
  .lf-motion-enabled .lf-motion-item,
  .lf-motion-enabled .lf-motion-item.lf-reveal-visible,
  .lf-motion-enabled .site-footer.lf-motion-item,
  .lf-motion-enabled .site-footer.lf-motion-item.lf-reveal-visible {
    opacity:1 !important;
    transform:none !important;
    transition:none !important;
  }
  .site-header,
  .lf-lightbox,
  .lf-lightbox-stage .lf-lightbox-image,
  .lf-lightbox-caption { transition:none !important; }
}
