Design Language

Type & Space

Three families, one scale, and the rhythm they sit on.

Three families, three jobs

Figtree is the interface. It carries every label, every button, every table cell, and it is the reason the product reads as calm rather than as literary. Instrument Serif is for names and titles only: the wordmark, page headings, section heads. Geist Mono is for anything a person might have to compare character by character.

The split has one hard rule behind it, and it comes from the logo: the word "Phloom" is always live Instrument Serif text, never an outlined graphic. That is why the wordmark can animate per letter, why it is what a screen reader announces, and why the symbol beside it is always aria-hidden.

Serif italic is not a utility voice. It was tried for descriptions under admin page titles and failed the review: at small sizes it is harder to read than the sans, for no gain. It stays reserved for genuine marginalia.

--font-sans · Figtree

Interface, labels, prose

Straight-sided digits with tabular numerals available, which is why it can carry data tables.

--font-heading · Instrument Serif

Names and titles

Also the wordmark, as live text. Never used for utility copy.

Geist Mono

IDs and addresses

Anything comparable character by character: tokens, hosts, UDIDs.

via font-mono

The scale

These are utilities, not sizes to reinvent per page. Each row below is set in the real class named beside it, so what you are reading is the scale as it currently exists rather than a description of it.

type scale utilities
.font-display

Every device, one tab

Marketing display type. Serif, tight, with an optional stroke weight escape hatch.

.font-display-sm

One farm, every phone

Display type at section scale.

.text-h1

Device control

Page title. Serif.

.text-h2

Provider hosts

Section title.

.text-h3

Streaming settings

Subsection.

.text-body

A phone is either free, in use by one person, or offline. Nothing else.

Default reading size for prose.

.text-body-sm

Utility copy under a heading, and most descriptions in the app.

The most-used body size in the product interior.

.text-caption

Last seen 5 minutes ago

Metadata, timestamps, counts.

.font-mono-sm

01HB4K2M9QZ · 192.168.1.24

Identifiers, addresses, anything a person may need to compare character by character.

Numbers that line up

Any column of numbers a person compares gets .tabular-nums-pro. Proportional digits are prettier in a sentence and useless in a column, because the ones are narrow and the rows stop aligning. This matters more here than in most products: the usage and analytics surfaces are almost entirely columns of numbers.

proportional (wrong for columns)
1,118 min911 min11,181 min41 min
.tabular-nums-pro (right)
1,118 min911 min11,181 min41 min

Spacing

The Tailwind 4px step, used plainly. Interior page rhythm settles on a small vocabulary rather than the whole scale: gap-1.5 to gap-2.5 inside a control, gap-4 between cards, gap-6 to gap-8 between page sections, and p-5 rising to sm:p-7 inside a card. When in doubt, match the nearest existing surface rather than picking a new step.

the steps that carry the interior
0.25rem4px · gap-1
0.5rem8px · gap-2
0.75rem12px · gap-3
1rem16px · gap-4
1.5rem24px · gap-6
2rem32px · gap-8
2.5rem40px · gap-10
3rem48px · gap-12
4rem64px · gap-16

Radii, and the squircle step-up

Radii come off one root, --radius (currently ), multiplied into seven tiers in @theme inline. Retuning the root moves every corner in the product together.

The part worth knowing: a squircle needs MORE radius than a circle to look the same. Where corner-shape: squircle is supported, the shell and card utilities step their radius up inside an @supports block rather than leaving it alone, because superellipse corners read visibly tighter at the same number. A card is 1.25rem normally and 1.5rem as a squircle. Tiles inside it step down one tier, so a squircle card never contains circular tiles.

the tiers
sm
md
lg (root)
xl
2xl
3xl
4xl
card and tile corners, as the utilities draw them
.surface-card-corners
.surface-tile-corners
.shell-squircle-bar

In a browser with corner-shape support these are true squircles at a larger radius; without it they are plain rounding at the smaller one. Both are correct, which is the point of putting the step-up inside @supports.