All designs

Character.ai

AI characters. Soft rounded chat UI, friendly neutrals, avatar-led rows.

extracted from https://character.ai/ on 2026-07-03

character.ai | AI Chat, Reimagined–Your Words. Your World.

light-leaning · 3 stylesheets · 45 native variables

fonts Open Sans · Google Sans · Archivo · Roboto · Arimo · EB Garamond · Lora · Roboto Condensed
---
name: character-ai-design-system
source: https://character.ai/
extracted: 2026-07-03
theme: light  # measured from neutral usage weight
colors:  # roles inferred from usage frequency + luminance; names verified against values
  canvas: "#ffffff"
  ink: "#121212"
  text-muted: "#8e918f"
  surface: "#dadce0"
  hairline: "#c4c7c5"
  accent: "#1a73e8"  # cyan
  accent-2: "#1967d2"  # cyan
  accent-3: "#2299dd"  # cyan
fonts:
  primary: "Open Sans"  # medium-confidence: usage counts are close
  serif: "EB Garamond"
---

# character.ai | AI Chat, Reimagined–Your Words. Your World. — Design System

Extracted from **https://character.ai/** on 2026-07-03.

> Chat with millions of AI Characters on the #1 AI chat app. Where will your next adventure take you?

Every value below is mined from the site's live CSS (45 native custom properties, ranked usage counts). Role assignments are inferred from usage and luminance and marked as such — treat them as a strong starting point, not gospel.

## Overview

The system reads as light: measured neutral usage weighs 53 light against 56 dark. The palette is chromatic: 12 saturated values against 9 neutrals, led by cyan (`#1a73e8`). **Open Sans** leads the font stack, though usage counts are close — verify against rendered pages before committing. Geometry mixes sharp corners (4px) with full pills.

## Usage rules

Derived from the measured usage below — each rule cites its evidence.

- Chromatic color carries 34% of measured usage — this palette uses color structurally. Saturated values can hold large surfaces here; timidity would misrepresent the source.
- The theme is light (measured neutral weight 53:56). Don't flip individual sections to the opposite mode.
- `8px` is the workhorse radius (x7); treat the other radii as exceptions, not options.
- The only shadows are blur-less hairline offsets — this system barely uses elevation; don't add soft drop shadows.

## Colors

### Neutrals (light → dark)

| Token | Value | Usage | Inferred role |
| --- | --- | --- | --- |
| `neutral-50` | `#ffffff` | 43 | **canvas** — lightest neutral, matches the measured light-leaning theme |
| `neutral-200` | `#dadce0` | 10 | **surface** — neutral closest to canvas luminance |
| `neutral-300` | `#c4c7c5` | 2 | **hairline** — next neutral near canvas, hairline-border weight |
| `neutral-500` | `#8e918f` | 2 | **text-muted** — most-used mid-luminance neutral |
| `neutral-600` | `#757575` | 1 | — |
| `neutral-700` | `#5f6368` | 19 | — |
| `neutral-800` | `#3c4043` | 6 | — |
| `neutral-900` | `#202124` | 7 | — |
| `neutral-950` | `#121212` | 2 | **ink** — darkest neutral, highest contrast against canvas |

### Accents

| Token | Value | Usage | Inferred role |
| --- | --- | --- | --- |
| `cyan` | `#1a73e8` | 15 | **accent** — most-used chromatic color |
| `cyan-2` | `#1967d2` | 12 | **accent-2** — supporting chromatic color |
| `cyan-3` | `#2299dd` | 6 | **accent-3** — supporting chromatic color |
| `pale-blue` | `#e8eaed` | 5 | — |
| `blue` | `#174ea6` | 2 | — |
| `green` | `#07bc0c` | 1 | — |
| `yellow` | `#f1c40f` | 1 | — |
| `red` | `#e74d3c` | 1 | — |
| `green-2` | `#4cd964` | 1 | — |
| `cyan-4` | `#5ac8fa` | 1 | — |
| `cyan-5` | `#007aff` | 1 | — |
| `cyan-6` | `#34aadc` | 1 | — |

## Typography

**Open Sans** has the most `font-family` declarations, but the margin over the rest is thin — treat the primary-face call as provisional and verify on rendered pages. Full list by usage:

| Family | Usage |
| --- | --- |
| Open Sans | 71 |
| Google Sans | 52 |
| Archivo | 31 |
| Roboto | 28 |
| Arimo | 16 |
| EB Garamond | 14 |
| Lora | 14 |
| Roboto Condensed | 14 |

**Size scale (px):** `11`, `12`, `14`, `16`, `18`, `20`, `24`

**Weights in use:** `300` (x1), `400` (x174), `500` (x145), `600` (x23), `700` (x13)

**Line-heights (unitless):** `1`

**Letter-spacing values:** `.25px`, `.3px`

## Spacing

Most-used values (px): `2`, `3`, `4`, `6`, `8`, `10`, `12`, `14`, `16`, `20`, `24`, `48`

## Border radius

| Token | Value | Usage |
| --- | --- | --- |
| `radius-sm` | `4px` | 6 |
| `radius-md` | `8px` | 7 |
| `radius-lg` | `10px` | 2 |
| `radius-xl` | `14px` | 3 |
| `radius-2xl` | `18px` | 2 |
| `radius-3xl` | `20px` | 4 |
| `radius-4xl` | `100%` | 1 |
| `radius-full` | `50%` | 3 |

## Shadows (ordered by blur radius)

