:root {
  color-scheme: light;
  --page: #f9f9f7;
  --surface: #fcfcfb;
  --surface-hover: #f0efec;
  --text-primary: #0b0b0b;
  --text-secondary: #52514e;
  --text-muted: #898781;
  --gridline: #e1e0d9;
  --baseline: #c3c2b7;
  --border: rgba(11, 11, 11, 0.1);
  --series-1: #2a78d6;
  --series-2: #eb6834;
  --series-3: #1baf7a;
  --highlight: rgba(42, 120, 214, 0.14);
  --success-text: #006300;
  --status-good: #0ca30c;
  --status-serious: #ec835a;
  /* The colors of a diff on GitHub, for the lines added and deleted */
  --diff-added: #1a7f37;
  --diff-deleted: #d1242f;
  --shadow: 0 8px 24px rgba(11, 11, 11, 0.12);
  /* The light a tilted person card catches, and its faint rainbow sheen */
  --glare: rgba(255, 255, 255, 0.7);
  --sheen-blend: multiply;
  --sheen-opacity: 0.16;
  /* The metals of the badges, lit from the top left; they read on both themes */
  --bronze: #b4682e;
  --bronze-light: #f3c79a;
  --bronze-ring: #7d4318;
  --silver: #9aa3ad;
  --silver-light: #f4f6f8;
  --silver-ring: #626b75;
  --gold: #dda21a;
  --gold-light: #fff1a8;
  --gold-ring: #9c6c00;
  --radius: 12px;
  --font: system-ui, -apple-system, 'Segoe UI', sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    color-scheme: dark;
    --page: #0d0d0d;
    --surface: #1a1a19;
    --surface-hover: #242423;
    --text-primary: #f0efec;
    --text-secondary: #c3c2b7;
    --text-muted: #898781;
    --gridline: #2c2c2a;
    --baseline: #383835;
    --border: rgba(255, 255, 255, 0.1);
    --series-1: #3987e5;
    --series-2: #d95926;
    --series-3: #199e70;
    --highlight: rgba(57, 135, 229, 0.22);
    --success-text: #0ca30c;
    --diff-added: #3fb950;
    --diff-deleted: #f85149;
    --shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
    --glare: rgba(255, 255, 255, 0.16);
    --sheen-blend: screen;
    --sheen-opacity: 0.15;
  }
}

:root[data-theme='dark'] {
  color-scheme: dark;
  --page: #0d0d0d;
  --surface: #1a1a19;
  --surface-hover: #242423;
  --text-primary: #f0efec;
  --text-secondary: #c3c2b7;
  --text-muted: #898781;
  --gridline: #2c2c2a;
  --baseline: #383835;
  --border: rgba(255, 255, 255, 0.1);
  --series-1: #3987e5;
  --series-2: #d95926;
  --series-3: #199e70;
  --highlight: rgba(57, 135, 229, 0.22);
  --success-text: #0ca30c;
  --diff-added: #3fb950;
  --diff-deleted: #f85149;
  --shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  --glare: rgba(255, 255, 255, 0.16);
  --sheen-blend: screen;
  --sheen-opacity: 0.15;
}

* {
  box-sizing: border-box;
}

/* Hidden means hidden, whatever display the element's own rules give it: a card or a tile shown as a grid or a flex box
   would otherwise stay visible. */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--text-primary);
  font: 14px/1.5 var(--font);
}

a {
  color: inherit;
}

code {
  font-size: 0.95em;
}

/* Layout: the pages and actions in a sidebar, the page beside it; a bar on top of it on narrower screens, where the
   tables need the width. */
.app {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  min-height: 100vh;
}

.sidebar {
  position: sticky;
  top: 0;
  z-index: 8;
  display: flex;
  flex-direction: column;
  gap: 24px;
  height: 100vh;
  padding: 24px 14px 16px;
  border-right: 1px solid var(--border);
  background: var(--surface);
}

.brand {
  display: grid;
  padding: 0 10px;
  color: inherit;
  text-decoration: none;
}

.brand-title {
  font-size: 18px;
  font-weight: 650;
}

.brand .org {
  color: var(--text-secondary);
  font-size: 13px;
}

.nav {
  display: grid;
  gap: 2px;
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  color: var(--text-secondary);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
}

.nav-link:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

/* The current page: a light tint, its icon in the accent colour. */
.nav-link[aria-current='page'] {
  background: color-mix(in srgb, var(--series-1) 12%, transparent);
  color: var(--text-primary);
}

.nav-link[aria-current='page'] svg {
  color: var(--series-1);
}

.nav-link svg {
  flex: none;
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sidebar-footer {
  display: grid;
  gap: 12px;
  margin-top: auto;
}

.sidebar .sync {
  justify-self: start;
}

.sidebar .header-actions {
  padding: 0 4px;
}

/* At the bottom of the sidebar, the sync menu and the button labels open upwards. */
.sidebar .sync-menu-panel {
  top: auto;
  right: auto;
  bottom: calc(100% + 6px);
  left: 0;
}

.sidebar .icon-button[data-label]::after {
  top: auto;
  right: auto;
  bottom: calc(100% + 6px);
  left: 0;
}

@media (max-width: 1279px) {
  .app {
    grid-template-columns: minmax(0, 1fr);
  }

  .sidebar {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 16px;
    height: auto;
    padding: 10px 16px;
    border-right: 0;
    border-bottom: 1px solid var(--border);
  }

  .brand {
    grid-auto-flow: column;
    align-items: baseline;
    gap: 8px;
    padding: 0;
  }

  .nav {
    display: flex;
    overflow-x: auto;
  }

  .sidebar-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 0 auto;
  }

  /* On a narrow bar the icons may wrap to the left: the menu hangs from the bar's right edge so that it always fits. */
  .sidebar .sync-menu {
    position: static;
  }

  .sidebar .sync-menu-panel {
    top: calc(100% + 6px);
    right: 16px;
    bottom: auto;
    left: auto;
  }

  .sidebar .icon-button[data-label]::after {
    top: calc(100% + 6px);
    right: 0;
    bottom: auto;
    left: auto;
  }
}

/* Beside the sidebar, the page starts right after it; above the narrow bar, it is centered. */
.page {
  width: 100%;
  max-width: 1320px;
  padding: 32px 40px 48px;
}

@media (max-width: 1279px) {
  .page {
    max-width: 1240px;
    margin: 0 auto;
    padding: 24px 16px 48px;
  }
}

.route {
  display: grid;
  gap: 16px;
}

.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px 24px;
  margin-bottom: 20px;
}

h1 {
  margin: 0;
  font-size: 24px;
  font-weight: 650;
  letter-spacing: -0.01em;
}

h1 .org {
  color: var(--text-secondary);
  font-weight: 500;
}

h2,
h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}

.mini h3 {
  font-size: 13px;
}

.card-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
}

