Kinetic Sand

sandkinetic

OpusSonnet
Opus$12.02 · 1h39m30s
Claude Opus 5.5$12.02 · 1h39m30s
Claude Opus 5.5 $12.02 · 1h39m30s
WinnerFastest
Sonnet$10.41 · 1h44m08s
Claude Sonnet 5.5$10.41 · 1h44m08s
Claude Sonnet 5.5 $10.41 · 1h44m08s
Cheapest

Opus wins. Opus's cut slab slumps, cracks and oozes apart like real kinetic sand; Sonnet cuts a crisper face but its crumbs break into blocky cubes.

Remix in Claude

Scorecard

Opus1Sonnet1

CriterionOpusSonnet
Slump and crumbleThe slab holds, a crack opens behind it, then it tilts and breaks into soft clumps that rejoin the sandBreaks into clumps with the layer colours, but they read as stacked cubes
Cut faceClean striated face; a fast cut sprays crumbsVery crisp, straight-edged layered face
Hand, Mold, Rake, RollerAll work; lift-and-pour stream, four molds, rake spirals, marbling rollerAll work; rake lines and prints show stair-steps up close
Sand stays sandMass conserved within 0.01% across every toolMass conserved within 0.03% after a 40-action abuse run
Easter eggA hidden dinosaur that says "Oh, hi."A hidden dinosaur revealed by the knife
Cost$12.02$10.41
Time1h39m30s1h44m08s
OverallWinner–

The prompt

Build **"Kinetic Sand"**: a real-time, interactive 3D tray of **cohesive kinetic sand** in pastel layers that people **slice** with a knife, **squish** and **lift** with their hand, **stamp** with molds, **rake** into patterns and **roll** smooth again, with **synthesised sound**, as ONE self-contained HTML file, rendered with **WebGPU (WGSL) and an automatic WebGL2 fallback**.

It should feel like the satisfying sand-cutting videos people watch on loop: a crisp, clean cut face that shows the coloured layers, a moment where the wall holds, then a slow slump as the slab cracks and crumbles off in soft clumps. No score you have to chase, no tutorial screens.

## Priorities

Build it in this order, and finish each tier properly before starting the next. A polished tier 1 beats a broken everything.

1. **Must be excellent:** the layered loaf, the Knife with crisp cut faces, the hold-then-slump-then-crumble behaviour, the sand look and the demo mode.
2. **Must work:** Hand (squish and lift), Mold, Rake, Roller, New block, Smooth tray, the sliders and switches, sound, the control card, the WebGL2 fallback, the Easter egg.
3. **Polish:** fine dust puffs, grain sparkle, blade striations on cut faces, the marbled colour mixing from the Roller, milestone toasts.

Never ship a feature half-working: if something from tier 3 can't be done well, leave it out cleanly.

## Deliverable

- One self-contained `.html` file with all JavaScript, WGSL, GLSL and CSS inline. Start the file with `<!doctype html>`, `<meta charset="utf-8">` and a viewport meta.
- **No external requests of any kind**: no libraries, CDNs, web fonts, images, textures or audio files. Generate everything procedurally in code (sound included). Use system font stacks.
- It must run inside a sandboxed iframe (`sandbox="allow-scripts allow-pointer-lock"`). Do not use `localStorage`, cookies, `alert`, pop-ups or top-level navigation, and wrap any storage access in `try/catch`.
- This must be a live simulation, not a video, a pre-baked animation, a static render or a 2D fake.

## The tray

- A shallow, pale birch-wood tray (about 40 x 30 cm, 4 cm rims, visible wood grain, softly rounded corners) on a warm off-white seamless studio sweep, seen from a **low three-quarter view**, so cut faces read clearly. The tray fills most of a square frame.
- In the middle sits a **loaf of kinetic sand** (about 22 x 9 x 8 cm) in four even horizontal layers, bottom to top: **butter yellow, lavender, mint, pink**. A thin loose bed of mixed sand covers the rest of the tray floor.
- The sand looks like real kinetic sand: very fine grain, matte with a faint soft sheen, slightly darker and smoother where it is packed or freshly cut, rough and grainy where it has crumbled.

## Physics

The sand is a **cohesive granular material**: it holds a sharp edge for a while, then creeps, cracks and breaks into soft clumps that pile up and re-join the mass. It is never a fluid and never a rigid solid.

