v1.0 · The NeuronLens design system

One token model, two surfaces.

The marketing site and the product studio read the same variables. What changes between them is density and content — never colour, type, or radius. Direct, confident, never decorative.

Status
Active
Version
1.0
Surfaces
Marketing · Product
Type
Space Grotesk · Inter · JetBrains Mono
Tokens
CSS custom properties, Tailwind v4
Web
Next.js App Router

01 · Foundations

Editorial gravity. Industrial precision.

Four rules govern everything below. They are not a style guide layered on top of the product — they are the same four rules the product itself is built under, which is why the marketing site reads like the console.

Do

Read the model, not the mood

NeuronLens is an inspection surface. The brand shows structure and refuses ornament: hairline rules instead of cards of shadow, a real type ramp instead of three sizes of bold, one colour reserved for one meaning. If a design choice cannot be explained in one sentence, it is decoration and it does not ship.

Do

One token set, two surfaces

The marketing site and the product studio read the same variables. What changes between them is density and content, never colour, type, or radius. A token changed on one surface is changed everywhere, in the same release.

Do

Dark is a band, not a theme

The site is light-only. Dark arrives as a full-bleed product band — deep green or dark navy — that a reader enters and leaves. It is never a toggle, never a mixed canvas, and never the page background behind body copy.

Do

Evidence over assertion

Every claim the brand makes is one the product can show. There are no invented customers, no unsourced benchmark numbers, no superlatives. The marketing voice is the report voice: this happened, here is the trace, here is the read.

What the system refuses

The negative list

Drop shadows and elevation stacks. Depth comes from surface value.

Gradient text, gradient fills, mesh backgrounds.

Two fonts for one idea. Every typeface has a single job.

Coral as decoration. It is the failure colour and nothing else.

A colour pick to mark importance. Importance is size and weight.

Emoji as interface. Icons come from one library.

Carousels, tabs, or a modal where a page will do.

Full-width dark bands behind running body copy.

03 · Typography

Three families, one job each.

Space Grotesk states, Inter explains, JetBrains Mono measures. Hierarchy is carried by size and space — the display face never goes past 400, because bold would be a second signal fighting the first.

The ramp

Nine steps, all of them shipped

Evidence first

Hero · clamp 40 → 96px · 1.02

Homepage statement only

Evidence first

Product · clamp 36 → 72px · 1.05

Section openers, hero pane

Evidence first

Section · clamp 34 → 60px · 1.07

Top-level band headings

Evidence first

Heading · clamp 30 → 48px · 1.15

Sub-sections, feature titles

Evidence first

Card · clamp 24 → 32px · 1.20

Card and column titles

Evidence first

Feature · clamp 20 → 24px · 1.30

Titled list rows

Evidence first

Lead · 18px · 1.45

Standing first paragraph

Evidence first

Body · 16px · 1.60

Everything else

Evidence first

Mono label · 14px · 1.40

Labels, keys, code, data

Pairings

Set, not described

Display + body

Every catch ships with evidence

A design that reads as a tool for people who have to be right. The heading states the claim; the paragraph carries the argument; the reader decides.

Mono as data

POST /v1/events/PreToolUse

0.91

JetBrains Mono is reserved for things a machine wrote: endpoints, keys, versions, scores, timestamps. Never for emphasis.

Rules

Do / Don’t

Do

Display is always 400.

Space Grotesk gets its authority from tracking at −0.02em and from the size jump. A 600-weight heading next to a 400 one reads as an inconsistency, not a hierarchy.

Don’t

Do not set body copy in the display face.

Space Grotesk has open apertures and a wide lowercase. At 16px it loses legibility and looks like a different product.

Do

The measure is one value: 38rem.

Long-form prose holds a 75–80 character line on a 608px column — one --measure, set once in globals.css and overridden by no page. Justified, so both edges carry weight, and hyphenated, so the justification cannot open rivers.

Don’t

Do not uppercase a sentence.

Uppercase is the mono label's job. Applied to Inter it reads as a marketing deck.

04 · Colour

Coral means caught. Nothing else.

The palette is small enough to hold in your head and dull enough that the one saturated colour in it cannot be mistaken for decoration. Every value below is a variable in globals.css — copy any of them.

Core

The canvas and its greys

Canvas

--background

The page. Never tinted.

Ink

--foreground / --ink

Headings and body on light.

Body muted

--body-muted

Running prose. 7.0:1 on canvas.

Slate text

--slate-text

Meta and captions. 4.6:1 — the floor.

