/* global React */
// Shared cyberprep primitives — composed from DS atoms where they fit.

const { useRef, useEffect, useState } = React;

/* HUD coordinate / label readout */
function Hud({ children, className = "", style = {} }) {
  return (
    <span className={"hud " + className} style={style}>{children}</span>
  );
}

/* Bracket corner frame — the engineering-overlay look */
function CornerFrame({ color = "var(--neon-celadon)" }) {
  const c = { position: "absolute", width: 14, height: 14, pointerEvents: "none", opacity: 0.7 };
  const b = `1.5px solid ${color}`;
  return (
    <React.Fragment>
      <span style={{ ...c, top: 8, left: 8, borderTop: b, borderLeft: b }} />
      <span style={{ ...c, top: 8, right: 8, borderTop: b, borderRight: b }} />
      <span style={{ ...c, bottom: 8, left: 8, borderBottom: b, borderLeft: b }} />
      <span style={{ ...c, bottom: 8, right: 8, borderBottom: b, borderRight: b }} />
    </React.Fragment>
  );
}

/* Section intro: HUD index + tag + display heading */
function SectionHead({ index, tag, title, sub, align = "left" }) {
  return (
    <div data-reveal style={{ textAlign: align, maxWidth: align === "center" ? 760 : 880, marginInline: align === "center" ? "auto" : 0 }}>
      <div style={{ display: "flex", gap: 14, alignItems: "center", justifyContent: align === "center" ? "center" : "flex-start", marginBottom: 18 }}>
        <span className="hud" style={{ color: "var(--neon-blue)", fontSize: "1.05rem", letterSpacing: "0.14em" }}>{index}</span>
        <span style={{ width: 34, height: 1, background: "var(--hairline)" }} />
        <span className="hud hud-dim">{tag}</span>
      </div>
      <h2 className="display" style={{ fontSize: "clamp(2.4rem, 5.4vw, 4.4rem)", margin: 0 }}>{title}</h2>
      {sub && <p style={{ marginTop: 18, fontSize: "var(--fs-lead)", fontWeight: "var(--fw-light)", color: "var(--t-body)", lineHeight: 1.55, maxWidth: 620, marginInline: align === "center" ? "auto" : 0 }}>{sub}</p>}
    </div>
  );
}

/* CRT television housing with a live screen (image / children) */
function CRT({ src, label = "CH 01", caption, children, w = "100%" }) {
  return (
    <div className="crt-flicker" style={{ width: w, position: "relative" }}>
      {/* outer housing */}
      <div style={{
        position: "relative",
        padding: "20px 20px 30px",
        borderRadius: 30,
        background: "linear-gradient(160deg, #15282b, #060d0e 70%)",
        border: "1px solid rgba(165,207,161,0.16)",
        boxShadow: "0 40px 90px rgba(0,0,0,0.7), inset 0 1px 0 rgba(255,255,255,0.06)"
      }}>
        {/* screen */}
        <div style={{
          position: "relative",
          borderRadius: 18,
          overflow: "hidden",
          background: "#02110f",
          boxShadow: "inset 0 0 60px rgba(0,0,0,0.9), inset 0 0 0 2px rgba(0,0,0,0.6)",
          aspectRatio: "4 / 3.2"
        }}>
          {src && (
            <img src={src} alt={caption || "screen"} style={{
              position: "absolute", inset: 0, width: "100%", height: "100%",
              objectFit: "cover", filter: "saturate(0.92) contrast(1.05)", transform: "scale(1.04)"
            }} />
          )}
          {children}
          {/* curvature + vignette */}
          <div style={{ position: "absolute", inset: 0, pointerEvents: "none",
            background: "radial-gradient(120% 120% at 50% 50%, transparent 58%, rgba(0,0,0,0.55) 100%)" }} />
          {/* scanlines */}
          <div className="crt-scan" style={{ position: "absolute", inset: 0, pointerEvents: "none",
            background: "repeating-linear-gradient(to bottom, rgba(0,0,0,0) 0 2px, rgba(0,0,0,0.28) 2px 3px)" }} />
          {/* glass glare */}
          <div style={{ position: "absolute", inset: 0, pointerEvents: "none",
            background: "linear-gradient(125deg, rgba(255,255,255,0.14), transparent 30%, transparent 75%, rgba(40,150,184,0.10))" }} />
          {/* on-screen HUD */}
          <div style={{ position: "absolute", top: 12, left: 14, right: 14, display: "flex", justifyContent: "space-between" }}>
            <span style={{ fontFamily: "var(--font-crt)", fontSize: 24, color: "var(--neon-celadon)", letterSpacing: 1, textShadow: "var(--glow-celadon)" }}>{label}</span>
            <span style={{ fontFamily: "var(--font-crt)", fontSize: 24, color: "#ff5b6e" }}>● REC</span>
          </div>
          {caption && (
            <div style={{ position: "absolute", bottom: 12, left: 14, fontFamily: "var(--font-crt)", fontSize: 23, color: "var(--neon-celadon)", letterSpacing: 1 }}>{caption}</div>
          )}
        </div>
        {/* control strip */}
        <div style={{ display: "flex", alignItems: "center", gap: 14, marginTop: 16, paddingInline: 4 }}>
          <span style={{ width: 12, height: 12, borderRadius: "50%", background: "var(--neon-seagrass)", boxShadow: "var(--glow-seagrass)" }} />
          <span style={{ flex: 1, height: 5, borderRadius: 99, background: "rgba(165,207,161,0.10)" }} />
          <span style={{ fontFamily: "var(--font-hud)", fontSize: 13, letterSpacing: 2, color: "var(--t-dim)" }}>VHS · NTSC</span>
          <span style={{ width: 22, height: 22, borderRadius: "50%", border: "2px solid rgba(165,207,161,0.25)" }} />
          <span style={{ width: 22, height: 22, borderRadius: "50%", border: "2px solid rgba(165,207,161,0.25)" }} />
        </div>
      </div>
    </div>
  );
}

