# KEZ Design System > Source of truth for the kez-chat redesign (`redesign-kez-theme` branch). > Goal: take the chat app out of the prototype phase into a real, > WhatsApp/Discord-caliber messenger with an iconic KEZ identity. ## Who we're designing for Hackers, infosec people, privacy absolutists, anti-surveillance / sovereignty folks, Meshtastic & off-grid comms operators, journalists/activists in hostile environments — the Signal / Briar / Tails / Mullvad / Monero crowd. They trust **verifiability over promises**, have a finely-tuned bullshit detector, and bounce instantly from anything that smells like VC surveillance-ware. **Positioning:** _KEZ is the sovereign identity layer + encrypted comms for people who assume the network is hostile._ ## Aesthetic direction **Muted tactical terminal — restraint, not neon cosplay.** Mullvad's calm authority. Monospace as identity. The first 3 seconds should feel like opening an operational tool, not a brochure. Hard-ish edges, visible structure, a single cold accent. No gradients-blobs, no mascots, no "delightful." ### Hard DO-NOTs - No rounded-blob/gradient SaaS look, no mascots, no illustrations of laughing people. - No "military-grade / bank-level" marketing adjectives. Show, don't boast. - No surveillance tells: no third-party analytics, no social login, no email-required signup. - No stock photography. ## Color palette (dark-first; light theme = v2, out of scope) Tailwind v4 `@theme` tokens, in `src/app.css`. | Token | Hex | Use | |---|---|---| | `--color-bg` | `#0B0C0E` | app background (neutral near-black) | | `--color-surface` | `#16181C` | cards, conversation list, sidebars | | `--color-elevated` | `#1E2127` | modals, menus, input wells | | `--color-border` | `#2A2E35` | hairlines, dividers | | `--color-text` | `#E8EAED` | primary text (neutral off-white) | | `--color-text-secondary` | `#9BA3AD` | secondary | | `--color-text-muted` | `#5C636D` | timestamps, meta | | `--color-text-disabled` | `#3A4049` | disabled | | `--color-accent` | `#28C8E8` | **the KEZ color** — electric cyan | | `--color-accent-dim` | `#1B9DBC` | hover/pressed, accent borders | | `--color-accent-contrast` | `#04131A` | text on accent fills | | `--color-verified` | `#4ADE80` | proof verified (distinct from accent) | | `--color-danger` | `#FF5C6C` | destructive, failed | | `--color-warning` | `#FFB13D` | needs-attention | | `--color-bubble-recv` | `#1B1F25` | received message bubble fill | Accent is used surgically: send bubbles, focus rings, active nav, the wordmark cursor, links, live/streaming indicators. Greys carry the weight. **Verified green is for proofs only** — never as a general accent, so a verification badge never camouflages into accent UI. ## Typography - **UI/body:** `Inter` — `--font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif` - **Monospace:** `JetBrains Mono` — `--font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace`. Used for keys, hashes, handles, the wordmark. Loaded via Google Fonts. | Role | Size / weight / line-height | Notes | |---|---|---| | Wordmark | 22px / 700 / 1.1 mono | `-0.02em`, + cyan block cursor | | Section header | 12px / 600 / 1.3 sans | uppercase, `+0.08em`, secondary color | | Body / message | 15px / 450 / 1.45 sans | | | Conversation name | 15px / 600 / 1.3 sans | | | Timestamp/meta | 12px / 500 / 1.2 | muted | | Mono key display | 13px / 500 / 1.5 mono | `+0.01em` | ## Spacing / radius / shadow - **Spacing** (4px base): 4, 8, 12, 16, 20, 24, 32, 48. - **Radius — tactical, mid-soft:** `--radius-sm: 4px` (chips/badges), `--radius-md: 8px` (inputs/buttons), `--radius-lg: 12px` (bubbles/cards), `--radius-xl: 16px` (modals). Fully-round reads consumer-soft; sharp reads unfinished; 8–12 says "engineered." - **Shadows = terminal glow, not ambient drop shadows.** Surfaces use `1px solid --color-border` hairlines. Modals: `0 8px 24px -8px rgba(0,0,0,0.6)`. Accent focus/glow: `0 0 0 1px #28C8E833, 0 0 16px -2px #28C8E866`. ## Signature components - **Message bubbles** — radius `lg`, padding `8px 12px`, max-width ~78%. - Sent: `--color-accent` fill, `--color-accent-contrast` text, `border-bottom-right-radius: 4px` tail. - Received: `--color-bubble-recv` fill, `--color-text`, `1px solid --color-border`, `border-bottom-left-radius: 4px`. - **Conversation row** — 64px tall, 40px avatar (`radius-md`), name 600, preview secondary, time muted. Active = left 2px accent bar + elevated bg. Unread = accent dot + name 700. - **Buttons** — height 40px, `radius-md`, 600. Primary: accent fill / contrast text / dim hover / 0.98 active / glow focus. Secondary: transparent, `1px solid border`, hover elevated bg + accent-dim border. - **Inputs** — elevated bg, `1px solid border`, `radius-md`, focus → accent border + `0 0 0 3px #28C8E822` ring. Key inputs use mono. - **Handle/identity chip** — inline mono, `radius-sm`, `2px 8px`, bg `#28C8E814`, `1px solid #28C8E833`, accent text; leading `@`/`0x` muted. - **Verified proof badge** — `radius-sm`, bg `#4ADE8014`, border `#4ADE8040`, `--color-verified` text, mono 11/600, leading ✓. - **Avatars** — deterministic identicon generated from the ed25519 key, so every KEZ has a stable face. Eliminates the biggest "prototype" tell. ## Motion Fast (120–200ms), `cubic-bezier(0.2,0.8,0.2,1)`, on state change only, respect `prefers-reduced-motion`. - Received message: slide-up 6px + fade. - Sent message: spring `scale .96→1` + brief accent-glow pulse decaying ~600ms. - Thread push/back slide on mobile. - Tasteful terminal flourish: a single cyan block-cursor blink on the empty compose field + after the wordmark. No content scanlines. ## Wordmark / icon - **Wordmark:** `kez` lowercase, JetBrains Mono 700, `-0.02em`, primary text, followed by a blinking cyan block cursor `▌`. The cursor is the brand mark. - **Icon:** evolve the amber key → cyan. Recolor `public/kez-icon.svg` stroke `#fbbf24` → `#28C8E8` on `#0B0C0E`; reshape so the key reads as a key-meets-cursor glyph. Drop the literal 🔑 emoji everywhere. Regenerate PWA icon set. Manifest `theme_color` + `background_color` → `#0B0C0E`. ## Information architecture (the big structural change) **Land logged-in users on Chats, not a Dashboard.** The "dashboard" as a destination is killed; its contents redistribute. ### Navigation — 4 destinations | Destination | Purpose | |---|---| | **Chats** | conversation list + threads (the home) | | **Contacts** | known KEZs + verification status + start-new-chat | | **Identity** | your KEZ + claims/proofs (the superpower surface) | | **Settings** | security, backup, notifications, account, about | - **Mobile (PWA):** fixed bottom tab bar, 4 tabs, unread badge on Chats. Thread view pushes full-screen with a back chevron. - **Desktop:** slim left icon rail (4 destinations) + secondary list column + main content pane. Replaces the current top nav bar entirely. ### Feature → new home | Existing | New home | |---|---| | Landing/Create/Restore/Unlock | unauthenticated flow (pre-nav), restyled | | Messages (list+thread+compose, SSE, emoji, unread, notifications) | **Chats** (default surface) | | Start chat by handle | **Contacts → New chat** (preview card before opening) | | Claims list | **Identity → My proofs** (grouped verified/failed/pending) | | AddClaim | **Identity → Add proof** | | Identity display (handle@server, ed25519 key, registry) | **Identity** header card (avatar, copyable KEZ, fingerprint, QR) | | Seed/key backup | **Settings → Security → Recovery phrase** (re-auth gated) | | Biometric/passkey | **Settings → Security → App lock** | | Notifications perm + test | **Settings → Notifications** | | Build SHA / source link | **Settings → About** | ### New-conversation flow (the KEZ moment) + FAB on Chats (mobile) / "New chat" in Contacts column (desktop) → "Enter a KEZ" (`handle@server`, paste/QR) → `lookup` → **preview card**: avatar, handle, key fingerprint, and **inline verified proofs** (✓ github:you, ✓ dns:yourdomain) → "Message". Verification is always one tap from a thread via the contact-detail header. You see who someone is before you trust them. ### Polish signals to ship 1. Identicon avatars everywhere (from ed25519 key). 2. Message status ticks (sent / SSE-delivered) + day separators. 3. Real empty + skeleton-loading states. 4. Verification shield badge system (green verified / neutral none / amber failed), consistent across Chats, Contacts, Identity. 5. Native push/back + send transitions; smooth auto-scroll (already shipped). ## Implementation phases 0. **Foundation** — `app.css` Tailwind v4 `@theme` tokens, Google Fonts, recolor icon + regenerate PWA assets, manifest colors. 1. **Shell + nav** — bottom tab bar / left rail, router lands on `/chats`, wordmark component. 2. **Chats** — restyle list + thread + bubbles, identicon avatars, empty/skeleton states. Keep SSE/emoji/notifications/auto-scroll. 3. **Identity** — identity card + proofs (migrate Claims/AddClaim). 4. **Settings** — Account / Security / Notifications / About (migrate Dashboard remainder). 5. **Contacts** — list + new-chat preview card with proofs. 6. **Auth flow restyle** — Landing/Create/Restore/Unlock to the new theme. All existing functionality is preserved; only its placement and presentation change.