/* trendrepo.dev. Two themes share every rule; only the variables differ.
   Solar is for night use: red, orange and amber only. No white, gray, blue, cyan, green or
   purple may appear in it, including browser defaults (focus rings, checkboxes, scrollbars). */

:root,
[data-theme="dark"] {
  --bg: #0d1117;
  --panel: #11161d;
  --raised: #161c24;
  --line: #222a34;
  --text: #e6edf3;
  --muted: #a7b1bb;
  --faint: #7f8a95;
  --gain: #3fb950;
  --slow: #f0605a;
  /* Brand teal, the logo's tile. As text on --bg it is 8.46:1; filled controls carry dark text
     (--on-accent), 8.46:1 on it. */
  --accent: #19c2b0;
  --fill: #19c2b0;
  --star: #e3b341;
  --on-accent: #0d1117;
  --sel: rgba(25, 194, 176, 0.1);
  --dim-bar: #3a4450;
  --heat-max: 28%;
  --heat-sel-max: 55%;
  color-scheme: dark;
}

[data-theme="solar"] {
  --bg: #0e0803;
  --panel: #140b04;
  --raised: #1b0f05;
  --line: #3a2210;
  --text: #f7ab3c;
  --muted: #d48d3c;
  --faint: #b07432;
  --gain: #ff8a1a;
  --slow: #e0352b;
  --accent: #ffb000;
  --fill: #ffb000;
  --star: #ffb000;
  --on-accent: #1a0e00;
  --sel: rgba(255, 176, 0, 0.08);
  --dim-bar: #5a3412;
  --heat-max: 28%;
  --heat-sel-max: 35%;
  color-scheme: dark;
}

* { box-sizing: border-box; }

/* Everything renders 30% larger, like browser zoom at 130%. Media query widths cannot read
   this, so each breakpoint below is its unzoomed width times 1.3 (1100 → 1430, 700 → 910), and
   viewport units are divided by it. */
:root { --zoom: 1.3; }
body { zoom: var(--zoom); }

