Circuit Board — Style Prompt

The subject is drawn as a printed circuit board seen from straight above: the world is copper under green solder mask, routes are traces, places are pads, words are white silkscreen, and what flows (power, water, signals, goods) is light running along the copper. The camera rides that light and jumps between the scale of a map and the scale of a single component. References (grammar only): real PCB design files and assembly drawings (layers, clearances, designators, detail callouts); macro photography of boards (shallow depth of field, gold sheen, soft key light); schematic and single-line diagrams (one symbol stands for one function). Draw your own boards: never copy a real board layout, a logo or a part marking.

Frame rate: 30 fps. Pass --fps 30 to video.mjs and 30 to mux.sh; this overrides the 24 fps in the DIRECTOR.md and TECHNIQUE.md examples.

1. Essence, and what it is not

2. Materials & rendering

Layers bottom-up, all in board space under one world → screen camera: 1. Laminate (FR-4): dark green, a glass-weave basket texture in two crossfaded octaves so its on-screen size stays bounded at every zoom. Bottom-layer copper may show through faintly. 2. Copper pour: fills the board; everything is a clearance punched out of it (channels, lakes, sea, keep-outs around parts and traces). Rendered twice: a lighter rim pass with the plain clearance, then the fill pass with the clearance grown by ~1.6 px, so every copper edge gets a bevelled rim. A soft mottling texture sits only on the pour (solder mask is never perfectly flat). 3. Traces: rim colour stroke + narrower fill stroke, round caps; a channel of bare laminate runs on both sides (the clearance). Parallel traces keep the pour out of the gap between them when they are a pair. 4. Exposed metal: ENIG-gold pads (rect, round, square pin-1) with a sheen band on the top third and a dark drill hole; vias are gold rings with dark bores; bare copper (salmon with a vertical gradient and brushed streaks) only for one heavy, special part. Fiducials and mounting holes at board corners. 5. Silkscreen: off-white monoline strokes with a pinhole texture punched out, slightly blurred (0.35 px). Outlines, designators, polarity marks, component symbols, labels. 6. Light: an additive layer (glow) with two blurs (≈24 px and ≈5 px) under a sharp copy. Current, water, lit pads all live here. 7. Screen space (once per frame): a soft warm key light drifting from the upper left, shallow depth of field (a blurred copy faded in at the top and bottom bands, stronger in macro shots, weak or off where text must be read), out-of-focus motes of light drifting with parallax in front of the board, a vignette, film grain at mux. A window's light (a soft parallelogram with a mullion shadow) may fall on the board when the whole board is on a desk. Level of detail: textures crossfade between octaves; small features (vias, designators, rims) fade out before they go sub-pixel, so zooms never shimmer. Nested boards (a module inside a board) are separate boards composited into their footprint, so a continuous zoom can cross six or more orders of magnitude without precision loss.

3. Colour logic

4. Type & subtitles

5. Motion quality

6. Camera grammar

Straight-down camera always (rotation about the view axis allowed, small). Moves:

Move What it expresses Can serve
Ride the pulse (camera locked to a moving head, head on a third) following one thing through a system a delivery route; a signal path; a single order through a process
Rise while following (zoom out during the ride until both ends are in frame) the whole length becomes visible a distance; a supply chain end to end; a timeline
Crash zoom onto a pad arrival, impact a deadline met; a package delivered; a test result
Locked macro hold reading, comparing, verdict two numbers side by side; a spec; a rule
Whip along a trace jump to the next station the next stage; skipping ahead
Matched cut on a centred symbol (same symbol, same screen size, the world around it changes scale) the same step repeated at every level step-downs; repeated approvals; hand-offs
Plunge through a hole / via, reverse out of another hole entering a smaller world into a device; into a building; into a file
Continuous pull-out across nested boards everything was one board the big picture after the detail; the system behind one object

Framing rules: the lit subject sits on a third or dead centre for symbols; at least two layers of detail around it (background copper/vias/routes, foreground motes or depth-of-field blur); the board edge appears only when the whole board is the subject. Transitions: motion-into-motion and matched cuts; no fades, no wipes, no page turns.

