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