html { background: var(--bg); scrollbar-color: var(--line) var(--bg); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

::selection { background: var(--fill); color: var(--on-accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
a { color: inherit; }

.num, .speed, .count, .rank-mono {
  font-family: ui-monospace, "Cascadia Mono", "SF Mono", Consolas, monospace;
  font-variant-numeric: tabular-nums;
}

/* Header */
.top {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 12px 24px;
  border-bottom: 1px solid var(--line);
}
/* Logo and wordmark. The tile takes the theme's fill (teal, or amber in Solar) and the letter is
   cut out in the page colour, so Solar shows the one-colour amber logo. */
.brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.logo { flex: none; display: block; }
.logo-tile { fill: var(--fill); }
.logo-ink { fill: var(--bg); }
.wordmark { font: 600 21px/1 ui-monospace, "Cascadia Mono", "SF Mono", Consolas, monospace; letter-spacing: -0.02em; }
.wordmark .tld { color: var(--muted); }
[data-theme="solar"] .wordmark { color: var(--accent); }
.search { margin-left: auto; }
.search input {
  width: 320px;
  padding: 8px 12px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--text);
  font: inherit;
}
.search input::placeholder { color: var(--faint); }
.theme { display: flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.theme button {
  padding: 7px 14px;
  background: transparent;
  border: 0;
  color: var(--muted);
  font: inherit;
  cursor: pointer;
}
.theme button[aria-pressed="true"] { background: var(--fill); color: var(--on-accent); }

/* Layout */
.layout { display: grid; grid-template-columns: 196px minmax(0, 1fr); min-height: calc(100vh / var(--zoom) - 58px); }
main { padding: 0 16px 24px; min-width: 0; }

/* Filter rail */
.rail { border-right: 1px solid var(--line); padding: 16px 20px; }
.rail-head { display: flex; align-items: baseline; justify-content: space-between; }
.rail h2 { margin: 0 0 8px; font-size: 15px; }
.clear { color: var(--accent); text-decoration: none; font-size: 13px; }
.rail fieldset { border: 0; padding: 0; margin: 0 0 18px; }
.rail legend { padding: 0; margin-bottom: 6px; color: var(--muted); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
.check { display: flex; align-items: center; gap: 8px; padding: 3px 0; cursor: pointer; }
.check .label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.check .count { color: var(--muted); font-size: 12px; }
.check input {
  appearance: none;
  width: 15px;
  height: 15px;
  margin: 0;
  flex: none;
  border: 1px solid var(--faint);
  border-radius: 3px;
  background: transparent;
  display: grid;
  place-content: center;
}
.check input:checked { background: var(--fill); border-color: var(--fill); }
.check input:checked::after {
  content: "";
  width: 8px;
  height: 4px;
  border: 2px solid var(--on-accent);
  border-top: 0;
  border-right: 0;
  transform: translate(0, -1px) rotate(-45deg);
}
.rail details summary { color: var(--accent); cursor: pointer; padding: 4px 0; font-size: 13px; list-style: none; }
.rail details summary::-webkit-details-marker { display: none; }
.apply { margin-top: 8px; padding: 6px 12px; background: var(--fill); color: var(--on-accent); border: 0; border-radius: 6px; font: inherit; }

/* Title bar */
.bar { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 16px; padding: 16px 0 10px; }
.bar h1 { margin: 0; font-size: 20px; white-space: nowrap; }
.caption { margin: 0 0 12px; color: var(--muted); max-width: 110ch; }
.updated { margin: 0 0 0 auto; color: var(--muted); font-size: 13px; white-space: nowrap; }
/* The main view shows no title (the h1 stays for screen readers); its update time ends the
   controls row instead, next to Columns. */
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
/* On the main view the heading scrolls away above the stuck header, so the controls row starts
   it and needs room at the top. */
.sticky-head > .controls:first-child { padding-top: 12px; }
.controls .updated + .cols { margin-left: 0; }

/* Table */
/* clip, not auto: a scrolling wrapper would pin the sticky header to itself instead of the page. */
.scroll { overflow: clip; border: 1px solid var(--line); border-radius: 8px; }
table.rank { width: 100%; border-collapse: collapse; }
/* Own header only: the detail row's .wins table sits inside this one and must not stick. */
table.rank > thead th {
  position: sticky;
  top: var(--head-h, 0px);
  z-index: 1;
  background: var(--panel);
  color: var(--muted);
  font-weight: 600;
  font-size: 13px;
  text-align: left;
  padding: 10px 4px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.rank th.num { text-align: right; }
/* Two-word headers wrap, so their columns are only as wide as the numbers under them; the width
   saved goes to a gap between number columns, which otherwise read as one run of text
   ("30d Above pace Momentum"). Headers sit on the bottom line when some wrap. */
table.rank > thead th { vertical-align: bottom; }
table.rank > thead th.above, table.rank > thead th.speed { white-space: normal; }
@media (min-width: 911px) {
  table.rank > thead th.num:not(:first-child),
  table.rank > tbody > tr.row > td.num:not(.rank), table.rank > tbody > tr.row > td.speed { padding-left: 10px; }
}
.rank th a { text-decoration: none; display: block; }
.rank th.sortable a:hover { color: var(--text); }
.rank th.active { color: var(--text); }
.rank th.sel { background: var(--fill); color: var(--on-accent); }
.rank th.sel a:hover { color: var(--on-accent); }
.arrow { font-family: system-ui, sans-serif; }

.rank td { padding: 8px 4px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.rank tbody tr.row:hover { background: var(--raised); }
.rank tbody tr.row.open { background: var(--raised); }
.rank td.num { text-align: right; white-space: nowrap; font-size: 13px; }
.rank td.rank { color: var(--muted); width: 44px; font-size: 20px; font-weight: 700; }
.rank td.stars { color: var(--text); }

/* The repo column takes whatever width the visible number columns leave (max-width: 0 lets
   the description ellipsis work inside an auto-width cell). */
.rank td.repo { width: 100%; max-width: 0; min-width: 180px; font-family: Verdana, Geneva, sans-serif; }
.rank th.repo { min-width: 180px; font-family: Verdana, Geneva, sans-serif; }
.expand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--text);
  font: inherit;
  font-weight: 600;
  font-size: 14.5px;
  text-align: left;
  cursor: pointer;
}
.expand:hover .name { text-decoration: underline; }
.desc, .meta { margin: 2px 0 0; }
.desc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.desc { color: var(--muted); font-size: 13px; }
.desc .none { color: var(--faint); }
.meta { color: var(--faint); font-size: 12px; }

/* Window cells: shaded by gain within the column; the selected window is stronger. The caps
   (--heat-max, --heat-sel-max) keep text at 4.5:1 or more at full heat, on --bg and --raised. */
.heat {
  color: var(--text);
  background: color-mix(in srgb, var(--gain) calc(var(--heat) * var(--heat-max)), transparent);
}
.heat.sel { background: color-mix(in srgb, var(--gain) calc(var(--heat) * var(--heat-sel-max)), transparent); font-weight: 600; }
.heat small { display: block; font-size: 10px; line-height: 1; }

/* Right-aligned like its header and the other number columns. */
.speed { white-space: nowrap; font-weight: 600; text-align: right; }
.above { font-weight: 600; }
.momentum { color: var(--text); }
.above.pos { color: var(--gain); }
.above.neg { color: var(--slow); }
.speed.up { color: var(--gain); }
.speed.flat { color: var(--text); }
.speed.down { color: var(--slow); }
.speed.new { color: var(--accent); }
.speed.none { color: var(--faint); font-weight: 400; }

td.bars { width: 106px; }
.strip { display: block; }
.strip .b { fill: var(--gain); }
.strip .d { fill: var(--dim-bar); }
.strip .base { stroke: var(--line); stroke-width: 1; }

.empty { padding: 40px; text-align: center; color: var(--muted); }

/* Row detail */
tr.detail > td, .card-detail { background: var(--panel); padding: 16px 20px 20px; }
.detail-grid { display: grid; grid-template-columns: minmax(0, 1fr) 440px; gap: 28px; }
.detail h3 { margin: 0 0 4px; font-size: 15px; overflow-wrap: anywhere; }
.detail .sub { margin: 0 0 10px; color: var(--muted); font-size: 13px; }
.chart { width: 100%; height: 170px; display: block; }
.chart .b { fill: var(--gain); }
.chart .today { fill: var(--gain); opacity: 0.55; }
.chart .loss { fill: var(--slow); }
.chart .grid { stroke: var(--line); stroke-dasharray: 3 3; }
.chart text { fill: var(--muted); font-size: 11px; font-family: ui-monospace, Consolas, monospace; }
.wins { width: 100%; border-collapse: collapse; }
.wins th, .wins td { padding: 6px 8px; border-bottom: 1px solid var(--line); text-align: right; }
.wins th:first-child, .wins td:first-child { text-align: left; }
.wins th { color: var(--muted); font-weight: 600; font-size: 12px; white-space: nowrap; }
.wins tr.sel td { background: var(--sel); }
/* Row detail's main action: a filled button, opens GitHub in a new tab. */
.gh {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding: 9px 16px;
  background: var(--fill);
  color: var(--on-accent);
  border-radius: 6px;
  font-weight: 600;
  text-decoration: none;
}
.gh:hover { filter: brightness(1.12); color: var(--on-accent); }
.gh:active { filter: brightness(0.95); }
.loading { color: var(--muted); }
.retry { margin-left: 6px; padding: 4px 10px; background: none; border: 1px solid var(--line); border-radius: 6px; color: var(--accent); font: inherit; cursor: pointer; }
.retry:hover { border-color: var(--accent); }
/* Cells rendered only for phone cards: columns the browser turned off (page.ts visibleColumns). */
@media (min-width: 911px) { .card-only { display: none; } }
/* A filter change that takes a moment dims the list until the new one arrives. */
main[aria-busy="true"] { opacity: 0.55; cursor: progress; transition: opacity 0.15s; }

/* Pager and notes */
.pager { display: flex; align-items: center; justify-content: space-between; padding: 14px 2px; color: var(--muted); }
.pages { display: flex; align-items: center; gap: 12px; }
.btn { padding: 6px 14px; border: 1px solid var(--line); border-radius: 6px; text-decoration: none; color: var(--text); }
.btn.off { color: var(--faint); }
.note { color: var(--faint); font-size: 12.5px; margin: 0; }

@media (max-width: 1430px) {
  .scroll { overflow-x: auto; }
  .layout { grid-template-columns: 1fr; }
  .search input { width: 200px; }
  .detail-grid { grid-template-columns: minmax(0, 1fr); }
}

/* Row detail text */
.detail .about { margin: 0 0 16px; max-width: 72ch; color: var(--text); font-size: 14.5px; line-height: 1.55; }
.detail .about.none { color: var(--muted); }
.detail h4 { margin: 0 0 6px; color: var(--muted); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }

/* Hide list and column picker (both stored per browser in cookies) */
.repo-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.expand { min-width: 0; }
/* The whole row or card opens the repo's detail (site.js), not only its name. */
tr.row, .card { cursor: pointer; }
/* The repo name wraps rather than being cut off; the one-line description is cut off, and its
   full text is in the panel the row expands to. */
.expand .name { min-width: 0; overflow-wrap: anywhere; }
.hide-btn {
  margin-left: auto;
  flex: none;
  display: grid;
  place-items: center;
  padding: 3px 5px;
  background: none;
  border: 1px solid transparent;
  border-radius: 5px;
  color: var(--muted);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  opacity: 0;
}
tr.row:hover .hide-btn, .card:hover .hide-btn, .hide-btn:focus-visible { opacity: 1; }
.hide-btn:hover { color: var(--text); border-color: var(--line); background: var(--panel); }
.hide-btn[data-unhide] { opacity: 1; border-color: var(--line); color: var(--text); }
@media (hover: none) { .hide-btn { opacity: 1; } }
/* With a mouse, star and hide take no room until the row is hovered or focused, so the name
   gets the width; a starred repo's star and the Unhide button always show. */
@media (hover: hover) {
  .hide-btn { display: none; }
  tr.row:hover .hide-btn, tr.row:focus-within .hide-btn, .card:hover .hide-btn, .card:focus-within .hide-btn, .fav-btn[aria-pressed="true"], .hide-btn[data-unhide] { display: grid; }
  tr.row:focus-within .hide-btn, .card:focus-within .hide-btn { opacity: 1; }
}

/* Favorites: star button on rows, folder at the top of the sidebar */
.fav-btn + .hide-btn { margin-left: 0; }
.fav-btn[aria-pressed="true"] { opacity: 1; color: var(--star); }
.fav-btn[aria-pressed="true"] svg { fill: currentColor; }
.fav-btn[aria-pressed="true"]:hover { color: var(--star); }
tr.row { scroll-margin-top: 48px; }
tr.row:target > td, .card:target { background: var(--sel); }
.favs { margin: 0 0 18px; padding-bottom: 14px; border-bottom: 1px solid var(--line); }
.rail .favs > summary { display: flex; align-items: center; gap: 8px; padding: 4px 0; color: var(--text); font-size: 14px; font-weight: 600; }
.favs > summary svg { color: var(--star); flex: none; }
.favs > summary .label { flex: 1; }
.favs > summary::after { content: "▸"; color: var(--muted); font-size: 11px; }
.favs[open] > summary::after { content: "▾"; }
.favs .count { color: var(--muted); font-size: 12px; font-weight: 400; }
.fav-list { list-style: none; margin: 6px 0 0; padding: 0 0 0 4px; }
.fav-list li { display: flex; align-items: baseline; gap: 8px; padding: 3px 0 3px 19px; }
.fav-list a { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); text-decoration: none; font-size: 13px; }
.fav-list a:hover { color: var(--accent); }
.fav-empty { margin: 6px 0 0 23px; color: var(--muted); font-size: 13px; }
.fav-all { display: inline-block; margin: 8px 0 0 23px; color: var(--accent); text-decoration: none; font-size: 13px; }
.fav-all[hidden], .fav-empty[hidden] { display: none; }

.toplink { color: var(--muted); text-decoration: none; white-space: nowrap; }
.toplink:hover { color: var(--text); }

.cols { position: relative; }
.cols summary {
  list-style: none;
  cursor: pointer;
  padding: 5px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--muted);
  font-size: 13px;
  white-space: nowrap;
}
.cols summary::-webkit-details-marker { display: none; }
.cols[open] summary, .cols summary:hover { color: var(--text); }
.cols-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 5;
  width: 190px;
  padding: 8px 12px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 16px;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--text);
}
.toast button { background: none; border: 0; padding: 6px 4px; color: var(--accent); font: inherit; font-weight: 600; cursor: pointer; }

