# Sworn introduction video (larger text for phones)

`artifacts/video.mp4`: H.264 (High, yuv420p), 30 fps, 1920x1080, 59.8 s, with a mono AAC-LC 48 kHz quiet synthesized bed and no voice.
`artifacts/poster.png`: 1920x1080, the frame at 37.5 s (frame 1125, written straight from the PNG sequence).

This is the parent job's video, rendered again from its own `video/render.cjs`. The only changes are the text sizes in scenes 4, 5 and 7, the wrapping those sizes need, and the positions that follow from them. All other frames are bit-identical to the parent script's output: frames 100, 300, 450, 1250, 1400, 1600 and 1720 (scenes 1, 2, 3, 6, 7 before the fee line, 8 and 9) were rendered with both the parent's script and the changed one, and the PNGs compared equal. The audio code was not changed.

## Commands run

```sh
# dependencies (not committed; installed outside the tree): viem, @resvg/resvg-js
npm i viem @resvg/resvg-js            # in a scratch dir, used via NODE_PATH
RPC=https://ethereum-rpc.publicnode.com node video/fetch-cards.cjs 26248738
RPC=https://ethereum-rpc.publicnode.com node video/verify-cards.cjs   # 8/8 "ok"
node video/render.cjs frames          # 1794 PNG frames f0000..f1793 + frames/bed.wav
ffmpeg -framerate 30 -i frames/f%04d.png -i frames/bed.wav \
  -c:v libx264 -preset slow -crf 18 -pix_fmt yuv420p -r 30 \
  -c:a aac -b:a 160k -shortest -movflags +faststart artifacts/video.mp4
cp frames/f1125.png artifacts/poster.png   # t = 1125 / 30 = 37.5 s
```

The RPC calls went to an Ethereum mainnet archive endpoint that forwards to the public endpoint named above. The repository's root `package.json` is an empty file, and Node refuses to resolve modules beneath it (`ERR_INVALID_PACKAGE_CONFIG`). Build configuration may not be edited, so the three scripts were run from an identical copy of `video/` whose sibling `artifacts/` is a symlink to this tree's `artifacts/`. The scripts were not modified for this. Run them the same way, or from any directory without a broken `package.json`.

Font: Liberation Mono Regular is loaded from `/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf`, as in the parent's script. That file exists on the render machine, so no font was added to the tree.

## Cards (Ethereum mainnet, block 26248738, hash 0x2a46f7417f73bd4b860c086c72a42a874a8fa6c820b1834ac9ef30b4239711bc)

All seven come from the deployed contracts through `eth_call` and are byte-identical to the parent's. On screen they are only rasterized with resvg and scaled to 680 px. They are never drawn, recoloured, retouched, upscaled by AI or generated. `artifacts/cards/PROVENANCE.json` records the call, arguments and state override for each one. The fetch also writes `card-2.svg` (802cd7fe…6d0e). It is not used in the video.

| file | source | sha256 |
|---|---|---|
| card-1.svg | Registry.tokenURI(1) | 08576413dfaf15932efcd930f399df1be215cea496e45b58d0ad1f44c619234c |
| card-3.svg | Registry.tokenURI(3) | 5e4d99452e1671b47078451f8ec5afa5254d36e38889e8f171544f201faf8188 |
| preview-1.svg | Renderer.tokenURIOf + state override (1 direct fact) | f8ab19756462924840789397b73d9385c54f3403665d1e14c6aca3cf2bc384d6 |
| preview-3.svg | Renderer.tokenURIOf + state override (3) | b34e1bc0d30a9a2fb19ddb73c0d4b3d76a60e9ea2a88ad91eb292cf65fdd0680 |
| preview-6.svg | Renderer.tokenURIOf + state override (6) | fc14e06e83cafa683d37f3b601ea3f11978251b7fbdfbfa6fcbda87312d3fa27 |
| preview-8.svg | Renderer.tokenURIOf + state override (8) | 2fb82b96c263dc46c111b23d6439c090ed0ff6576b13ba5dcde3a1360922d08f |
| preview-10.svg | Renderer.tokenURIOf + state override (10) | 5b778abdc5f514da7f2daffec15829110fee9a0df4d5e9db8d71aeb12971c769 |

