:root {
  --bg: #f6f7f8;
  --surface: #ffffff;
  --ink: #14171a;
  --ink-soft: #565c63;
  /* Muted text (labels, dates, zeros), still 4.5:1 on --bg and --surface
     (WCAG AA for small text). */
  --ink-faint: #6b7177;
  --hairline: #e3e5e8;
  --hairline-strong: #d2d5d9;
  /* Links and key UI: the brand violet (tokens.css, from assets/brand/), which
     switches to its dark-theme value by itself. */
  --accent: var(--nk-link-text);
  /* The sets updated in bulk, beside the accent's fully checked: another
     shade of the logo's, so the split doesn't read as progress. */
  --bulk: var(--nk-bulk-fill);
  /* Statuses: the brand tokens' roles (tokens.css), which switch to their
     dark-theme values by themselves. Dots use the brighter fill; text uses
     the darker text value, readable on the page's backgrounds. Outdated and
     the amber states (can't update, marked broken) still share --warn. */
  --ok: var(--nk-ok-fill);
  --ok-soft: var(--nk-ok-bg);
  --ok-devel: var(--nk-ok-text);
  --warn: var(--nk-outdated-text);
  --warn-dot: var(--nk-outdated-fill);
  --warn-soft: var(--nk-outdated-bg);
  --warn-devel: var(--nk-outdated-text);
  --stale: #8b8f94;
  --stale-soft: #eeeeef;
  /* Can't update, marked broken, a failed dependency: known problems that
     need a hand, not failures. */
  --caution: var(--nk-warn-text);
  --caution-dot: var(--nk-warn-fill);
  --danger: var(--nk-failed-text);
  --danger-dot: var(--nk-failed-fill);
  --danger-soft: var(--nk-failed-bg);
  /* "On master" (the update is merged, waiting for the channel): the brand
     violet. */
  --merged: var(--nk-merged-text);
  --merged-dot: var(--nk-merged-fill);
  --merged-emphasis: var(--nk-merged-badge);
  --merged-soft: var(--nk-merged-bg);
  /* Update PR badges: open in the up-to-date green, draft in grey. */
  --pr-open: var(--nk-ok-badge);
  --pr-draft: var(--nk-neutral-l55);
  /* Text on the solid badges (on master, update PRs). */
  --on-badge: #ffffff;
  --radius: 8px;
  color-scheme: light dark;
}
/* Dark: by the system's setting, unless the page is set to light, or when
   it's set to dark (the Theme menu: data-mode on <html>). The Catppuccin
   palette is in catppuccin.css. */
@media (prefers-color-scheme: dark) {
  :root:not([data-mode="light"]) {
    --bg: #16181c;
    --surface: #1d2025;
    --ink: #edeff2;
    --ink-soft: #a3a8b0;
    --ink-faint: #848990; /* 4.5:1 on --bg and --surface */
    --hairline: #2b2f35;
    --hairline-strong: #383d44;
    --stale: #82868c;
    --stale-soft: #24262a;
  }
}
:root[data-mode="dark"] {
  --bg: #16181c;
  --surface: #1d2025;
  --ink: #edeff2;
  --ink-soft: #a3a8b0;
  --ink-faint: #848990; /* 4.5:1 on --bg and --surface */
  --hairline: #2b2f35;
  --hairline-strong: #383d44;
  --stale: #82868c;
  --stale-soft: #24262a;
  color-scheme: dark;
}
:root[data-mode="light"] {
  color-scheme: light;
}
* {
  box-sizing: border-box;
}
/* Room for the scrollbar from the start: when the data makes the page
   taller than the window, the scrollbar doesn't narrow it and shift the
   centred page sideways (a layout shift). */
html {
  scrollbar-gutter: stable;
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "Instrument Sans", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}
.mono {
  font-family: "JetBrains Mono", ui-monospace, monospace;
}
.shell {
  max-width: 1280px;
  margin: 0 auto;
  padding: 28px 20px 80px;
}

header.top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--hairline-strong);
  flex-wrap: wrap;
}
.wordmark {
  display: flex;
  align-items: center;
  gap: 12px;
}
.wordmark h1 {
  margin: 0;
}
/* The nixkeeper lockup, the mark and the outlined wordmark
   (nixkeeper-lockup-tight*.svg, from the brand sources): the light one, or
   the dark one in dark mode. In the brand's colours in either palette. */
.wordmark .lockup {
  display: block;
  width: auto;
  height: 28px;
}
.wordmark .lockup.on-dark {
  display: none;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-mode="light"]) .wordmark .lockup.on-light {
    display: none;
  }
  :root:not([data-mode="light"]) .wordmark .lockup.on-dark {
    display: block;
  }
}
:root[data-mode="dark"] .wordmark .lockup.on-light {
  display: none;
}
:root[data-mode="dark"] .wordmark .lockup.on-dark {
  display: block;
}
.wordmark .tag {
  color: var(--ink-faint);
  font-size: 13px;
}

.actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* The toolbar: the filter (an icon, and "/" to jump to it), then icon
   buttons, all 34px high. */
.icon {
  width: 16px;
  height: 16px;
  flex: none;
}
.search {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 8px 0 10px;
  width: 220px;
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink-faint);
  cursor: text;
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
}
.search:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
.search input {
  flex: 1;
  min-width: 0;
  border: 0;
  padding: 0;
  font-family: inherit;
  font-size: 14px;
  background: none;
  color: var(--ink);
  outline: none;
}
.search input::placeholder {
  color: var(--ink-faint);
}
.search kbd {
  font-family: var(--nk-font-mono);
  font-size: 11px;
  line-height: 1;
  padding: 3px 6px;
  border: 1px solid var(--hairline-strong);
  border-radius: 4px;
  color: var(--ink-faint);
}
.search:focus-within kbd {
  display: none;
}
.btn {
  text-decoration: none;
  display: inline-grid;
  place-items: center;
  height: 34px;
  min-width: 34px;
  padding: 0 9px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  border-radius: var(--radius);
  border: 1px solid var(--hairline-strong);
  background: var(--surface);
  color: var(--ink-soft);
  cursor: pointer;
  transition:
    color 0.15s,
    background 0.15s,
    border-color 0.15s;
}
.btn:hover {
  color: var(--ink);
  background: var(--bg);
}
.btn[aria-pressed="true"],
.btn[aria-expanded="true"] {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--hairline-strong));
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}
/* The Theme menu: the palette and light or dark, kept in the browser. */
.theme {
  position: relative;
}
.theme-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 10;
  display: grid;
  gap: 12px;
  padding: 12px;
  min-width: 220px;
  background: var(--surface);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius);
  box-shadow: 0 6px 24px rgb(0 0 0 / 0.16);
}
.theme-panel[hidden] {
  display: none;
}
.theme-panel fieldset {
  margin: 0;
  padding: 0;
  border: 0;
  display: grid;
  gap: 6px;
}
.theme-panel legend {
  padding: 0 0 6px;
  color: var(--ink-faint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.theme-panel .choices {
  display: flex;
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius);
  overflow: hidden;
}
.theme-panel label {
  flex: 1;
  position: relative;
  text-align: center;
  padding: 6px 10px;
  font-size: 13px;
  color: var(--ink-soft);
  cursor: pointer;
}
.theme-panel label + label {
  border-left: 1px solid var(--hairline-strong);
}
.theme-panel input {
  position: absolute;
  opacity: 0;
  inset: 0;
  margin: 0;
  cursor: pointer;
}
.theme-panel label:has(input:checked) {
  color: var(--ink);
  background: var(--bg);
  font-weight: 600;
}
.theme-panel label:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.btn:focus-visible,
input:focus-visible,
select:focus-visible,
.row:focus-visible,
.failure-btn:focus-visible,
button.plat:focus-visible,
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.search input:focus-visible {
  outline: none; /* the field's ring instead */
}

/* One bar of filters: the counts (status), then the lists after a divider,
   then when the data was checked. Each a chip; the active one in the
   accent's tint, like the toolbar's buttons. */
.filterbar {
  display: flex;
  align-items: center;
  gap: 8px 12px;
  padding: 14px 0 16px;
  flex-wrap: wrap;
}
.filters {
  display: flex;
  align-items: center;
  gap: 8px 12px;
  flex-wrap: wrap;
}
.chips {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  color: var(--ink-soft);
  font-size: 13px;
}
.chips b {
  color: var(--ink);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.chips.lists:empty {
  display: none;
}
.chips.lists {
  padding-left: 12px;
  border-left: 1px solid var(--hairline-strong);
}
.stat-btn {
  font: inherit;
  color: inherit;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 4px 11px;
  cursor: pointer;
  transition:
    color 0.15s,
    background 0.15s,
    border-color 0.15s;
}
.stat-btn:hover:not(:disabled) {
  border-color: var(--hairline-strong);
  color: var(--ink);
}
.stat-btn[aria-pressed="true"] {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--hairline-strong));
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}
.stat-btn:disabled {
  cursor: default;
  opacity: 0.5;
}
.stat-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Narrowing any list: toggles, and how long the problem has lasted. Under
   the counts (one list), or the tiles (every package). */
.refine-row[hidden] {
  display: none;
}
.refine {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--ink-soft);
}
.refine-btn {
  font: inherit;
  color: inherit;
  background: none;
  border: 1px dashed var(--hairline-strong);
  border-radius: 999px;
  padding: 3px 10px;
  cursor: pointer;
}
.refine-btn:hover {
  color: var(--ink);
  border-style: solid;
}
.refine-btn[aria-pressed="true"] {
  color: var(--accent);
  border-style: solid;
  border-color: color-mix(in srgb, var(--accent) 45%, var(--hairline-strong));
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}
.refine-btn[aria-pressed="true"]::before {
  content: "✓ ";
}
.refine-btn:focus-visible,
.refine-age select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.refine-age {
  margin-left: 4px;
  color: var(--ink-faint);
}
.refine-age select {
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 2px 6px;
}
/* With every package: "Your packages", the visitor's handle. */
.mine-form {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.mine-form input {
  font: inherit;
  font-size: 13px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  padding: 3px 11px;
  width: 11em;
}
.mine-form select {
  font: inherit;
  font-size: 13px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  padding: 3px 9px;
  max-width: 14em;
}
.mine-form select:focus-visible,
.mine-form input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.mine-edit {
  font: inherit;
  font-size: 13px;
  color: var(--ink-faint);
  background: none;
  border: 0;
  padding: 2px 4px;
  margin-left: -2px;
  cursor: pointer;
}
.mine-edit:hover {
  color: var(--ink);
}
.lists-label {
  color: var(--ink-faint);
  font-size: 12px;
  margin-right: 2px;
}
/* When the data was checked, and the legend's "?". */
.filterbar .meta {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}
.filterbar .checked {
  color: var(--ink-faint);
  font-size: 13px;
}
/* "checked ... ago" opens where the data is from (a popover, like the
   legend's). */
.sources {
  position: relative;
}
button.checked {
  font: inherit;
  background: none;
  border: 0;
  padding: 2px 0;
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
button.checked:hover,
button.checked[aria-expanded="true"] {
  color: var(--ink);
}
button.checked:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
/* The legend: a "?" that opens what the dots mean (a popover, like the
   Theme menu). */
.legend {
  position: relative;
}
.help-btn {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border-radius: 999px;
  border: 1px solid var(--hairline-strong);
  background: var(--surface);
  color: var(--ink-faint);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.help-btn:hover,
.help-btn[aria-expanded="true"] {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--hairline-strong));
}
.help-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.legend-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 10;
  width: max-content;
  max-width: min(340px, calc(100vw - 40px));
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--hairline-strong);
  border-radius: var(--radius);
  box-shadow: 0 6px 24px rgb(0 0 0 / 0.16);
  font-size: 13px;
  color: var(--ink-soft);
}
.legend-panel[hidden] {
  display: none;
}
.legend-panel .pop-title {
  margin: 0 0 8px;
  color: var(--ink-faint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.legend-panel ul {
  list-style: none;
  margin: 0 0 10px;
  padding: 0;
  display: grid;
  grid-template-columns: auto auto 1fr;
  align-items: center;
  gap: 7px 8px;
}
.legend-panel li {
  display: contents;
}
.legend-panel b {
  color: var(--ink);
  font-weight: 600;
  white-space: nowrap;
}
.legend-panel > a {
  font-size: 12.5px;
}
/* Anchored left of the legend's "?": a little narrower, to stay on a
   phone's screen. */
.sources-panel {
  max-width: min(340px, calc(100vw - 72px));
}
.sources-panel ul {
  grid-template-columns: auto 1fr;
  /* A name beside the first line of what it says, when that wraps. */
  align-items: baseline;
}
.sources-panel .unused .src-what {
  color: var(--caution);
}
/* A digest's name, its sources below it, indented. */
.sources-panel .src-digest > a {
  grid-column: 1 / -1;
  margin-top: 4px;
  font-weight: 600;
}
.sources-panel .in-digest > b {
  padding-left: 10px;
  font-weight: 500;
}
.filterbar .checked.stale {
  color: var(--danger);
}

/* Mistakes in the package lists (a maintainer handle no package lists, ...). */
/* With every package: all of nixpkgs in numbers, the tiles (filters of the
   view shown), the generated sets, and the view shown. */
.scope {
  font-size: 13px;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 14px 16px;
  margin: 0 0 14px;
  display: grid;
  gap: 10px;
}
.scope[hidden] {
  display: none; /* display: grid above would show it */
}
.scope b {
  color: var(--ink);
  font-weight: 600;
}
.scope-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
}
.scope-label {
  color: var(--ink-faint);
  font-size: 12.5px;
}
.scope-total {
  color: var(--ink);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.scope-bar {
  height: 6px;
  border-radius: 3px;
  background: var(--bulk);
  overflow: hidden;
}
.scope-bar span {
  display: block;
  height: 100%;
  background: var(--accent);
}
.scope-split {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
}
.swatch {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  margin-right: 6px;
  vertical-align: 0;
}
.swatch.full {
  background: var(--accent);
}
.swatch.gen {
  background: var(--bulk);
}
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
}
.card {
  display: grid;
  gap: 2px;
  color: inherit;
  text-decoration: none;
  background: color-mix(in srgb, var(--ink) 4%, var(--surface));
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 9px 12px;
}
.card:hover {
  border-color: var(--hairline-strong);
}
.card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.card-label {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--ink-faint);
}
.card-go {
  color: var(--ink-faint);
  font-size: 15px;
  line-height: 1;
}
.card-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
}
.card-n {
  font-size: 20px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.card-change {
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-faint);
  white-space: nowrap;
}
.card-change.worse {
  color: var(--danger);
}
.card-change.better {
  color: var(--ok-devel);
}
.card-sub {
  font-size: 11.5px;
  color: var(--ink-faint);
}
.spark {
  width: 100%;
  height: 22px;
  margin-top: 2px;
}
/* The trends' marks: a staging-next merge, nixkeeper updated. */
.spark-mark {
  stroke-width: 1;
  stroke-dasharray: 2 2;
}
.spark-mark.staging-next {
  stroke: var(--ink-faint);
}
.spark-mark.nixkeeper,
.spark-mark.counting {
  stroke: var(--accent);
}
.card-note {
  color: var(--caution);
}
.spark-legend {
  margin: -2px 0 0;
  font-size: 11.5px;
  color: var(--ink-faint);
}
.spark-key {
  display: inline-block;
  width: 0;
  height: 10px;
  margin: 0 5px -1px 0;
  border-left: 1px dashed var(--ink-faint);
}
.spark-key.nixkeeper,
.spark-key.counting {
  border-left-color: var(--accent);
}
/* The overview's section and card titles are headings (to move between
   with a screen reader), drawn as the labels they were. */
