/* ================================================================
   FX LAYER — the anime "direction" language.
   All effects are CSS; JS only toggles classes / spawns nodes.
   ================================================================ */

/* ---- impact frame: the 2-frame invert flash. Hardest-hitting trick here.
   steps() is mandatory — smooth interpolation kills the effect. ---- */
#fx-impact{position:fixed;inset:0;z-index:var(--z-impact);pointer-events:none;opacity:0}
#fx-impact.hit{animation:impact 140ms steps(1) 1}
@keyframes impact{
  0%  {opacity:1;background:#fff}
  40% {opacity:1;background:#04060c}
  70% {opacity:1;background:var(--sys-cyan)}
  100%{opacity:0;background:transparent}
}
#fx-impact.hit-dark{animation:impactDark 120ms steps(1) 1}
@keyframes impactDark{
  0%{opacity:1;background:#04060c} 50%{opacity:1;background:#fff} 100%{opacity:0}
}

/* ---- screen shake ---- */
.shake{animation:shake 260ms var(--ease-smash) 1}
@keyframes shake{
  0%,100%{transform:translate(0,0)}
  15%{transform:translate(-7px,3px)} 30%{transform:translate(6px,-4px)}
  45%{transform:translate(-5px,-2px)} 60%{transform:translate(4px,3px)}
  80%{transform:translate(-2px,1px)}
}
.shake-hard{animation:shakeHard 420ms var(--ease-smash) 1}
@keyframes shakeHard{
  0%,100%{transform:translate(0,0) rotate(0)}
  10%{transform:translate(-14px,6px) rotate(-.6deg)}
  25%{transform:translate(12px,-9px) rotate(.5deg)}
  40%{transform:translate(-10px,-5px) rotate(-.4deg)}
  55%{transform:translate(9px,7px) rotate(.3deg)}
  75%{transform:translate(-5px,3px) rotate(-.2deg)}
}

/* ---- speed lines: radial streaks, opacity-toggled on fast scroll ---- */
#fx-speedlines{
  position:fixed;inset:0;z-index:var(--z-tone);pointer-events:none;opacity:0;
  transition:opacity 180ms var(--ease-slide);
  background:repeating-conic-gradient(from 0deg at 50% 50%,
    rgba(236,247,255,.5) 0deg .35deg, transparent .35deg 2.2deg);
  -webkit-mask-image:radial-gradient(circle at 50% 50%, transparent 26%, #000 68%);
  mask-image:radial-gradient(circle at 50% 50%, transparent 26%, #000 68%);
}
#fx-speedlines.rush{opacity:.85;animation:rush 420ms var(--ease-slide) 1}
@keyframes rush{from{transform:scale(1.5);opacity:1}to{transform:scale(1);opacity:.85}}

/* ---- onomatopoeia / impact text ---- */
.bang{
  position:fixed;z-index:var(--z-impact);pointer-events:none;
  font-family:var(--font-impact);font-size:var(--fs-bang);line-height:.9;
  color:var(--bright);letter-spacing:.02em;white-space:nowrap;
  text-shadow:
    4px 4px 0 var(--sys-violet), -3px -3px 0 var(--sys-cyan),
    0 0 30px rgba(53,224,255,.7);
  -webkit-text-stroke:2px #04060c;
  transform:translate(-50%,-50%) rotate(var(--rot,-8deg));
  animation:bang 700ms var(--ease-pop) forwards;
}
@keyframes bang{
  0%  {opacity:0;transform:translate(-50%,-50%) rotate(var(--rot)) scale(.2)}
  25% {opacity:1;transform:translate(-50%,-50%) rotate(var(--rot)) scale(1.25)}
  45% {transform:translate(-50%,-50%) rotate(var(--rot)) scale(1)}
  100%{opacity:0;transform:translate(-50%,-160%) rotate(var(--rot)) scale(1.1)}
}
.bang.jp{font-family:var(--font-jp);font-weight:700}

/* ---- eyecatch: the commercial-break card between arcs ---- */
#fx-eyecatch{
  position:fixed;inset:0;z-index:var(--z-eyecatch);pointer-events:none;
  display:grid;place-items:center;visibility:hidden;
}
#fx-eyecatch.play{visibility:visible;animation:ecHold 900ms steps(1) 1}
@keyframes ecHold{to{visibility:hidden}}
#fx-eyecatch .slab{
  position:absolute;inset:0;
  background:linear-gradient(105deg,var(--sys-violet),var(--void) 42%,var(--void) 58%,var(--sys-cyan));
  clip-path:polygon(0 0,0 0,0 100%,0 100%);
}
#fx-eyecatch.play .slab{animation:ecWipe 900ms var(--ease-smash) 1}
@keyframes ecWipe{
  0%  {clip-path:polygon(0 0,0 0,0 100%,0 100%)}
  22% {clip-path:polygon(0 0,100% 0,100% 100%,0 100%)}
  70% {clip-path:polygon(0 0,100% 0,100% 100%,0 100%)}
  100%{clip-path:polygon(100% 0,100% 0,100% 100%,100% 100%)}
}
#fx-eyecatch .txt{position:relative;text-align:center;opacity:0}
#fx-eyecatch.play .txt{animation:ecTxt 900ms var(--ease-pop) 1}
@keyframes ecTxt{
  0%,15%{opacity:0;transform:translateX(-40px) skewX(-12deg)}
  30%   {opacity:1;transform:none}
  70%   {opacity:1;transform:none}
  100%  {opacity:0;transform:translateX(40px) skewX(12deg)}
}
#fx-eyecatch .en{font-family:var(--font-sys);font-weight:900;
  font-size:clamp(24px,5vw,54px);letter-spacing:.22em;color:var(--bright)}
#fx-eyecatch .jp{font-family:var(--font-jp);font-size:clamp(12px,1.6vw,18px);
  letter-spacing:.7em;color:var(--sys-cyan);margin-top:10px}

/* ---- screentone / halftone overlay (manga arc) — pure CSS dots ---- */
.tone{position:relative}
.tone::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:radial-gradient(circle,#000 1px,transparent 1.6px);
  background-size:4px 4px;opacity:.22;mix-blend-mode:multiply;
}
.tone-light::after{background-size:5px 5px;opacity:.12}

/* ---- chromatic aberration (CRT sting) ---- */
.chroma{animation:chroma 300ms var(--ease-slide) 1}
@keyframes chroma{
  0%  {text-shadow:-4px 0 var(--sys-red),4px 0 var(--sys-cyan);filter:blur(.4px)}
  100%{text-shadow:none;filter:none}
}

/* ---- flash-cut reveal for panels entering ---- */
.cut-in{animation:cutIn var(--t-scene) var(--ease-pop) both}
@keyframes cutIn{
  0%  {opacity:0;transform:translateY(26px) scale(.97);filter:blur(6px) brightness(2.4)}
  55% {opacity:1}
  70% {opacity:.5}                 /* CRT flicker beat mid-settle */
  100%{opacity:1;transform:none;filter:none}
}

@media(prefers-reduced-motion:reduce){
  #fx-impact,#fx-speedlines,#fx-eyecatch,.bang{display:none!important}
  .shake,.shake-hard,.chroma,.cut-in{animation:none!important}
}
