internal/web/static/style.css

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

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