Appearance
Design Tokens
DoCurious uses a comprehensive design token system built on CSS custom properties. Tokens are defined in TypeScript (src/theme/defaults.ts), compiled to CSS variables via applyTheme.ts, and consumed throughout the app. Every token is available as a --variable on :root.
Source files:
src/theme/defaults.ts-- default token valuessrc/theme/types.ts-- TypeScript interfacessrc/theme/applyTheme.ts-- CSS variable injection
Brand Colors
The DoCurious palette draws from outdoor exploration: forest greens, warm golds, and natural earth tones.
Core Palette
| Token | CSS Variable | Default Value | Name | Usage |
|---|---|---|---|---|
primary | --primary | #3D5A3C | Scout Green | Buttons, active states, sidebar bg |
primaryHover | --primary-hover | #4A6B49 | -- | Primary hover state |
primaryActive | --primary-active | #2E4A2D | -- | Primary pressed state |
| -- | --primary-foreground | #ffffff | -- | Text on primary backgrounds |
accent | --accent | #D4A84B | Honey / Brass Gold | XP, rewards, highlights, badges |
accentHover | --accent-hover | #C89A3E | -- | Accent hover state |
secondary | --secondary | #5B8FA8 | Sky | Science, audio, secondary info |
secondaryHover | --secondary-hover | #4E7F96 | -- | Secondary hover state |
Background Colors
| Token | CSS Variable | Default Value | Name | Usage |
|---|---|---|---|---|
background | --background | #FAF8F3 | Cream | Page backgrounds (not pure white) |
backgroundSecondary | --background-secondary | #F3EFE6 | -- | Card backgrounds, alt sections |
Text Colors
| Token | CSS Variable | Default Value | Name | Usage |
|---|---|---|---|---|
text | --foreground | #1A1A1A | Ink | Primary body text (not pure black) |
textMuted | --foreground-muted | #6B6B6B | Stone | Secondary text |
border | --border | #E2DDD4 | -- | Warm light borders |
Status Colors
| Token | CSS Variable | Default Value | Usage |
|---|---|---|---|
error | --error | #D93025 | Form errors, destructive actions |
success | --success | #2E7D32 | Success states |
warning | --warning | #E07B5A | Warnings (Coral) |
Sidebar Colors
| Token | CSS Variable | Default Value | Usage |
|---|---|---|---|
sidebarBackground | --sidebar-bg | #3D5A3C | Scout Green background |
sidebarText | --sidebar-text | #FAF8F3 | Cream text |
sidebarTextMuted | --sidebar-text-muted | #B8C9B7 | Light green-tinted muted |
sidebarActiveBackground | --sidebar-active-bg | #4A6B49 | Active nav item |
sidebarActiveBorder | --sidebar-active-border | #D4A84B | Honey accent border |
Audience Accents
Each audience segment has a dedicated accent color for targeted UI elements.
| Token | CSS Variable | Default Value | Name | Audience |
|---|---|---|---|---|
accentB2C | --accent-b2c | #E07B5A | Coral | Parents & Kids |
accentSchools | --accent-schools | #D4A84B | Honey | Schools & Educators |
accentProviders | --accent-providers | #5B8FA8 | Sky | Activity Providers |
Typography
| Token | CSS Variable | Default Value | Usage |
|---|---|---|---|
fontFamily | --font-body | "Inter", -apple-system, ... | Body text, UI elements |
fontFamilyHeading | --font-heading | "Lexend", -apple-system, ... | All headings (h1--h6) |
fontFamilyMono | --font-mono | SFMono-Regular, Menlo, ... | Code blocks, data |
Heading Style Tokens
These tokens control heading appearance and vary per theme preset.
| CSS Variable | Default Value | Description |
|---|---|---|
--theme-heading-weight | 600 | Font weight for headings |
--theme-heading-letter-spacing | -0.01em | Letter spacing for headings |
--theme-heading-text-transform | none | Text transform (none, uppercase, capitalize) |
--theme-heading-border-bottom | none | Decorative heading underline |
Button Style Tokens
| CSS Variable | Default Value | Description |
|---|---|---|
--theme-button-radius | 0.5rem | Button border radius |
--theme-button-weight | 500 | Button font weight |
Spacing Scale
Spacing is density-aware. The density setting (compact, comfortable, spacious) selects a spacing multiplier set. Default is comfortable.
Density: compact
| CSS Variable | Value |
|---|---|
--theme-space-xs | 0.2rem |
--theme-space-sm | 0.35rem |
--theme-space-md | 0.5rem |
--theme-space-lg | 0.65rem |
--theme-space-xl | 0.85rem |
--theme-space-2xl | 1rem |
--theme-section-gap | 0.75rem |
--theme-card-padding | 0.75rem |
--theme-page-padding | 1rem |
Density: comfortable (default)
| CSS Variable | Value |
|---|---|
--theme-space-xs | 0.25rem |
--theme-space-sm | 0.5rem |
--theme-space-md | 0.75rem |
--theme-space-lg | 1rem |
--theme-space-xl | 1.25rem |
--theme-space-2xl | 1.5rem |
--theme-section-gap | 1rem |
--theme-card-padding | 1rem |
--theme-page-padding | 1.5rem |
Density: spacious
| CSS Variable | Value |
|---|---|
--theme-space-xs | 0.375rem |
--theme-space-sm | 0.625rem |
--theme-space-md | 1rem |
--theme-space-lg | 1.25rem |
--theme-space-xl | 1.75rem |
--theme-space-2xl | 2rem |
--theme-section-gap | 1.5rem |
--theme-card-padding | 1.25rem |
--theme-page-padding | 2rem |
Surface & Shadow Tokens
Cards and surfaces use layered shadows that vary per theme (flat, neumorphic, glassmorphic, neubrutalist, etc.).
| CSS Variable | Default Value | Description |
|---|---|---|
--theme-shadow-sm | 0 1px 2px rgba(0,0,0,0.05) | Small surface shadow |
--theme-shadow-md | 0 2px 8px rgba(0,0,0,0.08) | Medium surface shadow |
--theme-shadow-lg | 0 4px 16px rgba(0,0,0,0.10) | Large surface shadow |
--theme-card-shadow | 0 1px 3px rgba(0,0,0,0.08) | Card-specific shadow |
--theme-card-border-width | 1px | Card border thickness |
--theme-card-radius | 0.75rem | Card border radius |
--theme-card-bg | var(--background) | Card background (rgba for glass) |
--theme-card-backdrop-blur | 0 | Backdrop blur for glassmorphism |
--theme-card-accent-border | none | Top accent stripe on cards |
--theme-card-padding | 1rem | Card internal padding |
--theme-card-gap | 1rem | Gap between cards in grids |
Layout Tokens
| CSS Variable | Default Value | Description |
|---|---|---|
--theme-sidebar-width | 200px | Sidebar width |
--theme-sidebar-inset | 0px | Gap between sidebar and edges (0 = flush) |
--theme-sidebar-radius | 0 | Sidebar border radius (0 = sharp) |
--theme-nav-item-radius | 0 | Nav item border radius |
--theme-nav-item-border-width | 3px | Active nav item border |
--theme-topnav-height | 64px | Top navigation bar height |
--theme-content-max-width | 1400px | Main content area max width |
Border & Divider Tokens
| CSS Variable | Default Value | Description |
|---|---|---|
--theme-border-width | 1px | Default border width |
--theme-divider-style | solid | Divider line style (solid, dashed, dotted) |
--theme-input-radius | 0.5rem | Form input border radius |
--theme-input-border-width | 1px | Form input border width |
--theme-badge-radius | 9999px | Badge/tag border radius |
Motion Tokens
| CSS Variable | Default Value | Description |
|---|---|---|
--theme-transition | 0.2s | Default transition duration |
Background Texture
| CSS Variable | Default Value | Description |
|---|---|---|
--theme-bg-texture | none | Background image/gradient for page texture |
Themes use this for distinctive visual effects -- topo-map contour lines (Expedition), paper grain (Field Journal), aurora gradients (Stardust), etc.
Planned / Undefined Tokens
The following tokens have been identified as needed but do not yet have finalized values:
- Badge rarity colors: Common (Bronze), Uncommon (Silver), Rare (Gold), Epic (Purple), Legendary (Prismatic)
- Challenge difficulty: Beginner (Green), Intermediate (Yellow), Advanced (Orange)
- Journey Map region states: Unexplored, Discovered, Explored, Advanced, Mastered
- Category colors: Per-category colors for Journey Map regions
- Streak indicator: Flame colors by streak level (0/2/4/12+ weeks)
- Dark mode: Architecturally supported but no dark palette defined yet
Accessibility Notes
textMutedachieves 5.1:1 contrast ratio on white backgrounds, meeting WCAG AA- All status colors are paired with icons/text, never color-only indicators
- Badge rarity is distinguishable without color (border style, label, or icon)
- Celebration animations respect
prefers-reduced-motion
CSS Variable Reference (Complete)
For quick lookup, here is the full list of CSS variables injected by applyThemeVars():
css
/* Colors */
--primary, --primary-hover, --primary-active, --primary-foreground
--accent, --accent-hover
--secondary, --secondary-hover
--background, --background-secondary
--foreground, --foreground-muted
--border
--error, --success, --warning
--sidebar-bg, --sidebar-text, --sidebar-text-muted
--sidebar-active-bg, --sidebar-active-border
--accent-b2c, --accent-schools, --accent-providers
/* Typography */
--font-body, --font-heading, --font-mono
/* Card */
--theme-card-shadow, --theme-card-border-width, --theme-card-radius
--theme-card-bg, --theme-card-backdrop-blur, --theme-card-accent-border
--theme-card-padding, --theme-card-gap
/* Headings */
--theme-heading-weight, --theme-heading-letter-spacing
--theme-heading-text-transform, --theme-heading-border-bottom
/* Buttons */
--theme-button-radius, --theme-button-weight
/* Sidebar / Nav */
--theme-sidebar-width, --theme-sidebar-inset, --theme-sidebar-radius
--theme-nav-item-radius, --theme-nav-item-border-width
/* Shadows */
--theme-shadow-sm, --theme-shadow-md, --theme-shadow-lg
/* Borders */
--theme-border-width, --theme-divider-style
--theme-input-radius, --theme-input-border-width
--theme-badge-radius
/* Spacing (density-aware) */
--theme-space-xs, --theme-space-sm, --theme-space-md
--theme-space-lg, --theme-space-xl, --theme-space-2xl
--theme-section-gap, --theme-card-padding, --theme-page-padding
/* Layout */
--theme-content-max-width, --theme-topnav-height
/* Motion */
--theme-transition
/* Texture */
--theme-bg-texture