internal/web/static/style.css

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

1547 lines · 59801 bytes

   1/* gitbay stylesheet. Tokens first, on :root and again in the dark media
   2   query; components use tokens only. Two accents with separate jobs:
   3   blue is what you can do (links, primary buttons, focus, pressed
   4   toggles), orange is where you are and what wants you (current tab,
   5   rail counts, pending state, unverified signatures). Orange is never a
   6   button ground. internal/web/tokens_test.go measures every token;
   7   internal/web/classes_test.go checks every template class has a rule.
   8   No external requests: fonts are served from this origin. */
   9
  10@font-face {
  11  font-family: "Atkinson Hyperlegible Next";
  12  font-style: normal;
  13  font-weight: 400 700;
  14  font-display: swap;
  15  src: url(/static/fonts/atkinson-next-roman.woff2) format("woff2");
  16}
  17@font-face {
  18  font-family: "Atkinson Hyperlegible Next";
  19  font-style: italic;
  20  font-weight: 400 700;
  21  font-display: swap;
  22  src: url(/static/fonts/atkinson-next-italic.woff2) format("woff2");
  23}
  24@font-face {
  25  font-family: "Atkinson Hyperlegible Mono";
  26  font-style: normal;
  27  font-weight: 400 600;
  28  font-display: swap;
  29  src: url(/static/fonts/atkinson-mono-roman.woff2) format("woff2");
  30}
  31
  32:root {
  33  /* declare native light+dark support: correct form controls and
  34     scrollbars per scheme, and opt out of browser auto-darkening */
  35  color-scheme: light dark;
  36
  37  /* grounds: canvas, surface and inset are three steps, not one */
  38  --canvas: #ffffff;
  39  --surface: #ebedf1;
  40  --inset: #ffffff;
  41  --hover: #e1e4ea;
  42  --line: #8d939c;           /* 3.09:1 on canvas — a border you can see */
  43  --faint: #d8dce2;
  44
  45  /* ink */
  46  --fg: #1c1f24;
  47  --muted: #5a6270;
  48  --neutral: var(--muted);
  49
  50  /* blue: what you can do. --link is text, --fill is a ground; one blue
  51     cannot clear 4.5:1 as text and 3:1 as a ground in both schemes. */
  52  --link: #0033d6;
  53  --fill: #0000f0;
  54  --fill-fg: #ffffff;
  55  --focus: var(--link);
  56
  57  /* orange: where you are, what wants you. Two cuts because the floor
  58     differs by size: --mark for bars, --warn at text size. */
  59  --mark: #e4572e;
  60  --warn: #b8400f;
  61
  62  /* state */
  63  --ok: #0a7536;
  64  --bad: #c62828;
  65  --done: #6b21a8;
  66
  67  /* diff row tints: enough to scan, light enough that the syntax
  68     palette stays legible on them (TestSyntaxPaletteContrast) */
  69  --diff-add: #e4f6ea;
  70  --diff-del: #fdeaea;
  71
  72  /* the rail is black in both schemes: the one brand constant */
  73  --shell-bg: #000000;
  74  --shell-fg: #f2f2f2;
  75  --shell-muted: #8f8f8f;
  76  --shell-line: #1c1c1c;
  77  --shell-hover: #141414;
  78  --shell-mark: #ff6b3d;
  79
  80  /* the languages' own colours; the same in both schemes */
  81  --lang-go: #00add8;
  82  --lang-rust: #dea584;
  83  --lang-c: #555555;
  84  --lang-python: #3572a5;
  85  --lang-javascript: #f1e05a;
  86  --lang-typescript: #3178c6;
  87  --lang-shell: #89e051;
  88  --lang-ruby: #701516;
  89  --lang-java: #b07219;
  90  --lang-swift: #f05138;
  91  --lang-html: #e34c26;
  92  --lang-css: #563d7c;
  93  --lang-org: #77aa99;
  94  --lang-markdown: #083fa1;
  95  --lang-emacs-lisp: #c065db;
  96  --lang-nix: #7e7eff;
  97  --lang-sql: #e38c00;
  98
  99  --sans: "Atkinson Hyperlegible Next", -apple-system, BlinkMacSystemFont,
 100          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
 101  --mono: "Atkinson Hyperlegible Mono", ui-monospace, "SF Mono",
 102          SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
 103
 104  /* 12, 13, 14, 16, 20, 24, 32 */
 105  --fs-0: 0.75rem;
 106  --fs-1: 0.8125rem;
 107  --fs-2: 0.875rem;
 108  --fs-3: 1rem;
 109  --fs-4: 1.25rem;
 110  --fs-5: 1.5rem;
 111  --fs-6: 2rem;
 112
 113  /* 4, 8, 12, 16, 24, 32, 48 */
 114  --sp-1: 4px;
 115  --sp-2: 8px;
 116  --sp-3: 12px;
 117  --sp-4: 16px;
 118  --sp-5: 24px;
 119  --sp-6: 32px;
 120  --sp-7: 48px;
 121
 122  /* the rail: a column the width of one hit target, a row one tall */
 123  --rail-hit: 40px;
 124  --rail-strip-h: 48px;
 125  --rail-mark: 24px;
 126  --rail-mark-box: 32px;
 127
 128  --r-ctl: 4px;   /* controls and chips */
 129  --r-card: 6px;  /* cards, lists, code blocks */
 130  --shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
 131
 132  /* the native select arrow cannot be restyled, so draw our own;
 133     --chev carries the stroke colour per scheme */
 134  --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='%235a6270' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
 135}
 136@media (prefers-color-scheme: dark) {
 137  :root {
 138    --canvas: #101114;
 139    --surface: #212429;
 140    --inset: #0b0c0e;
 141    --hover: #2b2f36;
 142    --line: #61666f;
 143    --faint: #2f333a;
 144
 145    --fg: #e9eaec;
 146    --muted: #a3a9b3;
 147    --neutral: var(--muted);
 148
 149    --link: #8b9bff;
 150    --fill: #4d61f0;
 151    --fill-fg: #ffffff;
 152    --focus: var(--link);
 153
 154    --mark: #ff6b3d;
 155    --warn: #ff8a63;
 156
 157    --ok: #3fce7a;
 158    --bad: #ff6b6b;
 159    --done: #c084fc;
 160
 161    --diff-add: #0d2a18;
 162    --diff-del: #2c1113;
 163
 164    --shell-bg: #000000;
 165    --shell-fg: #f2f2f2;
 166    --shell-muted: #8f8f8f;
 167    --shell-line: #1c1c1c;
 168    --shell-hover: #141414;
 169    --shell-mark: #ff6b3d;
 170
 171    /* the languages' own colours; the same in both schemes */
 172    --lang-go: #00add8;
 173    --lang-rust: #dea584;
 174    --lang-c: #555555;
 175    --lang-python: #3572a5;
 176    --lang-javascript: #f1e05a;
 177    --lang-typescript: #3178c6;
 178    --lang-shell: #89e051;
 179    --lang-ruby: #701516;
 180    --lang-java: #b07219;
 181    --lang-swift: #f05138;
 182    --lang-html: #e34c26;
 183    --lang-css: #563d7c;
 184    --lang-org: #77aa99;
 185    --lang-markdown: #083fa1;
 186    --lang-emacs-lisp: #c065db;
 187    --lang-nix: #7e7eff;
 188    --lang-sql: #e38c00;
 189
 190    --shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
 191    --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='%23a3a9b3' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
 192  }
 193}
 194
 195/* ---- base ---- */
 196* { box-sizing: border-box; }
 197html { font-size: 16px; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
 198body {
 199  margin: 0;
 200  background: var(--canvas);
 201  color: var(--fg);
 202  font: var(--fs-3)/1.5 var(--sans);
 203  min-height: 100vh;
 204}
 205h1, h2, h3 { line-height: 1.25; font-weight: 600; }
 206h1 { font-size: var(--fs-5); margin: 0 0 var(--sp-3); text-wrap: balance; }
 207h2 { font-size: var(--fs-4); margin: var(--sp-6) 0 var(--sp-3); }
 208h3 { font-size: var(--fs-3); margin: var(--sp-5) 0 var(--sp-2); }
 209p { margin: 0 0 var(--sp-3); }
 210a { color: var(--link); text-decoration: none; }
 211a:hover { text-decoration: underline; }
 212/* a link inside running text is told apart by its underline: link and
 213   muted text are 1.07:1 apart in dark, and colour alone is not a cue
 214   (#232). Navigation, chips and buttons keep position as their cue. */
 215p a, .syscomment a { text-decoration: underline; }
 216/* a title or a path is the whole line: position is the cue */
 217p a.button, p a.btn, p a.chip, .repotitle a, p.title a, .pathbar a, .pager a { text-decoration: none; }
 218a.xref { color: var(--link); text-decoration: none; }
 219
 220code, pre, .mono, .code, td.mode, td.size {
 221  font-family: var(--mono);
 222  font-size: var(--fs-1);
 223}
 224.mono { overflow-wrap: anywhere; }
 225
 226/* ---- focus: one authored ring, so keyboard position is never the
 227   browser's guess ---- */
 228:focus-visible {
 229  outline: 2px solid var(--focus);
 230  outline-offset: 2px;
 231  border-radius: 1px;
 232}
 233/* the rail is black in both schemes and --focus is a dark blue in the
 234   light one — a ring nobody could see there */
 235.rail :focus-visible { outline-color: var(--shell-mark); }
 236
 237/* visually hidden, still read aloud */
 238.vh {
 239  position: absolute;
 240  width: 1px; height: 1px;
 241  margin: -1px; padding: 0; border: 0;
 242  clip-path: inset(50%);
 243  overflow: hidden;
 244  white-space: nowrap;
 245}
 246
 247/* ---- skip link: the rail runs ahead of the content in source order ---- */
 248a.skip {
 249  position: absolute;
 250  left: var(--sp-3); top: -3rem;
 251  z-index: 50;
 252  background: var(--fill);
 253  color: var(--fill-fg);
 254  padding: var(--sp-2) var(--sp-4);
 255  font-weight: 600;
 256}
 257a.skip:focus { top: var(--sp-3); text-decoration: none; }
 258
 259/* ---- rail: one row of glyphs across the top, no labels ----
 260   One strip the height of a hit target, at every width: fixed squares,
 261   no wrapping and no scrolling. Every item is a square link carrying an
 262   inline svg, its name in an aria-label and in a visually hidden span, so
 263   the nav reads the same to a screen reader as the old text list did. */
 264.rail {
 265  height: var(--rail-strip-h);
 266  background: var(--shell-bg);
 267  color: var(--shell-fg);
 268  border-bottom: 1px solid var(--shell-line);
 269  display: flex;
 270  flex-direction: row;
 271  align-items: center;
 272  padding: 0 var(--sp-1);
 273}
 274a.brand {
 275  display: flex;
 276  align-items: center;
 277  justify-content: center;
 278  flex: none;
 279  width: var(--rail-mark-box);
 280  height: var(--rail-strip-h);
 281  color: var(--shell-fg);
 282}
 283a.brand:hover { text-decoration: none; }
 284a.brand svg.mark { display: block; flex: none; width: var(--rail-mark); height: var(--rail-mark); }
 285
 286ul.raillist {
 287  list-style: none;
 288  margin: 0;
 289  padding: 0;
 290  display: flex;
 291  align-items: center;
 292  min-width: 0;
 293}
 294/* the spacer that holds settings, admin and the account cell at the far
 295   end of the row */
 296.railgap { flex: 1; }
 297.railicon {
 298  position: relative;
 299  display: flex;
 300  align-items: center;
 301  justify-content: center;
 302  flex: none;
 303  width: var(--rail-hit);
 304  height: var(--rail-strip-h);
 305  padding: 0;
 306  border: 0;
 307  background: none;
 308  color: var(--shell-fg);
 309  cursor: pointer;
 310}
 311.railicon:hover { background: var(--shell-hover); text-decoration: none; }
 312/* orange marks position along the bottom edge — the rail's only accent */
 313.railicon[aria-current] {
 314  background: var(--shell-hover);
 315  box-shadow: inset 0 -2px 0 var(--shell-mark);
 316}
 317.count {
 318  font-size: var(--fs-0);
 319  font-weight: 600;
 320  letter-spacing: 0;
 321  background: var(--shell-mark);
 322  color: var(--shell-bg);
 323  padding: 0 5px;
 324  border-radius: var(--r-ctl);
 325  margin-left: auto;
 326}
 327/* the unread count is a badge on the bell's corner, not a trailing number */
 328.railicon .count {
 329  position: absolute;
 330  top: 2px;
 331  right: 2px;
 332  margin: 0;
 333  padding: 0 3px;
 334  line-height: 1.35;
 335}
 336.railfoot {
 337  flex: none;
 338  display: flex;
 339  align-items: center;
 340  min-width: 0;
 341}
 342.railfoot a { color: var(--shell-fg); }
 343.railfoot form { margin: 0; }
 344a.railuser {
 345  display: flex;
 346  align-items: center;
 347  justify-content: center;
 348  flex: none;
 349  width: var(--rail-hit);
 350  height: var(--rail-strip-h);
 351}
 352a.railuser:hover { text-decoration: none; }
 353a.railuser .avatar { width: var(--rail-mark); height: var(--rail-mark); }
 354.avatar {
 355  display: inline-grid;
 356  place-items: center;
 357  width: 22px; height: 22px;
 358  flex: none;
 359  border-radius: 50%;
 360  background: var(--fill);
 361  color: var(--fill-fg);
 362  font-size: var(--fs-0);
 363  font-weight: 600;
 364}
 365
 366/* ---- shell: the rail above, then the pane, which fills the rest of the
 367   viewport so the footer sits at the bottom of a short page ---- */
 368.shell { display: flex; flex-direction: column; min-height: 100vh; }
 369.pane { flex: 1; min-width: 0; display: flex; flex-direction: column; }
 370main.content {
 371  flex: 1;
 372  width: 100%;
 373  padding: var(--sp-5) var(--sp-6) var(--sp-7);
 374}
 375main.wide { max-width: none; }
 376main.reading { max-width: calc(72rem + 2 * var(--sp-6)); }
 377main.bounded { max-width: calc(48rem + 2 * var(--sp-6)); }
 378footer {
 379  width: 100%;
 380  padding: var(--sp-4) var(--sp-6);
 381  border-top: 1px solid var(--faint);
 382  color: var(--muted);
 383  font-size: var(--fs-1);
 384}
 385footer p { margin: 0; }
 386footer a { color: var(--muted); text-decoration: underline; }
 387footer a:hover { color: var(--link); }
 388
 389/* ---- repository header ---- */
 390.repohead {
 391  padding: var(--sp-4) var(--sp-6) 0;
 392  border-bottom: 1px solid var(--line);
 393}
 394.identity { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
 395.grow { flex: 1; }
 396/* h1 on the repo home, p elsewhere so each page keeps its own h1 — but
 397   identical in size, because the tabs sit below and navigation must not
 398   move when you use it */
 399.repotitle {
 400  margin: 0;
 401  font-size: var(--fs-4);
 402  font-weight: 600;
 403  line-height: 1.25;
 404}
 405.repotitle a { color: var(--fg); }
 406.repotitle a.owner { color: var(--muted); font-weight: 400; }
 407.repotitle a:hover { color: var(--link); text-decoration: none; }
 408.repotitle .sep { color: var(--muted); margin: 0 2px; font-weight: 400; }
 409.repodesc {
 410  margin: var(--sp-2) 0 0;
 411  color: var(--fg);
 412  font-size: var(--fs-2);
 413  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
 414}
 415.repometa { margin: var(--sp-1) 0 0; color: var(--muted); font-size: var(--fs-1); }
 416.toggles { margin: var(--sp-2) 0 0; color: var(--muted); font-size: var(--fs-1); }
 417
 418nav.tabs {
 419  display: flex;
 420  gap: var(--sp-1);
 421  margin-top: var(--sp-3);
 422  overflow-x: auto;
 423  /* with overflow-y left visible the browser computes it to auto, which
 424     is a vertical drag on touch; the strip scrolls sideways only */
 425  overflow-y: hidden;
 426  scrollbar-width: none;
 427}
 428nav.tabs::-webkit-scrollbar { display: none; }
 429nav.tabs a {
 430  display: inline-flex;
 431  align-items: center;
 432  gap: var(--sp-1);
 433  padding: var(--sp-2) var(--sp-3) 10px;
 434  color: var(--muted);
 435  font-size: var(--fs-2);
 436  white-space: nowrap;
 437  border-bottom: 2px solid transparent;
 438  margin-bottom: -1px;
 439}
 440nav.tabs a:hover { color: var(--fg); text-decoration: none; }
 441nav.tabs a[aria-current] { color: var(--fg); font-weight: 600; border-bottom-color: var(--mark); }
 442/* a count in a tab is plain metadata, not a badge */
 443nav.tabs a i { font-style: normal; color: var(--muted); margin-left: 4px; }
 444
 445/* ---- page heads ---- */
 446.pagehead, .listhead, .headrow {
 447  display: flex;
 448  align-items: center;
 449  gap: var(--sp-3);
 450  flex-wrap: wrap;
 451  margin-bottom: var(--sp-5);
 452}
 453.pagehead h1, .listhead h1, .headrow h1, .listhead h2, .headrow h2 { margin: 0; }
 454.pagehead .grow, .listhead .spacer, .headrow .spacer { flex: 1; }
 455.issuetitle { margin: 0 0 var(--sp-2); font-size: var(--fs-5); }
 456.issuenumber { color: var(--muted); font-weight: 400; }
 457.issuemeta { color: var(--muted); font-size: var(--fs-2); margin: 0 0 var(--sp-4); }
 458.commithead p { margin: var(--sp-1) 0; }
 459.commithead h2 { margin-top: 0; margin-bottom: var(--sp-1); }
 460
 461nav.filters { display: inline-flex; gap: var(--sp-2); flex-wrap: wrap; }
 462nav.filters a {
 463  display: inline-flex;
 464  align-items: center;
 465  height: 32px;
 466  padding: 0 var(--sp-3);
 467  background: var(--canvas);
 468  border: 1px solid var(--line);
 469  border-radius: var(--r-ctl);
 470  color: var(--fg);
 471  font-size: var(--fs-2);
 472  font-weight: 500;
 473}
 474nav.filters a:hover { background: var(--hover); text-decoration: none; }
 475nav.filters a.active { background: var(--surface); border-color: var(--link); color: var(--link); }
 476
 477form.searchform, form.logfilter, form.compareform {
 478  display: flex;
 479  align-items: center;
 480  gap: var(--sp-2);
 481  flex-wrap: wrap;
 482  margin: 0 0 var(--sp-4);
 483}
 484form.searchform input[type="search"], form.searchform input[type="text"], form.logfilter input { flex: 1; min-width: 12rem; max-width: 32rem; }
 485form.searchform.compact { margin: 0; }
 486form.searchform.compact input[type="search"], form.searchform.compact input[type="text"] { min-width: 18rem; }
 487form.compareform label { display: inline-flex; align-items: center; gap: var(--sp-2); margin: 0; }
 488
 489/* ---- buttons: one family, 32px tall, so a row of them lines up ---- */
 490button, .button {
 491  display: inline-flex;
 492  align-items: center;
 493  justify-content: center;
 494  gap: 6px;
 495  height: 32px;
 496  padding: 0 var(--sp-3);
 497  font: inherit;
 498  font-size: var(--fs-2);
 499  font-weight: 500;
 500  border: 1px solid transparent;
 501  border-radius: var(--r-ctl);
 502  cursor: pointer;
 503  text-decoration: none;
 504  white-space: nowrap;
 505  /* a bare <button> is the primary action of its form group */
 506  background: var(--fill);
 507  color: var(--fill-fg);
 508}
 509button:hover, .button.primary:hover { filter: brightness(1.12); text-decoration: none; }
 510button.btn, .button.btn {
 511  background: var(--canvas);
 512  color: var(--fg);
 513  border-color: var(--line);
 514  filter: none;
 515}
 516button.btn:hover, .button.btn:hover { background: var(--hover); filter: none; text-decoration: none; }
 517button.btn[aria-pressed="true"] { background: var(--surface); color: var(--link); border-color: var(--link); }
 518button.linklike {
 519  background: none;
 520  border: 0;
 521  padding: 0;
 522  height: auto;
 523  color: var(--link);
 524  font-weight: 400;
 525  filter: none;
 526}
 527button.linklike:hover { text-decoration: underline; filter: none; }
 528button.danger, .button.danger {
 529  background: var(--canvas);
 530  color: var(--bad);
 531  border-color: var(--bad);
 532  filter: none;
 533}
 534/* --canvas, not --fill-fg: white on the dark scheme's --bad is 2.3:1 */
 535button.danger:hover, .button.danger:hover { background: var(--bad); color: var(--canvas); filter: none; }
 536button:disabled { opacity: 0.55; cursor: default; filter: none; }
 537.btngroup { display: inline-flex; gap: var(--sp-2); flex-wrap: wrap; }
 538form.inline { display: inline; }
 539.act { text-align: right; }
 540
 541/* ---- forms ---- */
 542/* not button: it sets its own colour above, and this rule comes later at
 543   the same specificity */
 544input, textarea, select { font: inherit; color: inherit; }
 545input[type="text"], input[type="search"], input[type="email"],
 546input[type="password"], input[type="number"], input:not([type]), textarea, select {
 547  background: var(--inset);
 548  color: var(--fg);
 549  border: 1px solid var(--line);
 550  border-radius: var(--r-ctl);
 551  padding: 0 10px;
 552  height: 32px;
 553  font-size: var(--fs-2);
 554  line-height: 1.4;
 555}
 556textarea {
 557  width: 100%;
 558  height: auto;
 559  padding: 8px 10px;
 560  resize: vertical;
 561  line-height: 1.5;
 562}
 563textarea[name="content"] { font-family: var(--mono); font-size: var(--fs-1); }
 564select {
 565  appearance: none;
 566  padding-right: 1.9rem;
 567  background-image: var(--chev);
 568  background-repeat: no-repeat;
 569  background-position: right 0.6rem center;
 570  background-size: 0.62rem;
 571  cursor: pointer;
 572}
 573input:hover, textarea:hover, select:hover { border-color: var(--muted); }
 574input[type="radio"] { accent-color: var(--fill); }
 575label { display: block; font-weight: 500; font-size: var(--fs-2); margin-bottom: 4px; }
 576label:has(> input[type="radio"]), label:has(> input[type="checkbox"]),
 577label:has(> select) { display: inline-flex; align-items: center; gap: var(--sp-2); }
 578.fieldname { display: block; font-size: var(--fs-2); font-weight: 500; }
 579.hint { display: block; color: var(--muted); font-size: var(--fs-1); font-weight: 400; margin: 0 0 6px; }
 580.field { margin-bottom: var(--sp-4); }
 581.field input[type="text"], .field input[type="email"], .field select { width: 100%; }
 582.check { display: flex; align-items: center; gap: var(--sp-2); font-weight: 400; }
 583::placeholder { color: var(--muted); opacity: 1; }
 584::selection { background: var(--fill); color: var(--fill-fg); }
 585/* :user-invalid, not :invalid — a required field is invalid the moment
 586   the page loads, and colouring it red before anyone has typed is a
 587   scolding, not a hint */
 588input:user-invalid, textarea:user-invalid { border-color: var(--bad); }
 589input[name="confirm"] { width: auto; margin-right: var(--sp-2); }
 590
 591/* A radio keeps the native control: a circle takes one answer, a square
 592   takes any number, and that shape survives greyscale and colour
 593   blindness. The checkbox is drawn so it matches the rest of the family. */
 594input[type="checkbox"] {
 595  appearance: none;
 596  flex: none;
 597  width: 16px;
 598  height: 16px;
 599  margin: 0;
 600  /* an empty box has nothing but its border to announce it */
 601  border: 1px solid var(--muted);
 602  border-radius: var(--r-ctl);
 603  background: var(--inset);
 604  cursor: pointer;
 605}
 606input[type="checkbox"]:not(:checked):hover { border-color: var(--fg); }
 607input[type="checkbox"]:checked {
 608  background: var(--fill);
 609  border-color: var(--fill);
 610  /* the mark sits on the blue ground, so it is white in both schemes */
 611  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 10'%3E%3Cpath d='M1 5l3.4 3.4L11 1.4' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
 612  background-repeat: no-repeat;
 613  background-position: center;
 614  background-size: 11px;
 615}
 616
 617/* a segmented control for a small, mutually exclusive set: real radios
 618   underneath, so arrow keys and screen readers behave as they always did */
 619fieldset.segmented { border: 0; margin: 0 0 var(--sp-4); padding: 0; }
 620fieldset.segmented legend { padding: 0; margin-bottom: var(--sp-2); color: var(--muted); font-size: var(--fs-2); }
 621fieldset.segmented .options { display: inline-flex; }
 622fieldset.segmented label { gap: 0; margin: 0; }
 623fieldset.segmented input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
 624fieldset.segmented span {
 625  display: flex;
 626  align-items: center;
 627  height: 32px;
 628  padding: 0 var(--sp-4);
 629  border: 1px solid var(--line);
 630  font-size: var(--fs-2);
 631  cursor: pointer;
 632}
 633fieldset.segmented label + label span { border-left: 0; }
 634fieldset.segmented label:first-child span { border-radius: var(--r-ctl) 0 0 var(--r-ctl); }
 635fieldset.segmented label:last-child span { border-radius: 0 var(--r-ctl) var(--r-ctl) 0; }
 636fieldset.segmented span:hover { border-color: var(--muted); }
 637fieldset.segmented input:checked + span {
 638  background: var(--fill);
 639  border-color: var(--fill);
 640  color: var(--fill-fg);
 641  font-weight: 600;
 642}
 643fieldset.segmented input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 2px; }
 644
 645p.branchpick { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
 646p.branchpick label { color: var(--muted); font-size: var(--fs-2); margin: 0; }
 647p.branchpick select { flex: 1 1 12rem; }
 648
 649form.signupform, form.editform { max-width: 40rem; }
 650form.signupform label, form.editform label { margin-bottom: 4px; }
 651.editform textarea { width: 100%; }
 652.editform input[name="message"] { width: 100%; }
 653
 654/* A previewed draft, above the textarea it came from. The orange edge is
 655   "where you are and what wants you": this is not saved yet. */
 656.preview {
 657  margin: var(--sp-4) 0;
 658  max-width: 48rem;
 659  background: var(--surface);
 660  border: 1px solid var(--line);
 661  border-left: 3px solid var(--mark);
 662  border-radius: var(--r-card);
 663}
 664.preview > .previewmark {
 665  margin: 0;
 666  padding: var(--sp-2) var(--sp-4);
 667  border-bottom: 1px solid var(--line);
 668  color: var(--warn);
 669  font-size: var(--fs-1);
 670}
 671.preview > .rendered { padding: var(--sp-3) var(--sp-4); }
 672.preview > .rendered > :first-child { margin-top: 0; }
 673.preview > .rendered > :last-child { margin-bottom: 0; }
 674.preview > .rendered:empty::before { content: "nothing to preview"; color: var(--muted); }
 675
 676form.commentform { margin: var(--sp-4) 0; max-width: 48rem; }
 677form.commentform p:last-child { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: 0; }
 678
 679details.editbox { margin: var(--sp-2) 0; max-width: 48rem; }
 680details.editbox > summary {
 681  display: inline-flex;
 682  align-items: center;
 683  height: 32px;
 684  padding: 0 var(--sp-3);
 685  background: var(--canvas);
 686  border: 1px solid var(--line);
 687  border-radius: var(--r-ctl);
 688  color: var(--fg);
 689  font-size: var(--fs-2);
 690  font-weight: 500;
 691  cursor: pointer;
 692  list-style: none;
 693}
 694details.editbox > summary::-webkit-details-marker { display: none; }
 695details.editbox > summary:hover { background: var(--hover); }
 696details.editbox[open] > summary { margin-bottom: var(--sp-2); }
 697details.editbox input[type="text"] { width: 100%; }
 698
 699/* ---- settings: one row per control, label then input then its own
 700   button. The name stays setform because the templates carry it. ---- */
 701form.setform {
 702  display: grid;
 703  grid-template-columns: 14rem minmax(0, 28rem) auto;
 704  gap: var(--sp-4);
 705  align-items: start;
 706  padding: var(--sp-3) 0;
 707  border-bottom: 1px solid var(--faint);
 708}
 709form.setform label { margin-top: 6px; }
 710form.setform .hint { margin: 2px 0 0; }
 711form.setform input[type="text"], form.setform input[type="number"], form.setform select { width: 100%; }
 712/* the third column takes the leftover width; the button keeps its own */
 713form.setform > button, form.setform > .btngroup { justify-self: start; }
 714form.setform.stack { grid-template-columns: 1fr; }
 715form.setform.stack textarea, form.setform.stack select { width: 100%; max-width: 48rem; }
 716nav.sections { display: flex; gap: var(--sp-4); flex-wrap: wrap; font-size: var(--fs-2); margin-bottom: var(--sp-5); }
 717ul.protlist { list-style: none; margin: var(--sp-2) 0; padding: 0; }
 718ul.protlist li {
 719  display: flex;
 720  align-items: center;
 721  gap: var(--sp-3);
 722  padding: var(--sp-2) 0;
 723  border-bottom: 1px solid var(--faint);
 724}
 725ul.protlist li:last-child { border-bottom: 0; }
 726ul.protlist form { margin-left: auto; }
 727ul.plain { list-style: none; margin: 0 0 var(--sp-3); padding: 0; }
 728ul.plain li { padding: var(--sp-1) 0; display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
 729
 730/* ---- messages: .error and .notice are one family. The names stay
 731   because e2e tests match class="error". ---- */
 732.error, .notice {
 733  border-left: 3px solid var(--bad);
 734  background: color-mix(in srgb, var(--bad) 6%, transparent);
 735  color: var(--fg);
 736  border-radius: 0 var(--r-ctl) var(--r-ctl) 0;
 737  padding: var(--sp-2) var(--sp-3);
 738  margin: 0 0 var(--sp-4);
 739  font-size: var(--fs-2);
 740}
 741.notice { border-left-color: var(--ok); background: color-mix(in srgb, var(--ok) 6%, transparent); }
 742.empty-note, .none, .empty, li.empty, td.empty { color: var(--muted); }
 743
 744/* ---- containers: one recipe for cards, lists and tables ---- */
 745.card, ul.list, ul.loglist, ul.repolist, ul.issuelist,
 746ul.milestonelist, .readme, .code, article.release, .blame, .teambody {
 747  background: var(--surface);
 748  border: 1px solid var(--line);
 749  border-radius: var(--r-card);
 750  overflow: hidden;
 751}
 752.cardhead {
 753  display: flex;
 754  align-items: center;
 755  gap: var(--sp-3);
 756  padding: var(--sp-2) var(--sp-4);
 757  border-bottom: 1px solid var(--line);
 758  font-size: var(--fs-1);
 759  color: var(--muted);
 760}
 761.cardhead b { color: var(--fg); font-weight: 500; }
 762.cardbody { padding: var(--sp-4) var(--sp-5); }
 763ul.list { list-style: none; margin: 0 0 var(--sp-4); padding: 0; }
 764ul.list li { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--faint); }
 765ul.list li:last-child { border-bottom: 0; }
 766ul.list li:hover { background: var(--hover); }
 767
 768table { border-collapse: collapse; width: 100%; font-size: var(--fs-2); }
 769th {
 770  text-align: left;
 771  font-weight: 500;
 772  font-size: var(--fs-1);
 773  color: var(--muted);
 774  padding: 6px var(--sp-4);
 775  border-bottom: 1px solid var(--line);
 776}
 777td { padding: 7px var(--sp-4); border-bottom: 1px solid var(--faint); vertical-align: top; }
 778tr:last-child td { border-bottom: 0; }
 779tbody tr:hover td { background: var(--hover); }
 780/* every header row a template writes, by the class it or its table
 781   carries: TestHeaderRowsAreLeftAligned reads these selectors */
 782tr.cols th, table.tree th, table.refs th, table.keys th, table.assets th { text-align: left; }
 783tr.cols th { background: var(--canvas); }
 784/* right-aligned columns keep their header with their values */
 785tr.cols th.age, tr.cols th.size { text-align: right; }
 786/* wide listings scroll inside their own box; the page never does. The
 787   wrapper is the scroller only — the table inside carries the card. */
 788.tablewrap { overflow-x: auto; max-width: 100%; }
 789
 790table.tree, table.refs {
 791  background: var(--surface);
 792  border: 1px solid var(--line);
 793  border-radius: var(--r-card);
 794  /* collapsed borders defeat a radius on the table itself */
 795  border-collapse: separate;
 796  border-spacing: 0;
 797  overflow: hidden;
 798  margin-bottom: var(--sp-4);
 799}
 800table.tree tr:last-child td, table.refs tr:last-child td { border-bottom: 0; }
 801table.tree tr:hover td, table.refs tr:hover td { background: var(--hover); }
 802td.name a { color: var(--fg); }
 803td.name a:hover { color: var(--link); }
 804table.tree td.name { width: 25%; white-space: nowrap; }
 805table.tree td.name.dir a { color: var(--link); }
 806table.tree th.lastcommit, table.tree td.lastcommit { width: 55%; }
 807table.tree td.lastcommit {
 808  max-width: 0;
 809  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
 810}
 811table.tree td.lastcommit a {
 812  color: var(--muted);
 813  display: block;
 814  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
 815}
 816table.tree td.lastcommit a:hover { color: var(--link); }
 817table.tree th.age, table.tree td.age { width: 20%; }
 818td.age, th.age { text-align: right; white-space: nowrap; color: var(--muted); font-variant-numeric: tabular-nums; }
 819td.size, td.mode { color: var(--muted); white-space: nowrap; }
 820table.tree th.size, table.tree td.size { text-align: right; }
 821table.refs td.name { width: 100%; }
 822table.refs td.sha, td.sha { color: var(--muted); }
 823
 824/* these tables sit flush with the page text: no outer border, and the
 825   header row drops the ground and the left padding */
 826table.keys, table.assets { background: none; border: 0; border-radius: 0; }
 827table.keys th, table.assets th, table.keys tr.cols th { background: transparent; padding-left: 0; }
 828table.keys td { padding-left: 0; }
 829table.keys td.act, table.assets td.size { text-align: right; }
 830/* The account list types a username to confirm, which is longer than
 831   the key prefixes the confirm field is sized for elsewhere. */
 832table.accounts input[name="confirm"] { width: 11rem; }
 833table.accounts form.actions { display: inline-flex; gap: var(--sp-2); margin: 0 var(--sp-2) var(--sp-2) 0; }
 834table.assets td.name { width: 100%; font-family: var(--mono); font-size: var(--fs-1); }
 835table.assets { margin-top: var(--sp-2); }
 836
 837/* the tip commit is the first row of the file table */
 838tr.tipbar td {
 839  background: var(--surface);
 840  padding: var(--sp-3) var(--sp-4);
 841  border-bottom: 1px solid var(--line);
 842  max-width: 0;
 843}
 844.tipbar .tip {
 845  display: flex;
 846  align-items: center;
 847  gap: var(--sp-2);
 848  flex-wrap: wrap;
 849  min-width: 0;
 850  font-size: var(--fs-2);
 851}
 852.tipbar .who { font-weight: 600; }
 853.tipbar .subject { color: var(--fg); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
 854.tipbar .subject:hover { color: var(--link); }
 855.tipbar .spacer { flex: 1; }
 856.tipbar .age { color: var(--muted); white-space: nowrap; }
 857
 858.readme { margin-top: var(--sp-5); }
 859.readme .cardbody { max-width: 78ch; }
 860/* until every card wraps its body in .cardbody, the rendered block is
 861   the body */
 862.readme > .rendered { padding: var(--sp-4) var(--sp-5); }
 863.code { background: var(--inset); padding: var(--sp-3) var(--sp-4); overflow-x: auto; }
 864.code pre { margin: 0; background: transparent !important; border: 0; padding: 0; }
 865pre.bigcode, .bigcode {
 866  font-family: var(--mono);
 867  /* the 404 numeral is a picture of a number, not body type */
 868  font-size: 4rem;
 869  color: var(--faint);
 870  -webkit-text-stroke: 1px var(--line);
 871  margin: 0;
 872  line-height: 1;
 873}
 874.notfound { text-align: center; padding: var(--sp-6) 0; }
 875.notfound h1 { margin-top: var(--sp-3); }
 876
 877ul.loglist { list-style: none; margin: var(--sp-3) 0; padding: 0; }
 878ul.loglist li {
 879  display: flex;
 880  align-items: baseline;
 881  gap: var(--sp-3);
 882  padding: var(--sp-3) var(--sp-4);
 883  border-bottom: 1px solid var(--faint);
 884}
 885ul.loglist li:last-child { border-bottom: 0; }
 886ul.loglist li:hover { background: var(--hover); }
 887ul.loglist p { margin: 0; }
 888ul.loglist .commitmain { flex: 1 1 auto; min-width: 0; }
 889ul.loglist .subject a { color: var(--fg); font-weight: 500; }
 890ul.loglist .subject a:hover { color: var(--link); }
 891ul.loglist .commitside { flex: none; display: flex; gap: var(--sp-2); align-items: center; white-space: nowrap; }
 892
 893ul.repolist { list-style: none; margin: var(--sp-3) 0 var(--sp-5); padding: 0; }
 894ul.repolist li { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--faint); }
 895ul.repolist li:last-child { border-bottom: 0; }
 896ul.repolist li:hover { background: var(--hover); }
 897ul.repolist p { margin: 0; }
 898ul.repolist .reponame { font-size: var(--fs-3); }
 899ul.repolist .reponame a { color: var(--fg); }
 900ul.repolist .reponame a strong { color: var(--link); font-weight: 600; }
 901ul.repolist .reponame .sep { color: var(--muted); margin: 0 2px; }
 902ul.repolist .desc { margin-top: 2px; }
 903ul.repolist .topics, ul.repolist .meta { margin-top: var(--sp-1); }
 904
 905/* pinned repos: a compact wrap of names, no description or meta */
 906ul.pinlist { list-style: none; margin: var(--sp-3) 0 var(--sp-5); padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-2); }
 907ul.pinlist li {
 908  background: var(--surface);
 909  border: 1px solid var(--line);
 910  border-radius: var(--r-ctl);
 911  padding: var(--sp-1) var(--sp-3);
 912}
 913ul.pinlist li:hover { background: var(--hover); }
 914ul.pinlist li a { color: var(--fg); }
 915ul.pinlist li a:hover { color: var(--link); text-decoration: none; }
 916ul.pinlist .sep { color: var(--muted); margin: 0 2px; }
 917
 918ul.issuelist { list-style: none; margin: var(--sp-3) 0; padding: 0; }
 919ul.issuelist li {
 920  display: flex;
 921  align-items: baseline;
 922  gap: var(--sp-3);
 923  padding: var(--sp-3) var(--sp-4);
 924  border-bottom: 1px solid var(--faint);
 925}
 926ul.issuelist li:last-child { border-bottom: 0; }
 927ul.issuelist li:hover { background: var(--hover); }
 928ul.issuelist li.empty { display: block; }
 929ul.issuelist p { margin: 0; }
 930ul.issuelist .issuemain { flex: 1 1 auto; min-width: 0; }
 931ul.issuelist .issueside { display: flex; gap: var(--sp-2); align-items: center; flex: none; }
 932ul.issuelist .title a { color: var(--fg); font-weight: 500; }
 933ul.issuelist .title a:hover { color: var(--link); }
 934
 935ul.milestonelist { list-style: none; margin: var(--sp-3) 0; padding: 0; }
 936ul.milestonelist li { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--faint); }
 937ul.milestonelist li:last-child { border-bottom: 0; }
 938ul.milestonelist li:hover { background: var(--hover); }
 939ul.milestonelist p { margin: 0; }
 940ul.milestonelist .msmain { min-width: 0; }
 941ul.milestonelist .title { font-weight: 500; }
 942.progress {
 943  height: 6px;
 944  max-width: 24rem;
 945  margin-top: var(--sp-2);
 946  background: var(--faint);
 947  border-radius: var(--r-ctl);
 948  overflow: hidden;
 949}
 950.progress .bar { height: 100%; background: var(--ok); }
 951
 952article.release { padding: var(--sp-4); margin: var(--sp-4) 0; }
 953.releasehead { background: none; border: 0; padding: 0; }
 954.releasehead h2 { margin: 0 0 var(--sp-1); font-size: var(--fs-3); }
 955.releasehead .meta { margin: 0 0 var(--sp-2); }
 956
 957ul.matchlist { list-style: none; margin: var(--sp-3) 0; padding: 0; }
 958ul.matchlist li { margin-bottom: var(--sp-3); }
 959.matchpath { font-family: var(--mono); font-size: var(--fs-1); }
 960pre.matchline {
 961  background: var(--inset);
 962  border: 1px solid var(--line);
 963  border-radius: var(--r-card);
 964  padding: var(--sp-1) var(--sp-3);
 965  margin: var(--sp-1) 0 0;
 966  overflow-x: auto;
 967}
 968pre.matchline mark { background: color-mix(in srgb, var(--mark) 25%, transparent); color: inherit; border-radius: 2px; }
 969p.pager { margin-top: var(--sp-4); }
 970.snippetfile { margin-bottom: var(--sp-5); }
 971p.filefacts { color: var(--muted); font-size: var(--fs-1); margin: 0 0 var(--sp-3); }
 972pre.buildlog { max-height: 40rem; overflow: auto; }
 973
 974/* ---- rendered prose ---- */
 975pre {
 976  background: var(--inset);
 977  border: 1px solid var(--line);
 978  border-radius: var(--r-card);
 979  padding: var(--sp-3) var(--sp-4);
 980  margin: 0 0 var(--sp-4);
 981  overflow-x: auto;
 982  font-size: var(--fs-2);
 983  line-height: 1.6;
 984}
 985code {
 986  background: var(--inset);
 987  border: 1px solid var(--faint);
 988  border-radius: var(--r-ctl);
 989  padding: 0 0.3em;
 990}
 991pre code { background: none; border: 0; padding: 0; font-size: inherit; }
 992code.fullsha { color: var(--muted); overflow-wrap: anywhere; }
 993pre.message {
 994  white-space: pre-wrap;
 995  overflow-wrap: anywhere;
 996}
 997.rendered { max-width: 100%; overflow-wrap: anywhere; }
 998.rendered a { text-decoration: underline; }
 999.prose, .rendered > p, .rendered > ul, .rendered > ol, .rendered > blockquote { max-width: 78ch; }
