Modern AI product surface without the clichés. Geist sans across the board, Geist Mono for prompts and metrics, very fine off-white surfaces with a 1px white inset highlight, a single muted electric-indigo accent reserved for the assistant's response state. Built for AI-first products that want to feel premium without leaning on rainbow gradients.
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.
Prose-first token file — decisions live next to their reasoning.
Fine micro-scale (1–5px) for pills, editorial scale (12–21px) for the grid.
The system's own radius tokens — sm for chips and inputs, md for buttons, lg for cards, pill for fully-rounded CTAs.
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.
1---2name: "Signal AI"3description: "Modern AI product surface without the clichés. Geist sans across the board, Geist Mono for prompts and metrics, very fine off-white surfaces with a 1px white inset highlight, a single muted electric-indigo accent reserved for the assistant's response state. Built for AI-first products that want to feel premium without leaning on rainbow gradients."4tags: [ai, saas, minimal, premium, modern]5colors:6 primary: "#0d0f12"7 secondary: "#646973"8 tertiary: "#0d0f12"9 neutral: "#eef0f3"10 surface: "#f7f8fa"11typography:12 display: Geist13 body: Geist14 mono: "Geist Mono"15 scale:16 hero: "3.5rem / 1.04 / 600 / -0.035em"17 h1: "2.25rem / 1.14 / 600 / -0.025em"18 h2: "1.5rem / 1.3 / 600 / -0.018em"19 body: "0.9375rem / 1.6 / 400 / -0.005em"20radius:21 sm: 5px22 md: 8px23 lg: 12px24 pill: 9999px25shadows:26 card: "rgba(255,255,255,0.85) 0 1px 0 inset, rgba(13,15,18,0.04) 0 1px 2px, rgba(13,15,18,0.04) 0 0 0 1px"27 button: "rgba(255,255,255,0.10) 0 1px 0 inset, rgba(13,15,18,0.18) 0 1px 2px"28borders:29 card: "1px solid rgba(13,15,18,0.06)"30 divider: rgba(13,15,18,0.08)31buttons:32 primary:33 background: #0d0f1234 color: #f7f8fa35 border: 1px solid rgba(0,0,0,0.4)36 shape: rounded37 padding: 9px 18px38 font: 500 / 0.8125rem39 shadow: rgba(255,255,255,0.10) 0 1px 0 inset, rgba(13,15,18,0.18) 0 1px 2px40 secondary:41 background: #ffffff42 color: #0d0f1243 border: 1px solid rgba(13,15,18,0.10)44 shape: rounded45 padding: 9px 18px46 font: 500 / 0.8125rem47 shadow: rgba(13,15,18,0.04) 0 1px 2px48 outline:49 background: transparent50 color: #0d0f1251 border: 1px solid rgba(13,15,18,0.16)52 shape: rounded53 padding: 9px 18px54 font: 500 / 0.8125rem55 ghost:56 background: transparent57 color: #64697358 border: none59 shape: rounded60 padding: 9px 14px61 font: 500 / 0.8125rem62charts:63 variant: line64 stroke_width: 1.7565 fill_opacity: 0.0866 gridlines: false67 bar_gap: 10px68 highlight: single69 dot_marker: true70fonts_url: "https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap"71dependencies: ["lucide-react"]72---73 74# Signal AI75 76## AI Build Instructions77 78> **Read this section before writing any code.** The rules below79> are non-negotiable. Every value used in the UI must come from this80> file's frontmatter — never substitute, approximate, or invent new81> colors, fonts, radii, or shadows. If a value is missing, ask the82> user before adding one.83 84### 1 · Your role85 86You are building UI for a project that has adopted **Signal AI** as its87design system. Treat `DESIGN.md` as the single source of truth.88Your job is to translate the user's product requirements into89components and pages that look like they were designed by the same90person who authored this file.91 92### 2 · Token compliance93 94- Pull every color, font family, radius, shadow, and spacing value95 from the frontmatter at the top of this file.96- Use semantic roles (e.g. `primary`, `accent`, `muted`) — never97 hard-code hex values that bypass the system.98- When a token can be expressed as a CSS variable, declare it once99 in your global stylesheet and reference it everywhere downstream.100- The Google Fonts `<link>` is provided in the Typography section.101 Add it to `<head>` before any component renders.102 103### 3 · Component recipes104 105Use these recipes verbatim when building the corresponding component.106 107#### Buttons108 109Four variants are defined. Pick one — never blend variants or invent a fifth.110 111- **Primary** — rounded shape, bg `#0d0f12`, text `#f7f8fa`, border `1px solid rgba(0,0,0,0.4)`, padding `9px 18px`, weight `500`, shadow `rgba(255,255,255,0.10) 0 1px 0 inset, rgba(13,15,18,0.18) 0 1px 2px`.112- **Secondary** — rounded shape, bg `#ffffff`, text `#0d0f12`, border `1px solid rgba(13,15,18,0.10)`, padding `9px 18px`, weight `500`, shadow `rgba(13,15,18,0.04) 0 1px 2px`.113- **Outline** — rounded shape, text `#0d0f12`, border `1px solid rgba(13,15,18,0.16)`, padding `9px 18px`, weight `500`.114- **Ghost** — rounded shape, text `#646973`, padding `9px 14px`, weight `500`.115 116Reach for **primary** as the single dominant CTA per screen.117**Secondary** for the supporting action. **Outline** for tertiary118actions in toolbars. **Ghost** for inline links and table actions.119 120#### Cards121 122- Background: `#f7f8fa`123- Border: `1px solid rgba(13,15,18,0.06)`124- Shadow: `rgba(255,255,255,0.85) 0 1px 0 inset, rgba(13,15,18,0.04) 0 1px 2px, rgba(13,15,18,0.04) 0 0 0 1px`125- Radius: `radius.lg` (`12px`)126- Internal padding: `20px` for compact cards, `24–28px` for content cards.127 128#### Tabs129 130Variant: `pill`. Segmented control inside a tinted track. Active tab gets a filled pill in the accent color.131 132#### Charts133 134- Bar/line variant: `line`135- No gridlines — let the bars/lines carry the data.136- Highlight strategy: `single` — emphasize a single bar/point per chart.137 138#### Typography pairings139 140- **Display (`Geist`)** — h1, h2, hero headlines, brand wordmarks.141- **Body (`Geist`)** — paragraphs, labels, button text, form inputs.142- **Mono (`Geist Mono`)** — code, eyebrows, metadata, numerals in tables.143 144### 4 · Hard constraints145 146Never do any of the following without explicit instruction from the user:147 148- Introduce a new color, font, radius, or shadow that isn't declared above.149- Mix this system with another (e.g. don't paste in Material or Bootstrap defaults).150- Use generic gradient defaults (purple→blue, peach→pink) — they break the system's voice.151- Reach for emoji icons. Use a consistent icon library and size icons in line with body type.152- Add motion that exceeds the system's restraint — keep transitions short (≤200ms) and subtle.153 154### 5 · Before you finish — verify155 156Run through this checklist for every screen you produce:157 158- [ ] Every color used appears in the Colors table above.159- [ ] Headlines use the display font; body copy uses the body font.160- [ ] Buttons match one of the declared variants exactly (shape, padding, weight).161- [ ] Border-radius values come from `radius.sm` / `radius.md` / `radius.lg` / `radius.pill`.162- [ ] Cards and dividers use the declared border + shadow tokens.163- [ ] No values were invented; if you needed something missing, you stopped and asked.164 165---166 167## 1. Atmosphere168 169Signal AI is a modern AI product surface that refuses the clichés of its category. No rainbow gradient, no purple-pink mesh, no shimmering "thinking" animation. The page is fine off-white `#f7f8fa` with cards lifted to pure white, each card carrying a 1px white inset highlight at its top edge — the catch-light that makes the surface read as physical, not flat. Geist handles every text role; Geist Mono carries prompts, model names, latency metrics, and token counts. The single accent is muted electric-indigo `#5567ff` that appears only when the assistant is responding — the avatar dot, the streaming caret, the active model pill in the dropdown. Idle, the system is greyscale.170 171The discipline is in the absence: no glow, no animation chrome, no second color. The accent earns its meaning by being reserved for one specific state.172 173**Signature moves**174- Indigo `#5567ff` only on the assistant-response state — avatar dot, streaming caret, active model pill175- 1px white inset highlight on every card and primary button — the physical catch-light176- Geist Mono with 0.04em uppercase tracking for every model name, latency, and token count177- Pill tabs only in the prompt composer (model selector); section tabs are pill too — consistency178- Off-white `#f7f8fa` page → pure white card — the tonal step is the only depth179 180## 2. Palette181 182### Surfaces183- **Page** `#f7f8fa` — primary background (cool fine off-white)184- **Card** `#ffffff` — elevated surface185- **Bone** `#eef0f3` — secondary surfaces, code blocks, table headers186 187### Ink188- **Ink** `#0d0f12` — text, headings, primary CTA fill189- **Ink 60** `#646973` — secondary text, mono labels190- **Hairline** `rgba(13,15,18,0.06)` — every card edge191 192### Accent193- **Indigo** `#5567ff` — assistant-response state (avatar dot, streaming caret, active model pill, focus ring)194- **Indigo Soft** `rgba(85,103,255,0.10)` — hovered model pill, focus ring background195 196## 3. Typography197 198| Role | Font | Size | Weight | Leading | Tracking |199|------|------|------|--------|---------|----------|200| Hero | Geist | 56px | 600 | 1.04 | -0.035em |201| H1 | Geist | 36px | 600 | 1.14 | -0.025em |202| H2 | Geist | 24px | 600 | 1.3 | -0.018em |203| Body | Geist | 15px | 400 | 1.6 | -0.005em |204| UI / Button | Geist | 13px | 500 | 1.4 | 0 |205| Prompt / Code | Geist Mono | 13px | 400 | 1.55 | 0 |206| Metric Label | Geist Mono | 11px | 500 | 1.0 | 0.04em uppercase |207| Latency / Tokens | Geist Mono | 12px | 500 | 1.0 | 0 tabular-nums |208 209Geist Mono carries the technical voice — anything a model touches (prompt, response chunk, latency in ms, token count, model name) lives in mono.210 211## 4. Buttons212 213### Primary (Ink with Inset Highlight)214```css215background: #0d0f12;216color: #f7f8fa;217padding: 9px 18px;218border-radius: 8px;219border: 1px solid rgba(0,0,0,0.4);220box-shadow:221 rgba(255,255,255,0.10) 0 1px 0 inset,222 rgba(13,15,18,0.18) 0 1px 2px;223```224 225The inset white highlight is the entire signature — without it the button reads as flat black. The dark border at 40% black above the inset is what gives the catch-light something to bend over.226 227### Secondary (Card White)228- Pure white, 1px hairline at 10% ink, ink text — small 1px shadow229 230### Outline & Ghost231- Outline: transparent, 1px hairline at 16% ink232- Ghost: no border, ink-60, hover lifts to ink233 234## 5. Cards235 236```css237background: #ffffff;238border: 1px solid rgba(13,15,18,0.06);239border-radius: 12px;240box-shadow:241 rgba(255,255,255,0.85) 0 1px 0 inset,242 rgba(13,15,18,0.04) 0 1px 2px,243 rgba(13,15,18,0.04) 0 0 0 1px;244```245 246The 1px white inset highlight at the top is the catch-light — it sells the surface as physical glass rather than flat fill. The 1px outline shadow doubles the edge for crispness on retina.247 248The active assistant card adds a 1px indigo top border — that is the only place indigo appears on a card edge.249 250## 6. Charts251 252Line charts at 1.75px ink with an 8% indigo fill, ending in an indigo dot marker. The line is the primary chart variant — bars are reserved for token-usage breakdowns. NO gridlines. Y-axis labels in Geist Mono uppercase 11px aligned to the right edge.253 254## 7. Tabs255 256Pill tabs in a tinted track. Active = white background with the same 1px inset highlight as cards, 1px indigo border, indigo text. Inactive = transparent, ink-60. The active pill carries its own catch-light — that's the consistency move.257 258## 8. Spacing259 260- Base 4px261- Scale: `4, 8, 12, 16, 20, 24, 32, 48, 64, 80`262- Section padding: 80px desktop, 40px mobile263 264## 9. Do's & don'ts265 266✅ **Do**267- Reserve indigo for the assistant-response state — avatar dot, streaming caret, active model pill268- Keep the 1px white inset highlight on every card and primary button — that's the physical catch-light269- Put every prompt, latency, token count, and model name in Geist Mono270- Hold the off-white page → pure white card tonal step271 272❌ **Don't**273- Use a rainbow / purple-pink gradient — the entire category does this; you do not274- Add an animated "thinking" shimmer — the indigo caret IS the response state275- Use Geist Mono for prose body — mono is reserved for technical strings276- Add a second accent color — indigo alone, on the assistant-response state only277 278---279 280## Tokens281 282> Generated from the same source the live preview renders from.283> Treat the values below as the contract — never substitute approximations.284 285### Colors286 287| Role | Value |288|-----------|-------|289| primary | `#0d0f12` |290| secondary | `#646973` |291| tertiary | `#0d0f12` |292| neutral | `#eef0f3` |293| surface | `#f7f8fa` |294 295### Typography296 297- **Display:** Geist298- **Body:** Geist299- **Mono:** Geist Mono300 301| Role | size / leading / weight / tracking |302|------|------------------------------------|303| Hero | 3.5rem / 1.04 / 600 / -0.035em |304| H1 | 2.25rem / 1.14 / 600 / -0.025em |305| H2 | 1.5rem / 1.3 / 600 / -0.018em |306| Body | 0.9375rem / 1.6 / 400 / -0.005em |307 308### Radius309 310- sm: `5px`311- md: `8px`312- lg: `12px`313- pill: `9999px`314 315### Shadows316 317- **card:** `rgba(255,255,255,0.85) 0 1px 0 inset, rgba(13,15,18,0.04) 0 1px 2px, rgba(13,15,18,0.04) 0 0 0 1px`318- **button:** `rgba(255,255,255,0.10) 0 1px 0 inset, rgba(13,15,18,0.18) 0 1px 2px`319 320### Borders321 322- **card:** `1px solid rgba(13,15,18,0.06)`323- **divider:** `rgba(13,15,18,0.08)`324 325### Buttons326 327Four variants, each fully tokenized. The preview renders from these exact values.328 329#### Primary330 331| Property | Value |332|----------|-------|333| shape | `rounded` |334| background | `#0d0f12` |335| color | `#f7f8fa` |336| border | `1px solid rgba(0,0,0,0.4)` |337| padding | `9px 18px` |338| fontWeight | `500` |339| fontSize | `0.8125rem` |340| shadow | `rgba(255,255,255,0.10) 0 1px 0 inset, rgba(13,15,18,0.18) 0 1px 2px` |341 342#### Secondary343 344| Property | Value |345|----------|-------|346| shape | `rounded` |347| background | `#ffffff` |348| color | `#0d0f12` |349| border | `1px solid rgba(13,15,18,0.10)` |350| padding | `9px 18px` |351| fontWeight | `500` |352| fontSize | `0.8125rem` |353| shadow | `rgba(13,15,18,0.04) 0 1px 2px` |354 355#### Outline356 357| Property | Value |358|----------|-------|359| shape | `rounded` |360| background | `transparent` |361| color | `#0d0f12` |362| border | `1px solid rgba(13,15,18,0.16)` |363| padding | `9px 18px` |364| fontWeight | `500` |365| fontSize | `0.8125rem` |366 367#### Ghost368 369| Property | Value |370|----------|-------|371| shape | `rounded` |372| background | `transparent` |373| color | `#646973` |374| border | `none` |375| padding | `9px 14px` |376| fontWeight | `500` |377| fontSize | `0.8125rem` |378 379### Charts380 381| Property | Value |382|----------|-------|383| variant | `line` |384| strokeWidth | `1.75` |385| fillOpacity | `0.08` |386| gridlines | `false` |387| barGap | `10px` |388| highlight | `single` |389| dotMarker | `true` |390 391---392 393## Pro tokens394 395> Production-fidelity tokens. States, density, motion, elevation,396> content rules and a measured WCAG contract — derived from the397> resting tokens unless explicitly authored.398 399### States400 401#### Button402 403- **hover** — shadow: `0 0 24px -4px rgba(13, 15, 18, 0.5), 0 8px 24px -8px rgba(0,0,0,0.6)`, filter: `brightness(1.1)`404- **focus** — outline: `1.5px solid #0d0f12`, outline-offset: `3px`405- **active** — transform: `translateY(1px)`, filter: `brightness(0.92)`406- **disabled** — opacity: `0.35`, filter: `saturate(0.4)`407- **loading** — opacity: `0.6`408- **selected** — bg: `#0d0f12`, color: `#0A0A0A`409 410#### Input411 412- **hover** — border: `1px solid rgba(13, 15, 18, 0.5)`413- **focus** — border: `1px solid #0d0f12`, shadow: `0 0 0 3px rgba(13, 15, 18, 0.2)`414- **disabled** — opacity: `0.35`415- **error** — border: `1px solid #F87171`, shadow: `0 0 0 3px rgba(248,113,113,0.2)`416 417#### Card418 419- **hover** — shadow: `0 16px 40px -12px rgba(0,0,0,0.7), 0 0 0 1px rgba(13, 15, 18, 0.18)`, transform: `translateY(-2px)`420- **selected** — border: `1px solid #0d0f12`, shadow: `0 0 0 1px #0d0f12`421- **dragging** — shadow: `0 24px 60px -16px rgba(0,0,0,0.85)`, transform: `scale(1.02)`, opacity: `0.85`422 423#### Tab424 425- **hover** — color: `#0d0f12`426- **focus** — outline: `1.5px solid #0d0f12`, outline-offset: `2px`427- **selected** — color: `#0d0f12`, border: `0 0 1.5px 0 solid #0d0f12`428 429### Density430 431| Mode | padding × | row × | body | radius × | Use for |432|------|-----------|-------|------|----------|---------|433| compact | 0.72 | 0.78 | 0.8125rem | 0.85 | Information-dense — tables, IDEs, dashboards |434| comfortable | 1 | 1 | 0.9375rem | — | Default — most product UI |435| spacious | 1.35 | 1.3 | 1rem | 1.15 | Editorial — marketing, long-form, settings |436 437### Motion438 439**Signature — Glide.** Fließende, leicht beschleunigte Übergänge mit Accent-Glow auf hover. Premium-Feeling durch kontrollierte Lichtspiele.440 441```css442transition: all 280ms cubic-bezier(0.32, 0.72, 0, 1);443```444 445| Token | Value |446|-------|-------|447| duration.instant | `100ms` |448| duration.fast | `180ms` |449| duration.base | `280ms` |450| duration.slow | `450ms` |451| easing.standard | `cubic-bezier(0.32, 0.72, 0, 1)` |452| easing.decelerate | `cubic-bezier(0.0, 0, 0.2, 1)` |453| easing.accelerate | `cubic-bezier(0.4, 0, 1, 1)` |454| easing.spring | `cubic-bezier(0.5, 1.25, 0.55, 1)` |455 456### Elevation457 458Five-level scale, system-specific recipe.459 460| Level | Shadow | Recipe |461|-------|--------|--------|462| level0 | `none` | Flat — Hairline mit Accent-Hauch. |463| level1 | `0 2px 4px rgba(0,0,0,0.45)` | Subtle drop — list items. |464| level2 | `0 12px 28px -8px rgba(0,0,0,0.6)` | Popover — vom Canvas gelöst. |465| level3 | `0 20px 48px -12px rgba(0,0,0,0.7), 0 0 32px -8px rgba(13, 15, 18, 0.25)` | Sheet — Accent-Halo. |466| level4 | `0 40px 96px -16px rgba(0,0,0,0.85), 0 0 64px -12px rgba(13, 15, 18, 0.4)` | Modal — voller Accent-Rim, dramatisch. |467 468### Content469 470- **measure:** `66ch` (max line length for body prose)471- **paragraph spacing:** `1.3em`472- **list indent:** `1.5em`473- **list gap:** `0.5em`474- **link:** color `#0d0f12`, underline `hover`475- **blockquote:** border `2px solid #0d0f12`, padding `0.8em 1.2em`476- **code:** background `rgba(13, 15, 18, 0.12)`, color `#0d0f12`477 478### Accessibility (WCAG 2.1)479 480**Overall:** AA481 482| Pair | Ratio | Required | Grade | Suggested fix |483|------|-------|----------|-------|---------------|484| Body text on surface | 18.06:1 | AA | AAA | — |485| Body text on canvas | 16.81:1 | AA | AAA | — |486| Muted text on surface | 5.19:1 | AA | AA | — |487| Accent on surface | 18.06:1 | AA-Large | AAA | — |488| Accent on canvas | 16.81:1 | AA-Large | AAA | — |489 # 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.<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap" />npm install lucide-react// tailwind.config.jsexport default { theme: { extend: { fontFamily: { display: ['"Geist"', 'serif'], sans: ['"Geist"', 'sans-serif'], mono: ['"Geist Mono"', 'monospace'], }, colors: { primary: '#0d0f12', secondary: '#646973', accent: '#0d0f12', neutral: '#eef0f3', surface: '#f7f8fa', }, borderRadius: { sm: '5px', md: '8px', lg: '12px', }, }, },};Crypto-grade trust on white. Saturated brand blue, ultra-tight 1.00 line-height display, distinctive 56px radius pill CTAs, alternating white/near-black sections.
A design-studio identity built on asymmetric oversized typography. Cream surfaces, Fraunces at extreme display scale paired with Inter Tight for body, an inked black block reserved for the studio mark and the single primary CTA, and an italic serif accent line that breaks every layout. Built for design agencies, art-direction portfolios, and creative studios that lead with type instead of imagery.