@pixerate/flair 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/catalog/glsl.ts","../src/catalog/shaders/gradients.ts","../src/catalog/images.ts","../src/catalog/shaders/image.ts","../src/catalog/shaders/light.ts","../src/catalog/shaders/organic.ts","../src/catalog/shaders/patterns.ts","../src/catalog/shaders/retro.ts","../src/catalog/types.ts","../src/catalog/vector.ts","../src/catalog/index.ts"],"sourcesContent":["/**\n * GLSL helpers the catalog's shaders are built from. Each effect's source\n * inlines the helpers it uses, so a source stays self-contained: copy it into\n * any Shadertoy-style host and it compiles.\n */\n\n/** Hashes: `hash12` (vec2 → float), `hash22` (vec2 → vec2), both 0–1. */\nexport const HASH = `\nfloat hash12(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * 0.1031);\n p3 += dot(p3, p3.yzx + 33.33);\n return fract((p3.x + p3.y) * p3.z);\n}\nvec2 hash22(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * vec3(0.1031, 0.1030, 0.0973));\n p3 += dot(p3, p3.yzx + 33.33);\n return fract((p3.xx + p3.yz) * p3.zy);\n}`.trim();\n\n/** Smooth value noise, 0–1 (needs {@link HASH}). */\nexport const NOISE = `\nfloat vnoise(vec2 p) {\n vec2 i = floor(p);\n vec2 f = fract(p);\n vec2 u = f * f * (3.0 - 2.0 * f);\n float a = hash12(i);\n float b = hash12(i + vec2(1.0, 0.0));\n float c = hash12(i + vec2(0.0, 1.0));\n float d = hash12(i + vec2(1.0, 1.0));\n return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);\n}`.trim();\n\n/** Fractal noise: `fbm(p, octaves)`, about 0–1 (needs {@link NOISE}). */\nexport const FBM = `\nfloat fbm(vec2 p, int octaves) {\n float sum = 0.0;\n float amp = 0.5;\n mat2 turn = mat2(0.8, 0.6, -0.6, 0.8);\n for (int i = 0; i < 8; i++) {\n if (i >= octaves) break;\n sum += amp * vnoise(p);\n p = turn * p * 2.02 + 17.0;\n amp *= 0.5;\n }\n return sum;\n}`.trim();\n\n/** Inigo Quilez's cosine palette: `palette(t, a, b, c, d)`. */\nexport const PALETTE = `\nvec3 palette(float t, vec3 a, vec3 b, vec3 c, vec3 d) {\n return a + b * cos(6.28318 * (c * t + d));\n}`.trim();\n\n/** Mixes colours in Oklab, so blends stay bright: `oklabMix(a, b, t)` on sRGB colours. */\nexport const OKLAB_MIX = `\nvec3 toOklab(vec3 c) {\n c = pow(max(c, 0.0), vec3(2.2));\n vec3 lms = mat3(0.4122, 0.2119, 0.0883, 0.5363, 0.6807, 0.2817, 0.0514, 0.1074, 0.6300) * c;\n lms = pow(lms, vec3(1.0 / 3.0));\n return mat3(0.2105, 1.9780, 0.0259, 0.7936, -2.4286, 0.7828, -0.0041, 0.4506, -0.8087) * lms;\n}\nvec3 fromOklab(vec3 c) {\n vec3 lms = mat3(1.0, 1.0, 1.0, 0.3963, -0.1056, -0.0895, 0.2158, -0.0639, -1.2915) * c;\n lms = lms * lms * lms;\n vec3 rgb = mat3(4.0767, -1.2684, -0.0042, -3.3077, 2.6098, -0.7034, 0.2310, -0.3413, 1.7076) * lms;\n return pow(max(rgb, 0.0), vec3(1.0 / 2.2));\n}\nvec3 oklabMix(vec3 a, vec3 b, float t) {\n return fromOklab(mix(toOklab(a), toOklab(b), t));\n}`.trim();\n\n/** 2D rotation matrix: `rot(angle)`. */\nexport const ROTATE = `\nmat2 rot(float a) {\n float c = cos(a);\n float s = sin(a);\n return mat2(c, s, -s, c);\n}`.trim();\n\n/** Joins helpers and a body into one source, a blank line apart. */\nexport function glsl(...parts: string[]): string {\n return parts.map((p) => p.trim()).join(\"\\n\\n\") + \"\\n\";\n}\n","import { FBM, glsl, HASH, NOISE, OKLAB_MIX, ROTATE } from \"../glsl.js\";\nimport type { ShaderEffect } from \"../types.js\";\n\nexport const aurora: ShaderEffect = {\n kind: \"shader\",\n id: \"aurora\",\n name: \"Aurora\",\n description: \"Soft curtains of light drifting over a night sky.\",\n category: \"gradient\",\n tags: [\"background\", \"hero\", \"calm\", \"night\"],\n source: glsl(\n `// Aurora: curtains of light drifting over a night sky.\nuniform vec3 uSky; // @control color default=#050816 label=\"Sky\"\nuniform vec3 uGlowA; // @control color default=#22D3A6 label=\"Glow A\"\nuniform vec3 uGlowB; // @control color default=#7C3AED label=\"Glow B\"\nuniform float uSpeed; // @control min=0 max=2 default=0.35 label=\"Speed\"\nuniform float uIntensity; // @control min=0 max=2 default=1 label=\"Intensity\"\nuniform float uHeight; // @control min=0 max=1 default=0.55 label=\"Height\"`,\n HASH,\n NOISE,\n FBM,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy;\n float t = iTime * uSpeed;\n vec3 col = uSky * (0.6 + 0.4 * uv.y);\n for (int i = 0; i < 3; i++) {\n float fi = float(i);\n float x = uv.x * (1.4 + 0.3 * fi) + fi * 3.7;\n float wave = fbm(vec2(x * 1.5 + t * 0.4, t * 0.25 + fi), 4);\n float centre = uHeight + 0.18 * (wave - 0.5) + 0.06 * fi;\n float band = exp(-pow((uv.y - centre) * (7.0 + 2.0 * fi), 2.0));\n float rays = 0.55 + 0.45 * fbm(vec2(x * 12.0, t * 0.6 + fi * 9.0), 3);\n float above = smoothstep(centre - 0.05, centre + 0.35, uv.y) * 0.35;\n vec3 glow = mix(uGlowA, uGlowB, clamp(uv.y * 1.4 - 0.2 + 0.25 * fi, 0.0, 1.0));\n col += glow * (band * rays + above * band) * 0.6 * uIntensity;\n }\n float stars = step(0.997, hash12(floor(fragCoord * 0.5))) * smoothstep(0.3, 1.0, uv.y);\n col += stars * 0.6 * (0.5 + 0.5 * sin(iTime * 3.0 + hash12(floor(fragCoord)) * 40.0));\n fragColor = vec4(col, 1.0);\n}`,\n ),\n presets: [\n { name: \"Arctic\", values: { uGlowA: [0.13, 0.83, 0.65], uGlowB: [0.49, 0.23, 0.93] } },\n { name: \"Ember\", values: { uSky: [0.06, 0.02, 0.03], uGlowA: [1, 0.45, 0.1], uGlowB: [0.9, 0.1, 0.4] } },\n { name: \"Ice\", values: { uSky: [0.01, 0.03, 0.06], uGlowA: [0.5, 0.9, 1], uGlowB: [0.2, 0.4, 1] } },\n ],\n};\n\nexport const meshGradient: ShaderEffect = {\n kind: \"shader\",\n id: \"mesh-gradient\",\n name: \"Mesh gradient\",\n description: \"Four colours blended across a slowly warping mesh, mixed in Oklab.\",\n category: \"gradient\",\n tags: [\"background\", \"hero\", \"brand\", \"soft\"],\n source: glsl(\n `// Mesh gradient: four colours on drifting points, blended in Oklab.\nuniform vec3 uColorA; // @control color default=#FF6B6B label=\"Colour A\"\nuniform vec3 uColorB; // @control color default=#FFD93D label=\"Colour B\"\nuniform vec3 uColorC; // @control color default=#6BCB77 label=\"Colour C\"\nuniform vec3 uColorD; // @control color default=#4D96FF label=\"Colour D\"\nuniform float uSpeed; // @control min=0 max=2 default=0.3 label=\"Speed\"\nuniform float uWarp; // @control min=0 max=1 default=0.35 label=\"Warp\"\nuniform float uGrain; // @control min=0 max=0.2 default=0.04 label=\"Grain\"`,\n HASH,\n NOISE,\n OKLAB_MIX,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy;\n float t = iTime * uSpeed;\n vec2 w = uv + uWarp * 0.3 * vec2(vnoise(uv * 2.0 + t), vnoise(uv * 2.0 - t + 5.0)) - uWarp * 0.15;\n vec2 pa = vec2(0.2, 0.2) + 0.15 * vec2(sin(t * 1.1), cos(t * 0.9));\n vec2 pb = vec2(0.8, 0.25) + 0.15 * vec2(cos(t * 0.7), sin(t * 1.3));\n vec2 pc = vec2(0.25, 0.8) + 0.15 * vec2(sin(t * 0.8 + 2.0), cos(t * 1.2));\n vec2 pd = vec2(0.8, 0.8) + 0.15 * vec2(cos(t * 1.0 + 1.0), sin(t * 0.6));\n vec4 d = vec4(distance(w, pa), distance(w, pb), distance(w, pc), distance(w, pd));\n vec4 k = 1.0 / (d * d + 0.02);\n k /= dot(k, vec4(1.0));\n vec3 ab = oklabMix(uColorA, uColorB, k.y / max(k.x + k.y, 1e-4));\n vec3 cd = oklabMix(uColorC, uColorD, k.w / max(k.z + k.w, 1e-4));\n vec3 col = oklabMix(ab, cd, k.z + k.w);\n col += (hash12(fragCoord + fract(iTime) * 100.0) - 0.5) * uGrain;\n fragColor = vec4(col, 1.0);\n}`,\n ),\n presets: [\n { name: \"Sunset\", values: { uColorA: [1, 0.42, 0.42], uColorB: [1, 0.85, 0.24], uColorC: [0.9, 0.3, 0.6], uColorD: [0.36, 0.2, 0.7] } },\n { name: \"Lagoon\", values: { uColorA: [0.0, 0.6, 0.7], uColorB: [0.5, 0.95, 0.85], uColorC: [0.1, 0.3, 0.6], uColorD: [0.85, 0.95, 1] } },\n { name: \"Mono\", values: { uColorA: [0.1, 0.1, 0.12], uColorB: [0.3, 0.3, 0.34], uColorC: [0.2, 0.2, 0.24], uColorD: [0.6, 0.6, 0.65] } },\n ],\n};\n\nexport const conicSweep: ShaderEffect = {\n kind: \"shader\",\n id: \"conic-sweep\",\n name: \"Conic sweep\",\n description: \"A rotating conic gradient with a soft glowing core.\",\n category: \"gradient\",\n tags: [\"background\", \"spotlight\", \"brand\"],\n loop: 10,\n source: glsl(\n `// Conic sweep: a rotating conic gradient with a glowing core.\nuniform vec3 uColorA; // @control color default=#0EA5E9 label=\"Colour A\"\nuniform vec3 uColorB; // @control color default=#A855F7 label=\"Colour B\"\nuniform vec3 uColorC; // @control color default=#F43F5E label=\"Colour C\"\nuniform float uTurns; // @control min=-3 max=3 default=1 step=1 label=\"Turns per loop\"\nuniform float uCore; // @control min=0 max=1 default=0.4 label=\"Core glow\"\nuniform vec2 uCenter; // @control min=-0.5 max=0.5 default=0,0 label=\"Centre\"`,\n OKLAB_MIX,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y - uCenter;\n float a = atan(p.y, p.x) / 6.28318 + 0.5;\n a = fract(a + iTime * uTurns / 10.0);\n float s = a * 3.0;\n vec3 col = s < 1.0 ? oklabMix(uColorA, uColorB, s)\n : s < 2.0 ? oklabMix(uColorB, uColorC, s - 1.0)\n : oklabMix(uColorC, uColorA, s - 2.0);\n float r = length(p);\n col *= 0.75 + 0.25 * smoothstep(0.9, 0.0, r);\n col += uCore * exp(-r * 6.0);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const silk: ShaderEffect = {\n kind: \"shader\",\n id: \"silk\",\n name: \"Silk\",\n description: \"Folds of glossy fabric rippling in a slow breeze.\",\n category: \"gradient\",\n tags: [\"background\", \"luxury\", \"soft\"],\n source: glsl(\n `// Silk: glossy folds of fabric rippling slowly.\nuniform vec3 uBase; // @control color default=#3B0764 label=\"Base\"\nuniform vec3 uSheen; // @control color default=#F0ABFC label=\"Sheen\"\nuniform float uSpeed; // @control min=0 max=2 default=0.4 label=\"Speed\"\nuniform float uFolds; // @control min=1 max=10 default=5 label=\"Folds\"\nuniform float uGloss; // @control min=0 max=2 default=1 label=\"Gloss\"`,\n ROTATE,\n `float folds(vec2 p, float t) {\n float h = 0.0;\n for (int i = 1; i <= 4; i++) {\n float fi = float(i);\n h += sin(p.x * uFolds * fi * 0.7 + t * (1.0 + 0.3 * fi) + sin(p.y * 2.0 * fi + t)) / fi;\n }\n return h;\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = rot(0.6) * (fragCoord - 0.5 * iResolution.xy) / iResolution.y;\n float t = iTime * uSpeed;\n float e = 0.002;\n float hx = (folds(p + vec2(e, 0.0), t) - folds(p - vec2(e, 0.0), t)) / (2.0 * e);\n float hy = (folds(p + vec2(0.0, e), t) - folds(p - vec2(0.0, e), t)) / (2.0 * e);\n vec3 n = normalize(vec3(-hx * 0.12, -hy * 0.12, 1.0));\n vec3 l = normalize(vec3(-0.4, 0.6, 0.7));\n float diff = clamp(dot(n, l), 0.0, 1.0);\n float spec = pow(clamp(dot(reflect(-l, n), vec3(0.0, 0.0, 1.0)), 0.0, 1.0), 20.0) * uGloss;\n vec3 col = uBase * (0.35 + 0.9 * diff) + uSheen * (spec + 0.12 * pow(diff, 6.0));\n fragColor = vec4(col, 1.0);\n}`,\n ),\n presets: [\n { name: \"Champagne\", values: { uBase: [0.55, 0.42, 0.25], uSheen: [1, 0.95, 0.8] } },\n { name: \"Midnight\", values: { uBase: [0.04, 0.08, 0.2], uSheen: [0.6, 0.75, 1] } },\n ],\n};\n\nexport const duotoneFlow: ShaderEffect = {\n kind: \"shader\",\n id: \"gradient-flow\",\n name: \"Gradient flow\",\n description: \"Two colours flowing through each other along a warped noise field.\",\n category: \"gradient\",\n tags: [\"background\", \"brand\", \"liquid\"],\n source: glsl(\n `// Gradient flow: two colours flowing through a warped noise field.\nuniform vec3 uColorA; // @control color default=#1E3A8A label=\"Colour A\"\nuniform vec3 uColorB; // @control color default=#F97316 label=\"Colour B\"\nuniform float uSpeed; // @control min=0 max=2 default=0.25 label=\"Speed\"\nuniform float uScale; // @control min=0.5 max=6 default=2 label=\"Scale\"\nuniform float uContrast; // @control min=0.5 max=4 default=1.5 label=\"Contrast\"`,\n HASH,\n NOISE,\n FBM,\n OKLAB_MIX,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = fragCoord / iResolution.y * uScale;\n float t = iTime * uSpeed;\n vec2 q = vec2(fbm(p + t, 4), fbm(p + vec2(5.2, 1.3) - t, 4));\n float f = fbm(p + 3.0 * q + vec2(1.7, 9.2) + 0.5 * t, 5);\n f = clamp((f - 0.5) * uContrast + 0.5, 0.0, 1.0);\n fragColor = vec4(oklabMix(uColorA, uColorB, smoothstep(0.0, 1.0, f)), 1.0);\n}`,\n ),\n};\n","/**\n * Sample pictures for the catalog's image effects: small SVGs as `data:` URLs,\n * so image controls have something to show with nothing to download.\n */\n\n/** An ASCII SVG as a base64 `data:image/svg+xml` URL. */\nexport function svgDataUrl(svg: string): string {\n const base64 =\n typeof btoa === \"function\" ? btoa(svg) : (globalThis as { Buffer?: { from(s: string): { toString(e: string): string } } }).Buffer!.from(svg).toString(\"base64\");\n return `data:image/svg+xml;base64,${base64}`;\n}\n\nconst LANDSCAPE = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 640 360\">\n<defs><linearGradient id=\"s\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop offset=\"0\" stop-color=\"#3b4cb8\"/><stop offset=\"1\" stop-color=\"#ffa36b\"/></linearGradient></defs>\n<rect width=\"640\" height=\"360\" fill=\"url(#s)\"/>\n<circle cx=\"420\" cy=\"170\" r=\"62\" fill=\"#ffe9b0\"/>\n<path d=\"M0 250 Q120 190 240 240 T480 230 T640 220 V360 H0Z\" fill=\"#2c4a52\"/>\n<path d=\"M0 290 Q160 240 320 290 T640 280 V360 H0Z\" fill=\"#1b2f33\"/>\n<path d=\"M0 330 Q200 300 400 330 T640 325 V360 H0Z\" fill=\"#0f1c1f\"/>\n</svg>`;\n\nconst CITY = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 640 360\">\n<rect width=\"640\" height=\"360\" fill=\"#0d1028\"/>\n<circle cx=\"520\" cy=\"80\" r=\"34\" fill=\"#f5f3d7\"/>\n<g fill=\"#252a52\"><rect x=\"20\" y=\"170\" width=\"70\" height=\"190\"/><rect x=\"110\" y=\"120\" width=\"60\" height=\"240\"/><rect x=\"190\" y=\"200\" width=\"80\" height=\"160\"/><rect x=\"290\" y=\"90\" width=\"55\" height=\"270\"/><rect x=\"365\" y=\"160\" width=\"90\" height=\"200\"/><rect x=\"475\" y=\"130\" width=\"60\" height=\"230\"/><rect x=\"555\" y=\"190\" width=\"70\" height=\"170\"/></g>\n<g fill=\"#ffcf5a\"><rect x=\"125\" y=\"140\" width=\"8\" height=\"8\"/><rect x=\"150\" y=\"170\" width=\"8\" height=\"8\"/><rect x=\"305\" y=\"110\" width=\"8\" height=\"8\"/><rect x=\"320\" y=\"150\" width=\"8\" height=\"8\"/><rect x=\"380\" y=\"180\" width=\"8\" height=\"8\"/><rect x=\"420\" y=\"220\" width=\"8\" height=\"8\"/><rect x=\"490\" y=\"150\" width=\"8\" height=\"8\"/><rect x=\"40\" y=\"200\" width=\"8\" height=\"8\"/><rect x=\"215\" y=\"230\" width=\"8\" height=\"8\"/><rect x=\"575\" y=\"215\" width=\"8\" height=\"8\"/></g>\n</svg>`;\n\nconst PORTRAIT = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 640 360\">\n<rect width=\"640\" height=\"360\" fill=\"#f2e6d8\"/>\n<circle cx=\"320\" cy=\"150\" r=\"70\" fill=\"#c98b6b\"/>\n<path d=\"M190 360 Q200 240 320 240 Q440 240 450 360Z\" fill=\"#33415c\"/>\n<path d=\"M250 130 Q260 60 320 62 Q385 60 392 135 Q370 100 320 100 Q275 100 250 130Z\" fill=\"#2b1d16\"/>\n<circle cx=\"295\" cy=\"150\" r=\"6\" fill=\"#2b1d16\"/><circle cx=\"345\" cy=\"150\" r=\"6\" fill=\"#2b1d16\"/>\n<path d=\"M300 185 Q320 198 340 185\" stroke=\"#7a3e2c\" stroke-width=\"5\" fill=\"none\"/>\n</svg>`;\n\n/** Built-in sample pictures, as image control values. */\nexport const SAMPLE_IMAGES = {\n landscape: svgDataUrl(LANDSCAPE),\n city: svgDataUrl(CITY),\n portrait: svgDataUrl(PORTRAIT),\n} as const;\n","import { getTransitionGLSL, type TransitionType } from \"../../shader/transition.js\";\nimport { glsl, HASH, NOISE } from \"../glsl.js\";\nimport { SAMPLE_IMAGES } from \"../images.js\";\nimport type { ShaderEffect } from \"../types.js\";\n\n/**\n * `picture(tex, uv)`: the image, or a test card while there is none (an empty\n * image control is bound to a 1 × 1 placeholder), so effects show something\n * before an image is chosen.\n */\nconst PICTURE = `\nvec3 testCard(vec2 uv) {\n vec3 sky = mix(vec3(0.98, 0.62, 0.42), vec3(0.24, 0.32, 0.72), uv.y);\n float sun = smoothstep(0.16, 0.15, length((uv - vec2(0.65, 0.58)) * vec2(1.6, 1.0)));\n float hills = step(uv.y, 0.32 + 0.06 * sin(uv.x * 9.0) + 0.04 * sin(uv.x * 23.0 + 1.0));\n vec3 col = mix(sky, vec3(1.0, 0.92, 0.7), sun);\n col = mix(col, vec3(0.12, 0.28, 0.24) + 0.08 * sin(uv.x * 40.0), hills);\n vec2 grid = abs(fract(uv * 8.0) - 0.5);\n col += 0.04 * step(0.48, max(grid.x, grid.y));\n return col;\n}\nvec3 picture(sampler2D tex, vec2 uv) {\n return textureSize(tex, 0).x > 1 ? texture(tex, uv).rgb : testCard(fract(uv));\n}`.trim();\n\nexport const imageRipple: ShaderEffect = {\n kind: \"shader\",\n id: \"image-ripple\",\n name: \"Ripple\",\n description: \"An image rippling as if seen through water, from the pointer or the centre.\",\n category: \"image\",\n tags: [\"image\", \"water\", \"interactive\", \"distortion\"],\n source: glsl(\n `// Ripple: an image rippling as if under water.\nuniform sampler2D uImage; // @control filter=linear wrap=mirror default=${SAMPLE_IMAGES.landscape} label=\"Image\"\nuniform float uAmplitude; // @control min=0 max=0.05 default=0.012 label=\"Amplitude\"\nuniform float uFrequency; // @control min=5 max=80 default=30 label=\"Frequency\"\nuniform float uSpeed; // @control min=0 max=6 default=2 label=\"Speed\"`,\n PICTURE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy;\n vec2 centre = (iMouse.z > 0.0 ? iMouse.xy : 0.5 * iResolution.xy) / iResolution.xy;\n vec2 d = uv - centre;\n d.x *= iResolution.x / iResolution.y;\n float r = length(d);\n float wave = sin(r * uFrequency - iTime * uSpeed) * smoothstep(0.9, 0.0, r);\n vec2 offset = normalize(d + 1e-5) * wave * uAmplitude;\n vec3 col = picture(uImage, uv + offset);\n col += 0.6 * max(wave, 0.0) * uAmplitude * 8.0;\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const imageGlitch: ShaderEffect = {\n kind: \"shader\",\n id: \"image-glitch\",\n name: \"Glitch\",\n description: \"Digital glitch on an image: RGB split, slice displacement and blocky corruption in bursts.\",\n category: \"image\",\n tags: [\"image\", \"glitch\", \"cyber\", \"transition\"],\n source: glsl(\n `// Glitch: RGB split, slice displacement and blocky corruption in bursts.\nuniform sampler2D uImage; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.landscape} label=\"Image\"\nuniform float uAmount; // @control min=0 max=1 default=0.5 label=\"Amount\"\nuniform float uSplit; // @control min=0 max=0.05 default=0.012 label=\"RGB split\"\nuniform float uRate; // @control min=0.5 max=12 default=4 label=\"Bursts per second\"`,\n HASH,\n PICTURE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy;\n float tick = floor(iTime * uRate);\n float burst = step(1.0 - uAmount * 0.6, hash12(vec2(tick, 1.0)));\n float slice = floor(uv.y * mix(8.0, 40.0, hash12(vec2(tick, 2.0))));\n float shift = (hash12(vec2(slice, tick)) - 0.5) * 0.15 * burst * step(0.6, hash12(vec2(slice, tick + 3.0)));\n vec2 block = floor(uv * vec2(16.0, 9.0));\n float corrupt = burst * step(0.97 - uAmount * 0.05, hash12(block + tick));\n vec2 st = uv + vec2(shift, 0.0);\n st = mix(st, floor(st * 24.0) / 24.0, corrupt);\n float split = uSplit * (0.3 + burst);\n vec3 col = vec3(\n picture(uImage, st + vec2(split, 0.0)).r,\n picture(uImage, st).g,\n picture(uImage, st - vec2(split, 0.0)).b\n );\n col = mix(col, col.bgr, corrupt);\n col *= 0.92 + 0.08 * sin(fragCoord.y * 2.0);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const imageDuotone: ShaderEffect = {\n kind: \"shader\",\n id: \"image-duotone\",\n name: \"Duotone\",\n description: \"An image mapped onto two colours, with a slow light sweep.\",\n category: \"image\",\n tags: [\"image\", \"brand\", \"editorial\", \"colour\"],\n source: glsl(\n `// Duotone: an image mapped onto two colours, with a light sweep.\nuniform sampler2D uImage; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.landscape} label=\"Image\"\nuniform vec3 uShadow; // @control color default=#1E1B4B label=\"Shadows\"\nuniform vec3 uHighlight; // @control color default=#FB7185 label=\"Highlights\"\nuniform float uContrast; // @control min=0.5 max=3 default=1.2 label=\"Contrast\"\nuniform float uSweep; // @control min=0 max=1 default=0.3 label=\"Light sweep\"`,\n PICTURE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy;\n vec3 src = picture(uImage, uv);\n float l = dot(src, vec3(0.2126, 0.7152, 0.0722));\n l = clamp((l - 0.5) * uContrast + 0.5, 0.0, 1.0);\n float sweep = exp(-pow((uv.x + uv.y * 0.4 - fract(iTime * 0.15) * 2.0 + 0.4) * 6.0, 2.0));\n vec3 col = mix(uShadow, uHighlight, l) + sweep * uSweep;\n fragColor = vec4(col, 1.0);\n}`,\n ),\n presets: [\n { name: \"Spotify\", values: { uShadow: [0.07, 0.1, 0.35], uHighlight: [0.12, 0.84, 0.38] } },\n { name: \"Newsprint\", values: { uShadow: [0.1, 0.1, 0.1], uHighlight: [0.96, 0.94, 0.88] } },\n ],\n};\n\nexport const imagePixelate: ShaderEffect = {\n kind: \"shader\",\n id: \"image-pixelate\",\n name: \"Pixel reveal\",\n description: \"An image resolving from big blocks to full detail, then back, in a loop.\",\n category: \"image\",\n tags: [\"image\", \"reveal\", \"transition\", \"8-bit\"],\n loop: 4,\n source: glsl(\n `// Pixel reveal: an image resolving from blocks to full detail and back.\nuniform sampler2D uImage; // @control filter=nearest wrap=clamp default=${SAMPLE_IMAGES.landscape} label=\"Image\"\nuniform float uMaxBlock; // @control min=4 max=128 default=48 label=\"Largest block (px)\"\nuniform bool uAnimate; // @control default=true label=\"Animate\"\nuniform float uProgress; // @control min=0 max=1 default=1 label=\"Detail (when still)\"`,\n PICTURE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n float k = uAnimate ? 0.5 - 0.5 * cos(iTime * 6.28318 / 4.0) : uProgress;\n float block = max(1.0, floor(mix(uMaxBlock, 1.0, k)));\n vec2 cell = (floor(fragCoord / block) + 0.5) * block;\n vec3 col = picture(uImage, cell / iResolution.xy);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const imageHalftone: ShaderEffect = {\n kind: \"shader\",\n id: \"image-halftone\",\n name: \"Halftone\",\n description: \"An image printed as rotated halftone dots, breathing slightly.\",\n category: \"image\",\n tags: [\"image\", \"print\", \"comic\", \"pop-art\"],\n source: glsl(\n `// Halftone: an image as rotated print dots.\nuniform sampler2D uImage; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.landscape} label=\"Image\"\nuniform vec3 uInk; // @control color default=#111827 label=\"Ink\"\nuniform vec3 uPaper; // @control color default=#FEF3C7 label=\"Paper\"\nuniform float uSpacing; // @control min=3 max=30 default=8 label=\"Dot spacing (px)\"\nuniform float uAngle; // @control min=0 max=90 default=45 label=\"Screen angle (°)\"`,\n PICTURE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n float a = radians(uAngle);\n mat2 r = mat2(cos(a), sin(a), -sin(a), cos(a));\n vec2 q = r * fragCoord / uSpacing;\n vec2 cell = floor(q) + 0.5;\n vec2 centre = transpose(r) * cell * uSpacing;\n float l = dot(picture(uImage, centre / iResolution.xy), vec3(0.2126, 0.7152, 0.0722));\n float radius = sqrt(1.0 - l) * 0.62 * (0.95 + 0.05 * sin(iTime * 2.0));\n float d = length(q - cell);\n float ink = smoothstep(radius + 0.06, radius - 0.06, d);\n fragColor = vec4(mix(uPaper, uInk, ink), 1.0);\n}`,\n ),\n};\n\nexport const crt: ShaderEffect = {\n kind: \"shader\",\n id: \"crt\",\n name: \"CRT screen\",\n description: \"An image on a curved CRT: scanlines, shadow mask, bloom and flicker.\",\n category: \"image\",\n tags: [\"image\", \"retro\", \"screen\", \"arcade\"],\n source: glsl(\n `// CRT screen: an image on a curved tube with scanlines and a shadow mask.\nuniform sampler2D uImage; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.landscape} label=\"Image\"\nuniform float uCurve; // @control min=0 max=0.5 default=0.15 label=\"Curvature\"\nuniform float uScanlines; // @control min=0 max=1 default=0.5 label=\"Scanlines\"\nuniform float uMask; // @control min=0 max=1 default=0.35 label=\"Shadow mask\"\nuniform float uFlicker; // @control min=0 max=0.2 default=0.03 label=\"Flicker\"`,\n HASH,\n PICTURE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy * 2.0 - 1.0;\n uv *= 1.0 + uCurve * dot(uv.yx, uv.yx) * 0.5;\n vec2 st = uv * 0.5 + 0.5;\n if (st.x < 0.0 || st.x > 1.0 || st.y < 0.0 || st.y > 1.0) {\n fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n vec3 col = picture(uImage, st);\n col += 0.25 * picture(uImage, st + vec2(0.003, 0.0)) * col;\n float scan = 1.0 - uScanlines * 0.5 * (1.0 - cos(st.y * iResolution.y * 3.14159));\n float m = mod(fragCoord.x, 3.0);\n vec3 mask = mix(vec3(1.0), vec3(m < 1.0 ? 1.2 : 0.8, m >= 1.0 && m < 2.0 ? 1.2 : 0.8, m >= 2.0 ? 1.2 : 0.8), uMask);\n col *= scan * mask;\n col *= 1.0 - uFlicker * hash12(vec2(floor(iTime * 24.0), 0.0));\n col *= smoothstep(1.0, 0.7, max(abs(uv.x), abs(uv.y)) * 0.98 + 0.02 * length(uv));\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const filmGrain: ShaderEffect = {\n kind: \"shader\",\n id: \"film-look\",\n name: \"Film look\",\n description: \"An image graded like film: grain, gate weave, halation and vignette.\",\n category: \"image\",\n tags: [\"image\", \"cinematic\", \"grain\", \"vintage\"],\n source: glsl(\n `// Film look: grain, gate weave, halation and vignette.\nuniform sampler2D uImage; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.landscape} label=\"Image\"\nuniform float uGrain; // @control min=0 max=0.3 default=0.08 label=\"Grain\"\nuniform float uWeave; // @control min=0 max=0.01 default=0.0015 label=\"Gate weave\"\nuniform float uHalation; // @control min=0 max=1 default=0.3 label=\"Halation\"\nuniform float uVignette; // @control min=0 max=1 default=0.45 label=\"Vignette\"\nuniform vec3 uTint; // @control color default=#FFF1DC label=\"Print tint\"`,\n HASH,\n NOISE,\n PICTURE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy;\n float frame = floor(iTime * 24.0);\n uv += uWeave * (vec2(vnoise(vec2(frame * 0.3, 0.0)), vnoise(vec2(0.0, frame * 0.3))) - 0.5);\n vec3 col = picture(uImage, uv);\n vec3 blur = (picture(uImage, uv + vec2(0.006, 0.0)) + picture(uImage, uv - vec2(0.006, 0.0)) +\n picture(uImage, uv + vec2(0.0, 0.006)) + picture(uImage, uv - vec2(0.0, 0.006))) * 0.25;\n float bright = smoothstep(0.6, 1.0, dot(blur, vec3(0.333)));\n col += vec3(1.0, 0.3, 0.1) * bright * uHalation * 0.5;\n col *= uTint;\n col += (hash12(fragCoord + frame * 31.7) - 0.5) * uGrain;\n col *= 1.0 - uVignette * smoothstep(0.3, 0.9, length(uv - 0.5) * 1.3);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nconst TRANSITIONS: { type: TransitionType; id: string; name: string; description: string }[] = [\n { type: \"linearWipe\", id: \"wipe\", name: \"Wipe\", description: \"A soft-edged wipe from one image to the next.\" },\n { type: \"radialIris\", id: \"iris\", name: \"Iris\", description: \"A circle opening from the centre onto the next image.\" },\n { type: \"blockDissolve\", id: \"block-dissolve\", name: \"Block dissolve\", description: \"Random blocks switching to the next image.\" },\n { type: \"gridWipe\", id: \"grid-wipe\", name: \"Grid wipe\", description: \"A diagonal cascade of cells revealing the next image.\" },\n { type: \"glassWipe\", id: \"glass-wipe\", name: \"Glass wipe\", description: \"A refracting glass edge sweeping across.\" },\n { type: \"twister\", id: \"twister\", name: \"Twister\", description: \"A swirl that twists one image into the next.\" },\n { type: \"lightLeak\", id: \"light-leak\", name: \"Light leak\", description: \"A warm flare of light burning through to the next image.\" },\n { type: \"crossZoom\", id: \"cross-zoom\", name: \"Cross zoom\", description: \"A zoom blur punching through to the next image.\" },\n];\n\n/** The transitions (see `getTransitionGLSL`) as looping effects between two images. */\nexport const transitions: ShaderEffect[] = TRANSITIONS.map(({ type, id, name, description }) => ({\n kind: \"shader\",\n id: `transition-${id}`,\n name,\n description: `${description} Loops back and forth; or turn Animate off and set Progress.`,\n category: \"transition\",\n tags: [\"transition\", \"image\", \"slideshow\"],\n loop: 4,\n source: glsl(\n `// ${name} transition between two images. Progress runs 0 → 1 → 0 when animated.\nuniform sampler2D uFrom; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.landscape} label=\"From image\"\nuniform sampler2D uTo; // @control filter=linear wrap=clamp default=${SAMPLE_IMAGES.city} label=\"To image\"\nuniform bool uAnimate; // @control default=true label=\"Animate\"\nuniform float uProgress; // @control min=0 max=1 default=0.5 label=\"Progress (when still)\"`,\n getTransitionGLSL(type),\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy;\n float p = uAnimate ? smoothstep(0.1, 0.9, 0.5 - 0.5 * cos(iTime * 6.28318 / 4.0)) : uProgress;\n fragColor = vec4(flair_transition(uFrom, uTo, uv, p).rgb, 1.0);\n}`,\n ),\n}));\n","import { FBM, glsl, HASH, NOISE, ROTATE } from \"../glsl.js\";\nimport type { ShaderEffect } from \"../types.js\";\n\nexport const bokeh: ShaderEffect = {\n kind: \"shader\",\n id: \"bokeh\",\n name: \"Bokeh\",\n description: \"Out-of-focus city lights drifting softly.\",\n category: \"light\",\n tags: [\"background\", \"festive\", \"dreamy\", \"night\"],\n source: glsl(\n `// Bokeh: soft out-of-focus lights drifting.\nuniform vec3 uBackground; // @control color default=#0B1026 label=\"Background\"\nuniform vec3 uWarm; // @control color default=#FFC56E label=\"Warm light\"\nuniform vec3 uCool; // @control color default=#6EC8FF label=\"Cool light\"\nuniform int uCount; // @control min=4 max=60 default=30 label=\"Lights\"\nuniform float uSize; // @control min=0.02 max=0.25 default=0.08 label=\"Size\"\nuniform float uSpeed; // @control min=0 max=1 default=0.15 label=\"Drift\"`,\n HASH,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = fragCoord / iResolution.y;\n float aspect = iResolution.x / iResolution.y;\n vec3 col = uBackground * (0.7 + 0.3 * fragCoord.y / iResolution.y);\n for (int i = 0; i < 60; i++) {\n if (i >= uCount) break;\n float fi = float(i);\n vec2 h = hash22(vec2(fi, 3.1));\n float depth = hash12(vec2(fi, 9.7));\n vec2 c = vec2(fract(h.x + iTime * uSpeed * (0.2 + depth) * 0.1) * (aspect + 0.4) - 0.2, h.y);\n c.y += 0.03 * sin(iTime * 0.5 + fi);\n float r = uSize * (0.5 + depth);\n float d = length(p - c);\n float disc = smoothstep(r, r * 0.85, d) * (0.6 + 0.4 * smoothstep(r * 0.4, r, d));\n vec3 light = mix(uWarm, uCool, step(0.5, hash12(vec2(fi, 1.3))));\n col += light * disc * (0.15 + 0.25 * (1.0 - depth));\n }\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const godRays: ShaderEffect = {\n kind: \"shader\",\n id: \"god-rays\",\n name: \"God rays\",\n description: \"Shafts of light fanning down through haze.\",\n category: \"light\",\n tags: [\"background\", \"hero\", \"heavenly\", \"spotlight\"],\n source: glsl(\n `// God rays: shafts of light fanning through haze.\nuniform vec3 uBackground; // @control color default=#0C0A09 label=\"Background\"\nuniform vec3 uLight; // @control color default=#FDE68A label=\"Light\"\nuniform vec2 uSource; // @control min=-1 max=1 default=0,0.6 label=\"Source\"\nuniform float uRays; // @control min=4 max=60 default=18 label=\"Rays\"\nuniform float uSpeed; // @control min=0 max=2 default=0.3 label=\"Speed\"\nuniform float uStrength; // @control min=0 max=2 default=1 label=\"Strength\"`,\n HASH,\n NOISE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;\n vec2 d = p - uSource * vec2(iResolution.x / iResolution.y, 1.0) * 0.5;\n float a = atan(d.x, -d.y);\n float r = length(d);\n float t = iTime * uSpeed;\n float rays = vnoise(vec2(a * uRays, t)) * 0.6 + vnoise(vec2(a * uRays * 2.3, -t * 1.3)) * 0.4;\n rays = pow(rays, 2.0) * smoothstep(1.6, 0.0, r);\n float glow = exp(-r * 4.0);\n vec3 col = uBackground + uLight * (rays * 0.9 + glow * 0.8) * uStrength;\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const sparkles: ShaderEffect = {\n kind: \"shader\",\n id: \"sparkles\",\n name: \"Sparkles\",\n description: \"Four-pointed glints twinkling on and off across the frame.\",\n category: \"light\",\n tags: [\"overlay\", \"magic\", \"celebration\", \"premium\"],\n source: glsl(\n `// Sparkles: four-pointed glints twinkling across the frame.\nuniform vec3 uBackground; // @control color default=#1E1B4B label=\"Background\"\nuniform vec3 uSparkle; // @control color default=#FFFFFF label=\"Sparkle\"\nuniform float uDensity; // @control min=2 max=30 default=10 label=\"Density\"\nuniform float uSize; // @control min=0.05 max=0.5 default=0.35 label=\"Size\"\nuniform float uSpeed; // @control min=0 max=4 default=1 label=\"Twinkle speed\"`,\n HASH,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = fragCoord / iResolution.y * uDensity;\n vec3 col = uBackground;\n for (int layer = 0; layer < 2; layer++) {\n vec2 q = p * (1.0 + float(layer) * 0.6) + float(layer) * 7.3;\n vec2 id = floor(q);\n vec2 f = fract(q) - 0.5;\n vec2 o = hash22(id) - 0.5;\n vec2 d = f - o * 0.6;\n float phase = hash12(id + 4.0) * 6.28318;\n float tw = pow(max(0.0, sin(iTime * uSpeed * 2.0 + phase)), 4.0);\n float r = length(d);\n float rays = max(0.0, 1.0 - abs(d.x * d.y) * 3000.0);\n float core = 0.01 / (r + 0.01);\n float star = (rays * 0.8 + core) * smoothstep(uSize, 0.0, r) * tw;\n col += uSparkle * star;\n }\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const neonRipple: ShaderEffect = {\n kind: \"shader\",\n id: \"neon-ripple\",\n name: \"Neon ripple\",\n description: \"Glowing neon rings radiating out from the pointer or the centre.\",\n category: \"light\",\n tags: [\"interactive\", \"glow\", \"music\", \"pulse\"],\n loop: 2,\n source: glsl(\n `// Neon ripple: glowing rings radiating from the pointer (or the centre).\nuniform vec3 uBackground; // @control color default=#09090B label=\"Background\"\nuniform vec3 uNeon; // @control color default=#FF2BD6 label=\"Neon\"\nuniform float uRings; // @control min=1 max=10 default=4 label=\"Rings\"\nuniform float uWidth; // @control min=0.002 max=0.05 default=0.01 label=\"Width\"\nuniform float uGlow; // @control min=0 max=3 default=1 label=\"Glow\"`,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 centre = iMouse.z > 0.0 ? iMouse.xy : 0.5 * iResolution.xy;\n float r = length(fragCoord - centre) / iResolution.y;\n float phase = fract(r * uRings - iTime * 0.5);\n float ringDist = min(phase, 1.0 - phase) / uRings;\n float fade = smoothstep(1.2, 0.0, r);\n float core = smoothstep(uWidth, 0.0, ringDist);\n float glow = uWidth * 2.0 / (ringDist + uWidth) * 0.25 * uGlow;\n vec3 col = uBackground + uNeon * (core + glow) * fade;\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const starfield: ShaderEffect = {\n kind: \"shader\",\n id: \"starfield\",\n name: \"Warp starfield\",\n description: \"Flying through a field of stars, from cruising to warp speed.\",\n category: \"space\",\n tags: [\"background\", \"space\", \"speed\", \"sci-fi\"],\n source: glsl(\n `// Warp starfield: flying through layers of stars.\nuniform vec3 uBackground; // @control color default=#000005 label=\"Background\"\nuniform vec3 uStar; // @control color default=#E0E7FF label=\"Star\"\nuniform float uSpeed; // @control min=0 max=4 default=0.6 label=\"Speed\"\nuniform float uStreak; // @control min=0 max=1 default=0.3 label=\"Streak\"\nuniform int uLayers; // @control min=1 max=8 default=5 label=\"Layers\"`,\n HASH,\n ROTATE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;\n vec3 col = uBackground;\n float n = float(uLayers);\n for (int i = 0; i < 8; i++) {\n if (i >= uLayers) break;\n float depth = fract(float(i) / n + iTime * uSpeed * 0.1);\n float scale = mix(20.0, 0.5, depth);\n float fade = depth * smoothstep(1.0, 0.85, depth);\n vec2 q = rot(float(i) * 1.7) * p * scale + float(i) * 13.1;\n vec2 id = floor(q);\n vec2 f = fract(q) - 0.5;\n vec2 o = hash22(id) - 0.5;\n vec2 d = f - o * 0.8;\n vec2 dir = normalize(p + 1e-4);\n float along = dot(d, dir);\n float across = length(d - dir * along);\n float len = 0.02 + uStreak * depth * 0.4;\n float star = smoothstep(0.03, 0.0, across) * smoothstep(len, 0.0, abs(along));\n star *= step(0.6, hash12(id + 2.0));\n col += uStar * star * fade * 1.5;\n }\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const nebula: ShaderEffect = {\n kind: \"shader\",\n id: \"nebula\",\n name: \"Nebula\",\n description: \"Glowing gas clouds and stars drifting in deep space.\",\n category: \"space\",\n tags: [\"background\", \"space\", \"cosmic\", \"hero\"],\n source: glsl(\n `// Nebula: glowing gas clouds over a field of stars.\nuniform vec3 uGasA; // @control color default=#7C3AED label=\"Gas A\"\nuniform vec3 uGasB; // @control color default=#EC4899 label=\"Gas B\"\nuniform vec3 uDeep; // @control color default=#020010 label=\"Deep space\"\nuniform float uSpeed; // @control min=0 max=1 default=0.05 label=\"Drift\"\nuniform float uDensity; // @control min=0 max=2 default=1 label=\"Density\"`,\n HASH,\n NOISE,\n FBM,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = fragCoord / iResolution.y * 2.0;\n float t = iTime * uSpeed;\n vec2 q = vec2(fbm(p + t, 5), fbm(p - t + 3.3, 5));\n float gas = fbm(p * 1.3 + 2.5 * q, 6);\n float dust = smoothstep(0.45, 0.75, fbm(p * 3.0 - q, 5));\n vec3 col = uDeep;\n col += uGasA * smoothstep(0.35, 0.8, gas) * uDensity;\n col += uGasB * smoothstep(0.5, 0.9, gas * q.x * 1.6) * uDensity;\n col *= 1.0 - 0.6 * dust;\n float star = step(0.996, hash12(floor(fragCoord)));\n float bright = step(0.9993, hash12(floor(fragCoord * 0.5) + 7.0));\n col += vec3(star * 0.7 + bright * (0.8 + 0.2 * sin(iTime * 4.0 + fragCoord.x)));\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const blackHole: ShaderEffect = {\n kind: \"shader\",\n id: \"event-horizon\",\n name: \"Event horizon\",\n description: \"A glowing accretion disc swirling into a black hole.\",\n category: \"space\",\n tags: [\"space\", \"dramatic\", \"vortex\", \"hero\"],\n source: glsl(\n `// Event horizon: an accretion disc swirling into a black hole.\nuniform vec3 uHot; // @control color default=#FFE4B5 label=\"Hot\"\nuniform vec3 uDisc; // @control color default=#FF6A00 label=\"Disc\"\nuniform float uRadius; // @control min=0.05 max=0.4 default=0.15 label=\"Horizon\"\nuniform float uSpin; // @control min=0 max=4 default=1 label=\"Spin\"`,\n HASH,\n NOISE,\n FBM,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;\n p.y *= 2.2;\n float r = length(p);\n float a = atan(p.y, p.x);\n float swirl = a + uSpin * iTime * 0.5 + 1.5 / (r + 0.05);\n float streaks = fbm(vec2(swirl * 3.0, r * 8.0), 5);\n float disc = smoothstep(uRadius, uRadius * 1.6, r) * smoothstep(1.0, uRadius * 1.6, r);\n vec3 col = mix(uDisc, uHot, smoothstep(0.5, 0.9, streaks) * smoothstep(0.6, 0.1, r));\n col *= disc * (0.4 + 1.2 * streaks);\n col += uHot * 0.6 * exp(-abs(r - uRadius * 1.05) * 60.0);\n col *= smoothstep(uRadius * 0.95, uRadius * 1.05, r);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const lightRibbons: ShaderEffect = {\n kind: \"shader\",\n id: \"light-ribbons\",\n name: \"Light ribbons\",\n description: \"A bundle of thin iridescent light strands weaving across a dark frame.\",\n category: \"light\",\n tags: [\"background\", \"hero\", \"tech\", \"iridescent\", \"flow\"],\n source: glsl(\n `// Light ribbons: thin glowing strands weaving across the frame, shading from one colour to the next.\nuniform vec3 uBackground; // @control color default=#05060D label=\"Background\"\nuniform vec3 uColorA; // @control color default=#4FD1FF label=\"Colour A\"\nuniform vec3 uColorB; // @control color default=#B06BFF label=\"Colour B\"\nuniform vec3 uColorC; // @control color default=#FF7AC6 label=\"Colour C\"\nuniform float uCount; // @control min=2 max=24 default=12 step=1 label=\"Strands\"\nuniform float uSpread; // @control min=0.02 max=0.6 default=0.18 label=\"Spread\"\nuniform float uWave; // @control min=0 max=0.5 default=0.22 label=\"Wave\"\nuniform float uTilt; // @control min=-1 max=1 default=0.3 label=\"Tilt\"\nuniform float uSpeed; // @control min=0 max=2 default=0.5 label=\"Speed\"\nuniform float uGlow; // @control min=0 max=2 default=1 label=\"Glow\"`,\n `// Three colours round a loop, so the shading drifts without a seam.\nvec3 shade(float g) {\n g = fract(g) * 3.0;\n return g < 1.0 ? mix(uColorA, uColorB, g) : g < 2.0 ? mix(uColorB, uColorC, g - 1.0) : mix(uColorC, uColorA, g - 2.0);\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;\n float px = 1.0 / iResolution.y;\n float t = iTime * uSpeed;\n float halfWidth = 0.5 * iResolution.x / iResolution.y;\n float x = p.x;\n float y = p.y - x * uTilt;\n // The bundle pinches and opens along its length, like ribbons twisting.\n float pinch = 0.35 + 0.65 * abs(sin(x * 1.3 - t * 0.7));\n vec3 light = vec3(0.0);\n for (int i = 0; i < 24; i++) {\n if (float(i) >= uCount) break;\n float f = float(i) / max(uCount - 1.0, 1.0) - 0.5;\n float centre = f * uSpread * pinch\n + uWave * (0.6 * sin(x * 1.7 + t + f * 2.0) + 0.3 * sin(x * 3.3 - t * 1.3 + f * 5.0));\n float d = abs(y - centre);\n float core = 1.0 - smoothstep(0.0, px * 1.5, d);\n float glow = uGlow * 0.006 / (d + 0.006);\n light += shade(f * 0.6 + x * 0.12 + t * 0.05) * (core * 0.9 + glow * 0.4);\n }\n light *= 1.0 - 0.75 * pow(min(abs(x) / halfWidth, 1.0), 2.0);\n fragColor = vec4(uBackground + (1.0 - exp(-light)), 1.0);\n}`,\n ),\n presets: [\n { name: \"Gold\", values: { uBackground: [0.03, 0.03, 0.04], uColorA: [1, 0.78, 0.4], uColorB: [0.75, 0.5, 0.2], uColorC: [1, 0.93, 0.75], uCount: 8, uSpread: 0.4 } },\n { name: \"Aurora\", values: { uColorA: [0.2, 1, 0.7], uColorB: [0.2, 0.6, 1], uColorC: [0.6, 0.3, 1], uTilt: -0.2, uWave: 0.3 } },\n ],\n};\n","import { FBM, glsl, HASH, NOISE, PALETTE } from \"../glsl.js\";\nimport type { ShaderEffect } from \"../types.js\";\n\nexport const marble: ShaderEffect = {\n kind: \"shader\",\n id: \"marble\",\n name: \"Liquid marble\",\n description: \"Veined marble swirling like ink in water (domain-warped noise).\",\n category: \"organic\",\n tags: [\"background\", \"ink\", \"liquid\", \"luxury\"],\n source: glsl(\n `// Liquid marble: domain-warped noise swirling like ink in water.\nuniform vec3 uStone; // @control color default=#F5F1E8 label=\"Stone\"\nuniform vec3 uVein; // @control color default=#1F2937 label=\"Vein\"\nuniform vec3 uAccent; // @control color default=#B08D57 label=\"Accent\"\nuniform float uSpeed; // @control min=0 max=1 default=0.15 label=\"Speed\"\nuniform float uScale; // @control min=0.5 max=6 default=2.5 label=\"Scale\"\nuniform float uWarp; // @control min=0 max=8 default=4 label=\"Warp\"`,\n HASH,\n NOISE,\n FBM,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = fragCoord / iResolution.y * uScale;\n float t = iTime * uSpeed;\n vec2 q = vec2(fbm(p + vec2(0.0, t), 5), fbm(p + vec2(5.2, 1.3 - t), 5));\n vec2 r = vec2(fbm(p + uWarp * q + vec2(1.7, 9.2) + 0.3 * t, 5), fbm(p + uWarp * q + vec2(8.3, 2.8), 5));\n float f = fbm(p + uWarp * r, 5);\n float vein = 1.0 - smoothstep(0.0, 0.06, abs(sin(f * 12.0 + r.x * 6.0)));\n vec3 col = mix(uStone, uStone * 0.85, length(q) * 0.6);\n col = mix(col, uAccent, smoothstep(0.55, 0.9, r.y) * 0.5);\n col = mix(col, uVein, vein * 0.85);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n presets: [\n { name: \"Nero\", values: { uStone: [0.08, 0.08, 0.09], uVein: [0.9, 0.88, 0.82], uAccent: [0.7, 0.55, 0.3] } },\n { name: \"Jade\", values: { uStone: [0.18, 0.45, 0.35], uVein: [0.85, 0.95, 0.88], uAccent: [0.05, 0.2, 0.15] } },\n ],\n};\n\nexport const smoke: ShaderEffect = {\n kind: \"shader\",\n id: \"smoke\",\n name: \"Smoke\",\n description: \"Billowing smoke or cloud drifting upwards.\",\n category: \"organic\",\n tags: [\"background\", \"atmosphere\", \"cloud\", \"mist\"],\n source: glsl(\n `// Smoke: billowing fractal noise drifting upwards.\nuniform vec3 uBackground; // @control color default=#0B0F19 label=\"Background\"\nuniform vec3 uSmoke; // @control color default=#CBD5E1 label=\"Smoke\"\nuniform float uSpeed; // @control min=0 max=2 default=0.3 label=\"Speed\"\nuniform float uDensity; // @control min=0 max=2 default=1 label=\"Density\"\nuniform int uDetail; // @control min=1 max=8 default=6 label=\"Detail\"`,\n HASH,\n NOISE,\n FBM,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = fragCoord / iResolution.y * 3.0;\n float t = iTime * uSpeed;\n p.y -= t;\n float n = fbm(p + fbm(p + vec2(t * 0.3, 0.0), uDetail), uDetail);\n float body = smoothstep(0.35, 0.85, n) * uDensity;\n float fade = smoothstep(0.0, 0.7, fragCoord.y / iResolution.y + 0.2);\n vec3 col = mix(uBackground, uSmoke, clamp(body * fade, 0.0, 1.0));\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const lavaLamp: ShaderEffect = {\n kind: \"shader\",\n id: \"lava-lamp\",\n name: \"Lava lamp\",\n description: \"Soft metaballs merging and parting as they rise and fall.\",\n category: \"organic\",\n tags: [\"background\", \"playful\", \"blobs\", \"retro\"],\n source: glsl(\n `// Lava lamp: metaballs merging as they rise and fall.\nuniform vec3 uBackground; // @control color default=#1A0B2E label=\"Background\"\nuniform vec3 uBlobA; // @control color default=#FF5E8A label=\"Blob A\"\nuniform vec3 uBlobB; // @control color default=#FFB347 label=\"Blob B\"\nuniform int uCount; // @control min=2 max=12 default=7 label=\"Blobs\"\nuniform float uSpeed; // @control min=0 max=2 default=0.5 label=\"Speed\"\nuniform float uSize; // @control min=0.02 max=0.3 default=0.12 label=\"Size\"`,\n HASH,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = fragCoord / iResolution.y;\n float aspect = iResolution.x / iResolution.y;\n float t = iTime * uSpeed;\n float field = 0.0;\n float tint = 0.0;\n for (int i = 0; i < 12; i++) {\n if (i >= uCount) break;\n float fi = float(i);\n vec2 seed = hash22(vec2(fi, 7.0));\n vec2 c = vec2(seed.x * aspect, 0.5 + 0.45 * sin(t * (0.4 + seed.y) + fi * 2.1));\n c.x += 0.1 * sin(t * 0.7 + fi);\n float r = uSize * (0.7 + 0.6 * seed.y);\n float k = r * r / dot(p - c, p - c);\n field += k;\n tint += k * seed.x;\n }\n float inside = smoothstep(0.9, 1.1, field);\n vec3 blob = mix(uBlobA, uBlobB, clamp(tint / max(field, 1e-3), 0.0, 1.0));\n blob *= 0.85 + 0.15 * smoothstep(1.0, 3.0, field);\n vec3 col = mix(uBackground, blob, inside);\n col += blob * 0.15 * smoothstep(0.3, 0.9, field) * (1.0 - inside);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const plasma: ShaderEffect = {\n kind: \"shader\",\n id: \"plasma\",\n name: \"Plasma\",\n description: \"The demoscene classic: interfering sine waves through a colour palette.\",\n category: \"organic\",\n tags: [\"background\", \"retro\", \"psychedelic\", \"loop\"],\n loop: 6.28318,\n source: glsl(\n `// Plasma: interfering sine waves through a cosine palette.\nuniform float uScale; // @control min=1 max=20 default=8 label=\"Scale\"\nuniform float uShift; // @control min=0 max=1 default=0 label=\"Hue shift\"\nuniform vec3 uPhase; // @control min=0 max=1 default=0,0.33,0.67 label=\"Palette phase\"`,\n PALETTE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y * uScale;\n float t = iTime;\n float v = sin(p.x + t);\n v += sin((p.y + t) * 0.5);\n v += sin((p.x + p.y + t) * 0.5);\n vec2 c = p + vec2(sin(t * 0.5), cos(t * 0.5)) * uScale * 0.3;\n v += sin(sqrt(dot(c, c) + 1.0) + t);\n vec3 col = palette(v * 0.25 + uShift, vec3(0.5), vec3(0.5), vec3(1.0), uPhase);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const caustics: ShaderEffect = {\n kind: \"shader\",\n id: \"caustics\",\n name: \"Caustics\",\n description: \"Light dancing on the floor of a swimming pool.\",\n category: \"organic\",\n tags: [\"background\", \"water\", \"summer\", \"calm\"],\n source: glsl(\n `// Caustics: light dancing on the floor of a pool.\nuniform vec3 uWater; // @control color default=#0369A1 label=\"Water\"\nuniform vec3 uLight; // @control color default=#E0F2FE label=\"Light\"\nuniform float uSpeed; // @control min=0 max=2 default=0.5 label=\"Speed\"\nuniform float uScale; // @control min=1 max=10 default=4 label=\"Scale\"\nuniform float uBright; // @control min=0 max=2 default=1 label=\"Brightness\"`,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n // After Dave Hoskins' \"Tileable water caustic\".\n vec2 uv = fragCoord / iResolution.y * uScale * 0.25;\n float t = iTime * uSpeed * 0.5 + 23.0;\n vec2 p = mod(uv * 6.28318, 6.28318) - 250.0;\n vec2 i = p;\n float c = 1.0;\n float inten = 0.005;\n for (int n = 0; n < 5; n++) {\n float tn = t * (1.0 - 3.5 / float(n + 1));\n i = p + vec2(cos(tn - i.x) + sin(tn + i.y), sin(tn - i.y) + cos(tn + i.x));\n c += 1.0 / length(vec2(p.x / (sin(i.x + tn) / inten), p.y / (cos(i.y + tn) / inten)));\n }\n c /= 5.0;\n c = 1.17 - pow(c, 1.4);\n float light = pow(abs(c), 8.0) * uBright;\n vec3 col = uWater + uLight * clamp(light, 0.0, 1.5);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const flames: ShaderEffect = {\n kind: \"shader\",\n id: \"flames\",\n name: \"Flames\",\n description: \"A wall of fire licking upwards from the bottom edge.\",\n category: \"organic\",\n tags: [\"fire\", \"energy\", \"hot\", \"overlay\"],\n source: glsl(\n `// Flames: a wall of fire licking upwards.\nuniform vec3 uHot; // @control color default=#FFF3B0 label=\"Hot\"\nuniform vec3 uMid; // @control color default=#FF7A00 label=\"Mid\"\nuniform vec3 uCool; // @control color default=#7A0000 label=\"Cool\"\nuniform float uSpeed; // @control min=0 max=3 default=1.2 label=\"Speed\"\nuniform float uHeight; // @control min=0.1 max=1.5 default=0.7 label=\"Height\"`,\n HASH,\n NOISE,\n FBM,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy;\n vec2 p = vec2(fragCoord.x / iResolution.y, uv.y);\n float t = iTime * uSpeed;\n float n = fbm(vec2(p.x * 4.0, p.y * 3.0 - t * 1.5), 5);\n float heat = (1.0 - uv.y / uHeight) + (n - 0.5) * 1.1;\n heat = clamp(heat, 0.0, 1.0);\n vec3 col = mix(vec3(0.0), uCool, smoothstep(0.05, 0.3, heat));\n col = mix(col, uMid, smoothstep(0.3, 0.6, heat));\n col = mix(col, uHot, smoothstep(0.6, 0.95, heat));\n fragColor = vec4(col, 1.0);\n}`,\n ),\n presets: [\n { name: \"Spirit\", values: { uHot: [0.85, 1, 1], uMid: [0.2, 0.6, 1], uCool: [0.05, 0.05, 0.4] } },\n { name: \"Toxic\", values: { uHot: [0.95, 1, 0.7], uMid: [0.4, 0.95, 0.2], uCool: [0.05, 0.25, 0.05] } },\n ],\n};\n","import { glsl, HASH, ROTATE } from \"../glsl.js\";\nimport type { ShaderEffect } from \"../types.js\";\n\nexport const dotWave: ShaderEffect = {\n kind: \"shader\",\n id: \"dot-wave\",\n name: \"Dot wave\",\n description: \"A halftone grid of dots swelling in a travelling wave.\",\n category: \"pattern\",\n tags: [\"background\", \"halftone\", \"tech\", \"minimal\"],\n loop: 4,\n source: glsl(\n `// Dot wave: a grid of dots swelling in a travelling wave.\nuniform vec3 uBackground; // @control color default=#0F172A label=\"Background\"\nuniform vec3 uDot; // @control color default=#38BDF8 label=\"Dot\"\nuniform float uSpacing; // @control min=8 max=64 default=22 label=\"Spacing (px)\"\nuniform float uWaves; // @control min=0.5 max=6 default=2 label=\"Waves\"\nuniform bool uRadial; // @control default=true label=\"Radial\"`,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 cell = floor(fragCoord / uSpacing);\n vec2 local = fract(fragCoord / uSpacing) - 0.5;\n vec2 centre = (cell + 0.5) * uSpacing;\n vec2 p = (centre - 0.5 * iResolution.xy) / iResolution.y;\n float d = uRadial ? length(p) : p.x + p.y * 0.3;\n float phase = d * uWaves * 6.28318 - iTime * 6.28318 / 4.0;\n float size = 0.1 + 0.32 * (0.5 + 0.5 * sin(phase));\n float aa = 1.5 / uSpacing;\n float disc = 1.0 - smoothstep(size - aa, size + aa, length(local));\n vec3 col = mix(uBackground, uDot * (0.6 + 0.4 * size / 0.42), disc);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const truchet: ShaderEffect = {\n kind: \"shader\",\n id: \"truchet\",\n name: \"Truchet flow\",\n description: \"Quarter-circle Truchet tiles forming endless winding paths, with light flowing along them.\",\n category: \"pattern\",\n tags: [\"background\", \"maze\", \"geometric\", \"tech\"],\n source: glsl(\n `// Truchet flow: winding quarter-circle tiles with light flowing along them.\nuniform vec3 uBackground; // @control color default=#111827 label=\"Background\"\nuniform vec3 uLine; // @control color default=#F472B6 label=\"Line\"\nuniform float uTiles; // @control min=3 max=30 default=10 label=\"Tiles\"\nuniform float uWidth; // @control min=0.02 max=0.3 default=0.1 label=\"Line width\"\nuniform float uSpeed; // @control min=0 max=3 default=1 label=\"Flow speed\"`,\n HASH,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = fragCoord / iResolution.y * uTiles;\n vec2 id = floor(p);\n vec2 f = fract(p) - 0.5;\n float flip = hash12(id) > 0.5 ? 1.0 : -1.0;\n f.x *= flip;\n vec2 c = f.x > -f.y ? vec2(0.5) : vec2(-0.5);\n vec2 q = f - c;\n float d = abs(length(q) - 0.5);\n float angle = atan(q.y, q.x);\n float checker = mod(id.x + id.y, 2.0) * 2.0 - 1.0;\n float flow = 0.5 + 0.5 * sin(angle * 4.0 * checker * flip + iTime * uSpeed * 4.0);\n float line = 1.0 - smoothstep(uWidth - 0.02, uWidth, d);\n vec3 col = mix(uBackground, uLine * (0.45 + 0.75 * flow), line);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const hexPulse: ShaderEffect = {\n kind: \"shader\",\n id: \"hex-pulse\",\n name: \"Hex pulse\",\n description: \"A honeycomb grid lighting up cell by cell in ripples.\",\n category: \"pattern\",\n tags: [\"background\", \"tech\", \"honeycomb\", \"sci-fi\"],\n source: glsl(\n `// Hex pulse: a honeycomb grid lighting up in ripples.\nuniform vec3 uBackground; // @control color default=#020617 label=\"Background\"\nuniform vec3 uEdge; // @control color default=#22D3EE label=\"Edge\"\nuniform vec3 uFill; // @control color default=#0E7490 label=\"Fill\"\nuniform float uCells; // @control min=3 max=40 default=12 label=\"Cells\"\nuniform float uSpeed; // @control min=0 max=3 default=1 label=\"Speed\"`,\n HASH,\n `vec4 hexCoords(vec2 p) {\n vec2 r = vec2(1.0, 1.7320508);\n vec2 h = r * 0.5;\n vec2 a = mod(p, r) - h;\n vec2 b = mod(p - h, r) - h;\n vec2 gv = dot(a, a) < dot(b, b) ? a : b;\n return vec4(gv, p - gv);\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y * uCells;\n vec4 h = hexCoords(p);\n vec2 gv = abs(h.xy);\n float edgeDist = 0.5 - max(dot(gv, normalize(vec2(1.0, 1.7320508))), gv.x);\n float ripple = 0.5 + 0.5 * sin(length(h.zw) * 0.6 - iTime * uSpeed * 3.0);\n float spark = step(0.92, hash12(h.zw + floor(iTime * uSpeed * 2.0)));\n float lit = clamp(pow(ripple, 6.0) + spark * 0.6, 0.0, 1.0);\n vec3 col = mix(uBackground, uFill, lit * smoothstep(0.0, 0.1, edgeDist));\n col = mix(col, uEdge, (1.0 - smoothstep(0.0, 0.04, edgeDist)) * (0.3 + 0.7 * ripple));\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const moire: ShaderEffect = {\n kind: \"shader\",\n id: \"moire\",\n name: \"Moiré rings\",\n description: \"Two sets of concentric rings sliding over each other into shimmering interference.\",\n category: \"pattern\",\n tags: [\"background\", \"op-art\", \"hypnotic\", \"minimal\"],\n source: glsl(\n `// Moiré rings: two ring sets interfering as they slide.\nuniform vec3 uInk; // @control color default=#111111 label=\"Ink\"\nuniform vec3 uPaper; // @control color default=#F5F5F0 label=\"Paper\"\nuniform float uRings; // @control min=10 max=200 default=80 label=\"Rings\"\nuniform float uDrift; // @control min=0 max=0.5 default=0.15 label=\"Drift\"`,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;\n vec2 o = uDrift * vec2(sin(iTime * 0.4), cos(iTime * 0.3));\n float a = sin(length(p - o) * uRings);\n float b = sin(length(p + o) * uRings);\n float v = smoothstep(-0.2, 0.2, a * b);\n fragColor = vec4(mix(uInk, uPaper, v), 1.0);\n}`,\n ),\n};\n\nexport const barberStripes: ShaderEffect = {\n kind: \"shader\",\n id: \"stripes\",\n name: \"Stripes\",\n description: \"Diagonal stripes marching across, for progress bars, banners and warnings.\",\n category: \"pattern\",\n tags: [\"progress\", \"banner\", \"warning\", \"loop\"],\n loop: 1,\n source: glsl(\n `// Stripes: diagonal stripes marching across.\nuniform vec3 uColorA; // @control color default=#FACC15 label=\"Colour A\"\nuniform vec3 uColorB; // @control color default=#18181B label=\"Colour B\"\nuniform float uWidth; // @control min=4 max=120 default=28 label=\"Stripe width (px)\"\nuniform float uAngle; // @control min=-90 max=90 default=45 label=\"Angle (°)\"\nuniform float uSoft; // @control min=0 max=1 default=0.05 label=\"Softness\"`,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n float a = radians(uAngle);\n float d = dot(fragCoord, vec2(cos(a), sin(a))) / (uWidth * 2.0);\n float s = fract(d - iTime);\n float edge = max(uSoft * 0.5, 0.5 / uWidth);\n float m = smoothstep(0.5 - edge, 0.5 + edge, s) - smoothstep(1.0 - edge, 1.0, s) + (1.0 - smoothstep(0.0, edge, s));\n fragColor = vec4(mix(uColorA, uColorB, clamp(m, 0.0, 1.0)), 1.0);\n}`,\n ),\n};\n\nexport const voronoi: ShaderEffect = {\n kind: \"shader\",\n id: \"voronoi\",\n name: \"Living cells\",\n description: \"Voronoi cells drifting and dividing, like a microscope slide.\",\n category: \"pattern\",\n tags: [\"background\", \"biology\", \"cells\", \"organic\"],\n source: glsl(\n `// Living cells: drifting Voronoi cells with glowing walls.\nuniform vec3 uBackground; // @control color default=#052E16 label=\"Background\"\nuniform vec3 uCell; // @control color default=#4ADE80 label=\"Cell\"\nuniform vec3 uWall; // @control color default=#DCFCE7 label=\"Wall\"\nuniform float uScale; // @control min=2 max=20 default=6 label=\"Scale\"\nuniform float uSpeed; // @control min=0 max=2 default=0.5 label=\"Speed\"`,\n HASH,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = fragCoord / iResolution.y * uScale;\n vec2 i = floor(p);\n vec2 f = fract(p);\n float d1 = 8.0;\n float d2 = 8.0;\n float shade = 0.0;\n for (int y = -1; y <= 1; y++) {\n for (int x = -1; x <= 1; x++) {\n vec2 g = vec2(float(x), float(y));\n vec2 o = hash22(i + g);\n o = 0.5 + 0.4 * sin(iTime * uSpeed + 6.28318 * o);\n float d = length(g + o - f);\n if (d < d1) { d2 = d1; d1 = d; shade = hash12(i + g); }\n else if (d < d2) { d2 = d; }\n }\n }\n float wall = 1.0 - smoothstep(0.0, 0.08, d2 - d1);\n vec3 col = mix(uBackground, uCell * (0.4 + 0.6 * shade), smoothstep(0.9, 0.1, d1));\n col = mix(col, uWall, wall);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const kaleidoscope: ShaderEffect = {\n kind: \"shader\",\n id: \"kaleidoscope\",\n name: \"Kaleidoscope\",\n description: \"Mirrored wedges of shifting colour turning around the centre.\",\n category: \"pattern\",\n tags: [\"psychedelic\", \"music\", \"symmetry\"],\n source: glsl(\n `// Kaleidoscope: mirrored wedges of shifting colour.\nuniform int uSegments; // @control min=2 max=16 default=8 label=\"Segments\"\nuniform float uZoom; // @control min=0.5 max=8 default=3 label=\"Zoom\"\nuniform float uSpeed; // @control min=0 max=2 default=0.4 label=\"Speed\"\nuniform vec3 uTint; // @control color default=#FFFFFF label=\"Tint\"`,\n ROTATE,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;\n float t = iTime * uSpeed;\n float n = float(uSegments);\n float a = atan(p.y, p.x) + t * 0.3;\n float r = length(p);\n float wedge = 6.28318 / n;\n a = mod(a, wedge);\n a = abs(a - wedge * 0.5);\n vec2 q = vec2(cos(a), sin(a)) * r * uZoom;\n q = rot(t * 0.2) * q + t;\n vec3 col = 0.5 + 0.5 * cos(vec3(0.0, 2.0, 4.0) + q.x * 2.0 + sin(q.y * 3.0) + t);\n col *= 0.6 + 0.4 * sin(q.x * 5.0) * sin(q.y * 5.0);\n col *= smoothstep(1.2, 0.2, r);\n fragColor = vec4(col * uTint, 1.0);\n}`,\n ),\n};\n\nexport const neonCircuit: ShaderEffect = {\n kind: \"shader\",\n id: \"neon-circuit\",\n name: \"Neon circuit\",\n description: \"Glowing neon traces routed up a circuit board, with pulses of light racing along them.\",\n category: \"pattern\",\n tags: [\"background\", \"neon\", \"circuit\", \"tech\", \"80s\", \"vaporwave\"],\n source: glsl(\n `// Neon circuit: glowing traces climbing a board in rounded jogs, with pulses running along them.\nuniform vec3 uBackground; // @control color default=#170A2E label=\"Background\"\nuniform vec3 uColorA; // @control color default=#FF5FA2 label=\"Trace A\"\nuniform vec3 uColorB; // @control color default=#43E5FF label=\"Trace B\"\nuniform vec3 uColorC; // @control color default=#FFD23F label=\"Trace C\"\nuniform vec3 uColorD; // @control color default=#9D7BFF label=\"Trace D\"\nuniform float uLanes; // @control min=4 max=40 default=14 label=\"Lanes\"\nuniform float uDensity; // @control min=0.1 max=1 default=0.7 label=\"Density\"\nuniform float uWidth; // @control min=0.04 max=0.4 default=0.16 label=\"Line width\"\nuniform float uGlow; // @control min=0 max=2 default=1 label=\"Glow\"\nuniform float uSpeed; // @control min=0 max=3 default=1 label=\"Pulse speed\"\nuniform float uPulses; // @control min=0 max=1 default=0.5 label=\"Pulses\"\nuniform float uScroll; // @control min=-2 max=2 default=0.4 label=\"Scroll\"\nuniform float uGrid; // @control min=0 max=1 default=0.3 label=\"Grid\"`,\n HASH,\n `// Each trace k owns lanes 3k..3k+2 and climbs in runs of RUN lanes, jogging\n// sideways between them on rounded corners, so traces never cross.\nconst float RUN = 2.5;\nconst float RADIUS = 0.35;\n\nfloat laneOf(float k, float j) {\n return 3.0 * k + floor(hash12(vec2(k, j) + 0.37) * 3.0) + 0.5;\n}\n\nvec3 traceColor(float k) {\n float h = hash12(vec2(k, 7.3));\n return h < 0.25 ? uColorA : h < 0.5 ? uColorB : h < 0.75 ? uColorC : uColorD;\n}\n\n// Distance to a quarter circle of RADIUS round c, in the quadrant whose signs are q.\nfloat arcDist(vec2 p, vec2 c, vec2 q) {\n vec2 d = p - c;\n return d.x * q.x >= 0.0 && d.y * q.y >= 0.0 ? abs(length(d) - RADIUS) : 1e5;\n}\n\n// Trace k's run j: distance from p to its climb (x) and how far up it p is (y), then\n// the same for its jog into run j + 1 (z, w), measured along the run.\nvec4 run(vec2 p, float k, float j) {\n float x0 = laneOf(k, j - 1.0);\n float x1 = laneOf(k, j);\n float x2 = laneOf(k, j + 1.0);\n float y0 = j * RUN;\n float y1 = y0 + RUN;\n float lo = y0 + (x0 == x1 ? 0.0 : RADIUS);\n float hi = y1 - (x2 == x1 ? 0.0 : RADIUS);\n vec4 r = vec4(length(p - vec2(x1, clamp(p.y, lo, hi))), p.y - y0, 1e5, 0.0);\n if (x2 != x1) {\n float sx = sign(x2 - x1);\n float h = length(p - vec2(clamp(p.x, min(x1, x2) + RADIUS, max(x1, x2) - RADIUS), y1));\n h = min(h, arcDist(p, vec2(x1 + sx * RADIUS, y1 - RADIUS), vec2(-sx, 1.0)));\n h = min(h, arcDist(p, vec2(x2 - sx * RADIUS, y1 + RADIUS), vec2(sx, -1.0)));\n r.zw = vec2(h, RUN + abs(p.x - x1));\n }\n return r;\n}\n\n// How bright a pulse is at s along run j of trace k: a bright head with a fading tail.\n// A pulse crosses one run per cycle and carries on into the next with the next cycle.\nfloat pulseAt(float k, float j, float s) {\n float cycle = iTime * uSpeed * 1.5 + hash12(vec2(k, 8.8));\n float behind = fract(cycle) * (RUN + abs(laneOf(k, j + 1.0) - laneOf(k, j))) - s;\n float lit = step(hash12(vec2(k, floor(cycle) - j)), uPulses);\n return lit * (behind >= 0.0 ? exp(-behind * 0.8) : exp(behind * 30.0));\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n float px = uLanes / iResolution.y;\n vec2 p = fragCoord * px;\n p.y += iTime * uScroll;\n\n vec2 g = abs(fract(p / 1.5) - 0.5);\n float grid = 1.0 - smoothstep(0.0, px * 1.5, (0.5 - max(g.x, g.y)) * 1.5);\n vec3 light = uColorD * 0.12 * uGrid * grid;\n\n float home = floor(p.x / 3.0);\n for (int i = -1; i <= 1; i++) {\n float k = home + float(i);\n if (hash12(vec2(k, 1.9)) > uDensity) continue;\n vec2 q = vec2(p.x, p.y + hash12(vec2(k, 4.1)) * RUN);\n float jq = floor(q.y / RUN);\n float w = uWidth * 0.5;\n // The trace's nearest point lights it; each piece's pulse lights only round that piece.\n float d = 1e5;\n float pulse = 0.0;\n for (int b = -1; b <= 1; b++) {\n float j = jq + float(b);\n vec4 r = run(q, k, j);\n d = min(d, min(r.x, r.z));\n pulse = max(pulse, pulseAt(k, j, r.y) * exp(-r.x / uWidth));\n if (r.z < 1e4) pulse = max(pulse, pulseAt(k, j, r.w) * exp(-r.z / uWidth));\n }\n float core = 1.0 - smoothstep(w - px, w + px, d);\n float glow = uGlow * (0.5 * exp(-d / uWidth) + 0.2 * exp(-d / (uWidth * 5.0)));\n vec3 c = traceColor(k);\n light += c * (core * 0.8 + glow + uGlow * pulse) + mix(c, vec3(1.0), 0.7) * core * pulse * 3.0;\n }\n fragColor = vec4(uBackground + (1.0 - exp(-light * 1.4)), 1.0);\n}`,\n ),\n presets: [\n { name: \"Mainframe\", values: { uBackground: [0.0, 0.04, 0.02], uColorA: [0.2, 1, 0.45], uColorB: [0.1, 0.75, 0.35], uColorC: [0.6, 1, 0.7], uColorD: [0.1, 0.5, 0.25] } },\n { name: \"Blueprint\", values: { uBackground: [0.02, 0.06, 0.16], uColorA: [0.35, 0.75, 1], uColorB: [0.6, 0.9, 1], uColorC: [1, 1, 1], uColorD: [0.25, 0.45, 0.9], uGlow: 0.6, uPulses: 0.3 } },\n { name: \"Dense\", values: { uLanes: 26, uDensity: 1, uWidth: 0.12, uPulses: 0.8 } },\n ],\n};\n","import { glsl, HASH } from \"../glsl.js\";\nimport type { ShaderEffect } from \"../types.js\";\n\nexport const synthwaveGrid: ShaderEffect = {\n kind: \"shader\",\n id: \"synthwave\",\n name: \"Synthwave\",\n description: \"A neon perspective grid racing towards a striped retro sun.\",\n category: \"retro\",\n tags: [\"background\", \"80s\", \"neon\", \"music\", \"loop\"],\n loop: 1,\n source: glsl(\n `// Synthwave: a neon grid racing towards a striped sun.\nuniform vec3 uSkyTop; // @control color default=#12002B label=\"Sky top\"\nuniform vec3 uSkyBottom; // @control color default=#7A1A6B label=\"Sky bottom\"\nuniform vec3 uSunTop; // @control color default=#FFE45E label=\"Sun top\"\nuniform vec3 uSunBottom; // @control color default=#FF3D7F label=\"Sun bottom\"\nuniform vec3 uGrid; // @control color default=#00F0FF label=\"Grid\"\nuniform float uHorizon; // @control min=0.2 max=0.7 default=0.42 label=\"Horizon\"`,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy;\n vec2 p = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;\n float horizon = uHorizon - 0.5;\n vec3 col;\n if (p.y > horizon) {\n float h = (p.y - horizon) / (0.5 - horizon);\n col = mix(uSkyBottom, uSkyTop, h);\n vec2 s = p - vec2(0.0, horizon + 0.18);\n float sun = smoothstep(0.2, 0.195, length(s));\n float bands = step(0.0, sin((s.y + 0.2) * 60.0 - 1.5)) + step(0.06, s.y);\n sun *= clamp(bands, 0.0, 1.0);\n col = mix(col, mix(uSunBottom, uSunTop, clamp(s.y / 0.2 * 0.5 + 0.5, 0.0, 1.0)), sun);\n col += uSunBottom * 0.25 * exp(-length(s) * 4.0);\n } else {\n float depth = (horizon - p.y);\n vec2 g = vec2(p.x / depth, 1.0 / depth);\n g.y += iTime * 2.0;\n vec2 grid = abs(fract(g * 0.5) - 0.5) / fwidth(g * 0.5);\n float line = 1.0 - clamp(min(grid.x, grid.y), 0.0, 1.0);\n float fade = smoothstep(0.0, 0.25, depth);\n col = mix(uSkyTop * 0.4, uSkyBottom * 0.3, uv.y);\n col += uGrid * line * fade + uGrid * 0.25 * exp(-depth * 20.0);\n }\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const tvStatic: ShaderEffect = {\n kind: \"shader\",\n id: \"tv-static\",\n name: \"TV static\",\n description: \"Analogue snow with rolling bars and scanlines.\",\n category: \"retro\",\n tags: [\"glitch\", \"analogue\", \"transition\", \"noise\"],\n source: glsl(\n `// TV static: analogue snow with a rolling bar and scanlines.\nuniform float uAmount; // @control min=0 max=1 default=0.9 label=\"Snow\"\nuniform float uScanlines; // @control min=0 max=1 default=0.35 label=\"Scanlines\"\nuniform float uRoll; // @control min=0 max=1 default=0.3 label=\"Rolling bar\"\nuniform vec3 uTint; // @control color default=#E6E6E6 label=\"Tint\"`,\n HASH,\n `void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 uv = fragCoord / iResolution.xy;\n float n = hash12(floor(fragCoord * 0.5) + floor(iTime * 30.0) * 17.31);\n float scan = 1.0 - uScanlines * 0.5 * (1.0 + sin(fragCoord.y * 3.14159));\n float bar = 1.0 + uRoll * 0.6 * smoothstep(0.15, 0.0, abs(fract(uv.y - iTime * 0.2) - 0.5) - 0.3);\n vec3 col = uTint * mix(0.5, n, uAmount) * scan * bar;\n col *= smoothstep(1.2, 0.4, length(uv - 0.5) * 1.4);\n fragColor = vec4(col, 1.0);\n}`,\n ),\n};\n\nexport const digitalRain: ShaderEffect = {\n kind: \"shader\",\n id: \"digital-rain\",\n name: \"Digital rain\",\n description: \"Columns of glyph-like characters raining down a terminal.\",\n category: \"retro\",\n tags: [\"hacker\", \"code\", \"tech\", \"cyber\"],\n source: glsl(\n `// Digital rain: glyph-like cells raining down in columns.\nuniform vec3 uBackground; // @control color default=#000000 label=\"Background\"\nuniform vec3 uGlyph; // @control color default=#22FF66 label=\"Glyph\"\nuniform float uCell; // @control min=6 max=40 default=14 label=\"Cell size (px)\"\nuniform float uSpeed; // @control min=0 max=4 default=1 label=\"Speed\"`,\n HASH,\n `float glyph(vec2 cell, vec2 f) {\n vec2 g = floor(f * vec2(3.0, 5.0));\n float on = step(0.45, hash12(g + cell * 13.7 + floor(iTime * 4.0 * hash12(cell))));\n vec2 inset = abs(fract(f * vec2(3.0, 5.0)) - 0.5);\n return on * step(max(inset.x, inset.y), 0.38);\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 q = fragCoord / uCell;\n vec2 cell = floor(q);\n vec2 f = fract(q);\n float col = cell.x;\n float speed = (0.5 + hash12(vec2(col, 1.0))) * uSpeed * 8.0;\n float offset = hash12(vec2(col, 2.0)) * 100.0;\n float head = fract((iTime * speed + offset) / 40.0) * (iResolution.y / uCell + 30.0);\n float y = iResolution.y / uCell - cell.y;\n float trail = head - y;\n float lit = trail >= 0.0 ? exp(-trail * 0.15) : 0.0;\n float isHead = step(abs(trail), 0.5);\n float g = glyph(cell, f);\n vec3 c = uBackground + uGlyph * g * lit + vec3(0.8) * g * isHead;\n fragColor = vec4(c, 1.0);\n}`,\n ),\n};\n\nexport const pixelSunset: ShaderEffect = {\n kind: \"shader\",\n id: \"dither-gradient\",\n name: \"Dithered gradient\",\n description: \"A 1-bit Bayer-dithered gradient wave, like an old Mac or Game Boy screen.\",\n category: \"retro\",\n tags: [\"pixel\", \"1-bit\", \"lo-fi\", \"background\"],\n source: glsl(\n `// Dithered gradient: a Bayer-dithered gradient wave in two colours.\nuniform vec3 uDark; // @control color default=#0F380F label=\"Dark\"\nuniform vec3 uLight; // @control color default=#9BBC0F label=\"Light\"\nuniform float uPixel; // @control min=1 max=12 default=4 step=1 label=\"Pixel size\"\nuniform float uSpeed; // @control min=0 max=2 default=0.5 label=\"Speed\"`,\n `float bayer4(vec2 p) {\n vec2 q = mod(floor(p), 4.0);\n int i = int(q.x) + int(q.y) * 4;\n int m[16] = int[16](0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5);\n return (float(m[i]) + 0.5) / 16.0;\n}\n\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n vec2 px = floor(fragCoord / uPixel);\n vec2 uv = px * uPixel / iResolution.xy;\n float v = uv.y + 0.15 * sin(uv.x * 6.0 + iTime * uSpeed * 2.0) + 0.1 * sin(uv.x * 13.0 - iTime * uSpeed * 3.0);\n v = clamp(v, 0.0, 1.0);\n float on = step(bayer4(px), v);\n fragColor = vec4(mix(uDark, uLight, on), 1.0);\n}`,\n ),\n presets: [\n { name: \"Mac\", values: { uDark: [0.05, 0.05, 0.05], uLight: [0.93, 0.93, 0.9] } },\n { name: \"Amber\", values: { uDark: [0.1, 0.04, 0], uLight: [1, 0.69, 0] } },\n ],\n};\n","import {\n checkControlValue,\n controlFromDeclaration,\n hexToRgb,\n rgbToHex,\n type ControlDef,\n type ControlType,\n type ControlValue,\n} from \"../shader/controls.js\";\nimport type { SvgMotion } from \"../vector/motion.js\";\n\n/** What an effect is for, used to group the catalog. */\nexport type EffectCategory =\n | \"gradient\"\n | \"organic\"\n | \"pattern\"\n | \"light\"\n | \"space\"\n | \"retro\"\n | \"image\"\n | \"transition\"\n | \"loader\"\n | \"data\"\n | \"icon\";\n\n/** Every category, in the order the catalog lists them. */\nexport const EFFECT_CATEGORIES: readonly EffectCategory[] = [\n \"gradient\",\n \"organic\",\n \"pattern\",\n \"light\",\n \"space\",\n \"retro\",\n \"image\",\n \"transition\",\n \"loader\",\n \"data\",\n \"icon\",\n];\n\n/** Named control values: a look an effect can be switched to. */\nexport interface EffectPreset {\n name: string;\n values: Record<string, ControlValue>;\n}\n\ninterface EffectBase {\n /** Stable id, kebab-case: `aurora`, `image-glitch`. */\n id: string;\n name: string;\n /** One sentence: what it looks like. */\n description: string;\n category: EffectCategory;\n tags: readonly string[];\n presets?: readonly EffectPreset[];\n}\n\n/**\n * A WebGL2 fragment shader (Shadertoy-style `mainImage`). Its controls are the\n * `// @control` uniforms in `source`; run it with `ShaderRenderer`,\n * `ShaderFrames`, `ThumbnailPool`, `recordGif` or `standaloneHtml`.\n */\nexport interface ShaderEffect extends EffectBase {\n kind: \"shader\";\n source: string;\n /** Seconds after which it repeats exactly, when it loops seamlessly. */\n loop?: number;\n}\n\n/**\n * A control of a vector effect, declared in a list rather than in the\n * picture (see {@link VectorEffect.controls}). The same shape as a shader's\n * controls (see `ControlDef`) less what only sources have; `vec3` colours\n * are written into the picture as `#rrggbb`.\n */\nexport type VectorControl = Pick<ControlDef, \"name\" | \"type\" | \"default\"> &\n Partial<Pick<ControlDef, \"label\" | \"color\" | \"min\" | \"max\" | \"step\">>;\n\n/**\n * An animated SVG picture (see `SvgMotion`) whose controls are declared in\n * the picture itself, the way a shader's are declared in its source. The\n * first `{{name: type …}}` declares a control and every `{{name}}` is\n * replaced by its value (see {@link vectorControls} and\n * {@link renderVectorEffect}); run the result with `SvgPlayer`.\n */\nexport interface VectorEffect extends EffectBase {\n kind: \"vector\";\n motion: SvgMotion;\n /**\n * Controls declared outside the picture, for effects written before\n * controls were declared inline. A control declared in the picture wins\n * over one of the same name here.\n */\n controls?: readonly VectorControl[];\n /**\n * More placeholders worked out from the control values (a bar's height\n * from its value, say), filled in after the controls.\n */\n derived?: (values: Record<string, ControlValue>) => Record<string, string | number>;\n /** Ms to rest on the last frame before it loops (default 600). */\n hold?: number;\n}\n\nexport type EffectDefinition = ShaderEffect | VectorEffect;\n\n/** The types a vector effect's `{{name: type …}}` placeholder can declare. */\nexport const VECTOR_CONTROL_TYPES = [\"float\", \"int\", \"bool\", \"color\", \"text\"] as const;\n\n/**\n * A placeholder: `{{name}}`, or a declaration `{{name: type attributes}}`\n * whose attributes are a shader `@control`'s (`min`, `max`, `step`,\n * `default`, `label`). Quote values with spaces in single quotes inside an\n * SVG attribute: `fill=\"{{accent: color default=#6366F1 label='Accent'}}\"`.\n */\nconst PLACEHOLDER = /\\{\\{\\s*([A-Za-z_]\\w*)\\s*(?::\\s*([A-Za-z0-9]*)([^}]*))?\\}\\}/g;\n\n/** Every string in a motion, the markup first, then each animation's values in order. */\nfunction motionStrings(motion: SvgMotion): string[] {\n const out: string[] = [];\n const walk = (v: unknown) => {\n if (typeof v === \"string\") out.push(v);\n else if (Array.isArray(v)) v.forEach(walk);\n else if (v && typeof v === \"object\") Object.values(v).forEach(walk);\n };\n walk(motion);\n return out;\n}\n\n/**\n * The controls a vector effect's picture declares, in the order they are\n * first declared: `{{word: text default=SLOP label=Word}}`, `{{accent:\n * color default=#6366F1}}`, `{{width: float min=2 max=20 default=8 step=1}}`,\n * `{{shadow: bool default=true}}`. A name declared twice counts once (the\n * first wins), and declarations with an unknown type are left out (see\n * {@link vectorControlIssues}). A control only `derived` reads can be\n * declared in an XML comment: `<!-- {{drip: float default=1}} -->`.\n */\nexport function vectorControls(motion: SvgMotion): ControlDef[] {\n const controls: ControlDef[] = [];\n const seen = new Set<string>();\n for (const text of motionStrings(motion)) {\n for (const [, name, type, attributes] of text.matchAll(PLACEHOLDER)) {\n if (type === undefined || seen.has(name!) || !(VECTOR_CONTROL_TYPES as readonly string[]).includes(type)) continue;\n seen.add(name!);\n const colour = type === \"color\";\n controls.push(controlFromDeclaration(name!, colour ? \"vec3\" : (type as ControlType), `${attributes}${colour ? \" color\" : \"\"}`, controls.length + 1));\n }\n }\n return controls;\n}\n\n/** A vector effect's controls: those its picture declares, then any in its `controls` list it does not. */\nexport function vectorEffectControls(effect: Pick<VectorEffect, \"motion\" | \"controls\">): ControlDef[] {\n const declared = vectorControls(effect.motion);\n const names = new Set(declared.map((c) => c.name));\n const listed = (effect.controls ?? []).filter((c) => !names.has(c.name));\n return [...declared, ...listed.map((c, i) => vectorControlDef(c, declared.length + i + 1))];\n}\n\n/**\n * Problems with a picture's placeholders, as sentences: declarations of an\n * unknown type, and a name declared twice in different ways.\n */\nexport function vectorControlIssues(motion: SvgMotion): string[] {\n const issues: string[] = [];\n const declarations = new Map<string, string>();\n for (const text of motionStrings(motion)) {\n for (const [whole, name, type] of text.matchAll(PLACEHOLDER)) {\n if (type === undefined) continue;\n if (!(VECTOR_CONTROL_TYPES as readonly string[]).includes(type))\n issues.push(`${whole}: a control's type is one of ${VECTOR_CONTROL_TYPES.join(\", \")}`);\n else if (declarations.has(name!) && declarations.get(name!) !== whole)\n issues.push(`\"${name}\" is declared twice; declare it once and write {{${name}}} everywhere else`);\n else declarations.set(name!, whole);\n }\n }\n return issues;\n}\n\n/** A vector control's value written into the picture: colours as hex, vectors space-separated, the rest as they are. */\nfunction written(control: Pick<ControlDef, \"color\">, value: ControlValue): string | number | boolean {\n if (control.color && Array.isArray(value)) return rgbToHex(value);\n if (Array.isArray(value)) return value.join(\" \");\n return value;\n}\n\nconst escapeMarkup = (text: string) =>\n text.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\").replace(/'/g, \"&#39;\");\n\n/** A vector control as a full `ControlDef`, so editors treat both kinds of effect alike. */\nexport function vectorControlDef(control: VectorControl, line = 0): ControlDef {\n const min = control.min ?? 0;\n return {\n name: control.name,\n type: control.type,\n label: control.label ?? control.name,\n color: control.color ?? false,\n min,\n max: control.max ?? Math.max(min + 1, 1),\n step: control.step ?? (control.type === \"int\" ? 1 : 0.01),\n default: control.default,\n line,\n };\n}\n\n/**\n * A vector effect's motion with its controls filled in. A string that is\n * only a placeholder (an animation's `\"{{width}}\"`) becomes the value\n * itself, so numbers stay numbers; elsewhere a placeholder becomes its text,\n * escaped in the markup so any text is safe to show. Comments are dropped\n * from the markup. Colours also take \"#RRGGBB\"; missing values, and values a\n * control cannot take, use defaults. Placeholders no control or derived\n * value fills stay put.\n */\nexport function renderVectorEffect(\n effect: Pick<VectorEffect, \"motion\" | \"controls\" | \"derived\">,\n values: Record<string, ControlValue> = {},\n): SvgMotion {\n const filled: Record<string, ControlValue> = {};\n const placeholders = new Map<string, string | number | boolean>();\n for (const control of vectorEffectControls(effect)) {\n const given = values[control.name];\n const check = given === undefined ? undefined : checkControlValue(control, given);\n filled[control.name] = check?.ok ? check.value : control.default;\n placeholders.set(control.name, written(control, filled[control.name]!));\n }\n for (const [name, value] of Object.entries(effect.derived?.(filled) ?? {})) placeholders.set(name, value);\n const fill = (text: string, markup: boolean): string | number | boolean => {\n const whole = /^\\{\\{\\s*([A-Za-z_]\\w*)\\s*(?::[^}]*)?\\}\\}$/.exec(text);\n if (!markup && whole && placeholders.has(whole[1]!)) return placeholders.get(whole[1]!)!;\n return text.replace(PLACEHOLDER, (match, name: string) => {\n if (!placeholders.has(name)) return match;\n const value = String(placeholders.get(name));\n return markup ? escapeMarkup(value) : value;\n });\n };\n const walk = (v: unknown): unknown => {\n if (typeof v === \"string\") return fill(v, false);\n if (Array.isArray(v)) return v.map(walk);\n if (v && typeof v === \"object\") return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, walk(x)]));\n return v;\n };\n const { svg, ...rest } = effect.motion;\n // Comments hold declarations, not picture, and a value with \"--\" in one would break the markup.\n return { svg: fill(svg.replace(/<!--[\\s\\S]*?-->/g, \"\"), true) as string, ...(walk(rest) as Omit<SvgMotion, \"svg\">) };\n}\n\n/** A colour control for vector effects. */\nexport function colorControl(name: string, hex: string, label?: string): VectorControl {\n return { name, type: \"vec3\", color: true, default: hexToRgb(hex) ?? [1, 1, 1], label: label ?? name };\n}\n\n/** A number control for vector effects. */\nexport function numberControl(\n name: string,\n value: number,\n min: number,\n max: number,\n label?: string,\n step?: number,\n): VectorControl {\n return { name, type: \"float\", default: value, min, max, label: label ?? name, step };\n}\n","import type { SvgAnimation } from \"../vector/motion.js\";\nimport type { VectorEffect } from \"./types.js\";\n\nexport const spinner: VectorEffect = {\n kind: \"vector\",\n id: \"spinner\",\n name: \"Spinner\",\n description: \"An arc chasing its tail: the classic indeterminate loader.\",\n category: \"loader\",\n tags: [\"loader\", \"ui\", \"minimal\"],\n hold: 0,\n motion: {\n svg: `<svg viewBox=\"0 0 100 100\"><!-- {{accent: color default=#6366F1 label='Arc'}} {{track: color default=#E5E7EB label='Track'}} {{width: float min=2 max=20 default=8 step=1 label='Stroke width'}} --><circle cx=\"50\" cy=\"50\" r=\"38\" fill=\"none\" stroke=\"{{track}}\" stroke-width=\"{{width}}\"/><g id=\"spin\" transform=\"rotate(0 50 50)\"><circle id=\"arc\" cx=\"50\" cy=\"50\" r=\"38\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"{{width}}\" stroke-linecap=\"round\" pathLength=\"1\" stroke-dasharray=\"0.25 1\"/></g></svg>`,\n animate: [\n { id: \"spin\", attrs: { transform: [\"rotate(0 50 50)\", \"rotate(720 50 50)\"] }, ms: 1600, ease: \"linear\" },\n { id: \"arc\", attrs: { \"stroke-dasharray\": [\"0.08 1\", \"0.6 1\"] }, ms: 800, ease: \"in-out\" },\n { id: \"arc\", attrs: { \"stroke-dasharray\": [\"0.6 1\", \"0.08 1\"] }, delay: 800, ms: 800, ease: \"in-out\" },\n ],\n },\n};\n\nexport const bouncingDots: VectorEffect = {\n kind: \"vector\",\n id: \"bouncing-dots\",\n name: \"Bouncing dots\",\n description: \"Three dots hopping in turn, for typing indicators and loaders.\",\n category: \"loader\",\n tags: [\"loader\", \"chat\", \"typing\", \"ui\"],\n hold: 0,\n motion: {\n svg: `<svg viewBox=\"0 0 120 60\"><!-- {{accent: color default=#0EA5E9 label='Dots'}} {{height: float min=4 max=30 default=18 step=1 label='Bounce height'}} --><circle id=\"a\" cx=\"30\" cy=\"40\" r=\"9\" fill=\"{{accent}}\"/><circle id=\"b\" cx=\"60\" cy=\"40\" r=\"9\" fill=\"{{accent}}\"/><circle id=\"c\" cx=\"90\" cy=\"40\" r=\"9\" fill=\"{{accent}}\"/></svg>`,\n animate: [\"a\", \"b\", \"c\"].flatMap((id, i): SvgAnimation[] => [\n { id, attrs: { transform: [\"translate(0 0)\", \"translate(0 -{{height}})\"] }, delay: i * 150, ms: 250, ease: \"out\" as const },\n { id, attrs: { transform: [\"translate(0 -{{height}})\", \"translate(0 0)\"] }, delay: i * 150 + 250, ms: 250, ease: \"in-out\" as const },\n { id, attrs: { opacity: [0.5, 1] }, delay: i * 150, ms: 250 },\n { id, attrs: { opacity: [1, 0.5] }, delay: i * 150 + 250, ms: 250 },\n ]),\n },\n};\n\nexport const progressRing: VectorEffect = {\n kind: \"vector\",\n id: \"progress-ring\",\n name: \"Progress ring\",\n description: \"A ring filling up to a percentage while the number counts with it.\",\n category: \"data\",\n tags: [\"progress\", \"kpi\", \"dashboard\", \"loader\"],\n derived: (v) => ({ fraction: Math.min(1, Math.max(0, Number(v.value) / 100)) }),\n motion: {\n svg: `<svg viewBox=\"0 0 120 120\" font-family=\"system-ui, sans-serif\"><!-- {{accent: color default=#22C55E label='Ring'}} {{track: color default=#E5E7EB label='Track'}} {{text: color default=#111827 label='Text'}} {{value: float min=0 max=100 default=72 step=1 label='Percent'}} --><circle cx=\"60\" cy=\"60\" r=\"48\" fill=\"none\" stroke=\"{{track}}\" stroke-width=\"10\"/><circle id=\"ring\" cx=\"60\" cy=\"60\" r=\"48\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"10\" stroke-linecap=\"round\" transform=\"rotate(-90 60 60)\"/><text id=\"label\" x=\"60\" y=\"68\" text-anchor=\"middle\" font-size=\"24\" font-weight=\"700\" fill=\"{{text}}\">0%</text></svg>`,\n animate: [\n { id: \"ring\", draw: [0, \"{{fraction}}\"] as unknown as [number, number], ms: 1600, ease: \"out\" },\n { id: \"label\", count: [0, \"{{value}}\"] as unknown as [number, number], format: \"{n}%\", ms: 1600, ease: \"out\" },\n ],\n },\n};\n\nexport const pulsePing: VectorEffect = {\n kind: \"vector\",\n id: \"pulse-ping\",\n name: \"Pulse ping\",\n description: \"Rings radiating from a dot, like a live indicator or radar ping.\",\n category: \"loader\",\n tags: [\"live\", \"notification\", \"location\", \"status\"],\n hold: 0,\n motion: {\n svg: `<svg viewBox=\"0 0 100 100\"><!-- {{accent: color default=#EF4444 label='Colour'}} --><circle id=\"r1\" cx=\"50\" cy=\"50\" r=\"8\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"3\"/><circle id=\"r2\" cx=\"50\" cy=\"50\" r=\"8\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"3\"/><circle cx=\"50\" cy=\"50\" r=\"9\" fill=\"{{accent}}\"/></svg>`,\n animate: [\n { id: \"r1\", attrs: { r: [8, 44], opacity: [0.9, 0], \"stroke-width\": [4, 1] }, ms: 1400, ease: \"out\" },\n { id: \"r2\", attrs: { r: [8, 44], opacity: [0.9, 0], \"stroke-width\": [4, 1] }, delay: 700, ms: 1400, ease: \"out\" },\n ],\n },\n};\n\nexport const successCheck: VectorEffect = {\n kind: \"vector\",\n id: \"success-check\",\n name: \"Success check\",\n description: \"A circle drawing itself closed, then a tick, then a little pop.\",\n category: \"icon\",\n tags: [\"success\", \"confirmation\", \"ui\", \"feedback\"],\n hold: 1200,\n motion: {\n svg: `<svg viewBox=\"0 0 100 100\"><!-- {{accent: color default=#16A34A label='Colour'}} {{width: float min=2 max=12 default=6 step=1 label='Stroke width'}} --><g id=\"badge\" transform=\"translate(50 50) scale(1) translate(-50 -50)\"><circle id=\"circle\" cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"{{width}}\" stroke-linecap=\"round\" transform=\"rotate(-90 50 50)\"/><path id=\"tick\" d=\"M31 52 L44 64 L70 37\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"{{width}}\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></g></svg>`,\n animate: [\n { id: \"circle\", draw: true, ms: 600, ease: \"in-out\" },\n { id: \"tick\", draw: true, delay: 500, ms: 400, ease: \"out\" },\n { id: \"badge\", attrs: { transform: [\"translate(50 50) scale(1) translate(-50 -50)\", \"translate(50 50) scale(1.12) translate(-50 -50)\"] }, delay: 850, ms: 150, ease: \"out\" },\n { id: \"badge\", attrs: { transform: [\"translate(50 50) scale(1.12) translate(-50 -50)\", \"translate(50 50) scale(1) translate(-50 -50)\"] }, delay: 1000, ms: 250, ease: \"in-out\" },\n ],\n },\n};\n\nexport const errorCross: VectorEffect = {\n kind: \"vector\",\n id: \"error-cross\",\n name: \"Error cross\",\n description: \"A circle and a cross drawing on, with a short shake.\",\n category: \"icon\",\n tags: [\"error\", \"failure\", \"ui\", \"feedback\"],\n hold: 1200,\n motion: {\n svg: `<svg viewBox=\"0 0 100 100\"><!-- {{accent: color default=#DC2626 label='Colour'}} {{width: float min=2 max=12 default=6 step=1 label='Stroke width'}} --><g id=\"badge\" transform=\"translate(0 0)\"><circle id=\"circle\" cx=\"50\" cy=\"50\" r=\"40\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"{{width}}\" stroke-linecap=\"round\" transform=\"rotate(-90 50 50)\"/><path id=\"a\" d=\"M36 36 L64 64\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"{{width}}\" stroke-linecap=\"round\"/><path id=\"b\" d=\"M64 36 L36 64\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"{{width}}\" stroke-linecap=\"round\"/></g></svg>`,\n animate: [\n { id: \"circle\", draw: true, ms: 600, ease: \"in-out\" },\n { id: \"a\", draw: true, delay: 500, ms: 250, ease: \"out\" },\n { id: \"b\", draw: true, delay: 700, ms: 250, ease: \"out\" },\n { id: \"badge\", attrs: { transform: [\"translate(0 0)\", \"translate(-6 0)\"] }, delay: 950, ms: 60, ease: \"linear\" },\n { id: \"badge\", attrs: { transform: [\"translate(-6 0)\", \"translate(6 0)\"] }, delay: 1010, ms: 100, ease: \"linear\" },\n { id: \"badge\", attrs: { transform: [\"translate(6 0)\", \"translate(0 0)\"] }, delay: 1110, ms: 80, ease: \"out\" },\n ],\n },\n};\n\nexport const heartbeat: VectorEffect = {\n kind: \"vector\",\n id: \"heartbeat\",\n name: \"Heartbeat\",\n description: \"A heart beating twice, with an ECG line tracing beneath it.\",\n category: \"icon\",\n tags: [\"health\", \"like\", \"love\", \"pulse\"],\n hold: 300,\n motion: {\n svg: `<svg viewBox=\"0 0 200 120\"><!-- {{accent: color default=#F43F5E label='Heart'}} {{line: color default=#94A3B8 label='Line'}} --><g id=\"heart\" transform=\"translate(100 46) scale(1)\"><path d=\"M0 22 C-30 0 -30 -26 -10 -26 C-3 -26 0 -20 0 -16 C0 -20 3 -26 10 -26 C30 -26 30 0 0 22Z\" fill=\"{{accent}}\"/></g><path id=\"ecg\" d=\"M10 100 H70 L80 86 L90 112 L100 76 L110 104 L118 100 H190\" fill=\"none\" stroke=\"{{line}}\" stroke-width=\"3\" stroke-linejoin=\"round\" stroke-linecap=\"round\"/></svg>`,\n animate: [\n { id: \"heart\", attrs: { transform: [\"translate(100 46) scale(1)\", \"translate(100 46) scale(1.18)\"] }, ms: 120, ease: \"out\" },\n { id: \"heart\", attrs: { transform: [\"translate(100 46) scale(1.18)\", \"translate(100 46) scale(1)\"] }, delay: 120, ms: 160, ease: \"in-out\" },\n { id: \"heart\", attrs: { transform: [\"translate(100 46) scale(1)\", \"translate(100 46) scale(1.12)\"] }, delay: 300, ms: 120, ease: \"out\" },\n { id: \"heart\", attrs: { transform: [\"translate(100 46) scale(1.12)\", \"translate(100 46) scale(1)\"] }, delay: 420, ms: 300, ease: \"in-out\" },\n { id: \"ecg\", draw: true, ms: 900, ease: \"linear\" },\n ],\n },\n};\n\nexport const barChart: VectorEffect = {\n kind: \"vector\",\n id: \"bar-chart\",\n name: \"Bar chart\",\n description: \"Bars growing into place one after another, values counting above them.\",\n category: \"data\",\n tags: [\"chart\", \"dashboard\", \"report\", \"explainer\"],\n hold: 1500,\n derived: (v) =>\n Object.fromEntries(\n [\"a\", \"b\", \"c\", \"d\"].flatMap((k) => {\n const h = Math.min(100, Math.max(0, Number(v[k]))) * 1.1;\n return [\n [`${k}_height`, +h.toFixed(2)],\n [`${k}_label_y`, +(134 - h).toFixed(2)],\n ];\n }),\n ),\n motion: {\n svg: `<svg viewBox=\"0 0 240 160\" font-family=\"system-ui, sans-serif\"><!-- {{accent: color default=#6366F1 label='Bars'}} {{text: color default=#334155 label='Text'}} {{a: float min=0 max=100 default=40 step=1 label='Bar 1'}} {{b: float min=0 max=100 default=65 step=1 label='Bar 2'}} {{c: float min=0 max=100 default=50 step=1 label='Bar 3'}} {{d: float min=0 max=100 default=90 step=1 label='Bar 4'}} --><line x1=\"20\" y1=\"140\" x2=\"220\" y2=\"140\" stroke=\"{{text}}\" stroke-opacity=\"0.3\" stroke-width=\"2\"/>${[\"a\", \"b\", \"c\", \"d\"]\n .map(\n (k, i) =>\n `<g id=\"bar-${k}\" transform=\"translate(${40 + i * 48} 140) scale(1 0)\"><rect x=\"0\" y=\"-1\" width=\"32\" height=\"1\" rx=\"0.02\" fill=\"{{accent}}\"/></g><text id=\"label-${k}\" x=\"${56 + i * 48}\" y=\"132\" text-anchor=\"middle\" font-size=\"12\" fill=\"{{text}}\" opacity=\"0\">0</text>`,\n )\n .join(\"\")}</svg>`,\n animate: [\"a\", \"b\", \"c\", \"d\"].flatMap((k, i): SvgAnimation[] => [\n { id: `bar-${k}`, attrs: { transform: [`translate(${40 + i * 48} 140) scale(1 0)`, `translate(${40 + i * 48} 140) scale(1 {{${k}_height}})`] }, delay: i * 180, ms: 700, ease: \"out\" as const },\n { id: `label-${k}`, attrs: { y: [132, `{{${k}_label_y}}`], opacity: [0, 1] }, delay: i * 180, ms: 700, ease: \"out\" as const },\n { id: `label-${k}`, count: [0, `{{${k}}}`] as unknown as [number, number], delay: i * 180, ms: 700, ease: \"out\" as const },\n ]),\n },\n};\n\nexport const lineChart: VectorEffect = {\n kind: \"vector\",\n id: \"line-chart\",\n name: \"Line chart\",\n description: \"A trend line drawing across with a marker riding its tip and the area fading in below.\",\n category: \"data\",\n tags: [\"chart\", \"trend\", \"growth\", \"dashboard\"],\n hold: 1500,\n motion: {\n svg: `<svg viewBox=\"0 0 240 140\"><!-- {{accent: color default=#0EA5E9 label='Line'}} {{grid: color default=#CBD5E1 label='Grid'}} --><defs><linearGradient id=\"fill\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop offset=\"0\" stop-color=\"{{accent}}\" stop-opacity=\"0.35\"/><stop offset=\"1\" stop-color=\"{{accent}}\" stop-opacity=\"0\"/></linearGradient></defs><g stroke=\"{{grid}}\" stroke-width=\"1\"><line x1=\"20\" y1=\"30\" x2=\"220\" y2=\"30\"/><line x1=\"20\" y1=\"70\" x2=\"220\" y2=\"70\"/><line x1=\"20\" y1=\"110\" x2=\"220\" y2=\"110\"/></g><path id=\"area\" d=\"M20 110 L60 92 L100 98 L140 64 L180 70 L220 30 L220 120 L20 120Z\" fill=\"url(#fill)\" opacity=\"0\"/><path id=\"trend\" d=\"M20 110 L60 92 L100 98 L140 64 L180 70 L220 30\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"3\" stroke-linejoin=\"round\" stroke-linecap=\"round\"/><circle id=\"marker\" r=\"5\" fill=\"#fff\" stroke=\"{{accent}}\" stroke-width=\"3\"/></svg>`,\n animate: [\n { id: \"trend\", draw: true, ms: 1400, ease: \"in-out\" },\n { id: \"marker\", along: \"trend\", ms: 1400, ease: \"in-out\" },\n { id: \"area\", attrs: { opacity: [0, 1] }, delay: 900, ms: 600 },\n ],\n },\n};\n\nexport const statCounter: VectorEffect = {\n kind: \"vector\",\n id: \"stat-counter\",\n name: \"Stat counter\",\n description: \"A headline number counting up, with its caption and underline sweeping in.\",\n category: \"data\",\n tags: [\"kpi\", \"number\", \"headline\", \"explainer\"],\n hold: 1500,\n motion: {\n svg: `<svg viewBox=\"0 0 240 120\" font-family=\"system-ui, sans-serif\"><!-- {{accent: color default=#F59E0B label='Accent'}} {{text: color default=#0F172A label='Text'}} {{value: float min=0 max=100000 default=1250 step=1 label='Value'}} {{caption: text default='happy customers' label='Caption'}} --><text id=\"number\" x=\"120\" y=\"62\" text-anchor=\"middle\" font-size=\"44\" font-weight=\"800\" fill=\"{{text}}\">0</text><path id=\"underline\" d=\"M60 78 H180\" stroke=\"{{accent}}\" stroke-width=\"6\" stroke-linecap=\"round\"/><text id=\"caption\" x=\"120\" y=\"104\" text-anchor=\"middle\" font-size=\"13\" fill=\"{{text}}\" opacity=\"0\">{{caption}}</text></svg>`,\n animate: [\n { id: \"number\", count: [0, \"{{value}}\"] as unknown as [number, number], ms: 1500, ease: \"out\" },\n { id: \"underline\", draw: true, delay: 300, ms: 900, ease: \"in-out\" },\n { id: \"caption\", attrs: { opacity: [0, 1], y: [112, 104] }, delay: 800, ms: 500, ease: \"out\" },\n ],\n },\n};\n\nexport const timelineTrack: VectorEffect = {\n kind: \"vector\",\n id: \"timeline-track\",\n name: \"Timeline track\",\n description: \"A vertical line drawing down with nodes popping along milestones.\",\n category: \"data\",\n tags: [\"timeline\", \"roadmap\", \"milestones\", \"history\"],\n hold: 1200,\n motion: {\n svg: `<svg viewBox=\"0 0 100 400\"><!-- {{track: color default=#E5E7EB label='Track'}} {{accent: color default=#F97316 label='Accent'}} {{width: float min=1 max=8 default=3 step=0.5 label='Line width'}} --><line x1=\"50\" y1=\"20\" x2=\"50\" y2=\"380\" stroke=\"{{track}}\" stroke-width=\"{{width}}\" stroke-linecap=\"round\"/><path id=\"line\" d=\"M50 20 L50 380\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"{{width}}\" stroke-linecap=\"round\"/><g id=\"n1\" transform=\"translate(50 60) scale(0)\"><circle r=\"8\" fill=\"{{accent}}\"/><circle r=\"4\" fill=\"#ffffff\"/></g><g id=\"n2\" transform=\"translate(50 160) scale(0)\"><circle r=\"8\" fill=\"{{accent}}\"/><circle r=\"4\" fill=\"#ffffff\"/></g><g id=\"n3\" transform=\"translate(50 260) scale(0)\"><circle r=\"8\" fill=\"{{accent}}\"/><circle r=\"4\" fill=\"#ffffff\"/></g><g id=\"n4\" transform=\"translate(50 360) scale(0)\"><circle r=\"8\" fill=\"{{accent}}\"/><circle r=\"4\" fill=\"#ffffff\"/></g></svg>`,\n animate: [\n { id: \"line\", draw: true, ms: 1400, ease: \"in-out\" },\n { id: \"n1\", attrs: { transform: [\"translate(50 60) scale(0)\", \"translate(50 60) scale(1)\"] }, delay: 200, ms: 250, ease: \"out\" },\n { id: \"n2\", attrs: { transform: [\"translate(50 160) scale(0)\", \"translate(50 160) scale(1)\"] }, delay: 550, ms: 250, ease: \"out\" },\n { id: \"n3\", attrs: { transform: [\"translate(50 260) scale(0)\", \"translate(50 260) scale(1)\"] }, delay: 900, ms: 250, ease: \"out\" },\n { id: \"n4\", attrs: { transform: [\"translate(50 360) scale(0)\", \"translate(50 360) scale(1)\"] }, delay: 1300, ms: 250, ease: \"out\" },\n ],\n },\n};\n\nexport const route: VectorEffect = {\n kind: \"vector\",\n id: \"route\",\n name: \"Route\",\n description: \"A dashed journey drawing between two pins, with a traveller following it.\",\n category: \"data\",\n tags: [\"map\", \"travel\", \"delivery\", \"journey\"],\n hold: 1200,\n motion: {\n svg: `<svg viewBox=\"0 0 240 150\"><!-- {{accent: color default=#8B5CF6 label='Route'}} {{pin: color default=#0F172A label='Pins'}} --><path id=\"path\" d=\"M30 120 C60 40 120 140 150 70 S210 30 210 30\" fill=\"none\" stroke=\"{{accent}}\" stroke-width=\"4\" stroke-linecap=\"round\"/><circle cx=\"30\" cy=\"120\" r=\"7\" fill=\"{{pin}}\"/><g id=\"end\" opacity=\"0\"><circle cx=\"210\" cy=\"30\" r=\"9\" fill=\"{{pin}}\"/><circle cx=\"210\" cy=\"30\" r=\"3.5\" fill=\"#fff\"/></g><g id=\"traveller\"><circle r=\"7\" fill=\"{{accent}}\"/><circle r=\"3\" fill=\"#fff\"/></g></svg>`,\n animate: [\n { id: \"path\", draw: true, ms: 1800, ease: \"in-out\" },\n { id: \"traveller\", along: \"path\", ms: 1800, ease: \"in-out\" },\n { id: \"end\", attrs: { opacity: [0, 1] }, delay: 1600, ms: 300 },\n ],\n },\n};\n\nexport const blobMorph: VectorEffect = {\n kind: \"vector\",\n id: \"blob-morph\",\n name: \"Blob morph\",\n description: \"An organic blob shape-shifting through three forms.\",\n category: \"organic\",\n tags: [\"shape\", \"background\", \"playful\", \"brand\"],\n hold: 0,\n motion: (() => {\n const shapes = [\n \"M100 30 C140 30 170 60 170 100 C170 140 140 170 100 170 C60 170 30 140 30 100 C30 60 60 30 100 30Z\",\n \"M100 20 C150 40 180 70 160 110 C140 160 120 175 85 165 C45 155 25 120 40 80 C55 40 70 15 100 20Z\",\n \"M110 35 C155 25 175 85 165 120 C155 160 105 180 70 160 C35 140 20 100 45 70 C65 45 80 40 110 35Z\",\n ];\n const step = 1200;\n return {\n svg: `<svg viewBox=\"0 0 200 200\"><!-- {{colorA: color default=#F472B6 label='Colour A'}} {{colorB: color default=#818CF8 label='Colour B'}} --><defs><linearGradient id=\"g\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\"><stop offset=\"0\" stop-color=\"{{colorA}}\"/><stop offset=\"1\" stop-color=\"{{colorB}}\"/></linearGradient></defs><path id=\"blob\" d=\"${shapes[0]}\" fill=\"url(#g)\"/></svg>`,\n animate: shapes.map((d, i) => ({\n id: \"blob\",\n attrs: { d: [d, shapes[(i + 1) % shapes.length]!] as [string, string] },\n delay: i * step,\n ms: step,\n ease: \"in-out\" as const,\n })),\n };\n })(),\n};\n\nexport const signature: VectorEffect = {\n kind: \"vector\",\n id: \"signature\",\n name: \"Signature\",\n description: \"A handwritten flourish drawing itself as if by pen.\",\n category: \"icon\",\n tags: [\"handwriting\", \"draw-on\", \"personal\", \"reveal\"],\n hold: 1500,\n motion: {\n svg: `<svg viewBox=\"0 0 260 120\"><!-- {{ink: color default=#1E293B label='Ink'}} {{width: float min=1 max=8 default=3 step=0.5 label='Pen width'}} --><path id=\"sig\" d=\"M20 80 C40 20 60 20 55 70 C52 95 70 95 85 60 C95 40 100 75 110 70 C120 65 125 40 135 55 C145 70 150 75 165 50 C175 35 185 60 190 65 C200 75 215 40 240 45\" fill=\"none\" stroke=\"{{ink}}\" stroke-width=\"{{width}}\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path id=\"dash\" d=\"M70 100 Q140 92 220 98\" fill=\"none\" stroke=\"{{ink}}\" stroke-width=\"{{width}}\" stroke-linecap=\"round\"/></svg>`,\n animate: [\n { id: \"sig\", draw: true, ms: 1800, ease: \"in-out\" },\n { id: \"dash\", draw: true, delay: 1700, ms: 400, ease: \"out\" },\n ],\n },\n};\n\nexport const equalizer: VectorEffect = {\n kind: \"vector\",\n id: \"equalizer\",\n name: \"Equalizer\",\n description: \"Audio level bars dancing, for now-playing badges and voice states.\",\n category: \"loader\",\n tags: [\"music\", \"audio\", \"voice\", \"now-playing\"],\n hold: 0,\n motion: (() => {\n const heights = [\n [0.3, 0.9, 0.5, 0.3],\n [0.7, 0.4, 1.0, 0.7],\n [0.5, 1.0, 0.3, 0.5],\n [0.9, 0.5, 0.7, 0.9],\n [0.4, 0.8, 0.6, 0.4],\n ];\n const beat = 250;\n return {\n svg: `<svg viewBox=\"0 0 100 100\"><!-- {{accent: color default=#10B981 label='Bars'}} -->${heights\n .map((_, i) => `<g id=\"bar${i}\" transform=\"translate(${14 + i * 16} 85) scale(1 ${heights[i]![0]})\"><rect x=\"0\" y=\"-70\" width=\"10\" height=\"70\" rx=\"5\" fill=\"{{accent}}\"/></g>`)\n .join(\"\")}</svg>`,\n animate: heights.flatMap((h, i) =>\n [0, 1, 2].map((k) => ({\n id: `bar${i}`,\n attrs: { transform: [`translate(${14 + i * 16} 85) scale(1 ${h[k]})`, `translate(${14 + i * 16} 85) scale(1 ${h[k + 1]})`] as [string, string] },\n delay: k * beat,\n ms: beat,\n ease: \"in-out\" as const,\n })),\n ),\n };\n })(),\n};\n\nexport const confetti: VectorEffect = {\n kind: \"vector\",\n id: \"confetti\",\n name: \"Confetti burst\",\n description: \"A burst of confetti flying out and fluttering down.\",\n category: \"icon\",\n tags: [\"celebration\", \"success\", \"party\", \"reward\"],\n hold: 400,\n motion: (() => {\n const pieces = Array.from({ length: 18 }, (_, i) => {\n const angle = (i / 18) * Math.PI * 2 + (i % 3) * 0.2;\n const dist = 55 + (i % 4) * 12;\n const x = Math.round(Math.cos(angle) * dist);\n const y = Math.round(Math.sin(angle) * dist * 0.8 - 20);\n const spin = (i % 2 ? 1 : -1) * (180 + (i % 5) * 60);\n return { i, x, y, spin, fill: [\"{{a}}\", \"{{b}}\", \"{{c}}\"][i % 3]! };\n });\n return {\n svg: `<svg viewBox=\"0 0 200 200\"><!-- {{a: color default=#F43F5E label='Colour A'}} {{b: color default=#FACC15 label='Colour B'}} {{c: color default=#22D3EE label='Colour C'}} -->${pieces\n .map((p) => `<rect id=\"p${p.i}\" x=\"-4\" y=\"-2\" width=\"8\" height=\"4\" rx=\"1\" fill=\"${p.fill}\" transform=\"translate(100 110) rotate(0)\" opacity=\"0\"/>`)\n .join(\"\")}</svg>`,\n animate: pieces.flatMap((p): SvgAnimation[] => [\n { id: `p${p.i}`, attrs: { opacity: [0, 1] }, ms: 50 },\n {\n id: `p${p.i}`,\n attrs: { transform: [\"translate(100 110) rotate(0)\", `translate(${100 + p.x} ${110 + p.y}) rotate(${p.spin})`] as [string, string] },\n ms: 600,\n ease: \"out\" as const,\n },\n {\n id: `p${p.i}`,\n attrs: {\n transform: [`translate(${100 + p.x} ${110 + p.y}) rotate(${p.spin})`, `translate(${100 + p.x * 1.2} ${180 + p.y * 0.2}) rotate(${p.spin * 2})`] as [string, string],\n },\n delay: 600,\n ms: 1000,\n ease: \"in-out\" as const,\n },\n { id: `p${p.i}`, attrs: { opacity: [1, 0] }, delay: 1300, ms: 300 },\n ]),\n };\n })(),\n};\n\n\n/** Flow network's nodes and links, left to right, with the critical path through them. */\nconst NODES: Record<string, [number, number]> = {\n s: [40, 120], a: [120, 60], b: [120, 180], c: [280, 50], d: [290, 130], e: [280, 200], t: [360, 120],\n};\nconst HUB: [number, number] = [200, 120];\nconst link = ([x1, y1]: [number, number], [x2, y2]: [number, number]) => {\n const mid = (x1 + x2) / 2;\n return `M${x1} ${y1} C${mid} ${y1} ${mid} ${y2} ${x2} ${y2}`;\n};\nconst LINKS: { from: [number, number]; to: [number, number]; column: number }[] = [\n { from: NODES.s!, to: NODES.a!, column: 0 },\n { from: NODES.s!, to: NODES.b!, column: 0 },\n { from: NODES.a!, to: HUB, column: 1 },\n { from: NODES.b!, to: HUB, column: 1 },\n { from: HUB, to: NODES.c!, column: 2 },\n { from: HUB, to: NODES.d!, column: 2 },\n { from: HUB, to: NODES.e!, column: 2 },\n { from: NODES.c!, to: NODES.t!, column: 3 },\n { from: NODES.d!, to: NODES.t!, column: 3 },\n { from: NODES.e!, to: NODES.t!, column: 3 },\n];\nconst CRITICAL = [NODES.s!, NODES.b!, HUB, NODES.c!, NODES.t!]\n .map((p, i, all) => (i === 0 ? \"\" : link(all[i - 1]!, p).replace(/^M[\\d.]+ [\\d.]+ /, i === 1 ? `M${all[0]![0]} ${all[0]![1]} ` : \"\")))\n .filter(Boolean)\n .join(\" \");\n/** The column a node is reached in, so it appears as the links arrive. */\nconst NODE_COLUMN: Record<string, number> = { s: 0, a: 1, b: 1, c: 3, d: 3, e: 3, t: 4 };\nconst COLUMN_MS = 280;\nconst PATH_START = 1500;\nconst PATH_MS = 1800;\n\nexport const flowNetwork: VectorEffect = {\n kind: \"vector\",\n id: \"flow-network\",\n name: \"Flow network\",\n description: \"A node graph linking up, then a glowing critical path racing through it to a pulsing hub.\",\n category: \"data\",\n tags: [\"network\", \"graph\", \"dag\", \"workflow\", \"tech\", \"explainer\"],\n hold: 1200,\n presets: [\n { name: \"Light\", values: { background: [0.93, 0.95, 0.96], link: [0.37, 0.72, 0.69], path: [0.96, 0.62, 0.04], ink: [0.2, 0.25, 0.33] } },\n { name: \"Neon\", values: { background: [0.04, 0.02, 0.1], link: [0.13, 0.83, 0.93], path: [0.96, 0.45, 0.71], ink: [0.85, 0.85, 1] } },\n ],\n motion: {\n svg: `<svg viewBox=\"0 0 400 240\" font-family=\"system-ui, sans-serif\"><!-- {{label: text default='Critical path' label='Hub label'}} {{background: color default=#0B1220 label='Background'}} {{link: color default=#4FD1C5 label='Links'}} {{path: color default=#F5A524 label='Critical path'}} {{ink: color default=#CBD5E1 label='Label'}} {{glow: float min=0 max=6 default=2.5 step=0.5 label='Glow'}} --><defs><filter id=\"glow\" x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\"><feGaussianBlur stdDeviation=\"{{glow}}\" result=\"blur\"/><feMerge><feMergeNode in=\"blur\"/><feMergeNode in=\"SourceGraphic\"/></feMerge></filter></defs><rect width=\"400\" height=\"240\" fill=\"{{background}}\"/>${LINKS.map(\n (l, i) => `<path id=\"l${i}\" d=\"${link(l.from, l.to)}\" fill=\"none\" stroke=\"{{link}}\" stroke-width=\"1.6\" stroke-opacity=\"0.75\" filter=\"url(#glow)\"/>`,\n ).join(\"\")}<path id=\"crit\" d=\"${CRITICAL}\" fill=\"none\" stroke=\"{{path}}\" stroke-width=\"3\" stroke-linecap=\"round\" filter=\"url(#glow)\"/>${[0, 1]\n .map((i) => `<circle id=\"ring${i}\" cx=\"${HUB[0]}\" cy=\"${HUB[1]}\" r=\"10\" fill=\"none\" stroke=\"{{link}}\" stroke-width=\"2\" opacity=\"0\"/>`)\n .join(\"\")}${Object.entries(NODES)\n .map(([id, [x, y]]) => `<circle id=\"n${id}\" cx=\"${x}\" cy=\"${y}\" r=\"6\" fill=\"{{background}}\" stroke=\"{{link}}\" stroke-width=\"2.5\" filter=\"url(#glow)\" opacity=\"0\"/>`)\n .join(\"\")}<g id=\"hub\" opacity=\"0\"><circle cx=\"${HUB[0]}\" cy=\"${HUB[1]}\" r=\"13\" fill=\"{{link}}\" fill-opacity=\"0.25\" stroke=\"{{link}}\" stroke-width=\"2\" filter=\"url(#glow)\"/><circle cx=\"${HUB[0]}\" cy=\"${HUB[1]}\" r=\"6\" fill=\"{{link}}\"/></g><text id=\"caption\" x=\"${HUB[0]}\" y=\"${HUB[1] + 34}\" text-anchor=\"middle\" font-size=\"12\" font-weight=\"600\" fill=\"{{ink}}\" opacity=\"0\">{{label}}</text>${[0, 1, 2]\n .map((i) => `<circle id=\"pkt${i}\" r=\"2.5\" fill=\"{{link}}\" filter=\"url(#glow)\" opacity=\"0\"/>`)\n .join(\"\")}<circle id=\"comet\" r=\"5\" fill=\"#FFFFFF\" stroke=\"{{path}}\" stroke-width=\"2\" filter=\"url(#glow)\" opacity=\"0\"/></svg>`,\n animate: [\n ...LINKS.map((l, i): SvgAnimation => ({ id: `l${i}`, draw: true, delay: l.column * COLUMN_MS, ms: 500, ease: \"out\" })),\n ...Object.keys(NODES).map((id): SvgAnimation => ({ id: `n${id}`, attrs: { opacity: [0, 1] }, delay: Math.max(0, NODE_COLUMN[id]! * COLUMN_MS - 120), ms: 250 })),\n { id: \"hub\", attrs: { opacity: [0, 1] }, delay: 2 * COLUMN_MS - 120, ms: 300 },\n { id: \"caption\", attrs: { opacity: [0, 1], y: [HUB[1] + 40, HUB[1] + 34] }, delay: 2 * COLUMN_MS, ms: 400, ease: \"out\" },\n // Data packets drift along a few links while the path waits.\n ...[3, 5, 8].map((link, i): SvgAnimation[] => [\n { id: `pkt${i}`, attrs: { opacity: [0, 1] }, delay: 1000 + i * 150, ms: 150 },\n { id: `pkt${i}`, along: `l${link}`, delay: 1000 + i * 150, ms: 1100, ease: \"in-out\" },\n { id: `pkt${i}`, attrs: { opacity: [1, 0] }, delay: 2000 + i * 150, ms: 200 },\n ]).flat(),\n { id: \"crit\", draw: true, delay: PATH_START, ms: PATH_MS, ease: \"in-out\" },\n { id: \"comet\", attrs: { opacity: [0, 1] }, delay: PATH_START, ms: 150 },\n { id: \"comet\", along: \"crit\", delay: PATH_START, ms: PATH_MS, ease: \"in-out\" },\n { id: \"comet\", attrs: { opacity: [1, 0] }, delay: PATH_START + PATH_MS, ms: 300 },\n // Rings pulse out from the hub as the comet passes it, halfway along.\n ...[0, 1].map((i): SvgAnimation => ({\n id: `ring${i}`,\n attrs: { r: [10, 52], opacity: [0.9, 0], \"stroke-width\": [3, 0.5] },\n delay: PATH_START + PATH_MS / 2 + i * 350,\n ms: 1200,\n ease: \"out\",\n })),\n ],\n },\n};\n\n/** Drip text's drips: where each leaves the word, as a fraction of its width, and how it runs. */\nconst DRIP_TOP = 106;\nconst DRIPS = [\n { at: 0.067, width: 11, length: 34, delay: 0, ms: 1500 },\n { at: 0.18, width: 8, length: 18, delay: 260, ms: 1100 },\n { at: 0.3, width: 13, length: 50, delay: 120, ms: 1800 },\n { at: 0.453, width: 9, length: 22, delay: 380, ms: 1200 },\n { at: 0.587, width: 10, length: 28, delay: 200, ms: 1400 },\n { at: 0.693, width: 12, length: 42, delay: 60, ms: 1700 },\n { at: 0.793, width: 11, length: 32, delay: 300, ms: 1500 },\n];\n\nexport const dripText: VectorEffect = {\n kind: \"vector\",\n id: \"drip-text\",\n name: \"Drip text\",\n description: \"A chunky outlined title popping in, then oozing slime drips from its letters.\",\n category: \"icon\",\n tags: [\"title\", \"text\", \"drip\", \"slime\", \"y2k\", \"headline\"],\n hold: 1200,\n presets: [\n { name: \"Slime\", values: { fill: [0.55, 0.93, 0.25], outline: [0.06, 0.2, 0.04], shine: [0.85, 1, 0.7] } },\n { name: \"Molten gold\", values: { fill: [1, 0.78, 0.2], outline: [0.35, 0.16, 0], shine: [1, 0.96, 0.75], drip: 1.5 } },\n ],\n // The word is stretched to a width set by its length (textLength), so the drips land under its letters in any font.\n derived: (v) => {\n const letters = Math.max(1, Array.from(String(v.word).trim()).length);\n const width = Math.min(380, letters * 75);\n const left = 200 - width / 2;\n return {\n width,\n ...Object.fromEntries(\n DRIPS.flatMap((d, i) => {\n const x = Math.round((left + d.at * width) * 10) / 10;\n const length = Math.round(d.length * Number(v.drip) * 10) / 10;\n return [\n [`x${i}`, x],\n [`left${i}`, x - d.width / 2],\n [`shine${i}`, x - d.width * 0.25],\n [`len${i}`, length],\n [`tip${i}`, DRIP_TOP + length],\n ];\n }),\n ),\n };\n },\n motion: (() => {\n const word = `<text x=\"200\" y=\"120\" text-anchor=\"middle\" textLength=\"{{width}}\" lengthAdjust=\"spacingAndGlyphs\" font-family=\"'Arial Black', Impact, system-ui, sans-serif\" font-size=\"104\" font-weight=\"900\" stroke-linejoin=\"round\"`;\n const drips = (layer: \"o\" | \"f\", paint: string) =>\n DRIPS.map(\n (d, i) =>\n `<rect id=\"${layer}r${i}\" x=\"{{left${i}}}\" y=\"${DRIP_TOP}\" width=\"${d.width}\" height=\"0\" rx=\"${d.width / 2}\" ${paint}/><circle id=\"${layer}c${i}\" cx=\"{{x${i}}}\" cy=\"${DRIP_TOP}\" r=\"${d.width * 0.72}\" ${paint}/>`,\n ).join(\"\");\n const outline = `fill=\"{{outline}}\" stroke=\"{{outline}}\" stroke-width=\"{{stroke}}\"`;\n const pop = (from: number, to: number) =>\n [`translate(200 100) scale(${from}) translate(-200 -100)`, `translate(200 100) scale(${to}) translate(-200 -100)`] as [string, string];\n return {\n svg: `<svg viewBox=\"0 0 400 200\"><!-- {{word: text default=SLOP label='Word'}} {{fill: color default=#FF7EB6 label='Fill'}} {{outline: color default=#3A0A2C label='Outline'}} {{shine: color default=#FFD1E6 label='Shine'}} {{drip: float min=0.2 max=2 default=1 label='Drip length'}} {{stroke: float min=0 max=14 default=7 step=0.5 label='Outline width'}} --><g id=\"word\" transform=\"${pop(0.6, 1)[0]}\" opacity=\"0\">${drips(\"o\", outline)}${word} fill=\"none\" stroke=\"{{outline}}\" stroke-width=\"{{stroke}}\">{{word}}</text>${drips(\"f\", `fill=\"{{fill}}\"`)}${word} fill=\"{{fill}}\">{{word}}</text>${DRIPS.map(\n (d, i) => `<circle id=\"s${i}\" cx=\"{{shine${i}}}\" cy=\"${DRIP_TOP}\" r=\"${d.width * 0.2}\" fill=\"{{shine}}\" opacity=\"0\"/>`,\n ).join(\"\")}</g></svg>`,\n animate: [\n { id: \"word\", attrs: { transform: pop(0.6, 1.08), opacity: [0, 1] }, ms: 260, ease: \"out\" },\n { id: \"word\", attrs: { transform: pop(1.08, 1) }, delay: 260, ms: 200, ease: \"in-out\" },\n ...DRIPS.flatMap((d, i): SvgAnimation[] => {\n const at = { delay: 400 + d.delay, ms: d.ms, ease: \"in-out\" as const };\n const tip = `{{tip${i}}}` as unknown as number;\n return [\n ...([\"o\", \"f\"] as const).flatMap((layer): SvgAnimation[] => [\n { id: `${layer}r${i}`, attrs: { height: [0, `{{len${i}}}` as unknown as number] }, ...at },\n { id: `${layer}c${i}`, attrs: { cy: [DRIP_TOP, tip] }, ...at },\n ]),\n { id: `s${i}`, attrs: { cy: [DRIP_TOP, tip], opacity: [0, 0.9] }, ...at },\n ];\n }),\n ],\n };\n })(),\n};\n\nexport const vectorEffects: VectorEffect[] = [\n spinner,\n bouncingDots,\n pulsePing,\n equalizer,\n progressRing,\n barChart,\n lineChart,\n statCounter,\n route,\n timelineTrack,\n successCheck,\n errorCross,\n heartbeat,\n signature,\n confetti,\n blobMorph,\n dripText,\n flowNetwork,\n];\n","/**\n * The effect catalog: ready-made shader and vector effects, each with\n * controls and presets, to drop into a product or start an edit from.\n *\n * - Browsing: `EFFECTS`, `getEffect`, `findEffects`, `EFFECT_CATEGORIES`.\n * - Controls: `effectControls`, `effectDefaults`.\n * - Vector effects: their pictures declare their controls (`vectorControls`),\n * and `renderVectorEffect` fills them in.\n *\n * @packageDocumentation\n */\n\nimport { controlValue, parseControls, type ControlDef, type ControlValue } from \"../shader/controls.js\";\nimport { aurora, conicSweep, duotoneFlow, meshGradient, silk } from \"./shaders/gradients.js\";\nimport {\n crt,\n filmGrain,\n imageDuotone,\n imageGlitch,\n imageHalftone,\n imagePixelate,\n imageRipple,\n transitions,\n} from \"./shaders/image.js\";\nimport { blackHole, bokeh, godRays, lightRibbons, nebula, neonRipple, sparkles, starfield } from \"./shaders/light.js\";\nimport { caustics, flames, lavaLamp, marble, plasma, smoke } from \"./shaders/organic.js\";\nimport { barberStripes, dotWave, hexPulse, kaleidoscope, moire, neonCircuit, truchet, voronoi } from \"./shaders/patterns.js\";\nimport { digitalRain, pixelSunset, synthwaveGrid, tvStatic } from \"./shaders/retro.js\";\nimport { EFFECT_CATEGORIES, vectorEffectControls, type EffectCategory, type EffectDefinition, type ShaderEffect } from \"./types.js\";\nimport { vectorEffects } from \"./vector.js\";\n\nexport {\n colorControl,\n EFFECT_CATEGORIES,\n numberControl,\n renderVectorEffect,\n VECTOR_CONTROL_TYPES,\n vectorControlDef,\n vectorControlIssues,\n vectorControls,\n vectorEffectControls,\n type EffectCategory,\n type EffectDefinition,\n type EffectPreset,\n type ShaderEffect,\n type VectorControl,\n type VectorEffect,\n} from \"./types.js\";\nexport { SAMPLE_IMAGES, svgDataUrl } from \"./images.js\";\nexport { FBM, glsl, HASH, NOISE, OKLAB_MIX, PALETTE, ROTATE } from \"./glsl.js\";\n\n/** The catalog's shader effects. */\nexport const SHADER_EFFECTS: readonly ShaderEffect[] = [\n meshGradient,\n aurora,\n duotoneFlow,\n conicSweep,\n silk,\n marble,\n smoke,\n lavaLamp,\n plasma,\n caustics,\n flames,\n dotWave,\n truchet,\n hexPulse,\n voronoi,\n moire,\n kaleidoscope,\n barberStripes,\n neonCircuit,\n bokeh,\n godRays,\n sparkles,\n neonRipple,\n lightRibbons,\n starfield,\n nebula,\n blackHole,\n synthwaveGrid,\n digitalRain,\n pixelSunset,\n tvStatic,\n imageRipple,\n imageGlitch,\n imageDuotone,\n imageHalftone,\n imagePixelate,\n crt,\n filmGrain,\n ...transitions,\n];\n\n/** Every effect in the catalog, shaders first, grouped by category. */\nexport const EFFECTS: readonly EffectDefinition[] = [...SHADER_EFFECTS, ...vectorEffects].sort(\n (a, b) => EFFECT_CATEGORIES.indexOf(a.category) - EFFECT_CATEGORIES.indexOf(b.category),\n);\n\nconst byId = new Map(EFFECTS.map((e) => [e.id, e]));\n\n/** The effect with this id, or undefined. */\nexport function getEffect(id: string): EffectDefinition | undefined {\n return byId.get(id);\n}\n\nexport interface EffectQuery {\n /** Words to look for in the name, description, tags and id (all must match). */\n text?: string;\n category?: EffectCategory;\n kind?: EffectDefinition[\"kind\"];\n /** Effects with every one of these tags. */\n tags?: readonly string[];\n}\n\n/** Effects matching a query, in catalog order. */\nexport function findEffects(query: EffectQuery = {}): EffectDefinition[] {\n const words = (query.text ?? \"\").toLowerCase().split(/\\s+/).filter(Boolean);\n return EFFECTS.filter((e) => {\n if (query.category && e.category !== query.category) return false;\n if (query.kind && e.kind !== query.kind) return false;\n if (query.tags && !query.tags.every((t) => e.tags.includes(t))) return false;\n const haystack = [e.id, e.name, e.description, e.category, ...e.tags].join(\" \").toLowerCase();\n return words.every((w) => haystack.includes(w));\n });\n}\n\n/** An effect's controls: a shader's `@control` uniforms, or a vector effect's declared controls. */\nexport function effectControls(effect: EffectDefinition): ControlDef[] {\n return effect.kind === \"shader\" ? parseControls(effect.source) : vectorEffectControls(effect);\n}\n\n/** An effect's values: each control's default, overridden by `values` (and a preset by name, when given). */\nexport function effectDefaults(\n effect: EffectDefinition,\n options: { preset?: string; values?: Record<string, ControlValue> } = {},\n): Record<string, ControlValue> {\n const preset = options.preset ? effect.presets?.find((p) => p.name === options.preset)?.values : undefined;\n const merged = { ...preset, ...options.values };\n return Object.fromEntries(effectControls(effect).map((c) => [c.name, controlValue(c, merged)]));\n}\n"],"mappings":"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","names":["link"]}