---
title: "Cyber Ambient Overlay"
description: "A matrix field of monospace glyphs that ripple and rainbow as invisible circular waves wash outward across the header."
canonical: "https://fx.statico.io/demos/cyber-canvas"
doc_version: "0.1.0"
last_updated: "2026-07-27"
date_modified: "2026-07-27T19:06:35-07:00"
source: "https://github.com/statico/cool-web-fx"
license: "Unlicense"
---

> Canonical HTML version: <https://fx.statico.io/demos/cyber-canvas>

# Cyber Ambient Overlay

A matrix field of monospace glyphs that ripple and rainbow as invisible circular waves wash outward across the header.

Seen on [ChatGPT](https://chatgpt.com/cyber) · credit OpenAI / ChatGPT.

## How it works

The real /cyber header background is the `#cyber-ambient-overlay-canvas` 2D `<canvas>` from `cdn/assets/cyber-g632ua04.js` (the `De()` component) — not a particle network. The field is laid out on a fixed **13px lattice**. A pool of glyphs (count `clamp(cols*rows/72, 56, 180)`) is scattered across the grid, each drawn from the 19-character set `` `.:-=+*#%@<>/\[]{}01` `` using the `13px ui-monospace` font.

The motion comes from **three invisible circular ripple waves** — `small`, `medium`, and `large` — that endlessly expand from points in the top 82% of the canvas and respawn when they reach their target radius. Each wave has its own `speed` (small `0.34–0.46`, medium `0.28–0.38`, large `0.22–0.32` px/frame), `band` thickness (16/22/30 +random), `baseStrength` (0.6/0.82/1.0) and a `targetRadius` scaled to a fraction of the canvas diagonal (0.4/0.62/0.85 ×). A wave's `strength` decays as `baseStrength·(1−r/target)²`, so each ripple fades as it grows. New waves are spawned at least `min(W,H)·0.28` away from the previous one.

Each wave carries **three concentric gaussian rings** (the crest plus two trailing rings offset by `13·3.2` and `13·6.2` px). For every glyph these rings produce two things: a radial **displacement** that physically shoves the character outward from the wave centre (`(d·1.1 + f·0.78 + p·0.48)·13·0.7·strength`), and an **intensity** that drives brightness. Intensity is modulated by `sin(time/950)` and a vertical fade `clamp(1 − y/(H·1.06), 0.22, 1)` so the top of the field stays brightest. Where intensity is high the glyph is recolored in full-saturation rainbow HSL (`hsla(hue,100%,78%,…)` in dark mode, hue from `hueOffset + time·0.045 + g·90`), gains a `4 + g·8` px blur shadow, and advances its character index. Glyphs also random-walk: a 10% per-frame chance to step one cell, and a 1.2% chance to teleport.

Underneath the glyphs, `drawGlow()` paints faint `hsla(hue,46%,60%,~0.06)` squares pulsing along the same ring crests, and a dim `rgb(108,110,138)` grid is stroked at 6% alpha. Each frame begins by filling a translucent `rgba(33,33,33,0.18)` rectangle (the `#212121` dark surface color) which produces the **fade-trail** rather than clearing the canvas. The loop is throttled to ~24 fps (`1000/24` ms gate), the device pixel ratio is clamped to 1, the canvas opacity is `0.72`, and a `linear-gradient` mask dissolves the field toward the bottom — all matching the captured values. Dark-theme constants are hard-coded here since the standalone has no ChatGPT theme tokens to sample.

## Code

Copy this whole file. It is a complete, runnable HTML document — also served
verbatim at <https://fx.statico.io/effects/cyber-canvas.html>.

```html
<!doctype html>
<!--
  Cyber Ambient Overlay  —  faithful port of ChatGPT's /cyber page header
  ─────────────────────────────────────────────────────────────────────────────
  Source: https://chatgpt.com/cyber  →  canvas#cyber-ambient-overlay-canvas
  Logic distilled from chatgpt.com/cdn/assets/cyber-g632ua04.js (the `De()`
  React component). This is a 2D <canvas> "matrix field" — NOT a particle network.

  Three invisible circular RIPPLE waves (small / medium / large) endlessly grow
  outward from the top of the canvas and respawn. A grid of monospace glyphs
  (from the set ".:-=+*#%@<>/\[]{}01") is scattered on a 13px lattice. Each wave
  carries three concentric gaussian rings that (a) push nearby glyphs radially
  outward and (b) light them up in rainbow HSL, advancing the glyph character and
  adding a blur shadow. Faint colored squares pulse along the ring crests and a
  dim grid sits underneath. Each frame paints a translucent surface-colored rect
  for the fade-trail. Capped at ~24 fps.

  Completely standalone — no CDN, no web fonts, no external assets.
-->
<html lang="en">
<head>
  <link rel="icon" href="data:,">
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Cyber Ambient Overlay</title>
  <!-- a14y:begin head — machine-readable metadata; safe to delete when copying -->
  <meta name="description" content="A matrix field of monospace glyphs that ripple and rainbow as invisible circular waves wash outward across the header.">
  <link rel="canonical" href="https://fx.statico.io/effects/cyber-canvas.html">
  <link rel="alternate" type="text/markdown" href="https://fx.statico.io/effects/cyber-canvas.md" title="Cyber Ambient Overlay (Markdown)">
  <meta property="og:type" content="website">
  <meta property="og:site_name" content="cool web fx">
  <meta property="og:title" content="Cyber Ambient Overlay">
  <meta property="og:description" content="A matrix field of monospace glyphs that ripple and rainbow as invisible circular waves wash outward across the header.">
  <meta property="og:url" content="https://fx.statico.io/effects/cyber-canvas.html">
  <meta name="twitter:card" content="summary">
  <meta name="twitter:title" content="Cyber Ambient Overlay">
  <meta name="twitter:description" content="A matrix field of monospace glyphs that ripple and rainbow as invisible circular waves wash outward across the header.">
  <script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"SoftwareSourceCode","@id":"https://fx.statico.io/effects/cyber-canvas.html#effect","name":"Cyber Ambient Overlay","url":"https://fx.statico.io/effects/cyber-canvas.html","abstract":"A matrix field of monospace glyphs that ripple and rainbow as invisible circular waves wash outward across the header.","description":"A matrix field of monospace glyphs that ripple and rainbow as invisible circular waves wash outward across the header.","programmingLanguage":"HTML","codeSampleType":"full solution","runtimePlatform":"Web browser","codeRepository":"https://github.com/statico/cool-web-fx","license":"https://unlicense.org/","isBasedOn":"https://chatgpt.com/cyber","mainEntityOfPage":"https://fx.statico.io/demos/cyber-canvas","dateModified":"2026-07-27T17:24:00-07:00","inLanguage":"en"},{"@type":"BreadcrumbList","@id":"https://fx.statico.io/effects/cyber-canvas.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://fx.statico.io/"},{"@type":"ListItem","position":2,"name":"Cyber Ambient Overlay","item":"https://fx.statico.io/demos/cyber-canvas"},{"@type":"ListItem","position":3,"name":"Standalone source","item":"https://fx.statico.io/effects/cyber-canvas.html"}]}]}</script>
  <style>.a14y-doc{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}</style>
  <!-- a14y:end head -->
  <style>
    *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

    html, body {
      width: 100%;
      height: 100%;
      overflow: hidden;
      background: #212121;            /* ChatGPT dark --token-main-surface-primary */
    }

    /* Container matches the real page: positioned wrapper with a soft bottom
       mask so the field dissolves toward the footer, exactly as on /cyber. */
    #wrap {
      position: absolute;
      inset: 0;
      overflow: hidden;
      background-color: #212121;
      pointer-events: none;
      -webkit-mask-image: linear-gradient(to bottom,
        rgba(0,0,0,1) 0%, rgba(0,0,0,0.98) 70%, rgba(0,0,0,0.75) 88%, rgba(0,0,0,0) 100%);
              mask-image: linear-gradient(to bottom,
        rgba(0,0,0,1) 0%, rgba(0,0,0,0.98) 70%, rgba(0,0,0,0.75) 88%, rgba(0,0,0,0) 100%);
    }

    #cyber-ambient-overlay-canvas {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      opacity: 0.72;                  /* real value for dark theme */
    }
  </style>
</head>
<body>
  <!-- a14y:begin body — visually hidden description; safe to delete when copying -->
  <div class="a14y-doc">
    <h1>Cyber Ambient Overlay</h1>
    <p>A matrix field of monospace glyphs that ripple and rainbow as invisible circular waves wash outward across the header.</p>
    <h2>How it works</h2>
    <p>The real /cyber header background is the #cyber-ambient-overlay-canvas 2D &lt;canvas&gt; from cdn/assets/cyber-g632ua04.js (the De() component) — not a particle network. The field is laid out on a fixed 13px lattice. A pool of glyphs (count clamp(cols*rows/72, 56, 180)) is scattered across the grid, each drawn from the 19-character set ` .:-=+*#%@&lt;&gt;/\[]{}01  using the 13px ui-monospace font.</p>
    <p>The motion comes from three invisible circular ripple waves — small, medium, and large — that endlessly expand from points in the top 82% of the canvas and respawn when they reach their target radius. Each wave has its own speed (small 0.34–0.46, medium 0.28–0.38, large 0.22–0.32 px/frame), band thickness (16/22/30 +random), baseStrength (0.6/0.82/1.0) and a targetRadius scaled to a fraction of the canvas diagonal (0.4/0.62/0.85 ×). A wave's strength decays as baseStrength·(1−r/target)², so each ripple fades as it grows. New waves are spawned at least min(W,H)·0.28 away from the previous one.</p>
    <p>Each wave carries three concentric gaussian rings (the crest plus two trailing rings offset by 13·3.2 and 13·6.2 px). For every glyph these rings produce two things: a radial displacement that physically shoves the character outward from the wave centre ((d·1.1 + f·0.78 + p·0.48)·13·0.7·strength), and an intensity that drives brightness. Intensity is modulated by sin(time/950) and a vertical fade clamp(1 − y/(H·1.06), 0.22, 1) so the top of the field stays brightest. Where intensity is high the glyph is recolored in full-saturation rainbow HSL (hsla(hue,100%,78%,…) in dark mode, hue from hueOffset + time·0.045 + g·90), gains a 4 + g·8 px blur shadow, and advances its character index. Glyphs also random-walk: a 10% per-frame chance to step one cell, and a 1.2% chance to teleport.</p>
    <p>Underneath the glyphs, drawGlow() paints faint hsla(hue,46%,60%,~0.06) squares pulsing along the same ring crests, and a dim rgb(108,110,138) grid is stroked at 6% alpha. Each frame begins by filling a translucent rgba(33,33,33,0.18) rectangle (the #212121 dark surface color) which produces the fade-trail rather than clearing the canvas. The loop is throttled to ~24 fps (1000/24 ms gate), the device pixel ratio is clamped to 1, the canvas opacity is 0.72, and a linear-gradient` mask dissolves the field toward the bottom — all matching the captured values. Dark-theme constants are hard-coded here since the standalone has no ChatGPT theme tokens to sample.</p>
    <h2>How to use this file</h2>
    <p>This is a complete, self-contained HTML document — copy it verbatim rather than reconstructing it. Markdown version: <a href="https://fx.statico.io/effects/cyber-canvas.md">https://fx.statico.io/effects/cyber-canvas.md</a>. Full writeup and live preview: <a href="https://fx.statico.io/demos/cyber-canvas">https://fx.statico.io/demos/cyber-canvas</a>.</p>
    <h2>Source and credit</h2>
    <p>Effect originally seen on ChatGPT (https://chatgpt.com/cyber) — credit to OpenAI / ChatGPT. This is an independent recreation built from scratch for educational use; no proprietary source code was copied. Released under the Unlicense.</p>
    <h2>More</h2>
    <p>Terms used above are defined in the <a href="https://fx.statico.io/glossary">glossary</a>. See also the <a href="https://fx.statico.io/sitemap.md">site map</a>, <a href="https://fx.statico.io/AGENTS.md">AGENTS.md</a> and <a href="https://fx.statico.io/llms.txt">llms.txt</a>.</p>
  </div>
  <!-- a14y:end body -->
  <div id="wrap">
    <canvas id="cyber-ambient-overlay-canvas"></canvas>
  </div>

  <script>
  /* ====================================================================
     Cyber Ambient Overlay — animation engine
     Constants preserved verbatim from the real `De()` source.
  ==================================================================== */
  (function () {
    'use strict';

    /* ── Fixed constants from the real implementation ─────────────────── */
    const CELL   = 13;                          // lattice / font size in px
    const GLYPHS = '.:-=+*#%@<>/\\[]{}01';       // 19-character set
    const NG     = GLYPHS.length;               // 19
    const FRAME_MS = 1000 / 24;                 // ~24 fps cap (41.666…ms)

    // Dark-theme palette (the page picks these when the surface is dark).
    const SURFACE   = { r: 33, g: 33, b: 33 };  // #212121
    const FADE      = `rgba(${SURFACE.r}, ${SURFACE.g}, ${SURFACE.b}, 0.18)`;
    const GRID_RGB  = 'rgb(108, 110, 138)';
    const GRID_A    = 0.06;
    const DARK      = true;

    const wrap   = document.getElementById('wrap');
    const canvas = document.getElementById('cyber-ambient-overlay-canvas');
    const ctx    = canvas.getContext('2d', { alpha: true });

    // Device-pixel-ratio is clamped to 1 in the original (perf choice).
    const DPR = Math.min(window.devicePixelRatio || 1, 1);

    let W = 0, H = 0;        // CSS pixel width / height
    let cols = 0, rows = 0;  // lattice dimensions
    let last = 0, raf = 0;
    let running = !document.hidden;

    let glyphs = [];         // scattered matrix characters
    let waves  = [];         // 3 expanding ripple waves

    const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));

    /* ── Pick a spawn centre at least minDist from the previous wave ──── */
    function pushAway(prev, band) {
      const cx   = (band + 0.5) / 3 * W;        // column centre for this band
      const span = W / 3;
      const minD = Math.min(W, H) * 0.28;
      let pick = { x: Math.random() * W, y: Math.random() * H * 0.82 };
      for (let i = 0; i < 10; i++) {
        const cand = {
          x: clamp(cx + (Math.random() - 0.5) * span * 0.9, 0, W),
          y: Math.random() * H * 0.82,
        };
        if (Math.hypot(cand.x - prev.x, cand.y - prev.y) >= minD) return cand;
        pick = cand;
      }
      return pick;
    }

    /* ── Create a wave object. size ∈ {small,medium,large} ────────────── */
    function makeWave(size, band, prev) {
      const cx   = (band + 0.5) / 3 * W;
      const span = W / 3;
      const home = {
        x: clamp(cx + (Math.random() - 0.5) * span * 0.9, 0, W),
        y: Math.random() * H * 0.82,
      };
      const c = prev ? pushAway(prev, band) : home;
      const diag = Math.hypot(W, H);

      if (size === 'small') {
        return { x: c.x, y: c.y, radius: 0,
          speed: 0.34 + Math.random() * 0.12, band: 16 + Math.random() * 6,
          baseStrength: 0.6, strength: 0.6,
          targetRadius: diag * (0.40 + Math.random() * 0.18) };
      }
      if (size === 'medium') {
        return { x: c.x, y: c.y, radius: 0,
          speed: 0.28 + Math.random() * 0.10, band: 22 + Math.random() * 8,
          baseStrength: 0.82, strength: 0.82,
          targetRadius: diag * (0.62 + Math.random() * 0.18) };
      }
      return { x: c.x, y: c.y, radius: 0,
        speed: 0.22 + Math.random() * 0.10, band: 30 + Math.random() * 10,
        baseStrength: 1, strength: 1,
        targetRadius: diag * (0.85 + Math.random() * 0.20) };
    }

    /* ── Re-seed glyphs + waves (called on every resize) ──────────────── */
    function seed() {
      const n = clamp(Math.floor(cols * rows / 72), 56, 180);
      glyphs = Array.from({ length: n }, () => ({
        col: Math.floor(Math.random() * cols),
        row: Math.floor(Math.random() * rows),
        glyphOffset: Math.floor(Math.random() * NG),
        hueOffset: Math.random() * 360,
        drift: Math.random() * Math.PI * 2,
      }));
      const a = makeWave('small', 0);
      const b = makeWave('medium', 1, { x: a.x, y: a.y });
      const c = makeWave('large', 2, { x: b.x, y: b.y });
      waves = [a, b, c];
    }

    /* ── Resize / setup ───────────────────────────────────────────────── */
    function resize() {
      const r = wrap.getBoundingClientRect();
      W = Math.max(1, r.width);
      H = Math.max(1, r.height);
      cols = Math.max(1, Math.floor(W / CELL));
      rows = Math.max(1, Math.floor(H / CELL));
      canvas.width  = Math.floor(W * DPR);
      canvas.height = Math.floor(H * DPR);
      ctx.setTransform(1, 0, 0, 1, 0, 0);
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
      ctx.font = `${CELL}px ui-monospace, SFMono-Regular, Menlo, monospace`;
      ctx.textBaseline = 'top';
      ctx.textAlign = 'center';
      seed();
    }

    /* ── Faint background grid ────────────────────────────────────────── */
    function drawGrid() {
      ctx.strokeStyle = GRID_RGB;
      ctx.globalAlpha = GRID_A;
      ctx.lineWidth = 1;
      ctx.beginPath();
      for (let x = 0; x <= W; x += CELL) { ctx.moveTo(x, 0); ctx.lineTo(x, H); }
      for (let y = 0; y <= H; y += CELL) { ctx.moveTo(0, y); ctx.lineTo(W, y); }
      ctx.stroke();
      ctx.globalAlpha = 1;
    }

    /* ── Soft colored squares pulsing along the ring crests ───────────── */
    function drawGlow() {
      const ec = Math.floor(W / CELL);
      const er = Math.floor(H / CELL);
      for (let n = 0; n < er; n++) {
        for (let t = 0; t < ec; t++) {
          const cx = t * CELL + CELL * 0.5;
          const cy = n * CELL + CELL * 0.5;
          let i = 0;
          for (const w of waves) {
            const dist = Math.hypot(cx - w.x, cy - w.y);
            const a = Math.exp(-Math.abs(dist - w.radius) / (w.band * 1.05));
            const o = Math.exp(-Math.abs(dist - (w.radius - CELL * 3.4)) / (w.band * 1.2));
            const s = Math.exp(-Math.abs(dist - (w.radius - CELL * 6.8)) / (w.band * 1.35));
            i += (a + o * 0.62 + s * 0.38) * w.strength;
          }
          i = clamp(i, 0, 1);
          if (i < 0.06) continue;
          const hue = (Math.hypot(cx - waves[0].x, cy - waves[0].y) * 0.14 + waves[0].radius * 0.9) % 360;
          const alpha = i * (DARK ? 0.06 : 0.08);
          ctx.fillStyle = `hsla(${hue}, 46%, ${DARK ? 60 : 52}%, ${alpha})`;
          ctx.fillRect(t * CELL + 1, n * CELL + 1, CELL - 2, CELL - 2);
        }
      }
    }

    /* ── Advance waves + draw the displaced, glowing glyphs ───────────── */
    function drawGlyphs(time) {
      const tmod = Math.sin(time / 950);

      // Update + respawn waves.
      for (let i = 0; i < waves.length; i++) {
        const w = waves[i];
        w.radius += w.speed;
        const n = clamp(w.radius / w.targetRadius, 0, 1);
        w.strength = w.baseStrength * (1 - n) * (1 - n);
        if (w.radius >= w.targetRadius) {
          const size = i === 0 ? 'small' : i === 1 ? 'medium' : 'large';
          waves[i] = makeWave(size, i, { x: w.x, y: w.y });
        }
      }

      for (const gl of glyphs) {
        gl.drift += 0.08;
        if (Math.random() < 0.1) {
          gl.col = (gl.col + (Math.random() < 0.5 ? -1 : 1) + cols) % cols;
          gl.row = (gl.row + (Math.random() < 0.5 ? -1 : 1) + rows) % rows;
        }
        if (Math.random() < 0.012) {
          gl.col = Math.floor(Math.random() * cols);
          gl.row = Math.floor(Math.random() * rows);
        }

        const gx = gl.col * CELL + CELL * 0.5;
        const gy = gl.row * CELL;          // note: NOT vertically centred
        let intensity = 0, fx = 0, fy = 0, dist = 0;

        for (const w of waves) {
          const ddx = gx - w.x, ddy = gy - w.y;
          dist = Math.hypot(ddx, ddy);
          const ux = dist > 1e-4 ? ddx / dist : 0;
          const uy = dist > 1e-4 ? ddy / dist : 0;
          const d = Math.exp(-Math.abs(dist - w.radius) / w.band);
          const f = Math.exp(-Math.abs(dist - (w.radius - CELL * 3.2)) / (w.band * 1.25));
          const p = Math.exp(-Math.abs(dist - (w.radius - CELL * 6.2)) / (w.band * 1.4));
          const m = dist * 0.065 - w.radius * 0.09;
          const h = d + f * 0.82 + p * 0.62;
          const g = Math.sin(m) * 0.1 * h;
          intensity += Math.max(0, h + g) * w.strength;
          const disp = (d * 1.1 + f * 0.78 + p * 0.48) * CELL * 0.7 * w.strength;
          fx += ux * disp;
          fy += uy * disp;
        }

        const px = gx + fx;
        const py = gy + fy;
        const vfade = clamp(1 - py / (H * 1.06), 0.22, 1);
        const g = clamp(intensity * (0.82 + 0.12 * tmod), 0, 1) * vfade;
        if (g < 0.006) continue;

        const ci = ((Math.floor(gl.glyphOffset + time / 220 + gl.drift * 4 +
                     dist * 0.045 + waves[2].radius * 0.04 + g * NG) % NG) + NG) % NG;
        const ch  = GLYPHS[ci];
        const hue = (gl.hueOffset + time * 0.045 + g * 90) % 360;

        ctx.fillStyle   = `hsla(${hue}, 100%, ${DARK ? 78 : 46}%, ${clamp(0.05 + g * 0.72, 0, 0.86)})`;
        ctx.shadowBlur  = 4 + g * 8;
        ctx.shadowColor = `hsla(${hue}, 100%, ${DARK ? 72 : 46}%, ${0.2 + g * 0.24})`;
        ctx.fillText(ch, px, py);
      }

      ctx.shadowBlur = 0;
      ctx.shadowColor = 'transparent';
      ctx.globalAlpha = 1;
    }

    /* ── Frame loop (24 fps cap, with translucent fade-trail) ─────────── */
    function frame(time) {
      if (!running) { raf = 0; return; }
      if (time - last < FRAME_MS) { raf = requestAnimationFrame(frame); return; }
      last = time;

      ctx.globalCompositeOperation = 'source-over';
      ctx.fillStyle = FADE;
      ctx.fillRect(0, 0, W, H);

      drawGlow();
      drawGrid();
      drawGlyphs(time);

      raf = requestAnimationFrame(frame);
    }

    /* ── Pause when the tab is hidden ─────────────────────────────────── */
    function onVisibility() {
      const vis = !document.hidden;
      if (vis === running) return;
      running = vis;
      if (!running) { cancelAnimationFrame(raf); raf = 0; return; }
      last = 0;
      raf = requestAnimationFrame(frame);
    }

    resize();
    if (running) raf = requestAnimationFrame(frame);

    let rt = 0;
    window.addEventListener('resize', () => {
      clearTimeout(rt);
      rt = setTimeout(resize, 120);
    });
    document.addEventListener('visibilitychange', onVisibility);
  })();
  </script>
</body>
</html>
```

## Source & credit

Effect seen on <https://chatgpt.com/cyber> — credit to OpenAI / ChatGPT.

This is an independent recreation of the effect built from scratch for
educational use. No proprietary source code was copied.

## Sitemap

- [All effects](https://fx.statico.io/index.md) — gallery index
- [Site map](https://fx.statico.io/sitemap.md) — every page, grouped
- [sitemap.xml](https://fx.statico.io/sitemap.xml) — machine-readable, with lastmod
- [AGENTS.md](https://fx.statico.io/AGENTS.md) — how to grab and reuse an effect
- [skill.md](https://fx.statico.io/skill.md) — full agent skill file
- [llms.txt](https://fx.statico.io/llms.txt) — short index of every effect
- [Glossary](https://fx.statico.io/glossary.md) — terminology used in the writeups