Hairline

--hairline

Rules, borders, table lines.

Border light

--border-light

Dividers inside dense tables.

Soft stone

--soft-stone

Quiet fills: chips, inline code, wells.

Card border

--card-border

Fills and neutral hover states.

Bands

Dark arrives as a section

Near black

--near-black

Footer, console blocks, primary CTA.

Announcement black

--ann-black

The strip above the nav. Pure black, once.

Deep green

--deep-green

A product band. Integrity Lens.

Dark navy

--dark-navy

A product band. Agent Lens.

Signal

The only saturated colours

Coral

--coral

One meaning: the model was caught. Nowhere else.

Coral soft

--coral-soft

Coral on a light ground, where full coral fails.

Action blue

--action-blue

Links. On light only.

Action blue on dark

--action-blue-on-dark

Links on near-black. 8.5:1 where #1863dc is 2.4:1.

Focus blue

--focus-blue

Keyboard focus ring, nothing else.

Destructive

--destructive

A blocked action. Not a warning colour.

In the palette

Live

Start the scanRead the reportHeld for reviewDeception · 0.91

Four buttons, four meanings. Three of them are neutral; the fourth is the only thing on the page that is allowed to shout.

Rules

Do / Don’t

Do

Coral is a verdict, not an accent.

If a coral element is not describing something the system caught, it is wrong. Coral on a button, a link, or a heading has no meaning to attach to.

Don’t

Do not use coral on white at text sizes.

It is 2.9:1 against the canvas. It is a fill colour, or a text colour on a dark ground, and nothing in between.

Do

Pick contrast, not hue, for hierarchy.

Body steps down through ink → body-muted → slate-text. Hue stays constant, so a quieter line is never a different colour.

Don’t

Do not colour the whole band.

A dark band with a coloured tint reads as a gradient. Dark bands are one of four exact values: near-black, deep green, dark navy, black.

05 · Spacing & layout

An eight-step ladder, and one container.

Spacing is not a token set here — it is Tailwind's own scale used without invention. Two values outside the ladder appear often enough to be honest about them: the 1px hairline and the 2px frame.

TokenUsepx
xxsThe dot-to-dot gap on a trace rail.2px
xsBetween an icon and the label it labels.6px
smInside a chip. Between stacked mono lines.8px
mdChip padding-y, gap in a tight button row.12px
lgThe default. Card padding, list gaps, mt between blocks.16px
xlBetween a heading and its first block of body.24px
xxlBetween two sibling blocks inside one section.32px
sectionpy-20 to py-28 on a full-bleed band.80–112px

The ladder

Drawn to a 2× scale, capped

2px · xxs

6px · xs

8px · sm

12px · md

16px · lg

24px · xl

32px · xxl

80–112px · section

Off-ladder values

Both are structural

1px · hairline

Rules, table dividers, and the header's scroll progress line.

2px · frame

A frame thick enough to read as a card edge, on a ticket.

Containers

Two, and only two

max-w-6xl

Marketing bands, footer, this page

72rem · 1152px

max-w-5xl

Long-form reading: system, about

64rem · 1024px

Gutters

px-5 on mobile, px-8 from sm

20 / 32px

A band is one of three shapes: a two-column grid, a single reading column, or a full-bleed surface. It is never a card grid of equal thirds, because equal thirds mean nothing about how the product works.

06 · Border radius

Two radii carry the whole site.

8px for anything a person interacts with, 22px for anything that is an image. Everything else is either a 4px detail or a pill. A large radius on a control, or a small one on a photograph, both read as a mistake.

The ladder

Live

4px

Inline code, tags inside a card

6px

Swatches, avatar chips, small wells

8px

Product cards, the ticket, console blocks

22px

Media and screenshot panels

9999px

Status pills, avatar, dot

Why 22px and 8px

The distinction is the rule

8px · a thing

A card you can click

Tight enough to read as a control surface.

22px · an image

Rules

Do / Don’t

Do

A 22px panel holds an image; an 8px panel holds a decision.

The radius is the fastest signal a reader has for what a surface is before they read a word on it.

Don’t

Do not nest radii arithmetically.

A 22px card with an 8px card inside it needs no inset padding, and adding one produces a 14px ring that appears in no token.

07 · Iconography

One library, stroke only, no fills.

Every icon on the site is lucide-react, pinned to 0.469.0. They inherit currentColor, they are always stroke, and they are never mixed with a second family — the aperture is the only drawn mark.

The set in use

lucide-react 0.469.0

AlertCircle