`artifacts/sworn-mark.svg` (sha256 1f745a9a1e2db3fcdb9d06c7b14f230c49dec80ad6bfdf51f33c81e6e8a6abd6) is the Sworn mark on the end card. **Limitation:** the parent's copy of this file never left its machine and is not in the tree. It was taken byte for byte from the live site's mark, https://swornbyswarm.sites.imd.fun/favicon.svg (a green hexagon on #0a0a0a). It has not been confirmed identical to the parent's file.

## Scenes, times and every line as shown

The card sits at x 110, y 200, 680x680 px, unchanged. Lines type in at 28 characters/s unless noted otherwise. "Fade" lines fade in over 0.4 s. Every line fades out over 0.35 s before its end time. Colours: text #d9e0da, accent #00ff41, muted #8c968e, background #0a0a0a. Position = x,baseline y. Right edge = the computed right end of the line (Liberation Mono advance 0.6 em), and every value is ≤ 1860 (60 px margin inside the 1920 frame).

| time (s) | size px | position | right edge | colour | line |
|---|---|---|---|---|---|
| **1 · 0–6** | | | | | |
| 0.30–6.0 | 56 | 240,430 | 710 | text | `19,522 wallets` |
| 1.60–6.0 | 56 | 240,530 | 912 | text | `66 hours of real gas` |
| 3.00–6.0 | 56 | 240,630 | 1282 | text | `one game: who is still onchain?` (cursor) |
| **2 · 6–11** | | | | | |
| 6.30–11.0 | 56 | 240,490 | 778 | text | `the game settled` |
| 8.00–11.0 | 56 | 240,590 | 1013 | text | `the list stayed onchain` (cursor) |
| **3 · 11–17** | | | | | |
| 11.30–17.0 | 56 | 240,490 | 1046 | text | `sworn reads that history` |
| 13.30–17.0 | 56 | 240,590 | 1483 | text | `and turns it into facts about wallets` (cursor) |
| **4 · 17–28** (card-1 at 17.0, then preview-1 19.6, preview-3 21.3, preview-6 23.0, preview-8 24.7, preview-10 26.4, cross-faded 0.6 s) | | | | | |
| 17.40–28.0 | **46** | 870,420 | 1505 | text | `every card starts empty` |
| 19.80–28.0 | **46** | 870,500 | 1450 | text | `direct facts light up` (wrapped, row 1) |
| 20.59–28.0 | **46** | 870,558 | 1505 | text | `straight from the chain` (row 2, types on after row 1) |
| 24.00–28.0 | **46** | 870,638 | 1477 | accent | `25 facts. 13 families.` |
| 17.40–19.6 | **28** | 870,758 | 1492 | muted | `card #1, minted: Registry.tokenURI(1)` (fade) |
| 19.60–28.0 | **28** | 870,758 | 1643 | muted | `previews: Renderer.tokenURIOf + state override` (fade) |
| **5 · 28–39** (card-3 28.0–39.0, plus 11 seat markers of 24x24 px at x 870+40i, y 590, shown 31.6–39.0 and filling from 32.0 every 0.3 s) | | | | | |
| 28.40–39.0 | **46** | 870,400 | 1698 | text | `the rest is sworn by the swarm` |
| 30.80–39.0 | **46** | 870,480 | 1643 | text | `11 IMD agents read the logs.` (wrapped, row 1) |
| 31.84–39.0 | **46** | 870,538 | 1201 | text | `7 must agree` (row 2) |
| 35.20–39.0 | **46** | 870,698 | 1339 | text | `the oracle signs.` (wrapped, row 1) |
| 35.84–39.0 | **46** | 870,756 | 1422 | text | `the registry checks.` (row 2) |
| 28.40–39.0 | **28** | 870,876 | 1492 | muted | `card #3, minted: Registry.tokenURI(3)` (fade) |
| **6 · 39–46** | | | | | |
| 39.30–46.0 | 52 | 360,420 | 1015 | text | `hasTrait(wallet, 601)` (18 cps) |
| 41.00–46.0 | 52 | 360,500 | 485 | accent | `true` (fade) |
| 42.00–46.0 | 40 | 360,640 | 936 | text | `any contract can read it` |
| 43.60–46.0 | 40 | 360,710 | 1032 | text | `no merkle root. no snapshot.` (cursor) |
| **7 · 46–52** | | | | | |
| 46.30–52.0 | 52 | 240,400 | 864 | text | `mint a card: 0.1 IMD` |
| 47.50–52.0 | 52 | 240,490 | 958 | text | `request a fact: 0.5 IMD` |
| 48.80–52.0 | 52 | 240,580 | 989 | accent | `your card updates itself` |
| 49.60–52.0 | **34** | 240,700 | 1688 | muted | `fees are forwarded to the BurnExecutor for bridging and burning on Base` (fade; fits on one line) |
| **8 · 52–56** | | | | | |
| 52.30–56.0 | 44 | 200,490 | 1520 | text | `contracts, site and this video: built by the swarm` (36 cps) |
| 53.80–56.0 | 44 | 200,580 | 992 | text | `no owner. no backend. no coin.` (cursor) |
| **9 · 56–59.8 (end card)** (Sworn mark 160x160 at 880,420, fades in from 56.0) | | | | | |
| 56.40–59.8 | 44 | 960,690 centred | 1303 | text | `swornbyswarm.sites.imd.fun` (fade) |
| 56.80–59.8 | 32 | 960,760 centred | 1085 | muted | `@swornbyswarm` (fade) |

