internal/web/static/style.css

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

1437 lines · 47877 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/* repo facts: the counts a visitor sizes a project up with */
 798.facts { margin: 0 0 var(--sp-4); }
 799.facts .counts {
 800  display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4);
 801  margin: 0 0 var(--sp-3); font-size: var(--fs-2);
 802}
 803.facts .counts a { color: var(--fg); text-decoration: none; }
 804.facts .counts a:hover { color: var(--accent); text-decoration: underline; }
 805.facts .counts .fact { color: var(--muted); }
 806.facts .counts strong { font-weight: 600; }
 807
 808.langbar {
 809  display: flex; height: 0.5rem; margin: 0 0 var(--sp-2);
 810  border-radius: var(--r-sm); overflow: hidden; background: var(--faint);
 811}
 812.langbar .lang { display: block; min-width: 2px; }
 813.langs {
 814  display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4);
 815  margin: 0 0 var(--sp-3); font-size: var(--fs-1);
 816}
 817.langs .lang-name { display: inline-flex; align-items: center; gap: var(--sp-1); }
 818.langs .muted { color: var(--muted); }
 819.langs .dot { width: 0.6rem; height: 0.6rem; border-radius: 50%; display: inline-block; }
 820/* named where it reads as the language's own color, neutral otherwise */
 821.lang { background: var(--neutral); }
 822.lang-go { background: #00add8; }
 823.lang-rust { background: #dea584; }
 824.lang-c, .lang-c- { background: #555555; }
 825.lang-python { background: #3572a5; }
 826.lang-javascript { background: #f1e05a; }
 827.lang-typescript { background: #3178c6; }
 828.lang-shell { background: #89e051; }
 829.lang-ruby { background: #701516; }
 830.lang-java { background: #b07219; }
 831.lang-swift { background: #f05138; }
 832.lang-html { background: #e34c26; }
 833.lang-css { background: #563d7c; }
 834.lang-org { background: #77aa99; }
 835.lang-markdown { background: #083fa1; }
 836.lang-emacs-lisp { background: #c065db; }
 837.lang-nix { background: #7e7eff; }
 838.lang-sql { background: #e38c00; }
 839
 840.contribs {
 841  display: flex; flex-wrap: wrap; align-items: baseline;
 842  gap: var(--sp-1) var(--sp-3); margin: 0; font-size: var(--fs-1);
 843}
 844.contribs .label { color: var(--muted); }
 845
 846/* diffs: one foldable section per file, a table so the line-number
 847   gutters stay put while the code scrolls */
 848details.difffold {
 849  border: 1px solid var(--line);
 850  border-radius: var(--r-md);
 851  margin: 0 0 var(--sp-3);
 852  background: var(--code-bg);
 853}
 854details.difffold summary {
 855  cursor: pointer;
 856  display: flex;
 857  align-items: baseline;
 858  gap: var(--sp-3);
 859  padding: var(--sp-2) var(--sp-3);
 860  list-style: none;
 861  font-size: var(--fs-2);
 862}
 863details.difffold[open] summary { border-bottom: 1px solid var(--line); }
 864details.difffold summary::-webkit-details-marker { display: none; }
 865/* flex summaries lose the native disclosure marker; draw our own */
 866details.difffold summary::before { content: "\25b8"; color: var(--muted); }
 867details.difffold[open] summary::before { content: "\25be"; }
 868details.difffold summary:hover { background: var(--fill-subtle); }
 869summary .fpath { font-family: var(--mono); overflow-wrap: anywhere; }
 870summary .fpath .was { color: var(--muted); }
 871summary .fstat { margin-left: auto; font-family: var(--mono); white-space: nowrap; }
 872details.difffold .add { color: var(--ok); }
 873details.difffold .del { color: var(--bad); }
 874details.difffold > .none { padding: var(--sp-3); margin: 0; }
 875details.difffold .tablewrap { border-radius: 0 0 var(--r-md) var(--r-md); }
 876
 877table.difftable {
 878  border-collapse: collapse;
 879  width: 100%;
 880  font-family: var(--mono);
 881  font-size: var(--fs-1);
 882  line-height: 1.5;
 883}
 884table.difftable td {
 885  border: 0;
 886  padding: 0;
 887  vertical-align: top;
 888  font-size: inherit;
 889}
 890table.difftable td.ln {
 891  width: 1%;
 892  min-width: 2.5rem;
 893  padding: 0 var(--sp-2);
 894  text-align: right;
 895  color: var(--muted);
 896  user-select: none;
 897  border-right: 1px solid var(--line);
 898  white-space: nowrap;
 899}
 900table.difftable td.code {
 901  padding: 0 var(--sp-3);
 902  white-space: pre-wrap;
 903  overflow-wrap: anywhere;
 904}
 905/* the marker is decoration, so it lives in CSS and stays out of a copied
 906   selection */
 907table.difftable tr.add td.code::before { content: "+"; color: var(--ok); }
 908table.difftable tr.del td.code::before { content: "\2212"; color: var(--bad); }
 909table.difftable tr.ctx td.code::before { content: " "; }
 910table.difftable tr.add { background: var(--diff-add); }
 911table.difftable tr.del { background: var(--diff-del); }
 912table.difftable tr.hunk td, table.difftable tr.dmeta td {
 913  color: var(--muted);
 914  padding: var(--sp-1) var(--sp-3);
 915  background: var(--fill-subtle);
 916  border-top: 1px solid var(--line);
 917  border-bottom: 1px solid var(--line);
 918}
 919table.difftable tr.hunk td.code { color: var(--accent); }
 920table.difftable tr.threadrow td { padding: var(--sp-2) var(--sp-3); background: var(--bg); }
 921
 922/* badges: signature and check states. Semantic colors stay distinct:
 923   green verified/success, amber pending/stale, red bad/failure, muted
 924   unsigned. */
 925.badge, .chip {
 926  --chip: var(--neutral);
 927  display: inline-block;
 928  padding: 0.05rem 0.55rem;
 929  border-radius: var(--r-pill);
 930  font-size: var(--fs-0);
 931  font-weight: 500;
 932  line-height: 1.5;
 933  color: var(--chip);
 934  border: 1px solid color-mix(in srgb, var(--chip) 35%, transparent);
 935  background: color-mix(in srgb, var(--chip) 7%, transparent);
 936  white-space: nowrap;
 937  vertical-align: middle;
 938}
 939.chip-open { --chip: var(--ok); }
 940.chip-closed { --chip: var(--bad); }
 941.chip-merged, .chip-done { --chip: var(--done); }
 942.chip-neutral, .chip-source_gone { --chip: var(--neutral); }
 943.chip-stale { --chip: var(--warn); }
 944.chip.label { font-weight: 500; }
 945.chip.topic { --chip: var(--accent); }
 946.repohead .topics { margin: 0 0 var(--sp-2); }
 947.repohead .mirrorline { margin: 0 0 var(--sp-2); }
 948.mirrorerr { color: var(--bad); }
 949.badge-verified { --chip: var(--ok); }
 950.badge-unsigned { --chip: var(--neutral); }
 951.badge-signed_unknown_key { --chip: var(--warn); }
 952.badge-signed_email_mismatch { --chip: var(--bad); }
 953.badge-signed_key_expired { --chip: var(--warn); }
 954.badge-signed_key_revoked { --chip: var(--bad); }
 955.badge-bad_signature { --chip: var(--bad); }
 956.badge.check-success { --chip: var(--ok); }
 957.badge.check-pending { --chip: var(--warn); }
 958.badge.check-failure, .badge.check-error { --chip: var(--bad); }
 959.badge.check-running, .chip.check-running { --chip: var(--warn); }
 960.chip.check-success { --chip: var(--ok); }
 961.chip.check-pending { --chip: var(--warn); }
 962.chip.check-failure { --chip: var(--bad); }
 963pre.buildlog { max-height: 40rem; overflow: auto; }
 964span.check-success { color: var(--ok); }
 965span.check-pending { color: var(--warn); }
 966span.check-failure, span.check-error { color: var(--bad); }
 967
 968/* issue and MR listings */
 969.listhead {
 970  display: flex;
 971  align-items: baseline;
 972  gap: var(--sp-4);
 973  flex-wrap: wrap;
 974}
 975.listhead h2 { margin-bottom: var(--sp-2); }
 976nav.filters { display: flex; gap: var(--sp-1); }
 977nav.filters a {
 978  color: var(--muted);
 979  font-size: var(--fs-2);
 980  padding: 0.05rem var(--sp-2);
 981  border-radius: var(--r-pill);
 982}
 983nav.filters a:hover { color: var(--fg); background: var(--hover); text-decoration: none; }
 984nav.filters a.active { color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
 985
 986ul.issuelist {
 987  list-style: none;
 988  margin: var(--sp-2) 0;
 989  padding: 0;
 990  background: var(--surface);
 991  border: 1px solid var(--line);
 992  border-radius: var(--r-lg);
 993  overflow: hidden;
 994}
 995ul.issuelist li {
 996  display: flex;
 997  align-items: baseline;
 998  gap: var(--sp-3);
 999  padding: var(--sp-3) var(--sp-4);
1000  border-bottom: 1px solid var(--faint);
1001}
1002ul.issuelist li:last-child { border-bottom: none; }
1003ul.issuelist li:hover { background: var(--hover); }
1004ul.issuelist li.empty { display: block; color: var(--muted); }
1005ul.issuelist .issuemain { flex: 1; min-width: 0; }
1006ul.issuelist p { margin: 0; }
1007ul.issuelist .title a { color: var(--fg); font-weight: 550; }
1008ul.issuelist .title a:hover { color: var(--accent); }
1009
1010/* releases */
1011article.release {
1012  background: var(--surface);
1013  border: 1px solid var(--line);
1014  border-radius: var(--r-lg);
1015  padding: var(--sp-3) var(--sp-4);
1016  margin: var(--sp-4) 0;
1017}
1018.releasehead { background: none; border: 0; padding: 0; }
1019.releasehead h3 { margin: 0 0 var(--sp-1); }
1020.releasehead .meta { margin: 0 0 var(--sp-2); }
1021table.assets { margin-top: var(--sp-2); }
1022table.assets td.size { color: var(--muted); white-space: nowrap; text-align: right; }
1023table.assets td.name { width: 100%; font-family: var(--mono); font-size: var(--fs-1); }
1024
1025/* milestones */
1026ul.milestonelist {
1027  list-style: none;
1028  margin: var(--sp-2) 0;
1029  padding: 0;
1030  border: 1px solid var(--line);
1031  border-radius: var(--r-lg);
1032  overflow: hidden;
1033}
1034ul.milestonelist li { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--faint); }
1035ul.milestonelist li:last-child { border-bottom: none; }
1036ul.milestonelist li.empty { color: var(--muted); }
1037ul.milestonelist p { margin: 0; }
1038ul.milestonelist .title { font-weight: 550; }
1039.progress {
1040  height: 6px;
1041  background: var(--faint);
1042  border-radius: var(--r-pill);
1043  margin-top: var(--sp-2);
1044  overflow: hidden;
1045  max-width: 24rem;
1046}
1047.progress .bar { height: 100%; background: var(--ok); }
1048.listhead .spacer { flex: 1; }
1049
1050/* issue / MR detail */
1051h2.issuetitle { margin-bottom: var(--sp-1); font-size: var(--fs-5); }
1052.issuenumber { color: var(--muted); font-weight: 400; }
1053.issuemeta { color: var(--muted); font-size: var(--fs-2); margin-top: 0; }
1054.review { font-size: var(--fs-2); }
1055
1056/* comment cards; discussion stays at a readable measure */
1057article.comment, form.commentform {
1058  max-width: 48rem;
1059}
1060article.comment {
1061  border: 1px solid var(--faint);
1062  border-radius: var(--r-lg);
1063  margin: var(--sp-4) 0;
1064}
1065article.comment .commenthead {
1066  background: var(--surface);
1067  border-bottom: 1px solid var(--faint);
1068  border-radius: var(--r-lg) var(--r-lg) 0 0;
1069  padding: var(--sp-2) var(--sp-4);
1070  font-size: var(--fs-2);
1071}
1072article.comment .commenthead .when { color: var(--muted); }
1073article.comment .rendered { padding: 0 var(--sp-4); }
1074article.comment .rendered > :first-child { margin-top: var(--sp-3); }
1075article.comment .rendered > :last-child { margin-bottom: var(--sp-3); }
1076form.commentform { margin: var(--sp-4) 0; }
1077details.editbox { margin: var(--sp-2) 0; max-width: 48rem; }
1078details.editbox summary { cursor: pointer; color: var(--muted); font-size: var(--fs-2); }
1079details.editbox summary:hover { color: var(--accent); }
1080details.editbox input[type="text"] { width: 100%; }
1081.syscomment {
1082  max-width: 48rem;
1083  color: var(--muted);
1084  font-size: var(--fs-2);
1085  margin: var(--sp-3) 0;
1086  padding-left: var(--sp-4);
1087  border-left: 3px solid var(--faint);
1088}
1089.syscomment p { display: inline; margin: 0; }
1090
1091/* review threads under diff lines */
1092.thread {
1093  border: 1px solid var(--faint);
1094  border-left: 3px solid var(--accent);
1095  border-radius: var(--r-md);
1096  padding: var(--sp-2) var(--sp-4);
1097  margin: var(--sp-2) 0 var(--sp-2) var(--sp-6);
1098}
1099.thread.resolved { border-left-color: var(--ok); opacity: 0.75; }
1100.thread.stale { border-left-color: var(--warn); }
1101.thread p.commenthead { font-size: var(--fs-2); margin: var(--sp-2) 0 0; }
1102.thread .when { color: var(--muted); }
1103.thread .rendered p { margin: var(--sp-1) 0; }
1104.thread .threadstate { color: var(--muted); font-size: var(--fs-1); margin: var(--sp-1) 0 0; }
1105
1106/* forms: every control shares one shell, so a select reads as a sibling
1107   of the text inputs beside it rather than as an OS control dropped in */
1108input, textarea, button, select { font: inherit; color: inherit; }
1109input[type="text"], input[type="search"], input[type="email"],
1110input[type="password"], input:not([type]), textarea, select {
1111  background: var(--bg);
1112  color: var(--fg);
1113  border: 1px solid var(--line);
1114  border-radius: var(--r-md);
1115  padding: var(--sp-2) var(--sp-3);
1116  line-height: 1.4;
1117}
1118textarea { width: 100%; resize: vertical; }
1119textarea[name="content"] { font-family: var(--mono); font-size: var(--fs-1); }
1120/* the native arrow cannot be restyled, so draw our own and match the
1121   inputs exactly; --chev carries the stroke colour per scheme */
1122select {
1123  appearance: none;
1124  padding-right: 1.9rem;
1125  background-image: var(--chev);
1126  background-repeat: no-repeat;
1127  background-position: right 0.6rem center;
1128  background-size: 0.62rem;
1129  cursor: pointer;
1130}
1131input:hover, textarea:hover, select:hover { border-color: var(--muted); }
1132/* the global :focus-visible ring covers these; only the border moves */
1133input:focus, textarea:focus, select:focus { border-color: var(--accent); }
1134input[type="radio"], input[type="checkbox"] { accent-color: var(--fill); }
1135label:has(> input[type="radio"]), label:has(> input[type="checkbox"]),
1136label:has(> select) { display: inline-flex; align-items: center; gap: var(--sp-2); }
1137
1138/* Shape carries the meaning on these two and nothing else does: a circle
1139   takes one answer, a square takes any number. It survives colour being
1140   removed — greyscale, high contrast, colour blindness — so the native
1141   shapes stay and only the colour joins the system. Drawing them by hand
1142   would align the corners at the cost of the one cue that always works. */
1143input[type="radio"], input[type="checkbox"] { accent-color: var(--fill); }
1144
1145/* a segmented control for a small, mutually exclusive set: real radios
1146   underneath, so arrow keys and screen readers behave as they always did */
1147fieldset.segmented { border: 0; margin: 0 0 var(--sp-4); padding: 0; }
1148fieldset.segmented legend {
1149  padding: 0;
1150  margin-bottom: var(--sp-2);
1151  color: var(--muted);
1152  font-size: var(--fs-2);
1153}
1154fieldset.segmented .options { display: inline-flex; }
1155fieldset.segmented label { gap: 0; }
1156fieldset.segmented input {
1157  position: absolute;
1158  width: 1px;
1159  height: 1px;
1160  opacity: 0;
1161  pointer-events: none;
1162}
1163fieldset.segmented span {
1164  display: block;
1165  padding: var(--sp-2) var(--sp-4);
1166  border: 1px solid var(--line);
1167  font-size: var(--fs-2);
1168  cursor: pointer;
1169}
1170fieldset.segmented label + label span { border-left: 0; }
1171fieldset.segmented label:first-child span { border-radius: var(--r-sm) 0 0 var(--r-sm); }
1172fieldset.segmented label:last-child span { border-radius: 0 var(--r-sm) var(--r-sm) 0; }
1173fieldset.segmented span:hover { border-color: var(--muted); }
1174fieldset.segmented input:checked + span {
1175  background: var(--fill);
1176  border-color: var(--fill);
1177  color: #ffffff;
1178  font-weight: 600;
1179}
1180fieldset.segmented input:focus-visible + span {
1181  outline: 2px solid var(--accent);
1182  outline-offset: 2px;
1183}
1184
1185/* remaining input states */
1186::placeholder { color: var(--muted); opacity: 1; }
1187::selection { background: var(--fill); color: #ffffff; }
1188/* :user-invalid, not :invalid — a required field is invalid the moment
1189   the page loads, and colouring it red before anyone has typed is a
1190   scolding, not a hint */
1191input:user-invalid, textarea:user-invalid {
1192  border-color: var(--bad);
1193}
1194.hint { display: block; color: var(--muted); font-size: var(--fs-1); margin-top: var(--sp-1); }
1195button {
1196  background: var(--fill);
1197  color: #ffffff;
1198  border: none;
1199  border-radius: var(--r-md);
1200  padding: var(--sp-2) var(--sp-4);
1201  font-weight: 600;
1202  cursor: pointer;
1203}
1204button:hover { filter: brightness(1.15); }
1205
1206/* 404 */
1207.notfound { text-align: center; padding: var(--sp-6) 0; }
1208.notfound .bigcode {
1209  font-family: var(--mono);
1210  font-size: 4rem;
1211  color: var(--faint);
1212  -webkit-text-stroke: 1px var(--line);
1213  margin: 0;
1214  line-height: 1;
1215}
1216.notfound h1 { margin-top: var(--sp-3); }
1217
1218/* footer */
1219footer {
1220  border-top: 1px solid var(--faint);
1221  padding: var(--sp-4) var(--sp-5) var(--sp-5);
1222  width: 100%;
1223  color: var(--muted);
1224  font-size: var(--fs-1);
1225}
1226footer p { margin: 0; }
1227footer a { color: var(--muted); text-decoration: underline; }
1228footer a:hover { color: var(--accent); }
1229
1230/* search */
1231form.searchform {
1232  display: flex;
1233  gap: var(--sp-2);
1234  margin: var(--sp-3) 0 var(--sp-4);
1235}
1236form.searchform input[type="search"] { flex: 1; max-width: 32rem; }
1237form.searchform.compact { margin: 0; }
1238form.searchform.compact input[type="search"] {
1239  padding: var(--sp-1) var(--sp-3);
1240  font-size: var(--fs-2);
1241  min-width: 18rem;
1242}
1243ul.matchlist { list-style: none; margin: var(--sp-3) 0; padding: 0; }
1244ul.matchlist li { margin-bottom: var(--sp-3); }
1245ul.matchlist .matchpath { font-family: var(--mono); font-size: var(--fs-1); }
1246pre.matchline {
1247  background: var(--code-bg);
1248  border: 1px solid var(--faint);
1249  border-radius: var(--r-md);
1250  padding: var(--sp-1) var(--sp-3);
1251  margin: var(--sp-1) 0 0;
1252  overflow-x: auto;
1253}
1254pre.matchline mark {
1255  background: color-mix(in srgb, var(--warn) 25%, transparent);
1256  color: inherit;
1257  border-radius: 2px;
1258}
1259
1260/* wiki */
1261.wikilayout { display: flex; gap: var(--sp-5); align-items: flex-start; }
1262.wikipage { flex: 1; min-width: 0; }
1263.wikinav { flex: none; width: 13rem; padding-top: var(--sp-4); }
1264.wikinav ul { list-style: none; margin: var(--sp-1) 0 var(--sp-4); padding: 0; }
1265.wikinav li a { display: block; padding: 0.15rem 0; color: var(--fg); }
1266.wikinav li a:hover { color: var(--accent); text-decoration: none; }
1267.wikinav li a.active { color: var(--accent); font-weight: 550; }
1268@media (max-width: 40rem) {
1269  /* Column direction + the desktop align-items:flex-start lets .wikipage
1270     take its content's intrinsic width, overflowing the viewport (and
1271     triggering iOS font inflation). Stretch pins it to the container. */
1272  .wikilayout { flex-direction: column; align-items: stretch; }
1273  .wikinav { width: auto; padding-top: 0; }
1274}
1275
1276/* blame */
1277.blame {
1278  border: 1px solid var(--line);
1279  border-radius: var(--rad-2, 6px);
1280  overflow: hidden;
1281}
1282.blamehunk {
1283  display: flex;
1284  gap: var(--sp-3);
1285  border-top: 1px solid var(--line);
1286  align-items: flex-start;
1287}
1288.blamehunk:first-child { border-top: none; }
1289.blameinfo {
1290  flex: none;
1291  width: 17rem;
1292  padding: var(--sp-2) var(--sp-3);
1293  min-width: 0;
1294}
1295.blameinfo .subject {
1296  margin: 0;
1297  font-size: var(--fs-1);
1298  white-space: nowrap;
1299  overflow: hidden;
1300  text-overflow: ellipsis;
1301}
1302.blameinfo .meta { margin: 0; font-size: var(--fs-1); color: var(--muted); }
1303.blamecode {
1304  flex: 1;
1305  margin: 0;
1306  padding: var(--sp-2) var(--sp-3) var(--sp-2) 0;
1307  overflow-x: auto;
1308  border-left: 1px solid var(--line);
1309  align-self: stretch;
1310}
1311.lineno {
1312  display: inline-block;
1313  min-width: 3.5em;
1314  padding-right: 1em;
1315  text-align: right;
1316  color: var(--muted);
1317  user-select: none;
1318}
1319
1320/* mobile */
1321@media (max-width: 40rem) {
1322  .container { padding-left: var(--sp-4); padding-right: var(--sp-4); }
1323  main.container { padding-top: var(--sp-2); }
1324  .repogrid { grid-template-columns: 1fr; }
1325  .thread { margin-left: var(--sp-3); }
1326  /* the commit subject is the widest thing in the listing and the one
1327     column a phone can do without: the tipbar above already names the
1328     latest commit. */
1329  table.tree td.lastcommit, table.tree th.lastcommit { display: none; }
1330  table.tree td.mode, table.tree th.mode { display: none; }
1331  .clone, .pathbar { overflow-wrap: anywhere; }
1332  .readme, .code { padding: var(--sp-3); }
1333  .blamehunk { flex-direction: column; gap: 0; }
1334  .blameinfo { width: auto; }
1335  .blamecode { border-left: none; padding-left: var(--sp-3); width: 100%; }
1336  .cardhead {
1337    margin: calc(-1 * var(--sp-3)) calc(-1 * var(--sp-3)) var(--sp-3);
1338    padding: var(--sp-2) var(--sp-3);
1339  }
1340}
1341
1342/* tree listing: the last commit is what a file table is scanned for, so
1343   it leads. The file's own facts moved to the blob page. */
1344.tipbar {
1345  display: flex;
1346  align-items: center;
1347  gap: var(--sp-3);
1348  padding: var(--sp-2) var(--sp-4);
1349  background: var(--hover);
1350  border: 1px solid var(--line);
1351  border-bottom: 0;
1352  border-radius: var(--r-lg) var(--r-lg) 0 0;
1353  font-size: var(--fs-2);
1354}
1355.tipbar .who { font-weight: 600; }
1356.tipbar .subject { color: var(--fg); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1357.tipbar .subject:hover { color: var(--accent); }
1358.tipbar .spacer { flex: 1; }
1359.tipbar .age { color: var(--muted); white-space: nowrap; }
1360.tipbar + table.tree { border-radius: 0 0 var(--r-lg) var(--r-lg); }
1361table.tree th.lastcommit, table.tree td.lastcommit { width: 55%; }
1362table.tree td.lastcommit a { color: var(--muted); display: block; overflow: hidden;
1363                             text-overflow: ellipsis; white-space: nowrap; }
1364table.tree td.lastcommit a:hover { color: var(--accent); }
1365table.tree th.age, table.tree td.age {
1366  text-align: right;
1367  white-space: nowrap;
1368  color: var(--muted);
1369  font-variant-numeric: tabular-nums;
1370}
1371table.tree td.name { width: 25%; white-space: nowrap; }
1372table.tree td.name.dir a { color: var(--accent); }
1373p.clone { margin: 0 0 var(--sp-3); }
1374p.filefacts { color: var(--muted); font-size: var(--fs-1); margin: 0 0 var(--sp-3); }
1375.pathbar .act { font-size: var(--fs-1); }
1376
1377/* merge request: a two-column split, so state has somewhere to live that
1378   is not a run-on sentence under the title */
1379.withaside {
1380  display: grid;
1381  grid-template-columns: minmax(0, 1fr) 15rem;
1382  gap: var(--sp-5);
1383  align-items: start;
1384}
1385.withaside .mainside { min-width: 0; }
1386@media (max-width: 62rem) { .withaside { grid-template-columns: 1fr; } }
1387
1388.aside { font-size: var(--fs-2); }
1389.aside .grp { border-top: 1px solid var(--line); padding: var(--sp-3) 0; }
1390.aside .grp:first-child { border-top: 0; padding-top: 0; }
1391.aside h2 {
1392  margin: 0 0 var(--sp-2);
1393  font-family: var(--mono);
1394  font-size: var(--fs-0);
1395  font-weight: 500;
1396  letter-spacing: 0.1em;
1397  text-transform: uppercase;
1398  color: var(--muted);
1399}
1400.aside .row { display: flex; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-1); flex-wrap: wrap; }
1401.aside .row:last-child { margin-bottom: 0; }
1402.aside .none { color: var(--muted); }
1403.aside .dot { width: 0.45rem; height: 0.45rem; flex: none; border-radius: 50%; background: var(--muted); }
1404.aside .dot.ok { background: var(--ok); }
1405.aside .dot.bad { background: var(--bad); }
1406.aside .dot.pend { background: var(--mark); }
1407
1408/* sub-navigation within an item; orange marks position as it does above */
1409nav.subtabs {
1410  display: flex;
1411  gap: var(--sp-4);
1412  border-bottom: 1px solid var(--line);
1413  margin: 0 0 var(--sp-4);
1414}
1415nav.subtabs a {
1416  display: inline-flex;
1417  align-items: center;
1418  gap: var(--sp-2);
1419  padding: 0 0 var(--sp-2);
1420  color: var(--muted);
1421  font-size: var(--fs-2);
1422  border-bottom: 2px solid transparent;
1423  margin-bottom: -1px;
1424}
1425nav.subtabs a:hover { color: var(--fg); text-decoration: none; }
1426nav.subtabs a[aria-current] { color: var(--fg); font-weight: 700; border-bottom-color: var(--mark); }
1427nav.subtabs a i {
1428  font-style: normal;
1429  font-family: var(--mono);
1430  font-size: var(--fs-0);
1431  background: var(--hover);
1432  border-radius: var(--r-sm);
1433  padding: 0 0.35rem;
1434}
1435p.diffstat { color: var(--muted); font-size: var(--fs-2); margin: 0 0 var(--sp-3); }
1436p.diffstat .add { color: var(--ok); }
1437p.diffstat .del { color: var(--bad); }