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