internal/web/static/style.css

d122636fc915dc95728bc74a3990da1630aa36d3
gitbay/internal/web/static/style.css history · blame · raw

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