# Marbling Table — independent web starter

A small mobile-first browser playground for dropping colors and dragging a
stick or comb through them. All rendering, photo sampling, and saved gallery
data stay in the browser. No backend, accounts, network dependencies, tracking,
or native iOS app are required for this starter.

## Run

From this directory:

```
python3 -m http.server 8080 --bind 127.0.0.1
```

Open http://localhost:8080. The local server is only serving files; computation
runs in your browser. On an iPhone/iPad on the same trusted Wi-Fi, serve with
`--bind 0.0.0.0` and open `http://YOUR_COMPUTER_LAN_IP:8080`. Stop the server
when finished. A later static HTTPS deployment can make sharing easier.
Do not expect JavaScript modules to work when opening the HTML as a file URL.

## Included

- Drop displacement, a stick, comb presets and user-defined tine counts (1–15), width/spacing controls.
- Named palette colors with physical paint/mixing notes, browser color picker, local photo pixel sampling.
- Undo/redo by gesture, keyboard (Control/Command Z), deterministic action replay, immediate replay option.
- Drops bloom outward with a faint capillary ripple ring outrunning the edge as it settles; motion only ever follows your actions.
- Line-preserving raster warps with continuous segment tine tracking, preserving crisp filaments without premature diffusion across repeated strokes.
- First-run demo (five drops plus a comb sweep) plays once per browser, skips on
  reduced-motion settings, and stops the moment you touch the tray.
- PNG export, replay-video export (WebM/MP4 captured on-device, shared or
  downloaded), editable/versioned JSON export/import with paint notes, twelve-item snapshot gallery.
- Touch/pointer input, basic keyboard tool access, large controls, no sound or
  automatic motion. An autistic user's preferences should guide later design;
  this is not a clinical or therapeutic product.

The code uses Canvas 2D at a fixed 384x480 internal resolution. Scaling the
display does not silently change replay results. JavaScript runs on-device
already; native iOS is a later option if measured performance or platform
integration warrants it. PWA installation/offline caching is not yet included.

## What the model actually does

Drops push existing colors outward with a geometric map. Sticks/combs apply
localized raster warps. These operations give interactive visual feedback;
they are not a calibrated simulation of acrylic chemistry, surface tension,
bath rheology, pigment thickness, drying, or transfer to silk. Finite tray
edges and repeated raster interpolation introduce artifacts. Early-drop
thinning/disappearance and composition-dependent spreading are future work.
Photo pixels do not determine pigment recipes or color on a finished fabric.

## Verification

```
node --test tests/*.test.mjs
node scripts/browser-smoke.mjs
```

The first command checks deterministic replay, nested-drop behavior, imports,
and reversible editing primitives. The optional second command requires Node
22+ and a local Chrome/Chromium. Set `MARBLING_CHROME` to its executable path;
on this development Mac the script also recognizes an existing Playwright
Chromium cache. It adds no package dependency. Results/screenshots go in the
ignored `test-output/` folder. A Chromium mobile viewport is not a real Safari
or iOS-device test; those remain an acceptance gate before sharing broadly.

Gallery storage belongs to the browser/origin and may be cleared or evicted.
Export JSON to keep an editable copy outside it. Uploaded photos are decoded
locally and are not included in project exports; sampled colors are included.

Verification on 2026-09-23: all twelve core tests passed (deterministic replay,
nested/adjacent drops, parallel vs alternating combs, thin filaments, drop
settle-frame determinism, demo-scene determinism, settings round trip,
version-1 compatibility, import rejection, palette notes and custom tines round trip),
and `node --check app.mjs` / `node --check core.mjs` passed. The browser smoke script
passed in local Chromium at a 390x844 mobile viewport (load, demo autoplay + suppression,
drop, undo, redo, gallery save/open with overwrite guard auto-accepted, clear,
instant + animated replay, comb stroke, keyboard undo/redo, replay-video export
with the share sheet stubbed, simple-mode toggle, color names and paint notes,
custom comb tines, pattern snapshots with custom labels, no horizontal overflow,
no JS exceptions; screenshot in ignored `test-output/mobile-smoke.png`). No physical
iPhone/iPad Safari was available, so touch scrolling, pointer cancellation,
orientation changes, color/photo inputs, JSON restore, and PNG saving/sharing
on real devices remain unverified. Do not treat this starter as device-tested.

## Continue

Read STARTER_BRIEF.md, then give the next agent NEXT_TASK.md. SOURCES.md credits
inspiration and the relevant mathematical work. This project has no dependency
on the espresso engine and no shared state with it. The package is marked
private; a public license and publication are future owner decisions.