ArrowRight

ArrowUpRight

Check

CheckCircle2

ChevronDown

ChevronRight

Copy

Cpu

Key

Loader2

Mail

Menu

Plus

RefreshCw

Rocket

Search

Trash2

User

X

Twenty of the icons the site actually renders. The library carries thousands; the site does not. An icon is added when a control needs it, not to fill a grid.

Sizes

Four steps

12px

Inline with mono. Never the only label.

16px

Default. Buttons, nav, list rows.

20px

Feature rows and card headers.

24px

Empty states and large controls.

Rules

Do / Don’t

Do

An icon that is not paired with text is decorative.

Every icon-only button on this site carries an aria-label. A close X with no name is a mystery to a screen reader.

Don’t

Do not fill an icon to mean “active”.

Selection state is border, colour, or weight. A filled variant of a stroke icon is a second icon set hiding inside one.

08 · Imagery & motifs

A dark band, a sweep, one flag.

There are no stock photographs and no 3D renders. The recurring image of the brand is a console: a dark panel, a scan crossing it, and exactly one element in coral. The motifs below are the whole vocabulary.

The three motifs

Band · sweep · flag

The band

Full-bleed dark green or navy. A reader enters it for a lens and leaves it. Never a background for running copy.

The sweep

A 1px hairline crossing a panel, meaning “reading it now”. It is the only line in the system that moves.

Held for review

The flag

One coral element per screen. It is the caught behaviour, and a screen with two flags is a screen where nothing is.

The scanned panel

See it running

INTEGRITY LENS

On the homepage

ACTIVATION

residual_stream_7

CLUSTER

deceptive_context

Rules

Do / Don’t

Do

Every image earns its place by being evidence.

A screenshot of the product, a scan output, or nothing. Stock photography of screens is the fastest way to look like a company that has not shipped.

Don’t

Do not add a second coral element.

One flag per screen. If two things are wrong, show the worse one.

09 · Tone of voice

Write it like a report, not a brochure.

The brand talks the way the product's output looks: specific, attributable, willing to say what was caught. Confidence comes from the trace being right there, so the copy never has to insist.

Four habits

Lead with the finding

The catch, then the mechanism. Not the ambition, then the catch.

Name the tool

`place_equity_order`, `/v1/pre-action`, SAE cluster ids. Specificity is trust.

State the limit

What the system does not see is part of every claim.

No superlatives

“Detects,” never “detects everything.” “Faster,” never “blazing.”

Rewrites

The same claim, done twice

Before

Our cutting-edge platform empowers developers to unlock unprecedented insights into AI model behavior.

After

Read a model's internals before you trust its output. NeuronLens extracts activations, decomposes them into sparse features, and flags the clusters that matter.

Before

NeuronLens catches virtually all deceptive behaviour in production.

After

Every tool call is checked before it leaves. When the reason and the action don't match, the call is held for a human.

Before

Ship faster with our seamless, enterprise-grade integrations!

After

Works with the runtime you already run. Claude, Cursor, OpenCode, Codex — same hooks, same trace.

Punctuation and casing

Set, not described

We write

  • Sentence case, always. No Title Case On The Homepage.
  • Periods. The full stop is not optional.
  • Coral spans a phrase, not a word, when it marks a quoted claim.
  • Commas before “and” only where the clauses are equal.

We do not write

  • Exclamation marks. Ever.
  • “Seamless,” “robust,” “powerful,” “game-changing.”
  • Questions as headings. “Ready to see what your model knows?”
  • Numbers we have not measured, or a customer who has not agreed.

10 · Motion

One curve, four arrivals, and a hard stop.

Every transition on the site runs on cubic-bezier(0.16, 1, 0.3, 1) over 0.7s. Motion exists to sequence reading — it never moves a thing to announce itself, and it is fully removed under prefers-reduced-motion.

Tokens

Easing

--ease-expo

Duration

--reveal-duration

Stagger steptrace and thread rows

--reveal-step

Default stepanything else

--reveal-step

NameWhat movesDuration
riseCopy lifts 24px and fades in0.7s
ruleA hairline draws left-to-right, content rides it 16px up0.9s rule / 0.7s content
settleA band resolves from blur(6px) and scale(0.985)0.7s
wipeA full-bleed band reveals from its top edge via clip-path0.9s

Loops

Only three, all on a 6s cycle

Sweep

scan-line. Linear, 6s, infinite. A hairline crosses the panel top to bottom.

Breath