:where(h2, h3) {
  margin: 0;
  font: inherit;
}
.scope h2.scope-label {
  margin: 4px 0 -4px;
}
.overview-more {
  display: grid;
  gap: 10px;
}
.overview-more[hidden] {
  display: none;
}
.hl-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 8px;
}
.hl-card {
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
  background: color-mix(in srgb, var(--ink) 4%, var(--surface));
  border-radius: 8px;
  padding: 10px 6px 6px;
  border-top: 2px solid color-mix(in srgb, var(--hl) 70%, transparent);
}
.hl-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 6px 8px;
}
.hl-title {
  display: grid;
  gap: 1px;
}
.hl-label {
  font-size: 12px;
  color: var(--ink-faint);
}
.hl-n {
  font-size: 18px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--hl);
  font-variant-numeric: tabular-nums;
}
.hl-modes {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  border-radius: 7px;
  background: color-mix(in srgb, var(--ink) 6%, var(--surface));
}
.hl-mode {
  font: inherit;
  font-size: 11.5px;
  color: var(--ink-faint);
  background: none;
  border: 0;
  border-radius: 5px;
  padding: 2px 9px;
  cursor: pointer;
}
.hl-mode:hover {
  color: var(--ink);
}
.hl-mode[aria-pressed="true"] {
  color: var(--ink);
  background: var(--surface);
  box-shadow: 0 1px 2px color-mix(in srgb, #000 25%, transparent);
}
.hl-mode:focus-visible,
.hl-row:focus-visible,
.hl-all:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.hl-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.hl-list > * + * {
  border-top: 1px solid color-mix(in srgb, var(--hairline) 60%, transparent);
}
.hl-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 5px 6px;
  border-radius: 5px;
  color: var(--ink);
  text-decoration: none;
}
.hl-row:hover {
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}
.hl-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
}
.hl-row:hover .hl-name {
  color: var(--accent);
}
.hl-age {
  margin-left: auto;
  flex: none;
  font-size: 11.5px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--hl);
  background: color-mix(in srgb, var(--hl) 12%, transparent);
  border-radius: 999px;
  padding: 1px 7px;
}
.hl-unit {
  font-size: 11.5px;
  color: var(--ink-faint);
}
.hl-none {
  margin: 0;
  padding: 6px;
  color: var(--ink-faint);
  font-size: 13px;
}
.hl-all {
  justify-self: start;
  margin: 4px 0 0;
  padding: 4px 6px;
  border-radius: 5px;
  font-size: 12.5px;
  color: var(--accent);
  text-decoration: none;
}
.hl-all:hover {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
/* The overview's search: large and centred, the team picker beside it. */
.find {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  width: min(100%, 720px);
  margin: 14px auto 10px;
}
.find-box {
  position: relative;
  flex: 3 1 320px;
  display: flex;
  align-items: center;
}
.find-icon {
  position: absolute;
  left: 14px;
  display: flex;
  color: var(--ink-faint);
  pointer-events: none;
}
.find-input {
  width: 100%;
  height: 44px;
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--hairline-strong);
  border-radius: 10px;
  padding: 0 14px 0 40px;
  box-shadow: 0 1px 2px color-mix(in srgb, #000 12%, transparent);
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
}
.find-input::placeholder {
  color: var(--ink-faint);
}
.find-input:hover {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--hairline-strong));
}
.find-input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent);
}
.find-box:focus-within .find-icon {
  color: var(--accent);
}
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px;
}
.tile {
  font: inherit;
  text-align: left;
  color: inherit;
  background: color-mix(in srgb, var(--ink) 4%, var(--surface));
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 8px 12px;
  cursor: pointer;
  display: grid;
  gap: 2px;
}
.tile:hover {
  border-color: var(--hairline-strong);
}
.tile:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.tile[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--hairline-strong));
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
}
.tile-label {
  font-size: 12px;
  color: var(--ink-faint);
}
.tile-n {
  font-size: 19px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.set-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
@media (max-width: 560px) {
  .set-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.set-card {
  display: grid;
  gap: 4px;
  min-width: 0;
  color: inherit;
  text-decoration: none;
  background: color-mix(in srgb, var(--ink) 4%, var(--surface));
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 9px 12px 10px;
}
.set-card:hover {
  border-color: var(--hairline-strong);
}
.set-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.set-name {
  font-size: 12.5px;
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.set-card:hover .set-name {
  color: var(--accent);
}
.set-n {
  font-size: 17px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.set-unit {
  font-size: 12px;
  font-weight: 400;
  color: var(--ink-faint);
}
.set-bar {
  display: flex;
  height: 4px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--hairline);
}
.set-bar-broken {
  background: var(--caution-dot);
}
.set-bar-failed {
  background: var(--danger-dot);
}
.set-bar-outdated {
  background: var(--warn-dot);
}
.set-meta {
  font-size: 11.5px;
  color: var(--ink-faint);
}
.set-by {
  font-size: 11.5px;
  color: var(--ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.set-failed {
  color: var(--danger);
}
.set-outdated {
  color: var(--warn);
}
.set-broken {
  color: var(--caution);
}
.scope-view {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  border-top: 1px solid var(--hairline);
  padding-top: 10px;
}
.view-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--hairline-strong));
  border-radius: 999px;
  padding: 2px 10px;
}
.view-x {
  color: inherit;
  text-decoration: none;
  opacity: 0.8;
}
.view-x:hover {
  opacity: 1;
}
.scope-hint {
  color: var(--ink-faint);
}
.team-pick {
  margin-left: auto;
  color: var(--ink-faint);
}
.team-pick select {
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 2px 6px;
  max-width: 14em;
}
.find .team-pick {
  flex: 1 1 200px;
  margin: 0;
}
.find .team-pick-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.find .team-pick select {
  width: 100%;
  max-width: none;
  height: 44px;
  font-size: 14px;
  border: 1px solid var(--hairline-strong);
  border-radius: 10px;
  padding: 0 12px;
  box-shadow: 0 1px 2px color-mix(in srgb, #000 12%, transparent);
  cursor: pointer;
}
.find .team-pick select:hover {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--hairline-strong));
}
.find .team-pick select:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent);
}
/* With every package, under a search: matching names beyond the view. */
.more-matches {
  margin-top: 18px;
  font-size: 13px;
}
.more-matches ul {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
  columns: 3 16em;
  column-gap: 24px;
}
.more-matches li {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
  break-inside: avoid;
}
/* With every package: maintainers (under an @ search, and the maintainers
   page): the handle, then their counts. */
