fuzzyworld

fuzzyworld-tools / files / server / site / _shared.css

_shared.css

Blame: the commit that last changed each line · file · history

510a1337 2026-10-28 Pavel Safronov1/* =============================================================================
2 FuzzyWorld Shared Design System
3
4 This file contains design tokens and common base styles shared across
5 all fuzzyworld.net sites (fuzzyworld.net, code.fuzzyworld.net, apps.fuzzyworld.net).
6
7 Import this file before site-specific styles.
8 ============================================================================= */
9
10/* ---------------------------------------------------------------------
11 Design Tokens: Colors
12 --------------------------------------------------------------------- */
13
14:root {
15 /* Light mode (default) */
16 --color-bg-primary: #ffffff;
17 --color-bg-secondary: #f6f6f8;
18 --color-bg-tertiary: #ffffff;
19 --color-bg-hover: #eaeaf0;
20
21 --color-fg-primary: #1d1d1f;
22 --color-fg-secondary: #62626a;
23 --color-fg-muted: #9a9aa2;
24
25 --color-border-primary: #e1e1e6;
26 --color-border-secondary: #c1c1c7;
27
28 /* Accent colors */
29 --color-accent: #0a58ca;
30 --color-accent-soft: #e8f0fe;
31 --color-accent-muted: #79b8ff;
32
33 /* Semantic colors */
34 --color-success: #116329;
35 --color-success-bg: #e6f4ea;
36 --color-error: #a40e26;
37 --color-error-bg: #fdecea;
38 --color-warning: #8250df;
39 --color-warning-bg: #e8e8ea;
40
41 /* Code syntax colors (light) */
42 --color-hl-comment: #6a737d;
43 --color-hl-keyword: #cf222e;
44 --color-hl-string: #0a3069;
45 --color-hl-number: #0550ae;
46 --color-hl-function: #8250df;
47 --color-hl-class: #953800;
48 --color-hl-type: #116329;
49}
50
51/* Dark mode */
52@media (prefers-color-scheme: dark) {
53 :root {
54 --color-bg-primary: #111113;
55 --color-bg-secondary: #1a1a1e;
56 --color-bg-tertiary: #17171a;
57 --color-bg-hover: #2a2a2f;
58
59 --color-fg-primary: #e8e8ea;
60 --color-fg-secondary: #9a9aa2;
61 --color-fg-muted: #62626a;
62
63 --color-border-primary: #2a2a2f;
64 --color-border-secondary: #3e3e42;
65
66 /* Accent colors */
67 --color-accent: #79b8ff;
68 --color-accent-soft: #16243a;
69 --color-accent-muted: #bf8700;
70
71 /* Semantic colors */
72 --color-success: #7ee787;
73 --color-success-bg: #12261a;
74 --color-error: #ff9492;
75 --color-error-bg: #2d1517;
76 --color-warning: #c5a5ff;
77 --color-warning-bg: #2a2a2f;
78
79 /* Code syntax colors (dark) */
80 --color-hl-comment: #8b949e;
81 --color-hl-keyword: #ff7b72;
82 --color-hl-string: #a5d6ff;
83 --color-hl-number: #79c0ff;
84 --color-hl-function: #d2a8ff;
85 --color-hl-class: #ffa657;
86 --color-hl-type: #7ee787;
87 }
88}
89
90/* Force color scheme support */
91:root {
92 color-scheme: light dark;
93}
94
95/* ---------------------------------------------------------------------
96 Design Tokens: Spacing
97 --------------------------------------------------------------------- */
98
99:root {
100 --spacing-xs: 0.25rem;
101 --spacing-sm: 0.5rem;
102 --spacing-md: 1rem;
103 --spacing-lg: 1.5rem;
104 --spacing-xl: 2rem;
105 --spacing-2xl: 3rem;
106
107 /* For grid gaps */
108 --gap-sm: 0.75rem;
109 --gap-md: 1rem;
110 --gap-lg: 1.5rem;
111}
112
113/* ---------------------------------------------------------------------
114 Design Tokens: Typography
115 --------------------------------------------------------------------- */
116
117:root {
118 --font-family-sans: system-ui, -apple-system, "Segoe UI", sans-serif;
119 --font-family-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
120
121 --font-size-xs: 0.8rem;
122 --font-size-sm: 0.9rem;
123 --font-size-base: 1rem;
124 --font-size-lg: 1.1rem;
125 --font-size-xl: 1.2rem;
126 --font-size-2xl: 1.75rem;
127
128 --font-weight-normal: 400;
129 --font-weight-medium: 500;
130 --font-weight-semibold: 600;
131 --font-weight-bold: 700;
132
133 --line-height-tight: 1.25;
134 --line-height-normal: 1.5;
135 --line-height-relaxed: 1.55;
136}
137
138/* ---------------------------------------------------------------------
139 Design Tokens: Borders & Shadows
140 --------------------------------------------------------------------- */
141
142:root {
143 --border-radius-sm: 4px;
144 --border-radius-md: 6px;
145 --border-radius-lg: 8px;
146 --border-radius-full: 9999px;
147
148 --box-shadow-sm: 0 1px 2px rgb(0 0 0 / 6%);
149 --box-shadow-md: 0 4px 6px rgb(0 0 0 / 8%);
150
151 /* No shadow in dark mode */
152 --box-shadow: var(--box-shadow-sm);
153}
154
155@media (prefers-color-scheme: dark) {
156 :root {
157 --box-shadow: none;
158 }
159}
160
161/* ---------------------------------------------------------------------
162 Design Tokens: Transitions
163 --------------------------------------------------------------------- */
164
165:root {
166 --transition-fast: 100ms ease;
167 --transition-normal: 200ms ease;
168 --transition-slow: 300ms ease;
169}
170
171/* ---------------------------------------------------------------------
172 Base Styles
173 --------------------------------------------------------------------- */
174
175* {
176 box-sizing: border-box;
177}
178
179html {
180 -webkit-text-size-adjust: 100%;
181 font-size: 16px;
182}
183
184body {
185 margin: 0;
186 background: var(--color-bg-primary);
187 color: var(--color-fg-primary);
188 font: var(--font-size-base)/var(--line-height-relaxed) var(--font-family-sans);
189 -webkit-font-smoothing: antialiased;
190 -moz-osx-font-smoothing: grayscale;
191}
192
193/* Text selection */
194::selection {
195 background: var(--color-accent);
196 color: var(--color-bg-primary);
197}
198
199/* Focus styles */
200:focus-visible {
201 outline: 2px solid var(--color-accent);
202 outline-offset: 2px;
203 border-radius: var(--border-radius-sm);
204}
205
206/* Links */
207a {
208 color: var(--color-accent);
209 text-decoration: none;
210}
211
212a:hover {
213 text-decoration: underline;
214}
215
216/* Images */
217img, picture, video, canvas, svg {
218 display: block;
219 max-width: 100%;
220}
221
222/* Lists */
223ul, ol {
224 padding: 0;
225 margin: 0;
226}
227
228/* Forms */
229input, button, textarea, select {
230 font: inherit;
231}
232
233/* Code */
234code, kbd, samp, pre {
235 font-family: var(--font-family-mono);
236}
237
238/* Headings */
239h1, h2, h3, h4, h5, h6 {
240 font-weight: var(--font-weight-semibold);
241 line-height: var(--line-height-tight);
242 letter-spacing: -0.01em;
243}
244
245/* ---------------------------------------------------------------------
246 Layout Utilities
247 --------------------------------------------------------------------- */
248
249.main-container {
250 max-width: 72rem;
251 margin: 0 auto;
252 padding: 0 var(--spacing-md) var(--spacing-2xl);
253}
254
255/* Visually hidden but accessible */
256.visually-hidden {
257 position: absolute;
258 width: 1px;
259 height: 1px;
260 padding: 0;
261 margin: -1px;
262 overflow: hidden;
263 clip: rect(0, 0, 0, 0);
264 white-space: nowrap;
265 border: 0;
266}
267
268/* Text utilities */
269.text-muted { color: var(--color-fg-muted); }
270.text-secondary { color: var(--color-fg-secondary); }
271.text-success { color: var(--color-success); }
272.text-error { color: var(--color-error); }
273.text-warning { color: var(--color-warning); }
274
275/* Truncate text */
276.truncate {
277 overflow: hidden;
278 text-overflow: ellipsis;
279 white-space: nowrap;
280}
281
282/* Overflow wrap */
283.overflow-wrap-anywhere {
284 overflow-wrap: anywhere;
285}
286
287/* ---------------------------------------------------------------------
288 Spacing Utilities
289 --------------------------------------------------------------------- */
290
291.mt-xs { margin-top: var(--spacing-xs); }
292.mt-sm { margin-top: var(--spacing-sm); }
293.mt-md { margin-top: var(--spacing-md); }
294.mt-lg { margin-top: var(--spacing-lg); }
295.mt-xl { margin-top: var(--spacing-xl); }
296
297.mb-xs { margin-bottom: var(--spacing-xs); }
298.mb-sm { margin-bottom: var(--spacing-sm); }
299.mb-md { margin-bottom: var(--spacing-md); }
300.mb-lg { margin-bottom: var(--spacing-lg); }
301.mb-xl { margin-bottom: var(--spacing-xl); }
302
303/* ---------------------------------------------------------------------
304 Card Component
305 --------------------------------------------------------------------- */
306
307.card {
308 background: var(--color-bg-tertiary);
309 border: 1px solid var(--color-border-primary);
310 border-radius: var(--border-radius-lg);
311 box-shadow: var(--box-shadow);
312 padding: var(--spacing-md);
313}
314
315.card:hover {
316 border-color: var(--color-accent);
317}
318
319/* ---------------------------------------------------------------------
320 Button Component
321 --------------------------------------------------------------------- */
322
323.btn {
324 display: inline-flex;
325 align-items: center;
326 gap: var(--spacing-xs);
327 padding: var(--spacing-xs) var(--spacing-md);
328 background: var(--color-accent);
329 color: var(--color-bg-primary);
330 border: none;
331 border-radius: var(--border-radius-md);
332 font: inherit;
333 font-size: var(--font-size-sm);
334 cursor: pointer;
335 transition: background var(--transition-fast);
336}
337
338.btn:hover {
339 background: var(--color-accent-muted);
340}
341
342.btn-secondary {
343 background: var(--color-bg-secondary);
344 color: var(--color-fg-primary);
345 border: 1px solid var(--color-border-primary);
346}
347
348.btn-secondary:hover {
349 background: var(--color-bg-hover);
350}
351
352/* ---------------------------------------------------------------------
353 Badge Component
354 --------------------------------------------------------------------- */
355
356.badge {
357 display: inline-block;
358 padding: var(--spacing-xs) var(--spacing-sm);
359 background: var(--color-bg-secondary);
360 color: var(--color-fg-secondary);
361 border: 1px solid var(--color-border-primary);
362 border-radius: var(--border-radius-full);
363 font-size: var(--font-size-xs);
364}
365
366.badge-success {
367 background: var(--color-success-bg);
368 color: var(--color-success);
369 border-color: var(--color-success);
370}
371
372.badge-error {
373 background: var(--color-error-bg);
374 color: var(--color-error);
375 border-color: var(--color-error);
376}
377
378.badge-warning {
379 background: var(--color-warning-bg);
380 color: var(--color-warning);
381 border-color: var(--color-warning);
382}
383
384/* ---------------------------------------------------------------------
385 Table Styles
386 --------------------------------------------------------------------- */
387
388table {
389 border-collapse: collapse;
390 width: 100%;
391}
392
393td, th {
394 padding: var(--spacing-xs) var(--spacing-sm);
395 border-bottom: 1px solid var(--color-border-primary);
396 text-align: left;
397 vertical-align: top;
398}
399
400th {
401 color: var(--color-fg-muted);
402 font-weight: var(--font-weight-medium);
403 font-size: var(--font-size-sm);
404}
405
406table:not(.source) tr:hover > td {
407 background: var(--color-bg-secondary);
408}
409
410/* ---------------------------------------------------------------------
411 Back to Top Button
412 --------------------------------------------------------------------- */
413
414.back-to-top {
415 position: fixed;
416 bottom: var(--spacing-xl);
417 right: var(--spacing-xl);
418 width: 2.5rem;
419 height: 2.5rem;
420 display: flex;
421 align-items: center;
422 justify-content: center;
423 background: var(--color-bg-secondary);
424 border: 1px solid var(--color-border-primary);
425 border-radius: var(--border-radius-full);
426 color: var(--color-fg-primary);
427 font-size: 1.25rem;
428 cursor: pointer;
429 transition: all var(--transition-fast);
430 opacity: 0;
431 visibility: hidden;
432 z-index: 1000;
433}
434
435.back-to-top:hover {
436 background: var(--color-bg-hover);
437}
438
439.back-to-top.visible {
440 opacity: 1;
441 visibility: visible;
442}
443
444/* ---------------------------------------------------------------------
445 Responsive Utilities
446 --------------------------------------------------------------------- */
447
448@media (max-width: 64rem) {
449 .main-container {
450 padding: 0 var(--spacing-sm) var(--spacing-xl);
451 }
452}
453
454@media (max-width: 40rem) {
455 .hide-on-mobile {
456 display: none !important;
457 }
458}