7. Sound palette

All synthesised: sine/saw tones, pulse waves, FM bells and glockenspiel, relay clicks (two-click transients), soft kicks and 16th ticks, filtered noise. Tune the drone to the mains hum (50 Hz ≈ G1; 60 Hz ≈ B♭1) so the hum belongs to the key. Rule the ear can follow: an amplitude-gated tremolo tone = alternating, a steady tone = direct; a component that converts one into the other is heard as the tremolo smoothing into the long tone. Arrivals are relay clicks or a filtered noise burst; a step-down is a relay one step lower each time; plotting silkscreen is a faint scratch of grains. Outside sounds (water, cicadas, traffic) only behind a low-pass, as if heard through a wall. Silence: drop the rhythm before a verdict, keep only long tones. With a voice, the voice leads: duck the bed so it sits 15–18 dB under the speech, effects a few dB. Mix around −16 LUFS before mastering, true peak under −3 dBTP, lean low end (high-pass ≈ 55 Hz).

Voice-over and subtitles

When the film explains something, a voice tells it and the board shows it at the same moment: each spoken line has one picture action (a pad lights, a stream changes shape, a tag prints). Every line gets a subtitle in the bottom safe area, a Chinese line over an English line on a dark translucent plate, appearing and leaving with the voice; the board itself prints only the key words and numbers the voice says (a name, a value, a verdict), never whole sentences. Keep the voice on top: the bed sits 15–18 dB under it and rises in the gaps. Pick one calm, clear voice for the whole film; numbers and units are spoken in full.

8. Native moves

9. Pitfalls of the medium

10. Engine

Reference code in demo/src/. Copy what you use into the project's src/ (never import from styles/); edit your copies freely. The build order (subtitle font, voice and check, events, score, render at 30 fps, mux, .srt, readcheck, stills) is in demo/build.sh.

Reusable as is (no demo content inside): - render.js — Board(canvas, world, {unit, noDesig}); board.frame(cam, sc) draws one board for a camera {x, y, z, r} (world centre, pixels per unit, rotation); board.texts(cam, sc) returns the label boxes for window.TEXTS; camFor(worldPt, screenPt, z, r) builds a camera that puts a world point at a screen point. unit is a typical feature size in world units: it sets where textures change octave and small features fade. - levels.js — nested boards: makeLevels, toChild/toParent, baseOf, drawLevel. Needed only when one board sits inside another. - font.js (+ your hanzi.js) — drawText(ctx, str, x, y, cap, {sw, align, progress}), layout, textWidth, isHanzi. - geo.js — octi (0/45/90° routing through waypoints, 'd' diagonal first), offset, measure/at/sub/trim, frameAt. - parts.js — footprint builders returning {pads, silk, keep, …anchors}: chip, ecap, xfmr, xformer, bridge (with flow paths for conduction glow), reactor, capBank, ground, tag, box. Add your own the same way. - post.js (key light, depth of field, motes, window light, vignette), palette.js (every colour).

Demo content, to replace: main.js (timeline, cameras, scenes, subtitles, sound events) and the world modules world.js, city.js, house.js, charger.js, loss.js. render.js also carries optional demo-specific keys, skipped when a world doesn't export them: DAM (the bare-copper bar), GENS, PENS, RESERVOIR, RES_FLOW, TAIL, and sc.water / sc.gens. loss.js is the smallest complete world module to read first.

A world module exports, in its own units: - required: BOARD {x0, y0, x1, y1, r, inset}, TRACES [{id, pts, w, layer?: 'bottom'}] (add m: measure(pts) to any trace that carries light), PADS [{x, y, shape: 'round'|'square'|'rect', r | w, h, hole?}]; - optional: LABELS [{id, text, x, y, cap, sw, align}] (plotted by sc.labels[id]), SILK [{pts, w, plot?} | {circle, w}], DESIG, KEEP (extra clearances), VIAS [[x, y, r, bore]], HOLES, FIDS, TPADS (pad grids lit by sc.lit), TITLE, clearances RIVER, LAKES, SEA, STREETS, SLOTS, CLEARLINES, sizes CLR, VIA_R, FENCE_R, HOLE_R, and functions fence() / stitch() returning via positions. - RIVER entries are channels cut out of the copper (and are where sc.water flows): use them only for something that really is a gap in the board.