.maint-list li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}
.maint-list a {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.maint-n {
  color: var(--ink-faint);
  font-size: 12px;
  white-space: nowrap;
}
.maint-page {
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  columns: 3 18em;
  column-gap: 28px;
  font-size: 13.5px;
}
.maint-page li {
  padding: 3px 0;
  break-inside: avoid;
}
.warn-text {
  color: var(--warn);
}
.danger-text {
  color: var(--danger);
}
.find-more {
  margin: -2px 0 4px;
  text-align: center;
  font-size: 12.5px;
  color: var(--ink-faint);
}
.fixed-to {
  flex: none;
  font-size: 12px;
  color: var(--ok-devel);
}
.list-problems {
  font-size: 13px;
  color: var(--ink-soft);
  background: var(--danger-soft);
  border-left: 3px solid var(--danger-dot);
  border-radius: 6px;
  padding: 8px 12px;
  margin: 0 0 14px;
}
.list-problems ul {
  margin: 4px 0 0;
  padding-left: 18px;
}
.list-problems li {
  color: var(--ink);
}

/* Separate borders (none apart): with collapsed ones, Chrome paints the
   rows' lines over the sticky headings as they scroll under them. So the
   lines are on the cells, which stay under the headings. */
table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
}
thead th {
  text-align: left;
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-faint);
  padding: 0 10px 8px;
  border-bottom: 1px solid var(--hairline);
}
/* While scrolling, the header and the filters stay at the top, and the
   table's column headings just under them (app.js measures the header into
   --sticky-h). The table needs no scroll box of its own for that: it fits
   (narrower windows get cards). Phones and tablets: see below. */
/* Marks where the filters are, to tell when they're stuck (app.js). */
.stick-mark {
  height: 1px;
  margin-bottom: -1px;
}
.sticky-top {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--bg);
  /* room above the logo once it's at the top, without moving it before */
  padding-top: 14px;
  margin-top: -14px;
}
thead th {
  position: sticky;
  top: var(--sticky-h, 0);
  z-index: 4;
  background: var(--bg);
}
tbody tr.row {
  cursor: pointer;
}
tbody tr.row td {
  border-bottom: 1px solid var(--hairline);
}
tbody tr.row:hover {
  background: var(--surface);
}
tbody tr.row td {
  padding: 12px 10px;
  vertical-align: middle;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex: none;
}
.status-dot.ok {
  background: var(--ok);
}
.status-dot.warn {
  background: var(--warn-dot);
}
.status-dot.merged {
  background: var(--merged-dot);
}
.status-dot.caution {
  background: var(--caution-dot);
}
.status-dot.missing {
  background: var(--danger-dot);
}
.status-dot.neutral {
  background: var(--ink-faint);
}

/* The platforms go under the name, lined up with the name, not the dot:
   the dot hangs in the padding. */
.pkg-name {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  padding-left: 18px; /* the dot and its gap */
}
/* The dot and the name stay together. */
.pkg-name .who {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-left: -18px;
}
/* Wraps after a dot or at a hyphen only (breakableName): a long name
   (home-assistant-custom-components.homematicip_local) would otherwise
   widen the table past the screen. */
.pkg-name .n {
  font-weight: 600;
  font-size: 14.5px;
}
/* Secondary to the name: the platforms as one small pill ("Linux ·
   Darwin"). Each is still a button: a click filters by platform. */
