/* Scene transitions and one-shot effects for VN mode.
   Shapes only — durations are set inline from vn-transitions.js so CSS
   and JS can't drift out of sync. */

/* ── FX layer base ─────────────────────────────────────────────────────── */

.vn-fx-layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    z-index: 15;
}

/* ── Fade (black / white) ──────────────────────────────────────────────── */

.vn-fx-cover {
    transition: opacity ease;
}
.vn-fx-cover.vn-fx-show { opacity: 1; }
.vn-fx-black { background: #000; }
.vn-fx-white { background: #fff; }
.vn-fx-red   { background: #d22; }

/* ── Flash ─────────────────────────────────────────────────────────────── */

.vn-fx-flash.vn-fx-flash-run {
    animation-name: vn-fx-flash-anim;
    animation-timing-function: ease-out;
    animation-fill-mode: forwards;
}
@keyframes vn-fx-flash-anim {
    0%   { opacity: 0; }
    15%  { opacity: 0.95; }
    100% { opacity: 0; }
}

/* ── Shake ─────────────────────────────────────────────────────────────── */
/* Uses the `translate` individual transform property so the animation
   doesn't clobber #avaFrame's inline `transform: scale(...)` set by
   scaling.js — if we wrote `transform: translate(...)` here, the frame
   would snap back to its unscaled 1x size for the duration of the shake. */

.vn-fx-shake-run {
    animation-name: vn-fx-shake-anim;
    animation-timing-function: ease-in-out;
}
@keyframes vn-fx-shake-anim {
    0%, 100% { translate: 0 0; }
    15%      { translate: -8px 2px; }
    30%      { translate: 7px -3px; }
    45%      { translate: -6px 3px; }
    60%      { translate: 5px -2px; }
    75%      { translate: -3px 1px; }
}

/* ── Blur ──────────────────────────────────────────────────────────────── */

.vn-fx-blur {
    opacity: 1;
    background: rgba(0, 0, 0, 0);
    backdrop-filter: blur(0px);
    -webkit-backdrop-filter: blur(0px);
    transition-property: backdrop-filter, -webkit-backdrop-filter, background;
    transition-timing-function: ease;
}
.vn-fx-blur.vn-fx-show {
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    background: rgba(0, 0, 0, 0.35);
}

/* Slide and Zoom are driven by the .vn-fx-snapshot rule below — they
   animate the frozen scene overlay directly rather than a color wash. */

/* ── Iris ──────────────────────────────────────────────────────────────── */

@property --iris-size {
    syntax: '<percentage>';
    initial-value: 150%;
    inherits: false;
}

.vn-fx-iris {
    opacity: 1;
    background: radial-gradient(circle at 50% 50%,
        transparent var(--iris-size),
        #000 var(--iris-size));
    transition: --iris-size ease-in-out;
}

/* ── Curtain ──────────────────────────────────────────────────────────── */

.vn-fx-curtain {
    opacity: 1;
    display: flex;
}
.vn-fx-curtain-left,
.vn-fx-curtain-right {
    flex: 1;
    background: #000;
    transition: transform ease-in-out;
}
.vn-fx-curtain-left  { transform: translateX(-100%); }
.vn-fx-curtain-right { transform: translateX(100%); }
.vn-fx-curtain-closed .vn-fx-curtain-left,
.vn-fx-curtain-closed .vn-fx-curtain-right {
    transform: translateX(0);
}

/* ── Glitch ────────────────────────────────────────────────────────────── */

.vn-fx-glitch {
    opacity: 1;
    animation-name: vn-fx-glitch-overlay;
    animation-timing-function: step-end;
    animation-fill-mode: forwards;
}
@keyframes vn-fx-glitch-overlay {
    0%   { clip-path: inset(0 0 80% 0);   background: rgba(255,0,0,0.3);   transform: translate(3px, 0); }
    10%  { clip-path: inset(60% 0 0 0);   background: rgba(0,255,0,0.3);   transform: translate(-2px, 1px); }
    20%  { clip-path: inset(20% 0 40% 0); background: rgba(0,0,255,0.3);   transform: translate(5px, 0); }
    30%  { clip-path: inset(80% 0 5% 0);  background: rgba(255,0,0,0.2);   transform: translate(-3px, 2px); }
    40%  { clip-path: inset(0 0 60% 0);   background: rgba(0,255,255,0.3); transform: translate(4px, -1px); }
    50%  { clip-path: inset(40% 0 20% 0); background: rgba(255,0,255,0.2); transform: translate(-5px, 0); }
    60%  { clip-path: inset(10% 0 50% 0); background: rgba(0,255,0,0.3);   transform: translate(2px, 3px); }
    70%  { clip-path: inset(70% 0 10% 0); background: rgba(255,0,0,0.3);   transform: translate(-4px, -2px); }
    80%  { clip-path: inset(30% 0 30% 0); background: rgba(0,0,255,0.2);   transform: translate(3px, 1px); }
    90%  { clip-path: inset(0);           background: rgba(255,255,255,0.1); transform: translate(0, 0); }
    100% { clip-path: inset(0);           background: transparent;           transform: translate(0, 0); opacity: 0; }
}

.vn-fx-glitch-frame {
    animation-name: vn-fx-glitch-shake;
    animation-timing-function: step-end;
}
@keyframes vn-fx-glitch-shake {
    0%, 100% { filter: none; }
    12%  { filter: hue-rotate(90deg) saturate(2); }
    24%  { filter: invert(0.15); }
    36%  { filter: hue-rotate(180deg); }
    48%  { filter: saturate(3) brightness(1.2); }
    60%  { filter: hue-rotate(270deg) saturate(2); }
    72%  { filter: invert(0.1) brightness(1.3); }
    84%  { filter: hue-rotate(45deg); }
}

/* ── Pixelate ─────────────────────────────────────────────────────────── */

.vn-fx-pixelate-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 15;
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
}

/* ── Scene snapshot (slide, etc.) ─────────────────────────────────────── */
/* A frozen copy of the scene pinned over #avaFrame, used by transitions
   that need the old and new scenes visible simultaneously. Sits under
   .vn-fx-layer (z-index 15) so fades/flashes still draw on top. */

.vn-fx-snapshot {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 14;
    pointer-events: none;
    transform-origin: center center;
    transform: translateX(var(--snap-x, 0)) scale(var(--snap-scale, 1));
    opacity: var(--snap-opacity, 1);
    transition-property: transform, opacity;
    transition-timing-function: ease-in-out;
}
