internal/web/static/style.css

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

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