/*
 * press2pixel — centralized template animations.
 *
 * Animation lives here once, not per template. A template opts in via its
 * `motion` field; the renderer (templates.js#applyMotion) stamps
 * `p2p-motion p2p-motion--<preset>` on the root and sets --p2p-anim-dur /
 * --p2p-anim-iter. These rules then animate the SHARED element classes
 * (.p2p-display / .p2p-title / .p2p-excerpt / .p2p-cta / …) with a per-role
 * stagger — so every template that uses the standard classes animates, with no
 * bespoke @keyframes. Loaded globally (index.html → covers live preview + the
 * export stage) and inlined by the audit.
 */

@keyframes p2p-kf-rise-title {
  0% { opacity: 0; transform: translateY(2.2em) scale(.98); filter: blur(8px); }
  10%, 42% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
  58%, 82% { opacity: 1; transform: translateY(-.22em) scale(1.015); filter: blur(0); }
  100% { opacity: 0; transform: translateY(-1.4em) scale(1.03); filter: blur(6px); }
}
@keyframes p2p-kf-rise-media {
  0% { opacity: 0; transform: translateY(1.4em) scale(1.08); filter: saturate(.8) contrast(.9); }
  12%, 48% { opacity: 1; transform: translateY(0) scale(1.025); filter: saturate(1.05) contrast(1.02); }
  84% { opacity: 1; transform: translateY(-.35em) scale(1.075); filter: saturate(1.14) contrast(1.06); }
  100% { opacity: 0; transform: translateY(-.8em) scale(1.12); filter: saturate(.9) contrast(.95); }
}
@keyframes p2p-kf-rise-card {
  0% { opacity: 0; transform: translateY(1.6em) rotate(.6deg); }
  16%, 54% { opacity: 1; transform: translateY(0) rotate(0); }
  78% { opacity: 1; transform: translateY(-.25em) rotate(-.4deg); }
  100% { opacity: 0; transform: translateY(-1em) rotate(-.6deg); }
}
@keyframes p2p-kf-rise-cta {
  0%, 18% { opacity: 0; transform: translateY(1em) scale(.96); }
  26%, 70% { opacity: 1; transform: translateY(0) scale(1); }
  80% { opacity: 1; transform: translateY(0) scale(1.045); }
  100% { opacity: 0; transform: translateY(-.7em) scale(.98); }
}

@keyframes p2p-kf-fade-title {
  0% { opacity: 0; transform: scale(.96); filter: blur(10px); }
  12%, 52% { opacity: 1; transform: scale(1); filter: blur(0); }
  74% { opacity: 1; transform: scale(1.025); filter: blur(0); }
  100% { opacity: 0; transform: scale(1.04); filter: blur(9px); }
}
@keyframes p2p-kf-fade-media {
  0% { opacity: 0; transform: scale(1.12); filter: brightness(.82) saturate(.8); }
  16%, 62% { opacity: 1; transform: scale(1.045); filter: brightness(1) saturate(1.08); }
  100% { opacity: 0; transform: scale(1); filter: brightness(.9) saturate(.85); }
}
@keyframes p2p-kf-fade-card {
  0%, 8% { opacity: 0; transform: translateY(.8em); }
  20%, 72% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-.45em); }
}
@keyframes p2p-kf-fade-cta {
  0%, 42% { opacity: 0; transform: scale(.94); }
  52%, 84% { opacity: 1; transform: scale(1); }
  92% { opacity: 1; transform: scale(1.055); }
  100% { opacity: 0; transform: scale(.98); }
}

@keyframes p2p-kf-pop-title {
  0% { opacity: 0; transform: scale(.78) rotate(-1.8deg); filter: blur(5px); }
  9% { opacity: 1; transform: scale(1.04) rotate(.5deg); filter: blur(0); }
  18%, 58% { opacity: 1; transform: scale(1) rotate(0); filter: blur(0); }
  74% { opacity: 1; transform: scale(1.035) rotate(-.35deg); }
  100% { opacity: 0; transform: scale(.88) rotate(1.2deg); filter: blur(5px); }
}
@keyframes p2p-kf-pop-media {
  0% { opacity: 0; transform: scale(.9) rotate(.8deg); }
  12%, 58% { opacity: 1; transform: scale(1.035) rotate(0); }
  86% { opacity: 1; transform: scale(1.095) rotate(-.5deg); }
  100% { opacity: 0; transform: scale(.96) rotate(-.8deg); }
}
@keyframes p2p-kf-pop-card {
  0%, 8% { opacity: 0; transform: scale(.86) translateY(.7em); }
  18% { opacity: 1; transform: scale(1.04) translateY(0); }
  30%, 76% { opacity: 1; transform: scale(1) translateY(0); }
  100% { opacity: 0; transform: scale(.9) translateY(-.5em); }
}
@keyframes p2p-kf-pop-cta {
  0%, 34% { opacity: 0; transform: scale(.82); }
  44% { opacity: 1; transform: scale(1.08); }
  54%, 86% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(.88); }
}

