One source,
read by people and agents.
The design system of this site. This page reads the tokens from the CSS and the code, so it cannot show a value that the site does not use. Coding agents read the same tokens and rules as JSON.
1. Rules
Each rule says what to do and why. Where a test checks the rule, the test is named. The other rules are checked in review.
Use the color tokens (bg-background, text-fg-muted, border-border, text-brand). Do not write a color value in a component.
Light and dark mode then change together, and one edit changes the site.
No text under 14px, and no capitals made with CSS. Use text-sm (14px) as the smallest size.
Small capital labels are hard to read and add noise without meaning.
Checked bye2e/pages.spec.ts (opens in a new tab)
Do not put a small label above a heading. Put the meaning in the heading, or number the heading.
A label above a heading repeats it, and screen readers read it as a separate line.
Use the mono font only for code, file paths and ids, at 14px or more.
Mono marks text that a reader can copy into a terminal or an editor.
Make headings with Title, PageHeading or SectionHeading. Use className for layout only, not for size or weight.
One scale for the whole site. To change a size, change the variant in Title.tsx.
Show less important text with text-fg-secondary or text-fg-muted. Do not lower the opacity of text-foreground. Use text-fg-faint only for decoration and disabled text.
One opacity looks much dimmer on a dark background. Each tone has its own light and dark value, tested for APCA contrast in both schemes.
Checked bysrc/lib/design/tokens.test.ts (opens in a new tab)
Never show a state with color alone. Add an icon and a text label.
WCAG 1.4.1. The claim checker grades each have an icon, a label and a color.
Every control shows the focus ring. When an overlay closes, focus goes back to the control that opened it.
Keyboard users must always know where they are.
Checked bye2e/lab.spec.ts (opens in a new tab)
A view that waits for the network has these states: idle, pending, streaming, complete, stopped and failed. Esc stops it, and the text that arrived stays.
A stream can be slow, stop or fail at any point. Each case needs a clear screen.
Checked bye2e/chat.spec.ts (opens in a new tab)e2e/check.spec.ts (opens in a new tab)e2e/lab.spec.ts (opens in a new tab)
Every stream event carries the attempt it belongs to. A reducer ignores events from an attempt that is not active.
A stopped answer must not write into a new one.
Checked bysrc/lib/chat/chat-machine.test.ts (opens in a new tab)
Animate with a spring, ease and duration from src/lib/design/motion.ts. Do not write new values in a component.
The same kind of change then moves the same way on every page.
Respect reduced motion. Motion does this through MotionConfig at the root. CSS animations need a prefers-reduced-motion block.
Large movement can make some people feel sick.
Make click and touch targets at least 24 by 24px. Buttons are 32px high.
WCAG 2.5.8. Small targets are hard to hit on a phone.
Build on the shadcn/ui base-nova components in src/components/ui, on Base UI. Merge classes with cn from the cn package. Use Lucide icons.
The primitives handle focus, keyboard and ARIA. Do not rebuild them.
2. Color
Colors are OKLCH custom properties. Dark mode changes the values, not the names. Text colors have their own value in each scheme, because one opacity looks much dimmer on a dark background. A test checks their APCA contrast.
Surface
bg-background
The page.
bg-card
Cards and panels that sit on the page.
bg-popover
Hover cards, menus and drawers.
bg-secondary
Quiet filled controls.
bg-muted
Wells and hover fills.
bg-page-base
Behind the page cards during a page transition.
Text
text-foreground
All text. Lower its opacity for less important text.
text-fg-secondary
Supporting text next to primary text. APCA Lc 75 or more.
text-fg-muted
Descriptions, metadata and hints. APCA Lc 60 or more.
text-fg-faint
Disabled text and decoration only.
text-card-foreground
Text on a card.
text-popover-foreground
Text on a popover.
text-secondary-foreground
Text on a secondary fill.
text-muted-foreground
Text on a muted fill.
Action
bg-primary
The main button of a view.
text-primary-foreground
Text on a primary fill.
bg-accent
Hover fill of menu items.
text-accent-foreground
Text on an accent fill.
bg-ring
The focus ring. Every control shows it.
bg-brand
Selection, the active citation and emphasis in headings.
text-brand-foreground
Text on a brand fill.
Line
border-border
Dividers and card edges.
border-input
Edges of fields.
Status
bg-destructive
Errors and actions that delete.
bg-verified
The claim checker: verified.
bg-partial
The claim checker: partly verified.
bg-contradicted
The claim checker: contradicted.
Each circle shows the light value on the left and the dark value on the right. The page follows the color scheme of your system.
3. Type
DM Sans Variable for all text, at weight 400 for titles. JetBrains Mono for code, paths and ids only. Title sizes are fluid and scale with the reader’s font settings.
page
Page title (h1) · 44–88px · 1.08
On purpose
section
Section title · 32–56px · 1.15
On purpose
card
Card and project title · 24–32px · 1.2
On purpose
subsection
Subsection title · 20–24px · 1.3
On purpose
detail
Detail title · 18px · 1.4
On purpose
Body
text-lg
18px on 32px
Lead paragraphs. The answer streams in, and each claim links to its source.
text-base
16px on 28px
Body text. The answer streams in, and each claim links to its source.
text-sm
14px on 24px
Controls, metadata and hints. The smallest size. The answer streams in, and each claim links to its source.
Tones
text-foreground
Primary. Headings and body text.
text-fg-secondary
Secondary. Supporting text next to primary text.
text-fg-muted
Muted. Descriptions, metadata and hints.
text-fg-faint
Faint. Disabled text and decoration. Never for text that people must read.
4. Space and shape
Spacing follows the Tailwind scale of 4px steps. Two tokens set the rhythm of sections, and they grow at the sm (40rem) and lg (64rem) breakpoints.
| Token | Phone | From 40rem | From 64rem |
|---|---|---|---|
| --section-paddingSpace above and below a page section. | 3rem | 4rem | 5rem |
| --section-content-gapSpace between a section title and its content. | 2rem | 2.5rem | 3rem |
| --radiusCorner radius of controls. Cards use radius + 4px, pills use full. | 0.5rem | — | — |
5. Motion
Springs for things that move, because a spring can stop and turn back with the pointer. Eases for things that fade. With reduced motion on, the dots jump, and only opacity changes on the rest of the site.
Springs
Panels and cards that move or resize.
List items that enter, and indicators that slide.
Citation chips and counts that appear.
Decorative pieces on the home page that bloom in.
Decorative pieces that answer the pointer.
Eases and durations
- EASE_OUT
- cubic-bezier(0.22, 1, 0.36, 1) · Things that enter.
- EASE_IN
- cubic-bezier(0.64, 0, 0.78, 0) · Things that leave.
- DURATIONS.enter
- 280 ms · A message or panel that enters.
- DURATIONS.exit
- 200 ms · Something that leaves.
- DURATIONS.page
- 550 ms · A view that replaces another.
- DURATIONS.reveal
- 700 ms · Content that scrolls into view, and the mobile menu.
- DURATIONS.showcase
- 1100 ms · Large decorative pieces on the home page.
6. Components
The real components, in each state. Hover and focus are shown with the same classes that the states use.
Button
Base UI button with the shadcn/ui base-nova styles. The focus state is the ring that keyboard focus shows. Disabled buttons that a stream turns off stay focusable, so focus is not lost.
default
The main action of a view. One for each view.
outline
Other actions, such as Stop and Replay.
secondary
Quiet actions in a group.
ghost
Actions in toolbars and lists.
destructive
Actions that delete or stop for good.
link
Actions inside text.
Verdict badge
The five grades of the claim checker. Each has an icon, a label and a color, so color is never the only signal.
- Verified
The sources state this.
- Partly verified
The sources support part of this, but not all of it.
- Not supported
The sources cover this topic, but they do not show this.
- Contradicted
The sources state something different.
- Unknown
The public record does not cover this.
Citation chip
A number in the answer text that opens its source. It is a toggle button: aria-pressed shows the source in view.
Streams
RestStreams
Hover, or its source has the pointerStreams
ActiveStreams
FocusStreams, drawers and panels
The parts that change with time have every state on a control bar in the Lab: idle, loading, slow, streaming, interrupted, error and done.
7. For agents
Coding agents work on this site. They read the same system as people do, from the files below, before they change the interface.
Tokens and rules as JSON
Colors with light and dark values and Tailwind names, type, space, motion and all rules. Built from the same modules as this page.
Instructions
The commands, the code style and a pointer to these rules. Agents read this file first.
Checks
A unit test fails when a color in the CSS has no description, or a rule names a test that does not exist. The end-to-end tests check text sizes, focus and stream states.