Velora
FoundationsColour · Type · Motion · Material

A black-and-white base with three flat colours and no gradients, two type families split by who is speaking, five named springs, and the surface utilities. Everything a component is allowed to use lives here.

Colour

Every token is OKLCH, so lightness steps are perceptually even and the light theme is a re-declaration rather than a second palette. The base is black and white with a ladder of neutral greys, and three flat colours sit on top of it — orange, yellow and pink. They are never blended: there is no gradient anywhere.

Ground

Zero-chroma white and near-black. Never tint the dark ground: a navy or violet background is the fastest way to make a site look generated.

--bg

var(--bg)

--bg-sub

var(--bg-sub)

--surface

var(--surface)

--surface-2

var(--surface-2)

Ink

Three weights of type colour. Anything below --fg-faint stops passing contrast against the ground, so there is no fourth.

--fg

var(--fg)

--fg-muted

var(--fg-muted)

--fg-faint

var(--fg-faint)

Structure

Borders and the lattice are alpha, never a solid grey, so they sit correctly on both the ground and a raised panel.

--line

var(--line)

--line-strong

var(--line-strong)

--dot

var(--dot)

Colour

Three flat colours on the black-and-white base, never blended into a gradient. Orange marks actions, pink marks anything in progress, and all three rotate through the icon tiles. Each loader wears one: generation orange, mosaic yellow, trace pink.

--orange

var(--orange)

--yellow

var(--yellow)

--pink

var(--pink)

--on-colour

var(--on-colour)

Signal

What the components read for their crest, readout and status dot. It points at orange here; retheme the components by changing it.

--accent

var(--accent)

--accent-soft

var(--accent-soft)

--accent-fg

var(--accent-fg)

Artwork

The demo pictures are black-and-white prints. Declared once and not re-declared for dark: a generated image is content, and content does not invert with the theme.

--art-deep

var(--art-deep)

--art-mid

var(--art-mid)

--art-light

var(--art-light)

--art-sun

var(--art-sun)

Typography

Two families, two jobs. Geist Sans carries everything we say, from display headlines to body copy. Geist Mono is the machine: prompts, readouts, identifiers, progress.

Display

Geist Sans · 600 · -0.052em

Animated components for AI products.

Section

Geist Sans · 600 · -0.045em

Next on the bench.

Title 3

Geist Sans · 500 · -0.02em

Resolution arriving, not coverage

Body

Geist Sans · 400 · 1.625 line-height

Anything a person can interrupt uses a spring, so it redirects from where it actually is rather than restarting a curve.

Machine

Geist Mono · 12.5px · prompts, readouts, identifiers

> a ridge line at first light, layered haze

Label

Geist Mono · 11px · 0.16em · uppercase

Family 01 · Image

Display lines are set big and tight. Emphasis inside a headline is a second tone of the same ink — the claim at full strength, the qualifier in grey — never a colour and never a gradient.

Motion

Five springs, named for what they are for rather than for their numbers, all from Motion. Durations exist only for passes nobody interrupts — a generation running, a caret blinking — where the ease-in-out is what gives the front its run-up and its landing.

Stiffness · damping · mass

press620 · 30 · 0.6
snappy420 · 32 · 0.7
smooth260 · 30 · 0.9
liquid170 · 21 · 1.1
gentle110 · 20 · 1.0
ease (for contrast)0.6s cubic-bezier

One property a frame

A loader animates hundreds of cells by writing a single custom property per frame. Each cell derives its own colour, size and opacity from it in CSS — no per-frame React renders.

Reduced motion

Every component calls useReducedMotion and lands on its finished state at once. Nothing is merely slowed down, and no information is carried by motion alone.

Material

Six utilities describe every surface. They are plain CSS in globals.css, not components, so they compose with anything. There is no grain and no noise texture — a flat fill is held together by a hairline, the lattice and the motion on top of it.

.dot-grid

A static lattice of 1px dots — the same lattice the loaders resolve out of. Used behind component stages only, never as page decoration. Never animated.

.panel

Opaque, lit from above: a single-colour face, a bright top rim, a shade pooling inside the bottom edge and two drop shadows. For consoles and dense content.

.inset-well

The inverse of a panel — a stage cut into the surface. Every loader's frame sits in one, so the picture reads as being made inside the interface rather than pasted on it.

.glass

Blur plus saturate, a specular hairline and a soft shadow. For chrome floating over a picture — the mosaic's HUD strip, a readout chip.

.liquid-field

Glass for form fields only: a specular top rim and light pooling inside the bottom edge. Light and blur, never a tint. Restraint is what keeps it reading as Apple rather than as a theme.

generating

.caret

A block standing in for the next token. It blinks in steps rather than fading, because a caret that breathes reads as a loader and this one is waiting.