internal/web/static/style.css

1502 lines · 51272 bytes

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