§ Explained — A technical diary

How it was made.

Nine acts, one page, nothing but CSS and a little JavaScript for sprinkling stars. Here is what is happening underneath — scene by scene, technique by technique.

§ 01

Becalmed — A warm horizon

A quiet opener before the storm.

The first scene is a cream-on-cream landscape with a single horizon rule and a boat no wider than a thumbnail. It is built with a linear gradient, layered radial glows, and a 1 pixel divider drawn as a pseudo-element. The boat is a small inline SVG anchored to the horizon with position: absolute.

The slow sway is a sub-pixel translateY keyframe running at 4 seconds, easing in and out. Nothing fancy — the goal is to feel still without being actually still. Living rooms are never silent.

linear-gradient radial-gradient SVG symbol @keyframes

§ 02

Storm — Rain, lightning, pressure

A registered property drives the sky's darkness.

Storm is where CSS starts earning its rent. The sky is driven by @property --storm-darkness, a custom property registered with a typed syntax so it can be animated smoothly. As the value climbs, a stack of gradients deepens and a second --rain-density property multiplies the opacity of the rain layer.

Rain itself is a single repeating-linear-gradient translated at two speeds, creating parallax for free. Lightning is a pair of SVG bolts with a brief full-screen flash courtesy of mix-blend-mode: screen.

@property repeating-linear-gradient mix-blend-mode SVG filters

§ 03

Wave — Liquid displacement

SVG filters applied to HTML.

The wave uses an <feTurbulence> and <feDisplacementMap> pair defined once in a hidden SVG at the top of the document, then referenced from CSS with filter: url(#wave-displace). The turbulence animates its baseFrequency, which is what makes the text crest and fall as if a slow tide were moving through it.

This is the cheapest liquid effect you can buy. One filter reference, no canvas, no shaders — the browser is doing the math in its compositor.

feTurbulence feDisplacementMap filter: url()

§ 04

Break — A hidden starfield

Two hundred stars, six constellations, one discovered ship.

The break slide reads as a single line of centered type over empty dark. Scroll past it, though, and the flashlight cursor reveals roughly 220 procedurally placed stars, labelled Ursa, Lyra, Orion, Corvus, Cygnus, and Draco, four cardinal points, a lunar phase row, a sketched clipper ship and a few shooting stars.

The flashlight itself is a radial-gradient mask driven by CSS variables the cursor writes (--mx, --my). The stars are DOM elements the script avoids placing over the centered text — an exclusion zone — so the headline never fights the dots.

mask-image custom properties radial-gradient procedural DOM

§ 05

Figures in space — 3D without a canvas

Pure transform-style: preserve-3d.

Every solid on this slide — the cube, the torus of blades, the double helix, the trefoil knot, the tunnel — is made of plain <div>s laid out with transform: rotateX / rotateY / translateZ. The parent carries perspective and transform-style: preserve-3d, and the children orbit through @keyframes.

The blades, rungs, and beads are generated at load by controller.js, which does nothing more than stamp N children with a calculated transform. The motion is entirely CSS — the script never runs again after the initial build.

preserve-3d perspective rotate3d trigonometric layout

§ 06

Geometry — A grid with memory

Sixty-four tiles, one hover.

A display: grid of 64 tiles, each with a transition on transform and background-color. On pointer move, the act writes --px and --py; each tile computes its distance from the pointer with calc() and a squared pow() — no per-tile JS, just math in the style engine.

CSS grid calc() cursor-reactive vars

§ 07

Kinetic — Marching type

Two lines, opposite directions, a seam of light.

The kinetic band is a single line of type duplicated and animated in opposite directions via translateX. A gradient mask fades the edges so the seam never reveals itself. The glow across the center is a background-clip: text trick — a moving linear gradient painted into the glyphs rather than behind them.

background-clip: text mask gradient infinite loops

§ 08

Goo — Blobs that know each other

A classic feGaussianBlur + threshold.

The goo filter is an old favourite: blur the group, then clamp the alpha channel with a steep feColorMatrix. Any two circles close enough to overlap in the blur will merge. Move them apart and they snap into separate drops. The circles are divs with border-radius: 50% tumbling on their own keyframes.

feGaussianBlur feColorMatrix filter: url()

§ 09

Calm — Still water, still space

A mirrored horizon, a breathing moon, rings that never move.

The final act is a reflection. The sky holds a starfield drawn as a stack of single-pixel radial-gradients; the space shapes — three concentric rings around the moon, two tilted planetary ellipses, two tiny planets — are intentionally motionless. Stillness given a shape.

Below the horizon line, a darker gradient carries a vertical column of moonlight, three horizontal shimmer bands, and six expanding ripples capped at a modest scale. The headline beneath is duplicated, flipped with transform: scaleY(-1), blurred, and faded toward its bottom with mask-image — a live reflection in the water plane, drifting every six seconds with a sub-degree skew.

scaleY(-1) mask-image mix-blend-mode: screen staggered @keyframes

§ Notes

A few principles

One page, one cascade. Every scene loads from the same set of stylesheets. Tokens — colour, type, easing — live in colors_and_type.css and are consumed everywhere else.

Motion with a brake. Every animated block respects prefers-reduced-motion. The showcase still reads as a showcase with animations off — just quieter.

No shortcuts for typography. Fraunces handles the display work with its optical size axis pinned to 144 at hero scale. Inter carries the body. JetBrains Mono marks the edges — section numbers, tags, footers.

Nothing is a screenshot. Every pixel you see is computed. Resize, zoom, swap to dark mode, print it — it composes.

© 2026 Layerwright Studio ← Back to the showcase