Skip to content

The AgentForge design system

Toybox

Bright, playful and light-first. Saturated colour, thick outlines, hard offset shadows, fat corners and springy motion — the reference is a well-made toy: tactile, friendly, obviously clickable. Not a dark IDE, which is what every competing tool looks like. Toybox Night is the same toy after dark, held to the same rules.

Every contrast figure on this page is computed by the same module that fails the build when a token drops below WCAG AA — for the theme you are looking at. Switch it and every number changes with the colours. Nothing here is a claim.

Theme

Cream and ink. The default. Kept in this browser only.

Colour

Every chromatic token comes in two registers. The plain token is safe as text on any surface. The -pop token is a fill only, always with its accent-ink label and always inside its outline. No token is ever asked to do both jobs, because a saturated colour vivid enough to be a good fill is exactly where text fails WCAG AA.

Surfaces

In Light: cream page, paper card, white lifted object, deeper cream recess. In Night the same four, in indigo, in the same order. The steps between them are deliberately small in both: an object is separated from the page by its outline and its shadow, never by being a paler shade.

--color-canvas#fdf4dd

The page

surface16.36:1 AAAbody text on it
--color-surface#fffdf7

A card, a panel

surface17.59:1 AAAbody text on it
--color-elevated#ffffff

A node, a dialog, a popover

surface17.94:1 AAAbody text on it
--color-sunken#f6e9cb

An input well, a log list

surface14.86:1 AAAbody text on it

Ink and line

Text, the outline every object wears, and the hard shadow under it. In Light they are one near-black; in Night text, outline and shadow are cream, because a dark line on a dark page is invisible. All three text steps clear WCAG AA on all four surfaces in both themes — including the faintest, which was not true of the Chapter 1 dark palette.

--color-ink#131722

Body text, and the focus ring

text14.86:1 AAAworst surface
--color-muted#525768

Captions, help text, log lines

text5.92:1 AAworst surface
--color-faint#63687a

Placeholders, footnotes, digests

text4.58:1 AAworst surface
--color-line#131722

The outline every object wears, at 2px. Its own name since Phase 27, so the outline can differ from the text

graphic6.23:1 ≥ 3:1worst surface or fill
--color-shade#131722

The hard offset shadow. Every shadow-* utility draws in it

graphic14.86:1 ≥ 3:1worst surface
--color-scrim#131722

Behind a modal, at 25–35%. Darkens the page in both themes

backdroptranslucent, so no fixed ratio

Accent

Grape. The text register is the default — it is what a link and a label use. The pop fill is what a primary button uses, and its label is always accent-ink, the same near-black in both themes.

--color-accent#7f3dc4

Links, selected labels, the traversed edge

safe as text5.16:1 AAworst surface
--color-accent-pop#b57cff

The primary button, the selected tab

fill only6.23:1 AAits label on it
--color-accent-ink#131722

The label on any pop fill. Never cream, in either theme

fill label6.23:1 AAon the worst fill
--color-spark#02e9e9

The second gradient hue, and the run sweep. Never text

fill only11.79:1 AAAits label on it

Status

The engine's four step outcomes. Status is never carried by colour alone — every use pairs the tone with a word, an icon or a position.

--color-ok#007044

Succeeded

safe as text5.11:1 AAworst surface
--color-ok-pop#00f199

A success badge or toast

fill only12.04:1 AAAits label on it
--color-live#00698f

Running

safe as text5.08:1 AAworst surface
--color-live-pop#5fcbff

A running badge, the live edge

fill only9.83:1 AAAits label on it
--color-warn#7b5d00

Skipped, or a validation warning

safe as text5.12:1 AAworst surface
--color-warn-pop#ffd166

A warning panel's marker

fill only12.43:1 AAAits label on it
--color-bad#c21725

Failed

safe as text5.07:1 AAworst surface
--color-bad-pop#ff726b

A destructive button, an error marker

fill only6.70:1 AAits label on it

Node categories

Trigger, logic and integration deliberately share a hue with ok, live and warn: a trigger is the “go” of a graph, and one hue meaning one thing is worth more than five more colours. Shape, icon and label carry the distinction.

--color-cat-trigger#007044

Trigger nodes

safe as text5.11:1 AAworst surface
--color-cat-trigger-pop#00f199