/* Controls above the table: window switch, sort menu, filter button, help, columns */
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-bottom: 10px; }
.windows { display: flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.windows a { padding: 5px 12px; color: var(--muted); text-decoration: none; font-size: 13px; }
.windows a + a { border-left: 1px solid var(--line); }
.windows a:hover { color: var(--text); }
.windows a[aria-current] { background: var(--fill); color: var(--on-accent); font-weight: 600; }
.sortform label { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: 13px; }
.sortform select {
  padding: 5px 8px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--text);
  font: inherit;
}
.sortform option { background: var(--panel); color: var(--text); }
.filter-btn {
  display: none;
  padding: 5px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--text);
  text-decoration: none;
  font-size: 13px;
}
.badge { display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 4px; border-radius: 9px; background: var(--fill); color: var(--on-accent); font-size: 11.5px; text-align: center; }
.help { position: relative; }
.help summary {
  list-style: none;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--muted);
  font-weight: 700;
  cursor: pointer;
}
.help summary::-webkit-details-marker { display: none; }
.help[open] summary, .help summary:hover { color: var(--text); }
.help-pop {
  position: absolute;
  left: 0;
  top: calc(100% + 6px);
  z-index: 6;
  width: min(420px, calc(100vw / var(--zoom) - 32px));
  padding: 12px 16px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
}
.help-pop dl { margin: 0; }
.help-pop dt { margin-top: 8px; color: var(--text); font-weight: 600; }
.help-pop dt:first-child { margin-top: 0; }
.help-pop dd { margin: 2px 0 0; color: var(--muted); line-height: 1.45; }
.controls .cols { margin-left: auto; }

