# UMBRA Design System & Stylesheet > This document defines the visual language for every page in UMBRA. > All frontend work MUST conform to these patterns. Do not invent new colors, spacing scales, or component styles. --- ## Visual Reference The dashboard establishes the canonical look: a near-black canvas with thin-bordered cards, cyan accent highlights, the Sora/DM Sans type pairing, and subtle glow effects on interactive elements. Every page should feel like a natural extension of this dashboard. **Key visual characteristics:** - Ultra-dark background (~#0a0a0a) with very subtle card elevation (#0d0d0d cards) - Thin 1px borders in dark gray (#262626) - never heavy or prominent - Accent color (default cyan) used sparingly: active nav, stat icons, today highlights, hover glows - High-contrast white text on dark, with muted gray (#a3a3a3) for secondary content - Cards have a gentle hover glow (`shadow-accent/5`) - not dramatic, just a hint of life - Clean data-dense layouts with compact spacing - no wasted space - Type badges and priority pills use color-coded backgrounds at 10% opacity (e.g. `bg-blue-500/10 text-blue-400`) --- ## 1. Color Tokens (CSS Custom Properties) All colors use HSL format via CSS variables. Never hardcode hex values. ### Surface Colors | Token | HSL | Approx Hex | Usage | |---|---|---|---| | `--background` | `0 0% 3.9%` | `#0a0a0a` | Page background | | `--card` | `0 0% 5%` | `#0d0d0d` | Card/panel surfaces | | `--card-elevated` | `0 0% 7%` | `#121212` | Hover states, elevated surfaces | | `--secondary` | `0 0% 10%` | `#1a1a1a` | Secondary backgrounds, muted surfaces | | `--muted` | `0 0% 10%` | `#1a1a1a` | Disabled/muted backgrounds | ### Text Colors | Token | HSL | Approx Hex | Usage | |---|---|---|---| | `--foreground` | `0 0% 98%` | `#fafafa` | Primary text | | `--muted-foreground` | `0 0% 63.9%` | `#a3a3a3` | Secondary/subtle text | ### Border & Input | Token | HSL | Approx Hex | Usage | |---|---|---|---| | `--border` | `0 0% 14.9%` | `#262626` | All borders, dividers | | `--input` | `0 0% 14.9%` | `#262626` | Input borders | ### Semantic Colors | Token | HSL | Usage | |---|---|---| | `--destructive` | `0 62.8% 30.6%` | Delete actions, errors | | `--primary` / `--accent-color` / `--ring` | Dynamic (accent HSL) | Primary actions, focus rings | ### Accent System (Dynamic) The accent is composed of three root variables set at runtime by `useTheme`: - `--accent-h` (hue) - `--accent-s` (saturation) - `--accent-l` (lightness) These feed into `--primary`, `--ring`, and `--accent-color`. **Presets:** | Name | H | S | L | Approx Color | |---|---|---|---|---| | `cyan` (default) | 187 | 85.7% | 53.3% | Teal-cyan | | `blue` | 217 | 91.2% | 59.8% | Bright blue | | `purple` | 258 | 89.5% | 66.3% | Violet | | `orange` | 21 | 94.6% | 53.3% | Warm orange | | `green` | 142 | 70.6% | 45.3% | Emerald | ### Semantic Color Assignments (Fixed per feature) These are NOT theme-dependent. They provide visual consistency for item types: | Feature | Text | Background | Usage | |---|---|---|---| | Todos | `text-blue-400` | `bg-blue-500/10` | Todo badges, type indicators | | Events | `text-purple-400` | `bg-purple-500/10` | Event badges, calendar items | | Reminders | `text-orange-400` | `bg-orange-500/10` | Reminder badges | | Projects | `text-blue-400` | `bg-blue-500/10` | Project counts | | In Progress | `text-purple-400` | `bg-purple-500/10` | Status indicators | | Open Todos | `text-teal-400` | `bg-teal-500/10` | Stat cards | | Weather | `text-amber-400` | `bg-amber-500/10` | Weather widget | | High priority | `text-red-400` | `bg-red-500/10` | Priority pills | | Medium priority | `text-yellow-400` | `bg-yellow-500/10` | Priority pills | | Low priority | `text-green-400` | `bg-green-500/10` | Priority pills | --- ## 2. Typography ### Font Families - **Headings:** `Sora` (`font-heading`) — all h1-h6, card titles, stat values, logo - **Body:** `DM Sans` (`font-body`) — everything else ### Type Scale (as used) | Class | Usage | |---|---| | `text-[9px]` | Micro labels (priority badges, type tags) | | `text-[10px] tracking-wider uppercase` | Stat labels | | `text-[11px]` | Small metadata | | `text-xs` | Timestamps, secondary metadata | | `text-sm` | Body text, list items, form inputs, nav items | | `text-lg font-semibold` | Card titles (with `font-heading`) | | `text-xl font-bold tabular-nums` | Stat values (with `font-heading`) | | `text-3xl font-bold tracking-tight` | Page greeting/hero (with `font-heading`) | ### Font Rendering ```css font-feature-settings: "rlig" 1, "calt" 1; -webkit-font-smoothing: antialiased; ``` --- ## 3. Spacing & Layout ### Border Radius | Token | Value | Usage | |---|---|---| | `rounded-lg` | `0.5rem` (8px) | Cards, panels | | `rounded-md` | `~6px` | Buttons, inputs | | `rounded-sm` | `~4px` | Small elements | | `rounded-full` | Pill | Badges, dots, icon containers | ### Page Layout ``` App Shell: flex h-screen overflow-hidden bg-background ├── Sidebar: w-64 (expanded) / w-16 (collapsed), border-r, bg-card │ transition-all duration-300 └── Content: flex-1 flex flex-col overflow-hidden ├── MobileHeader: md:hidden, h-14, border-b, bg-card └──
: flex-1 overflow-y-auto └── Page content: px-6 py-6 ``` ### Grid Patterns | Pattern | Classes | Usage | |---|---|---| | Stat row | `grid gap-2.5 grid-cols-2 lg:grid-cols-4` | Dashboard stats | | Main + sidebar | `grid gap-5 lg:grid-cols-5` → `lg:col-span-3` + `lg:col-span-2` | Dashboard layout | | Card grid | `grid gap-4 md:grid-cols-2 lg:grid-cols-3` | List pages (people, locations, projects) | ### Standard Spacing - Page padding: `px-6 py-6` - Card padding: `p-5` (header), `p-5 pt-0` (content/footer) - Card gap in grid: `gap-4` to `gap-5` - List row padding: `py-1.5 px-2` - Section gap: `space-y-4` to `space-y-6` --- ## 4. Component Patterns ### Card ``` Base: rounded-lg border bg-card text-card-foreground shadow-sm Hover: hover:shadow-lg hover:shadow-accent/5 hover:border-accent/20 Motion: transition-all duration-200 Header: flex flex-col space-y-1.5 p-5 Title: font-heading text-lg font-semibold leading-none tracking-tight Content: p-5 pt-0 Footer: flex items-center p-5 pt-0 ``` ### Button (CVA variants) ``` Base: inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:ring-ring Variants: default: bg-accent text-accent-foreground hover:bg-accent/90 destructive: bg-destructive text-destructive-foreground hover:bg-destructive/90 outline: border border-input bg-background hover:bg-accent/10 hover:text-accent secondary: bg-secondary text-secondary-foreground hover:bg-secondary/80 ghost: hover:bg-accent/10 hover:text-accent link: text-accent underline-offset-4 hover:underline Sizes: default: h-10 px-4 py-2 sm: h-9 px-3 lg: h-11 px-8 icon: h-10 w-10 ``` ### Badge ``` Base: inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold Variants: default: border-transparent bg-accent text-accent-foreground secondary: border-transparent bg-secondary text-secondary-foreground destructive: border-transparent bg-destructive text-destructive-foreground outline: text-foreground ``` ### Input / Select / Textarea ``` h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ``` ### Dialog ``` Overlay: fixed inset-0 bg-background/80 backdrop-blur-sm Content: border bg-card p-6 shadow-lg rounded-lg max-w-xl Header: flex flex-col space-y-1.5 Title: text-lg font-semibold leading-none tracking-tight Footer: flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 Close: absolute right-4 top-4, X icon h-4 w-4 ``` ### Empty State ``` Container: flex flex-col items-center justify-center py-16 px-4 Icon: rounded-full bg-muted p-4 mb-4, icon h-8 w-8 text-muted-foreground Title: text-lg font-semibold mb-1 Desc: text-sm text-muted-foreground text-center max-w-sm mb-4 Action: