/* ============================================================
   crt-glitch.css  —  drop-in CRT / VHS glitch effect
   Framework-agnostic. No build step, no dependencies.
   Pair with crt-glitch.js. See README.md.

   Structure it expects (crt-glitch.js builds this for you):
     <div class="crtfx">                  ← container (position: relative)
       <div class="crtfx-screen"></div>   ← optional image/gradient layer (RGB-split)
       <div class="crtfx-overlay">        ← scanlines + noise + vignette (on top)
         <div class="crtfx-scan"></div>
         <div class="crtfx-noise"></div>
         <div class="crtfx-vig"></div>
       </div>
     </div>

   Tunables (set on .crtfx or :root):
     --crtfx-scan-opacity  (default .55)
     --crtfx-scan-gap      (default 4px  — distance between scanlines)
     --crtfx-noise-opacity (default .06)
     --crtfx-vignette      (default .5   — corner darkness 0..1)
   ============================================================ */

.crtfx {
  position: relative;
  overflow: hidden;
  --crtfx-scan-opacity: .55;
  --crtfx-scan-gap: 4px;
  --crtfx-noise-opacity: .06;
  --crtfx-vignette: .5;
}

/* ---- image / gradient layer with RGB split ---- */
.crtfx-screen {
  position: absolute; inset: 0;
  background-image: var(--crtfx-src, none);
  background-size: cover; background-position: center;
  filter: saturate(1.1) contrast(1.03);
}
.crtfx-screen::before,
.crtfx-screen::after {
  content: ''; position: absolute; inset: 0;
  background-image: var(--crtfx-src, none);
  background-size: cover; background-position: center;
  mix-blend-mode: screen; opacity: .5;
  transition: transform .28s cubic-bezier(.22,.61,.36,1);
}
.crtfx-screen::before { transform: translateX(var(--crtfx-gx, 3px));            filter: url(#crtfx-cyan); }
.crtfx-screen::after  { transform: translateX(calc(-1 * var(--crtfx-gx, 3px))); filter: url(#crtfx-magenta); }

/* ---- overlay: scanlines + noise + vignette ---- */
.crtfx-overlay { position: absolute; inset: 0; pointer-events: none; z-index: 2; }

.crtfx-scan {
  position: absolute; inset: 0;
  opacity: var(--crtfx-scan-opacity);
  background: repeating-linear-gradient(to bottom,
    rgba(0,0,0,0) 0,
    rgba(0,0,0,0) calc(var(--crtfx-scan-gap) - 1px),
    rgba(0,0,0,.32) calc(var(--crtfx-scan-gap) - 1px),
    rgba(0,0,0,0) var(--crtfx-scan-gap));
}

.crtfx-noise {
  position: absolute; inset: -50%;
  opacity: var(--crtfx-noise-opacity);
  mix-blend-mode: screen;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: crtfx-noise .25s steps(3) infinite;
}
@keyframes crtfx-noise {
  0%   { transform: translate(0,0); }
  33%  { transform: translate(-12px,8px); }
  66%  { transform: translate(10px,-10px); }
  100% { transform: translate(0,0); }
}

.crtfx-vig {
  position: absolute; inset: 0;
  background: radial-gradient(120% 92% at 50% 50%, transparent 58%, rgba(0,0,0,var(--crtfx-vignette)) 100%);
  box-shadow: inset 0 0 130px 44px rgba(0,0,0,calc(var(--crtfx-vignette) * .8));
}

/* ---- glitch burst (toggled by crt-glitch.js) ---- */
.crtfx-shake { animation: crtfx-shake .32s steps(2) both; }
@keyframes crtfx-shake {
  0%   { transform: translate(0,0); }
  18%  { transform: translate(-7px,4px); }
  36%  { transform: translate(6px,-5px); }
  54%  { transform: translate(-5px,3px); }
  72%  { transform: translate(4px,-3px); }
  90%  { transform: translate(-2px,1px); }
  100% { transform: translate(0,0); }
}

/* ---- respect reduced-motion ---- */
@media (prefers-reduced-motion: reduce) {
  .crtfx-noise, .crtfx-shake { animation: none !important; }
  .crtfx-screen::before, .crtfx-screen::after { transition: none; }
}
