Orbit & Explode
N° 0006An earbuds pod separates into seven labelled parts as you scroll.
One vessel turns from glass to stone to brushed steel as you scroll, with a finish picker and copy for each material.
30 KB of text that builds one HTML file. Paste it into Claude Code, Cursor or v0 to rebuild this page.
One vessel turns from glass to stone to brushed steel as you scroll, with a chapter of copy for each material and a finish picker.
Signature momentMid scroll, a band of light climbs the stone vessel and leaves brushed steel behind it.
Two 8 second clips cut into 115 frames: the vessel turns from mouth blown glass to honed travertine to brushed steel without moving.
Each material name draws as an outline and fills from the bottom up in step with the band of change climbing the vessel.
Three swatches scroll the film to each material. The active one is marked, and the page copy changes with it.
Nine looks apply CSS grades to the film: warmth, saturation, contrast and exposure, plus page tone and inset.
Materials with prices, weights and lead times, a dimensions and care table and a reserve card with deposit terms.
The title takes a band above the film and the material word sits over the plinth.
DUSKLAYER.set()| Control | Key | Range | Default |
|---|---|---|---|
| Warmth (cool ← → warm) | warmth | -1 to 1 | 0 |
| Saturation | saturation | 0 to 1.5 | 1 |
| Contrast | contrast | 0.8 to 1.3 | 1 |
| Exposure | exposure | 0.8 to 1.2 | 1 |
| Paper (matches the studio backdrop) | paper | color | #D6D2CA |
| Ink | ink | color | #1C1A17 |
| Muted ink | muted | color | #5C5852 |
| Accent | accent | color | #9C4A2A |
| Page around the film | page | color | #D6D2CA |
| Film inset (fraction of the short side) | inset | 0 to 0.08 | 0 |
| Film corner radius (px) | radius | 0 to 32 | 0 |
| Copy side wash | scrim | 0 to 1 | 0.55 |
| Material word scale | materialScale | 0.6 to 1.3 | 1 |
| Portrait band above the film | mobileHeadroom | 0 to 0.35 | 0.2 |
| Camera push in on the vessel | cameraZoom | 1 to 1.3 | 1 |
| Pointer parallax | parallax | 0 to 1 | 0.5 |
| Scrub weight | scrubWeight | 0 to 1 | 0.55 |
| Film grain | grain | 0 to 0.08 | 0 |
| Seed | seed | 1 to 9999 | 3 |
Something wrong with this layer? Report a problem and we fix it in the next version.
One text file, 30 KB, 12 sections. Every number the page uses is in it, so another model can rebuild the layer without seeing this one.
# Material Shift: build prompt
## Role
You are a senior creative front-end developer. Build the layer below as one self-contained `index.html`: {{BRAND_NAME}}'s product page for {{PRODUCT_NAME}}. At the top, a scroll-scrubbed film: one vase turns from clear glass to honed stone to brushed steel across three scroll chapters. The vase never moves; a band of change climbs it from base to rim, and a large roman material word fills bottom-up in step with the band. A finish picker scrolls to each material. Below: the three materials as rows with stills from the film, a dimensions and care table, a reserve card and a four-group footer. It must read as a real studio's site, not a demo.
## Output contract
- One file `index.html`, no build step, no framework: plain HTML, CSS and an ES module.
- Import map with one exact version: `"lenis": "https://cdn.jsdelivr.net/npm/lenis@1.3.27/dist/lenis.mjs"`. Load it with `import('lenis')` after first paint (ignore failures); until it resolves, read `scrollY` and scroll natively.
- Fonts: one Google Fonts link after the preconnects, non-blocking (`media="print" onload="this.media='all'"`), `display=swap`: {{FONT_DISPLAY}} roman only, 300 and 400 across its optical-size axis (`Newsreader:opsz,wght@6..72,300;6..72,400`; no italic axis), {{FONT_BODY}} 400 and 500.
- Real DOM text for all copy; canvas, scrim, grain layer and the outline copies of the material words are `aria-hidden="true"`. Sections below the film carry `aria-labelledby`.
- Expose `window.DUSKLAYER = { version: 1, params, set(values), pause(), resume(), ready }`. `set` merges known keys and re-applies them. `ready` resolves one frame after the first film frame is drawn; then set `document.documentElement.dataset.dusklayerReady = '1'`.
- Presets live in `<script type="application/json" id="dusklayer-presets">` between `/*PRESETS*/` and `/*/PRESETS*/` markers (strip them before `JSON.parse`); `params = { ...PRESETS[0].values, ...preset.values }`, then `?seed` overrides `seed`.
[28,438 more characters. Copy the prompt to get all of it.]An earbuds pod separates into seven labelled parts as you scroll.
A bottle drops into its own splash as you scroll, then the camera circles it while droplets cross the headline.
An underwater scene that rises through the surface as you scroll.