refactor(css): consolidate form styles and document design tokens (#664)

- consolidate input/textarea styles in portal page (-12 lines)
- add docs/frontend/design-tokens.md documenting all CSS tokens
- update frontend/CLAUDE.md with design tokens guidance

closes #661

authored by zzstoatzz.io and committed by GitHub b9d0a2c7 b78cabfe

Changed files
+127 -22
docs
frontend
frontend
src
routes
portal
+117
docs/frontend/design-tokens.md
··· 1 + # design tokens 2 + 3 + CSS custom properties defined in `frontend/src/routes/+layout.svelte`. Use these instead of hardcoding values. 4 + 5 + ## border radius 6 + 7 + ```css 8 + --radius-sm: 4px; /* tight corners (inputs, small elements) */ 9 + --radius-base: 6px; /* default for most elements */ 10 + --radius-md: 8px; /* cards, modals */ 11 + --radius-lg: 12px; /* larger containers */ 12 + --radius-xl: 16px; /* prominent elements */ 13 + --radius-2xl: 24px; /* hero elements */ 14 + --radius-full: 9999px; /* pills, circles */ 15 + ``` 16 + 17 + ## typography 18 + 19 + ```css 20 + /* scale */ 21 + --text-xs: 0.75rem; /* 12px - hints, captions */ 22 + --text-sm: 0.85rem; /* 13.6px - labels, secondary */ 23 + --text-base: 0.9rem; /* 14.4px - body default */ 24 + --text-lg: 1rem; /* 16px - body emphasized */ 25 + --text-xl: 1.1rem; /* 17.6px - subheadings */ 26 + --text-2xl: 1.25rem; /* 20px - section headings */ 27 + --text-3xl: 1.5rem; /* 24px - page headings */ 28 + 29 + /* semantic aliases */ 30 + --text-page-heading: var(--text-3xl); 31 + --text-section-heading: 1.2rem; 32 + --text-body: var(--text-lg); 33 + --text-small: var(--text-base); 34 + ``` 35 + 36 + ## colors 37 + 38 + ### accent 39 + 40 + ```css 41 + --accent: #6a9fff; /* primary brand color (user-customizable) */ 42 + --accent-hover: #8ab3ff; /* hover state */ 43 + --accent-muted: #4a7ddd; /* subdued variant */ 44 + --accent-rgb: 106, 159, 255; /* for rgba() usage */ 45 + ``` 46 + 47 + ### backgrounds 48 + 49 + ```css 50 + /* dark theme */ 51 + --bg-primary: #0a0a0a; /* main background */ 52 + --bg-secondary: #141414; /* elevated surfaces */ 53 + --bg-tertiary: #1a1a1a; /* cards, modals */ 54 + --bg-hover: #1f1f1f; /* hover states */ 55 + 56 + /* light theme overrides these automatically */ 57 + ``` 58 + 59 + ### borders 60 + 61 + ```css 62 + --border-subtle: #282828; /* barely visible */ 63 + --border-default: #333333; /* standard borders */ 64 + --border-emphasis: #444444; /* highlighted borders */ 65 + ``` 66 + 67 + ### text 68 + 69 + ```css 70 + --text-primary; /* high contrast */ 71 + --text-secondary; /* medium contrast */ 72 + --text-tertiary; /* low contrast */ 73 + --text-muted; /* very low contrast */ 74 + ``` 75 + 76 + ### semantic 77 + 78 + ```css 79 + --success: #22c55e; 80 + --warning: #f59e0b; 81 + --error: #ef4444; 82 + ``` 83 + 84 + ## usage 85 + 86 + ```svelte 87 + <style> 88 + .card { 89 + border-radius: var(--radius-md); 90 + background: var(--bg-tertiary); 91 + border: 1px solid var(--border-default); 92 + } 93 + 94 + .label { 95 + font-size: var(--text-sm); 96 + color: var(--text-secondary); 97 + } 98 + 99 + input:focus { 100 + border-color: var(--accent); 101 + } 102 + </style> 103 + ``` 104 + 105 + ## anti-patterns 106 + 107 + ```css 108 + /* bad - hardcoded values */ 109 + border-radius: 8px; 110 + font-size: 14px; 111 + background: #1a1a1a; 112 + 113 + /* good - use tokens */ 114 + border-radius: var(--radius-md); 115 + font-size: var(--text-base); 116 + background: var(--bg-tertiary); 117 + ```
+1
frontend/CLAUDE.md
··· 6 6 - **state**: global managers in `lib/*.svelte.ts` using `$state` runes (player, queue, uploader, tracks cache) 7 7 - **components**: reusable ui in `lib/components/` (LikeButton, Toast, Player, etc) 8 8 - **routes**: pages in `routes/` with `+page.svelte` and `+page.ts` for data loading 9 + - **design tokens**: use CSS variables from `+layout.svelte` - never hardcode colors, radii, or font sizes (see `docs/frontend/design-tokens.md`) 9 10 10 11 gotchas: 11 12 - **svelte 5 runes mode**: component-local state MUST use `$state()` - plain `let` has no reactivity (see `docs/frontend/state-management.md`)
+9 -22
frontend/src/routes/portal/+page.svelte
··· 1262 1262 font-size: var(--text-sm); 1263 1263 } 1264 1264 1265 - input[type='text'] { 1265 + input[type='text'], 1266 + input[type='url'], 1267 + textarea { 1266 1268 width: 100%; 1267 1269 padding: 0.6rem 0.75rem; 1268 1270 background: var(--bg-primary); ··· 1274 1276 transition: all 0.15s; 1275 1277 } 1276 1278 1277 - input[type='text']:focus { 1279 + input[type='text']:focus, 1280 + input[type='url']:focus, 1281 + textarea:focus { 1278 1282 outline: none; 1279 1283 border-color: var(--accent); 1280 1284 } 1281 1285 1282 - input[type='text']:disabled { 1286 + input[type='text']:disabled, 1287 + input[type='url']:disabled, 1288 + textarea:disabled { 1283 1289 opacity: 0.5; 1284 1290 cursor: not-allowed; 1285 1291 } 1286 1292 1287 1293 textarea { 1288 - width: 100%; 1289 - padding: 0.6rem 0.75rem; 1290 - background: var(--bg-primary); 1291 - border: 1px solid var(--border-default); 1292 - border-radius: var(--radius-sm); 1293 - color: var(--text-primary); 1294 - font-size: var(--text-base); 1295 - font-family: inherit; 1296 - transition: all 0.15s; 1297 1294 resize: vertical; 1298 1295 min-height: 80px; 1299 - } 1300 - 1301 - textarea:focus { 1302 - outline: none; 1303 - border-color: var(--accent); 1304 - } 1305 - 1306 - textarea:disabled { 1307 - opacity: 0.5; 1308 - cursor: not-allowed; 1309 1296 } 1310 1297 1311 1298 .hint {