.definitions {
  display: grid;
  grid-template-columns: minmax(10rem, 14rem) minmax(0, 1fr);
  gap: 8px 24px;
  margin: 14px 0 0;
}

.definitions dt {
  font-weight: 600;
}

.definitions dd {
  max-width: 75ch;
  margin: 0;
  color: var(--text-secondary);
}

@media (max-width: 600px) {
  .definitions {
    grid-template-columns: minmax(0, 1fr);
  }

  .definitions dd {
    margin-bottom: 8px;
  }
}

.subtitle,
.card-sub {
  margin: 2px 0 0;
  color: var(--text-secondary);
}

.card-sub {
  font-size: 13px;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.icon-button {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text-secondary);
  cursor: pointer;
}

.icon-button:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

/* Label of an icon button, shown at once on hover or keyboard focus, aligned on its right edge to stay on screen. */
.icon-button[data-label] {
  position: relative;
}

.icon-button[data-label]::after {
  content: attr(data-label);
  position: absolute;
  z-index: 6;
  top: calc(100% + 6px);
  right: 0;
  padding: 4px 8px;
  border-radius: 6px;
  background: var(--text-primary);
  color: var(--surface);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s;
}

.icon-button[data-label]:hover::after,
.icon-button[data-label]:focus-visible::after {
  opacity: 1;
}

.sync-menu[open] .icon-button::after {
  display: none;
}

.icon-button svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Sync menu: a quick or a full sync started from the page */
.sync-menu {
  position: relative;
}

.sync-menu summary {
  list-style: none;
}

.sync-menu summary::-webkit-details-marker {
  display: none;
}

.sync-menu-panel {
  position: absolute;
  z-index: 5;
  top: calc(100% + 6px);
  right: 0;
  display: grid;
  gap: 2px;
  width: 280px;
  max-width: calc(100vw - 32px);
  padding: 6px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: var(--shadow);
}

.sync-menu-panel button {
  display: grid;
  gap: 2px;
  padding: 8px 10px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--text-primary);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.sync-menu-panel button:hover:not(:disabled) {
  background: var(--surface-hover);
}

.sync-menu-panel button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* While the page starts a sync, the chosen entry and the menu icon turn: one click is enough. */
.sync-menu-panel button.is-starting {
  opacity: 1;
  cursor: progress;
}

.sync-menu-panel button.is-starting strong::after {
  content: '';
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-left: 8px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -1px;
  animation: spin 0.8s linear infinite;
}

.sync-menu.is-starting summary svg {
  animation: spin 0.8s linear infinite;
}

.sync-menu-panel span {
  color: var(--text-secondary);
  font-size: 12px;
}

.sync-menu-error {
  margin: 4px 10px 6px;
  padding-left: 10px;
  border-left: 3px solid var(--status-serious);
  font-size: 13px;
}

.sync.is-syncing .sync-dot {
  animation: pulse 1.2s ease-out infinite;
}

/* Theme toggle: the moon switches to dark mode, the sun back to light mode. */
.theme-toggle[aria-pressed='true'] .icon-moon,
.theme-toggle[aria-pressed='false'] .icon-sun {
  display: none;
}

/* Lock screen */
.lock {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: 16px;
}

.lock-card {
  display: grid;
  gap: 16px;
  width: min(100%, 380px);
  padding: 28px 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.lock-card h1 {
  font-size: 20px;
}

.lock-field {
  display: grid;
  gap: 6px;
  color: var(--text-secondary);
  font-size: 13px;
}

.lock-field input {
  width: 100%;
  font-size: 14px;
}

.lock-error {
  margin: 0;
  padding-left: 10px;
  border-left: 3px solid var(--status-serious);
  font-size: 13px;
}

.lock-submit,
.button-primary {
  padding: 9px 14px;
  border: 0;
  border-radius: 10px;
  background: var(--text-primary);
  color: var(--surface);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.lock-submit:disabled {
  opacity: 0.6;
  cursor: progress;
}

.button-secondary {
  padding: 9px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: transparent;
  color: var(--text-primary);
  font: inherit;
  cursor: pointer;
}

.button-secondary:hover {
  background: var(--surface-hover);
}

/* Confirmation before a heavy action */
.confirm {
  width: min(100% - 32px, 440px);
  padding: 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  box-shadow: var(--shadow);
}

.confirm::backdrop {
  background: rgba(11, 11, 11, 0.45);
}

.confirm h2 {
  font-size: 17px;
}

.confirm p {
  margin: 10px 0 0;
  color: var(--text-secondary);
}

.confirm-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 22px;
}

/* Sync status */
.sync {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-secondary);
  font-size: 13px;
}

/* A dot that stays round when the label beside it takes two lines. */
.sync-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-muted);
}

.sync.is-live .sync-dot {
  background: var(--status-good);
}

.sync.is-stale .sync-dot,
.sync.is-error .sync-dot {
  background: var(--status-serious);
}

.sync.is-pulsing .sync-dot {
  animation: pulse 1.2s ease-out 2;
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(12, 163, 12, 0.5);
  }
  100% {
    box-shadow: 0 0 0 10px rgba(12, 163, 12, 0);
  }
}

/* Filters */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 20px;
}

.segmented {
  display: inline-flex;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}

.segmented button {
  padding: 6px 14px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  cursor: pointer;
}

.segmented button:hover {
  background: var(--surface-hover);
}

.segmented button[aria-checked='true'] {
  background: var(--text-primary);
  color: var(--surface);
  font-weight: 600;
}

/* A period the synced data does not cover yet. */
.segmented button:disabled {
  background: transparent;
  color: var(--text-muted);
  cursor: not-allowed;
}

/* On a phone, the periods share the whole width. */
@media (max-width: 600px) {
  .segmented {
    flex: 1 1 100%;
  }

  .segmented button {
    flex: 1;
    padding: 6px 4px;
    white-space: nowrap;
  }
}

.date-range {
  position: relative;
}

.date-range summary {
  display: flex;
  align-items: center;
  gap: 8px;
  list-style: none;
  cursor: pointer;
}

.date-range summary::-webkit-details-marker {
  display: none;
}

.date-range summary svg {
  flex: none;
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-width: 1.3;
  color: var(--text-secondary);
}

/* Picked dates replace the preset periods: they look selected the same way. */
.date-range.is-active summary {
  border-color: var(--text-primary);
  background: var(--text-primary);
  color: var(--surface);
  font-weight: 600;
}

.date-range.is-active summary svg {
  color: inherit;
}

.date-range-panel {
  position: absolute;
  z-index: 5;
  top: calc(100% + 6px);
  left: 0;
  display: grid;
  gap: 10px;
  width: 300px;
  max-width: calc(100vw - 32px);
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: var(--shadow);
}

.date-range-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.date-range-fields label {
  display: grid;
  gap: 4px;
  color: var(--text-secondary);
  font-size: 12px;
}

.date-range-fields input {
  min-width: 0;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text-primary);
  font: inherit;
}

