Tidal Glass
N° 0022An underwater scene that rises through the surface as you scroll.
A field of light responds to your pointer and opens on scroll.
35 KB of text that builds one HTML file. Paste it into Claude Code, Cursor or v0 to rebuild this page.
A dark field of 12,000 fibre optic stems sways in a two octave wind under a long lens; the cursor sends lit rings through it like wind through wheat, and scrolling parts the stems into a lane that runs to the button.
Signature momentMid scroll, a pulse lights both banks of the freshly parted lane while the far field fades into the fog under the headline.
12,000 camera facing ribbons (3,000 on phones and on the low tier), five segments each, drawn in one instanced call. They stand on a seeded jittered grid with 3.6 candidates per stem at full density, weighted toward the near rows so the mid field stays full.
Up to four rings alive at once. Each front travels at 2.6 units a second with a 0.6 unit soft leading edge, a tail that decays over 0.4 units and a damped wake that rocks the stems outward; the light climbs each fibre 0.22 s behind the front.
Two octaves of advected value noise, at 0.16 and 0.5 cycles a unit, bend every stem along a quadratic curve. A tip that tilts toward the camera shines up to 4.5 times brighter, which is what turns the gusts into visible waves.
Scrolling through 1.2 viewports parts the stems from the foreground out to 50 units, paced in inverse depth so the front climbs the screen evenly. The stems on its banks light up and point at the button.
A level camera 1.55 units up with a 21 degree lens (30 on a phone held upright). A lens shift sets the horizon under the copy so the stems stay vertical, near stems widen and dim as if out of focus, and fog runs from 6 to 50 units.
Raw WebGL2, three shader programs, in a Worker on an OffscreenCanvas. Lighthouse mobile 100 with 10 ms of blocking time; the whole layer is one 66 KB HTML file with no assets.
DUSKLAYER.set()| Control | Key | Range | Default |
|---|---|---|---|
| Stems | stemCount | 3000 to 20000 | 12000 |
| Stem height | stemHeight | 0.4 to 1.2 | 0.75 |
| Density | density | 0.3 to 1 | 0.9 |
| Camera height | cameraHeight | 0.9 to 2.4 | 1.55 |
| Path width | pathWidth | 0.3 to 1.6 | 0.55 |
| Seed | seed | 1 to 99 | 7 |
| Wind strength | windStrength | 0 to 2 | 0.8 |
| Wind speed | windSpeed | 0.2 to 2.5 | 1 |
| Pulse speed | pulseSpeed | 0.3 to 3 | 1 |
| Pulse radius | pulseRadius | 2 to 14 | 7 |
| Scroll lean | lean | 0 to 1.5 | 1 |
| Tip colour | tipColor | color | #B8F03A |
| Glow | glow | 0.2 to 2 | 1 |
| Ground | ground | color | #080A09 |
| Page tone | pageTone | select: dark, light | dark |
| Grain | grain | 0 to 1 | 0 |
Something wrong with this layer? Report a problem and we fix it in the next version.
One text file, 35 KB, 10 sections. Every number the page uses is in it, so another model can rebuild the layer without seeing this one.
# Signal Orchard: build prompt
## Role
Build the homepage of {{BRAND_NAME}}, an invented inference network serving open-weight models from 31 regions behind one endpoint, as one self-contained `index.html`. The hero is hand written WebGL2: a dark field of thin fibre optic stems seen through a long lens from just above the tips. Wind sways them, the cursor sends lit rings through them like wind through wheat, and only the tips carry light, in one acid green. Scrolling the pinned hero parts the stems into a lane that ends under the call to action. Below: network numbers, a quickstart with a real code block, plans, a changelog, a sign up card, a footer. A field at night under one signal colour, never a neon screensaver.
## Output contract
- One `index.html`: one `<style>`, a short head `<script>` (colour maths, first paint variables), one `<script type="module">` at the end. No assets, frameworks, Three.js, GSAP or bundler; requests only to the font hosts and jsDelivr.
- Import map `{"imports":{"lenis":"https://cdn.jsdelivr.net/npm/lenis@1.3.27/dist/lenis.mjs"}}`; when the scene boots (never under capture or reduced motion) import it and run `new Lenis({ lerp: 0.1, smoothWheel: true, autoRaf: false })` from the page loop.
- Fonts: one Google Fonts sheet, `media="print" onload="this.media='all'"`, a `<noscript>` copy, preconnects: `https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible+Mono&family=Atkinson+Hyperlegible+Next:wght@400;500&family=Bricolage+Grotesque:wght@300;500&display=swap`. Fallbacks open the CSS:
```css
@font-face{font-family:'Bricolage Fallback';src:local('Arial'),local('Liberation Sans');size-adjust:106%;ascent-override:87.7%;descent-override:25.5%;line-gap-override:0%}
@font-face{font-family:'Bricolage Fallback DV';src:local('DejaVu Sans');size-adjust:92.6%;ascent-override:100.4%;descent-override:29.2%;line-gap-override:0%}
@font-face{font-family:'Atkinson Fallback';src:local('Arial'),local('Liberation Sans');size-adjust:100.1%;ascent-override:98.3%;descent-override:31.6%;line-gap-override:0%}
[32,554 more characters. Copy the prompt to get all of it.]An underwater scene that rises through the surface as you scroll.
Chrome lettering breaks apart under soft studio light, one letter at a time as you scroll.
A chrome C forms from liquid metal, bristles into ferrofluid spikes near your cursor and slumps into a pool on scroll.