/* Glossy 3D keycap — used for the toolkit (analogue/digital hybrid object) */
function Keycap({ name, icon, color, sub }) {
  const ref = useRef(null);
  const onMove = (e) => {
    const el = ref.current; if (!el) return;
    const r = el.getBoundingClientRect();
    const px = (e.clientX - r.left) / r.width - 0.5;
    const py = (e.clientY - r.top) / r.height - 0.5;
    el.style.transform = `perspective(600px) rotateX(${(-py * 14).toFixed(2)}deg) rotateY(${(px * 16).toFixed(2)}deg) translateY(-6px)`;
  };
  const reset = (e) => { if (ref.current) ref.current.style.transform = ""; };
  return (
    <div className="keycap" ref={ref} onMouseMove={onMove} onMouseLeave={reset}
      style={{ "--kc": color }}>
      <div className="keycap-top">
        <i data-lucide={icon} className="keycap-icon" />
        <div className="keycap-name">{name}</div>
        {sub && <div className="keycap-sub">{sub}</div>}
      </div>
    </div>
  );
}

/* ===== Pixel-shatter on click (global helper) ===== */
function pixelShatter(el) {
  if (document.body.dataset.motion === "0") return;
  const r = el.getBoundingClientRect();
  if (r.width < 2) return;
  const cols = Math.max(6, Math.min(14, Math.round(r.width / 16)));
  const rows = Math.max(2, Math.min(6, Math.round(r.height / 14)));
  const cw = r.width / cols, ch = r.height / rows;
  const palette = ["#A5CFA1", "#3BA68C", "#2896B8", "#EAF6F1", "#0B5159"];
  for (let y = 0; y < rows; y++) {
    for (let x = 0; x < cols; x++) {
      const s = document.createElement("div");
      s.className = "shard";
      const sz = Math.min(cw, ch) * (0.5 + Math.random() * 0.5);
      s.style.left = (r.left + x * cw + cw / 2 - sz / 2) + "px";
      s.style.top = (r.top + y * ch + ch / 2 - sz / 2) + "px";
      s.style.width = sz + "px";
      s.style.height = sz + "px";
      s.style.background = palette[(Math.random() * palette.length) | 0];
      const ang = Math.atan2((y + 0.5) / rows - 0.5, (x + 0.5) / cols - 0.5);
      const dist = 30 + Math.random() * 80;
      s.style.setProperty("--dx", Math.cos(ang) * dist + (Math.random() - 0.5) * 30 + "px");
      s.style.setProperty("--dy", Math.sin(ang) * dist - 20 - Math.random() * 40 + "px");
      s.style.setProperty("--dr", (Math.random() - 0.5) * 180 + "deg");
      s.style.setProperty("--sd", 480 + Math.random() * 360 + "ms");
      document.body.appendChild(s);
      setTimeout(() => s.remove(), 900);
    }
  }
}