1000.rendered blockquote { border-left: 3px solid var(--line); margin-left: 0; padding-left: var(--sp-4); color: var(--muted); }
1001.rendered img { max-width: 100%; }
1002.rendered h1, .rendered h2 { border-bottom: 1px solid var(--faint); padding-bottom: var(--sp-1); }
1003.rendered table { border-collapse: collapse; margin: var(--sp-3) 0; display: block; max-width: 100%; overflow-x: auto; }
1004.rendered th, .rendered td {
1005  border: 1px solid var(--line);
1006  padding: var(--sp-1) var(--sp-3);
1007  text-align: left;
1008  overflow-wrap: normal; /* scroll the table, don't shatter words */
1009}
1010.rendered th { background: var(--surface); font-weight: 600; }
1011.rendered tr:last-child td { border-bottom: 1px solid var(--line); }
1012/* GFM task lists: the box sits in the line, sized to the prose */
1013.rendered li input[type="checkbox"] { width: 0.9em; height: 0.9em; margin: 0 0.35em 0 0; vertical-align: -0.05em; background-size: 0.7em; }
1014.rendered li:has(> input[type="checkbox"]) { list-style: none; margin-left: -1.2em; }
1015.blobimage { text-align: center; }
1016.blobimage img { max-width: 100%; border: 1px solid var(--line); border-radius: var(--r-card); background: var(--surface); }
1017
1018/* pinned repositories, on the dashboard now that the rail is icons only */
1019.pinned { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-4); }
1020.pinned .owner { color: var(--muted); }
1021
1022/* ---- two-column: conversation and aside ---- */
1023.withaside { display: grid; grid-template-columns: minmax(0, 1fr) 18rem; gap: var(--sp-6); align-items: start; }
1024.withaside .mainside { min-width: 0; }
1025aside.aside { font-size: var(--fs-2); }
1026.aside .grp { border-top: 1px solid var(--line); padding: var(--sp-3) 0; }
1027.aside .grp:first-child { border-top: 0; padding-top: 0; }
1028.aside h2 {
1029  margin: 0 0 var(--sp-2);
1030  font-size: var(--fs-0);
1031  font-weight: 500;
1032  letter-spacing: 0.08em;
1033  text-transform: uppercase;
1034  color: var(--muted);
1035}
1036.aside .row { display: flex; align-items: center; gap: 6px; margin: 0 0 var(--sp-1); flex-wrap: wrap; }
1037.aside .row:last-child { margin-bottom: 0; }
1038/* a row's second line: when it happened, under what it happened to */
1039.aside .row .sub { flex-basis: 100%; padding-left: 14px; color: var(--muted); font-size: var(--fs-1); }
1040.aside .row:has(.sub) { margin-bottom: var(--sp-2); }
1041.aside .none { color: var(--muted); }
1042.dot { display: inline-block; width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--neutral); margin-right: 2px; vertical-align: middle; }
1043.dot.ok { background: var(--ok); }
1044.dot.bad { background: var(--bad); }
1045.dot.pend { background: var(--mark); }
1046.ok { color: var(--ok); }
1047.bad { color: var(--bad); }
1048form.actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-2); }
1049form.actions button { flex: 1 1 auto; }
1050form.actions select, form.actions textarea { width: 100%; }
1051.feedline { margin-bottom: var(--sp-2); }
1052/* the dashboard's activity feed is a section after the queues, one column */
1053.feed { margin-top: var(--sp-6); max-width: 78ch; }
1054.feed h2 { margin-bottom: var(--sp-3); }
1055.feed .feedline { font-size: var(--fs-2); }
1056.feed .none { color: var(--muted); font-size: var(--fs-1); }
1057
1058/* ---- comments and threads ---- */
1059article.comment {
1060  max-width: 48rem;
1061  border: 1px solid var(--line);
1062  border-radius: var(--r-card);
1063  margin: var(--sp-4) 0;
1064  overflow: hidden;
1065}
1066article.comment .commenthead {
1067  display: flex;
1068  gap: var(--sp-2);
1069  flex-wrap: wrap;
1070  background: var(--surface);
1071  border-bottom: 1px solid var(--line);
1072  padding: var(--sp-2) var(--sp-4);
1073  margin: 0;
1074  font-size: var(--fs-1);
1075  color: var(--muted);
1076}
1077article.comment .commenthead b { color: var(--fg); font-weight: 500; }
1078article.comment .commenthead .when { color: var(--muted); }
1079article.comment .rendered { padding: var(--sp-3) var(--sp-4); }
1080article.comment .rendered > :first-child { margin-top: 0; }
1081article.comment .rendered > :last-child { margin-bottom: 0; }
1082a.authorlink { color: var(--fg); font-weight: 500; }
1083a.authorlink:hover { color: var(--link); }
1084
1085.syscomment {
1086  max-width: 48rem;
1087  color: var(--muted);
1088  font-size: var(--fs-1);
1089  margin: 0 0 var(--sp-4) var(--sp-3);
1090  padding: var(--sp-2) 0 var(--sp-2) var(--sp-4);
1091  border-left: 2px solid var(--faint);
1092}
1093.syscomment p { display: inline; margin: 0; }
1094
1095.thread {
1096  border: 1px solid var(--faint);
1097  border-left: 3px solid var(--link);
1098  border-radius: var(--r-ctl);
1099  padding: var(--sp-2) var(--sp-4);
1100  margin: var(--sp-2) 0 var(--sp-2) var(--sp-6);
1101}
1102.thread.resolved { border-left-color: var(--ok); opacity: 0.75; }
1103/* an unsubmitted comment is the viewer's own note, not the conversation */
1104.thread.pending { border-left-color: var(--neutral); border-left-style: dashed; }
1105.thread.stale { border-left-color: var(--warn); }
1106.thread.composing { border-left-color: var(--mark); }
1107.thread:target { outline: 2px solid var(--mark); outline-offset: 2px; }
1108.thread p.commenthead { font-size: var(--fs-2); margin: var(--sp-2) 0 0; }
1109.thread .when { color: var(--muted); }
1110.thread .rendered p { margin: var(--sp-1) 0; }
1111.thread .threadstate { color: var(--muted); font-size: var(--fs-1); margin: var(--sp-1) 0 0; }
1112.thread details.threadreply { margin: var(--sp-2) 0 0; }
1113.thread details.threadreply > summary { color: var(--link); font-size: var(--fs-1); cursor: pointer; }
1114.thread textarea { width: 100%; }
1115.thread.composing p, .thread details.threadreply p { margin: var(--sp-2) 0 0; }
1116form.threadact { margin: var(--sp-1) 0 0; padding: 0 var(--sp-3) var(--sp-2); }
1117
1118nav.subtabs {
1119  display: flex;
1120  gap: var(--sp-4);
1121  border-bottom: 1px solid var(--line);
1122  margin: 0 0 var(--sp-4);
1123}
1124nav.subtabs a {
1125  display: inline-flex;
1126  align-items: center;
1127  gap: var(--sp-1);
1128  padding: var(--sp-2) 0 10px;
1129  color: var(--muted);
1130  font-size: var(--fs-2);
1131  border-bottom: 2px solid transparent;
1132  margin-bottom: -1px;
1133}
1134nav.subtabs a:hover { color: var(--fg); text-decoration: none; }
1135nav.subtabs a[aria-current] { color: var(--fg); font-weight: 600; border-bottom-color: var(--mark); }
1136nav.subtabs a i { font-style: normal; color: var(--muted); margin-left: 4px; }
1137
1138/* ---- diffs and code ---- */
1139p.diffstat { color: var(--muted); font-size: var(--fs-2); margin: 0 0 var(--sp-3); }
1140p.diffstat .add { color: var(--ok); }
1141p.diffstat .del { color: var(--bad); }
1142
1143details.difffold {
1144  border: 1px solid var(--line);
1145  border-radius: var(--r-card);
1146  margin: 0 0 var(--sp-3);
1147  background: var(--inset);
1148  overflow: hidden;
1149}
1150details.difffold summary {
1151  display: flex;
1152  align-items: baseline;
1153  gap: var(--sp-3);
1154  padding: var(--sp-2) var(--sp-3);
1155  background: var(--surface);
1156  font-size: var(--fs-2);
1157  cursor: pointer;
1158  list-style: none;
1159}
1160details.difffold[open] summary { border-bottom: 1px solid var(--line); }
1161details.difffold summary::-webkit-details-marker { display: none; }
1162/* flex summaries lose the native disclosure marker; draw our own */
1163details.difffold summary::before { content: "\25b8"; color: var(--muted); }
1164details.difffold[open] summary::before { content: "\25be"; }
1165details.difffold summary:hover { background: var(--hover); }
1166details.difffold summary .fpath { font-family: var(--mono); overflow-wrap: anywhere; }
1167details.difffold summary .fpath .was { color: var(--muted); }
1168details.difffold summary .fstat { margin-left: auto; font-family: var(--mono); white-space: nowrap; }
1169details.difffold summary .add { color: var(--ok); }
1170details.difffold summary .del { color: var(--bad); }
1171details.difffold > .none { padding: var(--sp-3); margin: 0; }
1172details.difffold .tablewrap { background: none; border: 0; border-radius: 0; }
1173
1174table.difftable {
1175  border-collapse: collapse;
1176  width: 100%;
1177  font-family: var(--mono);
1178  font-size: var(--fs-1);
1179  line-height: 1.5;
1180}
1181table.difftable td { border: 0; padding: 0; vertical-align: top; font-size: inherit; }
1182table.difftable tbody tr:hover td { background: none; }
1183table.difftable td.ln {
1184  width: 1%;
1185  min-width: 2.5rem;
1186  padding: 0 var(--sp-2);
1187  text-align: right;
1188  color: var(--muted);
1189  user-select: none;
1190  border-right: 1px solid var(--line);
1191  white-space: nowrap;
1192}
1193/* not .code: that class carries its own ground, which painted over the
1194   row tints */
1195table.difftable td.src { padding: 0 var(--sp-3); white-space: pre-wrap; overflow-wrap: anywhere; }
1196/* the marker is decoration, so it lives in CSS and stays out of a copied
1197   selection */
1198table.difftable tr.add td.src::before { content: "+"; color: var(--ok); }
1199table.difftable tr.del td.src::before { content: "\2212"; color: var(--bad); }
1200table.difftable tr.ctx td.src::before { content: " "; }
1201table.difftable tr.add { background: var(--diff-add); }
1202table.difftable tr.del { background: var(--diff-del); }
1203table.difftable tr.hunk td, table.difftable tr.dmeta td {
1204  color: var(--muted);
1205  padding: var(--sp-1) var(--sp-3);
1206  background: var(--surface);
1207  border-top: 1px solid var(--line);
1208  border-bottom: 1px solid var(--line);
1209}
1210table.difftable tr.hunk td.src { color: var(--link); }
1211table.difftable tr.threadrow td { padding: var(--sp-2) var(--sp-3); background: var(--canvas); }
1212/* a line number is the handle for commenting on that line; it stays a
1213   plain number until pointed at, so the gutter is not a wall of links */
1214table.difftable td.ln a.cmt { color: inherit; text-decoration: none; }
1215table.difftable td.ln a.cmt:hover,
1216table.difftable td.ln a.cmt:focus { color: var(--link); text-decoration: underline; }
1217/* A linked line: f2-n17 on a diff, L17 on a file (see issue 118). */
1218.difftable tr:target td, .code .line:has(a:target) { background: color-mix(in srgb, var(--mark) 18%, transparent); }
1219.difftable tr:target td.ln, .code .line:has(a:target) .ln { border-left: 3px solid var(--mark); }
1220/* chroma writes the highlighted spans; the container only supplies the
1221   ground and the face */
1222.chroma { font-family: var(--mono); background: none; }
1223/* chroma's own LineLink rule is dropped from the served palette: it set
1224   outline: none and hid the focus ring. This is that rule without it, on
1225   a 24px box so a line number is a target and not a glyph (#232) */
1226.chroma .lnlinks { display: inline-block; min-width: 24px; min-height: 24px; line-height: 24px; text-decoration: none; color: inherit; }
1227.chroma .line { line-height: 24px; }
1228
1229.blamehunk { display: flex; gap: var(--sp-3); border-top: 1px solid var(--line); align-items: flex-start; }
1230.blamehunk:first-child { border-top: 0; }
1231.blameinfo { flex: none; width: 17rem; min-width: 0; padding: var(--sp-2) var(--sp-3); }
1232.blameinfo .subject { margin: 0; font-size: var(--fs-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
1233.blameinfo .meta { margin: 0; font-size: var(--fs-1); color: var(--muted); }
1234.blamecode {
1235  flex: 1;
1236  margin: 0;
1237  padding: var(--sp-2) var(--sp-3) var(--sp-2) 0;
1238  background: var(--inset);
1239  border: 0;
1240  border-left: 1px solid var(--line);
1241  border-radius: 0;
1242  overflow-x: auto;
1243  align-self: stretch;
1244}
1245.lineno {
1246  display: inline-block;
1247  min-width: 3.5em;
1248  padding-right: 1em;
1249  text-align: right;
1250  color: var(--muted);
1251  user-select: none;
1252}
1253
1254/* ---- chips and badges ---- */
1255.chip, .badge {
1256  --chip: var(--neutral);
1257  display: inline-block;
1258  padding: 1px 8px;
1259  border-radius: var(--r-ctl);
1260  font-size: var(--fs-0);
1261  font-weight: 500;
1262  line-height: 1.5;
1263  color: var(--chip);
1264  border: 1px solid color-mix(in srgb, var(--chip) 40%, transparent);
1265  background: color-mix(in srgb, var(--chip) 10%, var(--canvas));
1266  white-space: nowrap;
1267  vertical-align: middle;
1268}
1269.chip-open { --chip: var(--ok); }
1270.chip-closed { --chip: var(--bad); }
1271.chip-merged, .chip-done { --chip: var(--done); }
1272.chip-neutral, .chip-source_gone { --chip: var(--neutral); }
1273.chip-stale { --chip: var(--warn); }
1274.chip.topic { --chip: var(--link); }
1275.chip.topic:hover { text-decoration: none; background: color-mix(in srgb, var(--chip) 18%, transparent); }
1276/* a label carries its own colour inline, from the label's hex */
1277.chip.label { font-weight: 500; }
1278.badge-verified { --chip: var(--ok); }
1279.badge-unsigned { --chip: var(--neutral); }
1280.badge-signed_unknown_key, .badge-signed_key_expired { --chip: var(--warn); }
1281.badge-signed_email_mismatch, .badge-signed_key_revoked, .badge-bad_signature { --chip: var(--bad); }
1282.badge.check-success, .chip.check-success { --chip: var(--ok); }
1283.badge.check-pending, .chip.check-pending,
1284.badge.check-running, .chip.check-running { --chip: var(--warn); }
1285.badge.check-failure, .chip.check-failure,
1286.badge.check-error, .chip.check-error { --chip: var(--bad); }
1287.badge.check-cancelled, .chip.check-cancelled,
1288.badge.check-skipped, .chip.check-skipped { --chip: var(--neutral); }
1289span.check-success { color: var(--ok); }
1290span.check-pending, span.check-running { color: var(--warn); }
1291span.check-failure, span.check-error { color: var(--bad); }
1292
1293a.memberchip {
1294  display: inline-block;
1295  border: 1px solid var(--line);
1296  border-radius: var(--r-ctl);
1297  padding: 1px 8px;
1298  margin: 0 2px 2px 0;
1299  color: var(--fg);
1300  font-size: var(--fs-1);
1301}
1302a.memberchip:hover { text-decoration: none; border-color: var(--link); color: var(--link); }
1303a.memberchip .role { color: var(--muted); }
1304
1305.pathbar { display: flex; align-items: center; gap: var(--sp-2) var(--sp-3); margin: 0 0 var(--sp-3); flex-wrap: wrap; font-size: var(--fs-2); }
1306.pathbar .spacer { flex: 1; }
1307.pathbar .actions { display: flex; gap: var(--sp-2); }
1308/* history · blame · raw were 21px tall and "raw" 22px wide (#232) */
1309.pathbar .actions a { display: inline-block; padding: 6px 4px; }
1310.pathbar .acts { display: flex; gap: var(--sp-2); }
1311.crumbs { color: var(--muted); }
1312.crumbs a { color: var(--link); }
1313.crumbs strong { color: var(--fg); }
1314.refchip {
1315  display: inline-flex;
1316  align-items: center;
1317  gap: 6px;
1318  height: 32px;
1319  padding: 0 10px;
1320  background: var(--canvas);
1321  border: 1px solid var(--line);
1322  border-radius: var(--r-ctl);
1323  font-family: var(--mono);
1324  font-size: var(--fs-2);
1325  font-weight: 500;
1326  color: var(--fg);
1327}
1328details.refmenu { position: relative; }
1329details.refmenu summary { cursor: pointer; list-style: none; }
1330details.refmenu summary::-webkit-details-marker { display: none; }
1331details.refmenu summary::after { content: " \25be"; color: var(--muted); }
1332details.refmenu .refdrop {
1333  position: absolute;
1334  z-index: 10;
1335  top: calc(100% + 4px);
1336  left: 0;
1337  min-width: 12rem;
1338  max-height: 20rem;
1339  overflow-y: auto;
1340  background: var(--canvas);
1341  border: 1px solid var(--line);
1342  border-radius: var(--r-card);
1343  box-shadow: var(--shadow);
1344  padding: var(--sp-1) 0;
1345}
1346details.refmenu .refdrop a {
1347  display: block;
1348  padding: var(--sp-1) var(--sp-3);
1349  color: var(--fg);
1350  font-family: var(--mono);
1351  font-size: var(--fs-1);
1352}
1353details.refmenu .refdrop a:hover { background: var(--hover); text-decoration: none; }
1354details.refmenu .refdrop a.allrefs {
1355  color: var(--link);
1356  font-family: var(--sans);
1357  border-top: 1px solid var(--faint);
1358  margin-top: var(--sp-1);
1359}
1360
1361/* ---- repository overview layout ---- */
1362.overview { display: block; }
1363.overviewmain { min-width: 0; }
1364/* the side column exists only above 62rem; below it .facts keeps its
1365   own two-up layout and the 40rem factgrid rule applies untouched */
1366@media (min-width: 62.01rem) {
1367  .overview.withfacts { display: grid; grid-template-columns: minmax(0, 1fr) 18rem; gap: var(--sp-6); align-items: start; }
1368  .overview.withfacts .facts { display: block; margin-top: 0; max-width: none; }
1369  .overview.withfacts .facts .factgrid { grid-template-columns: repeat(2, auto); }
1370  .overview.withfacts .clone pre { white-space: pre-wrap; word-break: break-all; }
1371}
1372
1373/* ---- repository facts ---- */
1374.facts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5); margin: var(--sp-5) 0 var(--sp-4); max-width: 72rem; }
1375.facts h2 {
1376  margin: 0 0 var(--sp-2);
1377  font-size: var(--fs-1);
1378  font-weight: 500;
1379  letter-spacing: 0.08em;
1380  text-transform: uppercase;
1381  color: var(--muted);
1382}
1383.clone { margin: 0 0 var(--sp-3); }
1384.facts .about { min-width: 0; margin-bottom: var(--sp-5); }
1385.clone .fieldname { font-size: var(--fs-1); color: var(--muted); font-weight: 500; margin-bottom: 2px; }
1386.clone pre { margin-bottom: var(--sp-3); user-select: all; }
1387.factgrid { display: grid; grid-template-columns: repeat(4, auto); gap: var(--sp-2) var(--sp-4); font-size: var(--fs-2); margin-bottom: var(--sp-3); }
1388.factgrid b { font-weight: 600; }
1389.factgrid a { color: var(--fg); }
1390.factgrid a:hover { color: var(--link); }
1391.counts { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); margin: 0 0 var(--sp-3); font-size: var(--fs-2); }
1392.counts a { color: var(--fg); }
1393.counts a:hover { color: var(--link); }
1394.counts strong { font-weight: 600; }
1395.fact { color: var(--muted); }
1396.langbar { display: flex; height: 8px; margin: 0 0 var(--sp-2); border-radius: var(--r-ctl); overflow: hidden; gap: 1px; background: var(--faint); }
1397.langbar .lang { display: block; height: 100%; min-width: 2px; }
1398.langs { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); margin: 0 0 var(--sp-3); font-size: var(--fs-1); color: var(--muted); }
1399.langs .lang-name { display: inline-flex; align-items: center; gap: var(--sp-1); }
1400.langs .dot { width: 8px; height: 8px; }
1401/* named where it reads as the language's own colour, neutral otherwise */
1402.lang { background: var(--neutral); }
1403.lang-go { background: var(--lang-go); }
1404.lang-rust { background: var(--lang-rust); }
1405.lang-c, .lang-c- { background: var(--lang-c); }
1406.lang-python { background: var(--lang-python); }
1407.lang-javascript { background: var(--lang-javascript); }
1408.lang-typescript { background: var(--lang-typescript); }
1409.lang-shell { background: var(--lang-shell); }
1410.lang-ruby { background: var(--lang-ruby); }
1411.lang-java { background: var(--lang-java); }
1412.lang-swift { background: var(--lang-swift); }
1413.lang-html { background: var(--lang-html); }
1414.lang-css { background: var(--lang-css); }
1415.lang-org { background: var(--lang-org); }
1416.lang-markdown { background: var(--lang-markdown); }
1417.lang-emacs-lisp { background: var(--lang-emacs-lisp); }
1418.lang-nix { background: var(--lang-nix); }
1419.lang-sql { background: var(--lang-sql); }
1420.contribs { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-1) var(--sp-3); margin: 0; font-size: var(--fs-1); }
1421.contribs .label { color: var(--muted); }
1422.teambody { padding: var(--sp-3); }
1423.teambody .memberchip { margin-right: var(--sp-2); }
1424
1425/* ---- landing ---- */
1426/* the width class on main carries this too; the cap here keeps the page
1427   readable on the templates that do not set one yet */
1428.landing { max-width: 48rem; padding: var(--sp-6) 0; }
1429.landing h1 { font-size: var(--fs-6); display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-3); }
1430.landing h1 .mark { width: 32px; height: 32px; }
1431.lede { font-size: var(--fs-4); color: var(--muted); line-height: 1.5; max-width: 40rem; margin: 0 0 var(--sp-5); }
1432pre.quickstart { margin: 0 0 var(--sp-4); }
1433.shot { border: 1px solid var(--line); border-radius: var(--r-card); overflow: hidden; margin: var(--sp-5) 0; }
1434.shot img { display: block; width: 100%; height: auto; max-height: 420px; object-fit: cover; object-position: top; }
1435.facets { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-5); margin: var(--sp-5) 0; }
1436.facets h2 { font-size: var(--fs-3); margin: 0 0 var(--sp-1); }
1437.facets p { color: var(--muted); font-size: var(--fs-2); margin: 0; }
1438.routes { display: flex; gap: var(--sp-3); align-items: center; margin: var(--sp-4) 0 0; }
1439
1440/* ---- profile ---- */
1441.profilehead { border-bottom: 1px solid var(--faint); padding-bottom: var(--sp-4); margin-bottom: var(--sp-4); }
1442.profilehead h1 { margin: 0 0 var(--sp-1); }
1443.profilehead .lede { font-size: var(--fs-3); margin: 0 0 var(--sp-1); }
1444.profilehead .meta { margin: var(--sp-1) 0 0; }
1445.activity { margin-bottom: var(--sp-5); }
1446h2 .count { background: none; color: var(--muted); font-weight: 400; font-size: var(--fs-2); margin-left: var(--sp-2); padding: 0; }
1447h2.empty { color: var(--muted); font-weight: 500; font-size: var(--fs-3); margin: var(--sp-2) 0; }
1448/* 53 week columns x 7 day rows, tinted with the link blue */
1449.actgraph-scroll { overflow-x: auto; padding-bottom: var(--sp-1); }
1450.actgraph { display: flex; gap: 3px; width: max-content; padding-top: 18px; }
1451.actweek { display: flex; flex-direction: column; gap: 3px; position: relative; }
1452.actmonth { position: absolute; top: -16px; left: 0; font-size: var(--fs-0); color: var(--muted); }
1453.actday { width: 11px; height: 11px; border-radius: 2px; background: var(--faint); }
1454.actday.pad { background: transparent; }
1455.actday.l0 { background: var(--faint); }
1456.actday.l1 { background: color-mix(in srgb, var(--link) 25%, var(--canvas)); }
1457.actday.l2 { background: color-mix(in srgb, var(--link) 50%, var(--canvas)); }
1458.actday.l3 { background: color-mix(in srgb, var(--link) 75%, var(--canvas)); }
1459.actday.l4 { background: var(--link); }
1460.actlegend { display: flex; align-items: center; gap: 3px; margin-top: var(--sp-2); font-size: var(--fs-0); color: var(--muted); }
1461.actlegend span:first-child { margin-right: var(--sp-1); }
1462.actlegend span:last-child { margin-left: var(--sp-1); }
1463
1464/* ---- wiki ---- */
1465.wikilayout { display: flex; gap: var(--sp-5); align-items: flex-start; }
1466.wikipage { flex: 1; min-width: 0; }
1467.wikinav { flex: none; width: 14rem; }
1468.wikinav ul { list-style: none; margin: var(--sp-1) 0 var(--sp-4); padding: 0; }
1469.wikinav li a {
1470  display: block;
1471  padding: 5px var(--sp-2);
1472  border-radius: var(--r-ctl);
1473  color: var(--fg);
1474  font-size: var(--fs-2);
1475}
1476.wikinav li a:hover { background: var(--hover); color: var(--fg); text-decoration: none; }
1477.wikinav li a.active { background: var(--surface); color: var(--link); font-weight: 500; }
1478
1479/* ---- misc ---- */
1480.meta { color: var(--muted); font-size: var(--fs-1); }
1481.muted { color: var(--muted); }
1482.desc, td.desc { color: var(--muted); }
1483.spacer { flex: 1; }
1484.compact { margin: 0; }
1485.name { min-width: 0; }
1486svg.icon { vertical-align: -0.125em; }
1487.sep { color: var(--muted); }
1488.owner { color: var(--muted); }
1489.title { margin: 0; }
1490.subject { min-width: 0; }
1491.sha { font-family: var(--mono); }
1492.when { color: var(--muted); }
1493.who { font-weight: 500; }
1494.was { color: var(--muted); }
1495.role { color: var(--muted); }
1496.age { color: var(--muted); }
1497.size { color: var(--muted); }
1498.review { font-size: var(--fs-2); }
1499
1500/* ---- breakpoints ---- */
1501@media (max-width: 62rem) {
1502  /* one column, the aside after the thread: a phone shows the
1503     description first, checks and reviewers after it (#232) */
1504  .withaside { grid-template-columns: 1fr; }
1505}
1506
1507@media (max-width: 52rem) {
1508  main.content { padding: var(--sp-4) var(--sp-4) var(--sp-5); }
1509  footer { padding: var(--sp-4); }
1510  .repohead { padding: var(--sp-3) var(--sp-4) 0; }
1511  /* seven tabs do not fit a phone in one row; a hidden scrollbar made the
1512     ones past the edge look absent. Two rows show all of them. */
1513  nav.tabs { flex-wrap: wrap; overflow: visible; }
1514  .facts { grid-template-columns: 1fr; }
1515}
1516
1517@media (max-width: 40rem) {
1518  .facets { grid-template-columns: 1fr; gap: var(--sp-4); }
1519  .wikilayout { flex-direction: column; align-items: stretch; }
1520  .wikinav { width: auto; }
1521  form.setform { grid-template-columns: 1fr; gap: var(--sp-2); }
1522  form.setform label { margin-top: 0; }
1523  /* the commit subject is the widest thing in a file table and the one
1524     column a phone can do without: the tipbar above already names the
1525     latest commit */
1526  table.tree td.lastcommit, table.tree th.lastcommit { display: none; }
1527  table.tree td.mode, table.tree th.mode { display: none; }
1528  /* at 320px a nowrap name plus the age column overran the card by the
1529     cell padding and the card clipped the age; a long name wraps (#232) */
1530  table.tree td.name { white-space: normal; overflow-wrap: anywhere; }
1531  .clone pre { white-space: pre-wrap; word-break: break-all; }
1532  .pathbar { overflow-wrap: anywhere; }
1533  .readme .cardbody, .code { padding: var(--sp-3); }
1534  .thread { margin-left: var(--sp-3); }
1535  .blamehunk { flex-direction: column; gap: 0; }
1536  .blameinfo { width: auto; }
1537  .blamecode { border-left: 0; padding-left: var(--sp-3); width: 100%; }
1538  .factgrid { grid-template-columns: repeat(2, auto); }
1539  ul.loglist li { flex-wrap: wrap; }
1540  ul.loglist .commitside { width: 100%; justify-content: flex-start; }
1541}
1542
1543/* eleven squares at 40px overrun a phone; 32px keeps the row whole and
1544   the 48px height keeps the target big enough to hit */
1545@media (max-width: 30rem) {
1546  :root { --rail-hit: 32px; }
1547}