- Recommended approach (choose another only if it gives the same results): a **3D grid of sand cells** (about 160 x 64 x 120 over the tray on desktop, fewer on phones) where each cell stores fill, a **colour / layer id** and a **bond** value (how strongly it sticks to its neighbours), plus a pool of **clump bodies** for pieces that break free and fine **crumb particles** for dust and pouring. Clumps that come to rest deposit back into the grid with their colours intact.
- **Cohesion and slump:** a vertical cut face is stable at first. Bonds near an unsupported face slowly weaken (rate set by the Slump speed and Cohesion sliders). When a connected region's support fails, a **crack opens a few millimetres behind the face**, the slab peels away, tilts, and **breaks along its weakest bonds** into clumps of many sizes that tumble and settle into a small pile (a talus) at the base. Faces cut at a shallow angle hold longer than thin overhangs.
- **Layers are preserved:** every cut face, clump, crumb and pile shows the true colours of the cells it came from. Layers never smear into one colour unless the Roller marbles them.
- **Mass is conserved** within about 2% across every action.
- Never: sand passing through the tray or its rims, clumps sinking into or tunnelling through the mass, jitter at rest, pieces hanging in mid-air with no support for more than a few seconds, or explosions.
- **Fixed simulation timestep** with bounded substeps, decoupled from frame rate. On a slow frame, drop simulation time rather than exploding.

## Tools

A tool picker with **1 Knife**, **2 Hand**, **3 Mold**, **4 Rake** and **5 Roller**. The default tool is Knife. A press that ends within 6 px and 450 ms counts as a tap. Right-drag, dragging empty background, or two fingers orbit the camera. Use pointer events with **pointer capture** so drags never drop, and support mouse, pen and touch.

### Knife
- Dragging across the sand draws a thin vertical blade along the path (projected onto the sand), cutting straight down to the tray floor. The blade is visible: a short, thin, slightly reflective metal edge that follows the drag.
- **Speed decides the cut:** a slow drag gives a **glassy, clean face** with fine horizontal blade striations and crisp layer lines; a fast drag gives a rougher face with grains breaking off the top edge and a spray of crumbs.
- The cut face **holds** for about 0.6 to 2 s (longer when wet), then the thinner side slumps and crumbles as described in Physics. A slice thinner than about 1.5 cm freed on both sides falls over as a slab and breaks on landing.
- Curved cuts and crossing cuts work; cubes can be diced out of the loaf.

### Hand
- **Tap:** a single fingertip dent with a crisp rim.
- **Press and hold:** the palm pushes in with **five finger dents**, the sand bulging up and cracking around the edges; release leaves a clean print.
- **Press and drag (or pinch on touch):** grabs the chunk under the hand and **lifts it into the air**. The chunk dangles, crumbles from its edges and **pours a thin stream** back down that piles where it lands. Releasing drops it with a soft splat.

### Mold
- A small mold picker in the card: **Star**, **Heart**, **Cube**, **Castle** (`F` cycles them). A translucent ghost of the mold follows the pointer over the sand.
- **Tap:** turns out a packed shape: the mold presses down, fills from the sand around it (leaving a shallow dip), and lifts off to leave a **crisp standing shape** in the local layer colours, which slowly sags and crumbles at its corners over 10 to 20 s.
- **Hold:** presses the mold in like a cookie cutter; release lifts it, leaving a sharp imprint.

### Rake
- Dragging pulls a five-tine wooden rake through the surface, leaving **parallel grooves with soft ridges** and a few crumbs. Deep enough grooves reveal the next layer colour at their bottoms. Spirals and circles make zen patterns.

### Roller
- Dragging rolls a wooden rolling pin over the sand: heaps flatten, crumbs re-join, and surfaces turn smooth and slightly glossy. Repeated passes push the sand back towards a neat block. Colours are kept, but rolled sand **marbles** softly where layers are pressed together.

### Buttons
- **New block:** the tray clears and a fresh layered loaf presses back into shape in about 0.6 s with a soft thump.
- **Smooth tray:** all sand settles into one smooth, even bed across the tray, keeping its colours.

## Goal and Easter egg

- No required goal. Milestone toasts (once each per session): **"First slice."**, **"Clean cut."** (a slow cut longer than 15 cm with no crumbs), **"Ten slices."**, **"Diced."** (cut a cube free on four sides), **"Zen garden."** (a raked spiral or full circle), **"Total crumble."** (more than half the loaf turned into clumps).
- **Easter egg:** a tiny green toy dinosaur (about 2 cm) is buried at a random spot inside every new loaf. It is invisible until a knife cut passes through it: the cut face shows its cross-section, then it pops out of the sand, stands up, waves once, and a small toast says **"Oh, hi."** with a tiny chime. Never hint at it in the UI.

## Sound

Every action has a **synthesised sound**, generated live with the **Web Audio API** (oscillators, filtered noise, envelopes). **No audio files, no samples.** It should sound like a quiet ASMR recording.

