Batch 0
Foundations
Ten decisions that constrain everything after them. Colour, wire semantics, type, rhythm, surface craft, motion, icons, focus and the copy layer. Every later batch composes from these and adds no new raw values.
Colour and surfaces
A near-neutral interface so the circuit can be the only colourful thing on screen. Contrast is stated for every ink against the worst-case background.
Surfaces
app
#f5f7f8
Page background behind every panel
surface
#ffffff
Cards, panels, topbar
surface-sunken
#eef1f4
Circuit canvas, dock, inset wells
surface-hover
#f7f9fa
Row and ghost-button hover
surface-active
#eaeff3
Pressed state on quiet controls
surface-inverse
#111827
Tooltips, mono overlays on the canvas
Three depths only. Sunken carries the canvas and the device dock; raised is surface plus elevation, never a different colour.
Ink
ink
#11182716.5:1 AAA
Headings and primary body text
ink-secondary
#5b65765.5:1 AA
Supporting copy, descriptions
ink-tertiary
#6670854.6:1 AA
Metadata, evidence lines, timestamps
ink-disabled
#94a2b12.4:1 non-text
Non-text only: disabled glyphs, empty-state art
Measured against app background #F5F7F8 — the worst case in the product. Every ink that carries a word clears WCAG AA at 12px; ink-disabled is deliberately below it and is never allowed to hold text.
Lines
border
#e4e9ed
Hairline on cards, panels, inputs
border-strong
#cfd8e0
Dividers that must survive a busy canvas
grid
#dce3e8
Technical dot grid behind the circuit
Primary accent
accent
#1677ff
Primary buttons, active state
accent-hover
#0e63e0
Hover
accent-active
#0a53bd
Pressed
accent-soft
#eaf3ff
Selected row, active tab wash
accent-border
#b9d8ff
Inner layer on active surfaces
Electric blue is the agent's colour: actions it offers, tools it registers, targets it points at.
Secondary accent
teal
#14b8a6
Target rings, expected routes
teal-hover
#0f9e8e
Hover
teal-soft
#e6f7f5
Expected-state background
teal-border
#9ee4dc
Expected-state edge
Teal always means expected — the correct pin, the reference view, the position the servo should reach.
Status
success
#16a36a
Step verified, test passed
warning
#f59e0b
Recoverable finding
error
#e5484d
Failed test, blocking mismatch
success-soft
#e7f6ef
Passed row background
warning-soft
#fef4e6
Finding card background
error-soft
#fdecec
Failed row background
Each status is always paired with an icon and a word. Colour never carries the meaning alone.
Surface stack in context
app
surface
surface-sunken · canvas well
surface + elevation e2 · a floating panel over the canvas
The whole product is built from these four layers. Anything that looks like a fifth layer is elevation, not a new colour.
Semantic wire palette
Seven wire roles, each with a colour, an icon and a word. A cable is solid and plugged in at both ends; a dash means nothing is physically there. This is the only palette allowed to be saturated.
Roles
| Sample | Label | Meaning | Stroke | Token |
|---|---|---|---|---|
| 5V | Power | 3px · solid + rim | #e0393e | |
| GND | Ground | 3px · solid + rim | #3a4450 | |
| Signal A | Digital signal | 3px · solid + rim | #d99114 | |
| Signal B | Second digital signal | 3px · solid + rim | #2d7ff9 | |
| Servo signal | Position signal to the servo | 3px · solid + rim | #f5850f | |
| Servo GND | Ground, on the servo's brown lead | 3px · solid + rim | #8b4a1d | |
| Mismatch | Connected to the wrong point | 3.5px · solid + rim | #f0742a | |
| Expected | Where this wire belongs | 2.5px · dash 3 4 | #0fa98f | |
| Not wired | Nothing connected yet | 2px · dash 2 5 | #a9b4c0 |
A cable is always solid, however badly it is connected — a dash means there is nothing physically there. So a mismatch is never told by the stroke: the wire keeps its colour while every other one drains to grey, and the callout and pin marks say the rest.
Desaturated check
The same specimens with all colour removed. Cables stay separable from annotations — solid with a plug on each end against a bare dashed line — and power stays separable from ground by weight. Which cable is wrong is not a stroke property and never was: it is carried by the callout, the two pin marks, and the grey every other wire falls to.
Typography
Geist for the interface, IBM Plex Mono for anything the hardware reports or the sketch defines.
Geist — interface
display
30 / 36 · -0.021em · 600
Completion screen headline. Used once per screen at most.
Your build is working
h1
24 / 30 · -0.017em · 600
Dashboard and project detail headings.
Build real electronics with an agent beside you.
h2
19 / 26 · -0.012em · 600
Section headings, modal titles, project card titles.
Smart Parking Barrier
h3
15 / 22 · -0.006em · 600
Panel headers, finding titles, step names.
Connection mismatch
body-lg
16 / 24
Lead paragraph under a heading. Never inside dense panels.
Follow a real project, recover from wiring mistakes, and understand why every connection matters.
body
14 / 21
Default. Instructions, explanations, card copy.
Echo measures how long the reflected pulse takes to return.
body-sm
13 / 19
Dense panels: step rail, findings list, activity timeline.
Agent inspected wiring for Step 3
caption
12 / 16 · 500
Metadata under a title. Evidence lines, timestamps.
Camera frame · 94% confidence
overline
11 / 14 · +0.06em · 600 · uppercase
Group labels above lists. Sparingly.
Components in this step
Headings stop at 30px. This is a working tool: a headline that fills the viewport would push the actual product below the fold.
IBM Plex Mono — technical values
mono-lg
15 / 22
Live telemetry readout in the device dock.
Distance: 18 cm
mono
13 / 18
Serial monitor lines, tool names, pin references.
verify_current_step → passed in 240 ms
mono-sm
11 / 15 · +0.02em
Inline technical values inside body copy: D7, 5V, 94%.
D6 → D7 · 5V · GND
Anything the board reports or the sketch defines renders in mono with tabular figures, so a changing distance readout never shifts its neighbours.
Mixed in context
Wire the distance sensor
Connect the sensor's Echo pin to digital pin D7. Echo measures how long the reflected pulse takes to return.
Camera frame · 94% confidence
The pairing exists so a pin reference is recognisable mid-sentence without bold, colour or quotes.
Layout rhythm
A 4px scale for everything inside a panel, and fixed frames for the workbench's four zones.
4px scale
0.52pxIcon optical nudges only14pxIcon-to-label gap in dense chips1.56pxIcon-to-label gap in buttons28pxInside chips, badges, tight rows2.510pxList row padding312pxCard padding (dense), panel row gap416pxCard padding (default), panel padding520pxCard padding (roomy), section gap624pxBetween cards in a grid832pxBetween sections on a page1248pxBetween major page regions
Everything in the product snaps to this scale. Values above 48px only appear as page-level separation, never inside a panel.
Fixed frames
- topbar
- 64px
- Workbench control bar height
- rail
- 252px
- Left step panel width
- agent
- 360px
- Right agent workspace
- dock
- 44px
- Device dock, collapsed
- dock-open
- 224px
- Device dock, expanded
- shell
- 1360px
- Max content width off-workbench
The workbench is a four-zone instrument panel, so its regions are fixed rather than fluid. Only the canvas absorbs the remaining width.
Workbench frame at 1440×900
h 64w 252fluidw 360h 44 / 224Scaled proxy of Batch 7's four-zone layout, drawn from the same tokens. The canvas keeps 764px at 1440 and 604px at 1280 — enough for the board, breadboard and servo without scrolling.
Breakpoints
| Width | Behaviour |
|---|---|
| ≥ 1440 | Target layout. All four zones visible, dock expandable. |
| 1280–1439 | Same structure, canvas absorbs the difference. No horizontal scroll. |
| 1120–1279 | Agent workspace becomes a drawer over the canvas. |
| < 1120 | Stacked flow: instruction, canvas, steps, findings. Small-screen notice shown, nothing hidden. |
Radius and elevation
Restrained corners, three shadow levels, and inner layers instead of colour swaps for active states.
Radius
xs4px
Inline code, focus ring
sm6px
Badges, chips, pills
md10px
List rows, small wells
lg12px
Cards, findings, stages
xl14px
Fields, panels, dock, modals
2xl18px
Full-bleed feature block
full∞
Every button, badge, chip and segment
Surfaces sit at 10–14px. Interactive controls — buttons, badges, chips, segments — are full capsules, so shape alone separates “something to press” from “something to read”.
Elevation
e1
Resting cards. Barely there — the border does the work.
e2
Hovered cards, floating canvas controls.
e3
Popovers, dropdowns, modals. The only real lift in the product.
Three levels, all cool-grey and low-opacity. No glow, no coloured shadow except under the primary button.
Inner layers
Resting row
border + e1
Default
Active row
accent-soft + layer-active
Selected step, active tab
Sunken well
sunken + layer-sunken
Canvas, serial monitor
Active states add a second layer inside the surface instead of changing its colour wholesale. This keeps a selected row readable when it sits next to a coloured wire.
Raised primary
Static specimens — the live capsule buttons are in Batch 1.
The primary action lifts off the surface with a tinted shadow rather than a gradient — the one place the product allows a coloured shadow. Buttons are capsules (direction A).
Motion
Motion confirms that something happened. Four durations, three curves, five named behaviours, and a full collapse under reduced motion.
Preference
prefers-reduced-motion: no-preference
Full motion vocabulary active.
Every animated component reads this. When reduced motion is on, states still change — they just change immediately.
Durations
- instant
150msHover, focus, colour change - quick
220msTooltip, chip, finding card enter - settle
280msTab switch, step content swap, dock - deliberate
350msCanvas highlight, servo preview, guidance arrow
150–350ms. Nothing in the product animates longer than the time it takes to read the label that changed.
Easing
out-soft
cubic-bezier(0.16, 0.84, 0.44, 1)Default. Anything entering or settling.
in-out-soft
cubic-bezier(0.4, 0, 0.2, 1)Symmetric moves: pan, dock open and close.
overshoot
cubic-bezier(0.34, 1.26, 0.64, 1)Success confirmation only. One small bounce, never decorative.
Motion vocabulary
cp-pulse-ring
Agent is connected and listening. The only infinite loop allowed.
cp-trace
Light travelling along the wire the agent is talking about.
cp-attention
Error ring around a wrong pin. Fades, never flashes.
cp-sweep
A test stage is running with no known duration.
Five behaviours, defined once as keyframes. Components compose them; they never invent new ones.
Icon system
Lucide at 1.75 stroke weight, four sizes, and a small working vocabulary.
Stroke weight
2.0 — heavy
1.75 — product standard
1.5 — too faint at 14px
Lucide ships at stroke-width 2. Against Geist at 13–14px that reads heavy and slightly toy-like, so the product standardises on 1.75.
Sizes
xs14px
Inline with caption and mono-sm
sm16px
Buttons, list rows, tabs — default
md18px
Panel headers, toolbar actions
lg20px
Empty states, feature blocks
Icons sit on the text baseline with a 6px gap and never shrink below 14px. Icon-only controls always carry an aria-label.
Working set
Navigation & shell
ArrowLeft
Search
SlidersHorizontal
ChevronDown
Settings2
RotateCcw
Status
Check
TriangleAlert
CircleAlert
Activity
Play
Canvas
ZoomIn
ZoomOut
Maximize
Layers
Crosshair
Eye
Build domain
CircuitBoard
Cpu
Gauge
Lightbulb
Plug
Wrench
ListChecks
Terminal
Sparkles
A deliberately small vocabulary. New icons get added only when an existing one would mislead.
Focus
One visible ring on every interactive element, and hit areas that stay reachable in dense panels.
One ring
Press Tab through this row. Every interactive element in the product uses the same 2px accent ring at 2px offset — no per-component variation, no ring suppressed for aesthetics.
On coloured ground
outline-color switches to white; width and offset stay identical.
The ring keeps a white inner halo when it lands on an accent or status surface, so it never disappears into its own background.
Hit area
40×40
44 tall
Minimum 40px for dense panel controls, 44px for anything primary. Small glyphs get padding, not a smaller target.
Content layer
Brand and copy live in data, not in components — the working name can change without touching a screen.
Brand record
| brand.name | PilotCircuits |
| brand.agentName | Build Coach |
| brand.protocol | WebMCP |
| brand.origin | https://pilotcircuits.com |
Rename the product by editing one object. Nothing downstream hardcodes the name.
Copy namespaces
copy.labcopy.wirecopy.brandcopy.navcopy.dashboardcopy.landingcopy.projectscopy.componentscopy.conceptscopy.librarycopy.statuscopy.projectDetailcopy.buildcopy.briefingcopy.workbenchcopy.democopy.agentPanelcopy.findingscopy.coachcopy.workspacecopy.devicecopy.testcopy.inspectioncopy.completecopy.a11yScreens import one namespace each. Strings that appear in more than one place — status labels, agent actions — live in a shared group so they can never drift.
Voice
Good
“Echo is connected to D6. This build expects D7.”
Avoid
“Oops! Something went wrong with your wiring! 😅”
Good
“Demo feed · Simulated UNO-compatible board”
The interface always says when it is showing simulated data.
Short, factual, second person. The product states what it observed and what it expects; it never congratulates the user for existing, and never claims a capability it does not have.