.date-range-note {
  margin: 0;
  color: var(--text-muted);
  font-size: 12px;
}

/* On a phone the button may sit anywhere in the wrapped filters: the panel takes their whole width instead. */
@media (max-width: 640px) {
  .filters {
    position: relative;
  }

  .date-range {
    position: static;
  }

  .date-range-panel {
    right: 0;
    width: auto;
  }
}

.search {
  flex: 0 1 260px;
  min-width: 0;
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text-primary);
  font: inherit;
}

button:focus-visible,
input:focus-visible,
a:focus-visible,
summary:focus-visible,
.hit:focus-visible {
  outline: 2px solid var(--series-1);
  outline-offset: 2px;
}

/* Layout */
main {
  display: grid;
  gap: 16px;
  transition: opacity 0.2s;
}

main.is-loading {
  opacity: 0.4;
}

.grid-2 {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: 16px;
}

.grid-even {
  container-type: inline-size;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));
}

/* The four lists of the unblock page, two by two, one by one on narrow screens. */
.unblock-lists {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

@media (max-width: 900px) {
  .unblock-lists {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Three cards on two columns: the last one takes the whole second row rather than half of it. */
@container (min-width: 776px) and (max-width: 1171px) {
  .grid-even > :nth-child(3):last-child {
    grid-column: 1 / -1;
  }
}

@media (max-width: 900px) {
  .grid-2 {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 600px) {
  .card {
    padding: 16px;
  }

  .tile-value {
    font-size: 26px;
  }
}

.card {
  min-width: 0;
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.empty {
  padding: 16px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

/* Stat tiles */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 16px 24px;
  margin-top: 14px;
}

.tile-group {
  margin-top: 18px;
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.tile-group + .tiles {
  margin-top: 8px;
}

/* The label on top, the value at the bottom: values line up across a row whatever the lines of their labels. */
.tile {
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 2px;
}

.tile-label {
  color: var(--text-secondary);
  font-size: 13px;
}

.tile-value-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.tile-value {
  font-variant-numeric: tabular-nums;
  font-size: 30px;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.tile-bump {
  color: var(--success-text);
  font-size: 13px;
  font-weight: 600;
  opacity: 0;
  transform: translateY(4px);
  transition:
    opacity 300ms ease,
    transform 400ms var(--ease-out);
}

.tile-bump.is-visible {
  opacity: 1;
  transform: none;
}

/* Charts */
.chart {
  position: relative;
  height: 260px;
  margin-top: 12px;
}

.chart.chart-sm {
  height: 170px;
  margin-top: 4px;
}

.bar-chart {
  margin-top: 12px;
}

.chart svg,
.bar-chart svg {
  display: block;
  overflow: visible;
}

.gridline {
  stroke: var(--gridline);
  stroke-width: 1;
}

.baseline {
  stroke: var(--baseline);
  stroke-width: 1;
}

.tick,
.axis-label {
  fill: var(--text-muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.bar-chart .axis-label {
  fill: var(--text-secondary);
  font-size: 12px;
}

.value-label {
  fill: var(--text-secondary);
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.bar-chart .value-label {
  font-size: 12px;
}

.bar {
  fill: var(--series-1);
  transition: opacity 0.15s;
}

.bar-group.is-partial .bar {
  opacity: 0.45;
}

.bar-group.is-active .bar {
  opacity: 0.75;
}

.hit {
  fill: transparent;
}

.chart-empty {
  margin: 0;
  padding: 24px 0;
  color: var(--text-secondary);
  text-align: center;
}

/* What the columns of a table count: there to be found, quieter than the data. */
.table-legend {
  columns: 2 320px;
  column-gap: 32px;
  margin: 12px 0 0;
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.5;
}

.table-legend div {
  margin-bottom: 3px;
  break-inside: avoid;
}

.table-legend dt,
.table-legend dd {
  display: inline;
  margin: 0;
}

.table-legend dt {
  color: var(--text-secondary);
  font-weight: 500;
}

.table-legend dt::after {
  content: '\00a0: ';
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin-top: 10px;
  color: var(--text-secondary);
  font-size: 12px;
}

.legend span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.swatch {
  width: 10px;
  height: 10px;
  border-radius: 2px;
}

.minis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: 16px 24px;
  margin-top: 14px;
}

.mini {
  min-width: 0;
}

/* Four small charts: in a row on a wide screen, two by two below, one by one on a phone. */
.minis.minis-four {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 1440px) {
  .minis.minis-four {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (max-width: 600px) {
  .minis.minis-four {
    grid-template-columns: minmax(0, 1fr);
  }
}

.chart-data {
  margin-top: 8px;
  color: var(--text-secondary);
  font-size: 13px;
}

.chart-data summary {
  cursor: pointer;
}

.chart-data .table-wrap {
  max-height: 280px;
  margin-top: 8px;
}

/* Review matrix: the intensity of a cell says how many pull requests of the row its column reviewed. */
.heatmap {
  margin-top: 12px;
}

.heatmap svg {
  display: block;
  overflow: visible;
}

.heatmap .axis-label {
  fill: var(--text-secondary);
  font-size: 12px;
}

.heat-cell {
  transition: opacity 0.15s;
}

.heat-cell.is-empty {
  fill: var(--surface-hover);
}

.heat-group {
  outline: none;
}

.heat-group.is-active .heat-cell,
.heat-group:focus-visible .heat-cell {
  stroke: var(--text-primary);
  stroke-width: 1.5;
}

.heat-label {
  fill: var(--text-primary);
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.heat-label.is-strong {
  fill: #fff;
}

/* The median of a stage, inside its part of the bar: dark on every series color, in both themes. */
.stage-label {
  fill: #141413;
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.card-note {
  margin: 12px 0 0;
  color: var(--text-muted);
  font-size: 12px;
}

/* On a phone, the most frequent pairs replace the matrix. */
.pairs {
  margin: 12px -8px 0;
  padding: 0;
  list-style: none;
}

.pair-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 8px;
}

.pair-avatars {
  display: flex;
}

.pair-avatars .avatar + .avatar {
  margin-left: -6px;
  box-shadow: 0 0 0 2px var(--surface);
}

.pair-count {
  color: var(--text-secondary);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Team page: the people who left, with their last activity. */
.former-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: 10px 24px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}

.former-list li {
  display: grid;
  justify-items: start;
  gap: 2px;
  min-width: 0;
}


/* Under the name, past the avatar. */
.former-last {
  padding-left: 32px;
  color: var(--text-secondary);
  font-size: 13px;
}

/* Team page: the repository filter, then one card per person, as many columns as fit. */
.team-toolbar {
  display: flex;
}

.person-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 270px), 1fr));
  gap: 16px;
}

/* The whole card opens the person's details: the button of its head stretches over it. Its figures sit at its bottom,
   in line with those of the cards beside it, with or without badges above them. The cards of repositories share it. */
.person-card,
.repo-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  transition:
    border-color 160ms ease,
    box-shadow 160ms ease,
    transform 160ms var(--ease-out);
}

.person-card:hover,
.repo-card:hover {
  border-color: var(--baseline);
  box-shadow: var(--shadow);
  transform: translateY(-2px);
}

.person-card:has(.person-card-head:focus-visible),
.repo-card:has(.repo-card-head:focus-visible) {
  outline: 2px solid var(--series-1);
  outline-offset: 2px;
}

.person-card-head {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.person-card-head::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.person-card-head:focus-visible {
  outline: none;
}

.person-card-avatar {
  flex: none;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--gridline);
}

.person-card-name {
  display: grid;
  min-width: 0;
}

.person-card-name strong,
.person-card-name span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.person-card-name strong {
  font-size: 16px;
}

.person-card-name span {
  color: var(--text-secondary);
  font-size: 13px;
}

.person-card-stack {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 22px;
}

.person-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px 10px;
  margin: 0;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.person-card > .person-stats {
  margin-top: auto;
}

.person-stats div {
  display: grid;
  align-content: start;
  gap: 2px;
  min-width: 0;
}

.person-stats dt {
  overflow: hidden;
  color: var(--text-secondary);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.person-stats dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
  font-size: 20px;
  font-weight: 600;
  line-height: 1.2;
}

/* Monthly report: the figures of a month in a table, by group, each change on a tag colored by whether it goes the
   right way; then short lists. */
.report-table thead th {
  padding: 8px 6px;
}

.report-table tbody th {
  font-weight: 500;
}

.report-table tbody tr:hover th {
  background: var(--surface-hover);
}

.report-group th {
  padding-top: 16px;
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.report-value {
  font-weight: 600;
}

.report-change {
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--surface-hover);
  color: var(--text-primary);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.report-change.is-better {
  background: color-mix(in srgb, var(--series-3) 26%, var(--surface));
}

.report-change.is-worse {
  background: color-mix(in srgb, var(--series-2) 26%, var(--surface));
}

.report-list {
  display: grid;
  gap: 10px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}

.report-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-width: 0;
}

.report-champions li {
  align-items: flex-start;
}

.report-champions .award-leaders {
  align-items: flex-end;
  text-align: right;
}

.report-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
  white-space: nowrap;
}

/* Analysis page: one card per finding, two by two when there is room, its level in a tag. */
.findings {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 440px), 1fr));
  gap: 16px;
}

.findings:empty {
  display: none;
}

.finding {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.finding-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px 12px;
}

.finding-area {
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.finding-level {
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--surface-hover);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.finding-level.is-high {
  background: color-mix(in srgb, var(--series-2) 26%, var(--surface));
  color: var(--text-primary);
}

.finding-level.is-good {
  background: color-mix(in srgb, var(--series-3) 26%, var(--surface));
  color: var(--text-primary);
}

.finding-title {
  font-size: 16px;
}

.finding-text {
  margin: 0;
  color: var(--text-secondary);
  line-height: 1.5;
}

.finding-text strong {
  color: var(--text-primary);
}

.finding-figure {
  display: grid;
  gap: 8px;
  margin: 0;
}

.finding-figure figcaption {
  color: var(--text-muted);
  font-size: 12px;
}

.finding-figure .legend {
  margin-top: 0;
}

.finding-bars,
.finding-rows,
.finding-changes,
.analysis-clear {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.finding-bars li {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr) 4rem;
  align-items: center;
  gap: 10px;
  font-size: 13px;
}

.finding-bar-label {
  overflow: hidden;
  color: var(--text-secondary);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.finding-bar {
  height: 10px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--surface-hover);
}

.finding-bar > span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--series-1);
}

.finding-bar-value {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  text-align: right;
}

.finding-rows li,
.finding-changes li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 12px;
  min-width: 0;
  font-size: 13px;
}

.finding-row-name,
.finding-row-figures {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.finding-row-figures {
  margin-left: auto;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.finding-workflow {
  overflow: hidden;
  color: var(--text-muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.finding-change {
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.finding-change strong {
  color: var(--text-primary);
}

.finding-stack {
  display: flex;
  gap: 2px;
  height: 14px;
  overflow: hidden;
  border-radius: 999px;
}

.finding-stack > span {
  flex-basis: 0;
  min-width: 2px;
}

.finding-action {
  margin: 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--surface-hover);
  font-size: 13px;
  line-height: 1.5;
}

.finding-link {
  align-self: flex-start;
  margin-top: auto;
  color: var(--text-secondary);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}

.finding-link::after {
  content: ' →';
}

.finding-link:hover {
  color: var(--text-primary);
  text-decoration: underline;
}

.analysis-clear {
  margin-top: 12px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  color: var(--text-secondary);
  font-size: 13px;
}

.analysis-clear li {
  display: flex;
  gap: 8px;
}

.analysis-check {
  flex: none;
  color: var(--success-text);
  font-weight: 700;
}

.analysis-clear .is-few .analysis-check {
  color: var(--text-muted);
}

/* Hall of fame: one block per badge, three by three on a wide screen, two by two below, one by one on a phone; the
   months in a table. */
.awards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px 32px;
  margin-top: 16px;
}

@media (min-width: 1440px) {
  .awards {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (max-width: 600px) {
  .awards {
    grid-template-columns: minmax(0, 1fr);
  }
}

.award {
  display: grid;
  align-content: start;
  gap: 14px;
  min-width: 0;
}

.award-head {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.award-icon {
  font-size: 24px;
  line-height: 1;
}

.award-name {
  display: grid;
  min-width: 0;
}

.award-name span {
  color: var(--text-secondary);
  font-size: 12px;
}

.award-months {
  display: grid;
  gap: 12px;
  margin: 0;
}

/* The champions of the badges line up month by month, whatever the length of their names: each block spans three
   rows of the grid, shared with the blocks beside it. */
.awards.is-aligned > .award {
  grid-row: span 3;
  grid-template-rows: subgrid;
}

.awards.is-aligned .award-months {
  display: contents;
}

.award-months dt {
  color: var(--text-secondary);
  font-size: 12px;
}

.award-months dd {
  margin: 4px 0 0;
}

/* Each leader on a line, then how much: the same everywhere, whatever the width. */
.award-leaders {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
}

.award-value {
  color: var(--text-secondary);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.award-former {
  color: var(--text-secondary);
  font-style: italic;
}

/* Each badge's holders scroll past five and a half of them, so that the page does not grow as months go by; the
   padding keeps focus rings inside, and the medals take the tooltip of the charts (theirs would be cut). */
.award-holders {
  display: grid;
  gap: 12px;
  max-height: 320px;
  margin: -4px;
  padding: 4px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  list-style: none;
}

.award-holders .badge-tip {
  display: none;
}

.award-holders li {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}

/* The person, then how long: a long name gets the whole width, cut short rather than over the figure. */
.award-holder {
  display: grid;
  justify-items: start;
  gap: 2px;
  min-width: 0;
}

.award-holder .person-link,
.award-leaders .person-link {
  max-width: 100%;
}

.award-holder .person-link-name,
.award-leaders .person-link-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A column per badge, all as wide, the month a little narrower: long names are cut short and amounts take two lines
   when they must, so that the table fits from 1080 px; narrower, it scrolls sideways. */
.awards-table {
  table-layout: fixed;
  min-width: 840px;
}

.awards-table thead th:first-child {
  width: 120px;
}

.awards-table td {
  vertical-align: top;
}

.awards-table .award-value {
  white-space: normal;
}

/* Its heads are plain text, not the sort buttons of the other tables: they take the padding of the cells. */
.awards-table thead th {
  padding: 8px 6px;
}

.awards-table tbody th {
  font-weight: 600;
}

/* The month stays visible while the table scrolls sideways: its cell is opaque, so it takes the row's hover too, and
   its transition. */
.awards-table tbody tr:hover th {
  background: var(--surface-hover);
}

/* Repositories page: one card per repository, like those of people but wider, for their nine figures. The whole card
   opens the repository's dialog: the button of its head stretches over it, under the people, who open their own. */
.repo-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  gap: 16px;
}

.repo-card > .person-stats {
  margin-top: auto;
}

.repo-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.repo-card-head::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.repo-card-head:focus-visible {
  outline: none;
}

.repo-card-name {
  overflow: hidden;
  font-size: 16px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.repo-card .person-link {
  position: relative;
  z-index: 1;
}

.repo-card-head .stack-logos {
  margin-left: auto;
}

.repo-card-people {
  display: grid;
  gap: 8px;
}

.repo-card-people-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: var(--text-secondary);
  font-size: 12px;
}

.repo-card-people ul {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.repo-card-people li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
}

.repo-card-people p {
  margin: 0;
  font-size: 13px;
}

.repo-card-share,
.fragile-share {
  color: var(--text-secondary);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The bus factor of a repository: quiet, unless the repository rests on a single person or on people who left. */
.bus-factor {
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--surface-hover);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.bus-factor.is-fragile {
  background: color-mix(in srgb, var(--series-2) 26%, var(--surface));
  color: var(--text-primary);
}

/* The repositories that rest on a single person: the repository, the person, the share they wrote. */
.fragile-list {
  display: grid;
  gap: 10px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}

.fragile-list li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
  align-items: center;
  gap: 4px 16px;
}

.fragile-repo {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.fragile-repo .repo-link {
  overflow: hidden;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 600px) {
  .fragile-list li {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .fragile-share {
    grid-column: 1 / -1;
  }
}

/* Badges, like GitHub achievements: a round medal of its tier's metal, its icon in the middle, the length of its run of
   months on a tab. On a card they sit in a row under the stack; in the dialog, larger, on the right of the head. */
.person-badges,
.person-dialog-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.person-dialog-badges {
  gap: 14px;
  margin-left: auto;
  padding-right: 4px;
}

/* On a card, the badges sit above the button that covers it: they show what they mean on hover, and a click on them
   still opens the dialog. Over a medal the pointer stays the classic arrow. */
.person-card .person-badges {
  position: relative;
  z-index: 1;
  cursor: pointer;
}

.badge-medal {
  cursor: default;
}

.person-card:hover,
.person-card:focus-within,
.repo-card:hover,
.repo-card:focus-within {
  z-index: 1;
}

/* A medal: a brushed ring of its tier's metal around a domed face, lit from the top left, its icon in the middle. */
.badge-medal {
  --metal: var(--bronze);
  --metal-light: var(--bronze-light);
  --metal-ring: var(--bronze-ring);
  --size: 34px;
  position: relative;
  display: inline-grid;
  flex: none;
  place-items: center;
  width: var(--size);
  height: var(--size);
  padding: 3px;
  border-radius: 50%;
  background: conic-gradient(
    from 200deg,
    var(--metal-light),
    var(--metal) 18%,
    var(--metal-ring) 32%,
    var(--metal) 46%,
    var(--metal-light) 58%,
    var(--metal) 72%,
    var(--metal-ring) 86%,
    var(--metal-light)
  );
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.12),
    0 2px 4px rgba(0, 0, 0, 0.1),
    0 8px 18px -8px rgba(0, 0, 0, 0.3);
  outline-offset: 3px;
}

.badge-medal.is-silver {
  --metal: var(--silver);
  --metal-light: var(--silver-light);
  --metal-ring: var(--silver-ring);
}

.badge-medal.is-gold {
  --metal: var(--gold);
  --metal-light: var(--gold-light);
  --metal-ring: var(--gold-ring);
}

.badge-medal.is-large {
  --size: 58px;
  padding: 4px;
}

.badge-face {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 25%, var(--metal-light), var(--metal) 58%, var(--metal-ring));
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.35),
    inset 0 -2px 3px rgba(255, 255, 255, 0.3);
}

/* The light on the dome */
.badge-face::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: linear-gradient(150deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0) 46%);
  pointer-events: none;
}

.badge-icon {
  position: relative;
  font-size: 15px;
  line-height: 1;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35));
}

.is-large .badge-icon {
  font-size: 26px;
}

/* The run of months, on a tab of the same metal */
.badge-streak {
  position: absolute;
  right: -8px;
  bottom: -5px;
  padding: 0 5px;
  border: 1px solid var(--metal-ring);
  border-radius: 999px;
  background: linear-gradient(var(--metal-light), var(--metal));
  color: #1f1a12;
  font-size: 10px;
  font-weight: 800;
  line-height: 14px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

.is-large .badge-streak {
  font-size: 12px;
  line-height: 17px;
}

/* What a badge means, over it on hover or focus, at once, like the tooltips of the charts: its name and tier, then
   what won it. On a card it opens from the medal's left edge towards the right: centred, it ran under the sidebar for
   the medals at the left of a card. */
.badge-tip {
  position: absolute;
  z-index: 2;
  bottom: calc(100% + 12px);
  left: -6px;
  display: grid;
  gap: 4px;
  width: max-content;
  max-width: 250px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text-primary);
  font-size: 12px;
  line-height: 1.45;
  text-align: left;
  white-space: normal;
  box-shadow: var(--shadow);
  visibility: hidden;
  pointer-events: none;
}

.badge-medal:hover .badge-tip,
.badge-medal:focus-visible .badge-tip,
.badge-more:hover .badge-tip,
.badge-more:focus-visible .badge-tip {
  visibility: visible;
}

/* The medals left out: "+N" in a plain disc the size of a medal, their names in its tooltip. */
.badge-more {
  position: relative;
  display: inline-grid;
  flex: none;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface-hover);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  cursor: default;
}

.badge-more.is-large {
  width: 58px;
  height: 58px;
  font-size: 16px;
}

/* In the dialog the medals sit at the top right, near the close button, which comes forward as the card leans: their
   tooltip opens below them, on their right edge. */
.person-dialog-badges .badge-tip {
  top: calc(100% + 12px);
  right: -6px;
  bottom: auto;
  left: auto;
}

.badge-tip-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
}