@keyframes p2p-kf-slide-title {
  0% { opacity: 0; transform: translateX(-2.4em); filter: blur(6px); }
  12%, 52% { opacity: 1; transform: translateX(0); filter: blur(0); }
  78% { opacity: 1; transform: translateX(.55em); filter: blur(0); }
  100% { opacity: 0; transform: translateX(2em); filter: blur(6px); }
}
@keyframes p2p-kf-slide-media {
  0% { opacity: 0; transform: translateX(2.2em) scale(1.08); }
  14%, 60% { opacity: 1; transform: translateX(0) scale(1.035); }
  86% { opacity: 1; transform: translateX(-.8em) scale(1.08); }
  100% { opacity: 0; transform: translateX(-2em) scale(1.12); }
}
@keyframes p2p-kf-slide-card {
  0%, 8% { opacity: 0; transform: translateX(-1.5em); }
  18%, 72% { opacity: 1; transform: translateX(0); }
  100% { opacity: 0; transform: translateX(1.3em); }
}
@keyframes p2p-kf-slide-cta {
  0%, 40% { opacity: 0; transform: translateX(-1em); }
  50%, 82% { opacity: 1; transform: translateX(0); }
  100% { opacity: 0; transform: translateX(1em); }
}

.p2p-motion {
  --p2p-anim-dur: 15s;
  --p2p-anim-ease: cubic-bezier(.2, .7, .2, 1);
  --p2p-anim-iter: infinite;
  --p2p-title-anim: p2p-kf-rise-title;
  --p2p-media-anim: p2p-kf-rise-media;
  --p2p-card-anim: p2p-kf-rise-card;
  --p2p-cta-anim: p2p-kf-rise-cta;
}
.p2p-motion--rise  { --p2p-title-anim: p2p-kf-rise-title; --p2p-media-anim: p2p-kf-rise-media; --p2p-card-anim: p2p-kf-rise-card; --p2p-cta-anim: p2p-kf-rise-cta; }
.p2p-motion--fade  { --p2p-title-anim: p2p-kf-fade-title; --p2p-media-anim: p2p-kf-fade-media; --p2p-card-anim: p2p-kf-fade-card; --p2p-cta-anim: p2p-kf-fade-cta; }
.p2p-motion--pop   { --p2p-title-anim: p2p-kf-pop-title; --p2p-media-anim: p2p-kf-pop-media; --p2p-card-anim: p2p-kf-pop-card; --p2p-cta-anim: p2p-kf-pop-cta; }
.p2p-motion--slide { --p2p-title-anim: p2p-kf-slide-title; --p2p-media-anim: p2p-kf-slide-media; --p2p-card-anim: p2p-kf-slide-card; --p2p-cta-anim: p2p-kf-slide-cta; }

/* Hand-crafted story templates may use inline animation shorthands; keep their
   custom keyframes, but let the UI/export duration retime the whole piece. */
.p2p-motion [style*="animation"] {
  animation-duration: var(--p2p-anim-dur) !important;
  animation-iteration-count: var(--p2p-anim-iter) !important;
}

/* Animate the standard element classes with a per-role entrance stagger. */
.p2p-motion :is(.p2p-meta, .p2p-display, .p2p-title, .p2p-subtitle, .p2p-excerpt, .p2p-lead, .p2p-brand, .p2p-chip, .p2p-cta, .p2p-media, .p2p-card, .p2p-headline-color, .p2p-excerpt-color) {
  animation-duration: var(--p2p-anim-dur);
  animation-timing-function: var(--p2p-anim-ease);
  animation-delay: var(--p2p-anim-delay, 0s);
  animation-iteration-count: var(--p2p-anim-iter);
  animation-fill-mode: both;
  transform-origin: center center;
}
.p2p-motion :is(.p2p-display, .p2p-title, .p2p-subtitle, .p2p-headline-color, .p2p-excerpt, .p2p-lead, .p2p-excerpt-color) { animation-name: var(--p2p-title-anim); }
.p2p-motion :is(.p2p-media) { animation-name: var(--p2p-media-anim); }
.p2p-motion :is(.p2p-card, .p2p-chip, .p2p-meta, .p2p-brand) { animation-name: var(--p2p-card-anim); }
.p2p-motion :is(.p2p-cta) { animation-name: var(--p2p-cta-anim); }
.p2p-motion .p2p-meta     { --p2p-anim-delay: 0s; }
.p2p-motion .p2p-brand    { --p2p-anim-delay: .03s; }
.p2p-motion .p2p-display,
.p2p-motion .p2p-title    { --p2p-anim-delay: .08s; }
.p2p-motion .p2p-subtitle { --p2p-anim-delay: .12s; }
.p2p-motion .p2p-media,
.p2p-motion .p2p-card     { --p2p-anim-delay: .1s; }
.p2p-motion .p2p-excerpt,
.p2p-motion .p2p-lead     { --p2p-anim-delay: .16s; }
.p2p-motion .p2p-chip     { --p2p-anim-delay: .2s; }
.p2p-motion .p2p-cta      { --p2p-anim-delay: .26s; }