.plats {
  display: inline-flex;
  align-items: baseline;
  white-space: nowrap;
  font-size: 10.5px;
  font-weight: 500;
  padding: 1px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--stale-soft) 70%, transparent);
  color: var(--ink-soft);
}
.plat {
  font: inherit;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
}
.plat + .plat::before {
  content: "·";
  display: inline-block; /* keeps the hover underline off the dot */
  padding: 0 4px;
  color: var(--ink-faint);
  font-weight: 400;
}
button.plat {
  cursor: pointer;
}
button.plat:hover {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}
button.plat[aria-pressed="true"] {
  color: var(--accent);
  font-weight: 600;
}
.plat-filter {
  font: inherit;
  font-size: 12.5px;
  color: var(--accent);
  background: none;
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 4px 11px;
  cursor: pointer;
}

/* Text only screen readers get. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The version column wraps rather than widening the table past the screen
   (one long version would widen it for every row): only between its parts
   (before "→ target", before the age and badges), never inside a version. */
.ver {
  font-size: 13px;
}
.ver .v,
.ver .ref,
.ver .badge {
  white-space: nowrap;
}
/* The version cell: versions on the left, badges at the right edge (top:
   the update's PR or master badge; below: the age, devel, vulnerable, ...).
   Outdated, line 2 is the newest version, its changed part in the
   outdated orange (the merged violet when it's waiting for the channel). */
.vcell {
  display: grid;
  grid-template-columns: max-content 1fr;
  align-items: center;
  gap: 3px 16px;
}
/* Badges wrap under each other rather than widening the column (a long
   version with "older version" and "vulnerable" beside it). */
.v-tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 5px;
}
.v-tags:empty {
  display: none;
}
.v-tags .badge {
  margin-left: 0;
}
/* Both versions: one button that copies the update's title. */
.vcopy {
  grid-column: 1;
  grid-row: 1 / span 2;
  display: grid;
  gap: 3px;
  justify-items: start;
  position: relative;
  font: inherit;
  color: inherit;
  text-align: left;
  background: none;
  border: 0;
  border-radius: 4px;
  padding: 0;
  cursor: copy;
}
.vcopy:hover {
  text-decoration: underline dotted var(--ink-faint);
  text-underline-offset: 3px;
}
.vcopy:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
/* "Copied", for a moment, above the versions. */
.vcopy[data-copied]::after {
  content: attr(data-copied);
  position: absolute;
  left: 0;
  bottom: calc(100% + 4px);
  padding: 2px 8px;
  border-radius: 6px;
  font-family: var(--nk-font-ui);
  font-size: 11.5px;
  white-space: nowrap;
  background: var(--ink);
  color: var(--surface);
  pointer-events: none;
}
.v-now,
.v-tags.top {
  grid-row: 1;
}
.v-next,
.v-tags.bottom {
  grid-row: 2;
}
/* Master partway there: a line between, master's version beside its
   badge, and the newest below. */
.v-mid,
.v-tags.mid {
  grid-row: 2;
}
.v-now,
.v-mid,
.v-next {
  grid-column: 1;
  white-space: nowrap;
}
.v-tags {
  grid-column: 2;
}
.vcell.three .vcopy {
  grid-row: 1 / span 3;
}
.vcell.three .v-next,
.vcell.three .v-tags.bottom {
  grid-row: 3;
}
/* The newest version: the start it shares with nixpkgs' faded, the "→"
   hanging in the gap to the left, so both versions start in the same
   column. */
.v-mid .same,
.v-next .same {
  opacity: 0.4;
}
.v-mid .arrow,
.v-next .arrow {
  display: inline-block;
  width: 2ch;
  margin-left: -2ch;
  color: var(--ink-faint);
}
.ver .ref {
  color: var(--warn);
}
.ver .unknown {
  color: var(--ink-faint);
  font-family: var(--nk-font-ui);
  font-size: 12px;
}
.ver .ref.merged {
  color: var(--merged);
}
/* How long it's been outdated, after the package's name. */
.pkg-name .age {
  color: var(--warn);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}
/* Waiting for the channel: the merged violet, like its dot. */
.pkg-name .age.merged {
  color: var(--merged);
}
/* Failing: how long, in the failure's red. */
.pkg-name .age.failing {
  color: var(--danger);
}
.badge {
  display: inline-block;
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 20px;
  font-weight: 500;
  margin-left: 5px;
}
.badge.warn {
  background: var(--warn-soft);
  color: var(--warn);
}
.badge.devel.ok {
  background: var(--ok-soft);
  color: var(--ok-devel);
}
.badge.devel.warn {
  background: var(--warn-soft);
  color: var(--warn-devel);
}
.badge.missing {
  background: var(--danger-soft);
  color: var(--danger);
}
.badge.vuln {
  background: var(--danger-soft);
  color: var(--danger);
}
/* Outdated, but the update is already on master: a solid violet label with
   white text, like GitHub's "Merged". */
.badge.onmaster {
  background: var(--merged-emphasis);
  color: var(--on-badge);
}
/* An open update PR, like GitHub's "Open" and "Draft" labels. */
.badge.propen {
  background: var(--pr-open);
  color: var(--on-badge);
}
.badge.prdraft {
  background: var(--pr-draft);
  color: var(--on-badge);
}
a.badge {
  text-decoration: none;
}
a.badge:hover {
  filter: brightness(1.12);
}
.master-note {
  font-size: 12.5px;
  color: var(--ink-soft);
  background: var(--merged-soft);
  border-radius: 6px;
  padding: 6px 10px;
  margin-bottom: 10px;
}
.badge.neutral {
  background: var(--stale-soft);
  color: var(--ink-soft);
}