.badge-tier {
  padding: 0 7px;
  border-radius: 999px;
  background: linear-gradient(var(--metal-light), var(--metal));
  color: #1f1a12;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.04em;
  line-height: 16px;
  text-transform: uppercase;
}

.badge-tip-text {
  color: var(--text-secondary);
}

/* A person's details: a larger card in a dialog. It leans towards the pointer, its layers come apart and it catches
   the light, a spot under the pointer and a faint rainbow sheen. At rest it lies flat, its text crisp. The dialog is
   transparent and padded so that a leaning card never touches its edges. */
.person-dialog {
  width: min(100% - 16px, 900px);
  max-width: none;
  padding: 32px;
  border: 0;
  background: transparent;
  color: var(--text-primary);
}

/* On a screen tall and wide enough for the whole card, nothing clips it as it leans; on a smaller one it scrolls. */
@media (min-width: 761px) and (min-height: 761px) {
  .person-dialog {
    max-height: none;
    overflow: visible;
  }
}

.person-dialog::backdrop {
  background: rgba(11, 11, 11, 0.55);
  backdrop-filter: blur(3px);
}

.person-dialog-scene {
  perspective: 1100px;
}

.person-dialog-card {
  position: relative;
  display: grid;
  gap: 18px;
  padding: 24px 26px;
  border: 1px solid var(--border);
  border-radius: 18px;
  background: var(--surface);
  box-shadow:
    var(--shadow),
    0 30px 60px -24px rgba(0, 0, 0, 0.35);
  transform: rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
  transform-style: preserve-3d;
  transition: transform 500ms var(--ease-out);
}

