/* ============================================================
   fx.css — FX toolkit styles (igloo.inc specimen language)
   Adam Yee — portfolio site
   Styles for js/fx.js: scramble/decode caret, glitch cuts
   (RGB split + jitter on #universe), white-noise flash overlay.
   All behaviour is JS-gated; under prefers-reduced-motion every
   filter/flash/caret animation is inert.
   ============================================================ */

/* ---------- Scramble / decode ---------- */

/* Scrambled frames are whitespace-sensitive — keep them verbatim. */
[data-scramble] {
  white-space: pre-wrap;
}

/* Thin lime caret while a decode is in flight (.is-decoding is
   toggled by SCRAMBLE.decode). */
.is-decoding::after {
  content: '';
  display: inline-block;
  width: 1px;
  height: 1em;
  margin-left: 2px;
  vertical-align: -0.12em;
  background: var(--pop);
  animation: fx-caret-blink 0.75s steps(1) infinite;
}

@keyframes fx-caret-blink {
  0%, 55% { opacity: 1; }
  56%, 100% { opacity: 0; }
}

/* ---------- Glitch cut: chromatic split + jitter on the canvas ---------- */
/* body.fx-glitch is toggled by GLITCH.burst(ms); removing the class
   returns the canvas to its natural filter:none state. The RGB-split
   filter (#fx-rgbsplit) is injected once by js/fx.js as inline SVG. */
body.fx-glitch #universe {
  filter: url(#fx-rgbsplit);
  will-change: filter, transform;
  animation: fx-glitch-jitter 0.32s steps(2, end) infinite;
}

@keyframes fx-glitch-jitter {
  0%   { transform: translateX(2px); }
  50%  { transform: translateX(-2px); }
  100% { transform: translateX(2px); }
}

/* Injected SVG defs live in a zero-size, non-interactive container. */
.fx-svg-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
  pointer-events: none;
}

/* ---------- White-noise flash overlay ---------- */
/* .is-on is toggled by GLITCH.burst for 120ms. Sits below the chrome
   nav/HUD (z 100+) and above all section content. */
.fx-flash {
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  opacity: 0;
  background: rgba(255, 255, 255, 0.08);
  transition: opacity 90ms linear;
}

.fx-flash.is-on {
  opacity: 1;
}

/* ---------- Reduced motion guard ---------- */
/* No filter, no jitter, no flash, no caret blink. Decodes land
   instantly (handled in js/fx.js). */
@media (prefers-reduced-motion: reduce) {
  body.fx-glitch #universe {
    filter: none;
    animation: none;
  }

  .fx-flash {
    display: none;
  }

  .is-decoding::after {
    animation: none;
    opacity: 0;
  }
}