/* Direct link to the repo on GitHub, beside its name */
.gh-link { flex: none; display: grid; place-items: center; width: 24px; height: 24px; border-radius: 5px; color: var(--faint); }
.gh-link:hover { color: var(--text); background: var(--panel); }

.skip { position: absolute; left: 12px; top: -60px; z-index: 30; padding: 8px 14px; background: var(--fill); color: var(--on-accent); border-radius: 6px; text-decoration: none; }
.skip:focus { top: 10px; }
.fav-top { display: none; }
.sheet-head, .sheet-done, .backdrop { display: none; }

/* Narrow screens: favorites and filters move into a sheet opened by the Filters button. */
@media (max-width: 1430px) {
  .filter-btn { display: inline-block; }
  .fav-top { display: inline; }
  .fav-top[hidden] { display: none; }
  .rail { display: none; }
  .rail:target, body.filters-open .rail {
    display: block;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 20;
    width: min(360px, 100%);
    padding: 0 20px;
    overflow-y: auto;
    background: var(--bg);
    border-left: 1px solid var(--line);
  }
  body.filters-open { overflow: hidden; }
  body.filters-open .backdrop { display: block; position: fixed; inset: 0; z-index: 19; background: color-mix(in srgb, var(--bg) 70%, transparent); }
  .sheet-head { display: flex; align-items: center; justify-content: space-between; position: sticky; top: 0; z-index: 1; padding: 14px 0 10px; background: var(--bg); }
  .sheet-head h2 { margin: 0; font-size: 17px; }
  .sheet-close { padding: 6px 10px; color: var(--accent); text-decoration: none; }
  .rail-head h2 { visibility: hidden; }
  .sheet-done {
    display: block;
    position: sticky;
    bottom: 0;
    margin: 0 -20px;
    padding: 14px 20px;
    background: var(--bg);
    border-top: 1px solid var(--line);
    text-align: center;
    color: var(--on-accent);
    text-decoration: none;
    font-weight: 600;
  }
  .sheet-done::before { content: ""; position: absolute; inset: 8px 20px; z-index: -1; border-radius: 8px; background: var(--fill); }
  .sheet-done { isolation: isolate; }
}

