internal/web/static/style.css
1487 lines · 50274 bytes
1/* gitbay stylesheet — Harbor: black and white ground, two accents with
2 separate jobs. Blue is what you can do (links, buttons, focus); orange
3 is where you are and what wants you (active nav, counts, pending state,
4 unverified signatures). Orange is never a button, so the two never
5 compete. One file, light and dark via prefers-color-scheme. Tokens
6 first; components use tokens only. No external requests: Atkinson
7 Hyperlegible is served from this origin. */
8
9@font-face {
10 font-family: "Atkinson Hyperlegible Next";
11 font-style: normal;
12 font-weight: 400 700;
13 font-display: swap;
14 src: url(/static/fonts/atkinson-next-roman.woff2) format("woff2");
15}
16@font-face {
17 font-family: "Atkinson Hyperlegible Next";
18 font-style: italic;
19 font-weight: 400 700;
20 font-display: swap;
21 src: url(/static/fonts/atkinson-next-italic.woff2) format("woff2");
22}
23@font-face {
24 font-family: "Atkinson Hyperlegible Mono";
25 font-style: normal;
26 font-weight: 400 600;
27 font-display: swap;
28 src: url(/static/fonts/atkinson-mono-roman.woff2) format("woff2");
29}
30
31:root {
32 /* declare native light+dark support: correct form controls and
33 scrollbars per scheme, and opt out of browser auto-darkening */
34 color-scheme: light dark;
35
36 /* ground and ink */
37 --bg: #ffffff;
38 --fg: #0d0d0d;
39 --muted: #595959; /* 7.00:1 on white */
40 --faint: #eaeaea; /* hairlines, row separators */
41 --line: #d4d4d4; /* control borders, table edges */
42 --surface: #ffffff;
43 --hover: #f5f5f5;
44 --code-bg: #f5f5f5;
45 --fill-subtle: #ececec; /* hunk headers, summary hover */
46 --diff-add: #e4f6ea; /* row grounds: tinted enough to scan, light
47 enough that syntax colors stay legible */
48 --diff-del: #fdeaea;
49
50 /* blue: what you can do */
51 --accent: #0000f0; /* links, focus — 9.30:1 on white */
52 --accent-fg: #ffffff;
53 --fill: #0000f0; /* button grounds; white on it is 9.30:1 */
54
55 /* orange: where you are, what wants you */
56 --mark: #e4572e; /* bars and underlines — non-text, 3.0 bar */
57 --warn: #c2410c; /* the same orange at text size — 5.18:1 */
58
59 /* semantic */
60 --ok: #0a7d3c;
61 --bad: #c62828;
62 --done: #6b21a8; /* merged */
63 --neutral: #595959;
64
65 /* the rail is black in both schemes: the one brand constant */
66 --shell-bg: #000000;
67 --shell-fg: #f2f2f2;
68 --shell-muted: #8f8f8f;
69 --shell-line: #1c1c1c;
70 --shell-hover: #141414;
71 --shell-mark: #ff6b3d; /* 7.42:1 on black, both schemes */
72
73 /* type */
74 --sans: "Atkinson Hyperlegible Next", -apple-system, BlinkMacSystemFont,
75 "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
76 --mono: "Atkinson Hyperlegible Mono", ui-monospace, "SF Mono",
77 SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
78 --fs-0: 0.78rem;
79 --fs-1: 0.85rem;
80 --fs-2: 0.92rem;
81 --fs-3: 1rem;
82 --fs-4: 1.2rem;
83 --fs-5: 1.6rem;
84
85 /* spacing */
86 --sp-1: 0.25rem;
87 --sp-2: 0.5rem;
88 --sp-3: 0.75rem;
89 --sp-4: 1rem;
90 --sp-5: 1.5rem;
91 --sp-6: 2.5rem;
92
93 --chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23595959' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
94
95 /* radii: 2px everywhere — chart plates, not pills */
96 --r-sm: 2px;
97 --r-md: 2px;
98 --r-lg: 2px;
99 --r-pill: 2px;
100}
101@media (prefers-color-scheme: dark) {
102 :root {
103 --bg: #0a0a0a;
104 --fg: #f2f2f2;
105 --muted: #a1a1a1; /* 7.66:1 on #0a0a0a */
106 --faint: #1c1c1c;
107 --line: #2e2e2e;
108 --surface: #0f0f0f;
109 --hover: #161616;
110 --code-bg: #050505;
111 --fill-subtle: #161616;
112 --diff-add: #0d2a18;
113 --diff-del: #2c1113;
114 --accent: #5b6bff; /* 4.71:1 — pure #0000f0 is 2.13:1 here */
115 --accent-fg: #ffffff;
116 --fill: #0000f0; /* fills stay pure; white on it clears 9:1 */
117 --mark: #ff6b3d;
118 --warn: #ff6b3d;
119 --ok: #3fce7a;
120 --bad: #ff6b6b;
121 --done: #c084fc;
122 --neutral: #a1a1a1;
123 --chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23a1a1a1' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
124 }
125}
126
127* { box-sizing: border-box; }
128html { font-size: 15px; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
129body {
130 margin: 0;
131 background: var(--bg);
132 color: var(--fg);
133 font: var(--fs-3)/1.6 var(--sans);
134 min-height: 100vh;
135}
136
137a { color: var(--accent); text-decoration: none; }
138a:hover { text-decoration: underline; }
139
140/* one authored focus ring, so keyboard position is never the browser's
141 guess. Blue, because focus is an interactive state. */
142:focus-visible {
143 outline: 2px solid var(--accent);
144 outline-offset: 2px;
145 border-radius: 1px;
146}
147/* the shell is black in both schemes, and --accent is a dark blue in the
148 light one — a ring nobody could see. The shell's own mark clears 7:1 on
149 black either way. */
150.rail :focus-visible { outline-color: var(--shell-mark); }
151
152/* visually hidden, still read aloud: for headings a sighted reader gets
153 from the layout but a screen reader would otherwise miss */
154.vh {
155 position: absolute;
156 width: 1px; height: 1px;
157 margin: -1px; padding: 0; border: 0;
158 clip-path: inset(50%);
159 overflow: hidden;
160 white-space: nowrap;
161}
162/* the rail runs ahead of the content in source order, so give keyboard
163 and screen-reader users a way past it */
164a.skip {
165 position: absolute;
166 left: var(--sp-3); top: -3rem;
167 z-index: 50;
168 background: var(--fill);
169 color: #ffffff;
170 padding: var(--sp-2) var(--sp-4);
171 font-weight: 600;
172}
173a.skip:focus { top: var(--sp-3); text-decoration: none; }
174
175h1 { font-size: var(--fs-5); font-weight: 700; line-height: 1.18;
176 margin: 0 0 var(--sp-3); letter-spacing: -0.025em; text-wrap: balance; }
177h2 { font-size: var(--fs-4); font-weight: 700; line-height: 1.3;
178 margin: var(--sp-5) 0 var(--sp-3); letter-spacing: -0.015em; }
179h3 { font-size: var(--fs-3); font-weight: 600; margin: var(--sp-5) 0 var(--sp-2); }
180
181code, pre, .code, td.mode, td.size {
182 font-family: var(--mono);
183 font-size: var(--fs-1);
184}
185
186/* ---- shell: black rail, content pane ---- */
187.shell { display: flex; align-items: stretch; min-height: 100vh; }
188
189.rail {
190 flex: none;
191 width: 13rem;
192 background: var(--shell-bg);
193 color: var(--shell-fg);
194 border-right: 1px solid var(--shell-line);
195 position: sticky;
196 top: 0;
197 height: 100vh;
198 display: flex;
199 flex-direction: column;
200}
201a.brand {
202 display: flex;
203 align-items: center;
204 gap: var(--sp-2);
205 padding: var(--sp-3) var(--sp-4);
206 color: var(--shell-fg);
207 font-weight: 700;
208 font-size: var(--fs-3);
209 letter-spacing: -0.02em;
210 border-bottom: 1px solid var(--shell-line);
211}
212a.brand:hover { text-decoration: none; color: #ffffff; }
213a.brand svg.mark { display: block; flex: none; }
214a.brand span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
215
216.railbody { flex: 1; overflow-y: auto; padding: var(--sp-3) 0; }
217ul.raillist { list-style: none; margin: 0; padding: 0; }
218ul.raillist a {
219 display: block;
220 padding: 0.28rem var(--sp-4);
221 color: var(--shell-fg);
222 font-size: var(--fs-2);
223 border-left: 3px solid transparent;
224 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
225}
226ul.raillist a:hover { background: var(--shell-hover); text-decoration: none; }
227/* orange marks position — the rail's only accent */
228ul.raillist a[aria-current] {
229 border-left-color: var(--shell-mark);
230 background: var(--shell-hover);
231 font-weight: 600;
232}
233ul.raillist .owner { color: var(--shell-muted); }
234ul.raillist.wide a { white-space: normal; padding-top: var(--sp-1); padding-bottom: var(--sp-1); }
235ul.raillist.wide b { display: block; font-weight: 500; font-size: var(--fs-1); }
236ul.raillist.wide .owner { font-size: var(--fs-0); }
237
238.raillabel {
239 display: flex;
240 align-items: center;
241 gap: var(--sp-2);
242 margin: var(--sp-4) 0 var(--sp-1);
243 padding: 0 var(--sp-4);
244 font-family: var(--mono);
245 font-size: var(--fs-0);
246 font-weight: 500;
247 letter-spacing: 0.1em;
248 text-transform: uppercase;
249 color: var(--shell-muted);
250}
251.raillabel .count {
252 font-family: var(--sans);
253 font-size: var(--fs-0);
254 font-weight: 700;
255 letter-spacing: 0;
256 background: var(--shell-mark);
257 color: #000000;
258 padding: 0 0.35rem;
259 border-radius: var(--r-sm);
260}
261/* pinned above the account cell: always reachable, never scrolled away */
262.railpinned {
263 flex: none;
264 padding: var(--sp-2) 0;
265 border-top: 1px solid var(--shell-line);
266}
267.railfoot {
268 flex: none;
269 border-top: 1px solid var(--shell-line);
270 /* same vertical rhythm as the page footer, so the two rules line up
271 when the page is scrolled to the bottom; horizontal padding stays on
272 the rail's own grid so the avatar aligns with the nav items above */
273 padding: var(--sp-4) var(--sp-4) var(--sp-5);
274 display: flex;
275 align-items: center;
276 gap: var(--sp-3);
277 font-size: var(--fs-2);
278 line-height: 1.4;
279}
280.railfoot a { color: var(--shell-fg); }
281a.railuser { display: inline-flex; align-items: center; gap: var(--sp-2); }
282/* a descendant cannot cancel an ancestor's underline, so the link carries
283 none and the name draws its own — the avatar square stays undecorated */
284a.railuser:hover { text-decoration: none; }
285a.railuser:hover .uname { text-decoration: underline; }
286.railfoot .railsettings { color: var(--shell-muted); display: inline-flex; }
287.railfoot .railsettings:hover { color: var(--shell-fg); }
288.railfoot form { margin-left: auto; }
289.railfoot .linklike {
290 background: none; border: 0; padding: 0; cursor: pointer;
291 color: var(--shell-muted); font: inherit; text-decoration: underline;
292}
293.railfoot .linklike:hover { color: var(--shell-fg); }
294.avatar {
295 width: 1.4rem; height: 1.4rem; flex: none;
296 display: inline-grid; place-items: center;
297 background: var(--fill);
298 color: #ffffff;
299 font-size: var(--fs-0);
300 font-weight: 700;
301 border-radius: var(--r-sm);
302}
303
304.pane { flex: 1; min-width: 0; display: flex; flex-direction: column; }
305.content {
306 flex: 1;
307 padding: var(--sp-5) var(--sp-5) var(--sp-6);
308 width: 100%;
309}
310
311/* ---- repo header: identity and tabs on every page, the rest once ---- */
312.repohead {
313 padding: var(--sp-4) var(--sp-5) 0;
314 border-bottom: 1px solid var(--line);
315}
316.repohead .identity { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
317.repohead .identity .grow { flex: 1; }
318/* h1 on the repo home, p elsewhere so each page keeps its own h1 — but
319 identical in size, because the tabs sit below this and navigation must
320 not move when you use it */
321.repotitle {
322 margin: 0;
323 font-size: var(--fs-4);
324 font-weight: 700;
325 letter-spacing: -0.02em;
326 line-height: 1.3;
327}
328.repotitle a { color: var(--fg); }
329.repotitle a.owner { color: var(--muted); font-weight: 400; }
330.repotitle a:hover { color: var(--accent); text-decoration: none; }
331.repotitle .sep { color: var(--muted); margin: 0 0.12em; font-weight: 400; }
332.repodesc { margin: var(--sp-2) 0 0; color: var(--muted); font-size: var(--fs-2); max-width: 62ch; }
333.repometa { margin: var(--sp-1) 0 0; color: var(--muted); font-size: var(--fs-1); }
334.repohead .topics { margin: var(--sp-2) 0 0; }
335
336button.btn {
337 font: inherit;
338 font-size: var(--fs-1);
339 font-weight: 600;
340 padding: 0.15rem 0.7rem;
341 border: 1px solid var(--line);
342 border-radius: var(--r-sm);
343 background: var(--bg);
344 color: var(--fg);
345 cursor: pointer;
346}
347button.btn:hover { border-color: var(--accent); color: var(--accent); }
348button.btn[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
349form.inline { display: inline; }
350
351nav.tabs {
352 display: flex;
353 gap: var(--sp-1);
354 margin-top: var(--sp-4);
355 overflow-x: auto;
356 /* with overflow-y left visible the browser computes it to auto, which
357 is a vertical drag on touch; the strip scrolls sideways only. */
358 overflow-y: hidden;
359 scrollbar-width: none;
360}
361nav.tabs::-webkit-scrollbar { display: none; }
362nav.tabs a {
363 display: inline-flex;
364 align-items: center;
365 gap: var(--sp-2);
366 padding: var(--sp-2) var(--sp-3) 0.6rem;
367 color: var(--muted);
368 font-size: var(--fs-2);
369 white-space: nowrap;
370 border-bottom: 2px solid transparent;
371 margin-bottom: -1px;
372}
373nav.tabs a:hover { color: var(--fg); text-decoration: none; }
374/* orange marks position here too */
375nav.tabs a[aria-current] {
376 color: var(--fg);
377 font-weight: 700;
378 border-bottom-color: var(--mark);
379}
380nav.tabs a i {
381 font-style: normal;
382 font-family: var(--mono);
383 font-size: var(--fs-0);
384 background: var(--hover);
385 border-radius: var(--r-sm);
386 padding: 0 0.35rem;
387}
388
389/* ---- mobile: the rail becomes a single strip, not a wall of links ---- */
390@media (max-width: 52rem) {
391 .shell { display: block; }
392 .rail {
393 width: auto;
394 height: auto;
395 position: static;
396 flex-direction: row;
397 align-items: center;
398 gap: var(--sp-2);
399 border-right: 0;
400 border-bottom: 1px solid var(--shell-line);
401 overflow-x: auto;
402 }
403 a.brand { border-bottom: 0; padding-right: var(--sp-2); }
404 .railbody { flex: 1; overflow: visible; padding: 0; display: flex; align-items: center; }
405 /* pinned repos and the review queue both live on the dashboard, so the
406 strip keeps only what has nowhere else to go */
407 .railgroup { display: none; }
408 ul.raillist { display: flex; }
409 ul.raillist a { border-left: 0; border-bottom: 2px solid transparent; padding: var(--sp-2) var(--sp-3); }
410 ul.raillist a[aria-current] { border-left: 0; border-bottom-color: var(--shell-mark); }
411 /* the rail is a horizontal strip here: keep the account cell compact */
412 .railfoot { border-top: 0; padding: var(--sp-2); }
413 .railpinned { border-top: 0; padding: 0; }
414 .content { padding: var(--sp-4) var(--sp-4) var(--sp-5); }
415 .repohead { padding: var(--sp-3) var(--sp-4) 0; }
416}
417
418/* tables */
419table { border-collapse: collapse; width: 100%; }
420td {
421 padding: var(--sp-2) var(--sp-4) var(--sp-2) 0;
422 border-bottom: 1px solid var(--faint);
423 vertical-align: top;
424 font-size: var(--fs-2);
425}
426td:last-child { padding-right: 0; }
427td.size, td.mode { color: var(--muted); white-space: nowrap; }
428
429/* path bar on tree and blob pages */
430.pathbar {
431 display: flex;
432 flex-wrap: wrap;
433 align-items: center;
434 gap: var(--sp-2) var(--sp-3);
435 margin: var(--sp-3) 0;
436 font-size: var(--fs-2);
437}
438.pathbar .spacer { flex: 1; }
439.refchip {
440 display: inline-flex;
441 align-items: center;
442 gap: 0.3rem;
443 background: var(--surface);
444 border: 1px solid var(--faint);
445 border-radius: var(--r-md);
446 padding: 0.1rem 0.55rem;
447 font-family: var(--mono);
448 font-size: var(--fs-1);
449 color: var(--fg);
450}
451.pathbar .crumbs strong { color: var(--fg); }
452details.refmenu { position: relative; }
453details.refmenu summary { cursor: pointer; list-style: none; }
454details.refmenu summary::-webkit-details-marker { display: none; }
455details.refmenu summary::after { content: " ▾"; color: var(--muted); }
456details.refmenu .refdrop {
457 position: absolute;
458 z-index: 10;
459 top: calc(100% + 4px);
460 left: 0;
461 min-width: 12rem;
462 max-height: 20rem;
463 overflow-y: auto;
464 background: var(--bg);
465 border: 1px solid var(--line);
466 border-radius: var(--r-md);
467 box-shadow: 0 4px 16px rgba(0,0,0,0.12);
468 padding: var(--sp-1) 0;
469}
470details.refmenu .refdrop a {
471 display: block;
472 padding: var(--sp-1) var(--sp-3);
473 color: var(--fg);
474 font-family: var(--mono);
475 font-size: var(--fs-1);
476}
477details.refmenu .refdrop a:hover { background: var(--hover); text-decoration: none; }
478details.refmenu .refdrop a.allrefs { color: var(--accent); font-family: var(--sans); border-top: 1px solid var(--faint); margin-top: var(--sp-1); }
479
480/* file and refs tables: bordered cards, rows inside */
481/* wide listings scroll inside their own box; the page never does */
482.tablewrap { overflow-x: auto; max-width: 100%; }
483
484table.tree, table.refs {
485 background: var(--surface);
486 border: 1px solid var(--line);
487 border-radius: var(--r-lg);
488 border-collapse: separate;
489 border-spacing: 0;
490 overflow: hidden;
491 margin-bottom: var(--sp-4);
492}
493table.tree td, table.refs td {
494 padding: var(--sp-2) var(--sp-4);
495 border-bottom: 1px solid var(--faint);
496}
497table.tree tr:last-child td, table.refs tr:last-child td { border-bottom: none; }
498table.tree tr:hover td, table.refs tr:hover td { background: var(--hover); }
499tr.cols th {
500 text-align: left;
501 font-weight: 500;
502 font-size: var(--fs-1);
503 color: var(--muted);
504 padding: var(--sp-1) var(--sp-4);
505 border-bottom: 1px solid var(--line);
506 background: var(--bg);
507}
508tr.cols:hover th { background: var(--bg); }
509/* right-aligned columns keep their header with their values; this needs to
510 outrank the tr.cols th rule above, which is why it names both */
511tr.cols th.age, tr.cols th.size { text-align: right; }
512table.tree th.size { text-align: right; }
513table.tree td.name { width: 100%; }
514table.tree td.name a { color: var(--fg); }
515table.tree td.name a:hover { color: var(--accent); }
516table.tree td.size { text-align: right; }
517table.tree td.empty, table.refs td.empty, li.empty, ul.loglist li.empty { color: var(--muted); }
518
519/* refs page */
520table.refs td.name { width: 100%; }
521table.refs td.sha { color: var(--muted); }
522
523/* card header (README) */
524.cardhead {
525 font-family: var(--mono);
526 font-size: var(--fs-1);
527 color: var(--muted);
528 border-bottom: 1px solid var(--faint);
529 margin: calc(-1 * var(--sp-4)) calc(-1 * var(--sp-5)) var(--sp-4);
530 padding: var(--sp-2) var(--sp-5);
531 background: var(--bg);
532 border-radius: var(--r-lg) var(--r-lg) 0 0;
533}
534
535/* log */
536ul.loglist {
537 list-style: none;
538 margin: var(--sp-3) 0;
539 padding: 0;
540 background: var(--surface);
541 border: 1px solid var(--line);
542 border-radius: var(--r-lg);
543 overflow: hidden;
544}
545ul.loglist li {
546 display: flex;
547 align-items: baseline;
548 gap: var(--sp-3);
549 padding: var(--sp-2) var(--sp-4);
550 border-bottom: 1px solid var(--faint);
551}
552ul.loglist li:last-child { border-bottom: none; }
553ul.loglist li:hover { background: var(--hover); }
554ul.loglist .commitmain { flex: 1; min-width: 0; }
555ul.loglist p { margin: 0; }
556ul.loglist .subject a { color: var(--fg); font-weight: 550; }
557ul.loglist .subject a:hover { color: var(--accent); }
558ul.loglist .commitside {
559 display: flex;
560 align-items: baseline;
561 gap: var(--sp-2);
562 white-space: nowrap;
563}
564p.pager { margin-top: var(--sp-4); }
565
566/* commit page */
567.commithead p { margin: var(--sp-1) 0; }
568.commithead h2 { margin-bottom: var(--sp-1); }
569code.fullsha { color: var(--muted); overflow-wrap: anywhere; }
570.empty-note { color: var(--muted); }
571.crumbs { color: var(--muted); font-size: var(--fs-2); }
572.desc, td.desc { color: var(--muted); }
573.error {
574 color: var(--fg);
575 border: 1px solid var(--bad);
576 border-left-width: 3px;
577 border-radius: var(--r-sm);
578 padding: var(--sp-2) var(--sp-3);
579 margin-bottom: var(--sp-4);
580}
581/* settings: one row per control, label then input then its own button */
582form.setform {
583 display: flex;
584 flex-wrap: wrap;
585 align-items: center;
586 gap: var(--sp-3);
587 padding: var(--sp-2) 0;
588 border-bottom: 1px solid var(--faint);
589}
590form.setform label { min-width: 12rem; color: var(--muted); font-size: var(--fs-2); }
591form.setform input[type="text"], form.setform select { flex: 1 1 16rem; }
592form.setform input[type="number"] { width: 5rem; }
593ul.protlist { list-style: none; padding: 0; margin: var(--sp-2) 0; }
594ul.protlist li { padding: var(--sp-1) 0; display: flex; gap: var(--sp-3); align-items: baseline; }
595
596/* branch picker on the new merge request form */
597p.branchpick {
598 display: flex;
599 flex-wrap: wrap;
600 align-items: center;
601 gap: var(--sp-2);
602}
603p.branchpick label { color: var(--muted); font-size: var(--fs-2); }
604p.branchpick select { flex: 1 1 12rem; }
605
606/* merge request actions in the aside: stacked controls, full width */
607.aside form.actions {
608 display: flex;
609 flex-wrap: wrap;
610 gap: var(--sp-2);
611 margin-top: var(--sp-2);
612}
613.aside form.actions button { flex: 1 1 auto; }
614.aside form.actions select { width: 100%; }
615form.threadact { margin: var(--sp-1) 0 0; padding: 0 var(--sp-3) var(--sp-2); }
616
617.meta { color: var(--muted); font-size: var(--fs-1); }
618svg.icon { vertical-align: -0.125em; }
619.lede { font-size: var(--fs-3); margin: var(--sp-2) 0; }
620
621/* repo listings (explore, owner pages, dashboard): one row per repo */
622ul.repolist {
623 list-style: none;
624 margin: var(--sp-3) 0 var(--sp-5);
625 padding: 0;
626 background: var(--surface);
627 border: 1px solid var(--line);
628 border-radius: var(--r-lg);
629 overflow: hidden;
630}
631ul.repolist li { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--faint); }
632/* pinned repos: a compact wrap of name pills, no description or meta */
633ul.pinlist {
634 list-style: none;
635 margin: var(--sp-3) 0 var(--sp-5);
636 padding: 0;
637 display: flex;
638 flex-wrap: wrap;
639 gap: var(--sp-2);
640}
641ul.pinlist li {
642 background: var(--surface);
643 border: 1px solid var(--line);
644 border-radius: var(--r-md);
645 padding: var(--sp-1) var(--sp-3);
646}
647ul.pinlist li:hover { background: var(--hover); }
648ul.pinlist li a { color: var(--fg); }
649ul.pinlist li a:hover { color: var(--accent); text-decoration: none; }
650ul.pinlist .sep { color: var(--muted); margin: 0 0.15em; }
651ul.repolist li:last-child { border-bottom: none; }
652ul.repolist li:hover { background: var(--hover); }
653ul.repolist li.empty { color: var(--muted); }
654ul.repolist p { margin: 0; }
655ul.repolist .reponame { font-size: var(--fs-3); }
656ul.repolist .reponame a { color: var(--fg); }
657ul.repolist .reponame a strong { color: var(--accent); font-weight: 600; }
658ul.repolist .reponame .sep { color: var(--muted); margin: 0 0.1em; }
659ul.repolist .desc { margin-top: 0.1rem; }
660ul.repolist .topics { margin-top: var(--sp-1); }
661ul.repolist .meta { margin-top: var(--sp-1); }
662
663/* owner profile header */
664.profilehead {
665 border-bottom: 1px solid var(--faint);
666 padding-bottom: var(--sp-4);
667 margin-bottom: var(--sp-4);
668}
669.profilehead h1 { margin: var(--sp-4) 0 var(--sp-1); }
670.profilehead .lede { margin: 0 0 var(--sp-1); }
671.profilehead .meta { margin: var(--sp-1) 0 0; }
672h2 .count { color: var(--muted); font-weight: 400; font-size: var(--fs-2); }
673
674/* activity graph: 53 week columns x 7 day rows, accent-tinted levels */
675.actgraph-scroll { overflow-x: auto; padding-bottom: var(--sp-1); }
676.actgraph { display: flex; gap: 3px; width: max-content; }
677.actweek { display: flex; flex-direction: column; gap: 3px; }
678.actday {
679 width: 11px;
680 height: 11px;
681 border-radius: 2px;
682 background: var(--faint);
683}
684.actday.pad { background: transparent; }
685.actday.l1 { background: color-mix(in srgb, var(--accent) 25%, var(--bg)); }
686.actday.l2 { background: color-mix(in srgb, var(--accent) 50%, var(--bg)); }
687.actday.l3 { background: color-mix(in srgb, var(--accent) 75%, var(--bg)); }
688.actday.l4 { background: var(--accent); }
689
690/* heading row with actions on the right */
691.headrow {
692 display: flex;
693 align-items: baseline;
694 gap: var(--sp-4);
695 flex-wrap: wrap;
696}
697.headrow .spacer { flex: 1; }
698
699/* member and org chips on owner pages */
700a.memberchip {
701 display: inline-block;
702 border: 1px solid var(--line);
703 border-radius: var(--r-pill);
704 padding: 0.05rem 0.6rem;
705 color: var(--fg);
706 font-size: var(--fs-1);
707 margin: 0 0.15rem 0.15rem 0;
708}
709a.memberchip:hover { text-decoration: none; border-color: var(--accent); color: var(--accent); }
710a.memberchip .role { color: var(--muted); }
711
712/* landing page */
713.landing { max-width: 44rem; padding: var(--sp-6) 0; }
714.landing h1 { font-size: 1.8rem; margin-bottom: var(--sp-3); }
715.landing .lede { font-size: var(--fs-4); color: var(--muted); line-height: 1.7; margin: 0 0 var(--sp-4); }
716pre.quickstart {
717 background: var(--code-bg);
718 border: 1px solid var(--line);
719 border-radius: var(--r-md);
720 padding: var(--sp-3) var(--sp-4);
721 overflow-x: auto;
722 margin: 0 0 var(--sp-4);
723}
724.landing .explorelink { font-weight: 550; }
725
726/* index toolbar */
727p.toolbar { color: var(--muted); font-size: var(--fs-2); margin-top: var(--sp-4); }
728form.inline { display: inline; }
729button.linklike {
730 background: none;
731 border: none;
732 color: var(--accent);
733 padding: 0;
734 font: inherit;
735 font-size: var(--fs-2);
736 cursor: pointer;
737}
738button.linklike:hover { text-decoration: underline; filter: none; }
739
740/* cards: README, comments */
741.readme, .code {
742 background: var(--surface);
743 border: 1px solid var(--line);
744 border-radius: var(--r-lg);
745 padding: var(--sp-4) var(--sp-5);
746 margin-top: var(--sp-4);
747 overflow-x: auto;
748}
749/* Highlighting is class-based with a palette per scheme, so code blocks
750 follow the site's own colors. */
751.code { background: var(--code-bg); color: var(--fg); padding: var(--sp-3) var(--sp-4); border-color: var(--line); }
752.code pre { margin: 0; background: transparent !important; }
753@media (prefers-color-scheme: dark) {
754 .code { border-color: var(--line); }
755}
756
757/* rendered markdown / org / html */
758.rendered { max-width: 100%; overflow-wrap: anywhere; }
759/* line length is a reading constraint, so it applies to prose only —
760 tables, code blocks and images keep the full column */
761.rendered > p,
762.rendered > ul,
763.rendered > ol,
764.rendered > blockquote { max-width: 78ch; }
765.rendered pre {
766 background: var(--code-bg);
767 border: 1px solid var(--line);
768 padding: var(--sp-3) var(--sp-4);
769 border-radius: var(--r-md);
770 overflow-x: auto;
771}
772.rendered code {
773 background: var(--code-bg);
774 border: 1px solid var(--line);
775 padding: 0.05rem 0.3rem;
776 border-radius: var(--r-sm);
777}
778.rendered pre code { background: transparent; border: none; padding: 0; }
779.rendered blockquote {
780 border-left: 3px solid var(--line);
781 margin-left: 0;
782 padding-left: var(--sp-4);
783 color: var(--muted);
784}
785.rendered img { max-width: 100%; }
786.rendered h1, .rendered h2 { border-bottom: 1px solid var(--faint); padding-bottom: var(--sp-1); }
787.rendered table {
788 border-collapse: collapse;
789 margin: var(--sp-3) 0;
790 display: block;
791 max-width: 100%;
792 overflow-x: auto;
793}
794.rendered th, .rendered td {
795 border: 1px solid var(--line);
796 padding: var(--sp-1) var(--sp-3);
797 text-align: left;
798 overflow-wrap: normal; /* scroll the table, don't shatter words */
799}
800.rendered th { background: var(--surface); font-weight: 600; }
801.blobimage { text-align: center; }
802.blobimage img {
803 max-width: 100%;
804 border: 1px solid var(--faint);
805 border-radius: var(--r-md);
806 background: var(--surface);
807}
808
809pre.message {
810 background: var(--code-bg);
811 border: 1px solid var(--line);
812 padding: var(--sp-3) var(--sp-4);
813 border-radius: var(--r-md);
814 white-space: pre-wrap;
815 overflow-wrap: anywhere;
816}
817
818/* repo facts: the counts a visitor sizes a project up with */
819.teambody { padding: var(--sp-3); background: var(--bg); }
820.teambody .memberchip { margin-right: var(--sp-2); }
821
822form.logfilter {
823 display: flex; align-items: center; gap: var(--sp-2);
824 margin: 0 0 var(--sp-4); flex-wrap: wrap;
825}
826form.logfilter input { flex: 1; min-width: 12rem; max-width: 28rem; }
827
828/* account settings */
829table.keys td { padding: var(--sp-2) var(--sp-4) var(--sp-2) 0; }
830/* these tables sit flush with the page text, so the header row drops the
831 left padding the card-style listings use */
832table.keys tr.cols th { padding-left: 0; background: transparent; }
833table.keys td.mono, .mono { font-family: var(--mono); font-size: var(--fs-1); overflow-wrap: anywhere; }
834table.keys td.act { text-align: right; }
835ul.plain { list-style: none; margin: 0 0 var(--sp-3); padding: 0; }
836ul.plain li { padding: var(--sp-1) 0; display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
837form.setform.stack { display: block; }
838form.setform.stack textarea, form.setform.stack select { width: 100%; max-width: 48rem; display: block; margin-bottom: var(--sp-2); }
839p.notice {
840 border-left: 3px solid var(--ok);
841 background: var(--hover);
842 padding: var(--sp-2) var(--sp-3);
843 margin: 0 0 var(--sp-4);
844}
845
846.facts { margin: 0 0 var(--sp-4); }
847.facts .counts {
848 display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4);
849 margin: 0 0 var(--sp-3); font-size: var(--fs-2);
850}
851.facts .counts a { color: var(--fg); text-decoration: none; }
852.facts .counts a:hover { color: var(--accent); text-decoration: underline; }
853.facts .counts .fact { color: var(--muted); }
854.facts .counts strong { font-weight: 600; }
855
856.langbar {
857 display: flex; height: 0.5rem; margin: 0 0 var(--sp-2);
858 border-radius: var(--r-sm); overflow: hidden; background: var(--faint);
859}
860.langbar .lang { display: block; min-width: 2px; }
861.langs {
862 display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4);
863 margin: 0 0 var(--sp-3); font-size: var(--fs-1);
864}
865.langs .lang-name { display: inline-flex; align-items: center; gap: var(--sp-1); }
866.langs .muted { color: var(--muted); }
867.langs .dot { width: 0.6rem; height: 0.6rem; border-radius: 50%; display: inline-block; }
868/* named where it reads as the language's own color, neutral otherwise */
869.lang { background: var(--neutral); }
870.lang-go { background: #00add8; }
871.lang-rust { background: #dea584; }
872.lang-c, .lang-c- { background: #555555; }
873.lang-python { background: #3572a5; }
874.lang-javascript { background: #f1e05a; }
875.lang-typescript { background: #3178c6; }
876.lang-shell { background: #89e051; }
877.lang-ruby { background: #701516; }
878.lang-java { background: #b07219; }
879.lang-swift { background: #f05138; }
880.lang-html { background: #e34c26; }
881.lang-css { background: #563d7c; }
882.lang-org { background: #77aa99; }
883.lang-markdown { background: #083fa1; }
884.lang-emacs-lisp { background: #c065db; }
885.lang-nix { background: #7e7eff; }
886.lang-sql { background: #e38c00; }
887
888.contribs {
889 display: flex; flex-wrap: wrap; align-items: baseline;
890 gap: var(--sp-1) var(--sp-3); margin: 0; font-size: var(--fs-1);
891}
892.contribs .label { color: var(--muted); }
893
894/* diffs: one foldable section per file, a table so the line-number
895 gutters stay put while the code scrolls */
896details.difffold {
897 border: 1px solid var(--line);
898 border-radius: var(--r-md);
899 margin: 0 0 var(--sp-3);
900 background: var(--code-bg);
901}
902details.difffold summary {
903 cursor: pointer;
904 display: flex;
905 align-items: baseline;
906 gap: var(--sp-3);
907 padding: var(--sp-2) var(--sp-3);
908 list-style: none;
909 font-size: var(--fs-2);
910}
911details.difffold[open] summary { border-bottom: 1px solid var(--line); }
912details.difffold summary::-webkit-details-marker { display: none; }
913/* flex summaries lose the native disclosure marker; draw our own */
914details.difffold summary::before { content: "\25b8"; color: var(--muted); }
915details.difffold[open] summary::before { content: "\25be"; }
916details.difffold summary:hover { background: var(--fill-subtle); }
917summary .fpath { font-family: var(--mono); overflow-wrap: anywhere; }
918summary .fpath .was { color: var(--muted); }
919summary .fstat { margin-left: auto; font-family: var(--mono); white-space: nowrap; }
920details.difffold .add { color: var(--ok); }
921details.difffold .del { color: var(--bad); }
922details.difffold > .none { padding: var(--sp-3); margin: 0; }
923details.difffold .tablewrap { border-radius: 0 0 var(--r-md) var(--r-md); }
924
925table.difftable {
926 border-collapse: collapse;
927 width: 100%;
928 font-family: var(--mono);
929 font-size: var(--fs-1);
930 line-height: 1.5;
931}
932table.difftable td {
933 border: 0;
934 padding: 0;
935 vertical-align: top;
936 font-size: inherit;
937}
938table.difftable td.ln {
939 width: 1%;
940 min-width: 2.5rem;
941 padding: 0 var(--sp-2);
942 text-align: right;
943 color: var(--muted);
944 user-select: none;
945 border-right: 1px solid var(--line);
946 white-space: nowrap;
947}
948/* not .code: that class is the blob/code-block style and carries its own
949 background, which painted over every row tint */
950table.difftable td.src {
951 padding: 0 var(--sp-3);
952 white-space: pre-wrap;
953 overflow-wrap: anywhere;
954}
955/* the marker is decoration, so it lives in CSS and stays out of a copied
956 selection */
957table.difftable tr.add td.src::before { content: "+"; color: var(--ok); }
958table.difftable tr.del td.src::before { content: "\2212"; color: var(--bad); }
959table.difftable tr.ctx td.src::before { content: " "; }
960table.difftable tr.add { background: var(--diff-add); }
961table.difftable tr.del { background: var(--diff-del); }
962table.difftable tr.hunk td, table.difftable tr.dmeta td {
963 color: var(--muted);
964 padding: var(--sp-1) var(--sp-3);
965 background: var(--fill-subtle);
966 border-top: 1px solid var(--line);
967 border-bottom: 1px solid var(--line);
968}
969table.difftable tr.hunk td.src { color: var(--accent); }
970table.difftable tr.threadrow td { padding: var(--sp-2) var(--sp-3); background: var(--bg); }
971
972/* badges: signature and check states. Semantic colors stay distinct:
973 green verified/success, amber pending/stale, red bad/failure, muted
974 unsigned. */
975.badge, .chip {
976 --chip: var(--neutral);
977 display: inline-block;
978 padding: 0.05rem 0.55rem;
979 border-radius: var(--r-pill);
980 font-size: var(--fs-0);
981 font-weight: 500;
982 line-height: 1.5;
983 color: var(--chip);
984 border: 1px solid color-mix(in srgb, var(--chip) 35%, transparent);
985 background: color-mix(in srgb, var(--chip) 7%, transparent);
986 white-space: nowrap;
987 vertical-align: middle;
988}
989.chip-open { --chip: var(--ok); }
990.chip-closed { --chip: var(--bad); }
991.chip-merged, .chip-done { --chip: var(--done); }
992.chip-neutral, .chip-source_gone { --chip: var(--neutral); }
993.chip-stale { --chip: var(--warn); }
994.chip.label { font-weight: 500; }
995.chip.topic { --chip: var(--accent); }
996.repohead .topics { margin: 0 0 var(--sp-2); }
997.repohead .mirrorline { margin: 0 0 var(--sp-2); }
998.mirrorerr { color: var(--bad); }
999.badge-verified { --chip: var(--ok); }
1000.badge-unsigned { --chip: var(--neutral); }
1001.badge-signed_unknown_key { --chip: var(--warn); }
1002.badge-signed_email_mismatch { --chip: var(--bad); }
1003.badge-signed_key_expired { --chip: var(--warn); }
1004.badge-signed_key_revoked { --chip: var(--bad); }
1005.badge-bad_signature { --chip: var(--bad); }
1006.badge.check-success { --chip: var(--ok); }
1007.badge.check-pending { --chip: var(--warn); }
1008.badge.check-failure, .badge.check-error { --chip: var(--bad); }
1009.badge.check-running, .chip.check-running { --chip: var(--warn); }
1010.chip.check-success { --chip: var(--ok); }
1011.chip.check-pending { --chip: var(--warn); }
1012.chip.check-failure { --chip: var(--bad); }
1013pre.buildlog { max-height: 40rem; overflow: auto; }
1014span.check-success { color: var(--ok); }
1015span.check-pending { color: var(--warn); }
1016span.check-failure, span.check-error { color: var(--bad); }
1017
1018/* issue and MR listings */
1019.listhead {
1020 display: flex;
1021 align-items: baseline;
1022 gap: var(--sp-4);
1023 flex-wrap: wrap;
1024}
1025.listhead h2 { margin-bottom: var(--sp-2); }
1026nav.filters { display: flex; gap: var(--sp-1); }
1027nav.filters a {
1028 color: var(--muted);
1029 font-size: var(--fs-2);
1030 padding: 0.05rem var(--sp-2);
1031 border-radius: var(--r-pill);
1032}
1033nav.filters a:hover { color: var(--fg); background: var(--hover); text-decoration: none; }
1034nav.filters a.active { color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
1035
1036ul.issuelist {
1037 list-style: none;
1038 margin: var(--sp-2) 0;
1039 padding: 0;
1040 background: var(--surface);
1041 border: 1px solid var(--line);
1042 border-radius: var(--r-lg);
1043 overflow: hidden;
1044}
1045ul.issuelist li {
1046 display: flex;
1047 align-items: baseline;
1048 gap: var(--sp-3);
1049 padding: var(--sp-3) var(--sp-4);
1050 border-bottom: 1px solid var(--faint);
1051}
1052ul.issuelist li:last-child { border-bottom: none; }
1053ul.issuelist li:hover { background: var(--hover); }
1054ul.issuelist li.empty { display: block; color: var(--muted); }
1055ul.issuelist .issuemain { flex: 1; min-width: 0; }
1056ul.issuelist p { margin: 0; }
1057ul.issuelist .title a { color: var(--fg); font-weight: 550; }
1058ul.issuelist .title a:hover { color: var(--accent); }
1059
1060/* releases */
1061article.release {
1062 background: var(--surface);
1063 border: 1px solid var(--line);
1064 border-radius: var(--r-lg);
1065 padding: var(--sp-3) var(--sp-4);
1066 margin: var(--sp-4) 0;
1067}
1068.releasehead { background: none; border: 0; padding: 0; }
1069.releasehead h3 { margin: 0 0 var(--sp-1); }
1070.releasehead .meta { margin: 0 0 var(--sp-2); }
1071table.assets { margin-top: var(--sp-2); }
1072table.assets td.size { color: var(--muted); white-space: nowrap; text-align: right; }
1073table.assets td.name { width: 100%; font-family: var(--mono); font-size: var(--fs-1); }
1074
1075/* milestones */
1076ul.milestonelist {
1077 list-style: none;
1078 margin: var(--sp-2) 0;
1079 padding: 0;
1080 border: 1px solid var(--line);
1081 border-radius: var(--r-lg);
1082 overflow: hidden;
1083}
1084ul.milestonelist li { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--faint); }
1085ul.milestonelist li:last-child { border-bottom: none; }
1086ul.milestonelist li.empty { color: var(--muted); }
1087ul.milestonelist p { margin: 0; }
1088ul.milestonelist .title { font-weight: 550; }
1089.progress {
1090 height: 6px;
1091 background: var(--faint);
1092 border-radius: var(--r-pill);
1093 margin-top: var(--sp-2);
1094 overflow: hidden;
1095 max-width: 24rem;
1096}
1097.progress .bar { height: 100%; background: var(--ok); }
1098.listhead .spacer { flex: 1; }
1099
1100/* issue / MR detail */
1101h2.issuetitle { margin-bottom: var(--sp-1); font-size: var(--fs-5); }
1102.issuenumber { color: var(--muted); font-weight: 400; }
1103.issuemeta { color: var(--muted); font-size: var(--fs-2); margin-top: 0; }
1104.review { font-size: var(--fs-2); }
1105
1106/* comment cards; discussion stays at a readable measure */
1107article.comment, form.commentform {
1108 max-width: 48rem;
1109}
1110article.comment {
1111 border: 1px solid var(--faint);
1112 border-radius: var(--r-lg);
1113 margin: var(--sp-4) 0;
1114}
1115article.comment .commenthead {
1116 background: var(--surface);
1117 border-bottom: 1px solid var(--faint);
1118 border-radius: var(--r-lg) var(--r-lg) 0 0;
1119 padding: var(--sp-2) var(--sp-4);
1120 font-size: var(--fs-2);
1121}
1122article.comment .commenthead .when { color: var(--muted); }
1123article.comment .rendered { padding: 0 var(--sp-4); }
1124article.comment .rendered > :first-child { margin-top: var(--sp-3); }
1125article.comment .rendered > :last-child { margin-bottom: var(--sp-3); }
1126form.commentform { margin: var(--sp-4) 0; }
1127details.editbox { margin: var(--sp-2) 0; max-width: 48rem; }
1128details.editbox summary { cursor: pointer; color: var(--muted); font-size: var(--fs-2); }
1129details.editbox summary:hover { color: var(--accent); }
1130details.editbox input[type="text"] { width: 100%; }
1131.syscomment {
1132 max-width: 48rem;
1133 color: var(--muted);
1134 font-size: var(--fs-2);
1135 margin: var(--sp-3) 0;
1136 padding-left: var(--sp-4);
1137 border-left: 3px solid var(--faint);
1138}
1139.syscomment p { display: inline; margin: 0; }
1140
1141/* review threads under diff lines */
1142.thread {
1143 border: 1px solid var(--faint);
1144 border-left: 3px solid var(--accent);
1145 border-radius: var(--r-md);
1146 padding: var(--sp-2) var(--sp-4);
1147 margin: var(--sp-2) 0 var(--sp-2) var(--sp-6);
1148}
1149.thread.resolved { border-left-color: var(--ok); opacity: 0.75; }
1150.thread.stale { border-left-color: var(--warn); }
1151.thread p.commenthead { font-size: var(--fs-2); margin: var(--sp-2) 0 0; }
1152.thread .when { color: var(--muted); }
1153.thread .rendered p { margin: var(--sp-1) 0; }
1154.thread .threadstate { color: var(--muted); font-size: var(--fs-1); margin: var(--sp-1) 0 0; }
1155
1156/* forms: every control shares one shell, so a select reads as a sibling
1157 of the text inputs beside it rather than as an OS control dropped in */
1158input, textarea, button, select { font: inherit; color: inherit; }
1159input[type="text"], input[type="search"], input[type="email"],
1160input[type="password"], input:not([type]), textarea, select {
1161 background: var(--bg);
1162 color: var(--fg);
1163 border: 1px solid var(--line);
1164 border-radius: var(--r-md);
1165 padding: var(--sp-2) var(--sp-3);
1166 line-height: 1.4;
1167}
1168textarea { width: 100%; resize: vertical; }
1169textarea[name="content"] { font-family: var(--mono); font-size: var(--fs-1); }
1170/* the native arrow cannot be restyled, so draw our own and match the
1171 inputs exactly; --chev carries the stroke colour per scheme */
1172select {
1173 appearance: none;
1174 padding-right: 1.9rem;
1175 background-image: var(--chev);
1176 background-repeat: no-repeat;
1177 background-position: right 0.6rem center;
1178 background-size: 0.62rem;
1179 cursor: pointer;
1180}
1181input:hover, textarea:hover, select:hover { border-color: var(--muted); }
1182/* the global :focus-visible ring covers these; only the border moves */
1183input:focus, textarea:focus, select:focus { border-color: var(--accent); }
1184input[type="radio"], input[type="checkbox"] { accent-color: var(--fill); }
1185label:has(> input[type="radio"]), label:has(> input[type="checkbox"]),
1186label:has(> select) { display: inline-flex; align-items: center; gap: var(--sp-2); }
1187
1188/* Shape carries the meaning on these two and nothing else does: a circle
1189 takes one answer, a square takes any number. It survives colour being
1190 removed — greyscale, high contrast, colour blindness — so the native
1191 shapes stay and only the colour joins the system. Drawing them by hand
1192 would align the corners at the cost of the one cue that always works. */
1193input[type="radio"], input[type="checkbox"] { accent-color: var(--fill); }
1194
1195/* a segmented control for a small, mutually exclusive set: real radios
1196 underneath, so arrow keys and screen readers behave as they always did */
1197fieldset.segmented { border: 0; margin: 0 0 var(--sp-4); padding: 0; }
1198fieldset.segmented legend {
1199 padding: 0;
1200 margin-bottom: var(--sp-2);
1201 color: var(--muted);
1202 font-size: var(--fs-2);
1203}
1204fieldset.segmented .options { display: inline-flex; }
1205fieldset.segmented label { gap: 0; }
1206fieldset.segmented input {
1207 position: absolute;
1208 width: 1px;
1209 height: 1px;
1210 opacity: 0;
1211 pointer-events: none;
1212}
1213fieldset.segmented span {
1214 display: block;
1215 padding: var(--sp-2) var(--sp-4);
1216 border: 1px solid var(--line);
1217 font-size: var(--fs-2);
1218 cursor: pointer;
1219}
1220fieldset.segmented label + label span { border-left: 0; }
1221fieldset.segmented label:first-child span { border-radius: var(--r-sm) 0 0 var(--r-sm); }
1222fieldset.segmented label:last-child span { border-radius: 0 var(--r-sm) var(--r-sm) 0; }
1223fieldset.segmented span:hover { border-color: var(--muted); }
1224fieldset.segmented input:checked + span {
1225 background: var(--fill);
1226 border-color: var(--fill);
1227 color: #ffffff;
1228 font-weight: 600;
1229}
1230fieldset.segmented input:focus-visible + span {
1231 outline: 2px solid var(--accent);
1232 outline-offset: 2px;
1233}
1234
1235/* remaining input states */
1236::placeholder { color: var(--muted); opacity: 1; }
1237::selection { background: var(--fill); color: #ffffff; }
1238/* :user-invalid, not :invalid — a required field is invalid the moment
1239 the page loads, and colouring it red before anyone has typed is a
1240 scolding, not a hint */
1241input:user-invalid, textarea:user-invalid {
1242 border-color: var(--bad);
1243}
1244.hint { display: block; color: var(--muted); font-size: var(--fs-1); margin-top: var(--sp-1); }
1245button {
1246 background: var(--fill);
1247 color: #ffffff;
1248 border: none;
1249 border-radius: var(--r-md);
1250 padding: var(--sp-2) var(--sp-4);
1251 font-weight: 600;
1252 cursor: pointer;
1253}
1254button:hover { filter: brightness(1.15); }
1255
1256/* 404 */
1257.notfound { text-align: center; padding: var(--sp-6) 0; }
1258.notfound .bigcode {
1259 font-family: var(--mono);
1260 font-size: 4rem;
1261 color: var(--faint);
1262 -webkit-text-stroke: 1px var(--line);
1263 margin: 0;
1264 line-height: 1;
1265}
1266.notfound h1 { margin-top: var(--sp-3); }
1267
1268/* footer */
1269footer {
1270 border-top: 1px solid var(--faint);
1271 padding: var(--sp-4) var(--sp-5) var(--sp-5);
1272 width: 100%;
1273 color: var(--muted);
1274 font-size: var(--fs-1);
1275}
1276footer p { margin: 0; }
1277footer a { color: var(--muted); text-decoration: underline; }
1278footer a:hover { color: var(--accent); }
1279
1280/* search */
1281form.searchform {
1282 display: flex;
1283 gap: var(--sp-2);
1284 margin: var(--sp-3) 0 var(--sp-4);
1285}
1286form.searchform input[type="search"] { flex: 1; max-width: 32rem; }
1287form.searchform.compact { margin: 0; }
1288form.searchform.compact input[type="search"] {
1289 padding: var(--sp-1) var(--sp-3);
1290 font-size: var(--fs-2);
1291 min-width: 18rem;
1292}
1293ul.matchlist { list-style: none; margin: var(--sp-3) 0; padding: 0; }
1294ul.matchlist li { margin-bottom: var(--sp-3); }
1295ul.matchlist .matchpath { font-family: var(--mono); font-size: var(--fs-1); }
1296pre.matchline {
1297 background: var(--code-bg);
1298 border: 1px solid var(--faint);
1299 border-radius: var(--r-md);
1300 padding: var(--sp-1) var(--sp-3);
1301 margin: var(--sp-1) 0 0;
1302 overflow-x: auto;
1303}
1304pre.matchline mark {
1305 background: color-mix(in srgb, var(--warn) 25%, transparent);
1306 color: inherit;
1307 border-radius: 2px;
1308}
1309
1310/* wiki */
1311.wikilayout { display: flex; gap: var(--sp-5); align-items: flex-start; }
1312.wikipage { flex: 1; min-width: 0; }
1313.wikinav { flex: none; width: 13rem; padding-top: var(--sp-4); }
1314.wikinav ul { list-style: none; margin: var(--sp-1) 0 var(--sp-4); padding: 0; }
1315.wikinav li a { display: block; padding: 0.15rem 0; color: var(--fg); }
1316.wikinav li a:hover { color: var(--accent); text-decoration: none; }
1317.wikinav li a.active { color: var(--accent); font-weight: 550; }
1318@media (max-width: 40rem) {
1319 /* Column direction + the desktop align-items:flex-start lets .wikipage
1320 take its content's intrinsic width, overflowing the viewport (and
1321 triggering iOS font inflation). Stretch pins it to the container. */
1322 .wikilayout { flex-direction: column; align-items: stretch; }
1323 .wikinav { width: auto; padding-top: 0; }
1324}
1325
1326/* blame */
1327.blame {
1328 border: 1px solid var(--line);
1329 border-radius: var(--rad-2, 6px);
1330 overflow: hidden;
1331}
1332.blamehunk {
1333 display: flex;
1334 gap: var(--sp-3);
1335 border-top: 1px solid var(--line);
1336 align-items: flex-start;
1337}
1338.blamehunk:first-child { border-top: none; }
1339.blameinfo {
1340 flex: none;
1341 width: 17rem;
1342 padding: var(--sp-2) var(--sp-3);
1343 min-width: 0;
1344}
1345.blameinfo .subject {
1346 margin: 0;
1347 font-size: var(--fs-1);
1348 white-space: nowrap;
1349 overflow: hidden;
1350 text-overflow: ellipsis;
1351}
1352.blameinfo .meta { margin: 0; font-size: var(--fs-1); color: var(--muted); }
1353.blamecode {
1354 flex: 1;
1355 margin: 0;
1356 padding: var(--sp-2) var(--sp-3) var(--sp-2) 0;
1357 overflow-x: auto;
1358 border-left: 1px solid var(--line);
1359 align-self: stretch;
1360}
1361.lineno {
1362 display: inline-block;
1363 min-width: 3.5em;
1364 padding-right: 1em;
1365 text-align: right;
1366 color: var(--muted);
1367 user-select: none;
1368}
1369
1370/* mobile */
1371@media (max-width: 40rem) {
1372 .container { padding-left: var(--sp-4); padding-right: var(--sp-4); }
1373 main.container { padding-top: var(--sp-2); }
1374 .repogrid { grid-template-columns: 1fr; }
1375 .thread { margin-left: var(--sp-3); }
1376 /* the commit subject is the widest thing in the listing and the one
1377 column a phone can do without: the tipbar above already names the
1378 latest commit. */
1379 table.tree td.lastcommit, table.tree th.lastcommit { display: none; }
1380 table.tree td.mode, table.tree th.mode { display: none; }
1381 .clone, .pathbar { overflow-wrap: anywhere; }
1382 .readme, .code { padding: var(--sp-3); }
1383 .blamehunk { flex-direction: column; gap: 0; }
1384 .blameinfo { width: auto; }
1385 .blamecode { border-left: none; padding-left: var(--sp-3); width: 100%; }
1386 .cardhead {
1387 margin: calc(-1 * var(--sp-3)) calc(-1 * var(--sp-3)) var(--sp-3);
1388 padding: var(--sp-2) var(--sp-3);
1389 }
1390}
1391
1392/* tree listing: the last commit is what a file table is scanned for, so
1393 it leads. The file's own facts moved to the blob page. */
1394.tipbar {
1395 display: flex;
1396 align-items: center;
1397 gap: var(--sp-3);
1398 padding: var(--sp-2) var(--sp-4);
1399 background: var(--hover);
1400 border: 1px solid var(--line);
1401 border-bottom: 0;
1402 border-radius: var(--r-lg) var(--r-lg) 0 0;
1403 font-size: var(--fs-2);
1404}
1405.tipbar .who { font-weight: 600; }
1406.tipbar .subject { color: var(--fg); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1407.tipbar .subject:hover { color: var(--accent); }
1408.tipbar .spacer { flex: 1; }
1409.tipbar .age { color: var(--muted); white-space: nowrap; }
1410.tipbar + table.tree { border-radius: 0 0 var(--r-lg) var(--r-lg); }
1411table.tree th.lastcommit, table.tree td.lastcommit { width: 55%; }
1412table.tree td.lastcommit a { color: var(--muted); display: block; overflow: hidden;
1413 text-overflow: ellipsis; white-space: nowrap; }
1414table.tree td.lastcommit a:hover { color: var(--accent); }
1415table.tree th.age, table.tree td.age {
1416 text-align: right;
1417 white-space: nowrap;
1418 color: var(--muted);
1419 font-variant-numeric: tabular-nums;
1420}
1421table.tree td.name { width: 25%; white-space: nowrap; }
1422table.tree td.name.dir a { color: var(--accent); }
1423p.clone { margin: 0 0 var(--sp-3); }
1424p.filefacts { color: var(--muted); font-size: var(--fs-1); margin: 0 0 var(--sp-3); }
1425.pathbar .act { font-size: var(--fs-1); }
1426
1427/* merge request: a two-column split, so state has somewhere to live that
1428 is not a run-on sentence under the title */
1429.withaside {
1430 display: grid;
1431 grid-template-columns: minmax(0, 1fr) 15rem;
1432 gap: var(--sp-5);
1433 align-items: start;
1434}
1435.withaside .mainside { min-width: 0; }
1436@media (max-width: 62rem) { .withaside { grid-template-columns: 1fr; } }
1437
1438.aside { font-size: var(--fs-2); }
1439.aside .grp { border-top: 1px solid var(--line); padding: var(--sp-3) 0; }
1440.aside .grp:first-child { border-top: 0; padding-top: 0; }
1441.aside h2 {
1442 margin: 0 0 var(--sp-2);
1443 font-family: var(--mono);
1444 font-size: var(--fs-0);
1445 font-weight: 500;
1446 letter-spacing: 0.1em;
1447 text-transform: uppercase;
1448 color: var(--muted);
1449}
1450.aside .row { display: flex; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-1); flex-wrap: wrap; }
1451.aside .row:last-child { margin-bottom: 0; }
1452.aside .none { color: var(--muted); }
1453.aside .dot { width: 0.45rem; height: 0.45rem; flex: none; border-radius: 50%; background: var(--muted); }
1454.aside .dot.ok { background: var(--ok); }
1455.aside .dot.bad { background: var(--bad); }
1456.aside .dot.pend { background: var(--mark); }
1457
1458/* sub-navigation within an item; orange marks position as it does above */
1459nav.subtabs {
1460 display: flex;
1461 gap: var(--sp-4);
1462 border-bottom: 1px solid var(--line);
1463 margin: 0 0 var(--sp-4);
1464}
1465nav.subtabs a {
1466 display: inline-flex;
1467 align-items: center;
1468 gap: var(--sp-2);
1469 padding: 0 0 var(--sp-2);
1470 color: var(--muted);
1471 font-size: var(--fs-2);
1472 border-bottom: 2px solid transparent;
1473 margin-bottom: -1px;
1474}
1475nav.subtabs a:hover { color: var(--fg); text-decoration: none; }
1476nav.subtabs a[aria-current] { color: var(--fg); font-weight: 700; border-bottom-color: var(--mark); }
1477nav.subtabs a i {
1478 font-style: normal;
1479 font-family: var(--mono);
1480 font-size: var(--fs-0);
1481 background: var(--hover);
1482 border-radius: var(--r-sm);
1483 padding: 0 0.35rem;
1484}
1485p.diffstat { color: var(--muted); font-size: var(--fs-2); margin: 0 0 var(--sp-3); }
1486p.diffstat .add { color: var(--ok); }
1487p.diffstat .del { color: var(--bad); }