Gradients are stored as data rather than a CSS string, and each layer kind renders one differently — with two that ignore gradients entirely.
Stored as data, never as a CSS string, so the same value paints on canvas, reads back into the editor, and rides along inside a style preset.
Gradient { kind: "linear" | "radial" | "conic", angle, cx, cy, stops: { colour, at }[] }angle is direction for linear, sweep start for conic, and unused by radial. cx/cy are 0–1 origins for radial and conic only. MIN_STOPS = 2, MAX_STOPS = 8; addStop and removeStop are no-ops at the limits rather than errors.
Ten presets. CSS emission sorts and clamps stops first, rounds percentages to one decimal.
| Kind | Rendering |
|---|---|
| text | backgroundImage + backgroundClip: text + color: transparent |
| rect / line | backgroundImage on a div |
| ellipse | A div with borderRadius: 50% — deliberately not SVG, so a ramp and a border both work without a paint server |
| triangle | Stays SVG (a border cannot follow it), so the ramp becomes a <defs> paint server. Conic falls back to linear — SVG has no conic ramp |
| icon, image | Gradients are ignored |