/* ═══════════════════════════════════════════════════════════════════
   Palladium PageBuilder — entrance animations (motion effects)

   Loaded by BOTH the storefront (App.razor) and the editor canvas
   (pagebuilder-editor.js canvas.styles) — parity rule.

   Gating: pb-animations.js adds `pb-anim-ready` on <html> as soon as it
   runs, then IntersectionObserver adds `pb-anim-in` per element when it
   enters the viewport. Without JS (or with reduced motion) the ready
   class never appears and every element stays fully visible — the
   animation system can only ever ADD polish, never hide content.

   The editor previews with `pb-anim-preview` (DOM-only class, never
   saved): same keyframes, no ready gating — the canvas iframe does not
   load the runtime.

   Keyframes declare ONLY a `from` frame: the implicit `to` is the
   element's natural computed style, so elements with their own
   transforms/filters land exactly where their CSS puts them.
   ═══════════════════════════════════════════════════════════════════ */

html.pb-anim-ready .pb-anim:not(.pb-anim-in) { opacity: 0; }

html.pb-anim-ready .pb-anim.pb-anim-in,
.pb-anim.pb-anim-preview {
    animation-duration: var(--pb-anim-duration, .7s);
    animation-delay: var(--pb-anim-delay, 0s);
    animation-timing-function: cubic-bezier(.22, .61, .36, 1);
    animation-fill-mode: both;
}

html.pb-anim-ready .pb-anim--fade.pb-anim-in,       .pb-anim--fade.pb-anim-preview       { animation-name: pb-fade; }
html.pb-anim-ready .pb-anim--fade-up.pb-anim-in,    .pb-anim--fade-up.pb-anim-preview    { animation-name: pb-fade-up; }
html.pb-anim-ready .pb-anim--fade-down.pb-anim-in,  .pb-anim--fade-down.pb-anim-preview  { animation-name: pb-fade-down; }
html.pb-anim-ready .pb-anim--fade-left.pb-anim-in,  .pb-anim--fade-left.pb-anim-preview  { animation-name: pb-fade-left; }
html.pb-anim-ready .pb-anim--fade-right.pb-anim-in, .pb-anim--fade-right.pb-anim-preview { animation-name: pb-fade-right; }
html.pb-anim-ready .pb-anim--zoom-in.pb-anim-in,    .pb-anim--zoom-in.pb-anim-preview    { animation-name: pb-zoom-in; }
html.pb-anim-ready .pb-anim--zoom-out.pb-anim-in,   .pb-anim--zoom-out.pb-anim-preview   { animation-name: pb-zoom-out; }
html.pb-anim-ready .pb-anim--blur.pb-anim-in,       .pb-anim--blur.pb-anim-preview       { animation-name: pb-blur; }
html.pb-anim-ready .pb-anim--rise.pb-anim-in,       .pb-anim--rise.pb-anim-preview       { animation-name: pb-rise; }
html.pb-anim-ready .pb-anim--pop.pb-anim-in,        .pb-anim--pop.pb-anim-preview        { animation-name: pb-pop; }

@keyframes pb-fade       { from { opacity: 0; } }
@keyframes pb-fade-up    { from { opacity: 0; transform: translateY(28px); } }
@keyframes pb-fade-down  { from { opacity: 0; transform: translateY(-28px); } }
/* fade-left = enters FROM the left, fade-right = FROM the right (Elementor semantics) */
@keyframes pb-fade-left  { from { opacity: 0; transform: translateX(-36px); } }
@keyframes pb-fade-right { from { opacity: 0; transform: translateX(36px); } }
@keyframes pb-zoom-in    { from { opacity: 0; transform: scale(.88); } }
@keyframes pb-zoom-out   { from { opacity: 0; transform: scale(1.1); } }
@keyframes pb-blur       { from { opacity: 0; filter: blur(10px); } }
@keyframes pb-rise       { from { opacity: 0; transform: translateY(56px) scale(.97); } }
@keyframes pb-pop {
    from { opacity: 0; transform: scale(.5); }
    60%  { opacity: 1; transform: scale(1.06); }
    80%  { transform: scale(.98); }
}

/* Accessibility: motion off → everything visible, nothing animates.
   (The runtime also refuses to add pb-anim-ready, this is belt+braces
   for the case where the preference changes after load.) */
@media (prefers-reduced-motion: reduce) {
    html.pb-anim-ready .pb-anim {
        opacity: 1 !important;
        animation: none !important;
    }
}
