/* ═══════════════════════════════════════════════════════════════════
   psfx-cinematic.css — one-off cinematic beats.

   All transform/opacity so they run on the compositor. Every luminance change
   is gentle and every effect is a single short burst, staying well inside the
   WCAG limit of no more than three flashes per second.
   ═══════════════════════════════════════════════════════════════════ */

/* ── CAMERA SHAKE (impact) ────────────────────────────────────────── */
/* translate + a touch of rotate reads more organic than translate alone */
.fxcin-shake { animation: fxcinShake .62s cubic-bezier(.36,.07,.19,.97) both; }
@keyframes fxcinShake {
  0%, 100% { transform: translate3d(0,0,0) rotate(0deg); }
  10% { transform: translate3d(-5px, 2px, 0) rotate(-.25deg); }
  22% { transform: translate3d(5px, -2px, 0) rotate(.25deg); }
  35% { transform: translate3d(-4px, -1px, 0) rotate(-.18deg); }
  48% { transform: translate3d(4px, 1px, 0) rotate(.18deg); }
  62% { transform: translate3d(-2px, 1px, 0) rotate(-.1deg); }
  76% { transform: translate3d(2px, -1px, 0) rotate(.08deg); }
  88% { transform: translate3d(-1px, 0, 0) rotate(0deg); }
}

/* ── RGB SPLIT / GLITCH (shock) ───────────────────────────────────── */
/* a chromatic-aberration stinger: two offset tinted copies fading fast. Brief
   and low-contrast, so it punches without becoming a flash hazard. */
.fxcin-glitch::before,
.fxcin-glitch::after {
  content: ''; position: absolute; inset: 0; z-index: 60; pointer-events: none;
  mix-blend-mode: screen; animation: fxcinGlitch .42s steps(3, end) both;
}
.fxcin-glitch::before { background: rgba(255, 40, 60, .16); }
.fxcin-glitch::after  { background: rgba(40, 200, 255, .14); animation-direction: reverse; }
@keyframes fxcinGlitch {
  0%   { opacity: 0; transform: translate3d(0,0,0); }
  30%  { opacity: 1; transform: translate3d(-3px, 1px, 0); }
  60%  { opacity: .7; transform: translate3d(3px, -1px, 0); }
  100% { opacity: 0; transform: translate3d(0,0,0); }
}

/* ── VIGNETTE PULSE (mood spike) ──────────────────────────────────── */
/* the edges of the screen breathe in the mood colour — one slow swell, not a
   strobe. Uses the mood variable so it always matches the scene. */
.fxcin-pulse::before {
  content: ''; position: absolute; inset: 0; z-index: 55; pointer-events: none;
  background: radial-gradient(130% 100% at 50% 50%, transparent 48%,
    rgba(var(--fx-mood-rgb, 255,45,120), .30) 100%);
  animation: fxcinPulse 1.1s ease-out both;
}
@keyframes fxcinPulse {
  0% { opacity: 0; } 35% { opacity: 1; } 100% { opacity: 0; }
}

/* ── LETTERBOX (dramatic beat) ────────────────────────────────────── */
.fxcin-bars { position: absolute; inset: 0; z-index: 58; pointer-events: none; }
.fxcin-bars i {
  position: absolute; left: 0; right: 0; height: 8%;
  background: #000; transform: translateY(-100%);
  transition: transform .55s cubic-bezier(.4,0,.2,1);
}
.fxcin-bars i:first-child { top: 0; }
.fxcin-bars i:last-child { bottom: 0; transform: translateY(100%); }
.fxcin-bars.on i { transform: translateY(0); }

/* ── RESTRAINT ────────────────────────────────────────────────────── */
/* These are the first things to go: they are pure punctuation, and shake in
   particular is a vestibular trigger. */
@media (prefers-reduced-motion: reduce) {
  .fxcin-shake { animation: none; }
  .fxcin-glitch::before, .fxcin-glitch::after { animation: none; opacity: 0; }
  .fxcin-pulse::before { animation: none; opacity: 0; }
  .fxcin-bars i { transition: none; }
}
body.psfx-calm .fxcin-shake { animation: none; }
body.psfx-calm .fxcin-glitch::before,
body.psfx-calm .fxcin-glitch::after,
body.psfx-calm .fxcin-pulse::before { animation: none; opacity: 0; }