repos
/ orchard main

orchard

mirror

Every site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.

blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics

30.0 KB · 1233 lines · SCSS Raw History
   1// repos.bythewood.me. One hand written stylesheet rather than Bootstrap, since
   2// this site is dense text (file trees, diffs, commit lists) and a framework
   3// does not help with any of it.
   4//
   5// The palette is the one analytics, auth, logging and status share, written as
   6// custom properties here because there is no Sass variable file to import from
   7// a separate module. When a colour changes there it has to change here too.
   8
   9:root {
  10  --bg:          #0e0d0a;
  11  --surface:     #1c1a15;
  12  --raised:      #24211a;
  13  --sunken:      #090806;
  14  --line:        rgba(107, 158, 120, 0.34);
  15  --line-strong: rgba(107, 158, 120, 0.45);
  16
  17  --bright: #ede8e0;
  18  --text:   #ddd7cd;
  19  --muted:  #b3aba2;
  20  --faint:  #8a8279;
  21
  22  --accent:      #6b9e78;
  23  --accent-lift: #7db88c;
  24  --accent-dim:  rgba(107, 158, 120, 0.16);
  25  --link:        #7db88c;
  26  --link-lift:   #95cca2;
  27
  28  --add:      #7db88c;
  29  --add-bg:   rgba(125, 184, 140, 0.12);
  30  --del:      #c47055;
  31  --del-bg:   rgba(196, 112, 85, 0.12);
  32  --warn:     #c9a84c;
  33  --warn-bg:  rgba(201, 168, 76, 0.10);
  34
  35  // Newsreader is kept for repository names alone. Everything else is the one
  36  // face the rest of the estate sets, so --sans and --mono are the same family
  37  // here the way they are in the shared Bootstrap variables.
  38  --serif: "Newsreader", ui-serif, Georgia, "Times New Roman", serif;
  39  --sans: "Monaspace Argon", ui-monospace, "Cascadia Code", Consolas, "SF Mono", Menlo, monospace;
  40  --mono: var(--sans);
  41
  42  --t-xs:  0.75rem;
  43  --t-sm:  0.8125rem;
  44  --t-base: 0.92rem;
  45  --t-md:  1.0625rem;
  46  --t-lg:  1.375rem;
  47  --t-xl:  1.75rem;
  48
  49  --radius: 0.25rem;
  50  --radius-sm: 0.2rem;
  51  --wrap:   1140px;
  52  --bar:    52px;
  53
  54  // One tracking value, used everywhere a label is set in caps.
  55  --track: 0.1em;
  56}
  57
  58*, *::before, *::after { box-sizing: border-box; }
  59
  60html { -webkit-text-size-adjust: 100%; }
  61
  62body {
  63  margin: 0;
  64  background: var(--bg);
  65  color: var(--text);
  66  font-family: var(--sans);
  67  font-size: var(--t-base);
  68  line-height: 1.7;
  69  letter-spacing: 0.01em;
  70  -webkit-font-smoothing: antialiased;
  71
  72  background-image:
  73    linear-gradient(rgba(107, 158, 120, 0.028) 1px, transparent 1px),
  74    linear-gradient(90deg, rgba(107, 158, 120, 0.028) 1px, transparent 1px);
  75  background-size: 32px 32px;
  76  background-position: center top;
  77}
  78
  79code, pre, .mono { font-family: var(--mono); }
  80
  81.size, .num, .meta time, .count, .tokens td { font-variant-numeric: tabular-nums; }
  82
  83a {
  84  color: var(--link);
  85  text-decoration: none;
  86  transition: color 0.12s ease;
  87}
  88a:hover { color: var(--link-lift); text-decoration: underline; }
  89
  90:focus-visible {
  91  outline: 2px solid var(--accent);
  92  outline-offset: 2px;
  93  border-radius: 2px;
  94}
  95
  96::selection { background: var(--accent-dim); }
  97
  98h1, h2, h3, h4 {
  99  text-wrap: balance;
 100  font-weight: 600;
 101  line-height: 1.25;
 102  margin: 0;
 103}
 104
 105.pagetitle, .commitfull h2, section > h2,
 106.emptystate h2, .loginbox h1, .notfound h1, .markdown h1, .markdown h2 {
 107  font-family: var(--sans);
 108  font-weight: 700;
 109  letter-spacing: -0.01em;
 110}
 111
 112.repohead h1, .repocard .name {
 113  font-family: var(--serif);
 114  font-weight: 600;
 115  letter-spacing: -0.01em;
 116}
 117
 118.wrap {
 119  max-width: var(--wrap);
 120  margin: 0 auto;
 121  padding: 0 1.5rem;
 122}
 123
 124@media (prefers-reduced-motion: reduce) {
 125  *, *::before, *::after {
 126    animation-duration: 0.01ms !important;
 127    transition-duration: 0.01ms !important;
 128  }
 129}
 130
 131.topbar {
 132  position: sticky;
 133  top: 0;
 134  z-index: 50;
 135  background: var(--sunken);
 136  border-bottom: 1px solid rgba(107, 158, 120, 0.3);
 137
 138  .wrap {
 139    display: flex;
 140    align-items: center;
 141    gap: 0.85rem;
 142    height: var(--bar);
 143  }
 144
 145  // The wordmark the other four sites set: caps, tracked, with the identity
 146  // dot after it. The serif is kept for repository names and nothing else.
 147  .brand {
 148    display: inline-flex;
 149    align-items: center;
 150    gap: 0.6rem;
 151    font-family: var(--sans);
 152    font-weight: 600;
 153    font-size: 0.78rem;
 154    text-transform: uppercase;
 155    letter-spacing: var(--track);
 156    color: #ede8e0;
 157
 158    svg { width: 16px; height: 16px; color: var(--accent); flex: none; }
 159    &:hover { color: #ede8e0; text-decoration: none; }
 160    &:hover svg { color: var(--accent-lift); }
 161
 162    &::after {
 163      content: "";
 164      width: 6px;
 165      height: 6px;
 166      border-radius: 50%;
 167      background: var(--accent);
 168    }
 169  }
 170
 171  .context {
 172    display: flex;
 173    align-items: center;
 174    gap: 0.4rem;
 175    min-width: 0;
 176    flex: 1;
 177    font-family: var(--mono);
 178    font-size: var(--t-sm);
 179
 180    .sep { color: var(--faint); }
 181
 182    a { color: var(--muted); &:hover { color: var(--text); } }
 183
 184    .here {
 185      color: var(--text);
 186      overflow: hidden;
 187      text-overflow: ellipsis;
 188      white-space: nowrap;
 189    }
 190
 191    .ref {
 192      color: var(--muted);
 193      background: var(--raised);
 194      border-radius: 3px;
 195      padding: 0.05rem 0.4rem;
 196      font-size: var(--t-xs);
 197      white-space: nowrap;
 198    }
 199  }
 200
 201  nav {
 202    display: flex;
 203    align-items: center;
 204    gap: 0.4rem;
 205    font-size: 0.8rem;
 206    flex: none;
 207
 208    a {
 209      padding: 0.3rem 0.7rem;
 210      color: rgba(221, 215, 205, 0.8);
 211      text-transform: lowercase;
 212      letter-spacing: 0.05em;
 213      &:hover { color: #ede8e0; text-decoration: none; }
 214    }
 215
 216    // The sign in and account links read as the button the other four put in
 217    // the same corner.
 218    a:last-child {
 219      border: 1px solid rgba(221, 215, 205, 0.28);
 220      border-radius: var(--radius);
 221      text-transform: none;
 222      letter-spacing: 0.01em;
 223      &:hover { border-color: rgba(221, 215, 205, 0.5); }
 224    }
 225  }
 226}
 227
 228main.wrap { padding-top: 2rem; padding-bottom: 3rem; }
 229
 230.footer {
 231  border-top: 1px solid var(--line);
 232  margin-top: 5rem;
 233  padding: 2.25rem 0 2.5rem;
 234  font-size: var(--t-sm);
 235
 236  .cols {
 237    display: grid;
 238    grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr));
 239    gap: 2rem;
 240  }
 241
 242  // The `// Section` heading the other four sites set in their footers.
 243  .h5 {
 244    font-family: var(--sans);
 245    font-size: 0.7rem;
 246    font-weight: 600;
 247    letter-spacing: 0.12em;
 248    text-transform: uppercase;
 249    color: var(--warn);
 250    margin-bottom: 0.7rem;
 251  }
 252
 253  .about p { margin: 0; color: var(--muted); max-width: 46ch; }
 254
 255  ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
 256  a { color: var(--muted); &:hover { color: var(--text); } }
 257
 258}
 259
 260// The strip under the footer, matching the one the other four sites close on.
 261.footer-bar {
 262  border-top: 1px solid rgba(107, 158, 120, 0.2);
 263  padding: 1rem 0;
 264
 265  .wrap {
 266    display: flex;
 267    align-items: center;
 268    justify-content: space-between;
 269    gap: 1rem;
 270    flex-wrap: wrap;
 271  }
 272
 273  small { color: var(--faint); font-size: var(--t-xs); }
 274
 275  .footer-bar-link {
 276    display: inline-flex;
 277    color: var(--faint);
 278    &:hover { color: var(--accent-lift); }
 279  }
 280}
 281
 282.pagehead {
 283  display: flex;
 284  align-items: baseline;
 285  justify-content: space-between;
 286  gap: 1rem;
 287  flex-wrap: wrap;
 288  margin-bottom: 1.5rem;
 289}
 290
 291.pagetitle {
 292  font-size: var(--t-xl);
 293  letter-spacing: -0.02em;
 294  display: flex;
 295  align-items: center;
 296  gap: 0.65rem;
 297}
 298
 299.count {
 300  font-family: var(--mono);
 301  font-size: var(--t-xs);
 302  font-weight: 400;
 303  color: var(--muted);
 304  background: var(--raised);
 305  border-radius: 999px;
 306  padding: 0.1rem 0.5rem;
 307}
 308
 309.badge {
 310  font-size: var(--t-xs);
 311  font-weight: 500;
 312  letter-spacing: 0.02em;
 313  padding: 0.1rem 0.45rem;
 314  border-radius: 3px;
 315  border: 1px solid;
 316  white-space: nowrap;
 317
 318  &.mirror    { color: var(--link);   border-color: rgba(132, 169, 201, 0.4); }
 319  &.archived  { color: var(--faint);  border-color: var(--line-strong); }
 320  &.empty     { color: var(--faint);  border-color: var(--line-strong); }
 321  &.default   { color: var(--add);    border-color: rgba(127, 176, 105, 0.4); }
 322  &.annotated { color: var(--muted);  border-color: var(--line-strong); }
 323
 324  &.gone {
 325    color: var(--bg);
 326    background: var(--warn);
 327    border-color: var(--warn);
 328    font-weight: 600;
 329  }
 330}
 331
 332.hint  { color: var(--muted); font-size: var(--t-sm); }
 333.empty { color: var(--faint); }
 334.error { color: var(--del); }
 335.warn  { color: var(--warn); }
 336
 337// Its own element rather than a rule on `code`, since the same prose mentions
 338// commands inline and one selector would turn those sentences into blocks.
 339pre.cmd {
 340  display: block;
 341  font-family: var(--mono);
 342  font-size: var(--t-sm);
 343  line-height: 1.7;
 344  background: var(--sunken);
 345  border: 1px solid var(--line);
 346  border-radius: var(--radius);
 347  padding: 0.7rem 0.85rem;
 348  margin: 0.6rem 0;
 349  overflow-x: auto;
 350  white-space: pre-wrap;
 351  word-break: break-word;
 352  color: var(--text);
 353  user-select: all;
 354}
 355
 356p code, li code, .hint code, td code {
 357  font-family: var(--mono);
 358  font-size: 0.9em;
 359  background: var(--raised);
 360  border-radius: 3px;
 361  padding: 0.05rem 0.3rem;
 362  color: var(--text);
 363}
 364
 365.notice {
 366  background: var(--surface);
 367  border: 1px solid var(--line);
 368  border-radius: var(--radius);
 369  padding: 1rem 1.15rem;
 370  margin-bottom: 1.5rem;
 371}
 372
 373.emptystate {
 374  background: var(--surface);
 375  border: 1px solid var(--line);
 376  border-radius: var(--radius);
 377  padding: 1.5rem 1.65rem;
 378
 379  h2 { font-size: var(--t-md); margin-bottom: 0.4rem; }
 380  p  { margin: 0.5rem 0; color: var(--muted); }
 381}
 382
 383button, .btn {
 384  font-family: var(--sans);
 385  font-size: var(--t-sm);
 386  font-weight: 500;
 387  background: var(--raised);
 388  color: var(--text);
 389  border: 1px solid var(--line-strong);
 390  border-radius: var(--radius);
 391  padding: 0.3rem 0.75rem;
 392  cursor: pointer;
 393  transition: border-color 0.12s ease, background 0.12s ease, color 0.12s ease;
 394  white-space: nowrap;
 395
 396  &:hover { border-color: var(--muted); background: var(--line); text-decoration: none; }
 397}
 398
 399.btn {
 400  display: inline-block;
 401  padding: 0.6rem 1.1rem;
 402  border: 1px solid transparent;
 403  border-radius: var(--radius);
 404  background: none;
 405  font-size: 0.82rem;
 406  font-weight: 500;
 407  letter-spacing: 0.04em;
 408  color: var(--muted);
 409  &:hover { text-decoration: none; }
 410}
 411
 412.btn-primary {
 413  background: var(--accent-dim);
 414  border-color: var(--accent);
 415  color: var(--accent-lift);
 416  &:hover { background: rgba(107, 158, 120, 0.26); border-color: var(--accent); }
 417}
 418
 419// Matches Bootstrap's .btn-sm as the other four resolve it, since a button
 420// beside body text should be the same object on every site here.
 421.btn-sm {
 422  padding: 0.25rem 0.5rem;
 423  font-size: 0.805rem;
 424  border-radius: var(--radius-sm);
 425  letter-spacing: 0.02em;
 426}
 427
 428.btn-ghost {
 429  border-color: rgba(221, 215, 205, 0.28);
 430  color: var(--text);
 431  &:hover { border-color: rgba(221, 215, 205, 0.5); background: rgba(221, 215, 205, 0.05); color: var(--text); }
 432}
 433
 434button.primary {
 435  background: var(--accent);
 436  border-color: var(--accent);
 437  color: #17130c;
 438  &:hover { background: var(--accent-lift); border-color: var(--accent-lift); }
 439}
 440
 441button.danger:hover { border-color: var(--del); color: var(--del); background: var(--del-bg); }
 442
 443button.linkish {
 444  background: none;
 445  border: none;
 446  color: var(--muted);
 447  padding: 0;
 448  font-size: var(--t-sm);
 449  &:hover { color: var(--text); background: none; text-decoration: underline; }
 450}
 451
 452form.inline { display: inline-flex; gap: 0.5rem; align-items: center; }
 453
 454input[type="text"], input[type="password"], input[type="url"] {
 455  font-family: var(--mono);
 456  font-size: var(--t-sm);
 457  background: var(--sunken);
 458  color: var(--text);
 459  border: 1px solid var(--line);
 460  border-radius: var(--radius);
 461  padding: 0.4rem 0.65rem;
 462  width: 100%;
 463  transition: border-color 0.12s ease;
 464
 465  &:focus { border-color: var(--accent); }
 466  &[readonly] { color: var(--muted); cursor: pointer; }
 467}
 468
 469.repolist { list-style: none; padding: 0; margin: 0; }
 470
 471.repocard {
 472  border-top: 1px solid var(--line);
 473  padding: 0.85rem 0;
 474  display: grid;
 475  gap: 0.25rem;
 476
 477  &:last-child { border-bottom: 1px solid var(--line); }
 478
 479  .row { display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; }
 480
 481  .name {
 482    font-family: var(--serif);
 483    font-size: var(--t-lg);
 484    font-weight: 600;
 485    color: var(--text);
 486    letter-spacing: -0.01em;
 487    &:hover { color: var(--accent); text-decoration: none; }
 488  }
 489
 490  .desc { margin: 0; color: var(--muted); max-width: 68ch; }
 491
 492  .meta {
 493    margin: 0;
 494    color: var(--faint);
 495    font-size: var(--t-sm);
 496    display: flex;
 497    flex-wrap: wrap;
 498    gap: 0.35rem 1.1rem;
 499  }
 500
 501  .syncerr { color: var(--del); font-size: var(--t-sm); margin: 0; }
 502}
 503
 504.topics { margin: 0; display: flex; flex-wrap: wrap; gap: 0.35rem; }
 505
 506.topic {
 507  font-size: var(--t-xs);
 508  color: var(--muted);
 509  background: var(--raised);
 510  border-radius: 999px;
 511  padding: 0.05rem 0.55rem;
 512}
 513
 514.repohead {
 515  margin-bottom: 1.25rem;
 516
 517  .titlerow {
 518    display: flex;
 519    align-items: center;
 520    gap: 0.6rem;
 521    flex-wrap: wrap;
 522    margin-bottom: 0.35rem;
 523  }
 524
 525  h1 {
 526    font-family: var(--mono);
 527    font-size: var(--t-lg);
 528    letter-spacing: -0.02em;
 529    a { color: var(--text); &:hover { color: var(--accent); text-decoration: none; } }
 530  }
 531
 532  .desc { margin: 0 0 0.5rem; color: var(--muted); max-width: 68ch; }
 533}
 534
 535.repotabs {
 536  display: flex;
 537  gap: 0.25rem;
 538  margin-top: 0.9rem;
 539  border-bottom: 1px solid var(--line);
 540  overflow-x: auto;
 541  scrollbar-width: none;
 542  &::-webkit-scrollbar { display: none; }
 543
 544  a {
 545    display: flex;
 546    align-items: center;
 547    gap: 0.4rem;
 548    padding: 0.45rem 0.75rem;
 549    color: var(--muted);
 550    font-size: var(--t-sm);
 551    border-bottom: 2px solid transparent;
 552    margin-bottom: -1px;
 553    white-space: nowrap;
 554
 555    &:hover { color: var(--text); text-decoration: none; }
 556    &[aria-current="page"] {
 557      color: var(--text);
 558      border-bottom-color: var(--accent);
 559      font-weight: 500;
 560    }
 561  }
 562}
 563
 564.toolbar {
 565  display: flex;
 566  align-items: center;
 567  gap: 0.75rem;
 568  margin-bottom: 1rem;
 569  flex-wrap: wrap;
 570
 571  .stat { color: var(--faint); font-size: var(--t-sm); }
 572  .spacer { flex: 1; }
 573}
 574
 575.crumbs .leaf { color: var(--text); }
 576
 577.crumbs {
 578  font-family: var(--mono);
 579  font-size: var(--t-sm);
 580  color: var(--faint);
 581  a { color: var(--link); }
 582}
 583
 584.refswitch {
 585  position: relative;
 586
 587  summary {
 588    cursor: pointer;
 589    list-style: none;
 590    display: inline-flex;
 591    align-items: center;
 592    gap: 0.4rem;
 593    background: var(--raised);
 594    border: 1px solid var(--line-strong);
 595    border-radius: var(--radius);
 596    padding: 0.3rem 0.7rem;
 597    font-family: var(--mono);
 598    font-size: var(--t-sm);
 599    color: var(--text);
 600
 601    &::-webkit-details-marker { display: none; }
 602    &::after {
 603      content: "";
 604      width: 0; height: 0;
 605      border-left: 4px solid transparent;
 606      border-right: 4px solid transparent;
 607      border-top: 5px solid var(--muted);
 608    }
 609    &:hover { border-color: var(--muted); }
 610  }
 611
 612  .refmenu {
 613    position: absolute;
 614    z-index: 40;
 615    top: calc(100% + 4px);
 616    left: 0;
 617    min-width: 240px;
 618    max-height: 340px;
 619    overflow-y: auto;
 620    background: var(--raised);
 621    border: 1px solid var(--line-strong);
 622    border-radius: var(--radius);
 623    padding: 0.4rem 0;
 624    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
 625
 626    h4 {
 627      margin: 0.4rem 0.85rem 0.2rem;
 628      font-size: var(--t-xs);
 629      font-weight: 600;
 630      letter-spacing: 0.06em;
 631      text-transform: uppercase;
 632      color: var(--faint);
 633    }
 634    ul { list-style: none; margin: 0; padding: 0; }
 635    li a {
 636      display: block;
 637      padding: 0.25rem 0.85rem;
 638      font-family: var(--mono);
 639      font-size: var(--t-sm);
 640      color: var(--text);
 641      &:hover { background: var(--line); text-decoration: none; }
 642    }
 643  }
 644}
 645
 646.tree {
 647  width: 100%;
 648  border-collapse: collapse;
 649  border: 1px solid var(--line);
 650  border-radius: var(--radius);
 651  overflow: hidden;
 652  font-family: var(--mono);
 653  font-size: var(--t-sm);
 654  // A file listing is scanned rather than read, so it drops the body line-height.
 655  line-height: 1.45;
 656
 657  td {
 658    padding: 0.25rem 0.85rem;
 659    border-bottom: 1px solid var(--line);
 660  }
 661  tr:last-child td { border-bottom: none; }
 662  tr:hover td { background: var(--surface); }
 663
 664  .icon {
 665    width: 1.75rem;
 666    padding-right: 0;
 667    color: var(--faint);
 668    svg { display: block; width: 15px; height: 15px; }
 669  }
 670  tr.dir .icon { color: var(--accent); }
 671
 672  .name a { color: var(--link); }
 673  .size { text-align: right; color: var(--faint); white-space: nowrap; }
 674  .submodule { color: var(--muted); }
 675}
 676
 677.readme {
 678  margin-top: 1.75rem;
 679  border: 1px solid var(--line);
 680  border-radius: var(--radius);
 681  overflow: hidden;
 682
 683  .readmehead {
 684    background: var(--surface);
 685    border-bottom: 1px solid var(--line);
 686    padding: 0.5rem 1.15rem;
 687    color: var(--muted);
 688    font-family: var(--mono);
 689    font-size: var(--t-sm);
 690  }
 691  .markdown { padding: 1.5rem 1.75rem; }
 692}
 693
 694.markdown {
 695  > * { max-width: 72ch; }
 696  > pre, > table { max-width: none; }
 697
 698  h1, h2 { border-bottom: 1px solid var(--line); padding-bottom: 0.3rem; margin: 1.75rem 0 0.85rem; }
 699  h1 { font-size: var(--t-lg); }
 700  h2 { font-size: var(--t-md); }
 701  h3 { font-size: var(--t-base); margin: 1.5rem 0 0.6rem; }
 702  > :first-child { margin-top: 0; }
 703
 704  p, ul, ol { margin: 0.85rem 0; }
 705  li { margin: 0.25rem 0; }
 706
 707  img { max-width: 100%; }
 708
 709  table { border-collapse: collapse; display: block; overflow-x: auto; }
 710  th, td { border: 1px solid var(--line); padding: 0.35rem 0.7rem; text-align: left; }
 711  th { background: var(--surface); }
 712
 713  blockquote {
 714    margin: 1rem 0;
 715    padding: 0.1rem 0 0.1rem 1rem;
 716    border-left: 2px solid var(--line-strong);
 717    color: var(--muted);
 718  }
 719
 720  pre {
 721    background: var(--sunken);
 722    border: 1px solid var(--line);
 723    border-radius: var(--radius);
 724    padding: 0.85rem 1rem;
 725    overflow-x: auto;
 726    font-size: var(--t-sm);
 727  }
 728  code {
 729    background: var(--raised);
 730    padding: 0.1rem 0.35rem;
 731    border-radius: 3px;
 732    font-size: 0.9em;
 733  }
 734  pre code { background: none; padding: 0; }
 735
 736  hr { border: none; border-top: 1px solid var(--line); margin: 1.75rem 0; }
 737}
 738
 739.code {
 740  border: 1px solid var(--line);
 741  border-radius: var(--radius);
 742  background: var(--sunken);
 743  overflow-x: auto;
 744  font-size: var(--t-sm);
 745
 746  pre { margin: 0; padding: 0.85rem 0; }
 747  &.plain { margin: 0; padding: 0.85rem 1rem; white-space: pre; }
 748
 749  // chroma emits style="outline:none" inline on every line-number anchor, and
 750  // an inline style beats any author selector, so the site's focus ring has to
 751  // be restored with !important or those links are keyboard-invisible.
 752  a:focus-visible {
 753    outline: 2px solid var(--accent) !important;
 754    outline-offset: -2px;
 755  }
 756
 757  // chroma's line numbers.
 758  .lnt, .ln {
 759    color: var(--faint);
 760    user-select: none;
 761    padding-right: 1rem;
 762  }
 763}
 764
 765.commits { list-style: none; padding: 0; margin: 0; }
 766
 767.commit {
 768  border-top: 1px solid var(--line);
 769  padding: 0.7rem 0;
 770  &:last-child { border-bottom: 1px solid var(--line); }
 771
 772  .subject {
 773    display: block;
 774    color: var(--text);
 775    font-weight: 500;
 776    margin-bottom: 0.15rem;
 777    &:hover { color: var(--link-lift); }
 778  }
 779
 780  .meta {
 781    color: var(--faint);
 782    font-size: var(--t-sm);
 783    display: flex;
 784    flex-wrap: wrap;
 785    gap: 0.5rem 0.85rem;
 786  }
 787  .meta code { color: var(--accent); font-size: var(--t-xs); }
 788}
 789
 790.commitfull {
 791  h2 { font-size: var(--t-md); margin-bottom: 0.6rem; }
 792
 793  .body {
 794    background: var(--surface);
 795    border-left: 2px solid var(--line-strong);
 796    border-radius: 0 var(--radius) var(--radius) 0;
 797    padding: 0.8rem 1.1rem;
 798    white-space: pre-wrap;
 799    color: var(--muted);
 800    font-family: var(--mono);
 801    font-size: var(--t-sm);
 802    margin: 0 0 1rem;
 803  }
 804
 805  .meta {
 806    color: var(--faint);
 807    font-size: var(--t-sm);
 808    margin: 0.3rem 0;
 809    code { font-size: var(--t-xs); color: var(--accent); }
 810  }
 811
 812  .diffstat {
 813    margin: 1.5rem 0 0.85rem;
 814    font-size: var(--t-sm);
 815    color: var(--muted);
 816  }
 817}
 818
 819ins { color: var(--add); text-decoration: none; font-weight: 500; }
 820del { color: var(--del); text-decoration: none; font-weight: 500; }
 821
 822.pager {
 823  margin-top: 1.5rem;
 824  display: flex;
 825  gap: 0.75rem;
 826}
 827
 828.difffile {
 829  border: 1px solid var(--line);
 830  border-radius: var(--radius);
 831  margin-bottom: 1.25rem;
 832  // Not `overflow: hidden`. Clipping here would make this box the containing
 833  // block for the sticky header below, which would then stick to the box and
 834  // float over its own hunks. The corners are squared off on the header instead.
 835  overflow: visible;
 836
 837  .diffhead {
 838    // Sticky under the topbar, so the filename stays put while a long file's
 839    // hunks scroll.
 840    position: sticky;
 841    top: calc(var(--bar) - 1px);
 842    z-index: 10;
 843    border-radius: var(--radius) var(--radius) 0 0;
 844    background: var(--surface);
 845    border-bottom: 1px solid var(--line);
 846    padding: 0.5rem 0.85rem;
 847    display: flex;
 848    align-items: center;
 849    // A flex item will not shrink below its min-content width, so without the
 850    // wrap and the min-width below a deeply nested path sets the width of this
 851    // header, and with it the whole page's horizontal scroll.
 852    flex-wrap: wrap;
 853    gap: 0.7rem;
 854    font-size: var(--t-sm);
 855
 856    code {
 857      font-family: var(--mono);
 858      color: var(--text);
 859      min-width: 0;
 860      overflow-wrap: anywhere;
 861    }
 862    .counts { margin-left: auto; font-size: var(--t-xs); white-space: nowrap; }
 863  }
 864
 865  .binary { padding: 0.9rem; color: var(--faint); margin: 0; font-size: var(--t-sm); }
 866
 867  .status {
 868    font-size: var(--t-xs);
 869    font-weight: 600;
 870    letter-spacing: 0.04em;
 871    text-transform: uppercase;
 872    padding: 0.05rem 0.4rem;
 873    border-radius: 3px;
 874
 875    &.added    { color: var(--add);  background: var(--add-bg); }
 876    &.deleted  { color: var(--del);  background: var(--del-bg); }
 877    &.renamed  { color: var(--link); background: rgba(132, 169, 201, 0.1); }
 878    &.copied   { color: var(--link); background: rgba(132, 169, 201, 0.1); }
 879    &.modified { color: var(--warn); background: var(--warn-bg); }
 880  }
 881}
 882
 883.hunk {
 884  width: 100%;
 885  border-collapse: collapse;
 886  font-family: var(--mono);
 887  font-size: var(--t-sm);
 888  line-height: 1.55;
 889
 890  td { padding: 0 0.5rem; }
 891
 892  .num {
 893    width: 1%;
 894    min-width: 3.25rem;
 895    text-align: right;
 896    color: var(--faint);
 897    background: var(--sunken);
 898    user-select: none;
 899    // A wrapped code line must not drag its line numbers down with it.
 900    vertical-align: top;
 901    border-right: 1px solid var(--line);
 902    font-size: var(--t-xs);
 903  }
 904
 905  .code {
 906    white-space: pre-wrap;
 907    word-break: break-word;
 908    border: none;
 909    border-radius: 0;
 910    background: none;
 911  }
 912
 913  // A marker column in the text itself, so add and delete survive being read
 914  // without colour: copy-pasted, printed, or by anyone colour blind.
 915  tr.add .code::before,
 916  tr.del .code::before,
 917  tr.context .code::before {
 918    display: inline-block;
 919    width: 1ch;
 920    margin-right: 0.5ch;
 921    color: var(--faint);
 922  }
 923  tr.add .code::before     { content: "+"; color: var(--add); }
 924  tr.del .code::before     { content: "-"; color: var(--del); }
 925  tr.context .code::before { content: " "; }
 926
 927  tr.add td { background: var(--add-bg); }
 928  tr.del td { background: var(--del-bg); }
 929  tr.add .num { background: rgba(127, 176, 105, 0.14); }
 930  tr.del .num { background: rgba(209, 101, 107, 0.14); }
 931
 932  // `.hunkhead` is the row itself, so this has to be tr.hunkhead rather than a
 933  // descendant. The rule separates hunks, so the first one in a file skips it.
 934  tr.hunkhead td {
 935    background: var(--raised);
 936    color: var(--faint);
 937    padding: 0.25rem 0.85rem;
 938    font-size: var(--t-xs);
 939    border-top: 1px solid var(--line);
 940  }
 941  tr.hunkhead:first-child td { border-top: none; }
 942}
 943
 944.refs, .tokens {
 945  width: 100%;
 946  border-collapse: collapse;
 947  border: 1px solid var(--line);
 948  border-radius: var(--radius);
 949  overflow: hidden;
 950  font-size: var(--t-sm);
 951
 952  td { padding: 0.55rem 0.85rem; border-bottom: 1px solid var(--line); }
 953  tr:last-child td { border-bottom: none; }
 954  tr:hover td { background: var(--surface); }
 955
 956  .name { font-family: var(--mono); font-weight: 500; }
 957  .subject { color: var(--muted); }
 958  .when, .dl { color: var(--faint); white-space: nowrap; }
 959  .dl { text-align: right; }
 960  .dl a { margin-left: 0.75rem; }
 961}
 962
 963.clonebox {
 964  margin-top: 2.5rem;
 965  border: 1px solid var(--line);
 966  border-radius: var(--radius);
 967  background: var(--surface);
 968  padding: 1.15rem 1.35rem;
 969
 970  h3 {
 971    font-size: var(--t-xs);
 972    font-weight: 600;
 973    letter-spacing: 0.06em;
 974    text-transform: uppercase;
 975    color: var(--faint);
 976    margin-bottom: 0.5rem;
 977  }
 978  h3 + p, h3 + input { margin-top: 0; }
 979  input { margin-bottom: 0.35rem; }
 980  > h3:not(:first-child) { margin-top: 1.25rem; }
 981}
 982
 983// The 100MB ceiling Cloudflare puts on one request is invisible until a push
 984// fails, so the meter has to show it before that.
 985.meter {
 986  margin: 0.85rem 0 0;
 987  color: var(--faint);
 988  font-size: var(--t-xs);
 989  display: grid;
 990  gap: 0.35rem;
 991
 992  .bar {
 993    display: block;
 994    height: 5px;
 995    background: var(--sunken);
 996    border: 1px solid var(--line);
 997    border-radius: 3px;
 998    overflow: hidden;
 999
1000    span {
1001      display: block;
1002      height: 100%;
1003      background: var(--add);
1004      transition: width 0.3s ease;
1005    }
1006  }
1007
1008  // Past about three quarters it stops being trivia and starts being a warning.
1009  &.warn .bar span { background: var(--warn); }
1010  &.over .bar span { background: var(--del); }
1011}
1012
1013.pushlimit {
1014  margin-top: 1.25rem;
1015  border: 1px solid rgba(224, 164, 88, 0.3);
1016  border-radius: var(--radius);
1017  background: var(--warn-bg);
1018  padding: 1rem 1.15rem;
1019
1020  h4 {
1021    font-size: var(--t-sm);
1022    color: var(--warn);
1023    margin-bottom: 0.5rem;
1024  }
1025  p { margin: 0.6rem 0; font-size: var(--t-sm); color: var(--muted); }
1026  code { background: var(--sunken); }
1027  strong { color: var(--text); }
1028}
1029
1030.firstpush {
1031  align-self: flex-start;
1032
1033  summary {
1034    cursor: pointer;
1035    list-style: none;
1036    font-size: var(--t-sm);
1037    color: var(--muted);
1038    border: 1px solid var(--line-strong);
1039    border-radius: var(--radius);
1040    padding: 0.3rem 0.75rem;
1041    &::-webkit-details-marker { display: none; }
1042    &::before { content: "+ "; color: var(--accent); }
1043    &:hover { color: var(--text); border-color: var(--muted); }
1044  }
1045  &[open] summary::before { content: "\2212 "; }
1046
1047  .firstpushbody {
1048    margin-top: 0.85rem;
1049    border: 1px solid var(--line);
1050    border-radius: var(--radius);
1051    background: var(--surface);
1052    padding: 1.15rem 1.35rem;
1053    p { margin: 0 0 0.5rem; color: var(--muted); font-size: var(--t-sm); }
1054  }
1055}
1056
1057.loginbox {
1058  max-width: 360px;
1059  margin: 4rem auto;
1060
1061  h1 { font-size: var(--t-lg); margin-bottom: 0.5rem; }
1062  label { display: block; margin: 1rem 0 0.5rem; font-size: var(--t-sm); color: var(--muted); }
1063  button { width: 100%; padding: 0.45rem; margin-top: 0.85rem; }
1064}
1065
1066// Top and bottom, so a section following a panel like the README gets the same
1067// air as one following another section. Adjacent margins collapse, so two
1068// sections in a row still sit 2.5rem apart rather than 5.
1069section { margin: 2.5rem 0; }
1070section > h2 {
1071  font-size: var(--t-md);
1072  border-bottom: 1px solid var(--line);
1073  padding-bottom: 0.4rem;
1074  margin-bottom: 1rem;
1075}
1076
1077.tokennew {
1078  border-color: rgba(217, 154, 78, 0.35);
1079  background: var(--accent-dim);
1080  input { margin: 0.6rem 0; }
1081}
1082
1083.editbox {
1084  margin-top: 1.75rem;
1085  summary { cursor: pointer; color: var(--muted); font-size: var(--t-sm); }
1086  label { display: block; margin: 0.85rem 0 0.35rem; font-size: var(--t-sm); color: var(--muted); }
1087  button { margin-top: 0.85rem; }
1088}
1089
1090// The same shape the other four sites use for a 404: an amber caps label, a
1091// plain heading, the description the handler set, and a way back. Left aligned
1092// like every other page here rather than centred on its own.
1093.section-label {
1094  font-size: 0.7rem;
1095  font-weight: 600;
1096  letter-spacing: 0.12em;
1097  text-transform: uppercase;
1098  color: var(--warn);
1099}
1100
1101.notfound {
1102  padding: 3rem 0 5rem;
1103
1104  h1 {
1105    font-family: var(--sans);
1106    font-size: 2.3rem;
1107    font-weight: 700;
1108    color: var(--bright);
1109    letter-spacing: -0.01em;
1110    margin: 0.6rem 0 0.75rem;
1111  }
1112
1113  p { color: var(--muted); margin: 0 0 1.5rem; }
1114}
1115
1116@media (min-width: 1400px) {
1117  :root { --wrap: 1320px; }
1118}
1119
1120@media (max-width: 700px) {
1121  :root { --wrap: 100%; }
1122
1123  .topbar .context .sep:first-child, .topbar .context { font-size: var(--t-xs); }
1124  .footer .cols { grid-template-columns: 1fr; gap: 1.75rem; }
1125  .wrap { padding: 0 1rem; }
1126  main.wrap { padding-top: 1.25rem; }
1127
1128  .pagehead { flex-direction: column; align-items: stretch; gap: 0.75rem; }
1129
1130  .hunk .num { min-width: 2.25rem; }
1131  .difffile .diffhead { position: static; }
1132
1133  .repocard .meta { gap: 0.35rem 0.7rem; }
1134  .refs .subject, .tokens .subject { display: none; }
1135}
1136
1137// Home hero -----------------------------------------------------------------
1138//
1139// The same shape analytics, logging and status open with. Values are matched to
1140// their pages.scss rather than reinvented, since the point is that the four
1141// look like one suite.
1142
1143.hero {
1144  background: var(--sunken);
1145  border-bottom: 1px solid rgba(107, 158, 120, 0.3);
1146  padding: 4rem 0;
1147
1148  .hero-eyebrow {
1149    display: inline-flex;
1150    align-items: center;
1151    gap: 0.55rem;
1152    font-size: 0.72rem;
1153    font-weight: 600;
1154    letter-spacing: 0.12em;
1155    text-transform: uppercase;
1156    color: var(--warn);
1157    background: rgba(201, 168, 76, 0.16);
1158    border: 1px solid rgba(201, 168, 76, 0.5);
1159    padding: 0.35rem 0.75rem;
1160    border-radius: 999px;
1161  }
1162
1163  .eyebrow-dot {
1164    width: 6px;
1165    height: 6px;
1166    border-radius: 50%;
1167    background: var(--accent);
1168  }
1169
1170  .hero-title {
1171    font-family: var(--sans);
1172    font-size: clamp(2rem, 5vw, 3.2rem);
1173    font-weight: 700;
1174    line-height: 1.1;
1175    color: #ede8e0;
1176    letter-spacing: -0.01em;
1177    margin-top: 1.5rem;
1178
1179    .accent { color: var(--accent-lift); }
1180  }
1181
1182  .hero-sub {
1183    color: var(--muted);
1184    font-size: 1rem;
1185    line-height: 1.7;
1186    margin: 1.25rem 0 0;
1187    max-width: 620px;
1188  }
1189
1190  .hero-ctas {
1191    display: flex;
1192    gap: 0.75rem;
1193    flex-wrap: wrap;
1194    margin-top: 1.75rem;
1195
1196  }
1197}
1198
1199.stat-strip {
1200  padding: 1.5rem 0;
1201  border-bottom: 1px solid rgba(107, 158, 120, 0.3);
1202
1203  .stat-row {
1204    display: grid;
1205    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
1206    gap: 1.5rem;
1207  }
1208
1209  .stat { text-align: center; }
1210
1211  .stat-label {
1212    font-size: 0.66rem;
1213    font-weight: 600;
1214    letter-spacing: 0.12em;
1215    text-transform: uppercase;
1216    color: var(--faint);
1217  }
1218
1219  .stat-value {
1220    font-size: 1.75rem;
1221    font-weight: 700;
1222    color: var(--accent-lift);
1223    letter-spacing: -0.01em;
1224    line-height: 1.2;
1225    margin-top: 0.2rem;
1226    font-variant-numeric: tabular-nums;
1227  }
1228
1229  // A date is a longer string than a count and would otherwise set the row
1230  // height for the three tiles beside it.
1231  .stat-value-sm { font-size: 1.05rem; }
1232}