/* ============================================================
   Edes.MarkdownEditor Demo – fragment transition animations
   Apply as an additional class on <article class="rendered-md">
   together with @key="_index" so Blazor rebuilds the node and
   the animation re-runs on every fragment change.
   ============================================================ */

:root {
    --frag-anim-duration: 480ms;
    --frag-anim-ease: cubic-bezier(.22, 1, .36, 1);
}

/* Base: all fragment animations honor prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
    .frag-anim { animation: none !important; }
}

.frag-anim {
    animation-duration: var(--frag-anim-duration);
    animation-timing-function: var(--frag-anim-ease);
    animation-fill-mode: both;
    will-change: transform, opacity, filter, clip-path;
}

/* Stage that hosts outgoing + incoming articles during a fragment swap.
   Use CSS grid stacking so both articles occupy the exact same cell
   (same X/Y plane), while the incoming one is painted above (Z axis).
   This prevents the incoming fragment from appearing vertically below
   the outgoing fragment during transition. */
.frag-stage {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    min-height: 300px;
}

.frag-stage > * {
    grid-area: 1 / 1;
    width: 100%;
}

.frag-stage__outgoing {
    pointer-events: none;
    z-index: 0;
}

/* Incoming article stays on top. */
.frag-stage > :not(.frag-stage__outgoing) {
    position: relative;
    z-index: 1;
}

/* -------------------- IN animations -------------------- */

/* 1. Fade ---------------------------------------------------- */
.frag-anim--fade { animation-name: frag-fade; }

@keyframes frag-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* 2. Slide from right --------------------------------------- */
.frag-anim--slide-right { animation-name: frag-slide-right; }

@keyframes frag-slide-right {
    from { opacity: 0; transform: translateX(40px); }
    to   { opacity: 1; transform: translateX(0); }
}

/* 3. Slide from bottom -------------------------------------- */
.frag-anim--slide-up { animation-name: frag-slide-up; }

@keyframes frag-slide-up {
    from { opacity: 0; transform: translateY(30px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* 4. Zoom / scale in ---------------------------------------- */
.frag-anim--zoom { animation-name: frag-zoom; }

@keyframes frag-zoom {
    from { opacity: 0; transform: scale(.92); }
    to   { opacity: 1; transform: scale(1); }
}

/* 5. Flip in on X ------------------------------------------- */
.frag-anim--flip {
    animation-name: frag-flip;
    transform-origin: center top;
    backface-visibility: hidden;
}

@keyframes frag-flip {
    from { opacity: 0; transform: perspective(800px) rotateX(-18deg); }
    to   { opacity: 1; transform: perspective(800px) rotateX(0); }
}

/* 6. Reveal via clip-path ----------------------------------- */
.frag-anim--reveal { animation-name: frag-reveal; }

@keyframes frag-reveal {
    from { clip-path: inset(0 0 100% 0); opacity: .3; }
    to   { clip-path: inset(0 0 0 0);    opacity: 1; }
}

/* 7. Blur focus in ------------------------------------------ */
.frag-anim--blur { animation-name: frag-blur; }

@keyframes frag-blur {
    from { opacity: 0; filter: blur(10px); transform: scale(1.02); }
    to   { opacity: 1; filter: blur(0);    transform: scale(1); }
}

/* 8. Bounce in ---------------------------------------------- */
.frag-anim--bounce {
    animation-name: frag-bounce;
    animation-timing-function: cubic-bezier(.34, 1.56, .64, 1);
}

@keyframes frag-bounce {
    0%   { opacity: 0; transform: translateY(24px) scale(.95); }
    60%  { opacity: 1; transform: translateY(-6px) scale(1.02); }
    100% { opacity: 1; transform: translateY(0)   scale(1); }
}

/* -------------------- OUT animations -------------------- */

.frag-anim--fade-out { animation-name: frag-fade-out; }

@keyframes frag-fade-out {
    from { opacity: 1; }
    to   { opacity: 0; }
}

.frag-anim--slide-right-out { animation-name: frag-slide-right-out; }

@keyframes frag-slide-right-out {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(-40px); }
}

.frag-anim--slide-up-out { animation-name: frag-slide-up-out; }

@keyframes frag-slide-up-out {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(-30px); }
}

.frag-anim--zoom-out { animation-name: frag-zoom-out; }

@keyframes frag-zoom-out {
    from { opacity: 1; transform: scale(1); }
    to   { opacity: 0; transform: scale(1.06); }
}

.frag-anim--flip-out {
    animation-name: frag-flip-out;
    transform-origin: center bottom;
    backface-visibility: hidden;
}

@keyframes frag-flip-out {
    from { opacity: 1; transform: perspective(800px) rotateX(0); }
    to   { opacity: 0; transform: perspective(800px) rotateX(18deg); }
}

.frag-anim--reveal-out { animation-name: frag-reveal-out; }

@keyframes frag-reveal-out {
    from { clip-path: inset(0 0 0 0);    opacity: 1; }
    to   { clip-path: inset(100% 0 0 0); opacity: .3; }
}

.frag-anim--blur-out { animation-name: frag-blur-out; }

@keyframes frag-blur-out {
    from { opacity: 1; filter: blur(0);    transform: scale(1); }
    to   { opacity: 0; filter: blur(10px); transform: scale(.98); }
}

.frag-anim--bounce-out {
    animation-name: frag-bounce-out;
    animation-timing-function: cubic-bezier(.36, 0, .66, -0.56);
}

@keyframes frag-bounce-out {
    0%   { opacity: 1; transform: translateY(0)    scale(1); }
    40%  { opacity: 1; transform: translateY(6px)  scale(1.02); }
    100% { opacity: 0; transform: translateY(-24px) scale(.95); }
}
