Initial commit: Second Brain Platform

Complete platform with unified design system and real API integration.

Apps: Dashboard, Fitness, Budget, Inventory, Trips, Reader, Media, Settings
Infrastructure: SvelteKit + Python gateway + Docker Compose
This commit is contained in:
Yusuf Suleman
2026-03-28 23:20:40 -05:00
commit d3e250e361
159 changed files with 44797 additions and 0 deletions

View File

@@ -0,0 +1,324 @@
# Design System — Token Reference
> Source of truth: `src/app.css`
> Last updated: 2026-03-27
All UI values must come from these tokens unless listed under [Intentional Raw Values](#intentional-raw-values).
---
## Spacing
4px grid. Token name = multiplier (`--sp-3` = 3 × 4px = 12px).
| Token | Value | Use for |
|-------|-------|---------|
| `--sp-0` | 0px | Explicit zero |
| `--sp-px` | 1px | Borders, hairlines |
| `--sp-0.5` | 2px | Micro-nudge (margin-top on meta text) |
| `--sp-1` | 4px | Tight gap, field label gap, small padding |
| `--sp-1.5` | 6px | Badge gap, icon gap, footer gap |
| `--sp-2` | 8px | Compact gap, button group gap, inner padding |
| `--sp-3` | 12px | Standard gap, row padding, list item gap |
| `--sp-4` | 16px | Card padding (mobile), section margin, tab margin |
| `--sp-5` | 20px | Card padding (desktop), module gap, sidebar gap |
| `--sp-6` | 24px | Large padding, overlay padding, page container |
| `--sp-7` | 28px | Primary card padding, section group margin |
| `--sp-8` | 32px | Page top padding, empty state, desktop grid gap |
| `--sp-10` | 40px | Large elements (avatar width), empty list padding |
| `--sp-12` | 48px | Empty state padding, large spacing |
| `--sp-16` | 64px | Reserved |
| `--sp-20` | 80px | Page bottom padding (scroll clearance) |
### Semantic spacing aliases
| Token | Resolves to | Use for |
|-------|-------------|---------|
| `--section-gap` | `--sp-7` (28px) | Gap between major page sections |
| `--card-pad` | `--sp-5` (20px) | Default module/card padding |
| `--card-pad-primary` | `--sp-7` (28px) | Hero/primary module padding |
| `--card-pad-secondary` | `--sp-4` (16px) | Compact card padding |
| `--row-gap` | `--sp-3` (12px) | Gap between list rows |
| `--module-gap` | `--sp-5` (20px) | Gap between dashboard modules |
| `--row-pad-y` | 14px | Vertical padding inside data rows (off-grid, intentional) |
| `--row-pad-x` | `--sp-4` (16px) | Horizontal padding inside data rows |
| `--inner-gap` | `--sp-3` (12px) | Gap between items within a row |
### Mobile overrides (≤768px)
| Token | Desktop | Mobile |
|-------|---------|--------|
| `--card-pad` | 20px | 16px |
| `--card-pad-primary` | 28px | 20px |
| `--row-pad-y` | 14px | 16px |
| `--section-gap` | 28px | 20px |
---
## Radius
| Token | Value | Use for |
|-------|-------|---------|
| `--radius-xs` | 4px | Tiny pills, skeleton placeholders, kbd hints |
| `--radius-sm` | 6px | Badges, chips, nav links, danger buttons |
| `--radius-md` | 8px | Buttons, inputs, tabs, entry rows, icon containers |
| `--radius` | 12px | Cards, modals, panels, main containers |
| `--radius-lg` | 16px | Hero cards, action cards, pill chips, ImmichPicker modal |
| `--radius-full` | 9999px | Circles, toggles, avatars |
---
## Elevation (Shadows)
Light and dark mode have separate values. Dark mode uses higher opacity.
| Token | Light | Use for |
|-------|-------|---------|
| `--shadow-xs` | `0 1px 2px rgba(0,0,0,0.03)` | Row hover, active tabs, inner elements |
| `--shadow-sm` | `0 1px 3px rgba(0,0,0,0.04), 0 4px 12px rgba(0,0,0,0.04)` | Secondary cards, inputs, budget tables |
| `--shadow-md` | `0 2px 6px rgba(0,0,0,0.04), 0 8px 24px rgba(0,0,0,0.06)` | Standard card elevation (default `.module`) |
| `--shadow-lg` | `0 4px 12px rgba(0,0,0,0.06), 0 16px 40px rgba(0,0,0,0.1)` | Hero cards, primary modules, dropdowns |
| `--shadow-xl` | `0 8px 24px rgba(0,0,0,0.08), 0 24px 60px rgba(0,0,0,0.15)` | Modals, overlay panels |
**Legacy aliases**: `--card-shadow``--shadow-md`, `--card-shadow-sm``--shadow-sm`
---
## Colors
### Surfaces (3-layer depth)
| Token | Light | Dark | Layer |
|-------|-------|------|-------|
| `--canvas` | `#F5F6F8` | `#09090b` | Page background — everything sits on this |
| `--surface` | `#FFFFFF` | `#0f0f12` | Sidebars, panels, slide-out sheets |
| `--surface-secondary` | `#FAFAFB` | `#111114` | Input backgrounds, secondary panels |
| `--card` | `#FFFFFF` | `#161619` | Content containers, elevated with shadow |
| `--card-secondary` | `#FAFAFB` | `#111114` | Secondary cards, button backgrounds |
| `--card-hover` | `#f0f0f3` | `#1c1c20` | Row hover, interactive feedback |
### Borders
| Token | Light | Dark |
|-------|-------|------|
| `--border` | `rgba(0,0,0,0.06)` | `rgba(255,255,255,0.06)` |
| `--border-strong` | `rgba(0,0,0,0.1)` | `rgba(255,255,255,0.1)` |
### Text hierarchy
| Token | Light | Dark | Use for |
|-------|-------|------|---------|
| `--text-1` | `#1a1a1f` | `#fafafa` | Headings, names, amounts — read first |
| `--text-2` | `#4a4a55` | `#a1a1aa` | Body text, descriptions — read second |
| `--text-3` | `#6b6b76` | `#71717a` | Labels, metadata, captions — supporting |
| `--text-4` | `#b4b4bd` | `#3f3f46` | Placeholders, disabled, timestamps — background |
### Accent (indigo / blue)
| Token | Light | Dark | Use for |
|-------|-------|------|---------|
| `--accent` | `#4F46E5` | `#3b82f6` | Primary actions, links, active states |
| `--accent-bg` | `#EEF2FF` | `rgba(59,130,246,0.1)` | Icon wells, strong highlight backgrounds |
| `--accent-dim` | `rgba(79,70,229,0.06)` | `rgba(59,130,246,0.08)` | Subtle hover, selection backgrounds, focus rings |
| `--accent-border` | `rgba(79,70,229,0.10)` | `rgba(59,130,246,0.12)` | Accent-tinted borders |
| `--accent-focus` | `rgba(79,70,229,0.12)` | `rgba(59,130,246,0.15)` | Active states, selection bars |
### Semantic colors
| Token | Light | Dark | Use for |
|-------|-------|------|---------|
| `--success` | `#16A34A` | `#22c55e` | Positive values, income, completed |
| `--success-bg` | `#F0FDF4` | `rgba(34,197,94,0.1)` | Icon wells |
| `--success-dim` | `rgba(34,197,94,0.08)` | `rgba(34,197,94,0.08)` | Badge backgrounds |
| `--error` | `#DC2626` | `#ef4444` | Errors, issues, delete actions |
| `--error-bg` | `#FEF2F2` | `rgba(239,68,68,0.1)` | Icon wells |
| `--error-dim` | `rgba(239,68,68,0.08)` | `rgba(239,68,68,0.08)` | Badge backgrounds |
| `--warning` | `#d97706` | `#f59e0b` | Warnings, pending states |
| `--warning-bg` | `rgba(245,158,11,0.08)` | `rgba(245,158,11,0.1)` | Badge backgrounds |
### Overlay
| Token | Light | Dark | Use for |
|-------|-------|------|---------|
| `--overlay` | `rgba(0,0,0,0.3)` | `rgba(0,0,0,0.6)` | Modal backdrop, reading pane overlay |
| `--overlay-strong` | `rgba(0,0,0,0.5)` | `rgba(0,0,0,0.75)` | Heavy overlays |
| `--nav-bg` | `rgba(255,255,255,0.9)` | `rgba(15,15,18,0.9)` | Navbar blur background |
---
## Typography
| Token | Desktop | Mobile (≤768px) | Use for |
|-------|---------|-----------------|---------|
| `--text-xs` | 11px | 12px | Badges, pills, tiny counters |
| `--text-sm` | 13px | 15px | Labels, meta, captions, button text |
| `--text-base` | 14px | 16px | Body text, list items, inputs |
| `--text-md` | 15px | 17px | Card titles, important rows (16px+ avoids iOS zoom) |
| `--text-lg` | 17px | 18px | Section headers, modal titles |
| `--text-xl` | 22px | 22px | Page titles |
| `--text-2xl` | 28px | 26px | Hero headings |
| `--text-3xl` | 36px | 32px | Large hero numbers |
### Line heights
| Token | Value | Use for |
|-------|-------|---------|
| `--leading-tight` | 1.2 | Headings, hero numbers |
| `--leading-snug` | 1.35 | Card titles, compact text |
| `--leading-normal` | 1.5 | Body text |
| `--leading-relaxed` | 1.65 | Article content |
| `--leading-loose` | 1.8 | Long-form reading |
### Fonts
| Token | Value |
|-------|-------|
| `--font` | `'Inter', -apple-system, system-ui, sans-serif` |
| `--mono` | `'JetBrains Mono', ui-monospace, monospace` |
---
## Global Component Classes
Defined in `app.css`, usable in any component without local `<style>` duplication.
| Class | Description |
|-------|-------------|
| `.module` | Card container (bg, border, shadow, padding) |
| `.module.primary` | Hero card (more padding + elevation) |
| `.module.flush` | No padding (for flush content) |
| `.module-header` | Flex header row (title left, action right) |
| `.module-title` | Uppercase label |
| `.module-action` | Accent link → "View all →" |
| `.data-row` | Standard list item with hover + zebra striping |
| `.badge` + `.error/.success/.warning/.accent/.muted` | Semantic status badges |
| `.tab-bar` + `.tab` + `.tab-badge` | Pill-style tab navigation |
| `.section-label` | Uppercase group header |
| `.btn-primary` / `.btn-primary.full` | Primary action buttons |
| `.btn-secondary` | Secondary action buttons |
| `.btn-icon` | Square icon button (36×36) |
| `.input` | Standard text input |
| `.skeleton` | Shimmer loading placeholder |
| `.page` / `.page-header` / `.page-title` / `.page-greeting` | Page-level layout |
| `.app-surface` | Centered max-width container |
---
## Intentional Raw Values
These values exist outside the token system by design. Do not convert them.
### Non-scale spacing
Values that don't land on the 4px grid. Used for optical tuning where grid steps are too coarse.
| Value | Where | Why |
|-------|-------|-----|
| `1px` | `margin-top` on meta text, feed separators | Sub-pixel nudge for vertical alignment |
| `3px` | Badge padding-y, kbd padding | Optical centering within small elements |
| `5px` | Pill padding-y, chip padding | Between sp-1 (4px) and sp-1.5 (6px), tuned per element |
| `7px` | View-btn padding-y, sidebar gap | Between sp-1.5 (6px) and sp-2 (8px) |
| `9px` | Nav item padding-y, suggestion row padding-y | Between sp-2 (8px) and 10px |
| `10px` | Input padding-y, dropdown padding, various gaps | Common "comfortable touch" size, between sp-2 and sp-3 |
| `11px` | Entry row padding-y, toggle btn padding-bottom | Asymmetric optical alignment |
| `13px` | FAB action padding-y, list row padding | Between sp-3 (12px) and 14px |
| `14px` | Button padding-x, row padding-x, modal gap, field row gap | Most common off-grid value. Used as standard horizontal rhythm for interactive elements. Also `--row-pad-y` for data rows. |
| `15px` | Transaction row padding-y | Between sp-3.5 and sp-4, tuned for readability |
| `18px` | Detail header margin-bottom, AI guide padding-top | Between sp-4 (16px) and sp-5 (20px) |
| `22px` | Trip stats padding-x, modal body padding | Between sp-5 (20px) and sp-6 (24px) |
### Non-scale border-radius
| Value | Where | Why |
|-------|-------|-----|
| `9px` | Status segment control inner radius | Between radius-md (8px) and radius (12px) |
| `10px` | Event cards, photo thumbnails, notes, modals, unscheduled items, food rows | Heavily used "soft card" radius. Between radius-md (8px) and radius (12px). |
| `14px` | CommandPalette box, toggle track | Large interactive controls |
| `20px` | Bottom sheet top corners | Extra-round for sheet feel |
| `50%` | Circular elements (cover nav dots, meal-number, image-delete) | True circle, differs from radius-full on non-square elements |
### Data visualization colors
These are visual category identifiers, not semantic UI colors. They must remain consistent within their visualization set, independent of theme.
**Fitness macros:**
| Color | Hex | Use |
|-------|-----|-----|
| Protein | `#8B5CF6` | Purple macro bar |
| Carbs | `#F59E0B` | Amber macro bar |
| Fat | `#3B82F6` | Blue macro bar |
**Fitness meal weights:**
| Color | Background | Text | Meaning |
|-------|------------|------|---------|
| Heavy | `rgba(239,68,68,0.1)` | `#DC2626` | High-calorie meal |
| Moderate | `rgba(245,158,11,0.1)` | `#B45309` | Medium-calorie meal |
| Light | `rgba(34,197,94,0.1)` | `#15803D` | Low-calorie meal |
**Trip categories:**
| Color | Background | Text | Category |
|-------|------------|------|----------|
| Hotel | `rgba(168,85,247,0.1)` | `#a855f7` | Lodging |
| Restaurant | `rgba(249,115,22,0.1)` | `#f97316` | Food & dining |
| Hike | `rgba(34,197,94,0.15)` | `#16a34a` | Outdoor activity |
| Logistics | `rgba(161,161,170,0.1)` | `--text-3` | Transport, other |
**Other:**
| Color | Hex | Use |
|-------|-----|-----|
| Favorite star | `#F59E0B` | Star icon fill (reader, fitness) |
| AI badge | `rgba(59,130,246,0.1)` / `#3B82F6` | AI-logged entry indicator |
| Transfer pill | `rgba(59,130,246,0.1)` / `#3b82f6` | Budget transfer indicator |
### Glass & overlay effects
Applied to elements layered over images. Not theme-switchable because they depend on photo content, not UI surface.
| Value | Where |
|-------|-------|
| `rgba(0,0,0,0.7)..0.1` | Cover image gradient (trips) |
| `rgba(255,255,255,0.15)` | Cover nav button background |
| `rgba(255,255,255,0.3)` | Cover nav button hover |
| `rgba(0,0,0,0.3)` / `rgba(0,0,0,0.5)` | Cover share button / hover |
| `rgba(0,0,0,0.35)` | Modal overlays (trips), detail overlay (inventory) |
| `rgba(0,0,0,0.5)` | Image delete button, search saving overlay |
### Directional panel shadows
Non-standard shadow directions for slide-in panels and bottom sheets. Cannot use elevation tokens.
| Value | Where |
|-------|-------|
| `0 -8px 32px rgba(0,0,0,0.12)` | FAB bottom sheet (fitness, trips) |
| `-12px 0 40px rgba(0,0,0,0.12)` | Detail slide-in sheet (inventory) |
| `-6px 0 28px rgba(0,0,0,0.08)` | Reading pane (reader) |
| `-8px 0 32px rgba(0,0,0,0.1)` | Edit sheet (trips) |
| `8px 0 24px rgba(0,0,0,0.08)` | Mobile sidebar (reader) |
### Accent-tinted FAB shadows
Colored shadows for floating action buttons. Not in the elevation scale because they use accent color, not black.
| Value | Where |
|-------|-------|
| `0 8px 24px rgba(79,70,229,0.3)` | FAB resting (fitness) |
| `0 12px 32px rgba(79,70,229,0.4)` | FAB hover (fitness) |
| `0 6px 20px rgba(79,70,229,0.3)` | FAB resting (trips) |
| `0 8px 28px rgba(79,70,229,0.4)` | FAB hover (trips) |
### Near-match shadows
Shadows that are close to tokens but intentionally differ in blur radius or opacity.
| Value | Nearest token | Diff |
|-------|--------------|------|
| `0 2px 6px rgba(0,0,0,0.05)` | `--shadow-xs` | Larger blur, higher opacity |
| `0 1px 2px rgba(0,0,0,0.04)` | `--shadow-xs` | Opacity 0.04 vs 0.03 |
| `0 1px 4px rgba(0,0,0,0.04)` | `--shadow-xs` | Larger blur |
| `0 1px 4px rgba(0,0,0,0.08)` | `--shadow-xs` | Larger blur + opacity |
| `0 16px 48px rgba(0,0,0,0.15)` | `--shadow-xl` | Single layer vs dual |
| `0 1px 3px rgba(0,0,0,0.06)` | `--shadow-xs` | Higher opacity |
| `0 8px 24px rgba(0,0,0,0.12)` | `--shadow-md` | Higher opacity |
| `0 20px 60px rgba(0,0,0,0.15)` | `--shadow-xl` | Single layer |
| `0 20px 60px rgba(0,0,0,0.2)` | `--shadow-xl` | Single layer, higher opacity |
| `0 1px 3px rgba(0,0,0,0.15)` | `--shadow-sm` | Toggle thumb, much higher opacity |