A trigger node's colour band

fill only12.04:1 AAAits label on it
--color-cat-agent#a82795

Agent and LLM nodes

safe as text5.11:1 AAworst surface
--color-cat-agent-pop#fc73e3

An agent node's colour band

fill only7.44:1 AAAits label on it
--color-cat-logic#00698f

Branch, loop, delay

safe as text5.08:1 AAworst surface
--color-cat-logic-pop#5fcbff

A logic node's colour band

fill only9.83:1 AAAits label on it
--color-cat-transform#006d6d

Set, assert, log

safe as text5.08:1 AAworst surface
--color-cat-transform-pop#02e9e9

A transform node's colour band

fill only11.79:1 AAAits label on it
--color-cat-integration#7b5d00

HTTP, Discord, Sheets, Gmail

safe as text5.12:1 AAworst surface
--color-cat-integration-pop#ffd166

An integration node's colour band

fill only12.43:1 AAAits label on it

Themes

Light is the default and the reference; Toybox Night and System are choices a reader makes, kept in their own browser. Until Phase 27 one near-black did four jobs. On a cream page it can; on an indigo one it cannot — text must turn light, a label on a bright fill must stay dark, and an outline and a shadow must still show against the page. So each job has its own name.

The four ink roles and their value in each theme
RoleLightToybox Night
inkBody text, and the focus ring#131722#f8f1e2
accent-inkThe label on every pop fill#131722#131722
lineThe outline every object wears#131722#f8f1e2
shadeThe hard shadow under it#131722#f8f1e2

The fills are the one place the numbers decided the design. In Night a single outline must clear 3:1 against both the indigo page and every fill, which leaves the fills a band between “a dark label reads on it” and “a cream outline shows around it” — so Night's fills are a rich mid-tone rather than Light's near-pastels, and its text tones are the bright half instead. The two registers still sit twice apart, the other way round.

Contrast, measured

Every tone in the text register against every surface, graded against the 4.5:1 bar for normal-sized text — not the 3:1 large-text allowance, because the smallest tokens in this system carry 10 and 11px captions. These are the figures the build gate asserts.

WCAG contrast ratio of each text token against each surface, in Light
Tokencanvassurfaceelevatedsunken
ink16.36 AAA17.59 AAA17.94 AAA14.86 AAA
muted6.52 AA7.01 AAA7.15 AAA5.92 AA
faint5.04 AA5.42 AA5.52 AA4.58 AA
accent5.68 AA6.11 AA6.23 AA5.16 AA
ok5.63 AA6.05 AA6.17 AA5.11 AA
live5.59 AA6.01 AA6.13 AA5.08 AA
warn5.63 AA6.06 AA6.18 AA5.12 AA
bad5.58 AA6.00 AA6.12 AA5.07 AA
cat-trigger5.63 AA6.05 AA6.17 AA5.11 AA
cat-agent5.63 AA6.05 AA6.17 AA5.11 AA
cat-logic5.59 AA6.01 AA6.13 AA5.08 AA
cat-transform5.60 AA6.02 AA6.14 AA5.08 AA
cat-integration5.63 AA6.06 AA6.18 AA5.12 AA

Why the focus ring is ink, not the accent

WCAG 2.2 asks a focus indicator for 3:1 against what surrounds it. The accent fill is 2.63:1 against the cream page — under the bar. Ink is 16.36:1 there, and never below 6.23:1 on any fill in the system. So one ink ring is legal everywhere, and there is exactly one focus ring in the product.

Type

Geist and Geist Mono, self-hosted, variable axis. Three steps below Tailwind's smallest, because a node card, a status badge and a log line are all denser than body text. Mono is load-bearing rather than decorative: node ids, {{ }} references, cron expressions and JSON output are all monospaced.

text-3xs10pxDescribe the automationStatus badges, handle labels
text-2xs11pxDescribe the automationCaptions, log lines, help text
text-xs12pxDescribe the automationDense secondary text
text-ui13pxDescribe the automationForm controls and buttons
text-sm14pxDescribe the automationBody text
text-base16pxDescribe the automationA card or dialog heading
text-xl20pxDescribe the automationA section heading
text-3xl30pxDescribe the automationA page heading

Shape and elevation

