Phase 0 of the redesign (see DESIGN.md). Establishes the visual
foundation; route restyling + IA reorg follow in subsequent commits.
Design direction (decided with a 3-agent design-team debate):
• Audience: hackers, privacy absolutists, anti-surveillance, Meshtastic
/ off-grid, journalists in hostile environments.
• Aesthetic: "muted tactical terminal" — Mullvad-calm restraint, not
neon cyberpunk cosplay. Monospace as identity. Hard-ish edges.
• Signature color: electric cyan #28C8E8 on neutral near-black #0B0C0E
(chosen over signal-amber and phosphor-green — ages better, reads
"serious infrastructure" without shouting). Verified-green reserved
for proofs only.
Changes:
• app.css: full Tailwind v4 @theme token set — elevation ramp, text
tiers, accent + dim + contrast, semantic colors, Inter + JetBrains
Mono via Google Fonts, tactical radius scale, accent glow, dark
color-scheme, cyan text-selection, thin dark scrollbars, and the
kez-cursor blink keyframe (respects prefers-reduced-motion).
• Wordmark.svelte: `kez▌` mono wordmark with blinking cyan block
cursor — the cursor is the brand mark.
• Avatar.svelte: deterministic 5×5 symmetric identicon from the
ed25519 key, cyan-arc hue. Every KEZ gets a stable face.
• kez-icon.svg: amber key → cyan key-meets-cursor glyph; regenerated
the full PWA icon set + apple-touch-icon from it.
• manifest + index.html theme/background color → #0B0C0E.
• DESIGN.md: the full system + IA plan as source of truth.
Note: existing route components still use light-theme utility classes
and will look inconsistent until restyled in the next phases — that
work lands next (shell/nav → Chats → Identity → Settings → Contacts).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
9.2 KiB
KEZ Design System
Source of truth for the kez-chat redesign (
redesign-kez-themebranch). 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-borderhairlines. 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, padding8px 12px, max-width ~78%.- Sent:
--color-accentfill,--color-accent-contrasttext,border-bottom-right-radius: 4pxtail. - Received:
--color-bubble-recvfill,--color-text,1px solid --color-border,border-bottom-left-radius: 4px.
- Sent:
- 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 #28C8E822ring. Key inputs use mono. - Handle/identity chip — inline mono,
radius-sm,2px 8px, bg#28C8E814,1px solid #28C8E833, accent text; leading@/0xmuted. - Verified proof badge —
radius-sm, bg#4ADE8014, border#4ADE8040,--color-verifiedtext, 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:
kezlowercase, 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.svgstroke#fbbf24→#28C8E8on#0B0C0E; reshape so the key reads as a key-meets-cursor glyph. Drop the literal 🔑 emoji everywhere. Regenerate PWA icon set. Manifesttheme_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
- Identicon avatars everywhere (from ed25519 key).
- Message status ticks (sent / SSE-delivered) + day separators.
- Real empty + skeleton-loading states.
- Verification shield badge system (green verified / neutral none / amber failed), consistent across Chats, Contacts, Identity.
- Native push/back + send transitions; smooth auto-scroll (already shipped).
Implementation phases
- Foundation —
app.cssTailwind v4@themetokens, Google Fonts, recolor icon + regenerate PWA assets, manifest colors. - Shell + nav — bottom tab bar / left rail, router lands on
/chats, wordmark component. - Chats — restyle list + thread + bubbles, identicon avatars, empty/skeleton states. Keep SSE/emoji/notifications/auto-scroll.
- Identity — identity card + proofs (migrate Claims/AddClaim).
- Settings — Account / Security / Notifications / About (migrate Dashboard remainder).
- Contacts — list + new-chat preview card with proofs.
- Auth flow restyle — Landing/Create/Restore/Unlock to the new theme.
All existing functionality is preserved; only its placement and presentation change.