/* ─── Motion helper primitives (p2p-fx-*) ───────────────────────────────────
   Backing CSS for the `p2p` helper API handed to template JS
   (templates.js#createTemplateHelpers): staged entrances, ken-burns image
   pans, and the multi-image cross-fade rotator. Everything is a plain CSS
   animation, so the export pipeline can freeze any timestamp with the
   negative animation-delay technique and every frame samples correctly.
   Vars: --p2p-fx-dur (duration), --p2p-fx-delay (start offset),
   --p2p-fx-ease (timing). Documented in docs/TEMPLATES.md → Motion Helpers. */

@keyframes p2p-kf-enter-rise {
  0% { opacity: 0; transform: translateY(1.6em) scale(.985); filter: blur(6px); }
  60% { filter: blur(0); }
  100% { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
}
@keyframes p2p-kf-enter-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes p2p-kf-enter-slide-left {
  0% { opacity: 0; transform: translateX(-1.8em); filter: blur(4px); }
  100% { opacity: 1; transform: translateX(0); filter: blur(0); }
}
@keyframes p2p-kf-enter-slide-right {
  0% { opacity: 0; transform: translateX(1.8em); filter: blur(4px); }
  100% { opacity: 1; transform: translateX(0); filter: blur(0); }
}
@keyframes p2p-kf-enter-pop {
  0% { opacity: 0; transform: scale(.82); }
  55% { opacity: 1; transform: scale(1.045); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes p2p-kf-enter-blur {
  0% { opacity: 0; filter: blur(14px); transform: scale(1.02); }
  100% { opacity: 1; filter: blur(0); transform: scale(1); }
}
@keyframes p2p-kf-kenburns {
  0% { transform: scale(1) translate3d(0, 0, 0); }
  100% { transform: scale(var(--p2p-kb-scale, 1.14)) translate3d(var(--p2p-kb-x, -2.5%), var(--p2p-kb-y, -1.5%), 0); }
}

.p2p-fx {
  animation-duration: var(--p2p-fx-dur, .9s);
  animation-delay: var(--p2p-fx-delay, 0s);
  animation-timing-function: var(--p2p-fx-ease, cubic-bezier(.16, 1, .3, 1));
  animation-fill-mode: both;
  will-change: transform, opacity, filter;
}
.p2p-fx--rise        { animation-name: p2p-kf-enter-rise; }
.p2p-fx--fade        { animation-name: p2p-kf-enter-fade; }
.p2p-fx--slide-left  { animation-name: p2p-kf-enter-slide-left; }
.p2p-fx--slide-right { animation-name: p2p-kf-enter-slide-right; }
.p2p-fx--pop         { animation-name: p2p-kf-enter-pop; --p2p-fx-ease: cubic-bezier(.34, 1.56, .64, 1); }
.p2p-fx--blur        { animation-name: p2p-kf-enter-blur; }
.p2p-fx--kenburns {
  animation-name: p2p-kf-kenburns;
  animation-duration: var(--p2p-fx-dur, 12s);
  animation-delay: var(--p2p-fx-delay, 0s);
  animation-timing-function: cubic-bezier(.33, 0, .67, 1);
  animation-direction: alternate;
  animation-iteration-count: infinite;
  animation-fill-mode: both;
  will-change: transform;
}

/* Image rotator: cycles the extra imageUrl2..4 <img> slots with a cross-fade.
   Each slide runs the same looping keyframes over the full cycle, offset by a
   negative per-slide delay set from JS (p2p.rotateImages). The fade-out of
   slide N overlaps the fade-in of slide N+1 for a true cross-fade. */
@keyframes p2p-kf-rotate-2 {
  0%, 42% { opacity: 1; }
  50%, 92% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes p2p-kf-rotate-3 {
  0%, 28% { opacity: 1; }
  33.4%, 94.6% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes p2p-kf-rotate-4 {
  0%, 21% { opacity: 1; }
  25%, 96% { opacity: 0; }
  100% { opacity: 1; }
}
.p2p-fx-rotator { position: relative; overflow: hidden; }
.p2p-fx-rotator .p2p-fx-rotator__slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  margin: 0;
  animation-duration: var(--p2p-fx-dur, 10.8s);
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-fill-mode: both;
  will-change: opacity;
}
/* The first slide keeps the stage's layout size (it is the template's normal
   main image); the rotating extras stack on top of it. */
.p2p-fx-rotator .p2p-fx-rotator__base { position: relative; inset: auto; }
