The concept
A signal box is a safety machine dressed as furniture. Its levers are beautiful, but the real object is the bed of steel bars beneath them — the interlocking — which makes unsafe routes physically unpullable. The single job of this page is to let a visitor feel that: not a simulation that looks safe, but a machine that decides, and quotes you the rule when it says no. Audience: anyone who likes mechanisms, railways, or interfaces that mean what they show.
Palette
Argued straight from a lamp-lit box at dusk: near-black diagram enamel, one warm oil-lamp amber for lit track, and the true lever-cap colours of British signalling practice — red for signals, blue for the facing point lock, black for points.
Type
A condensed grotesque with the compressed, all-caps authority of enamel station and running-in signage. It carries the headline and every plate label; its narrow set lets the hero numeral run huge without crowding.
A monospace for the running text, register and timetable — because a signal box runs on ledgers, bell codes and train numbers, and tabular figures keep the clock and the times honestly aligned.
How it works
The signature — real interlocking
The box's actual locking table is encoded as two small maps: REQ (what must already be set before a lever will move) and HOLD (what each reversed lever grips so it cannot be disturbed). Every pull runs through one canMove() check: it first asks whether any track circuit is occupied, then whether another reversed lever holds this one, then whether this lever's own requirements are met. Only if all three pass does the lever move. The animation never decides anything — the SVG diagram, the point blades, the signal arms and the lit route are all painted from state after the logic has spoken. When a lever refuses, the readout quotes the exact row that stopped it and the offending lever's cap pulses red, so the interlocking is legible, not mysterious.
Diagram & trains — inline SVG
The illuminated diagram is hand-built SVG: track segments, swinging semaphore arms, point blades and a facing-point-lock lamp, all toggled by CSS classes driven from state. Trains are drawn along invisible measured route paths using getPointAtLength, and their position feeds a track-circuit occupancy map that both lights the rails red and locks the levers of any road in use.
Levers, bells & motion — CSS 3D + WebAudio
Each lever is a CSS 3D object pivoting on rotateX with a crafted over-throw easing, so pulling it feels weighted. Bells, the lever clunk and the refusal thud are synthesised live with the WebAudio API — no audio files — and the block bell codes (3–1, 2–3, 2–1) are real. One orchestrated load sequence lights the diagram lamp-by-lamp and raises the levers in turn; a single moth drifts across the panel on the rare long evening. No libraries, no images: SVG, CSS and vanilla JavaScript only.
The three passes
- Found the hero's intro sentence reusing the compact .hero-meta flex style and carrying a duplicate
styleattribute, so its top margin was silently dropped. - Gave it a proper .hero-lede — larger, its own measure and rhythm — so the one paragraph that sells the machine reads as prose, not metadata.
- The interlocking refused correctly but only told you why. The cause of a refusal — the lever holding you — was named in text but invisible on the frame.
- Threaded the blocking lever's id out of canMove() and made its brass cap pulse red on refusal, so the machine now points at the lever you must replace first. A second-read detail: a moth still crosses the lit diagram on long evenings.
- The animation loop was repainting the whole diagram every frame even when the box sat idle — needless work under scroll. Gated it so idle frames do nothing and lever moves repaint directly.
- Chanel rule: removed the ambient amber glow baked into the panel background so the lit track is the only light source. Re-checked the 375px layout, reduced-motion settle, focus rings and the DPR/visibility handling.