The whole picture fades in over 0.3 s at the start and out over 0.5 s at the end.

### What changed against the parent (bold sizes above)

- Scenes 4 and 5: main lines went from 34 to 46 px, and the card labels from 22 to 28 px. Three lines would run past the right margin at 46 px, so they wrap at a word boundary. A break after a full stop is preferred when both halves fit; otherwise the most balanced break is used. Wrapped rows sit 58 px apart, the second row types on right after the first, and the end time does not change. Each line block below moves down by the extra height. Spacing between blocks stays 80 px and the label stays 120 px below the last line, as in the parent. In scene 5 the seat markers keep their place under the "agents" line (52 px below its last row, now y 590 instead of 532), and the oracle lines keep their 84 px clearance below the markers.
- Scene 7: the fee line went from 24 to 34 px. It still fits on one line (right edge 1688), so nothing moved.
- Wording, times, colours, cards, markers, the end card and the audio did not change.

### Frames checked

Rendered frames were inspected at 20 s (frame 600), 27 s (810), 38 s (1140) and 51.5 s (1545). Scene 4: the card is at left with the four text rows and the label to its right, starting at x 870 (the card ends at x 790). The lowest row is the label at y 758, well inside the card's height. Scene 5 (also the poster at 37.5 s): card-3, the five text rows, the eleven filled markers between "7 must agree" and "the oracle signs.", and the label at y 876. Nothing overlaps. Scene 7: four lines with the fee line ending at x 1688. The other scenes match the parent's render bit for bit (see above).

## ffprobe summary (artifacts/video.mp4)

```
video: h264 (High), 1920x1080, yuv420p, 30/1 fps, 1794 frames, 59.800 s
audio: aac (LC), 48000 Hz, mono, 59.800 s
container: mp4, faststart, duration 59.800000 s, 1,801,926 bytes, ~241 kb/s
sha256 5ba6bae039a870207e533789e6f2bbf9adc0e6f270a4ba958e3699120b6cd598
poster.png: png 1920x1080, sha256 9dc98f800a8c380a36fdf2884df4097b5cef447b1cf47985142bad673c889cfc
```

Audio: the parent's own synthesized bed, unchanged. It is a soft A-minor drone (110, 164.81, 220 and 261.63 Hz sines with slow swells) at about −30 dBFS, with 3 s fades. There is no licensed music and no voice. The video can be read with the sound off.

## Limitations

- `sworn-mark.svg` comes from the live site (see above). The parent's own file was not available.
- Because of the empty root `package.json`, the scripts have to be run from a copy of `video/` (see Commands).
- Structural checks (codec, size, duration, card hashes, frame comparison) were done. Visual review covered the frames listed above, not every frame.