/* ===== Logo particle dots — scatter → assemble on scroll-in ===== */
function LogoDots({ text, src }) {
  const wrapRef = useRef(null);
  const canvasRef = useRef(null);
  useEffect(() => {
    const wrap = wrapRef.current, canvas = canvasRef.current;
    if (!wrap || !canvas) return;
    const ctx = canvas.getContext("2d");
    let dots = [], raf = 0, dpr = Math.min(2, window.devicePixelRatio || 1);
    let W = 0, H = 0, running = false;

    function buildTargets(img) {
      const rect = wrap.getBoundingClientRect();
      W = Math.max(40, rect.width); H = Math.max(40, rect.height);
      canvas.width = W * dpr; canvas.height = H * dpr;
      canvas.style.width = W + "px"; canvas.style.height = H + "px";
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      // render mark to a sampling buffer
      const buf = document.createElement("canvas");
      buf.width = W; buf.height = H;
      const bx = buf.getContext("2d");
      bx.clearRect(0, 0, W, H);
      bx.fillStyle = "#fff";
      if (img) {
        const ar = img.width / img.height;
        let dw = W * 0.9, dh = dw / ar;
        if (dh > H * 0.9) { dh = H * 0.9; dw = dh * ar; }
        bx.drawImage(img, (W - dw) / 2, (H - dh) / 2, dw, dh);
      } else {
        let fs = H * 0.74;
        bx.font = "800 " + fs + "px Inter, sans-serif";
        bx.textAlign = "center"; bx.textBaseline = "middle";
        // shrink to fit width
        while (bx.measureText(text).width > W * 0.94 && fs > 8) { fs -= 1; bx.font = "800 " + fs + "px Inter, sans-serif"; }
        bx.fillText(text, W / 2, H / 2 + 1);
      }
      const data = bx.getImageData(0, 0, W, H).data;
      const step = Math.max(4, Math.round(W / 60));
      const pts = [];
      for (let y = 0; y < H; y += step) {
        for (let x = 0; x < W; x += step) {
          if (data[(y * W + x) * 4 + 3] > 130) pts.push([x, y]);
        }
      }
      // cap for perf
      const cap = 120;
      let chosen = pts;
      if (pts.length > cap) {
        chosen = [];
        const stride = pts.length / cap;
        for (let i = 0; i < cap; i++) chosen.push(pts[Math.floor(i * stride)]);
      }
      const cx = W / 2, cy = H / 2;
      dots = chosen.map((p) => {
        const sizeRoll = Math.random();
        const rad = sizeRoll > 0.85 ? 3.4 + Math.random() * 1.4 : sizeRoll > 0.5 ? 2.1 + Math.random() : 1.2 + Math.random() * 0.8;
        const dist = Math.hypot(p[0] - cx, p[1] - cy);
        return { hx: p[0], hy: p[1], r: rad, dist };
      });
      // stagger center-out
      const maxd = Math.max(...dots.map((d) => d.dist), 1);
      dots.forEach((d) => { d.delay = (d.dist / maxd) * 260 + Math.random() * 90; });
    }

    function scatter() {
      dots.forEach((d) => {
        const ang = Math.random() * Math.PI * 2;
        const mag = 30 + Math.random() * 90;
        d.sx = d.hx + Math.cos(ang) * mag;
        d.sy = d.hy + Math.sin(ang) * mag;
      });
    }

    let startT = 0;
    const DUR = 520;
    const easeOut = (t) => 1 - Math.pow(1 - t, 3);
    function frame(now) {
      if (!startT) startT = now;
      const motionOff = document.body.dataset.motion === "0";
      ctx.clearRect(0, 0, W, H);
      let allDone = true;
      for (const d of dots) {
        let p = motionOff ? 1 : easeOut(Math.max(0, Math.min(1, (now - startT - d.delay) / DUR)));
        if (p < 1) allDone = false;
        const x = d.sx + (d.hx - d.sx) * p;
        const y = d.sy + (d.hy - d.sy) * p;
        ctx.beginPath();
        ctx.arc(x, y, d.r, 0, Math.PI * 2);
        const g = 0.55 + 0.45 * p;
        ctx.fillStyle = p > 0.6 ? "rgba(234,246,241," + g + ")" : "rgba(165,207,161," + g + ")";
        ctx.fill();
      }
      if (!allDone && running) raf = requestAnimationFrame(frame);
    }

    function play() {
      if (!dots.length) return;
      cancelAnimationFrame(raf);
      scatter(); startT = 0; running = true;
      raf = requestAnimationFrame(frame);
    }

    let built = false;
    function drawHome() {
      if (!dots.length) return;
      ctx.clearRect(0, 0, W, H);
      for (const d of dots) {
        ctx.beginPath();
        ctx.arc(d.hx, d.hy, d.r, 0, Math.PI * 2);
        ctx.fillStyle = "rgba(234,246,241,0.96)";
        ctx.fill();
      }
    }
    function ensureBuilt(cb) {
      if (src) {
        const img = new Image();
        img.onload = () => { buildTargets(img); built = true; drawHome(); cb(); };
        img.onerror = () => { buildTargets(null); built = true; drawHome(); cb(); };
        img.src = src;
      } else { buildTargets(null); built = true; drawHome(); cb(); }
    }

    const io = new IntersectionObserver((entries) => {
      entries.forEach((en) => {
        if (en.isIntersecting) {
          if (!built) ensureBuilt(play); else play();
        } else {
          running = false; cancelAnimationFrame(raf); drawHome();
        }
      });
    }, { threshold: 0.4 });
    io.observe(wrap);
    // build immediately so the canvas is never blank
    ensureBuilt(() => {});

    const onResize = () => { built = false; ensureBuilt(() => play()); };
    window.addEventListener("resize", onResize);
    return () => { io.disconnect(); cancelAnimationFrame(raf); window.removeEventListener("resize", onResize); };
  }, [text, src]);

  return (
    <div className="logo-dots" ref={wrapRef}>
      <canvas ref={canvasRef} />
    </div>
  );
}

