internal/web/static/style.css

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

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