# Tapedrive brand tools

Editors that produce slide graphics with the website's own renderers, so
presentation art matches the site exactly.

- `tear.html` composes the chromatic section transition onto a slide.
  Light or dark surface, tear at the top, bottom, or both, halftone height
  and offset, a seed for reproducibility, play and pause. Exports SVG and
  PNG at 1x to 4x.
- `particles.html` renders a twilight particle field: squares of the
  opposite color rise, spin on their vertical axis with perspective, and
  fade out. Count, size, depth, motion, lifetime, fades, easing, and
  scales are all in the sidebar; play, pause, and frame stepping; a seed
  for reproducibility. Exports SVG and PNG at 1x to 4x.
- `tape.html` renders the hero tape stream. Camera field of view,
  distance, height, aim, and tilt; the hero's wobble, trail reach, and
  VHS strength; play, pause, and frame stepping. Exports PNG at 1x to 4x.

The state of each editor lives in the URL hash. Copy the link to
reproduce a graphic later.

## Video

Every editor has a Video section: seconds, frame rate (24, 30, or 60),
scale (½x, 1x, or 2x), Export MP4, Export GIF, and Frames ZIP. Export starts at the frame on
screen. Each frame is rendered from the editor's time model at exactly
start + i / fps and handed to the encoder with a timestamp derived from
its index, so nothing depends on how fast the browser runs and no frame
is ever skipped or doubled. Afterwards the editor returns to the frame it
was on.

Loop seamlessly makes the last frame lead into the first, differently per
tool. The tear plays forward to the midpoint and back; its wave only
breathes, so the reversal does not read. The tape cannot reverse, but the
ring repeats exactly once per turn, so while Loop is on the Speed slider
is snapped so the clip holds a whole number of turns; the preview then
plays exactly what exports. The turn count comes from the speed you had
before Loop went on, so a longer clip returns toward that speed with
more turns. Dragging Speed while looping picks another turn count and
snaps again, and turning Loop off restores the speed you chose. The hero
speed is 36, one turn every 15.7 s. The chromatic trail is sampled at the
hero speed whatever the spin, so its look does not change. Particles fit every slot's cycle to a
whole number of lives inside the clip, with the per-life randomness
repeating on that count, so the field is exactly periodic; the preview
shows the fitted field while Loop is on.

- MP4 is H.264 in a plain MP4 container, encoded with the browser's
  WebCodecs encoder (Chrome, Edge, Safari 16.4 and later) and muxed in
  `shared/video.js`. Keynote, PowerPoint, and QuickTime open it. There is
  no alpha in H.264, so the tape exports on paper.
- GIF is written by the tool's own quantizer and LZW packer. One
  256-color palette is built for the whole clip so it does not shimmer;
  the Dither toggle adds Floyd-Steinberg dithering to the gradients at the
  cost of a bigger file. Browsers cap GIF at 50 fps, so a 60 fps request
  exports every second frame at 30. Use ½x for a shareable size.
- Frames ZIP is a PNG sequence (`frame-0000.png` …) for editing, or for a
  browser without a video encoder.

Long clips at 2x are large: a 4K frame sequence runs to roughly a
megabyte per frame.

## Run

```sh
./serve.sh          # http://localhost:8765/
./serve.sh 9000     # another port
```

Any static file server works. The pages are ES modules, so they need
http, not file://.

## Layout

This directory is self-contained and can be moved anywhere as a unit.
Every import and asset reference is relative to the page.

```
index.html            links to both tools
tear.html, tear.js    tear editor
tape.html, tape.js    tape editor
particles.html, particles.js   particle editor
engine/transition.js  copy of assets/scripts/transitions.js as a factory
engine/tape-scene.js  copy of assets/scripts/tape-stream.js as a factory
engine/particles.js   particle field, a pure function of seed and time
shared/shell.css      panel and stage chrome
shared/shell.js       hash state, stage fitting, export helpers
shared/video.js       frame-exact MP4 (WebCodecs + muxer) and PNG ZIP export
vendor/three.module.min.js   copy of assets/vendor/three.module.min.js
serve.sh              static server for this directory
```

## Keeping the engines in sync

The two engine files are copies of the site renderers with their page
wiring removed: no DOM queries at load, explicit width and height, explicit
time, and no scroll handoff, terminal, or globe inserts. The math inside
the functions is unchanged. When a site renderer changes, diff its function
bodies against the engine copy and port the difference.

The tear follows the site's one rule: paper above charcoal is the warm
`top` side (oxide, pulse); charcoal above paper is the cool `bottom` side
(signal, electric). The surface toggle only decides which of those the
slide edge needs. The tape has no dark variant because the hero only exists
on paper.