/* Phones: header on two rows, rows as cards showing the selected window and the sort. */
@media (max-width: 910px) {
  .top { flex-wrap: wrap; gap: 10px 12px; padding: 10px 14px; }
  /* Logo, full name and theme switch share the first row down to a 360 px screen. */
  .brand { gap: 8px; }
  .logo { width: 24px; height: 24px; }
  .wordmark { font-size: 14px; }
  .theme button { padding-left: 9px; padding-right: 9px; }
  .search { order: 5; flex: 1 1 100%; margin: 0; }
  .search input { width: 100%; }
  .toplink { margin-left: auto; font-size: 13px; }
  .toplink + .toplink { margin-left: 0; }
  .toplink[hidden] { display: none; }
  .theme { margin-left: auto; }
  .toplink:not([hidden]) ~ .theme { margin-left: 0; }
  main { padding: 0 12px 20px; }
  .controls .cols { display: none; }
  .scroll { overflow: visible; border: 0; border-radius: 0; }
  table.rank, table.rank > tbody { display: block; }
  table.rank > thead { display: none; }
  tr.row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0 14px; padding: 10px 0; border-bottom: 1px solid var(--line); }
  .rank tr.row > td { display: none; padding: 0; border: 0; }
  .rank tr.row > td.rank { display: block; width: 34px; align-self: flex-start; text-align: left; line-height: 1.2; }
  /* The name and description take the card's width; the GitHub, star and hide buttons share the
     line below them with the language and age. Beside the name they left it a third of the width. */
  .rank tr.row > td.repo, .card-repo { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; align-items: center; column-gap: 2px; }
  .rank tr.row > td.repo { flex: 1 1 calc(100% - 48px); min-width: 0; max-width: none; width: auto; }
  .repo-head { display: contents; }
  .repo-head .expand { grid-area: 1 / 1 / 2 / -1; }
  td.repo .desc, .card-repo .desc { grid-area: 2 / 1 / 3 / -1; }
  td.repo .meta, .card-repo .meta { grid-area: 3 / 1 / 4 / 2; margin: 0; }
  .repo-head .gh-link, .repo-head .hide-btn { grid-row: 3; margin: 0; }
  /* Pinned, so the buttons stay at the right end on a card with no language or age line. */
  .repo-head .gh-link { grid-column: 2; }
  .repo-head .fav-btn { grid-column: 3; }
  .repo-head .hide-btn:not(.fav-btn) { grid-column: 4; }
  .rank tr.row > td.sel, .rank tr.row > td.sorted { display: block; margin-top: 8px; padding: 3px 8px; border-radius: 5px; text-align: left; }
  .rank tr.row > td.sel { margin-left: 48px; }
  .rank tr.row > td.bars { display: block; margin-left: auto; width: auto; }
  .rank tr.row > td[data-label]::before { content: attr(data-label); display: block; color: var(--muted); font: 400 11px/1.3 system-ui, sans-serif; }
  .heat small { display: inline; margin-left: 4px; }
  tr.detail, tr.detail > td { display: block; }
  tr.detail > td { padding: 14px 12px; }
  .wins th, .wins td { padding: 6px 4px; font-size: 12.5px; }
  .pager { flex-wrap: wrap; gap: 10px; }
}

