/* @avartha/ui · motion: transitions and lazy loading · requires core.css · generated by scripts/finish-build.mjs */
@layer avartha {
/*
 * Transitions: entrances are a short fade with a small rise, exits a fade,
 * sections open on the grid-rows reveal, and below-the-fold content mounts
 * as it scrolls near. Loading primitives (skeletons, spinners, progress) live
 * in core.css. Everything here stops under prefers-reduced-motion.
 */
/* ── presence: enter with a short rise, leave with a fade ── */
.av-presence[data-state='enter'] {
  animation: av-rise-in var(--duration-base) var(--ease-out) both;
}
.av-presence[data-state='exit'] {
  animation: av-fade-out var(--duration-fast) var(--ease-in) both;
  pointer-events: none;
}
.av-presence[data-motion='fade'][data-state='enter'] {
  animation-name: av-fade-in;
}
.av-presence[data-motion='scale'][data-state='enter'] {
  animation-name: av-scale-in;
}
@keyframes av-rise-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes av-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes av-fade-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
@keyframes av-scale-in {
  from {
    opacity: 0;
    transform: scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ── collapse: the grid-rows reveal as a component ─────────────── */
.av-collapse {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition:
    grid-template-rows var(--duration-base) var(--ease),
    opacity var(--duration-fast) var(--ease);
}
.av-collapse[data-open='true'] {
  grid-template-rows: 1fr;
  opacity: 1;
}
.av-collapse > * {
  min-height: 0;
  overflow: hidden;
}

/* ── lazy mount and lazy image ─────────────────────────────────── */
.av-lazy {
  min-height: var(--av-lazy-min, 80px);
}
.av-lazy[data-mounted='true'] {
  min-height: 0;
}
.av-lazy-image {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--accent);
}
.av-lazy-image img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity var(--duration-fade) var(--ease-out);
}
.av-lazy-image[data-loaded='true'] img {
  opacity: 1;
}
.av-lazy-image[data-loaded='true'] > .av-skeleton {
  display: none;
}
.av-lazy-image > .av-skeleton {
  position: absolute;
  inset: 0;
  height: 100%;
  border-radius: 0;
}

/* ── view transitions: a quiet crossfade for route and tab changes ── */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--duration-base);
  animation-timing-function: var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .av-presence[data-state],
  .av-lazy-image img,
  .av-collapse {
    animation: none;
    transition: none;
  }
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
  }
}

/* Long-form reading progress. Motion itself is driven by the shared hook. */
.av-scroll-progress {
  position: fixed;
  inset: 0 0 auto;
  height: 2px;
  z-index: 60;
  pointer-events: none;
}
.av-scroll-progress > span {
  display: block;
  width: 100%;
  height: 100%;
  transform: scaleX(0);
  transform-origin: left;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--primary) 45%, transparent),
    var(--primary)
  );
}
@media print, (prefers-reduced-motion: reduce) {
  .av-scroll-progress {
    display: none;
  }
}
}
