What does not resolve, does not exist.
A design system for high information density contexts. Every visual decision justified by function.
Logical Brutalism is a design system for high information density contexts, built on the premise that technical truth is a legitimate form of aesthetics in software.
Just as brutalist architecture exposes concrete and refuses decorative coating over real structure, Logical Brutalism exposes system logic: no visual layers that contradict function, no ornament that carries no information, no element that fails to justify its presence with utility.
This is not the absence of design. It is design with maximum justification cost. Every visual decision must answer a functional question before it exists.
"What does not resolve, does not exist."
In minimalism, you remove until something looks elegant. In Logical Brutalism, you remove until only what resolves remains. The criterion is functional, not aesthetic.
| Approach | Criterion | Result |
|---|---|---|
| Minimalism | Remove until it looks elegant | Aesthetics by subtraction |
| Web Brutalism | Remove until it looks raw | Ugliness as statement |
| Logical Brutalism | Remove until only function remains | Structural truth |
Logical Brutalism is not a universal system. It is optimised for contexts where maximum information density in minimum screen space is a requirement: IDEs, enterprise dashboards, monitoring tools, internal systems, technical documentation. Where information is the product, Logical Brutalism is the system.
Three axioms underpin all system decisions. They are premises derived from how humans process information, not from aesthetic preference.
A visual element exists to convey information or guide action. If it does neither, it is cognitive noise. Norman demonstrated that the brain processes affordances before aesthetics: the user asks what does this do before asking is it beautiful. Beauty is a consequence of well-executed function, never an independent objective.
ref: Norman, The Design of Everyday Things: affordance precedes signifier.
The system does not hide how it works. The logic of hierarchy, state, and behaviour must be immediately readable on the visual surface, with no additional instruction. Kahneman showed that System 1 processes visual patterns before any conscious reading. If the structure is not obvious within 100ms, the design has failed.
ref: Kahneman, Thinking Fast and Slow: System 1 processes pattern before content.
Fewer options produce more consistency and lower cognitive load. A palette of 6 tokens with strict usage rules is more powerful than 20 colours without criterion. Restriction does not limit design: it defines the system and reduces decision cost for those who implement it.
ref: Alexander, Notes on the Synthesis of Form: form is the resolution of conflicting forces.
The palette is an attention hierarchy system. Each token maps to a specific urgency level and function. Using a token outside its role breaks system logic.
| Token | Hex | Role | Rule |
|---|---|---|---|
--color-void |
#0A0A0A | Primary Background | Foundation of all layouts. Represents the absence of visual noise. Never use as text colour or interactive element. |
--color-amber |
#FFB000 | Action Accent | Sole action accent. Reserved for active states, primary CTAs and headers. Historical reference: P3 phosphor terminals, 1970s. Contrast 10.81:1 over void, passes WCAG AAA. Rule: one amber element per screen. |
--color-surface |
#1E1E1E | Component Boundary | Context separation, card borders, secondary backgrounds. Never for text. Never for interactive elements. |
--color-text |
#888888 | Default Text | Default colour for continuous reading. Contrast 5.74:1 over void, passes WCAG AA. Do not use white for body text: excessive contrast causes visual fatigue. |
--color-white |
#F0F0F0 | Critical Emphasis | Headers, critical data, maximum emphasis. Contrast 18.1:1 over void, passes WCAG AAA. Use sparingly. |
--color-error |
#FF4444 | Error State | Exclusive use: errors, critical alerts, invalid data. Never decorative. Rationale: red activates Kahneman’s System 1 for immediate reading without deliberate effort. Contrast 5.6:1 over void, passes WCAG AA. |
Canonical parametric inversion for high ambient luminosity. The same mathematical hierarchy inverts signal urgency, ensuring density without glare.
| Token | Name | Hex | Rationale |
|---|---|---|---|
--color-void |
Industrial Concrete | #E3E3E3 | Primary background — minimises eye strain in sunlight. |
--color-amber |
Oxidized Amber | #B35900 | Action accent — calibrated for AAA contrast. |
--color-surface |
Drafting Board | #CCCCCC | Component boundary — solid structural demarcation. |
--color-text |
Graphite HB | #4D4D4D | Default text — immersive reading. |
--color-white |
Absolute Void | #0A0A0A | Critical emphasis — inverts the urgency pole for dense data. |
--color-error |
Emergency Stop | #BE123C | Error state — urgency with AAA calibration. |
| Situation | Token | Rationale |
|---|---|---|
| Primary action available | --color-amber |
System ready to execute |
| Continuous data reading | --color-text |
Neutral information, no urgency |
| Title or critical data | --color-white |
Maximum attention without immediate action |
| Context separation | --color-surface |
Visual structure, not information |
| Error or invalid state | --color-error |
Activates System 1 for immediate reading |
:root {
--color-void: #0A0A0A;
--color-amber: #FFB000; /* P3 phosphor, 1970s */
--color-surface: #1E1E1E;
--color-text: #888888;
--color-white: #F0F0F0;
--color-error: #FF4444;
}
[data-theme="infinity-white"] {
--color-void: #E3E3E3;
--color-amber: #B35900;
--color-surface: #CCCCCC;
--color-text: #4D4D4D;
--color-white: #0A0A0A;
--color-error: #BE123C;
}
Two families. Distinct functional roles. Scale in rem based on 16px to respect user browser font size preferences.
Designed for reading on high-density screens. Metrics optimised for legibility at small sizes. Use for all content the user needs to read, not scan.
Designed for code parsing: monospaced spacing, logical ligatures, maximum clarity in short strings. Use where content is raw system data: labels, status, identifiers, values, timestamps, code.
| Token | Family | rem | px | Use |
|---|---|---|---|---|
--text-display |
JetBrains Mono | 2.5rem | 40px | Page titles |
--text-title |
JetBrains Mono | 1.375rem | 22px | Section titles |
--text-body |
Inter | 1rem | 16px | Body — WCAG AA minimum |
--text-small |
Inter | 0.875rem | 14px | Notes, captions, metadata |
--text-label |
JetBrains Mono | 0.75rem | 12px | System labels — absolute minimum |
--text-code |
JetBrains Mono | 0.875rem | 14px | Code blocks, values |
| Token | Value | Use |
|---|---|---|
--space-1 |
0.25rem | Minimum separation, elements of the same group |
--space-2 |
0.5rem | Internal component padding |
--space-3 |
1rem | Separation between related elements |
--space-4 |
1.5rem | Separation between sections of same context |
--space-5 |
2rem | Separation between distinct contexts |
--space-6 |
3rem | Maximum separation, page sections |
--letter-spacing-code |
0.08em | JetBrains Mono in labels and buttons |
--letter-spacing-struct |
normal | Inter in body text |
:root {
--font-struct: 'Inter', sans-serif;
--font-code: 'JetBrains Mono', monospace;
--radius: 0px;
--line-height: 1.6;
--text-display: 2.5rem;
--text-title: 1.375rem;
--text-body: 1rem;
--text-small: 0.875rem;
--text-label: 0.75rem;
--text-code: 0.875rem;
--space-1: 0.25rem; --space-2: 0.5rem;
--space-3: 1rem; --space-4: 1.5rem;
--space-5: 2rem; --space-6: 3rem;
--letter-spacing-code: 0.08em;
--letter-spacing-struct: normal;
}
html { font-size: 16px; }
Generative principles dictate what to do and when. Any new decision can be evaluated against them without consulting the author.
Before choosing a colour, identify the element’s functional state. Colour is a consequence of state, never an independent choice.
When: New visual element.
How: 1. Define the state: active, inactive, neutral, error, critical. 2. Consult the attention hierarchy table. 3. Apply the token.
90-degree edges declare that the system does not soften reality. Permitted exception: circular progress indicators, where the form carries distinct functional meaning.
When: Every container or bordered element.
How: border-radius: 0 via --radius. Exceptions require documented functional rationale.
JetBrains Mono is the system’s voice: auto-generated data, identifiers, timestamps, status, code. Inter is the content’s voice: text written to be read. The distinction is semantic, not aesthetic.
When: Every typographic element.
How: System-generated data: JetBrains Mono. User-facing content: Inter.
The amber accent is the sole element competing with the dark background for maximum attention. If multiple elements are amber simultaneously, the signal loses strength and hierarchy collapses.
When: When using --color-amber.
How: Check if another amber element is active on the same screen. If so, one of them has the wrong role.
Spacing communicates structure: nearby elements belong to the same context, distant elements belong to distinct contexts. Use spacing tokens to communicate logical relationship, not to fill empty space.
When: Positioning any two elements.
How: Same context: --space-1 to --space-3. Distinct contexts: --space-4 to --space-6.
Every user action requires immediate visual response via state change. There are no smooth transitions: only discrete states. Dishonest feedback — such as indicating success before server confirmation — is a system integrity failure.
When: Every interactive element.
How: Define all states: default, hover, active, focus, disabled, loading, error. No state without visual response.
Icons introduce external dependency and require aria-label for accessibility. ASCII is pure text: zero overhead, universal rendering. Use icons only when the symbol is universally recognisable and ASCII cannot represent it with equivalent clarity.
When: When considering adding an icon.
How: Try ASCII first. If using an icon, always include functional aria-label.
The button is where the user executes. Absence of transition is not negligence: it declares that the system executes without hesitation. Feedback via state change, not via animation.
| State | BG | Text | Border | Cursor |
|---|---|---|---|---|
| Primary | #FFB000 | #0A0A0A | none | pointer |
| Hover | #CC8E00 | #0A0A0A | none | pointer |
| Active | #996B00 | #0A0A0A | none | pointer |
| Focus | #FFB000 | #0A0A0A | 2px offset amber | pointer |
| Secondary | transparent | #FFB000 | 1px #FFB000 | pointer |
| Disabled | transparent | #444444 | 1px #444444 | not-allowed |
| Loading | #1E1E1E | #888888 | none | wait |
.btn {
font-family: var(--font-code);
font-size: var(--text-label);
letter-spacing: var(--letter-spacing-code);
text-transform: uppercase;
border-radius: var(--radius);
padding: var(--space-2) var(--space-4);
min-height: 44px;
min-width: 44px;
cursor: pointer;
transition: none;
}
Error is the system's moment of maximum honesty. Four mandatory layers derived from Norman: what failed, why it failed, where it failed, what to do.
| Layer | Content | Font | Colour |
|---|---|---|---|
| Code | ERR_404 / HTTP_500 | JetBrains Mono | --color-error |
| Title | What failed | JetBrains Mono | --color-white |
| Description | Why it failed | Inter | --color-text |
| Action | What to do now | JetBrains Mono | --color-amber |
.error-container {
border-left: 3px solid var(--color-error);
background: var(--color-surface);
padding: var(--space-3) var(--space-4);
border-radius: var(--radius);
}
/* ARIA: role=alert ensures automatic reading by screen readers */
The card declares that a data block belongs to the same logical context. The coloured left border is the sole state indicator: a single, unambiguous signal, following Norman.
.card {
background: var(--color-surface);
border: 1px solid #2A2A2A;
border-radius: var(--radius);
padding: var(--space-3) var(--space-4);
}
.card.active { border-left: 3px solid var(--color-amber); }
.card.error { border-left: 3px solid var(--color-error); }
.card.inactive { opacity: 0.5; pointer-events: none; }
Loading is the only context where motion is permitted. Rationale: system activity feedback is functional, not decorative. The ASCII loader preserves aesthetics without introducing library dependency.
/* ASCII Loader — no external dependency */
.loader-ascii::after {
content: attr(data-frame); /* JS alternates: | / - \ */
font-family: var(--font-code);
font-size: var(--text-label);
color: var(--color-amber);
animation: none; /* swapped via JS, not CSS */
}
/* Linear loader — justified border-radius exception */
.loader-bar {
height: 2px;
background: var(--color-surface);
position: relative;
overflow: hidden;
}
.loader-bar::after {
content: '';
position: absolute;
height: 100%;
width: 40%;
background: var(--color-amber);
animation: lb-slide 1.2s linear infinite;
}
@keyframes lb-slide { from { left: -40%; } to { left: 100%; } }
When using ASCII as an action, the element must have explicit role and aria-label.
| Symbol | Meaning | Recommended aria-label | role |
|---|---|---|---|
[+] |
Add | Add item | button |
[x] |
Close/Remove | Close | button |
[>] |
Expand/Advance | Expand section | button |
[<] |
Go back | Go back | button |
[!] |
Alert | Attention: {description} | alert |
[?] |
Help | Help: {topic} | button |
[*] |
Favourite/Highlight | Mark as favourite | button |
[...] |
Loading/Wait | Loading | status |
Accessibility is not a concession. It is consistency with Axiom I: function precedes form. An interface unreadable by some users has failed in function before form.
| Pair | Ratio | AA | AAA | Use |
|---|---|---|---|---|
| #888888 / #0A0A0A | 5.74:1 | PASS | FAIL | Body text |
| #F0F0F0 / #0A0A0A | 18.1:1 | PASS | PASS | Headers and emphasis |
| #FFB000 / #0A0A0A | 10.81:1 | PASS | PASS | Amber accent |
| #0A0A0A / #FFB000 | 11.46:1 | PASS | PASS | Text on primary button |
| #FF4444 / #0A0A0A | 5.6:1 | PASS | FAIL | Error labels — never body |
| #444444 / #0A0A0A | 2.5:1 | FAIL | FAIL | Decorative only w/ aria-hidden |
Remove all colours from the interface. The information hierarchy must still be readable in grayscale. If not, the layout depends on colour to communicate structure: this is an architecture failure.
Any implementer can audit an interface against this checklist without consulting the author. Any 'no' is a system violation.
Every real system contains internal contradictions. Documenting these tensions is not weakness — it is structural honesty. Implementers need to know where the system may need adaptation.
0.75rem (12px) for system labels is a compromise between information density and legibility. WCAG does not define an absolute minimum, but 16px is the established practice for body. 12px may be inaccessible for users with low vision even with high contrast. User testing in real contexts will determine if this threshold is acceptable.
note: v1.2: test with real users and revise if necessary.
Absence of transition assumes users prefer instant feedback. This may be false for public interfaces: abrupt state change may be interpreted as system failure, not execution. The principle is correct for internal tools; may need revision in interfaces exposed to non-technical users.
note: v1.2: test instant change perception with general public.
The choice of 6 colour tokens is not derived from mathematical principle. It could be 5 (remove --color-white and use --color-text for everything) or 7 (add token for charts). 6 is the result of balancing attention hierarchy with minimum restriction. Extensions for specific contexts, such as dashboards with charts, may require additional tokens without violating axioms.
note: v1.2: define palette extension protocol.
#FFB000 is historically justified by P3 phosphor terminals, but it remains a choice within the 'single saturated accent' restriction. Any saturated colour with sufficient contrast over #0A0A0A would work. Amber is our documented decision, not an absolute system truth.
note: Implementers may substitute with another saturated colour as long as they maintain minimum WCAG AAA contrast over --color-void.
Logical Brutalism does not exist in a vacuum. Here is where it positions itself relative to existing systems and why someone would choose it over another.
| System | Relation | Operational Difference |
|---|---|---|
| Tailwind CSS | Similar logic | Utility-first shares the operational restriction, but without defined chromatic attention hierarchy. Each project reinvents the palette. |
| Radix UI | Close premise | Accessible primitives share 'exposed function', but without explicit chromatic system. |
| Material Design | Distinct objective | Expanded palette for corporate branding needs. Incompatible with 6-token restriction, but correct for its niche. |
| Carbon (IBM) | Distinct objective | Similar high information density, but palette and components aimed at enterprise scale. Higher weight and complexity. |
| Base UI | Critical difference | No styles proposes absence of decision. Logical Brutalism proposes maximum restriction decision. They are philosophical opposites. |
| Criterion | Logical Brutalism | Other System |
|---|---|---|
| Information density | High | Any |
| Target audience | Technical / internal | General consumer |
| Emotional branding | Not suitable | Material, Carbon |
| Bundle CSS | Minimal (< 5KB) | Variable |
| Learning curve | Low (6 tokens) | Higher |
| Accessibility out-of-box | WCAG AA/AAA documented | Variable |
A system that does not admit its limitations is dogma, not architecture.
Interfaces for the general public, children, or the elderly require visual affordances that the system deliberately avoids. Use a system with greater colour, rounding, and familiar icon support.
Brand materials need emotional and chromatic flexibility that the system does not offer by design.
Charts requiring extended palettes to differentiate series are incompatible with the 6 tokens. Palette extension for this context is outside the scope of v1.1.
Dogmatism is not part of the philosophy. If the user, the business, or the context requires another approach, use another system.
Le Corbusier :: Vers une Architecture :: 1923
Structure as aesthetics, material honesty over decoration. Grounds Axiom II: exposed structure.
Dieter Rams :: Ten Principles of Good Design :: 1970
Good design is as little design as possible. Grounds Axiom I: function precedes form.
Christopher Alexander :: Notes on the Synthesis of Form :: 1964
Form is the resolution of conflicting forces. Grounds Axiom III: restriction as tool.
Donald Norman :: The Design of Everyday Things :: 1988
Affordance, feedback, and conceptual model as functional foundations. Grounds P-06 and P-04.
Daniel Kahneman :: Thinking, Fast and Slow :: 2011
System 1 and System 2. Design that forces System 2 for routine tasks unnecessarily increases cognitive load. Grounds high contrast and single action signal.
Steve Krug :: Don't Make Me Think :: 2000
The user scans before reading. Interfaces that require deliberation for simple tasks fail in readability. Grounds visual hierarchy and exposed structure.
Bret Victor :: Inventing on Principle :: 2012
Logic as a tool for immediate visual thinking. The interface must make system logic perceptible without effort.
I build because I have something to deliver.
I refuse gradients because visual transition implies state transition,
and states are discrete.
I refuse rounded borders because the right angle communicates
hierarchical precision without ambiguity.
I use monospace for system data because parsing requires
alignment, not long-duration readability.
I use amber because a single, unambiguous signal
is worth more than ten competing signals.
I am not trying to impress.
I am trying to reduce cognitive load.
The interface is logic made perceptible.
The structure is exposed.
The plan is solid.
The rest is noise.
The system follows semver: MAJOR.MINOR.PATCH. MAJOR: changes that violate axioms or break compatibility. MINOR: new components, tokens, or principles without violating axioms. PATCH: bug fixes, text clarity, CSS adjustments.
Extensions are additions to the system that do not violate the axioms. Every extension must: 1. Name the axiom that grounds the addition. 2. Define when to use and when not to use. 3. Include its own evaluation checklist. Extensions that violate an axiom constitute a derived system, not an extension.