/* Row buttons sit at the right end whichever of them are showing: the GitHub link takes the gap. */
.repo-head .gh-link { margin-right: auto; }
.repo-head .hide-btn { margin-left: 0; }

/* Sidebar collapse (wide screens). Collapsed, the sidebar is a strip with the toggle and the
   number of active filters; narrow screens use the filter sheet instead. */
.rail-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 0 0 6px auto;
  padding: 4px 6px;
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--muted);
  cursor: pointer;
}
.rail-toggle:hover { color: var(--text); }
.rail-toggle svg { transition: transform 0.15s; }
.rail-toggle .badge { display: none; margin: 0; }
@media (min-width: 1431px) {
  body.rail-collapsed .layout { grid-template-columns: 44px minmax(0, 1fr); }
  body.rail-collapsed .rail { padding: 16px 6px; }
  body.rail-collapsed .rail > :not(.rail-toggle) { display: none; }
  body.rail-collapsed .rail-toggle { flex-direction: column; margin: 0 auto; }
  body.rail-collapsed .rail-toggle svg { transform: rotate(180deg); }
  body.rail-collapsed .rail-toggle .badge:not([hidden]) { display: inline-block; }
}
@media (max-width: 1430px) {
  .rail-toggle { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .rail-toggle svg, main[aria-busy="true"] { transition: none; }
}

/* Solar: draw emoji in repo descriptions as text glyphs in the theme colour where the font has
   one, instead of colour emoji (white, gray and blue). Emoji with no text glyph stay in colour. */
[data-theme="solar"] body { font-variant-emoji: text; }

/* Title, window switch and sort stay at the top while scrolling; the table header sticks under
   them (--head-h, set by site.js). Phones keep them in the flow: stuck, they would cover about a
   quarter of the screen. */
.sticky-head { position: sticky; top: 0; z-index: 3; background: var(--bg); }
.sticky-head .controls { margin-bottom: 0; padding-bottom: 10px; }
.sticky-head .caption { margin: 0; padding-bottom: 12px; }
@media (min-width: 1431px) {
  body.rail-collapsed .rail-toggle { position: sticky; top: 16px; }
}
@media (max-width: 910px) {
  .sticky-head { position: static; }
  table.rank > thead th { top: 0; }
}

/* Focus rings inside boxes that clip (theme switch, window tabs) and on filled controls, where
   the accent ring would vanish into the fill. */
.theme button:focus-visible, .windows a:focus-visible { outline-offset: -4px; }
.theme button[aria-pressed="true"]:focus-visible, .windows a[aria-current]:focus-visible,
.rank th.sel a:focus-visible, .gh:focus-visible, .skip:focus-visible { outline-color: var(--on-accent); }
.gh:focus-visible, .skip:focus-visible { outline-offset: -4px; }

/* Phones and narrow windows: the window tabs share the width, the help panel spans the content
   instead of hanging off its button, and tap targets reach 44 px as rendered (the page is
   drawn at 130%, so 44 / 1.3 in CSS pixels). */
@media (max-width: 910px) {
  .bar h1 { white-space: normal; }
  .controls { position: relative; }
  .help { position: static; }
  .help-pop { left: 0; right: 0; width: auto; }
  .windows { flex: 1 1 100%; }
  .windows a { flex: 1 1 0; min-width: 0; display: flex; align-items: center; justify-content: center; padding: 0 4px; }
  .windows a, .sortform select, .filter-btn, .theme button, .toplink, .expand, .toast button { min-height: calc(44px / var(--zoom)); }
  .filter-btn, .toplink { display: inline-flex; align-items: center; }
  .help summary { width: calc(44px / var(--zoom)); height: calc(44px / var(--zoom)); }
  .gh-link, .hide-btn { min-width: calc(44px / var(--zoom)); min-height: calc(44px / var(--zoom)); }
  .retry { min-height: calc(44px / var(--zoom)); }
}

/* The window table in an expanded row scrolls on its own when it is wider than a phone screen,
   so the page itself never scrolls sideways; on phones the speed-up text wraps first. */
.wins-wrap { overflow-x: auto; }
.detail-grid > * { min-width: 0; }
.wins-wrap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 910px) {
  .wins td:last-child { white-space: normal; min-width: 7ch; }
}

