OpenFactory
Machine-shop editorial: a sturdy serif and a pale 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 anywhere.
01 / Color
Type and rules in light theme. The page ground in dark theme. Warm black, never pure #000.
Poster grounds, pass chips, primary buttons. Ink on top, never white. A filled area only, never type or a thin line on a light ground.
White with a breath of green. The reading ground in light theme; headline and UI type in dark theme.
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) | Aa16.6:1AA | Aa16.6:1AA |
| Lemon zest as type or a thin line on the ground | Aa1.1:1Blocks only | Aa16.6: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 |
WCAG 2 contrast ratios. AA is fine for body text (4.5:1 or more). Large only is for headlines and chips (3:1 or more). 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. Blocks are separated by fills, so there are no borders to restyle between themes.
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
| 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. |
| 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.
- Hairlines only divideA 1px hairline may separate sections and table rows, and one 2px rule closes the page header. 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 Paper. Use it as a block in light theme; in dark theme it can also be type.
- 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
This is tokens.css from the package. The same values are in tokens.json in the W3C design tokens format. Dark theme follows the system setting, and setting data-theme on the root element to light or dark overrides it.
/* OpenFactory brand system V2 · tokens */
:root {
/* brand colors: the same in both themes */
--ink: #14120D;
--lemon: #F6F87E; /* Lemon zest. Ink on top, filled areas only 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);
/* 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);
}