.person-dialog-card.is-tilting {
  transition: transform 90ms linear;
}

.person-dialog-card::before,
.person-dialog-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  opacity: 0;
  pointer-events: none;
  transition: opacity 400ms ease;
}

.person-dialog-card::before {
  background: linear-gradient(
    115deg,
    transparent 25%,
    #ff4fa3 38%,
    #4fd8ff 50%,
    #ffe14f 62%,
    transparent 75%
  );
  background-position: var(--glare-x, 50%) var(--glare-y, 50%);
  background-size: 250% 250%;
  mix-blend-mode: var(--sheen-blend);
}

.person-dialog-card::after {
  background: radial-gradient(circle at var(--glare-x, 50%) var(--glare-y, 50%), var(--glare), transparent 55%);
}

.person-dialog-card.is-tilting::before {
  opacity: var(--sheen-opacity);
}

.person-dialog-card.is-tilting::after {
  opacity: 1;
}

/* The layers of the card come apart while it leans: the head nearest, the figures below it. */
.person-dialog-head,
.person-dialog-section {
  transition: transform 500ms var(--ease-out);
}

.person-dialog-card.is-tilting .person-dialog-head {
  transform: translateZ(18px);
}

.person-dialog-card.is-tilting .person-dialog-section {
  transform: translateZ(8px);
}