/* ===== CRT television with looping tool slideshow ===== */
function CrtTv({ group, channel, items, rot }) {
  const [i, setI] = useState(0);
  useEffect(() => {
    const t = setInterval(() => {
      if (document.body.dataset.motion === "0") return;
      setI((v) => (v + 1) % items.length);
    }, 2200);
    return () => clearInterval(t);
  }, [items.length]);
  return (
    <div className="crt-unit" data-rot={rot}>
      <div className="crt-box">
      <div className="crt-tv crt-flicker">
        <div className="crt-face crt-face-side" />
        <div className="crt-face crt-face-top" />
        <div className="crt-face crt-face-bottom" />
        <div className="crt-bezel">
          <div className="crt-screen">
            <div className="crt-head">
              <span className="crt-head-grp">
                {group.toUpperCase().split(" ").map((w, idx) => <span key={idx}>{w}</span>)}
              </span>
              <span className="crt-head-meta"><span className="dot" /> CH {channel}</span>
            </div>
            <div className="crt-guide">
              {items.map((t, idx) => (
                <div className="crt-row" data-on={idx === i ? "1" : "0"} key={t[0]}>
                  <span className="crt-row-ic"><i data-lucide={t[1]} /></span>
                  <span className="crt-row-nm">{t[0]}</span>
                  <span className="crt-row-sub">{t[2]}</span>
                </div>
              ))}
            </div>
            <div className="scan" />
          </div>
        </div>
        <div className="crt-controls">
          <span className="crt-power" />
          <span className="crt-label">{group}</span>
          <span className="crt-grille" />
          <span className="crt-knob" />
          <span className="crt-knob" />
        </div>
      </div>
      </div>
    </div>
  );
}