/* Main view heading: what the list is, above the controls. It scrolls away; the controls stick.
   Its tooltip and the Sort menu's carry how the list is ranked. */
.intro { padding: 18px 0 0; }
.intro h1 { margin: 0; font-size: 24px; letter-spacing: -0.01em; }

/* Top three as cards above the table (page.ts card); the first has the accent outline. The
   large pair wraps to one column when a card is too narrow for both side by side. */
.podium { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin: 0 0 14px; }
.card { display: flex; flex-direction: column; gap: 10px; min-width: 0; padding: 12px 14px 10px; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; }
.card.lead { border-color: var(--accent); }
.card.open { background: var(--raised); }
.card-top { display: flex; align-items: flex-start; gap: 12px; min-width: 0; }
.card-rank { min-width: 1.2ch; color: var(--accent); font: 700 30px/1 ui-monospace, "Cascadia Mono", "SF Mono", Consolas, monospace; }
.card-repo { flex: 1; min-width: 0; font-family: Verdana, Geneva, sans-serif; }
.card dl, .card dd { margin: 0; }
.card dt { color: var(--muted); font-size: 12px; }
.card-big { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 8px 12px; padding-top: 8px; border-top: 1px solid var(--line); }
.card-big dd { font-size: 26px; font-weight: 700; line-height: 1.15; white-space: nowrap; }
.card-big dd.speed { font-size: 18px; white-space: normal; }
.card-small { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.card-small dd { font-size: 13.5px; white-space: nowrap; }
.card .gain.pos { color: var(--gain); }
.card .gain.neg { color: var(--slow); }
.card small { margin-left: 3px; color: var(--muted); font-size: 10px; }
.card .strip { width: 100%; height: auto; margin-top: auto; }
@media (max-width: 910px) {
  .intro { padding-top: 14px; }
  .intro h1 { font-size: 20px; }
  .podium { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .card-big dd { font-size: 22px; }
}
