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