Label
48
Placeholder line
2026-09 · Aesthetic
How a soft gradient field gets made, and then what to do with it. Shapes drawn and blurred until they are one, or the same look written as a stop list — either way projected onto whatever geometry it is given. Shape and theme are separate axes, and everything else is a custom property.
Start here: this is where the colour comes from. Draw a few overlapping shapes in flat colour and blur them past recognition — the overlaps become the mid-tones a stop list has to be hand-tuned to produce. Each pair below is the same SVG: as drawn, then blurred. They are grouped by colour, three to a family — the theme is a separate axis from the drawing, so any of these shapes takes any of these colours.
Orange
Sunburst — radiating wedges
blur 0.16
Desert — dunes and a low sun
blur 0.18
One leaf, turned three times
transform="rotate(...)"
Blue
Quatrefoil, ribbon, star
--drawn / --raw
Pixels — a coarse mosaic
blur 0.1
Prism — crossed diagonals
blur 0.12
Mint
Ocean — stacked swells
blur 0.2
Crescent, teardrop, wedge
--drawn / --raw
Spots — a scattered field
blur 0.16
Night
Scanlines — analogue bands
blur 0.09
Ripples — concentric rings
blur 0.14
Nebula — drifting clouds
blur 0.24
With a field in hand, it gets projected onto geometry. One drawing and one theme are held constant here so geometry is the only variable — only border-radius and aspect-ratio change, and the artwork is re-projected to cover whatever it is poured into.
Tile
--tile
Circle
--circle
Arch
--arch
Pill
--pill
A theme sets three colour stops and nothing else, so it composes with any shape and either recipe. `--night` is the exception: it moves the base the colour settles to, and layers over any of them.
Five themes
--dawn --dusk --mint --ice --arc
Settling to ink
--night
Label
48
Placeholder line
Pools moved
--…-pool-x/y, --…-settle
Settle direction
default / --rise
Both recipes at once
--mix, --…-mix: 1 / 0.5 / 0
Content sits in the lower half, where the recipe has settled to the base and nothing needs a scrim to stay legible. --step is the other way round: the surface goes inside a block of type, its steps landing on the same lines.
Card ground
--card
Label
48
Placeholder line
Long to short — the step walks left
--step --ice --night
Short to long — the step walks right
--step --arc --drawn
Long to short, drawn rather than stopped
--step --arc --drawn --down
Two blocks, one field — the upper settle flipped
--step --rise / --step
Section band
--band
A section header
Section band
ref.png is a weather widget's gradient treatment, and it is where the recipe comes from: the two pools, the settle, and the drawing-then-blurring the folder is named after. ref2.png is a stepped block set into three lines of type, and it is where --step comes from — the interlock and nothing else. Not its rounded concave corners, not its palette, and not its copy.
The widget's content is not what is being captured. What is captured is how the colour sits on the surface: the reference could hold anything, and the gradient would still read the same way.
Rebuilt around how such a field is made. The primary technique here is to draw a few overlapping shapes in SVG and blur them past recognition — the shapes are the instrument, not the subject, which is why they are not what the reference is named after. A hand-written stop list reaches the same look more cheaply, so both are kept: the drawing for surfaces that are large or moving, the stop list for the static ones.
--drawn swaps the stop list for an SVG of two or three overlapping shapes blurred past recognition. The overlaps supply the mid-tones a stop list has to be hand-tuned to produce, and shapes with points — a star, a leaf — leave soft spokes that no arrangement of radial stops will give you. Two things make it work: the blur is a ratio of the surface rather than a fixed length, so it dissolves by the same amount at any size — and the ratio is per drawing, since a dense one (a mosaic, a scatter, stacked bands) averages to a single flat colour at the 0.26 a few large shapes want, and needs 0.1 or less; and the artwork bleeds 22% past the frame before being clipped, because blur samples the transparency outside the drawing and a fitted drawing fades to a vignette at every edge. --raw shows the same drawing before the blur, which is the useful half when building a new one. It carries no construction outline: at half fill-opacity the shapes already read from their own edges, and a stroke around each one fences off the overlaps — the part of the drawing actually worth seeing. --…-raw-stroke puts an outline back for anyone who wants one. On --night a drawing also has to cover the frame. Where the artwork leaves a gap the base shows through, and that gap reads as a highlight on paper but as a hole on ink — a mosaic with empty cells and crossed bands with open diamonds both blur to a blotchy field there, so they stay on the light themes and the night set is drawn edge to edge.
Colour gathers at two off-centre origins near the top edge and dissolves outward; a linear-gradient underneath carries the last of it down to the base. One linear ramp corner-to-corner is what makes cheap gradients band — the eye finds the axis. With the pools offset from each other there is no axis to find, and the falloff stays smooth at any size.
The bottom ~40% is plain #fff. That is what makes the shape read as lit from one corner rather than as a two-colour blend, and it is why body copy can sit on the lower half without a scrim.
The hot stop is the only saturated colour; the wash stop is already half-way to the base. Fading a gradient by lightness alone leaves a muddy middle — dropping saturation first keeps the mid-tones clean.
--drawn-gradients-art is declared once and every surface uses it; the shape modifiers change only border-radius and aspect-ratio. The pools are positioned in percentages, so a circle, a pill and a full-width band each get the same light from the same relative direction rather than needing their own gradient.
The figure, label and micro line are calc()s of --…-size, not fixed rem. Set in rem they stayed put while the card scaled, so a card shown small kept full-size type and the label ran outside its own box. The ratios resolve to the original values at the default size; only the legend that names a set keeps a fixed size, because it sits beside the surfaces rather than on them.
12% on the tile, so the squircle character holds whether the shape renders at 96px in a thumbnail or at 400px on a page. A fixed border-radius in px reads as a different shape at each size.
notes.md — the full record, including what was tried and dropped