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

461
frontend-v2/src/app.css Normal file
View File

@@ -0,0 +1,461 @@
@import 'tailwindcss';
/* ═══════════════════════════════════════════════
DESIGN SYSTEM — Single source of truth
RULES:
1. No raw px in component <style> blocks — use tokens
2. No raw rgba/hex colors — use semantic tokens
3. No copy-pasting base component styles — use globals
4. Surface hierarchy: canvas → surface → card
5. Text hierarchy: text-1 → text-2 → text-3 → text-4
═══════════════════════════════════════════════ */
@layer base {
:root {
/* ── Fonts ── */
--font: 'Inter', -apple-system, system-ui, sans-serif;
--mono: 'JetBrains Mono', ui-monospace, monospace;
--transition: 180ms ease;
/* ── Spacing scale (4px grid) ──
* Use these everywhere: padding, margin, gap.
* Naming: --sp-{n} where value = n × 4px
*/
--sp-0: 0px;
--sp-px: 1px;
--sp-0.5: 2px;
--sp-1: 4px;
--sp-1.5: 6px;
--sp-2: 8px;
--sp-3: 12px;
--sp-4: 16px;
--sp-5: 20px;
--sp-6: 24px;
--sp-7: 28px;
--sp-8: 32px;
--sp-10: 40px;
--sp-12: 48px;
--sp-16: 64px;
--sp-20: 80px;
/* Semantic spacing aliases */
--section-gap: var(--sp-7);
--card-pad: var(--sp-5);
--card-pad-primary: var(--sp-7);
--card-pad-secondary: var(--sp-4);
--row-gap: var(--sp-3);
--module-gap: var(--sp-5);
--row-pad-y: 14px;
--row-pad-x: var(--sp-4);
--inner-gap: var(--sp-3);
/* ── Radius scale ── */
--radius-xs: 4px;
--radius-sm: 6px;
--radius-md: 8px;
--radius: 12px;
--radius-lg: 16px;
--radius-full: 9999px;
/* ── Elevation scale ──
* xs: barely visible (row hover, inner elements)
* sm: subtle lift (secondary cards, inputs)
* md: standard card elevation
* lg: elevated (dropdowns, popovers, hero cards)
* xl: overlay (modals, slide-out panels)
*/
--shadow-xs: 0 1px 2px rgba(0,0,0,0.03);
--shadow-sm: 0 1px 3px rgba(0,0,0,0.04), 0 4px 12px rgba(0,0,0,0.04);
--shadow-md: 0 2px 6px rgba(0,0,0,0.04), 0 8px 24px rgba(0,0,0,0.06);
--shadow-lg: 0 4px 12px rgba(0,0,0,0.06), 0 16px 40px rgba(0,0,0,0.1);
--shadow-xl: 0 8px 24px rgba(0,0,0,0.08), 0 24px 60px rgba(0,0,0,0.15);
/* Legacy aliases */
--card-shadow: var(--shadow-md);
--card-shadow-sm: var(--shadow-sm);
/* ── Typography scale ──
* xs: badges, pills, tiny counters
* sm: labels, meta, captions, button text
* base: body text, list items, inputs
* md: card titles, important rows (16px avoids iOS zoom)
* lg: section headers, modal titles
* xl: page titles
* 2xl: hero headings
* 3xl: large hero numbers
*/
--text-xs: 11px;
--text-sm: 13px;
--text-base: 14px;
--text-md: 15px;
--text-lg: 17px;
--text-xl: 22px;
--text-2xl: 28px;
--text-3xl: 36px;
/* Line heights */
--leading-tight: 1.2;
--leading-snug: 1.35;
--leading-normal: 1.5;
--leading-relaxed: 1.65;
--leading-loose: 1.8;
}
/* ── LIGHT MODE ── */
:root {
/* Surface hierarchy: canvas (page bg) → surface (sidebars, panels) → card (content containers) */
--canvas: #F5F6F8;
--surface: #FFFFFF;
--surface-secondary: #FAFAFB;
--card: #FFFFFF;
--card-secondary: #FAFAFB;
--card-hover: #f0f0f3;
/* Borders */
--border: rgba(0,0,0,0.06);
--border-strong: rgba(0,0,0,0.1);
/* Text hierarchy: 1 (headings/names) → 2 (body) → 3 (labels/meta) → 4 (placeholder/disabled) */
--text-1: #1a1a1f;
--text-2: #4a4a55;
--text-3: #6b6b76;
--text-4: #b4b4bd;
/* Accent — indigo */
--accent: #4F46E5;
--accent-bg: #EEF2FF;
--accent-dim: rgba(79,70,229,0.06);
--accent-border: rgba(79,70,229,0.10);
--accent-focus: rgba(79,70,229,0.12);
/* Semantic: success */
--success: #16A34A;
--success-bg: #F0FDF4;
--success-dim: rgba(34,197,94,0.08);
/* Semantic: error */
--error: #DC2626;
--error-bg: #FEF2F2;
--error-dim: rgba(239,68,68,0.08);
/* Semantic: warning */
--warning: #d97706;
--warning-bg: rgba(245,158,11,0.08);
/* Overlay */
--overlay: rgba(0,0,0,0.3);
--overlay-strong: rgba(0,0,0,0.5);
--nav-bg: rgba(255,255,255,0.9);
}
/* ── DARK MODE ── */
.dark {
--canvas: #09090b;
--surface: #0f0f12;
--surface-secondary: #111114;
--card: #161619;
--card-secondary: #111114;
--card-hover: #1c1c20;
--border: rgba(255,255,255,0.06);
--border-strong: rgba(255,255,255,0.1);
--text-1: #fafafa;
--text-2: #a1a1aa;
--text-3: #71717a;
--text-4: #3f3f46;
--accent: #3b82f6;
--accent-bg: rgba(59,130,246,0.1);
--accent-dim: rgba(59,130,246,0.08);
--accent-border: rgba(59,130,246,0.12);
--accent-focus: rgba(59,130,246,0.15);
--success: #22c55e;
--success-bg: rgba(34,197,94,0.1);
--success-dim: rgba(34,197,94,0.08);
--error: #ef4444;
--error-bg: rgba(239,68,68,0.1);
--error-dim: rgba(239,68,68,0.08);
--warning: #f59e0b;
--warning-bg: rgba(245,158,11,0.1);
--overlay: rgba(0,0,0,0.6);
--overlay-strong: rgba(0,0,0,0.75);
--nav-bg: rgba(15,15,18,0.9);
/* Dark shadows need higher opacity */
--shadow-xs: 0 1px 2px rgba(0,0,0,0.1);
--shadow-sm: 0 1px 3px rgba(0,0,0,0.15), 0 4px 12px rgba(0,0,0,0.1);
--shadow-md: 0 2px 6px rgba(0,0,0,0.15), 0 8px 24px rgba(0,0,0,0.12);
--shadow-lg: 0 4px 12px rgba(0,0,0,0.2), 0 16px 40px rgba(0,0,0,0.2);
--shadow-xl: 0 8px 24px rgba(0,0,0,0.25), 0 24px 60px rgba(0,0,0,0.3);
}
/* ── Base resets ── */
html, body {
font-family: var(--font);
background: var(--canvas);
color: var(--text-1);
min-height: 100vh;
transition: background var(--transition), color var(--transition);
-webkit-font-smoothing: antialiased;
}
* { border-color: var(--border); }
a { color: inherit; text-decoration: none; }
button { font-family: var(--font); cursor: pointer; }
input { font-family: var(--font); }
}
/* ═══════════════════════════════════════════════
GLOBAL COMPONENT CLASSES
Use these in any component without re-declaring
═══════════════════════════════════════════════ */
/* ── Skeleton loader ── */
.skeleton {
background: linear-gradient(90deg, var(--card) 25%, var(--card-hover) 50%, var(--card) 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: var(--radius-xs);
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
/* ── Buttons ── */
.btn-primary {
padding: var(--sp-2) var(--sp-4);
border-radius: var(--radius-md);
background: var(--accent);
color: white;
border: none;
font-size: var(--text-sm);
font-weight: 500;
cursor: pointer;
transition: all var(--transition);
}
.btn-primary:hover { opacity: 0.9; }
.btn-primary.full {
width: 100%;
padding: var(--sp-3) var(--sp-4);
font-size: var(--text-md);
font-weight: 600;
border-radius: var(--radius);
}
.btn-secondary {
padding: var(--sp-2) var(--sp-4);
border-radius: var(--radius-md);
background: var(--card-secondary);
color: var(--text-2);
border: 1px solid var(--border);
font-size: var(--text-sm);
font-weight: 500;
cursor: pointer;
transition: all var(--transition);
}
.btn-secondary:hover { background: var(--card-hover); color: var(--text-1); }
.btn-icon {
width: 36px;
height: 36px;
border-radius: var(--radius-md);
background: var(--card-secondary);
border: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: var(--text-3);
transition: all var(--transition);
flex-shrink: 0;
}
.btn-icon:hover { color: var(--text-1); background: var(--card-hover); }
.btn-icon svg { width: var(--sp-4); height: var(--sp-4); }
/* ── Inputs ── */
.input {
width: 100%;
padding: 10px 14px;
border-radius: var(--radius-md);
background: var(--surface-secondary);
border: 1px solid var(--border);
color: var(--text-1);
font-size: var(--text-base);
font-family: var(--font);
outline: none;
transition: border-color var(--transition);
}
.input:focus { border-color: var(--accent); }
.input::placeholder { color: var(--text-4); }
/* ── Module (card container) ──
* Use for any content block: dashboard widgets, data tables, etc.
* Variants: .primary (hero, more padding + elevation), .flush (no padding)
*/
.module {
background: var(--card);
border-radius: var(--radius);
border: 1px solid var(--border);
box-shadow: var(--shadow-md);
padding: var(--card-pad);
}
.module.primary {
padding: var(--card-pad-primary);
box-shadow: var(--shadow-lg);
}
.module.flush { padding: 0; }
.module-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--sp-5);
}
.module-title {
font-size: var(--text-sm);
font-weight: 600;
color: var(--text-3);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.module-action {
font-size: var(--text-sm);
color: var(--accent);
font-weight: 500;
cursor: pointer;
text-decoration: none;
}
.module-action:hover { text-decoration: underline; }
/* ── Data row ──
* Standard list item pattern: name + meta on left, value/badge on right.
* Use in transactions, inventory items, feed entries, etc.
*/
.data-row {
display: flex;
align-items: center;
gap: var(--inner-gap);
padding: var(--row-pad-y) var(--row-pad-x);
transition: background var(--transition);
}
.data-row:hover { background: var(--card-hover); }
.data-row + .data-row { border-top: 1px solid var(--border); }
.data-row:nth-child(even) { background: color-mix(in srgb, var(--surface) 68%, var(--card)); }
.data-row:nth-child(even):hover { background: var(--card-hover); }
/* ── Badges ──
* Semantic status badges. Variants: error, success, warning, accent, muted.
*/
.badge {
font-size: var(--text-xs);
font-weight: 500;
padding: 3px 10px;
border-radius: var(--radius-sm);
flex-shrink: 0;
}
.badge.error { background: var(--error-dim); color: var(--error); }
.badge.success { background: var(--success-dim); color: var(--success); }
.badge.warning { background: var(--warning-bg); color: var(--warning); }
.badge.accent { background: var(--accent-dim); color: var(--accent); }
.badge.muted { background: var(--card-hover); color: var(--text-4); }
/* ── Tabs ──
* Pill-style tab bar.
*/
.tab-bar { display: flex; gap: var(--sp-1); }
.tab {
padding: var(--sp-2) 14px;
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: 500;
color: var(--text-3);
background: none;
border: none;
cursor: pointer;
transition: all var(--transition);
font-family: var(--font);
display: flex;
align-items: center;
gap: var(--sp-1.5);
}
.tab:hover { color: var(--text-1); background: var(--card-hover); }
.tab.active { color: var(--text-1); background: var(--card); box-shadow: var(--shadow-xs); }
.tab-badge {
font-size: var(--text-xs);
font-family: var(--mono);
background: var(--accent-dim);
color: var(--accent);
padding: 1px 6px;
border-radius: var(--radius-xs);
margin-left: var(--sp-1);
}
/* ── Section header ──
* Uppercase label above a group of content.
*/
.section-label {
font-size: var(--text-xs);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-3);
margin-bottom: var(--sp-1.5);
}
/* ── Page wrapper ── */
.page { padding: var(--sp-8) 0 var(--sp-20); }
.page-header { margin-bottom: var(--section-gap); }
.page-title {
font-size: var(--text-sm);
font-weight: 500;
color: var(--text-3);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: var(--sp-1);
}
.page-greeting {
font-size: var(--text-2xl);
font-weight: 300;
color: var(--text-1);
line-height: var(--leading-tight);
}
.page-greeting strong { font-weight: 600; }
/* ── App surface (centered container) ── */
.app-surface {
max-width: 1200px;
width: 100%;
margin: 0 auto;
padding: 0 var(--sp-6);
}
/* ── Responsive ── */
@media (max-width: 768px) {
:root {
--text-xs: 12px;
--text-sm: 15px;
--text-base: 16px;
--text-md: 17px;
--text-lg: 18px;
--text-xl: 22px;
--text-2xl: 26px;
--text-3xl: 32px;
--card-pad: var(--sp-4);
--card-pad-primary: var(--sp-5);
--row-pad-y: var(--sp-4);
--section-gap: var(--sp-5);
}
.page-greeting { font-size: var(--text-xl); }
.page { padding: var(--sp-5) 0 var(--sp-20); }
.app-surface { padding: 0 var(--sp-5); }
}