Light on the page, not a picture of trees

This article is wearing the effect.
Type on a white field is a document. You read, you leave. Light moving over the type is a room: afternoon, rain, a window somewhere out of frame. Same words, a different stay. That is the point of leaf-shadow. Not a prettier tree in WebGL. Not a garden photograph pasted on the essay. A looping take of light projected onto a pale surface, multiplied onto whatever you already published, at about 0.2 opacity.
Landing pages stop feeling like a CMS template. A long read picks up a time of day without rewriting a sentence. Switch the clip, and the mood changes: canopy, window, water, rain. The HUD in the corner is for that.
The clips are files we generated and compressed to a few hundred kilobytes.
Optical, not botanical
The thing you remember from a sunlit wall is the umbra: soft, out of focus, full of gaps. Theatre calls that a gobo. The page needed a looping one, multiplied onto the type.
When src is set, leaf-shadow plays that loop. When src is omitted, it falls back to a procedural canvas of leaf-shaped noise. The video path is the one that reads as light.
Four demos live next to the articles collection, without their own content.md, so they never enter the article index:
/en/articles/leaf-shadow-gobo/canopy.mp4 · window.mp4 · caustic.mp4 · rain-ripple.mp4
Lab with the same HUD, no article chrome: /en/leaf-shadow-lab/.
A sentence becomes a loop
The overlay is reusable. The clips should be too, without stealing someone else's video.
gobo-loop is the skill for that. You describe a scene. The agent does not generate a picture of the scene. It generates the projection of that scene onto a cream wall or pale floor, then a locked-camera 6 second loop, then compression to 100–400 KB (no audio, 12 fps).
The rewrite is the whole trick:
| You say | The still is |
|---|---|
| Garden shade | Leaf masses on a blank wall, gaps of light |
| Afternoon window | Mullions or gauze thrown across empty plaster |
| Rain on still water | Caustic ripples on pale stone, not a lake photograph |
The skill lives in this repository at .claude/skills/gobo-loop/SKILL.md. Compress with .claude/skills/gobo-loop/scripts/compress-gobo.sh. Hang the file with:
component fx slot=leaf-fx component=leaf-shadow
variant=overlay
intensity=0.2
src="/en/articles/leaf-shadow-gobo/<slug>.mp4"Props, dark-mode blend, reduced-motion, and the HUD protocol: leaf-shadow component doc.
Wear the weather, keep the words
The overlay is pointer-events: none except for the HUD. Links still work. The type is still the type.
Do not put a product screenshot, a face, or readable text into the gobo. Multiply will print it onto every paragraph. Do not ship the uncompressed 5 MB take; the compress script exists because a shadow loop has no business being larger than a font file.
If the reader asked for reduced motion, the video pauses. Intensity still applies, quieter.
Same essay, four weathers, one component. That is a richer page without a richer CMS.