.person-dialog-close {
  position: absolute;
  z-index: 1;
  top: 14px;
  right: 14px;
  transition: transform 500ms var(--ease-out);
}

/* The head comes forward as the card leans: the close button comes further still, or the head would take its clicks. */
.person-dialog-card.is-tilting .person-dialog-close {
  transform: translateZ(26px);
}

/* It takes clicks well around what it shows: as the card leans, it drifts a little under the pointer. */
.person-dialog-close::before {
  content: '';
  position: absolute;
  inset: -14px;
  border-radius: 50%;
}

.person-dialog-close svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
}

.person-dialog-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 20px;
  padding-right: 40px;
}

.person-dialog-avatar {
  flex: none;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  background: var(--gridline);
  box-shadow:
    0 0 0 4px var(--surface),
    0 8px 20px rgba(0, 0, 0, 0.2);
}

.person-dialog-identity {
  display: grid;
  gap: 6px;
  min-width: 0;
}

/* The name, and the GitHub profile at its right: under it when the name is too long for both. */
.person-dialog-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
  min-width: 0;
}

.person-dialog-identity h2 {
  margin: 0;
  font-size: 22px;
  overflow-wrap: anywhere;
}

.person-dialog-meta,
.person-dialog-scope {
  margin: 0;
  color: var(--text-secondary);
  font-size: 13px;
}

/* Someone who left the team: said on a tag of its own, then when they were last active. */
.person-dialog-former {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
}

.former-tag {
  padding: 1px 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--series-2) 26%, var(--surface));
  color: var(--text-primary);
  font-size: 12px;
  font-weight: 600;
}

/* Next to a name, in the repositories that rest on someone who left the team. */
.former-tag.is-small {
  flex: none;
  padding: 0 6px;
  font-size: 11px;
  white-space: nowrap;
}

.fragile-person {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* In the dialog of a repository, its main technology stands where a person's photo would. */
.repo-dialog-logo {
  display: grid;
  flex: none;
  place-items: center;
  width: 88px;
  height: 88px;
  border-radius: 24px;
  background: var(--surface-hover);
  box-shadow:
    0 0 0 4px var(--surface),
    0 8px 20px rgba(0, 0, 0, 0.2);
}

.person-dialog-github {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-secondary);
  font-size: 13px;
  text-decoration: none;
}

.person-dialog-github:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

.person-dialog-github svg {
  fill: currentColor;
}

.person-dialog-scope {
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}

.person-dialog-section {
  display: grid;
  gap: 10px;
}

