# Felt tip

A nib deposits ink; the finished mark comes from the brush rather than a revealed silhouette.

## What it does

Caveat provides the starting letter geometry. The browser rasterizes it, extracts centrelines and local widths, and applies writing-order rules for the opening's stems, loops, shoulders, and dot. An angled elliptical nib then stamps overlapping pigment along those paths. The font bitmap is never used as the final ink mask: the simulated nib determines the visible edges.

Pressure varies gradually along a stroke, contact tapers at its ends, and the felt face is narrower across its short axis. Overlapping translucent deposits darken into a matte near-black. Tiny dry streaks and sparse paper-tooth breaks interrupt the solid ink. A low-opacity halo and a small increase in nib spread over approximately 550 ms suggest ink soaking into the fibres. Pauses and retraced joins make the motion read as a held marker. The default writing takes 4.3 seconds, then the final absorption settles and animation stops.

## Paper and typography

A warm sheet (`#f3efe4`) carries a little more tooth than the other versions, without seams, stains, edges, or doodles. The phrase occupies more of the desktop and becomes three lines on the phone. Caveat's loose hand is the source of the brush paths. DM Mono is the only face used for supporting text.

## Libraries and assets

No JavaScript library or WebGL dependency. Native Canvas 2D is sufficient for this small, deterministic nib simulation; a full fluid solver would add substantial work without answering the opening comparison. [Caveat](https://github.com/google/fonts/tree/main/ofl/caveat) and [DM Mono](https://github.com/google/fonts/tree/main/ofl/dmmono) are local WOFF2 fonts, with `Caveat-OFL.txt` and `DMMono-OFL.txt` included. All paper texture is procedural. No third-party imagery or generated lettering image is used.

## Known gaps

- This is a pressure-and-absorption approximation, not a fluid or paper-fibre simulation. It has no real hand-motion recording.
- Caveat supplies a different hand from the team's photograph. The photo was not traced or redrawn to make this version.
- Skeleton junctions can require additional stroke-order rules for arbitrary text. The default title was inspected and corrected; broader text remains exploratory.
- Canvas drawing costs more than V1's SVG reveal. Local measurements are in `shots/performance.json`; they measure headless Chrome on this Mac, not a physical phone or Safari.

## Verification

Rendered with the project's `concepts/tools/render.cjs`, using headless Chrome at 1440×900 and 390×844, with a 5000 ms settle and no scrolling. Both PNGs were inspected. Frozen writing frames at 900, 1800, 2800, 3700, and 5400 ms were also inspected, including partial letters. The evidence lives in `shots/`.

Replay works with a pointer and keyboard. Initial reduced motion, changing reduced-motion preference, and replay under reduced motion all show the finished line. The page does not scroll at 320×568, 390×844, 844×390, 1440×900, or 1920×1080. A readable static phrase remains with JavaScript disabled. All headless browser instances were closed after their checks.

## Controls and capture

Use the replay button to restart. Add `?t=1800` to freeze at an elapsed millisecond; `?t=0` shows the blank page. Reduced motion overrides this parameter. `window.demo.draw(ms)` is a deterministic capture hook. The page stops scheduling animation frames after the ink has settled.

## Local footprint

The HTML, script, loaded fonts, and ink asset total approximately 204.3 KiB before HTTP compression. There are no external runtime requests. In the local 390×844, DPR 2 headless check, initial readiness was 162 ms and mean JavaScript draw cost was 4.13 ms across thirty sample times. These are local measurements, not network-load or physical-device benchmarks.
