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