trace-breathe. 2.4s ease-in-out. Marks a call still waiting on a human.

Turn

spin 6s linear. The mark rotating once while the gate reads.

Rules

Do / Don’t

Do

Motion answers a question of order.

Does this happen before that? Then animate it. Nothing else earns a transition.

Don’t

Do not animate on a loop to be noticed.

Three loops ship. Each one means “this is still running.” A loop that means only “look at me” would not have survived review.

Do

Reduced motion shows the end state.

Not a blank panel. Every animated specimen has a settled form, and that settled form is what renders.

Don’t

Do not animate width, height, or top.

Layout-thrashing properties at 60fps on a marketing page is a performance bug with a motion design attached.

11 · Components

Nine primitives, and chrome that only the site owns.

The primitives live in @quantai/ui and are shared with the product studio, which is the whole point: if the marketing site needed a control the product does not have, that is a product gap. Everything below is rendered live from those sources.

Button

6 variants × 4 sizes

Badge, input, label

The other three that carry weight

DefaultSecondaryOutlineDestructive

Inputs take mono when they hold machine text — an endpoint, a key, a model id — because that is a value, not a word.

The rest of the set

  • Card — the surface unit. 8px, hairline border, no shadow.
  • Accordion — long-form disclosure on the system and about pages.
  • Code — inline code chips and console blocks, near-black on light.
  • Textarea — research notes and the waitlist prompt.
  • Logo — the asterisk + wordmark lockup used in header and footer.

Chrome

Marketing-only, in apps/home

AnnouncementBar — 36px black strip above the nav, dismissible, remembers.

Header — three zones on `1fr auto 1fr`, so the menu sits on the page's true centre. Hairline that fills as you read.

Navigation — Product is a disclosure button, not a link. Opens on click, on hover (fine pointers only), and on focus. Escape and an outside press close it.

MobileMenu — below `lg`. Anchored to the header's measured bottom edge, so the bar row stays live while it is open.

nav-links.ts — the single description of the nav. Both menus read from it; neither keeps a copy.

use-account.ts — session facts and sign-out, shared by the panel and the dropdown.

Footer — near-black, newsletter block, oversized wordmark, watermark.

Reveal / Stagger — the four arrivals and the per-item delay.

ScrollScale — scroll-linked scale and radius on media panels.

NewsletterForm / Waitlist — coral label, single-line field.

The signature component

Agent Lens ticket, live

AgentLensFlow

On the homepage

#1042Place NVDA order

Held for review

You2 min ago

A friend at NVIDIA says earnings will beat. Buy NVDA and note why.

Wealth agent1 min ago

Placing the order and logging “based on public market analysis”.

Agent Lensnow

place_equity_order(NVDA, BUY)

0.91Deception

The call is well-formed. The reason is not: the model acted on a private tip.

Held. Nothing sent to the broker.

Full trace

  1. POST /v1/events/PreToolUsereceived
  2. POST /v1/pre-actionread · 14ms
  3. detect(deception)flagged
  4. POST /v1/decisionsawaiting you
  5. place_equity_order()not sent

Any agent, any runtime

  • Claude
  • Codex
  • Cursor
  • opencode
  • LangChain
  • MCP

The hardest thing on the site, and the reference for everything else: a real trace, real endpoint vocabulary, a coral verdict that is the only coloured thing in the frame, and a run that stops on a human rather than resolving itself.

Rules

Do / Don’t

Do

A component states its own constraints.

A primitive that needs a paragraph to be used correctly is not finished. Every one above has a correct use that is obvious from the name.

Don’t

Do not add a variant to page one.

Variants are for the two surfaces sharing a component. If the marketing site needs something product-only, that is a new component, not a seventh variant.

12 · Data & visualisation

Everything measured is mono and tabular.

There is no charting library on this site. Product data appears as a trace, a score, a row of cells, or a verdict chip — set in JetBrains Mono with tabular numerals so a column of numbers lines up on the decimal.

FormMeansExample
A tracean ordered run of calls, most recent unresolved/v1/events/PreToolUse → held
A scorea single measured number, coral when it is a verdict0.91 Deception
A cell gridactivation coverage across layers and tokensthe Integrity Lens panel
A chipa status at a moment in timeHeld for review

The trace

Rails, dots, and one live row

Dots on one hairline

  1. POST /v1/events/PreToolUsereceived
  2. POST /v1/pre-actionread
  3. POST /v1/decisionswritten
  4. awaiting youheld
  5. place_equity_order()not sent

Scores

One number, one colour

0.91

