Continua
The build · Generative Assets

A grid that is always dying

CONTINUA is a fictional lab instrument for watching SmoothLife — a continuous-domain cellular automaton — behave. Its single job: let a visitor paint life into a phosphor field and watch continuous gliders, blobs and colonies crawl, self-replicate and starve in real time. No stock imagery, no video: every pixel is computed by a shader on the GPU.

01The concept

Conway's Game of Life is binary and discrete — cells are on or off, neighbours are counted in whole numbers. In 2011 Stephan Rafler generalised it to the continuum: replace the neighbour count with an integral over two disks and the hard birth/death rules with smooth sigmoids. The result is an organism-like automaton whose gliders truly glide. CONTINUA dresses that mathematics as a phosphor readout — a lab terminal for a thing that is never fully alive and never fully dead.

02Palette

A phosphor-monitor palette, argued from the subject. The bright accents are reserved for marks and life; body text runs on a calmer pale-phosphor ink so it always clears 4.5:1 over the dark field.

Void
#0A0A06
The dead substrate. Near-black with a green undertone so it reads as screen, not paper.
Life mint
#33D6A6
Stable, living density. Phosphor P1 green pushed toward cyan. Marks and links only.
Plasma gold
#F2B840
The membrane and hot cores — cells changing fastest. Used sparingly, as a rim.
Grid
#0F1410
The lattice every cell sits on. Structure without state — a faint constant.

Text tokens: pale phosphor #CFE9DD for body, muted #89AA9C for secondary, gold-ink #B58421 for small categorical labels — never bright gold on the field.

03Type

Unica One — a condensed all-caps display face with an engineered, slightly retro-technical feel — carries every headline and number. IBM Plex Mono handles body, labels and the parameter table: it makes the copy read like instrument output and lets the equation and thresholds sit in honest, tabular figures.

Paint Life.
Unica One · display, .86 line-height, tight tracking
σ(n,m) · dt 0.115
IBM Plex Mono · body & readouts, tabular nums

The typographic bravery is scale contrast: an 8 vw Unica headline stacked hard against 12 px mono labels, and four oversized decimal thresholds (.257 .336 .365 .549) set as display figures — the rule itself becomes the ornament.

04Technique — the signature element

The field is a WebGL2 fragment-shader SmoothLife simulation, no libraries. State lives in a floating-point (RGBA16F) texture, one cell per texel, and is advanced by ping-ponging between two framebuffers. Each tick the simulation shader convolves the neighbourhood: for every cell it sums density over an inner disk (radius r/3) and an outer ring (radius r=11), then feeds those two averages m and n through Rafler's smooth transition s' = s + dt·(2·σ(n, σₘ(b1,d1,m), σₘ(b2,d2,m)) − 1). The grid wraps toroidally via REPEAT sampling. A second display shader maps density to the phosphor palette — mint for the living bulk, a thin gold rim where the local gradient is steepest — and stamps the cell lattice and a faint scanline.

Painting is done in the same simulation shader: pointer position is projected into grid space and passed as a brush uniform, injecting density within a small radius every tick, so cursor trails become living seeds. If the WebGL2 context or a floating-point render target is unavailable, the canvas is swapped for a static CSS phosphor scene so the hero is never blank.

05Iteration log

1Craft

Colour balance & contrast

  • First render washed to cream/white: the additive gold membrane plus a gold "hot-core" term fired across the whole high-density labyrinth, drowning the mint. Rebuilt the display ramp as void → deep mint → mint → bright-mint crest, cut gold to a thin gradient-gated rim at 0.5 strength, and removed the hot-core term. The field now reads as true phosphor life.
  • The small mint eyebrow sat over randomly-seeded bright blobs — contrast dipped below 2:1 on some loads. A global scrim couldn't fix a randomly-placed blob without killing the art, so gave the eyebrow its own dark terminal-label backing (matching the interaction chip). Guarantees legibility regardless of the field beneath.
  • Tightened the type scale: fixed the Unica headline to .86 line-height, aligned the parameter table's tabular values, and set the four birth/survival thresholds as display figures for deliberate scale contrast.
2Depth

Enrich the signature, add a second read

  • Added a second-read detail: the field spontaneously births a new colony every 10–16 seconds at a random cell, injected through the same brush path. Life keeps emerging from the void even when the cursor is idle — you notice it only on a second, longer look, and it stops the grid ever settling into a static death.
  • Refined the brush: hover paints a soft, low-amplitude seed; press-drag paints a stronger, wider splash — so a deliberate click births a colony while a passing cursor only nudges the field.
  • Ran two simulation ticks per frame so gliders visibly crawl at 60fps rather than creeping, then clamped the frame delta so a background tab can't fast-forward the automaton on resume.
3Hardening

Responsive, motion, performance

  • 375px: the parameter panel's white-space:nowrap equation forced its grid column to min-content, pushing the page to 472px wide. Grid children were still min-width:auto; setting min-width:0 let the equation scroll inside its own box. Verified nav, wordmark and headline all sit inside the 375 viewport (not just scrollWidth ≤ 375).
  • Reduced-motion: no rAF loop starts — the simulation is stepped 70 times synchronously and drawn once as a settled organic frame, never blank. Verified with an emulated prefers-reduced-motion load: zero errors, reveals applied, static field rendered.
  • Capped DPR at 2, decoupled the simulation grid from display resolution, debounced ResizeObserver, and paused the loop on document.hidden. Removed one redundant ornament (a bottom-left radial wash behind the hero text) now that the strengthened scrim and eyebrow chip carry contrast — the Chanel rule.

06Verification

Checked in headless Chrome (puppeteer-core) against the live route with a real 7-second settle: zero console errors, WebGL context live and canvas non-zero, hero and cursor-paint exercised, and no horizontal overflow at 375 px with nav and wordmark confirmed inside the viewport box. Reduced-motion and a fresh random seed each load were both verified visually.