A hard offset shadow, down-right, no blur and no spread — ink in Light, cream in Night, drawn in the shade token either way. Blur would read as a drop shadow; the hard edge is what makes an object read as a solid thing sitting on the page. The build gate refuses a shadow with a blur radius in either theme.

2px
shadow-flat

A checkbox, a switch — something small and fixed

3px
shadow-card

A button, a card, a badge

4px
shadow-node

A node card, a dialog, a toast

5px
shadow-lift

The hover state of anything with shadow-card

6px
shadow-drawer

A panel that slides over the page

1px
shadow-press

The pressed state — the object has moved into the page

Corner radius

rounded-sm
rounded-md
rounded-lg
rounded-xl
rounded-2xl
rounded-3xl

Primitives

The real components, not pictures of them. Every outlined object here presses into the page when clicked — it travels down-right by exactly the shadow offset it loses, so the shadow's far corner stays put and the object appears to move. Try them with a keyboard: every one is operable and shows a visible ink focus ring.

Tones

Sizes

States

A disabled button is flat on the table — no shadow to press, so no gesture. The loading button keeps its place in the tab order and reports aria-busy rather than becoming disabled, which would drop it out from under a keyboard user mid-announcement.

Motion

Eight named states, and nothing outside the list. Two curves: one that settles, one that overshoots. Everything here is decoration over a state that is also stated in text, which is what makes the blanket prefers-reduced-motion rule safe.

press120ms

An object moves down-right into the page and its shadow shrinks. Every button, every tab.

hover-lift120ms

The same object rises up-left and its shadow grows.

enter380ms

Something arriving: up, with a small overshoot.

appear200ms

Something appearing in place: a dialog, a tooltip, a menu.

success380ms

A settled overshoot. The toy landing in its slot.

failure420ms

A tight, short shake. “Look here”, not “your work is gone”.

waiting1.25s loop

Three dots bobbing in sequence. The agent is thinking.

idle3.4s loop

The mascot's bob. Decoration, and the only infinite motion that is not a status.

The two shadow states — press and hover-lift — have no keyframes, because they are transitions on an interaction. They are in the Primitives section above, where they can be felt rather than watched.

Illustration and character

Sparky is a forge sprite with three moods, and the third one is the careful one: a mascot must not read as flippant when someone's workflow has just failed. Concerned is attentive rather than sad — level mouth, inner brow ends raised, no tears — it is rendered small in error contexts, and it never replaces the error text.

happy
thinking
concerned

The thinking indicator

Used while an agent node is reasoning. The state is announced as a sentence; a bobbing dot is not information.

The agent is thinking

No workflows yet

Describe what you want in plain language and AgentForge will build the first one.

This canvas is empty

Drag a node in from the palette, or let an agent lay the whole graph out for you.

Nothing has run yet

Run this workflow once and every step's status and logs will stream in here.

Something went wrong

The page could not finish loading. Reloading usually fixes it, and nothing you saved was lost.

Accessibility

The constraints the system is built inside, rather than a list of things checked afterwards.

One focus ring, and it is ink

Near-black in Light, cream in Night. 2.5px, offset 3px, keyboard only. The offset leaves a gap of page colour between an object's own outline and the ring, which is what stops the two reading as one thicker border. No control anywhere sets outline-none.

Never colour alone

Every status pairs its tone with a word, an icon or a position. A pressed tab is darker AND moved. A failed toast is red AND says “Error” to a screen reader AND shakes.

An object is never drawn without its outline

Some fills sit as little as 1.3:1 off the cream page; in Night it is the cards that sit flat on the indigo. Either way the outline carries the separation, not the lightness — the build gate asserts both halves of that, in both themes.

Reduced motion is honoured, and the press is not motion

prefers-reduced-motion collapses every duration to zero. The 2px press displacement stays: that request asks for less animation, not for a control that stops responding.

Native elements where they are better

The select is a real <select>, the dialog a real <dialog>, the switch a real checkbox. Typeahead, focus trapping, Escape, the inert background and a phone's own picker all come free and are all commonly broken when hand-rolled.

The quiet register exists

A cartoon look earns goodwill on a landing page and gets in the way in a settings form. Form controls keep the outline and the radius and drop the shadow and the squish — a field is a hole in the page, not an object on it.