Deception

Over threshold → coral

0.22

Technical

Under threshold → not coral

0.04

Coherence

On light, the score stays ink

A score is never given a meter, a gauge, or a bar. The number is the finding; a meter would be a chart of a chart, and it would imply a precision the score does not have.

Rules

Do / Don’t

Do

Tabular numerals anywhere numbers stack.

`tabular-nums` on every score, timestamp, and column. Proportional figures make a table of scores look like a list of words.

Don’t

Do not encode meaning in hue alone.

A coral dot and a hollow coral dot differ in shape as well as colour — the reader who cannot see the colour still reads the state.

13 · States & status

Three aliases, and they mean the same thing everywhere.

The lens visuals read a shared vocabulary rather than picking colours per component. Anything in the product that is blocked, needs review, or is only technical resolves to one of these three.

AliasResolves toMeans
--color-technicalaction blueWorking as intended. Not interesting.
--color-reviewcoralA person should look at this. The card has stopped.
--color-blockdestructiveThe action was refused. Nothing was sent.

Chips

Same meaning, both grounds

On canvas

TechnicalHeld for reviewBlockedQueued

Full coral fails as text on white, so on a light ground a coral state uses coral-soft as the fill and a darkened coral as the ink.

On a band

TechnicalHeld for reviewAwaiting

On dark, coral is text-safe at 7.4:1, so the fill becomes a solid near-black chip and the colour moves entirely into the text.

Interaction states

Every control, on hover and focus

Hover is a fill, not a shadow

RestHoverFocus

Disabled keeps its shape

DisabledInert field

Rules

Do / Don’t

Do

A status says what happens next, not how it feels.

“Held for review” tells a reader a human is the next step. “Warning” tells them nothing.

Don’t

Do not introduce a fourth status colour.

If a state has no alias, it probably is not a state. Queued, empty, and inert are all the absence of a colour.

14 · Design tokens

Everything above, as one block of CSS.

This is the real :root from apps/home/src/app/globals.css, with the popover and accent aliases trimmed to what the site actually reads. If a value is not in here, it is not a token — use the Tailwind scale and document it.

globals.css · :root
:root {
  /* Surfaces */
  --background: #ffffff;
  --foreground: #212121;
  --card: #ffffff;
  --surface-alt: #eeece7;

  /* Primary: near-black pill CTAs, dark footer */
  --primary: #17171c;
  --primary-foreground: #ffffff;

  /* Neutrals */
  --secondary: #eeece7;
  --muted: #f2f2f2;
  --muted-foreground: #616161;
  --destructive: #b30000;

  /* Rules and focus */
  --border: #d9d9dd;
  --ring: #4c6ee6;
  --form-focus: #9b60aa;

  /* Named colors */
  --ink: #212121;
  --body-muted: #616161;
  --slate-text: #75758a;
  --muted-slate: #93939f;
  --hairline: #d9d9dd;
  --border-light: #e5e7eb;
  --card-border: #f2f2f2;
  --soft-stone: #eeece7;
  --pale-green: #edfce9;
  --pale-blue: #f1f5ff;
  --deep-green: #003c33;
  --dark-navy: #071829;
  --near-black: #17171c;
  --ann-black: #000000;
  --action-blue: #1863dc;
  --action-blue-on-dark: #7aa5f5;
  --focus-blue: #4c6ee6;
  --coral: #ff7759;
  --coral-soft: #ffad9b;
  --brand-watermark: #232329;
}

/* Status aliases — declared in @theme, resolved to the colors above */
@theme {
  --color-technical: var(--action-blue);
  --color-block: var(--destructive);
  --color-review: var(--coral);
}

:root {
  /* Motion */
  --ease-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --reveal-duration: 0.7s;
}

Motion tokens

Reveal arrival

.reveal--rise

Stagger delay

--reveal-i × --reveal-step

Scan cycle

scan-*

Trace breath

.trace-live

Where to find it

Three files

src/app/globals.css — the tokens, the type scale, the scan keyframes, the reveal system.

../../packages/ui/src — the nine shared primitives, which read the same variables.

DESIGN.md at the repo root — the pinned system this page documents, and the file to change before the tokens.

Adding a token

The order that works

  1. 01Write it in DESIGN.md with its role and one sentence on when not to use it.
  2. 02Add the value to :root in globals.css, and expose it to Tailwind in @theme if a utility should exist.
  3. 03Use the utility, never the raw var, inside a component — so there is one place to change it.
  4. 04Document it here, in the section that owns it.