OpenFactory
Machine-shop editorial: a sturdy serif and saturated Lemon for impact, a clean Paper ground and hairline rules for the restraint that keeps it readable. One set of brand colors, a light theme and a dark theme, and no outlines except the keyboard-focus indicator.
01 / Color
Type and rules in light theme, the page ground in dark theme, and the invariant feature-surface fill. Warm black, never pure #000.
Poster grounds, pass chips and primary buttons. Ink on top, never white. Type or thin rules only on Ink, never on light grounds.
White with a breath of green. The light-theme reading ground, dark-theme headline and UI text, and heading, UI and divider color on invariant Ink surfaces.
Failure and send-back only, one use per screen. Ink on top as a fill. The send-back text color in dark theme.
The send-back text shade in light theme, where Tangerine is too bright to read. Never a fill.
Panels, queue tracks and cards in dark theme. The alternate lockup ground on ink.
Theme roles
| Role | Light theme | Dark theme | Used for |
|---|---|---|---|
| --ground | Paper | Ink | Page background |
| --panel | #F1F4EB | Shop | Bands, cards, queue tracks, soft buttons |
| --text | Ink | Paper | Headlines, UI text, the header rule |
| --text-body | #41443B | #D2CDBD | Paragraphs |
| --text-caption | #666A5C | #A39D8A | Captions, mono labels |
| --hairline | #DEE3D5 | #3A3628 | Section and row dividers |
| --accent | Lemon zest | Lemon zest | Posters, pass chips, primary buttons (Ink on top) |
| --sendback-fill | Tangerine | Tangerine | Send-back chip (Ink on top) |
| --sendback-text | Rust | Tangerine | Send-back reasons in running text |
| --lockup-alt | Ink | Shop | Ground of the second lockup |
Contrast
| Pairing | Light theme | Dark theme |
|---|---|---|
| Body text on the page ground | Aa9.7:1AA | Aa11.8:1AA |
| Caption text on the page ground | Aa5.4:1AA | Aa6.9:1AA |
| Caption text on a panel | Aa5.0:1AA | Aa5.6:1AA |
| Ink on Lemon zest (posters, pass chips, primary button) | Aa11.5:1AA | Aa11.5:1AA |
| Lemon zest as type or a thin line on the ground | Aa1.6:1Blocks only | Aa11.5:1AA |
| Ink on Tangerine (send-back chip) | Aa6.0:1AA | Aa6.0:1AA |
| Send-back text on the page ground | Aa5.0:1AA | Aa6.0:1AA |
| Paper on Ink (ink button, ink lockup) | Aa18.2:1AA | Aa18.2:1AA |
Theme-invariant Ink feature surfaces: Paper heading and UI text is 18.2:1, #D2CDBD body text is 11.8:1, #A39D8A caption text is 6.9:1, and Lemon display emphasis is 11.5:1. These pairings remain unchanged in either outer theme.
WCAG 2 contrast ratios. Normal and small text, including chip text, needs at least 4.5:1. The 3:1 threshold is for large text and non-text UI boundaries. Blocks only means a filled area, never type or thin lines on that ground.
02 / Type
Nothing ships unchecked.
Sent back is not failed. It is the line doing its job.
Aa Ee Gg Kk Qq Rr Yy 24680 &?!
Writing code got cheap. Checking it did not. OpenFactory treats every change like a machined part: it moves down a line, gets measured against a tolerance, and either passes the gate or goes back with a reason attached. The type has to stay calm enough to carry that argument for a few hundred words at a time.
OF-2293 · image-resize · send-back · tol ±0.02 mm
218 passed · 3 sent back · 98.6% first pass
Scale
84px / 1.05 · Young Serif 400
OpenFactory
56px / 1.06 · Young Serif 400
Nothing ships unchecked.
36px / 1.1 · Young Serif 400
Sent back is not failed.
24px / 1.2 · Young Serif 400
Every build passes the gate.
18px / 1.5 · Instrument Sans 400
A clean paper ground and hairline rules for the restraint that keeps it readable.
16px / 1.55 · Instrument Sans 400
It moves down a line, gets measured against a tolerance, and either passes the gate or goes back.
14px / 1.45 · Instrument Sans 400
Failure and send-back only, one use per screen.
15px / 1.3 · Instrument Sans 700
Approve part
12px / 1.4 · IBM Plex Mono 400
Line 04 · Inspection
15px / 1.8 · IBM Plex Mono 400
OF-2293 · tol ±0.02 mm · 98.6%
03 / Logo
The logo is the solid square plus the word OpenFactory in Young Serif. The SVG files in the logo folder have the letters converted to outlines, so they work without the font installed.
- Solid and squareThe mark is a filled square. Never rotated, rounded, outlined or turned into a frame.
- One word, two capitalsAlways OpenFactory, with a capital O and F. Never all caps, never spaced into two words.
- One mark of clear spaceKeep at least the width of the square free on every side of a lockup.
- Ink on lemon, alwaysNothing but Ink sits on Lemon zest. No white type, no Tangerine, no photographs behind it.
04 / Components, light and dark
The same screen in both themes. Brand colors never change; only the ground, panels and text shades swap. The exception is an invariant brand-dark feature surface: its Ink fill and on-Ink roles stay fixed regardless of the outer theme.
Nothing ships unchecked.
Every build passes the gate or goes back with a reason.
- OF-2291auth-servicePass
- OF-2293image-resizeSend-back
- OF-2294search-indexIn check
Sent back is not failed.
A send-back carries the measurement that missed and the step that caught it, so the fix starts from a fact.
Send-back reason: tolerance out by 0.02 mm
Nothing ships unchecked.
Every build passes the gate or goes back with a reason.
- OF-2291auth-servicePass
- OF-2293image-resizeSend-back
- OF-2294search-indexIn check
Sent back is not failed.
A send-back carries the measurement that missed and the step that caught it, so the fix starts from a fact.
Send-back reason: tolerance out by 0.02 mm
Throughput is.
The question is not how much code your agents generated.
| Component | Build |
|---|---|
| Primary button | Lemon fill, Ink text, Instrument Sans 700 at 15px, padding 12 by 18, square corners, no outline. |
| Ink button | Ink fill, Paper text. Use on Lemon posters, where a Lemon button would vanish. |
| Soft button | Panel fill, theme text color. The secondary action next to a primary. |
| Status chip | IBM Plex Mono 11px caps, tracking 0.1em, padding 4 by 8. Pass is Lemon, send-back is Tangerine, in check is Panel. |
| Queue | Panel fill with rows in the ground color, 6px apart. No dividers. |
| Poster | Full Lemon fill, Young Serif headline, one Ink button. No outline. |
| Ink feature surface | Ink fill in every theme; Paper heading and UI text with a 2px divider; #D2CDBD body; #A39D8A caption; Lemon display emphasis. Never inherit page-theme text tokens. |
| Keyboard focus | 2px outline in the theme text color, 2px offset. The only outline in the system, and only while focused. |
05 / Layout rules
- Fills, not outlinesSeparate things with a change of fill: Paper to Panel in light, Ink to Shop in dark. No boxes drawn around anything.
- Lines only divideA 1px hairline may separate sections and table rows. A 2px emphasis divider may close the page header or divide an Ink feature surface. Lines never enclose.
- Square cornersRadius is zero everywhere, to match the mark.
- One Tangerine per screenIt means something went back. If two things are orange, neither reads as urgent.
- Yellow is an areaLemon zest is too pale for type or lines on light grounds. Use it as a block there; Lemon text and thin rules are permitted only on Ink.
- Caps are for labelsOnly the small mono labels are set in capitals. Headlines and the wordmark stay in upper and lower case.
Spacing
06 / Tokens
These are the reference tokens used by this page and the OpenFactory site. Dark theme follows the system setting, and setting data-theme to light or dark on the root or a container overrides it.
/* OpenFactory brand system V2 · tokens */
:root {
/* brand colors: the same in both themes */
--ink: #14120D;
--lemon: #F5C518; /* Lemon zest. Ink on top as a fill; type/thin rules on Ink only, never on light grounds */
--paper: #FAFDF7;
--tangerine: #FF5A1F; /* send-back fill, one use per screen, ink on top */
--rust: #C2410C; /* send-back text in light theme */
--shop: #2A2519;
/* fixed roles */
--accent: var(--lemon);
--on-accent: var(--ink);
--sendback-fill: var(--tangerine);
--on-sendback: var(--ink);
--on-ink: var(--paper);
--on-ink-body: #D2CDBD;
--on-ink-caption: #A39D8A;
--on-ink-rule: var(--paper);
/* type */
--font-display: "Young Serif", Georgia, "Times New Roman", serif;
--font-body: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
--font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
--size-display-xl: 5.25rem; /* 84px, line-height 1.05, tracking -0.015em */
--size-display-l: 3.5rem; /* 56px, line-height 1.06, tracking -0.015em */
--size-display-m: 2.25rem; /* 36px, line-height 1.1, tracking -0.015em */
--size-display-s: 1.5rem; /* 24px, line-height 1.2, tracking -0.01em */
--size-lede: 1.125rem; /* 18px, line-height 1.5, tracking 0 */
--size-body: 1rem; /* 16px, line-height 1.55, tracking 0 */
--size-caption: 0.875rem; /* 14px, line-height 1.45, tracking 0 */
--size-button: 0.9375rem; /* 15px, line-height 1.3, tracking 0.01em */
--size-label: 0.75rem; /* 12px, line-height 1.4, tracking 0.12em */
--size-data: 0.9375rem; /* 15px, line-height 1.8, tracking 0 */
/* layout */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 24px;
--space-6: 32px;
--space-7: 48px;
--space-8: 64px;
--space-9: 96px;
--radius: 0;
--rule: 1px; /* hairlines divide sections and rows; nothing gets a box outline */
}
/* light theme roles (default) */
:root, [data-theme="light"] {
--ground: var(--paper);
--panel: #F1F4EB;
--text: var(--ink);
--text-body: #41443B;
--text-caption: #666A5C;
--hairline: #DEE3D5;
--sendback-text: var(--rust);
--lockup-alt: var(--ink);
}
/* dark theme: follows the system setting... */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--ground: var(--ink);
--panel: var(--shop);
--text: var(--paper);
--text-body: #D2CDBD;
--text-caption: #A39D8A;
--hairline: #3A3628;
--sendback-text: var(--tangerine);
--lockup-alt: var(--shop);
}
}
/* ...and data-theme="dark" on the root, or on any container, wins either way */
[data-theme="dark"] {
--ground: var(--ink);
--panel: var(--shop);
--text: var(--paper);
--text-body: #D2CDBD;
--text-caption: #A39D8A;
--hairline: #3A3628;
--sendback-text: var(--tangerine);
--lockup-alt: var(--shop);
}