Hatch — Design & Branding System
Modern. Minimal. Elegant. Source of truth for every visual decision across the product. EN + 中文 parity enforced.
1. Brand Principles
| Principle | What it means | What it rejects |
|---|---|---|
| Hatched, not hyped | Trust through structure — numbers, verification, signal. | Rocket emojis, "moon" copy, crypto-bro flex. |
| Quiet confidence | A breathing layout, generous whitespace, a single calm accent. | Neon gradients, five CTAs per fold. |
| Human-scale | Bilingual, typographic, patient — you can read it slowly. | Walls of jargon, abbreviation soup. |
| Evidence-first | Every claim is a datum; every datum is explainable. | Vibes-based marketing claims. |
If a design decision feels loud, it's wrong. If it feels slow, it's wrong. If it feels clear, keep it.
2. Identity
2.1 Wordmark
Hatch — set in Inter 600, -0.02em letter-spacing, sentence case. Never ALL CAPS except in single-letter tag labels (EN, 中).
2.2 Mascot
🥚 — one emoji, used sparingly as a state indicator. Never as decoration.
2.3 Tagline
- EN: Every meme deserves to hatch.
- 中: 让每个 meme 顺利孵化。
Always paired when hero-adjacent. Subtitle lines keep parity.
3. Color
Color tokens live in apps/web/src/styles/globals.css as HSL CSS variables and in apps/web/tailwind.config.ts under hatch.*.
3.1 Core palette
| Token | Light (HSL) | Dark (HSL) | Use |
|---|---|---|---|
background |
0 0% 100% |
240 10% 4% |
Canvas |
foreground |
240 10% 4% |
0 0% 98% |
Primary text |
muted-foreground |
240 4% 46% |
240 5% 65% |
Secondary text |
border |
240 6% 90% |
240 4% 16% |
Hairlines, dividers |
primary |
48 96% 53% |
48 96% 53% |
Yolk — CTA fills, highlight |
accent |
240 5% 96% |
240 4% 16% |
Subtle tint (hover, inactive tabs) |
destructive |
0 84% 60% |
0 63% 31% |
Error, irreversible warnings |
3.2 Brand accents
| Token | Hex | Role |
|---|---|---|
hatch.yolk |
#FBC82E |
The one accent. CTAs, live indicators, score "green". |
hatch.shell |
#F5EBDA |
Warm neutral — section dividers, empty states. |
hatch.crack |
#E86B2F |
Graduation / milestone signal only. Never for error. |
3.3 Semantic score bands
| Band | Light bg | Text | Use |
|---|---|---|---|
score.green |
48 96% 94% |
48 96% 28% |
High-confidence score |
score.amber |
38 92% 92% |
28 90% 30% |
Mid score |
score.red |
0 84% 94% |
0 72% 35% |
Low / flagged |
Never stack bands with the primary yolk CTA in the same card — it muddles the signal.
3.4 Rules
- One accent at a time. Yolk OR crack in any viewport, not both.
- Contrast ≥ 4.5:1 for body text; ≥ 3:1 for UI chrome. Audited via
axe-coreper Sprint A.3 gate. - No raw hex in components. Always the token.
- No gradients except the subtle
score.*chip fills. No glows. No glassmorphism.
4. Typography
4.1 Family
- Sans:
Inter(variable, self-hosted vianext/font/google).--font-sans. - Mono:
JetBrains Monofor addresses, hashes, code.
CJK fallback: system fonts — "PingFang SC", "Microsoft YaHei", sans-serif — applied automatically for 中文.
4.2 Type scale (rem / line-height / tracking)
| Token | Size / LH / Tracking | Use |
|---|---|---|
display-2xl |
4.5rem / 1.05 / -0.03em | Hero — sparingly |
display-xl |
3.75rem / 1.08 / -0.025em | Marketing H1 |
display-lg |
3rem / 1.12 / -0.02em | Section H2 |
heading |
1.875rem / 1.25 / -0.015em | In-app H2 |
title |
1.25rem / 1.35 / -0.01em | Card title |
body |
1rem / 1.6 / 0 | Default |
body-sm |
0.875rem / 1.55 / 0 | Metadata |
caption |
0.75rem / 1.4 / 0.01em | Labels, tags, chips |
4.3 Weight
400body500emphasized inline, buttons600wordmark, H1-H3700reserved for numeric display (scores, amounts)
4.4 Rules
- No italics for emphasis — use weight instead.
- Balance headings with
text-balance. Always. - Tabular nums for any number that appears in a scanning column:
font-feature-settings: 'tnum'. - Bilingual pairing: when a hero subtitle has EN + 中, the 中 line sits at the same size and 80% opacity.
5. Spacing & Layout
5.1 Scale
Tailwind's 4-px scale. Common steps: 2, 3, 4, 6, 8, 12, 16, 24. Never arbitrary pixel values in components.
5.2 Rhythm
- Section vertical rhythm:
py-16 md:py-24baseline;py-20 md:py-32for hero. - Card padding:
p-6compact,p-8comfortable. - Line length:
max-w-prose(~65ch) for body copy;max-w-4xlfor hero.
5.3 Grid
- Container:
container mx-auto, centered,1remgutter, capped at1400pxon 2xl. - Gutter between grid items:
gap-4dense,gap-6standard,gap-8airy.
5.4 Elevation
One-step depth system. No multi-layer shadows.
| Token | Shadow | Use |
|---|---|---|
shadow-xs |
0 1px 2px 0 hsl(240 10% 4% / 0.04) |
Resting card |
shadow-sm |
0 2px 8px -2px hsl(240 10% 4% / 0.06) |
Hover card, popover |
shadow-md |
0 8px 24px -8px hsl(240 10% 4% / 0.12) |
Modal, dropdown |
No inner shadows. No colored shadows. Dark mode: drop shadow opacity by 50%.
5.5 Radius
--radius: 0.75rem(12px) — cards, buttons, inputs.rounded-full— chips, avatars, live dots.- Never mix radii on adjacent surfaces.
6. Motion
6.1 Tokens
--motion-fast: 120ms;
--motion-base: 200ms;
--motion-slow: 320ms;
--ease-standard: cubic-bezier(0.2, 0, 0, 1);
--ease-emphasis: cubic-bezier(0.2, 0, 0, 1.2);
6.2 Rules
- Hover/focus transitions:
--motion-fast. - Layout transitions (sheet, modal, accordion):
--motion-base. - Entrance animations (once per session):
--motion-slowwith--ease-emphasis. - Respect
prefers-reduced-motion: reduce— drop all non-essential motion. - Never animate color on scroll. Never parallax. No marquee.
6.3 The "hatch" moment
When a token graduates, play one 600ms sequence: scale 0.98→1.02→1, yolk ring pulse. Once. Ever.
7. Components
All components live in packages/ui/src/. Primitives wrap Radix; compositions are bespoke. No raw <div> for buttons.
7.1 Button
primary— yolk fill, black text,font-medium,rounded-md,px-5 py-2.5.secondary— border +hover:bg-accent.ghost— no border,hover:bg-accent.destructive— destructive fill, confirmation required.link— foreground text, underline on hover.
States: focus-visible ring = ring-2 ring-ring ring-offset-2 ring-offset-background. No outline: none without replacement.
7.2 Card
bg-background border border-border/60 rounded-lg shadow-xs
Hover: shadow-sm transition-shadow. Card title = title token.
7.3 Chip / Tag
- Height
h-6,px-2,rounded-full,captiontype, borderborder-border/60. - Live-state chip: leading dot
h-1.5 w-1.5 rounded-full bg-hatch-yolk animate-pulse(reduced-motion: no pulse).
7.4 Input
- Height
h-10,rounded-md,border-border,focus-visible:ring-2 ring-ring. - Error state:
border-destructive+ helper texttext-destructive. - Never a red background — only border + text.
7.5 Score display
- Numeric score in 700 tabular-nums,
display-lgsize. - Band chip inline-right.
- "Why?" link — ghost button,
captionsize. Opens explainability modal (Sprint C.4).
7.6 Toast
Top-right, shadow-md, auto-dismiss 6s success / never error. One at a time — collapse queue.
8. Iconography
- lucide-react is the only icon set.
- Stroke
1.5, size by context:16inline,20buttons,24headers. currentColorfill — never baked-in color.- Never mix icon sets.
9. Imagery & Illustration
- Launch-specific: Claude Vision-scored creator images shown at native aspect,
rounded-lg, 1px border. - Marketing: abstract, low-contrast grain textures only. No stock photography of people. No 3D renders of coins.
- The only brand illustration is the
🥚 → 🐣 → 🐥lifecycle, used once per surface max.
10. Content & Voice
10.1 Tone
- Plain > clever. "Verified buyer" not "Chad-tier degen."
- Numbers > adjectives. "Graduation rate: 38%" not "Strong graduation."
- Active > passive. "Hatch scores your token" not "Your token is scored by Hatch."
10.2 Case
- Sentence case everywhere (buttons, headings, nav).
Launch a tokennotLaunch A Token. - ALL CAPS only for 2-letter locale tags and on-chain opcodes in docs.
10.3 Numbers
- Thousands separator always:
1,234. - Percents:
38%not38 percent. - BNB amounts: 4 decimal places max in UI, full in receipts.
- Addresses:
0x1234…abcdtruncation in UI, full on hover + copy-button.
10.4 Bilingual rules
- EN primary in keys; 中 lives in
messages/zh.jsonwith full parity. - Same key → same meaning. No CN-only copy hacks.
- Numbers + addresses are locale-independent.
- Punctuation: CJK full-width
,。!?in zh; ASCII in en.
11. Accessibility
- WCAG 2.1 AA baseline; AAA for on-chain irreversible actions.
- Every interactive element has a visible focus ring.
- Every form field has an associated label (visible or sr-only).
- Min tap target:
44×44on mobile. - Landmark roles on header/nav/main/footer.
- Live regions for score updates, toast announcements.
- Color is never the sole signal — pair with icon + text.
Audit in CI via axe-core (Sprint A.3 gate).
12. Dark mode
Not a theme — a first-class surface. Every component is designed in both.
Rules:
- Yolk stays yolk in dark mode (same HSL).
- Borders get more opacity (
border/60→border/80). - Shadows lose 50% opacity.
- No pure
#000background — use240 10% 4%.
13. OG & social
- OG image template:
1200×630, yolk background, wordmark top-left, headline 64/72, no emoji. - Twitter card = summary_large_image.
- Each locale gets its own OG render. No "English OG on Chinese page."
14. Do / Don't cheatsheet
DO
- One clear CTA per viewport.
- Numbers in tabular-nums.
text-balanceon headings.- Border-first over shadow-first.
- Respect reduced-motion.
DON'T
- Gradients across full sections.
- Rocket, moon, fire emojis.
- Multiple accent colors in one card.
- Custom pixel values outside the spacing scale.
- Italics for emphasis.
15. Evolution
Design system is versioned. Every token change is a PR with:
- Before / after screenshot.
- Contrast audit diff.
- RTL / CJK spot check.
packages/uiStorybook (once stood up in Sprint F.*) regenerated.
Tag: design-vX.Y.Z. Current: v1.0.0.