A scene is the plain object frame reads each frame: {t, labels: {id: 0..1}, ac: [], dc: [], glow: [], flashes: [], lit, after}. - ac — {trace, s0, s1, a, lam, amp, phase} rocking dashes; with fade and v they travel forward and die away. dc — {trace, head, s0, a, decay, floor, v, minPx, maxPx, headGlow} a stream behind a head. Both are drawn in the current colour. - glow — {pts, w, a, c} any polyline in any light colour, with the bloom; flashes — {p, r, a, c: {h, g}, maxPx} blooms at a point. - after(ctx, M, z) — draws on top of the finished board (no bloom), for overlays such as a detail-callout circle.

Your own flows and light, without changing the engine (one way of doing it): a second flow along a trace (a signal, goods, water in a pipe) is built in your scene from glow and flashes: each frame cut the trace with sub(trace.m, s0, s1) into short pieces (a head, a fading tail, dashes moving at your speed) and push them as glow entries with the second light colour (PAL.water.g or your own), plus a flash with c: PAL.water at the head. A new kind of motion or a darkness that only the board (not the light) sits under needs a small hook in your copy of render.js, e.g. if (sc.myLight) sc.myLight(glowCtx, z, t, vb) at the end of glowLayer (it then gets the bloom), or a dark fill before the silkscreen pass; a darkening of the whole frame belongs in your main.js between the board stack and post.

Page contract: your main.js exposes window.render(t), DUR, TEXTS(t) (collect board.texts for every level drawn), EV, READY, as in core/README.md. Motion blur averages sub-frames of render(t); keep sub-frames within one shot.

Check the lettering before building: list every character used in LABELS, DESIG and silk text that is neither in HANZI nor in GLYPHS (e.g. a few lines in node importing font.js, or isHanzi plus the glyph table); the list must be empty.

New hanzi (hanzi.js): one entry per character, an array of strokes, each stroke a flat list [x, y, x, y, …] in a 12 × 12 box (y down), runs at 0/45/90° only. font.js chamfers right-angle corners and plots strokes in the order listed, so list them in writing order. A dot is a stroke about one unit long; a hook is a final short 45° run. Keep the same stroke width as the Latin: never vary width per glyph. One way to work: 1. Make a proof page in the project folder: for each character, a 12 × 12 grid, the character from an open-licence font (e.g. Noto Sans SC) faintly underneath as a structure reference, your routed glyph on top via drawText at a cap of a few hundred pixels; a second row without the reference; and once at the size it is used in the film. Render it with core/render/still.mjs. 2. Read the components and their proportions off the reference and route them by hand (not an automatic skeleton, which drops dots and merges strokes). Reuse shared components from glyphs you already have, so radicals match across the film (e.g. 氵, 扌, 亻 in the demo's hanzi.js). 3. Look at the proof image: every component of the reference present, nothing reads as a neighbouring character (聲 vs 青, 手 vs 毛), simplified forms. Fix and re-render until it reads without the reference. If a character still won't read, choose another word.

11. Variation space

The agent decides the structure, the stations, the scales visited, the camera path, the pacing and which flows get which light. Range, far from the demo: - Structures: a single packet's round trip and the time it took; three routes raced side by side on parallel buses; one board revealed component by component like an exploded view, ending on the whole. - Openings: a via drilled through in macro, light rising out of it; a whole board on a desk, the camera diving to one pad; a single silk label plotting itself in the dark, then the copper lighting under it. - Endings: the last pad lights and the board's power LED stays on; a pull-out to many identical boards in a rack; the title block of the board printing the answer.


How our demo was made (story, shots, score, end card, build): DEMO.md. Read it after your treatment exists.