.person-dialog-section h3 {
  margin: 0;
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.person-dialog-section .person-stats {
  grid-template-columns: repeat(6, minmax(0, 1fr));
  padding-top: 0;
  border-top: 0;
}

/* A label may take two lines in the dialog: the values of a row, and the medians under them, stay aligned. */
.person-dialog-section .person-stats div {
  grid-template-rows: 1fr auto auto;
}

.person-dialog-section .person-stats dt {
  white-space: normal;
}

.person-stats-peer {
  color: var(--text-secondary);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.person-dialog-columns {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px 24px;
  margin-top: 6px;
}

/* Two lists only, in the dialog of a repository: each takes half the width. */
.person-dialog-columns.is-pair {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 760px) {
  .person-dialog-section .person-stats {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .person-dialog-columns {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.person-dialog-list-title {
  margin: 0 0 6px;
  color: var(--text-secondary);
  font-size: 12px;
}

.person-dialog-list {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.person-dialog-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.person-dialog-list-name,
.person-dialog-list .person-link {
  flex: 1;
  min-width: 0;
}

.person-dialog-list-name,
.person-dialog-list .person-link-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 600px) {
  .person-dialog {
    padding: 8px;
  }

  .person-dialog-card {
    padding: 20px 18px;
  }

  .person-dialog-head {
    gap: 14px;
  }

  .person-dialog-avatar {
    width: 64px;
    height: 64px;
  }

  .person-dialog-columns {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Tooltip */
.tooltip {
  position: fixed;
  z-index: 10;
  min-width: 180px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: var(--shadow);
  font-size: 13px;
  pointer-events: none;
}

.tooltip-title {
  margin: 0 0 6px;
  color: var(--text-secondary);
}

.tooltip-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tooltip-row strong {
  min-width: 2.5em;
  font-variant-numeric: tabular-nums;
}

.tooltip-row span {
  color: var(--text-secondary);
}

.line-key {
  width: 12px;
  height: 2px;
  border-radius: 1px;
  background: var(--series-1);
}

.line-key.is-empty {
  background: transparent;
}

.tooltip-note {
  margin: 6px 0 0;
  color: var(--text-muted);
}

/* Feed */
/* A list fills its card down to the bottom when a neighbour makes the row taller: it counts for its minimum height
   only, then grows into the room left and scrolls. */
.card:has(> .feed) {
  display: flex;
  flex-direction: column;
}

.feed {
  flex-grow: 1;
  height: 0;
  min-height: 380px;
  margin: 12px -8px 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
}

.feed-item {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: 10px;
  padding: 8px;
  border-radius: 8px;
}

.feed-item.is-new {
  animation: flash 4s ease-out;
}

.feed-text {
  margin: 0;
  overflow-wrap: anywhere;
}

.feed-text a {
  font-variant-numeric: tabular-nums;
}

/* Who approved a pull request, or asked for changes, or the code owners it waits for, after its author. */
.feed-by {
  color: var(--text-secondary);
}

.feed-team {
  color: var(--text-primary);
  font-weight: 500;
}

/* What a pull request merged without approval got instead: quiet, next to its link. */
.feed-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--surface-hover);
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.feed-time {
  display: block;
  color: var(--text-secondary);
  font-size: 12px;
}

.feed-empty {
  padding: 8px;
  color: var(--text-secondary);
}

.avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--gridline);
}

/* Everyone who made a hotfix is listed: the list scrolls under its header rather than stretching the page. */
.scroll-table {
  max-height: 560px;
}

.scroll-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
}

.scroll-table thead th:first-child {
  z-index: 3;
}

/* A tile that leads to its page */
.tile-link {
  margin: -6px -8px;
  padding: 6px 8px;
  border-radius: 8px;
  color: inherit;
  text-decoration: none;
}

.tile-link:hover {
  background: var(--surface-hover);
}

.tile-link:hover .tile-label::after {
  content: ' →';
}

/* Repository table */
.repo-cell .stack-type {
  margin-left: 8px;
}

.stack-type.is-other {
  --type-color: var(--text-muted);
}

/* Repository filter */
.repo-filter {
  position: relative;
  margin-left: auto;
}

.repo-filter summary {
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 260px;
  list-style: none;
  cursor: pointer;
}

.repo-filter summary::-webkit-details-marker {
  display: none;
}

.repo-filter summary::after {
  content: '';
  flex: none;
  width: 6px;
  height: 6px;
  border-right: 1.5px solid var(--text-secondary);
  border-bottom: 1.5px solid var(--text-secondary);
  transform: translateY(-2px) rotate(45deg);
}

.repo-filter.is-filtered summary {
  border-color: var(--text-primary);
  font-weight: 600;
}

.repo-filter-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.repo-filter-panel {
  position: absolute;
  z-index: 5;
  top: calc(100% + 6px);
  right: 0;
  width: 300px;
  max-width: calc(100vw - 32px);
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: var(--shadow);
}

.repo-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.repo-presets button {
  padding: 3px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}

.repo-presets button:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

.repo-presets button[aria-pressed='true'] {
  border-color: var(--text-primary);
  background: var(--text-primary);
  color: var(--surface);
  font-weight: 600;
}

.repo-filter-note {
  margin: 4px 6px 0;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--gridline);
  color: var(--text-muted);
  font-size: 12px;
  text-align: right;
}

.repo-filter-list {
  max-height: 300px;
  margin: 6px 0 0;
  padding: 0;
  overflow: auto;
  list-style: none;
}

.repo-filter-list label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px;
  border-radius: 6px;
  cursor: pointer;
}

.repo-filter-list label:hover {
  background: var(--surface-hover);
}

.repo-group:not(:first-child) {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--gridline);
}

.repo-group label {
  font-weight: 600;
}

.repo-filter-list input {
  margin: 0;
  accent-color: var(--text-primary);
}

.repo-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.repo-count {
  color: var(--text-muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

/* Language logos: the brand color, or the text color where it would fade into the surface. */
.lang-icon {
  flex: none;
  color: var(--logo, var(--text-muted));
  fill: currentColor;
}

.lang-icon.is-faint-on-light {
  color: var(--text-primary);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .lang-icon.is-faint-on-light {
    color: var(--logo);
  }

  :root:not([data-theme='light']) .lang-icon.is-faint-on-dark {
    color: var(--text-primary);
  }
}

:root[data-theme='dark'] .lang-icon.is-faint-on-light {
  color: var(--logo);
}

:root[data-theme='dark'] .lang-icon.is-faint-on-dark {
  color: var(--text-primary);
}

/* Stack cell: main type, front / back / mobile split, main languages */
.stack-cell {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* Type label, tinted with the color of its type; full-stack blends front and back. The text stays in ink. */
.stack-type {
  padding: 1px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--type-color) 26%, var(--surface));
  color: var(--text-primary);
  font-size: 12px;
  font-weight: 600;
}

.stack-type.is-front {
  --type-color: var(--series-1);
}

.stack-type.is-back {
  --type-color: var(--series-2);
}

.stack-type.is-mobile {
  --type-color: var(--series-3);
}

.stack-type.is-full-stack {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--series-1) 26%, var(--surface)),
    color-mix(in srgb, var(--series-2) 26%, var(--surface))
  );
}

.stack-bar {
  display: flex;
  gap: 2px;
  width: 48px;
  height: 8px;
  overflow: hidden;
  border-radius: 4px;
}

.stack-bar span {
  min-width: 3px;
  flex-basis: 0;
}

.stack-logos {
  display: inline-flex;
  gap: 4px;
  min-width: 56px;
}

/* Main repository of a reviewer, the count of the others as a badge */
.top-repos {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  max-width: 120px;
}

.top-repos-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.top-repos-more {
  padding: 0 6px;
  border-radius: 999px;
  background: var(--surface-hover);
  color: var(--text-secondary);
  font-size: 12px;
}

