Oxide house system

One ring. Two names.

Everything a customer sees from Oxagen and Stella comes from one system, Oxide: soot and bone grounds, the open ring, Space Grotesk at its regular weight, and a gold that marks who acts.

oxagen lockup on soot
stella lockup on soot
oxagen lockup on bone
stella lockup on bone

Oxide

The decision

Mac set Oxide on 2026-10-09. It takes its look from macanderson.com: a warm near-black ground called soot (#151515), a cream ground called bone (#FCFDFC), the open ring as the mark, Space Grotesk headings at weight 400, round pill controls, and a brighter gold with a new rust in place of the old metal gold on obsidian.

Logos

Wordmarks

Both words are Space Grotesk 400, lowercase, at 131.7px per em. oxagen's x takes the gold, gold-deep on bone, and every other letter takes the text colour. oxagen is 453 by 93 in its ink box. stella is followed by a drawn gold asterisk, 399 by 94 with it.

baselinex-heightcap height453 x 93 box, em 131.7, Space Grotesk 400
oxagen construction
baselinex-heightcap height399 x 94 box, em 131.7, Space Grotesk 400
stella construction

The drawn asterisk

stella's asterisk is drawn, not taken from the font. It has six arms from one centre, made of three strokes with round caps: one upright, and two at 30 degrees either side of horizontal. Its box is 0.42 of the font size, and its top meets the cap height. Its stroke changes with the size the word is set at, so it keeps the weight of the letters: 3.4 on a 24 box at 64px and up, 3.7 at 38px, 4.2 at 25.4px, and 4.7 at 20px.

clear space: one x-height on every side
clear space: one x-height on every side

Variants

adaptive: the letters follow the page
mono: one colour, for print
sheen: light passes over the asterisk

Lockups

A lockup is the mark, a gap, and the word. The mark's 64 grid stands 1.5 times the font size, the gap is a third of the mark's height, and the mark centres on the x-height. stella's lockup drops the asterisk after the word, because the icon already holds it. oxagen's lockup carries the gold twice, in the agent dot and the x. stella's carries it once, in the asterisk.

oxagen lockup, sheen
stella lockup, mono

Minimum sizes

Wordmark 88px wide on screen, 24mm in print. Icon 24px, 8mm. Lockup 120px, 32mm. Below that, use the favicon.

Misuse

paint the word gold
use the font's asterisk
put the icon before stella and keep its asterisk
use another gold
set the word bold
stretch or condense

Icons

The open ring

The oxagen mark is the open ring, drawn on a 64 grid. The ring is centred at (32, 32) with radius 21 and a 4.5 stroke with round caps. Its gap is 64 degrees wide, centred 45 degrees up and to the right. The person is a dot of radius 5.5 at the centre, in the text colour. The agent is a gold dot of radius 4.25 at the gap, on the ring itself. On soot a rust glow sits behind the agent. On bone the agent takes gold-deep and the glow drops.

The person sits at the centre. The ring is the agent's loop. The gap is where the person steps in.

stella shares the ring. Its gold asterisk sits at the centre in place of both dots, with arms of 9 and a 4.2 stroke. The gap stays open for the person.

64 grid, centre (32, 32), ring radius 21, stroke 4.5gap 64 degrees, centred 45 degrees up and to the rightperson r 5.5agent r 4.25
construction on the 64 grid
oxagen and stella, side by side
oxagen on soot
stella on soot
oxagen on bone
stella on bone

Small marks thicken so the gap stays open. For oxagen the ring stroke, the person, and the agent are 32px: 5, 6, and 5, 24px: 5.5, 6.5, and 5.5, 16px: 7, 7.5, and 7. stella's ring and asterisk thicken the same way. A favicon PNG comes from a tile, because a ring in the text colour on nothing is no favicon on a tab of the same colour.

oxagen favicon 1616
oxagen favicon 3232
oxagen favicon 4848
oxagen app icon180 app
stella favicon 1616
stella favicon 3232
stella favicon 4848
stella app icon180 app

Colour

Palette

The gold is #F4B13E. Its two neighbours are derived from it in OKLCH, a colour space where equal steps look equal, and the build fails if they stop matching. The gold clears 9.7:1 on soot. On bone it is 1.8:1, so it never sets words there.

gold#F4B13Eidentity, and the one action on a screen
L 0.80, C 0.147, H 77
gold-bright#FFC567the gold action under the pointer, on soot
L 0.86, C 0.129, H 78
gold-deep#DF9D21the gold as a mark on bone
L 0.74, C 0.147, H 77
on-gold#1A1208the words on a gold fill
L 0.19, C 0.023, H 72

Rust is new in Oxide. Its words clear 4.5:1 on every surface of their theme, the same check the build runs for a status word.

rust#F4B13Ea mark, the glow, and the sweep, on soot
L 0.80, C 0.147, H 77
rust-text#F4B13Elinks and the accent word, on soot
L 0.80, C 0.147, H 77
rust-ink#9B6900a mark and the focus ring, on bone
L 0.56, C 0.117, H 76
rust-text-ink#865900links and the accent word, on bone
L 0.50, C 0.106, H 75

Ember ramp

The ember ramp is for charts of heat and volume, from low to high. It runs from rust's darkest tone up through the gold. The tokens are --ox-ember-0 to --ox-ember-7.

#2C1C00#493000#6B4800#8F6203#B57D08#D59725#F4B13E#FFD691

Grounds

Dark comes first. Each step up from the canvas is one step lighter on soot: the sidebar and fields, the panel, then the lifted row a pointer or the current item takes. On bone the lifted row steps darker. Every page ships both themes.

ink#151515
void#111111
panel#1A1A19
hl#20201F
border#2C2C2C
rule#474746
paper#FCFDFC
paper-void#FBFBF9
paper-panel#FFFFFF
paper-hl#EDECE8
paper-border#E3E4E3
paper-rule#CCCCCB

Text

Text comes in four roles, each with one value on soot and one on bone. Every role that carries meaning clears 4.5:1 on its ground, and the build checks it. The quietest text is for decoration only.

RoleOn sootOn boneUse
primaryAa #FCFDFC 17.9:1Aa #151515 17.9:1headings and the words that matter most
bodyAa #C8C7C2 10.8:1Aa #3A3936 11.3:1paragraphs and table cells
secondaryAa #9B9993 6.4:1Aa #52514E 7.8:1labels, captions, help text, and eyebrows
quietestAa #898782 5.1:1Aa #898782 3.5:1decoration only, never a word the reader needs

Status

A status shows a 16px glyph and a word, never colour alone. A filled dot is allowed or settled. The orbit is live work. The open ring with the mark's gap waits on a person. A diamond is failed. A hollow ring is quiet. The word sits beside the glyph in primary text at weight 500.

The hues are verdigris for allowed, lapis for approval, garnet for failed, denied, and critical, and verdigris teal for proven. Quiet states, such as waiting or closed, take secondary text.

On sootOn boneMeaning
allowed
mark #5FBF9F
words #60C0A0
allowed
mark and words #19704F
a request a rule allowed
approval
mark #7AA2F0
words #81AAF9
approval
mark and words #2E5FBF
a request routed to a person
denied
mark #E5596E
words #FF7688
denied
mark and words #B3283F
a request a rule denied
proven
mark #4FB3A9
words #5CBEB4
proven
mark and words #1C6F68
a result a named check proved
failed
mark #E5596E
words #FF7688
failed
mark and words #B3283F
a check that did not hold
critical
mark #E5596E
words #FF7688
critical
mark and words #B3283F
a run that needs a person now

Priority

Priority is an outlined badge with no fill, in Geist Mono 600. P0 takes a garnet border and garnet words. An item with no priority reads "none" in secondary text, with no badge.

P0 P1 P2 P3 none

Every token

TokenValueOn sootOn boneUse
--ox-gold#F4B13E9.7:11.8:1the gold: identity, and the one action on a screen. flat, always
--ox-gold-bright#FFC56711.7:11.5:1the gold action under the pointer on soot; the shimmer's light
--ox-gold-deep#DF9D217.8:12.3:1the gold as a mark on bone: the agent dot, the asterisk, the eyebrow square
--ox-gold-text-ink#8960163.3:15.5:1deprecated: gold as words on bone. Words take rust-text-ink
--ox-on-gold#1A12081.0:118.2:1the ink on a gold fill, in both themes
--ox-rust#F4B13E9.7:11.8:1where you are, as a mark and the sweep on soot: a gold stop
--ox-rust-text#F4B13E9.7:11.8:1where you are, as words on soot: links and the accent word
--ox-rust-ink#9B69003.8:14.7:1where you are, as a mark and the focus ring on bone
--ox-rust-text-ink#8659003.0:16.0:1where you are, as words on bone: links and the accent word
--ox-rust-deep#6240002.0:19.1:1the deep gold, for a fill under light text
--ox-ink#1515151.0:117.9:1the dark canvas: soot
--ox-void#1111111.0:118.5:1one step below the canvas: the sidebar and fields
--ox-panel#1A1A191.0:117.1:1panels, cards, code blocks
--ox-hl#20201F1.1:116.0:1a lifted row: hover and current
--ox-border#2C2C2C1.3:113.7:1hairlines on soot
--ox-rule#4747462.0:19.1:1a control's border on soot
--ox-paper#FCFDFC17.9:11.0:1the light canvas: bone
--ox-paper-void#FBFBF917.6:11.0:1one step from bone: the sidebar and fields
--ox-paper-panel#FFFFFF18.3:11.0:1light panel
--ox-paper-hl#EDECE815.4:11.2:1a lifted row on bone: hover and current
--ox-paper-border#E3E4E314.3:11.3:1hairlines on bone
--ox-paper-rule#CCCCCB11.4:11.6:1a control's border on bone
--ox-text#FCFDFC17.9:11.0:1primary text on ink
--ox-text-body#C8C7C210.8:11.7:1body text on ink
--ox-muted#9B99936.4:12.8:1secondary text on ink
--ox-dim#8987825.1:13.5:1the quietest text on ink: decoration only
--ox-text-ink#1515151.0:117.9:1primary text on paper
--ox-text-ink-body#3A39361.6:111.3:1body text on paper
--ox-muted-ink#52514E2.3:17.8:1secondary text on paper
--ox-muted-text-ink#52514E2.3:17.8:1secondary text on paper and on a lifted row there
--ox-dim-ink#8987825.1:13.5:1the quietest text on paper: decoration only

Type

Typefaces

Space Grotesk sets hero copy, every h1 to h3, and both wordmarks, on every surface, the app included. It always takes weight 400, and never runs below 20px. At the shipped bases its smallest step is 21.14px. Geist sets h4 to h6 and every other line. Geist Mono sets code, ids, digests, agent and runtime names, figures, and eyebrows.

Aeonik, Aeonik Mono, Aeonik Fono and Monaspace Neon load too, so a page that still names one keeps working. No role reads them.

Aa Gg 1234Space GroteskHero copy and every h1 to h3, at weight 400.--ox-font-displayweights 400
Aa Gg 1234GeistBody, labels, buttons, tables, navigation, and every h4 to h6.--ox-fontweights 100 to 900
0O 1lI 4f2cGeist MonoCode, ids, digests, agent and runtime names, figures, and eyebrows.--ox-font-monoweights 100 to 900

Samples

hero 400Your agents are a workforce now.
h1 400See which agent spent what.
h4 600Runs waiting for approval
text 400A rule the owning team wrote answers each request: allowed, denied, or routed to a person.
eyebrowSpend this week
figure$41.20

Scales

A surface picks one scale and keeps it. The marketing scale (text-m-*) is large and spaced, for a page read once. The app scale (text-a-*) is dense, for the web app, panels, tables, and logs. Each scale has one base: 16px on marketing and 14.8px in the app. Every other step is the base times its ratio, so a new base moves every step.

The steps under the base are for labels, badges, timestamps, and table headers: app micro is 12.69px, app 2xs is 11.1px, and marketing micro is 14px. Running text, buttons, inputs, menu items, and table cells use the base. Every size reads a step token or a house utility.

StepMarketing faceRatioSize, leading, weight, trackingApp faceRatioSize, leading, weight, tracking
base--ox-m-base16--ox-a-base14.8
herononeSpace Grotesk3.64864954, 1, 400, -0.035em
h1Space Grotesk4.572, 1, 400, -0.035emSpace Grotesk2.56756838, 1.05, 400, -0.03em
h2Space Grotesk2.540, 1.1, 400, -0.025emSpace Grotesk1.71428625.37, 1.15, 400, -0.02em
h3Space Grotesk1.7528, 1.2, 400, -0.02emSpace Grotesk1.42857121.14, 1.25, 400, -0.015em
h4Geist1.2520, 1.35, 600, -0.01emGeist1.14285716.91, 1.35, 600, -0.01em
bodyGeist116, 1.625, 400, 0Geist114.8, 1.5, 400, 0
microGeist0.87514, 1.5, 400, 0Geist0.85714312.69, 1.45, 400, 0
2xsnoneGeist0.7511.1, 1.3, 500, 0

Weights

TokenWeightSampleUse
--ox-weight-display400Runs waiting for approvalhero copy and every h1 to h3, in Space Grotesk
--ox-weight-logo400Runs waiting for approvalthe two wordmarks
--ox-weight-heading400Runs waiting for approvala section heading, h1 to h3, in Space Grotesk
--ox-weight-subheading600Runs waiting for approvalh4 to h6, in Geist
--ox-weight-ui500Runs waiting for approvalbuttons, labels, navigation, and eyebrows
--ox-weight-body400Runs waiting for approvalparagraphs, table cells, and help text

Tracking

Tracking is the space between letters. Headings track tighter as they grow, so large type does not look loose. The eyebrow opens up.

TokenValueSampleWhere
--ox-tracking-hero-0.035emSee which agent spent whatmarketing h1, app hero
--ox-tracking-display-0.03emSee which agent spent whatapp h1
--ox-tracking-title-0.025emSee which agent spent whatmarketing h2
--ox-tracking-headline-0.02emSee which agent spent whatmarketing h3, app h2
--ox-tracking-subhead-0.015emSee which agent spent whatapp h3
--ox-tracking-heading-0.01emSee which agent spent whatmarketing h4, app h4
--ox-tracking-none0See which agent spent whatevery other step, and the wordmarks
--ox-tracking-eyebrow0.08emSee which agent spent whatthe eyebrow

Type rules

Surfaces

Shape and surface

A panel at rest is solid: a card, a panel, a table's frame, or the sidebar. It takes 19px corners, a 1px hairline, a lit top edge, and a soft deep shadow. Glass is only for what floats over the page.

Corner radius

Each step multiplies one base, --ox-radius-base, which is 0.45rem. A card takes rounded-4xl. On the website, cards and panels round at 18px (--ox-radius).

rounded-sm4.3px, base x 0.6a checkbox
rounded-md5.8px, base x 0.8a small badge, a skeleton
rounded-lg7.2px, base x 1a tooltip
rounded-xl10.1px, base x 1.4an alert, an empty state
rounded-2xl13.0px, base x 1.8a menu row, a toast
rounded-3xl15.8px, base x 2.2a menu, a popover, a hover card
rounded-4xl18.7px, base x 2.6a card, a panel, a table's frame, the sidebar, a dialog
field12pxa text field, 44px tall
pill999pxa button, a chip, a filter, the search field

Canvas

The canvas is the ground under every surface. It carries the ember glow, rust at 0% on soot and 0% on bone, as a radial about 820px wide at the top left, behind the mark. Film grain sits over the canvas, never over a panel. A product sets both as --glass-canvas.

Spend this weeklit edge and soft shadow
a panel at rest
Open run
Copy run id
Move to queue
a menu at the popover level
Spend this weeka gold glow
add a glow to a panel

Glass

A glass surface keeps part of its fill and blurs what lies beneath it, so the page shows through as soft colour. Text that rests sits on a solid panel.

LevelUseFill on soot / boneBlur on soot / boneSaturation
panela card, a panel, the sidebar, and a table's frame at rest: solid100% / 100%0px / 0px100%
bara sticky bar over scrolling content: the site's nav, the app's header75% / 78%12px / 12px150%
popovera menu, a select's list, a tooltip, a hover card, and a toast70% / 55%40px / 16px150%
sheeta dialog, the command menu, a drawer, and the phone nav85% / 85%40px / 24px150%
work order 4f2caccepted
policy deploy-prodapproval
budget fleet-nightly$41.20
steering repo-syncallowed
check build 2210proven
Open run
Copy run id
Move to queue
a menu over a table in its frame
work order 4f2caccepted
policy deploy-prodapproval
budget fleet-nightly$41.20
steering repo-syncallowed
check build 2210proven
Approve this deploy?

The agent runs deploy-prod once you approve.

a dialog at the sheet level over its scrim

Interaction

Hover and press

Buttons, chips, filters, and the search field are pills. A button is 44px tall, a small button 36px, and a chip 40px. Fills, borders, text, and underlines change over 200ms. The press and the gold action's glow take 250ms, and only the press moves on its curve. A pressed button sinks to 0.97. With reduced motion on, hover and press apply at once. Try each control below.

Buttons

Chips and filters

Navigation

Tabs

Fields

Links

Read the mandate before you approve.

WorkStatusAgent
Rotate the staging keysRunningnight-shift
Review the March invoicesIn reviewledger
Retry the failed deployFailingdeploy-bot

Motion

Spinners and the radar

The oxagen spinner is the mark thinking: the agent dot and a rust sweep orbit the centre once every 2.4 seconds. Below 32px the sweep drops and the strokes thicken. stella's asterisk turns once every 3.2 seconds inside its still ring. The radar is the full orbit field, for a page or panel that waits. All of it is CSS inside the SVG, and it holds still at rest under reduced motion.

oxagen spinner
stella spinner
oxagen spinner, bone tile
oxagen radar
oxagen loading masthead
stella loading masthead

Art

Composition

A piece of art is a ground with the ember glow and the grain, the brand's mark or its radar placed off-centre, and at most a few lines of type. Headlines are Space Grotesk 400, and every other line is Geist. Every surface below is the vector the kit ships.

Wallpapers

radar is the default: a still of the orbit field at the top right of the Work page, turned 65 degrees so the agent dot and the sweep are in view. graph wires a field of nodes to the mark in rust. blocks rebuilds the mark from tiles. orbit hangs rings of nodes off the mark. glow and quiet are the mark alone, faint and as a hairline. word and echo carry the wordmark. eclipse draws a giant open ring with a rust glow at its gap. trails circles the mark with star trails that all turn the same 56 degrees. contour draws a contour map with the mark on its summit. dusk sets the mark on a horizon, with its reflection in dashes on the water below. emboss presses the mark into the ground and stamps its gold in foil.

oxagen desktop, radar, dark
stella desktop, radar, light
oxagen desktop, graph, dark
oxagen desktop, blocks, light
stella desktop, orbit, dark
oxagen desktop, glow, dark
stella desktop, quiet, light
oxagen desktop, word, light
oxagen desktop, eclipse, dark
stella desktop, trails, light
oxagen desktop, contour, light
stella desktop, dusk, dark
oxagen desktop, emboss, dark
oxagen desktop, dusk, light
oxagen iphone, radar, dark
stella iphone, radar, light
oxagen iphone, orbit, light
oxagen iphone, echo, dark
stella iphone, eclipse, dark
oxagen iphone, trails, light
stella iphone, contour, dark
stella iphone, emboss, light

Social

stella avatar
oxagen avatar
stella avatar, bone
oxagen avatar, bone
oxagen x header, 1500 by 500
stella x header, bone
stella open graph, 1200 by 630
oxagen open graph, bone

Ads

Every ad takes its copy from an approved, launch-released entry in messages/. The kicker is the ad's eyebrow, with its gold square. The rule under the headline is rust. The workforce ad takes the radar behind its type, because it draws many agents under one control plane.

oxagen workforce, 1080 by 1350, dark
oxagen authority, 1080 by 1080, light
oxagen equipment, 1200 by 628, dark
oxagen finance, 300 by 250, light
oxagen keys, 1200 by 628, light
stella proof, 1080 by 1080, dark
stella check, 1200 by 628, light
oxagen night-shift, 1080 by 1080, dark

Content cards

stella changelog card, dark
oxagen field note card, light
oxagen fleet note card, dark

Files

Kit files

No file in this kit is drawn by hand. Every PNG is a render of the SVG beside it, and every SVG comes from build/. Every value comes from theme/theme.json, so one change there moves every asset on the next run.

playbook.html
this document
brand-guide.html
how to change the brand, with every control live
message-bank.html
every line, generated from messages/
messages/
the message registry: one YAML file per line
theme/
theme.json, the one file a person edits, and its schema
build/
the generators: color, typeset, glyphs, marks, surfaces, build, messages, playbook
build/reference/
the wordmark reference the build checks against
fonts/
Space Grotesk, Geist, Geist Mono, Monaspace Neon, Aeonik, Aeonik Mono, and Aeonik Fono
tokens/
house-tokens.css, house-tailwind.css, house-text-scale.css, house-fonts.css, next-fonts.ts
logo/svg, logo/png
wordmarks, icons, and lockups for both brands: dark, light, adaptive, mono, sheen, tiles
icons/
favicons and app icons, 16 to 512
spinners/
the marks in motion and the radar, animated SVG, no script
wallpapers/
desktop 4K, 5K, 6K and three iPhones, in radar, glow, quiet, graph, blocks, orbit, word, echo, eclipse, trails, contour, dusk, and emboss
splash/
launch screens: the radar with the lockup
social/
avatar, x, linkedin, youtube, open graph
ads/
every approved campaign at 1080 square, 1080 by 1350, 1200 by 628, and 300 by 250
content/
changelog, essay, release, field note, fleet note, and always-on cards, 1200 by 675
python3 -m venv .venv && .venv/bin/pip install fonttools brotli pyyaml
brew install harfbuzz librsvg
.venv/bin/python build/build.py --check   # check the theme and every file, write nothing
.venv/bin/python build/build.py           # every asset
.venv/bin/python build/build.py --svg     # skip the raster pass
.venv/bin/python build/playbook.py        # rebuild this document