DESIGN-SYSTEM — Cetking Universe UI language (v1.0, 6 Oct 2026)
The shared look, parts and rules for every Universe page. Any AI tool or coder building UI reads this first. It sits on top of DESIGN.md (mascots, mood), MOTION.md (movement) and CARD-SYSTEM.md (cards and page layouts). If they disagree on a token or component, this file wins.
Code is the source of truth: if this file and the code differ, the code wins and this file is corrected in the same change.
1. Principles
- Apple-calm. White and light greys, dark-grey text, lots of space. Nothing shouts except the one main action.
- Greys for UI, colour for bots. Every button, tab, chip and line is a grey. Only the six mascots (and their soft glows) carry colour.
- One main action per card. One dark pill. Everything else is quieter.
- Same parts everywhere. A tab looks the same on every page; a button is always
PrimaryButton. No one-off styles. - Mobile first. Designed at 400px wide, then scaled up.
- Both themes. Every new colour must work in light and dark (section 2.6).
2. Tokens
Tokens are CSS custom properties. Use var(--token), never a raw hex in a component, except
mascot colours (which come from config/companions.config.ts).
Where they live:
app/globals.css— base colours, motionapp/theme.css— tab/toggle tokens, dark theme values, dark fixesconfig/companions.config.ts— bot names and colours (BOTS[domain].color,.gradient)
2.1 Colour
| Token | Light | Dark | Use |
|---|---|---|---|
--bg |
#ffffff |
#0c0c0d |
Page background |
--surface |
#ffffff |
#1c1c1e |
Cards |
--surface-2 |
#f5f5f7 |
#2c2c2e |
Depth: chips, inner panels, role chip |
--ink |
#1d1d1f |
#f5f5f7 |
Main text, headings |
--muted |
#6e6e73 |
#a1a1a6 |
Secondary text |
--dim |
#aeaeb2 |
#6e6e73 |
Quiet text, hints |
--line |
rgba(0,0,0,.08) |
rgba(255,255,255,.1) |
Borders, dividers |
Tabs and toggles (section 3.3):
| Token | Light | Dark |
|---|---|---|
--seg-track |
#f2f2f2 |
rgba(255,255,255,.08) |
--seg-pill |
#ffffff |
#3a3a3c |
--seg-pill-border |
rgba(0,0,0,.07) |
rgba(255,255,255,.08) |
--seg-pill-shadow |
soft 2-layer shadow | 0 1px 2px rgba(0,0,0,.3) |
--seg-text |
#6e6e73 |
#a1a1a6 |
--seg-text-on |
#111111 |
#ffffff |
Mascot colours (only for bots, glows, the bot's role-chip tint):
| Bot | Colour | Shape |
|---|---|---|
| Oracle (home) | #4029cb indigo |
round |
| Veda (Quant) | #fbc815 yellow |
tilted egg |
| Shabda (Verbal) | #8b5cf6 purple |
teardrop |
| Tarka (Logic & DILR) | #d90429 red |
jelly bean |
| Mocky (Mocks) | #66b3f7 light blue |
clay, 5 lobes |
| Purva (Admissions) | #f97316 orange |
cloud |
Never: blue links, coloured buttons, orange/indigo UI text, red error text (errors are grey cards with clear words).
2.2 Type
- Family:
Inter, system-ui, -apple-system, sans-serif(Tailwindfont-sans). Inter is not self-hosted yet, so phones show their system font (San Francisco / Roboto). Fine for now. - Scale (px, mobile → desktop):
| Role | Size | Weight | Example |
|---|---|---|---|
| Display | 32 → 72 | 900, tight tracking | "Learning Universe" |
| Page title | 30 → 40 | 900 | "Meet Veda" |
| Card title | 17–20 | 700 | "Live classes and recordings" |
| Body | 15–17 | 400–500 | Card copy |
| Button | 17 (pill), 15 (small) | 600–700 | "Start mock" |
| Tab | 14–17 | 600, selected 700 | "Classes" |
| Kicker | 11–13 uppercase, 0.2–0.3em tracking | 600–800 | "WELCOME HOME" |
| Caption | 12–13 | 400–600 | Terms line, hints |
- Numbers that line up (coins, ranks, dates):
font-variant-numeric: tabular-nums. - Phone inputs: 16px minimum (stops iPhone zoom).
2.3 Spacing
4px base. Common steps: 4, 8, 12, 16, 20, 24, 32, 40, 56. Page side gutter 16px on phones. Card padding 20px phone / 28px desktop. Gap between stacked cards 12–16px.
2.4 Radius
| Thing | Radius |
|---|---|
| Pills (buttons, tabs, chips, nav) | 9999px |
| Big cards (bot island, timetable card, login card) | 28px |
| Normal cards | 24px |
| Inner panels, inputs | 14–18px |
2.5 Shadow
Soft and low. Cards: 0 18px 50px -24px rgba(17,17,17,.25) or 0 10px 30px rgba(15,15,20,.06).
Nothing harder. Dark theme uses darker, larger shadows (see app/theme.css).
2.6 Dark theme
- Switch:
components/ThemeToggle.tsx(moon/sun left of the coins pill) sets<html data-theme="dark">. Saved per device inlocalStorage['ck-theme']; applied before first paint by a tiny script inapp/layout.tsx. - Light is the default. The site does not follow the phone's dark setting on its own.
- Tailwind
dark:classes follow the switch (darkMode: ['selector', '[data-theme="dark"]']). - New component colours: use tokens so dark works for free. If you must use a fixed colour,
add its dark version to
app/theme.csssection 4 in the same change.
2.7 Motion
See MOTION.md. Summary: UI moves under 250ms, ease-out cubic-bezier(.25,1,.5,1), no bounce on
UI, transform + opacity only, reduced-motion fades. Mascot loops and bounces are the deliberate
exception. Tokens: --ease-out, --dur-fast 150ms, --dur-base 200ms, --dur-slow 250ms.
3. Components
All live in cetking-one/components/. Reuse; don't copy.
3.1 PrimaryButton — the one call-to-action
components/ui/PrimaryButton.tsx + primary-button.css
- Dark satin pill in a recessed track, min 48px tall, 24px side padding, one 20px icon.
- Modes: link (
href) or action (onClickreturning a Promise → loading / success / error, blocks double taps, keeps width). - Labels: sentence-case actions ("Start mock", "Save changes"). Never "Click here", "OK".
- One per card. Small dark pill (
.tai-ctastyle) is allowed inside bot cards.
3.2 SiteNav — top bar
components/SiteNav.tsx + site-nav.css
- Floating translucent pill, 64px. Left: Oracle mini-bot + "Cetking" (goes home). Right: ThemeToggle, NavAccount (Login, or the student's coins → profile), 3-line menu.
- Menu card lists the five subject bots (not Oracle) + "Join us" PrimaryButton.
3.3 Segmented control — every tab and toggle
Look (Ravneet's "Chat | Work" reference): very light grey bar, white selected pill with a hair border and soft shadow, dark bold label; others grey.
- New code:
<div class="ck-seg" role="tablist">with<button role="tab" aria-selected>. - Existing users restyled in
app/theme.css: bot page tabs (.tai-tabs), Join for Free | Login (.ck-login-tabs), timetable All | CAT | CET, admissions exam/college tabs, profile exam toggles. - Rules: 2–4 options (bot pages), more only if they scroll; keyboard arrows move between tabs; never coloured.
3.4 Cards
- Bot island (
BotIsland.tsx): white card, segmented tabs, 2 lines of copy, exam chips, one small dark pill, 44px mascot signature bottom-right. - Timetable card (
components/timetable/TimetableCard.tsx): week strip, tabs, class list. - Profile cards (
components/profile/*): one card per profile block, edit in place. - Card sizes and lifecycles: CARD-SYSTEM.md.
3.5 Mascots
CompanionCharacterdraws any bot in SVG at any size (eyes = white pills, no mouth).CompanionDeck: the living tray. Tap = spotlight preview, tap again = open. Home shows the 5 subject bots;BotFootershows all 6 at the bottom of every other page.- Card signature size 44px; tray 64px; spotlight 136px; hero 130px.
3.6 Forms and login
OtpLogin(login card),QuickJoin(home "Mobile Number | Join for Free" bar).- Inputs: 16px text, 14–16px radius, grey border, darker grey on focus.
- Mobile number first, OTP second; never ask for anything else before OTP.
3.7 Other
SocialProofIndicator (footer avatars + marketing number), Reveal (scroll reveal),
BotTransition (jump + colour flood when opening a bot), ThemeToggle, NavAccount.
4. Patterns
- Page skeleton (bot pages): SiteNav → big bot → role chip → "Meet " → tagline →
bot island → About card → BotFooter. Shared via
BotSubPage.tsx; change it once for all. - Home: Oracle hero → "Learning Universe" → 5-bot tray → QuickJoin (signed out) → footer.
- Empty state: grey panel, one plain sentence of what will appear and when ("This week's Thane timetable is being updated. Please check back soon.").
- Errors: grey card, says what went wrong and what to do, plus a retry. Never red, never a
raw error code. Downtime is in-character (
lib/health/*). - Loading: skeletons the size of the real card; buttons keep their width.
- Privacy (opacity): never show user counts, view counts or "of N"; other students by username only. The footer marketing number is the one hand-set exception.
- Copy: plain, short, Hinglish taglines allowed for bots; buttons say exactly what happens.
5. Accessibility
- Contrast: body text ≥ 4.5:1 on its background in both themes (grey tokens above pass). Known weak spot: white eyes on yellow (Veda) and light blue (Mocky) mascots — decorative only.
- Tap targets ≥ 44px (nav buttons 40–44px, buttons 48px).
- Every icon-only button has an
aria-label(theme switch, menu). - Tabs use
role="tablist"/"tab",aria-selected, arrow-key movement. - Visible focus ring on every control (
:focus-visible). prefers-reduced-motion: animations become fades or stop.
6. Governance
- Owner: Ravneet approves anything students see. Bot names/colours change only in
config/companions.config.tsand only with his OK. - Change process: blue preview branch → screenshots light + dark at phone width → PR → "go live" → green (RELEASES.md).
- Versioning: this file has a version line. Bump the minor number for new tokens/components, the major for anything that changes existing looks; note it in MEMORY.md.
- Adding a component: put it in
components/, use tokens only, both themes, add it to section 3 here in the same change. - Deprecating: mark it here with a date and the replacement; remove after nothing uses it.
7. Tooling (now and next)
| Now | Next (when the team grows) |
|---|---|
| CSS custom properties + Tailwind 3.4 | Token JSON → generated CSS (one source) |
Shared React components in components/ |
Storybook page per component |
| Local build + Playwright phone screenshots before every PR | Automatic screenshot comparison (visual regression) in CI |
| Vercel preview per PR | Accessibility check (axe) in CI |
| Design System reference page (Claude artifact) | Figma library mirroring the tokens |
8. Do / Don't
| Do | Don't |
|---|---|
Use var(--ink), var(--muted) |
Write #333 in a component |
| One PrimaryButton per card | Two big buttons side by side |
| Grey tabs with white selected pill | Coloured or underlined tabs |
| Show the student's own data only | Show "1,240 students viewed this" |
| Test light and dark at 400px | Ship after checking only desktop light |
| Change the shared layout file | Copy a page and tweak it |