← LENS / AFTERIMAGE

β„– 10 Β· PROCESS GUIDE Β· WAVE 2 β€” THE DUEL

How the darkroom was printed.

One HTML file, no photographs, no libraries. Everything on the site β€” the enlarger, the wash line, the rain in the window β€” is drawn as SVG and racked through a computed plane of focus. This page is the negative sleeve: the brief, the trick, and what four hostile passes found.

01 Β· THE BRIEF, AS RECEIVED

W2-10 β€” lens-afterimage

CONCEPT
A photographic studio that develops memory β€” a focus ring pulls layered scenes in and out of the plane of focus, and what leaves focus leaves an afterimage.
SIGNATURE
A draggable focus dial. Layered depth planes (CSS/canvas blur + scale) rack focus between foreground / mid / far scenes; defocused planes ghost trails.
PALETTE
darkroom black #0b0a0c Β· silver print #d9d4cc Β· safelight red #d0453a Β· fix-bath green #5c7a6a (trace)
TYPE
EB Garamond (display, italic) + Manrope (text)
VOICE
A printer talking to negatives. Second person. Short lines.
DUEL RULES
Blind rebuild β€” the other model's version was never opened. First viewport must show the actual world. Every control keyboard-reachable. Verified at 375 / 768 / 1440.
02 Β· THE TRICK, EXECUTED DEEPLY

A focus rack with a memory.

Three full-viewport SVG scenes hang at different depths β€” the wash line at 0.45 m, the enlarger at 1.2 m, the monsoon window at infinity. One value, focus ∈ [0,1], drives everything: per-plane blur grows with the square of the distance error, scale breathes Β±4.5%, captions only sharpen when their plane is within the depth of field, the brass ring rotates, the distance scale slides, and the contact sheet highlights whichever exposure you are nearest to.

The afterimage is the honest part. Every plane is mounted twice β€” a live print and a ghost. The ghost chases focus at less than half speed, tinted toward safelight red, its opacity proportional to how far it lags. Rack hard and you drag a red echo through the room; hold still and the room forgives you. This is the loop, verbatim from the source:

focus = RM ? target : lerp(focus, target, Math.min(1, dt*5));
ghost = lerp(ghost, focus, Math.min(1, dt*2.1));   // the afterimage lags

for (const p of planes) {
  const err  = Math.abs(focus - p.d);
  const blur = Math.min(17, err*err*38 + err*3.5);   // optics: errorΒ², not error
  p.m.style.filter = blur > .25 ? `blur(${blur.toFixed(2)}px)` : "none";
  ...
  const gerr = Math.abs(ghost - p.d);
  p.g.style.filter  = `blur(...) sepia(.6) hue-rotate(-28deg) saturate(2.4)`;
  p.g.style.opacity = Math.min(.55, Math.abs(focus - ghost)*5);
}

Supporting cast, all derived from the same state: film grain regenerated on a 144px canvas tile every 90 ms whose opacity breathes and thickens with rack velocity; an idle drift that keeps the room breathing at Β±0.045 focus after six seconds of stillness; a safelight toggle that relights the entire page through a multiply overlay β€” with a real lamp-startup stutter; and one secret: hold the ring at infinity for a few seconds and the monsoon steps aside.

03 Β· WHAT THE PASSES FOUND

Four passes under the loupe.

PASS 1 β€” 1440 + 390, TOP/MID/BOTTOMThe room worked; the edges didn't.

  • The printer section shipped with an empty SVG β€” the wash line illustration was declared but never drawn. Drawn: three swaying prints, drips, a safelight glow.
  • Mobile header collision β€” the wordmark crashed into THE TANK, which wrapped to two lines. Nav trimmed and tightened under 640px.
  • The hero hint wrapped into a widow and sat naked over a bright defocused print. Shortened on mobile.
  • The visit section was half a viewport of nothing on desktop β€” copy about a red lamp above a door, and no door. Drew the shopfront at No. 47: transom, panels, moth, flickering lamp.

Upgrade: safelight mode went page-wide β€” a multiply overlay relights every section red, and the contact sheet and wash line re-tint under it.

PASS 2 β€” RESHOOT, BOTH VIEWPORTSThe strip read as mud.

  • The contact sheet's six frames read as one continuous dark band β€” non-selected frames were dimmed to 75% on already-dark crops. Brightened the emulsion, lifted the selected frame to 118%, lightened the cell base.
  • Frame 19's crop landed on a near-black region β€” an exposure that read as an error. Recropped to the loupe on the bench.
  • The hero hint still failed contrast over the brightest print at 390px. Gave it a proper scrim plate β€” the constitution's own law 12.

Upgrade: the safelight now switches on like a real lamp β€” a six-step startup stutter before it holds, page-wide.

PASS 3 β€” 1440 + 390 + 375 + 768Composed, but the margins were silent.

  • 375 and 768 both held: no collisions, dial centered, captions clear of the ring.
  • Frame 19 now reads as a loupe; the strip finally looks like six separate exposures.
  • Wide desktop margins were pure black with no texture β€” the sections floated in a void.

Upgrade: film-edge marginalia β€” faint vertical darkroom notation (ILFORD HP5 PLUS Β· SAFETY FILM, D-76 Β· 1+1 Β· 20Β°C, FIX 5:00 Β· WASH 20:00) running down the left margin of each section past 1280px, the way edge print runs down a negative.

PASS 4 β€” VERIFICATION, 375 / 390 / 768 / 1440Clean, but the footer lied by ten kilobytes.

  • All four widths held with zero console errors β€” no collisions, dial centred on mobile, captions clear of the ring.
  • The footer stat read β‰ˆ 62 KB; the file is 54,031 bytes. Corrected to β‰ˆ 53 KB β€” we sell speed, so the number has to be true.

Upgrade: the afterimage now lives on the instrument too β€” rack the ring and the distance scale drops fading red ghost ticks where focus just was, so the tool demonstrates the concept the room is named for.

04 Β· LAWS HONORED

The fixed points.