DICE.
Colophon — Generative Assets

How DICE. was made

A fair die rolled without end, and the one thing it cannot escape: the average of its pips is dragged, roll by roll, onto three and a half. This page is the workshop behind that number.

01 The concept

DICE is a study of the Law of Large Numbers for an imagined mathematics-of-chance series. Its audience is anyone who has felt that a coin is "due" to land heads — the page answers that instinct. Its single job: show that individual rolls owe the past nothing, yet their running mean is nonetheless pulled onto the exact value 3.5, and to make that pull something you can both watch and hear.

The die rolls continuously on a walnut bench. Each roll adds a pip value; the running mean is plotted against the roll count on a logarithmic axis, so the wild early wobble and the late, patient settling both fit in one frame. Around 3.5 a funnel is drawn — the theoretical spread of the mean — and it visibly narrows as more rolls bank. At rest a few hundred rolls have already been thrown, so the trace arrives mid-convergence rather than blank.

02 Palette

Warm and low, argued from the object: a dice bench in lamplight, brass pips, one hot face.

Table walnut
#20160F
The ground — a dark, warm timber the felt and figures sit on.
Pip amber
#E0B24A
Brass-pip gold for the trace, funnel and marks. Lines and marks only.
Six accent
#B5502E
The hot face — reserved for a rolled six, in the die, pips and head dot.
Bone ink
#EDE4D2
Body text and the big mean readout — carved bone on walnut.
Amber ink
#EFCF8C
A lighter amber derived for small accent text that must pass 4.5:1.

The bright #E0B24A pip amber fails legibility as small copy on the dark bench, so it is held to strokes and marks only; body copy uses bone ink, and small accent labels use the lighter #EFCF8C. The six accent is a mark colour too — when it must speak as text it is lifted to #D9825A.

03 Type

Fraunces — display
Three and a half.
A high-contrast "old-style" serif with optical sizing. It carries the wordmark, the lede, and the huge ghosted 3.5 painted on the law line — the one moment of typographic nerve. Its warmth matches the walnut; its authority suits a stated law.
IBM Plex Mono — data
N = 40,231 · ±0.01
Every number — roll count, running mean, band width, axis ticks, tally labels — is set in Plex Mono with tabular figures, so digits do not jitter as they tick. It reads as instrumentation against the serif's voice.

04 Technique — the signature

Everything is procedural on three <canvas> layers — the convergence chart, the tumbling die, and the roll strip — with no raster assets. Rolls are true fair draws (1 + (Math.random()*6 | 0)); the running mean is sum / N.

The funnel is the piece worth explaining. The standard deviation of one fair die is √(35/12) ≈ 1.708. The standard error of the mean of N rolls is that over √N — so the mean's expected spread shrinks as 1/√N. The page draws two bands around 3.5: a 68% band at ±σ/√N and a 95% band at ±1.96σ/√N, sampled every few pixels across the log axis. That is the closing funnel, and the running-mean trace is arithmetically forced to thread it — the Law of Large Numbers, drawn rather than asserted.

Sound. Each roll is two Web Audio voices scheduled on a user gesture only: a short filtered-noise knock with a low triangle body (the die on wood), and a tuned pip-tone mapping the value 1–6 onto an A-minor pentatonic scale, so a six always answers an octave above a one. The page starts muted; a labelled toggle fades a master gain in and out, and every visual works in silence.

Performance follows the collection's floor: device-pixel-ratio capped at 2, canvases sized to their containers and rebuilt on resize, the render loop paused on document.hidden, and a settled static frame under prefers-reduced-motion (the mean is banked to a few hundred rolls and painted once, no loop).

05 Iteration log

Pass 1 — Craft

  • Set the mean readout on tabular figures so the ticking decimal no longer shifted the whole number sideways each frame.
  • Pulled the plot padding off the wordmark and the readout — the funnel had been running under the tagline; padT/padB now clear both zones at every width.
  • Split the ink tokens: demoted pip amber to marks-only and derived #EFCF8C for small accent text after the sub-labels measured under 4.5:1 on the walnut.
  • Rebalanced the funnel opacity — a single flat band read muddy, so it became a faint 95% wash under a stronger 68% core, which reads as depth rather than fog.

Pass 2 — Depth

  • Enriched the signature: added the big ghosted Fraunces 3.5 sitting on the law line, so the trace is seen chasing a named target, not an anonymous dashed rule.
  • Second-read detail — a rolled six turns hot: the die body, its pips, the trace head dot and the tally cell all shift to the six accent, and the knock drops a third lower. You notice the sixes are "louder" only on the second watch.
  • Tuned the die tumble easing and the tally slide so a new roll lands with a small bob-and-settle instead of a hard cut, timed just under the roll interval.
  • Gave the live head a slow breathing halo so the eye finds the current mean instantly amid the funnel.

Pass 3 — Hardening

  • 375px: collapsed the notes to one column, hid the tagline, shrank the readout and the mono controls, and shortened the tally cells so the strip never clips; verified the wordmark and nav sit inside the viewport.
  • Reduced motion: no loop runs — the bank is primed to ~420 rolls and painted once; Pause becomes a single-step "roll once" so the page is still explorable without animation.
  • Confirmed :focus-visible rings on every control and link, DPR cap and resize rebuild across the three canvases, and the rAF loop halting on tab-hide.
  • Removed one ornament (the Chanel rule): dropped a redundant vertical grid flourish behind the trace that competed with the funnel; the plot breathes better with only the log ticks.
Designed & built by Sapience Analytics — part of the Generative Assets collection.