- **Knife:** a soft, crisp "shhk" (fine high-passed noise grains) that follows blade speed; slow is a long gentle hiss, fast is crunchier.
- **Slump and crumble:** a low soft "fwump" as the slab lets go, then a patter of small dull ticks as clumps land.
- **Hand:** a muffled squelch-crunch on press, a fine sifting hiss while a lifted chunk pours, a soft splat on drop.
- **Mold:** a pat on press and a small hollow pop on lift.
- **Rake:** a dry rhythmic scratch that follows speed. **Roller:** a low smooth rumbling crunch.
- **New block:** a soft thump. **Easter egg:** a tiny two-note chime. **Toasts:** a very soft tick.

Rules:
- Create the `AudioContext` only on the first user gesture, never before. Resume a `suspended` context on interaction, and wrap every audio call in `try/catch` so a failure can never break the toy.
- Master gain -> compressor / limiter, no clipping. Cap simultaneous voices at about 16.
- A **mute button** with a speaker icon, **sound on by default**; `M` toggles it.

## Camera and keys

- **Camera:** orbit within limits (yaw ±70°, pitch from 12° to 70° above the tray), wheel or pinch to zoom from the full tray down to a close-up of a cut face. Double-click empty background or `0` resets the view.
- **Keyboard:** `1` Knife, `2` Hand, `3` Mold, `4` Rake, `5` Roller, `F` next mold shape, `N` New block, `S` Smooth tray, `L` toggles layers, `C` Cinema, `M` mute, Space pauses or resumes, `R` resets everything (new block, default sliders, default view), `0` resets the view.

## Rendering (WebGPU with WebGL2 fallback)

- **WebGPU (WGSL) when available, with an automatic WebGL2 fallback that looks the same.** Detect at start; if WebGPU is missing or adapter / device creation fails, use WebGL2. No libraries: write both paths yourself, sharing the scene data and the simulation. Show which one runs in the status pill: `WEBGPU · LIVE` or `WEBGL2 · LIVE`.
- The sand surface is extracted from the grid (surface nets, marching cubes or ray marching) and updated only where it changed. Colour comes from the cells, blended softly across layer boundaries (about 1 mm) so lines are crisp but not aliased.
- **Grain:** fine procedural normal noise and tiny sparkle specks on rough surfaces; cut faces smoother, slightly darker and denser, with faint blade striations.
- **Light:** soft studio daylight from the upper left plus a large soft fill, **soft shadows** (shadow map with filtering) so cut faces and slabs cast clear shadows, ambient occlusion in grooves, dents and cracks. Filmic tone mapping, gentle vignette, no heavy bloom. The image must stay crisp.
- Clumps and crumbs are instanced, lit and shadowed like the main mass.
- Preallocate every buffer, pipeline and instance pool at start (cells, clumps, crumbs, surface vertices). Never create shaders, pipelines or geometry during interaction. Handle resize; cap device-pixel ratio at 2.
- An automatic **quality scaler**: if the frame rate drops, lower render resolution, shadow resolution and crumb count before ever touching grid resolution or the physics feel.
- Only if neither WebGPU nor WebGL2 exists, show a clear, well-designed message explaining what the piece needs.

## Interface

A calm, light interface that stays out of the way. The sand is the hero; UI must never cover the loaf on desktop or mobile.

**Top left:** small caps `POKEABLE · SPECIMEN 007`; a large italic serif heading on two lines: *Kinetic* / *Sand.*; caption lines: "Slice it." / "Squish it." / "It never sticks to you."

**Top right:** a live status dot with `WEBGPU · LIVE` or `WEBGL2 · LIVE`, a **speaker icon button** (`ON` / `MUTED`), and `PAUSED` when paused.

**Right: control card "Sand tray"**, a floating card about 240px wide, 20px corners, soft off-white, soft drop shadow, no hairline borders, plain system sans, with a **dusty coral accent**. Bold sentence-case title and section labels; tools as rounded tiles with small drawn icons and key numbers (active tool tinted and ringed in the accent); chunky sliders (6px rounded track filled with the accent, round white thumb) with live values in small rounded monospace chips; secondary buttons as light-grey chips without borders; on/off switches (label left, switch right); **Pause / Resume** as a solid dark full-width pill. The card collapses to a small button; on narrow screens it becomes a bottom sheet with rounded top corners.

- Tools: **Knife**, **Hand**, **Mold** (with the Star / Heart / Cube / Castle picker shown when active), **Rake**, **Roller**.
- Sliders: **Cohesion** (dry to wet: dry crumbles almost at once into small grains, wet holds sharp faces long and breaks into big soft clumps), **Slump speed** (0.25x to 3x), **Sound** (master volume).
- Buttons: **New block**, **Smooth tray**.
- Switches: **Slow motion** (¼ speed), **Show layers** (on by default; off renders all sand in one natural beige so shapes read by light alone), **Cinema**.
- **Pause / Resume**.

