internal/web/static/style.css

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

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