The dead web, on the machine that survived it
SIGNAL is a culture zine about the web we abandoned — open guestbooks, broken webrings, 88×31 buttons, the modem handshake — read on a CRT terminal someone found in a basement. The audience is anyone who remembers a hit counter, or wishes they did. The page has one job: make you feel like the machine booted up for you, and then make you read to the end.
Four ambers and one forbidden cyan
Everything is one phosphor. Amber monochrome monitors (P3 phosphor) rendered the entire coloured web in a single hue, so the palette is a brightness ladder of one colour, not a set of colours. Cyan is reserved exclusively for links — the one thing on a terminal that was ever a different colour — which makes every interactive element findable at a glance.
One face for the machine, one for the reader
VT323 is a digitisation of a real DEC VT320 terminal ROM font — it isn’t pretending to be a terminal, it is one. It carries the masthead, headlines, the giant pull quote, and the 88×31 buttons. IBM Plex Mono does the long reading: it has real italics, a full weight range, and enough humanity at 15px/1.8 to hold three essays without fatigue. The scale is deliberate: 13 / 15 / 17 / 22 / 32 for the mono voice, then VT323 jumps straight to clamp-sized display sizes — the machine speaks either quietly or in ALL CAPS, nothing in between.
CSS phosphor, JS cadence
The signature element is the boot sequence. On first visit a full-screen overlay types a nine-line POST log — BIOS check, memory test, mounting /dev/nostalgia, dialing the archive node — character by character with a variable cadence: dots print at a metronomic 14ms like a progress bar, letters wobble between 8–30ms, lines pause 110–290ms, and there is a deliberate 520ms breath before READY. lands with a blinking block cursor. Any key or tap skips it; sessionStorage remembers it so the zine never boots twice in one sitting. The colophon’s REBOOT command clears the flag and restarts the machine.
Everything else is CSS and small vanilla JS: scanlines are a repeating-linear-gradient with a stepped flicker keyframe; the barrel vignette is two stacked radial gradients on a fixed overlay; headlines retype themselves via IntersectionObserver; the masthead glitches on a randomised 5–13s timer; the DEGAUSS button in the status bar wobbles the whole screen with a scale/skew/hue-rotate keyframe, exactly like thumping the side of the monitor. No libraries, no canvas, no images — the entire zine is text, gradients, and timing.
Three passes with the case open
- PASS 1 — CRAFT
- found: without JS the load-cascade CSS left the header permanently invisible. Gated the hidden state on an
html.jsclass set by a one-line head script. - boot log results were ragged; rewrote the lines with a
post()helper so every OK lands flush right at column 41, and shortened labels so nothing wraps at 375px. - ring-survey ALIVE column was left-padded by eye and misaligned; recounted every row with a script and right-aligned the digits under the header.
- tightened headline-to-byline gap (1.5rem → .65rem), removed three unused type tokens, gave body text a 1px phosphor bloom, fixed badge hover reflow (position was only set on :hover), dropped a wrong
role="contentinfo"from the status bar. - PASS 2 — DEPTH
- power-on bloom: when the boot dismisses, the whole screen flashes bright and settles over 1.1s — the tube warming into focus.
- second-read detail: a phosphor burn-in ghost of
READY.▮at 5.5% alpha near the bottom-right corner, baked into the glass from years of the same prompt. - added the
*** END OF ISSUE 07 — NO CARRIER ***EOF marker, and a TOC micro-interaction — hovering a row wakes its[01]index and dot leaders from dim to amber. - PASS 3 — HARDENING
- VT323's advance width can't be trusted from CSS math alone, so the masthead now measures itself after
document.fonts.readyand scales down if it would clip; re-measured on debounced resize. - reduced-motion re-audit: the CSS override for the cascade lost a specificity fight against
html.js .rise— fixed; boot, typewriter, glitch, degauss and bloom are all separately gated in JS. - Chanel rule: deleted the CARRIER 300 status-bar segment — the boot log already says it. Boot skip hint now acknowledges touch (“any key — or tap”).
- verified: both inline scripts pass a syntax check, every text/background pair ≥ 5.4:1 (dim amber is decoration-only), the only external requests are the two allowlisted Google Fonts hosts.