.failure-btn {
  font: inherit;
  font-size: 12.5px;
  color: var(--ink-soft);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 4px 9px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.failure-btn:hover {
  background: var(--bg);
  border-color: var(--hairline);
  color: var(--ink);
}
.failure-btn.failing {
  color: var(--danger);
}
/* Nothing to report: muted, no dot. */
.failure-btn.calm {
  color: var(--ink-faint);
}
.failure-btn.calm .status-dot {
  display: none;
}
.failure-btn[aria-expanded="true"] {
  background: var(--surface);
  border-color: var(--hairline-strong);
  color: var(--ink);
}
/* The update cell's status joined to the robot (nixpkgs-update will try
   it, from its queue): kept together on one line, two buttons with a dot
   between, each opening the update panel; no pill behind them, so a row
   with the robot doesn't stand out from those without. The robot green
   when it's to the newest version and the last attempt didn't fail, amber
   when the bot will try but it's unsure (queuedTag). */
.upd-pair {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}
.upd-pair .failure-btn {
  padding-right: 4px;
}
.queued-tag {
  font: inherit;
  font-size: 12.5px;
  display: inline-flex;
  align-items: center;
  padding: 4px 9px 4px 0;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: none;
  color: var(--caution);
  cursor: pointer;
}
.queued-tag::before {
  content: "·";
  padding-right: 5px;
  color: var(--ink-faint);
}
.queued-tag.match {
  color: var(--ok-devel);
  font-weight: 500;
}
.queued-tag:hover {
  filter: brightness(1.15);
}
.bot-icon {
  display: block;
}
.queued-tag:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.failure-na {
  color: var(--ink-faint);
  padding: 4px 9px;
}
/* "build:" / "update:" before the text: only on phones, without the column
   headings. */
.cell-label {
  display: none;
}

/* A source the last sync couldn't refresh: shown, not alarming. */
.stale-note {
  font-size: 12.5px;
  color: var(--ink-soft);
  background: var(--stale-soft);
  border-radius: 6px;
  padding: 6px 10px;
  margin-bottom: 10px;
}
.vuln-note {
  font-size: 12.5px;
  color: var(--danger);
  background: var(--danger-soft);
  border-radius: 6px;
  padding: 6px 10px;
  margin-bottom: 10px;
}
.stale-tag {
  font-size: 10.5px;
  color: var(--ink-soft);
  background: var(--stale-soft);
  border-radius: 4px;
  padding: 1px 5px;
}
.log-excerpt {
  font-size: 12px;
  color: var(--ink-soft);
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 8px 10px;
  margin: 0 0 10px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.gh-links {
  display: inline-flex;
  gap: 6px;
}
.gh-btn {
  font-size: 12px;
  color: var(--ink-soft);
  text-decoration: none;
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 3px 8px;
  white-space: nowrap;
  display: inline-flex;
  gap: 5px;
  align-items: baseline;
}
.gh-btn:hover {
  border-color: var(--hairline-strong);
  color: var(--ink);
  background: var(--bg);
}
.gh-btn b {
  font-weight: 600;
  color: var(--ink);
}
/* None open: still a link, but out of the way. */
.gh-btn[data-zero] {
  color: var(--ink-faint);
  border-color: transparent;
}
.gh-btn[data-zero] b {
  color: inherit;
  font-weight: 500;
}
/* The expand chevron: a round target that lights up with the row, and
   turns down when the row is open. */
.chev {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  color: var(--ink-faint);
  transition:
    transform 0.2s,
    color 0.15s,
    background 0.15s;
}
tbody tr.row:hover .chev {
  color: var(--ink);
  background: var(--bg);
}
tbody tr.row.open .chev {
  transform: rotate(90deg);
  color: var(--accent);
}

tr.detail {
  display: none;
}
tr.detail.open {
  display: table-row;
}
/* An open row and its panel: one block, on the card colour. */
tbody tr.row.open,
tbody tr.detail.open {
  background: var(--surface);
}
tbody tr.detail td {
  padding: 4px 10px 18px 10px;
  border-bottom: 1px solid var(--hairline);
}
tbody tr.row.open td {
  border-bottom-color: transparent;
}
.detail-inner {
  padding-left: 18px;
  /* Takes the width the table gives it, without a say in the column widths:
     otherwise a long panel (the details' Repology chips) makes the table
     redistribute its columns, and the rows above shift when it opens. */
  contain: inline-size;
}
.nix-line {
  font-size: 14px;
  margin-bottom: 10px;
}
/* A package's panel: the verdict at a glance, what it means, then
   sections apart (compared against, people, links). */
.pd {
  display: grid;
  gap: 14px;
  padding-top: 6px;
}
.pd-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 22px;
}
.pd-verdict {
  font-size: 13px;
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 999px;
  white-space: nowrap;
}
.pd-verdict.ok {
  color: var(--ok-devel);
  background: var(--ok-soft);
}
.pd-verdict.warn {
  color: var(--warn);
  background: var(--warn-soft);
}
.pd-verdict.danger {
  color: var(--danger);
  background: var(--danger-soft);
}
.pd-verdict.merged {
  color: var(--merged);
  background: var(--merged-soft);
}
.pd-verdict.neutral {
  color: var(--ink-soft);
  background: var(--stale-soft);
}
/* The versions and the deciding source, as label over value. */
.pd-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 26px;
  margin: 0;
}
.pd-facts dt {
  color: var(--ink-faint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.pd-facts dd {
  margin: 2px 0 0;
  font-size: 13.5px;
  color: var(--ink);
}
.pd-newer {
  color: var(--warn);
  font-weight: 600;
}
.pd-ago {
  color: var(--ink-faint);
}
/* Inline icons (ICONS in app.js): the text's size and colour. */
.ic {
  width: 1.1em;
  height: 1.1em;
  flex: none;
}
/* Which source decided: ours in the accent's tint, Repology grey, master
   in merged's. */
.pd-source {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  font-weight: 500;
  padding: 3px 10px;
  border-radius: 999px;
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pd-source.ours {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.pd-source.repology {
  color: var(--ink-soft);
  background: var(--stale-soft);
}
.pd-source.merged {
  color: var(--merged);
  background: var(--merged-soft);
}
.pd-foot {
  margin: 0;
  font-size: 12px;
  color: var(--ink-faint);
}
.pd-verdict.caution {
  color: var(--caution);
  background: color-mix(in srgb, var(--caution-dot) 16%, transparent);
}
/* The builds panel: a row per system, its status, when it last built and
   what to open, in columns where there's room. */
.br-list {
  display: grid;
  /* Columns sized to what's in them and shared by every row (subgrid), so
     the buttons line up right after the longest detail, not at the far
     edge; the last, empty one takes the rest, for the rows' dividers. */
  grid-template-columns: max-content max-content minmax(0, max-content) max-content 1fr;
  column-gap: 20px;
  border-top: 1px solid var(--hairline);
}
.br {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: center;
  row-gap: 6px;
  padding: 9px 0;
  border-bottom: 1px solid var(--hairline);
  font-size: 13px;
}
.br-sys {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.br-attr {
  color: var(--ink-faint);
  font-size: 12px;
}
.br-st {
  justify-self: start;
  font-size: 12px;
  font-weight: 500;
  padding: 2px 10px;
  border-radius: 999px;
  white-space: nowrap;
}
.br-st.ok {
  color: var(--ok-devel);
  background: var(--ok-soft);
}
.br-st.missing {
  color: var(--danger);
  background: var(--danger-soft);
}
.br-st.caution {
  color: var(--caution);
  background: color-mix(in srgb, var(--caution-dot) 16%, transparent);
}
.br-st.neutral {
  color: var(--ink-soft);
  background: var(--stale-soft);
}
.br-what {
  color: var(--ink-soft);
  min-width: 0;
}
.br-acts {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}
.br-acts .pd-link {
  padding: 3px 9px;
}
@media (max-width: 640px) {
  .br-list {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .br-st {
    justify-self: end;
  }
  .br-what,
  .br-acts {
    grid-column: 1 / -1;
  }
}
.pd-why-body {
  display: grid;
  gap: 10px;
}
.pd-why-body[hidden] {
  display: none;
}
/* "Why?": the explanation's toggle, at the end of the links. */
.pd-why {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--accent);
  background: none;
  border: 0;
  padding: 5px 4px;
  cursor: pointer;
}
.pd-why .ic {
  transition: transform 0.15s;
}
.pd-why[aria-expanded="true"] .ic {
  transform: rotate(180deg);
}
/* The explanation: readable lines, quieter than the facts. */
.pd-text {
  margin: 0;
  max-width: 78ch;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-soft);
}
.pd-text .mono {
  color: var(--ink);
}
.pd-notes {
  display: grid;
  gap: 8px;
  max-width: 78ch;
}
.pd-notes > * {
  margin: 0;
}
/* Each section on its own, a hairline above. */
.pd-sec {
  border-top: 1px solid var(--hairline);
  padding-top: 12px;
}
.pd-sec .other-label {
  margin-top: 0;
}
.pd-sec .repo-chips,
.pd-sec .log-excerpt {
  margin-bottom: 0;
}
/* Maintainers and teams side by side where there's room. */
.pd-people {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0 28px;
}
.pd-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.pd-pills .pd-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--hairline);
  background: var(--bg);
}
.pd-pills button.pd-pill {
  color: var(--accent);
  font-weight: 500;
  cursor: pointer;
}
.pd-pills button.pd-pill:hover,
.pd-pills .pd-pill:has(.maint-btn:hover) {
  border-color: var(--hairline-strong);
}
.pd-pill .maint-btn:hover {
  text-decoration: none;
}
/* A team a list adds (teamsByList): said, quietly, inside its pill. */
.pd-pill-note {
  font-size: 10.5px;
  font-weight: 400;
  color: var(--ink-faint);
}
.pd-pill-go {
  color: var(--ink-faint);
  text-decoration: none;
  font-size: 11.5px;
}
.pd-pill-go:hover {
  color: var(--accent);
}
/* The package's links, as one row of buttons at the foot. */
.pd-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  border-top: 1px solid var(--hairline);
  padding-top: 12px;
}
.pd-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--accent);
  text-decoration: none;
  padding: 5px 12px;
  border-radius: var(--radius);
  border: 1px solid var(--hairline-strong);
  background: var(--surface);
}
.pd-link:hover {
  background: var(--bg);
}
/* A panel's small headings ("Compared against"): like the popovers'. */
.other-label {
  margin: 10px 0 8px;
  color: var(--ink-faint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
/* How old the comparison is, when Repology wasn't asked today. */
.other-label .since {
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}
.repo-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 10px;
}
.repo-chip {
  font-size: 12.5px;
  padding: 4px 11px;
  border-radius: 999px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  color: var(--ink-soft);
  display: inline-flex;
  gap: 6px;
  align-items: baseline;
  /* Never wider than the panel: a long version ("5.1.0~20221114gitd55acb1")
     breaks inside the chip instead of sticking out on a phone. */
  max-width: 100%;
}
.repo-chip[hidden] {
  display: none;
}
.more-btn {
  font: inherit;
  font-size: 12.5px;
  padding: 4px 11px;
  border-radius: 999px;
  border: 1px dashed var(--hairline-strong);
  background: none;
  color: var(--accent);
  cursor: pointer;
}
.more-btn:hover {
  border-style: solid;
  background: var(--bg);
}
.repo-chip .v {
  overflow-wrap: anywhere;
  color: var(--ink);
}
.repo-chip.ahead .v {
  color: var(--warn);
}
.detail-row {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}
/* A package's maintainers: each searches for their packages, with a link to
   their GitHub profile. */
.maintainers {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  align-items: baseline;
  margin-bottom: 10px;
  font-size: 13px;
}
.maintainer {
  display: inline-flex;
  gap: 3px;
  align-items: baseline;
}
.maint-btn {
  font: inherit;
  font-weight: 500;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  cursor: pointer;
}
.maint-btn:hover {
  text-decoration: underline;
}
.none-note {
  color: var(--ink-soft);
}
.files-link {
  font-size: 13px;
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
}
.files-link:hover {
  text-decoration: underline;
}
/* The pages, under the table: "1–200 of 241", then the page links. */
.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 16px 4px 4px;
  font-size: 13px;
}
.page-count {
  color: var(--ink-faint);
  margin-right: 6px;
}
/* The page size, after the page links. */
.page-size {
  margin-left: 10px;
  color: var(--ink-faint);
}
.page-size select {
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 2px 4px;
  margin-left: 4px;
}
.page-size select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.page-btn {
  min-width: 32px;
  padding: 4px 9px;
  text-align: center;
  color: inherit;
  text-decoration: none;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 999px;
}
a.page-btn:hover {
  border-color: var(--hairline-strong);
  color: var(--ink);
}
a.page-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.page-btn[aria-current="page"] {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--hairline-strong));
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  font-weight: 600;
}
.page-gap {
  color: var(--ink-faint);
}
.loading,
.empty,
.error {
  color: var(--ink-faint);
  font-size: 13px;
  padding: 30px 4px;
  text-align: center;
}
.error {
  color: var(--danger);
}
.error code {
  background: var(--bg);
  padding: 1px 5px;
  border-radius: 4px;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
}