- `shadow-sm` — `0 4px 8px rgba(0, 0, 0, 0.16)` (x1)
- `shadow-md` — `0 -2px 8px rgba(128, 134, 139, 0.09), 0 4px 8px rgba(128, 134, 139, 0.06), 0 1px 2px rgba(60, 64, 67, 0.3), 0 2px 6px rgba(60, 64, 67, 0.15)` (x1)
- `shadow-lg` — `0 0 10px #29D, 0 0 5px #29D` (x1)

### Focus rings (spread-only box-shadows, kept out of the elevation scale)

- `0 0 0 3px #FFFFFF` (x1)

## Breakpoints

`479px`, `480px`, `481px`

## Starter recipes

Tokens composed into components. The source site's real components were **not** inspected — these are starting points built from the extracted values, with contrast ratios computed rather than assumed.

```css
.button-primary {
  background: var(--color-accent); /* #1a73e8 */
  color: var(--color-canvas); /* #ffffff — contrast 4.5:1 */
  border-radius: 9999px; /* pill — mined as 50% */
  font-weight: 500;
}

.card {
  background: var(--color-surface); /* #dadce0 */
  border: 1px solid var(--color-hairline); /* #c4c7c5 */
  border-radius: 8px; /* most-used finite radius */
  box-shadow: var(--shadow-sm);
}

.input {
  background: var(--color-canvas); /* #ffffff */
  color: var(--color-ink); /* #121212 — contrast 18.7:1 */
  border: 1px solid var(--color-hairline); /* #c4c7c5 */
  border-radius: 4px;
  /* placeholder color: var(--color-text-muted) #8e918f */
}

.nav {
  background: var(--color-canvas); /* #ffffff */
  border-bottom: 1px solid var(--color-hairline); /* #c4c7c5 */
  color: var(--color-ink); /* #121212 */
  /* inactive links: var(--color-text-muted) #8e918f */
  /* active link: var(--color-accent) #1a73e8 — contrast vs canvas 4.5:1 */
}

.modal {
  background: var(--color-surface); /* #dadce0 */
  border-radius: 8px;
  box-shadow: var(--shadow-lg); /* largest mined shadow */
}

.modal-backdrop {
  background: color-mix(in srgb, var(--color-ink) 55%, transparent); /* scrim from #121212 */
}

.input-error {
  border-color: #e74d3c; /* mined token: red */
  /* error text: #e74d3c on canvas — contrast 3.8:1, below AA; darken for message text */
}

.input-success {
  border-color: #07bc0c; /* mined token: green */
}
```

## Observations

- 9 of 21 extracted colors are neutrals.
- 3 distinct shadows; the softest reaches 0px blur.
- 3 breakpoints, from 479px to 481px.

## Native CSS custom properties

First 40 of 45:

```css
:root {
  --toastify-color-light: #fff;
  --toastify-color-dark: #121212;
  --toastify-color-info: #3498db;
  --toastify-color-success: #07bc0c;
  --toastify-color-warning: #f1c40f;
  --toastify-color-error: hsl(6, 78%, 57%);
  --toastify-color-transparent: rgba(255, 255, 255, .7);
  --toastify-icon-color-info: var(--toastify-color-info);
  --toastify-icon-color-success: var(--toastify-color-success);
  --toastify-icon-color-warning: var(--toastify-color-warning);
  --toastify-icon-color-error: var(--toastify-color-error);
  --toastify-container-width: fit-content;
  --toastify-toast-width: 320px;
  --toastify-toast-offset: 16px;
  --toastify-toast-top: max(var(--toastify-toast-offset), env(safe-area-inset-top));
  --toastify-toast-right: max(var(--toastify-toast-offset), env(safe-area-inset-right));
  --toastify-toast-left: max(var(--toastify-toast-offset), env(safe-area-inset-left));
  --toastify-toast-bottom: max(var(--toastify-toast-offset), env(safe-area-inset-bottom));
  --toastify-toast-background: #fff;
  --toastify-toast-padding: 14px;
  --toastify-toast-min-height: 64px;
  --toastify-toast-max-height: 800px;
  --toastify-toast-bd-radius: 6px;
  --toastify-toast-shadow: 0px 4px 12px rgba(0, 0, 0, .1);
  --toastify-font-family: sans-serif;
  --toastify-z-index: 9999;
  --toastify-text-color-light: #757575;
  --toastify-text-color-dark: #fff;
  --toastify-text-color-info: #fff;
  --toastify-text-color-success: #fff;
  --toastify-text-color-warning: #fff;
  --toastify-text-color-error: #fff;
  --toastify-spinner-color: #616161;
  --toastify-spinner-color-empty-area: #e0e0e0;
  --toastify-color-progress-light: linear-gradient(to right, #4cd964, #5ac8fa, #007aff, #34aadc, #5856d6, #ff2d55);
  --toastify-color-progress-dark: #bb86fc;
  --toastify-color-progress-info: var(--toastify-color-info);
  --toastify-color-progress-success: var(--toastify-color-success);
  --toastify-color-progress-warning: var(--toastify-color-warning);
  --toastify-color-progress-error: var(--toastify-color-error);
}
```

## Files

- `tailwind.css` — Tailwind v4 `@theme` block; tokens become utilities (e.g. `bg-neutral-900`, `text-cyan`).
- `variables.css` — framework-agnostic `:root` variables, same values.
- `tokens.json` — W3C Design Tokens format for Figma plugins, Style Dictionary, etc.