Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Create a dark monochrome procedural background with enlarged square pixels and visible Bayer-style ordered dithering. Use when a page needs an atmospheric near-black dither field, broad organic waves or cloud masses, and restrained gray-white highlights behind framed UI, hero content, or data overlays.
.claude/skills/mengto-dither-background/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 20% | 0% |
| case-02 | ✗→✓ | ▲ Improved | -6% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 50% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 37% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 70% | 0% |
html<canvas class="dither-background" data-dither-background></canvas>
css.dither-background { position: fixed; inset: 0; z-index: 0; width: 100vw; height: 100vh; background: #030303; pointer-events: none; } .page-content { position: relative; z-index: 1; }
Use a real canvas when motion or procedural depth is needed.
jsconst BAYER_4X4 = [ 0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5, ].map((value) => (value + 0.5) / 16); function smoothstep(edge0, edge1, value) { const t = Math.max(0, Math.min(1, (value - edge0) / (edge1 - edge0))); return t * t * (3 - 2 * t); } function noise2(x, y) { const value = Math.sin(x * 127.1 + y * 311.7) * 43758.5453123; return value - Math.floor(value); } function valueNoise(x, y) { const ix = Math.floor(x); const iy = Math.floor(y); const fx = x - ix; const fy = y - iy; const ux = fx * fx * (3 - 2 * fx); const uy = fy * fy * (3 - 2 * fy); const a = noise2(ix, iy); const b = noise2(ix + 1, iy); const c = noise2(ix, iy + 1); const d = noise2(ix + 1, iy + 1); return ( a * (1 - ux) * (1 - uy) + b * ux * (1 - uy) + c * (1 - ux) * uy + d * ux * uy ); } function fbm(x, y) { let value = 0; let amplitude = 0.5; let frequency = 1; for (let octave = 0; octave < 4; octave++) { value += valueNoise(x * frequency, y * frequency) * amplitude; frequency *= 2.02; amplitude *= 0.5; } return value; } function initDitherBackground(canvas, options = {}) { if (!canvas) return () => {}; const ctx = canvas.getContext("2d", { alpha: false }); if (!ctx) return () => {}; const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches; const cell = options.cellSize || 7; const maxDpr = options.maxDpr || 1.5; let width = 1; let height = 1; let cols = 1; let rows = 1; let rafId = 0; const palette = options.palette || [ [3, 3, 3], [16, 16, 17], [34, 35, 37], [74, 75, 78], [168, 169, 171], [236, 236, 232], ]; function resize() { const dpr = Math.min(window.devicePixelRatio || 1, maxDpr); width = Math.max(1, window.innerWidth); height = Math.max(1, window.innerHeight); canvas.width = Math.floor(width * dpr); canvas.height = Math.floor(height * dpr); canvas.style.width = `${width}px`; canvas.style.height = `${height}px`; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); cols = Math.ceil(width / cell); rows = Math.ceil(height / cell); } function sampleField(x, y, time) { const nx = (x / cols - 0.5) * 2; const ny = (y / rows - 0.5) * 2; const distance = Math.sqrt(nx * nx * 0.84 + ny * ny * 1.28); const vignette = 1 - smoothstep(0.18, 1.15, distance); const drift = reduceMotion ? 0 : time * 0.018; const wave = Math.sin(nx * 2.8 + ny * 1.2 + drift) * 0.18 + Math.sin(nx * -1.4 + ny * 3.8 - drift * 0.8) * 0.14; const cloud = fbm(nx * 1.35 + drift * 0.16, ny * 1.35 - drift * 0.08); const ridge = smoothstep(0.48, 0.92, cloud + wave); const offAxisMass = smoothstep(0.98, 0.18, Math.hypot(nx + 0.22, ny - 0.08)); return Math.max(0, Math.min(1, ridge * vignette * 0.92 + offAxisMass * 0.18)); } function render(time = 0) { const seconds = time * 0.001; ctx.fillStyle = "rgb(3,3,3)"; ctx.fillRect(0, 0, width, height); for (let y = 0; y < rows; y++) { for (let x = 0; x < cols; x++) { const threshold = BAYER_4X4[(y % 4) * 4 + (x % 4)]; const brightness = sampleField(x, y, seconds); const stepped = Math.floor(Math.max(0, Math.min(0.999, brightness + threshold * 0.18)) * palette.length); const color = palette[Math.min(palette.length - 1, stepped)]; ctx.fillStyle = `rgb(${color[0]},${color[1]},${color[2]})`; ctx.fillRect(x * cell, y * cell, cell, cell); } } if (!reduceMotion) rafId = requestAnimationFrame(render); } function handleResize() { cancelAnimationFrame(rafId); resize(); render(); } resize(); render(); window.addEventListener("resize", handleResize); return () => { cancelAnimationFrame(rafId); window.removeEventListener("resize", handleResize); }; } const cleanupDither = initDitherBackground( document.querySelector("[data-dither-background]"), { cellSize: 7, maxDpr: 1.5, } );
5px-10px; larger cells make the Bayer matrix more legible.wave, cloud, ridge, and offAxisMass to create broad masses.cellSize or cap maxDpr before simplifying the field.pointer-events: none.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 23,691 | 17,162 | -28% | 1 | 1 | 0% | 5,416 | 6,487 | +20% | 0 | 0 | — |
case-02 | fail→pass | 27,436 | 14,445 | -47% | 1 | 1 | 0% | 6,194 | 5,853 | -6% | 0 | 0 | — |
case-03 | fail→fail | 25,968 | 21,515 | -17% | 1 | 1 | 0% | 5,443 | 6,367 | +17% | 0 | 0 | — |
case-04 | pass→pass | 11,668 | 11,934 | +2% | 1 | 1 | 0% | 1,865 | 4,977 | +167% | 0 | 0 | — |
case-05 | fail→pass | 11,060 | 3,516 | -68% | 1 | 1 | 0% | 1,953 | 2,921 | +50% | 0 | 0 | — |
case-06 | fail→pass | 21,391 | 4,357 | -80% | 1 | 1 | 0% | 2,195 | 3,013 | +37% | 0 | 0 | — |
case-07 | fail→pass | 11,682 | 4,806 | -59% | 1 | 1 | 0% | 1,833 | 3,107 | +70% | 0 | 0 | — |
case-08 | pass→pass | 11,059 | 7,439 | -33% | 1 | 1 | 0% | 2,116 | 3,651 | +73% | 0 | 0 | — |
case-09 | pass→pass | 12,918 | 6,545 | -49% | 1 | 1 | 0% | 2,118 | 3,462 | +63% | 0 | 0 | — |
case-10 | pass→pass | 13,925 | 11,480 | -18% | 1 | 1 | 0% | 2,419 | 4,248 | +76% | 0 | 0 | — |
case-11 | pass→pass | 7,741 | 4,266 | -45% | 1 | 1 | 0% | 1,282 | 2,871 | +124% | 0 | 0 | — |
case-12 | pass→pass | 9,156 | 4,706 | -49% | 1 | 1 | 0% | 1,817 | 3,184 | +75% | 0 | 0 | — |
case-13 | pass→pass | 14,092 | 17,881 | +27% | 1 | 1 | 0% | 3,218 | 6,358 | +98% | 0 | 0 | — |
case-14 | pass→pass | 13,686 | 12,803 | -6% | 1 | 1 | 0% | 2,840 | 4,868 | +71% | 0 | 0 | — |
case-15 | pass→pass | 13,649 | 15,883 | +16% | 1 | 1 | 0% | 3,015 | 5,718 | +90% | 0 | 0 | — |
case-16 | pass→pass | 10,289 | 2,931 | -72% | 1 | 1 | 0% | 1,837 | 2,731 | +49% | 0 | 0 | — |
case-17 | pass→pass | 12,177 | 6,970 | -43% | 1 | 1 | 0% | 2,221 | 3,751 | +69% | 0 | 0 | — |
case-18 | pass→pass | 12,680 | 7,129 | -44% | 1 | 1 | 0% | 1,874 | 3,442 | +84% | 0 | 0 | — |
case-19 | fail→pass | 15,004 | 12,228 | -19% | 1 | 1 | 0% | 3,032 | 4,406 | +45% | 0 | 0 | — |
case-20 | pass→pass | 9,910 | 6,527 | -34% | 1 | 1 | 0% | 1,595 | 3,364 | +111% | 0 | 0 | — |
case-21 | fail→pass | 12,680 | 10,205 | -20% | 1 | 1 | 0% | 2,170 | 4,014 | +85% | 0 | 0 | — |
case-22 | pass→pass | 13,598 | 9,842 | -28% | 1 | 1 | 0% | 2,704 | 4,252 | +57% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.