/* The last line: nixkeeper (and its version) on GitHub, and on a copy, its
   package lists. Quiet, centred. */
/* Hidden while the data loads (doneLoading shows it): it appears where the
   page ends, rather than being pushed down when the page fills in (a layout
   shift, which a page's speed is also judged by). */
.colophon[hidden] {
  display: none;
}
.colophon {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin: 24px 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--hairline);
  font-size: 12px;
  color: var(--ink-faint);
}
.colophon .files-link {
  color: var(--ink-faint);
  text-decoration: none;
}
.colophon .files-link:hover {
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
}

@media (max-width: 640px) {
  .actions {
    width: 100%;
  }
  /* The box gives up room to the buttons (40px each on a touch screen),
     rather than pushing the last one past the screen's margin. */
  .search {
    flex: 1;
    width: auto;
    min-width: 0;
  }
  .search input {
    min-width: 0;
  }
  .search kbd {
    display: none;
  }
}

/* Phones and narrow windows (where even the wrapped table doesn't fit):
   each package is a card instead of a table row, so nothing scrolls
   sideways. Line 1: name, platforms, chevron. Line 2: the version and its
   badges. Line 3: only what needs attention (failures, open PRs/issues);
   cells with nothing to report are left out. */
@media (max-width: 1080px) {
  /* The filters, on phones and tablets: one row that swipes sideways
     (status, a divider, the lists), fading out at the right edge to show
     there's more; when the data was checked on a line of its own under
     them. */
  .filterbar {
    display: block;
    padding: 12px 0 10px;
  }
  .filters,
  .chips {
    flex-wrap: nowrap;
  }
  .filters {
    overflow-x: auto;
    scrollbar-width: none;
    margin: 0 -20px; /* to the screen's edges */
    padding: 2px 36px 2px 20px; /* the last chip clears the fade */
    scroll-padding: 0 20px;
    scroll-snap-type: x proximity;
    mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
  }
  .filters::-webkit-scrollbar {
    display: none;
  }
  .stat-btn,
  .plat-filter {
    flex: none;
    white-space: nowrap;
    scroll-snap-align: start;
  }
  .lists-label {
    flex: none;
  }
  .filterbar .meta {
    justify-content: flex-end;
    margin-top: 8px;
  }
  .filterbar .checked {
    font-size: 12px;
  }
  /* Only the filters stay at the top: the whole header, stacked, would
     cover a fifth of a phone's screen. */
  .sticky-top {
    display: contents;
  }
  .filterbar {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--bg);
    border-bottom: 1px solid var(--hairline);
    /* edge to edge, so nothing shows beside it */
    margin: 0 -20px;
    padding: 12px 20px 10px;
  }
  /* Once stuck at the top (scrolled past), just the chips: "checked ..."
     comes back at the top of the page, like the logo. */
  .filterbar.stuck .meta {
    display: none;
  }
  table,
  tbody,
  tbody tr.detail td {
    display: block;
  }
  thead {
    display: none;
  }
  tbody tr.row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 6px;
    padding: 12px 6px;
    border-bottom: 1px solid var(--hairline);
    /* Cards off screen aren't laid out until scrolled near: with thousands
       of packages, a redraw takes a third of the time. (Real table rows, on
       wider screens, can't skip their layout this way.) Find in page still
       finds them. 72px is about a card's height inside its padding, so the
       scrollbar is about right before they're drawn. */
    content-visibility: auto;
    contain-intrinsic-size: auto 72px;
  }
  tbody tr.row.open {
    border-bottom-color: transparent;
  }
  tbody tr.row td {
    display: block;
    padding: 0;
    border-bottom: 0;
  }
  tbody tr.row td.c-name {
    order: 0;
    flex: 1 1 0;
    min-width: 0;
  }
  tbody tr.row td.c-chev {
    order: 1;
    padding: 0 4px;
  }
  tbody tr.row td.c-ver {
    order: 2;
    flex-basis: 100%;
    padding-left: 18px;
    white-space: normal;
  }
  tbody tr.row td.c-build {
    order: 3;
  }
  tbody tr.row td.c-update {
    order: 4;
  }
  tbody tr.row td.c-gh {
    order: 5;
  }
  /* Line 3 lines up with the version (the buttons have 6px of padding). */
  tbody tr.row td.c-build,
  tbody tr.row td.c-update {
    margin-left: 12px;
  }
  tbody tr.row td.c-gh {
    margin-left: 18px;
  }
  tbody tr.row td.quiet,
  tbody tr.row td:has(> .failure-na),
  tbody tr.row td:has(> [data-quiet]) {
    display: none;
  }
  .pkg-name .n {
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .failure-btn {
    padding: 2px 6px;
  }
  .cell-label {
    display: inline;
    color: var(--ink-faint);
    margin-right: -2px;
  }
  tr.detail.open {
    display: block;
  }
  tbody tr.detail td {
    padding: 4px 6px 18px;
  }
  .detail-inner {
    padding-left: 12px;
  }
}

