DESIGN.md inspired by Graphite
Near-black developer canvas — Matter type, near-white ink, one clean blue, 8px CTAs.
Compare to…
- bg
#070707 - bg-level-1
#0f0f0f - bg-level-2
#171717 - bg-level-3
#1f1f1f - bg-overlay
rgba(7,7,7,0.72) - surface
#0f0f0f - surface-strong
#171717 - surface-tinted-brand
rgba(59,130,246,0.08) - text AAA · 19.3
#fafafa - text-strong
#ffffff - text-secondary
#d4d4d4 - text-tertiary
#a3a3a3 - text-quaternary
#737373 - text-disabled
#525252 - brand AA · 5.5
#3b82f6 - brand-hover
#60a5fa - brand-press
#2f6fed - brand-soft
rgba(59,130,246,0.16) - accent
#60a5fa - link
#60a5fa - link-hover
#93c5fd - border — · 1.2
#1f1f1f - border-strong — · 1.5
#2e2e2e - border-subtle
rgba(255,255,255,0.06) - border-brand
#3b82f6 - cta-fill
#262626 - cta-fill-hover
#2e2e2e - cta-fill-press
#1f1f1f - cta-text
#fafafa - success
#22c55e - success-bg
rgba(34,197,94,0.12) - warning
#f59e0b - warning-bg
rgba(245,158,11,0.12) - danger
#ef4444 - danger-bg
rgba(239,68,68,0.12) - info
#3b82f6 - info-bg
rgba(59,130,246,0.12) - on-brand
#ffffff
- step-0 0px
- step-1 4px
- step-2 8px
- step-3 12px
- step-4 16px
- step-5 24px
- step-6 32px
- step-7 48px
- step-8 64px
- step-9 96px
- micro
2px - sm
4px - md
8px - lg
12px - xl
16px - pill
9999px
Maps the 8 canonical role names to this entry's actual tokens. Use these to plug the design into role-aware tools — shadcn/ui themes, role-aware Tailwind plugins, atelier-lint — without hard-coding token names.
- background → bg
- foreground → text
- primary → brand
- primary-foreground → on-brand
- accent → accent
- muted → text-secondary
- border → border
- ring → brand
Graphite draws from the dark-canvas dev-tool lineage — Linear, Vercel, GitHub's diff surfaces — and from the IDE itself. The near-black ground, near-white ink, single restrained blue, and 8px-radius dark CTAs are the vocabulary of a tool whose customers read code reviews all day. It rejects marketing softening: no gradient hero, no glow, just the product shown in its own native chrome.
- Dark-canvas product-as-marketing discipline; restrained single-accent palette
- Near-black dev-tool surface and Geist-family sans typography lineage
- Code-review and diff surface conventions that Graphite reframes for the AI age
- Blue-500/600 and neutral scale this system samples for its accent and tiers
- The geometric grotesque set tight at the 60px/500 hero — Graphite's type voice
theme.extend block for tailwind.config.js
:root { --bg, --text, --brand, … } you can paste anywhere
W3C Design Tokens Community Group format
Importable into Figma → Variables → Import
---
name: Graphite
tagline: Near-black developer canvas — Matter type, near-white ink, one clean blue, 8px CTAs.
updated_at: 2026-05-28T23:12:23.528Z
published_at: 2026-05-28T23:12:23.528Z
author: webdesignhot
source_url: https://graphite.dev
spec: webdesignhot/0.1
quality: curated
featured: false
categories: [dev-tools, saas]
tags: [dark, minimal, sans, developer, code-review]
preview_swatch: ['#070707', '#3b82f6', '#60a5fa']
description: 'Graphite renders its marketing site like the IDE its customers live in — a near-black `#070707` canvas, near-white `#fafafa` ink, and the Matter typeface set tight at a 60px/500 hero. The chromatic budget is a single clean blue `#3b82f6`, reserved for links, focus, and the rare emphasis; the dominant CTAs stay dark `#262626` with an 8px radius, so the blue never has to fight the page. It is developer-technical in register — Linear-adjacent restraint, built for engineers who read diffs all day.'
# Canonical 8-role aliases (bg / text / brand / border / accent / muted / surface / danger).
# Maps role names to this entry's actual token names so role-aware
# downstream tools resolve `theme.background` → entry's `bg`, etc.
# Auto-generated by scripts/add-aliases.mjs — do not edit manually;
# regenerate after changing color token names.
aliases:
background: bg
foreground: text
primary: brand
primary-foreground: on-brand
accent: accent
border: border
ring: brand
muted: text-secondary
colors:
# Page grounds
bg: '#070707' # canvas — near-black (lab 2.75), not pure #000
bg-level-1: '#0f0f0f' # first elevation tier (cards, panels)
bg-level-2: '#171717' # second elevation (hover, banners, emphasized)
bg-level-3: '#1f1f1f' # third tier — popovers, raised tooltips
bg-overlay: 'rgba(7,7,7,0.72)' # modal scrim
# Surfaces & containers
surface: '#0f0f0f'
surface-strong: '#171717'
surface-tinted-brand: 'rgba(59,130,246,0.08)' # brand-tinted callout wash
# Text
text: '#fafafa' # body copy, headlines (lab 98.26)
text-strong: '#ffffff' # display, max contrast
text-secondary: '#d4d4d4' # supporting copy
text-tertiary: '#a3a3a3' # metadata, captions
text-quaternary: '#737373' # placeholder, faint helpers
text-disabled: '#525252'
# Brand & accent — one clean blue
brand: '#3b82f6' # Graphite blue — links, focus, emphasis
brand-hover: '#60a5fa' # active states / hover lift
brand-press: '#2f6fed'
brand-soft: 'rgba(59,130,246,0.16)' # tinted backdrop
accent: '#60a5fa' # brighter blue for active glow
link: '#60a5fa' # link copy on dark
link-hover: '#93c5fd'
# Borders
border: '#1f1f1f' # default 1px hairline
border-strong: '#2e2e2e' # emphasized
border-subtle: 'rgba(255,255,255,0.06)' # near-invisible
border-brand: '#3b82f6'
# CTA-dark (the signature primary — observed live, 8px radius)
cta-fill: '#262626' # dark neutral pill button
cta-fill-hover: '#2e2e2e'
cta-fill-press: '#1f1f1f'
cta-text: '#fafafa'
# Semantic
success: '#22c55e'
success-bg: 'rgba(34,197,94,0.12)'
warning: '#f59e0b'
warning-bg: 'rgba(245,158,11,0.12)'
danger: '#ef4444'
danger-bg: 'rgba(239,68,68,0.12)'
info: '#3b82f6'
info-bg: 'rgba(59,130,246,0.12)'
on-brand: '#ffffff'
typography:
display:
family: 'matterFont, "Matter", system-ui, -apple-system, sans-serif'
weights: [500, 600, 700]
body:
family: 'matterFont, "Matter", system-ui, -apple-system, sans-serif'
weights: [400, 500, 600]
mono:
family: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace'
weights: [400, 500]
scale:
display-hero: { size: 72, weight: 500, lineHeight: 1.0, tracking: '-0.03em', family: display }
display-lg: { size: 60, weight: 500, lineHeight: 1.05, tracking: '-0.025em', family: display }
h1: { size: 60, weight: 500, lineHeight: 1.05, tracking: '-0.022em', family: display }
h2: { size: 40, weight: 500, lineHeight: 1.1, tracking: '-0.018em', family: display }
h3: { size: 28, weight: 500, lineHeight: 1.2, tracking: '-0.012em', family: display }
h4: { size: 20, weight: 600, lineHeight: 1.3, tracking: '-0.005em', family: display }
eyebrow: { size: 13, weight: 500, lineHeight: 1.4, tracking: '0.04em', family: body, transform: uppercase }
body-lg: { size: 18, weight: 400, lineHeight: 1.55, tracking: '0', family: body }
body: { size: 16, weight: 400, lineHeight: 1.55, tracking: '0', family: body }
body-sm: { size: 14, weight: 400, lineHeight: 1.5, tracking: '0', family: body }
body-emphasis: { size: 16, weight: 500, lineHeight: 1.55, tracking: '0', family: body }
label: { size: 13, weight: 500, lineHeight: 1.4, tracking: '0', family: body }
caption: { size: 12, weight: 500, lineHeight: 1.4, tracking: '0.02em', family: body }
code-inline: { size: 14, weight: 400, lineHeight: 1.5, tracking: '0', family: mono }
code-block: { size: 13, weight: 400, lineHeight: 1.6, tracking: '0', family: mono }
button: { size: 14, weight: 500, lineHeight: 1, tracking: '0', family: body }
button-large: { size: 16, weight: 500, lineHeight: 1, tracking: '0', family: body }
radius:
micro: 2
sm: 4
md: 8
lg: 12
xl: 16
pill: 9999
spacing:
base: 4
scale: [0, 4, 8, 12, 16, 24, 32, 48, 64, 96]
layout:
page-width: 1280
prose-width: 720
header-height: 64
section-y: 96
gutter: 24
grid-columns: 12
components:
button-primary:
backgroundColor: '#262626'
textColor: '#fafafa'
rounded: md
padding: '10px 16px'
height: 40
font: '14px Matter, weight 500'
hover: 'bg #2e2e2e'
active: 'bg #1f1f1f'
focus: 'ring 2px #3b82f6 offset 2px on bg'
use: 'log-in / get-started — dark neutral, observed live at 8px radius'
button-brand:
backgroundColor: '#3b82f6'
textColor: '#ffffff'
rounded: md
padding: '10px 16px'
use: 'rare — used only when emphasis must be brand-coded (sign-up, beta)'
hover: 'bg #60a5fa'
button-ghost:
backgroundColor: transparent
textColor: '#d4d4d4'
border: '1px solid #1f1f1f'
rounded: md
padding: '10px 16px'
height: 40
hover: 'bg rgba(255,255,255,0.05); text #fafafa; border #2e2e2e'
use: 'secondary nav, "Read the docs"'
button-icon:
backgroundColor: transparent
textColor: '#a3a3a3'
rounded: md
size: '32 × 32'
hover: 'bg #171717; text #fafafa'
use: 'header utility — search, theme, account'
card:
backgroundColor: '#0f0f0f'
border: '1px solid #1f1f1f'
rounded: lg
padding: 24
shadow: none
hover: 'border #2e2e2e; bg #171717'
use: 'feature blocks, doc cards — never shadowed'
card-hero:
backgroundColor: '#0f0f0f'
border: '1px solid #1f1f1f'
rounded: xl
padding: 48
use: 'product-screenshot frames, feature splits'
input:
backgroundColor: '#0f0f0f'
textColor: '#fafafa'
placeholderColor: '#737373'
border: '1px solid #1f1f1f'
rounded: md
height: 40
padding: '8px 12px'
focus: 'border #3b82f6; ring rgba(59,130,246,0.32) 0 0 0 3px'
font: '14px Matter 400'
use: 'compact dense — matches in-product surfaces'
pill-status:
backgroundColor: 'rgba(59,130,246,0.12)'
textColor: '#60a5fa'
border: '1px solid rgba(59,130,246,0.22)'
rounded: pill
padding: '2px 10px'
font: '12px Matter 500'
use: 'status: merged / approved / changes-requested — semantic colour swap'
navbar:
backgroundColor: 'rgba(7,7,7,0.72)'
backdrop-filter: 'blur(12px) saturate(180%)'
border-bottom: '1px solid #1f1f1f'
height: 64
use: 'sticky top — no shadow on scroll, just border edge'
tooltip:
backgroundColor: '#1f1f1f'
textColor: '#fafafa'
border: '1px solid #2e2e2e'
rounded: md
font: '12px Matter 500'
shadow: '0 8px 24px rgba(0,0,0,0.5)'
motion:
ease-standard: 'cubic-bezier(0.4, 0, 0.2, 1)'
ease-emphasized: 'cubic-bezier(0.2, 0, 0, 1)'
ease-out: 'cubic-bezier(0, 0, 0.2, 1)'
duration-fast: 150
duration-standard: 240
duration-slow: 320
hover-button: 'bg shift over 150ms ease-out; no transform'
hover-card: 'border #2e2e2e transition over 240ms; no transform'
page-transition: 'opacity 200ms ease-standard; no slide'
scroll-fade: 'opacity 0 → 1 over 320ms with translateY(8px) → 0'
reduced-motion: 'respects prefers-reduced-motion: reduce — transitions to opacity-only, transform disabled'
breakpoints:
mobile: 640
tablet: 1024
desktop: 1280
wide: 1536
shadows:
none: 'none'
ambient: '0 1px 2px rgba(0,0,0,0.5)'
popover: '0 8px 24px rgba(0,0,0,0.5)'
modal: '0 24px 48px rgba(0,0,0,0.6)'
ring-focus: '0 0 0 3px rgba(59,130,246,0.32)'
accessibility:
contrast-text-on-bg: 19.3 # #fafafa on #070707 — AAA
contrast-secondary-on-bg: 13.6 # #d4d4d4 on #070707 — AAA
contrast-brand-on-bg: 5.5 # #3b82f6 on #070707 — AA
contrast-cta-text: 14.5 # #fafafa on #262626 — AAA
focus-ring: '3px solid rgba(59,130,246,0.32) offset 2px'
reduced-motion-honored: true
keyboard-nav: 'visible focus on every interactive; skip-to-content link before header'
aria-patterns: 'dialog uses role=dialog + aria-modal=true; popover uses role=dialog + aria-labelledby; status pills use aria-live=polite'
dark-mode: native # Graphite is dark-first; marketing surface ships near-black only
lineage:
summary: 'Graphite draws from the dark-canvas dev-tool lineage — Linear, Vercel, GitHub''s diff surfaces — and from the IDE itself. The near-black ground, near-white ink, single restrained blue, and 8px-radius dark CTAs are the vocabulary of a tool whose customers read code reviews all day. It rejects marketing softening: no gradient hero, no glow, just the product shown in its own native chrome.'
influences:
- { name: Linear, role: 'Dark-canvas product-as-marketing discipline; restrained single-accent palette', url: 'https://linear.app' }
- { name: Vercel, role: 'Near-black dev-tool surface and Geist-family sans typography lineage', url: 'https://vercel.com' }
- { name: GitHub, role: 'Code-review and diff surface conventions that Graphite reframes for the AI age', url: 'https://github.com' }
- { name: Tailwind CSS Palette, role: 'Blue-500/600 and neutral scale this system samples for its accent and tiers', url: 'https://tailwindcss.com/docs/customizing-colors' }
- { name: Matter (Displaay Type Foundry), role: 'The geometric grotesque set tight at the 60px/500 hero — Graphite''s type voice', url: 'https://displaay.net/typeface/matter/matter/' }
---
## 1. Visual Theme & Atmosphere
Graphite is a code-review tool dressed as the editor its users already
trust. The marketing site is rendered on a near-black `#070707` canvas
(lab `2.75`, a hair off pure `#000` to keep type from crunching) with
near-white `#fafafa` ink, the Matter typeface set tight, and a single
clean blue `#3b82f6` held in reserve. The atmosphere is the IDE at
night: nothing decorative, no gradient orbs, no marketing glow — just
the product shown in its own native chrome. If you build software for
a living, the page reads as familiar before you've parsed a word.
What separates it from softer dev-tool sites is conviction about the
canvas. Most tools lighten their dark themes for marketing — bigger
margins, lifted text, friendly illustration. Graphite refuses. The
near-black holds across the whole page; section breaks are tonal
lifts (`#0f0f0f`, `#171717`), not new colours. The hero is a 60px
Matter headline at weight `500` — firm but not bold — over a single
line of supporting copy and one dark CTA. The screenshot of the
review surface does the persuading.
The chromatic budget is deliberately one blue. `#3b82f6` carries
links, focus rings, the active state of a tab, and the rare
brand-coded button — and that's the whole accent story. Because the
dominant CTAs are dark neutral `#262626` at an 8px radius (observed
live), the blue never competes with itself. One eye-anchor per
screen, one accent in the system. The restraint is the brand: it
signals a tool made by engineers who distrust ornament.
The register is developer-technical — Linear-adjacent. Copy is
declarative and present-tense; geometry is rectilinear at 8px, not
pill; depth is carried by tone and hairline borders, not shadows.
The mood is a workstation that respects your attention: dense where
it counts, quiet everywhere else.
**Key Characteristics**
- Near-black `#070707` ground (lab `2.75`, warm-leaning, never `#000`)
- Near-white `#fafafa` ink (lab `98.26`), never pure `#ffffff` for body
- Matter typeface (`matterFont`) — hero at 60px / weight `500`, tight tracking
- One clean blue `#3b82f6` — links, focus, rare emphasis; never the default CTA
- Dark-neutral CTAs `#262626` at **8px radius** (the live-observed signature)
- 8px is the working radius — rectilinear, not pill (contrast with Linear)
- Tonal layering for depth (`#070707` → `#0f0f0f` → `#171717` → `#1f1f1f`)
- No drop shadows on cards; hairline borders + tonal lift do the work
- Single eye-anchor per screen; the product screenshot is the hero
- Marketing surface ships dark-first — no light variant on the website
## 2. Color Palette & Roles
### Canvas (Primary)
- **bg** `#070707` — page canvas, near-black (lab `2.75`), the whole site lives here
- **bg-level-1** `#0f0f0f` — first elevation: cards, panels, section lifts
- **bg-level-2** `#171717` — second elevation: hover, banner strips, emphasized blocks
- **bg-level-3** `#1f1f1f` — third tier: popovers, tooltips, raised menus
- **bg-overlay** `rgba(7,7,7,0.72)` — modal scrim over the canvas
### Text
- **text** `#fafafa` — body copy and headlines (lab `98.26`), default ink
- **text-strong** `#ffffff` — display / max-contrast moments only
- **text-secondary** `#d4d4d4` — supporting copy, sub-headers
- **text-tertiary** `#a3a3a3` — captions, metadata, helper lines
- **text-quaternary** `#737373` — placeholders, faint helpers
- **text-disabled** `#525252` — disabled labels
### Brand
- **brand** `#3b82f6` — Graphite blue: links, focus, active tab, rare emphasis
- **brand-hover** `#60a5fa` — hover / active glow, brighter step
- **brand-press** `#2f6fed` — pressed state on branded controls
- **brand-soft** `rgba(59,130,246,0.16)` — tinted callout backdrop
- **accent** `#60a5fa` — brighter blue used for active glow and links
- **link** `#60a5fa` — link copy on dark; **link-hover** `#93c5fd`
### CTA (the live signature)
- **cta-fill** `#262626` — dark-neutral primary button (observed live, 8px radius)
- **cta-fill-hover** `#2e2e2e` — hover lift
- **cta-fill-press** `#1f1f1f` — pressed
- **cta-text** `#fafafa` — ink on the dark CTA
### Borders
- **border** `#1f1f1f` — default 1px hairline
- **border-strong** `#2e2e2e` — emphasized rule / hover border
- **border-subtle** `rgba(255,255,255,0.06)` — barely-visible separators
- **border-brand** `#3b82f6` — active input outline
### Surface
- **surface** `#0f0f0f` — default card
- **surface-strong** `#171717` — emphasized panel
- **surface-tinted-brand** `rgba(59,130,246,0.08)` — brand-coded callout wash
### Shadow
Shadows are *almost never used on cards.* When they appear (popovers,
modals), they are pure-neutral black, multi-layer:
- **shadow-popover** `0 8px 24px rgba(0,0,0,0.5)`
- **shadow-modal** `0 24px 48px rgba(0,0,0,0.6)`
- **shadow-ambient** `0 1px 2px rgba(0,0,0,0.5)` — subtle sticky-header lift
### Semantic
- **success** `#22c55e` + **success-bg** `rgba(34,197,94,0.12)` — merged / approved
- **warning** `#f59e0b` + **warning-bg** `rgba(245,158,11,0.12)` — pending / stale
- **danger** `#ef4444` + **danger-bg** `rgba(239,68,68,0.12)` — failing / blocked
- **info** `#3b82f6` + **info-bg** `rgba(59,130,246,0.12)` — uses the brand blue
Status pills follow one pattern: tinted bg + tinted border (~22% alpha)
+ tinted text at full saturation.
## 3. Typography Rules
### Font Family
- **Primary (display + body)**: `matterFont` — the Matter typeface
(Displaay Type Foundry), a geometric grotesque, with `"Matter"`,
`system-ui`, `-apple-system`, `sans-serif` fallback chain
- **Mono**: `ui-monospace`, `SFMono-Regular`, `"SF Mono"`, `Menlo`,
`monospace` — for inline code, diffs, and code blocks
- **Live-observed**: hero h1 renders at **60px / weight 500**, body at
**16px / weight 400** — both in `matterFont`. The headline weight is
`500` (firm, not bold), which is the system's whole voice.
### Hierarchy
| Role | Font | Size | Weight | Line Height | Tracking | Notes |
|---|---|---|---|---|---|---|
| display-hero | Matter | 72 | 500 | 1.0 | -0.03em | Largest landing splash |
| display-lg | Matter | 60 | 500 | 1.05 | -0.025em | Section heroes |
| h1 | Matter | 60 | 500 | 1.05 | -0.022em | Page title (live: 60/500) |
| h2 | Matter | 40 | 500 | 1.1 | -0.018em | Major sections |
| h3 | Matter | 28 | 500 | 1.2 | -0.012em | Sub-sections |
| h4 | Matter | 20 | 600 | 1.3 | -0.005em | Card titles |
| eyebrow | Matter | 13 | 500 | 1.4 | 0.04em uppercase | Section markers |
| body-lg | Matter | 18 | 400 | 1.55 | 0 | Hero subhead |
| body | Matter | 16 | 400 | 1.55 | 0 | Default body (live: 16/400) |
| body-emphasis | Matter | 16 | 500 | 1.55 | 0 | Inline emphasis |
| body-sm | Matter | 14 | 400 | 1.5 | 0 | Footnotes, dense copy |
| label | Matter | 13 | 500 | 1.4 | 0 | Form labels |
| caption | Matter | 12 | 500 | 1.4 | 0.02em | Metadata |
| code-inline | Mono | 14 | 400 | 1.5 | 0 | Inline code |
| code-block | Mono | 13 | 400 | 1.6 | 0 | Diffs, code blocks |
| button | Matter | 14 | 500 | 1 | 0 | Default button |
| button-large | Matter | 16 | 500 | 1 | 0 | Hero CTA |
### Principles
- **Weight 500 is the headline voice.** The hero renders at `500`, not
`700`. Hierarchy is carried by size and tight tracking, not bold —
`700` is reserved for the rare wordmark or code emphasis.
- **Tracking tightens with size.** The 60px h1 sits near `-0.022em`;
the 72px hero tightens to `-0.03em`. Display type must feel
engineered, not bloated. Body stays at `0`.
- **Matter is the brand vocabulary.** The geometric grotesque reads as
technical and modern without GitHub-mono or Inter-default fatigue.
Treat `matterFont` as load-bearing; the `system-ui` fallback is a
graceful but visible downgrade.
- **Mono is for the diff.** Code, file paths, and review snippets use
the mono stack. It signals the product's domain on a marketing page
without illustration.
- **Body never goes pure white.** `#fafafa` (lab `98.26`) is the ink;
`#ffffff` is held for display-only max-contrast moments.
- **Reading width caps at ~720px** even when the page is 1280. Long
copy is always constrained inside the wider frame.
## 4. Component Stylings
### Buttons (4 variants)
**Primary (the live signature — dark neutral)**
- Background: `#262626`
- Text: `#fafafa` at 14/500
- Padding: `10px 16px`, Height: 40
- Radius: **8 (md)** — observed live on the Log-in CTA
- Border: none
- Hover: bg `#2e2e2e`
- Active: bg `#1f1f1f`
- Focus: `ring 2px #3b82f6 offset 2px`
- Use: log-in, get-started — the dominant action on most screens
**Brand (rare)**
- Background: `#3b82f6`
- Text: `#ffffff` at 14/500
- Radius: 8 (md)
- Hover: bg `#60a5fa`
- Use: only when the action must read as brand-coded — sign-up, beta
enrolment. Most pages use the dark primary instead.
**Ghost**
- Background: transparent
- Text: `#d4d4d4` at 14/500
- Border: `1px solid #1f1f1f`
- Radius: 8 (md)
- Hover: bg `rgba(255,255,255,0.05)`; text `#fafafa`; border `#2e2e2e`
- Use: secondary nav, "Read the docs"
**Icon**
- Background: transparent → `#171717` on hover
- Text: `#a3a3a3` → `#fafafa` on hover
- Size: 32 × 32, Radius: 8 (md)
- Use: header utilities — search, theme toggle, account
### Cards (2 variants)
**Standard card**
- Background: `#0f0f0f`, Border: `1px solid #1f1f1f`, Radius: 12 (lg)
- Padding: 24, Shadow: none
- Hover: border `#2e2e2e`, bg `#171717`
- Use: feature blocks, doc cards
**Hero card**
- Background: `#0f0f0f`, Border: `1px solid #1f1f1f`, Radius: 16 (xl)
- Padding: 48
- Use: product-screenshot frames, feature splits
### Inputs / Forms
**Text input**
- Background: `#0f0f0f`, Border: `1px solid #1f1f1f`, Radius: 8 (md)
- Height: 40, Padding: `8px 12px`
- Font: `14px Matter 400`
- Placeholder: `#737373`
- Focus: border `#3b82f6`; ring `rgba(59,130,246,0.32) 0 0 0 3px`
- Disabled: bg `#070707`, text `#525252`
**Select** — same shell as input + a chevron icon at 12px in `#a3a3a3`;
the popover follows tooltip styling.
**Checkbox / Radio** — 16 × 16, `1px solid #2e2e2e`, 4px radius
(checkbox) or 9999 (radio); checked fill is brand `#3b82f6`.
### Badges, Tags, Pills
**Status pill** — pill radius, tinted bg + tinted border at ~22% alpha
+ tinted text at full saturation. Maps to review states: merged
(success `#22c55e`), approved (brand `#3b82f6`), changes-requested
(warning `#f59e0b`), failing (danger `#ef4444`).
**Tag** — neutral variant: `#171717` bg, `#2e2e2e` border, `#d4d4d4`
text. Used for repo / category labels.
### Navigation
**Top nav**: 64px tall, `rgba(7,7,7,0.72)` bg with `backdrop-filter:
blur(12px) saturate(180%)`, 1px bottom border `#1f1f1f`. Sticky on
scroll — no shadow added, just the border edge. (Note: the live audit
also caught a `Cursor Cloud Agents` banner strip at `#171717` — that
is announcement noise, not part of the nav system.)
**Footer**: dark with low-contrast `#737373` text on `#070707`; 1px
top border `#1f1f1f`.
**Side nav (docs)**: tonal column at `bg-level-1` with `#1f1f1f` rule
on the right; active item gets `bg-level-2` + 2px brand left border.
### Tooltips & Popovers
Tooltip: `#1f1f1f` bg, `#2e2e2e` border, 8 radius, `12px Matter 500`
text, 6 × 10 padding. Shadow `0 8px 24px rgba(0,0,0,0.5)`.
Popover (menu, combobox): `#1f1f1f` bg with the same border and shadow,
8 radius, max-width 320, list items use 6/8 padding.
### Modals
Centered overlay on `rgba(7,7,7,0.72)` scrim with backdrop blur.
Dialog box at `#171717`, 12 radius, 24 padding, 1px `#2e2e2e` border,
shadow `0 24px 48px rgba(0,0,0,0.6)`. Title at h3 500, body 16/400,
action row pinned to the footer with the primary CTA on the right.
## 5. Layout Principles
### Spacing System
- **Base unit**: 4px
- **Scale**: `[0, 4, 8, 12, 16, 24, 32, 48, 64, 96]`
- Small steps (4, 8) handle in-component spacing; big jumps (64, 96)
handle section rhythm. Density is product-grade: 8px between form
rows, 4px between an icon and its label, 16–24px between cards.
- The marketing page inherits the product's tight interior spacing
while keeping generous section gutters.
### Grid & Container
- **Page width**: 1280px max
- **Prose width**: 720px — multi-paragraph copy is capped here within
the 1280 frame
- **Gutter**: 24px
- **Grid**: 12 columns on tablet+, single column on mobile
- Hero: full-bleed near-black bg + centred 1280 content; the product
screenshot lives inside its own hero card, not full-bleed
- Feature grid: asymmetric splits (copy vs. screenshot) when one side
deserves visual primacy
### Whitespace Philosophy
Graphite is dense by product DNA but generous on marketing rhythm.
Sections breathe at ~96px vertical gutters; *within* sections the
density tightens to product values (8–24px). Macro-relaxed,
micro-tight — the same tempo the IDE uses.
### Section Cadence
The site stays on `#070707` throughout. Section breaks are tonal —
`bg-level-1` panels stand against the canvas rather than introducing
new colours. The exception is the occasional `bg-level-2` band
(customer quote, announcement strip) that lifts for one viewport and
returns to canvas.
## 6. Shapes & Radius Scale
| Tier | px | Use |
|---|---|---|
| Micro | 2 | Decorative corners, inline accents |
| Standard (sm) | 4 | Tags, micro-pills, checkboxes |
| Comfortable (md) | **8** | **Buttons, inputs, icon buttons — the working radius** |
| Relaxed (lg) | 12 | Cards, panel containers, modals |
| Featured (xl) | 16 | Hero cards, product-screenshot frames |
| Pill | 9999 | Status pills, avatar mode only |
The **8px (md)** corner is the system's signature — confirmed live on
the primary CTA. Graphite is rectilinear, not pill-driven: where
Linear rounds CTAs to full pills, Graphite keeps them at 8px, which
reads more like an IDE control. The pill (9999) is reserved for status
indicators and avatars, never the action buttons.
There is essentially no `0px`-radius element except 1px hairline
section rules. Compound radii appear only in modal headers (`12 12 0 0`
to lock to the body) and pinned tab strips (`8 8 0 0`).
## 7. Depth & Elevation
| Level | Treatment | Use |
|---|---|---|
| 0 | flat — `#070707` only | page canvas |
| 1 | `#0f0f0f` + 1px `#1f1f1f` border | cards, panels |
| 2 | `#171717` + 1px `#2e2e2e` border | hover, banners, emphasized |
| 3 | `#1f1f1f` + ambient shadow `0 1px 2px rgba(0,0,0,0.5)` | sticky header |
| 4 | `#1f1f1f` + popover shadow `0 8px 24px rgba(0,0,0,0.5)` | tooltips, menus, popovers |
| 5 | `#171717` + modal shadow `0 24px 48px rgba(0,0,0,0.6)` + scrim | modals, dialogs |
### Shadow Philosophy
Graphite uses **tonal stacking** as its default depth language. Each
elevation step lifts lightness a few points — barely perceptible
alone, readable as a stack. Borders pick up where tone is too subtle:
`#1f1f1f` → `#2e2e2e` is the two-step border ladder.
Drop shadows are **floating UI only**: popovers, tooltips, modals,
toasts. Cards never carry shadows; the hairline border plus the tonal
lift do all the work. Shadows are pure-neutral black (no tint),
multi-layer when deep. The result reads as solid surfaces on a solid
ground, not floating glass.
## 8. Interaction & Motion
### Easing curves
- **ease-standard**: `cubic-bezier(0.4, 0, 0.2, 1)` — default for
hover and state transitions
- **ease-emphasized**: `cubic-bezier(0.2, 0, 0, 1)` — page enters,
modal slide-in
- **ease-out**: `cubic-bezier(0, 0, 0.2, 1)` — settling motions
### Duration buckets
- **fast**: 150ms — button hover, focus ring, state changes
- **standard**: 240ms — card hover, popover open
- **slow**: 320ms — modal enter, scroll-fade
### Per-component micro-states
- **Button hover**: bg lift (`#262626 → #2e2e2e`) over 150ms ease-out;
*no transform* — the dark CTA stays planted
- **Button active**: bg press to `#1f1f1f` over 150ms
- **Card hover**: border transition `#1f1f1f → #2e2e2e` + bg lift
`#0f0f0f → #171717` over 240ms ease-standard; *no transform*
- **Link hover**: colour shift `#60a5fa → #93c5fd` only, 150ms; no
underline grow
- **Popover open**: opacity 0 → 1 + scale 0.98 → 1 over 240ms
ease-emphasized
- **Modal enter**: scrim fade 320ms + dialog slide from `translateY(8px)`
to 0 over 320ms ease-emphasized
### Page transitions
Marketing page changes are full opacity 0 → 1 over 200ms — no slide.
Scroll-fade for in-view content uses opacity + 8px `translateY` → 0
over 320ms.
### Reduced motion
Respects `prefers-reduced-motion: reduce`. All transforms disabled,
all transitions reduced to opacity-only at the same durations. The
sticky-header backdrop blur stays on (it is not motion).
## 9. Accessibility & A11y
### Contrast pairs (computed from live tokens)
- **#fafafa on #070707 (text on bg)**: **19.3** — AAA at all sizes
- **#d4d4d4 on #070707 (secondary on bg)**: 13.6 — AAA
- **#a3a3a3 on #070707 (tertiary on bg)**: 8.0 — AAA at body sizes
- **#737373 on #070707 (quaternary on bg)**: 4.2 — AA Large only; use
for non-essential helpers
- **#fafafa on #262626 (CTA text on dark fill)**: 14.5 — AAA
- **#3b82f6 on #070707 (brand on bg)**: 5.5 — AA for text and icons
- **#60a5fa on #070707 (link on bg)**: 7.9 — AAA
- **#ffffff on #3b82f6 (text on brand button)**: 3.7 — AA Large /
UI-component contrast only; keep brand-button label at 14px+ 500
### Focus indicators
Every interactive element ships a focus ring: `3px solid
rgba(59,130,246,0.32)` with 2px offset on the dark canvas — box-shadow
ring, not outline, so it composites cleanly over borders. Inputs get
the solid `#3b82f6` border on focus plus the ring.
### ARIA patterns
- **Combobox** (search): `role=combobox` + `aria-expanded` +
`aria-controls` + `aria-activedescendant`
- **Dialog**: `role=dialog` + `aria-modal=true` + `aria-labelledby`
pointing to the title node
- **Status pills**: `aria-live=polite` for in-page state changes;
state included in the accessible name (e.g., `aria-label="Status: merged"`)
### Keyboard nav
A skip-to-content link appears on first Tab focus (confirmed live).
Tab order: skip link → header logo → nav links → header CTA → hero CTA
→ in-page sections → footer. All buttons and links are keyboard
reachable; focus is always visible.
### Screen reader hints
- Icon-only buttons carry `aria-label` (e.g., `aria-label="Search"`)
- Decorative icons get `aria-hidden=true`
- Diff and code regions use `role=region` with a descriptive label
### Reduced motion
Honoured globally; see §8. Auto-playing demo loops respect the same
query and freeze on the first frame.
## 10. Responsive Behavior
| Breakpoint | px | Layout |
|---|---|---|
| mobile | < 640 | single-column, 16px gutter, h1 → 36px |
| tablet | 640–1023 | 2-column on splits, 20px gutter, h1 → 44px |
| desktop | 1024–1279 | full 12-col grid, h1 → 56px |
| wide | ≥ 1280 | page caps at 1280, h1 at 60px — refuses to over-stretch |
### Touch targets
Minimum 44 × 44 on mobile (buttons grow vertical padding from 10 to
12; icon buttons grow to 40 × 40). All keep the 8px radius —
fingerprint matches desktop.
### Collapsing strategy
- Header collapses to a hamburger at ≤ 768
- Feature grids switch from asymmetric splits to single-column stacks
at ≤ 768
- Comparison tables become card lists at ≤ 640
- Sticky docs sidebar becomes a top sheet on mobile
### Image behavior
Product screenshots use `aspect-ratio: 16 / 10` and `object-fit: cover`
with `loading=lazy`. SVG illustrations are inline and respect
`currentColor`. Screenshot corners match their parent hero card (16px),
no radius mismatch.
### Container queries
Used in hero-card variants where the screenshot frame switches from
landscape to portrait based on container width below ~480px.
## 11. Content & Voice
### Tone
Direct, technical, present-tense. Graphite writes like an engineer
leaving review comments: declarative, specific, allergic to hype. The
title itself sets the register — "Code review for the age of AI."
Sentences are short; metaphors are rare and mechanical when used.
### Microcopy patterns
- **Button verbs**: "Log in", "Get started", "Read the docs", "Start
reviewing" — short, imperative, present-tense. Never "Click here" or
"Learn more about our…".
- **Errors**: format `<noun> couldn't be <verbed>. <one-sentence
reason>.` Example: "Review couldn't be submitted. You're offline."
- **Success confirmations**: terse, no exclamation marks. Example:
"Branch merged."
- **Progress**: `Syncing…` rather than `Please wait…`
### Empty states
Empty review queues show a short headline (e.g., "No open reviews"),
one line of orientation, and a single CTA. No illustration, no upbeat
encouragement.
### CTA verb conventions
Observed verb ladder, by frequency:
1. **Get started** — top-of-page hero CTA
2. **Log in** — utility nav (the live-sampled dark CTA)
3. **Read the docs** — developer-facing pages
4. **Book a demo** — enterprise surfaces
Graphite avoids "Sign up free" / "Free trial" in the verb — the
free-tier fact lives in copy below the CTA, not in the button label.
## 12. Dark Mode & Theming
Graphite is **dark-first by design**. The marketing site ships
near-black only — the dark canvas *is* the brand identity, the same
surface the review product runs on. Inverting it would break
recognition with the engineering audience it targets.
If a downstream system needs to derive a light variant from these
tokens (e.g., for a light-mode docs portal):
```yaml
colors-light:
bg: '#ffffff'
bg-level-1: '#fafafa'
bg-level-2: '#f4f4f5'
text: '#070707'
text-secondary: '#404040'
text-tertiary: '#737373'
brand: '#2563eb' # darken the blue for white-bg contrast
border: '#e5e5e5'
cta-fill: '#171717' # dark CTA stays dark, near-black on white
cta-text: '#fafafa'
```
But Graphite's own marketing surface stays near-black. This is
intentional.
## 13. Lineage & Influences
Graphite's marketing surface is engineered as a continuation of the
review product, not a separate brand layer. The lineage runs through
three strands: dark-canvas dev-tool design (Linear, Vercel), the
code-review and diff conventions of GitHub that Graphite reframes "for
the age of AI," and the Bay-Area discipline of a single restrained
accent over a near-black ground. What it inherits is the refusal to
soften the canvas for marketing — to treat the website as a view into
the tool. What it adds is the specific Matter type voice (60px / weight
`500`) and the dark-neutral 8px CTA, which reads as an IDE control
rather than a marketing pill.
What it rejects: Stripe-class chromatic gradients, glassy chrome, and
playful illustration. The system has no mascot, no gradient mark, no
decorative element. Where Linear pills its CTAs, Graphite keeps them
rectilinear at 8px; where most tools spend a second accent colour,
Graphite spends exactly one blue. The blue is punctuation, never the
page.
**Influences:**
- **Linear** — Dark-canvas product-as-marketing discipline and the
single-accent restraint Graphite mirrors
([linear.app](https://linear.app))
- **Vercel** — Near-black dev-tool surface and the Geist-family sans
typography lineage that sets the register
([vercel.com](https://vercel.com))
- **GitHub** — The code-review and diff surface conventions Graphite
reframes for AI-assisted review ([github.com](https://github.com))
- **Tailwind CSS palette** — The blue-500/600 accent and neutral tiers
this system samples ([tailwindcss.com](https://tailwindcss.com/docs/customizing-colors))
- **Matter (Displaay Type Foundry)** — The geometric grotesque set
tight at the 60px/500 hero; Graphite's type voice
([displaay.net](https://displaay.net/typeface/matter/matter/))
## 14. Do's and Don'ts
### Do
- Use the near-black `#070707` ground across the whole surface — let
section breaks be tonal lifts, not new colours.
- Keep `#fafafa` as body ink; reserve pure `#ffffff` for display-only
max-contrast moments.
- Set headlines in Matter at weight `500` — firm, not bold. Carry
hierarchy with size and tracking.
- Tighten tracking as type scales up (`-0.022em` at 60px), keep body
at `0`.
- Make the dominant CTA dark-neutral `#262626` at **8px radius** — the
live-observed signature.
- Treat the blue `#3b82f6` as accent-only: links, focus, the rare
brand-coded button — one accent in the system.
- Use tonal layering (`#070707` → `#0f0f0f` → `#171717` → `#1f1f1f`)
for depth; lift cards a tonal step on hover.
- Keep buttons and inputs rectilinear at 8px — Graphite is not
pill-driven.
- Use hairline `#1f1f1f` borders, stepping to `#2e2e2e` on
hover/emphasis, instead of card shadows.
- Render code, diffs, and file paths in the mono stack to signal the
product's domain without illustration.
- Honour `prefers-reduced-motion` — switch all transforms to
opacity-only.
### Don't
- Use pure `#000` for the canvas or `#ffffff` for body — both are off
by design (`#070707`, `#fafafa`).
- Make the blue a default CTA fill. The primary action is dark
`#262626`; the blue is punctuation.
- Round CTAs to full pills (9999). That's Linear's move — Graphite
keeps action buttons at 8px.
- Introduce a second saturated accent. The chromatic budget is one
blue plus the semantic four.
- Add drop shadows on cards. Use tonal layering and hairline borders.
- Soften the dark canvas for marketing — the product is dark, the site
is dark.
- Set headlines at weight `700`. The system's voice is `500`.
- Treat the `Cursor Cloud Agents` banner or the skip-to-content link
as design tokens — the live audit flagged both as noise, not CTAs.
- Centre H1s — Graphite's headlines are left-aligned.
- Let the page stretch past 1280, or reading copy past ~720px.
## 15. Agent Prompt Guide
### Quick Color Reference
```
bg: #070707
bg-level-1: #0f0f0f
bg-level-2: #171717
text: #fafafa
text-muted: #a3a3a3
brand: #3b82f6
accent: #60a5fa
link: #60a5fa
border: #1f1f1f
cta-fill: #262626
cta-text: #fafafa
success: #22c55e
danger: #ef4444
```
### Example Component Prompts
1. **Hero**: "Create a hero section on `#070707` background with a
left-aligned 60px Matter headline at weight 500 and `-0.022em`
tracking, subhead at 18px/400 in `#fafafa`, reading copy capped at
720px, with a single primary CTA: a dark `#262626` button, 8px
radius, `#fafafa` text reading 'Get started'."
2. **Card**: "Design a feature card with `#0f0f0f` background, 1px
`#1f1f1f` border, 12px radius, 24px padding, no shadow. Title at
20px Matter 600, body at 16px/400 in `#d4d4d4`. On hover, transition
the border to `#2e2e2e` and bg to `#171717` over 240ms."
3. **Primary CTA**: "Create a dark primary button: 8px radius, `#262626`
background, `#fafafa` text at 14px Matter weight 500, padding
`10px 16px`, height 40. Hover: bg `#2e2e2e`; no transform. Focus:
`0 0 0 3px rgba(59,130,246,0.32)` ring with 2px offset."
4. **Status pill**: "Render a status pill with pill radius (9999),
`rgba(59,130,246,0.12)` background, `rgba(59,130,246,0.22)` border,
`#60a5fa` text at 12px Matter 500, 2px × 10px padding. Vary the
colour to map to merged (success `#22c55e`) / approved (brand
`#3b82f6`) / failing (danger `#ef4444`)."
5. **Sticky nav**: "Make a 64px-tall sticky nav with `rgba(7,7,7,0.72)`
background, `backdrop-filter: blur(12px) saturate(180%)`, 1px bottom
border `#1f1f1f`. Logo left, nav links centre, dark `#262626` 8px
'Log in' CTA right; on scroll the border edge stays — no shadow."
6. **Input**: "Build a text input with `#0f0f0f` background, 1px
`#1f1f1f` border, 8px radius, 40px height, `8px 12px` padding, 14px
Matter 400 text in `#fafafa`, placeholder `#737373`. On focus,
border `#3b82f6` plus a `0 0 0 3px rgba(59,130,246,0.32)` ring."
### Iteration Guide
1. **Near-black, not pure black.** If your `bg` reads as `#000`,
soften to `#070707` (lab `2.75`). The hair of warmth keeps Matter
from crunching.
2. **The CTA is dark, not blue.** If your primary action is
brand-coloured, you've missed the central move. Make it dark
neutral `#262626` at 8px; the blue goes on links, focus, and the
rare brand button only.
3. **8px, not pill.** If the CTAs are full pills, you've drifted toward
Linear. Graphite's action buttons are rectilinear at 8px — IDE
controls, not marketing pills.
4. **Matter at 500.** Headlines are weight `500`, not `700`. If the
type feels heavy, drop the weight before adjusting size; firmness,
not boldness, is the voice.
5. **One blue.** If a second saturated accent has crept in, remove it.
The chromatic budget is one blue plus the semantic four — nothing
else competes.
6. **No card shadows.** If a card needs depth, lift its bg one tonal
step (`#0f0f0f → #171717`) and tighten its border. Shadows belong to
floating UI only.
7. **Ink stays `#fafafa`.** Pure `#ffffff` body copy looks harsh on the
near-black ground; reserve it for display-only max-contrast.
8. **Reduced motion always.** Honour `prefers-reduced-motion` on every
transition. Graphite's motion is restrained even at full — reduced
should feel nearly identical.
1. Visual Theme & Atmosphere
Graphite is a code-review tool dressed as the editor its users already
trust. The marketing site is rendered on a near-black #070707 canvas
(lab 2.75, a hair off pure #000 to keep type from crunching) with
near-white #fafafa ink, the Matter typeface set tight, and a single
clean blue #3b82f6 held in reserve. The atmosphere is the IDE at
night: nothing decorative, no gradient orbs, no marketing glow — just
the product shown in its own native chrome. If you build software for
a living, the page reads as familiar before you’ve parsed a word.
What separates it from softer dev-tool sites is conviction about the
canvas. Most tools lighten their dark themes for marketing — bigger
margins, lifted text, friendly illustration. Graphite refuses. The
near-black holds across the whole page; section breaks are tonal
lifts (#0f0f0f, #171717), not new colours. The hero is a 60px
Matter headline at weight 500 — firm but not bold — over a single
line of supporting copy and one dark CTA. The screenshot of the
review surface does the persuading.
The chromatic budget is deliberately one blue. #3b82f6 carries
links, focus rings, the active state of a tab, and the rare
brand-coded button — and that’s the whole accent story. Because the
dominant CTAs are dark neutral #262626 at an 8px radius (observed
live), the blue never competes with itself. One eye-anchor per
screen, one accent in the system. The restraint is the brand: it
signals a tool made by engineers who distrust ornament.
The register is developer-technical — Linear-adjacent. Copy is declarative and present-tense; geometry is rectilinear at 8px, not pill; depth is carried by tone and hairline borders, not shadows. The mood is a workstation that respects your attention: dense where it counts, quiet everywhere else.
Key Characteristics
- Near-black
#070707ground (lab2.75, warm-leaning, never#000) - Near-white
#fafafaink (lab98.26), never pure#fffffffor body - Matter typeface (
matterFont) — hero at 60px / weight500, tight tracking - One clean blue
#3b82f6— links, focus, rare emphasis; never the default CTA - Dark-neutral CTAs
#262626at 8px radius (the live-observed signature) - 8px is the working radius — rectilinear, not pill (contrast with Linear)
- Tonal layering for depth (
#070707→#0f0f0f→#171717→#1f1f1f) - No drop shadows on cards; hairline borders + tonal lift do the work
- Single eye-anchor per screen; the product screenshot is the hero
- Marketing surface ships dark-first — no light variant on the website
2. Color Palette & Roles
Canvas (Primary)
- bg
#070707— page canvas, near-black (lab2.75), the whole site lives here - bg-level-1
#0f0f0f— first elevation: cards, panels, section lifts - bg-level-2
#171717— second elevation: hover, banner strips, emphasized blocks - bg-level-3
#1f1f1f— third tier: popovers, tooltips, raised menus - bg-overlay
rgba(7,7,7,0.72)— modal scrim over the canvas
Text
- text
#fafafa— body copy and headlines (lab98.26), default ink - text-strong
#ffffff— display / max-contrast moments only - text-secondary
#d4d4d4— supporting copy, sub-headers - text-tertiary
#a3a3a3— captions, metadata, helper lines - text-quaternary
#737373— placeholders, faint helpers - text-disabled
#525252— disabled labels
Brand
- brand
#3b82f6— Graphite blue: links, focus, active tab, rare emphasis - brand-hover
#60a5fa— hover / active glow, brighter step - brand-press
#2f6fed— pressed state on branded controls - brand-soft
rgba(59,130,246,0.16)— tinted callout backdrop - accent
#60a5fa— brighter blue used for active glow and links - link
#60a5fa— link copy on dark; link-hover#93c5fd
CTA (the live signature)
- cta-fill
#262626— dark-neutral primary button (observed live, 8px radius) - cta-fill-hover
#2e2e2e— hover lift - cta-fill-press
#1f1f1f— pressed - cta-text
#fafafa— ink on the dark CTA
Borders
- border
#1f1f1f— default 1px hairline - border-strong
#2e2e2e— emphasized rule / hover border - border-subtle
rgba(255,255,255,0.06)— barely-visible separators - border-brand
#3b82f6— active input outline
Surface
- surface
#0f0f0f— default card - surface-strong
#171717— emphasized panel - surface-tinted-brand
rgba(59,130,246,0.08)— brand-coded callout wash
Shadow
Shadows are almost never used on cards. When they appear (popovers, modals), they are pure-neutral black, multi-layer:
- shadow-popover
0 8px 24px rgba(0,0,0,0.5) - shadow-modal
0 24px 48px rgba(0,0,0,0.6) - shadow-ambient
0 1px 2px rgba(0,0,0,0.5)— subtle sticky-header lift
Semantic
- success
#22c55e+ success-bgrgba(34,197,94,0.12)— merged / approved - warning
#f59e0b+ warning-bgrgba(245,158,11,0.12)— pending / stale - danger
#ef4444+ danger-bgrgba(239,68,68,0.12)— failing / blocked - info
#3b82f6+ info-bgrgba(59,130,246,0.12)— uses the brand blue
Status pills follow one pattern: tinted bg + tinted border (~22% alpha)
- tinted text at full saturation.
3. Typography Rules
Font Family
- Primary (display + body):
matterFont— the Matter typeface (Displaay Type Foundry), a geometric grotesque, with"Matter",system-ui,-apple-system,sans-seriffallback chain - Mono:
ui-monospace,SFMono-Regular,"SF Mono",Menlo,monospace— for inline code, diffs, and code blocks - Live-observed: hero h1 renders at 60px / weight 500, body at
16px / weight 400 — both in
matterFont. The headline weight is500(firm, not bold), which is the system’s whole voice.
Hierarchy
| Role | Font | Size | Weight | Line Height | Tracking | Notes |
|---|---|---|---|---|---|---|
| display-hero | Matter | 72 | 500 | 1.0 | -0.03em | Largest landing splash |
| display-lg | Matter | 60 | 500 | 1.05 | -0.025em | Section heroes |
| h1 | Matter | 60 | 500 | 1.05 | -0.022em | Page title (live: 60/500) |
| h2 | Matter | 40 | 500 | 1.1 | -0.018em | Major sections |
| h3 | Matter | 28 | 500 | 1.2 | -0.012em | Sub-sections |
| h4 | Matter | 20 | 600 | 1.3 | -0.005em | Card titles |
| eyebrow | Matter | 13 | 500 | 1.4 | 0.04em uppercase | Section markers |
| body-lg | Matter | 18 | 400 | 1.55 | 0 | Hero subhead |
| body | Matter | 16 | 400 | 1.55 | 0 | Default body (live: 16/400) |
| body-emphasis | Matter | 16 | 500 | 1.55 | 0 | Inline emphasis |
| body-sm | Matter | 14 | 400 | 1.5 | 0 | Footnotes, dense copy |
| label | Matter | 13 | 500 | 1.4 | 0 | Form labels |
| caption | Matter | 12 | 500 | 1.4 | 0.02em | Metadata |
| code-inline | Mono | 14 | 400 | 1.5 | 0 | Inline code |
| code-block | Mono | 13 | 400 | 1.6 | 0 | Diffs, code blocks |
| button | Matter | 14 | 500 | 1 | 0 | Default button |
| button-large | Matter | 16 | 500 | 1 | 0 | Hero CTA |
Principles
- Weight 500 is the headline voice. The hero renders at
500, not700. Hierarchy is carried by size and tight tracking, not bold —700is reserved for the rare wordmark or code emphasis. - Tracking tightens with size. The 60px h1 sits near
-0.022em; the 72px hero tightens to-0.03em. Display type must feel engineered, not bloated. Body stays at0. - Matter is the brand vocabulary. The geometric grotesque reads as
technical and modern without GitHub-mono or Inter-default fatigue.
Treat
matterFontas load-bearing; thesystem-uifallback is a graceful but visible downgrade. - Mono is for the diff. Code, file paths, and review snippets use the mono stack. It signals the product’s domain on a marketing page without illustration.
- Body never goes pure white.
#fafafa(lab98.26) is the ink;#ffffffis held for display-only max-contrast moments. - Reading width caps at ~720px even when the page is 1280. Long copy is always constrained inside the wider frame.
4. Component Stylings
Buttons (4 variants)
Primary (the live signature — dark neutral)
- Background:
#262626 - Text:
#fafafaat 14/500 - Padding:
10px 16px, Height: 40 - Radius: 8 (md) — observed live on the Log-in CTA
- Border: none
- Hover: bg
#2e2e2e - Active: bg
#1f1f1f - Focus:
ring 2px #3b82f6 offset 2px - Use: log-in, get-started — the dominant action on most screens
Brand (rare)
- Background:
#3b82f6 - Text:
#ffffffat 14/500 - Radius: 8 (md)
- Hover: bg
#60a5fa - Use: only when the action must read as brand-coded — sign-up, beta enrolment. Most pages use the dark primary instead.
Ghost
- Background: transparent
- Text:
#d4d4d4at 14/500 - Border:
1px solid #1f1f1f - Radius: 8 (md)
- Hover: bg
rgba(255,255,255,0.05); text#fafafa; border#2e2e2e - Use: secondary nav, “Read the docs”
Icon
- Background: transparent →
#171717on hover - Text:
#a3a3a3→#fafafaon hover - Size: 32 × 32, Radius: 8 (md)
- Use: header utilities — search, theme toggle, account
Cards (2 variants)
Standard card
- Background:
#0f0f0f, Border:1px solid #1f1f1f, Radius: 12 (lg) - Padding: 24, Shadow: none
- Hover: border
#2e2e2e, bg#171717 - Use: feature blocks, doc cards
Hero card
- Background:
#0f0f0f, Border:1px solid #1f1f1f, Radius: 16 (xl) - Padding: 48
- Use: product-screenshot frames, feature splits
Inputs / Forms
Text input
- Background:
#0f0f0f, Border:1px solid #1f1f1f, Radius: 8 (md) - Height: 40, Padding:
8px 12px - Font:
14px Matter 400 - Placeholder:
#737373 - Focus: border
#3b82f6; ringrgba(59,130,246,0.32) 0 0 0 3px - Disabled: bg
#070707, text#525252
Select — same shell as input + a chevron icon at 12px in #a3a3a3;
the popover follows tooltip styling.
Checkbox / Radio — 16 × 16, 1px solid #2e2e2e, 4px radius
(checkbox) or 9999 (radio); checked fill is brand #3b82f6.
Badges, Tags, Pills
Status pill — pill radius, tinted bg + tinted border at ~22% alpha
- tinted text at full saturation. Maps to review states: merged
(success
#22c55e), approved (brand#3b82f6), changes-requested (warning#f59e0b), failing (danger#ef4444).
Tag — neutral variant: #171717 bg, #2e2e2e border, #d4d4d4
text. Used for repo / category labels.
Navigation
Top nav: 64px tall, rgba(7,7,7,0.72) bg with backdrop-filter: blur(12px) saturate(180%), 1px bottom border #1f1f1f. Sticky on
scroll — no shadow added, just the border edge. (Note: the live audit
also caught a Cursor Cloud Agents banner strip at #171717 — that
is announcement noise, not part of the nav system.)
Footer: dark with low-contrast #737373 text on #070707; 1px
top border #1f1f1f.
Side nav (docs): tonal column at bg-level-1 with #1f1f1f rule
on the right; active item gets bg-level-2 + 2px brand left border.
Tooltips & Popovers
Tooltip: #1f1f1f bg, #2e2e2e border, 8 radius, 12px Matter 500
text, 6 × 10 padding. Shadow 0 8px 24px rgba(0,0,0,0.5).
Popover (menu, combobox): #1f1f1f bg with the same border and shadow,
8 radius, max-width 320, list items use 6/8 padding.
Modals
Centered overlay on rgba(7,7,7,0.72) scrim with backdrop blur.
Dialog box at #171717, 12 radius, 24 padding, 1px #2e2e2e border,
shadow 0 24px 48px rgba(0,0,0,0.6). Title at h3 500, body 16/400,
action row pinned to the footer with the primary CTA on the right.
5. Layout Principles
Spacing System
- Base unit: 4px
- Scale:
[0, 4, 8, 12, 16, 24, 32, 48, 64, 96] - Small steps (4, 8) handle in-component spacing; big jumps (64, 96) handle section rhythm. Density is product-grade: 8px between form rows, 4px between an icon and its label, 16–24px between cards.
- The marketing page inherits the product’s tight interior spacing while keeping generous section gutters.
Grid & Container
- Page width: 1280px max
- Prose width: 720px — multi-paragraph copy is capped here within the 1280 frame
- Gutter: 24px
- Grid: 12 columns on tablet+, single column on mobile
- Hero: full-bleed near-black bg + centred 1280 content; the product screenshot lives inside its own hero card, not full-bleed
- Feature grid: asymmetric splits (copy vs. screenshot) when one side deserves visual primacy
Whitespace Philosophy
Graphite is dense by product DNA but generous on marketing rhythm. Sections breathe at ~96px vertical gutters; within sections the density tightens to product values (8–24px). Macro-relaxed, micro-tight — the same tempo the IDE uses.
Section Cadence
The site stays on #070707 throughout. Section breaks are tonal —
bg-level-1 panels stand against the canvas rather than introducing
new colours. The exception is the occasional bg-level-2 band
(customer quote, announcement strip) that lifts for one viewport and
returns to canvas.
6. Shapes & Radius Scale
| Tier | px | Use |
|---|---|---|
| Micro | 2 | Decorative corners, inline accents |
| Standard (sm) | 4 | Tags, micro-pills, checkboxes |
| Comfortable (md) | 8 | Buttons, inputs, icon buttons — the working radius |
| Relaxed (lg) | 12 | Cards, panel containers, modals |
| Featured (xl) | 16 | Hero cards, product-screenshot frames |
| Pill | 9999 | Status pills, avatar mode only |
The 8px (md) corner is the system’s signature — confirmed live on the primary CTA. Graphite is rectilinear, not pill-driven: where Linear rounds CTAs to full pills, Graphite keeps them at 8px, which reads more like an IDE control. The pill (9999) is reserved for status indicators and avatars, never the action buttons.
There is essentially no 0px-radius element except 1px hairline
section rules. Compound radii appear only in modal headers (12 12 0 0
to lock to the body) and pinned tab strips (8 8 0 0).
7. Depth & Elevation
| Level | Treatment | Use |
|---|---|---|
| 0 | flat — #070707 only | page canvas |
| 1 | #0f0f0f + 1px #1f1f1f border | cards, panels |
| 2 | #171717 + 1px #2e2e2e border | hover, banners, emphasized |
| 3 | #1f1f1f + ambient shadow 0 1px 2px rgba(0,0,0,0.5) | sticky header |
| 4 | #1f1f1f + popover shadow 0 8px 24px rgba(0,0,0,0.5) | tooltips, menus, popovers |
| 5 | #171717 + modal shadow 0 24px 48px rgba(0,0,0,0.6) + scrim | modals, dialogs |
Shadow Philosophy
Graphite uses tonal stacking as its default depth language. Each
elevation step lifts lightness a few points — barely perceptible
alone, readable as a stack. Borders pick up where tone is too subtle:
#1f1f1f → #2e2e2e is the two-step border ladder.
Drop shadows are floating UI only: popovers, tooltips, modals, toasts. Cards never carry shadows; the hairline border plus the tonal lift do all the work. Shadows are pure-neutral black (no tint), multi-layer when deep. The result reads as solid surfaces on a solid ground, not floating glass.
8. Interaction & Motion
Easing curves
- ease-standard:
cubic-bezier(0.4, 0, 0.2, 1)— default for hover and state transitions - ease-emphasized:
cubic-bezier(0.2, 0, 0, 1)— page enters, modal slide-in - ease-out:
cubic-bezier(0, 0, 0.2, 1)— settling motions
Duration buckets
- fast: 150ms — button hover, focus ring, state changes
- standard: 240ms — card hover, popover open
- slow: 320ms — modal enter, scroll-fade
Per-component micro-states
- Button hover: bg lift (
#262626 → #2e2e2e) over 150ms ease-out; no transform — the dark CTA stays planted - Button active: bg press to
#1f1f1fover 150ms - Card hover: border transition
#1f1f1f → #2e2e2e+ bg lift#0f0f0f → #171717over 240ms ease-standard; no transform - Link hover: colour shift
#60a5fa → #93c5fdonly, 150ms; no underline grow - Popover open: opacity 0 → 1 + scale 0.98 → 1 over 240ms ease-emphasized
- Modal enter: scrim fade 320ms + dialog slide from
translateY(8px)to 0 over 320ms ease-emphasized
Page transitions
Marketing page changes are full opacity 0 → 1 over 200ms — no slide.
Scroll-fade for in-view content uses opacity + 8px translateY → 0
over 320ms.
Reduced motion
Respects prefers-reduced-motion: reduce. All transforms disabled,
all transitions reduced to opacity-only at the same durations. The
sticky-header backdrop blur stays on (it is not motion).
9. Accessibility & A11y
Contrast pairs (computed from live tokens)
- #fafafa on #070707 (text on bg): 19.3 — AAA at all sizes
- #d4d4d4 on #070707 (secondary on bg): 13.6 — AAA
- #a3a3a3 on #070707 (tertiary on bg): 8.0 — AAA at body sizes
- #737373 on #070707 (quaternary on bg): 4.2 — AA Large only; use for non-essential helpers
- #fafafa on #262626 (CTA text on dark fill): 14.5 — AAA
- #3b82f6 on #070707 (brand on bg): 5.5 — AA for text and icons
- #60a5fa on #070707 (link on bg): 7.9 — AAA
- #ffffff on #3b82f6 (text on brand button): 3.7 — AA Large / UI-component contrast only; keep brand-button label at 14px+ 500
Focus indicators
Every interactive element ships a focus ring: 3px solid rgba(59,130,246,0.32) with 2px offset on the dark canvas — box-shadow
ring, not outline, so it composites cleanly over borders. Inputs get
the solid #3b82f6 border on focus plus the ring.
ARIA patterns
- Combobox (search):
role=combobox+aria-expanded+aria-controls+aria-activedescendant - Dialog:
role=dialog+aria-modal=true+aria-labelledbypointing to the title node - Status pills:
aria-live=politefor in-page state changes; state included in the accessible name (e.g.,aria-label="Status: merged")
Keyboard nav
A skip-to-content link appears on first Tab focus (confirmed live). Tab order: skip link → header logo → nav links → header CTA → hero CTA → in-page sections → footer. All buttons and links are keyboard reachable; focus is always visible.
Screen reader hints
- Icon-only buttons carry
aria-label(e.g.,aria-label="Search") - Decorative icons get
aria-hidden=true - Diff and code regions use
role=regionwith a descriptive label
Reduced motion
Honoured globally; see §8. Auto-playing demo loops respect the same query and freeze on the first frame.
10. Responsive Behavior
| Breakpoint | px | Layout |
|---|---|---|
| mobile | < 640 | single-column, 16px gutter, h1 → 36px |
| tablet | 640–1023 | 2-column on splits, 20px gutter, h1 → 44px |
| desktop | 1024–1279 | full 12-col grid, h1 → 56px |
| wide | ≥ 1280 | page caps at 1280, h1 at 60px — refuses to over-stretch |
Touch targets
Minimum 44 × 44 on mobile (buttons grow vertical padding from 10 to 12; icon buttons grow to 40 × 40). All keep the 8px radius — fingerprint matches desktop.
Collapsing strategy
- Header collapses to a hamburger at ≤ 768
- Feature grids switch from asymmetric splits to single-column stacks at ≤ 768
- Comparison tables become card lists at ≤ 640
- Sticky docs sidebar becomes a top sheet on mobile
Image behavior
Product screenshots use aspect-ratio: 16 / 10 and object-fit: cover
with loading=lazy. SVG illustrations are inline and respect
currentColor. Screenshot corners match their parent hero card (16px),
no radius mismatch.
Container queries
Used in hero-card variants where the screenshot frame switches from landscape to portrait based on container width below ~480px.
11. Content & Voice
Tone
Direct, technical, present-tense. Graphite writes like an engineer leaving review comments: declarative, specific, allergic to hype. The title itself sets the register — “Code review for the age of AI.” Sentences are short; metaphors are rare and mechanical when used.
Microcopy patterns
- Button verbs: “Log in”, “Get started”, “Read the docs”, “Start reviewing” — short, imperative, present-tense. Never “Click here” or “Learn more about our…”.
- Errors: format
<noun> couldn't be <verbed>. <one-sentence reason>.Example: “Review couldn’t be submitted. You’re offline.” - Success confirmations: terse, no exclamation marks. Example: “Branch merged.”
- Progress:
Syncing…rather thanPlease wait…
Empty states
Empty review queues show a short headline (e.g., “No open reviews”), one line of orientation, and a single CTA. No illustration, no upbeat encouragement.
CTA verb conventions
Observed verb ladder, by frequency:
- Get started — top-of-page hero CTA
- Log in — utility nav (the live-sampled dark CTA)
- Read the docs — developer-facing pages
- Book a demo — enterprise surfaces
Graphite avoids “Sign up free” / “Free trial” in the verb — the free-tier fact lives in copy below the CTA, not in the button label.
12. Dark Mode & Theming
Graphite is dark-first by design. The marketing site ships near-black only — the dark canvas is the brand identity, the same surface the review product runs on. Inverting it would break recognition with the engineering audience it targets.
If a downstream system needs to derive a light variant from these tokens (e.g., for a light-mode docs portal):
colors-light:
bg: '#ffffff'
bg-level-1: '#fafafa'
bg-level-2: '#f4f4f5'
text: '#070707'
text-secondary: '#404040'
text-tertiary: '#737373'
brand: '#2563eb' # darken the blue for white-bg contrast
border: '#e5e5e5'
cta-fill: '#171717' # dark CTA stays dark, near-black on white
cta-text: '#fafafa'
But Graphite’s own marketing surface stays near-black. This is intentional.
13. Lineage & Influences
Graphite’s marketing surface is engineered as a continuation of the
review product, not a separate brand layer. The lineage runs through
three strands: dark-canvas dev-tool design (Linear, Vercel), the
code-review and diff conventions of GitHub that Graphite reframes “for
the age of AI,” and the Bay-Area discipline of a single restrained
accent over a near-black ground. What it inherits is the refusal to
soften the canvas for marketing — to treat the website as a view into
the tool. What it adds is the specific Matter type voice (60px / weight
500) and the dark-neutral 8px CTA, which reads as an IDE control
rather than a marketing pill.
What it rejects: Stripe-class chromatic gradients, glassy chrome, and playful illustration. The system has no mascot, no gradient mark, no decorative element. Where Linear pills its CTAs, Graphite keeps them rectilinear at 8px; where most tools spend a second accent colour, Graphite spends exactly one blue. The blue is punctuation, never the page.
Influences:
- Linear — Dark-canvas product-as-marketing discipline and the single-accent restraint Graphite mirrors (linear.app)
- Vercel — Near-black dev-tool surface and the Geist-family sans typography lineage that sets the register (vercel.com)
- GitHub — The code-review and diff surface conventions Graphite reframes for AI-assisted review (github.com)
- Tailwind CSS palette — The blue-500/600 accent and neutral tiers this system samples (tailwindcss.com)
- Matter (Displaay Type Foundry) — The geometric grotesque set tight at the 60px/500 hero; Graphite’s type voice (displaay.net)
14. Do’s and Don’ts
Do
- Use the near-black
#070707ground across the whole surface — let section breaks be tonal lifts, not new colours. - Keep
#fafafaas body ink; reserve pure#fffffffor display-only max-contrast moments. - Set headlines in Matter at weight
500— firm, not bold. Carry hierarchy with size and tracking. - Tighten tracking as type scales up (
-0.022emat 60px), keep body at0. - Make the dominant CTA dark-neutral
#262626at 8px radius — the live-observed signature. - Treat the blue
#3b82f6as accent-only: links, focus, the rare brand-coded button — one accent in the system. - Use tonal layering (
#070707→#0f0f0f→#171717→#1f1f1f) for depth; lift cards a tonal step on hover. - Keep buttons and inputs rectilinear at 8px — Graphite is not pill-driven.
- Use hairline
#1f1f1fborders, stepping to#2e2e2eon hover/emphasis, instead of card shadows. - Render code, diffs, and file paths in the mono stack to signal the product’s domain without illustration.
- Honour
prefers-reduced-motion— switch all transforms to opacity-only.
Don’t
- Use pure
#000for the canvas or#fffffffor body — both are off by design (#070707,#fafafa). - Make the blue a default CTA fill. The primary action is dark
#262626; the blue is punctuation. - Round CTAs to full pills (9999). That’s Linear’s move — Graphite keeps action buttons at 8px.
- Introduce a second saturated accent. The chromatic budget is one blue plus the semantic four.
- Add drop shadows on cards. Use tonal layering and hairline borders.
- Soften the dark canvas for marketing — the product is dark, the site is dark.
- Set headlines at weight
700. The system’s voice is500. - Treat the
Cursor Cloud Agentsbanner or the skip-to-content link as design tokens — the live audit flagged both as noise, not CTAs. - Centre H1s — Graphite’s headlines are left-aligned.
- Let the page stretch past 1280, or reading copy past ~720px.
15. Agent Prompt Guide
Quick Color Reference
bg: #070707
bg-level-1: #0f0f0f
bg-level-2: #171717
text: #fafafa
text-muted: #a3a3a3
brand: #3b82f6
accent: #60a5fa
link: #60a5fa
border: #1f1f1f
cta-fill: #262626
cta-text: #fafafa
success: #22c55e
danger: #ef4444
Example Component Prompts
-
Hero: “Create a hero section on
#070707background with a left-aligned 60px Matter headline at weight 500 and-0.022emtracking, subhead at 18px/400 in#fafafa, reading copy capped at 720px, with a single primary CTA: a dark#262626button, 8px radius,#fafafatext reading ‘Get started’.” -
Card: “Design a feature card with
#0f0f0fbackground, 1px#1f1f1fborder, 12px radius, 24px padding, no shadow. Title at 20px Matter 600, body at 16px/400 in#d4d4d4. On hover, transition the border to#2e2e2eand bg to#171717over 240ms.” -
Primary CTA: “Create a dark primary button: 8px radius,
#262626background,#fafafatext at 14px Matter weight 500, padding10px 16px, height 40. Hover: bg#2e2e2e; no transform. Focus:0 0 0 3px rgba(59,130,246,0.32)ring with 2px offset.” -
Status pill: “Render a status pill with pill radius (9999),
rgba(59,130,246,0.12)background,rgba(59,130,246,0.22)border,#60a5fatext at 12px Matter 500, 2px × 10px padding. Vary the colour to map to merged (success#22c55e) / approved (brand#3b82f6) / failing (danger#ef4444).” -
Sticky nav: “Make a 64px-tall sticky nav with
rgba(7,7,7,0.72)background,backdrop-filter: blur(12px) saturate(180%), 1px bottom border#1f1f1f. Logo left, nav links centre, dark#2626268px ‘Log in’ CTA right; on scroll the border edge stays — no shadow.” -
Input: “Build a text input with
#0f0f0fbackground, 1px#1f1f1fborder, 8px radius, 40px height,8px 12pxpadding, 14px Matter 400 text in#fafafa, placeholder#737373. On focus, border#3b82f6plus a0 0 0 3px rgba(59,130,246,0.32)ring.”
Iteration Guide
- Near-black, not pure black. If your
bgreads as#000, soften to#070707(lab2.75). The hair of warmth keeps Matter from crunching. - The CTA is dark, not blue. If your primary action is
brand-coloured, you’ve missed the central move. Make it dark
neutral
#262626at 8px; the blue goes on links, focus, and the rare brand button only. - 8px, not pill. If the CTAs are full pills, you’ve drifted toward Linear. Graphite’s action buttons are rectilinear at 8px — IDE controls, not marketing pills.
- Matter at 500. Headlines are weight
500, not700. If the type feels heavy, drop the weight before adjusting size; firmness, not boldness, is the voice. - One blue. If a second saturated accent has crept in, remove it. The chromatic budget is one blue plus the semantic four — nothing else competes.
- No card shadows. If a card needs depth, lift its bg one tonal
step (
#0f0f0f → #171717) and tighten its border. Shadows belong to floating UI only. - Ink stays
#fafafa. Pure#ffffffbody copy looks harsh on the near-black ground; reserve it for display-only max-contrast. - Reduced motion always. Honour
prefers-reduced-motionon every transition. Graphite’s motion is restrained even at full — reduced should feel nearly identical.
Drop graphite-dev into your project, then ship the actual sections in an afternoon.
npx @webdesignhot/design-md add graphite-dev npx agentkit init --design graphite-dev