/* Tables */
.table-wrap {
  margin-top: 12px;
  overflow: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

/* Compact enough for both tables to fit from a 1080 px wide window, without scrolling sideways. */
th,
td {
  padding: 8px 6px;
  border-bottom: 1px solid var(--gridline);
  text-align: right;
  white-space: nowrap;
}

th:first-child,
td:first-child,
th.text,
td.text {
  text-align: left;
}

td.text {
  color: var(--text-secondary);
  font-size: 12px;
}

/* Lines added over lines deleted, within the height of a row, in the colors of a diff on GitHub. */
.lines-cell span {
  display: block;
  color: var(--diff-added);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.25;
}

.lines-cell span + span {
  color: var(--diff-deleted);
}

/* The person stays visible while a wide table scrolls sideways. */
th:first-child,
td.person {
  position: sticky;
  left: 0;
  background: var(--surface);
}

thead th:first-child {
  z-index: 2;
}

/* The sticky cell is opaque, so it repeats the row background and its transition. */
tbody tr:hover td.person {
  background: var(--surface-hover);
}

thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 0;
  background: var(--surface);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 500;
}

thead th button {
  width: 100%;
  min-width: 64px;
  padding: 8px 10px;
  white-space: normal;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: inherit;
  cursor: pointer;
}

thead th button:hover,
thead th[aria-sort] button {
  color: var(--text-primary);
}

thead th[aria-sort] button {
  font-weight: 600;
}

.sort-icon {
  display: inline-block;
  width: 1em;
  text-align: center;
}

tbody tr:hover {
  background: var(--surface-hover);
}

tbody tr.is-updated,
tbody tr.is-updated td.person {
  animation: flash 4s ease-out;
}

@keyframes flash {
  from {
    background: var(--highlight);
  }
  to {
    background: transparent;
  }
}

/* A person's name opens their dialog wherever it shows: a button that looks like the name. */
.person-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-weight: 500;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
}

.person-link:hover .person-link-name {
  text-decoration: underline;
}

/* A repository, wherever it shows: a button that looks like the link it replaced, and opens its dialog. */
.repo-link {
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  text-decoration: underline;
  cursor: pointer;
}

.person .person-link,
.person-secondary .person-link {
  max-width: 150px;
  white-space: normal;
  overflow-wrap: break-word;
}

.feed-text .person-link {
  display: inline;
  font-weight: 600;
}

.person-secondary {
  text-align: left;
}

.bar-cell {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

.inline-bar {
  width: 40px;
  height: 6px;
  border-radius: 3px;
  background: var(--gridline);
}

.inline-bar span {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--series-1);
}

.muted {
  color: var(--text-muted);
}

.page-footer {
  margin-top: 24px;
  color: var(--text-secondary);
  font-size: 12px;
}

/* Motion: short, eased and quiet. Everything below stops for those who ask their system to reduce motion. */
:root {
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

/* Interactive elements change colour softly */
.nav-link,
.icon-button,
.segmented button,
.tile-link,
.search,
th button,
.repo-presets button,
.repo-filter-list label,
.sync-menu-panel button,
.button-primary,
.button-secondary,
.lock-submit,
tbody tr,
tbody td.person,
tbody th {
  transition:
    background-color 160ms ease,
    color 160ms ease,
    border-color 160ms ease,
    box-shadow 160ms ease,
    opacity 160ms ease;
}

/* The theme cross-fades instead of switching at once */
.is-theme-changing,
.is-theme-changing *,
.is-theme-changing *::before,
.is-theme-changing *::after {
  transition:
    background-color 300ms ease,
    color 300ms ease,
    border-color 300ms ease,
    fill 300ms ease,
    stroke 300ms ease !important;
}

@keyframes rise-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
}

@keyframes grow-up {
  from {
    transform: scaleY(0);
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes grow-right {
  from {
    transform: scaleX(0);
  }
}

@keyframes pop-down {
  from {
    opacity: 0;
    transform: translateY(-6px) scale(0.98);
  }
}

@keyframes pop-up {
  from {
    opacity: 0;
    transform: translateY(6px) scale(0.98);
  }
}

/* A page that shows: its cards rise in turn, its bars grow from their axis, its rows follow one another. */
.route.is-entering > * {
  animation: rise-in 480ms var(--ease-out) both;
}

.route.is-entering > :nth-child(2) {
  animation-delay: 60ms;
}

.route.is-entering > :nth-child(3) {
  animation-delay: 120ms;
}

.route.is-entering > :nth-child(n + 4) {
  animation-delay: 180ms;
}

.is-entering .chart .bar {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: grow-up 700ms var(--ease-out) both;
  animation-delay: calc(var(--delay, 0ms) + 120ms);
}

.is-entering .bar-chart .bar {
  transform-box: fill-box;
  transform-origin: 0 50%;
  animation: grow-right 700ms var(--ease-out) both;
  animation-delay: calc(var(--delay, 0ms) + 120ms);
}

.is-entering .value-label {
  animation: fade-in 320ms ease both;
  animation-delay: 520ms;
}

.is-entering .heat-group {
  animation: fade-in 420ms ease both;
  animation-delay: calc(var(--delay, 0ms) + 120ms);
}

.is-entering .person-card,
.is-entering .repo-card {
  animation: rise-in 420ms var(--ease-out) both;
  animation-delay: calc(var(--delay, 0ms) + 60ms);
}

.is-entering tbody tr {
  animation: fade-in 420ms ease both;
  animation-delay: calc(var(--delay, 0ms) + 120ms);
}

.is-entering .inline-bar span,
.is-entering .stack-bar {
  transform-origin: 0 50%;
  animation: grow-right 640ms var(--ease-out) both;
  animation-delay: calc(var(--delay, 0ms) + 200ms);
}

/* Menus, tooltips and dialogs open with a short fade */
.repo-filter[open] .repo-filter-panel,
.sync-menu[open] .sync-menu-panel {
  transform-origin: top right;
  animation: pop-down 180ms var(--ease-out);
}

.date-range[open] .date-range-panel {
  transform-origin: top left;
  animation: pop-down 180ms var(--ease-out);
}

.sidebar .sync-menu[open] .sync-menu-panel {
  transform-origin: bottom left;
  animation-name: pop-up;
}

@media (max-width: 1279px) {
  .sidebar .sync-menu[open] .sync-menu-panel {
    transform-origin: top right;
    animation-name: pop-down;
  }
}

.tooltip:not([hidden]) {
  animation: fade-in 140ms ease-out;
}

.icon-button[data-label]::after {
  transform: translateY(-3px);
  transition:
    opacity 160ms ease,
    transform 160ms var(--ease-out);
}

.sidebar .icon-button[data-label]::after {
  transform: translateY(3px);
}

.icon-button[data-label]:hover::after,
.icon-button[data-label]:focus-visible::after {
  transform: none;
}

.confirm[open] {
  animation: pop-up 220ms var(--ease-out);
}

/* The person card rises into place: the scene moves, so that the card itself stays free to lean. */
.person-dialog[open] .person-dialog-scene {
  animation: pop-up 320ms var(--ease-out);
}

.person-dialog[open]::backdrop {
  animation: fade-in 220ms ease-out;
}

.confirm[open]::backdrop {
  animation: fade-in 220ms ease-out;
}

.lock:not([hidden]) .lock-card {
  animation: rise-in 420ms var(--ease-out) both;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}