/* Touch screens (a finger, not a mouse pointer): bigger targets, about
   40px for the toolbar and the filters, as touch guidelines ask. The
   layout stays the same; only the hit areas grow. */
@media (pointer: coarse) {
  .btn {
    height: 40px;
    min-width: 40px;
  }
  .search {
    height: 40px;
  }
  .stat-btn,
  .plat-filter {
    padding: 8px 13px;
  }
  .theme-panel label {
    padding: 10px 12px;
  }
  .gh-btn,
  .more-btn {
    padding: 6px 10px;
  }
  .failure-btn {
    padding: 6px 9px;
  }
  .chev {
    width: 36px;
    height: 36px;
  }
  .plats {
    padding: 3px 9px;
  }
  /* Everything else a finger taps: at least 24px each way (WCAG 2.2's
     minimum target size), most of it more. */
  .plat {
    padding: 6px 0;
  }
  .view-x {
    display: inline-block;
    padding: 6px 8px;
    margin: -6px -8px -6px 0;
  }
  .help-btn {
    width: 32px;
    height: 32px;
  }
  .checked,
  .hl-mode,
  .hl-all,
  .queued-tag,
  .refine-btn,
  .refine-age select,
  a.badge {
    min-height: 32px;
  }
  .files-link {
    padding-block: 4px;
  }
}

/* Less motion for people whose system asks for it (Reduce motion on macOS
   and iOS, Animation effects off on Windows, ...): changes happen at once
   instead of animating. Covers anything added later too. */
/* biome-ignore-start lint/complexity/noImportantStyles: it has to win over every transition on the page, however specific */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}
/* biome-ignore-end lint/complexity/noImportantStyles: - */
