fuzzyworld

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

style.css

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

510a1337 2026-10-28 Pavel Safronov1/* =============================================================================
2 FuzzyWorld Site Styles
3
4 This file contains site-specific styles for code.fuzzyworld.net and
5 apps.fuzzyworld.net. It builds upon the shared design system in _shared.css.
6
7 Import order:
8 1. _shared.css (design tokens and base styles)
9 2. _icons.css (icon system)
10 3. style.css (this file - site-specific styles)
11 ============================================================================= */
12
13/* Import shared design system */
14@import url("_shared.css");
15@import url("_icons.css");
16
17/* =============================================================================
18 Site Configuration
19 ============================================================================= */
20
21/* Site-specific color overrides (if needed) */
623239b7 2026-10-26 Pavel Safronov22:root {
510a1337 2026-10-28 Pavel Safronov23 --site-bg: var(--color-bg-primary);
24 --site-fg: var(--color-fg-primary);
25 --site-muted: var(--color-fg-muted);
26 --site-line: var(--color-border-primary);
27 --site-soft: var(--color-bg-secondary);
28 --site-card: var(--color-bg-tertiary);
29 --site-accent-soft: var(--color-accent-soft);
30
31 --site-link: var(--color-accent);
32
33 --site-add: var(--color-success-bg);
34 --site-add-fg: var(--color-success);
35 --site-del: var(--color-error-bg);
36 --site-del-fg: var(--color-error);
37 --site-hunk: var(--color-warning);
623239b7 2026-10-26 Pavel Safronov38}
510a1337 2026-10-28 Pavel Safronov39
623239b7 2026-10-26 Pavel Safronov40@media (prefers-color-scheme: dark) {
41 :root {
510a1337 2026-10-28 Pavel Safronov42 --site-add: var(--color-success-bg);
43 --site-add-fg: var(--color-success);
44 --site-del: var(--color-error-bg);
45 --site-del-fg: var(--color-error);
46 --site-hunk: var(--color-warning);
623239b7 2026-10-26 Pavel Safronov47 }
48}
510a1337 2026-10-28 Pavel Safronov49
50/* =============================================================================
51 Base Overrides
52 ============================================================================= */
53
54/* Ensure color-scheme is set */
55:root {
56 color-scheme: light dark;
57}
58
59html {
60 -webkit-text-size-adjust: 100%;
61}
62
63body {
64 margin: 0;
65 background: var(--site-bg);
66 color: var(--site-fg);
67 font: 16px/1.55 var(--font-family-sans);
68}
69
70a {
71 color: var(--site-link);
72 text-decoration: none;
73}
74
75a:hover {
76 text-decoration: underline;
77}
78
79/* =============================================================================
80 Site Header & Footer
81 ============================================================================= */
82
83header.site {
84 background: var(--site-soft);
85 border-bottom: 1px solid var(--site-line);
86}
87
88header.site .bar,
89footer.site .cols {
90 max-width: 72rem;
91 margin: 0 auto;
92 padding: 0 var(--spacing-md);
93}
94
95header.site .bar {
96 display: flex;
97 flex-wrap: wrap;
98 align-items: center;
99 gap: 0 var(--spacing-lg);
100}
101
102header.site .brand {
103 font-weight: var(--font-weight-bold);
104 font-size: var(--font-size-lg);
105 color: var(--site-fg);
106 padding: var(--spacing-sm) 0;
107 letter-spacing: -0.01em;
108}
109
110header.site .brand:hover {
111 text-decoration: none;
112 color: var(--site-link);
113}
114
115.site-nav {
116 display: flex;
117 flex-wrap: wrap;
118 gap: 0 var(--spacing-md);
119}
120
121.site-nav a {
122 color: var(--site-muted);
123 padding: var(--spacing-sm) 0 calc(var(--spacing-sm) - 2px);
124 border-bottom: 2px solid transparent;
125}
126
127.site-nav a:hover {
128 color: var(--site-fg);
129 text-decoration: none;
130}
131
132.site-nav a[aria-current] {
133 color: var(--site-fg);
134 font-weight: var(--font-weight-semibold);
135 border-bottom-color: var(--site-link);
136}
137
138/* Site icon in header */
139header.site .brand::before {
140 content: "";
141 display: inline-block;
142 width: 1.1em;
143 height: 1.1em;
144 margin-right: 0.3em;
145 vertical-align: -0.1em;
1ef72600 2026-10-28 Pavel Safronov146 background-image: url("/favicon.ico");
510a1337 2026-10-28 Pavel Safronov147 background-size: contain;
148 background-repeat: no-repeat;
149 background-position: center;
150}
151
152footer.site {
153 margin-top: var(--spacing-xl);
154 border-top: 1px solid var(--site-line);
155 background: var(--site-soft);
156 color: var(--site-muted);
157 font-size: var(--font-size-sm);
158}
159
160footer.site .cols {
161 display: grid;
162 grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
163 gap: var(--spacing-lg);
164 padding-top: var(--spacing-lg);
165 padding-bottom: var(--spacing-xl);
166}
167
168footer.site h2 {
169 font-size: var(--font-size-xs);
170 text-transform: uppercase;
171 letter-spacing: 0.06em;
172 color: var(--site-muted);
173 margin: 0 0 var(--spacing-xs);
174}
175
176footer.site a,
177footer.site span {
178 display: block;
179 padding: var(--spacing-xs) 0;
180}
181
182/* =============================================================================
183 Main Content Layout
184 ============================================================================= */
185
186main {
187 max-width: 72rem;
188 margin: 0 auto;
189 padding: 0 var(--spacing-md) var(--spacing-xl);
190}
191
192main > p,
193main > ul:not(.repos),
194main > ol {
195 max-width: 46rem;
196}
197
198/* =============================================================================
199 Typography
200 ============================================================================= */
201
202h1 {
203 font-size: var(--font-size-2xl);
204 line-height: var(--line-height-tight);
205 margin: var(--spacing-lg) 0 var(--spacing-md);
206 overflow-wrap: anywhere;
207 letter-spacing: -0.01em;
208}
209
210h2 {
211 font-size: var(--font-size-xl);
212 margin: var(--spacing-xl) 0 var(--spacing-md);
213}
214
215code, pre, .source, .diff {
216 font: 13px/1.5 var(--font-family-mono);
217 tab-size: 4;
218}
219
220pre {
221 background: var(--site-soft);
222 border: 1px solid var(--site-line);
223 border-radius: var(--border-radius-md);
224 padding: var(--spacing-sm);
225 overflow-x: auto;
226}
227
228/* =============================================================================
229 Navigation
230 ============================================================================= */
231
232.repo-nav {
233 display: flex;
234 flex-wrap: wrap;
235 gap: 0 var(--spacing-md);
236 margin-top: var(--spacing-md);
237 border-bottom: 1px solid var(--site-line);
238}
239
240.repo-nav a {
241 color: var(--site-muted);
242 padding: var(--spacing-xs) 0 calc(var(--spacing-xs) - 2px);
243 border-bottom: 2px solid transparent;
244}
245
246.repo-nav a:hover {
247 color: var(--site-fg);
248 text-decoration: none;
249 border-bottom-color: var(--site-line);
250}
251
252/* Breadcrumb navigation */
253.crumbs {
254 color: var(--site-muted);
255 overflow-wrap: anywhere;
256}
257
258/* =============================================================================
259 Metadata & Descriptions
260 ============================================================================= */
261
262.meta, .desc {
263 color: var(--site-muted);
264 overflow-wrap: anywhere;
265}
266
55e5fc3e 2026-11-04 Pavel Safronov267pre.message, pre.issue-text {
510a1337 2026-10-28 Pavel Safronov268 white-space: pre-wrap;
269 overflow-wrap: anywhere;
270}
09c576d4 2026-11-04 Pavel Safronov271pre.issue-text {
272 max-width: 100%;
273 box-sizing: border-box;
274 overflow-x: hidden;
275}
276hr.issue-sep {
277 border: 0;
278 border-top: 1px solid var(--site-line);
279 margin: var(--spacing-sm) 0;
280}
281table.issue-details {
282 width: auto;
283 max-width: 100%;
284 font-size: var(--font-size-xs);
285 margin: var(--spacing-sm) 0;
286}
287table.issue-details th {
288 text-align: left;
289 padding-right: var(--spacing-md);
290 color: var(--site-muted);
291 font-weight: normal;
292}
293.issue-nav {
294 display: flex;
295 justify-content: space-between;
296 margin-top: var(--spacing-md);
297}
510a1337 2026-10-28 Pavel Safronov298
299.clone {
300 user-select: all;
301}
302
303/* =============================================================================
304 Tables
305 ============================================================================= */
306
307table {
308 border-collapse: collapse;
309 width: 100%;
310}
311
312td, th {
313 padding: var(--spacing-xs) var(--spacing-sm);
314 border-bottom: 1px solid var(--site-line);
315 text-align: left;
316 vertical-align: top;
317}
318
319th {
320 color: var(--site-muted);
321 font-weight: var(--font-weight-medium);
322 font-size: var(--font-size-sm);
323}
324
325table:not(.source) tr:hover > td {
326 background: var(--site-soft);
327}
328
329td.num, td.date {
330 white-space: nowrap;
331 color: var(--site-muted);
332}
333
334td.date {
335 width: 7rem;
336}
337
338td.author {
339 color: var(--site-muted);
340 white-space: nowrap;
341}
342
5a659fb7 2026-10-29 Pavel Safronov343/* Project icons in headings (the Projects page) */
344.small-logo {
345 display: inline-block;
346 width: 1em;
347 height: 1em;
348 margin-right: 0.3em;
349 vertical-align: -0.1em;
350}
351
57d16c8b 2026-10-29 Pavel Safronov352/* Claude Code output tokens per commit (log and usage pages) */
353td.cost {
354 color: var(--site-muted);
355 white-space: nowrap;
356 text-align: right;
357}
358
359td.cost .track {
360 display: inline-block;
361 width: 5rem;
362 height: 0.6rem;
363 margin-right: var(--spacing-sm);
364 vertical-align: baseline;
365}
366
367td.cost .bar {
368 display: block;
369 height: 100%;
370 min-width: 2px;
371 background: var(--site-muted);
372}
373
374td.cost .bar.hot {
375 background: var(--site-hunk);
376}
377
799905ae 2026-11-04 Pavel Safronov378/* Inline SVG line charts (the usage page): colours only here, so they follow dark mode */
ced0eafa 2026-11-04 Pavel Safronov379svg.chart {
380 display: block;
381 width: 100%;
382 height: auto;
383 margin: var(--spacing-md) 0;
384}
385
799905ae 2026-11-04 Pavel Safronov386.chart .line {
387 fill: none;
388 stroke: var(--site-link);
389 stroke-width: 2;
390 stroke-linejoin: round;
391 stroke-linecap: round;
392 vector-effect: non-scaling-stroke;
393}
394
395.chart .line.muted {
396 stroke: var(--site-muted);
397}
398
399.chart .area {
400 fill: var(--site-link);
401 fill-opacity: 0.12;
402 stroke: none;
ced0eafa 2026-11-04 Pavel Safronov403}
404
799905ae 2026-11-04 Pavel Safronov405.chart .area.muted {
406 fill: var(--site-muted);
ced0eafa 2026-11-04 Pavel Safronov407}
408
799905ae 2026-11-04 Pavel Safronov409.chart .dot {
ced0eafa 2026-11-04 Pavel Safronov410 fill: var(--site-link);
411}
412
799905ae 2026-11-04 Pavel Safronov413.chart .dot.muted {
414 fill: var(--site-muted);
415}
416
ced0eafa 2026-11-04 Pavel Safronov417.chart .hit {
418 fill: transparent;
419}
420
421.chart .axis {
422 stroke: var(--site-line);
423}
424
425.chart .hatchline {
426 stroke: var(--site-muted);
427 stroke-width: 1;
428}
429
430.chart text {
431 fill: var(--site-muted);
432 font-size: 16px;
433}
434
510a1337 2026-10-28 Pavel Safronov435/* File listing table */
436.files td.dir a {
437 font-weight: var(--font-weight-semibold);
438}
439
440/* =============================================================================
441 Code Display
442 ============================================================================= */
443
444.table-wrap, .source, .log, .index {
445 display: block;
446 overflow-x: auto;
623239b7 2026-10-26 Pavel Safronov447}
510a1337 2026-10-28 Pavel Safronov448
449.source {
450 border: 1px solid var(--site-line);
451 border-radius: var(--border-radius-md);
452}
453
454.source td {
455 border: 0;
456 padding: 0 var(--spacing-sm);
457 white-space: pre;
458}
459
460.source td.ln {
461 text-align: right;
462 color: var(--site-muted);
463 user-select: none;
464 width: 1%;
465}
466
467.source td.ln a {
468 color: inherit;
469}
470
471.source tr:target {
472 background: var(--site-soft);
473}
474
475/* Diff styling */
476.diff .add {
477 background: var(--site-add);
478 color: var(--site-add-fg);
479 display: inline-block;
480 min-width: 100%;
481}
482
483.diff .del {
484 background: var(--site-del);
485 color: var(--site-del-fg);
486 display: inline-block;
487 min-width: 100%;
488}
489
490.diff .hunk {
491 color: var(--site-hunk);
492}
493
494.diff .file {
495 font-weight: var(--font-weight-bold);
496}
497
498/* Markdown content */
8d3e7e81 2026-10-29 Pavel Safronov499/* Plain lists in page content: room for the numbers and bullets, which sit outside the list box
500 (the reset in _shared.css removes all list padding). Lists with a class style themselves. */
501main ul:not([class]),
502main ol:not([class]) {
503 padding-left: 1.75em;
504 margin: 0 0 var(--spacing-md);
505}
506
507main ul:not([class]) li + li,
508main ol:not([class]) li + li {
509 margin-top: 0.25em;
510}
511
510a1337 2026-10-28 Pavel Safronov512.markdown img,
57d16c8b 2026-10-29 Pavel Safronov513main p > img,
510a1337 2026-10-28 Pavel Safronov514img.blob {
515 max-width: 100%;
516 height: auto;
517}
518
519.markdown table {
520 display: block;
521 overflow-x: auto;
522}
523
524.readme {
525 border-top: 1px solid var(--site-line);
526 margin-top: var(--spacing-xl);
527}
528
529/* =============================================================================
392edf54 2026-11-04 Pavel Safronov530 Repository/App tables (code and apps indexes)
510a1337 2026-10-28 Pavel Safronov531 ============================================================================= */
532
392edf54 2026-11-04 Pavel Safronov533table.repos .name {
510a1337 2026-10-28 Pavel Safronov534 font-weight: var(--font-weight-semibold);
535 overflow-wrap: anywhere;
536}
537
538/* Details/summary styling */
539details summary {
540 cursor: pointer;
541 color: var(--site-muted);
542 margin: var(--spacing-md) 0 var(--spacing-xs);
543}
544
545/* Branch note styling */
546.branch-note {
547 background: var(--site-soft);
548 border: 1px solid var(--site-line);
549 border-radius: var(--border-radius-md);
550 padding: var(--spacing-xs) var(--spacing-sm);
551 overflow-wrap: anywhere;
552}
553
554/* =============================================================================
555 Blame View
556 ============================================================================= */
557
558/* Blame: who last changed each run of lines. */
559.source.blamed td.blame {
560 white-space: nowrap;
561 color: var(--site-muted);
562 font-size: 0.75rem;
563 border-right: 1px solid var(--site-line);
564 min-width: 18rem;
565}
566
567.source.blamed tr.run td {
568 border-top: 1px solid var(--site-line);
569}
570
571.source.blamed .who {
572 display: inline-block;
573 max-width: 9rem;
574 overflow: hidden;
575 text-overflow: ellipsis;
576 vertical-align: bottom;
577}
578
579/* =============================================================================
580 CI Status
581 ============================================================================= */
582
583.ci {
584 font-weight: var(--font-weight-bold);
585 text-decoration: none;
586}
587
588.ci-success { color: var(--site-add-fg); }
589.ci-failed { color: var(--site-del-fg); }
590.ci-running { color: var(--site-hunk); }
591.ci-error { color: var(--site-muted); }
592
593pre.ci-log {
594 max-height: 40rem;
595 overflow: auto;
596 white-space: pre-wrap;
597 overflow-wrap: anywhere;
598}
599
600/* =============================================================================
601 Syntax Highlighting
602 ============================================================================= */
603
604:root {
605 --hl-c: var(--color-hl-comment);
606 --hl-k: var(--color-hl-keyword);
607 --hl-s: var(--color-hl-string);
608 --hl-m: var(--color-hl-number);
609 --hl-nf: var(--color-hl-function);
610 --hl-nc: var(--color-hl-class);
611 --hl-nt: var(--color-hl-type);
612}
613
614.code .c { color: var(--hl-c); font-style: italic; }
615.code .cp, .code .k { color: var(--hl-k); }
616.code .s { color: var(--hl-s); }
617.code .m, .code .nb, .code .na { color: var(--hl-m); }
618.code .nf, .code .nd { color: var(--hl-nf); }
619.code .nc { color: var(--hl-nc); }
620.code .nt { color: var(--hl-nt); }
621.code .gi { color: var(--site-add-fg); }
622.code .gd { color: var(--site-del-fg); }
623.code .gh { font-weight: var(--font-weight-bold); }
624
625/* =============================================================================
626 Screenshots
627 ============================================================================= */
628
1758548c 2026-10-27 Pavel Safronov629/* Screenshots: thumbnails on the apps index, a row on a repo's summary page. */
392edf54 2026-11-04 Pavel Safronov630table.repos td.shot {
631 width: 3.5rem;
632 padding-right: 0;
510a1337 2026-10-28 Pavel Safronov633}
634
392edf54 2026-11-04 Pavel Safronov635table.repos .thumb img {
510a1337 2026-10-28 Pavel Safronov636 display: block;
392edf54 2026-11-04 Pavel Safronov637 width: 3.5rem;
638 height: 4.75rem;
510a1337 2026-10-28 Pavel Safronov639 object-fit: contain;
640 object-position: left top;
641 border: 1px solid var(--site-line);
642 border-radius: var(--border-radius-md);
643 background: var(--site-soft);
644}
645
646.shots {
647 display: flex;
648 gap: var(--gap-sm);
649 overflow-x: auto;
650}
651
652.shots img {
653 display: block;
654 height: 16rem;
655 width: auto;
656 border: 1px solid var(--site-line);
657 border-radius: var(--border-radius-lg);
658}
659
660/* =============================================================================
661 Responsive Adjustments
662 ============================================================================= */
663
664@media (max-width: 40rem) {
665 td.author,
666 .log td.date {
667 display: none;
668 }
669}
670
671/* =============================================================================
672 Icon Integration
673 ============================================================================= */
674
675/* VS Code links get the VS Code icon automatically */
676a[href*="vscode://vscode.git/clone"]::before,
677a[href*="/vscode/" i]::before {
678 content: "";
679 display: inline-block;
680 width: 0.9em;
681 height: 0.9em;
682 margin-right: 0.35em;
683 vertical-align: -0.1em;
684 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' d='M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5'/%3E%3C/svg%3E");
685 background-size: contain;
686 background-repeat: no-repeat;
687 background-position: center;
688}
689
690/* Clone commands get a git icon */
691pre.clone::before {
692 content: "$ ";
693 color: var(--site-muted);
694}
695
696/* App badges for repo cards */
697.repo-has-app::after {
698 content: "app";
699 margin-left: var(--spacing-xs);
700 padding: 0 var(--spacing-xs);
701 background: var(--site-soft);
702 border-radius: var(--border-radius-sm);
703 font-size: 0.8em;
704 color: var(--site-muted);
705}
706
707/* =============================================================================
708 Badge Styles
709 ============================================================================= */
710
711.badge {
712 display: inline-block;
713 padding: var(--spacing-xs) var(--spacing-sm);
714 background: var(--site-soft);
715 color: var(--site-muted);
716 border: 1px solid var(--site-line);
717 border-radius: var(--border-radius-full);
718 font-size: var(--font-size-xs);
719}
720
721.badge-success {
722 background: var(--site-add);
723 color: var(--site-add-fg);
724 border-color: var(--site-add-fg);
725}
726
727.badge-error {
728 background: var(--site-del);
729 color: var(--site-del-fg);
730 border-color: var(--site-del-fg);
731}
732
733.badge-warning {
734 background: var(--color-warning-bg);
735 color: var(--color-warning);
736 border-color: var(--color-warning);
737}
738
739.badge-info {
740 background: var(--site-accent-soft);
741 color: var(--color-accent);
742 border-color: var(--color-accent);
743}
799905ae 2026-11-04 Pavel Safronov744
745/* Facts list on the usage pages: one fact per line */
746dl.stats {
747 margin: var(--spacing-md) 0;
748}
749
750dl.stats div {
751 display: flex;
752 flex-wrap: wrap;
753 gap: var(--spacing-sm);
754 padding: 2px 0;
755}
756
757dl.stats dt {
758 min-width: 14em;
759 color: var(--site-muted);
760}
761
762dl.stats dd {
763 margin: 0;
764}
765
766dl.stats small {
767 display: block;
768 color: var(--site-muted);
769}