**Bottom left:** a one-line hint per tool:
- Knife: "Drag to slice. Slow is clean, fast is crumbly."
- Hand: "Tap to poke, hold to squish, drag to lift a chunk."
- Mold: "Tap to turn out a shape. Hold to press one in."
- Rake: "Drag to draw grooves. Try a spiral."
- Roller: "Drag to roll it smooth again."

Under it, live readouts from the simulation: **slices**, **cleanest cut** (%), **sand disturbed** (% of the loaf), **clumps falling**. Values update smoothly, not every frame.

**Bottom right:** a collapsible **"How it works"** panel, 4 to 6 plain-English lines: the sand is a grid of sticky cells with colours; cuts weaken the bonds near the face; when support fails, a crack opens and the slab breaks into clumps; clumps rejoin the sand when they land; sounds are synthesised live.

**Toasts** appear top centre for milestones. **Cinema** (`C`) hides all UI and the cursor; a tap (without drag), `C` or Esc brings it back.

Respect `prefers-reduced-motion`: soften UI transitions and camera moves. The sand still responds fully.

## Test hook

If the URL has `?test=1`, expose `window.__toy` with no visible change: `setTool(name)`, `setMold(shape)`, `slice(points, speed)`, `press(x, z, ms)`, `lift(x, z, path)`, `mold(x, z, hold)`, `rake(points)`, `roll(points)`, `newBlock()`, `smoothTray()`, `set(param, value)` for every slider and switch, `step(seconds)` to advance the simulation, and `state()` returning `{ tool, renderer, paused, sandVolume, clumpsFalling, slices, cleanestCut, dinoFound, fps }`. Points are in tray centimetres.

## Demo mode (required)

If the URL has `?demo=1`, auto-play a 4-second loop with no user input: the object drops in, wobbles, gets poked or sliced once, then settles.

For this toy that means:
- **Hide all UI** and the cursor. Only the tray, the sand and the knife are visible.
- One **fixed demo quality preset** (no quality scaler), default sliders, layers on, no dinosaur in the loaf.
- **Never create an `AudioContext`**; play nothing.
- A fixed camera at the default low three-quarter view, the tray filling the square frame.
- Deterministic (fixed seed, no randomness); restart every **4.0 s of real time** from the identical state. Drive the simulation from real elapsed time with the fixed timestep.
- **0.0 to 0.5 s:** the loaf settles onto the tray with a tiny squash and a few crumbs.
- **0.5 to 1.2 s:** the knife enters from the right and makes one slow, straight, clean pass across the loaf about a third from its front end, reaching the tray floor by **1.0 s**.
- **1.2 to 1.8 s:** the cut face holds, showing four crisp layers in the light; a hairline crack appears behind it.
- **1.8 to 3.2 s:** the slab peels off, tilts forward and crumbles into clumps that tumble and pile at the base, with a puff of fine crumbs.
- **3.2 to 3.5 s:** the pile settles.
- **3.5 to 4.0 s:** the sand smoothly gathers back into the whole loaf (an eased reform), so the frame at 4.0 s matches 0.0 s exactly.
- Start moving within 1 second of page load. It is recorded in a slow software renderer: **the cut face and the slump must read clearly at 15 fps** (use a coarser grid and fewer crumbs in demo if needed, but keep the faces crisp).
- `?demo=1&t=<seconds>` freezes the demo at that time (for screenshots).

## Before you finish

Self-check against this list and fix anything that fails:
- Slice slowly, quickly, curved and crossing; dice a cube; cut a thin slice. Faces are crisp, hold, then slump and crumble with the right layer colours; nothing jitters, sinks or floats.
- Every tool: tap, hold and drag the Hand, all four molds by tap and hold, rake a spiral, roll everything flat; New block, Smooth tray, R, every slider at both extremes, both switches, Slow motion, Pause, Cinema, keys 1 to 5, F, N, S, L, C, M, 0, Space, resizing to phone width, touch with two fingers.
- Find the dinosaur. Check that mass stays within 2% after five minutes of abuse.
- Sound: every action has its effect, nothing plays before the first gesture, mute and volume work, rapid actions never clip or pile up.
- `?demo=1` matches the timeline, loops cleanly, shows no UI and plays no sound; `?test=1` exposes `window.__toy`.
- No console errors or WebGPU validation errors on **WebGPU AND WebGL2**, and it stays smooth on a mid-range phone.

Put the clean cut face and the slow slump first. It should be something people slice once to try and then can't stop slicing.

More toys

All toys →