Sable Hairline.
Precise dark surface with a faint 32px hairline grid baked into the canvas. Geist-class sans, JetBrains Mono, one desaturated violet accent. The primary CTA carries a 1px violet underline as its only chromatic mark.
The kitchen sink.
Build with Sable Hairline.
A complete design system, ready for your AI coding agent. Every primitive, token, and pattern below is generated straight from DESIGN.md — drop the file in your project and ship matching UI in minutes.
Palette
Type scale
Buttons
Form controls
Select & toggle
Labeling
Cards
Prose-first token file — decisions live next to their reasoning.
Tabs & breadcrumb
Spacing scale
Fine micro-scale (1–5px) for pills, editorial scale (12–21px) for the grid.
Border radius scale
The system's own radius tokens — sm for chips and inputs, md for buttons, lg for cards, pill for fully-rounded CTAs.
Depth & elevation
Charts
The states behind the resting style.
Tokens describe the resting state. A real product needs every interaction state. Hover, focus, active, disabled, loading — all derived from the system's resting tokens.
Button
Input
Card
Tab
DESIGN.md
1---2name: "Sable Hairline"3description: "Precise dark surface with a faint 32px hairline grid baked into the canvas. Geist-class sans, JetBrains Mono, one desaturated violet accent. The primary CTA carries a 1px violet underline as its only chromatic mark."4tags: [dark, "dev-tool", minimal, precise, hairline]5colors:6 primary: "#9D8CFF"7 secondary: "#E6E5E3"8 tertiary: "#7A7A82"9 neutral: "#0A0A0B"10 surface: "#131316"11typography:12 display: "Inter Tight"13 body: Inter14 mono: "JetBrains Mono"15 scale:16 hero: "3.75rem / 1.04 / 600 / -0.04em"17 h1: "2.25rem / 1.12 / 600 / -0.032em"18 h2: "1.375rem / 1.3 / 600 / -0.018em"19 body: "0.9375rem / 1.65 / 400 / -0.005em"20radius:21 sm: 4px22 md: 6px23 lg: 8px24 pill: 9999px25shadows:26 card: "0 0 0 1px rgba(255, 255, 255, 0.06)"27 button: "0 0 0 1px rgba(157, 140, 255, 0.35)"28borders:29 card: "1px solid rgba(255, 255, 255, 0.07)"30 divider: "rgba(255, 255, 255, 0.07)"31glass:32 surface: "#131316"33 blur: 0px34 border: "1px solid rgba(255, 255, 255, 0.07)"35 shadow: none36 backdrop: "linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px) 0 0 / 32px 32px, linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px) 0 0 / 32px 32px, #0A0A0B"37buttons:38 primary:39 background: #1B1B2040 color: #F4F3F041 border: 1px solid rgba(255, 255, 255, 0.10)42 shape: rounded43 padding: 10px 18px44 font: 500 / 0.875rem / -0.005em45 shadow: inset 0 -1px 0 0 #9D8CFF46 secondary:47 background: transparent48 color: #E6E5E349 border: 1px solid rgba(255, 255, 255, 0.10)50 shape: rounded51 padding: 10px 18px52 font: 500 / 0.875rem / -0.005em53 outline:54 background: transparent55 color: #9D8CFF56 border: 1px solid rgba(157, 140, 255, 0.35)57 shape: rounded58 padding: 10px 18px59 font: 500 / 0.875rem / -0.005em60 ghost:61 background: transparent62 color: #7A7A8263 border: none64 shape: rounded65 padding: 10px 6px66 font: mono / 400 / 0.8125rem / 067 hover: underline68charts:69 variant: line70 stroke_width: 1.571 gridlines: true72 highlight: last73 dot_marker: true74 axis_color: "#5A5A62"75 palette: ["#9D8CFF", "#7A7A82", "#3F3F46"]76fonts_url: "https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap"77dependencies: ["lucide-react"]78---79 80# Sable Hairline81 82## AI Build Instructions83 84> **Read this section before writing any code.** The rules below85> are non-negotiable. Every value used in the UI must come from this86> file's frontmatter — never substitute, approximate, or invent new87> colors, fonts, radii, or shadows. If a value is missing, ask the88> user before adding one.89 90### 1 · Your role91 92You are building UI for a project that has adopted **Sable Hairline** as its93design system. Treat `DESIGN.md` as the single source of truth.94Your job is to translate the user's product requirements into95components and pages that look like they were designed by the same96person who authored this file.97 98### 2 · Token compliance99 100- Pull every color, font family, radius, shadow, and spacing value101 from the frontmatter at the top of this file.102- Use semantic roles (e.g. `primary`, `accent`, `muted`) — never103 hard-code hex values that bypass the system.104- When a token can be expressed as a CSS variable, declare it once105 in your global stylesheet and reference it everywhere downstream.106- The Google Fonts `<link>` is provided in the Typography section.107 Add it to `<head>` before any component renders.108 109### 3 · Component recipes110 111Use these recipes verbatim when building the corresponding component.112 113#### Buttons114 115Four variants are defined. Pick one — never blend variants or invent a fifth.116 117- **Primary** — rounded shape, bg `#1B1B20`, text `#F4F3F0`, border `1px solid rgba(255, 255, 255, 0.10)`, padding `10px 18px`, weight `500`, shadow `inset 0 -1px 0 0 #9D8CFF`.118- **Secondary** — rounded shape, text `#E6E5E3`, border `1px solid rgba(255, 255, 255, 0.10)`, padding `10px 18px`, weight `500`.119- **Outline** — rounded shape, text `#9D8CFF`, border `1px solid rgba(157, 140, 255, 0.35)`, padding `10px 18px`, weight `500`.120- **Ghost** — rounded shape, text `#7A7A82`, padding `10px 6px`, weight `400`.121 122Reach for **primary** as the single dominant CTA per screen.123**Secondary** for the supporting action. **Outline** for tertiary124actions in toolbars. **Ghost** for inline links and table actions.125 126#### Cards127 128- Background: `#131316`129- Border: `1px solid rgba(255, 255, 255, 0.07)`130- Shadow: `0 0 0 1px rgba(255, 255, 255, 0.06)`131- Radius: `radius.lg` (`8px`)132- Internal padding: `20px` for compact cards, `24–28px` for content cards.133 134> This system ships a **glass treatment** — see the Glass token table.135> Apply `backdrop-filter: blur(0px)` to translucent panes.136> The page must have a backdrop (gradient mesh / blurred orbs) for glass to refract.137 138#### Charts139 140- Bar/line variant: `line`141- Highlight strategy: `last` — emphasize a single bar/point per chart.142- Use the declared palette in order: `#9D8CFF`, `#7A7A82`, `#3F3F46`.143 144#### Typography pairings145 146- **Display (`Inter Tight`)** — h1, h2, hero headlines, brand wordmarks.147- **Body (`Inter`)** — paragraphs, labels, button text, form inputs.148- **Mono (`JetBrains Mono`)** — code, eyebrows, metadata, numerals in tables.149 150### 4 · Hard constraints151 152Never do any of the following without explicit instruction from the user:153 154- Introduce a new color, font, radius, or shadow that isn't declared above.155- Mix this system with another (e.g. don't paste in Material or Bootstrap defaults).156- Use generic gradient defaults (purple→blue, peach→pink) — they break the system's voice.157- Reach for emoji icons. Use a consistent icon library and size icons in line with body type.158- Add motion that exceeds the system's restraint — keep transitions short (≤200ms) and subtle.159 160### 5 · Before you finish — verify161 162Run through this checklist for every screen you produce:163 164- [ ] Every color used appears in the Colors table above.165- [ ] Headlines use the display font; body copy uses the body font.166- [ ] Buttons match one of the declared variants exactly (shape, padding, weight).167- [ ] Border-radius values come from `radius.sm` / `radius.md` / `radius.lg` / `radius.pill`.168- [ ] Cards and dividers use the declared border + shadow tokens.169- [ ] No values were invented; if you needed something missing, you stopped and asked.170 171---172 173## Overview174Sable Hairline is a precise dark dev-tool surface. Near-black canvas (#0A0A0B) with a faint 32px hairline grid baked into the background — visible enough to register as engineered, quiet enough never to compete with content. One chromatic accent: a desaturated violet #9D8CFF, used only for active states and as a 1px bottom edge on the primary CTA.175 176For developer platforms, infra dashboards, observability tools, anything that needs to read as engineered without resorting to terminal nostalgia.177 178## The Hairline Grid179The grid is the signature. Two stacked 1px linear-gradients at 32px intervals, both at 2.5% white alpha:180 181```css182body {183 background:184 linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px) 0 0 / 32px 32px,185 linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px) 0 0 / 32px 32px,186 #0A0A0B;187}188```189 190Hold the alpha at 2.5%. At 4% the grid becomes graph paper; at 1% it disappears. The grid stays fixed during scroll on long pages.191 192## Color193- **Violet #9D8CFF** — the only chromatic mark. Active states, CTA accent line, chart line.194- **Bone #E6E5E3** — body text on near-black.195- **Graphite #7A7A82** — secondary text, axis labels, grid alpha at 7%.196- **Sable #0A0A0B** — page canvas, never pure #000.197- **Panel #131316** — lifted surface for cards.198 199## Typography200- **Display: Inter Tight 600** at 3.75rem with -4% tracking.201- **Body: Inter 400** at 0.9375rem with 1.65 leading.202- **Mono: JetBrains Mono 400** for ghost links and code — slightly smaller (0.8125rem).203 204| Role | Font | Size | Weight | Tracking |205|------|------|------|--------|----------|206| Hero | Inter Tight | 3.75rem | 600 | -0.04em |207| H1 | Inter Tight | 2.25rem | 600 | -0.032em |208| H2 | Inter Tight | 1.375rem | 600 | -0.018em |209| Body | Inter | 0.9375rem | 400 | -0.005em / 1.65 |210| Mono | JetBrains Mono | 0.8125rem | 400 | 0 |211 212## Geometry213- **Radii: 4 / 6 / 8.** Tight, precise — never soft. Pill exists only for status chips.214- **Section gap: 96px** desktop, 56px mobile.215- **12-column grid** with 24px gutters — aligns to the background grid module.216 217## Buttons218- **Primary** — flat panel surface with a 1px violet inset bottom edge. The single chromatic mark.219- **Secondary** — bare hairline panel.220- **Outline** — hairline in violet alpha, violet label.221- **Ghost** — JetBrains Mono in graphite, hover underline.222 223## Cards224Lifted panel #131316, 6px radius, 1px hairline at 7% white. No drop shadow — depth comes from the contrast between #0A0A0B canvas and #131316 panel only. Padding 24px minimum.225 226## Charts & Data2271.5px violet line on a faint hairline grid (already part of the canvas). One end-of-line dot marker in violet. Axis labels in graphite at 0.75rem. No fills, no curves — straight segments.228 229## Do's and Don'ts230- ✅ Hold the grid alpha at exactly 2.5% white.231- ✅ Violet is the only color outside the grayscale ramp.232- ✅ Tight radii throughout — the precision is the brand.233- ✅ Inter Tight for display; never substitute a softer geometric sans.234- ❌ No pure #000. Sable carries warmth.235- ❌ No second chromatic accent. The system stays single-hue.236- ❌ No drop shadows. Hairlines and surface contrast carry depth.237- ❌ No rounded corners above 8px outside the pill chip.238 239---240 241## Tokens242 243> Generated from the same source the live preview renders from.244> Treat the values below as the contract — never substitute approximations.245 246### Colors247 248| Role | Value |249|-----------|-------|250| primary | `#9D8CFF` |251| secondary | `#E6E5E3` |252| tertiary | `#7A7A82` |253| neutral | `#0A0A0B` |254| surface | `#131316` |255 256### Typography257 258- **Display:** Inter Tight259- **Body:** Inter260- **Mono:** JetBrains Mono261 262| Role | size / leading / weight / tracking |263|------|------------------------------------|264| Hero | 3.75rem / 1.04 / 600 / -0.04em |265| H1 | 2.25rem / 1.12 / 600 / -0.032em |266| H2 | 1.375rem / 1.3 / 600 / -0.018em |267| Body | 0.9375rem / 1.65 / 400 / -0.005em |268 269### Radius270 271- sm: `4px`272- md: `6px`273- lg: `8px`274- pill: `9999px`275 276### Shadows277 278- **card:** `0 0 0 1px rgba(255, 255, 255, 0.06)`279- **button:** `0 0 0 1px rgba(157, 140, 255, 0.35)`280 281### Borders282 283- **card:** `1px solid rgba(255, 255, 255, 0.07)`284- **divider:** `rgba(255, 255, 255, 0.07)`285 286### Glass287 288Translucent panes with backdrop-filter — the preview renders cards from these exact values.289 290| Property | Value |291|----------|-------|292| surface | `#131316` |293| blur | `0px` |294| border | `1px solid rgba(255, 255, 255, 0.07)` |295| shadow | `none` |296| backdrop | `linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px) 0 0 / 32px 32px, linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px) 0 0 / 32px 32px, #0A0A0B` |297 298### Buttons299 300Four variants, each fully tokenized. The preview renders from these exact values.301 302#### Primary303 304| Property | Value |305|----------|-------|306| shape | `rounded` |307| background | `#1B1B20` |308| color | `#F4F3F0` |309| border | `1px solid rgba(255, 255, 255, 0.10)` |310| padding | `10px 18px` |311| fontWeight | `500` |312| fontSize | `0.875rem` |313| tracking | `-0.005em` |314| shadow | `inset 0 -1px 0 0 #9D8CFF` |315 316#### Secondary317 318| Property | Value |319|----------|-------|320| shape | `rounded` |321| background | `transparent` |322| color | `#E6E5E3` |323| border | `1px solid rgba(255, 255, 255, 0.10)` |324| padding | `10px 18px` |325| fontWeight | `500` |326| fontSize | `0.875rem` |327| tracking | `-0.005em` |328 329#### Outline330 331| Property | Value |332|----------|-------|333| shape | `rounded` |334| background | `transparent` |335| color | `#9D8CFF` |336| border | `1px solid rgba(157, 140, 255, 0.35)` |337| padding | `10px 18px` |338| fontWeight | `500` |339| fontSize | `0.875rem` |340| tracking | `-0.005em` |341 342#### Ghost343 344| Property | Value |345|----------|-------|346| shape | `rounded` |347| background | `transparent` |348| color | `#7A7A82` |349| border | `none` |350| padding | `10px 6px` |351| fontFamily | `mono` |352| fontWeight | `400` |353| fontSize | `0.8125rem` |354| tracking | `0` |355| hoverHint | `underline` |356 357### Charts358 359| Property | Value |360|----------|-------|361| variant | `line` |362| strokeWidth | `1.5` |363| gridlines | `true` |364| highlight | `last` |365| dotMarker | `true` |366| axisColor | `#5A5A62` |367| palette | `#9D8CFF`, `#7A7A82`, `#3F3F46` |368 369---370 371## Pro tokens372 373> Production-fidelity tokens. States, density, motion, elevation,374> content rules and a measured WCAG contract — derived from the375> resting tokens unless explicitly authored.376 377### States378 379#### Button380 381- **hover** — shadow: `0 8px 24px -8px rgba(122, 122, 130, 0.35), inset 0 1px 0 rgba(255,255,255,0.18)`, transform: `translateY(-1px)`, filter: `saturate(1.15)`382- **focus** — outline: `2px solid rgba(122, 122, 130, 0.5)`, outline-offset: `3px`383- **active** — transform: `translateY(0) scale(0.98)`, filter: `brightness(0.96)`384- **disabled** — opacity: `0.4`, filter: `saturate(0.4) blur(0.4px)`385- **loading** — opacity: `0.7`386- **selected** — bg: `rgba(122, 122, 130, 0.18)`, color: `#7A7A82`387 388#### Input389 390- **hover** — border: `1px solid rgba(122, 122, 130, 0.4)`, shadow: `inset 0 1px 0 rgba(255,255,255,0.18)`391- **focus** — border: `1px solid rgba(122, 122, 130, 0.65)`, shadow: `0 0 0 4px rgba(122, 122, 130, 0.15), inset 0 1px 0 rgba(255,255,255,0.18)`392- **disabled** — opacity: `0.4`393- **error** — border: `1px solid rgba(248,113,113,0.7)`, shadow: `0 0 0 4px rgba(248,113,113,0.15)`394 395#### Card396 397- **hover** — shadow: `0 16px 48px -16px rgba(122, 122, 130, 0.25), inset 0 1px 0 rgba(255,255,255,0.18)`, transform: `translateY(-2px)`, filter: `saturate(1.1)`398- **selected** — border: `1px solid rgba(122, 122, 130, 0.5)`399- **dragging** — shadow: `0 24px 64px -16px rgba(0,0,0,0.4)`, transform: `scale(1.02)`, opacity: `0.85`400 401#### Tab402 403- **hover** — bg: `rgba(122, 122, 130, 0.08)`404- **focus** — outline: `2px solid rgba(122, 122, 130, 0.5)`, outline-offset: `2px`405- **selected** — bg: `rgba(122, 122, 130, 0.18)`, color: `#7A7A82`406 407### Density408 409| Mode | padding × | row × | body | radius × | Use for |410|------|-----------|-------|------|----------|---------|411| compact | 0.72 | 0.78 | 0.8125rem | 0.85 | Information-dense — tables, IDEs, dashboards |412| comfortable | 1 | 1 | 0.9375rem | — | Default — most product UI |413| spacious | 1.35 | 1.3 | 1rem | 1.15 | Editorial — marketing, long-form, settings |414 415### Motion416 417**Signature — Refract.** Long opacity- and blur-driven transitions. Not a hard move, but a shift of light across the glass surface.418 419```css420transition: opacity 350ms cubic-bezier(0.32, 0.72, 0, 1), backdrop-filter 350ms cubic-bezier(0.32, 0.72, 0, 1), transform 350ms cubic-bezier(0.32, 0.72, 0, 1);421```422 423| Token | Value |424|-------|-------|425| duration.instant | `100ms` |426| duration.fast | `200ms` |427| duration.base | `350ms` |428| duration.slow | `550ms` |429| easing.standard | `cubic-bezier(0.32, 0.72, 0, 1)` |430| easing.decelerate | `cubic-bezier(0.0, 0, 0.2, 1)` |431| easing.accelerate | `cubic-bezier(0.4, 0, 1, 1)` |432| easing.spring | `cubic-bezier(0.34, 1.2, 0.64, 1)` |433 434### Elevation435 436Five-level scale, system-specific recipe.437 438| Level | Shadow | Recipe |439|-------|--------|--------|440| level0 | `inset 0 1px 0 rgba(255,255,255,0.18)` | Flat glass surface — top-edge gloss only. |441| level1 | `0 2px 8px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255,255,255,0.18)` | Soft lift + top-edge gloss. |442| level2 | `0 12px 32px -8px rgba(0, 0, 0, 0.18), inset 0 1px 0 rgba(255,255,255,0.18)` | Floating pane — popover. |443| level3 | `0 24px 64px -16px rgba(0, 0, 0, 0.28), 0 0 0 1px rgba(122, 122, 130, 0.08), inset 0 1px 0 rgba(255,255,255,0.18)` | Sheet — accent rim for depth. |444| level4 | `0 40px 96px -24px rgba(0, 0, 0, 0.5), 0 0 48px -12px rgba(122, 122, 130, 0.25), inset 0 1px 0 rgba(255,255,255,0.18)` | Modal — dramatic glow, scrim required. |445 446### Content447 448- **measure:** `66ch` (max line length for body prose)449- **paragraph spacing:** `1.25em`450- **list indent:** `1.5em`451- **list gap:** `0.5em`452- **link:** color `#7A7A82`, underline `hover`453- **blockquote:** border `1px solid rgba(122, 122, 130, 0.4)`, padding `0.9em 1.2em`454- **code:** background `rgba(122, 122, 130, 0.1)`, color `#7A7A82`455 456### Accessibility (WCAG 2.1)457 458**Overall:** AA-Large459 460| Pair | Ratio | Required | Grade | Suggested fix |461|------|-------|----------|-------|---------------|462| Body text on surface | 6.74:1 | AA | AA | — |463| Body text on canvas | 7.19:1 | AA | AAA | — |464| Muted text on surface | 14.73:1 | AA | AAA | — |465| Accent on surface | 4.36:1 | AA-Large | AA-Large | — |466| Accent on canvas | 4.65:1 | AA-Large | AA | — |467 Wire it into your agent.
# CLAUDE.md Reference @DESIGN.md for all styling decisions. Apply tokens strictly — do not introduce colors, fonts, or radii outside the system. When in doubt, prefer the values declared in DESIGN.md frontmatter.Three snippets.
Google Fonts link
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" />Install dependencies
npm install lucide-reactTailwind config
// tailwind.config.jsexport default { theme: { extend: { fontFamily: { display: ['"Inter Tight"', 'serif'], sans: ['"Inter"', 'sans-serif'], mono: ['"JetBrains Mono"', 'monospace'], }, colors: { primary: '#9D8CFF', secondary: '#E6E5E3', accent: '#7A7A82', neutral: '#0A0A0B', surface: '#131316', }, borderRadius: { sm: '4px', md: '6px', lg: '8px', }, }, },};Try another system.
Mallow SaaS
A soft modern SaaS surface with the warmth of a marshmallow. Cream-mallow page background, butter-soft cards with generous radius, Manrope for UI and DM Mono for figures, a single muted lavender accent reserved for the primary CTA and the active sidebar item. Built for early-stage product pages, friendly B2C dashboards, and onboarding flows that need to feel approachable without going saccharine.
Token Mesh
Crypto without the neon cliché. Dark slate surfaces, Geist sans for prose and Geist Mono with tabular numerals for every figure, a single cool mint accent reserved for positive deltas. Built for crypto exchanges, DeFi dashboards, and on-chain analytics that want to look serious — no glow, no purple-blue gradient, no rocket emoji.