internal/web/static/style.css

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

1325 lines · 43447 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/* settings: one row per control, label then input then its own button */
 550form.setform {
 551  display: flex;
 552  flex-wrap: wrap;
 553  align-items: center;
 554  gap: var(--sp-3);
 555  padding: var(--sp-2) 0;
 556  border-bottom: 1px solid var(--faint);
 557}
 558form.setform label { min-width: 12rem; color: var(--muted); font-size: var(--fs-2); }
 559form.setform input[type="text"], form.setform select { flex: 1 1 16rem; }
 560form.setform input[type="number"] { width: 5rem; }
 561ul.protlist { list-style: none; padding: 0; margin: var(--sp-2) 0; }
 562ul.protlist li { padding: var(--sp-1) 0; display: flex; gap: var(--sp-3); align-items: baseline; }
 563
 564/* branch picker on the new merge request form */
 565p.branchpick {
 566  display: flex;
 567  flex-wrap: wrap;
 568  align-items: center;
 569  gap: var(--sp-2);
 570}
 571p.branchpick label { color: var(--muted); font-size: var(--fs-2); }
 572p.branchpick select { flex: 1 1 12rem; }
 573
 574/* merge request actions in the aside: stacked controls, full width */
 575.aside form.actions {
 576  display: flex;
 577  flex-wrap: wrap;
 578  gap: var(--sp-2);
 579  margin-top: var(--sp-2);
 580}
 581.aside form.actions button { flex: 1 1 auto; }
 582.aside form.actions select { width: 100%; }
 583form.threadact { margin: var(--sp-1) 0 0; padding: 0 var(--sp-3) var(--sp-2); }
 584
 585.meta { color: var(--muted); font-size: var(--fs-1); }
 586svg.icon { vertical-align: -0.125em; }
 587.lede { font-size: var(--fs-3); margin: var(--sp-2) 0; }
 588
 589/* repo listings (explore, owner pages, dashboard): one row per repo */
 590ul.repolist {
 591  list-style: none;
 592  margin: var(--sp-3) 0 var(--sp-5);
 593  padding: 0;
 594  background: var(--surface);
 595  border: 1px solid var(--line);
 596  border-radius: var(--r-lg);
 597  overflow: hidden;
 598}
 599ul.repolist li { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--faint); }
 600/* pinned repos: a compact wrap of name pills, no description or meta */
 601ul.pinlist {
 602  list-style: none;
 603  margin: var(--sp-3) 0 var(--sp-5);
 604  padding: 0;
 605  display: flex;
 606  flex-wrap: wrap;
 607  gap: var(--sp-2);
 608}
 609ul.pinlist li {
 610  background: var(--surface);
 611  border: 1px solid var(--line);
 612  border-radius: var(--r-md);
 613  padding: var(--sp-1) var(--sp-3);
 614}
 615ul.pinlist li:hover { background: var(--hover); }
 616ul.pinlist li a { color: var(--fg); }
 617ul.pinlist li a:hover { color: var(--accent); text-decoration: none; }
 618ul.pinlist .sep { color: var(--muted); margin: 0 0.15em; }
 619ul.repolist li:last-child { border-bottom: none; }
 620ul.repolist li:hover { background: var(--hover); }
 621ul.repolist li.empty { color: var(--muted); }
 622ul.repolist p { margin: 0; }
 623ul.repolist .reponame { font-size: var(--fs-3); }
 624ul.repolist .reponame a { color: var(--fg); }
 625ul.repolist .reponame a strong { color: var(--accent); font-weight: 600; }
 626ul.repolist .reponame .sep { color: var(--muted); margin: 0 0.1em; }
 627ul.repolist .desc { margin-top: 0.1rem; }
 628ul.repolist .topics { margin-top: var(--sp-1); }
 629ul.repolist .meta { margin-top: var(--sp-1); }
 630
 631/* owner profile header */
 632.profilehead {
 633  border-bottom: 1px solid var(--faint);
 634  padding-bottom: var(--sp-4);
 635  margin-bottom: var(--sp-4);
 636}
 637.profilehead h1 { margin: var(--sp-4) 0 var(--sp-1); }
 638.profilehead .lede { margin: 0 0 var(--sp-1); }
 639.profilehead .meta { margin: var(--sp-1) 0 0; }
 640h2 .count { color: var(--muted); font-weight: 400; font-size: var(--fs-2); }
 641
 642/* activity graph: 53 week columns x 7 day rows, accent-tinted levels */
 643.actgraph-scroll { overflow-x: auto; padding-bottom: var(--sp-1); }
 644.actgraph { display: flex; gap: 3px; width: max-content; }
 645.actweek { display: flex; flex-direction: column; gap: 3px; }
 646.actday {
 647  width: 11px;
 648  height: 11px;
 649  border-radius: 2px;
 650  background: var(--faint);
 651}
 652.actday.pad { background: transparent; }
 653.actday.l1 { background: color-mix(in srgb, var(--accent) 25%, var(--bg)); }
 654.actday.l2 { background: color-mix(in srgb, var(--accent) 50%, var(--bg)); }
 655.actday.l3 { background: color-mix(in srgb, var(--accent) 75%, var(--bg)); }
 656.actday.l4 { background: var(--accent); }
 657
 658/* heading row with actions on the right */
 659.headrow {
 660  display: flex;
 661  align-items: baseline;
 662  gap: var(--sp-4);
 663  flex-wrap: wrap;
 664}
 665.headrow .spacer { flex: 1; }
 666
 667/* member and org chips on owner pages */
 668a.memberchip {
 669  display: inline-block;
 670  border: 1px solid var(--line);
 671  border-radius: var(--r-pill);
 672  padding: 0.05rem 0.6rem;
 673  color: var(--fg);
 674  font-size: var(--fs-1);
 675  margin: 0 0.15rem 0.15rem 0;
 676}
 677a.memberchip:hover { text-decoration: none; border-color: var(--accent); color: var(--accent); }
 678a.memberchip .role { color: var(--muted); }
 679
 680/* landing page */
 681.landing { max-width: 44rem; padding: var(--sp-6) 0; }
 682.landing h1 { font-size: 1.8rem; margin-bottom: var(--sp-3); }
 683.landing .lede { font-size: var(--fs-4); color: var(--muted); line-height: 1.7; margin: 0 0 var(--sp-4); }
 684pre.quickstart {
 685  background: var(--code-bg);
 686  border: 1px solid var(--line);
 687  border-radius: var(--r-md);
 688  padding: var(--sp-3) var(--sp-4);
 689  overflow-x: auto;
 690  margin: 0 0 var(--sp-4);
 691}
 692.landing .explorelink { font-weight: 550; }
 693
 694/* index toolbar */
 695p.toolbar { color: var(--muted); font-size: var(--fs-2); margin-top: var(--sp-4); }
 696form.inline { display: inline; }
 697button.linklike {
 698  background: none;
 699  border: none;
 700  color: var(--accent);
 701  padding: 0;
 702  font: inherit;
 703  font-size: var(--fs-2);
 704  cursor: pointer;
 705}
 706button.linklike:hover { text-decoration: underline; filter: none; }
 707
 708/* cards: README, comments */
 709.readme, .code {
 710  background: var(--surface);
 711  border: 1px solid var(--line);
 712  border-radius: var(--r-lg);
 713  padding: var(--sp-4) var(--sp-5);
 714  margin-top: var(--sp-4);
 715  overflow-x: auto;
 716}
 717/* Highlighting is class-based with a palette per scheme, so code blocks
 718   follow the site's own colors. */
 719.code { background: var(--code-bg); color: var(--fg); padding: var(--sp-3) var(--sp-4); border-color: var(--line); }
 720.code pre { margin: 0; background: transparent !important; }
 721@media (prefers-color-scheme: dark) {
 722  .code { border-color: var(--line); }
 723}
 724
 725/* rendered markdown / org / html */
 726.rendered { max-width: 100%; overflow-wrap: anywhere; }
 727.rendered pre {
 728  background: var(--code-bg);
 729  border: 1px solid var(--line);
 730  padding: var(--sp-3) var(--sp-4);
 731  border-radius: var(--r-md);
 732  overflow-x: auto;
 733}
 734.rendered code {
 735  background: var(--code-bg);
 736  border: 1px solid var(--line);
 737  padding: 0.05rem 0.3rem;
 738  border-radius: var(--r-sm);
 739}
 740.rendered pre code { background: transparent; border: none; padding: 0; }
 741.rendered blockquote {
 742  border-left: 3px solid var(--line);
 743  margin-left: 0;
 744  padding-left: var(--sp-4);
 745  color: var(--muted);
 746}
 747.rendered img { max-width: 100%; }
 748.rendered h1, .rendered h2 { border-bottom: 1px solid var(--faint); padding-bottom: var(--sp-1); }
 749.rendered table {
 750  border-collapse: collapse;
 751  margin: var(--sp-3) 0;
 752  display: block;
 753  max-width: 100%;
 754  overflow-x: auto;
 755}
 756.rendered th, .rendered td {
 757  border: 1px solid var(--line);
 758  padding: var(--sp-1) var(--sp-3);
 759  text-align: left;
 760  overflow-wrap: normal; /* scroll the table, don't shatter words */
 761}
 762.rendered th { background: var(--surface); font-weight: 600; }
 763.blobimage { text-align: center; }
 764.blobimage img {
 765  max-width: 100%;
 766  border: 1px solid var(--faint);
 767  border-radius: var(--r-md);
 768  background: var(--surface);
 769}
 770
 771pre.message {
 772  background: var(--code-bg);
 773  border: 1px solid var(--line);
 774  padding: var(--sp-3) var(--sp-4);
 775  border-radius: var(--r-md);
 776  white-space: pre-wrap;
 777  overflow-wrap: anywhere;
 778}
 779
 780/* diffs */
 781details.difffold summary {
 782  cursor: pointer;
 783  display: flex;
 784  align-items: baseline;
 785  gap: var(--sp-3);
 786  margin: var(--sp-5) 0 var(--sp-2);
 787  list-style: none;
 788}
 789details.difffold summary::-webkit-details-marker { display: none; }
 790/* flex summaries lose the native disclosure marker; draw our own */
 791details.difffold summary::before { content: "▸"; color: var(--muted); }
 792details.difffold[open] summary::before { content: "▾"; }
 793details.difffold summary h3 { display: inline; margin: 0; }
 794details.difffold summary .add { color: var(--ok); }
 795details.difffold summary .del { color: var(--bad); }
 796pre.diff {
 797  background: var(--code-bg);
 798  border: 1px solid var(--line);
 799  padding: var(--sp-3) var(--sp-4);
 800  border-radius: var(--r-md);
 801  overflow-x: auto;
 802  line-height: 1.5;
 803}
 804pre.diff .add { color: var(--ok); }
 805pre.diff .del { color: var(--bad); }
 806pre.diff .hunk { color: var(--accent); }
 807pre.diff .meta { color: var(--muted); }
 808
 809/* badges: signature and check states. Semantic colors stay distinct:
 810   green verified/success, amber pending/stale, red bad/failure, muted
 811   unsigned. */
 812.badge, .chip {
 813  --chip: var(--neutral);
 814  display: inline-block;
 815  padding: 0.05rem 0.55rem;
 816  border-radius: var(--r-pill);
 817  font-size: var(--fs-0);
 818  font-weight: 500;
 819  line-height: 1.5;
 820  color: var(--chip);
 821  border: 1px solid color-mix(in srgb, var(--chip) 35%, transparent);
 822  background: color-mix(in srgb, var(--chip) 7%, transparent);
 823  white-space: nowrap;
 824  vertical-align: middle;
 825}
 826.chip-open { --chip: var(--ok); }
 827.chip-closed { --chip: var(--bad); }
 828.chip-merged, .chip-done { --chip: var(--done); }
 829.chip-neutral, .chip-source_gone { --chip: var(--neutral); }
 830.chip-stale { --chip: var(--warn); }
 831.chip.label { font-weight: 500; }
 832.chip.topic { --chip: var(--accent); }
 833.repohead .topics { margin: 0 0 var(--sp-2); }
 834.repohead .mirrorline { margin: 0 0 var(--sp-2); }
 835.mirrorerr { color: var(--bad); }
 836.badge-verified { --chip: var(--ok); }
 837.badge-unsigned { --chip: var(--neutral); }
 838.badge-signed_unknown_key { --chip: var(--warn); }
 839.badge-signed_email_mismatch { --chip: var(--bad); }
 840.badge-signed_key_expired { --chip: var(--warn); }
 841.badge-signed_key_revoked { --chip: var(--bad); }
 842.badge-bad_signature { --chip: var(--bad); }
 843.badge.check-success { --chip: var(--ok); }
 844.badge.check-pending { --chip: var(--warn); }
 845.badge.check-failure, .badge.check-error { --chip: var(--bad); }
 846.badge.check-running, .chip.check-running { --chip: var(--warn); }
 847.chip.check-success { --chip: var(--ok); }
 848.chip.check-pending { --chip: var(--warn); }
 849.chip.check-failure { --chip: var(--bad); }
 850pre.buildlog { max-height: 40rem; overflow: auto; }
 851span.check-success { color: var(--ok); }
 852span.check-pending { color: var(--warn); }
 853span.check-failure, span.check-error { color: var(--bad); }
 854
 855/* issue and MR listings */
 856.listhead {
 857  display: flex;
 858  align-items: baseline;
 859  gap: var(--sp-4);
 860  flex-wrap: wrap;
 861}
 862.listhead h2 { margin-bottom: var(--sp-2); }
 863nav.filters { display: flex; gap: var(--sp-1); }
 864nav.filters a {
 865  color: var(--muted);
 866  font-size: var(--fs-2);
 867  padding: 0.05rem var(--sp-2);
 868  border-radius: var(--r-pill);
 869}
 870nav.filters a:hover { color: var(--fg); background: var(--hover); text-decoration: none; }
 871nav.filters a.active { color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
 872
 873ul.issuelist {
 874  list-style: none;
 875  margin: var(--sp-2) 0;
 876  padding: 0;
 877  background: var(--surface);
 878  border: 1px solid var(--line);
 879  border-radius: var(--r-lg);
 880  overflow: hidden;
 881}
 882ul.issuelist li {
 883  display: flex;
 884  align-items: baseline;
 885  gap: var(--sp-3);
 886  padding: var(--sp-3) var(--sp-4);
 887  border-bottom: 1px solid var(--faint);
 888}
 889ul.issuelist li:last-child { border-bottom: none; }
 890ul.issuelist li:hover { background: var(--hover); }
 891ul.issuelist li.empty { display: block; color: var(--muted); }
 892ul.issuelist .issuemain { flex: 1; min-width: 0; }
 893ul.issuelist p { margin: 0; }
 894ul.issuelist .title a { color: var(--fg); font-weight: 550; }
 895ul.issuelist .title a:hover { color: var(--accent); }
 896
 897/* releases */
 898article.release {
 899  background: var(--surface);
 900  border: 1px solid var(--line);
 901  border-radius: var(--r-lg);
 902  padding: var(--sp-3) var(--sp-4);
 903  margin: var(--sp-4) 0;
 904}
 905.releasehead { background: none; border: 0; padding: 0; }
 906.releasehead h3 { margin: 0 0 var(--sp-1); }
 907.releasehead .meta { margin: 0 0 var(--sp-2); }
 908table.assets { margin-top: var(--sp-2); }
 909table.assets td.size { color: var(--muted); white-space: nowrap; text-align: right; }
 910table.assets td.name { width: 100%; font-family: var(--mono); font-size: var(--fs-1); }
 911
 912/* milestones */
 913ul.milestonelist {
 914  list-style: none;
 915  margin: var(--sp-2) 0;
 916  padding: 0;
 917  border: 1px solid var(--line);
 918  border-radius: var(--r-lg);
 919  overflow: hidden;
 920}
 921ul.milestonelist li { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--faint); }
 922ul.milestonelist li:last-child { border-bottom: none; }
 923ul.milestonelist li.empty { color: var(--muted); }
 924ul.milestonelist p { margin: 0; }
 925ul.milestonelist .title { font-weight: 550; }
 926.progress {
 927  height: 6px;
 928  background: var(--faint);
 929  border-radius: var(--r-pill);
 930  margin-top: var(--sp-2);
 931  overflow: hidden;
 932  max-width: 24rem;
 933}
 934.progress .bar { height: 100%; background: var(--ok); }
 935.listhead .spacer { flex: 1; }
 936
 937/* issue / MR detail */
 938h2.issuetitle { margin-bottom: var(--sp-1); font-size: var(--fs-5); }
 939.issuenumber { color: var(--muted); font-weight: 400; }
 940.issuemeta { color: var(--muted); font-size: var(--fs-2); margin-top: 0; }
 941.review { font-size: var(--fs-2); }
 942
 943/* comment cards; discussion stays at a readable measure */
 944article.comment, form.commentform {
 945  max-width: 48rem;
 946}
 947article.comment {
 948  border: 1px solid var(--faint);
 949  border-radius: var(--r-lg);
 950  margin: var(--sp-4) 0;
 951}
 952article.comment .commenthead {
 953  background: var(--surface);
 954  border-bottom: 1px solid var(--faint);
 955  border-radius: var(--r-lg) var(--r-lg) 0 0;
 956  padding: var(--sp-2) var(--sp-4);
 957  font-size: var(--fs-2);
 958}
 959article.comment .commenthead .when { color: var(--muted); }
 960article.comment .rendered { padding: 0 var(--sp-4); }
 961article.comment .rendered > :first-child { margin-top: var(--sp-3); }
 962article.comment .rendered > :last-child { margin-bottom: var(--sp-3); }
 963form.commentform { margin: var(--sp-4) 0; }
 964details.editbox { margin: var(--sp-2) 0; max-width: 48rem; }
 965details.editbox summary { cursor: pointer; color: var(--muted); font-size: var(--fs-2); }
 966details.editbox summary:hover { color: var(--accent); }
 967details.editbox input[type="text"] { width: 100%; }
 968.syscomment {
 969  max-width: 48rem;
 970  color: var(--muted);
 971  font-size: var(--fs-2);
 972  margin: var(--sp-3) 0;
 973  padding-left: var(--sp-4);
 974  border-left: 3px solid var(--faint);
 975}
 976.syscomment p { display: inline; margin: 0; }
 977
 978/* review threads under diff lines */
 979.thread {
 980  border: 1px solid var(--faint);
 981  border-left: 3px solid var(--accent);
 982  border-radius: var(--r-md);
 983  padding: var(--sp-2) var(--sp-4);
 984  margin: var(--sp-2) 0 var(--sp-2) var(--sp-6);
 985}
 986.thread.resolved { border-left-color: var(--ok); opacity: 0.75; }
 987.thread.stale { border-left-color: var(--warn); }
 988.thread p.commenthead { font-size: var(--fs-2); margin: var(--sp-2) 0 0; }
 989.thread .when { color: var(--muted); }
 990.thread .rendered p { margin: var(--sp-1) 0; }
 991.thread .threadstate { color: var(--muted); font-size: var(--fs-1); margin: var(--sp-1) 0 0; }
 992
 993/* forms: every control shares one shell, so a select reads as a sibling
 994   of the text inputs beside it rather than as an OS control dropped in */
 995input, textarea, button, select { font: inherit; color: inherit; }
 996input[type="text"], input[type="search"], input[type="email"],
 997input[type="password"], input:not([type]), textarea, select {
 998  background: var(--bg);
 999  color: var(--fg);
1000  border: 1px solid var(--line);
1001  border-radius: var(--r-md);
1002  padding: var(--sp-2) var(--sp-3);
1003  line-height: 1.4;
1004}
1005textarea { width: 100%; resize: vertical; }
1006textarea[name="content"] { font-family: var(--mono); font-size: var(--fs-1); }
1007/* the native arrow cannot be restyled, so draw our own and match the
1008   inputs exactly; --chev carries the stroke colour per scheme */
1009select {
1010  appearance: none;
1011  padding-right: 1.9rem;
1012  background-image: var(--chev);
1013  background-repeat: no-repeat;
1014  background-position: right 0.6rem center;
1015  background-size: 0.62rem;
1016  cursor: pointer;
1017}
1018input:hover, textarea:hover, select:hover { border-color: var(--muted); }
1019/* the global :focus-visible ring covers these; only the border moves */
1020input:focus, textarea:focus, select:focus { border-color: var(--accent); }
1021input[type="radio"], input[type="checkbox"] { accent-color: var(--fill); }
1022label:has(> input[type="radio"]), label:has(> input[type="checkbox"]),
1023label:has(> select) { display: inline-flex; align-items: center; gap: var(--sp-2); }
1024
1025/* Shape carries the meaning on these two and nothing else does: a circle
1026   takes one answer, a square takes any number. It survives colour being
1027   removed — greyscale, high contrast, colour blindness — so the native
1028   shapes stay and only the colour joins the system. Drawing them by hand
1029   would align the corners at the cost of the one cue that always works. */
1030input[type="radio"], input[type="checkbox"] { accent-color: var(--fill); }
1031
1032/* a segmented control for a small, mutually exclusive set: real radios
1033   underneath, so arrow keys and screen readers behave as they always did */
1034fieldset.segmented { border: 0; margin: 0 0 var(--sp-4); padding: 0; }
1035fieldset.segmented legend {
1036  padding: 0;
1037  margin-bottom: var(--sp-2);
1038  color: var(--muted);
1039  font-size: var(--fs-2);
1040}
1041fieldset.segmented .options { display: inline-flex; }
1042fieldset.segmented label { gap: 0; }
1043fieldset.segmented input {
1044  position: absolute;
1045  width: 1px;
1046  height: 1px;
1047  opacity: 0;
1048  pointer-events: none;
1049}
1050fieldset.segmented span {
1051  display: block;
1052  padding: var(--sp-2) var(--sp-4);
1053  border: 1px solid var(--line);
1054  font-size: var(--fs-2);
1055  cursor: pointer;
1056}
1057fieldset.segmented label + label span { border-left: 0; }
1058fieldset.segmented label:first-child span { border-radius: var(--r-sm) 0 0 var(--r-sm); }
1059fieldset.segmented label:last-child span { border-radius: 0 var(--r-sm) var(--r-sm) 0; }
1060fieldset.segmented span:hover { border-color: var(--muted); }
1061fieldset.segmented input:checked + span {
1062  background: var(--fill);
1063  border-color: var(--fill);
1064  color: #ffffff;
1065  font-weight: 600;
1066}
1067fieldset.segmented input:focus-visible + span {
1068  outline: 2px solid var(--accent);
1069  outline-offset: 2px;
1070}
1071
1072/* remaining input states */
1073::placeholder { color: var(--muted); opacity: 1; }
1074::selection { background: var(--fill); color: #ffffff; }
1075/* :user-invalid, not :invalid — a required field is invalid the moment
1076   the page loads, and colouring it red before anyone has typed is a
1077   scolding, not a hint */
1078input:user-invalid, textarea:user-invalid {
1079  border-color: var(--bad);
1080}
1081.hint { display: block; color: var(--muted); font-size: var(--fs-1); margin-top: var(--sp-1); }
1082button {
1083  background: var(--fill);
1084  color: #ffffff;
1085  border: none;
1086  border-radius: var(--r-md);
1087  padding: var(--sp-2) var(--sp-4);
1088  font-weight: 600;
1089  cursor: pointer;
1090}
1091button:hover { filter: brightness(1.15); }
1092
1093/* 404 */
1094.notfound { text-align: center; padding: var(--sp-6) 0; }
1095.notfound .bigcode {
1096  font-family: var(--mono);
1097  font-size: 4rem;
1098  color: var(--faint);
1099  -webkit-text-stroke: 1px var(--line);
1100  margin: 0;
1101  line-height: 1;
1102}
1103.notfound h1 { margin-top: var(--sp-3); }
1104
1105/* footer */
1106footer {
1107  border-top: 1px solid var(--faint);
1108  padding: var(--sp-4) var(--sp-5) var(--sp-5);
1109  max-width: 78rem;
1110  width: 100%;
1111  color: var(--muted);
1112  font-size: var(--fs-1);
1113}
1114footer p { margin: 0; }
1115footer a { color: var(--muted); text-decoration: underline; }
1116footer a:hover { color: var(--accent); }
1117
1118/* search */
1119form.searchform {
1120  display: flex;
1121  gap: var(--sp-2);
1122  margin: var(--sp-3) 0 var(--sp-4);
1123}
1124form.searchform input[type="search"] { flex: 1; max-width: 32rem; }
1125form.searchform.compact { margin: 0; }
1126form.searchform.compact input[type="search"] {
1127  padding: var(--sp-1) var(--sp-3);
1128  font-size: var(--fs-2);
1129  min-width: 18rem;
1130}
1131ul.matchlist { list-style: none; margin: var(--sp-3) 0; padding: 0; }
1132ul.matchlist li { margin-bottom: var(--sp-3); }
1133ul.matchlist .matchpath { font-family: var(--mono); font-size: var(--fs-1); }
1134pre.matchline {
1135  background: var(--code-bg);
1136  border: 1px solid var(--faint);
1137  border-radius: var(--r-md);
1138  padding: var(--sp-1) var(--sp-3);
1139  margin: var(--sp-1) 0 0;
1140  overflow-x: auto;
1141}
1142pre.matchline mark {
1143  background: color-mix(in srgb, var(--warn) 25%, transparent);
1144  color: inherit;
1145  border-radius: 2px;
1146}
1147
1148/* wiki */
1149.wikilayout { display: flex; gap: var(--sp-5); align-items: flex-start; }
1150.wikipage { flex: 1; min-width: 0; }
1151.wikinav { flex: none; width: 13rem; padding-top: var(--sp-4); }
1152.wikinav ul { list-style: none; margin: var(--sp-1) 0 var(--sp-4); padding: 0; }
1153.wikinav li a { display: block; padding: 0.15rem 0; color: var(--fg); }
1154.wikinav li a:hover { color: var(--accent); text-decoration: none; }
1155.wikinav li a.active { color: var(--accent); font-weight: 550; }
1156@media (max-width: 40rem) {
1157  /* Column direction + the desktop align-items:flex-start lets .wikipage
1158     take its content's intrinsic width, overflowing the viewport (and
1159     triggering iOS font inflation). Stretch pins it to the container. */
1160  .wikilayout { flex-direction: column; align-items: stretch; }
1161  .wikinav { width: auto; padding-top: 0; }
1162}
1163
1164/* blame */
1165.blame {
1166  border: 1px solid var(--line);
1167  border-radius: var(--rad-2, 6px);
1168  overflow: hidden;
1169}
1170.blamehunk {
1171  display: flex;
1172  gap: var(--sp-3);
1173  border-top: 1px solid var(--line);
1174  align-items: flex-start;
1175}
1176.blamehunk:first-child { border-top: none; }
1177.blameinfo {
1178  flex: none;
1179  width: 17rem;
1180  padding: var(--sp-2) var(--sp-3);
1181  min-width: 0;
1182}
1183.blameinfo .subject {
1184  margin: 0;
1185  font-size: var(--fs-1);
1186  white-space: nowrap;
1187  overflow: hidden;
1188  text-overflow: ellipsis;
1189}
1190.blameinfo .meta { margin: 0; font-size: var(--fs-1); color: var(--muted); }
1191.blamecode {
1192  flex: 1;
1193  margin: 0;
1194  padding: var(--sp-2) var(--sp-3) var(--sp-2) 0;
1195  overflow-x: auto;
1196  border-left: 1px solid var(--line);
1197  align-self: stretch;
1198}
1199.lineno {
1200  display: inline-block;
1201  min-width: 3.5em;
1202  padding-right: 1em;
1203  text-align: right;
1204  color: var(--muted);
1205  user-select: none;
1206}
1207
1208/* mobile */
1209@media (max-width: 40rem) {
1210  .container { padding-left: var(--sp-4); padding-right: var(--sp-4); }
1211  main.container { padding-top: var(--sp-2); }
1212  .repogrid { grid-template-columns: 1fr; }
1213  .thread { margin-left: var(--sp-3); }
1214  /* the commit subject is the widest thing in the listing and the one
1215     column a phone can do without: the tipbar above already names the
1216     latest commit. */
1217  table.tree td.lastcommit, table.tree th.lastcommit { display: none; }
1218  table.tree td.mode, table.tree th.mode { display: none; }
1219  .clone, .pathbar { overflow-wrap: anywhere; }
1220  .readme, .code { padding: var(--sp-3); }
1221  .blamehunk { flex-direction: column; gap: 0; }
1222  .blameinfo { width: auto; }
1223  .blamecode { border-left: none; padding-left: var(--sp-3); width: 100%; }
1224  .cardhead {
1225    margin: calc(-1 * var(--sp-3)) calc(-1 * var(--sp-3)) var(--sp-3);
1226    padding: var(--sp-2) var(--sp-3);
1227  }
1228}
1229
1230/* tree listing: the last commit is what a file table is scanned for, so
1231   it leads. The file's own facts moved to the blob page. */
1232.tipbar {
1233  display: flex;
1234  align-items: center;
1235  gap: var(--sp-3);
1236  padding: var(--sp-2) var(--sp-4);
1237  background: var(--hover);
1238  border: 1px solid var(--line);
1239  border-bottom: 0;
1240  border-radius: var(--r-lg) var(--r-lg) 0 0;
1241  font-size: var(--fs-2);
1242}
1243.tipbar .who { font-weight: 600; }
1244.tipbar .subject { color: var(--fg); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1245.tipbar .subject:hover { color: var(--accent); }
1246.tipbar .spacer { flex: 1; }
1247.tipbar .age { color: var(--muted); white-space: nowrap; }
1248.tipbar + table.tree { border-radius: 0 0 var(--r-lg) var(--r-lg); }
1249table.tree th.lastcommit, table.tree td.lastcommit { width: 55%; }
1250table.tree td.lastcommit a { color: var(--muted); display: block; overflow: hidden;
1251                             text-overflow: ellipsis; white-space: nowrap; }
1252table.tree td.lastcommit a:hover { color: var(--accent); }
1253table.tree th.age, table.tree td.age {
1254  text-align: right;
1255  white-space: nowrap;
1256  color: var(--muted);
1257  font-variant-numeric: tabular-nums;
1258}
1259table.tree td.name { width: 25%; white-space: nowrap; }
1260table.tree td.name.dir a { color: var(--accent); }
1261p.clone { margin: 0 0 var(--sp-3); }
1262p.filefacts { color: var(--muted); font-size: var(--fs-1); margin: 0 0 var(--sp-3); }
1263.pathbar .act { font-size: var(--fs-1); }
1264
1265/* merge request: a two-column split, so state has somewhere to live that
1266   is not a run-on sentence under the title */
1267.withaside {
1268  display: grid;
1269  grid-template-columns: minmax(0, 1fr) 15rem;
1270  gap: var(--sp-5);
1271  align-items: start;
1272}
1273.withaside .mainside { min-width: 0; }
1274@media (max-width: 62rem) { .withaside { grid-template-columns: 1fr; } }
1275
1276.aside { font-size: var(--fs-2); }
1277.aside .grp { border-top: 1px solid var(--line); padding: var(--sp-3) 0; }
1278.aside .grp:first-child { border-top: 0; padding-top: 0; }
1279.aside h2 {
1280  margin: 0 0 var(--sp-2);
1281  font-family: var(--mono);
1282  font-size: var(--fs-0);
1283  font-weight: 500;
1284  letter-spacing: 0.1em;
1285  text-transform: uppercase;
1286  color: var(--muted);
1287}
1288.aside .row { display: flex; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-1); flex-wrap: wrap; }
1289.aside .row:last-child { margin-bottom: 0; }
1290.aside .none { color: var(--muted); }
1291.aside .dot { width: 0.45rem; height: 0.45rem; flex: none; border-radius: 50%; background: var(--muted); }
1292.aside .dot.ok { background: var(--ok); }
1293.aside .dot.bad { background: var(--bad); }
1294.aside .dot.pend { background: var(--mark); }
1295
1296/* sub-navigation within an item; orange marks position as it does above */
1297nav.subtabs {
1298  display: flex;
1299  gap: var(--sp-4);
1300  border-bottom: 1px solid var(--line);
1301  margin: 0 0 var(--sp-4);
1302}
1303nav.subtabs a {
1304  display: inline-flex;
1305  align-items: center;
1306  gap: var(--sp-2);
1307  padding: 0 0 var(--sp-2);
1308  color: var(--muted);
1309  font-size: var(--fs-2);
1310  border-bottom: 2px solid transparent;
1311  margin-bottom: -1px;
1312}
1313nav.subtabs a:hover { color: var(--fg); text-decoration: none; }
1314nav.subtabs a[aria-current] { color: var(--fg); font-weight: 700; border-bottom-color: var(--mark); }
1315nav.subtabs a i {
1316  font-style: normal;
1317  font-family: var(--mono);
1318  font-size: var(--fs-0);
1319  background: var(--hover);
1320  border-radius: var(--r-sm);
1321  padding: 0 0.35rem;
1322}
1323p.diffstat { color: var(--muted); font-size: var(--fs-2); margin: 0 0 var(--sp-3); }
1324p.diffstat .add { color: var(--ok); }
1325p.diffstat .del { color: var(--bad); }