/* ===== Browser-window case card ===== */
function BrowserCard({ c }) {
  return (
    <a className="win" href={c.href}>
      <div className="win-chrome">
        <div className="win-dots">
          <i style={{ background: "#ff5f57" }} /><i style={{ background: "#febc2e" }} /><i style={{ background: "#28c840" }} />
        </div>
        <div className="win-url"><i data-lucide="lock" /> amreenshezan.work/{c.slug}</div>
      </div>
      <div className="win-body">
        <div className="win-cover" style={{ background: c.img ? "none" : c.grad, backgroundImage: c.img ? "url(" + c.img + ")" : undefined, backgroundSize: "cover", backgroundPosition: c.n === "02" ? "center 70%" : "center" }}>
          {(c.n === "03" || c.n === "04") && (
            <div style={{ position: "absolute", inset: 0, background: "rgba(4,16,15,0.55)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 2 }}>
              <span style={{ fontFamily: "var(--font-hud)", fontSize: "1.1rem", letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--neon-celadon)", border: "1px solid var(--neon-celadon)", borderRadius: "999px", padding: "9px 22px", background: "rgba(59,166,140,0.1)", backdropFilter: "blur(4px)" }}>Coming Soon!</span>
            </div>
          )}
        </div>
        <div className="skill-row">
          {c.tabs.map((t, idx) => <span className="skill-pill" key={idx}>{t}</span>)}
        </div>
        <span className="cat">{c.cat}</span>
        <h3>{c.title}</h3>
        <p className="desc">{c.desc}</p>
        <span className="open">Open case study <i data-lucide="arrow-right" /></span>
      </div>
    </a>
  );
}

/* ===== Pixel cursor trail (global, suppressed over #work) ===== */
function PixelTrail() {
  useEffect(() => {
    const palette = ["#FFFFFF", "#A5CFA1", "#3BA68C", "#2896B8", "#0B5159"];
    const active = [];
    let lastX = -999, lastY = -999, ci = 0, raf = 0, pending = null;
    function inCases(x, y) {
      const el = document.getElementById("work");
      if (!el) return false;
      const r = el.getBoundingClientRect();
      return x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;
    }
    function spawn(x, y) {
      const d = document.createElement("div");
      d.className = "px-trail-dot";
      const sz = 6 + Math.floor(Math.random() * 7);
      d.style.left = x + "px";
      d.style.top = y + "px";
      d.style.width = sz + "px";
      d.style.height = sz + "px";
      d.style.background = palette[ci % palette.length];
      ci++;
      const life = 320 + Math.random() * 180;
      d.style.setProperty("--life", life + "ms");
      document.body.appendChild(d);
      active.push(d);
      setTimeout(() => { d.remove(); const k = active.indexOf(d); if (k >= 0) active.splice(k, 1); }, life + 40);
      while (active.length > 18) { const old = active.shift(); if (old) old.remove(); }
    }
    function flush() {
      raf = 0;
      if (!pending) return;
      const { x, y } = pending; pending = null;
      if (document.body.dataset.motion === "0") return;
      if (inCases(x, y)) { lastX = x; lastY = y; return; }
      if (Math.hypot(x - lastX, y - lastY) < 13) return;
      lastX = x; lastY = y;
      spawn(x, y);
    }
    function onMove(e) {
      pending = { x: e.clientX, y: e.clientY };
      if (!raf) raf = requestAnimationFrame(flush);
    }
    window.addEventListener("mousemove", onMove, { passive: true });
    return () => {
      window.removeEventListener("mousemove", onMove);
      if (raf) cancelAnimationFrame(raf);
      active.forEach((d) => d.remove());
    };
  }, []);
  return null;
}

/* ===== Pixel-glitch cluster decorations — "tears in the screen" ===== */
function pgBuild(seed) {
  let s = seed >>> 0;
  const rnd = () => { s = (s * 1664525 + 1013904223) >>> 0; return s / 4294967296; };
  // ordered light → dark: rim pixels are brightest near the void, fading outward
  const PAL = ["#FFFFFF", "#A5CFA1", "#3BA68C", "#2896B8", "#0B5159"];
  const voidW = 18 + Math.floor(rnd() * 6);        // 18–23px dark center
  const voidH = 16 + Math.floor(rnd() * 6);
  const voidR = Math.max(voidW, voidH) / 2;
  const ringMax = 18;                             // fractured rim ≤18px past the center
  const n = 16 + Math.floor(rnd() * 6);           // 16–21 rim blocks
  const pts = [];
  for (let i = 0; i < n; i++) {
    const ang = rnd() * Math.PI * 2;
    const d = voidR - 1 + Math.pow(rnd(), 1.5) * ringMax;   // densest hugging the void edge
    const bright = Math.max(0, 1 - (d - voidR) / ringMax);   // 1 at void → 0 outer
    const size = (bright > 0.55 ? 4 : 3) + Math.floor(rnd() * 2);
    const op = +(0.42 + 0.58 * bright).toFixed(2);
    const glow = bright > 0.4 ? +(3 + bright * 6).toFixed(1) : 0;   // brighter rim pixels glow
    const ci = Math.min(PAL.length - 1, Math.floor((1 - bright) * (PAL.length - 1) + rnd() * 0.9));
    pts.push({ x: Math.cos(ang) * d, y: Math.sin(ang) * d * 0.92, size, color: PAL[ci], op, glow });
  }
  // 1–2 unstable rim pixels keep flickering (prefer outer ones)
  const fa = Math.floor(rnd() * n);
  const fb = (fa + 5 + Math.floor(rnd() * Math.max(1, n - 6))) % n;
  pts.forEach((p, i) => {
    if (i === fa || i === fb) { p.flick = true; p.dur = (2 + rnd() * 2).toFixed(2); p.delay = (rnd() * 3.4).toFixed(2); }
  });
  const half = voidR + ringMax + 4;
  pts.forEach((p) => { p.x += half; p.y += half; });
  return { size: half * 2, c: half, voidW, voidH, op: (0.78 + rnd() * 0.14).toFixed(2), squares: pts };
}

const PG_CLUSTERS = [pgBuild(10117), pgBuild(20231), pgBuild(30547), pgBuild(40903)];
const PG_SPOTS = [
  { s: "top", f: 0.72, mode: "inset", xf: 0.16 },
  { s: "toolkit", f: 0.32, mode: "inset", xf: 0.18 },   // left  — beside the TVs
  { s: "toolkit", f: 0.66, mode: "inset", xf: 0.8 },    // right — beside the TVs
  { s: "companies", f: 0.5, mode: "inset", xf: 0.8 }    // right — right of the heading
];

function PixelGlitch() {
  const refs = [useRef(), useRef(), useRef(), useRef()];
  useEffect(() => {
    const place = () => {
      const wrap = document.querySelector(".wrap");
      if (!wrap) return;
      const wr = wrap.getBoundingClientRect();
      const gutterOK = wr.left >= 52;
      const leftX = Math.min(wr.left * 0.55, wr.left - 26);   // nudged in, but clear of content edge
      refs.forEach((r, i) => {
        if (!r.current) return;
        const spot = PG_SPOTS[i];
        if (spot.mode === "gutter" && !gutterOK) { r.current.style.display = "none"; return; }
        r.current.style.display = "";
        const el = document.getElementById(spot.s);
        const t = el ? el.offsetTop : 0, h = el ? el.offsetHeight : 0;
        r.current.style.left = (spot.mode === "gutter" ? leftX : window.innerWidth * spot.xf) + "px";
        r.current.style.top = (t + h * spot.f) + "px";
      });
    };
    place();
    window.addEventListener("resize", place);
    const t = setTimeout(place, 450);
    return () => { window.removeEventListener("resize", place); clearTimeout(t); };
  }, []);
  return (
    <div className="pglitch-layer" aria-hidden="true">
      {PG_CLUSTERS.map((c, i) => (
        <div className="pgcluster" key={i} ref={refs[i]} style={{ width: c.size, height: c.size, opacity: c.op }}>
          <span className="pgvoid" style={{ left: c.c - c.voidW / 2, top: c.c - c.voidH / 2, width: c.voidW, height: c.voidH }} />
          {c.squares.map((p, j) => (
            <span key={j} className={"pgpx" + (p.flick ? " flick" : "")}
              style={Object.assign({ left: p.x - p.size / 2, top: p.y - p.size / 2, width: p.size, height: p.size, background: p.color, "--pgop": p.op },
                p.glow ? { boxShadow: "0 0 " + p.glow + "px " + p.color } : {},
                p.flick ? { "--pgdur": p.dur + "s", "--pgdelay": p.delay + "s" } : {})} />
          ))}
        </div>
      ))}
    </div>
  );
}

Object.assign(window, { Hud, CornerFrame, SectionHead, CRT, Keycap, pixelShatter, LogoDots, CrtTv, BrowserCard, PixelTrail, PixelGlitch });
