Commit 2baa586b20

2baa586b2032d50899a88ec2d99dbade01347de7

parent: b4ea1c20b8

Verified · cmc

cmc <hello@cleberg.net> · 2026-08-24 16:35 UTC

web: design token layer in the stylesheet

Spacing, type, and radius scales plus a considered palette (sea-blue
accent, distinct semantic colors, merged-purple) as CSS variables on
:root, overridden for dark. Existing markup restyled from the tokens:
softer separators, pill badges tinted via color-mix, muted tabs,
styled forms. Code blocks stay pinned light in both schemes.

Layout: unified · split

internal/web/static/style.css +238 −45
@@ -1,65 +1,258 @@
1/* gitbay stylesheet. One file, light and dark via prefers-color-scheme.
2 Tokens first; components use tokens only. No external requests. */
3
1:root { 4:root {
2 --bg: #ffffff; --fg: #1a1a1a; --muted: #666; --line: #ddd; 5 /* palette */
3 --link: #0550ae; --code-bg: #f6f8fa; 6 --bg: #ffffff;
4 --ok: #1a7f37; --warn: #9a6700; --bad: #cf222e; --neutral: #666; 7 --fg: #1f2328;
8 --muted: #667079;
9 --faint: #eceff1; /* hairlines, row separators */
10 --line: #d7dde2; /* control borders, card edges */
11 --surface: #f6f8fa; /* cards, code, table hover */
12 --accent: #0b6c80; /* sea blue: links, active tab, primary */
13 --accent-fg: #ffffff; /* text on accent */
14 --ok: #1a7f37;
15 --warn: #9a6700;
16 --bad: #cf222e;
17 --done: #8250df; /* merged */
18 --neutral: #667079;
19 --code-bg: #f6f8fa;
20
21 /* type */
22 --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
23 "Helvetica Neue", Arial, sans-serif;
24 --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas,
25 "Liberation Mono", monospace;
26 --fs-0: 0.8rem; /* 12.8px: chips, fine print */
27 --fs-1: 0.866rem; /* ~13px: metadata, mono in tables */
28 --fs-2: 0.933rem; /* 14px: dense table text */
29 --fs-3: 1rem; /* 15px: body */
30 --fs-4: 1.135rem; /* ~17px: h2 */
31 --fs-5: 1.335rem; /* ~20px: h1 */
32
33 /* spacing */
34 --sp-1: 0.25rem;
35 --sp-2: 0.5rem;
36 --sp-3: 0.75rem;
37 --sp-4: 1rem;
38 --sp-5: 1.5rem;
39 --sp-6: 2.5rem;
40
41 /* radii */
42 --r-sm: 4px;
43 --r-md: 6px;
44 --r-lg: 8px;
45 --r-pill: 999px;
5} 46}
6@media (prefers-color-scheme: dark) { 47@media (prefers-color-scheme: dark) {
7 :root { 48 :root {
8 --bg: #0d1117; --fg: #e6edf3; --muted: #8b949e; --line: #30363d; 49 --bg: #0d1117;
9 --link: #58a6ff; --code-bg: #161b22; 50 --fg: #e6edf3;
10 --ok: #3fb950; --warn: #d29922; --bad: #f85149; --neutral: #8b949e; 51 --muted: #8d96a0;
52 --faint: #1d242c;
53 --line: #30363d;
54 --surface: #161b22;
55 --accent: #58b7c9;
56 --accent-fg: #06272e;
57 --ok: #3fb950;
58 --warn: #d29922;
59 --bad: #f85149;
60 --done: #a371f7;
61 --neutral: #8d96a0;
62 --code-bg: #161b22;
11 } 63 }
12} 64}
65
13* { box-sizing: border-box; } 66* { box-sizing: border-box; }
67html { font-size: 15px; }
14body { 68body {
15 margin: 0; background: var(--bg); color: var(--fg); 69 margin: 0;
16 font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; 70 background: var(--bg);
71 color: var(--fg);
72 font: var(--fs-3)/1.6 var(--sans);
17} 73}
18header { border-bottom: 1px solid var(--line); padding: 0.6rem 1rem; } 74
19a.site { font-weight: 700; } 75a { color: var(--accent); text-decoration: none; }
20main { max-width: 60rem; margin: 0 auto; padding: 1rem; }
21a { color: var(--link); text-decoration: none; }
22a:hover { text-decoration: underline; } 76a:hover { text-decoration: underline; }
23h1 { font-size: 1.3rem; } 77
24h2 { font-size: 1.1rem; } 78h1 { font-size: var(--fs-5); font-weight: 600; line-height: 1.3;
25code, pre, .code, td.mode, td.size { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; } 79 margin: var(--sp-5) 0 var(--sp-3); letter-spacing: -0.01em; }
80h2 { font-size: var(--fs-4); font-weight: 600; line-height: 1.35;
81 margin: var(--sp-5) 0 var(--sp-3); }
82h3 { font-size: var(--fs-3); font-weight: 600; margin: var(--sp-5) 0 var(--sp-2); }
83
84code, pre, .code, td.mode, td.size {
85 font-family: var(--mono);
86 font-size: var(--fs-1);
87}
88
89/* layout */
90header {
91 border-bottom: 1px solid var(--faint);
92 padding: var(--sp-3) var(--sp-5);
93}
94a.site { font-weight: 650; color: var(--fg); letter-spacing: -0.01em; }
95a.site:hover { text-decoration: none; color: var(--accent); }
96main {
97 max-width: 64rem;
98 margin: 0 auto;
99 padding: var(--sp-3) var(--sp-5) var(--sp-6);
100}
101
102/* tables */
26table { border-collapse: collapse; width: 100%; } 103table { border-collapse: collapse; width: 100%; }
27td { padding: 0.25rem 0.6rem 0.25rem 0; border-bottom: 1px solid var(--line); vertical-align: top; } 104td {
105 padding: var(--sp-2) var(--sp-4) var(--sp-2) 0;
106 border-bottom: 1px solid var(--faint);
107 vertical-align: top;
108 font-size: var(--fs-2);
109}
110td:last-child { padding-right: 0; }
28td.size, td.mode { color: var(--muted); white-space: nowrap; } 111td.size, td.mode { color: var(--muted); white-space: nowrap; }
29nav.tabs a { margin-right: 1rem; } 112
30p.clone code { background: var(--code-bg); padding: 0.15rem 0.4rem; border-radius: 4px; } 113/* repo tabs */
31.crumbs { color: var(--muted); } 114nav.tabs { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
32.readme, .code { border: 1px solid var(--line); border-radius: 6px; padding: 1rem; margin-top: 1rem; overflow-x: auto; } 115nav.tabs a {
33/* chroma emits inline styles for a light background; pin the block to light 116 color: var(--muted);
34 colors in both schemes so unstyled tokens stay legible. */ 117 padding: var(--sp-1) var(--sp-2);
35.code { background: #f8f8f8; color: #1a1a1a; } 118 border-radius: var(--r-md);
119}
120nav.tabs a:hover { color: var(--fg); background: var(--surface); text-decoration: none; }
121
122p.clone code {
123 background: var(--surface);
124 border: 1px solid var(--faint);
125 padding: 0.15rem 0.5rem;
126 border-radius: var(--r-sm);
127}
128.crumbs { color: var(--muted); font-size: var(--fs-2); }
129.desc, td.desc { color: var(--muted); }
130.error { color: var(--bad); }
131
132/* cards: README, comments */
133.readme, .code {
134 border: 1px solid var(--faint);
135 border-radius: var(--r-lg);
136 padding: var(--sp-4) var(--sp-5);
137 margin-top: var(--sp-4);
138 overflow-x: auto;
139}
140/* chroma emits inline styles for a light background; pin code blocks to
141 light colors in both schemes so unstyled tokens stay legible. */
142.code { background: #f8f8f8; color: #1a1a1a; padding: var(--sp-3) var(--sp-4); }
36.code pre { margin: 0; background: transparent !important; } 143.code pre { margin: 0; background: transparent !important; }
37pre.message { background: var(--code-bg); padding: 0.8rem; border-radius: 6px; white-space: pre-wrap; overflow-wrap: anywhere; } 144@media (prefers-color-scheme: dark) {
145 .code { border-color: var(--line); }
146}
147
148/* rendered markdown / org / html */
38.rendered { max-width: 100%; overflow-wrap: anywhere; } 149.rendered { max-width: 100%; overflow-wrap: anywhere; }
39.rendered pre { background: var(--code-bg); padding: 0.8rem; border-radius: 6px; overflow-x: auto; } 150.rendered pre {
40.rendered code { background: var(--code-bg); padding: 0.1rem 0.3rem; border-radius: 3px; } 151 background: var(--code-bg);
41.rendered blockquote { border-left: 3px solid var(--line); margin-left: 0; padding-left: 1rem; color: var(--muted); } 152 border: 1px solid var(--faint);
42pre.diff { background: var(--code-bg); padding: 0.8rem; border-radius: 6px; overflow-x: auto; } 153 padding: var(--sp-3) var(--sp-4);
154 border-radius: var(--r-md);
155 overflow-x: auto;
156}
157.rendered code { background: var(--code-bg); padding: 0.1rem 0.35rem; border-radius: var(--r-sm); }
158.rendered pre code { background: transparent; padding: 0; }
159.rendered blockquote {
160 border-left: 3px solid var(--line);
161 margin-left: 0;
162 padding-left: var(--sp-4);
163 color: var(--muted);
164}
165.rendered img { max-width: 100%; }
166.rendered h1, .rendered h2 { border-bottom: 1px solid var(--faint); padding-bottom: var(--sp-1); }
167
168pre.message {
169 background: var(--code-bg);
170 border: 1px solid var(--faint);
171 padding: var(--sp-3) var(--sp-4);
172 border-radius: var(--r-md);
173 white-space: pre-wrap;
174 overflow-wrap: anywhere;
175}
176
177/* diffs */
178pre.diff {
179 background: var(--code-bg);
180 border: 1px solid var(--faint);
181 padding: var(--sp-3) var(--sp-4);
182 border-radius: var(--r-md);
183 overflow-x: auto;
184 line-height: 1.5;
185}
43pre.diff .add { color: var(--ok); } 186pre.diff .add { color: var(--ok); }
44pre.diff .del { color: var(--bad); } 187pre.diff .del { color: var(--bad); }
45pre.diff .hunk { color: var(--link); } 188pre.diff .hunk { color: var(--accent); }
46pre.diff .meta { color: var(--muted); } 189pre.diff .meta { color: var(--muted); }
47.error { color: var(--bad); } 190
48.desc, td.desc { color: var(--muted); } 191/* badges: signature and check states. Semantic colors stay distinct:
192 green verified/success, amber pending/stale, red bad/failure, muted
193 unsigned. */
49.badge { 194.badge {
50 display: inline-block; padding: 0.05rem 0.5rem; border-radius: 10px; 195 --chip: var(--neutral);
51 font-size: 12px; border: 1px solid; 196 display: inline-block;
52} 197 padding: 0.05rem 0.55rem;
53.badge-verified { color: var(--ok); border-color: var(--ok); } 198 border-radius: var(--r-pill);
54.badge-unsigned { color: var(--neutral); border-color: var(--line); } 199 font-size: var(--fs-0);
55.badge-signed_unknown_key { color: var(--warn); border-color: var(--warn); } 200 font-weight: 500;
56.badge-signed_email_mismatch { color: var(--bad); border-color: var(--bad); } 201 line-height: 1.5;
57.badge-signed_key_expired { color: var(--warn); border-color: var(--warn); } 202 color: var(--chip);
58.badge-signed_key_revoked { color: var(--bad); border-color: var(--bad); } 203 border: 1px solid color-mix(in srgb, var(--chip) 35%, transparent);
59.badge-bad_signature { color: var(--bad); border-color: var(--bad); } 204 background: color-mix(in srgb, var(--chip) 7%, transparent);
60.check-success { color: var(--ok); border-color: var(--ok); } 205 white-space: nowrap;
61.check-pending { color: var(--warn); border-color: var(--warn); } 206}
62.check-failure, .check-error { color: var(--bad); border-color: var(--bad); } 207.badge-verified { --chip: var(--ok); }
63.thread { border: 1px solid var(--line); border-left: 3px solid var(--link); border-radius: 6px; padding: 0.5rem 0.8rem; margin: 0.3rem 0 0.3rem 2rem; } 208.badge-unsigned { --chip: var(--neutral); }
209.badge-signed_unknown_key { --chip: var(--warn); }
210.badge-signed_email_mismatch { --chip: var(--bad); }
211.badge-signed_key_expired { --chip: var(--warn); }
212.badge-signed_key_revoked { --chip: var(--bad); }
213.badge-bad_signature { --chip: var(--bad); }
214.badge.check-success { --chip: var(--ok); }
215.badge.check-pending { --chip: var(--warn); }
216.badge.check-failure, .badge.check-error { --chip: var(--bad); }
217span.check-success { color: var(--ok); }
218span.check-pending { color: var(--warn); }
219span.check-failure, span.check-error { color: var(--bad); }
220
221/* review threads under diff lines */
222.thread {
223 border: 1px solid var(--faint);
224 border-left: 3px solid var(--accent);
225 border-radius: var(--r-md);
226 padding: var(--sp-2) var(--sp-4);
227 margin: var(--sp-2) 0 var(--sp-2) var(--sp-6);
228}
64.thread.resolved { border-left-color: var(--ok); opacity: 0.75; } 229.thread.resolved { border-left-color: var(--ok); opacity: 0.75; }
65.thread.stale { border-left-color: var(--warn); } 230.thread.stale { border-left-color: var(--warn); }
231
232/* forms */
233input, textarea, button, select { font: inherit; color: inherit; }
234input[type="text"], input:not([type]), textarea {
235 background: var(--bg);
236 border: 1px solid var(--line);
237 border-radius: var(--r-md);
238 padding: var(--sp-2) var(--sp-3);
239}
240textarea { width: 100%; resize: vertical; }
241input:focus, textarea:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); border-color: var(--accent); }
242button {
243 background: var(--accent);
244 color: var(--accent-fg);
245 border: none;
246 border-radius: var(--r-md);
247 padding: var(--sp-1) var(--sp-3);
248 font-weight: 500;
249 cursor: pointer;
250}
251button:hover { filter: brightness(1.08); }
252
253/* mobile */
254@media (max-width: 40rem) {
255 header { padding: var(--sp-3) var(--sp-4); }
256 main { padding: var(--sp-2) var(--sp-4) var(--sp-6); }
257 .thread { margin-left: var(--sp-3); }
258}